Skip to content

The emission instrument's subject was a String entry, so it could not say which root was primary — and three runs were reported as whole-corpus while measuring 3109 of 4170 sources - #9581

Merged
briansrls merged 4 commits into
mainfrom
session/clever-tern-899-s2subject
Aug 28, 2026

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

This is S2-B — binding the exact subject before another long run, rather than after.

Measured, not hypothetical

Three whole-corpus runs taken 2026-08-28 under --source-root dag --source-root src/v2 each reported, in the compiler's own words:

resolved 3109 sources (primary-root population root=dag), 1061 indexed modules in the name census only

The CLI takes the first source root as the primary population and later roots as dependency pools. So src/v2 — the v2 compiler, which is what self-host is about — was indexed and never compiled as subject. All three runs were reported as whole-corpus, by everyone including the session that took them.

A String entry cannot express that distinction, so no receipt built on one can be wrong about it out loud. It is simply silent, and a silent subject is read as the subject the reader expected.

What lands

EmissionScope = EntryScope { entry } | PrimaryRootScope { primary_root, dependency_pools }. The pool list is carried separately from the primary root, so the confusion that produced this is unrepresentable rather than documented (§5, construction over validation).

EmissionRenderTarget, and it decides the argv rather than describing it. The target was hardwired --target rust inside the invocation. A field beside it would have been a second representation of one fact, free to disagree with the run it claims to describe. emission_compile_args renders the invocation from the scope and the target, so a receipt saying Rust was produced by a run that passed rust, by construction.

measure_entry_emission keeps its name and signature and becomes one call into measure_scope_emission. An entry measurement and a primary-root measurement are one operation at two breadths — §2's horizontal move — not two instruments.

Assembly refuses rather than fabricating an entry. cssl_assemble takes a single --entry-dag; a primary-root scope names a population. Handing it the primary root would assemble a subject the measurement never named. It returns EmissionCargoUnreached at StageAssemble with a typed cause, carrying its emit population, which is real.

What is deliberately absent

The module roster's content-addressed identity. A subject now binds revision, tree standing, both binaries, scope and target — enough to say what was asked for, not enough to say which modules answered. A dirty tree is flagged but not enumerated. The next-rung trigger is recorded on the type rather than left to be discovered: a digest over the resolved roster, at which point two receipts can be compared for subject identity instead of for argv equality.

Evidence

45/45 witnesses pass.

The order claim is asserted as the whole argv rather than as a predicate over it, and that choice is the point: order is the fact under test, and a membership check cannot see order at all — the wrong argv contains identical elements.

Discriminating by mutation: rendering pools before the primary root fails a_primary_root_scope_renders_the_primary_root_before_its_pools alone (44 pass, 1 fail); restoring gives 45. Its mirror (swapping_which_root_is_primary_renders_a_different_argv) correctly stays green under that plant, since a swap still differs — the two are independent rather than redundant.

Scope

No open PR touches this instrument (checked across all 40 open PRs). This changes no milestone standing and persists no board: SelfHostWholeCorpusPopulationDerived remains NotDerivable. It is the subject carrier the board will need, landed first because the ruling is to bind the subject before spending another half hour measuring a denominator the eventual board cannot prove.

CI will be red until #9517 lands — main has been red for hours on a single over-cost row with failed=0 unexpected_failures=0. Not this diff.

gunbc-ci-auto-heal and others added 2 commits August 28, 2026 05:42
… say which root was primary — and three runs were reported as whole-corpus while measuring 3109 of 4170 sources

MEASURED, NOT HYPOTHETICAL. Three whole-corpus runs taken 2026-08-28 under
`--source-root dag --source-root src/v2` each reported, in the compiler's own
words:

  resolved 3109 sources (primary-root population root=dag),
  1061 indexed modules in the name census only

The CLI takes the FIRST source root as the PRIMARY POPULATION and later roots as
DEPENDENCY POOLS. So src/v2 -- the v2 compiler, which is what self-host is about
-- was indexed and never compiled as subject. All three runs were reported as
whole-corpus, by everyone including the session that took them.

A `String` entry cannot express that distinction, so no receipt built on one can
be WRONG ABOUT IT OUT LOUD. It is simply silent, and a silent subject is read as
the subject the reader expected.

