Development record
Every Spec Externalises How It Should And Shouldn't Be Modified
Rule
Every spec carries a ## Modification Grammar section with three sub-headings, each of which MUST be non-trivial and non-boilerplate:
### Extends cleanly— at least one concrete example with a constraint. "What kind of change can someone make to this spec's deliverables without breaking the design?" Concrete = at least one fenced code block OR file-path reference OR line-number reference; the constraint names a specific extension point.### Breaks the design— at least one named failure mode. "If someone does X, the design breaks because Y." Concrete failure mode, not "general code-quality concerns" or "anti-patterns to avoid."### Why— the structural rule from which both sub-headings follow. The rule, not a list of cases — a list of cases without an underlying rule fails the discipline. The rule must be specific enough that stripping the spec name still identifies the rule's spec.
A fourth axis — ### Ripple — captures the per-spec-external concerns absorbed from idea-3 (systems thinking) at adversarial review (chat idea-3-itd-38-adversaria-31A06A, MAJOR_RETHINK outcome): vocabulary delta (HARD-enforced via the vocabulary-registration requirement in 02-constraints/04-naming.md), surface delta (new commands / sub-verbs / agents / disciplines), coupling delta (what this spec newly depends on; what newly depends on it). The Ripple axis stays under itd-37 (same retrieval key as modification grammar — domain) rather than spawning a separate discipline.
At spec completion, principle-distiller (the role-extended curator from itd-36) extracts the ## Modification Grammar section into two memory pages per 05-internals/07-memory.md:
spec_modification_grammar_<spec_id>.md— append-only, per-spec. Source classspec_modification_grammar. Lifecycle: append-only per05-internals/04-universal-patterns.md § 8.modification_grammar_<domain>.md— compounding-curated, per-domain.principle-distillerruns a curator-pass that synthesises across the per-spec pages. Lifecycle: compounding-curated per the same taxonomy.
Two page classes, two lifecycles, two retrieval surfaces. The per-spec page preserves provenance; the per-domain page is the cross-cutting query surface that aggregates across specs in the same domain.
Why
abcd's three-layer mental model captures what (brief), why (intent), how to build (spec). It does not, until itd-37, capture how to extend without breaking the structure. Per Naur ("Programming as Theory Building", 1985, gwern.net/doc/cs/algorithm/1985-naur.pdf), there are three areas of tacit knowledge code cannot capture: Mapping (what the program represents), Justification (why each load-bearing decision), and Modification (the structural rules that govern modification). abcd already covers Mapping (press release + acceptance criteria) and Justification (audit notes + open questions + brief decisions + reclassification history) partially. Modification is the genuinely new gap.
The discipline is named for what's actually new — modification grammar, not "theory" writ large. The renaming was forced by adversarial RP review (chat adversarial-naur-theory--0A4174): "Theory" overpromised (the section captures a subset of theory, not theory writ large; an engineer seeing ## Theory guesses "academic justification" or "literature review" — both wrong); "modification grammar" is honest, specific, and forces concrete content.
Why two-layer enforcement. Boilerplate-rot is the discipline's principal failure mode. A ## Modification Grammar section that says "extending requires care; modifying requires understanding the design" is non-empty, parseable, content-free — and worse than no section at all because it occupies cross-cutting query surface with noise. A regex-level "non-empty" lint catches the laziest failure but not plausible-sounding boilerplate. Two layers:
- Concreteness lint (mechanical) rejects sections without a concrete reference (code block / file path / line ref). Lint codes
MG001-MG003. - Semantic boilerplate detection (reviewer judgement) runs
intent-auditorRole 1 (the discipline role per itd-1) at spec plan-review and ship time. Prompt-encoded test: "Strip the spec name. Could this## Modification Grammartext describe a different spec? If yes, reject." Lint codeMG004.
The semantic enforcement is genuine LLM-judgement work. The discipline owns the requirement explicitly — regex cannot catch boilerplate.
MG004 enforcement surface (made concrete by spc-12 (predecessor store)). The timing is unchanged — MG004 runs at plan-review and ship time — but the named surface is the abcd-owned CI / pre-commit path: the native disciplines lint/CI wrapper invoked from .github/workflows/ci.yml, not a plan-review-step integration. The Role 1 MG004 pass emits a PASS / FAIL boilerplate verdict; the verdict lands in a per-run batch receipt at .abcd/logbook/audit/spec-mg-<ts>/report.{json,md} (native specs have no ## Audit Notes section, so the verdict cannot land in-file). spc-12 (predecessor store) ships the MG004 judgement pass, its receipt writer, and the receipt schema; the CI wiring is added by spc-12 (predecessor store) itself via the native disciplines lint.
Why the cost is justified. itd-37 is the first expensive discipline in abcd's stack (~15-30 min careful thought per spec, vs ~5 min for itd-1 / itd-5 / itd-36's mechanical gates). With itd-1 + itd-5 + itd-36 + itd-37 all live, every spec carries 4 discipline gates costing ~30-45 min total — real, but justified. The failure modes the disciplines prevent (specs without acceptance bars, agents without quality gates, specs without modification grammar, specs without provenance) compound exponentially as the corpus grows. Disciplines are a fixed per-spec tax; the failures are exponential. Trade favourably.
Why all specs, no "trivial" carve-out. "Trivial" cannot be cleanly specified without inviting loophole-driven exemptions. A ## Modification Grammar section that says "this spec adds a config flag with no extension surface; modifications are limited to renaming the flag; the rule is: never bind config-flag names to public API" is valuable — documenting absence-of-extension-points IS modification grammar. Required for all; trivial specs produce short Modification Grammar sections, not absent ones.
Why memory routing as secondary index, not primary store. The dominant access pattern is "I'm modifying spec spc-N, give me spc-N's modification grammar" — that's a lookup the spec file already serves trivially. Memory routing earns its keep on the long-tail: "how has our modification grammar of dispatch evolved across the predecessor store's spc-1, spc-3, spc-7?" Cheap to add (principle-distiller already exists post-itd-36); worth it; not load-bearing for the common case. In-spec capture is the primary store. This is also why itd-36 is a builds_on edge, not a blocker: the capture + enforcement half (MG001-MG004, the Phase 0 discipline registration) ships independently of itd-36, and only the extraction-to-memory trigger waits on its substrate — the partial-ship fallback below is the designed behaviour, not a contingency.
What's In Scope
## Modification Grammarsection template carried by the native spec template in the Go binary (internal/core/...) with three sub-headings (Extends cleanly/Breaks the design/Why) plus theRippleaxis (vocabulary / surface / coupling deltas), one worked example per axis. Section header is fixed (parser depends on it).- Concreteness lint in the native intent lint with three codes:
MG001— section missing.MG002— sub-heading missing or empty.MG003— sub-heading present but contains no concrete reference (code block / file path / line ref).
- Semantic boilerplate detection via
intent-auditorRole 1's discipline-checking pass. New prompt-encoded test ("could this describe a different spec?"). Lint codeMG004— Role 1 boilerplate verdict.- Specific rejection criteria the prompt encodes: (a)
Extends cleanlyrejected if it doesn't name a concrete extension point with a constraint; (b)Breaks the designrejected if it doesn't name a specific failure mode; (c)Whyrejected if it's a list of cases without an underlying rule, OR if the rule could equally describe a different spec.
- Specific rejection criteria the prompt encodes: (a)
principle-distillerextraction trigger — at spec completion, the curator (per itd-36's role extension):- Writes append-only
spec_modification_grammar_<spec_id>.mdto.abcd/memory/withsource.class: spec_modification_grammar. - Updates curator-merged
modification_grammar_<domain>.mdwithsource.class: modification_grammar(compounding-curated).
- Writes append-only
- Recovery-humility paragraphs on
/abcd:disembarkand/abcd:embarksurfaces (≤4 sentences each). Disembark: lifeboat is the floor of recoverable theory, not theory itself. Embark: hunt the originating session before trusting the lifeboat blindly. Already landed in04-surfaces/02-disembark.mdand04-surfaces/03-embark.mdper Layer A brief edits. - Mental-model "Naurian gap" sub-section — added at
01-product/03-mental-model.md. Names the three Naur axes; identifies Modification as the genuinely new gap; cites Naur 1985. - Vocabulary-registration requirement (HARD) — every term introduced in
### Ripple > Vocabulary deltaMUST appear in the same spec in the registry that fits it, per the routing rule in02-constraints/04-naming.md: the canonical glossary for cross-cutting prose vocabulary, that file's reserved-vocabulary register for controlled enums. The intent lint is designed to block at plan-review with codeVR001(reserved; noSpecLinterimplementation exists yet, so registration is enforced by review today). - Karpathy & Naur citations in
research/related-work.md(Karpathy as pattern source for itd-36; Naur as philosophical citation for itd-37). Both inresearch/related-work.md. - Inheritance into every spec — every native spec plan-reviewed under abcd inherits this discipline's gates: spec must include
## Modification Grammar; concreteness lint runs at plan-review; Role 1 boilerplate detection runs at plan-review and ship time.
What's Out of Scope
- Naur's "theory layer" framing in mental-model — the mental-model file is for axes (brief / intents / specs), not components. Adding "the brief is itself a theory layer" conflates orientation with implementation, and the citation is a philosophical anchor that belongs in
research/related-work.md, not in the project's most-stable orientation file. This was held against in idea-2 R3 review. - Auto-classification of "trivial" specs that can skip the discipline — explicitly rejected. Trivial-self-exemption risk dominates; trivial specs produce short Modification Grammar sections (e.g., "this spec adds a config flag; modifications limited to renaming"), not absent ones.
- Full ADR-style decision documentation —
## Modification Grammaris the 1-page "what the theory of this spec is" so the next agent doesn't fly blind. Full ADRs (multi-page architectural decision records with stakeholders, alternatives evaluated, consequences) live at.abcd/development/decisions/adrs/and are not affected by this discipline. - Retroactive backfill of specs that ship before itd-37 lands — itd-36 + itd-37 ship together (per the contingent-pairing in idea-2 R5 review). If itd-36 + itd-37 ship first, all subsequent specs inherit the discipline. If itd-37 slips relative to itd-36, the partial-ship fallback (capture in spec + reviewer enforcement; extraction-to-memory deferred) covers the gap.
- Cross-intent modification grammar dependencies — each spec's modification grammar is independent. No "this spec's modification grammar inherits from itd-N" beyond the discipline's own application.
- Idea-3 standalone discipline (itd-38 system-impact) — explicitly absorbed as the
Rippleaxis (idea-3 R1 reviewer ruling: same retrieval key, same audience, same lifecycle as modification grammar; split was rhetorical not architectural). itd-38 ID released, not reserved.
Acceptance Criteria
BDD format, per itd-1 acceptance gates. These gates are checked by
intent-auditorRole 1 against every spec plan-reviewed under abcd.
- Given a spec without a
## Modification Grammarsection, when plan-review runs, then the intent lint emitsMG001and blocks promotion. - Given a spec with
## Modification Grammarbut missing one of the three required sub-headings (Extends cleanly/Breaks the design/Why), when plan-review runs, then the lint emitsMG002naming the missing sub-heading. - Given a spec where any of the three sub-headings is present but contains no concrete reference (no code block, no file path, no line ref), when plan-review runs, then the lint emits
MG003and points at the offending sub-heading. - Given a spec where
## Modification Grammarcontent could equally describe a different spec (boilerplate failure), whenintent-auditorRole 1 runs the discipline check, then the reviewer emitsMG004with the rejection reason ("strip-the-name test fails: this prose describes [generic concern] not [this spec's specifics]"). - Given a spec with
### Ripple > Vocabulary deltaintroducing a new term not registered in either registry named by02-constraints/04-naming.md, when plan-review runs, then the intent lint is designed to emitVR001and block promotion until the term is registered (reserved; not yet implemented — today this is a review-time check, not a lint gate). - Given a spec transitions to shipped, when
principle-distillerruns the extraction pass, then an append-only memory pagespec_modification_grammar_<spec_id>.mdis written to.abcd/memory/withsource.class: spec_modification_grammarAND a curator-merged pagemodification_grammar_<domain>.mdis updated withsource.class: modification_grammar. - Given the cost-discipline boundary (itd-37 is first expensive discipline; ~15-30 min capture per spec), when any spec proposes adding "modification grammar exemption for trivial specs", then the proposal is rejected — trivial-self-exemption invites loophole-driven bypass; trivial specs produce short Modification Grammar sections, not absent ones.
- Given the partial-ship fallback (itd-36 ships only
ingest/bare withoutask/lint, ORprinciple-distillerextraction trigger slips), when itd-37 lands, then capture (## Modification Grammarin a spec) and reviewer-Role-1 enforcement (MG001-MG004) survive independently; memory extraction (spec_modification_grammar_*andmodification_grammar_*pages) defers gracefully. - Given the brief's verification matrix at
06-delivery/02-verification-matrix.md, when itd-37 ships, then the matrix carries entries for: modification-grammar capture, boilerplate detection, extraction at spec completion, and vocabulary-registration enforcement. - Given Naur's 1985 paper as the philosophical citation, when a contributor reads
01-product/03-mental-model.md § The Naurian gap, then they find: the three axes (Mapping / Justification / Modification) named explicitly, the gap statement (Mapping + Justification already partially captured; Modification is the genuinely new piece), the Karpathy/Naur citation pointing atresearch/related-work.md, and the recovery-humility framing for disembark/embark.
Open Questions
- Discipline-set audit trigger — with itd-37 shipping, there are 3 disciplines (itd-1 + itd-5 + itd-37); under the user's deferred meta-discipline trigger threshold of ≥5. itd-36 is
kind: standalone(per the user's classification call on 2026-05-08), not counted as a discipline. Trigger doesn't fire yet; meta-discipline question stays dormant. Surfaces as a fresh idea if a new discipline lands OR contradiction is observed. - Lint code numbering collisions —
MG001-MG004(this discipline),MQ001-MQ002+MS001-MS002+ML001(itd-36),VR001(vocabulary-registration),SD001(bare-command-as-render discipline) all reserved post-2026-05-08. Verify against05-internals/06-lint.mdreservation table at promotion time. - principle-distiller overload — three roles (memory curator + per-spec extractor + per-domain curator) on one agent. Soft-cap risk per the agent-count discipline (15 agents, role extension preferred over agent splitting per itd-31 precedent). If coherence breaks, fork the curator role into a sibling agent. Logged in itd-37's risk register; not a current blocker.
- Recovery-humility wording length — disembark/embark paragraphs ≤4 sentences each (already landed in Layer A brief edits with closing imperative). Verify they don't grow into a wall of caveats over time; Role 2 cross-document audit should catch drift.
Audit Notes
Empty. Populated by intent-auditor Role 1 (single-document fidelity per itd-1) when this discipline is first audited. Like itd-1, this discipline is audited continuously via the rule-applies-to-every-spec semantics rather than via a planned→shipped transition. The reviewer's findings here record any spec that violated the discipline (e.g., shipped without ## Modification Grammar, or with boilerplate MG004 not caught at plan-review).
References
- Full assessment in a local working note (unmigrated), with 3-round review trail (chat
adversarial-naur-theory--0A4174); rename from "Theory transparency" to "Modification Grammar discipline" preserved in chat record. - Sibling assessment in a local working note (unmigrated); the
Rippleaxis on this discipline absorbs idea-3's per-spec-external concerns (chatidea-3-itd-38-adversaria-31A06A, MAJOR_RETHINK collapse). - Naur 1985 — "Programming as Theory Building", Microprocessing and Microprogramming 15(5):253-261; primary philosophical citation.
research/related-work.md § Naur 1985— full prior-art comparison.itd-1-acceptance-gates.md— companion discipline; this discipline's acceptance criteria conform to its Given-When-Then shape.itd-5-prompt-quality-additions.md— companion discipline; disciplines stack at three (itd-1 + itd-5 + itd-37).../shipped/itd-36-memory-unification.md— companion intent (standalone); ships alongside itd-37; provides the substrate forspec_modification_grammarandmodification_grammarpage classes.05-internals/07-memory.md— substrate spec for the curator agent's two-page-class extraction.02-constraints/04-naming.md— vocabulary-registration requirement (HARD) and bare-command-as-render discipline; both companion rules to this discipline'sRippleaxis.01-product/03-mental-model.md § The Naurian gap— the framing this discipline closes.04-surfaces/02-disembark.mdand04-surfaces/03-embark.md— recovery-humility paragraphs (Layer A brief edits).
Frontmatter
| id | itd-37 |
|---|---|
| type | intent |
| lifecycle | disciplines |
| kind | discipline |
| severity | major |
.abcd/development/intents/disciplines/itd-37-modification-grammar.md
open on GitHub ↗ · commit history ↗
References2
Referenced by10
- adr-2Three intent kinds (standalone / bundle-member / discipline)related
- iss-2610262032580449itd-37 extends principle-distiller into a curator that writes memory pages from specs when they complete; disembark says its lifeboat agents, principle-distiller among them, read the packed lifeboat's filesrelated
- iss-2610262034090653itd-37 has principle-distiller, as itd-36's role-extended curator, extract each spec's Modification Grammar into memory pages at spec completion; the library surface says that curator role is not builtrelated
- iss-2610262037246775itd-37 has an agent (principle-distiller) write memory pages into the repository's .abcd/memory/; 37-memory says agents write only the machine layer.related
- iss-2610262038495354itd-37 says Role 1 boilerplate detection runs at plan-review and ship time; 01-agents says the auditor's modification-grammar output is deferred and in no prompt or lintrelated
- iss-2610262038501901itd-37 defines the concreteness lint as numbered codes MG001 to MG003; 06-lint says the engine has no numbered codesrelated
- iss-2610262038511722itd-37 puts append-only pages into .abcd/memory/; universal pattern § 8 gives each namespace one lifecycle class and lists .abcd/memory/ as compounding-curatedrelated
- iss-2610262040508345itd-37's discipline says every spec carries a Modification Grammar section; the verification matrix says no committed spec carries one and nothing checks for it.related
- iss-2610262043232891itd-34 routes a standalone intent to a flow-next spec, while itd-37 places the spec template in abcd's native Go binaryrelated
- iss-2610262043436609itd-37 gives Role 1 the job of spotting spec boilerplate at plan-review; itd-48 defines Role 1 as grading a shipped intent's criteria against delivered realityrelated
mentions16
- dcn-26070800000000142026-07-08 — itd-37's itd-36 edge downgraded blocked_by → builds_on: the
- dcn-26080200000000082026-08-02 — iss-40: one canonical glossary, chosen as a ROUTING rule rather than a migration. `.abcd/development/brief/glossary/` keeps the name "glossary" and 04-naming.md stops claiming it; what stays behind in 04-naming.md is its ~60-row Reserved-vocabulary table, unchanged, because those rows are closed enums and spec-pinned reserved names (`dormant`, `task_classes` members, `index.json` field names) and the glossary schema's `aliases`/`forbidden_synonyms` fields mean nothing for an enum value. Folding them into term files would have invented scope and misused the schema; the defect was the false self-identification, and only that is retired. `VR001` keeps its reserved status and its two registration targets — the word "glossary" is removed from its descriptions across the brief and itd-37 so the term resolves to one place, but nothing about what the reserved lint would check is changed, since no Go code implements it. The index is made derived on the brief↔lifeboat-mapping pattern (`internal/core/glossary` renders, a test in the same package gates the committed README against it) rather than by a new schema-validation engine, which the README had been promising through a JSON-schema file and a `abcd lint terminology` verb that do not exist. Three limits are recorded rather than papered over: the drift gate checks the index against the term files, NOT each term file against the field tables, so the frontmatter shape stays a review responsibility; the banlist entry `names/record/glossary-self-identification` reaches only the docs-lint roots (`docs/`, root `README.md`), so it guards the published surface, not the brief where the retired phrase lived — adding `.abcd/development/brief` as a lint root surfaces 75 pre-existing blockers and is its own piece of work; and `05-internals/06-lint.md`'s `TM003`–`TM011`/H1 rows still claim `terminology.schema.json`-backed schema validation "Delivered" that no Go code implements — the same phantom-enforcement-claim class this change retires for the glossary README's validation section, but for TM003+ it sits outside iss-40's self-identification scope and inside iss-37 (phantom-enforcement-claims), stopped at round 13 pending maintainer disposition; left untouched here rather than pre-empting that disposition.
- iss-18phase-order violation: Phase 0 scopes itd-37 whose declared blocker itd-36 is Phase 2; split the hard-on-half edge (capture half vs memory-routing half) or reschedule
- iss-351the three-disciplines roster itd-1 itd-5 itd-37 is hand-enumerated at six sites while intents/disciplines/ holds six active disciplines, dropping itd-79 itd-81 itd-84 from the mental model, scope, roadmap dashboard and phase-0 acceptance
- iss-352three current-state records cite ADRs at development/research/adr/, a path that does not exist and a layout adr-30 explicitly rejected; all three are backticked code spans links_resolve never checks
- iss-390the pre-decided promotion of examples-use-reserved-identifiers to a discipline-kind intent never happened — the iss-154 lint shipped, the principles README contract says a mechanical gate promotes the principle, and no discipline intent exists
- iss-2609261536147903Planned intents and disciplines still cite specs of the retired predecessor store unqualified, and such an id at or below spc-70 resolves to a live spec on another subject (spc-12, for one, is live as the disembark grounding spec): itd-48, itd-50 and itd-53 name spc-12, spc-28, spc-29, spc-31, spc-33, spc-43 and spc-52 for the fidelity reviewer, lifecycle hook and cleanup work (which of these are predecessor ids is itself the reading this record owes); itd-24 names spc-66 as the phase-audit receipt; itd-1 and itd-37 name spc-12 as the manual reviewer. The specs charter (Two spc-N Namespaces) rules that every predecessor citation carries the '(predecessor store)' qualifier; iss-239 applied it to the draft corpus only. Each site needs a reading to tell a predecessor citation from a live one, which is why the sweep was not folded into iss-239.
- iss-261025221523227603-evidence/04-tradeoffs.md:41,49,57 cite .abcd/work/idea-assessments/*.md as sources. The directory does not exist (itd-37:109 calls them unmigrated local notes).
- iss-2610262030459672The mental model says principle-distiller extracts each spec's Modification Grammar into memory at spec completion; the library chapter says that extraction is not built
- itd-5Every Agent Prompt Carries Its Version, Earns Its Lock, And Survives Injection
- itd-31The Brief and Every Intent Stay Consistent — Or Abcd Tells You Why They Don't
- itd-48`intent-fidelity-reviewer` Gains Its Cross-Doc And Kind-Classification Roles
- itd-62abcd Routes The Invisible Risks An Amateur Cannot See To A Real, Fail-Closed Gate That Wraps A Trusted Scanner
- spc-3lifeboat-coverage-experiment
- spc-7abcd-intent-quoted-text-create-symmetric
- spc-12disembark-grounds-a-lifeboat-s-open-questions-on-a-repo-s-to