Files
deepseek-harness/docs/rfc/implemented/process/2026-07-05-uniform-rfc-format.md
Tianyi Cui e6fad266a6 docs(rfc): define and enforce a uniform RFC format; adopt it across the corpus
Define the in-file RFC contract in docs/rfc/README.md § The file format:
the header block (`# RFC: <title>` plus a dateless Status enum
cross-checked against the lifecycle folder), the per-lifecycle body
skeleton (a Problem opener everywhere; Proposal/Alternatives considered/
Acceptance criteria/Risks in proposed/; present-tense Decision/
Consequences with proposal-era headings banned in implemented/; the
frozen proposal shape in rejected/), and a mandatory Alternatives
considered section with a date-fenced grandfather comment for pre-format
RFCs whose alternatives are not reconstructible from the record.

Enforce it with a new doc-sync gate, scripts/verify-rfc-format.ts, and
normalize all 112 RFCs to it: ~15 Status-line spellings collapse to the
enum, 29 Context openers become Problem, the 39 legacy-format XXX debt
markers are resolved and banned from reappearing, proposal-era sections
in implemented RFCs are rewritten to shipped reality (including the
web/fs/subagent seam RFCs' migration plans and test checklists, closing
the doc-tiers deferred-work item on the web seam), every RFC gains an
Alternatives considered section or the grandfather comment, and the
bilingual pair is re-mirrored and re-recorded.

Move the generated index tables out of README.md into a fully generated
docs/rfc/INDEX.md — gen-rfc-index now writes the whole file, and
verify-rfc-classification checks its freshness and rejects index-shaped
rows in the curated README — which makes room for the format contract to
live in the README front door instead of a separate FORMAT.md.

The decision record, and the first RFC written in the new format, is
docs/rfc/implemented/process/2026-07-05-uniform-rfc-format.md.
2026-07-05 22:58:25 +08:00

5.2 KiB

RFC: One gated in-file format for RFCs

Status: implemented

Problem

The tree's layout is uniform — the classification scheme path-encodes lifecycle and class and gates both — but the file insides never were. The corpus the format decision faced had two H1 spellings; some fifteen Status: line spellings, from bare enums through dated parentheticals duplicating what the filename and git already carry, to four files with no status at all; two body genres side by side (ADR-style Context/Decision/Consequences beside proposal-style Problem/Proposal/Risks), so every new RFC guessed its shape from whichever neighbor its author opened; thirty-nine files carrying a debt comment that flagged them as "legacy ADR/RFC body format" awaiting a unified template that was never actually defined; and over twenty implemented RFCs still carrying the proposal-era headings (Acceptance criteria, Plan, Migration plan) that the documentation standard's slop checklist outlaws for implemented/ — outlawed, but enforced by nothing, so the proposed/ → implemented/ move could silently skip the rewrite implemented/AGENTS.md requires.

Decision

README.md § The file format is the in-file contract — the header block (# RFC: <title> plus a dateless, folder-agreeing Status: enum whose only content is the rejection reason), the per-lifecycle body skeleton (Problem opener everywhere; Proposal/Acceptance criteria/Risks in proposed/; present-tense Decision/Consequences with proposal-era headings banned in implemented/; frozen proposal shape in rejected/), a mandatory Alternatives considered section, and the canonical section vocabulary between which bespoke technical sections stay free-form. pnpm run verify-rfc-format (scripts/verify-rfc-format.ts) enforces every mechanical clause as part of doc-sync, so a lifecycle move that skips its rewrite now fails CI instead of review memory.

The whole corpus was normalized in the same change that defined the format — the pre-release stance: no transition period, no dual-format tolerance. The one grandfather is content, not format: alternatives are recorded, never invented, so a pre-format RFC whose alternatives are not reconstructible from the record carries the exact rfc-format: alternatives-not-recorded comment, which the gate accepts only for files dated before this RFC.

Alternatives considered

  • A full rigid template (one fixed section sequence per lifecycle, every RFC restructured to fit) — rejected: the big design RFCs carry eight to fifteen bespoke technical sections (package topology, wire contracts, schemas) that are load-bearing content, not drift; a rigid sequence would force destructive rewrites now and template-fighting forever.
  • Header-only normalization (H1 and Status, bodies untouched) — rejected: the debt markers flagged the body genre split, and leaving Context/Decision beside Problem/Proposal indefinitely resolves nothing.
  • No Status line (the folder already is the status; the four newest pre-format RFCs omitted the line) — rejected in favor of keeping a self-describing file: the drift risk that motivated dropping it is neutralized by gating the line against the folder instead.
  • Dated status (Status: implemented (accepted YYYY-MM-DD)) — rejected: the acceptance date is narrated history the writing rules keep out of docs; the filename carries first-proposed, git carries the rest, and the gate could check a date's format but never its truth.
  • A bare # <title> H1 — rejected: the RFC: prefix is the corpus-majority form and self-describes the genre when a file is read outside its tree; the index generator strips it, so index rows are identical either way.
  • ## What we give up as the implemented closer (the README's own phrase for what an RFC records) — rejected: it names only costs, and an honest consequences section records what the trade-off bought as well.
  • Convention without a gate (write the contract down, enforce by review) — rejected: the slop checklist already outlawed spec-speak in implemented/ by convention, and over twenty files show what convention alone achieves here.
  • A standalone FORMAT.md contract file — the first landed home; folded into README.md once the generated index moved out to INDEX.md: with the tables gone the README regained the room, and one front door carrying layout, classification, and format beats splitting the contract across two files.

Consequences

Every RFC now costs slightly more structure, and the mandatory Alternatives considered section is deliberate friction: a decision recorded without what it beat invites the re-litigation RFCs exist to prevent. Pre-format RFCs whose alternatives were not reconstructible carry the grandfather comment permanently — an honest gap on the record rather than fabricated rationale. doc-sync gains one gate, and moving an RFC between lifecycle folders is now real work at move time (the body rewrite the move always owed) instead of deferred cleanup nothing tracked. The thirty-nine debt markers are gone, resolved by the template they were waiting for.