WHAT LANDS

EmissionScope = EntryScope { entry } | PrimaryRootScope { primary_root,
dependency_pools }. The pool list is carried SEPARATELY from the primary root, so
the confusion that produced this is unrepresentable rather than documented
(DESIGN section 5, construction over validation).

EmissionRenderTarget, and it DECIDES THE ARGV rather than describing it. The
target was hardwired `--target rust` in the invocation; a field beside it would
have been a second representation of one fact, free to disagree with the run it
claims to describe. emission_compile_args renders the invocation FROM the scope
and the target, so a receipt saying Rust was produced by a run that passed rust,
by construction.

measure_entry_emission keeps its name and signature and becomes one call into
measure_scope_emission. An entry measurement and a primary-root measurement are
one operation at two breadths -- section 2's horizontal move -- not two
instruments.

ASSEMBLY REFUSES RATHER THAN FABRICATING AN ENTRY. cssl_assemble takes a single
--entry-dag and a primary-root scope names a population; handing it the primary
root would assemble a subject the measurement never named. It returns
EmissionCargoUnreached at StageAssemble with a typed cause, and carries its emit
population, which is real.

WHAT IS DELIBERATELY ABSENT, named rather than left to be discovered: the module
roster's content-addressed identity. A subject now binds revision, tree standing,
both binaries, scope and target -- enough to say WHAT WAS ASKED FOR, not enough
to say WHICH MODULES ANSWERED. Trigger recorded on the type.

EVIDENCE. 45/45 witnesses pass. The order claim is asserted as the WHOLE ARGV
rather than as a predicate over it, because order is the fact under test and a
membership check cannot see order at all -- the wrong argv contains identical
elements. Discriminating by MUTATION: rendering pools before the primary root
fails `a_primary_root_scope_renders_the_primary_root_before_its_pools` ALONE
(44 pass, 1 fail); restoring gives 45.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…over, and give the scope's entry ONE home instead of a projection per caller

review 57167 (codex, REQUEST_CHANGES) is correct and the finding is exactly the
one my own evidence should have caught: I ran the instrument's witness suite and
never the dependents I had already listed. gunbc.emit_subject_clean_frontier
projected `s.entry` at four sites and its fixture constructed the removed field,
so the migration was a root cutover that stopped short of two of its roots.

ONE AUTHORITY, TWO CONSUMERS. The obvious fix -- descend into the scope at each
site -- would have put a second scope projection in the frontier beside the one
the instrument already had for assembly. Both ask the same question: WHICH ENTRY,
IF ANY, DOES THIS SCOPE NAME. So EmissionAssemblyEntry is generalised to
EmissionScopeEntry (ScopeEntry | ScopeNamesNoEntry) and both callers consume it.
Naming it for the assembler was the accident of which consumer arrived first.

THE FRONTIER'S NO-ENTRY ARM IS THE PART THAT NEEDED THOUGHT, because the wrong
answer here is silent. The fold joins measurements to its roster on entry
identity. Returning the raw primary root would produce a FALSE ROSTER MATCH on a
measurement that was never about that entry. Returning the prefixed scope label
cannot equal a repository-relative `.dag` path, so the lookup answers
SubjectReadingAbsent -- accurate for a measurement about no entry in the roster.

WITNESSED WITH THE UNKIND FIXTURE: the population scope's primary_root IS
fixture_alpha, the entry the roster carries, so the false-match shape is what the
test discriminates against rather than something it could pass by luck. Its
sibling asserts the entry arm still returns the BARE path, so a change making
both return the label fails there rather than passing above.

This fold never receives a population scope today -- its measurements come from
measure_entry_emission, which always produces an EntryScope. The arm is witnessed
anyway: a state unreachable through one producer is still authorable in a
fixture, and an unwitnessed arm is where the next producer's mistake lands.

EVIDENCE. Frontier 63/63, instrument 45/45. Discriminating by MUTATION: making
the no-entry arm return its raw primary root fails
`a_population_scoped_measurement_does_not_match_a_roster_entry` ALONE (62 pass,
1 fail); restore gives 63.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

review 57167 is correct and I have pushed the fix (57f367e2e35). Both dependents are cut over.

