Skip to content

namespace-structural-observations: the closing check first, then one ordinary compiled file answering all four through it - #9554

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

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

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Closes the roadmap row namespace-structural-observations in the order its own first slice prescribes: the closing check first, then one ordinary compiled file producing all four in-file visibility observations through it.

The closing check (written before the production that satisfies it)

gunbc.namespace_structural_observations_contract requires four capabilities, each ESTABLISHED only by assessing a typed production observation through the single authority that already owns that judgement (gunbc.namespace_reference_derived_closure_admission assess_reference_binding_observation) — never by counting variants, so four StructuralBindingProductionRefused observations green nothing. The set difference is the parent row's own fold, parameterized in its required population rather than copied, so this row cannot drift from the parent's dominance rule and the parent's closing predicate is unchanged.

Subject provenance is the half the 2026-08-04 retraction named as missing. Every admission carries the module path THE PARSE DECLARED — read out of ParsedOccurrenceBindingSourceReady.module_path, never echoed from the caller's file argument — and the check refuses unless all four name the one declared subject. Four admissions from four hand-built sources satisfy the capabilities and fail this check, which is exactly the difference between the row as written and the fixture suite that preceded it.

One ordinary compiled file

The four hard-coded per-clause fixture sources in the v1 producer are deleted. It now takes one subject plus four probe spellings from its caller and reads all four observations out of a single parse; it knows no fixture text. One ordinary module carries all four cases: an earlier neighbour called from a later sibling, one let name in both arms of a decision, a callee declared further down, and a parameter plus a let of one spelling at two positions.

Each case shown failing on its own

Four red controls, each a single replace on the accepted subject text, so a control cannot quietly become a different program. Each asserts the missing-capability set is EXACTLY the capability whose rule the edit broke — a control asserting only "the contract is false" would pass equally well if the bridge returned nothing at all. A fifth control changes only the module declaration: all four capabilities still establish and the row still refuses, which is the provenance clause failing on its own.

The typed subject carrier, and the two ruled controls that came with it

The compiled-module result was a String with EMPTY standing for "the parse refused" — the empty-observation narrow, in a carrier that had a typed absence available. git grep nrdfc_compiled_module is absent at this PR's merge base and absent on main, so this PR introduces it; fixing an inherited defect in a follow-up is ordinary, landing a new one knowingly and scheduling its repair is not. It is now StructuralObservationSubjectModule = SubjectModuleProduced { module_path } | SubjectModuleProductionRefused { gap }, declared in std.reference_binding_observation — the neutral carrier both sides already import, so there is one authority rather than a v1 spelling and a dag spelling of one concept — with the refusal reusing ReferenceBindingProductionGap rather than a second gap vocabulary. "Fail-closed today" was not sufficient: "" never equalling the declared subject was a property of what the one current consumer did with the string, not of the carrier.

Two further controls, each discriminating by construction — delete the conjunct it targets and it reds:

  • a_row_nobody_produced_does_not_close_this_row. Stated honestly: this is the authorable projection of the ruled control "bridge registration removed → closing witness cannot execute", not that control itself. A witness cannot unregister a host builtin, so it asserts what that state looks like to this contract — no rows offered — and that a contract closing on zero rows would be green for a row nothing produced. Weaker than the ruled version, and discriminating: it is the only thing that fails if count(rows) > 0 is deleted.
  • established_capabilities_with_an_unproduced_subject_still_refuse. The carrier-shape control. Flattening the result to Bool keeps the capability half and loses the subject half, so the discriminating input is rows whose four capabilities all establish over a subject identity that was not produced.

