Skip to content

File the emitted-record Deserialize gap as its own class row - #9556

Merged
briansrls merged 6 commits into
mainfrom
session/quick-swift-434-emitter-deserialize-finding
Aug 28, 2026
Merged

briansrls merged 6 commits into
mainfrom
session/quick-swift-434-emitter-deserialize-finding

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

The class

A .dag record embedding a coproduct whose variant carries a sole_constructor type emits a Rust record deriving Deserialize over a Serialize-only, private-field struct. Both emitter rules are individually correct — an unforgeable carrier must not be reconstructible from wire bytes, and ordinary records derive Deserialize — and they compose into a shape the author cannot write.

Found by execution while building #9554, where the obvious single row { compiled_module: String, admission: ReferenceDerivedClosureAdmission } was unavailable. It was recorded there only as a note inside the producer that worked around it, which is found solely by someone already editing that producer. DESIGN §4b asks every discovered error class to file one row; this is that row.

Measured, not recalled

code lands on why
E0277 the emitted outer record's derived Deserialize the embedded coproduct does not implement it, because the sole_constructor type inside one variant is Serialize-only
E0616 a read of that type's carried field from outside its emitted module the field is emitted private — the wall behaving correctly; the accessor is the sanctioned route

Two rows rather than one: they land on different constructs and either can appear without the other.

What is claimed, and what is not

Rung: mitigatable, stated as such. Nothing in the ordinary .dag compile path refuses the shape — the .dag is accepted, and the refusal arrives as a generated-Rust build failure at maximum distance from its cause.

No executing RED is enrolled, and the reason is the fixture boundary rather than a saving. The only way to author this shape today is inside the seed's emit closure, where it stops the required build for every subject at once rather than going red on its own. Per §4b(2) that missing harness is the class's next-rung trigger, not a ceiling, and per the 2026-08-26 rule the trigger names the capability — emitting and compiling a candidate module the seed does not import — explicitly refusing the artifact form (an entry point that emits and compiles one module is insufficient unless it can carry a non-seed module).

The carried predicate asserts only that the finding is recorded with its codes and its shape. A predicate asserting the gap is closed would be satisfiable by editing this file, which is the validation-standing-where-construction-was-available tell.

Scope

One new gunbc/ module, imported by nothing. It does not enter the seed's emit closure, so it produces no mirror — confirmed against the analogous finding carrier gunbc.fabric_capacity_class_gap, which likewise has none. Parsed and evaluated green from the tree-built binary over --source-root dag --source-root src/v2.

🤖 Generated with Claude Code

https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje

gunbc-ci-auto-heal and others added 4 commits August 28, 2026 02:03
…th rustc codes and the minimal shape

