Skip to content

The heal route's step 1 deleted rows: stop telling authors to stage the ours side - #10383

Merged
gunbai-bot[bot] merged 2 commits into
mainfrom
session/bright-ram-778-heal-route-deletes-rows
Sep 4, 2026
Merged

gunbai-bot[bot] merged 2 commits into
mainfrom
session/bright-ram-778-heal-route-deletes-rows

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

The generated-artifact merge driver's own printed repair route instructs the action that deletes rows.

What happens

The driver refuses rather than answering: it leaves the ours side in the worktree with no conflict markers and marks the path unmerged. Step 1 said "stage the driver-left bytes as an explicitly PROVISIONAL projection: git add -- $merged_path".

Following it commits your rows over the base's — dropping every row the base added since the merge base, and adding none of your own.

The common diagnostic in this same file already states the hazard: "Taking either side drops the other side's authority-derived content." The route then instructed taking one. The artifact contradicted itself.

Measured

2026-09-04, on docs/design-failure-modes.md, five heads that hit this driver:

head projection authority rows lost vs base
base (main) 98 98 —
four heads that followed step 1 97 99 denominator_moved_between_measurement_and_comparison, absent_reads_identically_to_never_looked
one head that did not 99 99 none

The single clean head is the one that ignored the route — it read the index stages instead of the worktree (stage 2 carries your rows and none of the base's; stage 3 the base's and none of yours) and reconstructed. Two of the four deletions were mine.

Why it is this class

The route instructed the action that disarms the guard. Committing the provisional bytes moves the merge base, after which the driver has nothing left to refuse, merge-tree is clean, GitHub admits, and every instrument reports green over a head that deletes rows.

That is guard_precondition_discharged_by_the_route_that_uses_it with the route itself as the discharging agent — a sharper receipt than the one the row carries today.

The replacement

Take the base side verbatim. This is explicitly not claimed as a resolution: it leaves the tree authority-ahead by the branch's own rows, which is the state heal exists to repair and which the generated-artifact gate can still see. What it removes is the deletion, which nothing downstream can see at all.

Two further steps are added, because changing the wording alone leaves the trap intact for anyone who reads the file rather than the route:

  • Verify by set difference, never by count. A count says a number moved; only the difference names which rows went dark, and the name is the whole finding.
  • Do not check for conflict markers and conclude anything. Zero markers is precisely what this driver guarantees on a refusal — so a marker count reports that the driver worked, never that its subject is intact. Reading a mechanism's success signal as evidence about its subject is how three of the four deletions happened.

Scope

Authority-only. .githooks/generated-artifact-merge is left for heal-generated-artifacts to derive, per the route this PR is amending.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WgiDD3VoavwLrcu832nJ2V

…he ours side

The driver leaves the OURS side in the worktree with no conflict markers and marks the path
unmerged. Step 1 said "stage the driver-left bytes", so following it commits this branch's
rows over the base's and drops every row the base added since the merge base, adding none of
this branch's own.

The common diagnostic in this same file already stated the hazard -- "Taking either side
drops the other side's authority-derived content" -- and the route then instructed taking
one. The artifact contradicted itself.

MEASURED 2026-09-04 on docs/design-failure-modes.md, five heads that hit this driver:
four followed step 1 as written and each committed a 97-row projection against a base of 98
and an authority of 99, every one silently dropping the same two rows
(denominator_moved_between_measurement_and_comparison, absent_reads_identically_to_never_looked).
The single clean head was the one that did not follow the route -- it read the index stages
instead of the worktree and reconstructed. Two of the four were mine.

THE ROUTE INSTRUCTED THE ACTION THAT DISARMS THE GUARD: committing the provisional bytes
moves the merge base, after which this driver has nothing left to refuse, merge-tree is
clean, GitHub admits, and every instrument reports green over a head that deletes rows.
That is guard_precondition_discharged_by_the_route_that_uses_it with the route itself as the
discharging agent, which is a sharper receipt than the one the row carries today.

The replacement takes the BASE side verbatim. That is explicitly not claimed as a
resolution: it leaves the tree authority-ahead by this branch's own rows, which is the state
heal exists to repair and which the generated-artifact gate can still see. What it removes
is the DELETION, which nothing downstream can see at all.

Two steps are added because the wording alone leaves the trap intact for anyone who reads
the file rather than the route:

  - verify by SET DIFFERENCE, never by count. A count says a number moved; only the
    difference names WHICH rows went dark, and the name is the whole finding.
  - do not check for conflict markers and conclude anything. Zero markers is precisely what
    this driver GUARANTEES on a refusal, so a marker count reports that the DRIVER worked,
    never that its SUBJECT is intact -- reading a mechanism's success signal as evidence
    about its subject is how three of the four deletions happened.

