Skip to content

RFC: the spec engine — schema for full spec-drivenness (review before build) - #698

Open
MaxGhenis wants to merge 11 commits into
mainfrom
spec-engine-schema
Open

RFC: the spec engine — schema for full spec-drivenness (review before build)#698
MaxGhenis wants to merge 11 commits into
mainfrom
spec-engine-schema

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

RFC: the spec engine — one declared bundle drives the build

Status: v3 (48aa575) — two full rounds of cross-family review. Review the doc, not the diff: docs/spec-engine.md.

Implements Max's ruling (2026-08-15): "this part should just be a yaml file … full spec-drivenness and full visual lineage of every variable … let's do it right before making atomic fixes — scope out the right schema for everything first."

Review history

Round sol (code-grounded) GPT-5.6 Pro (design)
r1 on v1 16 MAJOR / 3 MINOR — request changes (full text) 15 findings
r2 on v2 11/20 resolved, 3 renamed, 9 new MAJORs — request changes (full text) 3/15 adopted-correctly, 1 LOST, 11 fresh MAJORs — request changes (extract)

Every code claim spot-checked across both sol rounds held (12/12 cumulative).

What v3 changed (the convergent blockers)

  1. Identity split: run_provenance_identity (records every run; restored schema_version → spec_sha256 → authority_version triad with precedence — Pro's LOST finding) vs node_reuse_key (decides reuse; actual seed material + behavior-relevant run inputs; no execution profile). Whole-run binding stays as the safe interim until plan.lock drives execution.
  2. F0 single-authored: bundle authored once → compiler generates the legacy payload the constants executor consumes (config_authority=constants_adapter). The v2 "edit constants+bundle together" fast path was a dual-authority trap (both reviewers).
  3. CHAMPVA lane goes first, pre-F0, under the existing Imputation lineage spec: per-variable predictors + model attributes as source of truth #695 mirror + its own OOS gate; the Column closure: every artifact column claimed by exactly one lineage class (spec totality) #697 inventory regenerates after (v2's lane order was backwards — the held fixture is missing 56 predictor columns).
  4. Eligibility guards are target-specific concept sets — the family-level generic [eligibility] tag did not actually make the CHAMPVA defect impossible.
  5. Take-up: orthogonal ownership × typed pipeline steps; all 13 real contract programs committed (wic/social_security never existed); generated engine ABI lock kills the derive-and-assert circularity.
  6. Frozen split ledger corrected: five batches / 37 targets (19 groups / 70 overall); F3 re-unification honestly scoped (donor mask, family seeds, shared RNG, chained features, owners, banks).
  7. Producer graph: field-lossless + graph-semantic (explicit edges, deterministic ordering, OR-of-AND fallbacks, 18-row ownership matrix, row-scope predicate algebra).
  8. Seeds enforced: RNG broker + exhaustive draw-site ledger + stream receipts — an unenforced stream map is documentation.
  9. Equivalence: four cold builds (A=B, C=D, A=C), plan-derived comparison vector including publication + model banks, concrete resume predicate + --resume-policy=forbid, adversarial fixtures.
  10. Publication: attempt events → immutable terminal seal; atomic promotion with recovery; strict-linear audit chain ≠ release relationship DAG.
  11. Catalogs split (contract / derived / docs), vintages become typed references, engine pin exactly once; F2 deletion checklist machine-decidable (zero-reference tombstones, node-invalidation matrix, dated selector retention).
  12. CountrySpec seam explicit: single typed resource manifest, ResolvedCountrySpec compatibility projections, generation semantics for fingerprint→spec_sha256, Belgian smoke build before the identity cutover.

Open for Max

  • Sign-off on v3's architecture (both reviews' full change lists are folded; excerpts are labeled pseudocode until schemas + the complete US bundle land as F0's first deliverable).
  • D6: release line rename — held provisional/non-normative, excluded from spec_sha256, until ruled. HF destination untouched without a separate explicit ruling.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits August 15, 2026 23:56
Scope-everything-first schema per Max's 2026-08-15 ruling ('do it right
before making atomic fixes'). docs/spec-engine.md defines the bundle
(sources/spine/geography/imputation/take_up/battery/calibration/
selection/publication/column_lineage), the kernel escape hatch for
per-variable custom logic, the spec_sha256 identity join, the
frozen-behavior equivalence gate for the authority flip, the migration
map from every constant and from the three held wave-1 lanes, and the
rollout order. specs/us/ carries skeleton drafts of the root manifest
and the two most mechanism-dense files. Review artifact only — nothing
is wired.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n the non-identified-county complement, never the whole state

County identification in CPS is a whole-county disclosure property, so a
household without a county code is known not to live in any identified
county. Drawing its block statewide leaks mass into ruled-out counties;
the universe is the state's complement (Max, 2026-08-16). Records the
identified-set source preference (official CPS availability list, with a
documented pooled-file fallback) and the PSU caveat.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis and others added 8 commits August 16, 2026 09:56
…-batch independence, keep-together groups

Within a fit, each target conditions on base predictors plus all
previously drawn targets (chained equations, per-target banked). But
max_targets_per_fit=8 splits wider families into separate chains that
are conditionally independent given base predictors, and chain order is
today the accidental order of a code tuple. All four choices become
spec declarations; the immigration-pair joint codec generalizes to
declared keep_together groups. Surfaced by Max's question, 2026-08-16.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rule and contract

Max, 2026-08-16: the flag column name is a deterministic function of the
program (takes_up_{program}{treatment_suffix}; legacy irregulars like
takes_up_eitc regularized at the flip) and the entity must come from the
program variable itself — the take-up contract already records it from
engine metadata (TakeUpProgram.entity). Both become derived-and-asserted
loader outputs, never independent declarations. Generalized as bundle
principle 7: derive, don't declare — every deterministic function of
another authority is derived and asserted; a second independent copy is
a future drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…torical; HF destination = explicit ruling only

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t-k validity gate cardinality_gate

support_assertions:on misrepresented unconditional fail-closed checks
(exact length k never clamped, unique, integer, in-pool, sorted; real
exceptions not assert) as a toggle. They move into sampford_exact_k's
declared kernel contract per the capability-typing amendment; the file
keeps only real knobs (k, pi_hi, group_ids, refusal policy) with seed in
the run request. Also reserves 'support' for donors — the selection gate
is about index-set validity, a naming collision the spec should kill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rebuilt after two independent reviews (sol: 16 MAJOR code-grounded,
7/7 spot-checks verified; Pro: 15 design findings):

- One spec system: bundle becomes CountrySpec resource kinds (US/UK/BE
  packages are live — Belgium is a conformance obligation, not future
  work); us_imputation_lineage.yaml retires at the flip
- Identity: four orthogonal classes (grammar/config/code/serialization),
  namespaced spec_binding, per-node keys, compiled plan.lock.json;
  builder_code_identity joins stacked identity; singleton canonicality
  replaced by loader provenance + digests
- Equivalence gate rebuilt: cold isolated resume-forbidden dual builds,
  content digests, normalized gates, identity_generation cutover
- Seeds split: legacy-v1 named streams for the flip; derived-v2
  stateless counters as F3 behavior change
- Kernels: capability typing + generic projection/patch/diff executor;
  lossless producer_graph; no library-default leakage into builds
- Lineage: column_lineage.yaml dissolves into derived closure +
  cell-scope (entity,column,row_scope,stage,write_policy) segments +
  catalogs (Max ruling)
- take_up.yaml: discriminated treatments with ordered pipelines; SNAP
  declared honestly as anchored_count_calibrated; contract absorbed
- Chaining: max_targets_per_fit=8 is dead (Max ruling) — declared-only
  splits; batch re-unification flagged as F3 (RNG-consumption change)
- Geography: block-first + ASEC complement moved to F3; flip encodes
  legacy behavior exactly
- Rollout F0-F3 with the value-fix fast path: CHAMPVA-class predictor
  fixes land right after F0 under mirror discipline
- v1 factual errors fixed: mass anchor asec (not acs), PUF tax-detail
  clone 1 by role (not 0)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both round-2 reviews converged on the blockers; v3 resolves them:

- Identity: restore the versioning triad (schema_version / spec_sha256 /
  authority_version with precedence + bump rules — Pro's LOST finding)
  composed with the four-class vocabulary; split run_provenance_identity
  (records, never gates reuse) from node_reuse_key (per-node, actual
  seed material + behavior-relevant run inputs; NO execution profile);
  identity_generation on concrete fields with closed reader rules
- F0 rebuilt single-authored: bundle authored once, compiler generates
  the legacy payload the constants executor consumes
  (config_authority=constants_adapter); full front-end coverage +
  usage accounting + mutation tests; NO manual dual-editing (the v2
  mirror-discipline fast path was a dual-authority trap — both reviews)
- CHAMPVA lane moves to pre-F0 under the existing #695 mirror + its own
  OOS gate; #697 inventory regenerates AFTER (v2 lane order was
  backwards — held fixture missing 56 predictor columns)
- Take-up: orthogonal ownership × typed pipeline steps; all 13 real
  contract programs committed (wic/social_security never existed);
  engine ABI lock kills the derive-and-assert circularity;
  total-and-injective column mapping (suffix rule died on takes_up_eitc)
- Eligibility guards become target-specific concept sets (family-level
  generic [eligibility] tag did NOT make CHAMPVA impossible)
- Frozen split ledger corrected: five batches/37 targets (19/70
  overall); F3 re-unification scoped honestly (donor mask, family
  seeds, shared RNG, chained features, owners, banks)
- Producer graph: lossless = field-lossless + graph-semantic (edges,
  deterministic order, commute-or-disjoint, OR-of-AND fallbacks,
  18-row ownership matrix, row-scope predicate algebra)
- Seeds: RNG broker + exhaustive draw-site ledger + receipts (a named
  stream map without enforcement is documentation)
- Catalogs split three ways; vintages become typed references; engine
  pin exactly once
- Equivalence: four cold builds (A=B, C=D, A=C); plan-derived vector
  incl. publication + model banks; concrete resume predicate +
  --resume-policy=forbid; adversarial fixtures
- Publication: attempt events -> immutable terminal seal; atomic
  promotion with recovery; audit chain != release relationship DAG
- Gates/calibration: executable records (formulas, populations,
  thresholds, uncertainty, missing-slice; full solver math contract;
  exact-k post-selection weight semantics)
- Kernels: brokers for file/env/clock/RNG; orthogonal capability
  fields; structural_delta replaces structural_effect
- CountrySpec: replacement-through-seam (single typed manifest,
  ResolvedCountrySpec compatibility projections, generation semantics,
  gate-battery spec_fingerprint migration, BE smoke build pre-cutover)
- F2 deletion checklist machine-decidable (zero-reference tombstones,
  node-invalidation matrix, fault injection, dated selector retention)
- D6: release line provisional/non-normative, excluded from
  spec_sha256, until Max rules

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d forward

defs (row-scope predicate algebra, executable gate record, surfaces),
resource manifest ({path,kind,schema_id} — the single inventory), and one
schema per authored kind + emitted locks (bundle/plan/engine_abi), all
draft 2020-12 with additionalProperties:false. v3-shaped: concept guards
per target, orthogonal take-up steps, full calibration math contract,
provisional release line (D6), catalogs with authored lineage forbidden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hasing

D6 (release-line rename) stays a separate open ruling; provisional and
excluded from spec_sha256 until then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review August 16, 2026 21:25
Line becomes normative in publication (hashed into spec_sha256); readers
accept legacy populace-us-2024 prefix (rows valid-historical); HF dataset
destination explicitly outside this ruling. Adds the publication.yaml
skeleton and tightens the schema (pattern + legacy_prefixes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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