You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
writ deploy narrates every conflict it detects, whatever the policy does about it; today skip is silent and skipped targets count as links #842
The three are dangling symlinks in ~/.Personal-secrets/ whose sources left the personal layer;
writ correctly treated them as occupied and, under skip, correctly left them. What it did not do
is say so. Compare stop, which lists every occupant before refusing. skip is the policy that continues past a problem, which is exactly when the reader most needs to be told what was passed
over.
And the summary is wrong: 217 is the plan, 214 is what happened. report.go (cmd/writ/writ/deploy/report.go:99)
counts links from the plan, not the outcome.
Wanted
Under skip, each skipped target is narrated — [△] skipped (occupied): ~/.Personal-secrets/…
— and the summary reads Deployed 214 files (214 links, 3 skipped) [home].
The summary counts what was done. A skipped, failed or refused entry is never counted as a link.
stop already lists occupants; replace should narrate each archive-and-overwrite the same way.
One rule: every policy names the targets it acted on differently from the plan.
Skip branch: cmd/writ/writ/deploy/deploy.go:56. Observed under noblefactor-ops#140's first base deploy.
The three were in the plan, sourced from files that exist:
personal Home/common/.Personal-secrets/com.amazon.developer.David-Noble.yaml -> ~/.Personal-secrets/com.amazon.developer.David-Noble.yaml
personal Home/common/.Personal-secrets/com.apple.developer.David-Noble.yaml -> ~/.Personal-secrets/com.apple.developer.David-Noble.yaml
personal Home/common/.Personal-secrets/com.discogs.yaml -> ~/.Personal-secrets/com.discogs.yaml
The targets were already symlinks — to …/repos/personal/Home/noblefactor.Unix/.Personal-secrets/…, a path the layer no longer has. Dangling, so not "writ's own unmodified output"; correctly classed as occupied. Under stop the earlier run listed them and refused. Under skip this run left them, said nothing, and formatSummary (report.go:39, completed(file.Link)) counted them among the 217. After the deploy the three links still point at the old path; reconcile reports them as conflict: symlink cannot be resolved.
So two defects, not one: the skip is silent, and a skipped operation is counted as a completed link. The right outcome for these three was replace — archive the stale link, relink to the source that now exists — and the reader had no way to know that from the deploy's output.
Ruled 2026-09-06: every conflict writ detects is narrated, regardless of the action taken — replacing, skipping, or stopping because of it.
That splits the work in two, which is the right split:
Detection narrates. The pre-flight already finds every occupied target and classifies it (writ's own unmodified output; foreign; locally modified; dangling). At that point, before any policy applies, each one is narrated with its classification — one line per target, the way stop already lists them.
Policy decides, and says what it decided.stop refuses and says so (as today); skip says skipped per target; replace says archived to <recovery site>, replaced per target. The summary counts outcomes — Deployed 214 files (214 links, 3 skipped) — never the plan.
The consequence for the reader: the same three lines appear whether they chose stop, skip, or replace; only the verb after each changes. Yesterday's stop run and today's skip run would have told the same story.
changed the title [-]writ deploy --conflict=skip is silent about what it skipped, and the summary counts skipped targets as links[/-][+]writ deploy narrates every conflict it detects, whatever the policy does about it; today skip is silent and skipped targets count as links[/+]on Sep 6, 2026
One more case for the narration rule, from #864 (closed 2026-09-08 as not a bug — greenfield, the old store is tossed on a shape change): when the readback inventory drops documents it cannot read, the stop pre-flight refuses every target they covered as "not recognized as writ's own unmodified output" and suggests --conflict=replace, which would archive-and-overwrite writ's own correct links — 270 of them on 2026-09-08. The refusal should say what reconcile's health already knows: "N targets unknown because M store documents are unreadable; run writ reconcile", and suggest skip, not replace.
Activity
David-Noble-at-work commentedon Sep 6, 2026
Precise evidence, from the same deploy.
The three were in the plan, sourced from files that exist:
The targets were already symlinks — to
…/repos/personal/Home/noblefactor.Unix/.Personal-secrets/…, a path the layer no longer has. Dangling, so not "writ's own unmodified output"; correctly classed as occupied. Understopthe earlier run listed them and refused. Underskipthis run left them, said nothing, andformatSummary(report.go:39,completed(file.Link)) counted them among the 217. After the deploy the three links still point at the old path;reconcilereports them asconflict: symlink cannot be resolved.So two defects, not one: the skip is silent, and a skipped operation is counted as a completed link. The right outcome for these three was
replace— archive the stale link, relink to the source that now exists — and the reader had no way to know that from the deploy's output.David-Noble-at-work commentedon Sep 6, 2026
Ruled 2026-09-06: every conflict writ detects is narrated, regardless of the action taken — replacing, skipping, or stopping because of it.
That splits the work in two, which is the right split:
stopalready lists them.stoprefuses and says so (as today);skipsaysskippedper target;replacesaysarchived to <recovery site>, replacedper target. The summary counts outcomes —Deployed 214 files (214 links, 3 skipped)— never the plan.The consequence for the reader: the same three lines appear whether they chose
stop,skip, orreplace; only the verb after each changes. Yesterday'sstoprun and today'sskiprun would have told the same story.[-]writ deploy --conflict=skip is silent about what it skipped, and the summary counts skipped targets as links[/-][+]writ deploy narrates every conflict it detects, whatever the policy does about it; today skip is silent and skipped targets count as links[/+]David-Noble-at-work commentedon Sep 8, 2026
One more case for the narration rule, from #864 (closed 2026-09-08 as not a bug — greenfield, the old store is tossed on a shape change): when the readback inventory drops documents it cannot read, the
stoppre-flight refuses every target they covered as "not recognized as writ's own unmodified output" and suggests--conflict=replace, which would archive-and-overwrite writ's own correct links — 270 of them on 2026-09-08. The refusal should say whatreconcile's health already knows: "N targets unknown because M store documents are unreadable; runwrit reconcile", and suggestskip, notreplace.