The emitted .githooks/generated-artifact-merge is left for heal to derive.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgiDD3VoavwLrcu832nJ2V
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
The merge at 4a9e6e6 followed the generated-artifact merge driver's
OLD printed remedy -- stage the driver-left ours bytes as a "provisional"
projection -- and that route does exactly what the driver's own diagnostic
says it does: it drops the other side's authority-derived content. Measured
by set difference against origin/main, this branch's projection was missing

  absent_reads_identically_to_never_looked
  denominator_moved_between_measurement_and_comparison

both of which are on main. 97 rows against main's 98. This is the fifth head
tonight to lose the same two rows to the same route; #10383 replaces that
remedy with "take the BASE side verbatim, verify by set difference, let heal
derive the projection", and this commit is that route applied.

docs/design-failure-modes.md is now origin/main's bytes VERBATIM: both
difference directions against main are empty and the file is byte-identical.

It is deliberately NOT regenerated. The roster carries 99 entries and this
projection carries 98, so it is authority-BEHIND by exactly one row -- this
PR's own emitted_entry_point_succeeds_doing_nothing -- and the required
generated-artifact phase will keep refusing until heal derives it. That
refusal is correct and is the mechanism working: it already caught this
defect once, reporting rostered=38 adjudicated=38 matches=37 drifted=1.
Authority-behind-and-loudly-refused is the benign shape; silently dropping
two of main's rows was not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgiDD3VoavwLrcu832nJ2V
@gunbai-bot
gunbai-bot Bot merged commit 42acdaa into main Sep 4, 2026
14 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/bright-ram-778-heal-route-deletes-rows branch September 4, 2026 12:12
briansrls pushed a commit that referenced this pull request Sep 4, 2026
Merged cleanly with no driver refusal, so the corrected route in #10383 did not fire here. Its
verification step was run anyway, because the check is cheap and the failure it catches is invisible:
set difference of the projection's row identities, main MINUS the merge result, is EMPTY -- no row
went dark. Counts are not used as the check; a count says a number moved, only the difference names
WHICH rows died.

The projection is behind its authority by this branch's two rows, which is the
authority-ahead-of-artifact state regeneration repairs and the generated-artifact gate can see. The
state that nothing downstream can see -- a deletion -- is absent, and that is what was verified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg
briansrls pushed a commit that referenced this pull request Sep 4, 2026
…rom the merged authorities

One conflicting path, .github/workflows/witnesses.yml, and it is a generated projection --
so this is the regeneration case, not a reconciliation of two intents about what the CI
jobs are. dag/gunbc/witness/witness_floor_workflow.dag auto-merged and
dag/gunbc/instruments/generated_artifact_gate.dag is untouched by main since the merge
base, so it cannot conflict at all.

THE DRIVER-PRINTED ROUTE IS NOT FOLLOWED HERE, and that is deliberate rather than
incidental: the driver that runs during a merge is the one the BRANCH had before it, so an
older checkout prints the pre-#10383 route whose step 1 stages the driver-left OURS side.
Staging those bytes deletes every row the base added since the merge base -- measured
across five heads, four of which committed a 97-row projection against a base of 98. This
resolution regenerates the path from the merged authorities instead, which is immune to
that failure by construction because it derives the bytes rather than choosing a side.

BOTH INTENTS VERIFIED PRESENT ON THE MERGED AUTHORITY, since a clean auto-merge establishes
only that git found no textual disagreement and says nothing about whether either side's
meaning survived:
  declaration step present and ordered Declare -> Regenerate -> Converge -> Commit
  fabric_evidence_job_id   0 occurrences   (the operator-ruled job cut honoured)
  rust_unit_tests_job_id   0 occurrences   (likewise)
  HealRepairDeclarationMissing refusal arm intact
and on the emitted workflow: four jobs, the declaration step sitting between Build and
Regenerate.

NO ROW WENT DARK, verified by SET DIFFERENCE rather than by count and never by counting
conflict markers, since zero markers is exactly what the driver guarantees on a refusal:
  failure-mode ledger   main 99, merged 99, lost []
  rung-drop ledger      main 34, merged 34, lost []
The zeros are readable because the same instrument was fired against a tree that really did
differ (main vs main~30), where it reported three named failure-mode identities and five
rung-drop headings lost. A zero with no accompanying nonzero establishes nothing.

15 witnesses green on the merged tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YRSSLXXVjavzktziwdpEpH
briansrls pushed a commit that referenced this pull request Sep 4, 2026
…thority-ahead-of-artifact gap

The remote tip 7f46e2c is a CI auto-heal commit that landed while this work was held locally, and
it carries exactly the artifact --required-regen does not emit: docs/design-failure-modes.md
regenerated to 101 rows, INCLUDING both of this branch's two.

So the gap the previous commit declared -- roster 101, projection 99, repaired by heal under the
design-ledger carve-out -- is closed here rather than after the next CI cycle. The carve-out worked
as declared; this merge just collects the result.