DESIGN 4b asks every discovered error class to file one row. This one was found by
execution while building namespace-structural-observations (#9554) and was recorded
only as a note inside the producer that worked around it, which is found solely by
someone already editing that producer.

THE CLASS: a .dag record embedding a coproduct whose variant carries a
sole_constructor type emits a Rust record deriving Deserialize over a Serialize-only
private-field struct. Two rules that are each individually correct compose into a
shape the author cannot write.

MEASURED, not recalled: E0277 on the outer record's derived Deserialize, E0616 on a
read of the carried field. They are separate rows because they land on different
constructs and either can appear without the other.

RUNG: mitigatable, and stated as such. Nothing in the ordinary .dag compile path
refuses the shape; the refusal arrives as generated-Rust build failures at maximum
distance from their cause.

NO EXECUTING RED IS ENROLLED, and the reason is the fixture boundary rather than a
saving: the only way to author the shape today is inside the seed's emit closure,
where it stops the required build for every subject at once rather than going red on
its own. That missing harness is named as the next-rung trigger, and the trigger
states the CAPABILITY -- emitting and compiling a module the seed does not import --
rather than an artifact that would contribute to one.

The carried predicate asserts only that the finding is recorded with its codes and
its shape, never that the gap is closed; a closure predicate would be satisfiable by
editing this file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
…se, and the clause is narrowed

The refusal clause said an added emit-compile roster entry could never retire this row
because "every rostered entry is a seed-closure entry". Nobody had checked that, and
snappy-dove-250 flagged the premise rather than the form.

MEASURED: computing the transitive IMPORT closure from every module under src/v1 over
src/v1 + dag -- the most generous seeding, so an OUTSIDE answer is robust -- three of
the eight rostered entries are outside it (gunbc.ci_layer_roots, gunbc.scm.load_standing,
std.abi). A second independent instrument agrees exactly: those three are the three with
no committed mirror under src/v1/stage0/src, while extdeps.uri and std.logic are inside
and have one. The phase already compiles non-seed modules.

So isolation from the seed was never the missing capability, and the trigger no longer
claims it is. The capability is an EXPECTED-RED COMPILE ARM: every route we have treats
a compile failure as a line stop, so authoring this shape anywhere reachable makes a gate
permanently red instead of producing an enrolled red. A rostered entry is still not
sufficient -- for that reason, not the one previously given.

WHY AN OVER-STRONG TRIGGER IS NOT THE SAFE ERROR: it is the mirror of the 4b(3) failure.
A trigger unsatisfiable while the capability is alive fails as quietly as one satisfied
while it is dead, because a row that never retires reads as diligence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
…refused, correctly

The workaround row cited namespace_structural_observation_admissions, which does not
exist on main -- it lands with #9554. The declaration index resolves every authored
citation on every required run, so this PR's parse phase would have refused it. Caught
by checking origin/main for the symbol rather than by CI.

It now cites namespace_structural_binding_observations_a_through_d, which is real in
both trees and is the half the two-export split was taken FROM, so the citation resolves
today and stays true after #9554 lands. The sibling export is named in prose, where
nothing can mistake a description for a resolvable symbol, and a comment records why the
citation points where it does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
…ong is deleted (review 57088)

review 57088 requested changes: the row declares mitigatable while a comment said the
required seed build reliably refuses the shape, and a mechanism that exposes and blocks
a writable invalid state is mechanically preventable under DESIGN 4b.

THE OBJECTION WAS FAIR AND THE SENTENCE IT READ WAS FALSE. That comment said "the only
way to author this shape today is to put it in the seed's emit closure". Measured over
4234 modules under src/v1 + dag + src/v2: the seed closure is 134 and the emit-compile
roster's closures add 5, so 139 are covered and 4095 ARE NOT. On those 4095 the shape is
accepted, the bad state is written, and no build ever fails. The false sentence is
deleted rather than softened, and the measurement is carried as its own data row.

WHY THE RUNG DOES NOT MOVE. 4b(1) sets a class's rung at the MINIMUM across its in-scope
paths, so the uncovered majority decides it. And on the 139 covered modules the refusal
is still not prevention: a build break at a distance from its cause, in generated code
the author did not write, with no typed located diagnostic naming the source construct,
is containment after failure. The invalid state stays writable on every path.

The no-executing-red justification now follows from the same split rather than from the
deleted claim: on 4095 modules the shape produces no signal for a probe to observe, and
on 139 it stops the required build rather than asserting a red. Neither yields an
enrollable red -- which is the capability the trigger already names.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

review 57088 — thank you, the objection was fair and it found a false sentence.

The rung stays at mitigatable; the comment that made it look contradictory is deleted, not softened. That comment read "the only way to author this shape today is to put it in the seed's emit closure", which would indeed make the seed build a gate over the whole population. It is false.

Measured over the 4234 modules indexed under src/v1 + dag + src/v2: the seed closure is 134, the emit-compile roster's eight entries add 5 more, so 139 are covered and 4095 are not. On those 4095 the shape is accepted, the bad state is written, and no build ever fails — nothing refuses it. Under §4b(1), a class's rung is the minimum across its in-scope paths, and that is the path that sets it.

And on the 139 covered modules the refusal is still not prevention. §4b reserves mechanically preventable for a mechanism that exposes and blocks the invalid state. What happens there is a build break at a distance from its cause, in generated code the author did not write, with no typed located diagnostic naming the source construct — containment after failure, which is the definition of the rung below it. The invalid state remains writable on every path, including that one.

The no-executing-red justification now follows from the same split rather than from the deleted claim: on the 4095 there is no signal for a probe to observe, and on the 139 the shape stops the required build for every subject at once rather than asserting a red on its own. Neither half yields an enrollable red — which is exactly the capability the trigger already names (an expected-red compile arm).

Pushed as 3214c09732b, carrying the measurement as its own data row so the claim is re-derivable rather than asserted.

— sent from quick-swift-434

gunbc-ci-auto-heal added 2 commits August 28, 2026 02:56
Base update only: #9556 was cut from a main that carried the three failures
snappy-dove-250 identified (gunbc#9535, #9541, #9551), all closed on main and
none of them this branch's. No content change.
Base update: this branch predated gunbc#9560 (ba27746), which brackets the
diagnostic-census memo fill out of CPU. The floor row refusing every run in this
lane -- callable_candidate_ambiguity_witness, COMPLETED-OVER-COST-REQUIREMENT --
is dominated by four nested compiles through that memo. Verified with
git merge-base --is-ancestor before merging, not assumed.
@briansrls
briansrls merged commit 82059ba into main Aug 28, 2026
1 of 3 checks passed
@briansrls
briansrls deleted the session/quick-swift-434-emitter-deserialize-finding branch August 28, 2026 18:04
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.

1 participant