Skip to content

rfc implementation

Thomas Mangin edited this page Jul 25, 2026 · 5 revisions

Pre-Alpha. This page describes behavior that may change.

Ze implements a lot of RFCs. Implementing an RFC in Ze is not a matter of "read the RFC and write the code". It is a matter of tracking which RFCs the project depends on, recording what has been implemented and what has not, and making sure the implementation stays aligned with the RFC text over time. This page covers how that process works.

The heart of the process is a machine-enforced gate. Every RFC 2119 MUST-level requirement of an enrolled RFC must be either proven by tests or explicitly annotated with a reason; make ze-rfc-check fails the build otherwise. As of this writing 166 documents are enrolled (163 RFCs and 3 drafts), covering 2720 gated MUST-level requirements across 173 summaries, with none outstanding. The gate runs as part of make ze-verify, so an implementation cannot quietly drift away from the RFC text without a red build.

The canonical rule file is ai/rules/rfc-compliance.md in the repo, and the enrolment/gate mechanics live in ai/skills/ze-rfc.md. This page summarises them.

Where RFCs live

RFCs tracked by Ze live under main/rfc/ in the repo.

main/rfc/
├── README.md           # Human index of core BGP RFCs
├── enrolled.txt        # The gate's scope: RFCs whose MUSTs are machine-enforced
├── short/              # Per-RFC requirement summaries (each MUST has a stable id)
├── drafts/             # Draft RFC tracking
├── full/               # Full RFC text references
├── audit/              # Letter-and-spirit audit verdicts per requirement
└── ...

The short extracts are compressed versions of the RFC sections that the code actually depends on, so cross-checking a claim against the RFC does not require re-reading the full document. Each MUST-level line in rfc/short/<rfc>.md carries a permanent requirement id of the form RFC<n>-<section>-<ordinal> (for example RFC7606-7.1-1). That id is the contract a test binds to.

rfc/enrolled.txt is the scope of the enforced gate: one row per document, and the file grows only. Un-enrolling an RFC fails the gate, so an obligation that was once proven cannot quietly stop being proven. As of this writing 163 RFCs and 3 drafts are enrolled.

The public, plain-English status ledger is separate: docs/features/rfc-status.md lists every RFC Ze implements, partially implements, or intentionally does not, with the source anchors and the named gaps.

The implementation process

Every RFC implementation in Ze follows the same five steps.

  1. Spec. Before any code is written, the maintainer drafts a spec under plan/ that names the RFC, lists the sections being implemented, and defines the acceptance criteria. The spec explicitly calls out what is out of scope. Specs are written from plan/TEMPLATE.md.

  2. Short extract. If the RFC has load-bearing sections that the code will reference (wire formats, validation rules, state machine transitions), the sections are extracted into rfc/short/<rfc>.md. The extract is a compression, not a summary: it preserves the exact text of the parts that matter.

  3. TDD implementation, with tagged tests. The tests come first, and every test that proves a MUST-level obligation is bound to that obligation by a tag: // RFC requirement: RFC7606-7.1-1 positive (and a matching negative). Binding the test to the requirement id is what lets the gate prove the link exists and catch a later regression.

  4. Code. The implementation goes in the appropriate component. Every non-trivial decision cites the RFC section in the code comment: // RFC 4271 §9.1.2.2: route selection and so on. This is what lets reviewers verify the code against the RFC without reading both cover to cover.

  5. Enrol in rfc/enrolled.txt. Once the tests exist, the RFC is added to rfc/enrolled.txt so make ze-rfc-check starts enforcing it. Writing a summary does not enrol an RFC; enrolment is a deliberate, separate step taken only once every MUST is proven or annotated. The file grows only: an obligation that was once proven cannot quietly stop being proven.

The requirement gate

The gate, make ze-rfc-check, is the mechanism that keeps an implementation honest over time. For every RFC listed in rfc/enrolled.txt, it requires that each MUST-level requirement in rfc/short/<rfc>.md is one of:

  • Proven both ways. A positive AND a negative test, each tagged with the requirement id. Both polarities are required because a one-sided test passes on a blanket accept or a blanket reject.
  • Annotated with a reason. {gap: why; ref} for a deliberate divergence, {not-applicable: why} for an obligation Ze cannot play (for example a role it never takes), or {single-polarity: positive|negative; why} when a requirement is genuinely testable only one way. A bare annotation is rejected; every one carries its reason.

The gate runs inside make ze-verify, so a change that breaks a proven obligation, or an enrolled RFC that loses a required test, fails the build.

The four ratchets

The gate reads the working tree to judge coverage, and a tree cannot tell "never proven" from "stopped being proven". Four ratchets compare against HEAD so coverage can only go up:

