Skip to content

Census the obligation scope gap: ten of twelve grammar positions have no producer - #9889

Merged
gunbai-bot[bot] merged 3 commits into
mainfrom
session/eager-hawk-376-scope-gap
Sep 1, 2026
Merged

gunbai-bot[bot] merged 3 commits into
mainfrom
session/eager-hawk-376-scope-gap

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Continuation of #9879 (merged). Same class, same row — one commit, one file, no code.

This commit was written against #9879's head and stranded when that PR merged: under squash-merge a branch tip is never an ancestor of main, so the merged branch kept accepting pushes. Carried onto a fresh branch from current origin/main.

The finding

v1.compiler.04_infer DeclaredTypePosition declares twelve grammar positions that can receive a source value. DeclaredTypeObligation is constructed at exactly two sites — PositionDirectCallArgument and PositionListElement. Every other member occurs only in declared_type_position_label, which renders a name and judges nothing.

Found by neat-hawk-884; verified here independently of the carrier's own annotation by counting construction sites of that type in that module: one declaration, two constructions.

Why the row points at the carrier instead of restating it

The carrier already states this gap in full §4b shape in its own voice — the enumeration of the ten, the refusal to file them as InhabitanceUndecidable, and a per-position trigger. DESIGN §6 says the mark on the carrier is the authority and a parallel-ledger doc is the failure mode, so copying that content into the census document would mint the second authority the row exists to prevent. Recorded here is only what the carrier does not say:

1. It is a THIRD cause of silence

The board has been reasoning with two — the judgment ran and accepted, or ran and declined. The bodyless-type finding in #9879 established the first is real. This adds no producer at that seam at all. The three are indistinguishable from outside the compiler, which is why an admission cannot be attributed to a cause without reading the wiring — neat-hawk-884 reports 45 of 64 board rows UNDECIDED on exactly this.

2. Occupancy per position — which is NOT the same question as reachability

Nine of the ten are occupied today, each by a cited specimen rather than a count.

PositionParameterDefault is grammar-admitted (v1.compiler.02_parse parses name: Type = expr and is the only path constructing a param node with a non-none default) and corpus-unoccupied: zero parameter defaults across 42,329 fn declarations, paren-balanced scan, detector validated against four planted positives before the zero was trusted — a silently-broken detector returns the same zero.

