Skip to content

Reshape the fn-arrow body skeleton so a call is a call: the marshal now emits the Transform carrier node_is_call accepts - #10282

Merged
gunbai-bot[bot] merged 18 commits into
mainfrom
session/cool-fox-470
Sep 4, 2026
Merged

gunbai-bot[bot] merged 18 commits into
mainfrom
session/cool-fox-470

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Every node the fn-arrow body skeleton marshal produced was a TypeNode { connective: Conj }
-- calls included -- while v2.std.node_query node_is_call accepts only a
ComputationNode { behavior: Transform } whose first positional child is a callee reference,
the carrier v2.compiler.body_lowering_fold produces for a lowered body. A Conj type node
cannot match a Transform computation node, so across the WHOLE live skeleton substrate
node_is_call was false, node_callee_symbol was Absent, and every call-shaped lens over it
-- v2.lens.determinism transitive findings, v2.lens.machine_shape, the origin probe's call
walk -- was GREEN BY CONSTRUCTION. That is DESIGN section 4b's decoration: a check whose RED is
unauthorable in the population it ranges over, worse than absent because it is cited as coverage.

THE REPAIR IS IN THE PRODUCER, NOT IN THE CHECK. Widening node_is_call to accept the Conj
spelling would have ratified the fork and made the substrate's own definition of a call
advisory. marshal_generic now returns transform_record for an ExprCall with a non-empty
authored name -- exactly the case where the callee identity leaf is already edges[0] -- and
conj_record for everything else, including a call through an unnamed callee expression, which
has no callee reference to be first and which node_is_call would refuse anyway.

THE SECTION 3 RECEIPT WAS ALREADY STANDING AND IS NOW DISSOLVED.
v2.lens.no_dual_representation_test.scan carried skeleton_is_call,
skeleton_is_callee_atom and skeleton_call_argument_targets -- private copies of
node_is_call / call_callee_target / call_argument_targets respelled against Conj, because
the shared authority could not read its own substrate. One question with two answers. The
copies are deleted, not parameterised, and that module now calls the authority. Its
replace_param_in_output descends every non-atom kind rather than Conj alone: a Conj-only arm
would have returned bodies containing calls UNSUBSTITUTED, answering "not alpha-equivalent" for
exactly the bodies the check is about.

EXECUTED EVIDENCE, with the delete arm confirmed to have deleted.
marshaled_call_carries_the_transform_call_carrier and its control
marshaled_non_call_stays_a_conj_type_node run on the required cargo test -p v1-compiler --lib path. Reverting marshal_generic to the unconditional conj_record reddens EXACTLY the
first of them (4 passed, 1 failed) and restoring returns 5/5 green -- the mutation asserted its
own substitution before the verdict was read.

In .dag, the_lens_fires_on_a_transform_shaped_call and
the_lens_is_blind_to_the_conj_shape_the_marshal_no_longer_emits are enrolled as a pair
differing in ONE field, the node kind: one green alone cannot separate a correct lens from an
inexpressible subject. The blind row stays enrolled per section 4b(4) as the regression
control. The determinism fixture's seed body is now the call carrier itself rather than a shape
no marshal emitted.

Files one recurring_failure_mode row,
fixture_shape_diverges_from_the_producer_shape, bounded against
executed_conjunct_discriminates_nothing (there the RED was never authored; here the fixture
EXISTS and is what hides the defect) and against the sibling v2.lens.effect_reach disjunction
defect at adhoc-f0508f41-ae9, which presents identically and is repaired in the check rather
than in the producer.

NOT REGENERATED HERE: docs/design-failure-modes.md. Resolve refuses on this tree for reasons
that predate this change -- absence_classifier_default_bucket and
green_reported_over_a_population_the_instrument_does_not_own are each declared twice in
gunbc.recurring_failure_mode on main, plus unresolved Plan/NonEmptyStr types under
dag/gunbc -- so no projection can be produced from this authority until gunbc#10278 lands. The
.dag authority carries the row; the projection is a generated artifact and heals downstream.

🤖 Generated with Claude Code

https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg

Brian Searls and others added 5 commits September 3, 2026 20:46
…ow emits the Transform call carrier node_is_call accepts

