Fix #1437: Wizard sync-now step counts a no-sinks exit-0 hyp sync child as a user decline - #1441
Fix #1437: Wizard sync-now step counts a no-sinks exit-0 hyp sync child as a user decline#1441philcunliffe wants to merge 6 commits into
Conversation
…ld as a user decline Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…xit code outrank a fail-open marker read Two defects found reviewing the fix for #1437. `hyp sync --dry-run` on a held machine with no instantiated sinks returned the new exit 3 with an error on stderr, where it previously exited 0. The new branch sits ahead of every dry-run path in `runSync`, so it caught a run that never offered to send anything. That contradicts the exemption stated 40 lines below it ("--dry-run is exempt: it sends nothing") and breaks a scripted inspection run after an attended enroll. The branch is now gated on `!dryRun`, so a dry run keeps the exit code it has with no window open. The wizard checked the child's exit code only inside `if (stillHeld !== null)`. `readFirstSyncDeadline` fails open by design (LLP 0101): a corrupt, unreadable, or lapsed marker reads as absent. A child that exited SYNC_HELD_NO_DESTINATIONS_EXIT, and so provably sent nothing (the code is returned before any export), would then have been reported as `{ released: true }` and `sync_now: released` - the false "your history is on its way" claim the step exists to prevent, and the opposite skew on the metric the PR is protecting. The code is now read before the marker. LLP 0203 #read-back's new paragraph and docs/CLI_REFERENCE.md updated to match. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review round:
|
…p's no-destinations line - `hyp sync --history <client>` on a held machine with no destinations now exits 0 again rather than 3. A replay can never end the window (`runHistorySync` already refuses with 2 while the hold is live), so the new code has no early release to be silent about, and its advice named a command the caller did not run. - The wizard's no-destinations line kept the deadline instead of dropping it. The hold marker is untouched on that path and still lapses on schedule, and the driver gates on the marker alone, so a destination that appears before the deadline by a route the user did not drive forwards this history with no `hyp sync` from anyone. The line now states the deadline conditionally rather than omitting it as inapplicable, and no longer repeats the child's own "run `hyp sync` again" verbatim. - `SYNC_HELD_NO_DESTINATIONS_EXIT`'s rationale said "1 is an export that ran and failed"; `runSync` also returns 1 for a marker that would not clear and for a hold that reappeared mid-run. Corrected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review round: head
|
# Conflicts: # src/core/cli/wizard/types.d.ts
Triage: head
|
Ship risk:
|
# Conflicts: # llp/0203-setup-offers-the-first-sync.decision.md # src/core/cli/wizard/sync_now.js # src/core/cli/wizard/types.d.ts # test/core/cli/wizard/sync_now.test.js
Triage: head
|
Ship risk:
|
# Conflicts: # llp/0203-setup-offers-the-first-sync.decision.md # src/core/cli/wizard/sync_now.js # src/core/cli/wizard/types.d.ts # src/core/commands/sync.js # src/core/usage-policy/first_sync_hold.js # test/core/cli/wizard/sync_now.test.js
|
What neutral was doing The Why it cannot proceed Resolving the conflict revealed that this PR is now empty, and that is a disposition question neutral has no authority to settle:
Issue #1437's acceptance condition is already satisfied on master ( What it needs from you A disposition call. Neutral does not close PRs or issues, so it is holding:
How to unstick Reply with a comment on this PR (or push to the branch). Neutral monitors this thread and will re-engage with your guidance on its next tick. |
Feature or issue
On an enrolled attended
hyp init, the closing send-now offer spawnshyp syncand then reads the hold marker to decide what happened. A child that found no destination exits 0 without ever rendering a plan (no sinks instantiated; nothing to do), which leaves the marker standing exactly as a user who read the plan and answered no does. The wizard therefore printed "runhyp syncany time to send it sooner" at a machine with nowhere to send, and reportedsync_now: sync-declined, inflating the declined rate LLP 0203 #consequences uses to size the review window.Solution
hyp syncnow reads the hold before the handle count and, when a window is open and no destination was instantiated, says so on stderr and exits withSYNC_HELD_NO_DESTINATIONS_EXIT(3) instead of exiting 0 having sent nothing, which is what LLP 0101 #no-release already requires of a release that cannot happen. With no window open the case is unchanged: exit 0, "nothing to do".no-destinations, new inWizardSyncNowResultand in LLP 0203'ssync_nowvalue list, whose Status is Draft). The release claim itself stays on the marker. The new statement drops both claims that are false here: the deadline is not when this history leaves, and re-runninghyp syncis not the way to send it sooner.test/core/sync-command.test.jsandtest/core/cli/wizard/sync_now.test.jsfail on master (the wizard reportssync-declined; the command exits 0) and pass after.npm test6132 pass / 0 fail,npm run typecheckandnpm run build:typesclean.Code: +76 / -4 lines
Fixes #1437