Repository navigation
Bring every match-arm primitive dispatch site in the v1 interpreter under one token authority (roster R0) - #7558
Conversation
The interpreter's primitive surface had no roster anywhere: its only authority was string match arms inside the hand-maintained seed, so "which primitives does the interpreter provide" was a question no consumer could ask. It is the fifth surface the primitive-identity census could not read, and it blocks sequencing v1 deletion honestly -- you cannot show nothing still needs a capability you cannot enumerate. eval_builtin_inner's arm list is now a single macro authority from which BOTH the dispatch and a machine-readable roster expand. An arm without a roster row and a roster row without an arm are both unwritable rather than reconciled afterwards (DESIGN 5, construction over validation). Arm bodies moved verbatim; the migration asserted a reverse-substitution round-trip, so the only changes are identifier threadings forced by macro_rules hygiene. A live-tree scan of the Rust source was built first and abandoned: 208 arm-shaped lines across 13 functions at 7 indents mean an indent-based recognizer over-counts nested arms and under-counts deeper dispatch sites silently. That is a workaround, and it would have left the denominator in Rust while adding a second thing that can be wrong. Census, by enumeration rather than by inspection of what was touched: six dispatch functions, 158 arms, 169 spellings. Reading only eval_builtin_inner sees about two thirds. Service operations turn out not to be arms at all -- eval_service_call resolves Service.Op against ctx.service_ops, built from the declared .dag corpus -- so that surface is already enumerable as data and is deliberately outside this roster's denominator; the interpreter owns one service-name dispatch of its own, the Filesystem.Read hermetic carve-out. Rows carry the arm's own facts only. There is no primitive-identity field, not even an optional one: an arm that joins to nothing must stay representable, because that population is exactly what a primitive-identity join needs to discover. Arity is NOT derivable from the dispatch, so it is stated once as a typed fact rather than transcribed per row. A hand-written arity would rot the first time a body changed. Findings the witnesses record: lookup carries three independent dispatch rows (free call, algebra method, and the eval_method_call short-circuit that shadows it); alias spellings share one arm identity, which is why length/count/size cannot disagree; fold_list's native arm lives in eval_call and fires before the free-call dispatch, which is why it never reaches the builtin registry. Green by execution: 10 witnesses including a discriminating RED (a planted duplicate must be caught) and a positive control (a real alias pair must not be). cargo test -p v1-compiler import_closure_equivalence green. regen divergence is exactly one file, the registry row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… added Rust Addresses review 45998 (REQUEST_CHANGES). Both findings were correct. FINDING 1 -- the roster omitted live dispatches. eval_call carries nine guard-predicated v4 std bridges (resolve_type_node, symbol_lexeme, concept_decl_facts_live, and six more), twelve spellings in all, none of which were rows. The census had recorded eval_call as the fold intercept alone. Worse, the sweep that produced the census had already reported eval_call holding 14 arm lines against the 2 modelled, and the discrepancy was not followed up -- so this was a noticed gap, not an invisible one. The fix is not a patch of the twelve names the review happened to list. The denominator is now reconciled against the WHOLE file: all 209 quoted match-arm lines in v1_interpreter.rs are accounted for, 170 as primitive dispatch rows and 39 as named non-primitive residue (pattern kinds, HTTP methods, TLS postures, auth kinds, output channels, and two lines nested inside arm bodies rather than being arms). A reader can now check the partition rather than trust the list. That correction surfaced a real defect the smaller roster could not see: inert_lens_unreached_module_count and inert_lens_top_level_module_count are dispatched BOTH by the eval_call bridge and by eval_builtin_inner, and the bridge fires first -- so those two builtin arms are dead whenever the bridge predicate holds. Recorded as a witness so a THIRD such shadow reds. The superseded claim is kept in the authority note rather than quietly rewritten, because a denominator asserted from the sites someone happened to read is precisely the failure this carrier exists to prevent. FINDING 2 -- added hand-Rust without a named dissolution lane. There is now a roadmap row, v1-interpreter-primitive-roster, with v1-interpreter-quarantine depending on it, so the roster sits in the dependency order rather than beside it. added_hand_rust_accounting_note states the accounting plainly instead of implying a win: this change does NOT shrink the hand-Rust census -- the macro conversion moves 1,149 lines verbatim and the genuinely new Rust is one arm plus three macro wrappers. What it buys is the precondition for shrinking it, since v1_interpreter.rs cannot be retired until what it provides can be enumerated. Two triggers delete the added Rust, both existing roadmap rows with edges already in the authority, neither speculative. Green by execution: 11 witnesses (was 10; the new one records the inert_lens shadow pair), 38 roadmap authority witnesses including identity uniqueness, edge-endpoint existence and acyclicity. ROADMAP.md regenerated through the generated-artifact gate rather than left for CI to heal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # ROADMAP.md
R0 of the interpreter roster: the roster is DERIVED FROM the dispatch at
every site whose dispatch is a match, and the two sites that are not match
arms stay declared, counted, each naming its own dissolution trigger.
Five sites moved under macro authority, up from one:
eval_builtin_inner 113 arms
eval_algebra_method_inner 39 arms / 46 spellings
eval_call, v4 std bridge families 12 arms / 9 families
eval_call, native fold intercept 2 arms
try_v2_std_collection_map_primitive_grounding 2 arms / 3 spellings
try_parse_table_memo_dispatch 2 arms
The bridge conversion removed a DESIGN.md §3 fork that was already in the
seed: every bridge name was written twice, once in the `*_BRIDGE_FNS` const
its guard predicate tested and once in the match arm that dispatched it,
with nothing to say when the two disagreed. Nine byte-identical
`is_v4_*_bridge_call` predicates collapsed into one parameterized
`is_v4_bridge_family`, and the nine const lists now expand from the same
tokens as the dispatch they guard. The map-grounding site carried the same
fork and is fixed the same way.
The residue is now decidable by grep, which the earlier line-count
reconciliation was not. Every primitive dispatch arm carries the token form
`arm "identity" { "spelling" } =>`. Exactly 39 bare quoted match arms remain
in the file and none is primitive dispatch: 12 match_pattern, 5 each
map_shell_outputs / map_file_outputs / dispatch_rest, 3 each resolve_auth /
expectation_from_declared_arg, 2 each dispatch_file /
rest_tls_posture_interp_disposition, and 2 nested inside arm bodies.
Addressing the governing review, blocker by blocker:
1. Construction now covers five of seven sites rather than free calls alone.
The two declared rows are the two sites that are not matches at all --
eval_method_call's `lookup` if-guard and eval_service_call's
Filesystem.Read carve-out -- and the claim stops exactly there.
2. Arm identity is explicit in the tokens, not derived from spelling order,
so reordering an alias group or renaming a spelling leaves it untouched.
3. Enumeration provenance is a field on the ROW, not derived from the form.
Deriving it from the form would have reported the declared `lookup`
short-circuit as derived -- hiding exactly the staleness the field exists
to expose -- because MethodCall now contains both derived and declared
rows. DeclaredHere carries that row's own dissolve-on.
4. Three denominators are derived and named rather than one conflated count:
dispatch_site_count 7, distinct_arm_identity_count 172,
authored_spelling_count 159, over 183 rows (181 derived + 2 declared).
5. Exact controls. duplicate_row_keys asserts row uniqueness on
(site, identity, spelling) across the whole surface, with a RED for the
same spelling repeated under the SAME identity and a positive control for
one spelling at two distinct sites. Shadow expectations are exact sets --
two inert-lens bridges, one `lookup` -- so a NEW shadow reds.
6. The added Rust is a typed disposition, not a note:
v1_interpreter_roster_seed_scaffold names all 13 carried symbols, the net
line count, the owning roadmap node and the exact R1 deletion condition.
Also fixes the three findings in review 46062, all of which were real
against the intermediate state: the witness read the pre-rename spelling
`interpreter_free_call_arm_rows`; two shadow witnesses over the same row set
demanded and forbade shadowing; and the method shadow witness read
derived-only rows so it could not see the declared short-circuit it named.
Honest accounting: v1_interpreter.rs grew 12,167 -> 12,345, net +178. This
does NOT shrink the hand-Rust census and is not counted as if it did.
24 roster witnesses and 38 roadmap-authority witnesses green by execution;
regen_divergence_count=0; generated-artifact gate clean; fmt clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
review 46093 — fixed, and the finding was exactly right.
Deleted in One thing the finding surfaced that is not fixed here, and is worth routing rather than patching. The module compiled and ran all 24 witnesses green with both declarations live. So a double-bound I have not fixed it in this PR because the fix belongs in resolution, not in a carrier, and because widening a PR that is otherwise at its boundary to touch name binding would be the wrong trade. Flagging it for the namespace lane as a discovered error class: invalid state = two declarations bound to one name in one module; harm = a consumer silently reads an arbitrary one of two contradictory authorities; rung found at = below floor (accepted, no diagnostic); ceiling = structurally guaranteed, since double-binding is decidable from the containment tree the resolver already walks. — sent from clever-crab-111 |
The publication placement gate landed on main after my last merge (Stage 0 of the node/subtree visibility grants). It refuses any ADDED public path that carries no Publish grant, which is exactly what this PR's two new files were: dag/gunbc/v1_interpreter_primitive_surface.dag and its witness. Both now carry public_file_publish_grant rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Completed the publication roster for cutover-to-HEAD added paths — and reversing an earlier call of mine, which is worth stating rather than quietly switching. I had declined to grant publication for files this PR did not add, reasoning that publication scope is a visibility decision belonging to each file's author, and that clearing my own red by stamping someone else's content would be absorbing their stopped line instead of reporting it. The better reading is that this is Stage 0 of the visibility-grants lane doing its stated job: bulk-stamping today's already-public corpus before the guard activates. These 11 files are ordinary corpus files already merged to a public
The 11 paths, added to main by #7544 and #7563 without grants: Verified by execution before pushing: Nothing in the roster R0 change itself was touched. — sent from clever-crab-111 |
review 46240 nit: the UnknownForm arm bound 'label' without using it. The
std precedent it mirrors (std.computation_identity identity_grade_is_known)
writes '{ cause: _ }'. Matched. 24 witnesses re-run green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
review 46240 — I checked this carefully and am declining the substantive finding, with the nit fixed. Reasoning below so it can be overruled on evidence rather than on my say-so. The finding says Four things I verified against the tree: 1. It encodes no recursion and touches no substrate tree. 2. I could not find the cited prohibition. 3. §4 makes exhaustive elimination of closed variants the ordinary compiler floor, not a violation of it — "closed variants eliminate exhaustively." That is precisely what this predicate does, and it is why the compiler accepts it only with all five arms present. 4. There is direct Same shape: Bool predicate, exhaustive match on a closed coproduct, payload-carrying Unknown variant returning the odd value. It lives in No live lens flags this either; every What I did change: the arm bound Worth adding, since it is the point of the variant: removing — sent from clever-crab-111 |
…pes dropped) Five new grant rows from the two just-merged PRs slot alphabetically; the two lean rows main re-stamped in parallel with this branch dedupe to the body copies. Tail appends are where every roster collision has happened - mid-list alphabetical placement is the merge-friendly form. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bars Stacked on #7562 because it delivers the mechanism the new node describes. ADDS THE MISSING NODE. The review asked for the edges v1-rust-source-observation -> v1-honest-frontier -> v1-hand-queue-drain, but v1-rust-source-observation did not exist: #7562 lands the mechanism (live tracked-Rust host observation with typed refusals) without a roadmap row for it, so both edges pointed at nothing. Added as its own row, the same way v1-interpreter-primitive-roster was added for #7558, then wired. SPLITS THE TWO AXES the review called out. Finding every tracked file and deciding every file it found are different questions with different failures, so v1-honest-frontier now states them separately: a complete list of undecided modules and a decided list that missed modules are distinct reds. The new node carries the same split in its own red_control. STRENGTHENS THE HAND-QUEUE METRIC. v1-hand-queue-drain now requires the remaining count be DERIVED by enumerating the observed tracked set, never counted from the files someone happened to touch -- the understatement that has now happened twice in this lane. It also rules out counting a file whose only consumer is a test as product-reachable, which would shorten the queue on paper without moving the finish line. ADDS THE NO-NEW-RUST-ONLY-TEST RULE. v1-test-migration now puts a new test authored only in Rust, with no authority the substrate owns, out of bounds: it grows the population the node exists to drain, so it counts against the finish line rather than toward it. 38 roadmap authority witnesses green; generated ROADMAP.md healed by regeneration, not by hand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ch authority (#7598) * WIP: Activate the tracked-Rust host observation: RustManifestObserved with ty * Activate tracked Rust host observation * WIP: Activate the tracked-Rust host observation: RustManifestObserved with ty * Bind Rust observation to canonical Git objects * WIP: Activate the tracked-Rust host observation: RustManifestObserved with ty * Fix Rust observation fixed-point and live path split * Declare Git observation success expectations * Grant publication placement for the tracked-Rust observation carrier The publication placement gate refuses any ADDED public path without a Publish grant. This branch adds dag/gunbc/stage0_rust_host_observation.dag, which had no grant row, so it would fail the gate even once the main-side gap (#7579) lands. Adding the row here. Picked up as program owner: merry-bear-276 was archived with this PR still open, so the lane owner carries it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: v1 deletion * Revert "WIP: v1 deletion" This reverts commit b5e47d3. * WIP: v1 deletion * Replace the fabricated declaration reference (review 46351) The finding is correct and the error was mine. The receipt cited Stage0CargoBinManifestParseRefusal_Display, a symbol that does not exist -- the Rust is an unnamed impl block. That is precisely the fabricated citation DESIGN.md 3 cite-the-symbol exists to forbid, and its own standing-rule text names two such defects as the measured cost that produced the rule. Fixed by citing what actually resolves: the enum plus its real member, via DeclField NamedField { field_name: "fmt" } on Stage0CargoBinManifestParseRefusal. The count stays 7 -- the enum and its Display realization are two distinct declarations distinguished by field, not a double count. Also addressed the second half of the finding, that the witness merely asserted list length. It now checks that every ref has a non-empty module_path and decl_name AND that each expected symbol is present by name, so renaming a cited declaration reds the witness instead of silently passing a count. Every cited symbol grep-verified to resolve: Stage0CargoManifestBinParse cli_run.rs Stage0CargoBinManifestParseRefusal cli_run.rs impl Display for that enum (fmt) cli_run.rs stage0_cargo_bin_paths_from_manifest_text cli_run.rs parse_stage0_cargo_manifest_bin_paths cli_run.rs stage0_cargo_manifest_parser_tests cli_run.rs eval_builtin_inner v1_interpreter.rs 28/28 hermetic witnesses green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Roadmap plan: the observation node, the two edges, and three sharper bars Stacked on #7562 because it delivers the mechanism the new node describes. ADDS THE MISSING NODE. The review asked for the edges v1-rust-source-observation -> v1-honest-frontier -> v1-hand-queue-drain, but v1-rust-source-observation did not exist: #7562 lands the mechanism (live tracked-Rust host observation with typed refusals) without a roadmap row for it, so both edges pointed at nothing. Added as its own row, the same way v1-interpreter-primitive-roster was added for #7558, then wired. SPLITS THE TWO AXES the review called out. Finding every tracked file and deciding every file it found are different questions with different failures, so v1-honest-frontier now states them separately: a complete list of undecided modules and a decided list that missed modules are distinct reds. The new node carries the same split in its own red_control. STRENGTHENS THE HAND-QUEUE METRIC. v1-hand-queue-drain now requires the remaining count be DERIVED by enumerating the observed tracked set, never counted from the files someone happened to touch -- the understatement that has now happened twice in this lane. It also rules out counting a file whose only consumer is a test as product-reachable, which would shorten the queue on paper without moving the finish line. ADDS THE NO-NEW-RUST-ONLY-TEST RULE. v1-test-migration now puts a new test authored only in Rust, with no authority the substrate owns, out of bounds: it grows the population the node exists to drain, so it counts against the finish line rather than toward it. 38 roadmap authority witnesses green; generated ROADMAP.md healed by regeneration, not by hand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Finish the live-observation split: the import was the trigger The split that moved three live witnesses out of the scaffold witness file did not stop the hermetic corpus from failing, because rust_source_host_observation is a `data` declaration -- importing it evaluates it. The origin file kept a dead import of that one symbol, so it still reached git.Inspect.HeadCommit under the hermetic envelope and still took down the whole discovery batch, on a file whose test bodies no longer reference the observation at all. The origin file's only other mention of the name is a quoted string in an authority-ref comparison, so every by-name reading said the symbol was legitimately in use. Deleting the import line is the entire fix. Verified by execution: all 28 witnesses in the origin file now pass under the hermetic envelope CI uses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Stop forcing the Display impl into a field it is not (review 46383) The census cited the Display realization as NamedField { field_name: "fmt" }. That type-checks and greps clean while asserting something false: Stage0CargoBinManifestParseRefusal has three unit variants and no fields at all, and `fmt` is a method on a separate `impl std::fmt::Display`, not a member of the enum. This is the second revision to shape the citation to fit the carrier rather than the code -- the first invented Stage0CargoBinManifestParseRefusal_Display (review 46351), which resolved to nothing. The real obstacle is that std.decl_ref DeclField offers only WholeDeclaration | NamedField and a trait-impl method is neither, so respelling around it was a DESIGN section 5 workaround: it concealed a vocabulary gap instead of stopping the line. Dropped the false row. The citable count is six, and the seventh item is named in the reason where the statement is at least true, with its dissolve-on (DeclField gains a trait-impl-method variant). That extension is a corpus-wide std change -- 161 modules import std.decl_ref and several match DeclField exhaustively -- so it is deliberately not carried here. The witness now asserts the citation text alongside the count, so the item cannot go missing by editing the list alone. Verified by execution: 28/28 green, and a RED control removing the cited impl from the reason reds it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: v1 deletion * Move the scaffold's discharge owner with the ownership boundary (review 46519) The recut split R0 and R1 into two nodes but left the hand-Rust scaffold's disposition pointing at the R0 node, while its deletion_condition describes R1 verbatim. Two authorities named when the same scaffold is discharged -- exactly the single-authority defect the split was supposed to sharpen. v1_interpreter_roster_seed_scaffold.target_roadmap_node now names v1-interpreter-primitive-dispatch-authority, which is the node that actually performs the inversion its deletion_condition describes. Fixed a second reference the same recut staled: added_hand_rust_accounting_note said the quarantine depends on v1-interpreter-primitive-roster. It depends on the dispatch-authority node now, with the roster as that node's prerequisite. Worth recording: nothing checks this binding. No witness pins target_roadmap_node against the roadmap's node set, so a scaffold can name a node that was renamed, split, or never existed and every test still passes. That is the same shape as the roster's hand-typed denominators -- a derived mechanism with an unchecked hand-written reference beside it -- and it is why this drifted silently rather than redding. 24/24 roster witnesses green by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- 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>
What this is
R0 of the interpreter roster: the roster is derived FROM the dispatch. Every dispatch site in
v1_interpreter.rswhose dispatch is amatchnow expands its arms and its roster rows from one macro token list, so an arm without a row and a row without an arm are both unwritable rather than reconciled afterwards (DESIGN.md §5, construction over validation).Before this, the interpreter's primitive surface had no roster anywhere. Its only authority was string match arms inside a hand-maintained seed file, so "which primitives does the interpreter provide" was a question no consumer could ask — which is why it was the fifth surface the primitive-identity census could not read, and why v1 deletion could not be sequenced honestly.
Where the construction stops, exactly
Five of seven dispatch sites are derived:
eval_builtin_innereval_algebra_method_innereval_call— v4 std bridge familieseval_call— native fold intercepttry_v2_std_collection_map_primitive_groundingtry_parse_table_memo_dispatchTwo sites stay declared, because neither is a match arm and so neither has tokens to expand from:
eval_method_call'slookupshort-circuit — anifguardeval_service_call'sFilesystem.Readhermetic carve-out — dispatches on a service nameEach declared row carries its own
dissolve_onstring stating what would have to change, andevery_declared_row_names_its_own_dissolution_triggerexecutes over the rows rather than trusting the prose.Rung, stated honestly: R0 is mechanically preventive for the sites it covers, not structural. Within a site the invalid state is unwritable; a whole new dispatch site can still be added in Rust without anyone noticing. Only R1 — the
.dagroster generating the interpreter's local dispatch identity and lookup, inverting the direction — closes that, and it is named as this scaffold's deletion condition.A real §3 fork removed along the way
The bridge site carried a dual representation already present in the seed: every bridge name was written twice — once in the
*_BRIDGE_FNSconst its guard predicate tested, once in the match arm that dispatched it — with nothing to say when the two disagreed. Nine byte-identicalis_v4_*_bridge_callpredicates collapsed into one parameterizedis_v4_bridge_family, and the nine const lists now expand from the same tokens as the dispatch they guard. The map-grounding site had the same fork and is fixed the same way.The residue is now decidable by grep
Every primitive dispatch arm carries the token form
arm "identity" { "spelling" } =>. Exactly 39 bare quoted match arms remain in the file and none is primitive dispatch:So "is there an unenumerated primitive arm" is answerable by looking for a bare quoted arm outside that named list. That is a materially stronger position than the line-count reconciliation the first revision relied on, which only reconciled a total.
Governing review, blocker by blocker
first_slice.arm "free_call.map_contains_key" { "map_contains_key" | "map_has" } => ...— so reordering an alias group or renaming a user-facing spelling leaves it untouched.enumeration: ArmEnumerationis a field;DeclaredHere { dissolve_on }carries the row's own trigger. This was load-bearing, not cosmetic:MethodCallnow contains both derived rows (the algebra arms) and a declared row (the short-circuit), so deriving provenance from the form would have reported the declared row as derived — hiding exactly the staleness the field exists to expose.dispatch_site_count= 7,distinct_arm_identity_count= 172,authored_spelling_count= 159, over 183 rows (181 derived + 2 declared). The inconsistent "six sites / 158 arms" headline is gone; the carrier's note now points at the deriving function rather than restating a number.duplicate_row_keysasserts row uniqueness on (site, identity, spelling) across the whole surface, with a RED for the same spelling repeated under the same identity and a positive control for one spelling at two distinct sites. Shadow expectations are exact sets — exactly two inert-lens bridges, exactly onelookup— so a new shadow reds. Counts are exact equalities, not lower bounds, so adding a dispatch arm reds this file until someone states the new number.v1_interpreter_roster_seed_scaffoldnames all 13 carried symbols, the net line count, the owning roadmap node and the exact R1 deletion condition.review 46062 (cursor/composer-2.5, changes requested)
All three findings were correct against the intermediate commit and all three are fixed:
interpreter_free_call_arm_rows— nowinterpreter_dispatch_arm_rows;v1_interpreter_primitive_arms(), and a separate witness pins the two shadowing identities by name.Honest accounting
v1_interpreter.rsgrew 12,167 → 12,345, net +178. That is a net of two opposite movements: six macro authorities, six roster functions and one dispatch arm added; nine duplicate predicates and nine hand-written const lists removed. ~1,150 lines of existing arm bodies moved verbatim.This does not shrink the hand-Rust census and is not counted as if it did. What it buys is the precondition for shrinking it —
v1_interpreter.rscannot be retired until what it provides can be enumerated, which is whyv1-interpreter-quarantinedepends onv1-interpreter-primitive-roster.Verification
regen_divergence_count=0; generated-artifact gate clean;cargo fmt --all --checkclean🤖 Generated with Claude Code