Every node the fn-arrow body skeleton marshal produced was a `TypeNode { connective: Conj }`
-- calls included -- while `v2.std.node_query` `node_is_call` accepts only a
`ComputationNode { behavior: Transform }` whose first positional child is a callee reference,
the carrier `v2.compiler.body_lowering_fold` produces for a lowered body. A Conj type node
cannot match a Transform computation node, so across the WHOLE live skeleton substrate
`node_is_call` was false, `node_callee_symbol` was Absent, and every call-shaped lens over it
-- `v2.lens.determinism` transitive findings, `v2.lens.machine_shape`, the origin probe's call
walk -- was GREEN BY CONSTRUCTION. That is DESIGN section 4b's decoration: a check whose RED is
unauthorable in the population it ranges over, worse than absent because it is cited as coverage.

THE REPAIR IS IN THE PRODUCER, NOT IN THE CHECK. Widening `node_is_call` to accept the Conj
spelling would have ratified the fork and made the substrate's own definition of a call
advisory. `marshal_generic` now returns `transform_record` for an `ExprCall` with a non-empty
authored name -- exactly the case where the callee identity leaf is already `edges[0]` -- and
`conj_record` for everything else, including a call through an unnamed callee expression, which
has no callee reference to be first and which `node_is_call` would refuse anyway.

THE SECTION 3 RECEIPT WAS ALREADY STANDING AND IS NOW DISSOLVED.
`v2.lens.no_dual_representation_test.scan` carried `skeleton_is_call`,
`skeleton_is_callee_atom` and `skeleton_call_argument_targets` -- private copies of
`node_is_call` / `call_callee_target` / `call_argument_targets` respelled against Conj, because
the shared authority could not read its own substrate. One question with two answers. The
copies are deleted, not parameterised, and that module now calls the authority. Its
`replace_param_in_output` descends every non-atom kind rather than Conj alone: a Conj-only arm
would have returned bodies containing calls UNSUBSTITUTED, answering "not alpha-equivalent" for
exactly the bodies the check is about.

EXECUTED EVIDENCE, with the delete arm confirmed to have deleted.
`marshaled_call_carries_the_transform_call_carrier` and its control
`marshaled_non_call_stays_a_conj_type_node` run on the required `cargo test -p v1-compiler
--lib` path. Reverting `marshal_generic` to the unconditional `conj_record` reddens EXACTLY the
first of them (4 passed, 1 failed) and restoring returns 5/5 green -- the mutation asserted its
own substitution before the verdict was read.

In .dag, `the_lens_fires_on_a_transform_shaped_call` and
`the_lens_is_blind_to_the_conj_shape_the_marshal_no_longer_emits` are enrolled as a pair
differing in ONE field, the node kind: one green alone cannot separate a correct lens from an
inexpressible subject. The `blind` row stays enrolled per section 4b(4) as the regression
control. The determinism fixture's seed body is now the call carrier itself rather than a shape
no marshal emitted.

Files one recurring_failure_mode row,
`fixture_shape_diverges_from_the_producer_shape`, bounded against
`executed_conjunct_discriminates_nothing` (there the RED was never authored; here the fixture
EXISTS and is what hides the defect) and against the sibling `v2.lens.effect_reach` disjunction
defect at adhoc-f0508f41-ae9, which presents identically and is repaired in the check rather
than in the producer.

NOT REGENERATED HERE: docs/design-failure-modes.md. Resolve refuses on this tree for reasons
that predate this change -- `absence_classifier_default_bucket` and
`green_reported_over_a_population_the_instrument_does_not_own` are each declared twice in
`gunbc.recurring_failure_mode` on main, plus unresolved `Plan`/`NonEmptyStr` types under
dag/gunbc -- so no projection can be produced from this authority until gunbc#10278 lands. The
.dag authority carries the row; the projection is a generated artifact and heals downstream.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
# Conflicts:
#	dag/gunbc/recurring_failure_mode.dag
…er_shape row to the per-class carrier main split it into
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Both findings in review 59532 verified against the current head (1e188e8). One is answered with a receipt, one is disputed on the authority it cites. Neither is fixed by a code change and I say why.

