RFC frontmatter — `phases:` array
rfc-frontmatter specs/rfc-frontmatter/phases.kmd
Convention for declaring multi-phase migration plans in RFC frontmatter so that `koder-spec-audit rfc-phase-pickup` can open backlog tickets automatically when each phase becomes eligible. Defined by `policies-RFC-003-rfc-phase-pickup.md`; this spec is the normative schema reference for the field.
Specification body
Spec — RFC frontmatter phases: array
Normative schema for the
phases:field that RFCs with multi-phase migration plans MUST declare in their YAML frontmatter. This spec is the contract between RFC authors and thekoder-spec-audit rfc-phase-pickupbinary (perpolicies-RFC-003-rfc-phase-pickup.md).
1. Where the field lives
RFCs in meta/docs/stack/rfcs/*.md carry two parallel sources of metadata:
- Markdown table at the top of the body — for human display (Status, Author(s), Date, Affects, Depends on).
- YAML frontmatter at the very top of the file — for tooling.
The phases: field lives in the YAML frontmatter. The markdown table may continue to display a summarised "Migration plan" reference, but the structured data the audit reads is YAML.
---
title: "Reuse-First policy hierarchy"
status: Accepted
date: 2026-05-02
phases:
- id: 1
summary: "Extract reuse-first meta-policy from sdk-first.kmd"
status: done
landed_in: 7a3a62db0
- id: 2
summary: "Author the four categorical sub-policies"
status: done
landed_in: 9c73390a0
depends_on: [1]
- id: 3
summary: "Sweep references in CLAUDE.md, commands, sibling policies, koder_kit RFC"
status: done
landed_in: 05da91e38
depends_on: [2]
- id: 4
summary: "Substantive behavioural audit hooks per sub-policy"
status: pending
depends_on: [3]
target_backlog: "engines/sdk/koder_kit"
- id: 5
summary: "Decommission sdk-first.kmd redirect stub"
status: pending
depends_on: [4]
target_date: "2026-08"
---
# RFC — …
| Field | Value |
|------------|----------------------|
| Status | **Accepted** (…) |
…
2. Schema
The field is an array of phase objects. Each phase object has:
| Field | Type | Required | Notes |
|---|---|---|---|
id |
integer | yes | Sequential within the RFC. Gaps allowed if a phase was cancelled in a previous edit; gap raises an audit warning, not a failure. |
summary |
string (one line) | yes | Concrete enough that a backlog reader knows what to do without reopening the RFC. |
status |
enum | yes | One of pending, in-progress, done, cancelled. |
landed_in |
string (commit hash) | optional | Populated when status flips to done. Audit warns if done without landed_in. |
depends_on |
array of integers | optional | Phase IDs that must be done before this phase becomes eligible. Defaults to [N-1] if not declared. |
target_backlog |
string (path) | optional | Override path for where the auto-opened ticket should land. Defaults inferred from RFC slug (see §4). |
target_date |
string (YYYY-MM or full ISO) |
optional | Soft trigger — the audit holds the ticket until that date even if dependencies are done. |
cancelled_reason |
string | optional | Required when status: cancelled. One-line justification, typically pointing at the superseding RFC or design change. |
3. Status semantics
| Value | Meaning | Triggers |
|---|---|---|
pending |
Not started; waiting on its dependencies | koder-spec-audit rfc-phase-pickup considers this phase for ticket opening once dependencies clear |
in-progress |
Ticket has been opened and someone is working on it | Audit suppresses re-opening; status flip is manual when a maintainer picks the ticket up |
done |
PR landed; landed_in populated |
Audit treats this phase as a satisfied dependency for descendants |
cancelled |
Phase was abandoned or superseded; cancelled_reason populated |
Audit treats it as resolved (not blocking descendants), but does not generate a ticket |
State transitions are linear: pending → in-progress → done. Going from in-progress back to pending is allowed (ticket re-queued); going to cancelled is allowed from any non-done state.
4. Default target_backlog resolution
When target_backlog is not declared, the audit resolves it in this order:
- RFC slug starts with
monorepo-RFC-→meta/backlog/pending/. - RFC slug starts with
policies-RFC-→meta/backlog/pending/. - RFC slug matches
<area>-RFC-for an existing area →<area>/backlog/pending/if it exists. - Fallback →
meta/backlog/pending/.
The author may override at any time by declaring target_backlog explicitly on a per-phase basis.
5. Mandatoriness
- New RFCs accepted on or after
2026-05-02(RFC-003 acceptance date) MUST declarephases:when their migration plan has more than one phase. Single-phase RFCs MAY declarephases:with one entry (recommended for symmetry) or omit the field. - Existing RFCs are NOT required to retroactively declare
phases:. Retrofit is opportunistic — when an existing RFC is amended for any reason, or when one of its phases is suspected to be drifting. - Sticky retrofit: when retrofitting, declare ALL phases (past and future). Past phases get
status: done+landed_in: <hash>; future phases getstatus: pending.
6. Validation rules (enforced by audit)
The koder-spec-audit rfc-phase-pickup --validate sub-command enforces:
- The field, if present, is a YAML list of objects.
idis a positive integer; values are unique within the RFC.idsequence is monotonically increasing; gaps trigger a warning ("phase 3 missing — was it cancelled?").statusis in the enum.depends_onreferences exist (every cited ID is also declared); cycles are forbidden.cancelledrequirescancelled_reason.donewithoutlanded_intriggers a warning (not failure).
7. Example: minimum legal phases
phases:
- id: 1
summary: "Single phase placeholder"
status: pending
8. Example: full retrofit (sticky, past phases marked done)
phases:
- id: 1
summary: "Extract meta-policy"
status: done
landed_in: 7a3a62db0
- id: 2
summary: "Author sub-policies"
status: done
landed_in: 9c73390a0
depends_on: [1]
- id: 3
summary: "Reference sweep"
status: done
landed_in: 05da91e38
depends_on: [2]
- id: 4
summary: "Substantive audit hooks"
status: pending
depends_on: [3]
- id: 5
summary: "Decommission stub"
status: pending
depends_on: [4]
target_date: "2026-08"
9. Anti-patterns
- Declaring
phases:and leaving every phase aspendingforever. The audit warns when an RFC has beenStatus: Acceptedfor > 90 days with all phases stillpending. - Updating
summaryof adonephase. Once a phase haslanded_in, its summary is frozen — it is now history. Edit the summary of apendingphase freely. - Using
phases:to track non-RFC work. This field is RFC-specific. Generic backlog progress tracking belongs in tickets directly.
10. Relationship to other specs and policies
- Defined by
policies-RFC-003-rfc-phase-pickup.md. - Consumed by
koder-spec-audit rfc-phase-pickup(see RFC-003 §3.2). - Backlog ticket scaffolding follows
policies/backlog.kmdnumbering. - Companion to RFC frontmatter conventions (Status, Author(s), Date, Affects, Depends on) — those remain markdown table for display.
References
meta/docs/stack/rfcs/policies-RFC-003-rfc-phase-pickup.mdpolicies/backlog.kmd