Repository navigation
A roster whose additive merge resolution does not compile: one-line rows on the two design ledgers - #9898
Conversation
…ows on the two design ledgers The two ledger carriers grow by appended rows, and every row was a multi-line block ending in a suffix every other row also ends in. A three-way merge never includes a shared suffix in the conflict region, so two lanes appending two independent rows get one tail below the markers for two half-blocks above them, and the correct additive resolution gives the first row's closing lines to the second. Rows are now one line each. A one-line row has no tail to lose; the only suffix a merge can factor out is the blank separator, which carries nothing. Measured, discriminating pair, gunbc built from source at d0009ca: RED byte-exact mis-resolved file -> module index refused, exit 1, "dag/gunbc/recurring_failure_mode.dag:65912-65913: expected expression, found Eq" GREEN same two-lane merge against the transformed carrier, same additive resolution -> parses, evaluates, and both appended rows render in the projected ledger. So the class is LOUD, not silent: claim_executor phase 1, the .dag parse sweep over src/v1, dag and src/v2 on the required witnesses lane, is the first phase in the job and a parse error there is a phase failure. No wall is owed and none is written. Strings carried byte-for-byte; regen writes exactly one added line to DESIGN.md and one to docs/design-ledgers.md, both the new failure-mode row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ae8qnkptQ8dhJgbsdJB6cZ
The annotation claimed construction of the one-line row shape. That is true of the thirty rows as they stand and false of the file: nothing enforces row shape on either carrier, so one hand-authored multi-line row restores the two-line tail and the whole geometry. Writable invalid state is mechanically preventable at best, and claiming otherwise is 4b(1) rung inflation sitting in the paragraph an appender reads first. Next-rung trigger named as the capability, not an artifact: a row-shape obligation decided for every declaration of a growth-surface type. data_decl_type_facts already reads a declared type per declaration; the missing producer is one carrying each declaration's source EXTENT, sufficient to refuse a multi-line row at authoring time. Also records the complete loss-state set, all three measured at d0009ca rather than the two previously run: losing both tail lines and losing `}` alone are PARSE refusals at the module index; losing `evidence: [],` alone is a RESOLVE refusal, "missing required field 'evidence'". Nothing silent in the set. Annotation-only: projections unchanged, no regen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ae8qnkptQ8dhJgbsdJB6cZ
A live instance of the class this branch is about: main landed mitigation_injected_where_judgment_declined (#9902) into the same append points. Because this branch had already reshaped the rows, the conflict arrived as WHOLE declarations on both sides rather than two half-blocks over one shared tail, and the resolution was additive with nothing severed. Main's row is kept, converted to the one-line shape, at main's source position; main's roster prefix is preserved and this branch's row appends after it. All 30 of main's `authored` strings carry byte-for-byte. DESIGN.md and docs/design-ledgers.md were left unmerged by the generated-artifact merge driver and are REGENERATED, not hand-resolved: generated_artifact_gate main_wet, exit 0, 35 artifacts written. Against origin/main both projections differ by exactly 1 added line and 0 deleted — this branch's one new row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ae8qnkptQ8dhJgbsdJB6cZ
briansrls
left a comment
There was a problem hiding this comment.
APPROVE ruling at exact head 4b710358a3e94f8acd7366038f6e1ccd84cc6a01. GitHub cannot register the connected PR-author identity's own formal approval, so this comment records the exact-head adjudication.
The two post-approval deltas close without a new blocker.
ae861f9397 removes the inflated construction claim from both carrier annotations and states the actual boundary: the one-line population exists, but row shape is unenforced and a multi-line declaration remains writable. The next-rung trigger is named at capability grain—the missing declaration-source-extent producer sufficient to decide and refuse multi-line declarations of a growth-surface type. The complete tail-loss set is now measured rather than inferred: both lines lost = PARSE refusal, closing brace lost = PARSE refusal, evidence field lost = RESOLVE refusal. That supports the decision not to add a permanently decorative downstream check.
4b710358a3 supplies the real two-sided witness previously owed. Its parents are the corrected PR side ae861f9397 and main 1fc2dec1ea, where #9902 independently appended mitigation_injected_where_judgment_declined to the same growth surface. The result preserves the main row and roster entry over the PR parent with no deletion, preserves the PR row over the main parent, and regenerates the projections as the union: 31 declared rows, 31 rostered identities, empty join differences. This is the requested live union-preservation witness, not a synthetic substitute.
The limit is held correctly: one successful live merge corroborates the repair but does not enforce the row shape or raise its rung. Run 33481728337 is green on this exact SHA—five successful jobs, with only the unrelated qualification battery skipped—and the PR is mergeable.
No blocking concern found. Nothing further is owed for this PR.
Resolves the recurring_failure_mode.dag conflict at identity grain: our one-line row shape, main's grown state_space_conflation authored bytes (#9906) carried verbatim. docs/design-ledgers.md regenerated from the merged authorities, not byte-resolved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STHUYKae35MnDiXb6FP1nN
briansrls
left a comment
There was a problem hiding this comment.
APPROVE ruling at exact head e2f896f03fb3126ac695626aed444e4047c08d19. GitHub cannot register the connected PR-author identity's own formal approval, so this comment records the exact-head adjudication.
This head is a merge-only advance from the previously approved 4b710358a3, with second parent 03890cbcc0. The PR-relative surface remains the same four paths and the substantive change remains the one-line carrier shape, its honestly stated mechanically-preventable rung, and the new failure-mode row.
The live conflict is admissibly resolved: main's expanded state_space_conflation.authored content is retained under the branch's one-line declaration shape, and the generated ledger is regenerated rather than byte-resolved. The reported bidirectional parent-union census closes the only material merge risk: every parent identity survives, no foreign identity appears, the declared/rostered join is empty both ways, and the regenerated projection retains every main-authored row byte-for-byte.
Exact-head workflow run 33500077335 succeeded, including both required lanes, Rust tests/clippy, fabric evidence, and the aggregate check; the PR is mergeable.
One evidence classification: the fixed-point receipt whose referenced_at remains 4b710358a3 is not exact-e2f896f03f fixed-point evidence and is not counted in this approval. It does not block this PR: the branch-relative diff contains no stage0 seed change, and the exact-head required first-generation regen phase is green. The discovered chained-flag/wrapper-exit defect is real and must not be inherited by BT-0's bootstrap recipe, but it is not a defect in #9898.
No blocking concern found. Nothing further is owed at this head.
#9898 collapsed every rung-drop row to a single line so that additive merges on the two design ledgers resolve; this branch extended `text_boundary_identity_wall`'s `authored` field. Both conflicts are real and neither is resolvable by picking a side. THE AUTHORITY (dag/gunbc/rung_drop.dag) is resolved by construction, after checking the premise rather than assuming it: main's `authored` value for this row is BYTE-IDENTICAL to the merge base (4893 chars), so #9898's change to it is formatting only; this branch's value is exactly the base plus a 5973-char suffix. The merged row is therefore main's one-line shape carrying the extended string, with no content dropped in either direction. Everything outside that row is identical between this branch and the base. THE PROJECTION (docs/design-ledgers.md) is derived, so it is not hand-resolved at all. The merge driver refused exactly as designed -- no markers, path left unmerged, ours side in the worktree, recipe printed -- and the file is regenerated from the merged authority through `tools.generated_artifact_gate` `main_wet_one`. The interpreter was rebuilt against the MERGED tree before regenerating. The binary that produced the previous revision of this file predates #9898 and would have re-emitted the old multi-line shape, re-drifting the artifact it was meant to converge; the prior binary was deleted before the rebuild so no stale build could serve. Against origin/main the projection is 14 insertions and 0 deletions: the seven paragraphs this branch authored, rendered in the new one-line format, and nothing else moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WJAqfo1UK4zkzcM7cQ8oj6
…usal_two_destinations (#9938) * Enroll the function-value adapter alignment control: the adapter fires exactly where the impl Fn bound is emitted This lands the EVIDENCE for a property that holds by construction today and which nothing else would notice losing. WHAT WAS CLAIMED AND IS FALSE. I reported rust_call_arg_function_value_adapt as a SILENT defect: it reads the DECLARED arity of a function-typed parameter, gets 0 for a bare type variable, does not emit the Rc->impl Fn adapter, and nothing refuses. bright-ram carried that into a standing correction of the XL-0 push ("loud sites self-select into the typeck count, this one does not"). It is wrong, and the correction has been withdrawn. WHY. The adapter predicate and the predicate that decides whether the parameter renders WITH an impl Fn bound are the same expression on the same node -- `param_node_type_expr(n: param).params |> count` in rust_call_arg_function_value_adapt, and `n.params |> count > 0` in emit_rust_param_type reached through emit_param. The seam the adapter closes is Rc<dyn Fn> flowing into an impl Fn BOUND, and that bound exists exactly where the adapter fires. Arity is also invariant under substitution: instantiation changes an arrow's type ARGUMENTS, never its parameter count, so the site was never answering the instantiated-type question at all. MEASURED, not argued (BuildBuddy, gunbc compile then cargo check on the emitted crate): pub fn make_adder() -> Rc<dyn Fn(i64) -> i64> pub fn apply_arrow(f: impl Fn(i64) -> i64 + Clone, v: i64) -> i64 pub fn hold_tv<T: Clone>(value: T) -> T apply_arrow({ let __adapt_f = hold_tv(make_adder()); move |__adapt_a0| __adapt_f(__adapt_a0) }, 1) A bare type variable renders as a plain generic with NO Fn bound, so there is no seam to close and adapting there would be a fabricated repair. The emitted crate compiles: 0 rustc errors. Building the refusal that was routed would have been a permanently-green decoration cited later as coverage. THE CONTROL IS THE DELIVERABLE. Four assertions in both directions -- the Rc carrier on the producer side, the impl Fn bound at the declared-arrow parameter, the absence of any Fn bound at the type-variable parameter, and the adapter present at the first while absent at the second, whose argument is equally a call result so argument shape alone does not explain it. Fork the two predicates and one of the four goes red. VALIDATION AND WHAT IS NOT DONE. v1_src_dag_parse reports 4475 files parse-clean with this edit, run with the discriminating control its own header requires: appending one unattached trailing `//` to this file produced exactly one refusal naming it at :3339, so the instrument did read the edited bytes. The stage0 mirrors are NOT regenerated here -- claim_executor --regen-round-cost refuses on a BuildBuddy runner (HostBudgetUnreadable: no cgroup memory.high or memory.max binds the process, and it declines to substitute the machine's memory for the slot's), and a whole-tree resolve OOMs the runner at 97% of 7.8 GB. The drift gate is therefore expected red until the mirrors are healed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * File one_refusal_two_destinations: a single refusal naming two different expected types, and the remedy row is the wrong one bright-ram asked for this class after two of us measured it independently. The row is authored in the .dag authority; DESIGN.md and docs/design-ledgers.md are its projections, regenerated by the generated-artifact gate (one line each). THE CLASS. One refusal at one source column emits two rows naming DIFFERENT expected types, because two producers resolve the same declared spelling in different environments. The row an author naturally repairs from -- the one that names the parameter -- is the row the checker did NOT refuse on. SPECIMEN, measured on two binaries and two phases (gunbc compile emit-stage and gunbc run entry-resolve), by calm-boar-314 and bold-carp-449 independently: type mismatch: expected 'Primitive(String)', got 'Primitive(Int)' value does not inhabit its declared type at the direct call argument for parameter 's': declared 'Node(String<Product(Char)>)', produced 'Primitive(Int)' THE PRODUCERS ARE NAMED FROM SOURCE, NOT FROM MESSAGE SHAPE, and the first attribution was wrong: I named declared_type_conformance_diags off the message text, and it is not that -- that function emits TypeMismatch and serves return conformance. Reading the source, the compat row is v1.compiler.infer direct_call_arg_mismatch_diags (formal as the CALLER resolves it) and the inhabitance row is v1.compiler.infer declared_type_obligation_diags (obligation.declared, via declared_type_inhabitance). Both render through v1.compiler.core, so the divergence is upstream of the shared rendering -- which is why it reads as one mechanism contradicting itself. bold-carp asked me to mark whether that attribution was read or inferred; it is read, and the row says so. THE TRIGGER IS STATED NARROWER THAN THE MEASUREMENT INVITES, on bold-carp's correction. "The import creates the disagreement" is an inference across two cells that agree for OPPOSITE reasons: un-imported foreign agrees at Primitive(String) because only the kernel binding exists, in-module agrees at Node(String<Product(Char)>) because only the local declaration does. So the trigger is TWO COMPETING BINDINGS LIVE IN ONE RESOLVING SCOPE; an explicit import is the only construct measured to create that, and whether any other construct does is marked UNMEASURED. Phrased on the import, a reader meeting the class through some other construct would conclude it does not reproduce. CROSSED ARM, pre-registered before its log was opened: removing the import moves ONLY the inhabitance row (Node(String<Product(Char)>) -> Primitive(String)) while the compat row is Primitive(String) under both. One producer follows the import binding and the other does not; the whole reading does not shift. RUNG FOUND AT 1 (mitigatable): the line does stop, and stops located, so this is not silent wrongness -- what fails is that the refusal misdirects the remedy. CEILING 3. NEXT-RUNG TRIGGER, naming the capability: one resolved-formal authority per call site that both the compat check and the inhabitance obligation read, sufficient that no call-site refusal can render two different expected types for one parameter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Regenerate the ledger projections on the rebased tree Route A (generated_artifact_gate main_wet_one) with a binary rebuilt AFTER the rebase, not before -- a pre-rebase binary re-emits the older rendering and re-drifts the file it is converging while exiting green (vivid-deer-102's receipt, #9898). One line added to each projection: the roster index entry and the row itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Install the two stage0 mirrors the enrolled control drifts, to the regen fixed point Route B (claim_executor --required-regen), locally, three rounds -- the third is the receipt and the first two are not: round 1 FAIL generated surface drift: v1_compiler_compiler_tests_rust.rs round 2 FAIL generated surface drift: compiler_tests.rs round 3 first_generation_equal=true, no drift, rc=0 Two rounds are structural, not a retry: installing the mirror of the generator module changes what the seed emits, so the generator's own output can only be measured against a seed rebuilt from the installed mirror. Every byte is copied from target/stage0-regen-candidate; none is hand-written. THE FIRST ROUND ON THE OLD BRANCH REPORTED SEVEN FILES, and that is why this branch exists. Six of them -- v1_compiler_compile.rs, v1_compiler_emit.rs, v1_compiler_emit_rust.rs, v1_compiler_infer_resolve.rs, v1_compiler_parse.rs, v1_std_core.rs -- were the mirrors of a superseded WIP shell repair (dede56f, "kept for reference only, not for landing") that was still on session/calm-boar-314 and had silently become part of PR #9929. It duplicates sharp-dove-805's open #9886. Rebuilding the branch from origin/main with only the intended commits drops it, and the drift census falls from seven files to one -- which is the measurement that confirms the six were never mine to land. Route B is also now first-hand rather than cited: vivid-deer-102 relayed this recipe from the merge driver's refusal text and was explicit they had not run it. It works locally. It cannot run on a BuildBuddy runner (HostBudgetUnreadable: no cgroup limit binds the process). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Regenerate the projections after merging main Binary rebuilt from the MERGED tree before regenerating. One line added to each file: the roster index entry and the row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Supersede the one-artifact memory ceiling: 8.37 GiB, measured the same way as the figure it replaces vivid-deer-102 asked me to file this and was right that it matters more than a number being slightly off: a documented ceiling that UNDERSTATES the measured peak gets cited as the reason a thing is safe to try. At 7.54 GiB against a 7.86 GB VM the margin reads as thin-but-conceivable, which invites the "maybe with a tighter budget setting" attempt whose only outcome is an rc=137 twenty minutes in. At 8.37 GiB against 7.32 GiB the requirement is a full gigabyte outside the whole VM. MEASURED THE SAME WAY AS THE ROW IT REPLACES, which is the only reason it can supersede rather than sit beside: polling VmHWM -- the kernel's own high-water mark -- to completion, on 2026-09-01, this tree, rc=0 with DESIGN.md written. 8,776,996 KiB. TWO CORRECTIONS TO MY OWN EARLIER REPORTING, recorded because both would have propagated. I first reported 8.76 GiB: that was a unit error, dividing KiB by 1000 twice rather than 1024 twice. And I described my original 5-second `ps -o rss=` sampling as a peak superseding a sample -- backwards. VmHWM cannot underreport; sampled RSS can only ever be a LOWER BOUND. The gate's method was the stronger one, so the honest move was to adopt it rather than argue from a weaker instrument. THE DATED PAIR IS DELIBERATE. 7.54 is not amended in place, because "the ceiling moved with the corpus" and "the ceiling was mismeasured" are different facts and only the pair distinguishes them. Same instrument, same method, 0.83 GiB higher in one day: it grew. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Weaken the adapter control's claim to what its bytes can decide (review 58256) The control asserted, in its annotation, that the adapter CLOSES the E0277 seam. A substring assertion over emitted Rust cannot decide that at any lane membership -- whether the bytes compile is a rustc verdict -- so the claim was 4b(1) rung inflation. Codex review 58256 named it; the remedy is a sentence, not a mechanism. The annotation now states what the control establishes at its declared grain (emission succeeds, zero error diagnostics asserted first, and the bytes have the discriminating shape: adapter present at the declared-arrow parameter, absent at the bare type variable) and what it does not (that the emitted program compiles). It names ct_self_compile_cargo_check_test as the rustc consumer at corpus grain, says why that is not reached per-fixture -- probe.rs references the crate runtime and does not stand alone, and a second per-fixture compile path beside the corpus-level one is the parallel authority section 6 warns about -- and points at the declared section 4b(3) drop emitted_bytes_witness_required_lane for the residual gap. Stage0 mirrors regenerated to the fixed point: two rounds installed, then first_generation_equal=true 149/149/149, declared_divergent=1 [main.rs]. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Drop the named non-candidate and the inflated assert string (review 58256, follow-through) Three further corrections, each verified before applying: - The annotation no longer NAMES any candidate rustc consumer, even negatively. A named non-candidate is still a pointer, and a pointer is what a later reader turns into coverage. It now states a fact about the tree instead: no enrolled fail-closed rustc consumer covers this synthetic fixture. Checked rather than assumed -- the committed workflow invokes cargo test --release -p v1-compiler --lib with no --ignored, so what is established is that no committed scheduled route exists, not that none could. - The assertion MESSAGE said the adapter must close the seam. That is a claim at a rung the test does not reach, and it is what a reader sees at the moment it goes red. It now says the forwarding adapter must be EMITTED at the impl Fn parameter. - No rung-drop citation remains in the annotation: the drop it named is a drop of lane membership and does not answer a discrimination objection. Mirrors driven to the fixed point over three rounds -- the emitter of the test text, then the test text, then the verify -- first_generation_equal=true, 149/149/149, declared_divergent=1 [main.rs]. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Roster the new hand-Rust test blob in the scaffold index (review 58290) gunbc.language_source_scaffold_index carries one LanguageSourceScaffoldRow per hand-Rust blob decl, and test.claim.language_source_scaffold_index_test counts ct_ declarations in the carrier against rows for that carrier. The new control's blob had no row, so the diff added a ct_ declaration without appending to the roster it belongs in. The row takes compiler_tests_rust_hand_assertion_scaffold_trigger -- the same Scaffold disposition every other hand-assertion blob in this carrier carries, dissolving to SingleAuthority at v1.compiler.coercion CoercionTestEntry -- rather than minting a new one, which would be a section 3 fork. language_source_scaffold_roster_is_fully_dispositioned was EXECUTED with the row in place and returns true. Separately, and not repaired here: the carrier's completeness check is already red on main -- 43 ct_ declarations against 40 rostered rows, three blobs unrostered before this branch existed. That is filed as its own work item; this commit discharges only this diff's contribution. Mirrors unchanged (first_generation_equal=true, 149/149/149) and both doc projections regenerate to identical bytes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b * Record the v1 admission for the adapter alignment control, and add EvidenceEnrollment (review 58359) Review 58359 refused the new compiler_tests blob for lacking a hand-Rust receipt naming a lane and a ROADMAP row. That vocabulary names nothing: verified independently by me and by the ruling manager against origin/main, DESIGN.md carries no such gate -- the SECOND time it has been cited at a PR and the second time it was found to name nothing (the first is recorded in the RcStr row of this same carrier). The receipt also cannot land in language_source_scaffold_index, whose row type has no field a lane or ROADMAP row could occupy; bolting it in as prose would be the section 4c violation. So the obligation lands where v1 admissions actually live. The row records the ruling relayed from bright-ram-778 on 2026-09-02, including the parts that are easiest to drop in the citing: PublicSurfaceGrowth FIRES LITERALLY and is admitted anyway, because the class exists to stop the seed accumulating CAPABILITY and a test emitter accumulates none; the cheaper ruling -- that compiler_tests blobs are not admission subjects at all -- was DECLINED, because a category exemption never comes up for review again while one admission does; the ruling admits this change only and does not resolve the new-declaration-versus-any-change boundary; and the counter-argument is preserved so overturning it is easy. EvidenceEnrollment is added to MaintenanceAdmissionInstance rather than forcing this into one of the four existing shapes -- every 4b(4) climb in v1 produces it, so it is a class and not a bespoke slot. Module typechecks (0 blocking diagnostics); no projection or mirror moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FdxzwWekWhHR2FCTTf8a1b --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
What this changes
gunbc.recurring_failure_modeandgunbc.rung_dropcarry one row per class / per declared drop, and every lane that finds one appends a row. Both authored their rows as multi-line record blocks ending in a suffix every other row also ends in —evidence: [],/}on the first,}alone on the second.A three-way merge never includes a shared suffix in the conflict region. Measured with
git merge-fileagainstdag/gunbc/recurring_failure_mode.dagat merge based0009ca531, two synthetic lanes each appending one row: the region opens at both lanes'dataline and closes after theirauthored:line, leaving ONE tail below the markers for TWO half-blocks above them. The purely additive resolution — delete the markers, keep both sides, which is the correct resolution when two lanes named two independent classes — gives the first row's closing lines to the second.This makes each row one line. A one-line row has no tail to lose: the only suffix a merge can factor out of the region is the blank separator between rows, which carries nothing, so both sides of every region are whole declarations and the additive resolution is total. Re-measured in the same lab after the transform: confirmed.
The property generalises past these two carriers: what makes the additive resolution total is that the growth surface's unit has no tail below its last authored field, which is a shape fact about the row, not a fact about failure modes or rung drops.
The discriminating pair (same instrument, one arm before and one after)
Both against a
gunbcbuilt from source atd0009ca531:module index refused: 1 unparseable .dag source(s)/dag/gunbc/recurring_failure_mode.dag:65912-65913: expected expression, found Eq, exit 1git merge-file, same additive resolution, against the post-fix carrierThe merge still conflicts after the fix — that is correct and unchanged, two lanes did touch one append point. What changes is that both sides of the region are now whole declarations, so resolving it additively loses nothing.
Rung, stated honestly
This is not structural, and the annotation says so where the next appender will read it. The population carries no severable tail, but the shape is not enforced — no lens covers row shape on these carriers — so one hand-authored multi-line row restores the two-line tail and the whole geometry. The invalid state stays writable: mechanically preventable at best. Next-rung trigger, named as the capability: a row-shape obligation decided for every declaration of a growth-surface type rather than observed on the rows that happen to exist.
v2.std.decl_indexdata_decl_type_factsalready reads a declared type per declaration; what is missing is a producer carrying each declaration's source extent, sufficient to refuse a multi-line row of such a type at authoring time. Until that exists the shape is a convention held by review and by that paragraph.What this does NOT claim
The reported class was that a severed row survives as a structurally broken declaration under which the natural check (declared names vs. rostered names) still passes, because both lists stay complete. That half does not survive measurement. The byte-exact resolved file, through a
gunbcbuilt from source atd0009ca531:All three loss states were run, and the set is complete — the two-line tail can be cut three ways and every one is loud: losing both lines and losing
}alone are parse refusals at the module index (expected expression, found Eq, adatakeyword in record-field position); losingevidence: [],alone is a resolve refusal (missing required field 'evidence' in literal of type 'RecurringFailureMode'). Nothing silent was found in that set.The executing route is
claim_executorphase 1, the.dagparse sweep over["src/v1", "dag", "src/v2"]on required lanewitnesses— the first phase in the job, nothing upstream can abort before it, and a parse error becomes a phase failure. So this class is loud and fail-closed today, and no wall is owed. A brace-balance or name-join check written here would be the §4b decoration: permanently green, because the only corpus it could fire on is one the compiler already refuses.What is real is the cost, not silent wrongness — a load-bearing authority whose every integration lands a conflict whose natural resolution does not compile, hand-repaired each time. That is what this removes.
Also here
One new row,
merge_region_excludes_shared_tail, carrying the recognition rule (for a carrier two lanes append to, ask what suffix the appended units SHARE) and the correction above, per §4b's "every newly discovered error class files or updates one row".Oracle
The
identity/subject/declared/authoredstrings are carried byte-for-byte; the only projection change is the one new row's sentence and its index entry.DESIGN.mdanddocs/design-ledgers.mdregenerated from the transformed authorities viagenerated_artifact_gate main_wet(exit 0, 35 artifacts written). The projection diff is 1 added line and 0 deleted lines in each — the new row's index entry and its sentence. Every pre-existing projected byte is unchanged, which is the oracle; the string-extraction equality alone would only have proved the inputs match.Annotations: no row in either file carried a leading annotation block, so the fold never had to move one. The only §4c blocks in these modules attach to the module head and, in
gunbc.rung_drop, tostanding_rung_drops— none of them to a transformed declaration. Both files' module-head blocks gain a paragraph recording why the row shape is one line.Out of scope, deliberately
The conflict pressure — two flat append points mean any two lanes appending collide — is untouched. Removing that is a carrier question (per-row files, as
extdeps/vendor/does), and it would still leave the roster as one shared append point. Its own change, not a side effect of this repair.The pressure, now dated rather than argued
This branch was conflicted by unrelated lanes twice on 2026-09-01, on a PR whose whole subject is that this file conflicts by construction:
recurring_failure_moderowdag/gunbc/recurring_failure_mode.dag,docs/design-ledgers.mdstate_space_conflation.authored(2370 → 4766 chars); #9910, #9883, #9904 also landedNeither lane was working on this PR's subject, and neither edit disagreed with anything here — #9902 appended a row, #9906 extended a different row's sentence. That is textual contention at the file's two flat append points standing in for semantic contention that does not exist, which is exactly what the "Out of scope" section below names and deliberately does not fix. The count is extendable: every future integration of this branch adds a row to this table.
Each resolution was verified at identity grain against both parents rather than by inspecting a clean-looking diff — every identity present in either parent present in the result (set difference both directions, not counts), declared ∖ rostered and rostered ∖ declared both empty, and every row's
authoredbytes present verbatim in the regenerated ledger.