Advisory — seed census for the hand-written Rust (accepted, receipt below). Measured on this diff, not estimated: coproduct_reflection.rs is +141/-1. The split is 22 comment lines, 3 production functions (nullary_behavior_variant, node_kind_computation_node, transform_record — 24 lines together), and the remaining ~95 lines are inside #[cfg(test)]: four helpers and the two discriminating tests. Production growth in the seed is 24 lines. NO SCAFFOLD PATH IS DELETED BY THIS DIFF and I am not claiming one. What this touches is a path ALREADY DECLARED a §7 scaffold with a dissolution trigger that predates me — v2.std.fn_index fn_arrow_skeleton_g2_marshal_host_scaffold_dissolution_trigger, which dissolves when fn-arrow body projection is a modeled substrate fold emitting the same skeleton facts, retiring the hand-Rust marshal expansion. That trigger is UNCHANGED and UNWEAKENED by this change: reshaping which node kind the marshal emits does not make the marshal any less scheduled for deletion, and the three new functions die with it. Deferral lane: the same #5364 corridor the existing trigger names. Tracking row: the trigger declaration itself, which is the carrier for this, not a new row — filing a second one would be the ledger-layer nicknaming the repo already refuses.

Blocking — §4c on the receipts: List<String> entries (disputed, and the citation does not reach this carrier). §4c's rule is about UNCLASSIFIED PROSE: "an ordinary String declaration whose sole purpose is commentary is misplaced or dead data", and its measured occasion was 215 dead prose rows hoisted into data …: String after // was made unwritable. The prose in a RecurringFailureMode row is not commentary beside program data — it IS the program data. gunbc.recurring_failure_mode is the authority DESIGN §4b names for this ledger, gunbc.design_document folds .authored over exactly these receipts, and the result is docs/design-failure-modes.md. Delete the strings and the projection is empty. That is the opposite of dead data: it is read, folded, and rendered.

The shape is also not mine to choose. receipts: List<String> is the carrier main established at 1af8892 for all ~90 rows, and its own header records the classification debt the review is describing — the analytic fields (misleading surface, actual question, failure mechanism, required guard) are "DELIBERATELY ABSENT", because "filling them for seventeen classes means authoring analysis that does not exist in the text today, which is semantic rewriting inside a structural cut and has no oracle." My row conforms to the declared shape. Typing the fields for ONE row would fork the type or leave one row shaped unlike its 90 siblings, which is the §3 defect this PR exists to remove, reintroduced one layer up in the same session.

So the finding is real as a CLASS OBSERVATION about the carrier and I am not disputing that the debt exists — it is filed on the carrier, by the carrier, today. It is not a defect in this row, and repairing it here would mean redesigning RecurringFailureMode and migrating every row, which is its own subject with its own oracle. Happy to open that as a work item; it should not ride on a marshal reshape.

— sent from cool-fox-470

gunbc-ci-auto-heal and others added 13 commits September 3, 2026 22:31
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	docs/design-failure-modes.md
… same class, dissolve the duplicated shape-gap pair, and retire the stall its trigger just satisfied

#10245 landed the same class from the same specimen while this PR was in review:
check_subject_shape_cannot_represent_the_state_the_check_detects. Two names for one concept is
the defect this PR exists to remove, so fixture_shape_diverges_from_the_producer_shape is DELETED
and the three receipts of mine that its row does not carry are appended to it instead -- the
non-symmetric repair direction (reshape the producer, never widen the check), the static field
tell (a private copy of the shared predicate is visible by reading), and the evidence shape (a
hand-built fixture can attest a lens and never a marshal, so the producer's row lives on the seed
test path).

Same move on the witness: #10245's shape_gap pair and mine were the same two rows, so mine are
deleted and theirs kept. Their blind arm is renamed for what it now means -- the marshal no longer
emits that shape -- and the paragraph's prediction that the blind arm would RED when the capability
landed is corrected rather than removed: the arm asserts a Conj node is not a call, which was true
before and is true after; what changed is whether the live substrate can produce the other one.

v2.lens.determinism's stall named its trigger as a capability -- the fn-arrow body skeleton
represents a call at a shape node_is_call accepts -- and this PR is that capability, so the
annotation retires it by its trigger. What it does NOT claim: that a live RED is constructible
end-to-end. atom_identities_in_node reads callees at depth one, so a call inside a block body is
below the horizon call_reachable_decls seeds from; that is a different defect, unrepaired here, at
work item adhoc-6af6a225-11d.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
…ape_cannot_represent_the_state_the_check_detects

An edit slip from appending receipts to an existing list: the anchor line already ended with a
comma and the insertion added its own, producing `",,` between two elements. Caught by review
59625 before the parser had to. No content change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
… for CI to regenerate from the authority

The only conflicting path is the GENERATED PROJECTION, and a generated artifact is not hand-merged:
choosing a side there is how two hand-resolved regions produced the duplicate-declaration break on
main earlier tonight. Neither side's bytes are authored, so main's are taken as a placeholder and the
heal-generated-artifacts actuator re-derives the file from gunbc.recurring_failure_mode -- the same
route that has healed this branch three times in this PR. The authority carries the receipts; the
projection follows it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
…ecl.output is Conj except a named call, which is the Transform carrier

