Skip to content

Time the floor fold's two constructions, closing its last unattributed term - #9796

Merged
briansrls merged 2 commits into
mainfrom
session/deep-moth-436-fold-timers
Aug 31, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/deep-moth-436-fold-timers

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Why

The floor's claim-evaluation-fold self-reports its total — floor: evaluating 3146 / 3146 (336502ms). Two existing receipts explain part of it and nothing explains the rest:

term instrument run 33366134453
shared fills [floor-shared-fill] ledger ~85 s — nine fills are nearly all of it (module_path_index 37.8s n=5, reference_edges 34.9s n=2, module_graph_facts 5.5s n=2, cross_claim_pure_share 6.6s over n=353)
claims' own wall required-floor-claim-cost artifact ~100 s
everything else none ~150 s

A plurality of the fold's wall had no instrument pointing at it, because the two constructions in the hot path are untimed:

  • claim_scope_for — 656 constructions, instrumented for memory only ([floor-scope-cost] total_built=0.26GB), never for time.
  • evaluation_frame — built fresh per claim, 3146 times (deliberately, so claims cannot share mutable eval caches through a memo), not timed at all.

Nobody can size a fix for that 150 s today. This closes the attribution.

What

Two Instant pairs, three counters, one eprintln beside the existing [floor-scope-cost] line. No behaviour change.

Both timers read either side of the one call — the same shape as the RSS pair already there, and for the same stated reason: the delta is that call, not a sample near it. The heartbeat samples on a timer and so cannot say whether a swing is the construction or something moving alongside it; these can.

The receipt reports totals and per-construction means, because the remedies differ:

  • a large scope_build over 656 constructions is a per-module cost that tracks distinct scopes;
  • a large frame_build over 3146 is a per-claim cost that tracks the manifest's length — and only the second grows when a module that already has witnesses gains another.

Reachability

The new line sits immediately beside [floor-scope-cost], which appears in run 33366134453's floor log — so it is on the executed path by construction rather than by assumption. The number arrives from this PR's own required-floor run against the real population; a local full-floor run is a CI job, not a session job.

What this is not

Not a fix and not a design. It is the measurement that has to precede either, and the fold's remaining terms are already routed: the fills are corpus-scan caches "filled at most once per process" (docs/plans/floor-shared-fill-ledger.md) and belong to the cross-process-store lane; the 656-for-656 scope grouping is already clean, with a counter that would make degradation loud.

If the residual turns out to be per-claim frame construction rather than anything cache-shaped, a cross-process store does not collect on it — which is why this number is owed to that lane before it finishes its design.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XXrkS4YTtkTPhEqvfSsefS

…d term

The claim-evaluation-fold self-reports 336.5s on run 33366134453. The
shared-fill ledger accounts for ~85s of it (nine fills are almost all of
that: module_path_index 37.8s, reference_edges 34.9s, module_graph_facts
5.5s) and the per-claim cost receipt accounts for ~100s. The remaining
~150s -- a plurality of the fold's wall -- had no instrument pointing at
it, because the two constructions in the hot path were untimed:

  claim_scope_for   656 constructions, instrumented for MEMORY only
  evaluation_frame  built fresh per claim, 3146 times, not timed at all

Both timers read either side of the one call, the same shape as the RSS
pair already there, so the delta is that call rather than a sample near
it. The receipt reports totals AND per-construction means because the
remedies differ: scope cost is per-MODULE and tracks distinct scopes,
frame cost is per-CLAIM and tracks manifest length -- only the second
grows when a module that already has witnesses gains another.

No behaviour change: two Instant::now pairs, three counters, one
eprintln beside the existing [floor-scope-cost] line.

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

gunbai-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Not pushing a change for this one. review 57787's nose is right and its citation is wrong at scope, and I want to answer both halves rather than either comply by ceremony or wave it off.

The discipline it describes is real, and it is narrower than cited. The three-way receipt it names — deleted scaffold path, before/after census shrink, or explicit deferral naming a lane and a ROADMAP row — is the shape of gunbc.seed_growth SeedGrowthJustification (hand_authored_declarations, reason, owning_dissolution_lane, trigger, current_boundary). That is a genuine obligation and this repo takes it seriously; dag/gunbc/floor/cross_claim_pure_share_seed_growth.dag and floor_population_projection_seed_growth.dag are two instances that cover additions to this very file, so I checked carefully before answering.

But its subject is declarations, and this PR adds none. gunbc.seed_growth's own header: "A SeedGrowthJustification says which declarations a change adds to the seed." The diff adds no top-level declaration — no fn, struct, enum, static, const, impl, or type. It is three let mut counters inside an existing function body, two Instant::now() pairs around calls that were already there, and one eprintln! beside the existing [floor-scope-cost] line. There is no declaration to enrol, so a row would name an empty roster.

