name: rfc-writer description: "Write well-structured RFCs with normative clauses. Use when: (1) Creating a new RFC, (2) Adding or editing RFC clauses, (3) User mentions RFC, specification, or normative requirements" allowed-tools: Read, Write, Edit, Bash, Glob, Grep, TodoWrite argument-hint: [optional RFC topic]
RFC Writer
Write RFCs that are precise, complete, and follow govctl conventions.
Invocation Mode
This helper skill may be used standalone or by /discuss, /gov, /spec, or /migrate.
It is responsible for RFC content and clause quality, not RFC lifecycle verbs. Use /spec or /gov for govctl rfc finalize, bump, or advance.
Authority
RFCs define obligations: what behavior, invariants, interfaces, and compatibility rules MUST be true. They are normative artifacts, not design diaries, code sketches, or task plans.
Quick Reference
govctl rfc new "<title>"
govctl clause new <RFC-ID>:C-<NAME> "<title>" -s "<section>" -k <kind>
govctl clause edit <RFC-ID>:C-<NAME> text --stdin <<'EOF'
clause text
EOF
govctl rfc add <RFC-ID> tags <tag>
RFC Structure
Every RFC should have:
- Summary clause (informative) — what this RFC covers and why
- Specification clauses (normative) — the actual requirements
- Rationale sections within clauses — why each requirement exists
Summary Clause Template
govctl clause new <RFC-ID>:C-SUMMARY "Summary" -s "Summary" -k informative
govctl clause edit <RFC-ID>:C-SUMMARY text --stdin <<'EOF'
Brief overview of what this RFC specifies and why.
**Scope:** What is covered and what is not.
**Rationale:** Why this specification is needed.
EOF
Normative Clause Template
govctl clause new <RFC-ID>:C-<NAME> "<Title>" -s "Specification" -k normative
govctl clause edit <RFC-ID>:C-<NAME> text --stdin <<'EOF'
The system MUST ...
The system SHOULD ...
The system MAY ...
**Rationale:**
Why this requirement exists.
EOF
Writing Rules
Authority Test
Before adding a requirement to an RFC clause, apply these checks:
- Observable contract: A user, script, stored artifact, integration point, or validator can observe whether the sentence is true.
- Implementation independence: The sentence remains valid if the implementation language, source module layout, helper names, or private data structures change.
- Right destination: Design rationale belongs in an ADR; task scope belongs in a Work Item; transient execution evidence belongs in loop state, round artifacts, or the final response.
- External representation only: CLI syntax, storage paths, schemas, and wire formats belong in RFCs only when they are part of the public or persisted contract.
Examples:
| Statement | Destination |
|---|---|
The search command MUST refresh stale derived indexes before querying. |
RFC |
We will use SQLite FTS5 for the derived search index because it avoids an external service. |
ADR |
changed: Update the search command to refresh stale indexes before returning results |
Work Item |
Implement this in sync_search_index with manifest rows. |
Work Item or code review, not RFC |
RFC 2119 Keywords
Use these keywords in ALL CAPS in normative clauses:
| Keyword | Meaning |
|---|---|
| MUST | Absolute requirement |
| MUST NOT | Absolute prohibition |
| SHOULD | Recommended but not required |
| SHOULD NOT | Discouraged but not prohibited |
| MAY | Optional |
Quality Checklist
- Be specific. Avoid vague terms: "appropriate", "reasonable", "as needed". Say exactly what.
- Include rationale. Every normative clause should explain why, not just what.
- One requirement per sentence. Don't chain MUST/SHOULD in a single sentence.
- Reference existing artifacts. Use
[[RFC-NNNN]]or[[ADR-NNNN]]syntax. - Testable. Each MUST/SHOULD should be verifiable — if you can't test it, rewrite it.
- Tagged. If the project has
[tags]configured, tag the RFC with relevant domain tags. - Stay implementation-agnostic. Describe externally relevant behavior or constraints, not language-specific type layouts or private code structure.
What Belongs in an RFC
- Externally observable behavior
- Validation and error semantics
- Lifecycle and compatibility rules
- External schemas, protocol fields, storage formats, or CLI surface that users/scripts depend on
What Does Not Belong in an RFC
- Rust/TypeScript/Python type declarations
- Private struct field lists or enum variant names
- Function signatures, module layout, helper names
- Work-item execution plans, step sequencing, or progress-log notes
Only include representation details when they are themselves the external contract.
Clause Naming
- Use
C-prefix followed by a descriptive uppercase name with hyphens - Good:
C-VALIDATION,C-ERROR-FORMAT,C-WORK-DEF - Bad:
C-1,C-Misc,C-stuff
Section Types
| Section | Clause Kind | Content |
|---|---|---|
| Summary | informative | Overview, scope, rationale |
| Specification | normative | MUST/SHOULD/MAY requirements |
| Rationale | informative | Extended explanation |
Rendering Rules
The renderer auto-generates structural elements. Do NOT include these in clause text:
- Clause heading (
### [RFC-XXXX:C-NAME] Title) — auto-generated from metadata *Since: vX.Y.Z*— auto-generated from thesincefield> **Superseded by:** ...— auto-generated from thesuperseded_byfieldAmended: ...— does not exist; do not hallucinate this
Clause text should contain only the specification prose, rationale, and [[...]] references.
Common Mistakes
| Mistake | Fix |
|---|---|
| Vague MUST: "MUST handle errors appropriately" | Specific: "MUST return a descriptive validation error to the caller" |
| No rationale | Add **Rationale:** section explaining why |
| Untestable requirement | Rewrite so it can be verified programmatically |
| Missing cross-references | Add [[RFC-NNNN]] or [[ADR-NNNN]] links |
| Rust/TS type layout in the clause | Rewrite it as semantic requirements or an external contract |
| Work-plan language in the clause | Move execution details to a work item |
| Design rationale in the clause | Move the "why this approach" discussion to an ADR |
| Current progress or validation output | Move transient evidence to loop state, round artifacts, or response |
Including Since: in clause text |
Don't — the renderer adds it from the since field automatically |
| Including clause heading in text | Don't — the renderer generates ### [RFC:C-NAME] Title from metadata |
Validation and Handoff
- Run
govctl checkafter substantive RFC edits - Use
rfc-reviewerbefore lifecycle handoff - Use
/specfor clarification-only or artifact-only RFC maintenance - Use
/govfor implementation-bearing RFC amendments