The finding is exactly the one my own evidence should have caught. I ran the instrument's witness suite and never the dependents I had already listed with a grep. That is the specification-without-execution shape one level out: I had the consumer list and tested none of them.

One authority, two consumers — not a projection per caller. The obvious fix is to descend into the scope at each of the four s.entry sites, but that would put a second scope projection in emit_subject_clean_frontier beside the one the instrument already had for assembly. Both ask the same question — which entry, if any, does this scope name — so EmissionAssemblyEntry is generalised to EmissionScopeEntry (ScopeEntry | ScopeNamesNoEntry) and both callers consume it. Naming it for the assembler was the accident of which consumer arrived first (§3).

The frontier's no-entry arm is the part that needed thought, because the wrong answer there is silent. That fold joins measurements to its roster on entry identity. Returning the raw primary root would produce a false roster match on a measurement that was never about that entry. Returning the prefixed scope label cannot equal a repository-relative .dag path, so the lookup answers SubjectReadingAbsent — the accurate answer for a measurement about no entry in the roster.

Witnessed with a deliberately unkind fixture: the population scope's primary_root is fixture_alpha, the very entry the roster carries — so the false-match shape is what the test discriminates against, not something it could pass by luck. Its sibling asserts the entry arm still returns the bare path, so a change making both return the label fails there rather than passing above.

This fold never receives a population scope today (its measurements come from measure_entry_emission, which always produces an EntryScope). The arm is witnessed anyway: a state unreachable through one producer is still authorable in a fixture, and an unwitnessed arm is where the next producer's mistake lands.

Evidence. Frontier 63/63, instrument 45/45. Discriminating by mutation: making the no-entry arm return its raw primary root fails a_population_scoped_measurement_does_not_match_a_roster_entry alone (62 pass, 1 fail); restoring gives 63.

On CI: this PR's floor lane reproduces main exactly. As of c9043b967c7 (#9106, "Delete the floor's stale live-tree decline"), main fails 47 witnesses — planned=12944 passed=12610 known_red_held=33 failed=47, identical counters here. Those are latent facts the deletion exposed, not defects in this diff; I have routed ten work items against the underlying facts.

— sent from clever-tern-899

…e new projection — reintroducing, on Unestablished, the exact class this PR closes

review 57181 is correct. measure_scope_emission bound
`let entry = emission_scope_label(sc: scope)` and threaded it into every
EmissionSubjectUnestablished arm. For EntryScope { entry: "foo.dag" } that label
is "entry foo.dag", so emission_measurement_entry returned "entry foo.dag" and
the frontier's roster join answered SubjectReadingAbsent FOR EXACTLY THE ENTRY
THE RUN WAS ABOUT.

That is the silent-subject-mismatch class this PR exists to close, reintroduced
on the arm I had not routed through the projection I had just built for the other
four. Before this PR those arms received the raw entry string and the join worked.

THE FIX IS ONE AUTHORITY, NOT A THIRD DESCENT. Three callers need the same
answer: the frontier joins on it, measure_scope_emission stamps it onto the
unestablished arms, and both must agree or a run joins to nothing under a name
that looks right. So emission_scope_join_key owns it, and the frontier's local
match is deleted in favour of calling it. A second derivation of one key is free
to disagree with the producer that writes it -- which is precisely the
disagreement the review found, in the other direction.

AN ENTRY SCOPE PRESENTS ITS BARE PATH, NEVER ITS LABEL. The label is correct
prose and a wrong key. A population scope presents the label deliberately:
prefixed, so it cannot collide with any path and joins to nothing -- the accurate
answer rather than a false match on whichever root it names.

EVIDENCE. Instrument 47/47, frontier 63/63. The regression control is
discriminating BY MUTATION against the review's own defect: collapsing the join
key to the label for BOTH arms fails
`an_entry_scopes_join_key_is_its_bare_path_and_not_its_label` ALONE (46 pass,
1 fail); restoring gives 47. Its sibling asserts the population arm still
presents the label, so a fix in the opposite direction fails there instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

review 57181 is correct and is a better catch than the one before it. Fixed in f93b6ca83c0.