Verified after the merge rather than assumed: projection 101 rows and roster 101 entries, both new
rows present in the projection exactly once, and the #10383 set-difference check -- rows on main
MINUS rows here -- EMPTY, so nothing went dark. Source work confirmed present by count on all three
carriers: the emit-side exclusion, the enrolled test in the emitted bytes, and the admission label.

Merged rather than force-pushed over: heal's commit is real work on a shared branch, and a force
push would have discarded a regeneration this branch needed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
…he route main changed under me

Seven commits behind, and the projection conflicted again. This merge follows the route
as it now reads, which is NOT the route I followed last time: main's #10383 rewrote step
1 from "stage the driver-left bytes" to "take the BASE side's projection verbatim --
git checkout <base-ref> -- docs/design-failure-modes.md -- and do NOT stage the bytes
sitting in your worktree: those are the OURS side, and staging them commits your rows
over the base's, deleting every row the base added since the merge base".

So the base side is checked out and staged, and the projection is again knowingly stale
in the other direction: it now carries main's rows and not mine. heal derives the union
from the merged authorities, as it did on e935809.

The hook that printed the OLD route during this merge is my worktree's copy, which this
same merge updates. Recorded because it is the shape this repository keeps finding: the
instrument that told me what to do was itself the stale artifact.

No authority bytes were touched. The only conflicted path was the projection.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NF46KAHEcLoqEyMqzPWNZ9
briansrls pushed a commit that referenced this pull request Sep 4, 2026
…ion the admissions array

TWO CONFLICTS, TWO DIFFERENT RESOLUTIONS, AND THE GENERATED ONE FOLLOWS #10383's CORRECTED ROUTE.

docs/design-failure-modes.md conflicted with ZERO markers, which is the generated-artifact driver
REFUSING rather than answering: it leaves the OURS bytes in the worktree and marks the path unmerged.
Staging what is sitting there is the move #10383 measured as destructive -- four of five heads that
did it silently dropped rows. So the BASE side is taken verbatim via `git checkout origin/main --`,
and the result is verified BY SET DIFFERENCE rather than by count: rows on the base MINUS rows here
is EMPTY, so no row went dark. A marker count would have established nothing here, because zero
markers is exactly what this driver GUARANTEES on a refusal.

That leaves the tree authority-ahead-of-artifact by this branch's two rows -- roster 101, projection
99 -- which is heal's to close under the design-ledger carve-out and which the generated-artifact
gate can see. It is the deliberate cost of the safe resolution: the deletion is what nothing
downstream can detect, and the deletion is what was avoided. Heal has already closed this same gap
once on this branch, at 7f46e2c.

namespace_wave_admission.rs is HAND-AUTHORED and conflicted substantively: main deleted the nineteen
gunbc#10344 asset-identity rows as CONSUMED and recorded a TWENTY-FOURTH DISSOLUTION entry for them,
while this branch still carried them. Main's array is current truth; taking this branch's side would
have resurrected nineteen rows main deliberately retired. Resolved by taking MAIN's array and
re-applying only this branch's delta -- the KERNEL_IDENTITY_RELOCATION_LABEL const and its two
TransitionAdmission rows.

Verified by assertion rather than by eye, and the assertions caught two off-by-one slices before
anything was written: exactly two rows carrying this branch's label, zero gunbc#10344 rows
surviving, main's dissolution entry preserved, the extracted block ending on a closing brace, and
zero conflict markers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
Main now carries the annotation repair (#10425, b4dfec3), so this
branch stops inheriting the fleet-wide parse breakage.

THE GENERATED-ARTIFACT ROUTE IS NOT THE ONE I FOLLOWED ON THE PREVIOUS TWO
MERGES. #10383 replaced it: step 1 used to say stage the driver-left ours
bytes as provisional. It now says take the BASE side verbatim
(git checkout <base-ref> -- docs/design-failure-modes.md) and explicitly
NOT to stage the worktree bytes, because those are the ours side and
committing them writes this branch's rows over the base's, deleting every
row the base added since the merge base.

So this merge takes origin/main's projection verbatim. My own row is
deliberately ABSENT from it -- the base does not have it yet, and heal
derives the merged projection from the merged authorities.

VERIFIED BY SET DIFFERENCE, WHICH IS WHAT THE ROUTE DEMANDS AND NOT BY
COUNT: every row identity in the base projection is still present after the
checkout, difference empty. A count would say a number moved; only the
difference names WHICH rows went dark, and the name is the finding.

I did NOT check for conflict markers and conclude anything from their
absence. The driver GUARANTEES marker-free bytes on a refusal, so a marker
count reports that the driver worked, never that its subject is intact.

Authority after merge: 105 roster entries. The projection is knowingly
behind that until heal derives it.

Unrelated observation, not fixed here: .githooks/generated-artifact-merge
emits `line 13: ([a-z0-9_]*): command not found` twice while printing the
route. The route text still renders and the refusal still fires, so it is
cosmetic, but the sed capture group in that message is being evaluated by
the shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U397y4s3dSBof7vGPAX87G
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants