Repository navigation
Language-files cleanout: derive operator emission from typed rows + typed scaffold inventory - #7272
Conversation
Reuses the existing std.disposition authority rather than building a prose probe:
Disposition = Terminal{reason} | Scaffold{dissolves_to, bind}. Because it has no
prose arm, a mark without a trigger is UNWRITABLE rather than merely counted --
construction over validation, and no string-content classifier is needed.
- dag/gunbc/language_source_scaffold_index.dag: typed rows + roster + all-triggered
check, modeled on hand_lens_host_bridge_scaffold_watchdog.
- dag/test/claim/language_source_scaffold_index_test.dag: 4/4 green including a
synthetic Terminal-dispositioned RED control.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… predicates, real coverage - FAIL-OPEN FIX (the hard-reject one): rust_pair_completion_impl_render mapped a missing spelling to "", silently dropping an operator impl. Now emits a located compile_error! naming the op and both tables, so drift refuses loudly instead of producing a GroupCompletion carrier with missing trait impls. Proven: removing the div spelling row yields compile_error! in the emission; restored yields none. I had noticed this arm while writing it and rationalized it as fail-closed downstream. That was wrong - it was a silent widen. - Dispositioned the std/ predicate pair (pair_completion_arm_uses_rhs / pair_completion_body_uses_rhs) with a dissolve-on naming the arity-projection construction that subsumes them. - Coverage is now READ FROM THE LIVE TREE, not pinned to hand-bumped census numbers: runtime_rust_blobs_are_all_rostered and compiler_tests_rust_blobs_are_all_rostered compare rt_/ct_ declaration counts in the carrier sources against the roster. Proven discriminating: appending an unrostered rt_ blob reds it. - Witness now imports explicitly (gunbc.language_source_scaffold_index, std.disposition, std.decl_ref, filesystem_io, live_tree) instead of relying on whole-pool resolution, and declares live_tree_disposition: ReadsLiveTree. - Removes rt_synthetic_unrostered_blob, a perturbation-test artifact the auto-committer captured into dbe6cc1. Seed re-baselined; regen_divergence_count=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Scope honesty: only Add, Mul and Neg are fully row-data - their bodies render from the polynomial arms, so perturbing a row changes the emission. Sub and Div are NOT polynomials in the four operand components (Sub is a DERIVED op, Add composed with Neg; Div quotients the canonical representative), so they still render as literals keyed by variant name. This PR's own B2 rule says a hand-authored body is a scaffold and needs a named trigger, so they get one. Dissolve-on names the two constructions their shapes actually need: an op-composition arm so Sub is derived rather than spelled, and a canonical-representative projection. Deliberately NOT fixed by widening the polynomial type - forcing a composition and a quotient into a sum-of-products would be a nickname for two constructions that are not sums of products. Witnesses green; regen_divergence_count=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Responses to review 43205 and review 43208, both verified against current code. review 43208 (REQUEST_CHANGES) — Now regenerated and pushed at Worth stating plainly why that wildcard existed at all, since it is the one genuine defect this PR has had: it was mine, and it redded the floor on Attribution checked rather than assumed: main's last six review 43205 — add an import block to That module is import-free today, which is not an oversight: it references 12 external symbols bare ( It may well be the better end state, and the test file does import explicitly. But it needs to land as a complete list verified by execution, not as a symmetry tidy-up — and this PR's floor has not yet completed a single uncancelled run, so I am not spending another ~45-minute cycle on a non-blocking cosmetic change. Happy to do it as a follow-up where it can be proven properly. Verification for this push — green by execution, not by typecheck:
Emission is unchanged by this fix: — sent from lively-eagle-570 |
|
Two notes on review 43214 (APPROVE — no action requested; recording these because one is a factual correction and the other is a disclosure against myself). Correction — No impl body changed. The distinction matters: "impls byte-different but semantically equivalent" would mean the derivation produced a different rendering than the hand-written blob, which would need justifying against the behavioral-equivalence bar. It didn't — the derived output is byte-identical to merged #7197 after rustfmt, which is a stronger result than the bar required and the reason no equivalence allowance was invoked. Disclosure — that comment's parenthetical is slightly over-broad, and it is mine. "arithmetic is row data, not free text" is fully true for Add, Mul and Neg. For Sub and Div it overstates: those are selected from the rows ( Not pushing a fix for it right now, deliberately. The correction is one word of a provenance comment in an emitted artifact, and landing it costs a — sent from lively-eagle-570 |
The pair-completion comment overstated "arithmetic is row data"; Add/Mul/Neg are, Sub/Div remain keyed literals. Completes the #7272 regen fixed point. Co-authored-by: Cursor <cursoragent@cursor.com>
…oster. Remove duplicate ct_render_rust_applied_type_qualified_base_test row (main already carries it after #7272/#7288); revert language_source_scaffold_index to main placement. Regenerate ci.yml/falsifier.yml via main_wet — block if then/else body lines use emit indentation (10-space), not hand-indented 12-space; matches heal job 89806546636 output the bot could not push. Co-authored-by: Cursor <cursoragent@cursor.com>
…ker (#7265) * WIP: shell→dag bucket D — foreign-executor emit cluster (gate #7216 now MERGE * WIP: shell→dag bucket D — foreign-executor emit cluster (gate #7216 now MERGE * Fix sccache emit if-branch semantics and commit regenerated ci.yml. Multi-statement if/then bodies must be semicolon-joined in a single Run (the if-else grammar inserts then_body verbatim without braces). The heal job failed because ci.yml drifted and the bot lacks workflows permission to push workflow files — commit the regenerated ci.yml and falsifier.yml here. Co-authored-by: Cursor <cursoragent@cursor.com> * Fold bucket-D census into arc census; delete orphan doc. The standalone bucket-d-foreign-executor-emit-census.md had zero inbound refs and would red the falsifier after merge. True-up §4.E/4.I and add §4.J punch-list to the existing shell-to-dag-residual census (reachable via design_document.dag) — single authority, no bind row needed. Co-authored-by: Cursor <cursoragent@cursor.com> * Repoint ci_sccache_opportunistic_detect scaffold to emit module. ci_sccache_provider_shell_injection moved to v2.workflow.ci_materialization_emit in this PR; host_build_cache_provision's scaffold bind still pointed at the deleted gunbc.ci_materialization declaration (review 43048). Co-authored-by: Cursor <cursoragent@cursor.com> * Fix merge-admission emit golden: hand-authored bytes, no trailing NL. ci_floor_disposition_marker_init_emit_matches_concat_golden_holds failed on CI because the concat-reconstructed golden carried a trailing newline after the echo redirect that orch_emit_pipeline does not emit. Switch to the #6467 hand-authored golden pattern (matches committed ci.yml). Co-authored-by: Cursor <cursoragent@cursor.com> * Mark ci_sccache_bound_branch semijoin as declared Scaffold. Three bound-branch Runs are semicolon-folded because multi-Do then_ inside realize_if_else inline binding is unguarded by the if-band corpus and byte-diverged on first ci.yml regen — not a carriage bug. Dissolution: emit-lane construction refusal for multi-step then_ at inline if_else bind, or block-bodied if_else row (emit lane, not D). Co-authored-by: Cursor <cursoragent@cursor.com> * Add missing Present import to ci_materialization_emit. Present is used for redirect and else_ arms but was not in the import list; golden tests executed green via compilation (review 43241). Co-authored-by: Cursor <cursoragent@cursor.com> * Roster ct_render_rust_applied_type_qualified_base_test for scaffold index. #7269 added the hand assertion blob after #7272 landed the inventory witness; merge main exposed compiler_tests_rust_blobs_are_all_rostered red (27 declared, 26 rostered). Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: shell→dag bucket D — foreign-executor emit cluster (gate #7216 now MERGE * Rework bucket D PR1: dissolve semijoin, extract shared emit plumbing. Replace semicolon-folded sccache bound branch with three Do steps so block-bodied if_else (#7277) emits multi-line workflow text; re-golden and regen ci.yml/falsifier.yml. Route both new emit modules through orchestration_bash_emit_support (run/do/emit_pipeline); pre-existing ci_*_emit forks migrate in PR2. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: shell→dag bucket D — foreign-executor emit cluster (gate #7216 now MERGE * Fix CI drift gate: regen ci.yml from emit authority; drop duplicate roster. Remove duplicate ct_render_rust_applied_type_qualified_base_test row (main already carries it after #7272/#7288); revert language_source_scaffold_index to main placement. Regenerate ci.yml/falsifier.yml via main_wet — block if then/else body lines use emit indentation (10-space), not hand-indented 12-space; matches heal job 89806546636 output the bot could not push. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: shell→dag bucket D — foreign-executor emit cluster (gate #7216 now MERGE * Remove duplicate ct_render_rust roster row from #7265 merge. Main already owns this entry via #7288; the branch copy made rostered exceed declared (27/28). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
…ckendCapability (#7286) * WIP: 7272 followons * WIP: 7272 followons * Qualify GroupCompletion emit provenance: Sub/Div not row-derived. The pair-completion comment overstated "arithmetic is row data"; Add/Mul/Neg are, Sub/Div remain keyed literals. Completes the #7272 regen fixed point. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: 7272 followons * WIP: 7272 followons * Cite dag language authority via Https DESIGN.md, not File scheme. File-scheme anchors fail the extdeps external-authority wall (Http/Https only). Keep the D2 repoint at DESIGN.md §4, but cite it as an Https github URL so corpus_live_clean_tree_wall_holds stays green. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop #7288 ct_ roster duplicate; bind GroupCompletion carrier dissolve-on to Ring. Name-match carrier selection is interim — terminal trigger binds std.algebra.Ring as the inhabitance authority that will replace it. Merge-main left a duplicate ct_render row; keep main's single copy. Co-authored-by: Cursor <cursoragent@cursor.com> * Bound react_jsx KEEP scaffold to one site-subsumption dissolution event. The prior bind named already-landed gunbc.site.markup.el, so the typed trigger was nominal; sole-owner the site lane and point the Scaffold at the named page-emission dissolve-on. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Language-files cleanout: B1 derivation mechanism + B2/B4/B5 typed scaffold inventory.
Defect statement (B1): selection derived, emission hand-authored.
v1_emit_struct_supplemental_implsalready gated on typed capability rows (repr_grounding_derive_completeness_predicateoverkernel_int_arithmetic_traits), but the impl body was a free-text Rust blob.B1 — derivation mechanism (landed)
dag/std/trait_derive_shape.dag— target-agnostic pair-completion rows. Each output component is a polynomial overself.pos/self.neg/rhs.pos/rhs.neg(arm = sum of terms, term = product of factors). ReusesReprGroundingDeriveTraitas the op key rather than minting a parallel operator enum. Operand arity is derived from the formula (pair_completion_body_uses_rhs), not tabulated.dag/extdeps/languages/rust/emit.dag— terminals only (trait paths, method names, where-bounds, carrier syntax). Impl bodies render from the rows. Clone placement is derived from last-use across arms, not spelled.Scope of the "arithmetic is row data" claim (review 43189, and it is a fair qualification). Fully true for Add, Mul and Neg: their bodies render from the polynomial arms, which is why perturbing the mul cross-term reds the witness. Sub and Div are not — they are not polynomials in the four operand components (Sub is a derived op, Add composed with Neg; Div quotients the canonical representative), so they still render as literals keyed by variant name. They now carry
rust_pair_completion_nonpolynomial_body_dissolve_on, naming the two constructions their shapes actually need. Deliberately not "fixed" by widening the polynomial type: forcing a composition and a quotient into a sum-of-products would be a nickname for two constructions that are not sums of products. 3 of 5 operators are row-derived; the other 2 are marked scaffolds.Receipts (by execution):
std_algebra.rsis the provenance comment. The behavioral-equivalence allowance was not needed.regen_divergence_count=0locally and CIregenpasses.group_completion_construction_test2/2 pass.src/v2/test/claim/emit/trait_derive_seed_emit_binding_test.dag. Perturbing the mul neg-arm cross-term drivesgroup_completion_mul_arms_are_grothendiecktofalse; restoring returnstrue.B2/B4/B5 — typed scaffold inventory (landed)
Built on the existing
std.dispositionauthority rather than a new prose probe:Scaffoldnames its derivation target as a type, andDispositionhas no prose arm — so a mark without a trigger is unwritable rather than merely counted. Construction over validation, and no string-content classifier is needed (respecting the fence). Modeled on the existinghand_lens_host_bridge_scaffold_watchdogtemplate.dag/gunbc/language_source_scaffold_index.dagdag/test/claim/language_source_scaffold_index_test.dag, 6/6 green (two of them live-tree coverage checks asserting EXACT equality: 13rt_declared == 13 rostered, 26ct_declared == 26 rostered).Scaffoldthat binds nothing is refused. Note the check was corrected mid-flight —Terminal-with-reason is legitimate (fnv1a64 is a named irreducible kernel), so "Terminal is bad" would have been the wrong control.Counts: 42 rostered, 42 dispositioned (40 Scaffold + 2 Terminal), 0 rostered-but-unmarked.
Coverage by carrier:
runtime_rust.dag— 13 of 13 blob fns (complete; the 14th,rust_runtime_source, is the assembler, not a blob)compiler_tests_rust.dag— 26 of 26ct_fns (complete, exact equality with no offset)extdeps/languages/rust/emit.dag+ the DryRunMode blob — 3Every bind was verified to resolve to a real declaration. Three were wrong on first pass (
std.observation::Observation,std.realization::RealizationPlan,std.ownership) and were corrected — a bind naming a nonexistent decl is exactly the hollow mark this mechanism exists to prevent.What completeness IS and IS NOT claimed. Enforced: for the two swept carriers —
runtime_rust.dagandcompiler_tests_rust.dag— coverage is checked against the live tree, not asserted from hand-maintained numbers: the witness readsrt_/ct_declaration counts out of the carrier sources and compares them to the roster, so a newly added blob reds instead of sitting unmarked (proven by appending one). Not claimed: corpus-wide completeness. Carriers outside those two — above all05_emit_rust.dag— have no such check, so a hand-authored blob can still land there unrostered and nothing reds. The parsed-roster census over the whole corpus remains the missing wall and the natural next step for this lane.Sizing the residue (discovery heuristic, explicitly NOT a claim): a structural scan — a fn whose body concatenates 5 or more string literals, which is shape rather than content — finds 231 blob-shaped fns across the Rust-carrying and language files, against 42 rostered. That 231 is an upper bound on candidates, not a count of violations: most are legitimate Class 1 or Class 2 (e.g.
css/properties.dagat 54 literals is a terminal list; the bulk of05_emit_rust.dag's 150 is the legitimate emitter). The two carriers where the brief predicted Class-3 debt are now swept to completion; the untouched remainder is dominated by05_emit_rust.dag(150), which the census placed in Class 1. Separating Class 1/2 from Class 3 there is the actual remaining work and is what the parsed-roster census has to do — which is also why this grep number stays in the methodology note and out of the claim.B4 finding:
runtime_rust.dagcarries zero substrate marks. Its dissolution notes live inside the emitted Rust strings as doc comments, so no lens over the.dagtree can check them — the same class as the arm_b defect this brief was written around. Lifted onto typed rows (trace_mark telemetry, kernel opcodes as Scaffold; fnv1a64 as Terminal).B5 finding — the census's Class-2 placement is refuted. The brief listed
compiler_tests_rust.dagunder Class 2 ("extracts typed assertion rows") with the instruction "verify, don't assume." Verified: 25 of 26ct_fns are purely hand-authored, 1,380 string literals in total, and the 26th (ct_coercion_tests) is a hybrid — row-driven core viaextract_coercion_tests, but it still emits a hand-authored header block and aggregates three hand blobs, so it is rostered too. The file belongs in Class 3. All 25 are now rostered, grouped by honest distinct dissolution: emitted-test harness scaffolding (7) toClaimWitnessCorpusClaimRunRow("its tests are data"); hand assertion suites (15) toCoercionTestEntry— the row-driven pattern that demonstrably already works for coercion; profile/benchmark emitters (3) toObservationSubject.Review response
First round (review 43129)
All three findings addressed. The second was a genuine catch and worth stating plainly.
The reviewer posed a dichotomy on
language_source_scaffold_row_is_dispositioned: either the construction wall is live, making the validator a redundant second representation, or it is not live, making the module note an overstatement. Checked rather than chosen — it resolves on the second horn.DeclarationRef.module_pathanddecl_nameare declaredNonEmptyStr(String where non_empty), but the empty-bind control row typechecks and evaluates, so the refinement is not enforced at construction.Consequences, both applied:
Scaffoldthat binds the empty string, so it is load-bearing rather than a second representation.language_source_scaffold_enforcement_boundaryseparating what is genuinely construction (Dispositionhas no absent or prose arm, so an unmarked row really is unwritable) from what is merely validated here (non-emptiness), with the execution receipt and a dissolve-on: the check deletes itself once refinement predicates are construction-enforced, at which point the control row stops typechecking.That overstatement was the same defect this PR exists to remove — a mark claiming more enforcement than it has — so it is corrected in the carrier rather than argued away.
Findings 1 and 3 (ad-hoc
*_is_*tag predicates overPairCompletionOperandandDisposition): both inlined to directmatch. All 8 witnesses re-verified green afterward, and the seed was re-baselined (the inline changed emitted output;regen_divergence_count=0).Second round (reviews 43154 / 43161 — REQUEST_CHANGES, all four addressed)
1. Fail-open on spelling drift — the one worth blocking on.
rust_pair_completion_impl_rendermapped a missing spelling to"", silently dropping an operator impl so a row/spelling divergence would compile green withGroupCompletiontrait impls missing. That is a §5 silent widen, and the old hardcoded emitter had no such gap. Now a missing spelling emits a locatedcompile_error!naming the op and both tables, so the emitted crate refuses to build. Proven: removing thedivspelling row makescompile_error!appear in the emission; restoring it makes it vanish. Owning the process failure plainly — I noticed this arm while writing it and rationalized it as "fail-closed downstream." It wasn't.2. Undispositioned predicates in
std/.pair_completion_arm_uses_rhs/pair_completion_body_uses_rhsnow carry adissolve-on:per thestd/convention, naming the arity-projection construction that subsumes them and stating why storing an arity field today would be a second representation of what the arms already encode.3. Coverage was a hand-bumped census — the sharpest finding. The first fix for the tautology replaced it with hardcoded per-carrier counts, which a new
rt_*/ct_*blob could outrun silently until someone bumped the number. Coverage is now read from the live tree:runtime_rust_blobs_are_all_rosteredandcompiler_tests_rust_blobs_are_all_rosteredcomparert_/ct_declaration counts in the carrier sources against the roster. Proven discriminating — appending an unrosteredrt_blob reds it. This moves B2 completeness for the two swept carriers from "not claimed" to actually enforced.4. Missing imports. The witness now imports explicitly (
gunbc.language_source_scaffold_index,std.disposition,std.decl_ref,filesystem_io,live_tree) and declareslive_tree_disposition: ReadsLiveTree, matching peer scaffold witnesses instead of relying on whole-pool resolution.Also removed in this round:
rt_synthetic_unrostered_blob, a perturbation-test artifact the auto-committer captured intodbe6cc1, along with a seed that had been regenerated while that perturbation was live. Both corrected; seed re-baselined atregen_divergence_count=0with a clean worktree.Third round (reviews 43176 / 43177 / 43183)
43177 (REQUEST_CHANGES) — the
+ 1coverage offset. Correct and adopted.declared == rostered + 1absorbed exactly one unrostered blob while the witness claimed full coverage — an absorbing fallback in the very check written to stop one. My first instinct was an exclusion list, which is only a softer form of the same absorption; the reviewer's fix is better.ct_coercion_testsis now rostered and both assertions are exact equality: 13rt_declared == 13 rostered, 26ct_declared == 26 rostered, no offset anywhere.Classification settled by reading the code rather than by the earlier heuristic:
ct_coercion_testsis a hybrid — its core genuinely is row-driven (extract_coercion_tests |> map(render_coercion_test_rust)), which is why the audit first binned it as row-driven, but it also emits a hand-authored header block and aggregates three hand blobs. It carries hand-authored target source, so it belongs in the roster like any other.43183 — no action needed. It asks that the witness consume
compiler_tests_row_driven_exclusion_count(). That function, and the whole exclusion model, existed only briefly as an intermediate state and were removed in favour of the stronger fix above. Recorded here so it is not mistaken for an ignored finding.43176 — the unexplained
+ 1is the same item, resolved by removal rather than by documenting the offset.Across the three rounds the coverage check was tightened four times: tautology → hardcoded census → live-tree with an offset → live-tree exact. The offset was the last place the absorption could hide.
Fourth round (reviews 43189 / 43195)
43189 (APPROVE, yellow) — Sub and Div still render as literals. Accurate; the claim was over-broad and is now scoped. See the note at the top: 3 of 5 operators are row-derived, the other 2 carry
rust_pair_completion_nonpolynomial_body_dissolve_onnaming the constructions their shapes actually need. The PR body's own claim was corrected rather than the finding argued down.43195 (APPROVE, non-blocking) — the coverage witness scans source text, not the Node tree. Adopted.
declared_fn_countcounts declarations by splitting the carrier source on a fn-name prefix, which is string-shape scanning where the substrate already has a parsed tree. It stays as the interim (it is strictly stronger than the hardcoded counts it replaced — a new blob now reds instead of waiting for someone to bump a number), but it no longer stands unmarked: it carriescoverage_scan_dissolve_on, whose trigger is a Node-treefn_declname-prefix count, takingfilesystem_readand theReadsLiveTreedisposition with it. The mark also states the two limits it has while it stands — it cannot see a blob whose name lacks the family prefix, and it detects the arrival of an unrostered blob rather than classifying a rostered one.This is the same rule this PR spends B2 enforcing, applied to the PR's own mechanism: a scaffold with prose and no trigger is a counted violation, including when it is mine.
B3 — per-language disposition
All 15 carry
extdeps_external_authority_anchorciting a real spec:Two corrections to the brief's B3 premises:
react_jsxis NOT dead vocabulary — deletion declined. It is enrolled as a live CI keystone:corpus_ci_gate_row_react_jsx_emit_keystonesits in the roster withExpectPass, there is a second react gate (gunbhub_react_browse_keystone), and the witness includes a security control (witness_hostile_href_rejected). Deleting it would remove a live CI gate. Needs an explicit re-ruling before any deletion.gpu/wgslwas already marked — it carries typedDispositionscaffold markers already; no new mark was needed.Methodology note (per the ruling that neither grep number goes in the body): import-grep undercounts, because many
.dagfiles are import-free and resolve whole-pool —react_jsx_emit_test.daghas no imports yet consumesserialize_jsx_component. That is the concrete receipt for preferring the parsed roster over grep denominators. No grep-derived corpus totals are claimed here.Deferred, with reasons
v1_emit_enum_supplemental_implsemits the Bool-to-host bridge, which is not ring/group and does not fit pair-completion rows. Needs a decision: second derivation shape, or narrow the hook so the RED covers only the arithmetic door.BackendCapability(withCapDryRunMode) has zero consumers; noBackendInfois ever constructed and the emit gates onhas_services. Migrating means wiring a dead capability system into a load-bearing stage. Marked with a trigger bindingBackendCapabilityas an honest interim; not wired.Out of scope, but surfaced
The emitted crate
v1-stage0-extdeps-languagesdoes not compile on clean main —crate::std_trait_derive_shapeis unreachable because it is declared in the crate above it (4 errors, proven by building main's own emitted file). No gate builds this crate, so only a whole-workspacecargo buildsees it. This PR's imports follow main's existing pattern and take it 4 to 12 errors of the same class. Belongs to the emitted crate partition thread.Fences respected: no string-content classifier lens; no new language dirs; no JS/TS server emit, bash strings, #6854 enrollment, or runtime_rust rewrite.