measure_scope_emission bound let entry = emission_scope_label(sc: scope) and threaded that into every EmissionSubjectUnestablished arm. For EntryScope { entry: "foo.dag" } the label is "entry foo.dag", so emission_measurement_entry returned "entry foo.dag" and the frontier's roster join answered SubjectReadingAbsent for exactly the entry the run was about.

That is the silent-subject-mismatch class this PR exists to close, reintroduced on the one arm I had not routed through the projection I had just built for the other four. Before this PR those arms received the raw entry string and the join worked — so I made it worse on that path while fixing it on the rest.

The fix is one authority, not a third descent. Three callers need the same answer: the frontier joins on it, measure_scope_emission stamps it onto the unestablished arms, and they must agree or a run joins to nothing under a name that looks right. emission_scope_join_key now owns it and the frontier's local match is deleted in favour of calling it. A second derivation of one key is free to disagree with the producer that writes it — which is precisely the disagreement this review found, in the other direction.

An entry scope presents its bare path, never its label: the label is correct prose and a wrong key. A population scope presents the label deliberately — prefixed, so it cannot collide with any path and joins to nothing, the accurate answer rather than a false match on whichever root it names.

Evidence. Instrument 47/47, frontier 63/63. The regression control is discriminating by mutation against the review's own defect: collapsing the join key to the label for both arms fails an_entry_scopes_join_key_is_its_bare_path_and_not_its_label alone (46 pass, 1 fail); restoring gives 47. Its sibling asserts the population arm still presents the label, so a fix in the opposite direction fails there instead rather than passing silently.

Worth noting what the two reviews on this PR have in common, since it is the same defect at two depths: both found a join key that looked right and could not match. The first was four sites reading a removed field; the second was one site reading the wrong projection of the new one. The repair for both is that the key has exactly one producer.

CI: this branch reproduces main. As of c9043b967c7 (#9106) main fails 47 witnesses with identical counters; those are latent facts that deletion exposed, not this diff. Ten work items are routed against the underlying facts.

— sent from clever-tern-899

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Investigated. This PR introduces no failure and there is nothing here for me to fix — the evidence is below, because "same count" is not an argument.

The 47 failing identities are identical to main's, by identity join and not by count. I extracted the FAIL set from this run (job 98778652400) and from main's, and diffed them:

only in #9581:  (none)
only in main:   (none)
shared:         47

Count equality would have proved nothing — a PR can fix one row and break another and still report 47. The empty symmetric difference is what establishes it.

Positive evidence that this branch's own witnesses pass, from the arm-by-arm comparison against main's run:

planned                          12944 -> 12961   +17
passed                           12610 -> 12627   +17
known_red_held                      33 ->    33   unchanged
failed                              47 ->    47   unchanged
stale_quarantine                     1 ->     1   unchanged
interrupted_before_verdict          44 ->    44   unchanged
completed_over_cost_requirement      2 ->     2   unchanged
route_gap_held                     207 ->   207   unchanged

This PR adds 17 planned identities and 17 passes — every identity it introduces passed. required-witnesses-build also passes; only the floor lane fails, on rows this branch does not touch.

Why the arm table matters and is not padding. A change touching a budget, a route-gap disposition or a home-policy prefix silently relocates identities between failed and interrupted_before_verdict, so two runs can agree on failed while measuring different populations. Here every non-passed arm is pinned and only planned/passed moved, by exactly the same amount — so no relocation occurred and the comparison is sound. That check is owed whenever failure counts are compared across branches; without it, "47 = 47" is not a null result.

Main is red with these 47 (see the same figures on main's own run). They are routed: I have children on the doc-graph, enforcement, realization-vocabulary, mandatory-tag, grammar round-trip and self-host-candidate rows, and I dispatched the largest remaining cluster — the 14-identity guarantee-probe family — this morning. Fixing them from this branch would be repairing unrelated subjects inside an instrument-scope PR.

So: no fix pushed, deliberately. If a further review finds a defect in this diff I will act on it; the red is not one.

— sent from clever-tern-899

@briansrls
briansrls merged commit 44aab00 into main Aug 28, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/clever-tern-899-s2subject branch August 28, 2026 19:28
@briansrls
briansrls restored the session/clever-tern-899-s2subject branch August 28, 2026 19:29
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