A consumer of `FnArrowDecl.output` looks up the type here, not in the seed marshal that builds it,
and a consumer that guesses the shape wrong does not get an error -- it gets a green. That is
exactly how this defect ran: every call-shaped lens over these skeletons was permanently green,
and `v2.lens.no_dual_representation_test.scan` grew a private copy of `node_is_call` spelled
against `Conj` rather than anyone noticing the authority did not apply. Both repaired in this PR;
the shape is now stated where the type is declared, with the pre-#10282 state kept as the reason
the paragraph exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
… main (generated projection left to the heal actuator)

Review 59706 is right and it is this repo's own §5 tell aimed at my regression wall: the probe read
only the outer variant names, so a marshal emitting ComputationNode { behavior: Loop } over a
TypeNode { connective: Conj } child would have kept it green while node_is_call went false again.
The assertion could be satisfied while the realization lied. It now reads the full path both
predicates read -- kind ComputationNode AND behavior Transform, first positional child TypeNode AND
connective Atom -- and the control asserts Conj rather than merely TypeNode.

The mutation receipt still holds and is now stronger for a different reason: it discriminated
before because the mutation changed the outer tag, which is exactly the narrow case the old
assertion happened to cover.

docs/design-failure-modes.md is the only conflicting path and it is generated; neither side's bytes
are authored, so main's are taken and heal-generated-artifacts re-derives it from the authority.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vmMNtRoPfgkR75q8feHYg
@gunbai-bot
gunbai-bot Bot merged commit ce937d0 into main Sep 4, 2026
14 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/cool-fox-470 branch September 4, 2026 06:44
@briansrls
briansrls restored the session/cool-fox-470 branch September 4, 2026 06:53
briansrls pushed a commit that referenced this pull request Sep 4, 2026
…der 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
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
…t the rung above

codex review 59889 is right and it is a blocking defect: the row declared
"CEILING: 3 (mechanically preventable)", and DESIGN.md section 4b numbers those
differently -- 2 is mechanically preventable, 3 is structurally guaranteed. A row
whose whole subject is a grain mismatch between a stated loss and its trigger
carried a grain mismatch between its own ceiling's number and its name.

THE NUMBER WAS RIGHT AND THE NAME WAS WRONG, established from the mechanism the
row already described rather than by picking the safer digit. "Triggers and losses
become typed references to the same capability identity" is a refusal the compiler
derives from modeled structure, which is section 4b's rung 3 -- not a gate that must
execute and stay enrolled, which is rung 2.

AND THE ROW NOW DERIVES WHY IT IS NOT 4, because "could this be structurally
impossible" is the question a corrected ceiling invites and leaving it unanswered is
how the next reader re-opens it. Section 4b(1) reads a class's rung as the MINIMUM
across its in-scope parts. The subject-mismatch half could reach 4: typed at one
grain, a trigger naming a route has no constructor. The other half cannot, because
retirement also requires the capability's discriminating witness to HOLD at its named
position, and a witness holding is executed evidence rather than a constructor. The
ceiling is the weaker of the two, and claiming 4 would be the rung inflation this
ladder exists to name.

Projection regenerated as a UNION rather than resolved to a side: main's content
(#10282's amendment among it) plus this row's new body. Verified at both halves
rather than by confirming my own row came back -- membership join 97/97 MISSING=0
order-equal, and the authority diff against main shows only this row file and the two
roster lines, so every other row is byte-identical to main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSjamJZnktJ59XsarNLyeH
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
… it was never there

Review point from the #10282 lane: writing all four rows as "declared cause
falsified" lets the next reader conclude #10282 fixed nothing. It fixed one of
these four. The structural-fixture row WAS held red by the marshal, that repair is
real, and what remains is a different mechanism -- the marker read -- holding the
same row red. The other three were never operatively blocked by the marshal.

So that row's note, its admission reason, and the fixture module's annotation now
name the superseded sentence, say it was true when written, and say what took over.
The file-level paragraph splits the four the same way rather than asserting one
verdict over all of them.

Wording only; the four rows are still red and the admission walls still hold.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JFCwaz6h5cQv3fih9is2Yc
gunbai-bot Bot added a commit that referenced this pull request Sep 4, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants