ACCEPTED
How to write a spec that is immediately useful to both human developers and AI agents. Readability at a glance is paramount — a contributor should understand what a spec requires within 30 seconds of opening it.
Specs serve two audiences simultaneously:
- Human developers who scan for rules while implementing or reviewing code
- AI agents who load specs into limited context windows and need unambiguous instructions
A spec that requires careful reading to extract the rules is a spec that will be ignored or misapplied. Every spec should be optimized for fast, correct comprehension.
Every spec MUST have these sections in this order:
| Section | Purpose | Length guidance |
|---|---|---|
# SPEC_NNNN: Title |
Descriptive title in 3-8 words | — |
## Status |
ACCEPTED, DRAFT, or REFERENCE | 1 line |
## Summary |
One sentence: what this spec requires | 1-2 sentences max |
## Specification |
The actual rules | As needed |
Every spec SHOULD have these sections when applicable:
| Section | Purpose |
|---|---|
## Motivation |
Why this spec exists (keep brief — 3-5 bullets max) |
## Rationale |
Why alternatives were rejected (only if non-obvious) |
## References |
Links to MLS sections, related specs, external docs |
Default shape — table of rules: every multi-rule section MUST use a
table whose columns are Rule | Owner/Where | Brief Justification. Tables
scan in 2 seconds; prose scans in 30. A figure (ASCII tier diagram, IR
pipeline, etc.) belongs immediately above the table when the structure is
what the rule is about.
REQUIRED — rules table:
| Rule | Owner | Why |
|---|---|---|
| Public IR fields use `IndexMap` | `rumoca-ir-*` crates | Deterministic serialization |
| Generated code embeds source-equation comments | codegen templates | Audit trail back to MLS source |REQUIRED — allow/deny lists are acceptable for short rule sets that
don't need a Where column:
**REQUIRED:**
- All IR fields use IndexMap for deterministic iteration
- Generated code includes source-equation comments
**PROHIBITED:**
- HashMap as a public field on any IR type
- Span::DUMMY without a justifying commentPROHIBITED — narrative prose for rules:
It is generally recommended that developers should consider using IndexMap
when they need deterministic iteration, although HashMap may sometimes be
appropriate in certain circumstances.Justification cells in tables MUST stay under 15 words. If the
reasoning needs more, put it in a **Why:** block below the table. Long
prose inside table cells defeats the purpose of the table.
Specs MUST show the actual types and signatures from the codebase, not idealized pseudocode. Include the source file location.
REQUIRED:
Located in `rumoca-ir-dae/src/lib.rs`:
\```rust
pub struct Dae {
pub states: IndexMap<VarName, Variable>,
// ...
}
\```PROHIBITED:
\```rust
// Conceptual design (not actual code)
pub struct Dae {
pub vars: Vars,
pub eqs: Eqs,
}
\```If the code doesn't match the spec, either update the spec or file an issue. Aspirational designs belong in DRAFT specs, clearly labeled.
Active spec count is capped. The whole rule set must fit in a single human reading session and a small number of AI context loads. If contributors can't hold the set of rules in mind, the rules don't get applied.
| Status | Cap | Rationale |
|---|---|---|
| ACCEPTED + DRAFT | 15 specs total | ~3000 lines of normative content at cap; fits 2-3 AI context loads |
| REFERENCE | uncapped | Lookup catalogs (e.g. SPEC_0022) are not rules; size doesn't burden rule comprehension |
Adding a 16th ACCEPTED/DRAFT spec requires either:
- merging into an existing spec, or
- moving inactive future-work proposals to
archive/deferred/, or - deleting inactive proposals that are not worth preserving.
Enforced by crates/rumoca/tests/spec_budget_test.rs::test_active_spec_count_under_cap.
ACCEPTED design specs MUST fit a reader's working memory. Long specs get skimmed; skimmed specs get misapplied.
| Spec size | Word budget | Line budget | Assessment |
|---|---|---|---|
| Ideal | < 500 words | < 80 lines | Fits in a single context load |
| Good | 500–1000 words | 80–150 lines | One focused topic |
| Acceptable | 1000–1800 words | 150–250 lines | Needs a clear section index |
| Too long | > 1800 words | > 250 lines | Split, trim, or add an index |
Hard cap: an ACCEPTED design spec MUST NOT exceed 2500 words / 350 lines
without an explicit REFERENCE status. Going over requires moving the spec
to REFERENCE (lookup catalogs only, like SPEC_0022) or splitting it into
multiple ACCEPTED specs.
What to cut:
- Implementation code that duplicates what's in the source (link to the file instead)
- Rationale for decisions that are obvious or uncontested
- Multiple examples showing the same pattern
- Aspirational features (move to DRAFT specs or issues)
- Long prose explaining a rule that already fits in a table row
A spec that doesn't match the code is worse than no spec — it actively misleads contributors.
REQUIRED:
- Specs MUST reflect the current codebase, not a planned future state
- If code structures change, the spec MUST be updated in the same PR
- If a spec is paused future work, move it to
archive/deferred/ - If a spec is no longer implemented and not future work, delete it
PROHIBITED:
- ACCEPTED specs that describe unimplemented features
- Code examples using types or functions that don't exist
- Stale references to deleted or renamed specs
Every spec follows this lifecycle:
PROPOSED → ACCEPTED (majority vote)
→ REJECTED (majority vote) → delete
→ DRAFT (needs more work before vote)
DRAFT → DEFERRED (future work that maintainers want to preserve)
ACCEPTED → delete (if removed, rejected, or replaced)
REFERENCE (no vote needed — lookup tables, catalogs)
| Status | Meaning |
|---|---|
| PROPOSED | New spec awaiting maintainer vote |
| ACCEPTED | Implemented and enforced — code MUST follow this spec |
| REJECTED | Voted down by maintainers; not retained in-tree |
| DRAFT | Work in progress — not yet ready for a vote, may describe unimplemented features |
| DEFERRED | Non-active future work in archive/deferred/; not review-gating |
| REFERENCE | Lookup table — not a set of rules (e.g., MLS contract catalog), no vote needed |
- Author opens a PR with the new spec file (status: PROPOSED) and a README table entry
- Maintainers review the spec in the PR — discussion happens in PR comments
- Vote: each maintainer approves or requests changes
- Majority of maintainers approves → status changes to ACCEPTED, PR merges
- Majority rejects → the spec is removed before merge; the PR discussion records the rejection rationale
A spec may be sent back to DRAFT if maintainers agree it needs more work before a vote.
Changes to ACCEPTED specs follow the same process — open a PR, maintainers vote. Trivial fixes (typos, line count updates, syncing code examples to match refactored code) do not require a vote.
A contributor reading only the README table should know whether a spec is relevant to their task. The title and summary must be self-explanatory without reading the full spec.
Good titles: "Lean DAE (No Derived Data)", "Case-Sensitive Identifiers", "Phase-Local Error Types"
Bad titles: "Expression Handling", "Compiler Design", "Data Structures"
- Reference only active specs
- Deferred specs may reference other deferred specs; active specs should mention deferred specs only when explicitly labeling them as non-active future work
- Use relative links in the README:
[SPEC_0001](SPEC_0001_DEFID.md) - When specs are complementary, state the relationship clearly instead of duplicating the same rule in both files
The spec index (spec/README.md) MUST include:
| Column | Purpose |
|---|---|
| Spec | Link to the spec file |
| Title | Descriptive title |
| Domain | Topic tag for filtering (IR, phase, architecture, convention, etc.) |
| Lines | Approximate line count for context-window budgeting |
| Status | ACCEPTED, DRAFT, or REFERENCE |
Before marking a spec as ACCEPTED:
- Summary is one sentence
- Multi-rule sections use a table (Rule | Owner/Where | Why), not prose
- All code examples match actual codebase
- Rules use REQUIRED/PROHIBITED framing where possible
- Under 1800 words / 250 lines (hard cap: 2500 words / 350 lines)
- README table entry includes Domain and Lines
- No references to deleted specs; deferred references are marked as non-active
- Status matches reality (ACCEPTED = implemented)