Single-source the shape-check path from the template (leg 1 of #405)#432
Merged
Merged
Conversation
… (Part of #405) kind_shape now reads a surface's required shape from its TEMPLATE frontmatter via the catalog (catalog -> template -> shape -> instance), so the thing the AI authors from is the thing the validator checks and the two cannot drift. Adds a standing check that every template's shape-spec is well-formed, and fixes two parser bugs. - validate.py: _template_shape_spec resolves the surface's catalog `template` -> frontmatter; kind_shape sources required/allowed/budget from it (rule-only length_budget_overrides stays on the rule; an un-catalogued target falls back to an inlined spec, exercised only by the negative-fixture meta-check). Frontmatter and fenced code blocks are excluded from length + section detection (F0232). - strip the now-dead inlined spec from the 6 shape rules; retire the 6 per-surface template-vs-rule drift tests (single source, nothing to drift); migrate the shape logic tests to the template-sourced model. - new engine/check/template-shape-spec (custom/script, hard, CI) governs every frontmatter-bearing template against template.v1 (F0222/F0223) + its negative fixture; registered in validators-core + the test_modules corpus (42). - conduct.md: drop its inert, instance-false shape-spec frontmatter (F0227) — conduct is governed by conduct_shape_check (data-driven titles), not a fixed-section spec. - regen graph.json + self-map.md. Full suite (2992) + validate --suite CI green. Part of #405. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Make the validator read a surface's required shape from its template, so the thing the AI authors from is the thing the validator checks — one source, no drift.
<Impact: a surface's shape can no longer silently diverge between what the AI writes and what the engine checks; a new or edited template with malformed shape settings is caught at the gate.>
Scope
Leg 1 of #405 (F0224, F0222, F0223, F0227, F0232).
kind_shapenow resolves a target's shape settings from its surface's catalogtemplatereference → the template frontmatter (_template_shape_spec). The six shape rules' now-dead inlined copies are removed; the six per-surface drift tests are retired (nothing left to drift); the shape-logic tests are migrated to the template-sourced model.engine/check/template-shape-spec(hard, CI) validates every template that declares shape settings againsttemplate.v1, with a negative fixture proving it bites. It catches the orphanrisk-assessment.mdtoo.conduct.md: its inert, instance-false shape-spec frontmatter is removed (conduct's shape is data-driven — each code's own title — and governed byconduct-shape, not a fixed-section rule).##inside a ``` block is code, not a section).<Impact: delivers the single-source shape path and its standing guard; behaviour over the real repo is unchanged (verified below).>
Out of scope
Legs 2 and 3 of #405.
Part of #405.Part of #405.Closes #405. Split out from the originally-planned single PR to keep context and each consent surface manageable.<Impact: this PR is the self-contained shape-path slice; the remaining legs are independent and follow separately.>
Risk
Low and behaviour-preserving; two guardrail-relevant points to note plainly.
.engine/check/) to the unguarded template frontmatter. So loosening a governance-critical surface's shape — e.g. dropping a contract's required Anti-choice section — would no longer tripengine-guard/an ack; it relies on the new well-formedness check plus your merge review. This follows the locked design's "shape is data, not code" intent, and you chose it over guarding the templates. Flagged on its own line so it is not lost among the mechanical changes.engine-guardwill be red pendingguardrail-ack:validate.py(the validator) and the six*-shape.jsonrules (edited to remove the inlined spec). Surfaced for you to apply the ack deliberately; the engine does not apply it.<Impact: bounded to the merge gate; no generated repo behaves differently, and the guard-posture change is a disclosed, consented trade, not a silent one.>
Validation
Full suite and the CI validator are green; the change is behaviour-preserving over the real repo.
python -m unittest discover -s tools -p 'test_*.py' -b— 3003 tests, OK (2 skipped), on the currentorigin/mainbase.python tools/validate.py --suite CI— passes clean with a token (the sole local red is the documented token-less artifact on an unrelated network check).template-shape-speccheck is wired into the checker-of-checkers and its fixture bites; the six live shape checks are green over the real repo.<Impact: an approver can rely on the mechanical floor being green in CI; correctness is covered by the Review below.>
Review
A four-lens cold plan-review ran before building, and a two-lens deliverable review on the built leg; verdict: conforms, no blocking or serious findings.
templatefield rather than a duplicate pointer, and surface the shape-spec de-guarding as a decision (resolved as above).##in frontmatter); mixed ```/~~~fence strictness (zero live impact — no~~~fences in the repo); a per-target catalog re-read (pre-existing pattern, sub-second).spec_referent.py review-steps --issue 405: "Nothing here is something you can run yourself — there's no settled description for this project yet."<Impact: the engine's own account of the review — your merge is the binding gate.>
Files of interest
The validator's shape path and the new standing check.
.engine/tools/validate.py—_template_shape_spec, the rewrittenkind_shape,_body_without_frontmatter, fence-awaresection_blocks/section_order..engine/tools/template_shape_spec_check.py+.engine/check/template-shape-spec.json— the standing template-shape guard..engine/templates/conduct.mdand the six*-shape.jsonrules — the conduct fix and the stripped inlined specs.<Impact: these determine the new single-source behaviour and its guard.>
Claude involvement
Design decisions were AI-made under a cold plan-review; edits are mechanical.
templatefield (spec-faithful single source), accepting the shape-spec de-guarding (your decision), the standing check's scope (every frontmatter-bearing template, conduct exempt), and removing conduct.md's inert spec. Recorded here and in the build record.templates/ontology/validationREADMEs and [conformance] Wire the validation/templates layer: single-source shape-check path, local triggers, module check-kind seam, and fail-closed gates #405's F0224/F0222/F0223/F0227/F0232.<Impact: the catalog-routing and de-guarding are the load-bearing AI judgments; the refactor and test migration are mechanical.>