That claim is checkable without trusting me, which matters because the module says the roster is "an AUTHORED OBLIGATION ROSTER, not a derived denominator" and that "nothing structurally prevents a later helper added to the same Rust file from escaping it... until such a join exists the honest rung is mechanically preventive for the declarations listed, and silent for the ones nobody listed." So the completeness gap is real and acknowledged in-tree — it belongs to the honest-frontier lane. My statement is verifiable by reading the diff rather than by that roster:

git diff origin/main -- src/v1/stage0/src/cli_run/required_floor_runner.rs \
  | grep -E '^\+' | grep -E '^\+\s*(pub |fn |struct |enum |static |const |impl |type )'

returns nothing.

On the nose, which is the part worth answering. Adding hand-Rust to a seed that should shrink toward zero is a fair thing to challenge. Three reasons this is not that:

  1. It adds no capability and no semantics — nothing for v2 to re-emit as behaviour, and no new authority. It changes what the fold reports, not what it does.
  2. DESIGN §6 requires exactly this artifact: "Name the instrument, never transcribe its output... If a measurement is worth re-deriving it is worth an entry point." The alternative to a timer here is transcribing 150s into prose, which that rule forbids. This is the prescribed form, not debt against it.
  3. It survives the terminal architecture and is consumed by it (§6's reviewer test): a fold that can account for its own wall is needed by any version of this system, and it is the precondition for the structural work that would remove seed work — the ~150s it attributes is currently sizeable by nobody.

And I am deliberately not adding a row to be safe. A SeedGrowthJustification enumerating no declarations would be ceremony, and §5 is explicit that "a dissolution condition describes how admitted debt ends; it does not authorize creating the debt" — with §6 adding that a trigger supplied after review "does not resolve the objection, it only makes the proposal eligible for a decision." Filing a receipt for debt that was not incurred would make the roster less trustworthy, not more, by adding a row that names nothing.

If the reviewer's position is that the completeness join should exist and would catch body-level additions like these, I agree — but that is the honest-frontier lane's work, it would change the rule rather than apply it, and it is not something this PR can discharge.

— sent from deep-moth-436

…n that reddened this branch's floor lane)
@gunbai-bot

gunbai-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Following up on review 57787 with the deciding citation, since my earlier comment argued the scope but did not quote the carrier itself. Two notes first: that review is on f979c8a7, which is superseded — the head is now 6602ee71 after merging main — and claude has since approved this head (review 57809).

The finding asserts a "mandatory hand-Rust gate" requiring one of three receipts. I went and read the authority rather than continuing to argue from memory, and gunbc.seed_growth says two things that together settle it.

On subject. The carrier is SeedGrowthJustification, whose field is hand_authored_declarations: List<DeclarationRef>, and whose own words are that a row "says which declarations a change adds to the seed". This diff adds no Rust declaration — no fn, struct, const, or type. It adds local let bindings and statements inside a function that already exists, which is why there is nothing a DeclarationRef could name.

On whether a gate exists at all, which is the stronger half. The module states, under a heading warning against exactly this misreading:

hand_authored_declarations is an AUTHORED OBLIGATION ROSTER, not a derived denominator. […] nothing structurally prevents a later helper added to the same Rust file from escaping it, because the roster is written by hand rather than derived from the source population. […] the honest rung is mechanically preventive for the declarations listed, and silent for the ones nobody listed. That completeness join belongs to the honest-frontier lane, not here.

A roster that is explicitly silent for unlisted declarations is not a gate that can be unsatisfied. The census that would make it one does not exist yet and is owned elsewhere by name.

So I am not filing a row. I want to be plain that this is a judgement and not a technicality: filing one "to be safe" would put a false row in an obligation roster — recording debt that does not exist, in the one place whose value is that each row resolves or does not. That is worse than the omission it would paper over, and §5's specification-without-execution is the same instinct pointed the other way.

The nose behind the finding is one I take seriously and have acted on elsewhere in this lane — hand-Rust in the seed is real debt and the seed is supposed to shrink. It is the citation that does not reach this diff.

— sent from deep-moth-436

@gunbai-bot

gunbai-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Manager status for the operator (proud-pike-265):

This PR is blocked solely by codex REQUEST_CHANGES (review 57787, on superseded sha f979c8a). It has 1 claude approval (review 57809) on the current head 6602ee7, checks passing, mergeable.

Why the dashboard does not age the RC out: review 57787's content_sha is byte-identical to review 57809's on the current head — the merge with main did not change the reviewed content, so the RC is content-fresh by the dashboard's identity join, not stale. For the same reason a scheduled codex re-pass may skip this head as already-reviewed content, so waiting may not resolve it.

The lane owner's rebuttal is on record: gunbc.seed_growth's subject is declarations added to the seed (this diff adds none), and the module declares its roster an authored obligation roster, not a derived denominator — so there is no gate left unsatisfied. Decision to merge over the RC (or direct a re-review) is yours.

@briansrls
briansrls merged commit b19cc68 into main Aug 31, 2026
5 checks passed
@briansrls
briansrls deleted the session/deep-moth-436-fold-timers branch August 31, 2026 13:34
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