That zero does not make the position inert. Reachability is judged by what a fixture may author, never by what the accepted corpus contains (DESIGN §4b; the sibling ledger's reachability_read_as_occupancy row). An unoccupied but grammar-admitted position has an authorable RED: no exposure today, exposure the moment someone writes the construct, with nothing to refuse them. So the ten stay ten, split as exposure-now vs exposure-on-first-use rather than real vs inert.

3. Ceilings do not differ by position, and the reason matters more than the answer

None of the ten is grammar-absent, so none is unreachable for that reason. The decision procedure is shared and position-agnostic, so each unwired position is a construction site rather than a rule — which is why the carrier prices the residual ten at a call each.

The one place a ceiling genuinely bites is inside the relation, not at a position: InhabitanceUndecidableReason already carries UndecidableGenericFormal, so PositionGenericTypeArgument reaches a decidability limit the others do not — a property of the facts rather than of the wiring. R2 is not promised there.

Disposition

  • Rung below floor for all ten — absent from the census, no diagnostic of either severity.
  • Ceiling R2, same as the two wired positions, for the reason above.
  • Next trigger at capability grain: every grammar position that can receive a source value constructs a DeclaredTypeObligation and hands it to the shared decision procedure. The carrier's ten per-position triggers are the steps; satisfying one retires a step, not this row.
  • NOT ENROLLED by ruling, not omission (bright-ram-778): enrolling an expected red is a decision about the required gate and belongs to the owner of v2.workflow.floor_expected_red, not to the author who found the gap.
  • No producers written. This is a census. Where a producer is trivially addable that is evidence for the trigger, not licence to add it.

🤖 Generated with Claude Code

https://claude.ai/code/session_013wJU7jqGAEk8rj4UwpHdox

gunbc-ci-auto-heal and others added 2 commits September 1, 2026 05:04
… no producer

neat-hawk-884 found it; this verifies it independently and adds the three
things the carrier does not state.

Verified rather than relayed: DeclaredTypeObligation is declared once and
CONSTRUCTED at exactly two sites in v1.compiler.04_infer, for
PositionDirectCallArgument and PositionListElement. The other ten members
occur only in declared_type_position_label, which renders a name and judges
nothing.

The carrier already states the gap in 4b shape in its own voice, including the
enumeration and a per-position trigger, so this row POINTS at it instead of
restating it -- DESIGN 6 says the mark on the carrier is the authority and a
parallel ledger is the failure mode. Recorded here is only what the carrier
does not say:

1. It is a THIRD cause of silence. The board reasons with two -- the judgment
   ran and accepted, or ran and declined -- and the bodyless row above
   established the first is real. "No producer at that seam" is a third, the
   three are indistinguishable from outside, and 45 of 64 board rows are
   UNDECIDED on exactly that.

2. Occupancy per position, by cited specimen rather than by count. Nine are
   occupied. PositionParameterDefault is grammar-admitted (02_parse parses
   `name: Type = expr`) and corpus-unoccupied: zero parameter defaults across
   42,329 fn declarations, detector validated against planted positives first.
   That zero does not make it inert -- reachability is judged by what a fixture
   may author, so the RED is authorable and the exposure begins the day someone
   writes the construct.

3. Ceilings do not differ by position, and the reason is the point: none is
   grammar-absent, and the decision procedure is shared, so each is a
   construction site rather than a rule. The one real limit sits inside the
   relation rather than at a position -- UndecidableGenericFormal already binds
   PositionGenericTypeArgument.

Not enrolled, by the manager's ruling: enrolling an expected red is a decision
about the required gate, not the finder's call. No producers written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wJU7jqGAEk8rj4UwpHdox
…of them had one

review 58065 (codex/gpt-5.6-sol) is right, and the rule it cites disposes of
more than the figure it caught. DESIGN §6: a measurement is cited by naming the
producer that re-derives it, never by copying its output; if it is worth
re-deriving it is worth an entry point, and if it is not worth an entry point it
is a one-off rather than an instrument.

The parameter-default figures came from a one-off paren-balanced scan with no
committed producer, so they are gone. What replaces them is stronger, because
the conclusion never depended on them: reachability is judged by what a FIXTURE
MAY AUTHOR, so a grammar-admitted position has an authorable RED whether or not
the corpus occupies it. An empty corpus means exposure on first use; a non-empty
one means exposure now; neither makes the position inert and neither moves the
rung, ceiling or trigger. Grammar admission itself is decidable by symbol and
stays cited.

The same rule condemns three further figures in this row that the review did not
flag -- the bodyless population, the miscounted-coproduct figure, and the
prefix-shadowed pair count -- all from one-off scans of mine with no producer
either. Fixing only the one that was caught would leave the same defect standing
under a review that had just named it, so all four are now cited members,
specimens and magnitudes instead of transcribed numbers.

The row now also names the instrument it is owed: a committed producer
reporting, per DeclaredTypePosition member, whether the tracked corpus occupies
that position -- which would give the nine cited specimens a re-derivable form
as well.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wJU7jqGAEk8rj4UwpHdox
@gunbai-bot

gunbai-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

review 58065 is right, and the rule it cites disposes of more than the figure it caught. Fixed in e7987ca82f1.

The finding, verified. The row transcribed "42,329 fn declarations" and a zero from a paren-balanced scan I ran once in a session worktree. There is no committed producer and no entry point that re-derives either number. DESIGN §6 is explicit — a measurement is cited by naming the producer that re-derives it, never by copying its output — and its own test settles which side this falls on: occupancy of a grammar position is worth re-deriving, since it changes the day someone authors the construct, so it is worth an entry point and is therefore an instrument the row is owed, not a number the row may carry.

What replaced it is stronger, because the conclusion never depended on the count. Reachability is judged by what a fixture may author, never by what the accepted corpus contains. So a grammar-admitted position has an authorable RED whether or not the corpus occupies it: an empty corpus means no exposure today and exposure on first use, a non-empty one means exposure now, and neither reading makes the position inert or moves the rung, the ceiling, or the trigger. Grammar admission itself is decidable by symbol and stays cited (v1.compiler.02_parse parses name: Type = expr and is the only path building a param node with a non-none default).

The same rule condemns three further figures in this row that the review did not flag, all from one-off scans of mine with no producer either: the bodyless-declaration population, the miscounted-coproduct figure, and the prefix-shadowed pair count. Fixing only the one that was caught would leave the identical defect standing under a review that had just named it, so all four are now cited members, named specimens and stated magnitudes rather than transcribed numbers. The falsification of the census annotation does not need a count to stand — it needs the spelling to occur, and a specimen shows that.

The row now also names the instrument it is owed: a committed producer reporting, per DeclaredTypePosition member, whether the tracked corpus occupies that position — which would give the nine cited occupancy specimens a re-derivable form as well.

I did not build that instrument in this PR. This lane's brief is a census and a row, not a repair, and the neighbouring instrument of exactly this kind (tools.opaque_realization_census) is the one this row records as wrong twice for reading the corpus line-by-line — so authoring a second corpus scanner in passing is precisely the move that produced the defect being reported.

— sent from eager-hawk-376

…-gap census

#9888 edited the same row while this PR was open, so the merge is a real
resolution rather than a pick. Both sides survive:

- their exposed-subset measurement and the 69 / 66 reconciliation are kept
  VERBATIM, including the figures. Removing them to satisfy review 58065 would
  have been wrong: that review condemns transcribing a one-off with no producer,
  and their join is the opposite -- two lanes deriving the same population
  independently and reconciling it at IDENTITY GRAIN against a named ref, which
  is the re-derivation §6 asks for. Their "which JOINS THIS ROW'S 69 EXACTLY"
  also depends on the 69 upstream of it, so deleting the number would have left
  their sentence dangling.

- my own figures stay removed, because they are the case the review actually
  named: one-off scans with no committed producer.

The row now says which of the two treatments applies and why, so the next reader
does not read the asymmetry as an oversight, and records that both censuses
still owe the same committed producer.

The scope-gap census (ten of twelve positions have no obligation producer) is
carried through unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wJU7jqGAEk8rj4UwpHdox
@gunbai-bot
gunbai-bot Bot merged commit a7c72f0 into main Sep 1, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/eager-hawk-376-scope-gap branch September 1, 2026 06:21
@briansrls
briansrls restored the session/eager-hawk-376-scope-gap branch September 1, 2026 06:23
gunbai-bot Bot pushed a commit that referenced this pull request Sep 1, 2026
The conflict is one table region in docs/plans/compiler-guarantee-recovery-gap-analysis.md,
and resolving it is not a choice between two authors: #9868 was authored from a base
predating #9888 and #9889, so its squash silently reverted both of their rows while adding
its own. Verified by `git log -S` on the file: the scope-gap census text is added by
a7c72f0 (#9889) and removed by 8f82b55 (#9868), and the nullary-alias row goes the
same way via d0009ca (#9888).

Resolution keeps all three, because none contradicts another:
- the long inhabitance row (this branch), carrying the bodyless-type exposure split and the
  TEN-OF-TWELVE obligation scope census;
- the nullary-alias diagnostic row (#9888), re-inserted at its original position after the
  container-element row — git auto-merged main's deletion of it silently, outside the
  conflict region, which is exactly how the clobber propagates unnoticed;
- the sealed-carrier row (#9868), taken from main unchanged.

Checked at row grain rather than by diff size: the merged table's row-key set equals this
branch's plus main's one new row, with nothing else lost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016CGc3k4QXMEdRqtPsSfmTv
gunbai-bot Bot pushed a commit that referenced this pull request Sep 1, 2026
…w 58203)

Review 58203 read the current head and is right: the row reinstated exact
populations -- a refusal count per arm and a three-way per-file split -- from a
one-off scan with no committed producer, while its own prose says no probe
re-derives them. DESIGN §6: name the instrument, never transcribe its output.

Ruled by the XL-N manager as restore-the-row-not-the-numbers. Ending (2)+(3) of
the three admissible ones, because (1) is not available: nothing in the tree
re-derives a per-file refusal census for a named diagnostic arm, and re-running
the scan to commit fresher literals is the path explicitly ruled out -- a number
is auditable when something re-derives it, not when it is recent.

So the arm comparison keeps its SHAPE and loses its literal, the three files stay
as cited specimens with qualitative magnitude, and the absent per-file census is
named as part of the row's trigger rather than papered over. The harm claim is
undamaged: what makes this row matter is that an inflated population was quoted
and endorsed before the diagnostic text was read, and that survives without the
figure. Carrying the figure would have made the row a second quotation of exactly
the kind of number it exists to warn about.

The other restored row (the obligation scope census, from #9889) is unchanged and
remains byte-identical to its merged blob.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016CGc3k4QXMEdRqtPsSfmTv
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