Document stages for Requested
Summary
Add a notion of stage to Requested documents so RFCs can advertise where they are in their lifecycle — draft, open for comment, accepted, withdrawn — and so comments can be contextualized accordingly.
This is itself a Requested RFC. It's partly an honest proposal and partly a live demo of what the tool is for, so the comments matter more than the resolution.
Motivation
A Requested document currently has two observable states: it exists, and it has some number of versions. Nothing tells a reader whether the author considers it:
- a half-formed thought from yesterday,
- a serious proposal actively soliciting feedback,
- a decided thing no longer accepting comment, or
- a withdrawn idea kept visible for posterity.
That distinction is the whole point of most RFC processes. Without it, every doc looks equivalently weighty, and commenters can't tell whether their feedback is welcome or whether they're arguing with someone's frozen position.
Prior art
- TC39 uses numeric stages 0–4. Advancement requires committee consensus; stages are linear and ordinal.
- Python PEPs use a status field (Draft / Active / Accepted / Final / Rejected / Withdrawn / Superseded).
- IETF uses Internet-Draft / Proposed Standard / Internet Standard / Historic.
Common thread: a small enumerated set of states, a roughly linear transition graph, and provenance for who advanced what and when.
Proposed stage set
| stage | meaning |
|---|---|
draft |
Author is still writing. Comments welcome but everything is fluid. |
proposed |
Author considers this ready for serious feedback. The "open for comment" state. |
final-comment |
Author is preparing to lock the doc. Last call. |
accepted |
Author has decided. Doc is frozen; comments archived. |
withdrawn |
Author has abandoned the doc but is keeping it visible for context. |
Open questions on the set itself:
- Five feels right, but four would also work — drop
final-commentand let the author signal it informally in the body. - Should
acceptedandwithdrawnbe distinct, or collapsed intoclosedwith a reason field? - Do we need a
supersededstate for docs replaced by a later proposal? (PEPs have it; TC39 doesn't.) - Should
draftbe the implicit default for newly-created documents, or should "unset" be a real state?
Lexicon encoding
The interesting design question. Four options, in roughly increasing order of ceremony.
Option A — field on document
fyi.requested.document.stage: string (knownValues: draft, proposed, ...)
Simplest. One mutable field on the existing record; bumping stage is a single putRecord. No history, no provenance — the author can rewrite the stage silently. Fine if you trust authors not to lie about their own docs (which, for a v1 personal-publishing tool, is probably fine).
Option B — field on documentVersion
fyi.requested.documentVersion.stage: string
Each immutable version snapshot records its stage. Stage history falls out of the version chain for free. Comments — already pinned to a version CID — automatically carry the stage they were written against, so "show me all comments written while this was proposed" is a free query.
Cost: bumping the stage requires minting a new version even when the body hasn't changed. Arguably a feature: a stage transition is a meaningful checkpoint, and freezing the body at that moment is what the version chain is for.
Option C — separate stageTransition record
fyi.requested.stageTransition {
document: at-uri,
version?: strongRef,
stage: string,
note?: string,
createdAt: datetime,
}
Each transition is its own record on the author's PDS. Current stage = most recent transition. Clean audit log, room for transition commentary ("Moving to FCP — API feels settled, last call on naming"), no need to mint a version for stage-only changes.
Cost: a new NSID and an extra listRecords call (or Constellation query) on every doc render.
Option D — endorsements from other PDSes
fyi.requested.endorsement {
document: at-uri,
version: strongRef,
endorsedStage: string,
createdAt: datetime,
}
Stage advancement requires N endorsements from designated maintainers, each publishing on their own PDS. The atproto-native end state — no central committee, just a quorum visible across repos.
Out of scope for v1 (Requested has no concept of "maintainer" yet), but worth designing toward so we don't paint ourselves into a corner.
Recommendation
Start with B. It piggybacks on machinery we already have, makes "what stage was this comment written against?" answerable for free, and forces a body checkpoint at each transition. The "every stage bump mints a version" objection is the actual feature.
Promote to C if/when authors complain about version-chain noise, or when transition notes start to matter. Hold D in reserve.
Also: stage values should be a knownValues open string, not a closed enum. Forks of Requested may want their own process names, and atproto idiom is to keep these open.
UI implications
Assuming B:
- Stage badge on the document header, color-coded by stage.
- Progression indicator — TC39-style
● ● ○ ○ ○is tempting but probably overkill for five stages. A single badge is enough. - Home page (
/) groups the signed-in user's docs by stage.withdrawncollapsed by default. - Comment composer soft-warns when commenting on an
acceptedorwithdrawndoc: "this doc is closed — your comment will be visible but the author has stopped iterating." - History view distinguishes stage-only versions from substantive edits (small icon, dimmed row) so the chain stays readable.
- Diff view surfaces the stage transition in the header alongside the body diff.
Open questions
- Can authors demote a stage (
accepted→proposed)? They own the doc, so yes — but the UI should make it visible rather than silent. - Should comments themselves carry a stage hint, or is the version-CID linkage enough?
- Is there a place for reader-side filtering on a future global discovery view ("show me docs in
proposedorfinal-commentonly")? - How does this interact with private/unlisted docs, if those ever exist?
Non-goals
- Committee voting or multi-author governance. That's Option D territory; not now.
- Automatic stage transitions based on time or comment activity. Stage is an author signal, not derived state.
- Cross-document dependency tracking ("this doc supersedes that one"). Interesting but orthogonal.