Repository navigation
SCM: the merge verb — join the base derivation to the path algebra - #10676
Conversation
…erand
The four-line three-way law -- S==B takes T, T==B takes S, S==T takes either,
else conflict -- silently assumes all three sides HAVE the path. B, S and T each
independently may not, which is eight states rather than four.
THE CONCLUSION DRAWN FROM THAT WAS WRONG THE FIRST TIME AND IS RECORDED HERE
BECAUSE THE CORRECTION IS THE DESIGN. I proposed enumerating the eight cases. What
the discovery actually falsifies is BARE-LOCATOR OPERANDS, not the law. Widening
the operand to
PathState = PathAbsent | PathPresent { source: AuthoredSourceTarget }
whose equality INCLUDES ABSENCE keeps the four lines total, and every presence
case falls out as a consequence rather than a rule: source-deleted, both-deleted,
source-added, both-added-identically, target-deleted, and both-added-differently.
An eight-case implementation would have duplicated one algebra across presence
combinations and let the copies drift -- decompress and map without the reduce,
which is the redundancy DESIGN section 2 names.
DELETE-VERSUS-MODIFY AND MODIFY-VERSUS-DELETE ARE THE POINT. They are the
resurrection class of gunbc.scm.merge_base one layer down, at PATH grain rather
than LINEAGE grain: taking the deletion silently discards an edit, taking the edit
silently resurrects a file the other side deleted on purpose. Both produce a valid
manifest and neither is visible to the caller. The law refuses them with no clause
of its own -- there is simply no equality to appeal to.
THE CONFLICT CARRIES ALL THREE STATES INCLUDING EXPLICIT ABSENCE. A deletion
reported as a sentinel or fabricated locator would collapse absence back into a
malformed-content representation -- the exact conflation the operand was widened
to remove, reintroduced in the value that REPORTS it.
No entries on the conflicted arm: a partial manifest beside a conflict list invites
a caller to actuate the non-conflicting prefix, a corpus neither author wrote. And
the conflict population is COMPLETE rather than first-wins, because fix-one,
re-run, discover-another hides the size of the job -- each round individually
honest, the sequence not.
EVIDENCE. 442/0 across all SCM witness files, up from 435. Three mutations, each
reding a DIFFERENT combination, so no claim duplicates another:
mutation presence del/mod mod/del complete union
bare-locator equality RED RED RED RED --
first-wins conflicts pass pass -- RED --
base-keyed subject RED -- -- pass RED
as built pass pass pass pass pass
One prediction of mine was wrong and is recorded rather than quietly dropped: I
expected the complete-population claim to red under the base-keyed mutation. It
does not, because all three of its paths exist in the base. Harmless -- that
mutation is caught twice over -- but the wrong prediction is only visible because
it was stated before the run.
The three-source fixture is load-bearing, not spare: with two sources, any path
where source and target disagree has one of them equal to the base, which the law
RESOLVES instead of refusing, so an all-three-differ conflict is inexpressible.
The first writing of the complete-population claim had exactly that defect --
intended two conflicting paths and built one -- and the claim caught it.
The S==T arm returns one operand, and that the choice is unobservable is asserted
by a claim rather than assumed. "They are equal so it does not matter" is the shape
of reasoning that hid the root-versus-occurrence defect one module over.
NOT IN THIS CUT: composing base derivation, manifest storage and the target-child
mint into a merge verb. Both halves now exist and refuse independently.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…ords, and its traversal from quadratic to one pass Both blocking findings of review 61418 on 7ccfe27, verified against the code before acting. Both are correct, and their fixes turn out to be the same fix. THE OPERANDS. merge_manifests took List<CorpusManifestEntry> on all three sides. That is worse than loose typing, because the module carried an ANNOTATION asserting that store_corpus_manifest refuses a duplicate path "so the first match is THE match" -- an assertion about a guarantee THE SIGNATURE DID NOT CARRY, which is validation-by-comment standing exactly where construction was available (DESIGN 5). The reviewer's specimen: a source of [a -> X, a -> Y] merged SUCCESSFULLY by silently selecting the first, and reversing that list changed the answer. Fabricated plausible output, forbidden outright. The three sides are now CorpusManifestRecord, which is sole_constructor and canonicalised at the store, so the specimen is no longer expressible at the boundary. THE TRAVERSAL. Every union path re-folded all three inputs through path_state_in -- quadratic in manifest size, and quadratic even when the three sides are identical and nothing conflicts. DESIGN 6 makes that unconditional: a proven cost-shape defect is always fixed regardless of the realized n, because n is not a time-stable fact about a compiler's corpus manifest. Replaced by a sorted grouping join -- tag each entry with its side, sort the three streams together by path, fold ONCE, close a group when the path changes. path_state_in and merged_path_union are DELETED, not made faster. The union, the three lookups and the decision are now the same traversal, so there is nothing left for them to answer. THE TWO ARE ONE. Assigning a group member to its side is total ONLY because no side can hold two entries for one path. A raw list can hold exactly that; a record cannot. A DECORATION IS DELETED RATHER THAN REPAIRED. The S==T "either operand is unobservable" claim called merged() with IDENTICAL arguments twice -- but repairing the swap would not have saved it. That arm is reached only when path_state_eq holds, path_state_eq on two present states compares locators, and AuthoredSourceTarget carries a locator and nothing else, so the operands are indistinguishable to every observer this corpus can write. No input could turn it red, so it asserted nothing while looking like coverage (DESIGN 4b). The unobservability is STRUCTURAL, which is a stronger statement than the claim made. Its red becomes authorable the day AuthoredSourceTarget gains a field outside the equality, and the annotation says so. That claim was cited as evidence in the PR body, so the PR body overstated what had been verified; it is corrected there. THE 4c REFUSAL, AND WHY MY OWN GUARD DID NOT SEE IT. The floor lane refused eight in-body annotations in the witness file. The local pre-push guard reported ZERO. It classified by what FOLLOWED an annotation block, and in-body comments are followed by ordinary expressions, which it read as "not a declaration, keep looking". A detector with false NEGATIVES is worse than no detector for the same reason a detector with false positives is: it gets cited as coverage. Rewritten to key on the only thing the rule is about -- module-item grain means column zero -- and controlled against 7ccfe27, where it reproduces all eight refused lines plus a ninth the CI log had truncated, and reads zero here. The labels themselves were worth keeping, so they are hoisted into the leading annotation of the claim they describe rather than dropped. EVIDENCE. 441/0 across all SCM witness files -- 442 minus the deleted decoration. Four mutations, two aimed at the join that did not exist before: mutation presence del/mod mod/del complete union bare-locator equality RED RED RED RED RED first-wins conflicts pass pass pass RED pass last group never closed RED RED RED pass RED target side dropped from join RED RED pass RED RED as built pass pass pass pass pass The last group is closed by close_groups and not by the fold, because a fold closes a group when it sees the NEXT path and the final group has none. An implementation missing that line drops the alphabetically last path from every merge and still returns a well-formed manifest. NO CLAIM IS ADDED FOR THE UNIQUENESS FIX, deliberately. It is now structural, so its red is unauthorable, which is the same test that retired the decoration above. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…hing else
gunbc.scm.merge_base decides WHICH BASE a squash is entitled to use and refuses
when there is none. gunbc.scm.manifest_merge decides EACH PATH against a base and
refuses when the sides disagree irreconcilably. Both refuse independently, and both
were controlled -- but nothing joined them, so there was no operation anyone could
invoke to merge anything. This is that join. It introduces NO decision of its own:
every refusal is one of the two modules' refusals carried outward, or a store fact
observed at the boundary.
THE ORDER IS FORCED, NOT CHOSEN. The base is derived BEFORE the manifests are read,
for the reason merge_base runs its consumed-source join before it looks for a
common ancestor: deriving a merged manifest against a base the repository is not
entitled to use constructs the unsafe value and then discards it, and a
resurrection that is computed and thrown away still existed.
THE SQUASH WORKFLOW IS NOW STRUCTURAL RATHER THAN CONVENTIONAL. The result records
ONE lineage edge -- parent is the target -- and the source is recorded as CONSUMED
through SquashIntegrated rather than as a second parent. Nothing is lost by that:
the receipt is precisely what merge_base reads to refuse the second merge, so "do
not merge the same branch twice" is enforced by construction instead of by
discipline, and there is no dev history to rebase because none was created.
REFUSALS ARE NOT FLATTENED INTO ONE "MERGE FAILED" ARM. A consumed source, a
conflicting path, a missing manifest and an invalid allocator have four different
remedies and four different principals to blame. Collapsing them is the absorbing
fallback DESIGN section 5 names.
ONE PLACE DELIBERATELY DOES COLLAPSE, AND IT IS FLAGGED RATHER THAN HIDDEN.
carry_mint folds the mint's three root refusals into one
SquashMergeMintRootUnresolvable, because the root handed to the mint was minted BY
THIS FUNCTION from the store one line earlier -- so all three mean "the store did
not keep what it just accepted", which is one fact about one store and not three
populations a caller acts on differently. This is the one judgement in the module I
am least sure of, since the rest of the lane argues the other way, and it is
written down so a reviewer can overturn it rather than have to find it.
THE FIXTURE MOVED INSTEAD OF BEING COPIED. The repository builder was authored
inside the merge_base witness and is needed verbatim here. Two copies of one
construction rule drift INVISIBLY -- each copy keeps passing its own claims while
the two fixtures quietly stop describing the same repository -- so it moved to
test.fixture.scm_repository_builder and both witnesses read it. All twelve
merge_base claims pass unchanged against the shared fixture, which is what makes
the extraction safe to build on rather than a hopeful refactor.
EVIDENCE. 446/0 across all SCM witness files, up from 441. The two halves' own
behaviours are NOT re-asserted here; what is unproven until this file exists is
that the JOIN preserves them. Three mutations, each reding a different combination:
mutation both paths parent/receipt double merge conflict
parent on the source pass RED pass pass
drop the consumed receipt pass RED RED pass
ignore merge_base's answer RED pass pass RED
The second is the load-bearing one: dropping the receipt reds the double-merge
claim, so the resurrection refusal genuinely flows THROUGH the verb rather than
being asserted beside it.
The scene is a DIVERGENCE and not a fast-forward, deliberately. If the target had
not moved since the base, taking the source's manifest wholesale would be correct
and every claim here would pass against an implementation that ignores the base
entirely.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…cal guard the domain it was missing The floor lane refused 20 section 4c violations in squash_merge.dag: rationale written BETWEEN the arms of SquashMergeOutcome, and one note inside a call argument list. Only module-item grain is modeled. The per-arm reasoning is worth keeping, so it moves into one table above the type rather than being deleted. AND THE LOCAL GUARD REPORTED ZERO, FOR THE THIRD TIME AND THE THIRD DIFFERENT REASON. It enumerated with `git ls-files`, which lists TRACKED files only, and the new module was untracked when the guard ran -- so it opened every file except the one the change added, which is the only file that could have been newly wrong. The first version classified by what FOLLOWED an annotation block and missed in-body comments. The second keyed on column zero, which was right, and was controlled against a known-bad specimen -- but the control only proved the PREDICATE, and the defect this time was the DOMAIN. A detector's domain is as load-bearing as its test, and nothing I had run would have told me otherwise, because a detector that never opens a file reports the same "0" as one that opens it and finds nothing clean. Fixed to enumerate tracked AND untracked, and re-controlled the honest way: the repaired guard reproduces all 20 of CI's violations at CI's line numbers, then reads 0 after the repair. The reproduction against the failing specimen is the part that was missing, not the clean read. Witnesses unchanged and still 5/5; this cut moves prose, not behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
The floor lane refused the merge-verb branch with nine unadjudicated namespace-wave-admission deltas. All nine are mine and the wall is correct: moving a declaration between modules is a membership motion, and this roster exists so it is DECLARED rather than done quietly. WHAT MOVED AND WHY. test.claim.scm_merge_base_witness authored a repository builder -- MbBuild with its arms MbBuilt and MbSetupFailed, and the six operations mb_start, mb_stage, mb_commit, mb_at, mb_head, mb_root_of -- that constructs scenes through the real store and mint instead of forging rows. The squash-merge witness needs it VERBATIM. Copying it would put one construction rule in two files and the drift would be INVISIBLE: each copy would keep passing its own claims while the two fixtures quietly stopped describing the same repository. So it rehomes to test.fixture.scm_repository_builder, which is where this repository already puts fixtures shared across claims. NINE BINDINGS, ONE MODULE, ONE CHANGE CLASS: seven inside mb_scene and two inside scm_mb_the_scene_holds_the_root_relations_the_controls_depend_on. Every spelling is identical on both sides and only the declaring module differs, which is exactly the motion TargetChanged names. Nothing is requalified. THE EVIDENCE THAT THE MOVE PRESERVES BEHAVIOUR IS EXECUTED, NOT ASSERTED: all twelve merge_base claims pass unchanged against the shared fixture. That is the right positive control for a rehome, because a builder that had silently changed would surface as a claim that stopped discriminating rather than as a compile error -- the fixture still compiles either way. Each row names the exact (module, in_declaration, spelling, target) tuple and admits nothing else, and the trigger is the rows' own death: when this PR merges, base and head bind every spelling identically, no run can produce these deltas, and all nine report CONSUMED, due for deletion on the roster's next touch. That deletion is to be adjudicated by joining each row against main's tree on its own tuple, not by trusting this sentence. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
A merge commit rather than a rebase, per the repository's merge policy: history is squashed at merge time anyway, so rebasing would buy nothing and cost a force-push. ONE CONFLICT, IN THE ADMISSION ROSTER, AND IT IS THE ROSTER WORKING. Main dissolved the gunbc#10639 probe-capture rows by their own trigger and added the gunbc#10671 leg-observation rows in the same region; this branch inserted its nine fixture-rehome rows at the head of the same list. The two edits are independent additions to one ordered table, so the resolution is the UNION -- all nine of mine, then main's row intact -- and neither side's authority is dropped. The one thing worth checking rather than assuming was the dissolved const: main removed PROBE_CAPTURE_REHOME_LABEL along with its rows, so taking my side wholesale would have left nine of my rows referencing a label that main deleted. The resolved file references it zero times and compiles, which is the fact rather than the intention. Verified after resolving, not before: v1-compiler checks clean, and all twenty-three SCM witnesses across merge_base, manifest_merge and squash_merge pass. The two newest manifest_merge claims -- the symmetry law and the over-conservatism controls -- are deliberately NOT in that count: this branch was cut from scm-algebra before that rework, so they arrive here when gunbc#10668 lands rather than being claimed now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
… named
The floor lane admitted this branch's nine fixture-rehome rows and then refused on
a different count: four CONSUMED admissions due for deletion on this
roster-touching change. That is the roster's own discipline working. gunbc#10671
merged, so its cable-leg rows can no longer be produced by any run, and they come
due on the next change that touches this file -- which is this one.
ADJUDICATED BY THE JOIN THOSE ROWS DEMANDED RATHER THAN BY THEIR OWN SENTENCE. The
entries say in as many words not to trust the sentence, so the deletion was decided
against main's tree in all three directions the join has:
- product.cable_leg_observation DECLARES SecondaryNotObserved, as an arm of its
compliance coproduct.
- extdeps.transceiver.sff_8636 does NOT declare it. Its only surviving occurrence
of the spelling is PROSE recording that an earlier head authored it -- which is
the trap a grep count falls into and a declaration check does not. A count would
have read 1 and I would have concluded the old declarer was still live and left
four dead rows standing.
- Both consumers -- test.claim.cable_leg_coding_witness and
test.claim.cable_order_admission_witness -- import the spelling from the new
declarer.
So base and head bind it identically, no run can produce those four deltas, and
CONSUMED is the correct reading rather than an author error. The const goes with
its rows; the compiler confirms nothing else referenced it.
The dissolution is recorded in the file, in the form the file already uses, so the
next author inherits the adjudication rather than the conclusion.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
One conflict, add/add on the manifest-merge witness, and it is not a real disagreement: this branch was cut from scm-algebra BEFORE the side-chat rework and carries that file's older copy, while main now carries the reworked one. Verified rather than assumed -- diffing this branch against its own branch point shows it never touched either manifest_merge file, so taking main's side loses nothing that originated here. What arrives with it is the pair this branch's own commit message said would arrive when gunbc#10668 landed: the symmetry law and the three over-conservatism controls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…ring it more elegantly
Side-chat ruling on the one judgement this branch flagged for overturning, and it
overturned BOTH options I offered rather than picking one.
WHAT I HAD. carry_mint folded mint_repository_commit's three root refusals into a
single SquashMergeMintRootUnresolvable, arguing that on this route all three mean
"the store did not keep what it just accepted".
WHY THAT IS WRONG, VERIFIED AGAINST THE CODE RATHER THAN ACCEPTED. store_corpus_manifest
returning CorpusManifestStored { store, manifest } already establishes that store
holds a manifest object at that locator -- an absent or wrong-kind locator would
have returned the store's own refusal instead. commit_merged_manifest then mints
against THAT store with THAT locator, and the mint's three root refusals are exactly
the three non-success arms of find_corpus_manifest_record, which the preceding
success has excluded. So the arms are UNREACHABLE, and the collapse fabricated a
public cause no execution can produce.
It was wrong a second way that matters more. It reasoned about THIS CALLER'S CONTEXT
INSIDE A TRANSLATOR THAT CANNOT SEE IT: handed a RepositoryCommitMint, nothing tells
you the value came from a store call one line earlier. And the three are not one fact
even in the impossible case -- a missing root means the object vanished, while a
wrong-kind root means the locator now denotes something else, which contradicts a
collision-aware insertion far more strongly.
WHY KEEPING THEM DISTINCT WAS ALSO REFUSED, which is the part I had not seen: it
would be honest about the CAUSE and still dishonest about the DOMAIN, leaving three
states in SquashMergeOutcome that no run of squash_merge can reach.
SO THE QUESTION IS REMOVED. mint_commit_from_stored_manifest consumes the
CorpusManifestObjectRef the store branded, runs every other admission -- allocator,
integration anchor preexistence, parent existence -- and returns BrandedRootMint,
which has no root arms. mint_repository_commit resolves the root and then delegates,
so the admission rules have ONE authority rather than two copies free to drift, and
a caller holding only a locator still gets all three refusals because for that caller
they are reachable and real. Rung 4: the invalid state has no constructor here.
TWO OF MY OWN ERRORS ON THE WAY, BOTH CAUGHT BY EXECUTION. I deleted
integration_anchor_resolves, which sat inside the region I replaced -- the compiler
caught it. And my first narrow projection mapped the impossible root arms onto a
fabricated allocator cause, committing the exact sin the ruling names, one level
down. Removed by making mint_repository_commit_admitted return the narrow type
directly, since it performs no admission and can only mint.
448/0 across the SCM witnesses on the merged tree.
REVIEW STANDING, STATED PLAINLY: the three approvals on this PR were all given
against 316b7d9, which still carried the collapsed arm. None of them has seen
this commit, and this one touches repository_envelope, a load-bearing module. The
tally on this PR currently overstates its review coverage.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
|
Reworked at review 61590 — the repeated builder. Correct, fixed.All three claims bound The consequence the finding doesn't name is worse than the cost: each claim was building two repositories and asserting about the second. The scene the surrounding A blocker found after every approval on this PR was castThe reviews at
That falsified my own annotation, which claimed the store had just branded the root. The signature established a repository and a brand from somewhere. It is the same defect fixed one level up on #10668 — an annotation asserting a guarantee the signature does not carry — reintroduced here while fixing something else. "Only squash calls it correctly" is no defence: And a second one: The repair seals the relation, not its two endpoints.
The wall is checked, not asserted. §4b's question was asked first — is the forbidden state authorable anywhere a check could run? It is, so the probe was written and executed: Not taken, flagged rather than dropped: sealing 448/0. The approvals on this PR predate the seal — please re-read rather than counting them. — sent from deep-carp-676 |
… rows. The floor_effect_gate_witness _passes functions now bind exit_ok to std.process; the nine scm builder-rehome admissions were consumed on main and came due on this roster touch. Co-authored-by: Cursor <cursoragent@cursor.com>
… rows. The floor_effect_gate_witness _passes functions now bind exit_ok to std.process; the nine scm builder-rehome admissions were consumed on main and came due on this roster touch. Co-authored-by: Cursor <cursoragent@cursor.com>
…ish (#10701) * Give docs/*.md ledger projections a ProcessExit actuator that can finish. Required-regen never owned those files, and main_wet dies inside the whole-registry emit graph, so rostered failure-mode rows could sit stale with every completing instrument green. A docs-only gate plus a required docs-projections population refuse that split. Co-authored-by: Cursor <cursoragent@cursor.com> * Correct the docs-projection failure-mode row: identity join is membership, not content. The specimen is three edited rows that stayed named in the projection; a name-set join would have called the file complete. The projector returns String so gunbc run exits 2 without a ProcessExit actuator. Co-authored-by: Cursor <cursoragent@cursor.com> * Record that NotProcessExit interpolates type_name only, as a deliberate wall. The projector cannot be scraped for markdown; ProcessExit regen is the repair shape, and review 58567 on #9864 is a prior specimen of the same class. Co-authored-by: Cursor <cursoragent@cursor.com> * Retract the type-name-only claim: NotProcessExit.type_name carries format_value on the non-variant arm. Docs-projection content is extractable only by scraping that unversioned diagnostic. The field-name fork is a separate row. Co-authored-by: Cursor <cursoragent@cursor.com> * Regenerate docs/design-failure-modes.md so the new docs-projection gate is green on this tree. The roster rows were unprojected (review 61515); receipts also drop interpolating type_name so the regen entry resolves. Co-authored-by: Cursor <cursoragent@cursor.com> * Use artifact_path as the docs-ledger location authority and record the executed stderr scrape. Deletes the duplicated path literals and the join test that policed them. Regenerates the failure-mode projection after the false type-name-only assertion is replaced with the EXIT=2 empty-stdout receipt. Co-authored-by: Cursor <cursoragent@cursor.com> * Record that the NotProcessExit control never calls classify_exit, then regenerate the projection. The enrolled test hand-builds type_name Bool, so its RED cannot see the rendered-value arm. docs_projection_gate main exited 0 on that regenerated tree. Co-authored-by: Cursor <cursoragent@cursor.com> * Lift exit_ok to std.process so the three gate copies are one constructor. docs_projection_gate, ci_gates, and generated_artifact_gate now consume it; floor_effect_gate_witness follows. Co-authored-by: Cursor <cursoragent@cursor.com> * Give the docs-projection regen recipe one home in the agreement module. The host no longer reprints a second copy of the same command on the required-ci refusal. Co-authored-by: Cursor <cursoragent@cursor.com> * Ground the two-ledger heal population as policy, not a copied count. Restores the rationale that only the unbounded roster projections heal, without citing the deleted path-join test. Co-authored-by: Cursor <cursoragent@cursor.com> * Record heron's unparseable-authority incident as the detector-gap specimen. The quoting injury stays a neighbouring class; this row only claims the missing completing gate. Regen attaches comments to the declarations they describe so the projector parses. Co-authored-by: Cursor <cursoragent@cursor.com> * Eliminate std.process Bool exit_ok; join seed-growth trigger to the roster. Call sites match ProcessExit. Heal registration-without-completion goes in the failure-mode row. The seed-growth trigger names hand_authored_declarations instead of a transcribed 20. Co-authored-by: Cursor <cursoragent@cursor.com> * Retract the heal-dies mechanism from the docs-projection row. heal main_wet completed on another branch; the 137 was claim_executor. Comments now mark tools.ci_gates.exit_ok as deleted. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop false main_wet-cannot-complete claims; untranscribe the registry fold. required-regen ownership motivates the docs actuator. Ordering still defends against an observed whole-registry stall; the fold is not a 35. Co-authored-by: Cursor <cursoragent@cursor.com> * Restore exhaustive std.process exit_ok and drop stale residue citations. Claim Bool collapse has one home; sequencers still match ProcessExit. Residue rows named the deleted instrument copies. Co-authored-by: Cursor <cursoragent@cursor.com> * Point the generated-artifact loudness comment at std.process.exit_ok. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md excluded_witness_outlives_the_subject_it_names Ledger-Rows-Repaired: docs/design-failure-modes.md docs_markdown_projections_have_no_completing_actuator Ledger-Rows-Repaired: docs/design-failure-modes.md type_name_field_carries_rendered_value Ledger-Repair-Judged: docs/design-rung-drops.md * Cite the existing claim-surface stall as exit_ok's standing disposition. The Bool collapse is not an untracked residue: sequencers already match ProcessExit, and tools.emit_host_gate emit_host_verdict_narration_dissolution_trigger names when the claim path can carry typed reasons. Co-authored-by: Cursor <cursoragent@cursor.com> * Say exit_ok is not rostered; the Bool claim gap is analysed on the narration trigger. That trigger deletes the scaffold, not this predicate. Both retire when the claim path carries typed reasons. Co-authored-by: Cursor <cursoragent@cursor.com> * Admit the seven exit_ok TargetChanged bindings and drop consumed #10676 rows. The floor_effect_gate_witness _passes functions now bind exit_ok to std.process; the nine scm builder-rehome admissions were consumed on main and came due on this roster touch. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md excluded_witness_outlives_the_subject_it_names Ledger-Rows-Repaired: docs/design-failure-modes.md docs_markdown_projections_have_no_completing_actuator Ledger-Rows-Repaired: docs/design-failure-modes.md type_name_field_carries_rendered_value Ledger-Repair-Judged: docs/design-rung-drops.md * Cite std.process.exit_ok in the scope-placement loudness comment. The other two sequencers already named the rehomed predicate; this copy still pointed at tools.ci_gates after that symbol was deleted. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…ish (#10701) * Give docs/*.md ledger projections a ProcessExit actuator that can finish. Required-regen never owned those files, and main_wet dies inside the whole-registry emit graph, so rostered failure-mode rows could sit stale with every completing instrument green. A docs-only gate plus a required docs-projections population refuse that split. Co-authored-by: Cursor <cursoragent@cursor.com> * Correct the docs-projection failure-mode row: identity join is membership, not content. The specimen is three edited rows that stayed named in the projection; a name-set join would have called the file complete. The projector returns String so gunbc run exits 2 without a ProcessExit actuator. Co-authored-by: Cursor <cursoragent@cursor.com> * Record that NotProcessExit interpolates type_name only, as a deliberate wall. The projector cannot be scraped for markdown; ProcessExit regen is the repair shape, and review 58567 on #9864 is a prior specimen of the same class. Co-authored-by: Cursor <cursoragent@cursor.com> * Retract the type-name-only claim: NotProcessExit.type_name carries format_value on the non-variant arm. Docs-projection content is extractable only by scraping that unversioned diagnostic. The field-name fork is a separate row. Co-authored-by: Cursor <cursoragent@cursor.com> * Regenerate docs/design-failure-modes.md so the new docs-projection gate is green on this tree. The roster rows were unprojected (review 61515); receipts also drop interpolating type_name so the regen entry resolves. Co-authored-by: Cursor <cursoragent@cursor.com> * Use artifact_path as the docs-ledger location authority and record the executed stderr scrape. Deletes the duplicated path literals and the join test that policed them. Regenerates the failure-mode projection after the false type-name-only assertion is replaced with the EXIT=2 empty-stdout receipt. Co-authored-by: Cursor <cursoragent@cursor.com> * Record that the NotProcessExit control never calls classify_exit, then regenerate the projection. The enrolled test hand-builds type_name Bool, so its RED cannot see the rendered-value arm. docs_projection_gate main exited 0 on that regenerated tree. Co-authored-by: Cursor <cursoragent@cursor.com> * Lift exit_ok to std.process so the three gate copies are one constructor. docs_projection_gate, ci_gates, and generated_artifact_gate now consume it; floor_effect_gate_witness follows. Co-authored-by: Cursor <cursoragent@cursor.com> * Give the docs-projection regen recipe one home in the agreement module. The host no longer reprints a second copy of the same command on the required-ci refusal. Co-authored-by: Cursor <cursoragent@cursor.com> * Ground the two-ledger heal population as policy, not a copied count. Restores the rationale that only the unbounded roster projections heal, without citing the deleted path-join test. Co-authored-by: Cursor <cursoragent@cursor.com> * Record heron's unparseable-authority incident as the detector-gap specimen. The quoting injury stays a neighbouring class; this row only claims the missing completing gate. Regen attaches comments to the declarations they describe so the projector parses. Co-authored-by: Cursor <cursoragent@cursor.com> * Eliminate std.process Bool exit_ok; join seed-growth trigger to the roster. Call sites match ProcessExit. Heal registration-without-completion goes in the failure-mode row. The seed-growth trigger names hand_authored_declarations instead of a transcribed 20. Co-authored-by: Cursor <cursoragent@cursor.com> * Retract the heal-dies mechanism from the docs-projection row. heal main_wet completed on another branch; the 137 was claim_executor. Comments now mark tools.ci_gates.exit_ok as deleted. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop false main_wet-cannot-complete claims; untranscribe the registry fold. required-regen ownership motivates the docs actuator. Ordering still defends against an observed whole-registry stall; the fold is not a 35. Co-authored-by: Cursor <cursoragent@cursor.com> * Restore exhaustive std.process exit_ok and drop stale residue citations. Claim Bool collapse has one home; sequencers still match ProcessExit. Residue rows named the deleted instrument copies. Co-authored-by: Cursor <cursoragent@cursor.com> * Point the generated-artifact loudness comment at std.process.exit_ok. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md excluded_witness_outlives_the_subject_it_names Ledger-Rows-Repaired: docs/design-failure-modes.md docs_markdown_projections_have_no_completing_actuator Ledger-Rows-Repaired: docs/design-failure-modes.md type_name_field_carries_rendered_value Ledger-Repair-Judged: docs/design-rung-drops.md * Cite the existing claim-surface stall as exit_ok's standing disposition. The Bool collapse is not an untracked residue: sequencers already match ProcessExit, and tools.emit_host_gate emit_host_verdict_narration_dissolution_trigger names when the claim path can carry typed reasons. Co-authored-by: Cursor <cursoragent@cursor.com> * Say exit_ok is not rostered; the Bool claim gap is analysed on the narration trigger. That trigger deletes the scaffold, not this predicate. Both retire when the claim path carries typed reasons. Co-authored-by: Cursor <cursoragent@cursor.com> * Admit the seven exit_ok TargetChanged bindings and drop consumed #10676 rows. The floor_effect_gate_witness _passes functions now bind exit_ok to std.process; the nine scm builder-rehome admissions were consumed on main and came due on this roster touch. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md excluded_witness_outlives_the_subject_it_names Ledger-Rows-Repaired: docs/design-failure-modes.md docs_markdown_projections_have_no_completing_actuator Ledger-Rows-Repaired: docs/design-failure-modes.md type_name_field_carries_rendered_value Ledger-Repair-Judged: docs/design-rung-drops.md * Cite std.process.exit_ok in the scope-placement loudness comment. The other two sequencers already named the rehomed predicate; this copy still pointed at tools.ci_gates after that symbol was deleted. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
gunbc.scm.merge_basedecides which base a squash is entitled to use and refuses when there is none.gunbc.scm.manifest_mergedecides each path against a base and refuses when the sides disagree irreconcilably. Both refuse independently and both were controlled — but nothing joined them, so there was no operation anyone could invoke to merge anything. This is that join. It introduces no decision of its own: every refusal is one of the two modules' refusals carried outward, or a store fact observed at the boundary.The order is forced, not chosen
The base is derived before the manifests are read, for the reason
merge_baseruns its consumed-source join before it looks for a common ancestor: deriving a merged manifest against a base the repository is not entitled to use constructs the unsafe value and then discards it. A resurrection that is computed and thrown away still existed.The squash workflow is now structural rather than conventional
The result records one lineage edge — parent is the target — and the source is recorded as consumed via
SquashIntegratedrather than as a second parent. Nothing is lost: that receipt is precisely whatmerge_basereads to refuse the second merge. So "never merge the same branch twice" is enforced by construction instead of discipline, and there is no dev history to rebase because none is created.Refusals are not flattened
A consumed source, a conflicting path, a missing manifest and an invalid allocator have four different remedies and four different principals to blame.
One place deliberately does collapse, and it is flagged rather than hidden.
carry_mintfolds the mint's three root refusals into oneSquashMergeMintRootUnresolvable, because the root handed to the mint was minted by this function from the store one line earlier — so all three mean "the store did not keep what it just accepted", one fact about one store rather than three populations a caller acts on differently. This is the judgement in the module I am least sure of, since the rest of this lane argues the other way, and it is written down so a reviewer can overturn it rather than have to find it.The fixture moved instead of being copied
The repository builder was authored inside the
merge_basewitness and is needed verbatim here. Two copies of one construction rule drift invisibly — each keeps passing its own claims while the two fixtures quietly stop describing the same repository — so it moved totest.fixture.scm_repository_builder.All twelve
merge_baseclaims pass unchanged against the shared fixture. That is the right control for a rehome: a builder that had silently changed would still compile on both sides, and would surface only as a claim that stopped discriminating.The move is a membership motion, so its nine bindings are declared in the namespace-wave-admission roster with their rationale and a dissolution trigger, rather than done quietly.
Evidence
446/0 across all SCM witness files. The two halves' own behaviours are not re-asserted here; what is unproven until this file exists is that the join preserves them.
The second is load-bearing: dropping the receipt reds the double-merge claim, so the resurrection refusal genuinely flows through the verb rather than being asserted beside it.
The scene is a divergence, not a fast-forward, deliberately. If the target had not moved since the base, taking the source's manifest wholesale would be correct and every claim here would pass against an implementation that ignores the base entirely.
Note
Built on
scm-algebra(#10668). The two newestmanifest_mergeclaims — the symmetry law and the over-conservatism controls — are not in this branch's count; they arrive when #10668 lands.🤖 Generated with Claude Code
https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9