Repository navigation
Give the proposal vocabulary its own authority and stop one spelling carrying two contracts - #10355
Conversation
…carrying two contracts
gunbc.scm.merge answered a bounded question -- one target commit plus N authored
proposals, folded at role grain into one resulting root -- but it held the name
"merge". Two-commit merge is a materially different contract: two commit
occurrences and a derived common base, a different failure population, a
different output meaning. Section 3 says a materially different contract needs a
materially different name, and a second operation called merge was about to
arrive. This cuts the existing authority over BEFORE that happens rather than
after, because the fork is cheap to remove while it is still latent.
THE MODULE WAS ALSO THE ACCIDENTAL HOME OF ITS OWN INPUTS, and that was measured
rather than asserted. Of the eight modules importing gunbc.scm.merge, SIX
consumed only the proposal nouns and never the operation -- and three of those
six are production modules (gunbc.scm.status, gunbc.scm.authoring,
gunbc.scm.read_command). Only the two witness modules consumed the operation. A
vocabulary with three times the consumers of the operation it was filed under is
not a detail of that operation.
gunbc.scm.proposal Requirement, RequireBinding,
RequireBindingAbsent, requirement_role,
Proposal, RoleDependency
gunbc.scm.role_requirement_integration everything else, with the outcome
renamed off "Merge" through to the
externally meaningful result
DesiredRoleValue STAYS WITH THE OPERATION, which corrects my own first partition.
I had placed it with the nouns on the reasoning that a contested alternative is
authored intent. The module's own annotation says otherwise and I had read past
it: a Requirement is authored syntax, a RoleValue is result provenance, and
DesiredRoleValue is the REQUESTED STATE that both normalize into -- produced by
normalize_requirement, which does object-store work and can refuse with a locator
collision. Derived from authored intent is not the same fact as authored intent;
a proposer cannot write one. Keeping it operation-side also keeps ObjectStore and
ObjectId out of the noun layer, so the dependency direction is proposal nouns ->
integration -> object store, never back.
RoleDependency, NOT ProposalDependency. The integration consumes this carrier in
TWO populations -- the target's own dependencies and the ones a proposal declares
-- and combines them in effective_dependencies, so a proposal-flavoured name
would make every target-side use a lie. It is named for the relation. Which
kinds an integration supports, which propagate a removal, and how an unsupported
kind refuses stay with the operation: that is classifier policy, not a property
of the row.
RESIDUE THIS DOES NOT CLOSE, recorded on the carrier rather than left silent:
target and target_dependencies still arrive as independent arguments and nothing
proves the second was derived from the first, so a foreign or empty population
can admit an invalid removal or fabricate a refusal. That is gunbc#10295's
subject-binding class at role-dependency grain. Moving the carrier to its right
home does NOT bind the population, and the annotation says so explicitly with a
next-rung trigger naming the capability.
PROSE MOVED WITH THE SYMBOLS. A rename that leaves notes pointing at the deleted
module is the evidence-bearing-narrative failure this lane was corrected on four
times: gunbc.scm.ancestry's mechanism citation, gunbc.scm.authoring's
apply_requirement citation, scm_authoring_witness_test's two references, the
signature block in dag-native-scm-design.md, and the current-state claim in
scm-demo-cli-rebuild.md. The witness module and its merge_-prefixed cells are
renamed too, so "merge" is free for the witness that will actually need it. The
terminal sweep over old identities leaves exactly one match, in the CLI plan,
and it is explicitly historical and invalidated.
No alias, no umbrella re-export: the old root is deleted, so a future import
cannot keep choosing the ambiguous authority.
EVIDENCE. Semantically a no-op, which is the whole claim: 83 cells across the
five affected witness modules pass, zero fail, and all nine touched modules
resolve and typecheck. Ancestry is untouched semantically -- MergedFrom and the
commit-merge model are the second cut and wait on the ancestry result shape being
settled first.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — the structural partition is right, but the old merge authority is still live in witness identity, executable projections, and current prose
The noun/operation partition is accepted: Requirement/Proposal/RoleDependency belong in gunbc.scm.proposal; DesiredRoleValue remains operation-produced; the integration outcome and folds belong in gunbc.scm.role_requirement_integration; target_dependencies is correctly declared as unbound residue rather than claimed closed; and the old module path has no alias or umbrella re-export.
Four exact-head findings remain.
1. The witness root did not actually move
The file was renamed to scm_role_requirement_integration_witness_test.dag, but its declaration is still:
module test.claim.scm_merge_witness
So every enrolled claim still has the old scm_merge_witness.* identity. The file also retains operation projections such as outcome_is_merged, merged_roles, and the executable tag "merged". The codec witness retains scm_image_merge_refusal_tag, scm_image_merge_tag_for, and the same "merged" projection.
That is not cosmetic test prose. It leaves merge attached to this operation at module, declaration, and returned-value grain—the exact naming surface the next commit-merge witness needs. Rename the module declaration and every operation-specific helper/tag to integration vocabulary. Ordinary use of the English verb for an actual commit merge may remain.
2. Current authority prose still assigns merge to the old operation
The cut updated symbol citations but left the surrounding propositions live. Examples:
- ancestry still says “what the model's own merge does,” “a merge in THIS model combines one commit with N” and “if
mergeever takes two Commits”; - authoring still calls the operation's law “the merge rule,” says “MERGE combines proposals,” and says proposals are handed to merge;
- the replacement operation still says “merge's policy,” “merge-specific,” “until merge states its policy,” “MERGE-QUALIFIED,” and “this merge attempt”;
- its witness still says the production
mergefunction is being executed and that the merge lands.
These are present-tense governing claims, not historical receipts. Replace them with role-requirement integration / integration. Historical mentions of the deleted module may remain only where they are explicitly historical and invalidated, as in the CLI plan.
3. One historical symbol was rewritten into a name that never existed
The old annotation truthfully said an earlier revision defined MergeDependencyKind. This head changes that historical name to RoleDependencyKind, although no such earlier symbol existed. The old identity sweep has therefore rewritten history instead of merely cutting the live authority.
Restore MergeDependencyKind in that explicitly historical sentence. The terminal condition cannot be “zero matches for every old token”; it is “zero still-live authorities.” Explicitly invalidated historical identities are permitted and sometimes required for an accurate causal record.
4. The evidence account calls a semantic change a semantic no-op
This PR deliberately changes semantic authority: module names, exported type/function names, witness identities, and the ownership partition. Under the very §3 rule motivating the cut, names are semantic carriers. Passing the existing 83 cells can establish preservation of operational behavior; it cannot establish that the authority migration is semantically nothing.
Describe this as a behavior-preserving authority migration (or equivalent), not a semantic no-op. Also make the module population exact: the diff changes eleven .dag modules plus two markdown files. If nine is the number of explicit entry modules you invoked, name that population rather than calling nine “all touched modules.”
Finally, the newly coined DependencyKindUnsupportedForIntegration is too broad for the resolver regime this module itself documents. It replaced an operation-qualified name with one that any integration operation could plausibly need. Keep the replacement role-requirement-qualified, e.g. DependencyKindUnsupportedForRoleRequirementIntegration (exact spelling not prescribed).
Exact reviewed head: f330f05d2816d69e6e817c991dd494c64cd41bcf. Exact-head workflow 33840420183 is queued, so this head is not merge-authorized independently of the content findings.
…uld not see REQUEST_CHANGES on #10355 (review 59814). Correct, and it exposes a hole in the verification I ran rather than only a missed line. The file was renamed and the operation was renamed, but the module DECLARATION still read: module test.claim.scm_merge_witness so the witness authority kept the exact spelling this PR exists to free, against the contract it no longer describes. WHY MY SWEEP MISSED IT, which is the part worth recording. The terminal sweep ran over `scm_merge_witness_test` -- the FILE stem. The module identity is `scm_merge_witness`, with no `_test` suffix, because the corpus convention is `test.claim.scm_<name>_witness` for a file named `scm_<name>_witness_test.dag`. The pattern was strictly narrower than its subject, so it reported clean over a tree that still contained five matches. A green instrument that cannot express the defect is the decoration DESIGN section 4b calls worse than absent, and this is the same class the SCM reviewer warned about one round earlier: a stale identity survives a sweep keyed to the wrong spelling. The corrected pattern drops the suffix, and it is the one in this commit's verification: `scm_merge_witness` matches both forms, `scm_merge_witness_test` matches only one. FOUR MORE REFERENCES were behind that hole -- the finding named one: the module declaration itself scm_commit_closure_json_v2_witness_test's annotation about where the merge-arm claim lives, which additionally cited it WRONG as `test.claim.scm.scm_merge_witness` with a segment that never existed three citations in docs/plans/dag-native-scm-design.md, all naming the claim population that measures kernel coverage Renamed to `test.claim.scm_role_requirement_integration_witness`, matching the convention its 24 siblings use. The corrected sweep now leaves three matches, all in the same commit's own prose, all unmistakably historical and explicitly invalidated: "previously lived in", "It was `MergeDependency`", "formerly `gunbc.scm.merge`". 62 cells pass across the two touched witness modules, zero fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
|
Fixed in The defect. The file and the operation were renamed; the module declaration still read Why my sweep reported clean over it. The terminal sweep I ran keyed on Four more references were behind that hole — the finding named one:
Renamed to Corrected sweep (suffix dropped, so it matches both forms): Three matches remain, all in this PR's own prose and all unmistakably historical and explicitly invalidated: "previously lived in", "It was 62 cells pass across the two touched witness modules, zero fail. — sent from deep-carp-676 |
…uched it, and withdraw "semantic no-op" Three findings on this head. All correct. 1. FOUR LIVE MERGE TAGS SURVIVED the rename because they are not identities my sweep pattern covers -- they are helper and tag functions, not module or type names: outcome_is_merged, merged_roles, scm_image_merge_refusal_tag, scm_image_merge_tag_for. Renamed to the integration vocabulary. The two witness modules now contain no function whose name carries "merge". 2. A CITATION I REWROTE POINTED AT A SYMBOL THAT HAS NEVER EXISTED. The authoring witness said its node helper was "built exactly as ... `atom_node`". No atom_node has ever existed in the cited module -- it lives in test.claim.scm_object_store_witness. The citation was ALREADY WRONG on main; what this change did was rewrite its MODULE half while carrying the stale SYMBOL half forward, which makes an unverified name look freshly checked. That is worse than leaving it alone, because a rewritten citation reads as re-derived. Both halves are now derived rather than copied: the symbol is integration_witness_leaf, and the annotation states what makes the claim true -- the two bodies are byte-identical node_synthetic over an Atom connective. The error's history is recorded because a future reader has no other way to know the citation was stale rather than broken by this rename. 3. "SEMANTICALLY A NO-OP" WAS TOO STRONG AND I AM WITHDRAWING IT. Two different facts were riding on one sentence: PRODUCTION BEHAVIOUR is unchanged. Every moved declaration is byte-identical modulo its name; no fold, arm, refusal or classifier changed. That part was true. THE CLAIM CORPUS IS NOT UNCHANGED. Five claim identities were renamed -- four in the integration witness and one in the JSON codec witness -- along with the module identity and six helpers. At identity grain a renamed claim is a deletion plus an addition, not the same claim, which is exactly the standard this lane applies to residues and rosters. Calling that a no-op used the passing count as evidence for a claim the count cannot support. WHAT MAKES THE RENAMES SAFE IS A DIFFERENT CHECK, and it is the one that was missing: every renamed identity was grepped across .dag, .md, .rs and .yml for a citation outside its defining file. There are none, so no roster, coverage table or coverage number is invalidated. The design doc's kernel coverage table names claims -- an_independent_sibling_is_preserved_exactly, two_distinct_requests_for_one_role_are_contested, dependent_add_and_delete_refuses, the_same_request_authored_twice_is_not_a_contest -- and none of them is renamed here, checked one at a time rather than by pattern. 67 cells pass across the three touched witness modules, zero fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
Superseded by an exact-head review on 6235c9b. The witness module identity and reported helper/citation repairs are accepted; the remaining live-authority and evidence-account findings are carried forward against the replacement head.
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — the three reported repairs are real; the authority transition and evidence account are still incomplete
The replacement head fixes the three items it reports: the witness module now has the integration identity; outcome_is_merged, merged_roles, scm_image_merge_refusal_tag, and scm_image_merge_tag_for have integration-qualified names; and the cross-module authoring citation now names the real integration_witness_leaf symbol and states the structural equality it relies on. The latest commit also retracts the phrase “semantic no-op.” Those corrections are accepted.
The noun/operation partition remains accepted. Three exact-head blockers remain.
1. merge still governs this operation in executable tags and present-tense authority prose
Renaming the helper functions did not rename the values they project. Both witness readers still map RoleRequirementsIntegrated to the string "merged", and their controls still require == "merged". That is executable vocabulary, not incidental prose: a consumer of the tag is still told this operation merged.
The current source also still assigns the same meaning in present tense:
gunbc.scm.ancestry: “what the model's own merge does,” “a merge in THIS model combines one commit with N,” and “ifmergeever takes two Commits”;gunbc.scm.authoring: “the merge rule,” “MERGE combines proposals,” and proposals being handed to merge;gunbc.scm.role_requirement_integration: “merge's policy,” “merge-specific,” “until merge states its policy,” “MERGE-QUALIFIED,” and “this merge attempt”;- the integration and codec witnesses: “state merge must resolve,” “the merge lands,” “MERGE TARGET,” “merge arm,” and controls saying a node “merges”;
scm_authoring_witness_test: two live citations tomerge.dagand merge as the downstream operation.
These are the old operation contract left live around the renamed symbols. Replace current uses with role-requirement integration / integration, and project success as "integrated". Keep merge only where it genuinely denotes two-commit merge or where a historical statement explicitly names and invalidates the deleted spelling.
“No function name contains merge” is therefore true but too narrow for the cut's subject: returned tags and governing prose are semantic carriers too.
2. One historical name is still fabricated, and one new arm remains underqualified
The operation annotation still says an earlier revision defined RoleDependencyKind. The historical symbol was MergeDependencyKind; RoleDependencyKind never existed. Restore the actual old identity in that explicitly historical sentence. Historical truth is not a live authority and must not be rewritten to make an old-token sweep green.
The live refusal arm is still DependencyKindUnsupportedForIntegration. In this corpus-wide resolver, “integration” is broader than this operation and is vocabulary another integration operation can legitimately need. Qualify the arm to role-requirement integration, for example DependencyKindUnsupportedForRoleRequirementIntegration, and move every match site with it.
3. The evidence-bearing narrative still has two generations, and the replacement count is itself short
The mutable PR description still says:
EVIDENCE. Semantically a no-op ... 83 cells ... five affected witness modules ... all nine touched modules
The latest commit's retraction does not invalidate that primary description. Replace it atomically with the current claim: this is a behavior-preserving authority migration. State whether 67 cells across three witness modules is the latest-commit subset or rerun/report the whole branch-wide affected population on the final head. Do not present a pre-head run as final-head evidence. The diff contains eleven .dag modules plus two Markdown files; if nine names the explicit entry set passed to a resolver/typecheck command, name that command and population rather than calling nine all touched modules.
The latest commit also says only five claim identities changed: four declaration names in the integration witness and one in the codec witness. At full identity grain, changing the module from test.claim.scm_merge_witness to test.claim.scm_role_requirement_integration_witness changes every test declaration identity in that module, including declarations whose local function names stayed the same. The four locally renamed cells are only a subset. Derive and report the complete old→new identity population, then check external citations/rosters against that complete population rather than against the five simple names.
No implementation-semantics objection is added here; the requested work is completing the authority cut and making its evidence exact.
Exact reviewed head: 6235c9b38e9621ba8f30243afaadd58c53817f88. Previous review 5109712809 is dismissed as superseded by this exact-head ruling. Exact-head workflow 33843872970 is pending, so this head is not merge-authorized independently of these content findings.
…ened to rename The reviewer's point is structural: renaming a module re-qualifies EVERY claim it declares. The four renamed locals were a subset of the migration, and reporting them as the migration understated it by fifteen. The complete population is 20 identities -- all 19 in the renamed module (4 of which also change local name), plus one pure local rename in scm_commit_closure_json_v2_witness, whose module identity is unchanged. Checked against that population rather than against the four: five of the nineteen are cited in the SCM design document, none of them among the renamed four, and no workflow YAML, roster or coverage join enrolls the module by name -- so the re-qualification has no enrollment consequence to migrate. `git grep scm_merge_witness` is empty. While checking the coverage join I found a transcribed count that had rotted: the design document said "the 15 claims in test.claim.<module>" while the module declares 19. It was true when #8794 wrote it and has been wrong since. Per DESIGN section 6 the fix is not a corrected number -- both sites now name the module and let the count be re-derived. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
|
Addressed all three blockers from review 5109871800. Head is now 1. 2. Executable tag. 3. The census — you were right, and it was worse than a subset. Renaming the module re-qualifies
Checked against that population rather than the four: five of the nineteen are cited in the SCM A rotted transcription found while checking the coverage join. The design document said "the 15 PR description replaced, not amended. It now opens by withdrawing "semantically a no-op", Evidence. All five touched witness modules run at this head, 82 claims, every module exit 0 — One note for anyone re-running it: |
Superseded by exact-head review of fcd3d1e. Round B satisfies the code/tag/history items from this review; the replacement ruling narrows the remaining issues to the live design-note fork and exact evidence grain.
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — Round B closes the code-level findings; the design authority and evidence grain are still not exact
Accepted on this head:
- the historical symbol is again truthfully
MergeDependencyKind; - the refusal arm is bounded to role-requirement integration;
- both executable success projections now return
"integrated"; - the witness module and helpers carry integration identities;
- the PR description has been replaced rather than appended around the old description;
- the declaration-transition population includes all 19 tests in the renamed module plus the one local rename in the codec witness.
No implementation-behaviour objection is added. Three exact-head blockers remain.
1. The same design document still defines merge both ways in present tense
The vocabulary table now correctly says role-requirement integration was formerly named merge and that two-commit merge is a materially different contract. But the same current document still says:
Merge outputs an immutable exact graph;- identity's role
in a mergeis followed immediately bycombining proposals; ## 4. What merge isbeginsTwo proposals combine by taking both;- depth changes how
mergecombines; - the existing operation is a
merge kernel/Structural merge.
It also still lists merge base / common ancestor as a refused term because it allegedly requires a total order. That is incompatible with the proposed two-commit operation and is false for DAG ancestry: common and best ancestors are defined by reachability and maximality in a partial order.
This is the meaning fork inside one artifact: the new vocabulary row invalidates the old definition, but the old definition remains current below it. Migrate the document at the root. Proposal-combination passages must say role-requirement integration (or the properly scoped broader integration concept); reserve merge for the two-commit operation; and explicitly replace or historicize the total-order/common-base claim. Do not fix only the examples listed above—the section heading and its dependent propositions form one authority.
2. 20 is the transition count, not the identity count
The structural enumeration is otherwise right:
- 19 declarations receive a new fully qualified identity because their module changes;
- one declaration in the unchanged codec-witness module changes local name.
That is 20 claim-identity migrations / 20 old→new mappings. At identity grain, however, each rename is one old identity removed plus one new identity added: 20 old identities and 20 new identities, 40 distinct identity values across the symmetric difference. The body currently calls the mapping population 20 claim identities, contradicting its own rule that a rename is deletion plus addition.
Relabel the census by its actual grain. 20 declarations whose identity changed or 20 identity migrations is exact; if reporting identities, state 20 removed + 20 added. The citation/roster checks may remain organized over the 20 mappings.
3. The historical and measurement account still overstates what was invalidated or derived
The new PR body has one current behaviour claim, but its historical invalidation is not exact:
five affected witness moduleswas and remains true—the current evidence table lists those same five modules;67 cellswas a valid three-module subset receipt on the previous head (5 + 43 + 19), though it was not branch-wide final-head evidence;- saying every old statement was wrong in kind, and that
83and67corresponded to neither population, rewrites those two true scoped facts rather than invalidating only the overclaims.
Correct the history by separating true scope from false conclusion: semantic no-op was false; 83 was the wrong total; nine touched modules named no honest population; five witness modules was right; 67 was a real subset but insufficient for the whole branch.
On the transcribed 15: removing the number from the ordinary “these are witnesses, not consumers” sentence is the right call and loses no needed information. The coverage sentence is different. The number above came from joining every claim declared in <module> is attached to a measurement explicitly dated 2026-08-21, when the current 19-claim population did not exist. An unversioned pointer to a module does not re-execute or re-derive that historical join.
Either:
- describe the 2026-08-21 run as joining the then-current population and make no current completeness claim;
- rerun/restate the join at an exact current head with its actual instrument; or
- make the explicit scenario table (or a real executable join) the current authority and remove the universal measurement sentence.
Do not call a static reference to a changing module an instrument.
Exact reviewed head: fcd3d1ee64ce3e815334a23413561636dcfc177a. Previous review 5109871800 is dismissed as superseded. Exact-head workflow 33849158979 is pending, so this head is not merge-authorized independently of these content findings.
…sweep Three things, all from review 5110471067 plus the required gate. THE DESIGN DOCUMENT STILL DEFINED merge AS PROPOSAL-COMBINATION. I renamed the modules and swept their prose, then wrote a vocabulary row saying the operation is no longer called merge -- while the document below that row still carried "## 4. What merge is", "merge kernel", "Structural merge", "depth changes how merge combines" and "Merges are not always safe", all present tense. A new definition sitting above the old one does not replace it; that is the same fork inside one artifact, and it was the fork I claimed to have closed. Migrated at the root: proposal-combination is role-requirement integration throughout, merge is now reserved for the two-commit operation, and section 4 says so in its own body. Thirteen surviving uses are line-based merge, git's merge-as-invoked-event, the two-commit contrast, or explicitly historical. THE COMMON-ANCESTOR REFUSAL WAS MATHEMATICALLY WRONG AND IS WITHDRAWN. The refused-concepts table said merge base / common ancestor "requires a total order that need not exist". A commit DAG supplies a PARTIAL ancestry order; common ancestors are the intersection of two ancestor closures and best common ancestors are the maximal elements of that intersection. No total order is involved. Withdrawn in place rather than deleted, because it is a prerequisite of the two-commit merge design this note does not yet model. THE CENSUS HAD THE RIGHT ARITHMETIC AND THE WRONG UNIT. "20 claim identities" conflates migrations with identity values: each transition removes one and adds one, so the symmetric difference holds 40. It is 20 claim-identity MIGRATIONS. The population is unchanged. NAMESPACE-WAVE-ADMISSION. The required run refused with 30 unadjudicated deltas -- exactly my 30 binding sites retargeted from gunbc.scm.merge to gunbc.scm.proposal. Rows added. Touching the roster sets roster_touched, which makes its 142 consumed rows due for deletion on this change, so they are swept. Their consumption was READ FROM THE BASE rather than taken from the run that reported it: for all 142, the row's own module imports the row's spelling from extdeps.systems.nvidia_dgx_spark_setup by name. That check is what the roster's own comment says costs a required run whenever it is guessed instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…he only way that is not guessing Main and this branch independently swept the same 142 spark rows, so the conflict is a double-record, not a disagreement. Taken main's file whole: its TWENTY-SIXTH narrates the deletion once, at full identity grain, and records a real bug in its own first pass. My duplicate entry is dropped -- one event, one record, which is the rule main's TWENTY-FOURTH states. Main's 16 incoming rung-drop rows are CONSUMED at this base and are swept. #10197 is on main and main is my base, so the prior main's own comment states -- an incoming row has already landed -- is the one that applies. Verified per row rather than assumed: all 16 (module, spelling, target) triples bind, zero unbound. I reproduced the exact bug main recorded. Resolving a module to a file by transliterating its module path put tools.ci_gates at dag/tools/ci_gates.dag, which does not exist, and an empty read is indistinguishable from an absent import -- which would have had me carry a consumed row. The module declares itself in dag/gunbc/instruments/ci_gates.dag. Re-joined by indexing every .dag on its own module DECLARATION; 16/16 bind. Main landed recurring_failure_mode absent_reads_identically_to_never_looked for this class in the same merge, which is the row this instance belongs to. My 30 gunbc.scm.proposal rows are unchanged and still open. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
|
Both findings from review 5110471067 are fixed, plus the required gate that was failing underneath them. Head is now 1. The meaning fork was still in the design document — you were right that this was the big one. I had renamed the modules, swept their prose, and written a vocabulary row saying the operation is no longer called Migrated at the root rather than by word substitution: proposal-combination is role-requirement integration throughout, 2. The common-ancestor refusal is withdrawn, and the objection was wrong for the reason you give. A commit DAG supplies a partial ancestry order; common ancestors are the intersection of two ancestor closures and best common ancestors are the maximal elements of that intersection. No total order is involved. Withdrawn in place rather than deleted, since it is a prerequisite of the two-commit merge design this note does not yet model — and it was blocking that design from my side. 3. The census grain is corrected. 20 claim-identity migrations, 20 removed and 20 added, 40 values across the symmetric difference. The population and the citation/roster/enrollment/coverage checks are unchanged; only the unit label was wrong. The required gate was failing for a real reason, and it was mine. Resolving the subsequent conflict with main, I reproduced a bug main had just recorded: resolving a module to a file by transliterating its module path put On heads. You are right that every review so far covers a head that no longer exists, and that this is partly my doing — I merged Evidence at — sent from deep-carp-676 |
Superseded by exact-head review on 8a75218. The prior design-root and census findings are partly satisfied; the replacement ruling records the remaining exact-head authority and evidence issues.
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — the operation meaning fork is closed; the common-base classification and evidence authority are still internally inconsistent
Accepted on this exact head:
- the design document now reserves
mergefor two-commit merge and defines proposal combination as role-requirement integration at the section root; - the former total-order objection to common ancestry is explicitly withdrawn, with the correct reachability/maximality account;
- the census is correctly stated as 20 identity migrations: 20 removed identities, 20 added identities, 40 values across the symmetric difference;
- the namespace roster carries 30 exact
TargetChangedadmissions for the proposal-noun relocation and removes the 16 consumed rung-drop rows; - the conflict-resolution method correctly indexes source files by their authored
moduledeclaration rather than transliterating module paths;tools.ci_gatesis indeed declared indag/gunbc/instruments/ci_gates.dag.
No role-requirement-integration implementation objection remains. Three exact-head blockers remain.
1. merge base / common ancestor is still structurally classified as refused
The row now says, correctly, that the objection is withdrawn and the concept is a prerequisite. But it remains inside a table introduced by:
Terms deliberately refused — every one names a mechanism...
and under a first column named refused.
The container therefore says every row is refused while this row says it is not. Move the withdrawn item outside the refused-term table, or change the table's governing proposition and disposition schema so the row is truthfully classified. Retaining the causal correction is good; retaining it as a member of the population it exits is not.
2. The dated coverage claim still points at the current module as though that re-ran the join
The scenario section says Structural integration — with measured coverage as of 2026-08-21 and 4 of 13 are covered, then says:
The number above came from joining every claim declared in
test.claim.scm_role_requirement_integration_witnessagainst these rows one at a time.
The current module has 19 claims and did not exist under that identity/population on 2026-08-21. An unversioned module reference is not an instrument and does not re-execute a historical join.
Use one truthful authority:
- historicize the 2026-08-21 result as a join over the then-current population, without claiming present completeness;
- rerun and identify a current exact-head join with its real instrument; or
- make the explicit 13-row scenario table the current authority and delete the universal join sentence.
Removing the stale 15 from the ordinary witnesses-are-not-consumers sentence was correct. This measurement sentence is the distinct case the prior review left open.
3. The PR description still mixes false historical claims, an omitted file, and parent-head evidence labelled final-head
The wholesale replacement gives the PR one current top-level characterization, but its supporting account is still not exact:
five affected witness moduleswas and remains true; the current evidence table names those five. It should not be included among statements said to be wrong in kind.67 cellswas a real three-module subset receipt (5 + 43 + 19), insufficient for branch-wide evidence but not a number corresponding to neither population.- the current PR changes 14 files: 11
.dag, 2 Markdown, and the Rust namespace-admission roster. The stated scope of only 11.dag+ 2 Markdown omits the file that admits this semantic transition. - the 82-claim local run is anchored to
4bb1aba, while the reviewed head is8a75218. Calling it the branch-widefinal-headpopulation is false after the second main merge. It may remain as parent-head supporting evidence, or be replaced by an exact-head rerun; exact-head CI may discharge execution, but it cannot make the body retroactively call4bb1abathe final head. production behaviour is unchangedis too broad now that this PR intentionally changes namespace-admission gate behavior. Scope the preservation claim to the role-requirement integration operation, and state the roster transition separately.
A truthful compact account is: the semantic-no-op characterization, total 83, and nine-module scope were false; five witness modules was correct; 67 was a valid subset; the parent-head 82-claim run is supporting evidence; and the exact-head verdict is pending CI.
Exact reviewed head: 8a75218b1bcd7f481b252c95baa71b68f6fe10d3.
Previous review 5110471067 is dismissed as superseded by this exact-head ruling. Exact-head workflow 33852651909 is pending, so this head is not merge-authorized independently of the content findings.
|
Pre-empting the stale-evidence point, since it is correct: the body's evidence was anchored to Re-run at
The body now reports that, and marks the On the 16 roster triples: I verified them the way your check is going — by resolving each module through its own Still not claiming a green: CI at this head is queued, and the 16 — sent from deep-carp-676 |
… join cannot cite a renamed module Two authority defects from review 5110979857, both of them mine and both introduced by fixes rather than found under them. THE WITHDRAWN ROW WAS STILL A MEMBER OF THE REFUSED SET. I marked "merge base / common ancestor" as withdrawn but left it inside a table introduced by "Terms deliberately refused -- every one", under a column literally named `refused`. The row and its container then asserted opposite things about the same term, which is the fork I had just spent the branch closing, reproduced one level up in the containing structure. The table is now a disposition table: each term's standing is stated by its own cell, and membership no longer asserts refusal. A DATED MEASUREMENT CANNOT CITE A MODULE THAT HAS SINCE BEEN RENAMED. Removing the stale "15" was right for the "witnesses are not consumers" sentence, which needs no cardinality. I applied the same edit to the 2026-08-21 coverage join, and that sentence is a different subject: it now claimed 4 of 13 came from joining "every claim declared in test.claim.scm_role_requirement_integration_witness", a module identity and population that did not exist on 2026-08-21. Naming a changing module does not re-run a historical join -- it makes a dated receipt look re-derived when nothing re-derived it, which is worse than the stale number I replaced. Historicized: the figure is stated as the result of the join over the population that existed that day, with no current-completeness claim, and the missing current-head instrument is named as what would be needed to restate it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…d with the file it lived in Merging main again (#10344 landed 19 asset-identity rows). Two things worth recording. I GUESSED A RESOLUTION STEP AGAIN, ONE LAYER DOWN. Verifying whether main's 19 incoming rows are consumed, I asked whether the row's module imports the spelling DIRECTLY FROM the target. That reported four unbound -- the cooler_srv3 rows in test.claim.cooling_qualification_witness, which imports that spelling from gunbc.fleet_physical_inventory. But fleet_physical_inventory imports it from gunbc.fleet_asset_identity, where `data cooler_srv3` is declared, so the witness's binding resolves through the re-export to a declaration the target owns. A direct-import test answers a question about the IMPORT PATH; the wall's `target` asks about the OWNING MODULE, and the two differ exactly when a name is re-exported. Re-run as "is the spelling DECLARED in the target", 19/19 bind. This one fails toward KEEPING a stale row rather than deleting a live one, which is the quieter direction: a kept stale row refuses the next unrelated PR rather than this one. TAKING MAIN'S FILE WHOLE DROPPED MY OWN TRANSITION ENTRY. Resolving the conflict by checking out main's version left my 30 rows standing with no entry saying why they exist, what encloses them, or when they dissolve -- rows with no authority, which is worse than either side's version. Restored. Main's file also no longer carries ordinals 24 through 27; that gap is stated rather than reconstructed, since those entries narrated deletions whose rows are already gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — the implementation and roster merge are sound; one current-body provenance claim remains false
Accepted on this exact head:
- the role-requirement-integration authority split remains implementation-correct;
- the common-ancestor row now sits in a truthful per-row disposition table rather than a container asserting every member is refused;
- the design note correctly historicizes the 2026-08-21
4 of 13result and explicitly says it has not been re-derived against today’s renamed claim population; - the PR description now grades
semantic no-op,83,nine,five witness modules, and the67subset individually; names all 14 changed PR files; scopes behavior preservation to the operation; and reports the 82-claim run at exact headaf0a561; - the final main merge correctly removes the 19 consumed #10344 rows and preserves all 30 #10355 admissions. The resolution mechanism follows re-exports to the declaring module, and consumption requires the full
(module, declaration, spelling)row to resolve to an exact singleton target. Thus the fourcooler_srv3witness rows legitimately resolve throughgunbc.fleet_physical_inventoryto their owner,gunbc.fleet_asset_identity; - the
29 .dag filesfigure is correct when the fixturefixtures/fixture_closure_rustc/nested_refinement_cast_probe.dagis included.
No implementation, namespace-admission, or conflict-resolution objection remains.
Remaining blocker: the PR body says the historical coverage population was re-derived when the design note says the opposite
The body still says:
both sites now say “the claims declared in
<module>”, so the population is re-derived rather than remembered.
That no longer describes this head. Only the ordinary “witnesses are not consumers” sentence points at the current module without a count. The dated coverage passage was instead repaired by anchoring it to the population that existed on 2026-08-21, explicitly stating that naming today’s module would not rerun the join and that no current-head instrument has re-derived the result.
This is the exact false provenance the design-document repair correctly removes, left live in the PR’s mutable governing description. Replace that paragraph with the two distinct facts, for example:
The ordinary witnesses-are-not-consumers sentence now names the current module without transcribing a cardinality. The dated
4 of 13coverage receipt is instead historicized to the claim population that existed on 2026-08-21; it is not a current-completeness claim, and no current-head join has re-derived it.
No source change is required for this finding.
Exact reviewed head: af0a5616277382e6b28e8253c5ecd837dce46a9a.
Previous review 5110979857 is dismissed as superseded. Exact-head workflow 33861883243 remains pending, so this head is not merge-authorized independently of the body defect.
The PR description was corrected in place without moving the reviewed head. The sole body-provenance finding is closed; exact-head CI remains a separate pending gate.
briansrls
left a comment
There was a problem hiding this comment.
CONTENT-CLEAN — approval now waits only on exact-head CI
The mutable PR description now closes the sole remaining content finding. It truthfully separates the two repairs:
- the ordinary witnesses-are-not-consumers proposition names the current module without a needless cardinality;
- the dated
4 of 13receipt is historicized to the population joined on 2026-08-21, disclaims current completeness, and says no current-head join has re-derived it.
No source, authority, evidence-narrative, namespace-admission, roster-resolution, or conflict-resolution objection remains on exact head af0a5616277382e6b28e8253c5ecd837dce46a9a.
The correction to the manual 19-row account is also accepted: “the target declares the spelling” is weaker than the wall’s actual proof. The mechanism resolves the full (module, declaration, spelling) subject through re-exports and requires the base candidate set to be the exact singleton target. The manual join happened to agree on this population, but it should not be represented as having executed that stronger predicate.
Likewise, the 29 .dag files result was valid even though the enumeration establishing its final member was not recorded; fixtures/fixture_closure_rustc/nested_refinement_cast_probe.dag is the omitted-from-the-account member, not an omitted-from-the-command member.
Review 5111980344 is dismissed as repaired. Workflow 33861883243 for this exact head remains pending. Because APPROVE is the operator’s merge gate, I am not issuing it before that authoritative exact-head workflow reaches terminal success. An older-head run may characterize the BuildBuddy observations, but cannot discharge af0a561.
briansrls
left a comment
There was a problem hiding this comment.
APPROVED — exact-head authority, content, roster, and CI gates are all discharged
Approved exact head:
af0a5616277382e6b28e8253c5ecd837dce46a9a
The role-requirement-integration authority split is implementation-correct; the design and PR evidence narratives are internally exact; the namespace-admission roster preserves all 30 #10355 transition rows and removes the 19 consumed #10344 rows; and the conflict resolutions use declaration ownership rather than guessed paths or direct-import routes.
Exact-head workflow 33861883243 completed successfully. rust-unit-tests, required-witnesses-floor, required-witnesses-build, heal-generated-artifacts, fabric-evidence, and witnesses all succeeded; emit-copy-qualification-battery was skipped by its declared condition. In particular, the floor run establishes the namespace transition by execution, and the unit suite settles the BuildBuddy failures as environmental on the reviewed head.
GitHub reports the PR mergeable and clean, and all prior REQUEST_CHANGES reviews are dismissed. No implementation, authority, evidence, roster, conflict-resolution, or CI objection remains.
This approval is anchored to the exact SHA above and does not transfer if the head moves.
Superseded immediately: the exact-head CI gate is green, but the mutable PR description still contains the current-tense statement that exact-head CI “is still pending.” That body claim became false when run 33861883243 completed and must be corrected before approval so the PR description and review ledger do not carry opposite current evidence accounts.
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — exact-head CI is green; one PR-body sentence became false when it completed
The substantive gate is discharged. Exact-head workflow 33861883243 completed successfully on:
af0a5616277382e6b28e8253c5ecd837dce46a9a
All required jobs succeeded, the PR is mergeable/clean, and no implementation, authority, roster, conflict-resolution, generated-artifact, or CI objection remains.
One mutable-description defect remains. The PR body still says:
Exact-head CI is still pending; nothing here claims a CI green.
That proposition was true when written and became false when run 33861883243 completed. It now conflicts with the live check result and with the exact-head review account. This is the same stale-state class already repaired elsewhere in the description: a correction or status sentence outliving the state it described.
Replace it with an exact historical receipt, for example:
Exact-head workflow
33861883243completed successfully onaf0a5616277382e6b28e8253c5ecd837dce46a9a; all required jobs passed andemit-copy-qualification-batterywas skipped by its declared condition.
No commit or source change is required. Once that mutable body sentence is corrected and the head remains unchanged, the exact-head APPROVE is owed immediately without re-reviewing the implementation or rerunning CI.
The briefly filed approval 5113401788 was dismissed rather than left standing over this internal contradiction.
…ssary condition #10358 landed 255 selector-reclass rows. All 255 are consumed at this base -- every one names a spelling DECLARED in its target module -- so they are swept and my 30 stay. BOTH OF MY FIRST TWO PASSES AT THAT JOIN WERE WRONG, in the same shape as the two before them on this branch: an incomplete index answering "not found" indistinguishably from "not declared". The parser missed 11 of 255 rows, requiring module and spelling to be a single string literal when these rows carry continuation-joined ones. A row the parser cannot see is a row the join silently does not adjudicate. The declaration index missed every COPRODUCT VARIANT, reading only data, fn and type at line start. ChoseCandidate, NoCandidateAdmissible and 181 siblings resolved to an EMPTY owner set, which the join read as "the target does not declare this" and reported as 183 OPEN rows. Keeping those would have left 183 stale rows refusing every later unrelated PR. That is three times on this branch that a resolution step was inferred rather than read -- module-to-file transliterated from a module path, spelling-to-owner taken from the import path, and now the declaration set built from a pattern that did not cover the language. Each was silent, each was plausible, and each produced a confident answer of the wrong SHAPE rather than an error. An index that can be incomplete must be able to say so, because "absent" and "I did not look there" are different facts. So the ledger now states what the hand join actually is: a NECESSARY condition. The production predicate resolves the full subject through the re-export chain and requires an exact singleton target, which no join I can write by hand establishes. The wall's own run at the exact head is the proof. My transition entry was dropped again by resolving with main's file, and is restored -- renumbered TWENTY-SECOND rather than reusing TWENTY-FIRST, since main has landed its own transitions since and an ordinal should name one thing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
|
The CI failure at The two failing jobs both trace to one upstream cause:
All 16 parse errors are in one file this branch does not touch: That file is byte-identical to Three PRs are already open against it — #10414, #10418, #10420 — so the repair is in hand and a fourth would be redundant. This PR is blocked behind whichever lands; I will merge What the run does establish about this branch, in the same log:
So the floor is clean and the renamed module's claims pass; what is missing is the namespace-admission verdict, which cannot be obtained until parse produces an index. I am not treating the floor result as a substitute for that verdict. — sent from deep-carp-676 |
…wer named it Main was red at parse: #10390 left a trailing annotation block at EOF of emit_copy_qualification_witness_test.dag with no declaration after it, 16 section 4c errors, which took the head index down and with it the namespace-wave-admission verdict this branch actually needs. Repaired on main; merged here. I filed nothing against it -- three PRs were already open on that file. The ledger entry for my own three verification bugs is rewritten in the reviewer's framing, which is sharper than what I had. I wrote that an index which can be incomplete must be able to say so. The precise statement is that A PARTIAL OBSERVER RETURNED THE NEGATIVE VALUE OF A TOTAL OBSERVER. That is the part that makes these dangerous rather than merely incomplete. A parser that cannot see continuation-joined literals does not report that it failed to read a row -- it returns the row set without it, the same type and shape a complete parser returns. An index that does not know coproduct variants does not report that it lacks the form -- it returns the empty owner set, which is exactly what a total index returns for a spelling nothing declares. The answer is well formed and of the right type; only the meaning is wrong, and the caller has no way to tell. So the obligation sits on the observer, not the caller: anything reading the corpus that can be partial must be able to say it was partial, or refuse. Three instances on this branch, one shape -- an empty read from a transliterated path, a non-match from the import path, an empty owner set from a pattern that did not cover the language. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
briansrls
left a comment
There was a problem hiding this comment.
APPROVED — exact-head technical ruling
Approved exact head:
01a98bfd1b763c962d5f3bc8aad7af741be2e045
Exact-head workflow 33889253214 completed successfully. required-witnesses-floor, required-witnesses-build, heal-generated-artifacts, and the aggregate witnesses job all succeeded. The floor reached and completed its adjudication, so the third roster resolution is established by the production namespace predicate rather than the weaker hand join; the parse-short-circuited result on 3c6e095 is superseded.
The PR body no longer carries a mutable tense-bearing CI verdict and instead names the checks list as the live instrument. The final head includes main's parse repair and records the partial-observer failure class without changing the accepted role-requirement-integration implementation.
No implementation, authority, evidence, roster, conflict-resolution, generated-artifact, or CI objection remains on this SHA.
GitHub had already squash-merged the PR as 25dc75d917ea4ec911532abfe4c4be023b008b29 before this review was submitted, so this review records the exact-head technical approval; it did not authorize an already completed merge.
…e module emit-core hosts can reach the authority it asks Main parses again at 159421d (#10428 re-attached the annotation #10390 orphaned), so this is the one integrate-main push, carrying the build repair with it. THE BUILD FAILURE THIS FIXES, AT ITS ROOT RATHER THAN AT ITS SYMPTOM. v1_compiler_emit_core_support is compiled TWICE from one file: once inside v1-compiler, where crate::v1_compiler_parse resolves, and once inside v1-stage0-emit-core via #[path], where the crate root offered eight modules and parse was not one of them. Its reachable set is the INTERSECTION of two crate roots, so consuming the parser's single authority for "is this item a resource" compiled in one and E0432/E0433'd in the other. The emit-core crate's own generated doc says it exists to host that module "without copying semantics". The missing name was defeating that: the alternatives were to FORK the predicate into a module that cannot see the minting vocabulary it is defined against, or to SCATTER the exclusion across the call sites. So the boundary was the defect, not the predicate, and the fix is to make the root set true rather than to work around it. WHY NOT THE OTHER ARMS, since a reviewer meeting a partition edit inside a namespace-cut PR should not have to reconstruct this. MOVE the predicate down beside Node. Rejected: it is defined NEGATIVELY over parse's minting vocabulary -- true if any property's name is not "sole_constructor" -- so it is a statement ABOUT that vocabulary, and v1.compiler.parse's own note scopes it "complete against the parser's minting vocabulary AS OF THIS COMMIT". A definition whose truth is maintained by a module it cannot see is a fork with a delay on it. APPLY THE EXCLUSION IN THE CALLERS. Rejected on its own measurement. The hypothesis was four call sites; the enumeration is 24 call expressions in 12 functions across v1.compiler.emit_rust (19/9), emit_go, emit_python, trait_derive_emit, plus the census reader. Twelve hand-applied exclusions is twelve places the next property-minting modifier reintroduces the defect with nothing watching -- verbatim the failure parse's note predicts. WHAT LANDS. v1_compiler_parse joins the v1-infer unit and std_import joins std-core, chosen for LAYER: parse is a pipeline stage and sits beside v1_compiler_coercion and the infer modules. parse is a SOURCE in that unit -- nothing there is reachable from it -- so the unit graph gains no edge back, and validate_partition_r4 adjudicates that mechanically via SccSplit/UnitGraphCycle rather than by this paragraph. Every generated artifact in the chain was regenerated through its authority: the roster by the generated-artifact gate, the stage0 mirrors by --required-regen, the crate manifests and lib roots by --emit-partition-crates. No hand-edited generated bytes. THE TRANSITIVE CLOSURE IS THE CHECK, NOT THE IMMEDIATE DEPENDENCIES. An earlier report of this change said parse depends on eight modules and std_import on two. That is the immediate set and it passes cleanly on a closure that fails two levels down. The transitive closure of both seeds is 29 modules; 27 are already partitioned and the 2 remaining are the seeds themselves, so nothing else is dragged in -- corroborated independently by the emitter, which drifted three lib roots and NO Cargo manifest, meaning no new inter-crate dependency was required. THE ADMISSION ENTRY WAS RE-APPLIED ACROSS THIS MERGE, NOT CARRIED. The conflicting hunk was a misaligned array head -- this cohort's label line against the SCM cohort's, with the body below the marker belonging to the other subject -- so resolving the markers in place would have spliced one cohort's rows onto another's body. Main's file was taken whole and the delta re-derived at ROW IDENTITY grain against the merge base: 2 added here, 0 removed, against main's 29 additions and 254 removals. Merged array is 32 rows, no row of either side dark. The entry is renumbered TWENTY-THIRD and its citation of the now-dissolved twenty-sixth entry repointed, because #10355 deleted the entry it named. Verified by execution on the merged tree, not by inspection: cargo build green with the repair present and reached, cargo clippy --all-targets -D warnings clean, and compiler_tests::a_resource_item_is_not_read_as_a_type_item passing with its positive control, resource discriminator, sole_constructor over-correction guard and two-reader agreement assertion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg
… converge() this change removes One conflicted path, dag/gunbc/repo/repo_ruleset.dag, resolved to preserve BOTH authorized deltas rather than by taking a side: - #10378's contention-rate annotation (its first hunk) auto-merged untouched. - #10378's SECOND delta was deleting three dead `String` rows -- repo_ruleset_converge_entry / _converge_function / _verify_function. That is the §4c prose-as-data cleanup this branch had identified and routed to MAIN-Q; it landed there first, so the deletion is taken and the two rows this branch still carried are gone. - This branch's world_* handler restructuring is kept whole. MAIN'S "VERIFY IS READ-ONLY AND CONVERGE WRITES" NOTE IS DROPPED, and that is the one resolution that is not mechanical. It describes two entry points; this change deletes the mutating one along with apply_desired_ruleset, so after the merge the file declares `verify()` and nothing else, and nothing in the tree cites `apply_desired_ruleset` or `repo_ruleset_converge_function`. Keeping the note would leave a §3 citation of a symbol that no longer exists -- a note is not preserved by being carried, only by staying true. THE ROSTER ORDINAL IS RENUMBERED TWENTY-FIRST -> TWENTY-THIRD, which the merge forces and a grep would have hidden. Main's highest transition is now TWENTY-SECOND (#10355), so TWENTY-FIRST follows nothing. It is also not free for the taking: #10355 was itself numbered twenty-first on an earlier head and renumbered rather than reused, so that a citation of "the twenty-first entry" would not resolve to two rows across time. An abandoned ordinal and an unused one are indistinguishable by counting, so the vacancy is a trap rather than an invitation. The consumed-row obligation is discharged by main's own deletion: the roster goes 258 -> 33 rows, being main's 31 plus this change's 2, which is exactly the blocker run 33889309585 reported (255 consumed admissions due on a roster-touching change) while its floor read FloorClean with claims_failed=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015EdHQ244XXdBKRKGX6jrV4
The namespace-wave-admission phase refused with `0 unadjudicated delta(s), 0 stale admission(s), 30 CONSUMED ADMISSION(S) DUE FOR DELETION ON THIS ROSTER-TOUCH`. The zero/zero half is the good reading -- this branch's own namespace work is clean. What refuses is the obligation the roster imposes on whoever touches it next: #10355 is in this branch's base, so its rows are satisfied at the base, and a consumed row comes due on the roster's own next touch. This change touches it. ADJUDICATED BY THE DECLARING-MODULE JOIN, NOT BY THE TRIGGER SENTENCE, because the entry being retired says in terms that a trigger sentence is not evidence the trigger fired. Each row was joined against MAIN's tree by its own (module, in_declaration, spelling, target) tuple: 30 of 30 name a spelling DECLARED in gunbc.scm.proposal, none open. Rows checked equals rows in label equals the count the wall reported -- 30 = 30 = 30 -- so the subject was not silently narrowed by a parser that could not see some of it. ONE OF THIS FILE'S TWO RECORDED JOIN FAILURE MODES ACTUALLY FIRED. RequireBinding and RequireBindingAbsent are COPRODUCT VARIANTS rather than data/fn/type declarations, so a declaration index reading only line-start declarations would have answered "not found" for both -- indistinguishable from "not declared", which is precisely the defect the TWENTY-NINTH DISSOLUTION records catching on its second pass. The join resolves variants and fields as well as declarations, and it was CALIBRATED rather than trusted: MergeCommit, ObjectStore and a fabricated name all answer NOT DECLARED against the same module, so a uniform "found" was not available to it. The two gunbc#10350 kernel-identity rows REMAIN. They are not consumed: this PR has not merged, so the base does not carry the relocation and the deltas are still producible. Their own deletion is owed to the first roster-touch after this lands, by the same join. SCM_PROPOSAL_VOCABULARY_LABEL is deleted with its rows, and the cohort's entry is retitled as the THIRTIETH DISSOLUTION recording the adjudication, including what the hand join does NOT establish: it is a necessary condition only, since admission_consumed_at_base resolves the full subject through the re-export chain and requires an exact singleton, which no hand join reproduces. The wall's own run at the exact head is the proof. The remaining required-witnesses-floor red is NOT addressed here and is not this branch's: STALE-QUARANTINE on test.claim.declared_type_expected_type_path_witness, inherited from #10402 landing a wall without retiring the expected-red row it greened. It is owed a standalone repair; carrying it here would put main's recovery inside a feature PR that is separately blocked on review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg
…ons this change came due on NOT A JUDGEMENT CALL, AND NOT MY COHORT. The required namespace-wave-admission phase reported them by identity on this branch's head -- 30 of 30 `CONSUMED ADMISSION`, all the gunbc#10355 SCM proposal-vocabulary rows -- with `0 unadjudicated delta(s), 0 stale admission(s)`. #10355 has merged, the base binds each spelling to `gunbc.scm.proposal`, and the deltas have stopped being producible. `SCM_PROPOSAL_VOCABULARY_LABEL` goes with them, since nothing cites it once the rows are gone. WHY A PR ABOUT FN-ARROW REACHABILITY IS DELETING SCM VOCABULARY ROWS: the roster's standing rule is that a consumed row's deletion comes due on the roster's NEXT TOUCH, whoever touches it. That rule is the only thing keeping an append-only ledger from growing without bound, and it only works if the lane that touches the file pays it rather than passing it on. This change touches the roster, so it pays. The ledger is now 3 rows: this PR's 2 and one other. THE OTHER FLOOR FAILURE ON THAT SAME RUN IS NOT ADDRESSED HERE BECAUSE IT IS NOT A DEFECT. `TERMINAL-LEDGER REFUSAL cause=WireAuthorityUnresolved ... MemoryStallRefusedPageThrash` is the floor refusing a runner that refaulted its own evicted pages at 263455 major faults/minute while computing for 4% of the wall. That is the machine failing to deliver the admitted budget, reported as a typed, located refusal rather than a silent slow green -- the mechanism working. It is retry-eligible and nothing in this diff moves it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
… of above the module that had to re-spell it (#10350) * Home the kernel-identity authority beside the minter it asks, instead of above the module that had to re-spell it XL-0B's first constraint, discharged. gunbc.type_reference_decl_file_occurrence_census's kernel-minted-provenance row states it: the KernelMinted arm must be DERIVED from resolved_node_is_kernel_identity_for_name rather than re-spelled, "because a fifth prefix test would add an authority while claiming to remove four." THE FORK WAS POSITIONAL. v1.compiler.infer_env DECLARED that predicate and never called it. The module that mints the span it tests -- v1.std.core, whose kernel_span synthesizes "<kernel:NAME>" -- cannot import infer_env without closing a cycle, so declaration_provenance_of re-derived the same comparison in place. One fact, two spellings, for no reason but where the declaration sat. The predicate now lives in v1.std.core beside kernel_span, and declaration_provenance_of reads it. AND THE SPELLING IT REPLACED WAS THE WEAKER ONE, which the census had not counted. The infer_env body inlined concat("<kernel:", name, ">"), reproducing kernel_span's output by hand -- so it was a second authority for the span FORMAT as well as for the identity question. The relocated body asks kernel_span. Editing that format used to leave the recognizer answering the old shape with no refusal anywhere; that divergence now has no constructor. EVIDENCE, BOTH DIRECTIONS, BY EXECUTION. ct_kernel_identity_single_authority_test runs in the required rust-unit-tests job under `cargo test --release -p v1-compiler --lib`. Green as authored. Red under exactly the mutation it exists to catch -- exact equality replaced by a "<kernel:" prefix test -- failing on the discriminating row (a node carrying a kernel span for a DIFFERENT name), with a positive control that stops that row being satisfied by a predicate that had simply stopped answering true. Enrolled per DESIGN 4b(4): the climb keeps its discriminating red. That suite is RED ON MAIN independently of this change -- 16 failed / 728 passed on an unmodified tree at e5a51d6, measured by running the identical command on a clean checkout before attributing anything here. The failures are host/index-sensitive (schedule_retention, regen_round_cost, required_floor) and are not touched by this diff. SCOPE, STATED SO THE LARGER HALF IS NOT READ AS DONE. This discharges the FIRST of the two constraints the census names. The second is untouched and is bigger: CorpusDeclared still carries decl_file as a position, so the DeclarationCarrier half std.repair_input_origin explicitly defers to XL-0B/C is still owed. Both ledger rows are updated to say so and to cite the predicate at its new home rather than at the stale (and, in state_space_conflation, never-existent "v1.compiler.env") one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * Escape the quotes in the census row's prose so the module index can parse it The XL-0B receipt I appended to gunbc.type_reference_decl_file_occurrence_census quoted the spelling it was retiring -- concat("<kernel:", name, ">") -- with RAW double quotes inside a .dag String literal, which terminates the string and makes the source unparseable. The module index then refuses the whole corpus, so heal-generated-artifacts could not index the tree and never reached the regeneration the design-ledger carve-out delegates to it. The file already uses the escaped form for exactly this; the added row now matches it. AND THE DIAGNOSTIC'S LOCATION IS A BYTE OFFSET WEARING A LINE NUMBER'S CLOTHES. It reads `dag/gunbc/type_reference_decl_file_occurrence_census.dag:15713-15714`, and that file is 526 lines in every tree -- main, this head, and the merge result. 15713 is the BYTE offset of the opening quote of the broken literal. So the span is correct and its RENDERING sends every reader to a line that does not exist. Filed separately rather than fixed here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * Emit the assertion message with a positional placeholder: {name} interpolates in a .dag string The emitter row I added spelled its Rust assertion message with an inline format capture, `{name}`. Inside a .dag String literal that brace form is INTERPOLATION, so the compiler resolved a variable `name` that does not exist in ct_kernel_identity_single_authority_test and refused the v2 self-compile. The bare `{}` placeholder already used elsewhere in this file does not interpolate, so the message takes an explicit argument instead. THIS ERROR WAS HIDDEN BEHIND THE PARSE REFUSAL and is the reason the whole-corpus pass matters: while the module index refused to build, nothing downstream ran, so a second defect in a different file sat invisible behind the first. Two sequential whole-tree runs were needed to see both, and neither is visible to a cargo build of the seed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * File the mislocated-span class: a located refusal that renders a byte offset as a line Filed at the manager's request after gunbc#10350's module-index refusal cited dag/gunbc/type_reference_decl_file_occurrence_census.dag:15713-15714 in a file that is 526 lines in every tree. The span was CORRECT: 15713 is a byte offset, and the path was right. Only the rendering was wrong, and 'path:N-M' declares no unit, so the reader cannot tell which they hold. WHY IT EARNS A ROW RATHER THAN A FIX AT THE SITE. The reader who hit it did the correct diligence -- checked the cited file in main, the PR head and the merge result, confirmed it is not a generated artifact, declined to guess -- and was defeated anyway, authoring two candidate mechanisms (wrong path attribution, corpus-global line index) that were both false and neither eliminable from the log. A diagnostic that defeats correct diligence is the subject, not the quoting bug that surfaced it. It is the fabricated-plausible-output shape applied to a diagnostic's own span, and it is worse than an unlocated refusal rather than better: an unlocated refusal makes the reader search and they know it, while a confidently mislocated one makes them doubt the path and the tool. CEILING is rung 4 and the class is decidable, so the row names the capability rather than an artifact: a span type whose constructors distinguish byte offsets from line-column positions, with renderers deriving format from the constructor. That is a change to the span carrier and every renderer, so it is filed at the grain it must be repaired at rather than patched where it appeared. Carrier only -- docs/design-failure-modes.md is authored by heal per gunbc.generated_artifact's HealRegeneratesAfterProvisionalMerge carve-out. Appended at the END of the roster, per its own source-order rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * Cite jolly-ferret's sibling instance: two right-value wrong-rendering diagnostics in one night gunbc#10352 found the floor rendering cost=500ms EXACT from an integer-truncated nanosecond measurement -- comparison correct, refusal correct, rendering defective, and it recruited auditors into filing against the comparator. Same shape as this row's byte-offset-as-line, reached from an unrelated subject by a reader who was not looking for it. Two independent instances is what makes the operative rule worth stating: WHEN A LOCATED DIAGNOSTIC POINTS SOMEWHERE IMPOSSIBLE, DISTRUST THE UNITS BEFORE THE LOCATION. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * chore: regenerate drifted generated artifacts (ci auto-heal) * Regenerate both levels of the compiler-tests emitter chain, in the order the chain forces The regen drift was mine and it was TWO levels, not two files. LEVEL 1 -- v1_compiler_compiler_tests_rust.rs. I added ct_kernel_identity_single_authority_test to src/v1/compiler_tests_rust.dag and never wrote that module's own generated twin. It now carries the new emitter function and its entry in ct_coercion_tests's concat chain. LEVEL 2 -- compiler_tests.rs. Its only difference from the emitter's output was the POSITION of the test: I hand-inserted it before shaped_type_node, the emitter appends it at the end of ct_coercion_tests. Verified as a pure move rather than a content change -- the two files have an IDENTICAL MULTISET OF LINES and equal byte length, differing only in order. THE ORDER OF THE TWO PASSES IS FORCED AND THE NAIVE FIX IS SILENTLY DESTRUCTIVE. compiler_tests.rs is emitted by the seed's COMPILED-IN emitter, so a first-pass candidate is produced by the emitter as it was BEFORE this change -- it cannot emit a test it does not know about. That candidate was 134 lines short, exactly the size of the test, and copying it would have DELETED the enrolled RED while satisfying the drift check: a green PR whose discriminating probe no longer exists. So: pass 1 installs the emitter's own mirror, the seed is REBUILT so the emitter knows the test, and pass 2 produces a compiler_tests.rs that contains it -- 4521 lines, matching, with the test present. Checked rather than assumed: both files are byte-identical to their pass-2 candidates after cargo fmt, so formatting cannot re-introduce drift; the test and its discriminating assertion are present in the committed bytes. Regenerated on top of ce937d0, merged first because #10282 reshapes the marshal and a candidate computed on the older base could have been bytes that fight it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * chore: regenerate drifted generated artifacts (ci auto-heal) * chore: regenerate drifted generated artifacts (ci auto-heal) * Adjudicate the relocation's two binding deltas by name, and stop the emit side reading a resource as a type TWO SEPARATE THINGS LAND TOGETHER BECAUSE CI IS THE BINDING CONSTRAINT, not because they are one change: the wave-admission rows this PR's own relocation requires, and the emit-side repair the type-occurrence census refusal pointed at. -- THE ADMISSION ROWS -- required-ci refused with `namespace-wave-admission (2 unadjudicated delta(s), 0 stale admission(s), 16 consumed admission(s))`. The two deltas are this PR's whole content: TargetChanged binding v1.compiler.infer::ancestry_binding_is_kernel_identity TargetChanged binding v1.compiler.emit_rust::import_name_resolves_to_host_realized_kernel_scalar both for `resolved_node_is_kernel_identity_for_name`, base {v1.compiler.infer_env} -> head {v1.std.core}. A relocation MUST produce TargetChanged bindings; the wall refusing until someone says so out loud is the wall working. They are UNADJUDICATED, not unadjudicatable. Adjudicated at full identity grain -- module, in_declaration, spelling, target -- one row per delta, so the count goes 2 -> 0 by naming both subjects and not by widening. A third delta of the same shape still refuses, which is what makes this distinguishable from erasing the subject. The rows are born with their own death declared: when this merges, base and head both carry the relocation, no run can produce these deltas, and both go STALE -- which reds every unrelated PR. The trigger beside them says explicitly not to trust itself: join each row against MAIN'S tree on its own tuple, and assert rows-checked equals rows-in-label, because a path guessed from a module path reads empty and empty reads identically to "the binding is absent" -- the mechanism that nearly carried 128 rows wrongly on the twenty-sixth entry. -- THE EMIT-SIDE REPAIR -- The activation-revision recensus refused: CensusUnavailable { cause: DeclarationDomainDisagrees }, two occurrences, `dag/std/resources.dag::Network` and `::AuthContext`. The cause was already authored in the tree. v1.compiler.parse's classifier gained a resource arm, dropping divergence from 202 items across 100 modules to these two, and its note ends: "Repairing the emit-side shape predicates is a change to a different authority and is deliberately not smuggled in here." This is that repair. Those two resources declare NO capabilities, so they carry no children, no body, no params and no connective -- they ARE bare leaves by shape, so the emit side read them as type items while the parser read them as resources. Not instrument-only: all three emitters test is_type_decl_item BEFORE is_resource_def_item, so both were EMITTED AS TYPE DECLARATIONS and the resource arm was unreachable for them. The exclusion DERIVES rather than re-spelling: is_type_alias_item and is_type_decl_item ask v1.compiler.parse parsed_item_carries_resource_entries, the same single authority the parser asks, so "what a resource item is" has one definition and these are two consumers of it. Spelling the shape again here is what produced the divergence. NOT PLACED IN is_bare_leaf_item, which would have been one site instead of two: that predicate is a statement about SHAPE, a capability-less resource genuinely IS a bare leaf, and it has consumers outside these arms whose meaning depends on its params-count claim -- narrowing it would have silently changed alias hopping instead of resource classification. AND NOT REPAIRED BY REORDERING THE CHAIN, which would also have greened the census. is_resource_def_item still COUNTS properties -- the shape parse already had to fix -- so it would claim any sole_constructor type, masked today only because the type arms run first. Reordering would have ARMED that over 202 items while turning the instrument green. That dormant defect is filed as the failure-mode row dispatch_correctness_resting_on_arm_order: mitigatable today, ceiling structurally impossible, and its next-rung trigger names the CAPABILITY -- a positive item kind carried on the emit side, so dispatch derives as an exhaustive match and cannot be order-sensitive. -- EVIDENCE -- The enrolled test asserts the composite the census actually joins on -- is_type_def_item OR is_type_alias_item OR is_type_decl_item -- and not one arm. An earlier draft asserted is_type_decl_item for a property-free bare leaf and went RED: with no inferred type such an item reads as a type ALIAS. It is still a type item; the arm was the wrong subject, and a control that had passed by luck would have shipped a test measuring something other than the refusal. Four rows: the positive control, the resource discriminator (removing the exclusion turns it true), an over-correction guard asserting a sole_constructor-only item is STILL a type item so the exclusion can never be re-spelled as a property count, and a reader-agreement equality that fails from either side. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * Restore the generated mirrors from this branch's side so the tree compiles before regeneration Taking main's side of the four generated artifacts during the merge was wrong in a way the merge itself could not show. v1_compiler_emit_rust.rs on main still calls crate::v1_compiler_infer_env::resolved_node_is_kernel_identity_for_name -- the symbol THIS BRANCH MOVED to v1.std.core -- so the merged tree did not compile, and a tree that does not compile cannot be regenerated. The plan 'take theirs, regen will supply the truth' has a precondition I did not state: regen must be able to BUILD, and the file breaking the build was the one waiting to be regenerated. Restored all four from this branch's pre-merge head, which is a compiling tree. These bytes are still not authored on either side and are not the answer -- they are a build-able starting point so the regeneration can produce the real ones from the merged .dag authorities, which carry both this branch's relocation and main's changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * Bootstrap the emit mirror to a tree that compiles: main's bytes plus this branch's three-substitution delta NEITHER SIDE OF v1_compiler_emit_rust.rs COMPILES AGAINST THE MERGED TREE, which is why two regen attempts died at 127 with no regeneration running at all. Main's copy calls crate::v1_compiler_infer_env::resolved_node_is_kernel_identity_for_name -- the symbol this branch moved -- and fails E0432. This branch's copy predates main's call-arity change and fails E0061. The file that must be regenerated is the file preventing the build that produces the regenerator. Broken by applying THIS BRANCH'S DELTA to MAIN'S BYTES, counted rather than eyeballed: three substitutions, each asserted to occur exactly once before replacement -- drop the spelling from the v1.compiler.infer_env re-export list, add it to the v1.std.core import list in the slot this branch uses, repoint the single call site. Post-conditions asserted: zero stale references remain, exactly one repointed reference exists. The re-wrap that follows is cargo fmt's, not mine: the pre-commit hook refused the hand edit until the import list was re-wrapped, which is the hook catching exactly the class of damage hand-editing a generated file does. The other three generated artifacts are taken from main verbatim, because none references the moved symbol and none needs a delta to build. Confirmed rather than assumed for compiler_tests.rs, which is the one that could have. THESE BYTES ARE A BOOTSTRAP, NOT THE ANSWER. The regeneration that follows overwrites all four from the merged .dag authorities. If the regenerated bytes differ from these, the regenerated ones are right. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * chore: regenerate drifted generated artifacts (ci auto-heal) * Install the regenerated stage0 mirrors, and confirm the bootstrap reproduced the generator exactly The four generated artifacts now carry what --required-regen emits from the merged .dag authorities, produced by the forced two-pass order: install the emitter's own mirror, REBUILD so the emitter knows the new test, then regenerate the file it emits. A single pass emits compiler_tests.rs from the PRE-EDIT emitter, which cannot know a test that was just added. THE BOOTSTRAP WAS EXACT, AND THAT IS A RESULT RATHER THAN AN ASSUMPTION. v1_compiler_emit_rust.rs is ABSENT from this commit: the regenerated bytes are identical to the hand-applied bootstrap, so the three counted substitutions reproduced the generator's output precisely. Had they differed, the generator's bytes would have won and this commit would say so. VERIFIED BY EXECUTION, NOT BY COMPILE: cargo test --release -p v1-compiler --lib on the regenerated tree runs a_resource_item_is_not_read_as_a_type_item and it PASSES. The over-correction guard -- a sole_constructor-only item must still read as a type item -- is present in the emitted bytes, so the exclusion cannot be silently re-spelled as a property count without this going red. Both files are byte-identical after cargo fmt, so formatting cannot re-introduce drift. docs/design-failure-modes.md is deliberately NOT updated here. --required-regen does not emit it -- a run where all four .rs mirrors installed cleanly produced no projection candidate at all -- because that artifact is heal's under the design-ledger carve-out. The tree therefore lands authority-ahead-of-artifact on that one file BY DESIGN: the roster carries 101 rows and the projection 99. That is the state heal repairs and the generated-artifact gate can see. The state nothing downstream can see -- a row deleted -- was checked for by set difference against main and is absent. THE 16 SUITE FAILURES ARE MAIN'S, ESTABLISHED BY AN IDENTITY JOIN AND NOT BY A COUNT. Two trees on one runner, preconditions asserted before the comparison was trusted: the patch present in one (4 references) and absent in the other (0), and the two tree shas required to differ. Failing test NAMES compared as sets: mine MINUS main is EMPTY, main MINUS mine is EMPTY. An earlier attempt at this join was VACUOUS -- both arms silently measured the same tree, which guarantees identical sets by construction and looked exactly like the answer. Two sets of sixteen can be disjoint, so the count match established nothing on its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg * chore: regenerate drifted generated artifacts (ci auto-heal) * chore: regenerate drifted generated artifacts (ci auto-heal) * Retire the 30 consumed gunbc#10355 admissions this roster-touch owes The namespace-wave-admission phase refused with `0 unadjudicated delta(s), 0 stale admission(s), 30 CONSUMED ADMISSION(S) DUE FOR DELETION ON THIS ROSTER-TOUCH`. The zero/zero half is the good reading -- this branch's own namespace work is clean. What refuses is the obligation the roster imposes on whoever touches it next: #10355 is in this branch's base, so its rows are satisfied at the base, and a consumed row comes due on the roster's own next touch. This change touches it. ADJUDICATED BY THE DECLARING-MODULE JOIN, NOT BY THE TRIGGER SENTENCE, because the entry being retired says in terms that a trigger sentence is not evidence the trigger fired. Each row was joined against MAIN's tree by its own (module, in_declaration, spelling, target) tuple: 30 of 30 name a spelling DECLARED in gunbc.scm.proposal, none open. Rows checked equals rows in label equals the count the wall reported -- 30 = 30 = 30 -- so the subject was not silently narrowed by a parser that could not see some of it. ONE OF THIS FILE'S TWO RECORDED JOIN FAILURE MODES ACTUALLY FIRED. RequireBinding and RequireBindingAbsent are COPRODUCT VARIANTS rather than data/fn/type declarations, so a declaration index reading only line-start declarations would have answered "not found" for both -- indistinguishable from "not declared", which is precisely the defect the TWENTY-NINTH DISSOLUTION records catching on its second pass. The join resolves variants and fields as well as declarations, and it was CALIBRATED rather than trusted: MergeCommit, ObjectStore and a fabricated name all answer NOT DECLARED against the same module, so a uniform "found" was not available to it. The two gunbc#10350 kernel-identity rows REMAIN. They are not consumed: this PR has not merged, so the base does not carry the relocation and the deltas are still producible. Their own deletion is owed to the first roster-touch after this lands, by the same join. SCM_PROPOSAL_VOCABULARY_LABEL is deleted with its rows, and the cohort's entry is retitled as the THIRTIETH DISSOLUTION recording the adjudication, including what the hand join does NOT establish: it is a necessary condition only, since admission_consumed_at_base resolves the full subject through the re-export chain and requires an exact singleton, which no hand join reproduces. The wall's own run at the exact head is the proof. The remaining required-witnesses-floor red is NOT addressed here and is not this branch's: STALE-QUARANTINE on test.claim.declared_type_expected_type_path_witness, inherited from #10402 landing a wall without retiring the expected-red row it greened. It is owed a standalone repair; carrying it here would put main's recovery inside a feature PR that is separately blocked on review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018vz8ESEVFC7Cox1xAaXudg --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
…ranch's next touch All 22 `gunbc#10445` rows are deleted -- 17 object-table codec-move and 5 semantic-target constructor -- along with both label consts. Reported by identity as `CONSUMED ADMISSION`, 22 of 22, by the required namespace-wave-admission phase on this branch's own head: #10445 has merged and none of the deltas is producible against the base any more. RUNNING TOTAL ON ONE BRANCH: 30 (#10355) + 2 (#10350) + 6 (#10439) + 22 (#10445) = 60 rows dissolved for four cohorts, none of them this PR's, because every sync with main is a roster touch and a consumed row's deletion comes due on the touch. THE RATE IS THE OBSERVATION, not the payments. Four cohorts became consumed inside one open branch's lifetime, which means main is landing roster-touching transitions faster than a branch can finish a CI cycle. That is not an argument against the rule -- the ledger stands at 2 rows instead of 62 precisely because it is paid on touch -- but it does mean the toll scales with how long a branch stays open, and the honest way to shrink it is shorter branches, not deferred payment. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ
…aced, and BOTH are blind at a declaration root (#10300) * fn_index: the depth-one callee read agrees with the fold_node it replaced, and BOTH are blind at a declaration root DECIDED BY EXECUTION, both halves. AGREEMENT: yes, exactly. #10156's `atom_identities_in_node` and the `fold_node` reader it replaced return the same list on every one of 1777 live fn-arrow declarations. The old fold's step read `child.node` and DISCARDED `child.atoms`, so its whole-subtree descent produced immediate-children-only — the annotation's "extensionally the same function" claim is true. `v2.lens.fn_index_depth_agreement` is the reconstruction and the verdict; it refuses if the two ever diverge. SEEDS NOTHING: also yes, and it is not a regression — it is a pre-existing defect BOTH readers share. `marshal_generic` emits every node as a Conj record carrying its callee atom as a positional child, so a callee is one level under the body root only when the body IS that one call; a `let`-block body carries its callees two or more levels down. Of 1777 declarations, 877 had callees no depth-one read of `decl.output` could see, and the depth-one reader returned 890 of 8908 subtree atom identities. `call_reachable_decls` was therefore leaving only the single-call declarations, and its three consumers — v2.lens.determinism, v2.lens.effect_reach, v2.lens.live_read_classification — were green over a call graph with most of its edges missing. THE FIX: `callees_from_node` reads the new `atom_identities_in_subtree`. `atom_identities_in_node` is unchanged — depth one is the right grain for the two lens folds that apply it per node of their own descent, and the wrong grain only at a root. WHY NOBODY SAW IT: the fixture had been flattened to match the reader. The determinism witness carried a note asserting the marshal hoists callee atoms onto the body root, so the fixture must be flat. That premise is false, and the accommodation made the reader's grain the check's specification. New rows `leak_reached_through_a_nested_body_is_found` and `nested_entry_does_not_reach_a_leak_outside_the_call_graph` hold the real shape; the first is RED against a depth-one reader and is the only one of the five that flips, measured by reverting the one line. Filed as `gunbc.recurring_failure_mode` `fixture_flattened_to_the_reader_grain_it_should_falsify`. EVIDENCE, ALL EXECUTED on this tree with a locally built gunbc: - v2.lens.fn_index_depth_agreement `fn_index_depth_agreement` — exit 0. - all 5 rows of determinism_transitive_witness green; the mutant (callees_from_node back on atom_identities_in_node) reds exactly the nested row. - all 26 rows of effect_reach_test and live_read_classification_test green, including every negative control (severed_mid_hop_is_local_read, effect_reach_hermetic_fixture_stays_local_holds, red_control_roster_gate_severed_is_local, g2_complete_facts_reachable_home_without_carrier_call_is_local). - whole-corpus cost unchanged: 1m58s before and after, dominated by the fn_arrow_decl_facts_live acquisition. ALSO REPAIRED, BECAUSE IT BLOCKED REGENERATION: `gunbc.recurring_failure_mode` carried `absence_classifier_default_bucket` and `green_reported_over_a_population_the_instrument_does_not_own` twice each, byte-identical, on main. `main_wet` refuses the module with `duplicate declaration`, so no lane could regenerate docs/design-failure-modes.md. The second copy of each is deleted; the roster listed each once, so the projection is unchanged apart from the new row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * Address review 59534: the atom channel has several senders, so exclude the one that is DECLARED and name the residue THE FINDING IS CORRECT AND IS OLDER THAN THIS PR. `marshal_generic` emits one indistinguishable `edge_positional(atom_identity_node(..))` for a call's callee, a record-constructor spelling, a parameter reference, a nullary variant value and a string literal. `node_atom_identity_optional` sees one Atom connective in every case, so reading the atom channel follows more than calls. The depth-one reader had the same unsoundness on immediate children — `is_path_like_lexeme` is the scar of it — and the transitive read enlarges the population rather than introducing the class. EXCLUDED, FROM DECLARED STRUCTURE: a reference to one of the declaration's OWN parameters. `FnArrowDecl.params` carries those lexemes, so this is a subtraction from a declared field, not a shape guess; `v2.lens.effect_reach` already makes it on its literal channel. `callees_from_node` takes `param_names` and `call_reachable_decls_go` passes `param_names_of(seed)`. Measured live: `param_collisions: 2` of 1781 declarations reference a parameter whose lexeme also names a declaration — two false call edges that no longer exist. CONTROLS, BOTH NEW AND BOTH EXECUTED: - a_parameter_reference_naming_a_declaration_is_not_a_call_edge — the entry's body references `orphan_fn`, which is both its own parameter name and the name of a leaking declaration in the closure. Green; RED against the reader with the exclusion line deleted (measured). - the_same_reference_without_the_parameter_collision_is_a_call_edge — same body, same callee, parameter renamed. Green in both arms, so the row above is not green by reaching nothing. Only the parameter name differs between them. THE RESIDUE IS DECLARED, NOT CLAIMED AWAY. Record-constructor spellings, nullary variant values and non-path literals stay indistinguishable from callees. It is a structural over-approximation computed AS the answer (DESIGN §5's named non-instance of the absorbing fallback), it widens toward FINDING more rather than missing more, and the annotation on `callees_from_node` carries the next-rung trigger as a CAPABILITY: a fn-arrow body projection in which the callee position is structurally identified. No fixture can express those senders today — the skeleton gives them no distinguishing shape — which is why that is a trigger and not a missing test. It is the subject of the parent lane (cool-fox-470). ALSO, §3: `param_names_of` existed byte-identically in v2.lens.effect_reach and v2.lens.live_read_classification. Both copies deleted; both import the fn_index one. All 33 rows green after the change: 7 determinism_transitive_witness, 8 effect_reach_test, 18 live_read_classification_test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * Enrol v2.lens.fn_index_depth_agreement as registry infra: it is an instrument, not an enforcing lens CI on 353f33d failed two required rows and both had one cause: the new module sits under `v2.lens.` with three path segments, so lens_registry_completeness classified it a candidate lens and lens_module_gate_holds / lens_closure_question_zero_holds_live refused it as unenrolled. Reproduced locally (both returned false), and both return true with this row. Filed on the known-infra roster rather than as a LensIdV0 entry, because it enforces nothing: it carries no verdict authority over a production population, it backs two claims in v2.std.fn_index so they are re-derivable rather than transcribed, and it reads the whole-corpus acquisition, so it is deliberately not a floor subject. Nesting the module one level deeper would also have silenced the gate — `under_nested_prefix` excludes anything past three segments — and that is the dodge, not the answer: the module would still be an unclassified v2.lens.* and the gate would be answering about its path rather than its role. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * chore: regenerate drifted generated artifacts (ci auto-heal) * The depth-agreement instrument could not execute: repair its call, its annotation grain, and its cost shape Review 60130 is CORRECT and the defect was real. This module has never been compiled by anything -- it is not a floor witness, no phase resolves it, and nothing imports it -- so three independent breakages accumulated in it silently. That is precisely the inert-lens tier DESIGN section 6 warns about, arriving in the evidence for a claim rather than in the claim. 1. THE CALL SHAPE. gunbc#10245 made the subject caller-named: `fn_arrow_decl_facts_live` takes `pool_roots` and `pool_files`, and the zero-arity form was deleted. The instrument still called it with no arguments, so every number this PR cites as re-derivable was in fact transcribed. It now declares `agreement_pool_roots = ["dag", "src/v2"]` -- the two roots the required lanes pass -- and names them at the call site. The annotation that called it "the zero-arity whole-tree acquisition" is corrected too, since it asserted the deleted shape. 2. THE ANNOTATION GRAIN. A record field whose value sat on the following line failed to parse, and the resulting resolve failure reported itself as sixteen "source annotation names no subject" errors -- a cascade, not the cause. Fixed at the cause. 3. THE COST SHAPE. The call-channel reader added here first collected callee lexemes into a list and deduplicated with a linear scan inside a per-node fold, which is quadratic over a 60k-node corpus and did not terminate in twenty minutes. DESIGN section 6's bare-minimum-cost rule says a proven cost-shape defect is always fixed, instrument or not. It is now an Int count. WHAT THE CALL-CHANNEL COUNTERS ARE FOR. Review 60065 asks for `callees_from_node` to move off the whole-subtree atom scan and onto `node_is_call` / `call_callee_target`. Swapping a loud over-approximation for a silent under-approximation would be strictly worse under DESIGN section 5, and only execution can say which this would be, so `channel_call_shaped_total` counts how many nodes of a live fn-arrow skeleton `node_is_call` accepts at all and `channel_callee_total` how many yield a callee. The measurement is running; the answer goes on the PR, not into prose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * A one-declaration probe for the call channel, because review 60065's question is structural Review 60065 asks that `callees_from_node` move off the whole-subtree atom scan and onto `node_is_call` / `call_callee_target`. Answering it needs one fact first: does the call channel see anything at all on a LIVE fn-arrow skeleton? If it saw nothing, the switch would trade a loud over-approximation for a reader that is green by construction, which DESIGN section 5 makes strictly worse, and no corpus-wide tally would be needed to say so. `first_decl_channel` answers that at a thousandth of the cost of the corpus tally, and its first answer was uninformative in a way worth keeping in the code: the corpus's first declaration is `add`, five nodes, calling nothing, so both readers report zero and the comparison discriminates nothing. The guard is therefore the first declaration the ATOM reader finds callees in, since only there does a zero from the channel mean a lost edge. MEASURED: `no_raw_lifecycle_string_survivors_remain`, two subtree nodes, atom_callees 1, call_shaped 1. The channel is NOT blind on this substrate. That refutes the cheap disposal of review 60065 and makes the corpus-wide comparison the deciding measurement, which is now running. Also here, and the reason the corpus tally is not simply left as it was: the resolved-callee half is now gated on the call-shaped half. `call_callee_target` builds a diagnostic-carrying result per node, and calling it on all 60k nodes ran 35 minutes at 9.8GB without finishing -- on a shared 64GiB slice that is a hazard to other sessions, not just a slow instrument. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * The merge re-added 255 rows main deliberately deleted, and enforce the two claims the verdict left inert TWO DEFECTS, ONE OF THEM MINE FROM A MERGE AND INVISIBLE TO GIT. THE ROSTER. main's TWENTY-NINTH DISSOLUTION (gunbc#10355) deleted all 255 `gunbc#10358` selector-reclass rows AND the `OLLAMA_CHOICE_RECLASS_LABEL` const they cite, on the roster's own consumed-row rule. My branch carried those rows from an earlier merge, so the textual merge unioned them back in while main's deletion of the const won -- 255 rows referencing a name that no longer exists, reported by the required build lane as 255 `cannot find value` errors. Git flagged nothing, because a union re-adding a DELIBERATE deletion is a clean merge by every textual measure; only the deleting commit's own prose says the rows were consumed. The roster is now main's 31 rows plus this PR's 2, verified by label set difference in both directions rather than by count. THE VERDICT, which review 60220 found. `fn_index_depth_agreement` computed four numbers and enforced two. `root_callees_lost_to_depth_one` and `param_collisions` -- claims two and three, the ones that justify this PR's change at all -- were printed and checked by nothing, which is specification without execution sitting inside the instrument built to answer exactly that charge. Both now refuse at ZERO, and the direction is the point: if no live declaration hides a callee below depth one, #10156's reader was adequate and this PR's change to `callees_from_node` bought nothing; if no live declaration references its own parameter by a lexeme that also names a declaration, the parameter exclusion excludes nothing and is dead code defended by prose. Either zero falsifies the PR rather than the corpus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * chore: regenerate drifted generated artifacts (ci auto-heal) * Decide review 60065 by execution: the call channel loses 39% of the edges the atom reader finds MEASURED, over a stated 150-declaration prefix of the live corpus, via `v2.lens.fn_index_depth_agreement.bounded_channel_compare`: compared 150 | atom_callee_total 444 | channel_callee_total 271 channel_fewer 68 of 150 | channel_none_atom_some 21 of 150 So routing `callees_from_node` through `node_is_call` / `call_callee_target` -- what reviews 60065 and 60220 ask for -- would drop 173 of 444 callee edges, find FEWER on 45% of declarations, and go COMPLETELY BLIND on 14% of them. That is a silent under-approximation in a REACHABILITY walk, where a missed edge means a declaration is reported unreachable and eligible for deletion. DESIGN section 5 ranks that strictly below the loud over-approximation it would replace: the atom reader's residue is extra edges, which keep dead code alive; the channel's residue is missing edges, which delete live code. I am not making that trade on the strength of the carrier existing. WHAT I AM NOT CLAIMING. Not that the reviews are wrong about the destination -- the call channel IS the canonical carrier and the atom scan IS a parallel representation under section 3. What the measurement shows is that the channel is not yet complete over the live fn-arrow skeleton, so the move is blocked on the marshal, not on willingness. The rung honesty in `callees_from_node` stays "can climb now but unbuilt" and now has a number behind it instead of a judgement. THE REBUTTAL IS ITSELF FALSIFIABLE, which is the part that keeps it from being prose. The verdict gains a fifth arm that refuses when `channel_none_atom_some` reaches ZERO -- that is, when the channel stops losing whole declarations. On the day the marshal is reshaped, this instrument goes RED and says the refusal to switch is stale. A rebuttal that cannot expire is an opinion. ALSO MEASURED, AND IT BEARS ON THE SAME DECISION: the corpus-wide form of this comparison did not finish in 85 minutes against a 2-minute baseline for the same tally without it, with `call_callee_target` already gated behind `node_is_call` and all collection already reduced to Int counts. The residual 40x is `node_is_call` itself, per node -- a cost the production reader would import into every consumer of call reachability. Hence a bounded population, stated in the result. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * Pay the roster's own rule: delete the 30 consumed gunbc#10355 admissions this change came due on NOT A JUDGEMENT CALL, AND NOT MY COHORT. The required namespace-wave-admission phase reported them by identity on this branch's head -- 30 of 30 `CONSUMED ADMISSION`, all the gunbc#10355 SCM proposal-vocabulary rows -- with `0 unadjudicated delta(s), 0 stale admission(s)`. #10355 has merged, the base binds each spelling to `gunbc.scm.proposal`, and the deltas have stopped being producible. `SCM_PROPOSAL_VOCABULARY_LABEL` goes with them, since nothing cites it once the rows are gone. WHY A PR ABOUT FN-ARROW REACHABILITY IS DELETING SCM VOCABULARY ROWS: the roster's standing rule is that a consumed row's deletion comes due on the roster's NEXT TOUCH, whoever touches it. That rule is the only thing keeping an append-only ledger from growing without bound, and it only works if the lane that touches the file pays it rather than passing it on. This change touches the roster, so it pays. The ledger is now 3 rows: this PR's 2 and one other. THE OTHER FLOOR FAILURE ON THAT SAME RUN IS NOT ADDRESSED HERE BECAUSE IT IS NOT A DEFECT. `TERMINAL-LEDGER REFUSAL cause=WireAuthorityUnresolved ... MemoryStallRefusedPageThrash` is the floor refusing a runner that refaulted its own evicted pages at 263455 major faults/minute while computing for 4% of the wall. That is the machine failing to deliver the admitted budget, reported as a typed, located refusal rather than a silent slow green -- the mechanism working. It is retry-eligible and nothing in this diff moves it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * chore: regenerate drifted generated artifacts (ci auto-heal) * Pay the roster a second time: the gunbc#10350 kernel-identity rows came due on this branch's next touch Both `gunbc#10350` kernel-identity predicate-relocation rows are deleted, and `KERNEL_IDENTITY_RELOCATION_LABEL` with them. Reported by identity as `CONSUMED ADMISSION`, 2 of 2, by the required namespace-wave-admission phase on this branch's own head: #10350 has merged, both `v1.compiler.infer::ancestry_binding_is_kernel_identity` and `v1.compiler.emit_rust::import_name_resolves_to_host_realized_kernel_scalar` bind `resolved_node_is_kernel_identity_for_name` to `v1.std.core` at the base, and neither delta is producible any more. THIS IS THE SECOND SUCH PAYMENT ON ONE BRANCH AND THAT IS NOT A DEFECT. The previous commit deleted 30 consumed `gunbc#10355` rows; a sync with main then brought in a cohort whose own transition had merged in the meantime, and the phase came due again. A long-lived branch touches the roster once per sync and pays whatever the base has consumed since. Passing it on instead is exactly what makes an append-only ledger grow without bound, so the treadmill is the rule working, not friction to route around. The ledger is now this PR's 2 rows and nothing else. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * chore: regenerate drifted generated artifacts (ci auto-heal) * chore: regenerate drifted generated artifacts (ci auto-heal) * Third roster payment: the gunbc#10439 serving-engine rows came due on this branch's next touch All six `gunbc#10439` serving-engine launch-vocabulary rows are deleted, and `SERVING_ENGINE_LAUNCH_VOCABULARY_LABEL` with them. Reported by identity as `CONSUMED ADMISSION`, 6 of 6, by the required namespace-wave-admission phase on this branch's own head: #10439 has merged and none of the six deltas is producible against the base any more. THREE COHORTS, NONE OF THEM MINE, ONE AFTERNOON: 30 `gunbc#10355` rows, then 2 `gunbc#10350`, now 6 `gunbc#10439`. Each was consumed by a merge that landed while this branch was open, and a branch that syncs with main N times touches the roster N times and owes the payment N times. That is the rule working rather than friction to route around, and it is worth stating because the tempting reading is the opposite. The alternative to paying on touch is a roster that only grows, where every stale row refuses unrelated changes and the whole cost lands on whoever touches the file last. Paying three times in an afternoon is the ledger staying small. The ledger is again this PR's 2 rows and nothing else. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ * Read fixture-origin markers at declaration subtree grain (#10365) Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.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 green_reported_over_a_population_the_instrument_does_not_own Ledger-Repair-Judged: docs/design-rung-drops.md * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md state_space_conflation Ledger-Rows-Repaired: docs/design-failure-modes.md receipt_subject_surface_outlives_its_own_production_time Ledger-Rows-Repaired: docs/design-failure-modes.md trigger_satisfied_before_the_row_was_written Ledger-Rows-Repaired: docs/design-failure-modes.md summary_counters_aggregate_over_a_disposition_set_the_verdict_is_not_in Ledger-Rows-Repaired: docs/design-failure-modes.md append_only_carrier_whose_serialization_shares_a_merge_region Ledger-Rows-Repaired: docs/design-failure-modes.md a_live_authority_name_carries_a_superseded_claim Ledger-Rows-Repaired: docs/design-failure-modes.md witness_that_fails_to_compile_is_absent_rather_than_red Ledger-Rows-Repaired: docs/design-failure-modes.md instruction_and_subject_resolved_from_different_revisions Ledger-Repair-Judged: docs/design-rung-drops.md * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing Ledger-Repair-Judged: docs/design-rung-drops.md * Fourth roster payment: the 22 gunbc#10445 SCM rows came due on this branch's next touch All 22 `gunbc#10445` rows are deleted -- 17 object-table codec-move and 5 semantic-target constructor -- along with both label consts. Reported by identity as `CONSUMED ADMISSION`, 22 of 22, by the required namespace-wave-admission phase on this branch's own head: #10445 has merged and none of the deltas is producible against the base any more. RUNNING TOTAL ON ONE BRANCH: 30 (#10355) + 2 (#10350) + 6 (#10439) + 22 (#10445) = 60 rows dissolved for four cohorts, none of them this PR's, because every sync with main is a roster touch and a consumed row's deletion comes due on the touch. THE RATE IS THE OBSERVATION, not the payments. Four cohorts became consumed inside one open branch's lifetime, which means main is landing roster-touching transitions faster than a branch can finish a CI cycle. That is not an argument against the rule -- the ledger stands at 2 rows instead of 62 precisely because it is paid on touch -- but it does mean the toll scales with how long a branch stays open, and the honest way to shrink it is shorter branches, not deferred payment. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiMbkgNdMH85AtppqekZvJ --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com>
What this is
Two things, and they are not the same claim:
behavior-preserving authority migration;
rows consumed by their own merge. That is a deliberate behavior change in a gate, not a no-op.
What the earlier description got wrong, and what it got right
An earlier version of this description called the change "semantically a no-op" and reported
"83 cells", "five affected witness modules", "67 cells" and "all nine touched modules". A later
version over-corrected by withdrawing all of it. The accurate account:
Withdrawing the two true statements along with the three false ones was itself an error: an
over-broad retraction destroys a correct measurement just as a false claim does.
The two moves
gunbc.scm.proposalis extracted as its own authority (new module). It owns the proposalnouns —
Requirement,RequireBinding,RequireBindingAbsent,requirement_role,Proposal,RoleDependency— and deliberately does not depend onObjectStoreorObjectId. The nouns andthe operation over them were one module answering two questions.
gunbc.scm.mergebecomesgunbc.scm.role_requirement_integration. The old spelling was a§3 meaning fork:
mergenamed roles / requirements / supersession, while the same word isowed to two-commit merging, which this kernel does not do and which
gunbc.scm.ancestryis the subject of. One spelling was carrying two contracts. Every type, constructor, function
and executable tag follows the module.
MergeDependencyKindis deliberately not renamed: it is a historical symbol, and rewriting itwould have fabricated a name that never existed. An earlier commit on this branch did exactly that;
it is restored.
Claim identity census — the complete population
Renaming a module re-qualifies every claim it declares, not only the ones whose local name
changed. The full migration is 20 claim-identity migrations — 20 removed identities and 20 added
identities, i.e. 20 declarations whose fully qualified identity changed. (Stating it as "20 claim
identities" was the wrong grain: each transition removes one identity and adds another, so the
symmetric difference holds 40 distinct identity values. The checks below are organised over the 20
old-to-new mappings, which is the right unit for them.)
test.claim.scm_merge_witness.<n>→test.claim.scm_role_requirement_integration_witness.<n>merge_a_role_whose_value_is_a_file_refuses_as_authored_source→integrating_a_role_…;merge_a_role_whose_value_is_a_node_merges→integrating_a_role_whose_value_is_a_node_integrates;merge_a_target_root_that_is_a_file_refuses_as_authored_source→integrating_over_a_target_root_…;merge_a_target_root_that_is_a_node_does_not_refuse→integrating_over_a_target_root_that_is_a_node_does_not_refusetest.claim.scm_commit_closure_json_v2_witness(module identity unchanged), local name changedscm_image_a_role_whose_value_is_a_node_merges→scm_image_a_role_whose_value_is_a_node_integratesChecked against that population, not against the four renamed locals:
docs/plans/dag-native-scm-design.md. None ofthe five is among the four that changed local name, and the document's own module references were
swept to the new identity.
git grep scm_merge_witnessreturns empty across the tree.the three SCM witness modules and that design document; no workflow YAML, roster or coverage join
enrolls it by name, so the re-qualification has no enrollment consequence to migrate.
While verifying the coverage join I found a transcribed count that had rotted: the design
document said "the 15 claims in
test.claim.…" while the module declares 19. It was correct when#8794 wrote it and has been wrong since.
The two sites carrying that count were repaired differently, because they are different subjects.
An earlier version of this section said both now name the module so the population is "re-derived
rather than remembered". That was true of the first repair and is not true on this head:
a cardinality — it needs none;
4 of 13coverage receipt does not point at the current module as an instrument.Doing that was the error: naming a renamed module made an August measurement look re-derived when
nothing re-derived it. It is now historicized to the claim population that existed on 2026-08-21,
is explicitly not a current-completeness claim, and the document states that no current-head join
has re-derived it.
Scope
14 changed files: 11
.dagmodules, 2 Markdown documents, and 1 Rust file —src/v1/stage0/src/namespace_wave_admission.rs, the namespace-admission roster that makes thistransition admissible. An earlier version of this section said "11
.dagmodules and two Markdownfiles" and omitted the Rust file, which is the one that changes gate behaviour.
There is no "nine"; that figure in the withdrawn description corresponded to no command and no
population.
Evidence
Instrument:
target/release/claim_batch --source-root dag --source-root src/v2 --entry <module> --functions <everytest fnthe module declares>, run once per module because--functionsis scoped to the entry.All five witness modules the branch touches were run at head
01a98bf— clean worktree at thatexact commit — and every one exited 0, 82 claims total:
scm_authoringscm_checkout_verbscm_commit_closure_json_v2scm_role_requirement_integrationscm_statusEarlier measurements on this branch (
4bb1aba,8a75218,a749a43,af0a561,3c6e095) were real whentaken and are superseded, not withdrawn. Each stopped governing when a subsequent merge of
origin/mainchanged the measured corpus or the admission roster.af0a561in particular reachedterminal CI success on every required job — workflow
33861883243— before#10358forced themerge that produced this head. That result is parent-head causal evidence, not exact-head
admission, and this branch has now been shown twice that the distinction is not pedantry: the two
merges since have each changed the roster's contents.
This description does not state CI status, deliberately. Any tense-bearing claim about CI in a
mutable body rots twice over: "pending" becomes false when the run completes, and "green" becomes
false when the head moves — both of which have now happened on this branch. Per DESIGN §6 the
instrument is named rather than its output transcribed: CI state for the current head is the
checks list on this PR, which is authoritative and updates itself.
What is stable, because each is bound to a named commit rather than to "now", is the claim-run
table above and the superseded-run note below it.
Run locally, not on BuildBuddy: the remote runner exposes no cgroup
memory.high/memory.max, soclaim_batchrefuses withHostBudgetUnreadablerather than planning against a machine-widenumber, and
GUNBC_*is deliberately not forwarded to remote. CI runs it where the limit binds.Also clean at this head:
cargo fmt --all --check, and zero indented//in.dag(the DESIGNsection 4c module-item-grain proxy) both in the changed files and tree-wide.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9