A third ruled control is deliberately absent, and reading the producer made the reason stronger than "wrong owner". The ruled control is "live-tree acquisition introduced → SubstrateInputsOnly refuses". v2.std.live_tree live_tree_disposition_note states in the tree, at length, that a row declaring SubstrateInputsOnly while actually reading live state is re-checked by nothing — the enforcement it used to name (the nightly affected-set falsifier's predict-only cold run) died with falsifier.yml in the 2026-08-15 floor cut, and its re-add sits on DESIGN's unguarded list. So the control would not be testing a wall I do not own; it would be asserting a wall the corpus documents as absent, which is worse than the permanently-green decoration it superficially resembles, because it would be cited as coverage of a known no-wall.

One qualification, because "nothing checks it" is very slightly too strong and the difference is load-bearing: v2.std.effect_reach reads_live_tree_effective takes the declared answer first and falls through to a derivation only when the row says SubstrateInputsOnly — so a partial backstop does fire on exactly the lying case. Its ceiling is declared at effect_reach_detection_ceiling and executed by a planted fixture pair: it classifies a closure as host-reading only when a repository path literal and a host-sink call shape both occur, so a closure performing a real read while naming no path derives NOT-live. That is a declared, executed ceiling — not an enforcement a control could stand on, and not nothing either.

A control asserting merely that the disposition field reads SubstrateInputsOnly is not written here on purpose: its red is unreachable by construction, which §4b calls worse than absent. The disposition of this gap is an obligation, not a ceiling — the named next-rung capability is call-reachability-grade classification (fn-arrow DependencyView over lowered bodies), and it is unbuilt.

The host bridge, and why it exists

The observations come from v1.compiler.parse, and the required floor resolves dag and src/v2 only; measured over the corpus, no dag module imports v1, so a dag witness cannot name the producer. namespace_structural_observation_admissions is a hermetic transport across that boundary — one in-memory source, no repository file read, no module index — so the witness declares SubstrateInputsOnly truthfully and executes in the floor rather than landing in its DeclinedLiveTree arm. It decides nothing: subject from the caller, observations composed in .dag, judgement by the shared authority. Declared and enrolled as seed growth (gunbc.namespace_structural_observation_bridge_seed_growth, 2 hand items), with a trigger naming the CAPABILITY it must be sufficient for rather than an artifact that would contribute to one.

The two rejected alternatives are recorded in that row: a witness under src/v1/tests would bind the contract to evidence no required run executes (coverage by illusion), and rebuilding the observations on the v2 pipeline would put a second resolution authority beside the P2a/P1 kernel.

Measured

  • All six witnesses PASS through the bridge from a dag-only witness (--source-root dag --source-root src/v2), and independently on both architectures via the direct v1 route before the bridge existed.
  • claim_executor --required-regen: first_generation_equal=true, EXIT=0.
  • Generated artifacts converged via generated_artifact_gate main_wet (ROADMAP.md, the dispatch surface).

One substrate limitation found by execution and recorded rather than routed around

A .dag record embedding a sole_constructor-bearing coproduct emits Serialize-only with a private field, so the seed does not compile (E0277 on the record, E0616 on the receipt field). That is why the producer exports the compiled module and the admissions separately; both are pure functions of (file, source), so one pair of strings cannot pair a module path with admissions from a different subject.

Note for review

Four emitted mirrors (v1_compiler_emit_{core_support,go,python,rust}.rs) are not this change's — they are a pre-existing regen drift on main that my regen correctly picked up, already in flight as #9537. Measured by hash, all four are byte-identical to #9537's (6317702515, e4e4fd9bd2, 705cfab2ca, 8abac9e235), so this change contributed no qualification of its own; had it, the bytes would differ. Its cause (established by smart-ram-730 and clever-boar-140) is a composition of #9486 and #9461, merged three minutes apart from an identical base with no textual conflict for any gate to see. Identical bytes cannot conflict, so #9554 and #9537 may land in either order. Installed from the regen candidate, never hand-edited; --required-regen is the adjudicator and it is green.

🤖 Generated with Claude Code

https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje

…ordinary compiled file answering all four through it

WHAT THE ROW ASKED. Make an ordinary compiled path produce, for each name written
in a file, the declarations actually in view from that position: an earlier
neighbour is in view, a declaration in another decision branch is not, one written
further down is not, and two same-spelled declarations at different positions stay
distinct. Write the closing check FIRST, then make ONE file answer all four
through it.

THE CLOSING CHECK, WRITTEN BEFORE THE PRODUCTION THAT SATISFIES IT.
gunbc.namespace_structural_observations_contract requires four capabilities, each
ESTABLISHED only by assessing a typed production observation through the one
authority that already owns that judgement (assess_reference_binding_observation),
never by counting variants -- so four StructuralBindingProductionRefused
observations green nothing. The set difference is the parent row's own fold,
parameterized in its required population rather than copied, so this row cannot
drift from the parent's dominance rule.

SUBJECT PROVENANCE IS THE HALF THE 2026-08-04 RETRACTION SAID WAS MISSING. Every
admission carries the module path THE PARSE DECLARED -- read out of
ParsedOccurrenceBindingSourceReady, never echoed from the caller's file argument --
and the check refuses unless all four name the one declared subject. Four
admissions from four hand-built sources satisfy the capabilities and fail this
check, which is exactly the difference between the row as written and the fixture
suite that preceded it.

ONE FILE, AND THE FOUR HARD-CODED FIXTURE SOURCES ARE DELETED. The v1 producer no
longer knows any fixture text: it takes one subject and four probe spellings from
its caller, and reads all four observations out of a single parse. Its own note
already recorded that four independent strings could not satisfy this row; keeping
them beside a subject-parameterized producer would have left two ways to answer one
question and made the easier one the one that cannot close the row.

EACH CASE SHOWN FAILING ON ITS OWN. Four red controls, each a SINGLE `replace` on
the accepted subject text, so a control cannot quietly become a different program:
the neighbour stops being earlier, the else arm loses its own binder, the later
declaration is hoisted into view, the two homonyms merge into one. Each asserts the
missing-capability set is EXACTLY the capability whose rule the edit broke -- a
control asserting only "the contract is false" would pass just as well if the
bridge returned nothing. A fifth control changes only the module declaration: all
four capabilities still establish and the row still refuses, which is the
provenance clause failing on its own.

THE HOST BRIDGE, AND WHY IT EXISTS. The observations come from v1.compiler.parse
and the required floor resolves `dag` and `src/v2` only; measured over the corpus,
NO dag module imports v1, so a dag witness cannot name the producer.
namespace_structural_observation_admissions is a hermetic transport across that
boundary: one in-memory source, no repository file read, no module index, so the
witness declares SubstrateInputsOnly truthfully and executes in the floor rather
than landing in its DeclinedLiveTree arm. It decides nothing -- subject from the
caller, observations composed in .dag, judgement by the shared authority. Declared
and enrolled as seed growth (2 hand items) with a trigger naming the CAPABILITY it
must be sufficient for, not an artifact that would contribute to one.

MEASURED, NOT ASSERTED. All six witnesses PASS through the bridge from a dag-only
witness (roots dag + src/v2), and independently on both architectures via the
direct v1 route before the bridge existed. required-regen:
first_generation_equal=true, EXIT=0.

ONE SUBSTRATE LIMITATION FOUND BY EXECUTION AND RECORDED RATHER THAN ROUTED
AROUND: a .dag record embedding a sole_constructor-bearing coproduct emits
Serialize-only with a private field, so the seed does not compile (E0277, E0616).
That is why the producer exports the compiled module and the admissions separately;
both are pure functions of (file, source), so one pair of strings cannot pair a
module path with admissions from another subject.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
gunbai-bot Bot pushed a commit that referenced this pull request Aug 28, 2026
…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
Brian Searls and others added 5 commits August 28, 2026 02:54
Brings the three main-side causes this branch was failing on, all closed on main:
  gunbc#9535 the barren test sidecar (BarrenTestSidecar)
  gunbc#9541 the 53 stale namespace-transition admissions
  gunbc#9551 restore the four emit mirrors to what the closure emits (regen drift)
The branch was behind main and inherited all three; the merge is clean and carries
no content change of its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013crMNyLvjKC2Q5UF851PKy
…Debug (review 57100)

review 57100 approved and flagged the Debug-formatted variant encoding in
reference_derived_closure_admission_value as mildly fragile. It is, and the fix is
cheap: all three enums are spelled by a total match returning the name.

WHAT THE FRAGILITY ACTUALLY IS, measured rather than assumed. All three enums --
Capability, ScenarioFailure, Trigger -- are nullary today, so Debug prints exactly the
variant name and the seam is correct. It stops being correct the moment any variant
gains a payload: Debug would print `Foo { .. }` and this seam would mint a variant name
no .dag match accepts. That fails LOUDLY rather than silently, so the objection is not
that it hides a defect -- it is that the failure lands at runtime on a name. A total
match makes the same mistake a compile error at this seam, which is the
construction-over-validation direction, and it stops the Rust identifier from standing
as a second representation of the variant's identity.

All six witnesses re-run PASS through the bridge after the change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
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.
…eProductionRefused

The compiled-module result was a String with EMPTY standing for "the parse refused" --
the empty-observation narrow, in a carrier that had a typed absence available. Ruled
fixable HERE rather than in a follow-up, on a fact I verified before acting: git grep
nrdfc_compiled_module is ABSENT at this PR's merge base and absent on main, so this PR
INTRODUCES the conflation. Landing a new one knowingly and scheduling its repair is the
deferred-refactor pattern, and registering a future fix is not a permit.

WHY "FAIL-CLOSED TODAY" WAS NOT SUFFICIENT: '' never equalling the declared subject is a
property of what the one current consumer does with the string, not of the carrier. The
next consumer gets no help from the type, and the conflation is invisible exactly where
it would go wrong. The module note said "a source that does not parse reports no module
at all" -- true of the VALUE, false of the CARRIER. Both are true now.

WHERE THE TYPE LIVES: std.reference_binding_observation, the neutral carrier both sides
already share, so there is one authority rather than a v1 spelling and a dag spelling of
one concept; and the refusal reuses ReferenceBindingProductionGap rather than minting a
second gap vocabulary beside it.

TWO OF THE THREE RULED CONTROLS, both authored and both discriminating by construction --
delete the conjunct each targets and it goes red:

  a_row_nobody_produced_does_not_close_this_row
    the authorable projection of "bridge registration removed -> witness cannot execute".
    A witness cannot unregister a builtin; it can assert what that state looks like here --
    no rows offered -- and that a contract closing on zero rows would be green for a row
    nothing produced. It is the only thing that fails if count(rows) > 0 is removed.

  established_capabilities_with_an_unproduced_subject_still_refuse
    the carrier-shape control. Flattening to Bool keeps the capability half and loses the
    subject half, so the discriminating input is rows whose four capabilities ALL establish
    over a subject identity that was not produced. It also pins that the refusal reports its
    own reason rather than an empty path.

THE THIRD CONTROL IS NOT HERE AND IS NOT FAKED. "Live-tree acquisition introduced ->
SubstrateInputsOnly refuses" needs a mutant that actually performs a live read, which is
not authorable from inside a hermetic witness. Raised separately rather than allowed to
hold the other two.

MEASURED: all six original witnesses PASS on the typed carrier, plus the two new controls.
required-regen first_generation_equal=true EXIT=0; generated-artifact gate EXIT=0.
Seed-growth roster updated to +3 with subject_module_value enumerated.

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

review 57241 approved and flagged, as nit-quality, that structural_admission_subject_mismatch
reported an unproduced subject as the literal "<subject module not produced>" and the
acceptance test asserted that exact spelling. The observation is right and the fix is the
same one this PR already made one level up, so leaving it would have been inconsistent with
its own argument: a coproduct that already has names does not need a string that repeats one
of them, and a test coupled to the spelling would go green on any other sentinel.

  StructuralAdmissionSubjectMismatch
    = AdmissionNamesAnotherModule { module_path }
    | AdmissionSubjectNotProduced { gap }

The gap travels through rather than being flattened, so the reason the subject was not
produced survives to the consumer instead of stopping at "not produced". The control now
counts the AdmissionSubjectNotProduced variant rather than matching text.

No mirror or regen impact: the contract module is not in the seed's emit closure, and the
type is contract-local rather than another row in the neutral std carrier -- a subject
mismatch is this contract's judgement, not a neutral observation about a parse.

MEASURED: all eight witnesses PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nRBJLauCBLwBH8inAFHje
@briansrls
briansrls merged commit 7da3856 into main Aug 28, 2026
1 of 3 checks passed
@briansrls
briansrls deleted the session/quick-swift-434 branch August 28, 2026 18:04
briansrls pushed a commit that referenced this pull request Aug 28, 2026
* File the emitted-record Deserialize gap as its own class row, with both 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

* Measure the premise the trigger's refusal clause rested on: it is false, 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

* Cite an export that exists on main: the forward reference would have 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

* The rung stands at mitigatable, and the sentence that made it look wrong 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

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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.

1 participant