Ratchet Fires when
Enrolment is monotonic An RFC whose MUSTs were gated stops being gated.
Proof is monotonic A requirement loses a polarity it had at HEAD. Annotating it {gap} is not an escape: that is the move being blocked.
Requirements do not vanish A requirement id of an enrolled RFC disappears from its summary.
Adding an RFC adds checking A summary that is new since HEAD declares gated MUSTs but is not enrolled, fails to parse, or captures nothing while the full text has MUST-level keywords.

The third exists because deleting a checklist line would otherwise be the cheapest route from red to green, cheaper than {gap}, which costs a public disclosure row. That would pressure contributors to hide obligations rather than declare them. Correcting a misquote is still allowed: edit the text under the same id.

What none of this catches is a tagged test whose assertions are weakened in place while it keeps its tag. That is what the audit below is for.

Two companion tools sit alongside it:

  • ai/RFC-REQUIREMENTS.md is the generated ledger of requirement to enforcing test, and the tracked backlog: un-enrolled RFCs are listed there marked "not enrolled", so the remainder is visible, not hidden.
  • /ze-rfc-audit reads the RFC text and each tagged test and judges whether the test would actually fail if the code stopped complying. The gate proves a link exists; the audit judges whether the link is meaningful, and make ze-rfc-check re-stales a verdict when the requirement text or a tagged test changes.

A tagged test is the requirement: once a test carries an RFC requirement: tag, you fix the code to pass, never the test. Changing a tagged test needs explicit recorded approval, and a hook blocks the edit otherwise.

What "complete" means

Enrolment is the closest thing Ze has to a binary "complete": an enrolled RFC has every MUST-level obligation either proven or reasoned. That is a stronger and more honest bar than "we wrote the code", because the divergences are named in the summary and surfaced in the public ledger rather than left implicit.

The plain-English status is a separate, coarser view. docs/features/rfc-status.md records each RFC as Supported, Experimental, Partial, Unsupported, or Future, with the named gaps. A Partial there often means "enrolled, with the specific MUSTs it does not meet annotated as {gap}", not "untested".

Deviations from RFCs

Ze deviates from RFCs in a small number of cases, and every deviation is documented in docs/exabgp/exabgp-differences.md or in the relevant in-tree architecture doc. Two examples.

Attribute ordering in UPDATE messages. The RFC does not mandate an ordering; Ze adds attributes in RFC 4271 section 5 description order, then optional attributes. The resulting wire bytes differ from ExaBGP (which sorts by type code) but both are compliant.

Neighbor qualifier syntax for multi-session targeting. ExaBGP supports per-session targeting through qualifiers on the neighbor keyword. Ze does not: commands apply to every session matching the peer IP. This is an API deviation, not a protocol deviation, but it is documented for the same reason.

Deviations that are not documented are bugs.

Cross-checking an implementation against an RFC

When you need to verify that a piece of Ze code matches what the RFC says, the process is:

  1. Find the short extract under rfc/short/<rfc>.md.
  2. Cross-reference with the code comments that cite the section.
  3. Read the tests that target the section.
  4. If anything is missing or unclear, read the full RFC section.

The short extract plus the code comments plus the tests should be enough for most reviews. The full RFC is a fallback.

When a new RFC appears

Step zero of implementing a new RFC in Ze is to write its requirement summary under rfc/short/<rfc>.md, giving every MUST-level line a permanent id, before any spec is written. This makes the RFC's obligations concrete and forces the question "is this RFC actually worth implementing in Ze" to be answered against a real list rather than a vibe. Until the tests exist the RFC stays un-enrolled, and appears in ai/RFC-REQUIREMENTS.md marked "not enrolled": tracked as backlog, not silently dropped.

Extraction completeness

The gate can only check requirements a summary actually lists, so an obligation that was never extracted is invisible to it. Enrolling a summary therefore requires a completeness pass first, and two signals matter most:

  • A {not-applicable} whose reason is "Ze has no X at all." That admission is often itself the violation of a separate MUST requiring X to exist. RFC 4271 section 5.1.4 requires a mechanism that allows MULTI_EXIT_DISC to be removed; that MUST was unextracted, and two other requirements cited its absence as their own exemption.
  • A section whose siblings are enumerated but one clause is not. RFC 8666 section 5's "MUST be ignored on reception" was omitted while sections 6, 7.1 and 7.2 each carried it. That is an enumeration hole, not a style choice.

The gate's silence is not conformance. An unextracted obligation is still an obligation.

The /ze-rfc and /ze-rfc-audit commands

Claude Code has two project-specific slash commands for this workflow. /ze-rfc generates a requirement summary from an RFC and allocates the permanent requirement ids; it is a planning aid, not a code generator. /ze-rfc-audit performs the letter-and-spirit audit described above, reading the RFC and the tagged tests to judge whether the tests really enforce the requirement.

See also

  • Contributing for the spec-first contribution workflow.
  • Coding standards for the TDD rule.
  • Claude Code for the slash commands.
  • main/rfc/enrolled.txt, main/ai/RFC-REQUIREMENTS.md, and main/ai/rules/rfc-compliance.md for the canonical gate and ledger.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally