Skip to content

RFC-5: an RFC process, RFCs as files, and the four existing RFCs migrated - #127

Open
maxinelevesque wants to merge 7 commits into
mainfrom
rfc/process-and-migration
Open

RFC-5: an RFC process, RFCs as files, and the four existing RFCs migrated#127
maxinelevesque wants to merge 7 commits into
mainfrom
rfc/process-and-migration

Conversation

@maxinelevesque

@maxinelevesque maxinelevesque commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Proposals live in the issue tracker, documents live in .design/, and requirements live in the registry — and none of the three references the others. An issue is a report: one author, one body, open or closed. So an amendment becomes a comment, and the document a reader sees first is its stalest version.

This makes an RFC a file, migrates the four that exist, and ships the gate.

The proposal — RFC-5

---
rfc: 5
title: An RFC process, and RFCs as files
status: draft | accepted | rejected | superseded
supersedes: []
introduces: [REQ-RFC-FRONTMATTER, REQ-RFC-GATE, REQ-RFC-REGISTRY-LINK]
---
  • One PR per RFC. Review is line-by-line on the document.
  • Always merge, never close. A rejected RFC merges with status: rejected, so the argument for not doing something survives — the expensive thing to reconstruct later.
  • introduces: links an RFC to the registry, so implementation status is derived rather than declared. There is deliberately no implemented status; a hand-maintained one would drift from the registry, which is the failure the registry exists to prevent.
  • Versions are derived from git. One commit per edit, cited as RFC-4 r3 @ a1b2c3d, where the revision is the commit count on that file. No version: field, for the same reason.
  • A draft's number is provisional; merging makes it canonical. No extra field says so — draft already means it. That way an RFC is citable while it is being argued about, and the slot can still move at merge.

The migration, and a renumber

#17 is the reason this is worth doing. It proposed the canonical REQ registry, it shipped, and it was never numbered — so an RFC that built the requirement-tracking system is itself untracked, in no sequence, with nothing linking it to what it created.

It was filed second, so the sequence is renumbered chronologically:

RFC issue was is
Thermite 2 #2 RFC-1 RFC-1
Canonical REQ registry #17 unnumbered RFC-2
The certification surface #119 RFC-2 RFC-3
Versioning #120 RFC-3 RFC-4

Affordable exactly once, and only now: nothing in the tree references RFC-2 or RFC-3, and no issue or PR body does either. From here a number is identity — never reused, never reassigned.

Bodies are copied verbatim, front matter added above them; each round-trip was checked against the issue rather than eyeballed. Comments stay in the issue, which discussion: links, because the file is the document and the issue is the discussion. #119 and #120 stay open — their conversations are live, and nobody should have to move a thread mid-argument.

One thing this found

req-registry.py parses the registry with tomllib, standard library from Python 3.11. On an older interpreter it reports

REQ registry inconclusive: tomllib is unavailable (Python < 3.11)

and exits 3 — it fails rather than passes, which is right. What it does not do is say anything about the registry, so the environment error stands in front of whatever the real verdict was. Here the verdict was a fault of mine: three requirements added without regenerating the status view they appear in. It surfaced only once the gate ran on an interpreter that could parse the file.

So rfc-check.py, req-registry.py and reqs carry a PEP 723 header declaring their floor, and uv run tooling/reqs check returns a verdict rather than an excuse.

Three design-doc pins are refreshed: .design/tooling/req-registry.md because this changes files it governs, and .design/build/bootable-multicore-kernel.md plus .design/stage4-epr-reconstruction.md because ci.yml gains one step and both govern it. Neither pipeline they describe is otherwise affected.

Reviewing

Self-hosting on purpose: if the process is wrong, the thing demonstrating it is the thing being reviewed.

Proposals live in the issue tracker, documents live in `.design/`, and
requirements live in the registry, and none of the three references the others.
An issue is a report — one author, one body, open or closed — so an amendment
becomes a comment and the document a reader sees first is its stalest version.

This makes an RFC a file with front matter, one PR per RFC, always merged so a
rejection keeps its reasoning, and `introduces:` linking an RFC to the
requirements it creates. Implementation status is then derived from the registry
rather than declared, and a version is derived from git rather than written down.

Ships with its gate (`tooling/rfc-check.py`, wired into CI) and its own three
requirements, so the proposal is checked by the mechanism it proposes.
Body copied verbatim; front matter added above it. Comments stay in the issue,
which `discussion:` links, because the file is the document and the issue is the
discussion.
Body copied verbatim; front matter added above it. Comments stay in the issue,
which `discussion:` links, because the file is the document and the issue is the
discussion.
Body copied verbatim; front matter added above it. Comments stay in the issue,
which `discussion:` links, because the file is the document and the issue is the
discussion.
Body copied verbatim; front matter added above it. Comments stay in the issue,
which `discussion:` links, because the file is the document and the issue is the
discussion.
`rfc-check.py`, `req-registry.py` and `reqs` carry a PEP 723 header so `uv run`
fetches a matching interpreter instead of inheriting whatever `python3` is on
PATH.

`req-registry.py` parses the registry with `tomllib`, standard library from 3.11.
On an older interpreter it reports "REQ registry inconclusive" and exits 3 — it
fails rather than passes, which is right — but the environment error stands in
front of the verdict. In this branch the verdict was a fault of mine: three
requirements added to the registry without regenerating the status view they
appear in. It surfaced only once the gate ran on an interpreter that could parse
the file.

`.design/reqs/status.md` is regenerated here, and three design-doc pins are
refreshed: `.design/tooling/req-registry.md` because this changes files it
governs, and `.design/build/bootable-multicore-kernel.md` plus
`.design/stage4-epr-reconstruction.md` because `ci.yml` gains one step and both
govern it. Neither pipeline they describe is otherwise affected.
@maxinelevesque
maxinelevesque force-pushed the rfc/process-and-migration branch from 56c53aa to a649d40 Compare August 6, 2026 07:48
@maxinelevesque

Copy link
Copy Markdown
Collaborator Author

Correction to the original description, now edited in: I wrote that req-registry.py "exits 0" on a missing tomllib. It exits 3. My reading came from … | tail -8; echo $?, which reports tail's status rather than the gate's.

The gates do not silently pass, and the claim that one of them did was wrong. What is true is narrower: an inconclusive result is not actionable, and the environment error stood in front of a real fault in this branch — a stale generated status view — until the gate ran on an interpreter that could parse the registry. The PEP 723 headers are justified by that, not by a silent-pass bug.

The branch is force-pushed with the claim corrected in the RFC, the design doc, and the commit message.

Fifteen tests under `tooling/tests/`, where CI already discovers them. Each
asserts on the reported message rather than only the exit code: a gate that fails
for the wrong reason sends the next reader to the wrong place, and an
exit-code-only test cannot tell those apart.

They cover the front-matter reader, the status enum including the rejection of
`implemented`, filename and number agreement, the registry link in both
directions, and `supersedes` resolution.

Three of them pin the provisional-number rule, which is the part most likely to
be mis-implemented later: two drafts may share a number and the gate says so
without failing, a draft may not take a canonical one, and two canonical RFCs may
never collide. One more derives a revision from real git history rather than a
declared field, which is the property the version scheme rests on.

`REQ-RFC-GATE` gains test evidence, which is the kind the registry schema prefers
for a shipped requirement, and `.design/tooling/req-registry.md` is re-pinned
because its governed files changed again.
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