Skip to content

Reconcile's three exit codes, and a bare writ deploy that deploys the implicit set - #954

Merged
David-Noble-at-work merged 3 commits into
developfrom
fix/756-reconcile-exit-codes
Sep 26, 2026
Merged

David-Noble-at-work merged 3 commits into
developfrom
fix/756-reconcile-exit-codes

Conversation

@David-Noble-at-work

@David-Noble-at-work David-Noble-at-work commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

PR B of #916, the writ lifecycle schedule: lane 4, and lanes
9 and 10 pulled ahead on 2026-09-24 because no deploy runs anywhere until the bare form works.

  • Reconcile's three exit codes (#756) — 66 never
    deployed, 0 clean, 1 drifted, gateable like git diff --exit-code. BuildReport codes the fold's not-found; the
    report gains HasDrift and DriftCount; the command renders the report under every --output and then exits 1
    with a one-line count. Health findings are the store's self-report and leave the code at 0. The two design pages
    carry the numbers, and the manage-environments guide is rewritten in full to the six words and the current option
    set (ruled 2026-09-24): writ inspect and a decommission state-file table that never existed are gone.
  • Bare writ deploy (#843) — the argument requirement
    goes; the zero case is common, which the issue's premise had wrong (withCommonProject returned an empty
    selection unchanged).
  • The implicit set (#850) — resolveSelection, one
    place, three kinds: implicit (common and one project per configured layer repository, named for its root
    directory), recorded (every project the current record holds; ruled 2026-09-26, the record is the selection and
    there is no list of its own), named (the command line; a name no registered layer carries is refused at 64).
    Upgrade selects the same way; decommission stays explicit; the deploy narrates the selection by kind. The layer
    journey's shim is gone: it deploys bare, and step 2.6 runs for the first time.

Lanes 9 and 10 share a commit: the journey's probe treats the bare form and the implicit projects as one change.

Evidence

Each lane ran on both VMs, snapshotted first; raw logs under build/e2e/756-e2e-*.log and 850-e2e-*.log in the
worktree.

Lane danoble-ud24-1.local linux/arm64 danoble-wd11-3.local windows/arm64
4 0 clean (167 entries); 66 on a fresh store with the message; 1 with the report naming the removed link absent, also under -o none and --silent; 0 after a redeploy the same; the redeploy was refused by nine occupants a writ deploy common run at 13:20Z had left outside the record, restored by lane 10's bare deploy
9, 10 Projects: common, noblefactor-ops, devlore-cli, Personal (implicit); 172 files; reconcile 0; record common 70 + noblefactor-ops 102; nosuchproject refused 64; a plain bare redeploy accepted everything as writ's own the same, 76 files, the nine noblefactor-ops links back in the record

Locally: make check and make test-scenario green on every lane, the layer journey with an empty skip list on
its ruled steps. Coverage total 63.3%; reconcile 86.2%; the selection's functions 80–100%. Nothing new over
complexity 8. Size: +660 −215 across the changed files against develop.

Found, for placement: a path-registered layer contributes its directory's name, so ~/Workspace/Personal yields
the implicit project Personal, and a Home/personal project would not be implicit on a case-sensitive filesystem.
The rule stands as ruled; whether the name should come from the remote is the owner's call.

Test plan

  • make check, make test-scenario, per lane
  • both VMs per lane, above
  • the owner's row after merge: install the official build, then one bare writ deploy --allow-dirty --conflict=replace on this Mac

Closes #756
Closes #843
Closes #850

Time

Marker UTC Elapsed
opened (first commit) 2026-09-24T20:14:36Z —
submitted (PR opened) 2026-09-26T10:52:21Z 38.6 h after opened
merged 2026-09-26T11:05:06Z 0.2 h after submitted; 38.8 h in all

Computed by the algorithm of noblefactor-ops#188 at merge.

https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW

David Noble added 3 commits September 24, 2026 22:14
…, 1 drifted

Reconcile is valid only after a deployment, and its exit status is the answer a script gates on the way it gates
on git diff --exit-code. BuildReport codes the fold's not-found as ExitNoInput (66): the code is assigned in the
reader that answers the question, not in the fold, because deploy's pre-flight reads the same not-found as
"nothing to conflict with". The report gains HasDrift and DriftCount over the four drift words; runReconcile emits
the report under every --output, then returns ExitError (1) with a one-line count when any entry is absent,
changed, dangling or stale. The store's health findings are its self-report, not drift, and leave the code at 0.

The tests carry the contract: the unit test asserts 66; the deploy scenario asserts 66 on an empty store and 1
after a removed link with the report still on stdout; the layer journey's reconcile helper asserts on every call
that the code is 1 exactly when the entries hold drift. Proven on danoble-ud24-1 (linux/arm64) and danoble-wd11-3
(windows/arm64): 0 clean, 66 on a fresh store, 1 with the report naming the removed link.

The two design pages and their status files carry the numbers; 5.1's "At reconcile" item drops the retired words
fresh, modified and conflicting for the six. The manage-environments guide is rewritten in full to the six words
and the current option set (ruled 2026-09-24): writ inspect and the decommission state-file table are gone, adopt
is spelled by --project, reconcile carries the codes. writ decommission's help drops an example for a --force flag
it does not define.

Part of #916, lane 4. Closes with PR B.

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
…project per layer repository, and what the record holds

The argument requirement on deploy goes (#843). A deploy's selection is resolved in one place, resolveSelection, by
how each project got in (#850): implicit, which is common and one project per configured layer repository named
for the repository's root directory; recorded, every project the current record holds, so a project named once
stays selected wherever it put a file (ruled 2026-09-26: the record is the selection, no list of its own); named,
the command line. A name no registered layer carries is refused at 64 with the name. Upgrade selects the same way;
decommission stays explicit. The deploy narrates the selection by kind before it plans.

Lanes 9 and 10 land together because the layer journey's probe reads the refusal's absence as the ruled form: the
shim that named the implicit set is gone, the journey deploys bare, and step 2.6 -- a bare deploy keeps a named
project -- runs for the first time. The deploy scenario opens with a bare deploy. Proven on danoble-ud24-1
(linux/arm64) and danoble-wd11-3 (windows/arm64): the implicit set narrated, reconcile 0, an unknown name 64, and
on wd11 the bare deploy is the ruled restore that put the nine noblefactor-ops links back in the record.

The command-line design's deploy row and the three guides state the rule; withCommonProject keeps the zero case as
common alone, which the selection builds on.

Part of #916, lanes 9 and 10. Closes with PR B.

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
@David-Noble-at-work David-Noble-at-work self-assigned this Sep 26, 2026
@David-Noble-at-work
David-Noble-at-work merged commit ba3eea9 into develop Sep 26, 2026
13 checks passed
@David-Noble-at-work
David-Noble-at-work deleted the fix/756-reconcile-exit-codes branch September 26, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment