Repository navigation
design: producer-shape factoring + six sub-signature lens bindings + §11 subsumption model (operator-direct emit_rust.dag analysis) - #3489
Conversation
…§11 subsumption model (operator-direct emit_rust.dag analysis) Operator delivered substantive algebraic analysis of emit_rust.dag's dissolution coverage gaps. This PR lands the three architectural moves they identified: [A] Three new producer stages (§10.1 + §10.2) — the algebraic move 'broader rules prevent repeats': - v4.lens.decision_tree_shape — normalizes closed-vocab branch dispatch REGARDLESS of source spelling (match / if-else chain / string-eq chain). Replaces match-only detection with shape-detection-regardless- of-syntax. Carries KeyVocabulary (resolved ConstructorId set, authoritative not by-spelling), per-branch BodyShape (α-renamed expression tree, same algebra as L1.12.b's body normalization), missing-key behavior, and source-form fact-of-finding. - v4.lens.generated_forest_shape — the META scope of L1.13's skeleton- collapse: catches fns that walk a closed coproduct's variant-set AND emit a per-variant target artifact (text or AST). Reuses SkeletonGroup + NormalizedArmBody from match_arm_skeleton at the emission scope (Practice 11 — same mechanism, two scopes). - v4.lens.target_syntax_string_shape — classifies string-construction graphs as DataString vs TargetGrammarTokenSequence vs Unknown. Gated on a per-target TargetGrammarTokenSet substrate carrier; rust.dag's LanguageModel (PR #3476) is the canonical first instance. Targets without a TargetGrammarTokenSet → Unknown → lens fails closed (no false positives). §10.3 dissolution stage's consumes: list updated for all three. [B] Six sub-signature lens bindings — all bound under existing L1.x parents (no new top-level IDs per the standing 2026-05-19 directive); each shares the parent's coverage_defect_* acceptance key with a new diagnostic-payload Trigger discriminator (same pattern as L1.12.b under L1.12): - L1.4.c PolicyTableAsFunctions — function whose body IS a typed table over closed vocabulary. Consumes decision_tree_shape. Seed kill: rust_string_policy_for_naming vs rust_internal_policy_for_naming. Subsumes the prior 'L1.13.b match-as-typed-table' reservation (L1.13's TotalMap dependency text retired to L1.4.c). - L1.5.b GeneratedForestCollapse — meta-walk emitting per-variant target artifacts that collapse to K skeletons. Consumes generated_forest_shape. Seed kill: emit_enum_shared_accessors. - L1.10.c NameDiscriminantBypass — spelled-name dispatch where resolved identity is available. Consumes decision_tree_shape with source_form = StringEqChain. Seed kill: variant_encoding_is_string_variant shape predicates. - L1.10.d TargetSyntaxByConcat — grammar-token concat that should be a TargetSurfaceNode. Consumes target_syntax_string_shape. Seed kills: emit_rust_block_stmts / emit_typed_record_lit / emit_rest_url_line / emit_rest_body_line; whole emit_rust.dag is a pile-up of L1.10.d findings. - L1.11.b PlausibleScalarFallback — missing-arm fabricates scalar literal used as target authority. Consumes decision_tree_shape + target_syntax_string_shape. Seed kills: emit_rest_auth_line's None=>'Authorization' / None=>'x-api-key' defaults; service base URL 'http://localhost' fallback. - L1.13.b DecisionTreeCollapse — generalizes parent L1.13's skeleton-collapse beyond match expressions to any closed-vocab decision tree. Same classification (PureTemplate / Outlier / etc.) regardless of source-form. Consumes decision_tree_shape. §5.0 / §5.1 cross-reference rows added/extended for all six. [C] §11 Subsumption model — new section addressing the operator's side-thought: 'what if the dag has multiple lens violations simultaneously — diagnosis should find the minimal pattern immediately, not surface one-at-a-time creating a fix → reveal → fix → reveal cycle.' Introduces DissolutionSubsumption substrate carrier with two verification kinds (MechanicalReverification via TestClaim re-run / ProducerStageDerivation via consumes: graph). Diagnostic surface ordering: roots first (Apply X — closes 47 other findings), leaves on root-rejection, subsumed-leaf preview. Worked example: the rust.dag LanguageModel subsumption-root for emit_rust.dag's 100+ findings under L1.5.b / L1.10.c / L1.10.d / L1.13.b / L1.4.c / L1.11.b. Renumbered prior §11 'Open — audit of current coverage' to §12. All sub-signatures share the producer-stage architecture under Facts Flow Forward / P2: one shared producer (decision_tree_shape / generated_forest_shape / target_syntax_string_shape) consumed by multiple downstream lenses. No new producer stages are minted per lens — same discipline that made L1.12.b + L1.4.b co-define cleanly. Enforcement gates uniformly require: (i) producer stage lands with the documented schema, (ii) parent diagnostic payload extends with the appropriate Trigger discriminator, (iii) for sub-signatures needing substrate carriers (TargetGrammarTokenSet, TotalMap), at least one canonical first instance lands as migration target. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…2-decision-tree-producer-families
….13.c relocation)
Operator delivered substantive review with 7 specific tightenings. All
addressed in this commit:
[1] L1.13.c TotalMap too concrete for payload-bearing variants
(rust_serde policy's StripPrefixAndSnakeCase { prefix } etc. would
imply infinite table). Two clean shapes now distinguished:
- Pattern A: TotalMap<K, V> — for finite payload-free keys + fully
materialized values
- Pattern B: TotalPolicy<K, Context, RowTemplate> — for payload-
bearing key vocabularies; row templates reference payload fields
by name and materialize per-call by substituting runtime payload
into the template's holes
Auto-fix infers the pattern from KeyVocabulary's payload-bearing-ness.
[2] decision_tree_shape needs 04_infer + typed-subject rule.
StringEqChain now produces KeyVocabulary ONLY when the compared
subject has a UNIQUE resolved closed carrier per 04_infer. Ambiguous
or open cases get a new OpenOrAmbiguousNameDispatch source_form
variant; lens consumers (L1.10.c) do NOT auto-fire on it (open-
vocabulary escape preserved). Producer consumes: list extended.
[3] target_syntax_string_shape classification inconsistency fixed.
'Absence of TargetGrammarTokenSet → DataString' was wrong (absence of
substrate is not evidence of data). Now: no TargetGrammarTokenSet for
any target the string might reach → Unknown. Spelled out the four-
case closed predicate (1-no-substrate / 2-no-grammar-token-evidence-
in-data-sink / 3-grammar-token-evidence-in-target-sink / 4-other).
NO numeric token-density threshold — entirely closed structural test
(addresses tightening #6).
[4] L1.11.b needs broader use-site producer than target_syntax_string_shape.
New producer added: v4.lens.scalar_authority_use_shape produces
Map<ScalarRhsId, ScalarAuthorityUseShape> with closed ScalarUseRole
coproduct: TargetSyntaxUse / IdentifierUse / UrlUse / HeaderNameUse /
FilePathUse / ResourceCoordinateUse / DataStringUse / UnknownUse.
Gated on scalar_authority_use_registry substrate carrier (per-
consumer ScalarUseRole declarations). L1.11.b consumes this producer
NOT target_syntax_string_shape (different classification axes:
production-site vs use-site role).
[5] Generated-forest asymmetric coverage Escape now requires substrate-
derived subset witness (VariantCoverage row citing structural
predicate). Local unregistered filters like
'children |> filter(child => child.children |> count > 0)' do NOT
pass — those are L1.5.b / L1.10.c / L1.13.b territory depending on
the filter's shape. The escape requires structural authority.
[6] TargetSyntaxByConcat threshold language replaced with closed
structural predicate (addressed in #3 via the four-case predicate in
producer-stage spec; L1.10.d's Signature text also updated to
reference the closed predicate explicitly, not 'classification
threshold').
[7] L1.4.c taxonomy move: L1.4.c (Policy-table-as-functions) relocated
to L1.13.c (Table decision-tree) under the Skeleton-collapse family.
Operator: 'function body is a typed table is not really a carrier
clone; closer to decision-table dissolution.' Mechanism is
decision_tree_shape (same as L1.13.b), not type-declaration-shape
(L1.4/L1.4.b's). L1.4.c original site replaced with a 'Moved' notice;
L1.13.c added under L1.13.b with the payload-aware TotalPolicy
refinement from item #1 baked in.
Tables + cross-refs updated in lockstep:
- §5.0 L1.4 row (L1.4.c removed); L1.13 row (L1.13.c added)
- §5.1 L1.4.c row removed; L1.13.c row added; L1.13.b discriminator
extended to include TableDecisionTree variant
- §10.1: L1.4.c→L1.13.c across producer-row consumers
- §10.2: producer-shape spec edits per items 2/3/6; new
scalar_authority_use_shape producer added; stage count
'Eight'→'Nine'
- §10.3: dissolution consumes list extended with scalar_authority_use_shape
- §10.2 closing paragraph: cross-stage routing updated to reflect the
relocations + new producer
- §11 subsumption worked example: L1.4.c→L1.13.c references updated
All seven tightenings preserve the producer-stage architecture under
Facts Flow Forward / P2 — no producer-stage duplication; consumers
cleanly partitioned per classification axis.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…table' prose (cursor APPROVE_WITH_COMMENTS doc-hygiene) cursor APPROVE_WITH_COMMENTS flagged INVARIANTS P2 (single authority) issue: I rebound L1.13.b to DecisionTreeCollapse and moved the F16 match-as-typed-table case to L1.13.c, but several pre-existing prose passages from origin/main still described L1.13.b as the 'future per-arm-name / match-as-typed-table sub-signature.' Two incompatible authorities for the same sub-signature ID in one design doc. Reconciled four residual references: 1. L1.13's borderline-case discussion (:2227-2233 originally) — the prose listed 'L1.13.b (future)' OR 'separate match-as-typed-table lens' as the two possible bindings for the manual_test_claim_for_manual_anchor pattern. Both pointers now unified under L1.13.c. Added a historical-traceability note explaining the original two-option phrasing for readers who hit the prior text. 2. L1.13's Kills section (:2103) — 'proposed L1.13.b that detects arm-name-parameterizes-reference pattern' → 'L1.13.c Table decision-tree' with the same historical note inline. 3. v4.lens.match_arm_skeleton producer comment (:2789-2794) — 'L1.13 auto-fix and any future L1.13.b sub-signature' + 'reusable by: L1.13, future L1.13.b (per-arm-name-parameterized-reference sub-signature), future match-as-typed-table lens' → 'L1.13 auto- fix needs (and the L1.13.c table-decision-tree sub-signature reuses it for per-arm-RHS-referencing-typed-data cases)' + 'reusable by: L1.13 (base, MatchExpr-scoped), L1.13.c (table decision-tree)'. 4. v4.lens.decision_tree_shape producer comment (:2881-2882) — 'reusable by: L1.13, L1.13.b, L1.13.c, L1.10.c, future match-as-typed-table sub-signature' → cleanly enumerated by binding without the residual 'future match-as-typed-table' pointer (which is now L1.13.c). After reconcile, the only remaining 'future L1.13.b' mentions in the doc are inside the explicit historical-traceability notes (intentional — they explain the binding history for readers who encounter the prior text). Net effect: L1.13.b now consistently binds to DecisionTreeCollapse throughout; L1.13.c consistently binds to TableDecisionTree throughout; the match-as-typed-table case has one single authoritative pointer (L1.13.c) across the whole doc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nter, not authority (codex APPROVE_WITH_COMMENTS Practice 9 / P2 reconcile) codex APPROVE_WITH_COMMENTS on PR #3489 flagged §5.1 as a Practice 9 / INVARIANTS P2 violation: the section opened with 'Downstream consumers MUST use the canonical key names enumerated here. The lens suite is the single authority...' That framing makes the design doc authoritative for coverage_defect_* keys when the actual substrate authority is src/v4/lens/coverage.dag's declared rows. Classic parallel-authority / maintained-ledger-doc anti-pattern (operator- direct standing 2026-05-19 retired this class). Fix: - §5.1 header retitled 'L1.x acceptance-key names — substrate registry pointer.' - Opening prose rewritten: explicit 'Authority pointer (not authority itself)' framing — src/v4/lens/coverage.dag is the authoritative registry; this doc describes but does NOT own. If table and substrate disagree, substrate wins. - Added explicit cite of the no-prose-ledger discipline (Practice 9 / INVARIANTS P2 / operator-direct standing 2026-05-19). - Reframed table purpose as 'reading scaffold for readers walking the lens family' — claims about substrate state at this revision, not definitional rules. - 'Downstream-consumer guidance' clarified: code reads keys from src/v4/lens/coverage.dag directly, NOT from this table. Substrate- driven projection, not doc-rebase-driven. - 'Migration notes' closing line rewritten: future taxonomy changes update the substrate first; this table follows. Net effect: doc describes the registry; substrate IS the registry. No change to row content (the keys are the same and they're what src/v4/lens/coverage.dag already declares); just the authority framing reconciled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
6c3df186· Trigger:schedule - Thinking:
286s wall
BLOCKING (3)
Root Cause
src/v4/lens/coverage.dagmissing substrate acceptance key for L1.13 Skeleton-collapse → land theCoverageDefectKeyandcoverage_defect_skeleton_collapserows first, or remove the doc rows until the registry existsdocs/design-dissolution-lens.mdL1.11.b kept the pre-split producer dependency after introducingscalar_authority_use_shape→ make the gate namedecision_tree_shapeplusscalar_authority_use_shapeand reservetarget_syntax_string_shapeonly for the TargetSyntaxUse cross-referencedocs/design-dissolution-lens.md§11.4 retained TotalMap-only wording after the payload-awareTotalPolicyrefinement → describe the root fix asTotalMapfor payload-free tables andTotalPolicyfor payload-bearing policies
| other than `DataStringUse` AND `UnknownUse`. `target_syntax_string_shape` | ||
| classifies what is being BUILT at the production site (target-grammar | ||
| tokens vs data strings); `scalar_authority_use_shape` classifies | ||
| what role the scalar FILLS at the consumer call-site — different |
There was a problem hiding this comment.
BLOCKING: L1.11.b says its enforcement gate waits on target_syntax_string_shape, but the same section later says it consumes scalar_authority_use_shape and explicitly does not consume target_syntax_string_shape, creating a Facts Flow Forward / P2 dependency contradiction.
| density, which makes the per-author surface SIMPLER, not more | ||
| cluttered. | ||
| - **The framework is honest about leverage.** A lens that fires | ||
| often but is always subsumed by a higher root never blocks an |
There was a problem hiding this comment.
BLOCKING: The subsumption example still routes serde-policy decision trees to TotalMap rows even though L1.13.c requires TotalPolicy for payload-bearing keys, reintroducing the impossible infinite-table shape the earlier section rejects under Practice 2 / P2.
| | **L1.10.c** `NameDiscriminantBypass` (sub-signature of Textual-bypass family) | `coverage_defect_template_hole` *(shared with the textual-bypass family — diagnostic payload carries a `TextualBypassKind` discriminator distinguishing the four sub-signatures a/b/c/d)* | | ||
| | **L1.10.d** `TargetSyntaxByConcat` (sub-signature of Textual-bypass family) | `coverage_defect_template_hole` *(shared with the textual-bypass family — same `TextualBypassKind` discriminator)* | | ||
| | **L1.11.b** `PlausibleScalarFallback` (sub-signature of Plausible-fallback family) | `coverage_defect_plausible_fallback` *(shared with parent — diagnostic payload carries a `PlausibleFallbackKind` discriminator distinguishing constructor-fabrication (parent) from scalar-fabrication (this sub-signature))* | | ||
| | **L1.13.b** `DecisionTreeCollapse` (sub-signature of Skeleton-collapse family) | `coverage_defect_skeleton_collapse` *(shared with parent — diagnostic payload carries a `SkeletonCollapseScopeTrigger` discriminator distinguishing `MatchExpr` (parent) from `DecisionTreeGeneralized` (this sub-signature) and `TableDecisionTree` (L1.13.c))* | |
There was a problem hiding this comment.
Invariant violation: BLOCKING: These added rows reference coverage_defect_skeleton_collapse, but the authoritative src/v4/lens/coverage.dag registry has no SkeletonCollapse/coverage_defect_skeleton_collapse row, so the doc table becomes the only authority in violation of Practice 9 / INVARIANTS P2.
…t + §11.4 TotalPolicy refinement) codex BLOCKING wrap on PR #3489 sha 6c3df18 raised three findings; finding #1 (substrate row landing for coverage_defect_skeleton_collapse) was addressed in auto-snapshot WIP commit b5c6996 (added SkeletonCollapse variant + data row to src/v4/lens/coverage.dag + updated the integration test ratchet's EXPECTED_ACCEPTANCE_ROWS). This commit addresses findings #2 + #3: [#2] L1.11.b enforcement-gate text still referenced target_syntax_string_shape as the prerequisite producer after I'd split the use-site classification out to scalar_authority_use_shape. Fix: Enforcement gate text rewritten to require BOTH - (a) v4.lens.decision_tree_shape lands (for None-arm scalar-RHS detection) - (b) v4.lens.scalar_authority_use_shape lands (for use-site authority- role classification) plus per-ScalarUseRole-variant gating via scalar_authority_use_registry. Explicit statement: target_syntax_string_shape is NOT a prerequisite — it classifies the production-site (L1.10.d's axis); L1.11.b consumes the orthogonal use-site-role axis. Only referenced for the TargetSyntaxUse cross-reference variant. [#3] §11.4 subsumption worked example R-root-B still described the root fix as TotalMap-only after the payload-aware TotalPolicy refinement landed in earlier commit. Fix: R-root-B prose rewritten to distinguish TotalMap (finite payload- free) from TotalPolicy<K, Context, RowTemplate> (payload-bearing policies, per the L1.13.c payload-aware refinement). The serde-policy case specifically called out as TotalPolicy (because VariantNaming has payload-bearing constructors like StripPrefixAndSnakeCase { prefix }); auth-defaults case may be TotalMap or TotalPolicy depending on auth-source vocabulary. All three codex BLOCKING findings now reconciled across substrate + design doc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same finding as codex BLOCKING #2 — addressed in commit
|
Same finding as codex BLOCKING #3 — addressed in commit
|
Same finding as codex BLOCKING #1 — addressed in commit
|
Summary
Operator delivered substantive algebraic analysis of
src/v2/05_emit_rust.dag's dissolution coverage gaps, identifying that current lenses catch source-level structural shapes but miss equivalent shapes hidden behind: if/else trees instead of match, string comparisons instead of constructor identity,map(children)that generates a target match forest,concat/formattarget syntax instead of literal{0}templates, String defaults instead of enum constructors, and non-identical but parameterizable policy functions.The operator's algebraic move: don't add one-off lenses for each pattern; define three reusable structural producers (
DecisionTreeShape,GeneratedForestShape,TargetSyntaxStringShape) capturing the algebraic shape, then express individual lenses as consumers of those facts. Single Producer → Multiple Lens Consumers, Facts Flow Forward / P2.This PR lands all three architectural moves:
(A) Three new producer stages (§10.1 + §10.2)
v4.lens.decision_tree_shapematchvsif-elsevs string-equality chainv4.lens.generated_forest_shapematchvsmap(children)vs textual emissionv4.lens.target_syntax_string_shape{0}template vsconcat()vsformat!()target_syntax_string_shapeis gated on a per-targetTargetGrammarTokenSetsubstrate carrier.rust.dagLanguageModel from PR #3476 is the canonical first instance — targets without LanguageModel substrate fail closed (no false positives).(B) Six sub-signature lens bindings — all under existing L1.x parents (no new IDs)
Each shares the parent's
coverage_defect_*acceptance key with a new diagnostic-payload Trigger discriminator (same pattern as L1.12.b under L1.12):PolicyTableAsFunctionsGeneratedForestCollapseNameDiscriminantBypassTargetSyntaxByConcatTargetSurfaceNodePlausibleScalarFallbackDecisionTreeCollapseReal-corpus seed kills cited from operator's
emit_rust.daginventory:rust_string_policy_for_namingvsrust_internal_policy_for_naming(L1.4.c + L1.13.b co-fire),emit_enum_shared_accessors(L1.5.b),variant_encoding_is_string_variant(L1.10.c),emit_rust_block_stmts/emit_typed_record_lit/emit_rest_url_line/emit_rest_body_line(L1.10.d pile-up),emit_rest_auth_linedefaults + service base URL fallthrough (L1.11.b).L1.13's existing TotalMap-substrate dependency (originally scoped to "future L1.13.b match-as-typed-table") is rebound to L1.4.c — the new L1.13.b is the decision-tree-generalization (no TotalMap dependency).
(C) §11 Subsumption model — minimal-edit dissolution ordering
Addresses the operator's side-thought: "what if the dag has multiple lens violations simultaneously — diagnosis should find the minimal pattern immediately, not surface one-at-a-time creating a fix → reveal → fix → reveal cycle."
Introduces
DissolutionSubsumptionsubstrate carrier:Diagnostic surface ordering: roots first ("Apply X — closes 47 other findings"), leaves on root-rejection, subsumed-leaf preview. Worked example: the
rust.dagLanguageModel subsumption-root foremit_rust.dag's 100+ findings across L1.5.b / L1.10.c / L1.10.d / L1.13.b / L1.4.c / L1.11.b.Renumbered prior §11 ("Open — audit of current coverage") to §12.
Architectural discipline preserved
decision_tree_shapeis consumed by L1.13.b + L1.10.c + L1.4.c;target_syntax_string_shapeis consumed by L1.10.d + L1.11.b. One mechanism, multiple downstream projections.TargetGrammarTokenSet,TotalMap,DissolutionSubsumptionare all substrate data carriers, not comment markers.Test plan
🤖 Generated with Claude Code