Introduction
This book contains the governance documentation for govctl, an opinionated CLI for RFC-driven software development.
How This Book Is Organized
Specifications
RFCs (Requests for Comments) are the normative specifications that define govctl’s behavior. They are constitutional law — implementation must conform to them.
- RFC-0000: The governance framework itself. Start here to understand the core concepts: RFCs, Clauses, ADRs, and Work Items.
- RFC-0001: Lifecycle state machines for all artifact types.
Decisions
ADRs (Architectural Decision Records) document significant design choices. They explain why things are built a certain way.
Work Items
Work Items track units of work from inception to completion. They provide an audit trail of what was done and when.
The Data Model
All governance artifacts have a Single Source of Truth (SSOT) in the gov/ directory:
gov/
├── config.toml # govctl configuration
├── rfc/ # RFC-NNNN/rfc.toml + clauses/*.toml
├── adr/ # ADR-NNNN-*.toml
├── work/ # WI-YYYY-MM-DD-NNN-*.toml
├── guard/ # GUARD-*.toml verification guards
└── releases.toml # Release history
The markdown files in this book are rendered projections — generated from the SSOT by govctl render. Each includes a SHA-256 signature for tampering detection.
Phase Discipline
govctl enforces a strict phase lifecycle:
spec → impl → test → stable
- spec: Defining what will be built. No implementation work permitted.
- impl: Building what was specified.
- test: Verifying implementation matches specification.
- stable: Released for production use.
Phases cannot be skipped. This discipline ensures specifications precede implementation.
Getting Started
- Read RFC-0000 to understand the governance model
- Follow the Getting Started guide to install and initialize
- Read the Recommended Workflows guide to choose the right path for each change
- Learn about RFCs, ADRs, and Work Items
Getting Started
This guide walks you through installing govctl and creating your first governed artifact.
Requirements
- Rust 1.96+ (per
Cargo.tomlrust-version)
Installation
# From crates.io (includes TUI by default)
cargo install govctl
# Without TUI
cargo install govctl --no-default-features
# Or build from source
git clone https://github.com/govctl-org/govctl
cd govctl
cargo build --release
# Binary at ./target/release/govctl
Features
| Feature | Default | Description | Dependencies |
|---|---|---|---|
tui | Yes | Interactive terminal dashboard (govctl tui) | ratatui, crossterm |
Shell Completion
Generate completion scripts for your shell:
# Bash
govctl completions bash > ~/.local/share/bash-completion/completions/govctl
# Zsh (add to your .zshrc or install to completion directory)
govctl completions zsh > ~/.zsh/completions/_govctl
# Then add to fpath: fpath=(~/.zsh/completions $fpath)
# Fish
govctl completions fish > ~/.config/fish/completions/govctl.fish
# PowerShell (add to your profile)
govctl completions powershell >> $PROFILE
Restart your shell or source the configuration to enable tab completion.
Initialize a Project
govctl init
This creates the governance directory structure:
gov/
├── config.toml # Configuration (project name, schema version, guards)
├── rfc/ # RFC sources (TOML)
├── adr/ # ADR sources (TOML)
├── work/ # Work item sources (TOML)
├── guard/ # Verification guards (TOML)
├── schema/ # JSON schemas for validation
└── releases.toml # Release history
All governance artifacts use TOML with #:schema comment headers for IDE discoverability:
#:schema ../schema/adr.schema.json
[govctl]
id = "ADR-0001"
title = "My Decision"
status = "proposed"
...
Create Your First RFC
govctl rfc new "Feature Title"
This creates gov/rfc/RFC-0000/rfc.toml with the RFC metadata.
Add a Clause
RFCs are composed of clauses — atomic units of specification:
govctl clause new RFC-0000:C-SCOPE "Scope" -s "Specification" -k normative
Edit Clause Content
govctl clause edit RFC-0000:C-SCOPE text --set --stdin <<'EOF'
The feature MUST do X.
The feature SHOULD do Y.
EOF
View Artifacts
# Styled markdown to stdout
govctl rfc show RFC-0000
govctl adr show ADR-0001
govctl work show WI-2026-01-17-001
govctl clause show RFC-0000:C-SCOPE
# Interactive TUI dashboard
govctl tui
Search Artifacts
Search looks across RFCs, clauses, ADRs, work items, and verification guards:
govctl search cache
govctl search "schema migration" --type rfc --type adr
govctl search RFC-0002 --output json
govctl search cli --tag validation -n 5
govctl search loop --reindex
Search keeps any persisted index under .govctl/ as disposable local state.
Artifacts under gov/ remain authoritative; --reindex forces a rebuild before
returning results.
Validate Everything
govctl check
This validates all governance artifacts against JSON schemas, phase rules, cross-references, and source code annotations.
Recommended Workflow
Before using govctl on non-trivial work, read the Recommended Workflows guide. It explains when to use RFCs, ADRs, Work Items, execution loops, reviewer agents, and verification guards together.
Render to Markdown
govctl render
Generates human-readable markdown in docs/.
Current Views and History
Human-readable show output is optimized for the current governance context.
Deprecated RFC bodies, superseded ADR bodies, and deprecated or superseded
Clause text are hidden by default while their identity, lifecycle state, and
replacement metadata remain visible.
# Current context for humans and agents
govctl rfc show RFC-0002
# Complete historical body content
govctl rfc show RFC-0002 --history
# Complete structured resources for automation
govctl rfc show RFC-0002 --output json
govctl rfc show RFC-0002 --output yaml
govctl rfc show RFC-0002 --output toml
--history applies only to human-readable table and plain output. Structured
output is always complete. render also always preserves complete historical
content in generated Markdown; it is not affected by the default show
projection. Work Items and Guards have no obsolete-body lifecycle state, so
their current and archival human-readable views are equivalent.
Read Output Formats
Resource list commands support table, json, and yaml. They default to a
table in a terminal and JSON when piped. Complete get supports table, json,
yaml, and toml; field retrieval supports plain, json, and yaml, with
plain text as the field default.
govctl rfc list --output yaml
govctl rfc get RFC-0002 --output toml
govctl rfc get RFC-0002 phase
govctl rfc get RFC-0002 owners --output json
Interactive TUI
govctl includes an optional read-only terminal cockpit:
govctl tui
The cockpit is for human inspection: overview, artifact lists, search, loop state and dependency DAGs, guards, releases, tags, and check diagnostics. State-changing operations remain CLI commands.
TUI Keyboard Shortcuts
| Key | Action |
|---|---|
1 / r | RFC list |
2 / c | Clause list |
3 / a | ADR list |
4 / w | Work item list |
5 / g | Guard list |
6 / s | Search view |
7 / l | Loop list and loop DAG inspector |
8 / d | Diagnostics view |
9 | Release list |
t | Tag list |
j / ↓ | Navigate down |
k / ↑ | Navigate up |
Enter | Open selected detail or search result |
Esc | Go back or leave input mode |
/ | Filter lists; edit query in search view |
e | Edit query in search view |
n / p | Next/previous filtered match |
g / G | Jump to top/bottom in lists |
Ctrl+d / u | Scroll half page in detail views |
PageDown / PageUp | Scroll page in detail views |
? | Toggle help overlay |
q | Quit |
Cutting a Release
When a set of work items is complete and ready for release:
# Collect all unreleased done work items into a version
govctl release 0.2.0
# Specify a custom date
govctl release 0.2.0 --date 2026-04-15
This records the release in gov/releases.toml and makes those work items available for changelog generation.
Adopting govctl in an Existing Project
govctl init is safe to run in existing repositories — it only creates the gov/ directory structure alongside existing files.
For AI-assisted migration, use the /migrate skill to systematically discover undocumented decisions, backfill ADRs, and annotate source code with [[...]] references.
govctl migrate vs the /migrate Skill
govctl migrate | /migrate skill | |
|---|---|---|
| What | Upgrade existing govctl artifacts to current format | Adopt govctl in an existing project |
| When | After updating govctl version | When starting governance in a brownfield repo |
| Effect | Rewrites TOML files in gov/ and syncs schemas | Discovers decisions, backfills ADRs, annotates source |
| Risk | Low — transactional, reversible | Medium — requires human review of generated ADRs |
Run govctl migrate for supported schema upgrades and bundled-file synchronization. Schema versions below 3 require migration with a compatible earlier govctl version before upgrading. Use the /migrate skill when bringing a project under governance for the first time.
Canonical Edit Surface
Editable artifact fields use a unified path-based edit interface:
Quote every path containing brackets so shells such as zsh do not expand it as
a glob. For rich text containing backticks, $(), or other shell syntax, use
--stdin so the shell does not interpret the value.
# Set a scalar value
govctl rfc edit RFC-0010 title --set "Updated title"
# Add to an array
govctl adr edit ADR-0003 refs --add RFC-0010
# Replace a scalar list item in place
govctl rfc edit RFC-0010 "owners[0]" --set "@new-owner"
# Correct criterion text and optionally its category
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --set "fix: Handle edge case"
# Remove by index
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --remove
# Tick checklist items
govctl adr edit ADR-0003 "alternatives[0]" --tick accepted
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --tick done
Nested object fields use dot-delimited paths:
govctl adr edit ADR-0003 decision --set "We will use Redis"
govctl adr edit ADR-0003 "alternatives[0].pros" --add "Low latency"
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0].text" --set "Literal criterion text"
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0].category" --set fixed
CLI Self-Description
govctl provides a machine-readable command catalog:
govctl describe
govctl describe --context # Adds actionable project state and read-only next commands
The versioned JSON describes the command grammar compiled into the running binary. Context mode reports complete lifecycle counts but enumerates only non-terminal RFCs, ADRs, work items, and loops, so historical records do not inflate an agent’s working context. Workflow policy remains in the RFCs and installed skills.
Next Steps
- Working with RFCs — Full RFC lifecycle
- Working with ADRs — Decision records
- Working with Work Items — Task tracking
- Validation & Rendering — Quality gates, guards, tags, and more
Recommended Workflows
govctl is a governance tool, not a single enforced process. The recommended workflow is upstream-first: clarify requirements before design, design before execution, and execution before release.
Use this page as the default operating model when you are working with an AI agent or coordinating changes across a team.
The Default Path
For non-trivial product work, prefer:
RFC -> ADR -> Work Item -> Code -> Verification -> Release
Each layer has a different job:
| Artifact | Role | Good content | Bad content |
|---|---|---|---|
| RFC | Defines obligations | Behavior, interfaces, lifecycle rules, compatibility, validation semantics | Private module layout, helper names, current implementation plan |
| ADR | Explains decisions | Alternatives, trade-offs, chosen approach, consequences | New product requirements, task checklists, progress logs |
| Work Item | Tracks execution | Task scope, acceptance criteria, dependencies, durable notes | Normative behavior, design rationale, transient progress |
| Loop | Coordinates local execution | Round evidence, blockers, changed paths, next local action | Product requirements, durable design decisions |
When in doubt, ask what the text is trying to do:
- “What must be true?” belongs in an RFC.
- “Why this option?” belongs in an ADR.
- “What are we doing in this task?” belongs in a Work Item.
- “What happened in this round?” belongs in loop state or the final response.
Agent Guidance Model
Bundled skills provide policy and discovery, not a second copy of the CLI manual. Each workflow skill keeps a compact operational baseline:
- where to inspect current state and find deeper guidance;
- hard stops for authority, authorization, and unsafe mutation;
- policy for choosing the next action from repository context; and
- evidence that defines completion.
Information stays with its authoritative owner:
| Information | Primary owner |
|---|---|
| Normative behavior and lifecycle invariants | RFCs |
| Design rationale | ADRs |
| Repository-specific authority boundaries | Project instructions |
| Task strategy and escalation triggers | Workflow skills |
| Current syntax, state, validation, and available recovery | Canonical CLI surfaces |
| Explanation, examples, and uncommon recovery detail | Guides and indexed references |
Skills retain safety-critical triggers even when the full explanation lives elsewhere. Detailed material moves out of a skill only after it has a stable discovery route. If authoritative state or the named fallback is unavailable, the safe response is to stop before mutation rather than infer permission.
This structure lets capable agents plan from live context while keeping weaker agents recoverable. Guidance changes should be staged and checked across both common paths and lifecycle-sensitive recovery paths before older instructions are removed.
Small Changes
Not every change needs every artifact.
Use the smallest path that still leaves a useful record:
| Change | Typical path |
|---|---|
| Typo, comment, small docs fix | Edit directly, run govctl check |
| Bug fix for already specified behavior | Work Item -> Code -> Verification |
| New user-visible behavior | RFC -> ADR if needed -> Work Item -> Code |
| New architecture or trade-off | ADR -> Work Item -> Code |
| Deprecation or removal | RFC amendment -> Work Item -> Code |
| Mechanical cleanup | No Work Item, or one coarse Work Item if the outcome is durable |
Do not create work items for helper extraction, file moves, fixture sharing, formatting, or other low-level steps whose durable record is the diff.
Discovery And Drafting
Use /discuss when the problem is still unclear. Good /discuss output is a
draft RFC, a proposed ADR, or a decision that no new artifact is needed.
During discovery:
- Keep RFCs focused on externally relevant obligations.
- Keep ADRs focused on trade-offs and decisions.
- Do not start implementation while the governing RFC is still ambiguous.
- Use reviewer agents before treating RFC or ADR drafts as settled.
RFC and ADR drafting should remain human-in-the-loop. Agents can produce strong
drafts, but semantic review is still necessary because govctl check validates
structure, not judgment.
Upstream-First Refinement
RFCs and ADRs may change as you learn. The important rule is direction:
Update upstream artifacts first, then implement downstream work.
If implementation reveals that a requirement is wrong, incomplete, or ambiguous, do not silently make the code diverge. Amend the RFC or ADR first, then continue the Work Item.
Avoid the reverse pattern:
Code first -> patch RFC/ADR afterward to match what happened
That pattern turns governance into a log of implementation choices instead of a source of authority.
Work Item Execution
Use Work Items for non-trivial implementation even when no new RFC or ADR is needed. A good Work Item says what will be completed and how closure is checked.
Before implementation:
govctl work new --active "Implement stale search index refresh"
govctl work edit WI-YYYY-MM-DD-NNN refs --add RFC-0002
govctl work edit WI-YYYY-MM-DD-NNN acceptance_criteria --add "changed: Search refreshes stale derived indexes before querying"
govctl work edit WI-YYYY-MM-DD-NNN acceptance_criteria --add "chore: govctl check passes"
govctl work list active
Confirm the intended work item appears in the active list. During execution:
- Tick acceptance criteria as they become true.
- Add
notesonly for durable constraints or retry rules. - Do not put progress updates, command output, review status, next actions, or
temporary blockers in
notes.
After execution:
govctl work edit WI-YYYY-MM-DD-NNN "acceptance_criteria[0]" --tick done
govctl work edit WI-YYYY-MM-DD-NNN "acceptance_criteria[1]" --tick done
govctl work move WI-YYYY-MM-DD-NNN done
Moving to done runs verification guards when verification is enabled.
When To Use Loops
Use a loop when non-trivial execution needs resumable local round evidence, including single-Work-Item work.
Good loop use cases:
- A batch has multiple independently meaningful Work Items.
- Work Items have
depends_onedges and need ready-item planning. - You expect several implementation/review/verification rounds.
- You need local evidence for changed paths, blockers, note candidates, or validation results without polluting Work Item fields.
Do not use a loop to justify over-splitting one task into mechanical Work Items. Do not create a separate loop for every tiny cleanup.
Typical loop flow:
govctl loop list open
govctl loop start WI-YYYY-MM-DD-001 WI-YYYY-MM-DD-002
govctl loop run LOOP-YYYY-MM-DD-NNN
# implement, verify, and fill the opened round evidence
govctl loop run LOOP-YYYY-MM-DD-NNN
Important boundaries:
loop runadvances local round state only.- It does not implement code.
- It does not tick acceptance criteria.
- It does not add Work Item notes.
- It does not move Work Items to
done.
If batch scope changes, keep the same loop identity:
govctl loop add LOOP-YYYY-MM-DD-NNN work WI-YYYY-MM-DD-003
govctl loop remove LOOP-YYYY-MM-DD-NNN work WI-YYYY-MM-DD-002
govctl loop replan LOOP-YYYY-MM-DD-NNN
If loop show or loop list reports a stale plan, the current Work Item
dependency closure differs from the stored loop plan. Run govctl loop replan LOOP-YYYY-MM-DD-NNN before opening another round.
Loop state is local execution memory under .govctl/loops/. Work Items remain
the durable task record.
Agent Goals And Loops
Some agent runtimes provide session-level goal features, such as /goal. These
work well with batched Work Items in a loop when the boundaries stay clear:
| Layer | Role |
|---|---|
| Work Item | Durable outcome and acceptance criteria |
| Loop | Batch coordination, ready-work planning, and round evidence |
| Agent goal | Current session focus, budget, and resume target |
For a batched loop, set the agent goal to the current loop or round instead of duplicating the Work Item list:
Goal: Complete the current round for LOOP-YYYY-MM-DD-NNN.
That goal gives the agent a narrow execution target while the loop remains the source of truth for ready Work Items, blockers, changed paths, validation evidence, and note candidates.
Use a simpler goal for simple work:
- For one small Work Item, a goal may point directly at that Work Item.
- For a multi-Work-Item batch, prefer one goal for the active loop or current round.
- Do not create one goal per mechanical substep.
Do not store agent goals in RFCs, ADRs, or Work Item notes. Goals are runtime focus. Loop state is local execution memory. Work Items are the durable task record.
Review And Verification
Run structural checks directly:
govctl check
govctl check validates schemas, references, lifecycle rules, tags, source
annotations, and other deterministic constraints. It does not decide whether an
RFC is too implementation-specific or whether an ADR is intellectually honest.
When closing a Work Item, use govctl work move <WI-ID> done as the final
verification gate. The move runs the Work Item’s effective verification guards,
so do not run govctl verify --work <WI-ID> immediately beforehand. Run
govctl verify independently only to diagnose guards or when the Work Item will
remain active.
Use reviewer agents for semantic checks:
rfc-reviewercatches vague requirements and implementation details inside RFCs.adr-reviewercatches missing alternatives, dishonest consequences, and ADRs that invent requirements.wi-reviewercatches vague criteria, transient notes, local requirements, and over-split Work Items.compliance-checkeraudits implementation against normative RFC clauses and accepted ADR decisions.
Treat reviewer findings as design feedback, not just formatting feedback.
Project-Specific Guards
Domain projects often need extra checks. For example:
- Requirement ID tracing from RFC clauses to tests and source comments.
- Generated-code or assembler inspection for low-level performance work.
- Protocol conformance suites.
- Language-specific lint or style checks.
Model these as verification guards when they can be automated:
govctl guard new "Requirement trace"
govctl guard edit GUARD-REQUIREMENT-TRACE command --set "cargo run --bin trace-check"
govctl work edit WI-YYYY-MM-DD-NNN verification.required_guards --add GUARD-REQUIREMENT-TRACE
Keep the guard domain-specific. govctl provides the governance structure; your project owns the language, framework, and protocol-specific checks. Project defaults are the checks every Work Item needs. Select heavier or domain-specific guards per Work Item, and reserve full suites for changes whose blast radius crosses the narrower domains.
Common Pitfalls
- Writing implementation details into RFCs because they are easy to describe.
- Writing new requirements into ADRs because the decision needs justification.
- Writing current plans or validation output into Work Item notes.
- Creating many tiny Work Items for one coherent refactor.
- Treating loops as mandatory ceremony instead of local execution coordination.
- Treating an agent goal as durable governance state.
- Treating
govctl checkas a substitute for human or agent semantic review.
The goal is not to maximize artifact count. The goal is to keep authority, decision rationale, execution state, and verification evidence in the right places.
Working with RFCs
RFCs (Requests for Comments) are the normative specifications in govctl. They define what will be built before implementation begins.
Creating RFCs
# Auto-assign next available ID
govctl rfc new "Feature Title"
# Specify ID manually
govctl rfc new "Feature Title" --id RFC-0010
RFC Structure
An RFC consists of:
- Metadata (
rfc.toml) — ID, title, status, phase, version, owners - Clauses (
clauses/*.toml) — Atomic units of specification
The TOML files use #:schema headers and a [govctl] + [content] layout:
#:schema ../../schema/rfc.schema.json
[govctl]
id = "RFC-0010"
title = "Feature Title"
version = "0.1.0"
status = "draft"
phase = "spec"
owners = ["@you"]
created = "2026-03-17"
refs = []
[content]
summary = "Brief summary of this RFC."
Tagging RFCs
Once tags are registered in the project vocabulary, apply them to RFCs:
govctl rfc edit RFC-0010 tags --add caching
govctl rfc edit RFC-0010 tags --add api
Filter lists by tag:
govctl rfc list --tag caching
govctl rfc list --tag caching,api
Canonical Edit Surface
Editable RFC and Clause fields use path-based operations. Lifecycle-owned fields
such as RFC versions, changelog dates, and Clause since values use dedicated
commands or automatic assignment instead:
# Lifecycle-managed fields use dedicated verbs
govctl rfc finalize RFC-0010 normative
govctl rfc bump RFC-0010 --minor -m "Add new clause for edge case"
# Correct metadata for the current RFC version only
govctl rfc get RFC-0010 changelog
govctl rfc edit RFC-0010 changelog.summary --set "Clarify edge-case behavior"
govctl rfc edit RFC-0010 changelog.fixed --add "Correct timeout wording"
govctl rfc edit RFC-0010 "changelog.fixed[0]" --remove
# Add to array fields
govctl rfc edit RFC-0010 refs --add RFC-0001
govctl rfc edit RFC-0010 owners --add "@co-maintainer"
# Remove by index or pattern
govctl rfc edit RFC-0010 "refs[0]" --remove
govctl rfc edit RFC-0010 owners --remove "@old-owner"
# Edit clause text
govctl clause edit RFC-0010:C-SCOPE text --set --stdin <<'EOF'
New clause text here
EOF
Finalization is the initial publication boundary for a draft RFC. A
version-changing bump opens the next candidate from a normative RFC in impl,
test, or stable; draft, deprecated, and already-open spec RFCs are rejected.
Changelog-only corrections do not change the version and remain available
through either rfc edit ... changelog or rfc bump --change.
Working with Clauses
Clauses are first-class CLI resources. Use the root govctl clause namespace
for every Clause operation, even though Clause IDs and files are scoped by an
RFC. govctl rfc operates on the RFC resource itself.
Create a Clause
govctl clause new RFC-0010:C-SCOPE "Scope" -s "Specification" -k normative
Options:
-s, --section— Section name (e.g., “Specification”, “Rationale”)-k, --kind—normative(binding) orinformative(explanatory)
Clause files use the same [govctl] + [content] layout:
#:schema ../../../schema/clause.schema.json
[govctl]
id = "C-SCOPE"
title = "Scope"
kind = "normative"
status = "active"
since = "0.1.0"
[content]
text = """
The system MUST validate all inputs."""
since is assigned when the target version is known. Clauses created in a
draft RFC remain pending until finalization. Clauses created in a normative RFC
already in spec receive the current RFC version immediately. Clauses created
in impl, test, or stable remain pending until the content amendment is
released by an RFC version bump.
Edit Clause Text
# From stdin (recommended for multi-line)
govctl clause edit RFC-0010:C-SCOPE text --set --stdin <<'EOF'
The system MUST validate all inputs.
The system SHOULD log validation failures.
EOF
# Inline text
govctl clause edit RFC-0010:C-SCOPE text --set "The system MUST validate all inputs."
# From file
govctl clause edit RFC-0010:C-SCOPE text --set --stdin < clause-text.md
Delete a Clause
Accidentally created clauses can be deleted before they become part of a sealed version:
govctl clause delete RFC-0010:C-MISTAKE -f
Safety: Deletion is only allowed when no artifact references the Clause and either:
- The RFC status is
draft; or - The RFC is
normative/specand the Clausesinceequals the current RFC version.
The second case identifies a Clause introduced only in the open candidate.
Inherited Clauses and all Clauses in sealed phases use govctl clause deprecate
or govctl clause supersede instead.
List Clauses
govctl clause list
govctl clause list RFC-0010
govctl clause list --tag core # Filter by tag
View a Clause
govctl clause show RFC-0010:C-SCOPE
Status Lifecycle
RFCs have three statuses:
draft → normative → deprecated
Finalize to Normative
When the spec is complete and approved:
govctl rfc finalize RFC-0010 normative
This ratifies the RFC lineage. While its current version remains in spec, that
content is still an authoring candidate. The version becomes the implementation
baseline when it advances to impl.
Deprecate
When an RFC is superseded or obsolete:
govctl rfc deprecate RFC-0010
Phase Lifecycle
RFCs progress through four phases:
spec → impl → test → stable
Advance Phase
govctl rfc advance RFC-0010 impl # Ready for implementation
govctl rfc advance RFC-0010 test # Implementation complete, ready for testing
govctl rfc advance RFC-0010 stable # Tested, ready for production
Phase transitions are gated:
spec → implrequiresstatus = normativespec → implrequires every Clause to have a resolvedsinceversionspec → implseals the current RFC and Clause content signatureimpl → testandtest → stablerequire that sealed signature to remain present- Each phase has invariants that must be satisfied
The sealed signature is a content baseline, not a file lock. A code-only defect
found during impl can be fixed without changing the RFC. If RFC or Clause
content must change, edit it and then release that amendment with a patch,
minor, or major bump. The bump starts the new version in spec; phase
progression rejects the amendment until that happens. Changelog-only corrections
do not affect the sealed baseline. If a sealed-phase RFC has no signature, bump
and later phase progression stop without changing files; run govctl migrate or
restore the baseline from version-control history instead of guessing it.
Versioning
RFCs use semantic versioning after normative finalization. Draft RFCs remain on their initial version while they are authored, and deprecated RFCs cannot start a new version lifecycle:
# Bump version with changelog entry
govctl rfc bump RFC-0010 --patch -m "Fix typo in clause C-SCOPE"
govctl rfc bump RFC-0010 --minor -m "Add new clause for edge case"
govctl rfc bump RFC-0010 --major -m "Publish the stable 1.0 contract"
The bump flags select literal SemVer components; they are not remapped impact
labels. For an RFC at 0.y.z, use --minor for a breaking pre-1.0 amendment
that starts the next 0.(y+1).0 line, and reserve --major for the deliberate
transition to 1.0.0. Use --patch for amendments that remain compatible
within the current 0.y line.
A content-changing bump starts the new version in spec only from impl, test,
or stable. RFC and Clause content can continue changing during that spec phase
without another version bump; a second version-changing bump is rejected.
Advancing to impl seals the final content for the version.
Use change-only bump syntax to append categorized metadata without changing the RFC version:
govctl rfc bump RFC-0010 --change "fix: Correct current-version wording"
Current-version changelog correction always resolves the entry whose version matches the RFC version, regardless of array order. Historical entries and all RFC/changelog version and date fields are not editable through the resource edit surface.
Listing and Viewing
govctl rfc list
govctl rfc list normative # Filter by status
govctl rfc list impl # Filter by phase
govctl rfc list --tag api # Filter by tag
govctl rfc show RFC-0010 # Styled markdown to stdout
Working with ADRs
ADRs (Architectural Decision Records) document significant design choices. They explain why things are built a certain way.
Creating ADRs
govctl adr new "Use Redis for caching"
This creates a TOML file in gov/adr/ with the decision context.
ADR Structure
ADRs are TOML files with #:schema headers:
#:schema ../schema/adr.schema.json
[govctl]
id = "ADR-0003"
title = "Use Redis for caching"
status = "proposed"
date = "2026-03-17"
refs = ["RFC-0001"]
[content]
context = "We need a caching layer for..."
decision = "We will use Redis because..."
consequences = "Positive: faster reads. Negative: operational complexity."
[[content.alternatives]]
text = "Memcached"
pros = ["Simpler"]
cons = ["No persistence"]
rejection_reason = "Persistence is required for our use case"
ADRs contain:
- Context — The situation requiring a decision
- Decision — What was decided
- Consequences — Expected outcomes (positive and negative)
- Alternatives — Options considered with pros, cons, and rejection reasons (per [[ADR-0027]])
- Status —
proposed,accepted,rejected, orsuperseded
Editing ADRs
Use govctl to get/set fields:
# Get specific field
govctl adr get ADR-0003 status
# Set content field value
govctl adr edit ADR-0003 decision --set "We will use Redis because..."
# Set multi-line content from stdin
govctl adr edit ADR-0003 context --set --stdin <<'EOF'
We need a caching layer that can handle
10k requests per second with sub-millisecond latency.
EOF
Canonical Edit Paths
All ADR fields are accessible through a unified path-based edit interface:
# Scalar fields
govctl adr edit ADR-0003 decision --set "We will use Redis"
govctl adr edit ADR-0003 context --set --stdin < context.md
# Array fields — add, remove, tick
govctl adr edit ADR-0003 refs --add RFC-0010
govctl adr edit ADR-0003 "refs[0]" --remove
# Nested alternatives
govctl adr edit ADR-0003 alternatives --add "Option C: Use etcd"
govctl adr edit ADR-0003 "alternatives[0].pros" --add "Fast reads"
govctl adr edit ADR-0003 "alternatives[0].cons" --add "Operational cost"
govctl adr edit ADR-0003 "alternatives[0]" --tick accepted
govctl adr edit ADR-0003 "alternatives[0].rejection_reason" --set "Too complex"
# Tick alternative status
govctl adr edit ADR-0003 "alternatives[0]" --tick accepted
Edit paths use logical field names:
| Field | Path |
|---|---|
| Decision | decision |
| Context | context |
| Consequences | consequences |
| Alternatives | alternatives |
| Alternative pros | alternatives[i].pros |
| Alternative cons | alternatives[i].cons |
| Rejection reason | alternatives[i].rejection_reason |
Tagging ADRs
Once tags are registered in the project vocabulary, apply them to ADRs:
govctl adr edit ADR-0003 tags --add caching
govctl adr edit ADR-0003 tags --add performance
Filter lists by tag:
govctl adr list --tag caching
govctl adr list --tag caching,performance
Status Lifecycle
proposed → accepted → superseded
↘ rejected
Accept a Decision
Before accepting, the ADR must have at least 2 alternatives with 1 accepted and 1 rejected per [[ADR-0042]]:
govctl adr edit ADR-0003 "alternatives[0]" --tick accepted
govctl adr edit ADR-0003 "alternatives[1]" --tick rejected
govctl adr accept ADR-0003
Use --force for historical backfills where alternatives cannot be reconstructed:
govctl adr accept ADR-0003 --force
When consensus is reached:
govctl adr accept ADR-0003
Reject a Proposal
When a proposed ADR should not proceed:
govctl adr reject ADR-0003
Accepted ADRs are not deprecated. When a newer decision replaces an accepted ADR, supersede it instead.
Supersede
When a new decision replaces an old one:
govctl adr supersede ADR-0001 --by ADR-0005
This marks ADR-0001 as superseded and records ADR-0005 as its replacement.
Listing and Viewing
govctl adr list
govctl adr list accepted # Filter by status
govctl adr show ADR-0003 # Styled markdown to stdout
Working with Work Items
Work Items track durable units of work from inception to completion, including scope, lifecycle state, acceptance criteria, references, dependencies, and durable notes. Round-by-round execution trace belongs in local loop state and round artifacts.
See also: Tags, TUI, Canonical Edit
Creating Work Items
# Create in queue (pending)
govctl work new "Implement caching layer"
# Create and activate immediately
govctl work new --active "Urgent bug fix"
Work items are automatically assigned IDs like WI-2026-01-17-001.
Work Item Structure
Work items are TOML files with #:schema headers:
#:schema ../schema/work.schema.json
[govctl]
id = "WI-2026-01-17-001"
title = "Implement caching layer"
status = "active"
started = "2026-01-17"
refs = ["RFC-0010", "ADR-0003"]
depends_on = ["WI-2026-01-16-001"]
[content]
description = "Add Redis caching for the query endpoint."
notes = ["Do not retry the old validation path"]
[[content.acceptance_criteria]]
text = "Cache invalidation on write"
status = "pending"
category = "added"
[[content.acceptance_criteria]]
text = "govctl check passes"
status = "pending"
category = "chore"
Work items contain:
- Title — Brief description
- Description — Task scope declaration
- Notes — Durable learnings and constraints
- Acceptance Criteria — Checkable completion criteria with changelog category
- Refs — Links to related RFCs, ADRs, or external resources
- Depends On — Blocking dependencies on other work items
Status Lifecycle
queue → active → done
↘ ↘ cancelled
Move Between States
# By ID
govctl work move WI-2026-01-17-001 active
govctl work move WI-2026-01-17-001 done
# By filename (without path)
govctl work move implement-caching.toml active
Moving to done requires all verification guards to pass (see Validation).
Acceptance Criteria
Add Criteria
govctl work edit WI-2026-01-17-001 acceptance_criteria --add "chore: Unit tests pass"
govctl work edit WI-2026-01-17-001 acceptance_criteria --add "add: Documentation updated"
Category prefixes (add:, fix:, change:, chore:, etc.) are required and drive changelog generation. Conventional-commit aliases like feat:, refactor:, test:, docs: are also accepted.
Canonical changelog categories are still the preferred form in stored artifacts. The conventional-commit aliases are accepted as input sugar and normalized into the changelog model.
Correct Criteria
Set an indexed criterion directly to correct its text. A recognized category prefix updates the category at the same time; input without one preserves the existing category. Both forms preserve checklist status.
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --set "fix: Handle empty input"
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --set "Handle empty input"
Use the child path when a recognized prefix must remain literal text:
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0].text" --set "fix: shown to the user"
Mark Criteria Complete
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --tick done
Checklist state changes address one item by index.
Canonical Edit Paths
Most work item fields are accessible through the unified path-based edit interface. Lifecycle-managed fields (such as status) are excluded — use govctl work move for status transitions instead.
# Set scalar fields
govctl work edit WI-2026-01-17-001 description --set --stdin <<'EOF'
New description here
EOF
# Add to array fields
govctl work edit WI-2026-01-17-001 refs --add RFC-0010
govctl work edit WI-2026-01-17-001 depends_on --add WI-2026-01-16-001
govctl work edit WI-2026-01-17-001 acceptance_criteria --add "fix: Handle edge case"
# Remove by index
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --remove
# Tick checklist items
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --tick done
govctl work edit WI-2026-01-17-001 "acceptance_criteria[1]" --tick cancelled
Edit paths use logical field names:
| Field | Path |
|---|---|
| Description | description |
| Acceptance criteria | acceptance_criteria |
| Notes | notes |
| Criterion category | acceptance_criteria[i].category |
Dependencies and Execution Loops
Use depends_on for hard execution ordering between work items. Keep refs for
informational links to RFCs, ADRs, clauses, guards, or related work.
govctl work edit WI-2026-01-17-002 depends_on --add WI-2026-01-17-001
govctl check
govctl check validates dependency targets and rejects dependency cycles. A
work item should only depend on another work item when the dependent work cannot
start until the blocker has completed.
For a batch with multiple independently meaningful work items, create one local execution loop and let govctl generate the loop ID:
govctl loop list open
govctl loop start WI-2026-01-17-001 WI-2026-01-17-002
govctl loop run <LOOP-ID>
Loop state and round evidence live under .govctl/loops/<LOOP-ID>/. loop run
opens or validates local rounds; it does not implement code, tick acceptance
criteria, add notes, or move work items to done.
When batch scope changes, keep the same loop identity:
govctl loop add <LOOP-ID> work WI-2026-01-17-003
govctl loop remove <LOOP-ID> work WI-2026-01-17-002
govctl loop replan <LOOP-ID>
Use work item notes only for durable lessons or constraints. Put transient
execution trace, failed attempts, blockers, next actions, and round summaries in
loop state and round artifacts.
Tagging Work Items
Once tags are registered in the project vocabulary, apply them to work items:
govctl work edit WI-2026-01-17-001 tags --add backend
govctl work edit WI-2026-01-17-001 tags --add performance
Filter lists by tag:
govctl work list --tag backend
govctl work list --tag backend,performance
Per-Work-Item Guards
Work items can require extra verification guards in addition to the project’s default guard set.
Example:
[verification]
required_guards = ["GUARD-CLIPPY"]
This means:
GUARD-CLIPPYis required for this work item even if it is not a project default- project defaults from
gov/config.tomlstill apply when verification is enabled - the work item cannot move to
doneuntil the effective required guards pass or are explicitly waived
Project defaults should contain only the checks required by every Work Item. Choose additional guards from the Work Item’s changed surface, governing references, and acceptance criteria. Prefer a narrow domain guard over a full test suite; require the full suite when the change crosses shared boundaries or cannot be covered reliably by narrower checks.
To run the effective guard set for a single work item:
govctl verify --work WI-2026-01-17-001
Use this command for early feedback or diagnosis while the Work Item remains
active. Moving the Work Item to done runs the same effective guard set, so
running both commands back to back repeats the guards.
Waiving A Guard
If a specific guard must be waived for this work item, record that in the artifact with a reason:
[[verification.waivers]]
guard = "GUARD-CARGO-TEST"
reason = "Temporarily flaky on macOS runners; tracked in issue #123"
Waivers are per-work-item only. They do not disable the guard globally, and they should remain rare and justified.
Notes
Add closure-worthy durable notes for constraints or retry rules that should remain useful after the work item is done:
govctl work edit WI-2026-01-17-001 notes --add "Do not retry the old validation path; it fails on missing refs"
govctl work edit WI-2026-01-17-001 "notes[0]" --set "Retry only after the referenced RFC is normative"
Do not use notes for progress updates, commands run, validation output, current plans, next actions, temporary blockers, or TODOs. Put transient execution trace in local loop state and round artifacts instead.
Nested path edits are also available for structured fields:
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0]" --set "fix: Handle edge case"
govctl work edit WI-2026-01-17-001 "acceptance_criteria[0].category" --set fixed
Removing Items
Remove items from array fields using flexible matching:
# Exact value
govctl work edit WI-2026-01-17-001 notes --remove "edge case"
# Another exact value
govctl work edit WI-2026-01-17-001 notes --remove "Discovered edge case in validation"
# By index (0-based)
govctl work edit WI-2026-01-17-001 "notes[0]" --remove
# Regex pattern
govctl work edit WI-2026-01-17-001 refs --remove "RFC-.*" --regex
# Remove every item
govctl work edit WI-2026-01-17-001 refs --remove --all
Deleting Work Items
Accidentally created work items can be deleted if they’re still in queue status:
govctl work delete WI-2026-01-17-999 -f
Safety: Deletion is only allowed when:
- The work item status is
queue(never activated) - No other artifacts reference it
For work items that have been activated, use status transitions instead:
govctl work move WI-2026-01-17-001 cancelled
Listing and Viewing
govctl work list
govctl work list queue # Pending items
govctl work list active # In progress
govctl work list done # Completed
govctl work show WI-2026-01-17-001 # Styled markdown to stdout
Conformance Cases
Conformance Cases connect a project-owned acceptance scenario to one or more versioned RFC Clause requirements and reusable Verification Guards:
RFC Clause requirement -> Conformance Case -> Verification Guard
normative authority derived scenario execution entrypoint
A Case is traceability metadata, not a test runner or a source of normative requirements. When a Case and an RFC disagree, the RFC governs.
Create A Case
The scenario path must already exist, stay inside the repository, and remain
outside gov/. The selector is project-defined; use * for the complete file.
govctl conformance new "Cache invalidation behavior" \
--path tests/conformance/cache.toml \
--selector cache-expiry \
--requirement RFC-0012:C-CACHE-EXPIRY@1.2.0 \
--guard GUARD-CACHE-CONFORMANCE
Requirement values always use <CLAUSE-ID>@<RFC-VERSION>. A Case may bind
multiple requirements and Guards.
Inspect And Edit
govctl conformance list
govctl conformance show CONF-CACHE-INVALIDATION-BEHAVIOR
govctl conformance get CONF-CACHE-INVALIDATION-BEHAVIOR requirements
govctl conformance edit CONF-CACHE-INVALIDATION-BEHAVIOR \
requirements --add RFC-0012:C-CACHE-FALLBACK@1.2.0
govctl conformance edit CONF-CACHE-INVALIDATION-BEHAVIOR \
requirements[0].version --set 1.3.0
govctl conformance edit CONF-CACHE-INVALIDATION-BEHAVIOR \
requirements[1] --remove
Case mutations validate the complete prospective trace graph before writing. Removing the final requirement is rejected.
Query Traceability
govctl conformance trace
govctl conformance trace RFC-0012
govctl conformance trace RFC-0012:C-CACHE-EXPIRY
govctl conformance trace CONF-CACHE-INVALIDATION-BEHAVIOR --output json
govctl conformance trace GUARD-CACHE-CONFORMANCE
Trace output derives provisional, candidate, current, or stale
applicability from the referenced RFC version and Clause lifecycle. These values
describe the declared relationship only; they do not mean that a scenario has
run or passed.
Cases also participate in govctl search, controlled-vocabulary tags,
govctl status, and govctl check.
Schema Migration
Conformance Cases were introduced in project schema version 4. Upgrade an existing project to the current schema with:
govctl migrate
govctl check
Migration preserves valid prospective Case files and rejects an invalid Case graph without partially changing the repository.
Validation & Rendering
govctl provides tools to validate governance artifacts, enforce completion gates, and render human-readable documentation.
Validation
Check All Artifacts
govctl check
This validates:
- Schema conformance — All required fields present, correct types
- Phase discipline — No invalid state transitions
- Cross-references —
refsand[[...]]annotations point to existing artifacts - Controlled-vocabulary tags — All artifact tags are registered in
gov/config.toml [tags] allowed - Clause structure — Normative clauses in spec sections
- Source code scanning —
[[RFC-0001]]annotations in source files are verified
Exit Codes
0— All validations passed1— Validation errors found
Source Code Scanning
govctl scans source files for [[artifact-id]] annotations and verifies they reference existing, non-deprecated artifacts:
#![allow(unused)]
fn main() {
// Implements [[RFC-0001:C-VALIDATION]]
fn validate() { ... }
// Per [[ADR-0005]], we use semantic colors
}
Configure scanning in gov/config.toml:
[source_scan]
enabled = true
include = ["src/**/*.rs"]
include is the positive scan domain and uses Git gitignore path-pattern
semantics. Project .gitignore files provide the baseline exclusions.
Governance-specific exclusions and re-inclusions belong in .govignore files:
# Skip generated source evidence
generated/
# Restore one governed subtree excluded by .gitignore
!fixtures/
!fixtures/governed/
.govignore uses normal gitignore ordering and ! re-inclusion, and its rules
take precedence over .gitignore. Re-including a descendant requires
re-including each excluded parent directory. govctl prunes excluded directories
before reading their contents.
An optional source_scan.pattern override must be a valid regular expression
whose capture group 1 returns the complete artifact ID for every match. Unknown
and outdated reference diagnostics report the normalized source path followed
by a one-based line and byte column.
Controlled-Vocabulary Tags
Tags provide cross-cutting categorization across all governance artifacts. Every tag must be registered in a project-level allow list before use.
Managing the Tag Registry
# List all registered tags with usage counts
govctl tag list
# Register a new tag
govctl tag new caching
# Remove a tag (fails if any artifact still uses it)
govctl tag delete caching
Tagging Artifacts
Once a tag is registered, apply it to any artifact via the standard edit command with --add:
govctl rfc edit RFC-0010 tags --add caching
govctl adr edit ADR-0003 tags --add caching
govctl work edit WI-2026-01-17-001 tags --add caching
Filtering by Tag
List commands support --tag to filter by one or more tags (comma-separated, AND logic):
govctl rfc list --tag caching
govctl adr list --tag caching,performance
govctl work list --tag breaking-change
Tags are validated at govctl check time — any tag not in the allow list produces error E1105.
Verification Guards
Guards are executable completion checks that run automatically when a work item moves to done. They prevent work items from closing unless all configured checks pass.
How Guards Work
When you run govctl work move <WI-ID> done, govctl executes each guard defined in gov/config.toml:
[verification]
enabled = true
default_guards = ["GUARD-GOVCTL-CHECK"]
Each guard is a TOML file in gov/guard/:
#:schema ../schema/guard.schema.json
[govctl]
id = "GUARD-LIFECYCLE-TESTS"
title = "lifecycle tests pass"
refs = ["RFC-0000"]
[check]
command = "cargo test --test lifecycle_tests"
timeout_secs = 300
Guard Subcommands
Guards are first-class resources with their own CRUD verbs:
# Create a new guard
govctl guard new "My Lint Check"
# List all guards
govctl guard list
# Show guard definition
govctl guard show GUARD-MY-LINT
# Set guard fields
govctl guard edit GUARD-MY-LINT command --set "npm run lint"
govctl guard edit GUARD-MY-LINT timeout_secs --set 60
# Delete a guard (blocked if still referenced by work items or project defaults)
govctl guard delete GUARD-MY-LINT
Guard Fields
| Field | Required | Description |
|---|---|---|
id | Yes | Unique guard identifier (e.g., GUARD-LINT) |
title | Yes | Human-readable description |
refs | No | Related RFCs/ADRs |
command | Yes | Shell command to execute from project root |
timeout_secs | No | Max execution time (default: 300s) |
pattern | No | Regex pattern that must match stdout+stderr |
Guard Behavior
- A guard passes when its command exits with code 0 (and matches
patternif specified) - A guard fails when the command exits non-zero, times out, or doesn’t match the pattern
- All guards must pass before
govctl work move <WI-ID> donesucceeds
Running Guards Independently
Use govctl verify to run guards without moving a work item:
# Run all project default guards
govctl verify
# Run specific guards
govctl verify GUARD-CARGO-TEST GUARD-GOVCTL-CHECK
# Run guards required by a specific work item
govctl verify --work WI-2026-01-17-001
govctl work move <WI-ID> done runs the same effective required guards. Do not
run govctl verify --work <WI-ID> immediately before that move; doing so
executes the guards twice. Use independent verification for early feedback,
diagnosis, or workflows that leave the Work Item active.
Per-Work-Item Guards
Project-level default_guards are only part of the picture. A work item can also require additional guards of its own:
[verification]
required_guards = ["GUARD-CLIPPY"]
This is useful when one work item needs an extra check that should not become a project-wide default.
The effective required guard set for a work item is:
- the project-level
default_guardswhen verification is enabled - plus the work item’s
verification.required_guards - minus any explicitly waived guards
Choosing Guard Granularity
Treat default_guards as the intersection of checks required by every Work
Item, not as a catalog of everything the project can verify. A default guard
should be necessary even for documentation-only work, fast enough for every
completion gate, stable, and independent of optional services.
Keep reusable checks narrow and name them for the risk domain they cover, such as lifecycle tests, schema tests, or CLI parsing tests. Add those guards to affected Work Items:
govctl work edit WI-2026-01-17-001 verification.required_guards --add GUARD-LIFECYCLE-TESTS
Full test suites, full lint suites, integration tests, and other expensive aggregate checks should remain available as guards, but normally be required only by Work Items that change shared infrastructure or cross multiple risk domains. One-off diagnostic commands do not need Guard artifacts.
Repeated waivers are not a substitute for correct scope. If many unrelated Work
Items waive the same default guard, remove it from default_guards and require
it only where its risk applies.
Guard Waivers
If a guard must be waived for a specific work item, record that explicitly with a reason:
[[verification.waivers]]
guard = "GUARD-CARGO-TEST"
reason = "Flaky on CI runner image; tracked in issue #123"
Waivers are scoped to a single work item. They do not disable verification globally, and they should be treated as an exception that must be explained.
Rendering
Render governance artifacts to markdown for documentation.
Render All
govctl render # RFCs to docs/rfc/
govctl render adr # ADRs to docs/adr/
govctl render work # Work items to docs/work/
govctl render all # Everything
govctl render changelog # CHANGELOG.md
Render Single Items
govctl rfc render RFC-0010
govctl adr render ADR-0005
govctl work render WI-2026-01-17-001
View Without Writing Files
The show commands render styled markdown to stdout without writing files:
govctl rfc show RFC-0010
govctl adr show ADR-0005
govctl work show WI-2026-01-17-001
govctl clause show RFC-0010:C-SCOPE
Hash Signatures
Rendered markdown includes a SHA-256 signature for tampering detection:
<!-- SIGNATURE: sha256:abc123... -->
If the source changes, the signature won’t match — indicating the rendered doc is stale.
Project Status
govctl status
Shows RFC/ADR/work item counts by status, phase breakdown, and active work items.
Search
govctl search cache
govctl search "work item" --type work
govctl search RFC-0002 --output json
govctl search migration --tag cli -n 5
govctl search cache --reindex
Search is project-wide discovery across RFCs, clauses, ADRs, work items, and
verification guards. Use repeated --type flags to restrict artifact kinds and
repeated --tag flags to require all listed tags.
Supported output formats are table (default), json, and plain. If govctl
persists a search index, it lives under .govctl/ as derived local state. The
command establishes index freshness before returning results; --reindex
forces a full rebuild.
CLI Self-Description
govctl provides a machine-readable command catalog for agent discoverability:
govctl describe
govctl describe --context # Adds counts and non-terminal project state
The output includes a schema version and derives its command tree from the
running CLI. Context mode omits terminal artifact details and offers only
read-only discovery commands; use resource show commands or installed skills
for deeper guidance.
Self-Update
Update govctl to the latest release:
govctl self-update # Download and replace binary
govctl self-update --check # Check for newer version without downloading
Supports GITHUB_TOKEN environment variable for authenticated API requests.
Agent Integration
Install or update govctl’s user-scoped integration through the agent runtime’s native plugin mechanism:
govctl agent doctor all
govctl agent install claude
govctl agent install codex
govctl agent update all
doctor is read-only. install preserves existing Codex reviewer-role files;
update refreshes govctl’s installed role files. Start a new agent session
after installation or update so the runtime reloads its integration. Both
runtimes load bundled skills and hooks from their native plugin. Claude also
loads Markdown reviewer agents from that plugin; Codex reviewer agents are
standalone TOML roles managed by the same command.
Claude and Codex load separate hook manifests so each client receives fields and output in its native protocol. At session start, govctl uses normal upward project discovery and injects compact active-work and loop context only when the working directory belongs to a governed project. It stays silent in unmanaged directories and reports damaged governance state as non-blocking recovery context.
Before a direct edit to lifecycle-managed artifacts, the hook advises using the
resource-specific CLI when it can express the change. The edit is never blocked:
direct editing remains the recovery path for unsupported operations, followed by
govctl check. The plugin does not run project-wide validation at the end of
every turn.
Use init-skills only when a project-local or custom-directory copy is needed:
govctl init-skills --format claude
govctl init-skills --format codex
govctl init-skills --dir /path/to/agent-config
This direct projection does not register a native user plugin. It writes bundled workflow skills, writer/helper skills, and reviewer agents to the resolved destination.
Schema Migration
When the governance schema evolves between govctl versions, artifact files may need format upgrades:
govctl migrate
This upgrades TOML artifact file formats (e.g., adding #:schema headers or normalizing schema metadata) with transactional safety — changes are staged, backed up, and committed atomically.
govctl migrate vs the /migrate Workflow
These are related but serve different purposes:
govctl migrate | /migrate skill | |
|---|---|---|
| What | Upgrade existing govctl artifacts to current format | Adopt govctl in an existing project |
| When | After updating govctl version | When starting governance in a brownfield repo |
| Effect | Syncs TOML artifacts, schemas, ignore configuration, and local support files | Discovers decisions, backfills ADRs, annotates source |
| Risk | Low — transactional, reversible | Medium — requires human review of generated ADRs |
Run govctl migrate when govctl reports an outdated schema version, missing or
stale bundled schema files, or missing govctl-managed local-state .gitignore
entries such as .govctl.lock and .govctl/. Schema versions below 3 require
migration with a compatible earlier govctl version before upgrading. Legacy RFC
or clause JSON storage is rejected explicitly. Use the /migrate skill when
bringing an existing project under governance for the first time.
RFC-0000: govctl Governance Framework
Version: 1.9.0 | Status: normative | Phase: impl Owners: @govctl-org Tags:
core,schema,validation,lifecycle
1. Summary
[RFC-0000:C-SUMMARY] Framework Summary (Informative)
govctl is a governance CLI that manages seven artifact types:
- RFCs: Normative specifications that define intent and constraints
- Clauses: Individual requirements within RFCs
- ADRs: Architectural Decision Records documenting design choices
- Work Items: Units of work tracking implementation progress
- Releases: Local version-cut records and the Work Items included in each version
- Verification Guards: Reusable executable checks that turn completion requirements into auditable pass/fail gates
- Conformance Cases: Current non-normative declarations relating acceptance scenarios to RFC versions and Guards
All artifacts follow explicit lifecycle states, phase gates, or constrained mutation rules to ensure disciplined development.
Tags:
core
Since: v1.0.0
2. RFC Specification
[RFC-0000:C-RFC-DEF] RFC Definition (Normative)
An RFC (Request for Comments) is a normative document that defines intent, constraints, or decisions governing implementation.
An RFC is not a suggestion. It is law.
The canonical RFC storage format is TOML. Repositories MUST store each RFC as a TOML file (rfc.toml) containing:
[govctl]section with:id,title,version,status,phase,owners,created- optional
[govctl]fields:updated,supersedes,refs,signature [[sections]]array with ordered section definitions and clause references[[changelog]]array for version history
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Entries in sections[].clauses MUST reference clause TOML files by relative path (for example clauses/C-EXAMPLE.toml).
Each reference MUST resolve to an existing Clause TOML file within the directory containing that RFC’s rfc.toml. Implementations MUST reject unresolved references and references whose resolved targets escape that directory, including through symbolic links.
The RFC version field is lifecycle-owned. Resource editing operations MUST NOT modify the RFC version field.
An RFC MUST have exactly one current changelog entry whose version equals the RFC’s current version. Other changelog entries are historical versions. Validation MUST reject an RFC with zero current changelog entries. Validation MUST reject an RFC with multiple current changelog entries. Current-changelog field operations MUST reject either invalid state without mutation.
The current entry’s summary and categorized changes MAY be corrected without changing the RFC version or phase. Changelog version fields are lifecycle-owned. Changelog date fields are lifecycle-owned. Resource editing operations MUST NOT modify either lifecycle-owned field. Resource editing operations MUST NOT modify any historical changelog entry.
Implementations MUST reject legacy RFC JSON storage files (rfc.json) during normal operations. The diagnostic MUST instruct users to migrate those repositories with a govctl version earlier than 0.9 before upgrading to a TOML-only govctl release.
Rationale: The current changelog entry describes the current RFC version and may need refinement while that version is authored. Matching by version avoids relying on array position. Keeping version identity, dates, and historical entries lifecycle-owned preserves version provenance.
Tags:
core,schema
Since: v1.0.0
[RFC-0000:C-STATUS-LIFECYCLE] RFC Status Lifecycle (Normative)
RFC status follows this lifecycle:
draft -> normative -> deprecated
draft: Under discussion. Implementation MUST NOT depend on draft RFCs.
normative: The RFC lineage is ratified. A normative version in impl, test, or stable is sealed, and implementation MUST conform to that sealed version. A normative version in spec is a controlled authoring candidate and MUST NOT be used as an implementation conformance baseline. The most recently sealed version remains the implementation baseline until the current spec version enters impl.
deprecated: Superseded or obsolete. Implementation SHOULD migrate away.
Transition rules:
- The draft -> normative transition MUST require explicit finalization.
- The normative -> deprecated transition MUST require a superseding RFC or explicit deprecation.
- Reverse status transitions MUST be rejected.
Rationale:
Normative status ratifies the RFC lineage, while phase identifies whether its current version is still being authored or has been sealed for implementation. This distinction permits controlled current-version authoring without presenting mutable spec content as a binding implementation contract.
Tags:
core,lifecycle
Since: v1.0.0
[RFC-0000:C-PHASE-LIFECYCLE] RFC Phase Lifecycle (Normative)
RFC phase describes the current RFC version and follows this lifecycle within that version:
spec -> impl -> test -> stable
spec: Authoring the current version candidate. Implementation work against that candidate MUST NOT begin.
impl: Building what the sealed current version specifies.
test: Verifying implementation against the sealed current version.
stable: Implementation and tests for the sealed current version are complete.
Phase rules:
- Phases within one version MUST proceed in order.
- Phase transitions MUST NOT skip a phase.
- Each phase transition MUST satisfy the preceding phase gate.
stableMUST be terminal for one RFC version.- A version-changing bump MUST be rejected while the current version remains in
spec. - A later version-changing bump MAY start another phase lifecycle only when the current version is in
impl,test, orstable. - A version bump that releases a detected content amendment MUST start the new version at
spec. - Only a normative RFC MAY advance from
spectoimpl. - While phase is
spec, RFC and clause content belongs to the current version candidate and MAY change without another version bump. - The
spec->impltransition MUST set or replace the stored amendment signature with a signature of the current RFC and clause content. - The
spec->impltransition MUST reject pending clauses as defined by RFC-0000:C-CLAUSE-DEF. - Changelog-only updates MUST preserve phase.
- Changelog-only updates MUST NOT change the amendment signature.
- In
impl,test, orstable, content that differs from the stored amendment signature is an unversioned amendment. - An unversioned amendment MUST be released by a version bump before further phase progression.
- A normative RFC in
impl,test, orstableMUST have a stored amendment signature. A version-changing bump or later phase progression MUST reject a missing signature without mutation and MUST leave pending clauses unchanged. - A draft RFC MUST NOT enter
stable. - A deprecated RFC MUST NOT enter
implortest.
For amendment detection, RFC content is the canonical RFC and clause data other than RFC version, phase, changelog, and signature fields. Those four fields are lifecycle or changelog bookkeeping and MUST be excluded from amendment comparison. A stored signature is the sealed content baseline for the current version after it enters impl. While the version remains in spec, establishing or replacing that baseline MUST NOT be treated as a content amendment. While the version remains in spec, establishing or replacing that baseline MUST NOT require another version bump.
Rationale:
Scoping phase to one version lets later amendments reuse the existing ordered gates. The spec phase is the mutable authoring boundary for that version, and entry into impl seals the exact contract that implementation follows. Defining the comparison surface prevents phase progression and changelog bookkeeping from recursively appearing as new content amendments. Rejecting another version-changing bump from spec prevents an unsealed candidate from becoming compatibility history. A missing signature outside spec cannot establish a trustworthy amendment baseline through a version change; it requires migration or restoration of the sealed baseline.
Tags:
core,lifecycle
Since: v1.0.0
[RFC-0000:C-REFERENCE-HIERARCHY] Artifact Reference Hierarchy (Normative)
Governance artifacts follow a strict authority hierarchy. References between artifact types MUST respect this hierarchy.
Authority Order (highest to lowest):
- RFC — Constitutional law. Defines what the system does.
- ADR — Interpretation. Documents decisions implementing RFCs.
- Work Item — Execution. Tracks work implementing ADRs and RFCs.
Structured reference rules:
Implementations MUST validate these rules during project validation (for example govctl check).
-
RFC
refsentries,[[...]]link targets, and known artifact-ID mentions in governed RFC clause text MUST NOT identify an ADR or a Work Item. -
ADR
refsentries,[[...]]link targets, and known artifact-ID mentions in governed ADR content fields MUST NOT identify a Work Item. -
Work Item
refsentries and[[...]]link targets MAY identify any artifact type except a Conformance Case. -
RFC and ADR
refsentries,[[...]]link targets, and known Conformance Case ID mentions in governed content fields MUST NOT identify a Conformance Case. Known Conformance Case ID mentions in governed Work Item prose MUST NOT identify a Conformance Case.
Known artifact-ID mentions in reviewable governed RFC clause text, governed ADR content fields, and governed Work Item prose SHOULD use [[artifact-id]] inline reference syntax. This inline syntax expectation does not apply to structured refs field entries.
For this inline syntax warning, reviewable governed prose means draft RFC clause text, proposed ADR content fields, and Work Item description, notes, and acceptance criteria for Work Items that are not done.
Project validation SHOULD report a warning when a known artifact ID appears in reviewable governed prose outside [[...]] inline reference syntax.
Project validation MAY omit this inline syntax warning for accepted, stable, deprecated, superseded, done, or otherwise historical artifacts.
Unknown artifact-ID-shaped text MAY appear as an example without being treated as an artifact reference.
This clause defines the RFC/ADR/Work Item authority hierarchy, inline reference syntax expectations, and the Conformance Case target restriction. It does not impose other target-kind restrictions for artifact types outside that hierarchy.
Rationale:
This hierarchy prevents circular dependencies and maintains clear authority chains. An RFC that links to or names an ADR or Work Item as a governed reference inverts the dependency direction — lower layers become authorities over the specification.
Conformance Cases are mutable current declarations rather than durable authorities. Prohibiting RFC, ADR, and Work Item references to them prevents later Case edits or deletion from rewriting the meaning of authoritative specifications, decisions, or historical execution records.
Inline reference syntax makes artifact links explicit in source while allowing rendered projections to remain human-readable. A validation warning gives reviewers source-level evidence for raw reference syntax without requiring them to infer it from rendered output. Limiting this warning to reviewable artifacts avoids forcing historical backfill before existing accepted or completed artifacts can pass normal project validation.
Prose outside governed reference surfaces:
Normative RFC clause text SHOULD remain self-contained. Non-governed explanatory text MAY mention artifact identifier shapes as examples, but known lower-authority artifact identifiers in governed RFC clause text and governed ADR content fields are validated as references even without [[...]] delimiters.
Tags:
core,validation
Since: v1.0.1
3. Clause Specification
[RFC-0000:C-CLAUSE-DEF] Clause Definition (Normative)
A clause is an individual requirement or statement within an RFC.
The canonical clause storage format is TOML. Repositories MUST store each clause as a TOML file containing:
[govctl]section with:id,title,kind,status- optional
[govctl]fields:since,superseded_by,anchors [content]section with:text
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Implementations MUST reject legacy clause JSON storage files (gov/rfc/<RFC-ID>/clauses/*.json) during normal operations. The diagnostic MUST instruct users to migrate those repositories with a govctl version earlier than 0.9 before upgrading to a TOML-only govctl release.
Clause kinds:
- normative: Defines a requirement. Implementations MUST comply.
- informative: Provides context. No compliance requirement.
Deprecation is a lifecycle state (in status), not a document kind.
The since field identifies the first RFC version that contains the clause. A clause whose since field is absent is a pending clause. since is lifecycle-owned: generic editing MUST NOT set, change, or remove it. Finalization and version bumps MUST assign since only to pending clauses and MUST preserve every non-pending clause’s existing since value.
Clause creation and version assignment MUST follow these rules:
- A new clause in a draft RFC MUST be pending.
- Finalizing a draft RFC as normative MUST assign the RFC’s current version to every pending clause.
- A new clause in a normative RFC whose phase is
specMUST setsinceto the RFC’s current version. - A new clause in a normative RFC whose phase is
impl,test, orstableMUST be pending. - A version bump of a normative RFC MUST assign the new RFC version to every pending clause.
- Creating a clause in a deprecated RFC MUST be rejected.
Permanent clause deletion MUST be allowed when the containing RFC is draft. Permanent clause deletion MUST also be allowed when the containing RFC is normative, its phase is spec, and the clause since equals the RFC current version. Permanent deletion MUST be rejected for every other RFC status, phase, or clause-version combination. Permanent deletion MUST reject a clause referenced by any other artifact and MUST report the referencing artifact IDs.
Advancing a normative RFC from spec to impl MUST reject every pending clause. That transition MUST NOT assign clause version metadata. That transition MUST NOT rewrite existing clause version metadata.
Rationale:
A clause can record its version immediately only after that target version is known. Initial draft clauses receive a version only at finalization, amendments created outside spec receive a version at the next normative RFC bump, and clauses added to an already-open normative spec version can safely use the current version. This preserves version provenance without making phase advancement own clause metadata. Lifecycle-only assignment and preservation make since == current version reliable evidence that a Clause belongs only to the open candidate, while the reference gate prevents dangling governance links.
Tags:
core,schema
Since: v1.0.0
4. ADR Specification
[RFC-0000:C-ADR-DEF] ADR Definition (Normative)
An ADR (Architectural Decision Record) documents a significant design decision.
Every ADR MUST be stored as a TOML file containing:
[govctl]section with:id,title,status,date,refs- optional
[govctl]field:superseded_by [content]section with:context,decision,consequences
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Implementations MUST define a machine-readable JSON Schema for the ADR file structure and MUST validate ADR files against that schema during project validation.
ADR status lifecycle:
proposed → accepted → superseded
→ rejected
proposed: Under consideration. Not yet binding.
accepted: Ratified. Design SHOULD follow this decision.
rejected: Declined after consideration. Reason documented in decision field.
superseded: Replaced by a newer ADR. Listed in superseded_by field.
Tags:
core,schema
Since: v1.0.0
[RFC-0000:C-ADR-PROJECTION-OWNERSHIP] ADR Projection Ownership (Normative)
ADR source fields and rendered projections MUST have one canonical owner for each semantic section.
The ADR renderer owns the artifact title and the fixed Context, Decision, Consequences, and Alternatives Considered section headings. The structured refs field owns the rendered reference inventory. Structured content.alternatives entries own their generated alternative headings and trade-off labels.
ADR content fields MUST contain section body prose rather than reproducing renderer-owned structure.
A conflicting heading is a Markdown heading recognized by CommonMark parsing outside a code block whose visible text, after surrounding whitespace is removed, matches one of the following using ASCII case-insensitive comparison:
- the rendered artifact title
<ADR-ID>: <title>; Context,Decision,Consequences,References,Alternatives Considered, or the semantic aliasOptions Considered;- a heading generated for a structured alternative: its
text, followed by(accepted)or(rejected)when that status suffix applies.
Project validation MUST inspect content.context, content.decision, and content.consequences in proposed ADRs for conflicting headings. Project validation MUST report a validation error for each conflict. Each diagnostic MUST identify the content field. Each diagnostic MUST identify the conflicting visible heading text.
ADR acceptance MUST apply the same projection-ownership validation before changing status. A force option that bypasses alternatives-completeness checks MUST NOT bypass projection-ownership validation.
Project validation MAY omit projection-ownership diagnostics for ADRs that are no longer proposed so that historical artifacts do not become invalid solely because govctl gained this validation.
Inline references that support nearby prose remain valid. This clause does not prohibit contextual [[...]] references inside content fields.
Rationale: A single owner for each rendered section prevents structurally valid source fields from producing duplicated or contradictory human-readable ADRs. CommonMark heading events distinguish actual headings from examples in fenced code blocks and normalize inline formatting to visible text. Acceptance-time enforcement prevents a proposed violation from escaping validation by becoming historical.
Since: v1.4.0
5. Work Item Specification
[RFC-0000:C-WORK-DEF] Work Item Definition (Normative)
A Work Item tracks a unit of work from inception through a release-eligible completion. Release membership freezes its lifecycle status.
Every Work Item MUST be stored as a TOML file containing:
[govctl]section with required fields:id,title,status,created- optional
[govctl]fields:started,completed,refs [content]section with required field:description- optional
[content]fields:acceptance_criteria,notes - optional
[verification]section with:required_guards,waivers
Omitted list-valued fields refs, acceptance_criteria, notes, verification.required_guards, and verification.waivers MUST be interpreted as empty lists.
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Implementations MUST define a machine-readable JSON Schema for the Work Item file structure and MUST validate Work Item files against that schema during project validation.
When present, verification.required_guards MUST be an array of Verification Guard IDs defined by RFC-0000:C-GUARD-DEF. These guard IDs augment project-level default guard requirements when project verification is enabled.
When present, each verification.waivers entry MUST be an object with exactly two fields: guard and reason.
The guard field MUST name exactly one Verification Guard ID.
The reason field MUST be a non-empty string.
Waiver entries MUST reference only guards that appear in the work item’s effective required guard set. Duplicate waivers for the same guard MUST be rejected during validation.
A waiver MUST suppress only the named guard. A Work Item MUST NOT disable the verification system globally.
Work Item status transitions:
queue → active
queue → cancelled
active → done
active → cancelled
done → active (unreleased only)
queue: Planned but not started.
active: Currently in progress. Only one active item recommended per focus area.
done: Completed and eligible for release. All acceptance criteria met, and any required verification guards have passed or been explicitly waived.
cancelled: Abandoned from queue or active. Reason documented in notes.
A Work Item MUST contain at least one acceptance criterion before it transitions to done.
A Work Item MUST NOT transition to done if any acceptance criteria are pending.
A done Work Item that is not referenced by a release MUST be allowed to return to active. This transition MUST preserve started and remove completed.
A Work Item referenced by a release MUST remain done.
Rationale: An unreleased completion is a correctable judgment. Release membership supplies the immutable lifecycle boundary without adding another persisted Work Item status. Omitting empty list fields keeps the TOML representation minimal without changing the logical data model.
Tags:
core
Since: v1.0.0
6. Release Specification
[RFC-0000:C-RELEASE-DEF] Release Definition (Normative)
A Release is a local version-cut record that groups completed Work Items under a semantic version. A Release records local governance state; it is not proof that Git tags, hosted releases, packages, or other external artifacts were published.
Release data MUST be stored as a TOML file at gov/releases.toml containing:
[[releases]]array with entries containing:version,date,refs
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Each releases[].version MUST be a valid semantic version.
Each releases[].date MUST use ISO 8601 calendar date format YYYY-MM-DD.
Each releases[].refs entry MUST reference an existing Work Item ID whose status is done.
A Work Item ID MUST appear in the refs of at most one release.
A release cut MUST include every Work Item whose status is done and which is not referenced by an existing release. It MUST reject the cut without modifying governed artifacts when no such Work Item exists.
When a release cut omits --date, it MUST use the current calendar date in the host’s local timezone.
Release entries MUST be stored newest-first. Release creation MUST prepend the new entry to the releases array.
A Work Item referenced by any release MUST remain done. Lifecycle commands MUST reject transitions away from done for that Work Item.
Project validation MUST report a release reference to a Work Item whose status is not done.
Project validation MUST report a Work Item ID referenced by more than one release.
A release entry has no persistent lifecycle status. An existing entry MUST remain immutable except when the newest entry is removed through the guarded latest-release correction defined below.
The latest-release correction MUST require an expected version. The correction MUST reject an empty release history or an expected version that does not exactly match the newest entry’s version without modifying governed artifacts.
A successful latest-release correction MUST remove only the newest release entry. It MUST NOT mutate the referenced Work Items; those items remain done and become unreleased because no release references them.
The latest-release correction MUST mutate only canonical release data. It MUST NOT create, remove, or modify CHANGELOG.md, Git tags, hosted releases, or published packages.
After a latest-release correction, govctl render changelog --force MUST derive release membership only from the current canonical release entries. The full projection MUST omit release versions absent from canonical release data and MUST classify as unreleased every done Work Item not referenced by a current release.
Implementations MUST define a machine-readable JSON Schema for the release file structure and MUST validate gov/releases.toml against that schema during project validation.
Rationale:
Release membership is the immutability boundary for a completed Work Item while its release entry exists. Unique membership and a frozen done status preserve release history. Restricting correction to the newest entry restores the immediately preceding local state without permitting arbitrary history rewriting, while the expected-version check rejects stale operator intent.
Tags:
core,release
Since: v1.0.2
7. Verification Guard Specification
[RFC-0000:C-GUARD-DEF] Verification Guard Definition (Normative)
A Verification Guard defines a reusable executable completion check for a govctl project.
Every Verification Guard MUST be stored as a TOML file under gov/guard/ containing:
[govctl]section with:id,title- optional
[govctl]field:refs [check]section with:command- optional
[check]fields:timeout_secs,pattern
Format evolution is tracked by the project-level [schema] version in gov/config.toml, not per-artifact fields.
Implementations MUST define a machine-readable JSON Schema for the Verification Guard file structure and MUST validate guard files during project validation.
Verification Guard IDs MUST be unique within a repository.
A guard check MUST execute its command non-interactively from the project root.
If timeout_secs is absent, implementations MUST use a default timeout of 300 seconds.
A guard check that exceeds its timeout MUST fail.
A guard check MUST evaluate pattern, when present, against the combined standard output and standard error streams using case-insensitive regular-expression matching.
A guard check MUST pass only when the command exits successfully. If pattern is provided, the combined output MUST also match that pattern.
Rationale: Verification Guards make completion rules explicit, reusable, and machine-executable so agents cannot satisfy them with checklist text alone.
Tags:
core,validation
Since: v1.1.0
Changelog
v1.9.0 (2026-07-27)
Define Conformance Case authority boundary
Added
- Recognize Conformance Cases as derived governance resources
Changed
- Exclude Conformance Cases as RFC, ADR, and Work Item reference targets
v1.8.0 (2026-07-26)
Define contained Clause reference resolution
Fixed
- Reject dangling Clause references
Security
- Require Clause references to resolve within their RFC directory
v1.7.0 (2026-07-20)
Define single-candidate RFC version boundaries
Changed
- Restrict version-changing bumps to sealed RFC versions
- Allow deletion of unreferenced Clauses introduced in the current spec candidate
v1.6.1 (2026-07-16)
Clarify Clause version assignment at RFC publication boundaries
Fixed
- Keep draft Clause versions pending until normative finalization
v1.6.0 (2026-07-16)
Define current-version RFC authoring and changelog invariants
Changed
- Defined spec-phase sealing, Clause version assignment, and current changelog ownership
v1.5.0 (2026-07-15)
Define guarded correction for local release cuts
Added
- Define guarded newest-release correction and canonical changelog projection
Changed
- Define Releases as local version-cut records
v1.4.2 (2026-07-15)
Clarify optional Work Item verification lists
Changed
- Define omitted verification guard and waiver lists as empty
v1.4.1 (2026-07-15)
Clarify Work Item serialized field requirements
Changed
- Allow empty Work Item list fields to be omitted while requiring created metadata and completion criteria
v1.4.0 (2026-07-15)
Clarify lifecycle and ADR projection boundaries
Added
- Define ADR projection ownership validation
Changed
- Scope RFC phase to each version
- Freeze Work Items at unique release membership
v1.3.3 (2026-06-11)
Clarify inline reference validation
Changed
- Project validation should warn on known artifact IDs in governed prose that are not written with inline reference syntax
v1.3.2 (2026-06-04)
Align reference hierarchy wording
Changed
- reference hierarchy wording now describes only the RFC-to-ADR-or-Work Item and ADR-to-Work Item prohibitions
v1.3.1 (2026-06-04)
Close plain-text reference hierarchy loophole
Changed
- Known lower-authority artifact IDs in governed RFC/ADR prose are validated even without [[…]] delimiters
v1.3.0 (2026-06-04)
Remove legacy JSON artifact storage compatibility
Removed
- legacy RFC and clause JSON storage is no longer supported in normal operation
v1.2.0 (2026-05-31)
Remove a legacy execution-history field from Work Item field operations
Changed
- historical execution entries may still be parsed for Work Item rendering
Removed
- legacy execution-history field is no longer path-addressable per ADR-0047
v1.1.1 (2026-03-22)
Clarify machine-validated reference hierarchy for refs and [[…]]
Added
- Structured rules: RFC must not link ADR/WI; ADR must not link WI
v1.1.0 (2026-03-17)
Add verification guards and work-item verification metadata
Added
- Added Verification Guard artifact definition and work-item verification fields
v1.0.2 (2026-03-17)
Record release artifact clause and migration amendments
v1.0.1 (2026-01-26)
Add artifact reference hierarchy clause
Added
- Add C-REFERENCE-HIERARCHY clause defining that RFCs must not reference ADRs
v1.0.0 (2026-01-17)
Initial stable release of the govctl governance framework.
Added
- RFC specification with status and phase lifecycle
- Clause specification for normative and informative requirements
- ADR specification for architectural decisions
- Work Item specification for task tracking
RFC-0001: Lifecycle State Machines
Version: 0.7.0 | Status: normative | Phase: stable Owners: @govctl-org Tags:
core,lifecycle
1. Summary
[RFC-0001:C-SUMMARY] Summary (Informative)
This RFC defines state machines governing RFC, ADR, Work Item, and Clause lifecycles, including the additional transition gates that control when work may be treated as complete.
Tags:
lifecycle
Since: v0.1.0
2. Specification
[RFC-0001:C-RFC-STATUS] RFC Status Transitions (Normative)
An RFC MUST have exactly one of the following status values:
- draft — Initial state. The RFC is under development and not yet binding.
- normative — The RFC defines required behavior. Implementations MUST conform. Normative RFCs MAY be amended via version bumping; amendments MUST include a changelog entry documenting the change.
- deprecated — The RFC is no longer recommended. Existing conforming implementations MAY continue, but new implementations SHOULD NOT use this RFC.
Valid transitions:
- draft → normative (via
finalizecommand) - normative → deprecated (via
deprecatecommand)
Invalid transitions (MUST be rejected):
- normative → draft (no “un-finalize”)
- deprecated → normative (no resurrection)
- deprecated → draft (no resurrection)
- Any skip (e.g., draft → deprecated directly)
Tags:
lifecycle
Since: v0.1.0
[RFC-0001:C-RFC-PHASE] RFC Phase Transitions (Normative)
An RFC MUST have exactly one of the following phase values. The phase describes conformance work for the RFC’s current version:
- spec - Specification phase. The current version candidate is being written. Implementation work against that candidate is not permitted.
- impl - Implementation phase. Code is being written to conform to the sealed current version.
- test - Testing phase. Implementation is complete; tests are being written and validated against the sealed current version.
- stable - Stable phase. Implementation and tests for the sealed current version are complete.
Within one RFC version, valid transitions are forward only via the advance command:
- spec -> impl
- impl -> test
- test -> stable
Within one RFC version, the following transitions MUST be rejected:
- Any backward transition (for example, impl -> spec)
- Any skip (for example, spec -> test or spec -> stable)
- stable -> any (
stableis terminal for that version)
A version bump that releases a detected RFC or clause content amendment MUST start the new RFC version in spec, regardless of the prior version’s phase. This starts a new version lifecycle and is not a backward transition within one version. Version-changing bump eligibility MUST follow RFC-0000:C-PHASE-LIFECYCLE.
Only a normative RFC MAY advance from spec to impl. A normative RFC’s current spec content is an authoring candidate rather than an implementation conformance baseline. The most recently sealed version remains the implementation baseline until the current candidate enters impl.
RFC and clause content MAY change while the current version remains in spec. Such changes belong to the current version. Such changes MUST NOT require another version bump. Advancing from spec to impl MUST set or replace the current version’s stored signature with the current amendment content. The transition MUST reject every pending clause defined by RFC-0000:C-CLAUSE-DEF.
After the current version enters impl, amendment content that differs from the stored signature MUST be treated as an unversioned amendment. Phase progression MUST reject that amendment until a version bump releases it and starts the next version in spec.
Changelog-only updates MUST preserve the current phase. Changelog-only updates MUST preserve the current signature. Establishing or replacing the signature while sealing a spec version MUST preserve the selected RFC version.
Amendment content and bookkeeping fields are defined by RFC-0000:C-PHASE-LIFECYCLE.
Rationale:
Scoping phase to the current RFC version preserves ordered specification, implementation, and testing gates while allowing the RFC itself to evolve through versioned amendments. Treating spec as the current version’s mutable authoring boundary avoids version inflation, while sealing at impl gives implementation a precise contract.
Tags:
lifecycle
Since: v0.1.0
[RFC-0001:C-WORK-STATUS] Work Item Status Transitions (Normative)
A Work Item MUST have exactly one of the following status values:
- queue — Initial state. The work item is defined but not yet started.
- active — The work item is currently being worked on.
- done — The work item is complete and eligible for release. All acceptance criteria are satisfied, and any required verification guards have passed or been explicitly waived.
- cancelled — The work item was abandoned. No further work will be done.
Valid transitions via the move command are:
- queue → active (start work)
- queue → cancelled (abandon before starting)
- active → done (complete work)
- active → cancelled (abandon in progress)
- done → active when no release references the Work Item (correct a pre-release completion)
The following transitions MUST be rejected:
- done → active when any release references the Work Item
- done → queue or cancelled
- cancelled → any (
cancelledis terminal) - queue → done (cannot complete without being active)
- active → queue (no “un-start”)
Release membership is derived from releases[].refs; it does not add another Work Item status. A released Work Item MUST remain done.
Timestamp behavior:
- queue → active: Sets
startedif it is not already set - active → done: Sets
completed - active → cancelled: Sets
completed - done → active: Preserves
startedand removescompleted
Returning a Work Item to done after reopening MUST apply the same acceptance-criteria and verification-guard gates as any other active → done transition.
Reopening a Work Item MUST NOT mutate existing loop state or round artifacts. Existing loop-local done, failed, and cancelled outcomes remain terminal according to RFC-0006:C-WORK-ITEM-INTERACTION, RFC-0006:C-LOOP-RESUMPTION, and RFC-0006:C-LOOP-SCOPE-MUTATION. A reopened Work Item can be executed through a new loop or explicit non-terminal loop scope according to those clauses.
Rationale:
Completion remains correctable until release membership freezes the lifecycle record. Clearing completed on reopening keeps status and timestamp semantics consistent, while release membership prevents the same Work Item ID from re-entering later release collection. Keeping loop outcomes separate preserves existing execution audit history.
Tags:
lifecycle
Since: v0.1.0
[RFC-0001:C-ADR-STATUS] ADR Status Transitions (Normative)
An ADR MUST have exactly one of the following status values:
- proposed — Initial state. The decision is under consideration.
- accepted — The decision has been accepted and is in effect.
- rejected — The decision was considered and explicitly declined.
- superseded — The decision has been replaced by another ADR.
Valid transitions:
- proposed → accepted (via
acceptcommand) - proposed → rejected (via
rejectcommand) - accepted → superseded (via
supersedecommand, requires--byto specify replacement)
Invalid transitions (MUST be rejected):
- proposed → superseded (cannot supersede without first accepting)
- accepted → proposed (no “un-accept”)
- accepted → rejected (accepted decisions must be superseded, not retroactively rejected)
- rejected → any (rejected is terminal)
- superseded → any (superseded is terminal)
When an ADR is superseded:
- The
superseded_byfield MUST be set to the ID of the replacing ADR - The replacing ADR SHOULD reference the superseded ADR
When an ADR is rejected:
- The ADR MUST remain available as historical record
- The
superseded_byfield MUST NOT be set
Tags:
lifecycle
Since: v0.1.0
[RFC-0001:C-CLAUSE-STATUS] Clause Status Transitions (Normative)
A Clause MUST have exactly one of the following status values:
- active — Default state. The clause is in effect.
- deprecated — The clause is no longer recommended but still valid.
- superseded — The clause has been replaced by another clause.
Valid transitions:
- active → deprecated (via
deprecatecommand) - active → superseded (via
supersedecommand, requires replacement clause) - deprecated → superseded (already deprecated, now replaced)
Invalid transitions (MUST be rejected):
- deprecated → active (no resurrection)
- superseded → any (superseded is terminal)
A clause supersession transition has the following preconditions:
- The replacing clause MUST exist.
- The replacing clause MUST be active when the transition is performed.
- The replacing clause MUST be different from the clause being superseded.
- A replacing clause in another RFC MUST be identified by its qualified
RFC-NNNN:C-NAMEID.
The transition MUST be rejected if any required precondition is not satisfied.
After a successful clause supersession transition:
- The source clause status MUST be
superseded. - The source clause
superseded_byfield MUST identify the direct replacing clause selected for that transition. - The replacing clause SHOULD have a
sincefield indicating the version it was introduced.
Every populated superseded_by field defines a directed edge from its source clause to its target clause. The clause supersession graph consists of these edges across every RFC in the governed project.
Repository validation MUST reject an edge whose target clause does not exist. Repository validation MUST NOT reject an existing edge solely because its target clause was later deprecated or superseded.
If clause A identifies clause B as its direct replacement and B is later replaced by clause C, B MUST identify C as its direct replacement. Clause A MUST continue to identify B. The clause supersession graph MUST NOT contain a cycle. Repository validation MUST reject a graph that contains a cycle.
Rationale:
Transition-time checks ensure that a newly selected replacement is in effect. Persisted edges record historical direct replacements, so later clause evolution does not invalidate or erase prior provenance. Qualified IDs allow the same model to represent unambiguous replacements across RFC boundaries.
Tags:
lifecycle
Since: v0.1.0
[RFC-0001:C-GATE-CONDITIONS] Transition Gate Conditions (Normative)
Certain transitions have additional gate conditions beyond the state machine rules.
Work Item -> done:
- The work item MUST have at least one acceptance criterion defined.
- All acceptance criteria MUST have status
doneorcancelled. - Every guard named in the work item’s
verification.required_guardsMUST pass or be explicitly waived with a reason. - If project verification is enabled, every project-level default guard MUST also pass or be explicitly waived with a reason.
The effective required verification guards are the union of the work item’s verification.required_guards and, only when project verification is enabled, the project’s configured default guards. Only guards covered by explicit waivers are removed from that set.
Rationale: Prevents marking work as complete without defined success criteria or executable completion proof.
RFC draft -> normative:
- No additional gates (policy decision, not structural).
RFC phase spec -> impl:
- RFC status MUST be normative.
- Every clause MUST have a resolved
sinceversion under RFC-0000:C-CLAUSE-DEF.
Rationale: Implementation must follow a ratified and version-resolved specification.
RFC phase impl -> test:
- No additional gates.
RFC phase test -> stable:
- No additional gates (assumes tests are passing externally).
Future gates MAY be added via RFC amendment, but MUST NOT break existing valid workflows. Project verification MUST default to disabled when the project config does not opt into it.
Tags:
lifecycle,validation
Since: v0.1.0
Changelog
v0.7.0 (2026-07-20)
Clarify RFC candidate phase transitions
Changed
- Bind version bumps and signature sealing to explicit phase boundaries
v0.6.0 (2026-07-16)
Align RFC phase gates with current-version sealing
Changed
- Required normative status and resolved Clause versions before implementation entry
v0.5.0 (2026-07-15)
Scope terminal states to versions and releases
Changed
- Restart phase progression for amended RFC versions
- Allow unreleased done Work Items to return to active
v0.4.2 (2026-06-28)
Split direct-edge preservation requirements
Changed
- Express B-to-C insertion and A-to-B preservation as separate testable obligations
v0.4.1 (2026-06-28)
Clarify clause supersession validation boundaries
Added
- Define project-wide direct-edge graph semantics and explicit rejection behavior for missing targets and cycles
Changed
- Separate transition-time replacement checks from persisted graph validation
- Document the distinct-target rule and preserve historical edges after target status changes
v0.4.0 (2026-06-28)
Define direct clause supersession chains
Added
- Require active transition targets, qualified cross-RFC references, and acyclic supersession graphs
Changed
- Treat superseded_by as a persistent direct replacement edge
v0.3.0 (2026-03-17)
Add executable verification gates to work completion
Added
- Added required verification guard gate conditions for work completion
v0.2.1 (2026-01-26)
Remove ADR reference from C-RFC-STATUS; RFCs are self-contained and should not reference ADRs
Added
- Inline amendment rule in C-RFC-STATUS clause (was referencing ADR-0016)
v0.2.0 (2026-01-19)
Clarify that normative RFCs may be amended via version bumping
v0.1.0 (2026-01-17)
Initial draft
RFC-0002: CLI Resource Model and Command Architecture
Version: 3.6.0 | Status: normative | Phase: stable Owners: @govctl-org Tags:
cli,editing,lifecycle,validation,release
1. Summary
[RFC-0002:C-SUMMARY] Summary (Informative)
This RFC defines the resource-first command architecture for the govctl CLI. It establishes normative requirements for command structure, resource types, verb semantics, and project-level verification commands to ensure consistency and discoverability.
The design follows established patterns from Docker, kubectl, and other modern CLIs where commands are grouped by resource type (noun-first) rather than operation type (verb-first).
Scope: This RFC specifies the structural contract (which commands exist, how they’re organized, what resources they operate on). Implementation details (flag syntax, help text formatting, terminal colors) are left to ADRs.
Rationale: A stable command structure enables:
- Predictable UX across all resource types
- Agent/script automation via consistent patterns
- Scoped help and command discovery
- Future extensibility without namespace pollution
Tags:
cli
Since: v0.1.0
2. Specification
[RFC-0002:C-RESOURCE-MODEL] Resource-First Command Structure (Normative)
The govctl CLI MUST use a resource-first command structure. Except for the stable release-creation form defined below, resource operations MUST use:
govctl <resource> <verb> [arguments] [flags]
Where:
<resource>is a governance artifact type such asrfc,adr,work,clause,release, orguard<verb>is an operation defined for that resource, such asnew,list,get,show,edit,delete, or a resource-specific lifecycle operation[arguments]are positional parameters with stable roles[flags]are modifiers defined by the selected operation
Only command and subcommand names defined by normative RFC clauses are part of the accepted CLI grammar. Implementations MUST reject alternative command-name and subcommand-name aliases. This restriction does not prohibit short option flags that are part of a documented command syntax.
Global command exceptions are governed by RFC-0002:C-GLOBAL-COMMANDS. A command MAY remain at the global namespace when it operates across multiple resource types, performs project-level or CLI-level work, or manages local execution state that coordinates governed resources without becoming a governed artifact resource.
Resource-specific CRUD, field-editing, and lifecycle operations MUST remain resource-first unless an RFC explicitly defines an alternative grammar.
Release creation is a stable alternative grammar. Implementations MUST support govctl release <version> [--date <YYYY-MM-DD>].
Release correction is a resource-first operation. Implementations MUST support govctl release undo <expected-version>.
Both release forms MUST coexist. The token undo selects correction because it is not a valid semantic version; a semantic-version token selects release creation.
Rationale:
Resource-first organization provides scoped discovery, clear namespaces, stable argument roles, and room to extend one resource without polluting the global namespace. A canonical-only command vocabulary removes parser ambiguity and prevents documentation and agent metadata from teaching multiple spellings for the same operation.
Tags:
cli
Since: v0.1.0
[RFC-0002:C-RESOURCES] Resource Types (Normative)
The following resource types MUST be supported as top-level command namespaces:
1. rfc - Request for Comments
Manages RFC specifications (normative documents defining system behavior).
- ID Format:
RFC-NNNN(e.g., RFC-0001) - Lifecycle: draft → normative → deprecated (per RFC-0001:C-RFC-STATUS)
- Phase: spec → impl → test → stable (per RFC-0001:C-RFC-PHASE)
2. adr - Architecture Decision Record
Manages ADRs (records of architectural decisions).
- ID Format:
ADR-NNNN(e.g., ADR-NNNN-style IDs) - Lifecycle: proposed → accepted → superseded, or proposed → rejected (per RFC-0001:C-ADR-STATUS)
3. work - Work Item
Manages Work Items (tasks, features, bugs).
- ID Format:
WI-YYYY-MM-DD-NNN(e.g., WI-YYYY-MM-DD-NNN) - Lifecycle: queue → active → done, with cancellation at any stage (per RFC-0001:C-WORK-STATUS)
4. clause - RFC Clause
Manages individual clauses within RFCs.
- ID Format:
RFC-NNNN:C-NAME(e.g., RFC-0001:C-SUMMARY) - Lifecycle: active → deprecated → superseded (per RFC-0001:C-CLAUSE-STATUS)
Clause Namespace vs Storage:
Clauses remain at the CLI top-level namespace despite being child resources of RFCs because their ID format (RFC-NNNN:C-NAME) is self-scoping and unambiguous.
The CLI namespace is independent of filesystem layout. Implementations MAY store clause files nested under RFC directories (e.g., gov/rfc/RFC-0001/clauses/C-NAME.toml) while maintaining the flat CLI command structure (govctl clause get RFC-0001:C-NAME).
5. guard - Verification Guard
Manages reusable executable completion checks defined by RFC-0000:C-GUARD-DEF.
- ID Format:
GUARD-NAME(e.g., GUARD-CARGO-TEST) - Storage:
gov/guard/as individual TOML files - No lifecycle (guards are either present or removed)
6. conformance - Conformance Case
Manages current non-normative acceptance-scenario declarations.
- ID Format:
CONF-[A-Z][A-Z0-9-]*(e.g.,CONF-RFC-BUMP) - Storage:
gov/conformance/as individual TOML files - No persistent lifecycle status
7. release - Release Cut
Manages local version-cut records and their included Work Item references.
- ID Format: Semantic version (e.g., 1.0.0)
- Storage:
gov/releases.tomlas defined by RFC-0000:C-RELEASE-DEF - Mutation boundary: the newest entry may be corrected through
release undo; all other entries are immutable - No persistent lifecycle status
Resource Identification:
Each resource type MUST have a unique, predictable ID format that:
- Is stable across filesystem operations
- Can be referenced in other artifacts
- Clearly identifies the resource type without context
- Supports lexicographic sorting where meaningful
- Is case-sensitive (RFC-0001 ≠ rfc-0001)
Date Format:
All date-valued resource metadata fields (such as created, updated, started, completed, and date) MUST use ISO 8601 calendar date format YYYY-MM-DD.
Tags:
RFCs, clauses, ADRs, Work Items, guards, and Conformance Cases MAY include an optional tags array in the [govctl] section. Each tag MUST be a string from the project’s controlled vocabulary defined in gov/config.toml under [tags] allowed. Tags MUST match the pattern [a-z][a-z0-9-]* (lowercase kebab-case). Releases do not carry tags. govctl check MUST reject any artifact that references a tag not present in the allowed set.
Future Extensions:
Additional resource types MAY be added via RFC amendment. New resource types MUST follow the same structural patterns defined in RFC-0002:C-CRUD-VERBS.
Tags:
cli,schema
Since: v0.1.0
[RFC-0002:C-CRUD-VERBS] Universal CRUD Verbs (Normative)
Governed artifact resources MUST expose the following universal operations where applicable. Release records MUST NOT expose these operations; their constrained creation and correction commands are defined by RFC-0002:C-LIFECYCLE-VERBS.
1. new - Create Resource
Syntax: govctl <resource> new <arguments>
new MUST be supported for RFCs, ADRs, Work Items, Clauses, Guards, and Conformance Cases. It MUST validate inputs. It MUST generate or validate the resource ID. It MUST initialize schema-defined defaults and create the canonical storage structure.
Guard creation through govctl guard new "<title>" MUST scaffold a Guard TOML file under gov/guard/. The generated ID MUST use the GUARD- prefix. The command SHOULD print guidance for adding the Guard to project verification policy.
2. list - List Resources
Syntax: govctl <resource> list [status] [--tag <tag>[,<tag>...]]
list MUST be supported for RFCs, ADRs, Work Items, Clauses, Guards, and Conformance Cases. Results MUST be sorted lexicographically by ID. A positional status filter, where supported by the resource lifecycle, MUST accept only that resource’s defined status values. Tag filtering MUST require every requested tag. Tag filtering MUST accept comma-separated tag values for taggable resource types. Output MUST follow RFC-0002:C-OUTPUT-FORMAT.
3. get - Read Resource
Syntax: govctl <resource> get <id> [field]
get MUST be supported for RFCs, ADRs, Work Items, Clauses, Guards, and Conformance Cases. With no field, it returns the complete structured resource. With a field, it returns that logical field value. Unknown resources and fields MUST be rejected. Output MUST follow RFC-0002:C-OUTPUT-FORMAT.
Field identifiers exposed by get MUST be logical artifact field names rather than persisted table-layout paths. Renaming a logical field identifier requires a breaking govctl release.
4. show - Present Resource
Syntax: govctl <resource> show <id> [--history] [--output <format>]
show MUST be supported as defined by RFC-0002:C-SHOW-PROJECTION.
5. edit - Mutate Resource
Syntax:
govctl <resource> edit <id> <path> --set [<value>]
govctl <resource> edit <id> <path> --add [<value>]
govctl <resource> edit <id> <path> --remove [<pattern>]
govctl <resource> edit <id> <path> --tick <status>
edit MUST be supported for RFCs, ADRs, Work Items, Clauses, Guards, and Conformance Cases. It MUST be the only universal field-mutation subcommand for those resources. These resources MUST NOT expose set, add, remove, or tick as sibling mutation subcommands.
An edit invocation MUST select exactly one mutation operation. --stdin MAY supply the value for --set or --add. Selectors and their exclusivity rules are defined by RFC-0002:C-EDIT-FIELD-CONTRACT.
A path MUST use a canonical logical path defined by RFC-0002:C-EDIT-FIELD-CONTRACT. Nested object and array traversal MUST use dotted and indexed segments such as alternatives[0].pros. The parser MUST consume the complete path. Unknown fields MUST be rejected. Invalid indices MUST be rejected. Aliases and wire-layout prefixes MUST be rejected. An operation not permitted for the addressed path MUST be rejected.
The same edit grammar and flag roles MUST apply across supported resource types. Resource-specific compatibility flags MUST be rejected. Values MUST be validated against the addressed field type before writing. A failed edit MUST leave the artifact unchanged.
6. delete - Delete Resource
Syntax: govctl <resource> delete <id>
delete MUST be supported for Work Items, Clauses, Guards, and Conformance Cases. RFCs and ADRs MUST use their lifecycle operations instead.
For Guards, deletion MUST reject references from Work Item verification requirements, Work Item waivers, project default Guards, and Conformance Case guard bindings.
For Clauses, deletion MUST enforce RFC-0000:C-CLAUSE-DEF and report every governed referrer that prevents deletion.
For Work Items, deletion MUST require queue status and MUST reject any governed referrer.
Deletion SHOULD require confirmation unless an explicit force option is provided. A delete operation MUST be atomic.
Consistency requirements:
- ID arguments MUST precede field paths across resources.
- Equivalent universal operations MUST use the same flag names and exit-code conventions.
- Error messages MUST identify the rejected resource, field path, or value.
- Input transport such as stdin MUST NOT change mutation semantics.
- A mutating universal operation invoked with
--dry-runMUST perform the same validation and target selection as execution, MUST report the planned mutation, and MUST leave persistent state unchanged.
Rationale:
A path-oriented mutation command lets users and agents select a field and then apply one permitted operation. A closed canonical field contract removes ambiguous spellings while retaining set, add, remove, and checklist-transition capabilities.
Tags:
cli,editing
Since: v0.1.0
[RFC-0002:C-LIFECYCLE-VERBS] Resource-Specific Lifecycle Operations (Normative)
Resource-specific lifecycle and constrained-mutation operations implement state transitions defined in RFC-0001 or mutation defined by their resource contract. These operations MUST be scoped to their resource namespace.
RFC Lifecycle Operations:
-
govctl rfc finalize <id> normative- Implements the draft -> normative transition in RFC-0001:C-RFC-STATUS.
- Assigns the RFC’s current version to pending clauses as defined by RFC-0000:C-CLAUSE-DEF.
-
govctl rfc deprecate <id>- Implements the normative -> deprecated transition in RFC-0001:C-RFC-STATUS.
-
govctl rfc advance <id> <spec|impl|test|stable>- Implements RFC-0001:C-RFC-PHASE transitions.
- Phase progression MUST be forward-only within the current RFC version.
- A
spec->impltransition MUST require normative RFC status. - A
spec->impltransition MUST reject every pending clause. - A
spec->impltransition MUST NOT assign clause version metadata. - A
spec->impltransition MUST set or replace the stored amendment signature with a signature of the current amendment content. - A later phase transition MUST reject amendment content that differs from the stored signature.
-
govctl rfc bump <id> <patch|minor|major> -m <message>- The version-changing form MUST require normative RFC status.
- The version-changing form MUST enforce the source-phase and stored-signature eligibility in RFC-0000:C-PHASE-LIFECYCLE.
- Rejection for draft or deprecated RFC status, phase
spec, or a missing sealed signature MUST occur without mutation. - Missing-signature rejection outside
specMUST leave pending clauses unchanged and MUST instruct the user to migrate the repository or restore its sealed baseline. - Version bumping MUST follow semantic versioning.
- A version bump MUST update the changelog automatically.
- A version bump MAY include
--change <description>for additional changelog entries. - A version bump MUST be rejected when the RFC has a stored amendment signature and no amendment content has changed since that signature.
- Amendment comparison MUST exclude RFC
version,phase,changelog, andsignaturefields. - A bump that releases detected RFC or clause content MUST set phase to
spec. - A bump MUST assign its new version to pending clauses as defined by RFC-0000:C-CLAUSE-DEF.
--changewithout a bump level MUST remain a changelog-only operation.- The normative-status and source-phase requirements for version-changing bumps MUST NOT apply to
--changewithout a bump level. --changewithout a bump level MUST resolve the unique current changelog entry by matching the entry version to the RFC version.--changewithout a bump level MUST reject zero or multiple current entries without mutation.--changewithout a bump level MUST preserve the RFC version.--changewithout a bump level MUST preserve the current changelog date.--changewithout a bump level MUST preserve phase.--changewithout a bump level MUST preserve the amendment signature.--changewithout a bump level MUST NOT make a later version bump valid.- A change prefixed by
add:,change:,deprecate:,remove:,fix:, orsecurity:MUST be appended to the corresponding changelog category. - A change without a category prefix MUST be appended to
added. - An unknown category prefix MUST be rejected.
-
RFC current-version changelog access
govctl rfc get <id> changelogMUST expose only the unique changelog entry whose version matches the RFC’s current version.- The field result MUST be one object rather than an array.
- The object MUST contain
version,date,summary,added,changed,deprecated,removed,fixed, andsecurityfields. summaryMAY be a string or null.- Each categorized field MUST be an array of strings.
- Full-resource retrieval and RFC rendering MAY include historical changelog entries.
- Indexed changelog get paths MUST be rejected.
- Nested changelog get paths MUST be rejected.
govctl rfc edit <id> changelog.summary --set <value>MUST update the current entry’s summary.govctl rfc edit <id> changelog.<category> --add <value>MUST append to one ofadded,changed,deprecated,removed,fixed, orsecurity.govctl rfc edit <id> changelog.<category>[<index>] --removeMUST remove an indexed item from the current category.- Current-entry resolution MUST match by version.
- Current-entry resolution MUST NOT depend on changelog array position.
- Current-changelog operations MUST reject zero or multiple current entries without mutation.
- Changelog editing MUST reject historical entry selection.
- Changelog editing MUST reject changelog
versionanddatepaths. - RFC editing MUST reject the top-level RFC
versionpath. - Changelog editing MUST preserve the RFC version.
- Changelog editing MUST preserve phase.
- Changelog editing MUST preserve the amendment signature.
- Changelog editing MUST preserve the current changelog date.
-
govctl rfc supersede <id> --by <replacement-id>- Marks RFC as superseded by another RFC.
- Both RFCs must exist.
ADR Lifecycle Operations:
-
govctl adr accept <id>- Implements RFC-0001:C-ADR-STATUS proposed -> accepted.
-
govctl adr reject <id>- Implements RFC-0001:C-ADR-STATUS proposed -> rejected.
-
govctl adr supersede <id> --by <replacement-id>- Implements RFC-0001:C-ADR-STATUS accepted -> superseded.
- Both ADRs must exist.
Work Lifecycle Operations:
govctl work move <id> <queue|active|done|cancelled>- Implements RFC-0001:C-WORK-STATUS transitions.
- Validates gate conditions when entering
done. - MUST reject done -> active when any release references the Work Item.
- queue -> active MUST set
startedwhen it is absent. - active -> done MUST set
completed. - active -> cancelled MUST set
completed. - done -> active MUST preserve
started. - done -> active MUST remove
completed. - done -> active MUST NOT mutate loop state or round artifacts governed by RFC-0006:C-WORK-ITEM-INTERACTION.
Release Lifecycle Operations:
-
The CLI MUST support
govctl release <version> [--date <YYYY-MM-DD>]. The operation MUST create the newest local release entry according to RFC-0000:C-RELEASE-DEF. -
The CLI MUST support
govctl release undo <expected-version>. The operation MUST correct the newest local release entry according to RFC-0000:C-RELEASE-DEF.
Clause Lifecycle Operations:
-
govctl clause new <id> <title>- MUST assign or defer
sinceaccording to the parent RFC status and phase rules in RFC-0000:C-CLAUSE-DEF.
- MUST assign or defer
-
govctl clause deprecate <id>- Implements RFC-0001:C-CLAUSE-STATUS active -> deprecated.
-
govctl clause supersede <id> --by <replacement-id>- Implements RFC-0001:C-CLAUSE-STATUS active/deprecated -> superseded.
- Both clauses must exist.
Consistency Requirements:
- All lifecycle operations MUST validate transitions per RFC-0001 or their resource definition.
- All lifecycle operations MUST update timestamp fields where applicable.
- Except for the rollback-failure path in requirement 4, before a lifecycle invocation exits with a non-zero status, it MUST restore each governed-artifact path it created, deleted, or wrote to the path-existence state observed at baseline and, when that path existed at baseline, to its baseline byte content.
- If an I/O or storage error prevents complete restoration, the invocation MUST return a non-zero exit status.
- The rollback-failure diagnostic MUST contain the term
rollback. - The rollback-failure diagnostic MUST state that governed-artifact restoration may be incomplete.
- For each governed-artifact path covered by requirement 3, the restoration baseline is whether its resolved path existed and, when it existed, its artifact byte content observed after the invocation acquires its exclusive write scope under RFC-0004:C-SCOPE and before its first governed-artifact mutation.
- Unexpected process termination before restoration completes, host failure, and the rollback-failure path in requirement 4 are outside the lifecycle atomicity guarantee.
- Permissions, ownership, timestamps, and other filesystem metadata are outside the lifecycle atomicity guarantee.
- All lifecycle operations MUST support global
--dry-runflag. - Invalid transitions MUST error with clear explanation of valid transitions.
Rationale:
Lifecycle operations are resource-specific because:
- RFCs have status AND phase (two dimensions of state).
- ADRs can be rejected (not applicable to RFCs).
- Work Items have gate conditions (acceptance criteria).
- Release correction has a newest-entry and expected-version boundary.
- Each resource has different valid transitions.
Scoping these operations to resources makes their applicability explicit and prevents confusion. Lifecycle atomicity defines path existence and byte content for the non-zero exits covered by requirement 3; it does not require filesystem-metadata restoration or a crash-recovery subsystem for the flat-file artifact store.
Tags:
cli,lifecycle
Since: v0.1.0
[RFC-0002:C-OUTPUT-FORMAT] Output Format Control (Normative)
All commands that output resource data MUST support the --output (or -o) flag with the following format options:
Required Output Formats:
-
table(default for human use)- Formatted tables with headers and aligned columns
- MAY use colors when terminal supports them
- MUST be readable in plain text (no control codes in non-TTY)
-
json- Valid JSON output
- Pretty-printed with 2-space indentation
- MUST be parseable by standard JSON tools
-
yaml- Valid YAML output
- Formatted for readability
- MUST be parseable by standard YAML tools
-
toml- Valid TOML output (native format for governance artifacts)
- MUST be parseable by standard TOML tools
-
plain- Plain text values with no formatting
- One value per line for lists
- Single value (no newline) for scalar fields
- Suitable for shell scripting and piping
Applicability:
Commands MUST support output formats as follows:
getwith no field: table, json, yaml, tomlgetwith field: plain (default), json, yamllist: table (default), json, yaml
Commands MAY add format-specific flags (e.g., --format-json-compact) but MUST NOT remove or change behavior of standard formats.
Format Selection:
- Explicit
--output <format>takes precedence - If not specified:
- For TTY: default is
table - For non-TTY: default MUST be
json
- For TTY: default is
- Invalid format names MUST error with list of valid formats
Exceptions:
govctl status is exempt from output format requirements and always produces human-readable tabular output intended for interactive use only.
govctl conformance trace is a scoped exception and supports only table and json.
Consistency Requirements:
- JSON/YAML/TOML output MUST match the internal schema exactly
- Table format MAY omit fields for readability but MUST show all critical fields
- Plain format MUST output stable, parseable text (no decorations)
- Output format MUST NOT affect command semantics (same data, different representation)
Rationale:
Universal output format control enables:
- Human readability (table)
- Script automation (json/yaml)
- Integration with standard tools (jq, yq)
- Native format inspection (toml for governance artifacts)
This pattern follows kubectl and Docker conventions where -o json works on all read operations.
Tags:
cli
Since: v0.1.0
[RFC-0002:C-GLOBAL-COMMANDS] Global Commands (Normative)
The following commands operate at the project or CLI level and MUST remain at the global namespace level rather than under an artifact resource namespace:
1. govctl init
Initializes a new govctl project in the current directory.
Syntax: govctl init [--force]
Behavior:
- Creates
gov/directory structure - Generates
gov/config.tomldeclaring project schema version 5 - Creates subdirectories for RFCs, ADRs, Work Items, verification guards, and Conformance Cases
- Installs bundled JSON Schema files under
gov/schema/ - MUST error if already initialized (unless
--force) - MUST NOT install agent skills or agents (see
init-skills) - SHOULD print a hint about
govctl init-skillsand plugin installation
2. govctl check
Validates all governance artifacts across the project.
Syntax: govctl check [--deny-warnings]
Behavior:
- Validates RFCs, ADRs, clauses, work items, releases, verification guards, and Conformance Cases
- Implementations MUST define a corresponding machine-readable JSON Schema for each governance artifact type: RFC, clause, ADR, work item, release, verification guard, and Conformance Case
- These schemas MUST be JSON files stored under
gov/schema/ - For TOML artifacts, MUST validate the canonical structured layout against the corresponding JSON Schema after parsing
- Checks state machine invariants
- Verifies cross-references
- Validates the semantic correctness of the optional
[verification]section ingov/config.toml, including that configured default guard IDs resolve - Scans source code for references (if enabled in config)
- MUST enforce the repository and unsupported-storage rules in RFC-0002:C-COMPATIBILITY-BOUNDARY before reporting successful validation
- If any bundled JSON Schema file under
gov/schema/is missing or differs from the current bundled schema, MUST report a schema-outdated diagnostic that instructs users to rungovctl migrate - If any govctl-managed local-state
.gitignoreentry is missing or outdated, MUST report a project-support-outdated diagnostic that instructs users to rungovctl migrate - Returns exit code 0 if valid, non-zero if errors
- With
--deny-warnings: treats warnings as errors
3. govctl status
Shows summary counts of all artifacts grouped by status.
Syntax: govctl status
Behavior:
- Displays counts by status/phase for each resource type
- Highlights active work items
- Shows pending decisions (proposed ADRs, draft RFCs)
- Uses colors in TTY mode for visual scanning
- No output format flag (always human-readable table)
4. govctl render
Generates markdown documentation from source-of-truth governance artifacts.
Syntax: govctl render [targets...] [--dry-run] [--force]
Behavior:
- Renders RFCs from TOML to markdown (published)
- Renders ADRs from TOML to markdown (local only)
- Renders work items from TOML to markdown (local only)
- Generates CHANGELOG.md from releases
- For changelog rendering without
--force: updates the unreleased section and adds missing releases while preserving existing released sections - For changelog rendering with
--force: regenerates the complete changelog from current canonical release data and Work Items - Default: renders RFCs only
- With targets:
rfc,adr,work,changelog,all - MUST validate before rendering
5. govctl describe
Provides machine-readable discovery for agent and tool integration as defined by RFC-0002:C-DESCRIBE-COMMAND.
Syntax: govctl describe [--context]
6. govctl completions
Generates shell completion scripts.
Syntax: govctl completions <bash|zsh|fish|powershell>
Behavior:
- Outputs completion script for specified shell
- Can be sourced or installed per shell conventions
7. govctl migrate
Performs versioned repository-local format migration for governance artifacts.
Syntax: govctl migrate [--dry-run]
Behavior:
- Reads the current schema version from
gov/config.toml[schema] version - Enforces the minimum supported schema version in RFC-0002:C-COMPATIBILITY-BOUNDARY before planning file operations
- Runs all pending migration steps from a supported version to the latest
- Each step produces a set of file operations executed transactionally
- With
--dry-run, MUST perform the same schema checks, repository validation, project-support discovery, and migration planning as execution; MUST report every planned file operation; and MUST leave persistent project and local state unchanged - Bumps
[schema] versioningov/config.tomlafter successful migration - If a migration operation fails after changing any target, implementation MUST attempt rollback before returning
- When rollback succeeds, implementation MUST leave every migration target file unchanged and return the original operation failure
- If rollback fails, implementation MUST return E0903, identify that restoration may be incomplete and where recovery backups were retained, MUST NOT report migration success, and MUST NOT discard the recovery backups
- MUST be safe to run on an already-migrated repository and report a no-op result
- MUST NOT perform heuristic project discovery or broad adoption tasks
- MUST ensure all bundled JSON Schema files exist in
gov/schema/, overwriting with the latest version regardless of schema version - MUST ensure local govctl state ignore entries are present in
.gitignore, including.govctl.lockand.govctl/, regardless of schema version - MUST enforce the migration and unsupported-storage behavior in RFC-0002:C-COMPATIBILITY-BOUNDARY
8. govctl verify
Executes reusable verification guards.
Syntax:
govctl verify [GUARD-ID ...]govctl verify --work WI-ID
Behavior:
- Loads Verification Guard artifacts from
gov/guard/ - Explicit
GUARD-IDarguments and--work WI-IDMUST NOT be combined in the same invocation - With explicit
GUARD-IDarguments: runs those guards - With
--work WI-ID: runs the effective required guards for that work item after applying project defaults and work-item waivers - With no explicit guards and no
--work: runs the project-level default guards fromgov/config.toml - Reads project-level verification policy from RFC-0002:C-VERIFY-CONFIG
- Executes each guard command non-interactively from the project root
- Reports pass/fail per selected guard
- Returns non-zero if any selected guard fails, if no guards are selected, or if a requested guard ID is unknown
9. govctl init-skills
Installs agent skills and agents into the project’s agent directory.
Syntax: govctl init-skills [--force] [--format <claude|codex>] [--dir PATH]
Behavior:
--diroverrides the output directory for this invocation. Resolution order:--dirflag >agent_dirfrom config > format-implied default (.claudefor claude,.codexfor codex)--formatselects the output format for agent definitions (defaultclaude):claude: skills as fullskills/*/bundles rooted atSKILL.md, agents asagents/*.mdwith YAML frontmatter (compatible with Claude Code, Cursor, Windsurf, and similar editors)codex: skills as fullskills/*/bundles rooted atSKILL.md(same format), agents asagents/*.tomlwithdeveloper_instructionsfield (compatible with Codex CLI)
- Skill bundle resources under directories such as
references/,assets/, andscripts/MUST be installed with their parent skill; agent output remains format-specific - Skips files that already exist unless
--forceis used - Reports created/updated/skipped counts
- This command is separate from
initbecause plugin users receive skills globally and do not need local copies
10. govctl tag
Manages the project’s controlled tag vocabulary.
Syntax:
govctl tag new <tag>govctl tag delete <tag>govctl tag list
Behavior:
new: registers a new tag ingov/config.tomlunder[tags] allowed. Tags MUST match[a-z][a-z0-9-]*(lowercase kebab-case). MUST error if the tag already exists.delete: removes a tag from the allowed list. MUST error if any artifact still references the tag.list: displays all registered tags with usage counts (how many artifacts reference each tag).
Artifact-level tagging uses existing resource verbs on taggable types (rfc, clause, adr, work, guard, conformance):
govctl {rfc|clause|adr|work|guard|conformance} edit <ID> tags --add <tag>- assign a tag to an artifactgovctl {rfc|clause|adr|work|guard|conformance} edit <ID> tags --remove <tag>- remove a tag from an artifact
11. govctl self-update
Updates the govctl binary to the latest release.
Syntax: govctl self-update [--check]
Behavior:
- Downloads and replaces the running binary from GitHub Releases
- With
--check: prints version comparison without downloading - Full specification in RFC-0002:C-SELF-UPDATE
12. govctl loop
Manages project-local loop execution state for driving work items through iterative rounds.
Syntax: govctl loop <subcommand> [arguments] [flags]
Behavior:
- Operates on local execution state under
.govctl/loops/, not on a governed artifact resource - Coordinates work items, verification guards, and local loop state according to RFC-0006
- MUST NOT expose universal CRUD field-editing verbs for loop state
- MUST keep work item lifecycle transitions routed through
govctl worksemantics - MUST use stable subcommand and argument semantics defined by RFC-0006:C-LOOP-COMMAND-SURFACE
13. govctl search
Searches governed artifacts across the project by user-provided query text.
Syntax: govctl search <query>... [--type <rfc|clause|adr|work|guard|conformance>]... [--tag <tag>]... [-n <limit>] [-o <table|json|plain>] [--reindex]
Behavior:
- Operates across RFCs, clauses, ADRs, work items, verification guards, and Conformance Cases according to RFC-0002:C-SEARCH-COMMAND
- MUST remain at the global namespace because it is project-level discovery across multiple governed resource types, not a resource-specific CRUD operation
- MUST NOT be required as a universal resource verb under each artifact namespace unless a future RFC amendment explicitly adds scoped search aliases
14. govctl agent
Manages the user-scoped govctl agent integration.
Syntax:
govctl agent <doctor|install|update> <codex|claude|all>govctl agent hook <session-start|pre-tool-use>(internal adapter)
Behavior, including the internal adapter exception to runtime selection, is defined by RFC-0002:C-AGENT-INTEGRATION.
Rationale:
These commands are global because they:
- Operate on multiple resource types simultaneously
- Don’t fit the
<resource> <verb>pattern semantically - Are project-level operations, not resource-level
- Match user mental model of “project commands” vs “resource commands”
- May manage local execution state that coordinates governed resources without becoming a governed resource itself
govctl migrate qualifies because it operates across the governance repository as a whole and changes multiple resource types in one coordinated step.
govctl verify qualifies because it executes project-level completion checks that may be required by multiple work items and by the project configuration.
govctl init-skills qualifies because it performs project-level initialization of agent assets (criterion 2).
govctl tag qualifies because it manages project-level configuration that applies across all resource types (criterion 1).
govctl self-update qualifies because it provides meta-information about the CLI itself and performs binary lifecycle management (criterion 3).
govctl loop qualifies because it manages local execution state that coordinates work items and verification guards without making loop state a governed resource (criterion 5).
govctl search qualifies because it performs project-level discovery across multiple governed resource types (criterion 1).
govctl agent qualifies because it manages CLI-level integration state for external agent runtimes without becoming a governed artifact resource (criterion 3).
Future Additions:
New global commands MAY be added via RFC amendment. They MUST meet at least one criterion:
- Operate on multiple resource types
- Perform project-level initialization or cleanup
- Provide meta-information about the CLI itself
- Manage local execution state that coordinates governed resources without becoming a governed resource itself
Tags:
cli
Since: v0.1.0
[RFC-0002:C-VERIFY-CONFIG] Verification Configuration (Normative)
The project config file gov/config.toml MAY include an optional [verification] section.
When present, the section MUST support the following fields:
enabled— boolean, defaultfalsedefault_guards— array of Verification Guard IDs, default[]
If the section is absent, the implementation MUST behave as if enabled = false and default_guards = [].
Every guard ID listed in default_guards MUST resolve to an existing Verification Guard defined by RFC-0000:C-GUARD-DEF. Unknown IDs MUST cause validation failure.
When enabled = false, project-level default guards MUST NOT be applied automatically by govctl verify or by Work Item completion checks.
Work Item verification.required_guards remain effective regardless of the project-level enabled value.
Rationale: The project config controls whether shared default guard policy is active. Explicit Work Item requirements remain local and auditable instead of becoming inert metadata.
Tags:
cli,validation
Since: v0.3.0
[RFC-0002:C-SELF-UPDATE] Self-Update Command (Normative)
11. govctl self-update
Updates the govctl binary to the latest release.
Syntax: govctl self-update [--check]
Behavior:
- Queries the GitHub Releases API for the
govctl-org/govctlrepository to determine the latest published version - Compares the latest version against the running binary’s compiled version
- Without
--check: downloads the platform-appropriate binary asset, verifies integrity, and replaces the running executable. MUST print the old and new version on success. MUST exit with code 0 if already up to date, printing a message indicating no update is needed. - With
--check: prints current version and latest available version without downloading. MUST exit with code 0 if up to date, exit with code 1 if a newer version is available. - MUST detect the current platform target at compile time and select the matching release asset
- MUST display download progress when connected to a TTY
- MUST error with a clear message if the binary lacks write permission to its install location
- MUST error with a clear message if the GitHub API is unreachable or rate-limited
- SHOULD support
GITHUB_TOKENenvironment variable for authenticated API requests to avoid rate limits
Rationale:
A self-update command provides a single canonical update path that works regardless of how govctl was originally installed (cargo install, cargo binstall, or direct binary download). This meets criterion 3 of RFC-0002:C-GLOBAL-COMMANDS (meta-information about the CLI itself).
Tags:
cli,release
Since: v0.8.0
[RFC-0002:C-SEARCH-COMMAND] Search Command (Normative)
govctl search searches governed artifacts by user-provided query text.
Syntax:
govctl search <query>... [--type <rfc|clause|adr|work|guard|conformance>]... [--tag <tag>]... [-n <limit>] [-o <table|json|plain>] [--reindex]
Behavior:
- The command MUST operate at the global command namespace as an explicit RFC-0002:C-RESOURCE-MODEL exception listed in RFC-0002:C-GLOBAL-COMMANDS, because it searches across multiple governed resource types and is project-level discovery rather than a resource-specific CRUD operation.
- The command MUST search RFCs, clauses, ADRs, work items, verification guards, and Conformance Cases unless one or more
--typefilters are provided. - Positional
<query>...values MUST be interpreted as user search terms by default, not as backend-specific raw query syntax. - The command MUST support artifact ID lookup as a search use case. A query containing an existing artifact ID SHOULD rank that artifact ahead of lower-confidence full-text matches. Results with equal relevance MUST be ordered lexicographically by artifact kind and then artifact ID.
- The command MUST support
--tag <tag>filters. When multiple tags are provided, returned artifacts MUST contain all requested tags. - The command MUST support
-n, --limit <limit>and MUST apply a finite default limit when the flag is omitted. - The command MUST support
--reindex, which forces a rebuild of any local derived search index before returning results. - The command MUST NOT modify governed artifact files or rendered documentation.
- If the implementation persists a search index, it MUST store that index under
.govctl/local state and MUST NOT store it undergov/or the rendered docs directory. - A persisted search index is derived local state and MUST NOT be treated as an authoritative artifact source. TOML governance artifacts remain the source of truth.
- The command MUST establish index freshness before returning indexed results. If freshness cannot be established, the command MUST rebuild the index, perform an uncached authoritative scan, or return a diagnostic. It MUST NOT silently return stale indexed results.
- Search index synchronization MAY mutate
.govctl/local state. This local-state mutation MUST NOT require the RFC-0004 gov-root exclusive write lock because it does not mutate governed artifacts or rendered documentation. - Output rows MUST include at least artifact kind, artifact ID, title, source path, and a match snippet or equivalent human-readable context.
- JSON output MUST expose stable result fields including
kind,id,title,path, andsnippet. It MAY include ranking score and status metadata. - Plain output MUST emit one artifact ID per line in result order.
Rationale:
Search is discovery across the governance corpus, not a resource-specific CRUD operation. Keeping indexes under .govctl/ preserves the boundary between authoritative governed artifacts and disposable local execution or cache state. Requiring freshness before returning results prevents the local index from becoming a misleading second source of truth.
Since: v0.10.1
[RFC-0002:C-SHOW-PROJECTION] Show Projection Modes (Normative)
For the purposes of this clause, table and plain are human-readable output formats, while json, yaml, and toml are structured output formats. current is the projection used to omit obsolete body content, and archive is the complete historical projection.
RFC, ADR, Work Item, Clause, Guard, and Conformance Case resource commands MUST expose show <id> as a side-effect-free projection operation distinct from get. This distinction is a scoped exception to RFC-0002:C-CRUD-VERBS: get retrieves a field or complete structured resource, while show presents either the current or archival projection defined here.
The show output matrix MUST be:
show <id>with no--outputuses the human-readabletableformat and thecurrentprojection, regardless of whether stdout is a TTY.show <id> --historywith no--outputuses the human-readabletableformat and thearchiveprojection, regardless of whether stdout is a TTY.show <id> --output tableandshow <id> --output plainuse thecurrentprojection unless--historyselectsarchive.show <id> --output json,--output yaml, or--output tomlreturns the complete structured resource with a schema equivalent to completeget <id>retrieval.- Combining
--historywith--output json,--output yaml, or--output tomlMUST be rejected.
This matrix is a scoped exception to RFC-0002:C-OUTPUT-FORMAT for the implicit non-TTY default and for the historical-body completeness of human-readable show. Choosing among structured formats MUST NOT change resource semantics or completeness.
For an RFC whose status is deprecated under RFC-0001:C-RFC-STATUS, the current projection MUST retain its heading, identity, title, version, status, phase, owners, tags, references, and direct replacement metadata when present. It MUST omit the RFC body sections, Clause list and bodies, and changelog. Parent suppression MUST take precedence over the status of nested Clauses.
For an RFC not suppressed by the preceding rule, the current projection MUST fully render the RFC body and every active Clause. A nested Clause whose status is deprecated or superseded under RFC-0001:C-CLAUSE-STATUS MUST retain its heading, generated heading anchor, identity, title, kind, status, since, tags, and direct superseded_by metadata when present. Its Clause text MUST be omitted.
For an ADR whose status is superseded under RFC-0001:C-ADR-STATUS, the current projection MUST retain its heading, identity, title, status, date, tags, references, and direct superseded_by metadata. It MUST omit context, alternatives, decision, and consequences.
For a directly shown Clause whose status is deprecated or superseded, the current projection MUST retain the same metadata required for a suppressed nested Clause. Its Clause text MUST be omitted.
For resources without a deprecated or superseded lifecycle state, including Work Items, Guards, and Conformance Cases, current and archive MUST be content-equivalent. Other lifecycle states MUST remain fully rendered.
The archive projection MUST render all governed resource content supported by the resource’s human-readable renderer without lifecycle-based omission. In particular, it MUST include every RFC section, Clause text, RFC changelog entry, ADR content section and alternative, Work Item content section, Guard field, and Conformance Case field present in the selected resource. Terminal styling and transport-only wrappers MAY differ. render MUST always use the archive projection and MUST NOT suppress deprecated or superseded content.
get, validation, signatures, search, and the authoritative governance artifacts MUST remain unaffected by human-readable projection mode.
Rationale: Agents need a concise default view that does not present obsolete requirements as current, while maintainers and generated documentation need an explicit, lossless path to the complete governance history. An explicit projection boundary preserves both uses without changing stored artifacts or structured automation interfaces.
Since: v0.15.0
[RFC-0002:C-COMPATIBILITY-BOUNDARY] Compatibility Boundary (Normative)
This clause defines the compatibility boundary for the canonical-only breaking release.
CLI boundary:
- The CLI MUST accept only command names, subcommand names, field paths, and mutation flags defined by the current normative RFC clauses.
- The CLI MUST reject compatibility aliases for command names and subcommand names.
- The CLI MUST accept only the field paths defined by RFC-0002:C-EDIT-FIELD-CONTRACT.
- The CLI MUST reject field-path aliases and wire-layout prefixes such as
content.,govctl., andcheck.. - The CLI MUST reject resource-specific compatibility flags on the universal
editoperation.
Repository boundary:
- Project schema version 3 MUST be the minimum supported project schema version, and the running binary’s current schema version MUST be the maximum supported project schema version.
- Project schema version 4 introduced Conformance Case storage and validation. Normal commands on a version 3 repository containing prospective Case files MUST reject the repository without mutation and instruct the user to run
govctl migrate; migration MAY inspect those files under version 4 rules before updating the declared version. - Project schema version 5 MUST be the current schema version. Version 5 removes
source_scan.excludeand establishes the source-selection and ignore contract in RFC-0009. Normal commands on a version 4 repository MUST reject the repository without mutation and instruct the user to rungovctl migrate. Migration MUST apply the version 4 to version 5 behavior defined by RFC-0009:C-IGNORE-MIGRATION. - Any command that loads an existing governance project MUST validate that the declared project schema version is within the supported inclusive range before reading or writing governed artifacts, generated documentation, or
.govctllocal state. - A repository whose
gov/config.tomldeclares a schema version below 3 MUST be rejected. The rejection MUST leavegov/, generated documentation, and.govctlunchanged. The diagnostic MUST instruct the user to migrate the repository with a compatible earlier govctl version before upgrading. - A repository whose
gov/config.tomldeclares a schema version newer than the running binary’s current schema version MUST be rejected without mutation. The diagnostic MUST instruct the user to upgrade govctl to a version that supports the repository schema. - If
gov/config.tomlis absent whilegov/contains governance project state, the project schema cannot be established and normal project commands MUST reject the repository without mutation. The diagnostic MUST identify the missing configuration. A new project with no existing governance state MAY still be initialized. - RFC and Clause artifacts MUST use the structured TOML wire layout defined by their current schemas. The former flat RFC and Clause TOML layouts MUST be rejected.
- RFC, Clause, ADR, Work Item, Guard, and Conformance Case TOML files MUST NOT contain the legacy
[govctl].schemafield. - Work Item TOML containing
content.journalMUST be rejected. - Loading or rewriting a loop round TOML file containing
max_roundsMUST be rejected. - Project schema version 3 establishes the content-signature interpretation for stored RFC signatures. RFC signatures stored for project schema version 3 or later MUST use the content-signature contract in RFC-0000:C-PHASE-LIFECYCLE. Repositories below version 3 MUST be migrated with a compatible earlier govctl version before the current binary loads their RFC baselines. The current binary MUST NOT infer a pre-version-3 signature algorithm from an untagged hash value.
Migration and safety:
govctl migrateMUST support migration from project schema version 3 to each later schema version supported by the running binary.govctl migrateMUST reject project schema versions below 3 without mutation. Its diagnostic MUST direct the user to a compatible earlier govctl version.- JSON RFC files matching
gov/rfc/RFC-NNNN/rfc.jsonMUST produce an unsupported-storage diagnostic that identifies the path. - JSON Clause files matching
gov/rfc/RFC-NNNN/clauses/C-NAME.jsonMUST produce an unsupported-storage diagnostic that identifies the path. - Project loading and validation MUST perform those JSON checks before reporting success. Recognized legacy JSON files MUST NOT be silently ignored.
- Historical RFCs, Clauses, ADRs, Work Items, release records, and released changelog content that conform to the supported schemas MUST remain authoritative history.
- Lifecycle status alone MUST NOT make a conforming historical artifact unsupported.
Rationale:
A single explicit boundary is smaller and more predictable than indefinitely carrying transitional parsers and CLI grammars. Requiring an earlier compatible binary for pre-baseline repositories preserves an upgrade path without making every future release understand every historical representation. Explicit unsupported-storage diagnostics prevent apparent success when governed data would otherwise be skipped.
Since: v1.0.0
[RFC-0002:C-EDIT-FIELD-CONTRACT] Canonical Edit Field Contract (Normative)
This clause defines the complete canonical mutation-path contract for govctl <resource> edit. A path not listed here MUST be rejected. Lifecycle-owned fields remain mutable only through the lifecycle verbs in RFC-0002:C-LIFECYCLE-VERBS.
Each resource MUST support these paths and operations:
| Resource | Canonical path | Permitted operation |
|---|---|---|
| RFC | title | --set |
| RFC | owners, refs, tags | --add, --remove |
| RFC | changelog.summary | --set |
| RFC | changelog.added, changelog.changed, changelog.deprecated, changelog.removed, changelog.fixed, changelog.security | --add, --remove |
| ADR | title, date, context, decision, consequences | --set |
| ADR | refs, tags | --add, --remove |
| ADR | alternatives | --add, --remove, --tick |
| ADR | alternatives[i].text, alternatives[i].rejection_reason | --set |
| ADR | alternatives[i].pros, alternatives[i].cons | --add, --remove |
| Work Item | title, description | --set |
| Work Item | refs, depends_on, tags, notes | --add, --remove |
| Work Item | acceptance_criteria | --add, --remove, --tick |
| Work Item | acceptance_criteria[i], acceptance_criteria[i].text, acceptance_criteria[i].category | --set |
| Work Item | verification.required_guards | --add, --remove |
| Work Item | verification.waivers | --remove |
| Work Item | verification.waivers[i].guard, verification.waivers[i].reason | --set |
| Clause | title, text, kind | --set |
| Clause | anchors, tags | --add, --remove |
| Guard | title, command, timeout_secs, pattern | --set |
| Guard | refs, tags | --add, --remove |
| Conformance Case | title, path, selector | --set |
| Conformance Case | requirements, guards, tags | --add, --remove |
| Conformance Case | requirements[i] | --remove |
| Conformance Case | requirements[i].version | --set |
Every listed list path whose items are scalar values also defines an indexed <list-path>[i] path supporting --set and --remove. Indexed scalar replacement MUST replace exactly one item in place, preserve the list length and item position, and apply before persistence the same value and reference validation as --add on the owning list. Structured list items MUST NOT inherit direct --set unless the indexed item path is explicitly listed above; their listed child paths remain the scalar replacement surface.
Acceptance-criterion category input MUST recognize these ASCII case-insensitive prefix tokens when the trimmed token precedes the first colon:
add,added,feat, andfeaturemap toadded;change,changed,refactor, andperfmap tochanged;deprecateanddeprecatedmap todeprecated;removeandremovedmap toremoved;fixandfixedmap tofixed;securityandsecmap tosecurity; andchore,internal,test,tests,doc,docs,ci, andbuildmap tochore.
The text following a recognized prefix MUST be trimmed and non-empty. acceptance_criteria --add MUST require a recognized prefix and reject an absent or unrecognized prefix.
For Work Item acceptance_criteria[i], --set <value> MUST update the existing criterion without changing its status. If <value> begins with a recognized acceptance-criterion category prefix, the operation MUST update both the criterion text and category using the mapping above. Otherwise, it MUST treat the complete trimmed value as criterion text and preserve the existing category. The direct acceptance_criteria[i].text path MUST treat its value as literal text and preserve both status and category. An empty resulting text MUST be rejected.
For Conformance Case requirements, --remove MUST select either one exact <CLAUSE-ID>@<VERSION> value or one indexed path. --regex and --all MUST be rejected for this object-valued, non-empty list.
List selection MUST use only these canonical forms:
govctl <resource> edit <id> <scalar-list-path>[<index>] --set <value>
govctl work edit <id> acceptance_criteria[<index>] --set <value>
govctl <resource> edit <id> <list-path>[<index>] --remove
govctl <resource> edit <id> <list-path> --remove <exact-value>
govctl <resource> edit <id> <list-path> --remove <pattern> --regex
govctl <resource> edit <id> <list-path> --remove --all
govctl <resource> edit <id> <checklist-path>[<index>] --tick <status>
Indices MUST be zero-based decimal integers. --remove <value> MUST use exact matching unless --regex is present. --all MUST NOT be combined with a value, indexed path, or --regex. --tick MUST require an indexed path and a lifecycle value permitted for that checklist type. Selector flags such as --at and --exact MUST be rejected because the canonical path and exact-value form already express those selections.
RFC changelog paths address only the current version record. Released historical changelog records MUST NOT be editable through this surface.
The logical Guard paths command, timeout_secs, and pattern map to persisted check configuration without exposing the wire-layout name. Work Item waiver creation remains owned by the verification waiver command; edit only corrects or removes an existing waiver.
Rationale:
A closed list gives scripts and agents one discoverable interface and makes removal of aliases testable. Uniform indexed replacement gives scalar lists one predictable correction operation. Acceptance criteria expose a concise item-level text update while retaining explicit child paths for precise field edits. Logical paths keep the command contract independent of TOML table layout while lifecycle and verification commands retain ownership of constrained transitions.
Since: v1.0.0
[RFC-0002:C-NAMESPACE-RECOVERY] Misrouted resource command recovery (Normative)
Governed artifact resources are first-class CLI namespaces even when their storage or identifiers express ownership by another resource.
An invocation under the rfc namespace MUST fail with a non-zero exit when an argument in the command’s canonical RFC-ID position is a Clause reference (RFC-NNNN:C-NAME). The rejected invocation MUST leave governed artifacts and local state unchanged. For the shared get, show, and edit verbs, the diagnostic MUST show the corresponding govctl clause command when replacing only the resource token rfc with clause produces a syntactically valid Clause invocation with every remaining argument and flag unchanged. For any other RFC verb, or when the token-preserving replacement is not a valid Clause invocation, the diagnostic MUST identify the reference as a Clause and the expected govctl clause namespace without synthesizing a complete command.
The exact nested form govctl rfc clause ... MUST remain invalid and fail with a non-zero exit. It MUST leave governed artifacts and local state unchanged. Its diagnostic MUST direct the user to the command formed by removing the rfc token: govctl clause ....
When govctl rfc edit <RFC-ID> <path> ... rejects an unknown path whose first logical segment is clause or clauses, its diagnostic MUST identify Clause content as belonging to the govctl clause edit <RFC-ID:C-NAME> ... namespace. Because that form does not identify a Clause, the diagnostic MUST NOT invent a Clause ID or claim a complete replacement command.
Recovery guidance MUST NOT make an invalid invocation an alias, rewrite it into an executable command, or otherwise cause the requested operation to succeed.
Rationale: Deterministic guidance lets agents recover from the storage-derived assumption that Clauses are RFC subcommands while preserving one accepted resource-first grammar. Restricting exact replacements to token-preserving namespace changes avoids guessing user intent.
Since: v1.0.1
[RFC-0002:C-PRE-1-RELEASE-TARGET-COMPATIBILITY] Pre-1.0 Release Target Compatibility (Normative)
For govctl release versions at or after 0.17.0 whose SemVer major component is zero, the canonical prebuilt-binary target set is:
x86_64-unknown-linux-muslaarch64-unknown-linux-muslx86_64-apple-darwinaarch64-apple-darwinx86_64-pc-windows-gnuaarch64-pc-windows-gnullvm
Every release in that scope MUST also publish compatibility alias archives with these mappings:
x86_64-unknown-linux-gnu->x86_64-unknown-linux-muslaarch64-unknown-linux-gnu->aarch64-unknown-linux-muslx86_64-pc-windows-msvc->x86_64-pc-windows-gnuaarch64-pc-windows-msvc->aarch64-pc-windows-gnullvm
{version} below denotes the complete SemVer release version without a leading v; the v shown in each template is literal. For every canonical or alias target identifier listed by this Clause, release archives MUST use this layout:
- Linux and macOS targets: asset filename
govctl-v{version}-{target}.tar.gz, gzip-compressed tar format, one root directory namedgovctl-v{version}-{target}, and executable pathgovctl-v{version}-{target}/govctl. - Windows targets: asset filename
govctl-v{version}-{target}.zip, ZIP format, one root directory namedgovctl-v{version}-{target}, and executable pathgovctl-v{version}-{target}/govctl.exe.
For each compatibility mapping, the executable bytes at the alias executable path MUST equal the executable bytes at the mapped canonical executable path for the same release version.
The alias set applies to every release in this pre-1.0 transition window so legacy-target self-update clients and package installers can cross the target transition even when versions are skipped.
A release version whose SemVer major component is one or greater, including a prerelease such as 1.0.0-rc.1, MUST NOT publish the four compatibility alias target archives defined by this Clause. A pre-1.0 installation that has not crossed the target transition before that breaking boundary may require reinstallation through another distribution channel.
Since: v3.1.0
3. Global Commands
[RFC-0002:C-DESCRIBE-COMMAND] Agent Introspection Contract (Normative)
govctl describe provides read-only, machine-readable discovery for the running CLI.
Syntax
govctl describe [--context]
The command MUST emit JSON and MUST NOT mutate project or local execution state. Without --context, it MUST succeed without an initialized governance project.
Schema v1
The top-level object MUST contain:
schema_version: the integer1tool_version: the running binary semantic version as a stringpurpose: a stringcommands: an array of command nodesworkflow: an object containing onlyphase_order
Without --context, project_state and suggested_actions MUST be absent. With --context, both fields MUST be present.
A command node MUST contain name, summary, and usage strings plus a subcommands array of command nodes. The command catalog MUST represent every top-level command and nested command defined by the accepted CLI grammar. Generic help dispatch MUST be omitted. commands and every subcommands array MUST be sorted lexicographically by name. usage MUST contain the canonical invocation without a leading Usage: label. Command nodes MUST NOT contain examples, prerequisites, workflow policy, or when_to_use guidance.
workflow.phase_order MUST equal ["spec", "impl", "test", "stable"] and MUST NOT prescribe a task sequence.
With --context, project_state MUST contain counts, rfcs, adrs, work_items, and loops.
counts MUST contain these objects and integer fields, including zero-valued fields:
rfcs:total,draft,normative,deprecated,spec,impl,test, andstableadrs:total,proposed,accepted,rejected, andsupersededwork_items:total,queue,active,done, andcancelledloops:total,pending,active,paused,completed, andfailed
RFC status and phase counts MUST cover every RFC according to RFC-0001:C-RFC-STATUS and RFC-0001:C-RFC-PHASE. ADR, Work Item, and loop counts MUST cover every corresponding record according to RFC-0001:C-ADR-STATUS, RFC-0001:C-WORK-STATUS, and RFC-0006:C-LOOP-LIFECYCLE.
rfcs MUST enumerate only draft RFCs and normative RFCs whose phase is not stable. Each RFC record MUST contain id, title, status, and phase strings.
adrs MUST enumerate only proposed ADRs. Each ADR record MUST contain id, title, and status strings.
work_items MUST enumerate only Work Items in queue or active. Each Work Item record MUST contain id, title, and status strings.
loops MUST enumerate only loops in pending, active, or paused. Each loop record MUST contain id, state, and next_action strings plus a work array of Work Item ID strings. If valid loop state omits next_action as permitted by RFC-0006:C-LOOP-STATE-STORAGE, the record MUST report "start". The work array MUST preserve the stored loop.work order.
Each context record array MUST be sorted lexicographically by id. Terminal records MUST affect counts but MUST NOT be enumerated. Context output MUST NOT contain artifact body text, changelogs, acceptance criteria, notes, loop round records, or other historical content.
suggested_actions MUST be an array of canonical read-only command strings. It MUST contain one discovery command for each enumerated record, ordered by RFCs, ADRs, Work Items, then loops, preserving each record array’s order:
- RFC:
govctl rfc show <id> - ADR:
govctl adr show <id> - Work Item:
govctl work show <id> - loop:
govctl loop resume <id>
A suggested action indicates only how to inspect current state. It MUST NOT assert that a lifecycle gate passes or recommend a mutating transition.
If requested context cannot be loaded completely, describe --context MUST exit non-zero, MUST emit no JSON or partial context to stdout, and MUST report diagnostics to stderr.
Compatibility
schema_version MUST increase for a backward-incompatible output change. Removing or renaming a field, changing a field’s type or meaning, making an optional field required, or changing required ordering is backward-incompatible. A backward-incompatible schema change also requires a major govctl version bump. Additive optional fields MAY retain the current schema version. Consumers SHOULD ignore unknown fields.
Rationale
A small versioned command map lets agents discover the running binary without loading a duplicate workflow manual. Counts retain project-scale awareness, while non-terminal records and read-only inspection commands keep context proportional to current work rather than repository history.
Since: v2.0.0
[RFC-0002:C-AGENT-INTEGRATION] Agent Integration Management (Normative)
govctl agent manages the user-scoped govctl agent integration independently of project governance state.
Syntax
govctl agent doctor <codex|claude|all>
govctl agent install <codex|claude|all>
govctl agent update <codex|claude|all>
govctl agent hook <session-start|pre-tool-use>
The runtime selector is required for doctor, install, and update; all selects Codex and Claude. hook is an internal adapter entry point used by bundled runtime manifests. It takes no runtime selector, consumes the native event payload as JSON on standard input, and emits the applicable non-blocking hook response as JSON on standard output. It MUST remain hidden from user-facing command discovery.
Shared behavior
- These commands MUST work without an initialized govctl project.
doctorMUST be read-only. It MUST verify that every selected runtime exposes the native plugin operations required byinstallandupdate, and it MUST exit non-zero when any selected runtime is unavailable or incompatible.installandupdateMUST use plugin assets bundled with the running govctl version. They MUST materialize those assets at a persistent user-scoped support path before registering that path as a native marketplace source.- The materialized plugin version MUST equal the running govctl version.
installMUST preserve an existing Codex reviewer-role file rather than replacing it.updateMUST replace the govctl reviewer-role files for Codex with the bundled projection.- When
allis selected, request validation and native-operation preflight MUST complete for both runtimes before the first native mutation. The command MUST exit non-zero unless every selected runtime succeeds, and failure output MUST identify completed, failed, and skipped runtime work without claiming cross-runtime atomicity. - With global
--dry-run,installandupdateMUST perform target resolution and readiness checks, report planned persistent writes and native operations, and leave persistent state unchanged. - Successful
installandupdateMUST tell the user that a new agent session is required before refreshed integration is available.
Client projections
- Claude MUST receive the bundled skills, Claude Markdown reviewer agents, and hooks through its native plugin mechanism.
- Codex MUST receive the bundled common skills and hooks through its native plugin mechanism.
- Codex reviewer agents MUST be installed separately as standalone TOML files in the selected user’s Codex agent directory. Every generated role MUST contain
name,description, anddeveloper_instructions, and review-only roles MUST select a read-only sandbox mode. - The bundled plugin MUST select a runtime-specific hook manifest for each client. Shared governance behavior MUST be adapted to the client’s supported event fields and output protocol rather than relying on one shared hook document.
Bundled hook behavior
- On
SessionStart, the hook adapter MUST resolve the event working directory with the same upward project-discovery semantics as other govctl commands. - If no governed project is found,
SessionStartMUST succeed without model-visible output. If governance state is found but cannot be loaded, it MUST provide concise, non-blocking recovery context. For a valid governed project, it MUST provide bounded, actionable context about current active Work Items and non-terminal loops without running project-wide validation. - Before a direct file-edit tool changes lifecycle-managed RFC, Clause, ADR, Work Item, Guard, Conformance Case, or release artifacts,
PreToolUseMUST provide non-blocking guidance to prefer a canonical govctl command when that command can express the change. The hook MUST allow the tool call to proceed, MUST acknowledge direct editing as the recovery path for unsupported operations, and MUST recommendgovctl checkafter such an edit. - Bundled hooks MUST NOT run project-wide validation on
Stopor after every file edit. Hook advice is a recoverability aid and MUST NOT be treated as an enforcement boundary.
The existing govctl init-skills command remains the project-local and custom-directory projection path. Agent plugin management MUST NOT change its overwrite or destination semantics.
Since: v3.2.0
Changelog
v3.6.0 (2026-08-02)
Make acceptance-criterion text correction ergonomic
Added
- Define item-level acceptance-criterion replacement with category-prefix parsing
v3.5.0 (2026-07-31)
Define the internal agent hook adapter command contract
Added
- Specify hook event syntax, JSON invocation, and the runtime-selector exception
v3.4.0 (2026-07-31)
Adapt bundled hooks to Claude and Codex runtimes
Changed
- Define runtime-specific hook manifests and shared governance semantics
- Replace per-turn validation with governed-project context and advisory edit guidance
v3.3.0 (2026-07-31)
Clarify native agent plugin projections
Added
- Require Codex hooks to load through its native plugin
v3.2.0 (2026-07-31)
Add native agent integration management
Added
- Define agent doctor, install, and update commands
v3.1.0 (2026-07-30)
Define pre-1.0 release target compatibility
Added
- Define canonical prebuilt targets and compatibility aliases through 0.x
Removed
- End legacy target alias publication at 1.0.0
v3.0.3 (2026-07-30)
Clarify rollback target boundary
Fixed
- Separate target restoration from best-effort temporary-state cleanup
v3.0.2 (2026-07-30)
Narrow recovery boundary to rollback failure
Fixed
- Keep temporary transaction cleanup best-effort without redefining migration results
v3.0.1 (2026-07-30)
Define migration recovery failure boundary
Fixed
- Preserve recovery backups and report E0903 when rollback or cleanup fails
v3.0.0 (2026-07-30)
Adopt schema v5 source scan ignore semantics
Changed
- Define schema v5 as the current repository format
Removed
- Replace source_scan.exclude with gitignore-compatible .govignore rules
v2.2.0 (2026-07-29)
Define uniform indexed replacement for scalar-valued lists
Added
- Define in-place indexed replacement for canonical scalar-list paths
Fixed
- Require replacement values to pass owning-list validation before persistence
v2.1.0 (2026-07-27)
Integrate Conformance Cases into the resource model
Added
- Define the Conformance Case resource and canonical CRUD surface
Changed
- Extend validation, search, tag, output, and migration contracts
v2.0.0 (2026-07-26)
Define reliable agent introspection
Changed
- Derive describe command metadata from the compiled CLI and limit context to actionable state
v1.1.0 (2026-07-26)
Define universal dry-run preflight semantics
Changed
- Require dry-runs to preserve execution validation and target selection
v1.0.4 (2026-07-26)
Restore schema boundary formatting
Fixed
- Render repository schema rules as separate requirements
v1.0.3 (2026-07-26)
Close repository schema validation gaps
Fixed
- Reject future schemas and existing projects with missing configuration
v1.0.2 (2026-07-26)
Clarify schema-3 RFC signature semantics
Changed
- Define schema version 3 as the content-signature interpretation boundary
v1.0.1 (2026-07-25)
Guide misrouted Clause commands to the canonical namespace
Changed
- Define deterministic recovery diagnostics for Clause commands sent through the RFC namespace
v1.0.0 (2026-07-25)
Adopt the canonical-only compatibility boundary
Changed
- Define the complete canonical edit path and selector contract
- Diagnose recognized unsupported legacy storage before project operations succeed
Removed
- Remove sibling mutation verbs, command aliases, field aliases, wire-layout paths, and resource-specific edit flags
- End migration support for project schemas below version 3 and remove legacy storage readers
v0.15.0 (2026-07-21)
Define current and archival show projections
Added
- Define current-context show output, explicit history access, and complete structured serialization
v0.14.0 (2026-07-20)
Align lifecycle commands with sealed RFC versions
Changed
- Enforce candidate bump and signature baseline rules
- Permit deletion of unreferenced current-candidate Clauses
v0.13.2 (2026-07-16)
Clarify lifecycle rollback restoration state
Changed
- Define rollback over target path existence and byte content
v0.13.1 (2026-07-16)
Reject version-changing bumps for non-normative RFCs
Fixed
- Restrict version-changing RFC bump to normative status
v0.13.0 (2026-07-16)
Specify current-version changelog editing and RFC sealing
Added
- Defined current changelog access and in-version spec authoring lifecycle operations
v0.12.1 (2026-07-15)
Restore stable release creation syntax
Fixed
- Preserve govctl release
alongside release undo
v0.12.0 (2026-07-15)
Make release commands consistently resource-first
Added
- Add guarded release undo
Changed
- Replace the legacy no-verb release syntax with release cut
- Exclude release records from universal CRUD verbs
v0.11.1 (2026-07-15)
Align RFC lifecycle verb definitions
Changed
- Separate RFC finalization from deprecation in the lifecycle command contract
v0.11.0 (2026-07-15)
Align lifecycle command semantics
Changed
- Align lifecycle verbs with version-scoped phases and pre-release Work Item reopening
v0.10.4 (2026-06-28)
Clarify lifecycle failure atomicity boundary
Changed
- define byte-for-byte restoration for normally returned lifecycle errors and explicit rollback-failure boundaries
v0.10.3 (2026-06-15)
Reject empty RFC version bumps
Fixed
- reject RFC version bumps without RFC or clause content changes
v0.10.2 (2026-06-08)
Clarify init-skills skill bundle installation
Changed
- init-skills installs full skill bundles rooted at SKILL.md, including bundled references/assets/scripts
v0.10.1 (2026-06-04)
Set search clause version metadata
Fixed
- C-SEARCH-COMMAND has derived since version metadata
v0.10.0 (2026-06-04)
Add search command contract
Added
- C-SEARCH-COMMAND clause for govctl search
v0.9.4 (2026-06-04)
Narrow project support diagnostics
Changed
- project-support diagnostics are scoped to govctl-managed local-state .gitignore entries
v0.9.3 (2026-06-04)
Clarify edit path addressing
Changed
- edit operations use deterministic path-based addressing for arrays and nested fields
v0.9.2 (2026-06-04)
Clarify project support file sync
Changed
- govctl check and migrate cover project support file freshness
v0.9.1 (2026-06-04)
Require check to surface stale bundled schemas
Changed
- govctl check reports missing or stale bundled schema files and instructs users to run govctl migrate
v0.9.0 (2026-06-04)
Remove legacy JSON migration support
Removed
- govctl migrate no longer converts legacy RFC or clause JSON storage in v0.9 and later
v0.8.0 (2026-04-13)
Add self-update global command (ADR-0041)
Added
- C-SELF-UPDATE clause for govctl self-update command
Changed
- C-GLOBAL-COMMANDS updated with entry 11 and rationale for self-update
v0.7.0 (2026-04-09)
Add controlled-vocabulary tags: tags field on RFC/clause/ADR/work/guard, –tag filter on list, govctl tag new/delete/list for registry management (ADR-0040)
v0.6.1 (2026-04-08)
Add –dir flag to init-skills for one-step directory override without config editing
v0.6.0 (2026-04-08)
Add –format flag to init-skills for cross-platform agent format support (claude/codex)
v0.5.0 (2026-03-27)
Add guard as a resource type with CRUD verbs
Added
- Added guard to C-RESOURCES as resource type 5 (renumbered release to 6)
- Updated C-CRUD-VERBS with guard-specific verb applicability
- Updated C-RESOURCE-MODEL to include guard in resource list
v0.4.0 (2026-03-17)
Add init-skills command, update init and migrate per ADR-0035
Added
- init-skills global command for explicit agent asset installation
Changed
- init no longer installs skills/agents
- migrate now ensures schema JSON files are up to date
v0.3.0 (2026-03-17)
Add project-level verification command and config semantics
Added
- Added global verify command and verification config contract
v0.2.0 (2026-01-19)
Incorporate review feedback: add deletion safety constraints, field name stability, output format defaults, describe schema versioning, and editorial clarifications
Added
- Added deletion safety constraints requiring draft RFCs and reference checks
- Added field name stability guarantee for get command
- Specified json as default output format for non-TTY
- Added status command exception to output format requirements
- Added describe command schema versioning contract
- Clarified clause namespace vs filesystem storage independence
- Added case-sensitivity and timestamp format requirements
v0.1.0 (2026-01-19)
Initial draft
RFC-0003: TUI UX improvements
Version: 0.1.0 | Status: normative | Phase: stable Owners: @govctl-org Tags:
tui
1. Summary
[RFC-0003:C-SUM] Summary (Informative)
- Define a consistent TUI navigation frame with shared header and footer.
- Add list filtering and quick-jump for faster browsing.
- Improve detail view readability with consistent layout and scroll position.
Tags:
tui
Since: v0.1.0
2. Specification
[RFC-0003:C-NAV] Shared header/footer navigation (Normative)
- The TUI MUST render a persistent header and footer across all views.
- The header MUST show the current view hierarchy (breadcrumb) and basic counts for the active view.
- The footer MUST provide the current keymap for primary navigation, including quit and back.
- Existing navigation keys MUST remain functional.
Tags:
tui
Since: v0.1.0
[RFC-0003:C-FILTER] List filtering and quick-jump (Normative)
- List views MUST support an inline filter mode that matches ID, title, or status.
- Filter mode MUST be entered with a single key and exited without leaving the list view.
- When a filter is active, the list MUST show only matching items and navigation MUST operate over the filtered set.
- List views MUST support quick-jump to top and bottom and allow stepping through matches.
Tags:
tui
Since: v0.1.0
[RFC-0003:C-DETAIL] Detail view readability (Normative)
- Detail views MUST present metadata and content sections consistently across artifact types.
- Detail views MUST show scroll position to indicate where the user is within the content.
- Scrolling MUST not lose the current view context or selection.
Tags:
tui
Since: v0.1.0
Changelog
v0.1.0 (2026-02-07)
Initial draft
RFC-0004: Concurrent write safety for governance artifacts
Version: 0.1.1 | Status: normative | Phase: stable Owners: @govctl-org Tags:
safety
1. Summary
[RFC-0004:C-SUMMARY] Summary (Informative)
This RFC specifies that govctl MUST preserve integrity of governance artifacts when multiple processes invoke write operations concurrently (e.g. agent-triggered parallel tasks creating or editing RFCs, ADRs, or work items).
Scope: Applies to any command that modifies files under the gov root or writes rendered output under the docs root. The concrete mechanism to satisfy this requirement is an implementation detail.
Backward compatibility: Existing command invocations and arguments remain valid. This RFC adds only coordination and failure behaviour; it does not change command semantics.
Specification outline: The RFC defines terms (write command, read-only command, concurrent invocations, corrupted file); requires that every write command participate in a single global concurrency mechanism and that read-only commands never block on it; requires that concurrent writes never produce corrupted files, duplicate work item IDs, or lost read-modify-write updates; and requires predictable failure behaviour (bounded wait, then either proceed or fail with an actionable error) when the mechanism cannot be acquired.
Rationale: Concurrent writes without coordination cause file corruption, duplicate IDs, and lost updates. Agents and scripts often run multiple govctl invocations in parallel; the implementation must prevent observable corruption and provide clear behaviour on conflict.
Tags:
safety
Since: v0.1.0
2. Specification
[RFC-0004:C-CONCURRENT-WRITE] Concurrent write safety (Normative)
Commands that modify the governance tree or rendered output MUST use a concurrency mechanism such that:
- No two concurrent invocations (across processes) produce corrupted artifact files. Corrupted means: invalid JSON/TOML, truncated content, or interleaved content from different writes.
- Work item creation MUST NOT assign the same ID to two items created by concurrent invocations when both use the same ID prefix (e.g. same date under sequential or author-hash strategy). The scenario is same repository, concurrent processes (distinct from branch-merge ID collision).
- Read-modify-write operations (e.g. edit, set, bump) MUST NOT lose updates from another concurrent invocation modifying the same artifact.
This RFC requires the observable behaviour: artifact integrity and no duplicate IDs under concurrent write load. The concrete mechanism (e.g. process-level filesystem locking) is an implementation detail.
Rationale: Agents and CI may run multiple govctl write commands in parallel. Without a defined concurrency strategy, races are observable in practice (file corruption, duplicate WI IDs). The normative requirement ensures implementors address this.
Tags:
safety
Since: v0.1.0
[RFC-0004:C-DEFINITIONS] Definitions (Informative)
Write command: A govctl invocation that may create, modify, or delete files under the gov root, or write files under the docs root (e.g. render output). Any invocation that writes files under the docs root is a write command regardless of command name. Examples: rfc new, adr new, work new, clause new, guard new, rfc edit, adr edit, work edit, clause edit, guard edit, rfc bump, rfc finalize, rfc advance, adr accept, work move, render.
Read-only command: A govctl invocation that does not modify gov or docs. Examples: rfc list, adr list, work list, clause list, guard list, rfc get, adr get, work get, clause get, guard get, check, status. The commands show and describe are read-only when they do not write to gov or docs (e.g. when they output only to stdout).
Concurrent invocations: Two or more govctl processes running at the same time, such that their execution may overlap (e.g. multiple agent tasks, or a script spawning parallel govctl calls).
Corrupted artifact file: A file under gov or docs that does not conform to the expected schema (invalid JSON or TOML), or that contains truncated or interleaved content from more than one logical write.
Rationale: These definitions make the scope and guarantees of this RFC testable and unambiguous.
Tags:
safety
Since: v0.1.0
[RFC-0004:C-FAILURE-BEHAVIOUR] Behaviour when concurrency mechanism is unavailable (Normative)
When a write command cannot obtain exclusive access (e.g. because another write command is in progress), the implementation MUST either wait for a bounded time and then proceed, or wait for a bounded time and then fail. The maximum wait time is implementation-defined and MUST be documented. Implementations SHOULD use a default maximum wait of at least 30 seconds for interoperability and testability. The maximum wait time MAY be configurable.
If the implementation chooses to fail after waiting, it MUST exit with a non-zero status and MUST emit an actionable error message that indicates that another govctl write is in progress and that the user or agent should retry later. The message MUST NOT assume a specific concurrency mechanism (e.g. must not require the word “lock”).
If the implementation waits until access is granted, it MUST eventually proceed; it MUST NOT deadlock.
Implementations SHOULD ensure that exclusive access is released on process exit or that time-based expiry or stale-lock cleanup applies, so that a crashed process does not block writers indefinitely.
Rationale: Predictable failure behaviour allows agents and scripts to retry or serialise writes; clear errors avoid confusion. A documented, implementation-defined bound makes conformance testable; the 30-second SHOULD gives implementations and tests a shared expectation. The stale-lock note supports the “MUST NOT deadlock” requirement when a holder crashes.
Tags:
safety
Since: v0.1.0
[RFC-0004:C-SCOPE] Scope of write commands (Normative)
Every write command MUST participate in the concurrency mechanism before performing any mutation of the gov tree or docs output. Participation means acquiring exclusive access (or equivalent) for the duration of the write operations performed by that invocation.
Read-only commands MUST NOT acquire exclusive access and MUST NOT block on the concurrency mechanism. They MAY run concurrently with each other and with at most one write command.
The concurrency mechanism SHALL apply to the entire gov root (and, when a command writes rendered output, to the docs root) as a single unit. Exclusive access MUST NOT be held by more than one write command at the same time.
Rationale: Defining scope ensures that all mutation paths are covered and that read-only usage is never blocked by writers.
Tags:
safety
Since: v0.1.0
Changelog
v0.1.1 (2026-07-26)
Refresh command examples for the canonical edit surface
Fixed
- Replace removed mutation command examples with canonical commands
v0.1.0 (2026-02-15)
Initial draft
RFC-0006: Loop Execution Model
Version: 1.0.0 | Status: normative | Phase: stable Owners: @govctl-org
1. Summary
[RFC-0006:C-SUMMARY] Summary (Informative)
This RFC defines the loop execution model for coordinating local agent execution rounds around one or more Work Items.
A loop is a first-class local execution concept that tracks one or more Work Items through dependency-aware rounds of implementation, verification evidence collection, and refinement. Loops support:
- Single Work Item execution context: Create resumable local round state for one Work Item
- Multi-Work Item batch execution context: Coordinate several Work Items with dependency resolution and deterministic readiness ordering
- Failure and blocker propagation: Represent failed, blocked, or cancelled loop-level outcomes without adding new Work Item lifecycle states
- Resumption: Resume interrupted execution from loop state and round artifacts
The loop model maintains clear separation between:
- Work Items: Durable outcome artifacts that contain scope (
description), success criteria (acceptance_criteria), durable memory (notes), references, dependencies, and verification policy - Loop state: Local execution state that tracks rounds, selected work, summary evidence, blockers, and next action
This separation ensures Work Items remain clean outcome artifacts while enabling rich local execution traceability for debugging and resumption.
Loops interact with Work Item lifecycle exclusively through existing govctl work semantics. govctl loop run advances local round state; it does not implement code, tick acceptance criteria, add notes, or mark Work Items done on behalf of the agent.
Tags:
core
Since: v0.1.0
2. Specification
[RFC-0006:C-LOOP-DEFINITION] Loop Definition (Normative)
A loop is a local execution session that coordinates one or more Work Items through iterative rounds of agent implementation, verification evidence collection, and refinement.
Each loop MUST:
- Be initialized from an explicit, finite root set of Work Items
- Resolve the transitive dependency closure before execution begins
- Recompute the transitive dependency closure after any successful scope mutation defined by RFC-0006:C-LOOP-SCOPE-MUTATION
- Track execution state independently of Work Item files
- Store transient round evidence in loop-local artifacts rather than Work Item fields
- Terminate when all Work Items in the current resolved loop set reach terminal loop-level outcomes or a failure condition is met
A loop MAY support explicit scope mutation after start. A scope mutation MUST be requested through loop commands; implementations MUST NOT treat unrelated Work Item file edits as implicit loop scope changes.
A loop MUST NOT:
- Modify Work Item files directly except by invoking existing
govctl workcommand semantics where explicitly required - Persist execution trace to Work Item fields; execution trace belongs in loop state and round artifacts
- Assume a specific implementation order (sequential or parallel) beyond dependency readiness
- Introduce parallel replacements for Work Item
notes,depends_on, acceptance criteria, or verification guards
Rationale: Loops are a first-class execution concept that coordinates Work Item completion without becoming a second Work Item model. By keeping loops separate from Work Item files, govctl preserves the boundary between local execution trace (ephemeral) and governance artifacts (durable). Work Item notes hold durable constraints and learnings that should survive future work; loop state holds transient execution evidence. Explicit scope mutation lets long cleanup loops adapt without replacing the execution session identity.
Tags:
core
Since: v0.1.0
[RFC-0006:C-LOOP-LIFECYCLE] Loop Lifecycle (Normative)
A loop MUST have exactly one of the following lifecycle states:
- pending — Initial state. The loop is defined but execution has not started.
- active — The loop is currently executing rounds on work items.
- paused — Execution stopped before a terminal outcome and may be resumed.
- completed — All work items in the resolved loop set reached non-failed terminal loop outcomes (
doneorcancelled) without anyfailedorblockedloop outcomes. - failed — An unrecoverable failure condition was met, such as a critical local-state error, an explicit failed work item, or a blocked dependency chain.
Valid transitions:
- pending → active (loop execution begins)
- active → paused (loop pauses for resumption)
- paused → active (loop execution resumes)
- active → completed (all work items finish without failed or blocked outcomes)
- active → failed (failure condition met)
- paused → failed (resumption detects unrecoverable state)
Invalid transitions (MUST be rejected):
- completed → any (terminal state)
- failed → any (terminal state)
- pending → completed (cannot complete without being active)
- pending → failed (cannot fail without being active)
- paused → completed (completion requires active execution)
Round count is audit metadata. Implementations MUST NOT infer loop failure, Work Item failure, or dependency blockage from round count alone.
Rationale: The loop lifecycle provides clear semantics for tracking execution progress and enables resumption after interruption. A distinct paused state avoids overloading pending, which means execution has not started. Terminal states (completed, failed) indicate the loop has finished and cannot be restarted. Keeping round count out of failure semantics preserves the separation between govctl’s local round protocol and caller-level retry policy.
Tags:
lifecycle,core
Since: v0.1.0
[RFC-0006:C-DEPENDENCY-SEMANTICS] Work Item Dependency Semantics (Normative)
Work items MAY declare dependencies on other work items using the depends_on field in the [govctl] section. The depends_on field MUST contain a list of work item IDs.
The depends_on field is an optional Work Item metadata field for repositories implementing this RFC. Implementations that validate Work Items against a JSON Schema MUST include govctl.depends_on as an optional array of Work Item IDs in that schema.
At loop start, and after every scope mutation, the loop MUST resolve the dependency closure for the current explicit root set. The resolved loop set MUST include every transitive depends_on dependency needed by the current root set. If any dependency ID does not identify an existing Work Item, the loop start or scope mutation MUST be rejected before the new state becomes authoritative.
Dependency rules:
-
Acyclicity: The dependency graph MUST be acyclic. Implementations MUST detect cycles at loop start and after scope mutation and reject the operation before the new state becomes authoritative. The diagnostic MUST include at least one Work Item ID from the detected cycle.
-
Selection readiness: A work item MUST NOT be selected for new round work until every dependency has a terminal loop-level outcome.
-
Outcome checking: After a dependency reaches a terminal loop-level outcome, the loop MUST check that outcome:
- If all dependencies are
done: the dependent work item MAY be selected for round work - If any dependency is
cancelled,failed, orblocked: the dependent work item MUST be marked asblockedin loop state and MUST NOT be selected
- If all dependencies are
-
Distinction from refs: The
depends_onfield is distinct fromrefs:refs: informational cross-references to related artifacts (RFCs, ADRs, work items)depends_on: blocking execution dependencies (work items only)
-
Failure propagation: When a work item is marked as
blocked, all work items that depend on it (directly or transitively) MUST also be marked asblocked.
Loop-level status tracking: The blocked, failed, and cancelled states are loop-level execution statuses tracked in loop state, not additional Work Item status field values. Work Items maintain their own lifecycle states (queue, active, done, cancelled) per RFC-0001:C-WORK-STATUS. A Work Item with Work Item status cancelled MUST be represented as cancelled in loop state when it is part of the resolved loop set.
Rationale: Dependencies enable complex workflows where work items must be selected in a specific order. By keeping depends_on separate from refs, we maintain clear semantics: refs are informational, depends_on are blocking. Resolving a dependency closure preserves an explicit root set while ensuring the loop has every prerequisite needed for deterministic planning. Re-resolving after explicit scope mutation lets a long-running loop adapt to corrected or newly discovered work without losing its execution session. Loop-level status tracking avoids polluting the Work Item status field with execution-specific states.
Tags:
lifecycle,validation,work-items
Since: v0.1.0
[RFC-0006:C-ROUND-EXECUTION] Round Execution (Normative)
Loop rounds are local execution-protocol checkpoints for one loop, not automatic implementation performed by govctl.
A loop round MAY cover one or more work items from the loop’s current resolved dependency closure. The selected work set for a round MUST be derived from the loop state, dependency readiness, and any explicit --work selector accepted by RFC-0006:C-LOOP-COMMAND-SURFACE.
Round lifecycle:
Each round MUST have one of these local round states:
- open — govctl has created the round skeleton and the agent is expected to implement, verify, and fill the summary evidence.
- submitted — the round summary evidence has been provided but has not yet been incorporated into authoritative loop state.
- closed — govctl has validated the round evidence and updated loop state.
govctl loop run LOOP-ID MUST advance exactly one local round-protocol step. It MUST NOT implement repository changes itself. It MUST NOT mark a Work Item done directly merely because loop-local criteria appear satisfied. Work Item lifecycle transitions remain owned by govctl work move per RFC-0002:C-LIFECYCLE-VERBS.
Opening a round:
When no open round exists, loop run MUST:
- Load and validate the loop state.
- Re-read current Work Item files for the selected work set.
- Verify dependency readiness using RFC-0006:C-DEPENDENCY-SEMANTICS.
- Create a loop-level round artifact under the loop directory.
- Write a summary skeleton that records where the agent MUST provide actions, changed paths, verification evidence, blockers, and note candidates.
- Display the round artifact path and the next required agent action.
Opening a round MAY update loop-local item statuses and round counters, but MUST NOT write transient execution trace into Work Item files. Round counters are audit metadata only and MUST NOT control selection, failure, or dependency propagation.
Closing a round:
When an open round exists, loop run MUST validate the round summary before advancing loop state. A round summary MUST distinguish:
- actions performed during the round
- changed paths or explicitly state that no file changes were made
- verification evidence, including existing
govctl verify --work WI-IDor project guard output when applicable - blockers or open questions
- note candidates that may become durable Work Item
notesthrough explicitgovctl work edit <WI-ID> notes --add ...
If required summary evidence is missing, loop run MUST return a Diagnostic that names the round artifact to complete and MUST leave loop state unchanged.
If blockers prevent progress, loop run MUST keep the loop non-terminal and record the next action in loop state. Durable retry rules MAY be added to Work Item notes, but only through explicit Work Item commands.
If the relevant Work Items have already reached terminal Work Item lifecycle states through govctl work move, loop run MUST reflect those lifecycle states in loop-local item status and MAY mark the loop completed when every current resolved item is terminal without failed or blocked loop outcomes.
loop run MUST NOT infer loop failure, Work Item failure, or dependency blockage from the number of rounds opened or closed for a Work Item.
Rationale:
govctl coordinates local execution state, Work Item metadata, dependency readiness, and verification evidence while the agent performs implementation work. This keeps loop execution trace in local loop artifacts and preserves Work Items as durable outcome artifacts. Retry budgets and repeated-invocation limits belong to callers because callers decide how much autonomous execution is appropriate.
Tags:
core,validation
Since: v0.1.0
[RFC-0006:C-WORK-ITEM-INTERACTION] Work Item Interaction (Normative)
Loops interact with work items by reading Work Item lifecycle state, mapping it into loop-local item state, and recording local execution evidence. Loops MUST NOT own Work Item lifecycle transitions.
Lifecycle ownership:
- Work Items in the resolved loop set MUST remain valid Work Items whose lifecycle state is one of
queue,active,done, orcancelled. govctl loop runMUST NOT transition a Work Item fromqueuetoactive.govctl loop runMUST NOT transition a Work Item fromactivetodone.- Work Item lifecycle transitions remain owned by
govctl work moveand its existing acceptance-criteria and verification-guard gates. - A Work Item with lifecycle state
doneMUST be represented asdonein loop state when reflected by a loop operation. - A Work Item with lifecycle state
cancelledMUST be represented ascancelledin loop state when reflected by a loop operation and MUST NOT be selected for new round work.
Validation requirements:
Before a Work Item is transitioned to done, the Work Item lifecycle command MUST verify the existing gate conditions defined by RFC-0001:C-GATE-CONDITIONS. A loop MAY record verification evidence in round summary artifacts, but that evidence does not replace the Work Item lifecycle gate.
Durable work item context:
The work item notes field is reserved for durable context that should persist across sessions:
- Key decisions made during implementation
- Blockers encountered and how they were resolved
- Important technical insights
Execution trace, including round-by-round progress, MUST be tracked in loop state and round artifacts, not in Work Item fields.
Loop-level work item status:
The loop tracks additional execution status for each work item in loop state:
pending: Work item has not been selected or reflected as active/done/cancelled in this loopactive: Work item is selected for local execution protocol or remains in progressdone: Work item completed successfully through Work Item lifecycle statefailed: Local loop execution evidence records an unrecoverable failure and dependents must not be selectedblocked: Work item cannot be selected because dependencies failed, blocked, or were cancelledcancelled: Work item has Work Item statuscancelledand is not selected
The loop-level statuses are independent of Work Item status field values except where explicitly mapped above. done, failed, blocked, and cancelled are terminal loop-level outcomes for dependency planning.
Rationale: Existing Work Item commands already provide lifecycle validation, acceptance criteria, verification guards, and durable governance history. Loops provide resumable local execution protocol state around those commands without becoming a second Work Item lifecycle engine. Separating loop-level status from Work Item status and notes maintains clear boundaries between execution state and governed artifacts.
Tags:
lifecycle,validation,work-items
Since: v0.1.0
[RFC-0006:C-LOOP-RESUMPTION] Loop Resumption (Normative)
A loop MAY be paused and resumed across CLI invocations or agent sessions.
If a loop implementation supports resumption, it MUST:
- Persist loop state using the storage contract defined by RFC-0006:C-LOOP-STATE-STORAGE.
- Resume existing loop operations by positional
LOOP-IDas defined by RFC-0006:C-LOOP-COMMAND-SURFACE. - Resume from the last recorded state and open round artifact rather than starting fresh when the requested loop state exists and is non-terminal.
- Reject operations that require a non-terminal loop when the loop is terminal.
Discovery semantics:
Loop discovery MUST be separate from loop execution. Implementations MAY discover existing loops by listing persisted state, by filtering list output, or by reusing an existing non-terminal loop during loop start [--id LOOP-ID] WI-ID... when the requested work set matches exactly.
A stored loop matches a requested work set when its current editable work field contains the same Work Item IDs as the request, ignoring order. If a command performs work-set discovery and exactly one matching non-terminal loop exists, the implementation MAY select that loop. If more than one matching non-terminal loop exists, the implementation MUST reject the discovery attempt as ambiguous and require a positional LOOP-ID.
loop run MUST NOT perform work-set discovery and MUST NOT start a new loop.
Resumption semantics:
When resuming a loop:
- Work items in
doneloop state MUST NOT be selected for new round work. - Work items in
activeloop state MAY be selected again only through the local round protocol. - Work items in
blocked,failed, orcancelledloop state MUST remain terminal for dependency planning unless an explicit scope mutation recomputes a dependency-derivedblockedoutcome. - Work items in
pendingloop state MAY be selected in dependency order when opening a round unless an explicit run selector narrows execution per RFC-0006:C-LOOP-COMMAND-SURFACE. - If
loop.current_roundpoints at an open round artifact,loop runMUST validate or reject that artifact before opening another round. - Prior round counts MUST NOT prevent a non-terminal work item from being selected again when it is otherwise ready.
State preservation:
The loop state MUST preserve:
- Execution status of each current work item (pending, active, done, failed, blocked, cancelled)
- Round count for each current work item as audit metadata
- Last selected round for each current work item when known
- Current editable
workfield values - Dependency graph at last planning time
- Current loop-level round number when known
- Next required action when known
The loop state MAY preserve:
- Detailed round history
- Guard execution result summaries
- Agent context and decision history inside local round artifacts
Rationale: Resumption enables long-running multi-WI loops to survive agent session boundaries without losing progress. Positional loop IDs provide precise lookup that matches the CLI’s noun/verb/object shape. Work-set matching remains a discovery convenience for start/list workflows, not an execution command mode. By persisting state independently of work item files, govctl maintains the separation between execution state and governed artifacts. Scope mutation makes the stored work set current rather than historical, so discovery continues to match the loop the user intends to resume. Round counts remain useful for audit and display without becoming hidden retry policy.
Tags:
lifecycle
Since: v0.1.0
[RFC-0006:C-LOOP-STATE-STORAGE] Loop State Storage (Normative)
Loop execution state MUST be stored under .govctl/loops/<loop-id>/.
A loop ID is local execution-state identity, not a governed resource ID. A generated loop ID MUST match ^LOOP-\d{4}-\d{2}-\d{2}-\d{3}$. The date component MUST use ISO 8601 calendar date format YYYY-MM-DD for the local date when the ID is generated. The sequence component MUST be a three-digit positive sequence starting at 001 for each date. Implementations MUST choose the first available sequence for the date that does not collide with an existing .govctl/loops/<loop-id>/ directory. Implementations MUST generate a loop ID when one is omitted. Implementations MUST reject explicit loop IDs that do not match the canonical loop ID pattern. A loop ID MUST NOT contain /, \, or .. path traversal segments.
Each loop directory MUST contain state.toml as its authoritative current-state file. The state.toml file MUST use the following top-level shape:
[loop]
id = "<loop-id>"
state = "pending|active|paused|completed|failed"
work = ["WI-YYYY-MM-DD-NNN"]
resolved = ["WI-YYYY-MM-DD-NNN"]
current_round = 0
next_action = "start|write_summary|continue|resolve_blocker|complete"
[dependencies]
"WI-YYYY-MM-DD-NNN" = ["WI-YYYY-MM-DD-NNN"]
[items."WI-YYYY-MM-DD-NNN"]
status = "pending|active|done|failed|blocked|cancelled"
round_count = 0
last_round = 0
The loop.id value MUST match the <loop-id> directory name. The loop.state value MUST be one of the loop lifecycle states defined by RFC-0006:C-LOOP-LIFECYCLE. The loop.work array MUST preserve the current explicit work item set for the loop. The loop.resolved array MUST contain the current resolved dependency closure and MUST include every loop.work entry. The loop.work and loop.resolved arrays MUST NOT contain duplicate Work Item IDs.
The optional loop.current_round value records the latest loop-level round number known to state. The optional loop.next_action value records the next required human or agent action. Older state files that omit these fields MAY be upgraded in place when written.
The [dependencies] table MUST contain one entry for each work item in loop.resolved. Each dependency entry MUST be an array of Work Item IDs. Each dependency ID MUST also appear in loop.resolved. Dependency arrays MUST NOT contain duplicate Work Item IDs.
The [items.<WI-ID>] table MUST contain one entry for each work item in loop.resolved. Each item status MUST be one of the loop-level work item statuses defined by RFC-0006:C-WORK-ITEM-INTERACTION. Each round_count MUST be a non-negative integer. The optional last_round value records the last loop-level round that selected or updated the item. round_count and last_round are audit metadata and MUST NOT encode retry budgets or failure policy.
Loop state storage MUST be keyed by loop ID, not by work item ID. A multi-work-item loop MUST have one shared loop state root so dependency planning, failure propagation, and resumption use the same authoritative state.
Loop round artifacts MUST be stored under .govctl/loops/<loop-id>/rounds/round-NNN.toml, where NNN is the three-digit loop-level round number. A round artifact MUST identify the loop ID, round number, selected work item IDs, round state, summary evidence, blockers, and note candidates. Round artifacts MUST NOT encode maximum round limits or caller retry budgets. Round artifacts are local execution trace and MUST NOT be written to Work Item fields.
Round artifacts MAY mention Work Item IDs when evidence applies to specific work, but the storage root is loop-level. Implementations MUST NOT require per-work-item round directories for the canonical state model.
Loop state is local execution state, not a governed artifact. Deleting .govctl/loops/ MUST NOT invalidate RFCs, ADRs, Work Items, Guards, or rendered governance projections, but MAY remove resumability and local execution trace.
Rationale: A loop can drive multiple work items, so a per-work-item state root cannot represent the loop lifecycle, dependency graph, aggregate outcome, or round evidence. A single loop directory keeps execution state separate from Work Item files while preserving enough protocol state for resumption. Canonical generated loop IDs follow the existing artifact style of a type prefix, date, and sequence while avoiding collision-prone plain-text IDs. Keeping retry budgets out of persisted loop state prevents caller policy from becoming hidden local-state semantics.
Tags:
core
Since: v0.1.0
[RFC-0006:C-LOOP-SCOPE-MUTATION] Loop Scope Mutation (Normative)
A loop implementation MAY support explicit scope mutation for a non-terminal loop. A scope mutation changes or refreshes the loop’s current editable work field and recomputes the resolved dependency closure without creating a new loop ID.
Scope mutation MUST support these operations:
- Replan: keep the current editable
workfield and recompute its dependency closure from the current work item files. - Add work: add one Work Item ID to the current editable
workfield, then recompute the dependency closure. - Remove work: remove one Work Item ID from the current editable
workfield, then recompute the dependency closure.
Implementations MUST reject scope mutation for terminal loops. Implementations MUST reject scope mutation that would leave the editable work field empty. Implementations MUST validate added or removed work values as Work Item IDs. Implementations MUST store the explicit work set without duplicates.
A scope mutation MUST build a candidate loop state before replacing the stored state. The candidate state MUST use the current explicit work set after the requested add/remove/replan operation. The candidate state MUST resolve dependencies using the rules in RFC-0006:C-DEPENDENCY-SEMANTICS. If dependency resolution fails, the implementation MUST leave the previously stored loop state unchanged.
For work items that remain in the resolved dependency closure, scope mutation MUST preserve round_count. Scope mutation MUST preserve explicit terminal execution outcomes done, failed, and cancelled. Scope mutation MUST recompute blocked outcomes from the current dependency graph and current terminal dependency outcomes; a previously blocked work item MAY return to pending when its current dependencies no longer require blocking. Non-terminal work items MUST NOT be selected for a new round until their current dependencies satisfy RFC-0006:C-DEPENDENCY-SEMANTICS.
For newly introduced work items, scope mutation MUST initialize loop-level item state using the same Work Item status mapping used at loop start. For work items that no longer appear in the resolved dependency closure, scope mutation MUST remove their entries from loop.resolved, [dependencies], and [items] in state.toml. Removing a work item from current loop state MUST NOT undo any Work Item lifecycle transitions that already happened through govctl work commands. Optional historical round artifacts for removed work items MAY remain under the loop directory, but they MUST NOT be treated as part of the current loop state.
Rationale:
Long-running cleanup and implementation loops often discover that the original batch is missing work, contains unnecessary work, or needs dependency files re-read after edits. Scope mutation keeps one execution session identity while making the current work field and dependency closure explicit, validated, and recoverable. Modeling this as a field mutation keeps loop commands aligned with the existing edit model while preserving loop-specific replanning behavior.
Since: v0.2.0
[RFC-0006:C-LOOP-LISTING] Loop Listing (Normative)
If provided, the listing command MUST enumerate persisted loop state from .govctl/loops/*/state.toml without requiring a caller to know a loop ID or work item set first. The command MUST validate each canonical loop state it lists using the storage contract in RFC-0006:C-LOOP-STATE-STORAGE.
The listing command MUST produce deterministic output ordered by loop ID. Each listed loop MUST include at least the loop ID, lifecycle state, editable work field values, resolved work item count, and aggregate round count across current loop items. Machine-readable output, when supported, MUST expose the same user-facing fields.
The listing command MAY support filters by lifecycle state, loop ID substring, or work item ID substring. Filtering MUST NOT mutate loop state and MUST NOT select a loop for execution by itself.
Rationale: Work-set discovery is useful only after the caller has a stable loop identity. A listing command gives agents and humans a stable discovery entrypoint for interrupted or long-running batch loops while preserving the rule that loop state remains local execution state rather than a governed artifact. The caller can then pass the listed loop ID as the positional object to commands such as loop run, loop show, or loop resume.
Since: v0.3.0
[RFC-0006:C-LOOP-COMMAND-SURFACE] Loop Command Surface (Normative)
Implementations that expose a govctl loop command MUST treat it as a project-level local execution-state command namespace as defined by RFC-0002:C-GLOBAL-COMMANDS. Loop state is not a governed artifact resource, so loop commands MUST NOT expose unrestricted resource CRUD field-editing verbs for arbitrary loop state. Loop commands MAY expose specified editable fields whose semantics are defined by this RFC.
Argument roles:
Loop command arguments MUST have stable roles:
- A positional
LOOP-IDargument identifies an existing persisted local loop state directory. - A
--id LOOP-IDflag MAY be used only by commands that create a loop state, where it requests the ID to create or reuse. - Positional
WI-ID...arguments identify explicit loopworkfield values for loop creation or field mutation. - Positional
WI-ID...arguments MUST NOT mean an execution target subset. - Execution target selection MUST use an explicit selector flag.
- Loop field mutation MUST use the explicit
add LOOP-ID work WI-IDandremove LOOP-ID work WI-IDshapes defined below.
Canonical subcommands:
The canonical loop subcommands are:
loop list [filter]: read persisted loop states. This command MUST be read-only.loop show LOOP-ID: read one persisted loop state by loop ID. This command MUST be read-only.loop start [--id LOOP-ID] WI-ID...: create or reuse a loop for an explicitworkfield set.loop resume LOOP-ID: select and display an existing non-terminal loop by loop ID. This command MUST be read-only and MUST NOT advance rounds.loop run LOOP-ID [--work WI-ID ...]: advance the local round protocol for an existing loop state.loop replan LOOP-ID: recompute the dependency closure for the current explicitworkfield set.loop add LOOP-ID work WI-ID: add a Work Item ID to the loop’s editableworkfield and replan.loop remove LOOP-ID work WI-ID: remove a Work Item ID from the loop’s editableworkfield and replan.
loop run MUST NOT accept a maximum-rounds argument or any other caller retry-budget argument. Repeated execution limits belong to callers and MUST NOT be persisted in loop state or round artifacts.
The work field is the only accepted user-facing field name for the loop’s explicit work set. Implementations MUST reject wi and every other field alias.
Discovery semantics:
loop start [--id LOOP-ID] WI-ID... MAY reuse an existing non-terminal loop with the same current explicit work field set instead of creating a new loop. If more than one non-terminal loop matches the requested work set, the implementation MUST reject the operation as ambiguous and require the caller to use loop list and then pass a positional LOOP-ID to the desired operation.
loop list [filter] MUST support discovering loop state without requiring a caller to know a loop ID first per RFC-0006:C-LOOP-LISTING. Work-set discovery is a discovery behavior, not an execution selector.
loop run MUST NOT start a new loop and MUST NOT discover a loop by positional Work Item IDs. It operates only on the positional LOOP-ID argument.
Run selection semantics:
The --work WI-ID flag selects execution targets inside the loop identified by the positional LOOP-ID. Implementations MUST reject duplicate --work values. Implementations MUST reject any --work value that is not a Work Item ID in the current loop.resolved array. These validations MUST complete before writing loop state.
If no --work selector is provided, loop run LOOP-ID MUST consider every current work item in the loop’s resolved dependency closure when opening a round, subject to dependency readiness.
If one or more --work selectors are provided, loop run LOOP-ID --work WI-ID... MUST restrict the opened or advanced round to the selected target work items and their current in-loop transitive dependencies. The implementation MUST NOT select unrelated work items for that round. The implementation MAY update derived loop-level dependency outcomes, such as blocked dependents, when required to keep loop state consistent with RFC-0006:C-DEPENDENCY-SEMANTICS.
Targeted run selection MUST NOT replace, shrink, expand, or otherwise mutate the loop’s editable work field. Scope changes MUST use replan, add, or remove.
loop run MUST NOT silently perform repository implementation work, tick acceptance criteria, add Work Item notes, or move Work Items to done. Agents and humans MUST perform those operations through the existing Work Item and verification command surfaces. loop run records and validates local round evidence so those existing operations have resumable execution context.
Rationale:
The loop command namespace coordinates several governed resources but stores its own local execution state, so it is neither a governed artifact resource nor a simple single global command. Existing-loop operations use positional LOOP-ID arguments to match the rest of the CLI’s noun/verb/object shape. Stable argument roles prevent hidden mode switches: positional work item IDs in add and remove are field values for the loop’s work field, while --work is the explicit work-item execution selector. Keeping the field position visible preserves the CLI edit model while making loop-specific replanning a domain side effect of changing the field. Reusing run as the round-protocol advancement command preserves existing skill guidance while removing the misleading interpretation that govctl itself implements code. Excluding retry-budget flags keeps the command surface small and leaves autonomous execution policy to callers.
Since: v0.4.0
3. Rationale
[RFC-0006:C-UNIFIED-MODEL] Unified Model Rationale (Informative)
The unified loop model (single primitive for both single-WI and multi-WI execution) was chosen over separate /loop and /batch skills because:
-
Work items naturally form DAGs: Agents frequently create multiple related work items with dependencies, then iterate through them as a batch. Separate skills would force users to choose between
/loop WI-001and/batch WI-001 WI-002 WI-003when the underlying mechanism is identical. -
Simpler mental model: “A loop drives work items to completion” is one concept. “A loop drives one work item, a batch drives multiple” is two concepts with overlapping semantics.
-
Consistent state model:
.govctl/loops/<loop-id>/works the same whether the loop contains one work item or ten. Execution logs, state file, and round logs scale naturally. -
Downstream flexibility: The loop does not prescribe sequential or parallel execution. Downstream applications (agents, CI systems) can choose the execution model that fits their constraints.
Tags:
core
Since: v0.1.0
[RFC-0006:C-EXECUTION-STATE-SEPARATION] Execution State Separation Rationale (Informative)
Execution state lives in .govctl/loops/<loop-id>/ (not in work item TOML) because:
-
Work items are outcome artifacts: They should contain scope (description), success criteria (acceptance_criteria), and durable context (notes). They should not accumulate execution logs during active work.
-
Rich execution traceability: Loops need to track round-by-round progress, guard results, criteria addressed per round, and detailed logs. This is too much data for a work item TOML file.
-
Clean diffs: Work item TOML files remain stable and reviewable. Execution state changes frequently during a loop and is not meant for code review.
-
Ephemeral by design: Loop state is local to the developer’s machine. It can be deleted without losing governance artifacts. The work item’s
notesfield captures durable learnings. -
Shared loop coordination: Multi-work-item loops need one state root for lifecycle, dependency graph, failure propagation, and resumption. A per-work-item state root would force the loop to reconstruct shared state from fragments.
Tags:
core
Since: v0.1.0
[RFC-0006:C-DEPENDENCY-SEPARATION] Dependency Separation Rationale (Informative)
The depends_on field is separate from refs because they serve different purposes:
-
refs: Informational cross-references (“this work item is related to that RFC”). Does not block execution. Used for traceability and navigation. -
depends_on: Execution dependencies (“this work item cannot start until that work item completes”). Blocks execution. Used for dependency resolution and failure propagation.
Conflating these would force the loop to guess whether a ref is a hard dependency or just a related artifact. Separate fields make intent explicit.
Tags:
core,work-items
Since: v0.1.0
Changelog
v1.0.0 (2026-07-25)
Use canonical loop command and round metadata surfaces
Changed
- Use canonical Work Item edit syntax in round evidence guidance
Removed
- Remove the loop work-item field alias and legacy round metadata tolerance
v0.5.0 (2026-06-15)
Remove loop max-rounds budget from the round protocol
Changed
- round_count is audit metadata and cannot drive failure semantics
Removed
- loop run –max-rounds retry-budget argument
- max_rounds from new loop round artifacts
v0.4.0 (2026-06-03)
Define loop command surface
Added
- Loop command surface defines canonical loop subcommands and argument roles
Changed
- Loop run advances an existing local round protocol by LOOP-ID with explicit –work target selection
v0.3.0 (2026-06-01)
Define loop listing discovery
Added
- Loop listing command discovers persisted local loop state
v0.2.0 (2026-06-01)
Define loop scope mutation and canonical loop IDs
Added
- Loop scope mutation supports replan plus add/remove of the editable work field
Changed
- Loop IDs use LOOP-YYYY-MM-DD-NNN canonical format
v0.1.0 (2026-05-31)
Initial draft
RFC-0007: TUI v2 read-only cockpit
Version: 0.4.0 | Status: normative | Phase: impl Owners: @govctl-org Tags:
tui
References: RFC-0003, RFC-0006, RFC-0002, RFC-0008
1. Summary
[RFC-0007:C-SUMMARY] Summary (Informative)
This RFC defines TUI v2 as a human-first, read-only cockpit for understanding a governed project.
TUI v2 builds on the baseline browsing behavior in RFC-0003, the global search contract in RFC-0002:C-SEARCH-COMMAND, and the loop state model in RFC-0006. It focuses on project overview, artifact discovery, loop state visualization, diagnostics, and readable navigation.
Scope: This RFC covers externally visible TUI behavior and interaction constraints. It does not specify private Rust module layout, ratatui widget internals, or a full interactive artifact editor.
Rationale: The existing TUI is useful for browsing RFCs, ADRs, and work items, but it does not expose newer governance concepts such as search, loop local state, dependency DAGs, guards, releases, or check diagnostics. TUI v2 should help a human understand project state quickly without creating a second mutation surface parallel to the CLI.
Since: v0.1.0
2. Specification
[RFC-0007:C-READ-ONLY] Read-only cockpit boundary (Normative)
TUI v2 MUST be read-only for governed project state in its first implementation phase.
TUI v2 MUST NOT create, edit, delete, move, finalize, accept, reject, supersede, deprecate, render, or otherwise mutate governed artifacts.
TUI v2 MUST NOT mutate persisted loop state or round artifacts under .govctl/loops/.
TUI v2 MAY refresh disposable derived local indexes under .govctl/ only when doing so follows the freshness and local-state rules defined by RFC-0002:C-SEARCH-COMMAND.
When TUI v2 presents an operation that would mutate state, it MUST present it as a suggested CLI command or help text rather than executing it.
Rationale: The CLI already owns mutation semantics, dry-run behavior, diagnostics, lock handling, and lifecycle gates. Keeping the first TUI v2 phase read-only gives humans a richer project cockpit without creating a second, weaker edit model.
Since: v0.1.0
[RFC-0007:C-RESPONSIBILITY-BOUNDARIES] TUI responsibility boundaries (Normative)
TUI v2 MUST keep terminal I/O, input dispatch, data loading, and rendering as separate responsibilities.
The terminal adapter MUST be limited to terminal lifecycle, event polling, event reading, frame drawing, and shutdown handling.
Input dispatch MUST translate keyboard input into in-memory TUI state transitions.
Input dispatch MUST NOT perform filesystem I/O, database access, command execution, terminal drawing, or governed artifact mutation.
Renderers MUST read already-loaded TUI state and draw frames.
Renderers MUST NOT load project artifacts, refresh indexes, execute commands, mutate governed state, or mutate persisted loop state.
Data-loading code MUST convert filesystem, schema, search-index, and loop-state failures into visible diagnostic state rather than hiding them from the cockpit.
New primary views or key-routing behavior SHOULD be covered by focused state-transition tests, renderer tests using a terminal test backend, or both.
Rationale: These boundaries keep TUI v2 human-facing, read-only, and testable without creating a second hidden execution model beside the CLI.
Since: v0.2.0
[RFC-0007:C-COCKPIT-VIEWS] Cockpit view model (Normative)
TUI v2 MUST provide a top-level human navigation model with visible entry points for overview, artifact browsing, search, loops, and diagnostics.
The overview view MUST summarize at least RFCs, ADRs, work items, and verification guards when those artifacts are available.
The artifact browsing views MUST preserve the existing RFC, ADR, and Work Item browsing capabilities required by RFC-0003.
The artifact browsing views SHOULD include verification guards, clauses, releases, and tags when those data sources can be loaded without violating RFC-0007:C-READ-ONLY.
Artifact detail views MUST use the current projection defined by RFC-0002:C-SHOW-PROJECTION so obsolete RFC, ADR, and Clause body content is omitted by default.
The current view, selection context, active filter or query, and primary key bindings MUST remain visible or discoverable without leaving the TUI.
Rationale: A cockpit should orient a human before asking them to drill into details. Reusing the current projection keeps obsolete requirements from appearing authoritative, while the CLI retains explicit archival access. The top-level model makes newer governance concepts discoverable while preserving the older RFC/ADR/Work browsing workflows.
Since: v0.1.0
[RFC-0007:C-LOOP-VIEWS] Loop state views (Normative)
TUI v2 MUST provide a loop list view that discovers persisted loop states according to RFC-0006:C-LOOP-LISTING.
Each listed loop MUST show the loop ID, lifecycle state, editable work roots, resolved work item count, aggregate round count, and next action when those values are present in valid loop state.
TUI v2 MUST provide a loop inspector for a selected loop.
The loop inspector MUST show the selected loop’s lifecycle state, current round, next action, editable work roots, resolved work set, loop-level item statuses, round counts, and dependency information.
If a loop state file is invalid, TUI v2 MUST present a readable diagnostic for that loop and MUST NOT treat invalid loop state as authoritative.
TUI v2 MUST NOT repair, replan, resume, run, or otherwise mutate loop state while rendering loop views.
Rationale: Loop state is local but highly useful to humans resuming or auditing work. The TUI should expose this state directly while preserving RFC-0006 ownership of loop execution semantics.
Since: v0.1.0
[RFC-0007:C-LOOP-DAG] Loop dependency DAG visualization (Normative)
TUI v2 MUST render a selected loop’s dependency graph as a visual DAG derived from the loop state’s dependencies table.
The DAG view MUST represent every work item in the loop state’s resolved work set unless viewport constraints require an explicit neighborhood or layer-limited fallback.
The DAG view MUST distinguish loop-level item statuses such as pending, active, done, failed, blocked, and cancelled using readable text and semantic styling.
The DAG view MUST make the selected work item visually distinct and MUST show its direct dependencies and direct dependents when that information is available.
The DAG layout MUST be deterministic for the same loop state.
When the graph is too large or the terminal viewport is too small for a full DAG, TUI v2 MUST degrade to a readable representation that still exposes ordering, dependencies, selected item context, and hidden item counts.
Rationale: A plain topological list is not enough for humans to understand batch execution. A visual DAG exposes why work is ready, blocked, or downstream of another item while still allowing terminal-size fallbacks.
Since: v0.1.0
[RFC-0007:C-SEARCH] TUI search (Normative)
TUI v2 MUST provide a search view for governed artifacts.
The search view MUST interpret query text according to RFC-0002:C-SEARCH-COMMAND rather than exposing backend-specific raw query syntax.
The search view SHOULD support artifact type filtering and tag filtering when the terminal interaction model can expose those filters clearly.
Search results MUST show at least artifact kind, ID, title, and enough snippet or metadata context for a human to choose a result.
Selecting a search result MUST navigate to the corresponding TUI detail view when that artifact kind is supported by TUI v2.
Search result loading MUST follow the read-only boundary in RFC-0007:C-READ-ONLY.
Rationale: Search is the fastest way for humans to recover context in a large governed repository. Reusing the CLI search contract prevents TUI search from drifting into a separate discovery model.
Since: v0.1.0
[RFC-0007:C-DIAGNOSTICS] Diagnostics view (Normative)
TUI v2 MUST provide a diagnostics view that presents project check diagnostics to a human.
The diagnostics view MUST show diagnostic severity, code, message, and target context when those fields are available.
The diagnostics view SHOULD group or filter diagnostics by severity and artifact target.
When a diagnostic target corresponds to an artifact that TUI v2 can display, selecting the diagnostic SHOULD navigate to that artifact’s detail view or an equivalent contextual view.
The diagnostics view MUST NOT automatically apply migrations, edit artifacts, render documents, or run mutation commands to resolve diagnostics.
Rationale: govctl check is the central safety signal for governed work. TUI v2 should make those diagnostics easier for a human to triage without turning validation into an implicit repair workflow.
Since: v0.1.0
[RFC-0007:C-HUMAN-UX] Human-first terminal UX (Normative)
TUI v2 MUST optimize rendered screens for human comprehension rather than machine parsing.
TUI v2 MUST use consistent semantic styling for artifact kind, lifecycle status, phase, diagnostic severity, loop item status, selection, and muted secondary information.
TUI v2 MUST preserve keyboard-only navigation across all primary views.
TUI v2 MUST expose view-specific key bindings through persistent footer text, help overlay, or an equivalent discoverable mechanism.
TUI v2 MUST avoid layouts where essential text overlaps, truncates without context, or becomes unreadable on common narrow terminal widths.
When a terminal is too small for the preferred layout, TUI v2 MUST fall back to a simpler readable layout rather than preserving a broken multi-pane layout.
Rationale: A human-facing terminal UI succeeds when state, hierarchy, and next steps are quickly legible. Visual polish should come from semantic consistency and resilient layout, not from decorative complexity.
Since: v0.1.0
[RFC-0007:C-CONFORMANCE-VIEWS] Conformance Case views (Normative)
TUI v2 MUST expose Conformance Cases as a first-class read-only artifact view when the project schema supports Conformance Cases.
The overview MUST show the number of Conformance Cases.
The Conformance Case list MUST show each Case ID, title, aggregate requirement applicability, scenario path and selector, and associated Verification Guards.
The Conformance Case detail view MUST show the Case ID, title, tags, scenario path and selector, all versioned requirement bindings with their derived applicability, the aggregate requirement applicability, and all associated Verification Guards.
Requirement applicability MUST be derived according to RFC-0008:C-TRACE-QUERY. TUI v2 MUST NOT label a Case, requirement, or Guard as covered, passed, conformant, or evidenced.
Selecting a Conformance Case search result MUST navigate to its detail view. When a diagnostic target identifies a Conformance Case, selecting that diagnostic SHOULD navigate to its detail view.
Tag usage summaries MUST include Conformance Case tags.
All Conformance Case views MUST follow RFC-0007:C-READ-ONLY and the resilient layout requirements in RFC-0007:C-HUMAN-UX.
Rationale: First-class Case browsing keeps requirement-to-scenario-to-Guard relationships visible in the same cockpit as other governed artifacts while preserving the declared-not-evidenced boundary.
Tags:
tui
Since: v0.4.0
Changelog
v0.4.0 (2026-07-27)
Expose Conformance Cases in the TUI cockpit
Added
- Add read-only Conformance Case overview, list, detail, and navigation
v0.3.0 (2026-07-27)
Align TUI detail views with current governance state
Changed
- Use current projections for artifact detail views
v0.2.0 (2026-06-07)
Specify TUI responsibility boundaries
Added
- Require terminal I/O, input dispatch, data loading, and rendering to remain separate testable responsibilities
v0.1.0 (2026-06-06)
Initial draft
RFC-0008: Conformance Case and Declared Traceability Model
Version: 0.1.1 | Status: normative | Phase: impl Owners: @govctl-org
References: RFC-0000:C-CLAUSE-DEF, RFC-0000:C-GUARD-DEF, RFC-0000:C-REFERENCE-HIERARCHY, RFC-0001:C-RFC-STATUS, RFC-0001:C-CLAUSE-STATUS, RFC-0002:C-RESOURCE-MODEL, RFC-0002:C-RESOURCES, RFC-0002:C-CRUD-VERBS, RFC-0002:C-EDIT-FIELD-CONTRACT, RFC-0002:C-SHOW-PROJECTION, RFC-0002:C-GLOBAL-COMMANDS, RFC-0002:C-COMPATIBILITY-BOUNDARY, RFC-0002:C-OUTPUT-FORMAT, RFC-0002:C-SEARCH-COMMAND
1. Summary
[RFC-0008:C-SCOPE] Scope and Authority (Informative)
Projects can identify RFC Clauses and execute reusable Verification Guards, but they cannot give individual acceptance scenarios stable governance identities or query the declared relationships between scenarios, requirements, and Guards. At scale, scenario prose is copied into RFCs or Work Items, positional test references become unstable, and agents must search opaque project files to reconstruct context.
This RFC defines a first-class Conformance Case as a version-aware, non-normative declaration between RFC Clauses and Verification Guards. An RFC Clause remains the sole semantic authority. A Case identifies project-owned scenario content and declared Guard associations; it does not prove execution, passage, coverage, or conformance.
This RFC covers current Case identity and storage, stable scenario locators, version-bound requirement relationships, derived applicability state, structural validation, and trace queries. It does not define sub-Clause requirement anchors, a test runner, domain-specific fixture or oracle formats, Work Item completion requirements, persistent run results, Case revisions or lifecycle states, Suite resources, or a general custom-artifact framework.
The Conformance Case resource integrates with the authority, resource, CRUD, edit, show, global-command, search, compatibility, and output contracts defined by RFC-0000:C-REFERENCE-HIERARCHY, RFC-0002:C-RESOURCES, RFC-0002:C-CRUD-VERBS, RFC-0002:C-EDIT-FIELD-CONTRACT, RFC-0002:C-SHOW-PROJECTION, RFC-0002:C-GLOBAL-COMMANDS, RFC-0002:C-SEARCH-COMMAND, RFC-0002:C-COMPATIBILITY-BOUNDARY, and RFC-0002:C-OUTPUT-FORMAT.
Tags:
core
Since: v0.1.0
2. Specification
[RFC-0008:C-CONFORMANCE-CASE] Conformance Case Definition (Normative)
A Conformance Case is a current, non-normative declaration that gives one project-owned acceptance scenario a stable identity and relates it to RFC version markers and reusable Verification Guards.
Every Conformance Case MUST be stored at gov/conformance/<CONF-ID>.toml with:
- a
[govctl]section containingidandtitle; - an optional
[govctl]fieldtags; and - a
[case]section containingpath,selector,requirements, and optionalguards.
Each requirements entry MUST be an object containing exactly ref and version. ref MUST be a fully qualified RFC Clause ID. version MUST be a semantic version belonging to the owning RFC. The version is a declared applicability and rebaseline marker; it MUST NOT be interpreted as a retrievable historical Clause snapshot, content signature, or execution result. Omitted guards and tags fields MUST be interpreted as empty arrays.
A Conformance Case ID MUST match CONF-[A-Z][A-Z0-9-]*. The ID MUST be unique within the repository. The filename stem MUST equal the ID. The title MUST be non-empty.
path MUST be a repository-relative path that resolves within the project root, outside the configured gov root, to an existing regular file. selector MUST be a non-empty, project-defined locator token associated with that file. The reserved selector * MUST declare that the Case applies to the complete file. govctl MUST treat all other selector syntax and resolution semantics as opaque. The (path, selector) pair MUST be unique among Conformance Cases. Pair equality MUST compare the canonical resolved filesystem target for path and the exact stored selector string, so lexically different paths or symlinks to the same file do not create duplicate locators.
A Case MAY bind one scenario to multiple requirement Clauses and multiple Guards. These bindings are declarations only. A Case MUST NOT establish, alter, or broaden an RFC obligation, and humans and agents MUST resolve every semantic disagreement in favor of the RFC.
A Conformance Case has no persisted lifecycle status. Its requirement bindings derive current, candidate, provisional, or stale applicability under RFC-0008:C-TRACE-QUERY. Editing or deleting a Case changes only the current declaration; repository version control remains the history mechanism. Case mutation MUST NOT modify RFC versions, changelogs, Clause metadata, or sealed content signatures.
Conformance Case storage MUST use project schema version 4. Conformance commands on a version 3 project MUST fail without mutation and instruct the user to run govctl migrate. Normal project loading of version 3 data that contains gov/conformance/*.toml MUST fail with the same instruction rather than ignore those files.
Migration from version 3 to version 4 MUST install all current bundled schemas and MUST NOT create Cases or requirement bindings. A successfully migrated project MUST load and validate Conformance Case files, enforce prohibited Conformance Case references, expose the conformance resource commands, and include Cases in search --type conformance. As a recovery exception to normal version 3 loading, govctl migrate MUST validate prospective Case files with the version 4 schema and MUST validate the complete prospective Case graph under RFC-0008:C-VALIDATION before mutation. Valid files MUST be preserved by the atomic migration; any schema or graph error MUST produce diagnostics and leave the project unchanged.
Rationale: Stable locator tokens and RFC version markers make declared relationships addressable without importing project test semantics into govctl. Current-only mutation keeps the resource small, while derived stale applicability exposes RFC evolution without creating another artifact lifecycle.
Tags:
schema
Since: v0.1.0
[RFC-0008:C-TRACEABILITY] Case-Owned Declared Traceability (Normative)
Conformance traceability MUST use Case-owned edges:
- A Conformance Case owns its versioned
requirementsedges to RFC Clauses. - A Conformance Case MAY own
guardsedges to Verification Guards. - Verification Guards and Work Items MUST NOT persist reverse Conformance Case lists. A Verification Guard
refsentry MUST NOT identify a Conformance Case.
Each Guard ID in a Case MUST identify an existing Verification Guard. A Case-to-Guard edge declares that the project associates that Guard with execution of the Case locator. It MUST NOT be treated as evidence that the Guard selects the locator, has run, has passed, or establishes conformance.
Implementations MUST derive Clause-to-Case, Guard-to-Case, and Clause-to-Guard views from Case-owned edges. A Guard associated with a multi-requirement Case is related to that Case and its listed requirement bindings; this relationship MUST NOT be summarized as proof that every obligation in a Clause is covered.
Deleting a Verification Guard MUST be rejected while any Conformance Case identifies that Guard. The diagnostic MUST identify every Case referrer.
Conformance Case target restrictions for RFCs, ADRs, and Work Items are defined by RFC-0000:C-REFERENCE-HIERARCHY. Work Item completion policy MUST continue to select Verification Guards through the existing required-Guard surface rather than through Cases.
Rationale: Keeping both edge types in the Case makes one scenario locally understandable and avoids Guard files containing hundreds of reverse IDs. Prohibiting durable Work Item references preserves current-only Case mutation without rewriting historical task meaning.
Tags:
validation
Since: v0.1.0
[RFC-0008:C-VALIDATION] Conformance Validation (Normative)
Project validation MUST validate every Conformance Case and the complete declared trace graph.
Validation MUST report an error when:
- a Case file fails its machine-readable schema;
- a Case ID is duplicated or differs from its filename;
- a title, path, or selector is empty;
- a path is absolute, escapes the project root, resolves under the configured gov root, is missing, or does not resolve to a regular file;
- two Cases use the same
(path, selector)pair under the equality rule in RFC-0008:C-CONFORMANCE-CASE; - a Case has no requirement binding;
- a requirement
refis missing, is not a Clause, or identifies an informative Clause; - a requirement
versionis not present in the owning RFC changelog, predates the Clausesinceversion, or differs from the current version of a draft RFC; - a requirement targets a pending Clause whose owning RFC is not draft;
- a Case repeats the same requirement
ref; - a Guard ID is missing or repeated within a Case;
- a Case repeats a tag, or uses an unregistered or malformed tag; or
- a Verification Guard
refsentry identifies a Conformance Case.
A pending Clause in a draft RFC has no since version. For such a Clause, validation MUST accept only a binding to the draft RFC current version. A pending Clause in a normative or deprecated RFC MUST NOT be a valid Case target because no RFC version owns it yet.
A permanent Clause deletion MUST reject a Clause referenced by a Conformance Case and MUST identify the Case as a referrer. RFC or Clause status transitions and RFC version changes MUST NOT be rejected solely because they make a valid Case binding stale.
A structurally valid stale, candidate, or provisional binding MUST NOT produce a project-validation diagnostic. An empty Case guards array MUST NOT produce a diagnostic. govctl validates identities, versions, paths, and typed edges; it MUST NOT claim to validate the opaque scenario semantics, selector resolution, or actual Guard execution.
Rationale: Structural validation keeps declared traceability navigable and prevents silent data loss. Derived applicability avoids either blocking RFC evolution or forcing users to retarget stable Case IDs merely to keep the repository valid.
Tags:
validation
Since: v0.1.0
[RFC-0008:C-COMMAND-SURFACE] Conformance Resource Commands (Normative)
Implementations MUST expose Conformance Cases through the top-level conformance resource namespace and the resource-first structure defined by RFC-0002:C-RESOURCE-MODEL.
Creation MUST use:
govctl conformance new "<title>" --path <path> --selector <selector> --requirement <CLAUSE-ID>@<VERSION> [--requirement <CLAUSE-ID>@<VERSION> ...] [--guard <GUARD-ID> ...] [--id <CONF-ID>]
--path and --selector MUST each occur exactly once. --requirement MUST be repeatable and occur at least once. --guard MAY be repeated. When --id is absent, govctl MUST generate a valid unused ID from the title. When --id is present, govctl MUST validate and use that ID.
The resource MUST support list, get, show, edit, and delete with the applicable shared behavior defined by RFC-0002:C-CRUD-VERBS and RFC-0002:C-SHOW-PROJECTION. get <id> [field] MUST expose id, title, tags, path, selector, requirements, and guards. Plain retrieval of requirements MUST emit one <CLAUSE-ID>@<VERSION> value per line; plain retrieval of guards and tags MUST emit one stored value per line. Because Cases have no lifecycle state, current and archive show projections MUST be content-equivalent.
conformance edit MUST accept only these logical paths and operations:
| Path | Permitted operation |
|---|---|
title, path, selector | --set |
requirements, guards, tags | --add, --remove |
requirements[i] | --remove |
requirements[i].version | --set |
Adding or exact-value removing a requirement MUST accept the same <CLAUSE-ID>@<VERSION> value used by new. Changing a requirement ref MUST use an add followed by removal of the old binding; it MUST NOT expose a scalar requirements[i].ref mutation that can create an invalid intermediate ref-version pair. Indexed removal MUST use requirements[i] --remove.
Wire-layout prefixes such as govctl. and case. MUST be rejected. Every Case creation and edit MUST validate the mutated Case’s own fields, locator uniqueness, and direct Clause, Guard, tag, and scenario-path dependencies before writing. Case deletion MUST validate its governed referrers. Repository-wide consistency remains owned by govctl check; a Case mutation MUST NOT be rejected solely because an unrelated artifact or derived projection is invalid or stale. An edit that would remove the final requirement binding MUST be rejected. Every failed creation, edit, or deletion MUST leave governed files unchanged.
Conformance Case tags MUST use the controlled vocabulary and syntax defined by RFC-0002:C-RESOURCES. conformance list MUST support the shared --tag filter. Cases MUST be included in govctl tag list usage counts, and govctl tag delete MUST reject a tag still used by a Case.
Global search MUST index Conformance Case IDs, titles, tags, paths, selectors, requirement refs and versions, and Guard IDs. govctl search --type conformance MUST select this resource type. A Case search result path MUST identify the gov/conformance/<CONF-ID>.toml artifact source rather than the scenario path; JSON Case results MUST expose the scenario path separately as scenario_path.
Rationale: Canonical CRUD keeps authoring consistent with existing resources, while a dedicated trace query supplies reverse navigation without creating a general graph language or a second execution policy.
Tags:
cli
Since: v0.1.0
[RFC-0008:C-TRACE-QUERY] Declared Trace Query (Normative)
Implementations MUST support the resource-first query:
govctl conformance trace [TARGET] [--output <format>]
TARGET MAY be absent or identify one RFC, Clause, Conformance Case, or Verification Guard. An absent target MUST select all Cases. An RFC target MUST select Cases with at least one binding owned by that RFC. A Clause target MUST select Cases with a matching requirement ref. A Case target MUST select that Case. A Guard target MUST select Cases containing that Guard ID. Every selected Case record MUST retain all of its requirement and Guard bindings. An unknown or unsupported target MUST produce a diagnostic and a non-zero exit status.
Each requirement binding MUST derive one requirement-applicability value:
provisionalwhen its owning RFC is draft, the Clause is active, and the binding version equals the RFC current version;candidatewhen its owning RFC is normative inspec, the Clause is active, the Clause has asinceversion, and the binding version equals the RFC current version;currentwhen its owning RFC is normative inimpl,test, orstable, the Clause is active, the Clause has asinceversion, and the binding version equals the RFC current version; orstaleotherwise.
A Case requirement_applicability value MUST be stale when any binding is stale. Otherwise it MUST be provisional when any binding is provisional. Otherwise it MUST be candidate when any binding is candidate. Otherwise it MUST be current. This value describes only the relationship to RFC versions and Clause lifecycle state. It MUST NOT imply that the path content, selector, Guard command, or execution result is current or valid.
The logical result MUST be one collection of Case records. Each record MUST contain id, title, tags, path, selector, requirements, guards, and derived requirement_applicability. Each requirement record MUST contain ref, version, and its derived requirement_applicability. The command MUST NOT label any Case, Clause, or Guard as covered, passed, conformant, or evidenced.
JSON output MUST encode the logical result as an object with a cases array. Table output MUST expose the same Case records in human-readable form. Cases MUST be sorted by ID. Tags and Guards MUST be unique and lexicographically sorted. Requirement records MUST be unique by ref and sorted by ref and then version.
The command MUST support table and json output as a scoped exception to RFC-0002:C-OUTPUT-FORMAT. In a TTY the default MUST be table; outside a TTY the default MUST be json.
The command MUST validate the complete Conformance Case graph before emitting data. Structural errors MUST produce a non-zero exit status and no partial result. Stale, candidate, or provisional bindings and Cases without Guards MUST remain successful trace results.
Rationale: A single Case-oriented result is sufficient to derive every reverse relationship without materializing conflicting graph projections. Explicit applicability and vocabulary keep a declared mapping from being mistaken for execution evidence.
Since: v0.1.0
Changelog
v0.1.1 (2026-07-27)
Keep Case mutations local and recoverable
Fixed
- Limit Case mutation validation to the target and its direct dependencies
v0.1.0 (2026-07-27)
Define version-aware current Conformance Cases and declared traceability
Added
- Conformance Case resource definition
- Canonical Conformance Case command and edit surface
- Case-owned Clause and Guard traceability bindings
- Version-aware declared trace query and derived applicability states
RFC-0009: Source Scan Selection and Ignore Semantics
Version: 0.3.0 | Status: normative | Phase: stable Owners: @govctl-org
References: RFC-0002
1. Summary
[RFC-0009:C-SUMMARY] Source Scan Model (Informative)
Source reference scanning has two independent path-selection layers. The source-scan include list defines the positive scan domain. Repository .gitignore files and governance-specific .govignore files define traversal exclusions and explicit re-inclusions. Keeping these layers separate lets projects reuse established ignore policy, override it for governance evidence, and avoid enumerating excluded directory trees.
Since: v0.1.0
2. Specification
[RFC-0009:C-SOURCE-SELECTION] Source Selection (Normative)
When source_scan.enabled is false, source reference validation MUST NOT enumerate project source paths.
When source reference validation is enabled, a regular file is eligible for content scanning only when its normalized project-relative path matches at least one source_scan.include entry and its final ignore decision is not excluded. Normalized paths MUST use / as the separator, MUST omit a leading ./, and MUST be matched case-sensitively on every platform.
Each include entry represents one positive Git gitignore path pattern evaluated from the project root. A leading / anchors the pattern to the project root. A pattern with no / MUST match at any depth. A trailing / MUST select regular-file descendants of a matching directory. An empty entry or an unescaped leading ! MUST be rejected. Because include entries are configuration values rather than ignore-file lines, a leading # MUST be treated as a pattern character rather than a comment marker. Git escaping and wildcard forms, including *, ?, character classes, and **, MUST retain their gitignore meanings.
An empty include list MUST select no files. An ignore re-inclusion MUST NOT admit a file that is outside the positive include domain.
Since: v0.1.0
[RFC-0009:C-IGNORE-RULES] Ignore Sources and Precedence (Normative)
Source traversal MUST evaluate .gitignore and .govignore files located at the project root and in reached descendant directories. Both file types MUST use Git gitignore pattern syntax, including comments, escaping, directory-only patterns, ordered matches, and ! re-inclusion. Matching MUST use normalized project-relative paths and MUST NOT depend on whether a path is tracked by Git or whether the project root is a Git repository.
When matching rules conflict, a matching .govignore rule MUST take precedence over a matching .gitignore rule. Within one file type, a rule in a deeper directory MUST take precedence over a rule inherited from an ancestor directory. Within one ignore file, the last matching rule MUST win.
When the winning rule is a re-inclusion, the path MUST become non-excluded unless an ancestor remains excluded. Otherwise, a winning exclusion MUST keep the path excluded. After ignore resolution, source_scan.include MUST be applied only to decide whether a non-excluded regular file is eligible for content scanning; it MUST NOT prevent traversal through a non-excluded directory.
Source traversal MUST NOT consult ignore rules outside the project root, user-level or global Git ignore configuration, .git/info/exclude, or generic .ignore files. A path MUST NOT be excluded solely because its name is hidden.
Since: v0.1.0
[RFC-0009:C-TRAVERSAL] Traversal and Pruning (Normative)
The final ignore decision for a reached directory MUST be evaluated before enumerating its child entries. When the final decision excludes a directory, source traversal MUST prune the directory without enumerating its descendants.
A re-inclusion that targets a descendant of an excluded directory MUST have no effect unless every excluded ancestor is also re-included by rules available from reached directories. Ignore files beneath a pruned directory MUST NOT be read and MUST NOT re-include that directory or its descendants.
Source traversal MUST NOT follow symbolic links.
While source scanning is enabled, an invalid include rule, an unreadable or invalid ignore file discovered in a reached directory, an error while traversing a directory that was not pruned, or a read or decoding error for a selected regular file MUST produce a validation diagnostic. Source reference validation MUST NOT report success after such an error.
A directory named .git MUST be treated as repository metadata and pruned before its child entries are enumerated, regardless of source_scan.include or ignore-file rules.
Since: v0.1.0
[RFC-0009:C-IGNORE-MIGRATION] Ignore Configuration Migration (Normative)
Project schema version 5 MUST establish the source-selection and ignore contract in this RFC. Normal project commands other than govctl migrate that load a version 4 project MUST reject the project without mutation and instruct the user to run govctl migrate. Project-independent commands MUST NOT require repository migration. Migration from version 4 to version 5 MUST follow the transactional and dry-run behavior in RFC-0002:C-GLOBAL-COMMANDS.
The version 5 configuration MUST remove source_scan.exclude. When that legacy list is non-empty, migration MUST place each entry as one root .govignore rule, preserving array order and placing the migrated rules before any pre-existing .govignore content. A leading ! or # that was a literal character in a legacy entry MUST be escaped when written as an ignore-file rule. A legacy entry containing a carriage return or line feed MUST cause migration to fail without mutation and identify that entry.
Pre-existing .govignore content MUST remain byte-for-byte unchanged after the inserted migration block. The version 5 source-scan migration step MUST NOT modify .gitignore; independent project-support synchronization required by RFC-0002:C-GLOBAL-COMMANDS MAY modify .gitignore in the same govctl migrate invocation.
Migrated entries adopt Git gitignore matching semantics in version 5. Migration MUST NOT claim that their match sets remain identical to the legacy glob matcher. govctl migrate --dry-run MUST show the resulting configuration and .govignore changes before they are applied.
When the legacy list is empty, migration MUST remove the field without creating .govignore. A version 5 project without a .govignore file MUST be valid and MUST behave as though it has no governance-specific ignore rules. A version 5 configuration that contains source_scan.exclude MUST be rejected without mutation, and the diagnostic MUST identify the unsupported field.
Since: v0.1.0
[RFC-0009:C-REFERENCE-REPORTING] Source Reference Reporting (Normative)
A configured source_scan.pattern MUST compile successfully and MUST define capture group 1 as the artifact-reference target. govctl check MUST report E0501 when either condition is not met, whether or not source-file traversal is enabled. Every full match MUST produce a present, non-empty capture group 1; otherwise source scanning MUST report E0501 and MUST NOT treat that match as a reference.
A diagnostic about an unknown or outdated detected source reference MUST identify the normalized project-relative source path and the one-based line and byte-column position at which capture group 1 starts.
Source-reference diagnostics MUST be ordered by ascending normalized path, line, and byte column, with diagnostic code and captured target as ascending tie-breakers. Diagnostics with the same code, normalized path, capture-start position, and captured target MUST be emitted once.
Since: v0.2.0
Changelog
v0.3.0 (2026-07-30)
Exclude Git metadata from source traversal
Changed
- Prune .git directories before enumerating their contents
v0.2.0 (2026-07-30)
Make source-reference diagnostics precise and deterministic
Added
- Define reference-pattern validation and source locations
Changed
- Order and deduplicate source-reference diagnostics
v0.1.1 (2026-07-30)
Close source traversal failure gaps
Fixed
- Treat selected source read and decoding failures as validation errors
v0.1.0 (2026-07-29)
Initial draft
RFC-0010: Multi-workspace coordination for parallel agents
Version: 0.2.0 | Status: normative | Phase: impl Owners: @govctl-org Tags:
collaboration
References: RFC-0004, RFC-0002
1. Summary
[RFC-0010:C-SUMMARY] Summary (Informative)
This RFC specifies how govctl coordinates governance work when one repository clone hosts multiple concurrent working trees — git worktrees or jj workspaces — driven by parallel agents.
Scope: Applies to every govctl command invocation in any working tree of a clone that hosts more than one working tree. It covers command scope classification, a shared coordination registry, cross-workspace ID reservation, exclusive claims for version-semantics operations, and cross-workspace presence visibility.
Backward compatibility: Single-checkout repositories are unaffected: with exactly one working tree, coordination reduces to the behavior defined by RFC-0004. Without version control, multiple workspaces cannot exist, so commands silently behave as they always have. One deliberate exception: because allocation consults shared version-control history, identifiers of deleted artifacts are not reused, which protects historical references from dangling onto unrelated successors.
Specification outline: Commands are classified as workspace, branch-content, or trunk scoped, and trunk-scoped commands are refused outside the primary workspace. A per-clone coordination registry holds ID reservations, artifact claims, and presence records. ID reservation makes cross-branch ID collisions impossible by construction; claims make concurrent version-semantics changes to the same RFC visible and serialized; presence lets agents in one workspace see active work in others.
Rationale: Governance artifacts remain versioned with the branch so that changes travel through pull request review, while coordination state — which is live, operational, and not reviewable — is shared per clone. Without this split, parallel agents in separate worktrees collide on sequential IDs, cannot see each other’s active work, and can silently bump or finalize the same RFC.
Since: v0.1.0
2. Specification
[RFC-0010:C-DEFINITIONS] Definitions (Informative)
Working tree / workspace: A distinct checkout of a repository clone that shares version-control metadata with the clone’s other working trees — a linked git worktree or a jj workspace. A workspace is identified by the absolute path of its working-tree root. Moving or renaming a workspace therefore invalidates its registry records, which expire under the liveness rules below and are recreated by new activity from the moved workspace.
Primary workspace: The working tree designated as the canonical location for trunk-scoped commands. For git, the main working tree (the one containing the repository’s shared metadata directory). For VCS tools whose workspaces are peers, the workspace named by project configuration.
Shared repository storage: Storage provided by the version-control system that is common to every working tree of a clone, such as the git common directory or the jj repository store. It is distinct from any working tree’s checked-out files. Shared version-control history is the commit history recorded in that shared storage and visible to every workspace of the clone.
Coordination registry: Local, per-clone state in shared repository storage that records ID reservations, artifact claims, and presence records. The registry is coordination state, not a governed artifact, and is never committed to version control.
ID reservation: An atomic registry record that binds a not-yet-merged artifact ID to the workspace that generated it. Reservation liveness is defined by RFC-0010:C-ID-RESERVATION through the existence of the artifact file at the owning workspace’s recorded path, not by an activity timestamp.
Artifact claim: An exclusive registry record binding an existing RFC to the workspace performing version-semantics operations on it.
Presence record: A registry record indicating that a workspace is actively working on a specific work item.
Live record: A claim or presence record whose owning workspace path still exists and whose recorded activity has not exceeded the configured inactivity period.
Since: v0.1.0
[RFC-0010:C-COMMAND-SCOPE] Command scope classification (Normative)
Every govctl command that reads or writes governed artifacts or coordination state has exactly one scope: workspace, branch-content, or trunk. This classification applies to every command in the CLI surface defined by RFC-0002, and any command added to that surface MUST be assigned exactly one scope at the time it is added.
Workspace scope. Read-only and local-execution commands such as status, check, list, show, search, verify, describe, claim list, and loop execution. Workspace-scoped commands MUST run in any workspace and MUST NOT mutate governed artifacts. Coordination-state-mutating commands that never touch governed artifacts, such as claim release and claim steal, are branch-content scoped for enforcement purposes but MUST NOT acquire the gov-root write lock.
Branch-content scope. Commands that create or mutate governed artifacts in the invoking workspace’s working tree, including artifact creation, content editing, lifecycle transitions, and rendering. Branch-content commands MUST run in any workspace, subject to the reservation and claim rules of RFC-0010:C-ID-RESERVATION and RFC-0010:C-ARTIFACT-CLAIM.
Trunk scope. Exactly the commands that cut or undo a release or migrate the repository’s governance format are trunk-scoped. A trunk-scoped command invoked outside the primary workspace MUST refuse to execute, MUST leave governed and coordination state unchanged, and MUST report a diagnostic that identifies the primary workspace.
The primary workspace MUST be determined from version-control metadata when the VCS defines a main working tree. Where the VCS treats workspaces as peers, the primary is the workspace named by project configuration, or — absent configuration, for jj — the workspace named default, which jj assigns to the initial workspace of every repository. When version control is present but no primary workspace can be determined, trunk-scoped commands MUST proceed as if the current workspace were primary and MUST emit a warning that trunk-scope enforcement is inactive. Without version control, multiple workspaces cannot exist, so trunk-scope enforcement is inapplicable and commands proceed silently, consistent with RFC-0010:C-REGISTRY degradation.
Rationale: Release cutting, release undo, and format migration rewrite the canonical line of project history and must have a single point of execution, while content work benefits from running wherever the agent’s branch lives. Refusing trunk operations in secondary workspaces replaces an entire class of merge conflicts with an explicit, actionable error. The warning is reserved for the case where enforcement is expected but impossible; a project without version control has no second workspace to protect against. Treating jj’s initial default workspace as the fallback primary mirrors the convention every jj repository already has, so most projects need no configuration at all.
Tags:
collaboration
Since: v0.1.0
[RFC-0010:C-REGISTRY] Shared coordination registry (Normative)
The coordination registry MUST be stored in shared repository storage so that every workspace of a clone observes and updates the same records. The registry MUST be namespaced per governed project root, so a clone hosting multiple governed projects keeps independent registries.
The registry MUST NOT be stored inside any workspace’s working tree, under the gov root, or under rendered documentation directories. Registry records are local coordination state: they are not governed artifacts, MUST NOT be committed to version control, and MUST NOT be treated as an authoritative source over TOML governance artifacts. The registry MAY inform only coordination-facing output — the presence overlay in govctl status and reservation or claim diagnostics — and MUST NOT alter the parsed content, status fields, or lifecycle state of governed artifacts as loaded from their TOML sources.
Concurrent registry updates from parallel processes across workspaces MUST be atomic: two concurrent invocations MUST NOT produce lost, duplicated, or interleaved registry records. This coordination mechanism is distinct from, and does not replace, the concurrency mechanism required by RFC-0004 for mutations of the gov tree. Registry access MUST NOT block read-only commands.
Because multiple working trees are themselves a version-control facility, a directory without version control cannot host more than one workspace. Commands in such a directory MUST silently use single-checkout behavior; coordination is not merely inactive but inapplicable, and no warning is emitted. Degraded detection MUST resolve toward caution: when version-control metadata is present but unreadable, or its presence cannot be reliably determined, commands MUST behave as if version control were present and shared storage were unavailable — that is, degrade with a warning — rather than taking the silent no-VCS path. Under the same caution rule, a registry write failure or detected registry corruption with version control present MUST degrade to single-checkout behavior and MUST emit a warning, since the clone may host other workspaces whose coordination state is now stale. Registry loss or corruption MUST NOT make governed artifacts unusable; the consequence is limited to losing the uniqueness and visibility guarantees of this RFC until the registry is repopulated by new activity.
Rationale: Placing coordination state in VCS-shared storage gives every workspace of a clone a single rendezvous point without a daemon or network service, while keeping the working tree — and therefore pull requests — free of operational state. Because the storage is VCS metadata rather than a checked-out file, the registry requires no ignore rules. Warning on registry failure when version control is present surfaces a real coordination gap, while staying silent without version control avoids punishing single-checkout projects for a facility they cannot use.
Tags:
collaboration
Since: v0.1.0
[RFC-0010:C-ID-RESERVATION] Cross-workspace ID reservation (Normative)
A branch-content command that creates a governed artifact with a generated identifier MUST atomically reserve that identifier in the coordination registry as part of creation, and the reservation MUST record the owning workspace.
Two artifact creations in different workspaces of the same clone MUST NOT be assigned the same identifier, regardless of when their respective branches merge. This extends the concurrent-invocation uniqueness required by RFC-0004:C-CONCURRENT-WRITE from same-checkout processes to across-workspace sequences. Across clones — where no shared registry exists — identifier strategies that derive collision-safe identifiers from author identity or randomness remain the available mitigation.
Identifier allocation MUST take as its input the union of three witnesses: the identifiers present in the invoking workspace’s gov tree, the identifiers bound by live reservations in the registry, and the identifiers recorded in the clone’s shared version-control history. An identifier is recorded in shared history when a governed-artifact source path bearing that identifier exists in any commit reachable from the clone’s shared storage. Allocation MUST choose the next identifier monotonically within the numbering scheme of the artifact type, so identifiers stay sortable and predictable for humans. Because shared history is visible to every workspace of the clone, a merged artifact witnesses its identifier even to workspaces on stale branches.
A reservation for a newly created artifact MUST be honored as live while the artifact file exists at the owning workspace’s recorded path. The reservation MAY be discarded only once the artifact is recorded in the clone’s shared version-control history, from which point the history entry is the uniqueness witness for every workspace.
Rationale: Sequential identifiers are a deliberate readability choice for RFCs and ADRs. Reservation preserves that choice under parallel branch work by moving the collision point from merge time — where renumbering breaks references — to creation time, where an atomic shared record costs nothing. Defining the allocation input as local tree plus reservations plus shared history keeps the uniqueness guarantee intact across the reservation’s entire lifecycle, including after its discard.
Tags:
collaboration
Since: v0.1.0
[RFC-0010:C-ARTIFACT-CLAIM] Artifact claims for version-semantics operations (Normative)
Operations that change an RFC’s version semantics — version bump, finalization, phase advancement, deprecation, and supersession — MUST acquire an exclusive artifact claim before mutating, on every RFC whose version-semantics fields the operation mutates. A supersession therefore requires claims on both the superseding and the superseded RFC. When another workspace holds a live claim on a required RFC, the command MUST fail without mutating anything, and its diagnostic MUST identify the claiming workspace.
Commands that edit an RFC’s content without changing version semantics — including clause authoring — MUST NOT be blocked by a claim. When a live claim held by another workspace exists, they MUST emit a non-blocking warning naming the claiming workspace, so overlapping intent is visible without forbidding parallel work on independent clauses.
A claim MUST record the owning workspace and a last-activity timestamp. Any govctl invocation that writes coordination state in the claiming workspace SHOULD refresh that workspace’s claim and presence timestamps; read-only invocations MUST NOT refresh, so that they never become writers. A claim whose owning workspace no longer exists, or whose last activity exceeds a configurable inactivity period, MUST be treated as expired and MUST NOT block operations.
Users MUST be able to explicitly release a claim and to take over a claim held by another workspace. Every takeover MUST be recorded in the registry as an audit event that names both workspaces involved, and audit events MUST be retained beyond the expiry of the claim they transferred, so that claim transfers remain auditable after the fact.
Rationale: Version-semantics operations on one RFC cannot merge meaningfully when performed on two branches at once — both would edit the same version and changelog fields — so they are serialized by an exclusive claim. Content edits to independent clause files merge cleanly, so they receive visibility rather than exclusion. Refresh is scoped to coordination-writing invocations so that read-only commands never take the registry lock, per RFC-0010:C-REGISTRY.
Tags:
collaboration
Since: v0.1.0
[RFC-0010:C-PRESENCE] Cross-workspace presence (Normative)
Activating a work item — or creating one directly in active status — in any workspace MUST register a presence record in the coordination registry naming the work item and the owning workspace.
govctl status MUST surface work items with live presence records owned by other workspaces of the clone, identifying both the work item and the owning workspace, so an agent can tell which items are being worked on elsewhere before starting new work.
Presence records follow the liveness rules of RFC-0010:C-ARTIFACT-CLAIM: they record a last-activity timestamp, are refreshed by invocations in the owning workspace, and expire after the same configurable inactivity period.
Presence is advisory visibility, not exclusion: it MUST NOT block activating or editing the same work item in another workspace. Where hard coordination for work items is wanted, projects use work item dependency and assignment workflows rather than presence.
Rationale: The common multi-agent failure is two agents unknowingly doing the same work. A live, shared view of active work removes the invisibility without turning advisory information into a locking protocol.
Tags:
collaboration
Since: v0.1.0
Changelog
v0.2.0 (2026-09-08)
Clarify trunk scope and workspace detection
Added
- Name release undo in the trunk-scoped command set
- Classify claim list as workspace-scoped and claim release/steal as lock-free branch-content commands
- Treat jj’s default workspace as the fallback primary when no primary is configured
Changed
- Scope claim and presence timestamp refresh to coordination-writing invocations so read-only commands never write
v0.1.0 (2026-09-08)
Initial normative version
ADR-0001: Use TOML for ADRs and Work Items
Status: superseded | Date: 2026-01-17 Superseded by: ADR-0034
Tags:
schema
References: RFC-0000:C-ADR-DEF, RFC-0000:C-WORK-DEF
Context
ADRs and Work Items need a human-readable, machine-parseable format. JSON is verbose and hard to edit manually. YAML has implicit typing issues. TOML provides explicit typing, clean multiline strings, and good tooling support.
Decision
Use TOML for ADRs and Work Items instead of JSON. Structure follows [govctl] metadata section and [content] body section. This aligns with Rust ecosystem conventions (Cargo.toml).
Consequences
Positive: Easier manual editing, cleaner diffs, natural multiline support. Negative: Different format from RFC clauses (which remain JSON for richer structure). Migration: Existing JSON-based work items would need conversion.
ADR-0002: Fix artifact lifecycle design flaws
Status: accepted | Date: 2026-01-17
Tags:
lifecycle
References: RFC-0000
Context
Analysis of the artifact lifecycle state machines revealed several design flaws:
-
Clause
kindvsstatusduplication: Thekindenum includesdeprecatedalongsidenormativeandinformative, butstatusalso hasdeprecated. This creates confusion about where deprecation state belongs. -
ADR missing
rejectedstate: The ADR lifecycle isproposed → accepted → superseded. If a proposal is rejected rather than accepted, there is no state to record this outcome. The alternative is leaving it asproposedforever or deleting it, both of which lose information. -
Work Item forced activation before cancellation: The lifecycle
queue → active → done|cancelledimplies you must start work before abandoning it. This is illogical - planned work can be abandoned before starting. -
RFC status×phase constraint rules undocumented: The 3×4 matrix of valid/invalid status×phase combinations exists implicitly but is not formally documented in SCHEMA.md.
Decision
We will fix all four lifecycle design flaws:
-
Remove
deprecatedfrom Clausekind: Thekindfield should only contain semantic categories (normative,informative). Deprecation is a lifecycle state that belongs instatus. -
Add
rejectedto ADR lifecycle: The new lifecycle becomes:proposed → accepted → superseded → rejectedThis allows recording when a proposal was considered but declined.
-
Allow Work Item
queue → cancelled: The new lifecycle becomes:queue → active → done ↘ ↘ cancelledWork can be abandoned at any stage.
-
Document RFC constraint rules: Add explicit invariant rules to SCHEMA.md stating when status×phase combinations are forbidden.
Consequences
Positive:
- Cleaner separation of concerns (kind = category, status = lifecycle)
- Complete lifecycle coverage for all artifact types
- Explicit rules prevent confusion about valid state combinations
Negative:
- Existing tools validating
kind: deprecatedwill need updating - Schema version bump required for breaking changes
Migration:
- Any clause with
kind: deprecatedshould change tokind: normative, status: deprecated - Currently no such clauses exist in the codebase
ADR-0003: Deterministic hash signatures for rendered projections
Status: accepted | Date: 2026-01-17
Tags:
validation
References: RFC-0000
Context
govctl renders markdown files from authoritative JSON/TOML sources (RFCs, ADRs, Work Items). These rendered markdown files are projections — read-only views intended for human consumption.
Problem: Without a mechanism to detect tampering, someone could edit docs/rfc/RFC-0000.md directly. This edit would:
- Be overwritten on next
govctl render - Create confusion about which version is authoritative
- Violate the Single Source of Truth (SSOT) principle
We need a mechanism to:
- Mark rendered files as generated (not authoritative)
- Detect when a rendered file has been edited directly
- Ensure verification is deterministic (same source always produces same hash)
Decision
Implement deterministic hash signatures embedded in rendered markdown.
Signature Format:
<!-- GENERATED: do not edit. Source: RFC-0000 -->
<!-- SIGNATURE: sha256:<64-hex-chars> -->
Hash Computation:
- Collect all source JSON content (RFC metadata + clauses, or ADR/Work Item TOML)
- Canonicalize JSON/TOML: sort object keys recursively, normalize whitespace
- For RFCs: sort clauses by
clause_idbefore hashing - Compute SHA-256 of the canonical representation
- Include a signature version prefix for future-proofing
Determinism Requirements:
- Object keys sorted alphabetically at all nesting levels
- Arrays preserve order (only objects get key-sorted)
- Consistent string escaping and number formatting
- No dependency on file modification times or filesystem order
Verification:
govctl checkextracts signature from rendered markdown- Recomputes hash from current source files
- Reports mismatch as a diagnostic error
Consequences
Positive:
- Enforces “edit the source, not the projection” discipline
- Tampered markdown is detected automatically by
govctl check - Deterministic hashes enable reproducible builds
- Clear provenance: every rendered file traces back to its source
Negative:
- Existing rendered markdown will fail verification until re-rendered
- Minor source reformatting (whitespace) changes the hash
- Adds complexity to the render pipeline
Migration:
- Run
govctl renderto regenerate all markdown with signatures - Commit the updated files
ADR-0004: Adopt Keep a Changelog format for RFC changelogs
Status: accepted | Date: 2026-01-17
Tags:
release
References: RFC-0000
Context
RFC changelogs use a flat changes array. This makes it difficult to categorize changes by type (additions, fixes, removals). The Keep a Changelog format (keepachangelog.com) is a widely-adopted standard that organizes changes into semantic categories aligned with semver.
Decision
Replace the flat changes array with categorized arrays: added, changed, deprecated, removed, fixed, security. Keep summary field as optional notes. Migrate existing RFC-0000 changelog (trivial: one entry).
Consequences
Positive: Standard format, better scanability, semver-aligned categories. Negative: More verbose schema, breaking change to ChangelogEntry model. Migration cost is minimal (RFC-0000 has only one entry).
ADR-0005: CLI output color scheme and formatting
Status: accepted | Date: 2026-01-17
Tags:
cli
References: RFC-0000
Context
CLI output uses plain text with no visual hierarchy. Users cannot quickly distinguish success from failure, or identify important values. Status messages blend together making output hard to scan.
Decision
Adopt semantic color scheme: Green for success, Red for errors, Yellow for warnings, Cyan for paths/IDs, Bold for emphasis. Use owo-colors crate (zero-cost, no deps). Auto-detect terminal color support. All output via ui module for consistency.
Consequences
Positive: Better UX, faster scanning, clearer status. Negative: One new dependency (owo-colors). Migration: All eprintln! calls routed through ui module.
ADR-0006: Global dry-run support for content-modifying commands
Status: accepted | Date: 2026-01-17
Tags:
cli
References: RFC-0000:C-WORK-DEF, ADR-0019
Context
All content-modifying commands (new, set, add, remove, edit, tick, bump, finalize, advance, accept, deprecate, supersede, move) write files immediately with no way to preview changes. Only render commands support –dry-run. Users and agents need a way to preview what changes will be made before committing to disk, especially for destructive or complex operations.
Decision
Add global -n/–dry-run flag at CLI level. Create WriteOp enum with Preview/Execute variants in write.rs. All write functions accept WriteOp. In Preview mode: serialize, display via ui::dry_run_preview, skip fs::write. Read-only commands ignore the flag.
Consequences
Positive: Unified dry-run UX, follows Unix -n convention, DRY write logic. Negative: Signature changes for write functions. Migration: Update all write callsites to use WriteOp.
ADR-0007: Ergonomic array field matching for remove and tick commands
Status: superseded | Date: 2026-01-17 Superseded by: ADR-0037
Tags:
editing
References: RFC-0000:C-WORK-DEF, RFC-0000:C-ADR-DEF
Context
The remove command requires exact string match, which is fragile for long strings like URLs. The tick command uses substring matching but remove does not. Checklist fields (acceptance_criteria, decisions, alternatives) require separate semantics from string fields, leading to confusion about when to use remove vs tick.
Decision
Unify matching semantics: (1) Default to case-insensitive substring matching for remove and tick. (2) Add –exact flag for exact matching. (3) Add --at <index> for positional removal. (4) Add –regex flag for pattern matching. (5) Add –all flag for bulk removal. (6) Single match proceeds; multiple matches error with guidance. (7) remove works on all array types including checklists; tick only changes status.
Consequences
Positive: Ergonomic default matching, safe bulk operations, unified semantics. Negative: Breaking change for scripts relying on exact match. Migration: Existing exact-match callers should add –exact flag.
ADR-0008: Add refs field to RfcSpec for artifact cross-referencing
Status: accepted | Date: 2026-01-17
Tags:
schema
References: RFC-0000
Context
RFCs are the supreme governance documents in govctl, yet they cannot formally reference other artifacts (ADRs, other RFCs, work items). Meanwhile, ADRs and Work Items both have a refs field for cross-referencing.
This asymmetry creates problems:
- RFCs cannot declare dependencies on ADRs that informed their design
- No way to trace which ADRs led to an RFC’s creation
- Validation cannot check RFC references for consistency
- Impact analysis for deprecation is incomplete
The existing pattern in AdrMeta and WorkItemMeta is: refs: Vec<String> with validation against known artifact IDs.
Decision
Add refs field to RfcSpec following the same pattern as AdrMeta and WorkItemMeta:
- Add
refs: Vec<String>to RfcSpec model (serde skip_serializing_if empty) - Add diagnostic code E0105RfcRefNotFound for validation errors
- Extend validate_artifact_refs() to include RFC refs validation
- Support add/remove/get refs operations in edit commands for RFCs
- Validate RFC supersedes field against known RFCs (currently unvalidated)
This creates consistency across all artifact types and enables complete cross-reference tracking.
Consequences
Positive:
- RFCs can now reference ADRs, other RFCs, and work items
- Complete artifact graph for impact analysis
- Consistent API across all artifact types
- Existing RFCs remain valid (refs is optional, defaults to empty)
Negative:
- Minor schema change to RfcSpec
- Slightly more validation overhead on check
Neutral:
- Existing RFCs do not need migration (empty default)
ADR-0009: Configurable source code reference scanning
Status: superseded | Date: 2026-01-17 Superseded by: ADR-0059
Tags:
validation
References: RFC-0000
Context
Source code often contains references to governance artifacts (RFCs, clauses, ADRs) in comments. These references can become stale when artifacts are deprecated, superseded, or renamed.
Currently govctl validates internal artifact references (refs fields) but has no mechanism to detect broken references in source code comments. This creates a gap where documentation in code can drift from the actual governance state.
neotex-spec implements this via a hardcoded comment scanning pattern, but govctl needs a generalized solution with configurable patterns to work across different projects and conventions.
Decision
Add configurable source code scanning with:
-
New [source_scan] config section with:
- enabled: bool (default false)
roots: Vec<PathBuf>(directories to scan)exts: Vec<String>(file extensions to include)- pattern: String (regex with capture group for artifact ID)
-
Default pattern matches RFC-0001:C-NAME and ADR-0001 style references
-
Scanner walks configured directories, applies pattern, validates extracted IDs against ProjectIndex
-
New diagnostics: E0107SourceRefUnknown (error), W0107SourceRefOutdated (warning for deprecated/superseded)
-
Scanner runs during ‘govctl check’ when source_scan.enabled = true
Consequences
Positive:
- Dead link detection in source code comments
- Configurable pattern supports different project conventions
- Disabled by default - opt-in for projects that want it
- Catches outdated references to deprecated/superseded artifacts
Negative:
- Adds walkdir dependency
- Additional check time when scanning large codebases
Neutral:
- Pattern configuration requires regex knowledge
- Projects must explicitly enable and configure
ADR-0010: Validate work item descriptions for placeholder content
Status: accepted | Date: 2026-01-17
Tags:
validation
References: RFC-0000:C-WORK-DEF
Context
Work items are created with a placeholder description template: “Describe the work to be done. What is the goal? What are the acceptance criteria?” This placeholder is meant to be replaced with actual content, but 21 of 24 existing work items still have this placeholder text.
Empty or placeholder descriptions provide no value for audit trails, make it hard to understand what was actually done, and defeat the purpose of structured governance.
Decision
Add a warning diagnostic (W0106) for work items with placeholder or empty descriptions.
Detection patterns:
- Description matches the exact template text
- Description is empty or whitespace-only
- Description contains only generic phrases like “TODO”, “TBD”, “Fill in later”
This is a warning (not error) because:
- Existing work items should not block
govctl check - It’s advisory during development, not a hard gate
- Users can address warnings incrementally
Consequences
Positive:
- Encourages meaningful documentation of completed work
- Improves audit trail quality
- Catches forgotten placeholders before they become permanent
Negative:
- Existing 21 work items will trigger warnings until fixed
- Minor noise during
govctl checkuntil addressed
Migration: Fix existing work items by adding meaningful descriptions based on their titles and acceptance criteria.
ADR-0011: Inline reference expansion in rendered content
Status: accepted | Date: 2026-01-17
Tags:
editing
References: RFC-0000
Context
Content fields (description, context, decision, consequences) are rendered as-is with no link expansion. The refs field gets expanded to markdown links, but inline references like [RFC-0000](../rfc/RFC-0000.md) in text remain as literal strings.
This creates an inconsistency:
- The
source_scanfeature uses[[artifact-id]]pattern to detect references in source code - Users might expect the same pattern to work in content fields
- Without expansion, content authors must write full markdown links manually
The source_scan config already defines a customizable pattern field for reference format.
Decision
Add inline reference expansion to content fields during rendering:
- Use the same pattern from
source_scan.patternconfig (defaults to[[RFC-NNNN]]format) - Expand matched references using existing
ref_link()function - Apply to: description, context, decision, consequences, notes, acceptance_criteria text
- Pattern is evaluated at render time, so config changes apply on next render
This creates consistency between source code scanning and content rendering — the same reference format works everywhere.
Consequences
Positive:
- Inline references in content become clickable links
- Consistent with
source_scanpattern format - No new config needed (reuses
source_scan.pattern) - Works with custom patterns if configured
Negative:
- Couples rendering to source_scan config (even if source_scan.enabled is false)
- Literal
[[text]]in content will be matched if it looks like an artifact ID
Migration: Existing content with literal [[...]] that happens to match artifact patterns will now become links. This is likely the desired behavior.
ADR-0012: Prefix-based changelog category parsing
Status: accepted | Date: 2026-01-17
Tags:
release
References: ADR-0013
Context
The govctl bump command supports adding changelog entries via -c flags, but all changes are hardcoded to the added category. The ChangelogEntry model supports 6 categories (added, changed, deprecated, removed, fixed, security) per Keep a Changelog format, but users must manually edit JSON to use any category other than added.
Decision
Parse conventional-commit-style prefixes from change strings to route to the correct changelog category. Supported prefixes: add:, fix:, changed:, deprecated:, removed:, security:. Unknown prefixes produce a validation error. No prefix defaults to added for backward compatibility.
Example: govctl bump RFC-0001 --patch -m "Bug fixes" -c "fix: memory leak" -c "security: patched CVE"
Consequences
Users can populate all changelog categories via CLI without JSON editing. The prefix syntax follows conventional commits, reducing learning curve. Invalid prefixes are caught early with helpful error messages listing valid options.
ADR-0013: Add category field to acceptance criteria for changelog generation
Status: accepted | Date: 2026-01-17
Tags:
schema
References: ADR-0012
Context
Work items track implementation work (features, fixes, refactoring), but lack categorization that maps to Keep a Changelog format. RFC changelog entries already use Keep a Changelog categories (Added, Changed, Deprecated, Removed, Fixed, Security). To generate a repo-level CHANGELOG.md from completed work items, we need the same categorization. Acceptance criteria are the natural atomic unit for changelog entries - each criterion represents one deliverable.
Decision
Add a category field to ChecklistItem (acceptance criteria) using the existing ChangelogCategory enum (added, changed, deprecated, removed, fixed, security). Default to added for backward compatibility. Reuse ADR-0012 prefix parsing: govctl add WI-xxx acceptance_criteria "fix: memory leak" parses to category=fixed, text="memory leak". This consolidates ChangelogCategory from write.rs into model.rs for reuse across RFC changelogs and work item criteria.
Consequences
Acceptance criteria can be grouped by category when rendering CHANGELOG.md. Each criterion becomes one changelog entry. Work items can span multiple categories without being split. Existing work items remain valid (criteria default to added). Single ChangelogCategory enum used for both RFC changelog entries and work item criteria.
Alternatives Considered
Add category field to WorkItemMeta (work-item level) (rejected)
Add category field to ChecklistItem (criterion level) with prefix parsing (accepted)
ADR-0014: Release management with releases.toml
Status: accepted | Date: 2026-01-17
Tags:
release
References: ADR-0013, RFC-0000:C-WORK-DEF
Context
To generate a CHANGELOG.md from work items, we need version information. Work items have completed dates but no version. Version is a release-time concept, not a work-time concept. We need a way to track which work items belong to which release without mutating completed work items.
Decision
Store release history in a single gov/releases.toml file with explicit work item references:
[[releases]]
version = "0.2.0"
date = "2026-01-17"
refs = ["WI-YYYY-MM-DD-029", "WI-YYYY-MM-DD-008"]
The govctl release <version> command collects all done work items not yet in any release and adds them to a new release entry. The govctl render changelog command generates CHANGELOG.md grouped by release version and category.
Consequences
Completed work items remain immutable. Explicit refs list eliminates ambiguity about release membership. Single file is simpler than per-release artifacts. Unreleased work items appear under [Unreleased] section in changelog.
Alternatives Considered
Add version field to work items after release (rejected)
Store releases in single gov/releases.toml with explicit refs (accepted)
ADR-0015: Context-aware self-describing CLI for agent discoverability
Status: superseded | Date: 2026-01-18 Superseded by: ADR-0058
Tags:
cli
References: RFC-0000
Context
AI coding agents (Claude, Cursor, Codex, etc.) can invoke shell commands, making govctl immediately usable. However, agents lack semantic understanding of when to use which command and why.
User feedback: “I need to tell the agent in my prompt what this tool is and when to run it.”
Current solutions:
- MCP (Model Context Protocol) — adds structured tool definitions, but requires server setup, process management, and creates a parallel interface to maintain
- Agent guide files (
.claude/CLAUDE.md) — static, requires manual updates, doesn’t reflect current project state --helpoutput — describes syntax, not semantics or workflow context
The core problem: discovery and context-awareness, not invocation. Agents need to understand govctl’s philosophy, command purposes, and what actions are relevant given current project state.
Decision
Add a govctl describe command with two modes:
1. Static mode (default):
govctl describe --json
Outputs machine-readable JSON containing:
version: govctl versionpurpose: one-line description of govctl’s rolephilosophy: core principles (RFC supremacy, phase discipline)commands[]: for each command:name: command name (e.g., “new rfc”, “advance”)purpose: what it doeswhen_to_use: semantic guidance on when to invokeexample: concrete usageprerequisites: what must be true before running
workflow: typical command sequence for common tasks
2. Context-aware mode:
govctl describe --context --json
Reads current project state and outputs:
project_state: current RFCs, ADRs, work items with their statuses/phasessuggested_actions[]: contextually relevant commands with reasons- Example: “RFC-0001 is in impl phase. If implementation complete, run
govctl advance RFC-0001 test”
- Example: “RFC-0001 is in impl phase. If implementation complete, run
warnings[]: governance issues detected (stale items, blocked transitions)
Implementation:
- Command metadata derived from existing clap
#[command(about = "...")]attributes where possible - Semantic guidance (
when_to_use) defined as static data - Context mode reuses
statusandlistlogic for project state - Output format follows JSON Schema for predictable parsing
Consequences
Positive:
- Agents gain semantic understanding without MCP complexity
- Single interface (CLI) — no parallel implementation to maintain
- Context-aware mode reduces agent trial-and-error
- Works with any shell-capable agent (not limited to MCP-compatible tools)
- Self-documenting:
govctl describeoutput stays in sync with actual commands - Distribution unchanged:
cargo install govctlis all users need
Negative:
- Additional ~200-300 lines of code for command metadata and describe logic
- Semantic guidance (
when_to_use) must be manually authored and maintained - JSON output format becomes a compatibility surface (changes need care)
Neutral:
- Agents must call
govctl describeonce per session (cacheable) - Plain
--helpremains available for human users - Does not preclude future MCP integration if demand materializes
Comparison to MCP:
| Aspect | govctl describe | MCP |
|---|---|---|
| Distribution | cargo install govctl | Server config + process mgmt |
| Agent compatibility | Any shell-capable agent | MCP-compatible agents only |
| Maintenance | Single codebase | CLI + MCP server |
| Context awareness | Built-in | Separate implementation |
| Works offline | Yes | Depends |
ADR-0016: Allow RFC amendments via versioning during implementation
Status: accepted | Date: 2026-01-19
Tags:
lifecycle
References: RFC-0001, ADR-0004
Context
Real-world governance experience from the neotex-v2 project shows that RFCs often need amendments during implementation. This conflicts with the current govctl mental model that treats normative status as “frozen” — the documentation (CLAUDE.md:79) states “normative: Frozen. Implementation MUST conform.”
This creates a false dichotomy:
- Theory: Spec everything perfectly, then implement
- Practice: You discover spec bugs, ambiguities, and wrong assumptions during implementation
The problem is not with RFC-0001:C-RFC-STATUS (which only says “normative” means “binding”), but with the interpretation that “binding” implies “immutable.” This forces workarounds: draft ADRs, inline comments, or ignoring governance entirely.
The infrastructure for RFC evolution already exists: versioning (version field) and changelog (changelog array per ADR-0004). We’re just not using it for governance.
Decision
Clarify the semantics of “normative”:
normativemeans binding (code must conform to current version)normativedoes NOT mean frozen (spec can evolve with version bumps)
Operational changes:
- Remove “normative = frozen” messaging from all documentation
- Document that normative RFCs MAY be amended via version bumping
- When amending a normative RFC:
- Bump version according to semantic versioning
- Add changelog entry documenting the change
- Rationale and audit trail live in git/jj history
Precedent: Linux kernel APIs are both binding (drivers must conform) and evolving (with deprecation, versioning, compatibility) simultaneously.
Consequences
Easier:
- Amending RFCs during implementation (matches real workflow)
- Iterative spec refinement (discover-fix-document cycle)
- Honest governance (no pretending specs are perfect)
More difficult:
- Reviewers must check RFC changelog to see what changed
- Multiple versions of an RFC might exist during development (but this is reality anyway)
No breaking changes:
- Existing RFCs remain valid
- No data model changes required
- Validation rules simplified (remove frozen assumption)
ADR-0017: CLI Command Implementation Details
Status: superseded | Date: 2026-01-19 Superseded by: ADR-0037
Tags:
cli
References: RFC-0002, ADR-0037
Context
RFC-0002 defines the structural contract for govctl CLI commands: resource-first organization, universal CRUD verbs, lifecycle operations, and output format control. However, RFC-0002 intentionally defers implementation details to preserve flexibility while maintaining a stable interface contract.
Implementation requires decisions on:
- Exact flag syntax and naming conventions
- Array field editing notation (how to add/remove items)
- Help text formatting and structure
- Error message templates and exit codes
- Terminal capability detection (colors, interactive prompts)
- Confirmation prompt behavior
- Progress indicators for long-running operations
Without documented conventions, implementers would make inconsistent choices, leading to:
- Flags named differently across commands (–filter vs –query)
- Array editing syntax that varies by resource type
- Inconsistent help text structure
- Error messages with different formats
- Terminal behavior that breaks in non-interactive contexts
This ADR establishes implementation conventions that realize RFC-0002’s structural contract with consistent UX.
Decision
We adopt the following implementation conventions:
1. Flag Syntax and Naming
Long flags: Always use double-dash with kebab-case
--output,--filter,--dry-run,--force
Short flags: Single letter aliases for common flags only
-ofor--output-ffor--force-nfor--limit(per ADR-0019, aligns with head/tail convention)
No short flag for --dry-run: Safety flags benefit from explicit long form.
No short flags for domain-specific options to avoid collision:
--filterhas no short form--rfc-idhas no short form
Flag values:
- Space-separated:
--output json(preferred) - Equals accepted:
--output=json(clap auto-supports) - No colons: avoid
--output:json
2. Field Editing Commands
govctl uses distinct verbs for different mutation operations. Each verb is clear and discoverable via --help.
Scalar fields: Use set
govctl rfc set RFC-0001 title "New Title"
govctl work set WI-001 description "Updated description"
govctl adr set ADR-001 status accepted
Array fields - append: Use add
govctl work add WI-001 refs RFC-0001
govctl rfc add RFC-0001 owners @alice
govctl work add WI-001 acceptance_criteria "New criterion"
Array fields - remove: Use remove
govctl work remove WI-001 refs RFC-0001
govctl rfc remove RFC-0001 owners @bob
Checklist status: Use tick
govctl work tick WI-001 acceptance_criteria "Tests pass" -s done
govctl work tick WI-001 acceptance_criteria "Docs" -s pending
Pattern matching for array operations: Same semantics as ADR-0007
- Default: case-insensitive substring match
- Use
--exactfor exact match - Use
--regexfor pattern match - Use
--at Nfor index-based access
Rationale: Distinct verbs (set, add, remove, tick) are more intuitive and discoverable than a unified edit command with prefix notation. Users immediately understand what each command does.
3. Help Text Structure
All commands follow this template:
USAGE:
govctl <resource> <verb> [OPTIONS] <ARGS>
ARGS:
<required> Description
[optional] Description
OPTIONS:
-o, --output <FORMAT> Output format [default: table] [possible: json, yaml, toml, plain]
--filter <EXPR> Filter results (KEY=VALUE)
--dry-run Preview changes without writing
-h, --help Print help
EXAMPLES:
govctl rfc list draft
govctl rfc get RFC-0001 -o json
govctl rfc set RFC-0001 title "New Title"
Ordering:
- Universal flags first (output, filter, dry-run)
- Resource-specific flags second
- Help/version last
4. Error Messages and Exit Codes
Exit codes:
0- Success1- General error (validation, not found, invalid transition)2- Usage error (wrong arguments, unknown flag)
Error format:
error[CODE]: <message>
--> <location>
|
| <context>
Example:
error[E0102]: RFC not found: RFC-9999
--> gov/rfc/RFC-9999
|
| Run 'govctl rfc list' to see available RFCs
Diagnostic codes: Use existing govctl error taxonomy (E0xxx, W0xxx).
5. Terminal Capability Detection
Color output:
- Auto-detect TTY with
attyoris-terminalcrate - Respect
NO_COLORenvironment variable - Respect
--color <always|never|auto>flag (future)
Interactive prompts:
- Only show in TTY mode
- Skip if
--forceflag provided - Skip if stdin is not TTY
Progress indicators:
- Use
indicatifcrate for long operations (>2s expected) - Show progress for: render, check, bulk operations
- Suppress if
--quietor non-TTY
6. Confirmation Prompts
Destructive operations require confirmation unless --force:
delete(clauses, work items)deprecate(RFCs, clauses)supersede(RFCs, ADRs, clauses)
Prompt format:
Delete work item WI-YYYY-MM-DD-NNN? [y/N]
Behavior:
- Default to “no” (capital N)
- Accept: y, Y, yes, Yes, YES
- Reject: n, N, no, No, NO, empty, anything else
- Timeout: none (wait indefinitely)
7. Filter Syntax
Per RFC-0002:C-CRUD-VERBS, list commands support filtering.
Simple filter (shorthand):
govctl rfc list draft # filter by status
govctl work list active # filter by status
Explicit filter (future extension):
govctl rfc list --filter status=draft
govctl rfc list --filter phase=impl,status=normative
Implementation: Start with simple substring matching, defer explicit expressions to future ADR.
8. Stdin Handling
When --stdin flag is present:
- Read entire stdin to EOF
- Trim trailing newline only (preserve internal newlines)
- Empty stdin is valid (allows heredocs with empty content)
HEREDOC pattern (recommended for multi-line):
govctl clause set RFC-0001:C-SCOPE text --stdin <<'EOF'
This clause defines the scope.
EOF
9. Dry-Run Behavior
Global --dry-run flag:
- Shows what would be written
- Prints diff or file preview
- Exits with 0 (success simulation)
- No short flag (safety flags should be explicit)
Output format:
[DRY RUN] Would write: gov/rfc/RFC-0001/rfc.json
--- before
+++ after
10. Subcommand Organization (clap)
Structure:
Use nested Subcommand enums for resource-first organization.
Resource commands contain their own verb subcommands.
Global commands remain at top level.
Backward compatibility aliases: Emit deprecation warning when old verb-first commands are used.
Consequences
Positive:
-
Consistent UX: All commands follow the same patterns. Users learn once, apply everywhere.
-
Agent-friendly: Predictable flags, stable error codes, machine-readable output defaults make automation reliable.
-
Maintainable: Implementation conventions documented, not scattered across code comments.
-
Discoverable: Distinct verbs (
set,add,remove,tick) are immediately understandable. Users can explore via--helpwithout reading documentation. -
Safe: Confirmation prompts prevent accidental destructive actions. Dry-run mode enables testing before committing.
-
Debuggable: Structured error messages with codes and locations make issues easy to diagnose.
Negative:
-
Multiple verbs: Users must learn four verbs for mutation operations (
set,add,remove,tick) instead of one. However, each verb’s meaning is immediately clear. -
Testing complexity: Need tests for TTY detection, confirmation prompts, dry-run mode, error formatting, etc.
Trade-offs Accepted:
-
Clarity over brevity: Distinct verbs are more verbose than a unified
editcommand, but much easier to understand.addandremoveare clearer thanedit +valueandedit -value. -
Discoverability over uniformity: Four clear verbs are better than one verb with special syntax that requires documentation.
-
Safety over speed: Confirmation prompts slow down destructive operations. This is intentional to prevent accidents.
Alternatives Considered
Document shared CLI implementation conventions. (accepted)
- Pros: Keeps command behavior consistent across resources
- Cons: Requires maintaining a single convention document
Leave CLI implementation details undocumented per command. (rejected)
- Pros: No extra ADR maintenance
- Cons: Commands drift in flags, prompts, errors, and help shape
- Rejected because: Inconsistent command behavior undermines RFC-0002’s stable interface contract.
ADR-0018: Global Command Shortcuts vs Strict Resource-First Syntax
Status: accepted | Date: 2026-01-19
Tags:
cli
References: RFC-0002, ADR-0017
Context
During implementation of RFC-0002, we successfully built the resource-first command structure (govctl <resource> <verb>). However, a design question emerged about backward compatibility with existing verb-first shortcuts.
Current Implementation
Both syntaxes currently work:
# Resource-first (RFC-0002 canonical)
govctl rfc list
govctl work new "title"
govctl adr accept ADR-0001
# Verb-first shortcuts (legacy)
govctl list rfc
govctl new work "title"
The Tension
RFC-0002:C-GLOBAL-COMMANDS explicitly defines which commands should remain global:
init,check,status,render,describe,completions
Notably absent from this list: list, new, and all resource-specific operations like move, tick, accept, etc.
This suggests the RFC intentionally designed these as resource-scoped operations, not global commands.
Problem Statement
Should we:
- Keep
listandnewas convenient global shortcuts that delegate to resource-first implementations? - Remove them entirely and enforce strict resource-first syntax per RFC-0002?
- Keep them with deprecation warnings for gradual migration?
User Impact
We have ~40 completed work items and governance workflows that use the old syntax. Scripts, documentation, and muscle memory are built around patterns like govctl list rfc and govctl new work.
However, we are pre-1.0 (currently 0.2.0), which traditionally allows breaking changes.
Implementation Complexity
Current implementation maintains both paths through the canonical command pattern, adding ~40 lines of delegation code. This works but violates the “one way to do it” principle.
Decision
Decision: Remove shortcuts immediately (Option 2)
We will remove govctl list and govctl new shortcuts entirely, enforcing strict resource-first syntax per RFC-0002.
Rationale
-
RFC Compliance: RFC-0002:C-GLOBAL-COMMANDS deliberately defines the exhaustive list of global commands.
listandneware not on that list, indicating they should be resource-scoped. -
Design Clarity: The resource-first pattern (
govctl <resource> <verb>) provides a clear, predictable structure:govctl rfc list- list RFCsgovctl work new- create work itemgovctl adr accept- accept ADR
Having two ways (
govctl list rfcvsgovctl rfc list) violates the “one obvious way” principle. -
Reduced Complexity: Maintaining both patterns adds ~40 lines of delegation code and increases cognitive load for users (“which way should I use?”).
-
Pre-1.0 Window: We’re at version 0.2.0, which traditionally allows breaking changes before stabilizing at 1.0.
-
Shell Aliases Sufficient: Users who want shortcuts can add personal aliases:
alias gl='govctl rfc list' alias gw='govctl work' alias ga='govctl adr'This moves convenience to where it belongs—user preference—rather than mandating it in the tool.
-
Consistency: If we keep
listandnewas globals, why notmove,tick,accept,reject? The line becomes arbitrary. Resource-first is consistent across all operations.
Migration Plan
Since this is a breaking change:
- Update all documentation to use resource-first syntax ✅ (done)
- Update internal workflows (gov.md, .claude/CLAUDE.md) ✅ (done)
- Remove from Commands enum in main.rs
- Remove delegation logic from command_router.rs
- Update CHANGELOG.md noting the breaking change
- Consider: Add migration guide in docs showing the mapping
Non-breaking Alternative Considered
We could keep shortcuts with deprecation warnings (Option 3), but this:
- Extends the transition period indefinitely
- Keeps dual-path complexity in codebase
- Delays the inevitable
Given pre-1.0 status, clean break is preferable.
Consequences
Positive
- Single Canonical Syntax: Only one way to invoke commands reduces confusion
- RFC Compliance: Aligns perfectly with RFC-0002:C-GLOBAL-COMMANDS
- Simpler Codebase: ~40 fewer lines of delegation logic to maintain
- Clearer Documentation: Examples show only one pattern, easier to teach
- Predictable:
govctl <resource> <verb>works for all operations without exceptions - Tab Completion: Clearer completion tree (type
govctl→ see resources, not mix of resources + verbs)
Negative
- Breaking Change: Existing scripts using
govctl listorgovctl newwill break- Mitigation: We’re pre-1.0, document in CHANGELOG
- More Keystrokes:
govctl rfc listis longer thangovctl list rfc- Mitigation: Shell aliases for personal shortcuts
- Learning Curve: Users familiar with old syntax need to adjust
- Mitigation: Clear error messages suggesting correct syntax
Migration Required
Users need to update:
# Old → New
govctl list rfc → govctl rfc list
govctl list adr → govctl adr list
govctl list work → govctl work list
govctl list clause → govctl clause list
govctl new rfc "..." → govctl rfc new "..."
govctl new adr "..." → govctl adr new "..."
govctl new work "..." → govctl work new "..."
govctl new clause ... → govctl clause new ...
Future Extension
This decision does NOT prevent adding convenience aliases later if user demand warrants it. However, any such addition would require an RFC amendment to RFC-0002:C-GLOBAL-COMMANDS.
Recommendation for Users
Add personal shell aliases for frequently used commands:
# In ~/.bashrc or ~/.zshrc
alias gr='govctl rfc'
alias ga='govctl adr'
alias gw='govctl work'
alias gc='govctl clause'
# Usage becomes:
gr list # govctl rfc list
gw new "task" # govctl work new "task"
This provides the convenience without coupling it to the tool.
Alternatives Considered
Keep both syntaxes permanently
Remove shortcuts immediately (strict RFC-0002)
Phased deprecation (warnings now, remove in 1.0)
Expand shortcuts to all common operations
ADR-0019: Change -n from dry-run to limit for better Unix convention alignment
Status: accepted | Date: 2026-01-19
Tags:
cli
References: ADR-0006, ADR-0017
Context
ADR-0006 and ADR-0017 assigned -n as the short flag for --dry-run, following rsync’s convention. However, this conflicts with the more universal Unix convention where -n means “number” or “limit”:
Standard Unix tools using -n for number/limit:
head -n 10(limit to N lines)tail -n 10(limit to N lines)grep -n(show line numbers)sort -n(numeric sort)ls -n(numeric IDs)
Tools using -n for dry-run:
rsync -n(dry-run) - notable exception- Very few other standard tools
Current problem:
We need to add --limit flag to all list commands to control result count. The natural short flag would be -n, but it’s already taken by dry-run. This forces us to either:
- Use no short flag for limit (verbose, less ergonomic)
- Change
-nto mean limit (breaks ADR-0006/ADR-0017)
Impact of current design:
govctl work list --limit 5is verbose (no short option)- Inconsistent with
head -n 5/tail -n 5muscle memory - Dry-run is a safety flag (verbose is acceptable)
- Limit is used frequently in interactive sessions (short flag valuable)
Decision
Reassign -n from dry-run to limit:
-
Remove
-nshort flag from--dry-run(keep long form only)- Dry-run remains accessible as
--dry-run - This is a safety flag - verbosity is appropriate
- Dry-run remains accessible as
-
Add
-nshort flag to--limiton all list commandsgovctl rfc list -n 10govctl work list -n 5- Aligns with
head -n/tail -nconventions
-
Amend ADR-0006 and ADR-0017 to reflect this change
Rationale:
- Unix convention alignment:
-nfor “number” is far more common - Ergonomics: Limit is used frequently, dry-run less so
- Safety: Dry-run benefits from being explicit (
--dry-run) - Pre-1.0 window: Breaking changes are acceptable now
- Consistency: Follows head/tail patterns users know
Consequences
Positive:
- Natural
-nfor limit matches Unix expectations - More ergonomic interactive use:
govctl work list -n 5 - Explicit
--dry-runis clearer for safety-critical flag - Consistent with standard tooling (head, tail, etc.)
Negative:
- Breaking change: Scripts using
-nfor dry-run will break - Requires updating ADR-0006 and ADR-0017
- Requires updating any documentation mentioning
-n
Migration:
- All uses of
-nmust change to--dry-run - Update
.claude/CLAUDE.mdand other docs - Add to CHANGELOG as breaking change
- Search codebase for any hardcoded
-nusage
Affected ADRs:
ADR-0020: Configurable work item ID strategies for multi-person collaboration
Status: accepted | Date: 2026-01-26
Tags:
collaboration,work-items
References: RFC-0000
Context
The current work item ID format (WI-YYYY-MM-DD-NNN) uses local sequential numbering. The govctl work new command scans gov/work/ to find the max sequence number for today’s date, then increments by 1.
Problem: When multiple people work on parallel branches and both create work items on the same day, they get the same ID:
Alice: scans → max=002 → creates WI-YYYY-MM-DD-003
Bob: scans → max=002 → creates WI-YYYY-MM-DD-003 (collision!)
On merge, these IDs collide. This blocks multi-person teams from adopting govctl.
Options considered:
| Strategy | Format | Pros | Cons |
|---|---|---|---|
| Author namespace | WI-2026-01-26-alice-001 | Clear ownership, sequential per author | Requires config |
| Git identity hash | WI-2026-01-26-a7f3-001 | Auto from git email, no config | Less readable |
| Random suffix | WI-2026-01-26-a7f3 | Simple, no coordination | Non-sequential |
| Timestamp | WI-2026-01-26-143257 | Natural ordering | Clock skew issues |
| Merge-time renumber | Keep current | Minimal change | Breaks refs on rename |
govctl is primarily single-contributor but must support multi-person teams as external adopters.
Decision
Add opt-in ID strategies via gov/config.toml, keeping current behavior as default.
-
Default:
sequential(current behavior)- Format:
WI-YYYY-MM-DD-NNN - Solo projects keep simple, readable IDs
- No breaking change for existing users
- Format:
-
Opt-in:
author-hash(recommended for teams)- Format:
WI-YYYY-MM-DD-{hash4}-NNN {hash4}= first 4 chars ofsha256(git config user.email)- Example:
WI-2026-01-26-a7f3-001 - Each contributor gets their own sequence namespace
- Zero configuration (auto-derived from git identity)
- Format:
-
Opt-in:
random(simple uniqueness)- Format:
WI-YYYY-MM-DD-{rand4} {rand4}= 4 random hex chars (65,536 possibilities per day)- Example:
WI-2026-01-26-b2c9 - No sequence number, just unique suffix
- Format:
Configuration:
# gov/config.toml
[work_item]
id_strategy = "author-hash" # or "sequential" (default), "random"
Rationale:
- Backward compatible: default remains
sequential - Teams explicitly opt-in to collision-safe strategy
author-hashis recommended because it preserves sequential numbering within author namespace- Uses git identity (already required for commits) — zero additional config
Consequences
Positive:
- Multi-person teams can adopt govctl without ID collision risk
- Existing single-contributor projects unchanged
author-hashprovides both collision safety AND sequential ordering- Zero configuration for author-hash (uses git email)
Negative:
- New ID formats (
WI-...-a7f3-001) are less human-memorable - Cannot easily tell “who created this” without looking up the hash
- Projects must explicitly configure for team use
Implementation:
- Add
id_strategytoConfigstruct - Modify
src/cmd/new.rs::create_work_item()to dispatch based on strategy - Add validation that all work items follow configured strategy
- Update
gov/schema/SCHEMA.mdto document new formats
Migration for teams:
- Set
[work_item] id_strategy = "author-hash"ingov/config.toml - Existing work items retain their IDs (no renaming required)
- New work items use the new format
ADR-0021: Resource-scoped render commands for single-item rendering
Status: accepted | Date: 2026-01-29
Tags:
cli
References: RFC-0002, ADR-0018
Context
The global govctl render command currently has an --rfc-id flag for rendering a single RFC, but no equivalent flags for ADRs or work items. This creates an asymmetry in the CLI.
Problem Statement
When users want to render a single artifact, the current options are:
| Artifact | Current Syntax | Works? |
|---|---|---|
| RFC | govctl render rfc --rfc-id RFC-0001 | ✅ Yes |
| ADR | (none) | ❌ No |
| Work Item | (none) | ❌ No |
Constraints
- RFC-0002:C-GLOBAL-COMMANDS defines
renderas a global command that “operates across all resources” - ADR-0018 established the “one way to do it” principle
- Resource-scoped commands follow the noun-first pattern per RFC-0002:C-RESOURCE-MODEL
Decision
We will add resource-scoped render commands and remove the --rfc-id flag from the global render command.
New Commands
govctl rfc render <RFC-ID> # Render single RFC
govctl adr render <ADR-ID> # Render single ADR
govctl work render <WI-ID> # Render single work item
Modified Command
# Global render now ONLY does bulk operations
govctl render [rfc|adr|work|changelog|all] # No --rfc-id flag
Rationale
- Clean separation: Global
render= bulk operations, resource-scoped = single-item - No flag proliferation: Avoids
--rfc-id,--adr-id,--work-idon global command - Discoverable:
govctl rfc --helpshowsrenderalongside other verbs - Noun-first for single items: Consistent with
govctl rfc get,govctl rfc list - RFC-0002 compatible:
renderremains global for bulk; adding resource verbs doesn’t violate this
Implementation Notes
- Resource-scoped
rendershares implementation with global render (just filters to single ID) - Error handling: if ID not found, return clear error message
- Output: same format as bulk render, just for one item
Consequences
Positive
- Symmetric API: All resource types support single-item render equally
- Cleaner global command: No proliferation of
--*-idflags - Intuitive mental model: “Work with RFC” →
govctl rfc render RFC-0001 - Better discoverability:
govctl rfc --helpshows all RFC operations including render
Negative
- Breaking change: Scripts using
govctl render --rfc-idmust update- Mitigation: Pre-1.0, document in CHANGELOG
- Two entry points for render: Global (bulk) and resource-scoped (single)
- Mitigation: Clear purpose split makes this a feature, not a bug
Migration
# Old syntax (removed)
govctl render rfc --rfc-id RFC-0001
# New syntax
govctl rfc render RFC-0001
Alternatives Considered
Add –adr-id and –work-id flags to global render: Proliferates flags, violates ‘one way’ principle
Leave as-is with only –rfc-id: Asymmetric, inconsistent UX
ADR-0022: Add show command for stdout rendering
Status: accepted | Date: 2026-02-07
Tags:
cli
References: RFC-0002, ADR-0021
Context
Agents (Claude, Cursor, etc.) intuitively try govctl rfc show RFC-0001 to read an RFC’s rendered content, but this command doesn’t exist. The error unrecognized subcommand 'show' is a recurring failure mode.
Problem Statement
The current CLI has an asymmetry in read operations:
| Verb | Purpose | Output |
|---|---|---|
get | Read individual field value | stdout |
render | Generate full markdown | file (side effect) |
| (missing) | Read full rendered content | stdout |
The gap: there’s no way to get the full rendered representation to stdout without writing a file.
Current Workarounds
govctl rfc render RFC-0002 --dry-run— shows preview, but semantically wrong (dry-run is for previewing writes)- Read
docs/rfc/RFC-0002.mddirectly — requires knowing the configurable output path
Both are awkward for agents who just want to “see” an artifact.
Constraints
- RFC-0002:C-CRUD-VERBS defines standard CRUD verbs for resources
- RFC-0002:C-OUTPUT-FORMAT specifies output format handling (–output flag, TTY detection)
- ADR-0021 established resource-scoped
renderfor single-item file generation
Mental Model
Unix convention: commands that read data print to stdout; commands that generate files write to filesystem. show fits the “read and display” pattern like cat, kubectl get -o yaml, or docker inspect.
Decision
We will add a show verb to all renderable resources that outputs content to stdout.
New Commands
govctl rfc show <RFC-ID> # Print rendered RFC to stdout
govctl adr show <ADR-ID> # Print rendered ADR to stdout
govctl work show <WI-ID> # Print rendered work item to stdout
govctl clause show <CLAUSE-ID> # Print clause content to stdout
Output Format
- Default: Markdown text (the human-readable rendered form)
- With
--output json: Structured JSON (equivalent togetwith no field) - Respects RFC-0002:C-OUTPUT-FORMAT conventions
Semantic Distinction
| Command | Purpose | Side Effects |
|---|---|---|
show | Read and display to stdout | None |
render | Generate and write to file | Writes file |
get | Read single field value | None |
Rationale
- Agent-friendly: Natural command that agents try first (
show= “let me see this”) - Unix convention: Read operations → stdout; write operations → filesystem
- Minimal implementation: Reuses existing render logic, just changes output target
- Symmetric with render:
showis torenderascatis tocp - Format flexibility:
--output jsongives structured access when needed
Consequences
Positive
- Fixes agent failures:
govctl rfc show RFC-0001will work as expected - Cleaner semantics: Clear separation between read (show) and write (render)
- Pipeable:
govctl rfc show RFC-0002 | lessor| grep patternjust works - Consistent UX: All renderable resources get the same
showverb
Negative
- New verb to learn: Users must understand show vs render distinction
- Mitigation: Intuitive naming makes this self-evident
- Slight command surface growth: 4 new subcommands
- Mitigation: Natural extension of existing pattern, improves discoverability
Neutral
--output jsononshowis functionally equivalent togetwith no field argument — this redundancy is acceptable for discoverability
Alternatives Considered
Extend get with –rendered flag: Overloads get semantics, less discoverable
Use view instead of show: Equally valid, but show is more common in CLIs (docker inspect, kubectl describe)
Use cat as the verb: Unix-y but loses semantic meaning (cat is for concatenation)
ADR-0023: Organize assets into commands, skills, and agents subdirectories
Status: accepted | Date: 2026-02-11
Tags:
skills-agents
References: ADR-0024
Context
The assets/ directory currently contains a flat mix of files: four command workflow definitions (gov.md, quick.md, discuss.md, status.md) and four logo SVGs. As we prepare to add skill definitions (specialized AI agent capabilities) and agent definitions (agent role/behavior configurations), the flat structure becomes ambiguous — it conflates three distinct categories of assets.
Problem Statement
With new asset types incoming, a flat assets/ directory provides no semantic separation. Developers (and tools like sync-commands.sh) must rely on conventions or file extensions to distinguish command templates from skills from agents.
Constraints
govctl initcopies command templates viainclude_str!insrc/cmd/new.rs— paths are compile-time constantsbuild.rstracks command files for rebuild — paths must stay in syncscripts/sync-commands.shandsync-commands.ps1globassets/*.md— pattern must be updated- Logo SVGs are referenced from
README.mdand are a fourth category (static images)
Decision
Organize assets/ into three subdirectories by category:
assets/commands/— AI workflow command definitions (gov.md, quick.md, discuss.md, status.md)assets/skills/— Skill definitions (new, initially empty)assets/agents/— Agent definitions (new, initially empty)
Logo SVGs remain at the assets/ root since they are static images, not AI-consumable definitions.
All compile-time paths (include_str!), build system paths (build.rs), and script globs are updated to reference assets/commands/.
Rationale
- Semantic clarity — the directory name tells you what kind of asset it is
- Minimal blast radius — logos stay put, only command
.mdfiles move one level deeper - Future-proof — skills and agents get their own home from day one
Consequences
Positive
- Clear separation of concerns for three distinct asset categories
- New skills/agents have a designated location from the start
- Scripts and tooling can target specific subdirectories
Negative
- One-time update to all paths referencing command assets (4 files)
- Test snapshots that reference output paths may need updating
Neutral
- Logo SVGs stay at
assets/root — no change to README references
Alternatives Considered
Flat with naming conventions: Keep flat assets/ and use prefixes like cmd-gov.md, skill-foo.md. Rejected: naming conventions are fragile and don’t scale.
Separate top-level directories: commands/ skills/ agents/ at repo root. Rejected: over-scatters related assets.
ADR-0024: Writers as skills, reviewers as agents for governance artifacts
Status: superseded | Date: 2026-02-11 Superseded by: ADR-0057
Tags:
skills-agents
References: ADR-0023
Context
govctl manages three governance artifact types — RFCs, ADRs, and work items. We need to add AI-assisted capabilities for both creating (writing) and reviewing these artifacts.
Per ADR-0023, the assets/ directory is organized into commands/, skills/, and agents/ subdirectories. Skills and agents are synced to .claude/skills/ and .claude/agents/ respectively.
Problem Statement
Each artifact type needs writing guidance (structure, conventions, quality patterns) and review criteria (completeness checks, quality gates). The question: should each capability be a skill (augments the main agent inline) or an agent (runs as isolated subagent with its own system prompt)?
Key Distinction
- Skills run in the main agent’s context. They have full access to the conversation and codebase. They augment what the main agent knows.
- Agents run in isolated contexts with custom system prompts. They receive delegated tasks and return results. They have no access to the main conversation.
Constraints
- Skills MUST be <250 lines per SKILL.md (progressive disclosure via
references/) - Agents MUST have focused system prompts
- Each capability should follow “one skill, one capability” principle
- The existing
/discussand/govcommands orchestrate workflows that need writing knowledge
Decision
Writers are skills. Reviewers and auditors are agents. Seven items total:
Skills (in assets/skills/)
| Skill | Purpose |
|---|---|
rfc-writer | How to write well-structured RFCs: normative language (MUST/SHOULD/MAY), clause structure, versioning, since fields |
adr-writer | How to write effective ADRs: context/decision/consequences, trade-off analysis, alternatives documentation |
wi-writer | How to write good work items: acceptance criteria with category prefixes, description quality |
Agents (in assets/agents/)
| Agent | Purpose |
|---|---|
rfc-reviewer | Review RFC drafts for completeness, normative language quality, clause coverage, cross-references |
adr-reviewer | Review ADR drafts for context quality, decision clarity, alternatives, honest consequences |
wi-reviewer | Review work items for acceptance criteria structure, category correctness, description quality |
compliance-checker | Verify code conforms to normative RFC clauses and ADR decisions — detect spec violations in implementation |
Rationale
-
Writers need conversation context. An RFC writer must know why the user is creating the RFC — what problem, what constraints, what existing artifacts relate. Skills run inline and have full context.
-
Reviewers benefit from cognitive isolation. When the main agent writes an artifact and then reviews it, confirmation bias is unavoidable. An isolated review agent has no memory of authoring — it evaluates purely on quality criteria.
-
Compliance checking is auditing, not writing. The
compliance-checkeragent cross-references source code against normative RFC clauses (MUST/MUST NOT) and ADR decisions. It is distinct from artifact reviewers — those check if an artifact is well-written, this checks if code follows what artifacts specify. Isolation ensures no “I wrote this code so it must conform” bias. -
Seven separate, not consolidated. Each capability is genuinely different. Each stays well under 250 lines. The ~15% shared knowledge (govctl commands,
[[ref]]syntax) is 3-5 lines of duplication — not worth coupling distinct capabilities to eliminate.
Integration
/discussand/govcommands will reference writer skills for quality guidance- Review agents can be invoked at quality gates (e.g., after drafting, before finalization)
compliance-checkercan be invoked during/govPhase 4 (testing) or on demandsync-assets.shalready syncs bothskills/andagents/directories
Consequences
Positive
- Writers augment the main agent with domain knowledge while preserving conversation context
- Reviewers provide unbiased quality checks through cognitive isolation
- Compliance checker catches spec violations that
govctl checkcannot (it validates references exist; the agent validates semantic conformance) - Seven focused items follow “one skill, one capability” — each stays under 250 lines
- Future artifact types get their own skill + agent pair without touching existing files
sync-assets.shalready supports the directory structure (ADR-0023)
Negative
- 7 files to maintain (mitigation: each is small and focused, changes are rare)
- ~15% knowledge duplication across items (mitigation: 3-5 lines per file, not worth abstracting)
- Review/audit agents lack conversation context (mitigation: they evaluate on merit, which is the point)
- Compliance checking is inherently imprecise — agent may flag false positives (mitigation: output is advisory, not blocking)
Neutral
- Existing
/discussand/govcommands continue to work unchanged initially; skills/agents integration is additive govctl checkcontinues to handle structural validation;compliance-checkerhandles semantic validation — complementary, not competing
Alternatives Considered
All skills: Make both writers and reviewers skills. Rejected: reviewers lose cognitive isolation, confirmation bias when main agent reviews its own work.
All agents: Make both writers and reviewers agents. Rejected: writers lose conversation context, cannot access why the user is creating the artifact.
4 consolidated items (governance-writer + wi-writer, governance-reviewer + wi-reviewer): Rejected: RFC and ADR capabilities are genuinely different, merging creates a skill that branches on artifact type — special cases we want to eliminate.
2 consolidated items (one writer, one reviewer): Rejected: work items differ fundamentally from RFCs/ADRs, no shared domain knowledge worth coupling.
ADR-0025: Concurrent write safety for agent-driven parallel tasks
Status: accepted | Date: 2026-02-15
Tags:
safety
References: RFC-0002, ADR-0020
Context
When an agent (e.g. Cursor, Claude Code) runs multiple tasks in parallel that each invoke govctl to create or modify RFCs, ADRs, or work items, concurrent writes to the same files or to the same directory can cause:
- File corruption — Two processes write to the same file; interleaved writes or truncate-then-write races produce partial or invalid content.
- ID collision — Work item creation uses
find_max_sequence(work_dir, id_prefix)then writes a new file. Two processes can read the same max, both write the same ID or overwrite the same path (same date-slug). - Lost updates — Read-modify-write (e.g. edit, set, bump) without coordination: one process overwrites the other’s write.
This is distinct from ADR-0020, which addresses ID collision across branches (merge-time). Here the scenario is same repository, multiple concurrent processes (e.g. multiple agent tasks in one workspace).
Constraints: govctl is a CLI; no daemon. Implementation must work across processes. No network or external services. Must remain portable (Unix/macOS/Windows where feasible).
Decision
Use process-level filesystem locking so that only one govctl process mutates the governance tree at a time.
-
Scope of locking
- Any command that modifies
gov/or writes todocs/(render, new, set, add, edit, tick, bump, finalize, advance, accept, move, etc.) MUST acquire a lock before performing mutations and release it when done. - Read-only commands (list, get, check, status, show) do NOT need to hold the lock.
- Any command that modifies
-
Lock mechanism
- A single gov-root lock file (e.g.
gov/.govctl.lockor a lock in a well-known location under gov root). One lock for the entire gov tree. - Acquire: exclusive (write) lock on that file (e.g.
flock(LOCK_EX)on Unix; equivalent on Windows). - Blocking: if lock is held by another process, wait with optional timeout; on timeout, fail with a clear error instructing the user to retry or avoid parallel govctl writes.
- A single gov-root lock file (e.g.
-
Granularity
- Coarse-grained (one lock per gov root) is chosen over per-artifact or per-directory locks to avoid deadlock and to keep implementation and behavior simple. Parallel agents serialize at the gov root; throughput is traded for correctness and simplicity.
Consequences
Positive
- Prevents file corruption and ID collision under concurrent agent tasks.
- Single lock file: no deadlock, no lock ordering, easy to reason about.
- Portable: file locking is available on all supported platforms (flock/cfg with fallbacks).
Negative
- Parallel govctl write commands serialize; one task may block until another finishes. Mitigation: agents can be designed to queue writes or run write commands sequentially; CLI documents the locking behavior.
- Stale lock if process crashes without releasing. Mitigation: lock is process-scoped (OS releases on exit); optional timeout + clear error message for “stuck” waiters.
- Slight complexity in CLI entrypoint: acquire lock early for write commands, release on all exit paths.
Neutral
- Render (writing to docs/) is included in the lock scope so that render + new/edit from two processes do not interleave.
Alternatives Considered
File lock (gov-root): One exclusive lock for entire gov/ tree. Blocks concurrent writers until release. Chosen for simplicity and no deadlock.
Per-artifact lock: Lock only the file or directory being written. Rejected: deadlock risk (e.g. A holds rfc/ B holds adr/; A needs adr/ B needs rfc/), more complex lock ordering.
Write queue / single-writer daemon: One process accepts write requests over a socket or FIFO. Rejected: requires a long-running daemon, contradicts CLI-only design.
Documentation-only: Tell users/agents not to run write commands in parallel. Rejected: does not prevent races; agents and scripts often parallelize by default.
Atomic write + retry: Write to temp then rename; for work item ID, retry on collision. Rejected: avoids partial writes but does not fix read-modify-write races or deterministic ID collision from find_max_sequence.
ADR-0026: Add journal field to WorkItem for execution tracking
Status: superseded | Date: 2026-02-22 Superseded by: ADR-0047
Tags:
editing
References: RFC-0000
Context
During agent-driven governance workflows, agents naturally use work items as “working memory” to track execution progress. Currently, this working memory is stored in the description field, mixing multiple semantic purposes:
- Task declaration — “What needs to be done” (static scope definition)
- Execution tracking — Progress updates, bug fixes, verification results (dynamic, frequently updated)
- Planning adjustments — Next steps, design decisions (evolves during execution)
This mixing causes description to become very long (4000+ characters in observed cases) and conflates declarative “what” with imperative “how it’s going.”
Example: In WI-2026-02-21-004, the description field contains:
- Initial implementation plan (Steps 1-6)
- Multiple “Progress update (YYYY-MM-DD, scope)” sections with detailed execution notes
- Bug fix records, verification results, and next-step planning
The notes field exists but is underutilized because its original intent (“observations and decisions made during work”) was not clear enough, and agents naturally reached for description as the primary writing surface.
Reference: RFC-0000:C-CONTENT defines the content model but does not distinguish between declaration and tracking semantics.
Decision
Add a new journal field to WorkItemContent as a structured array for execution tracking, distinct from description (task declaration) and notes (ad-hoc points).
TOML structure:
Each journal entry has three fields:
date(required): ISO date string “YYYY-MM-DD”scope(optional): Topic/module identifier for this entrycontent(required): Markdown text with progress details
Example work item with journal:
[content]
description = "Big-bang AST/IR v2 migration with 6 implementation steps..."
[[content.journal]]
date = "2026-02-21"
scope = "typub-html"
content = "v2 parse + serialize paths active; fixed footnote issues"
[[content.journal]]
date = "2026-02-21"
scope = "typub-markdown"
content = "Migrated renderer tests to v2 fixtures; fixed footnote refs"
Data structure (Rust):
pub struct JournalEntry {
pub date: String,
pub scope: Option<String>,
pub content: String,
}
Semantic boundaries:
| Field | Purpose | Update Pattern |
|---|---|---|
description | Task scope declaration | Define once, rarely change |
journal | Execution process tracking | Append on each progress |
notes | Ad-hoc key points | Add anytime, concise |
acceptance_criteria | Completion criteria | Define then tick |
Backward compatibility: The journal field is optional with #[serde(default)]. Existing work items remain valid without migration. New work items can adopt the field incrementally.
Changes required:
- Update
WorkItemContentstruct insrc/model.rs - Update
gov/schema/work.schema.toml - Update render logic in
src/render.rsto include journal section - Update wi-writer skill documentation
Consequences
What becomes easier:
- Clear separation of concerns:
descriptionstays focused on task scope; execution details go tojournal - Better readability: Rendered markdown shows a clean structure with dedicated sections
- Agent ergonomics: Agents have a designated place for execution tracking without polluting description
- Historical traceability: journal entries preserve the execution timeline
What becomes more difficult:
- None significant. The field is optional and additive.
Migration impact:
- No migration required for existing work items
- Agents may gradually adopt
journalfor new or active work items - Old work items with “progress updates” in description remain valid
Documentation updates:
wi-writerskill updated with field usage guidelineswork.schema.tomlupdated with journal field definition- Rendered markdown includes “## Journal” section after description
ADR-0027: Extend Alternative structure with pros, cons, and rejection_reason
Status: accepted | Date: 2026-02-22
Tags:
schema
References: RFC-0000:C-ADR-DEF
Context
The current Alternative structure in ADRs only has two fields: text and status. This is insufficient for capturing structured decision rationale:
-
No pros/cons tracking: When comparing options, the advantages and disadvantages are key decision factors, but they cannot be structured.
-
No rejection reason: When an alternative is rejected, the reason is often scattered in the
decisionorcontextfields instead of being directly attached to the alternative. -
Manual workarounds: Current practice requires authors to write Markdown tables in the
contextfield to compare options, which is not structured and cannot be processed programmatically.
Example of current limitation:
[[content.alternatives]]
text = "Option A: Sequential IDs"
status = "rejected"
# Where do I put the pros/cons? In context as markdown table?
Comparison with other fields:
- WorkItem has structured
acceptance_criteriawith status and category - RFC has structured
changelogwith categorized entries - ADR alternatives should have similar structure for decision tracking.
Decision
Extend the Alternative structure with three new optional fields:
pub struct Alternative {
pub text: String,
pub status: AlternativeStatus,
pub pros: Vec<String>, // NEW: advantages
pub cons: Vec<String>, // NEW: disadvantages
pub rejection_reason: Option<String>, // NEW: why rejected
}
Field semantics:
pros: List of advantages for this alternativecons: List of disadvantages for this alternativerejection_reason: If status isrejected, explains why
Backward compatibility:
All new fields use #[serde(default)] and skip_serializing_if_empty, so existing ADRs remain valid without migration.
Consequences
What becomes easier:
- Structured comparison: Each alternative has its own pros/cons attached
- Clearer rendering: Rendered output can show options with their trade-offs
- Better tooling: CLI can display alternatives in a structured format (e.g., comparison table)
- Self-documenting decisions: The reason for rejection is directly linked to the alternative
What becomes more difficult:
- None significant. The fields are optional and additive.
Migration impact:
- No migration required
- Existing ADRs with simple alternatives continue to work
- New ADRs can opt into the extended structure
Rendering example:
## Alternatives Considered
### Sequential IDs (rejected)
- Pros: Simple, Readable
- Cons: Collisions in teams
- Rejected because: Does not solve the collision problem
### Author hash namespace (accepted)
- Pros: Auto isolation, Zero config
- Cons: Slightly less readable
ADR-0028: Migrate commands to skills format for cross-platform compatibility
Status: accepted | Date: 2026-02-22
Tags:
skills-agents
References: ADR-0024, ADR-0023
Context
The project currently has two mechanisms for AI agent capabilities:
- Commands (
.claude/commands/): Slash commands for workflow orchestration - Skills (
.claude/skills/): Knowledge augmentation for the main agent
Industry trend: Major AI coding platforms are converging on skills as the standard format:
- Claude/Cursor: Skills can be triggered via slash commands (commands and skills are functionally equivalent)
- Codex: Only supports skills, no commands
Current structure:
.claude/commands/
├── discuss.md # Design discussion workflow
├── gov.md # Governed implementation workflow
├── quick.md # Fast path workflow
└── status.md # Governance status (rarely used)
.claude/skills/
├── rfc-writer/
├── adr-writer/
└── wi-writer/
Problem:
- Two similar concepts (commands vs skills) create confusion
- Commands are not portable to Codex
statuscommand has very low usage frequency
Decision
Migrate all workflow commands to skills format:
Migration:
| Source | Target | Action |
|---|---|---|
commands/discuss.md | skills/discuss/SKILL.md | Migrate |
commands/gov.md | skills/gov/SKILL.md | Migrate |
commands/quick.md | skills/quick/SKILL.md | Migrate |
commands/status.md | — | Delete (low usage) |
Format change:
Extend skill frontmatter to include command-specific fields:
---
name: gov
description: "Execute governed workflow — work item, RFC/ADR, implement, test, done"
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
argument-hint: <what-to-do>
---
Why keep current names:
discuss- Clear intent for design discussion phasegov- Established shorthand for governed workflowquick- Clear intent for fast path
Why delete status:
- Very low usage frequency observed
- Equivalent information available via
govctl statusCLI - Reduces maintenance burden
Consequences
Positive:
- Single unified format for all agent capabilities
- Portable across Claude, Cursor, and Codex
- Reduces conceptual overhead (one concept instead of two)
- Eliminates underutilized
statuscommand
Negative:
- One-time migration effort (minimal: 3 files)
- Breaking change for users who reference commands directly
- Need to update any documentation referencing commands/
Migration steps:
- Create skill directories for discuss, gov, quick
- Convert command files to skill format (add
namefield, preserveallowed-tools/argument-hint) - Delete commands/ directory
- Update ADR-0023 to reflect new structure
Future structure:
.claude/skills/
├── discuss/
│ └── SKILL.md
├── gov/
│ └── SKILL.md
├── quick/
│ └── SKILL.md
├── rfc-writer/
│ └── SKILL.md
├── adr-writer/
│ └── SKILL.md
└── wi-writer/
└── SKILL.md
ADR-0029: Path-based nested field addressing for artifact edits
Status: superseded | Date: 2026-02-25 Superseded by: ADR-0037
Tags:
editing
References: RFC-0002, ADR-0007, ADR-0017, ADR-0027
Context
govctl currently edits artifacts with resource-scoped verbs (set, add, remove, tick), matching ADR-0017.
Problem Statement
The current CLI shape becomes verbose and awkward when users need to edit deeply nested fields, especially ADR alternatives extended by ADR-0027 (pros, cons, rejection_reason).
Concrete pain point today:
# Create or replace whole alternative entries
govctl adr add ADR-0001 alternatives "Option 3: Use Raft" --pro "Strong consistency"
# Remove by match or index
govctl adr remove ADR-0001 alternatives "Option 3" --exact
What is missing is direct nested addressing, for example: update only the second pro of the second alternative without rewriting the entire object.
Constraints
- Preserve resource-first command architecture from RFC-0002.
- Preserve verb semantics from ADR-0017 instead of replacing everything with a new universal verb.
- Reuse existing array matching behavior from ADR-0007 where possible.
- Keep backward compatibility for existing scripts and habits.
Decision
We will introduce path-based nested field addressing as an additive capability, while keeping existing resource-scoped verbs (set, add, remove, tick) defined in ADR-0017.
This decision is primarily motivated by ADR-0027, which introduced structured ADR alternatives (pros, cons, rejection_reason) that need precise nested edits.
Path expressions will be accepted where a field name is currently accepted for get, set, add, and remove.
Path Syntax (proposed)
- Grammar (strict):
path := segment ('.' segment | "[" index "]")* - Segment token:
segment := [a-z_][a-z0-9_]* - Index token:
index := -?[0-9]+ - Dot notation for object traversal:
content.alternatives - Bracket notation for array indexing:
alternatives[2].pros[2] - Index semantics: 0-based, with optional negative index for from-end addressing (aligned with ADR-0007
--atsemantics) - Aliases for ergonomics:
alt->alternativespro->proscon->consreason->rejection_reason
Alias Collision Rule
Canonical field names take precedence. Alias expansion applies only when the token is not an exact field name in the current object scope. This keeps future schema evolution safe and predictable.
Verb Semantics
get: existing read verb, now path-aware for scalar/object/array readsset: replace scalar value at resolved pathadd: append into array resolved by pathremove: remove by explicit indexed path, or by existing matcher options when path resolves to an arrayremoveconflict rule: explicit indexed paths and matcher flags (--exact,--regex,--all, pattern args) are mutually exclusive; the CLI MUST fail fast with a usage error when mixed.tick: unchanged behavior; only checklist roots are supported (alternativesfor ADR,acceptance_criteriafor work item). Nested paths fortickare invalid.
Before and After Example
# Before: remove and re-add an entire alternative to change one nested value
govctl adr remove ADR-0001 alternatives "Option 3" --exact
govctl adr add ADR-0001 alternatives "Option 3: Use Raft" --pro "Updated pro"
# After: direct nested edit
govctl adr set ADR-0001 alt[2].pro[0] "Updated pro"
Validation Timing
- Eager validation (parse time): path grammar, token class, alias normalization
- Resolution-time validation: field existence, index bounds, target type compatibility for verb
Compatibility and Convergence
- Existing top-level field syntax remains valid.
- Existing
adr add ... alternatives --pro/--con/--reject-reasonremains supported during migration. - Convergence plan: docs and examples immediately prefer path syntax; legacy alternative-specific flags receive deprecation warnings after rollout stabilizes (target: two minor releases), then are removed only in a major release.
Consequences
Positive
- Enables concise, direct nested edits such as
alt[2].pro[2]without editing raw TOML. - Preserves current mental model (
set/add/remove/tick) and command discoverability. - Reuses existing match semantics from ADR-0007, reducing conceptual fragmentation.
- Creates a reusable abstraction for nested fields across ADRs and work items.
Negative
- Adds parser and resolver complexity in the edit pipeline.
- Mitigation: strict grammar, bounded depth, and dedicated parser tests (including fuzz/property tests).
- Requires broader validation and diagnostics coverage.
- Mitigation: explicit diagnostic matrix for parse/resolution/type errors and snapshot tests for representative failures.
- Dual syntax during migration (
--pro/--conand path syntax) can confuse users.- Mitigation: docs prefer path syntax immediately, deprecation warnings for legacy flags after rollout, and a published convergence timeline.
- Documentation and examples require coordinated updates across guides and help text.
- Mitigation: track doc updates in implementation work items and gate release on docs parity checks.
Neutral
- No data migration is required for existing ADR files; the change is CLI-surface and parser behavior.
- Alias set is intentionally small and closed (
alt,pro,con,reason); future alias additions require explicit schema/governance update to avoid accidental drift.
Alternatives Considered
Option 1: Keep current field-only operations and use manual TOML edits for nested changes (rejected)
- Pros: No new parser or resolver, Lowest immediate implementation risk
- Cons: Poor CLI ergonomics for nested edits, Hard to script precise updates for ADR-0027 nested fields
- Rejected because: Does not address the primary usability gap
Option 2: Add a universal edit verb with JSONPath-like expressions (rejected)
- Pros: Single conceptual mutation entry point, Potentially expressive for advanced operations
- Cons: Conflicts with verb separation rationale in ADR-0017, Higher migration and discoverability cost
- Rejected because: Overlaps existing verbs and weakens current command architecture
Option 3: Keep verbs and add path-based field addressing (accepted)
- Pros: Compatible with existing command model, Directly solves nested edit ergonomics, Supports incremental rollout with low script breakage
- Cons: Introduces parser and resolver complexity, Creates temporary dual-syntax cognitive load during migration
ADR-0030: Parser strategy for path-based field expressions
Status: superseded | Date: 2026-02-25 Superseded by: ADR-0056
Tags:
editing
References: ADR-0029, ADR-0017, ADR-0007, RFC-0002
Context
govctl recently introduced path-based field addressing in ADR-0029 for commands like get/set/add/remove. During implementation review, we identified parser correctness risks in the current hand-written parser flow (for example, extra trailing segments being ignored, and some path-shape rules enforced inconsistently by verb).
Problem Statement
We need a parser design that guarantees strict grammar handling, full-input consumption, and stable diagnostics, while preserving existing CLI compatibility behavior for legacy field forms.
Scope
This ADR focuses on parser architecture for field-path expressions only:
- grammar parsing and AST shape
- parser technology choice
- legacy compatibility policy (
content.*,govctl.*, aliases) - validation layering (parse-time vs verb/resolution-time)
It does not decide broader CLI command architecture, which remains governed by RFC-0002 and ADR-0017.
Constraints
- Maintain resource-first and verb-separated CLI semantics from RFC-0002 and ADR-0017.
- Keep compatibility commitments from ADR-0029 for legacy dotted prefixes and short aliases.
- Preserve deterministic diagnostic behavior (
E0814toE0818) for automation and tests. - Keep parser dependency and complexity proportionate to grammar size.
Decision
We will adopt winnow-based strict parsing with a typed FieldPath AST, replacing the ad-hoc character-walk parser for path expressions.
Technical Selection
winnow is selected because it gives us:
- explicit grammar composition in Rust types
- full-input consumption checks by default pattern (
terminated(parser, eof)) - precise, testable parse failures without introducing a full external DSL/toolchain
- lower operational overhead than a separate grammar generator for this small grammar
Grammar Contract
path := segment (("." segment) | ("[" index "]"))*segment := [a-z_][a-z0-9_]*index := -?[0-9]+
Parsing MUST fail if any trailing tokens remain unconsumed.
Legacy Field Compatibility Policy
Compatibility is preserved as a normalization layer after parse, before resolution:
- canonical field names always win over aliases in the same scope
- supported aliases remain:
ac,alt,desc,pro,con,reason - legacy two-segment prefixes remain:
content.<field>,govctl.<field> - prefix collapse is limited to compatibility-allowed roots and known simple fields; invalid combinations fail with diagnostics
Validation Layering
- Parse-time validation: lexical/grammar correctness, token class, full consumption
- Normalization-time validation: alias/prefix compatibility rules
- Resolution-time validation: existence, index bounds, verb/path shape constraints, type mismatch
Non-Goals
- No expression language expansion (wildcards, slices, recursive descent) in this ADR
- No change to command verbs or lifecycle semantics
Migration Plan
- Introduce
winnowparser behind currentparse_field_pathAPI. - Keep current diagnostics mapping (
E0814/E0815/E0816/E0817/E0818). - Add golden tests for legacy compatibility inputs.
- Add negative tests for over-deep/over-specified paths and verb-shape violations.
- Remove old parser implementation after parity tests pass.
Consequences
Positive
- Eliminates a class of silent-acceptance bugs via full-input consumption.
- Makes grammar behavior explicit and easier to reason about during review.
- Provides a stable foundation for future extensions without reintroducing ad-hoc state logic.
- Improves confidence in diagnostics by separating parse/normalize/resolve phases.
Negative
- Adds a third-party parsing dependency.
- Mitigation: keep dependency surface small and isolate parser module behind a narrow API.
- Introduces a learning curve for maintainers unfamiliar with parser combinators.
- Mitigation: document grammar and parser module invariants with examples and tests.
- Migration requires careful parity testing to avoid compatibility regressions.
- Mitigation: snapshot parity suite for legacy field forms and aliases before rollout.
Neutral
- Runtime cost is expected to be negligible for CLI-scale path strings; this should be verified by micro-benchmarks in CI but is not expected to be user-visible.
Alternatives Considered
Option 1: Keep manual parser and harden it (rejected)
- Pros: No new dependencies, Minimal refactor scope
- Cons: Higher long-term maintenance risk for state-machine edge cases, Harder to prove full-consumption and grammar invariants
- Rejected because: Recent review findings indicate brittle behavior under malformed or over-specified paths
Option 2: Use winnow parser combinators with typed AST (accepted)
- Pros: Strict grammar with full-input consumption, Rust-native and testable composition, Balanced complexity for small grammar
- Cons: Adds dependency and parser-combinator learning curve
Option 3: Use PEG/grammar generator approach (rejected)
- Pros: Clear formal grammar artifacts, Good for larger language evolution
- Cons: Heavier tooling/runtime surface for current grammar size, Additional integration overhead without near-term need
- Rejected because: Overkill for current path grammar scope
ADR-0031: Unified Artifact Edit Engine with SSOT and Format Adapters
Status: accepted | Date: 2026-02-27
Tags:
editing
References: ADR-0029, ADR-0030, ADR-0001, ADR-0017, ADR-0007, RFC-0002
Context
govctl artifact editing has evolved from simple field updates into nested path edits (per ADR-0029) with parser hardening work (per ADR-0030). The current implementation now mixes parser logic, alias/legacy normalization, verb-path validation, dispatch generation, and artifact-specific read/write behavior across large files.
Problem Statement
We currently pay complexity twice:
- We maintain substantial command semantics in hand-written Rust control flow.
- We effectively treat JSON and TOML as separate operational paths in parts of the stack, even though the underlying operation is the same: read structured document, modify addressed node, validate, write.
This increases code volume, review difficulty, and risk of behavioral drift between artifacts and formats.
Before/After (architecture intent)
- Before: parser + routing + validation + handlers are coupled, with format concerns leaking into command logic.
- After: one semantic edit engine (
parse -> canonicalize -> resolve -> plan -> validate -> execute) with thin format adapters.
Constraints
- Preserve resource-first and verb semantics from RFC-0002 and ADR-0017.
- Preserve index and matcher semantics from ADR-0007 (0-based indexing, negative indices from end, existing conflict diagnostics).
- Preserve user-facing path syntax and compatibility promises from ADR-0029 and ADR-0030.
- Respect storage decisions from ADR-0001: ADR/Work artifacts remain TOML at rest unless separately decided.
- Keep deterministic diagnostics and stable error codes for automation scripts.
Decision
We will adopt Option C: a single SSOT-driven semantic edit engine with explicit format adapters.
Core Architecture
- Single semantic pipeline for all artifacts and formats:
parse -> canonicalize -> resolve -> plan -> validate -> execute
- Single SSOT model (
edit-model.json+ JSON Schema) defines:- field tree, indexability, verb capability matrix
- alias/legacy mapping and conflict policy
- validator bindings and handler IDs
- Single execution engine consumes typed
EditPlanoperations. - Thin format adapters implement storage-specific read/write behavior:
JsonAdapterTomlAdapter
Parser Selection
Per ADR-0030, parser implementation will use winnow (not a grammar generator), while grammar remains documented in PEG/EBNF style.
Field-token acceptance is strict:
- parser accepts syntactic segments
- resolver accepts only SSOT-known canonical fields/aliases
- unknown fields fail with deterministic diagnostics
Compatibility and Convergence Policy
- Existing path syntax and legacy forms from ADR-0029 remain supported during migration.
- Canonical names take precedence over aliases on conflict.
- Documentation will prefer canonical path syntax; legacy forms are compatibility-only.
- Legacy form deprecation warnings begin after full V2 parity is reached.
Consequences
Positive
- Reduces long-term maintenance cost by centralizing edit semantics in one engine.
- Eliminates JSON/TOML behavioral drift risk by sharing the same plan/validation pipeline.
- Makes parser and resolver behavior auditable through SSOT and generated tables.
- Improves extensibility: new fields and verbs are primarily SSOT additions.
Negative
- Migration complexity is significant because V1 and V2 must coexist temporarily.
- Mitigation: enforce a bounded coexistence window (max two releases) with explicit phase exit criteria and deletion checklist.
- Generator/SSOT errors can affect many paths at once.
- Mitigation: schema validation at build-time, generated-table snapshot tests, and golden command fixtures per artifact/verb.
- Temporary dual operation styles (legacy vs canonical path forms) can confuse users.
- Mitigation: docs prefer canonical syntax immediately; legacy usage prints guidance warnings after V2 parity milestone.
- Documentation and contributor onboarding work increases initially.
- Mitigation: track docs updates as required migration work items and block V2 cutover completion until docs/tests are updated.
Neutral
- Runtime overhead should remain negligible for CLI-scale paths, but this will be measured with parser and end-to-end micro-benchmarks before finalizing ADR status.
Alternatives Considered
Option A: Continue incremental cleanup on current architecture (rejected)
- Pros: Lowest immediate implementation risk, No major migration event required
- Cons: Continues structural duplication and code growth, Does not solve JSON/TOML semantic divergence risk
- Rejected because: It optimizes short-term churn but leaves the root architecture problem unsolved.
Option B: Standardize internal editing on JSON only (rejected)
- Pros: Maximizes reuse of mature JSON tooling and standards, Simplifies internal document mutation mechanics
- Cons: Introduces conversion boundary risk for TOML-only semantics and formatting expectations, Weakens direct TOML-at-rest operational clarity established by ADR-0001
- Rejected because: It shifts complexity to conversion boundaries and does not provide a first-class TOML contract.
Option C: SSOT-driven semantic engine with explicit JSON/TOML adapters (accepted)
- Pros: Preserves storage-format independence while unifying semantic behavior, Enables SSOT-driven extensibility with lower long-term maintenance cost
- Cons: Requires staged migration and temporary dual-path operation, Demands high-quality generator and parity tests to avoid systemic regressions
ADR-0032: Migration skill for adopting govctl in existing projects
Status: accepted | Date: 2026-03-02
Tags:
migration
References: ADR-0023, ADR-0024, ADR-0028
Context
govctl currently assumes greenfield projects — govctl init creates the governance directory structure from scratch, and all workflows (skills, agents) assume artifacts exist from day zero.
Problem Statement
The majority of real-world projects that would benefit from govctl are existing codebases that lack formal governance. These projects have:
- Undocumented architectural decisions embedded in code, comments, and tribal knowledge
- Existing specifications scattered across markdown docs, wikis, or issue trackers
- In-progress work tracked informally (GitHub Issues, Jira, sticky notes)
- No artifact cross-references in source code
Adopting govctl today requires teams to either:
- Start fresh (losing existing context), or
- Manually create dozens of ADRs, RFCs, and work items — a tedious process that discourages adoption
Requirements
A migration skill should:
- Guide an AI agent through systematically discovering and codifying existing decisions
- Use only existing
govctlCLI commands (no new CLI capabilities needed) - Support incremental migration (not all-or-nothing)
- Produce well-structured artifacts that pass
govctl check - Add
[[...]]references to existing source code where decisions are implemented
Decision
We will create a migrate skill (.claude/skills/migrate/SKILL.md) that guides the agent through a multi-phase migration workflow using existing govctl commands only.
Migration Phases
Phase 0: Scaffold — Initialize govctl in the existing project.
- Run
govctl init(safe alongside existing files) - Read project structure (README, docs, config files) to understand the codebase
Phase 1: Discover — Systematically scan the project for implicit governance artifacts.
- Decisions: Read architecture docs, README sections, config comments, and code patterns to identify undocumented architectural decisions
- Specifications: Find existing specs, API contracts, or design docs that could become RFCs
- Work in progress: Check issue trackers, TODO comments, and branch names for active work
Phase 2: Backfill ADRs — Create ADRs for discovered decisions.
- For each significant decision found, create an ADR using
govctl adr new - Populate context (what prompted the decision), decision (what was chosen), consequences
- Add alternatives where the rejected options are known
- Accept the ADR immediately (
govctl adr accept) since these are historical records
Phase 3: Backfill RFCs (optional) — Create RFCs for existing specifications.
- Only for projects that have existing specification documents
- Create RFC + clauses from existing spec content
- Finalize as normative and advance to stable (these specs are already implemented)
Phase 4: Annotate source — Add [[...]] references to existing code.
- Scan source files for implementations of newly-created ADRs/RFCs
- Insert
// Implements [[ADR-NNNN]]or// Per [[RFC-NNNN:C-NAME]]comments - Run
govctl checkto verify references resolve
Phase 5: Establish baseline — Create work items for any in-progress work.
- Create work items for known active tasks
- Going forward, all new work uses the
/govworkflow
Skill Properties
- Interactive: The skill prompts the user at each phase to confirm discoveries and prioritize what to backfill
- Incremental: Each phase can be run independently; partial migration is valid
- Non-destructive: Never overwrites existing files; only adds governance artifacts alongside existing content
- Idempotent: Running the skill again skips already-created artifacts
Consequences
Positive
- Lowers adoption barrier — Existing projects can adopt govctl without starting from scratch.
- Preserves institutional knowledge — Undocumented decisions get codified as searchable, cross-referenced ADRs.
- Gradual onboarding — Teams can migrate incrementally, one module or decision at a time.
- Agent-native — The skill leverages Claude Code’s ability to read codebases and synthesize decisions, making backfill practical.
Negative
- Quality depends on agent understanding — Auto-discovered decisions may be incomplete or inaccurately described.
- Mitigation: Interactive confirmation at each step; user reviews all generated artifacts.
- Source annotation churn — Adding
[[...]]references to existing code creates a large diff.- Mitigation: Phase 4 is optional and can be done incrementally per-module.
- Historical ADRs may lack alternatives — Old decisions often don’t have documented rejected options.
- Mitigation: The skill accepts “considered” as the only alternative when history is unclear.
Neutral
- No new govctl CLI commands are needed — the skill composes existing commands.
- The skill is bundled with govctl and installed via
govctl sync, like other skills.
Alternatives Considered
Agent-assisted skill using existing govctl commands (accepted)
- Pros: Zero new CLI code needed, Ships immediately as a bundled skill
- Cons: Requires an AI agent to execute the workflow
New govctl migrate CLI command with auto-detection (rejected)
- Pros: Works without AI agent, Deterministic output
- Cons: Significant new CLI code to write and maintain, Auto-detection heuristics are brittle across project types
- Rejected because: The discovery and synthesis tasks are inherently judgment-heavy — an AI agent handles ambiguity better than heuristic code. CLI commands can be added later if common patterns emerge.
ADR-0033: Distribute govctl agent integration as Claude Code plugin
Status: superseded | Date: 2026-03-04 Superseded by: ADR-0061
Tags:
plugin
References: ADR-0015, ADR-0024, ADR-0028
Context
govctl has a mature agent integration layer: 8 skills (gov, quick, discuss, commit, migrate, rfc-writer, adr-writer, wi-writer) and 4 agents (compliance-checker, adr-reviewer, wi-reviewer, rfc-reviewer) in .claude/. This works well for developing govctl itself, but creates a distribution problem for adopters.
Problem Statement
Every project that adopts govctl must manually recreate the agent configuration: copy skills, agents, and CLAUDE.md into their .claude/ directory. govctl init scaffolds a basic CLAUDE.md, but the full skill/agent suite requires manual setup and ongoing maintenance when govctl updates its workflows.
Claude Code’s plugin system (introduced in v1.0.33, documented at https://docs.claude.com/en/plugins) solves exactly this: a standardized package format with skills, agents, hooks, and MCP servers that can be installed once and used across all projects.
Constraints
- ADR-0015 decided against MCP in favor of CLI-based agent discoverability — maintaining two interfaces (CLI + MCP) is a maintenance burden
- ADR-0024 established writers as skills and reviewers as agents — this architecture maps directly to the plugin format
- ADR-0028 migrated commands to skills for cross-platform compatibility — the unified skill format is already plugin-compatible
- The plugin must work with any shell-capable agent, not just Claude Code (graceful degradation)
- Plugin skills are namespaced (e.g.,
/govctl:govinstead of/gov)
Decision
We will package govctl’s agent integration as a Claude Code plugin with enforcement hooks, following the oh-my-claudecode pattern. The .claude/ directory IS the plugin content. The marketplace catalog at the repo root points to it.
Structure
govctl/
├── .claude-plugin/
│ └── marketplace.json ← source: "./.claude"
├── .claude/ ← plugin content (auto-discovered)
│ ├── skills/ ← already exists
│ ├── agents/ ← already exists
│ ├── hooks/
│ │ └── hooks.json
│ ├── scripts/
│ │ ├── post-edit-check.sh
│ │ ├── session-start.sh
│ │ └── pre-stop-check.sh
│ └── settings.local.json ← gitignored, not copied
├── src/
├── gov/
└── Cargo.toml
No plugin.json inside .claude/ — the marketplace entry provides all metadata, and Claude Code auto-discovers skills/, agents/, hooks/ from the plugin directory.
Hook Enforcement
Three hooks provide automatic governance enforcement:
-
PostToolUse (matcher:
Write|Edit): Inspects the edited file path. If undergov/, runsgovctl checkand surfaces validation errors. -
SessionStart: Runs
govctl statusfor context. Checksgovctlbinary availability. -
Stop: Runs
govctl check. Warns about pending failures before session ends.
Distribution
cargo install govctl
/plugin marketplace add govctl-org/govctl
/plugin install govctl@govctl
/govctl:gov "implement feature X"
- Zero duplication:
.claude/is the SSOT for skills, agents, and plugin content - One
.claude-plugin/: marketplace.json at repo root, no nested manifest - Versioning:
just stamp-plugin-versionupdates marketplace.json from Cargo.toml
Consequences
Positive
- Zero duplication:
.claude/is both the local dev config and the plugin content - One-step installation for adopters:
/plugin install govctl@govctl - Automatic governance enforcement via hooks
- No build step, no sync task, no symlinks — just files in
.claude/ - No MCP server complexity — single codebase, single distribution, per ADR-0015
- Plugin format is the Claude Code standard — compatible with marketplace distribution
Negative
- Plugin skills are namespaced (
/govctl:govvs/gov) when installed as plugin (mitigation: only affects plugin users, not in-repo developers) - Hook scripts are shell-only — Windows users need WSL or Git Bash (mitigation: hooks are additive enforcement, not required functionality)
- Binary dependency: plugin requires
govctlinstalled separately (mitigation: SessionStart hook checks and provides install instructions) - Plugin format is Claude Code-specific — non-Claude-Code agents cannot use hooks or plugin metadata (mitigation: skills and agents are plain markdown, usable by any agent)
.claude/directory gains additional files (hooks/, scripts/, .claude-plugin/) that are plugin-specific (mitigation: these are small, clearly organized, and don’t interfere with local dev)
Neutral
govctl initstill works for non-Claude-Code users- Future MCP integration remains possible per ADR-0015 — the plugin format supports
.mcp.json - Developers working on govctl see
.claude/as both their local config and the plugin source — this is a feature, not a bug
Alternatives Considered
Option A — Thin Plugin (skills + agents only, no hooks): Simplest approach, zero new code, but no automatic enforcement. Agent must remember to run govctl check manually. (rejected)
- Pros: Zero new code, No shell scripts to maintain
- Cons: No automatic governance enforcement, Agent must remember validation
- Rejected because: Hooks are the high-leverage differentiator between ‘works with Claude Code’ and ‘great Claude Code plugin’. Without them, the plugin is just a file distribution mechanism.
Option C — Plugin + MCP Server: Full structured integration wrapping govctl CLI as MCP tools. Richest agent experience but doubles the API surface. (rejected)
- Pros: Structured tool interface with typed parameters, Richer error handling
- Cons: Two interfaces to maintain (CLI + MCP), MCP server is a separate process to manage, Significant new code (~1000+ lines)
- Rejected because: Per ADR-0015, maintaining two interfaces is a maintenance nightmare for marginal parsing convenience. The CLI works. Shell-capable agents invoke it fine. The door remains open if demand materializes.
Option D — Separate repository (govctl-plugin): Independent repo with its own release cycle. (rejected)
- Pros: Independent versioning, Smaller repo for plugin contributors
- Cons: Sync between repos is error-prone, Skills and agents drift from main codebase
- Rejected because: The skills and agents ARE the govctl agent layer. Splitting them into a separate repo creates a sync problem that doesn’t need to exist.
Separate plugin/ directory with symlinks or copied files: Duplicates .claude/ content or requires symlinks and build steps. Creates a maintenance burden solving a problem that doesn’t need to exist — .claude/ already IS the plugin structure. (rejected)
- Cons: File duplication or symlink fragility, Requires build/sync step, Extra directory to maintain
- Rejected because: The .claude/ directory already has the exact structure a Claude Code plugin expects (skills/, agents/). Adding a second directory is solving a problem that doesn’t exist.
ADR-0034: Use TOML as the canonical storage format for all governance artifacts
Status: superseded | Date: 2026-03-16 Superseded by: ADR-0056
Tags:
schema
References: ADR-0001, ADR-0014, ADR-0031, ADR-0032, RFC-0000, RFC-0002
Context
govctl currently stores ADRs, work items, and releases as TOML, while RFCs and RFC clauses remain JSON. In this ADR, “governance artifacts” means RFCs, clauses, ADRs, work items, and releases. Project config is out of scope. That split is no longer buying us anything useful.
Problem Statement
The format split leaks into loaders, writers, adapters, schema docs, help text, and migration behavior. ADR-0031 already had to introduce explicit JSON and TOML adapters just to keep one semantic edit engine honest. Keeping RFCs and clauses on JSON forever would preserve that special case in the exact place we are trying to simplify.
We also lack real schema validation for generated TOML artifacts. Today TOML artifacts are parsed structurally and then checked semantically, but they are not validated against machine-readable artifact schemas. That means malformed or drifted TOML can survive longer than it should. Before this change, release data was the worst special case: it lived in gov/releases.toml without a first-class artifact definition in RFC-0000 or an explicitly required JSON Schema contract.
Finally, existing repositories already contain JSON RFC and clause files. If we switch formats without an explicit migration boundary, we either keep dual-format support indefinitely or break existing repositories silently. Both are bad designs.
Constraints
- Preserve the normative meaning of existing governance artifacts and references under RFC-0000 and RFC-0002.
- Keep normal operation simple: after migration, the main load/edit/render paths should be TOML-only.
- Respect ADR-0032 by keeping this migration command narrow and deterministic. This is not a heuristic project-adoption workflow.
- Preserve auditability and deterministic failures for automation and agent workflows.
Decision
We will use TOML as the canonical on-disk source-of-truth format for governance artifacts because it removes a persistent storage-format special case, matches the existing direction of ADR/work/release storage, and gives humans a format they can read and edit without carrying JSON-only baggage forward.
- One storage format: RFCs, clauses, ADRs, work items, and releases will all be stored as TOML at rest.
- One normal code path: After explicit repository migration, steady-state govctl operations will treat TOML as the only supported artifact storage format.
- One compatibility boundary: Legacy JSON support and deterministic TOML shape upgrades will exist only inside a migration command that converts existing JSON RFC and clause files to TOML and applies govctl-managed structural upgrades such as release-file metadata normalization.
- One validation model: RFC, clause, ADR, work item, and release artifacts will each have a corresponding machine-readable JSON Schema, and generated or edited TOML will be validated against that schema after parsing and normalization.
This decision supersedes the storage split recorded in ADR-0001.
Consequences
Positive
- Removes the last major on-disk format split in governance artifacts.
- Makes storage expectations easier to explain: governance artifacts are TOML, rendered docs are projections.
- Creates a clean place to contain legacy JSON support instead of spreading it across the whole codebase.
- Enables real schema validation for all TOML governance artifacts, including releases, using one existing validation technology (
jsonschema) after TOML parsing.
Negative
- Existing repositories with JSON RFCs and clauses will require an explicit migration step before normal TOML-only operation. (mitigation: normal commands should emit a dedicated
govctl migratediagnostic instead of attempting mixed-format behavior.) - RFC and clause path conventions will change from
.jsonto.toml, so docs, tests, and direct file-path tooling must be updated carefully. (mitigation:govctl migraterewrites govctl-managed clause-path references, but user-maintained references remain explicit follow-up work.) gov/releases.tomlwill need a small structural migration to add explicit metadata for schema validation. (mitigation: keep the release-entry payload shape stable and migrate the file automatically with deterministic rewrite rules.)- External scripts, CI glue, and older govctl versions that assume
.jsonRFC paths will break after migration. (mitigation: this is an intentional compatibility drop that must be documented plainly in release notes and migration docs.) - A broad format migration touches foundational governance definitions, so review and rollout discipline matter. (mitigation: require draft review plus full
govctl checkvalidation before rollout.)
Neutral
- This does not replace the broader project-adoption migration workflow in ADR-0032; it only adds a deterministic repository-format migration boundary.
- The semantic meaning of RFCs, clauses, ADRs, and work items does not change. Only their canonical storage format and validation contract change.
Alternatives Considered
Keep mixed JSON/TOML storage with format adapters (rejected)
- Pros: Lowest immediate disruption to existing RFC storage, Avoids a repo-wide format migration in the short term
- Cons: Preserves storage-format branching in loaders, writers, docs, and tests, Keeps JSON/TOML drift as a permanent maintenance cost
- Rejected because: This keeps the special case alive instead of deleting it.
Standardize all governance artifacts on JSON (rejected)
- Pros: Would reuse the existing RFC and clause storage model, Could lean on mature JSON tooling and schemas
- Cons: Moves ADRs, work items, and releases away from the format already chosen for human editing, Fights the existing TOML direction established across most governance artifacts
- Rejected because: It optimizes around legacy RFC storage instead of the current human-facing workflow.
Standardize all governance artifacts on TOML with explicit migration (accepted)
- Pros: Eliminates the on-disk format split in normal operation, Keeps compatibility code confined to a single migration boundary
- Cons: Requires a carefully specified migration command, Creates one-time churn in paths, docs, and tests
ADR-0035: Decouple skill and agent installation from project initialization
Status: accepted | Date: 2026-03-17
Tags:
skills-agents
References: RFC-0002, ADR-0033, ADR-0028
Context
govctl init currently bundles three concerns into one command: governance directory scaffolding (gov/), JSON Schema deployment, and agent asset installation (skills + agents to .claude/). ADR-0033 introduced plugin distribution, giving users a second path to receive skills and agents — globally, via the Claude Code plugin system.
Problem Statement
- Redundant local copies for plugin users. Users who install govctl as a Claude Code plugin receive skills and agents globally.
govctl initalso writes them locally, creating two copies with unclear authority. - Missing schemas for old projects. Projects initialized with earlier govctl versions lack
gov/schema/*.jsonfiles. The#:schemarelative-path comments in TOML artifacts resolve to nonexistent files, breaking IDE validation. Neithergovctl syncnorgovctl migratefills this gap. - Unclear
syncnaming.govctl synconly syncs agent assets (skills + agents), but the name implies general synchronization.
Constraints
- RFC-0002:C-GLOBAL-COMMANDS specifies
initwith “optionally creates.claude/commands/” — the skill dump was always optional. - RFC-0002:C-GLOBAL-COMMANDS requires new global commands to be added via RFC amendment and meet at least one criterion (multi-resource, project-level init/cleanup, or meta-information).
govctl syncis not specified in RFC-0002 — it exists only as an implementation convenience.
Decision
We will separate the three concerns as follows:
-
govctl initcreates governance structure (gov/directories,config.toml, JSON Schemas). It no longer installs skills or agents. After completion, it prints a hint aboutgovctl init-skillsand plugin installation. -
govctl init-skills(replacesgovctl sync) explicitly installs skills and agents into the configuredagent_dir. This is the opt-in command for users who do not use the plugin. Supports-fto overwrite existing files. -
govctl migrateensures all bundled JSON Schema files exist ingov/schema/, always overwriting with the latest version. This fills the gap for projects initialized with older govctl versions.
Implementation Notes
initremoves the skill/agent writing loop and the hardcoded.claudepath.init-skillsreuses the existingsync_commands()implementation unchanged.migrateadds a schema-sync step that runs unconditionally (not gated by schema version), writing allARTIFACT_SCHEMA_TEMPLATESentries toconfig.schema_dir().- RFC-0002:C-GLOBAL-COMMANDS is amended to add
init-skillsand update theinitandmigratedescriptions.
Consequences
Positive
- Plugin users no longer get redundant local skill/agent copies from
init - Old projects get working
#:schemacomments after runninggovctl migrate - Command names are self-documenting:
init= governance,init-skills= agent assets - The hardcoded
.claudepath ininitis eliminated;init-skillsuses the configuredagent_dir
Negative
- Users who had
govctl initin onboarding docs will find.claude/empty after upgrading (mitigation:initprints a hint, and the changelog documents the change) - Two commands instead of one for full setup (mitigation: plugin users need zero commands for agent assets; CLI-only users run
inittheninit-skills)
Neutral
govctl syncis removed as a command name;init-skillsreplaces it- Schema files are now overwritten on every
migraterun, even if unchanged — this is safe since they are generated artifacts
Alternatives Considered
Keep init bundled: init continues to dump skills/agents alongside governance structure (rejected)
- Cons: Redundant for plugin users, Hardcoded .claude path ignores agent_dir config
- Rejected because: Plugin distribution per ADR-0033 makes unconditional local dumping obsolete
Add –skills flag to init instead of separate command: govctl init –skills dumps agent assets (rejected)
- Cons: Discovery problem: users must know the flag exists, Couples governance init with agent concerns
- Rejected because: Separate command is more discoverable and aligns with single-responsibility
ADR-0036: Restructure ADR chosen-option and migration semantics
Status: superseded | Date: 2026-04-06 Superseded by: ADR-0038
Tags:
editing
References: ADR-0034, ADR-0031, ADR-0027, ADR-0032
Context
The current ADR model stores the chosen option as an accepted entry inside content.alternatives[]. That shape creates two related problems:
- It duplicates the decision itself. The chosen path is already described in
decision, but tooling also expects anacceptedalternative. - It leaks checklist-style status semantics into decision options.
govctl adr tickacceptsdone|pending|cancelled, which are internally mapped toaccepted|considered|rejectedfor alternatives. This is implementation-centric rather than domain-centric and confuses both users and bundled skill examples. - It makes migration and rendering harder. Historical ADRs may have incomplete alternative metadata, yet the current model has no explicit place to record migration gaps while keeping the artifact renderable.
We need a cleaner ADR model that:
- makes the chosen option explicit without duplicating it as an alternative,
- keeps alternatives focused on non-selected options,
- structures consequences so mitigations attach to negative outcomes,
- allows migration to produce schema-valid, renderable ADRs even when some historical intent cannot be fully recovered.
Decision
We will redesign ADR storage around four principles:
- Chosen option is first-class. ADR content gains an explicit
selected_optionfield. The chosen path is no longer represented as anacceptedalternative. - Alternatives only model non-selected options.
content.alternatives[]remains for options that were not chosen. Each alternative may keeppros,cons, andrejection_reason, but no longer carries astatusfield. - Consequences become structured.
content.consequencesbecomes a structured object withpositive,neutral, andnegativeentries. Negative consequences may includemitigations. - Migration state is explicit metadata.
govctl.migrationrecords whether an ADR needs post-migration review and carries warning entries describing unresolved historical gaps.
Migration semantics
- Legacy
acceptedalternatives migrate intoselected_optionand are removed fromalternatives. - Legacy
rejectedalternatives remain alternatives. - Legacy
consideredalternatives in accepted or superseded ADRs are migrated into alternatives with synthesized rejection rationale and a migration warning. - If migration cannot determine the chosen option, the migrated ADR remains renderable and schema-valid, but
govctl.migration.state = "needs_review"andgovctl checkemits warnings until a human resolves it.
CLI semantics
govctl adr tick ... alternatives ... no longer participates in ADR option state. ADR editing uses direct field paths such as selected_option and alternatives[0].rejection_reason. tick remains checklist-oriented and continues to apply to work item acceptance criteria.
Recovered Selected-Option Advantages
- Eliminates accepted-alternative duplication
- Keeps unresolved migrations renderable
Consequences
Positive
- The chosen option becomes explicit and no longer needs to be duplicated as an accepted alternative.
- ADR CLI and skills can use domain language directly instead of checklist-style status remapping.
- Migration gains a principled place to record unresolved historical gaps without breaking rendering.
- Negative outcomes and mitigations become attachable data rather than prose hidden inside a markdown block.
Negative
- This is a breaking schema change for ADR files, renderer output, and edit semantics.
- Existing ADRs require a versioned migration and some will still need manual follow-up.
- Bundled skills, reviewer guidance, and examples all need coordinated updates.
- Requires a schema migration.
Neutral
decisionremains a prose field; the redesign adds structure around it rather than replacing it with a fully object-shaped decision document.- The migration pipeline becomes responsible for one more schema step.
Alternatives Considered
Keep alternative status as considered/accepted/rejected (rejected)
- Pros: Minimal data-model churn
- Cons: Preserves confusing tick-to-status mapping, Continues duplicating the chosen option inside alternatives
- Rejected because: Keeps the same semantic collision between checklist state and decision state.
Use a fully object-shaped decision document instead of keeping decision prose (rejected)
- Pros: Captures rationale in more machine-readable form
- Cons: Much larger writer, renderer, and documentation rewrite, Makes the redesign harder to adopt in one migration step
- Rejected because: The immediate problem is chosen-option and migration semantics, not replacing ADR narrative writing with a new decision DSL.
Explicit selected_option field, structured consequences, and migration metadata (accepted)
- Pros: Makes the chosen option explicit rather than implicit in prose and option status., Provides a dedicated place for migration-only review state.
- Cons: Introduces a breaking schema change for ADRs., Requires coordinated migration and ecosystem updates.
ADR-0037: Canonical edit surface for nested artifact mutation
Status: superseded | Date: 2026-04-06 Superseded by: ADR-0056
Tags:
editing
References: ADR-0031, ADR-0029, ADR-0017, ADR-0030, ADR-0007, RFC-0002
Context
govctl currently exposes artifact mutation through resource-first verbs such as set, add, remove, and tick, with path-based field addressing layered in via ADR-0029 and strict parsing via ADR-0030. The semantic engine behind those commands is being unified per ADR-0031.
Problem Statement
The current CLI surface is still too shape-dependent for reliable agent use:
- Whether an operation uses
set,add,remove, ortickdepends on the target field’s storage shape rather than the user’s intent alone. - Nested editing support is asymmetric. Some paths behave like true field paths, while others still rely on special-case command semantics.
- The CLI surface leaks artifact-specific implementation details, which increases agent failure rates and makes help text harder to generalize.
- Upcoming schema work, including richer ADR structures, will increase nested object/array combinations and amplify the problem if the edit surface remains verb-fragmented.
Constraints
- Preserve resource-first command organization from RFC-0002.
- Preserve the SSOT-driven engine direction from ADR-0031.
- Keep a stable migration path for existing human users and scripts.
- Make the canonical mutation interface regular enough that agents can synthesize commands from field paths without artifact-specific guessing.
- Avoid introducing a new batch-specific input language unless single-operation ergonomics prove insufficient.
Decision
We will introduce a canonical path-oriented edit surface for governed artifact mutation:
govctl <resource> edit <ID> <path> --set <value>
govctl <resource> edit <ID> <path> --add <value>
govctl <resource> edit <ID> <path> --remove <pattern>
govctl <resource> edit <ID> <path> --tick <status>
where:
<path>is a canonical fully qualified field path- exactly one mutation flag is provided per invocation
- existing resource-first verbs (
set,add,remove,tick) remain available as human-friendly sugar that compile into the same semantic edit plan
Canonical Interface Rules
- Canonical path syntax is fully regular. It MUST support nested object and array traversal for arbitrary depth, subject to SSOT validation.
- Canonical paths prefer explicit field names. Aliases remain compatibility-only, but documentation and agent examples prefer full canonical paths.
editis the authoritative mutation interface. New nested-field capabilities are specified first againstedit; shorthand verbs are layered on top.tickremains checklist-oriented. It stays available only where the schema marks a status-bearing checklist item. It is not the canonical mechanism for arbitrary state mutation.- Path semantics are SSOT-defined. The engine resolves paths and operation legality from generated schema/rules, not from artifact-specific handwritten branching.
- This ADR standardizes single-operation editing only. Multi-step orchestration remains the responsibility of the calling agent or shell layer for now.
Compatibility Strategy
- Existing commands such as
govctl adr set ...,govctl adr add ..., andgovctl work tick ...remain supported during migration. - Help text, docs, and agent-facing examples will progressively move to the canonical
editform. - Compatibility verbs are treated as sugar over the same
EditPlan, not as separate semantic implementations. - No new YAML/JSON patch language is introduced in this phase.
Examples
govctl adr edit ADR-0001 content.decision --set "We will ..."
govctl adr edit ADR-0001 content.alternatives --add "Option A"
govctl adr edit ADR-0001 content.alternatives[0].pros --add "Readable"
govctl work edit WI-YYYY-MM-DD-NNN content.acceptance_criteria[0] --tick done
This keeps resource-first organization intact while giving both humans and agents a single canonical grammar for mutation.
Recovered Selected-Option Advantages
- Gives humans and agents one stable canonical mutation grammar
- Lets existing verbs converge onto the same EditPlan without immediate breakage
- Keeps the target path visually primary when reading or typing commands
Consequences
Positive
- Agents can synthesize mutation commands from one regular shape instead of guessing between multiple top-level verbs.
- The CLI surface aligns with the SSOT edit engine in ADR-0031, reducing semantic drift.
- Nested object/array edits can be documented once and reused across ADRs, RFCs, work items, and future artifact types.
- Existing human-friendly verbs can remain as convenience entrypoints without blocking engine regularization.
- The design does not add a separate patch document format, so the CLI remains focused on a single mutation grammar.
Negative
- The CLI surface grows: users must understand that
editis canonical even if shorthand verbs still exist. - Help text, docs, examples, and tests require a coordinated rewrite.
- Compatibility layering adds temporary maintenance cost until sugar commands fully delegate to the canonical path.
- Multi-step batch edits are not made atomic by this ADR; callers still need orchestration logic when applying a series of mutations.
- Requires dual-surface docs during migration.
Neutral
- Resource-first organization is unchanged; only the mutation entrypoint is normalized.
- This ADR does not itself redesign artifact schemas such as ADR consequences or alternatives. It defines the edit surface that future schema work can rely on.
- If transactional batch mutation becomes necessary later, it can be addressed in a separate ADR with clearer evidence of need.
Alternatives Considered
Keep set/add/remove/tick as the only mutation interface and continue expanding path support (rejected)
- Pros: Lowest immediate CLI churn, Keeps current verb-first UX intact
- Cons: Agents still need field-shape-specific verb selection, Does not establish a single canonical mutation grammar
- Rejected because: It fixes capability gaps incrementally but leaves the core ergonomics problem unresolved for automation.
Replace current verbs with a JSONPatch-like or DSL-heavy universal mutation language (rejected)
- Pros: Maximum expressiveness in one command family
- Cons: Higher cognitive load for humans, Too large a break from current resource-first mutation ergonomics
- Rejected because: Over-corrects toward a mini language and sacrifices discoverability for power we do not currently need.
Add a canonical edit command with path-first operation flags, while preserving current verbs as sugar (accepted)
- Pros: Establishes one canonical mutation grammar without breaking existing workflows., Keeps nested mutation semantics centered on field paths instead of ad hoc verb choice.
- Cons: Expands the CLI surface during the transition period., Requires documentation and help text to teach the canonical form clearly.
ADR-0038: Keep ADR schema discussion-oriented and avoid broad migration
Status: accepted | Date: 2026-04-06
Tags:
schema
References: ADR-0027, ADR-0036, ADR-0037
Context
We have two goals that now need to be balanced more carefully.
Problem Statement
- The canonical edit surface from ADR-0037 is valuable and should remain.
- The broader ADR schema redesign from ADR-0036 proved too heavy for the value it provides.
- In practice, ADR authoring works best when alternatives are written first, discussed, and then one option is marked as selected before the final decision prose is written.
- The
selected_optionplus structured-consequences redesign pushed the model toward a final-state representation and away from the natural discussion flow. - The migration burden is not justified while this work is still on a PR branch and has not landed on the main branch.
Constraints
- Preserve the canonical edit-surface work already captured in ADR-0037.
- Preserve the discussion-oriented alternative model from ADR-0027.
- Avoid a repository-wide ADR migration for a change that is not yet merged.
- Keep the ADR schema simple enough that humans and agents can both use it reliably.
Decision
We will keep the current ADR schema discussion-oriented and avoid the broad schema/migration redesign from ADR-0036 because:
- Authoring flow matters more than final-shape normalization. ADRs are written by exploring alternatives first and only then recording the final decision. The current alternatives-with-status model supports that flow directly.
- The migration cost is disproportionate. A schema and repository-wide migration is not justified for a redesign that has not landed on the main branch.
- The canonical edit surface already solves the more valuable problem. ADR-0037 gives us the regular mutation interface we wanted without requiring the ADR artifact itself to become deeply restructured.
- Future ADR refinement can still happen incrementally. If we later need a machine-readable chosen-option field or richer consequence structure, that should be justified by a narrower problem and designed without coupling it to a broad migration.
Implementation Notes
- Keep
content.consequencesas prose markdown. - Keep
content.alternatives[]withstatus = considered|rejected|accepted. - Continue to model the selected option by marking one alternative as
acceptedand then writing the final decision prose. - Do not introduce
selected_option, structured consequences, or migration-specific ADR metadata in this line of work.
Consequences
Positive
- Preserves the natural ADR writing flow: alternatives first, decision last.
- Avoids a repository-wide ADR migration for a redesign that has not merged.
- Keeps canonical edit-surface gains from ADR-0037 without tying them to a broader artifact rewrite.
- Keeps ADR authoring understandable for humans and agents using today’s schema.
Negative
- The chosen option remains represented partly by alternative status and partly by decision prose.
- ADR tooling will have less machine-readable structure than ADR-0036 proposed.
- Some future refinement pressure is deferred rather than eliminated. (mitigation: revisit only when a narrower, clearly justified problem emerges.)
Neutral
- This decision supersedes the schema-and-migration redesign from ADR-0036 but does not change the canonical edit-surface direction from ADR-0037.
- Existing ADR files remain valid without conversion.
Alternatives Considered
Keep ADR-0036 full redesign with selected_option, structured consequences, and migration metadata (rejected)
- Pros: Makes the chosen option explicit, Provides more machine-readable structure
- Cons: Encourages premature final-state authoring, Requires schema and repository migration
- Rejected because: The migration and authoring costs are too high for a change that has not landed on the main branch.
Keep the current ADR schema and reinforce the alternatives-first workflow (accepted)
- Pros: Matches the natural authoring flow of ADR discussion, Avoids repository-wide migration, Works with the canonical edit surface from ADR-0037
- Cons: Keeps chosen-option state partly in alternative status and partly in decision prose
Add only a lightweight selected_option field and leave other ADR fields unchanged (rejected)
- Pros: Gives tooling a direct chosen-option field
- Cons: Still encourages agents to write the conclusion too early, Adds schema surface without solving the broader authoring-flow issue
- Rejected because: It keeps the premature-conclusion problem while still introducing schema churn.
ADR-0039: Use SQLite FTS5 as read-only search index for governance artifacts
Status: accepted | Date: 2026-04-09
Tags:
cli
References: RFC-0002, RFC-0004, ADR-0048
Context
govctl manages governance artifacts (RFCs, ADRs, clauses, work items, guards) as TOML files in gov/. As the corpus grows (currently 200+ artifacts, projected to reach 1000+ in active projects), finding artifacts by content becomes increasingly difficult.
Problem Statement
Users need to answer questions like “which ADR discussed caching?”, “which RFC clause mentions backward compatibility?”, or “which work items reference RFC-0002?”. Currently this requires:
grepover raw TOML files (poor UX, no ranking, no stemming)govctl list+ manual inspection (only searches titles)- Memorizing artifact IDs
None of these scale or provide relevance-ranked results.
Constraints
- RFC-0002 establishes TOML files as the source of truth — any index must be derived, not authoritative
- RFC-0004 governs concurrent write safety — the index must not interfere with the file locking protocol
- The index must work offline with no external services
- Rebuild must be fast enough to run transparently on every search query
Decision
Use SQLite FTS5 with lazy incremental sync as the search backend for govctl search, stored as derived local state under .govctl/index.db.
Design
-
Index location:
.govctl/index.db, with SQLite sidecars such as.govctl/index.db-waland.govctl/index.db-shmwhen WAL mode is active. The database is disposable local state and is covered by the existing.govctl/gitignore invariant. -
Catalog separation: The database may contain shared artifact catalog tables for ID-to-path lookup and freshness metadata per ADR-0048. Those catalog tables are shared lookup infrastructure. Search-specific FTS tables, ranking data, and snippets remain derived search data.
-
Indexed content: RFCs, clauses, ADRs, work items, and guards. Each search document stores artifact ID, type, title, source path, stable status metadata where applicable, tags, refs, and a curated concatenation of searchable content fields. Work item descriptions, acceptance criteria, and notes are searchable; legacy inline journal entries remain render-only compatibility data and are not indexed. Raw TOML is not the search document.
-
Sync strategy — lazy incremental: On every
govctl search, compare current artifact path and freshness metadata against the local index manifest. New or changed files are parsed and upserted into the search projection. Deleted files are removed. Missing, corrupt, or incompatible index state is rebuilt. -
Freshness rule:
govctl searchmust not return results from an index whose freshness cannot be established. If freshness cannot be established, it must rebuild, fall back to an uncached scan where possible, or return a diagnostic instead of silently returning stale results. -
No write-through optimization: Artifact write commands do not need to update the search FTS tables directly. Lazy sync remains correct for manual edits, branch switches, and govctl writes.
-
Concurrency: SQLite WAL mode and transactions protect the local index from corruption during concurrent search invocations. The search index is not a governed artifact and does not participate in the RFC-0004 gov-root write lock.
-
Explicit escape hatch:
govctl search --reindexforces a full rebuild before querying.
Why This Design
.govctl/is the existing local-state boundary for loop execution and other derived state.- Keeping the index out of
gov/avoids treating disposable search data as a governed artifact mutation. - Lazy sync avoids coupling between artifact write paths and search indexing.
- SQLite FTS5 provides BM25 ranking and snippets without a daemon or external service.
Consequences
Positive
- Users can find artifacts by content with relevance ranking instead of relying on raw grep, title-only lists, or memorized IDs.
- The index is disposable and self-healing: deleting
.govctl/index.dbonly removes local cache state, and the next search can rebuild it. - Lazy sync keeps search correct across manual edits, branch switches, and govctl writes without coupling every artifact mutation to the search backend.
- Using
.govctl/keeps derived search data out of governed artifacts and rendered outputs. - Shared catalog metadata from ADR-0048 lets search avoid duplicating path and freshness discovery logic.
Negative
- Adds
rusqlitewith bundled SQLite, increasing binary size and build complexity. - First search after a large branch switch or cache deletion may be slower while the local index rebuilds.
- CJK text may require tokenizer improvements beyond the default English-oriented stemming setup.
- Search must guard freshness carefully; returning stale results would be worse than a slower rebuild or diagnostic.
Neutral
- The local SQLite database is a cache, not a new artifact storage format. TOML files remain the source of truth.
Alternatives Considered
SQLite FTS5 with lazy incremental sync: single-file read-only index using rusqlite (bundled), Porter stemming, BM25 ranking, and content-hash-based incremental updates on each search query. (accepted)
- Pros: Battle-tested BM25 ranking out of the box, Single-file index, no daemon or external service, Porter stemming handles English morphology (cache/caching/cached), rusqlite is mature with bundled compilation — no system SQLite dependency, Lazy sync means no separate build step or cache invalidation protocol
- Cons: Adds ~3MB to binary size from bundled SQLite, CJK segmentation requires additional tokenizer configuration
Tantivy (Rust-native full-text search): Use the tantivy crate, a Lucene-inspired search engine written in Rust. Supports BM25, tokenizers, and schema-defined fields natively. (rejected)
- Pros: Pure Rust, no C dependency, More powerful query language (boolean, phrase, fuzzy), Purpose-built for search — better performance at scale
- Cons: Much heavier dependency (~50 crates in dependency tree), Index is a directory of segment files, not a single file, Overkill for <1000 documents
- Rejected because: Dependency weight and complexity are disproportionate to the scale of govctl’s artifact corpus. SQLite FTS5 covers the requirements with a single well-understood dependency.
In-memory inverted index with no persistence: Build a simple inverted index on every search invocation by scanning all TOML files, tokenizing content, and ranking by term frequency. No disk cache. (rejected)
- Pros: Zero dependencies — no SQLite, no new crates, No cache invalidation problem — always fresh
- Cons: Full rebuild on every query (~100ms at 200 files, grows linearly), No stemming or advanced tokenization without additional code, No BM25 — would need a custom ranking implementation
- Rejected because: Lacks stemming and BM25 ranking out of the box. Rebuild cost scales linearly and becomes noticeable beyond 500 artifacts. The UX gap versus FTS5 is significant for the marginal dependency savings.
ADR-0040: Controlled-vocabulary tags for governance artifacts
Status: accepted | Date: 2026-04-09
Tags:
schema
References: RFC-0002, ADR-0039
Context
As the govctl artifact corpus grows (currently 200+ artifacts), finding related artifacts by domain becomes difficult. Users resort to grep or memorizing IDs.
Problem Statement
There is no structured way to answer “show me everything related to caching” or “which ADRs touch the parser”. Artifact titles provide some signal, but titles are inconsistent and not designed for cross-cutting categorization.
Constraints
- RFC-0002:C-RESOURCES defines the field surface for each artifact type — adding
tagsrequires a schema amendment - RFC-0002:C-CRUD-VERBS governs how fields are mutated — tags must follow existing
add/removeverb semantics - Tags must be diffable and reviewable in PRs (no hidden state)
- The system should prevent tag sprawl — typos and near-duplicates degrade signal
Decision
We will use a controlled-vocabulary tag system where tags must be registered in a project-level allowed list before any artifact can reference them.
Why Controlled Vocabulary
The core trade-off is between friction and signal quality. Free-form tags have zero friction but degrade rapidly — typos, case variants, and synonyms fragment the taxonomy. In a governed workflow where artifacts are meant to be auditable and cross-referenced, unreliable metadata defeats the purpose.
A controlled vocabulary enforces consistency at the cost of a one-time registration step for each new tag. This cost is intentional: introducing a new domain category is a project-level decision that should be visible and reviewable.
Design Outline
- Registry: a
[tags] allowedlist ingov/config.toml— flat, lowercase kebab-case strings - Artifact field: an optional
tagsarray in the[govctl]section of RFCs, clauses, ADRs, work items, and guards (releases do not carry tags) - Management: registry-level
new/delete/listcommands; artifact-level tagging via existingadd/removeverbs - Filtering:
--tagflag on existinglistcommands for taggable resource types - Validation:
govctl checkrejects tags not in the allowed set;addrejects unregistered tags immediately
Detailed command syntax, schema changes, and validation rules will be specified in an RFC-0002 amendment.
Constraints
- No maximum tag count per artifact — signal quality is maintained by the controlled vocabulary, not by limiting labels
- The initial seed list of allowed tags is a separate operational decision from the mechanism itself
- Tags complement but do not replace potential future full-text search (see ADR-0039)
Consequences
Positive
- Cross-cutting discovery becomes a first-class operation — “show me everything about caching” is a single command
- Controlled vocabulary prevents tag sprawl — consistency is enforced, not hoped for
- Tags are part of the TOML source — diffable, reviewable in PRs, greppable
- Agents can enumerate available tags and use them programmatically
- Extends existing
add/remove/listverb model — minimal new CLI grammar
Negative
- Friction to introduce a new tag — requires a config edit before first use (mitigation: this friction is intentional and the operation is a one-liner)
- Retroactive tagging of existing artifacts requires effort (mitigation: incremental adoption — untagged artifacts simply don’t appear in filtered queries)
- Schema change across all five taggable artifact types (mitigation:
tagsis optional with empty-array default — existing artifacts remain valid without modification)
Neutral
govctl tagbecomes a new top-level command namespace for registry management- The tag vocabulary will need periodic curation as the project evolves — orphaned or overly broad tags should be pruned
- Tags complement but do not replace full-text search; ADR-0039 remains a viable future option if content-level discovery is needed
- An RFC-0002 amendment is a prerequisite before implementation — this ADR authorizes the design direction but not the schema change
Alternatives Considered
Controlled vocabulary: tags registered in gov/config.toml before use, enforced by govctl check. Lowercase kebab-case, flat list. (accepted)
- Pros: Prevents tag sprawl — typos and near-duplicates are caught at check time, Registry is diffable and reviewable in PRs, Tag list is enumerable — agents and CLI completion can offer suggestions, Removing a tag from the registry is an explicit, auditable decision
- Cons: Friction to add a new tag — requires a config edit before first use
Free-form tags: any string can be used as a tag on any artifact. No registry. Tags are created implicitly on first use. (rejected)
- Pros: Zero friction — tag immediately without config changes
- Cons: Tag sprawl is inevitable — cache vs caching vs Cache are all different tags, No way to enforce consistency across contributors, Removing a stale tag requires finding and editing every artifact that uses it
- Rejected because: In a governed workflow, uncontrolled metadata defeats the purpose of structured artifacts. Tag sprawl would quickly make filtering unreliable.
No tags — improve search and filtering instead: rely on title grep, rendered markdown search tools (rg, qmd), or future FTS (ADR-0039) to find artifacts by content rather than adding structured metadata. (rejected)
- Pros: Zero schema changes — no new fields, no config section, no validation rules, No tagging discipline burden on authors
- Cons: Finding all artifacts related to a topic requires remembering the right search terms, No enumerable taxonomy — agents cannot discover what categories exist, Cross-cutting queries remain ad hoc and fragile
- Rejected because: Search finds text matches, not intentional categorization. Tags express author intent about which domain an artifact belongs to — a dimension that free-text search cannot reliably recover.
ADR-0041: Self-update and cargo-binstall binary distribution
Status: superseded | Date: 2026-04-13 Superseded by: ADR-0060
Tags:
release
References: RFC-0002, ADR-0018, ADR-0033
Context
govctl is distributed via cargo install govctl and as prebuilt binaries on GitHub Releases. The release CI (.github/workflows/release.yml) already produces binaries for five platform targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, and x86_64-pc-windows-msvc.
Problem Statement
Two gaps exist in the binary distribution story:
-
No in-place update. Users must remember to re-run
cargo install govctlor manually download from GitHub Releases to get a new version. There is no built-in way to check for or apply updates. -
No
cargo binstallsupport.cargo-binstallcan install prebuilt binaries from GitHub Releases without compiling from source, but requires[package.metadata.binstall]inCargo.tomlto locate the correct asset. Without this metadata,cargo binstall govctlfalls back to a full source build.
Constraints
- RFC-0002:C-GLOBAL-COMMANDS requires new global commands to meet at least one criterion: (1) multi-resource, (2) project-level init/cleanup, or (3) meta-information about the CLI itself. A self-update command qualifies under criterion 3.
- ADR-0018 established “one canonical way” — the update mechanism should be singular.
- Release assets use the naming convention
govctl-v{version}-{target}.{ext}(tar.gz for Unix, zip for Windows). - The project already depends on
reqwestfor HTTP (via other crates), so adding network capability is not a new dependency class.
Decision
We will use the self_update crate for a built-in govctl self-update command and add [package.metadata.binstall] to Cargo.toml for cargo-binstall support, because:
-
Existing infrastructure fits perfectly. The release CI already produces platform binaries with naming that
self_updateexpects (govctl-v{version}-{target}.{ext}). No CI changes needed. -
Minimal effort, maximum coverage. The
self_updatecrate handles the hard parts (API queries, platform detection, archive extraction, binary replacement) in ~20 lines.cargo-binstallmetadata is a 4-line addition toCargo.toml. -
Two complementary install paths, one asset layout. Users who installed via
cargo binstallcan update viacargo binstall govctl. Users who installed via direct download orgovctl self-updatecan update in place. Both paths consume the same GitHub Release assets.
Consequences
Positive
- Users can update govctl with a single command (
govctl self-update) regardless of how it was originally installed cargo binstall govctlinstalls prebuilt binaries in seconds instead of compiling from source (~2 min)- Both update paths share the same GitHub Release assets — no additional CI or hosting required
- Version check (
govctl self-update --check) enables scripted staleness detection in CI or hooks
Negative
- New runtime dependency on
self_updatecrate and its transitive dependencies (mitigation: the crate is well-maintained with 8M+ downloads; feature-flag to compile only the GitHub backend + rustls) - Binary replacement requires write permission to the install directory (mitigation: clear error message when permission is denied, suggesting
sudoor ownership fix) - GitHub API rate limits apply to unauthenticated requests — 60 requests/hour per IP (mitigation: self-update is infrequent; document
GITHUB_TOKENenv var for authenticated requests if needed)
Neutral
cargo install govctlcontinues to work unchanged — this adds paths, does not replace existing ones- Plugin users (ADR-0033) are unaffected — plugin updates are managed by Claude Code’s plugin system
Alternatives Considered
self_update crate with GitHub Releases backend: Use the self_update crate (v0.44, ~8M downloads, actively maintained) to query GitHub Releases API, download platform-appropriate binary, and replace the running executable. Pair with cargo-binstall metadata in Cargo.toml so both self-update and cargo-binstall share the same release asset layout. (accepted)
- Pros: Minimal code (~20 lines) — the crate handles API queries, platform detection, archive extraction, and binary replacement, Actively maintained with broad adoption (8M+ downloads), Reuses existing release CI assets without changes — asset naming already matches, cargo-binstall support is additive metadata only, zero code, Both update paths share one asset layout, reducing maintenance
- Cons: Adds a runtime dependency (~5 transitive crates for HTTP, archive, self-replace)
Manual implementation with reqwest: Implement GitHub Releases API querying, asset download, archive extraction, and binary replacement manually using reqwest and flate2/tar crates. (rejected)
- Pros: Full control over behavior and error messages, No dependency on third-party update crate
- Cons: Significant implementation effort (~200+ lines) for a solved problem, Must handle platform detection, archive formats, binary replacement, and edge cases manually, Ongoing maintenance burden for update logic
- Rejected because: The self_update crate already solves this reliably. Reimplementing is unnecessary complexity for marginal control benefit.
Shell out to cargo install or cargo binstall: Instead of a built-in self-update, invoke cargo install govctl or cargo binstall govctl as a subprocess. (rejected)
- Pros: Zero new code for the update mechanism itself, Leverages existing package manager infrastructure
- Cons: Requires Rust toolchain (cargo install) or cargo-binstall installed separately, Slow for source builds — full compilation on every update, Poor UX — error messages come from external tools, not govctl, Cannot work in environments where govctl was installed via direct binary download
- Rejected because: Depends on external toolchain being present. Users who installed from GitHub Releases would not have cargo available. Per ADR-0018, prefer one canonical path.
ADR-0042: Enforce ADR writing order with structural gates
Status: accepted | Date: 2026-04-14
Tags:
validation
References: ADR-0027, RFC-0001
Context
The adr-writer skill prescribes a specific writing order — context, alternatives, mark alternatives as accepted/rejected, decision, consequences — but nothing in the CLI enforces it. Today, an agent or user can write decision on a fresh ADR with zero alternatives, or accept an ADR with empty context and no rejected options.
Problem Statement
Without structural enforcement, ADRs drift toward “conclusion-first” writing: a decision is stated without evidence that alternatives were considered. This undermines the purpose of ADRs as justificatory artifacts per ADR-0027.
The threshold of “at least 2 alternatives, with at least 1 accepted and 1 rejected” comes from the adr-writer skill’s core principle: “Let the alternatives show the discussion.” A decision that evaluated zero alternatives is not a decision — it is an assertion. A decision with only one option (the chosen one) has no visible trade-off. Two alternatives (one chosen, one rejected) is the minimum structure that demonstrates deliberation.
Current State
govctl adr set <ID> decisionhas no precondition checksgovctl adr accept <ID>only validates the status transition (proposed -> accepted) per RFC-0001:C-ADR-STATUS, not content completenessgovctl checkvalidates schema and cross-references but has no ADR completeness rules- The adr-writer skill documents the order but cannot enforce it
Constraints
- Historical backfills are a legitimate use case where alternatives may not be recoverable — enforcement must have an escape hatch
- Write-time gates should not block exploratory drafting of other fields (context, alternatives, consequences) — only
decisionis order-sensitive - The force flag is the established override pattern in govctl (used by
init,init-skills,delete); it applies to the lifecycle gate (adr accept --force) but not to the write-time gate
Decision
We will enforce ADR writing order at two points: when the decision field is written, and when the ADR is accepted, because:
-
Write-time gates catch conclusion-first thinking at the source. Blocking
decisionbefore alternatives are evaluated forces the author to consider options before committing to a conclusion. This is the critical moment — once a decision is written, the mental model shifts from exploration to defense. This gate is strict and not bypassable. -
Lifecycle gates provide a completeness checkpoint. Acceptance requires evaluated alternatives per the adr-writer skill’s prescribed order and the minimum-deliberation threshold described in the context.
-
The force flag on
adr acceptpreserves historical backfill workflows. When alternatives cannot be reconstructed, the lifecycle gate can be bypassed explicitly viaadr accept --forcerather than silently.
The specific validation rules (minimum alternative count, required statuses) are implementation details guided by the adr-writer skill’s prescribed order and the minimum-deliberation threshold described in the context.
Consequences
Positive
- ADRs become structurally complete before decisions are recorded — alternatives-first thinking is enforced, not just recommended
- Agents cannot shortcut the process by writing decision before evaluating options
- Acceptance gate catches incomplete ADRs even when write-time gate was bypassed
- Historical backfills remain possible via the force flag with explicit intent
Negative
- Authors who prefer to draft decision first and refine alternatives later face friction on every ADR (mitigation: this friction is intentional — the force flag exists for genuinely exceptional cases like historical backfills, not as a routine workflow bypass; the expected frequency of force usage should be low)
- Validation logic spans two code paths (edit and lifecycle), which adds maintenance surface as the ADR schema evolves (mitigation: the checks are field-presence and count checks with clear error messages; both paths share the same validation function)
Neutral
- Existing accepted ADRs are unaffected — the gates only apply to future write and accept operations
- The adr-writer skill documentation remains the same; the CLI now enforces what the skill recommends
Alternatives Considered
Both write-time and lifecycle gates: Gate the decision field behind alternatives completeness, and gate acceptance behind overall ADR completeness. Both gates bypassable with the force flag for historical backfills. (accepted)
- Pros: Enforces alternatives-first thinking at the moment it matters most, Lifecycle gate provides a second checkpoint at acceptance time, Consistent with the adr-writer skill prescribed order
- Cons: Adds validation logic to two code paths (edit and lifecycle)
Lifecycle gate only: Enforce completeness only at adr accept time, no write-time restrictions on setting decision. (rejected)
- Pros: No new edit-path complexity, Allows flexible drafting order
- Cons: Decision can be written without evidence of alternatives-first thinking, Quality check only at acceptance, not at authoring time
- Rejected because: Lifecycle-only enforcement misses the critical moment: when the decision is being written. By then, the conclusion-first pattern is already established.
No enforcement: Keep the current behavior where the adr-writer skill documents the order but the CLI does not enforce it. (rejected)
- Pros: Zero implementation effort
- Cons: No enforcement at all — relies entirely on skill guidance and human discipline, Agents can and do skip alternatives when not enforced
- Rejected because: The adr-writer skill already documents the order. The problem is that documentation alone does not prevent conclusion-first writing.
ADR-0043: Redirect journal entries to local .govctl storage
Status: superseded | Date: 2026-05-31 Superseded by: ADR-0047
References: ADR-0032, ADR-0026, RFC-0000:C-WORK-DEF
Context
ADR-0026 added a journal field to WorkItemContent for execution tracking. It was designed as an in-file array of structured entries (date, scope, content) within the work item TOML under gov/work/.
The journal field serves two distinct purposes that are now in tension:
- Execution trace — round-by-round logs during iterative implementation loops (high frequency, high verbosity, ephemeral value after closure)
- Institutional memory — curated summaries of what was done and why (low frequency, concise, permanent value)
The next-generation /loop skill requires the work item to drive an iterative execution cycle where each round produces structured journal entries, detailed round logs, and guard output files. Storing all of this in the work item TOML creates unacceptable noise: diff pollution, commit hygiene degradation, mixed concerns between plan/outcome and execution log, and unbounded size growth.
The resolution is to separate execution state from governance artifacts. The .govctl/ directory (a local, gitignored directory for execution state that is not durable governance) becomes the home for loop execution state, while the work item returns to being a pure outcome artifact.
This is a breaking schema change: the journal field is removed from the work item TOML schema, and all existing journal entries (58 of 144 work items currently have them) must be extracted to the new location.
RFC conflict: RFC-0000:C-WORK-DEF currently mandates journal as part of the [content] section. This ADR proposes removing that field, which directly contradicts the normative clause. The RFC clause MUST be amended as part of implementation — the implementing work item will track both the code changes and the clause amendment together.
Decision
We will remove the journal field from WorkItemContent and redirect all journal operations to .govctl/loops/<WI-ID>/journal.toml.
Key invariants
- Single source of truth: Journal data lives exclusively in
.govctl/loops/<WI-ID>/journal.toml. The work item TOML contains no journal entries. - CLI surface unchanged:
govctl work add WI journal,govctl work show WI, andgovctl work remove WI journalcontinue to work identically from the user’s perspective. Internally they read/write the journal file directly. .govctl/is local state: Created bygovctl init, added to.gitignore, theloops/subdirectory created on-demand.- Automated migration: A schema v2 → v3 migration step extracts inline journals from existing work items into the new location.
- Backward compat: During the transition, v2 work items with inline journals render read-only with a warning.
govctl checkemits a diagnostic prompting migration. - RFC amendment: RFC-0000:C-WORK-DEF will be amended to remove
journalfrom the[content]section, reflecting that journal is no longer a work item field.
What this does NOT specify
The exact journal.toml schema, migration implementation steps, CLI command internals, and specific diagnostic codes are implementation details that belong in the implementing work item, not in this ADR.
Work item fields after this change
| Field | Location | Purpose |
|---|---|---|
description | work item TOML | Task scope declaration |
acceptance_criteria | work item TOML | Completion criteria (scope contract) |
notes | work item TOML | Durable constraints, lessons, retry rules |
journal | .govctl/loops/<WI-ID>/ | Execution process tracking (local, ephemeral) |
Consequences
Positive
- Work items become pure outcome artifacts — clean diffs, no execution noise, smaller files
- Journal operations gain a dedicated, structured storage with room for round metadata without schema churn on the work item itself
.govctl/loops/provides a natural home for future loop state (round logs, guard output files) without further breaking changes- Migration is automated via
govctl migrate— same framework used for v1→v2
Negative
- Breaking schema change: v2 work items with inline journal require
govctl migrate. Mitigation: the migration step is automatic and idempotent;govctl checkemits a warning for unmigrated items so users are prompted. - Journal data is not version-controlled: if
.govctl/is deleted (e.g.,git clean -fdx), execution history is lost. Mitigation:govctl initadds.govctl/to.gitignoreautomatically; thenotesfield captures durable learnings for cross-clone sharing; this ephemeral-by-design property is documented. - Remote clones don’t include journal history: new contributors see work items without execution context. Mitigation:
notesfield carries durable learnings that survive cloning; the journal is a local development aid, not an institutional record. - Large blast radius across the codebase: changes touch model, render, edit, migrate, init, check, and schema layers. This increases regression risk and requires coordinated testing across the journal read/write paths.
Neutral
- The
notesfield remains in the work item TOML as the sole durable, freeform text field — its role sharpens to “things future work must remember” - CLI surface is unchanged —
govctl work add WI journalworks identically from the user’s perspective - The migration follows the existing versioned step framework from
cmd/migrate.rs JournalEntrystruct is reused in the new location; only its storage path changes
Alternatives Considered
Chosen: Remove journal from work item schema, redirect to .govctl/loops/
See decision section for full rationale and key invariants. (accepted)
Rejected: Dual-write — keep journal in work item for institutional memory, add .govctl/loops/ for execution trace
Maintain journal in the work item TOML for curated, human-written summaries. Add .govctl/loops/<WI-ID>/ for detailed round logs and guard output. Two layers of journaling.
Rejected because:
- Creates ambiguity: which journal is authoritative?
- Requires agents to remember to write to both locations
- The in-file journal still accumulates noise during active work
- Duplicates the concept — “journal” means two different things depending on where it lives
- Violates SSOT principle that the codebase already enforces elsewhere (rejected)
Rejected: Redirect journal to .govctl/, add a closure_summary field to work item
Move journal to .govctl/loops/. Add a new closure_summary field to the work item that the loop skill writes at closure — a curated, committed summary of what happened.
Rejected because:
notesalready serves this purpose (“durable constraints, lessons, retry rules future steps must remember”)- Adding a new field for closure summaries creates yet another text field with unclear boundaries
- The journal itself, in
.govctl/loops/, is available locally for anyone who needs the detail - Keeps the work item schema minimal — only fields with clear, distinct purposes (rejected)
ADR-0044: Unified loop model for single and multi-WI execution
Status: accepted | Date: 2026-05-31
References: RFC-0006
Context
The /loop skill needs to drive work items to completion through iterative rounds. Two distinct use cases emerged:
- Single work item iteration: Agent works on one WI until acceptance criteria are satisfied
- Multi-WI batch execution: Agent creates multiple related WIs with dependencies, then iterates through them as a batch
The question: should these be handled by separate primitives (/loop for single WI, /batch for multiple WIs) or a unified primitive?
Key observations:
- Work items naturally form DAGs (dependencies)
- The execution mechanism is identical: resolve dependencies → iterate → verify → terminate
- The state model is identical:
.govctl/loops/<loop-id>/works for both - Agents already use the pattern: “batch create WIs, then iterate through all of them”
Decision
We will use the unified model: a single /loop skill that accepts one or more work item IDs.
Key design points:
/loop WI-001drives a single work item/loop WI-001 WI-002 WI-003drives multiple work items with dependency resolution- Work items declare dependencies via
depends_onfield - Execution state lives in
.govctl/loops/<loop-id>/ - Downstream applications choose execution model (sequential/parallel)
This treats single-WI and multi-WI cases as the same primitive with different cardinality.
Consequences
Positive
- One mental model to learn instead of two.
- State management is consistent (
.govctl/loops/works for both single and multi-work-item loops). - Natural support for DAGs through work item dependencies.
- Agents can use the same pattern for both use cases.
- Future enhancements apply to both automatically.
Negative
- Initial implementation is more complex because dependency resolution is present even for single-work-item loops. Mitigation: single-work-item loops use the same planner with an empty dependency graph.
- Users who only need single-work-item iteration may see multi-work-item options as overhead. Mitigation: the command surface keeps the one-work-item invocation as the simple path.
- Documentation must cover both use cases. Mitigation: docs introduce the single-work-item case first, then describe multi-work-item dependency behavior as an extension.
Neutral
- Aligns with existing agent workflow patterns (batch create work items, then iterate).
- No breaking changes to existing
/govor/quickskills.
Alternatives Considered
Separate primitives: distinct /loop (single WI) and /batch (multiple WIs) skills (rejected)
- Pros: Simpler initial implementation
- Cons: Two concepts with overlapping semantics, Forced choice for users, Duplicate state management
- Rejected because: Underlying mechanism is identical; separate skills create artificial distinction
Unified model: single /loop skill accepts one or more WI IDs (accepted)
- Pros: Simpler mental model, Consistent state model, Natural DAG support
- Cons: Slightly more complex implementation
ADR-0045: Work item dependency declaration via depends_on field
Status: accepted | Date: 2026-05-31
References: RFC-0000:C-REFERENCE-HIERARCHY, RFC-0006
Context
Work items can depend on other work items, creating execution ordering constraints. The question: should dependencies be declared via a new depends_on field, or by reusing the existing refs field?
Key considerations:
refsis already used for cross-referencing RFCs and ADRs (informational)- Dependencies are blocking (“cannot proceed until this completes”)
- Refs are informational (“I am aware of this artifact”)
- The loop needs to distinguish between hard dependencies and soft references
- Work items may reference RFCs/ADRs they implement while also depending on other work items
Decision
We will add a separate depends_on field to work items for declaring execution dependencies.
Key design points:
depends_oncontains work item IDs that must complete successfully before this work item can startrefsremains for informational cross-references (RFCs, ADRs, related work items)- A work item can have both
refs(I implement RFC-0001) anddepends_on(I need WI-001 to finish first) - Work item schemas include
depends_onas an optional[govctl]metadata field - The loop uses
depends_onto resolve a transitive dependency closure before execution - The loop uses
depends_onfor dependency ordering and failure propagation - Cyclic dependencies and missing dependency IDs are detected and rejected at loop start
This separates blocking dependencies from informational references, making intent explicit.
Consequences
Positive
- Explicit semantics: dependencies are clearly marked as blocking.
- Loop planning can reliably distinguish dependencies from references.
- Work items can reference what they implement and what they depend on without ambiguity.
- Dependency closure gives agents and humans a deterministic view of the executable set.
Negative
- Schema change required: work item JSON Schema must accept optional
govctl.depends_on. Mitigation: the field is additive and optional. - Slightly more metadata for users to understand. Mitigation:
refsremains informational anddepends_onis used only for blocking execution dependencies. - Existing work items that used
refsto imply dependencies may need manual cleanup. Mitigation: loops only treatdepends_onas blocking, so legacy refs remain safe informational links.
Neutral
- Aligns with RFC-0000:C-REFERENCE-HIERARCHY because
refsstays informational. - No breaking changes to existing refs usage.
Alternatives Considered
Reuse refs field for all cross-references (rejected)
- Pros: No schema change, Fewer fields
- Cons: Ambiguous semantics, Loop must guess dependency vs reference, Conflates informational and blocking relationships
- Rejected because: Ambiguous semantics; loop cannot distinguish hard dependencies from soft references
Separate depends_on field for work item dependencies (accepted)
- Pros: Explicit semantics, Clear intent, Allows both refs and depends_on
- Cons: Schema change required
ADR-0046: Use loop-centric execution state storage
Status: accepted | Date: 2026-05-31
References: ADR-0043, RFC-0006, ADR-0047
Context
ADR-0043 chose a work-item-centric local execution-state layout under .govctl/loops/<WI-ID>/. ADR-0047 then removed execution history from the work item field surface while preserving render compatibility for legacy inline data.
RFC-0006 introduces a unified loop model where one loop can drive one or more work items. A per-work-item storage root cannot represent a multi-work-item loop because dependency graph, execution order, aggregate lifecycle, failure propagation, and resumption are loop-level concepts.
RFC-0006 now specifies .govctl/loops/<loop-id>/state.toml as the loop state anchor. That supersedes older storage-path wording that treated a per-loop execution-log file as the primary execution-tracking location. This ADR records the storage orientation for loop execution state so implementation does not inherit the older work-item-centric layout or legacy execution-history terminology.
Decision
We will store loop execution state by loop ID under .govctl/loops/<loop-id>/.
The required state anchor is .govctl/loops/<loop-id>/state.toml. Optional detailed per-round artifacts live below the same loop directory as loop-level round records, for example .govctl/loops/<loop-id>/rounds/round-NNN.toml. Round artifacts may mention relevant Work Item IDs in their payload, but the canonical storage path is loop-level rather than per-work-item.
Loop resumption supports two lookup paths: explicit lookup by loop ID, and root-set discovery when the caller provides the same explicit root work item set and exactly one matching non-terminal loop state exists. Ambiguous root-set matches require the caller to provide a loop ID.
Work item files remain outcome artifacts. Durable context belongs in notes; execution trace belongs in loop state and round artifacts. ADR-0047 remains authoritative for removing execution history from the work item field surface. This ADR replaces the older work-item-centric storage direction from ADR-0043 with loop-centric execution state storage and resolves stale future-storage wording in favor of state.toml.
Consequences
Positive
- Enables unified multi-work-item loop execution with one shared state root.
- Keeps dependency graph, execution order, lifecycle, failure propagation, and resumption state together.
- Preserves the boundary that work item files are durable outcome artifacts, not execution traces.
- Aligns local state layout with RFC-0006 and the ADR-0047 field-surface removal.
- Gives resumption a deterministic fallback: exact loop ID first, root-set discovery only when unambiguous.
Negative
- Existing experiments that wrote per-work-item local state need migration or removal. Mitigation: this work predates a stable loop implementation, so compatibility can be limited to explicit migration code or documented cleanup.
- Loop ID generation becomes part of the storage contract. Mitigation: RFC-0006 constrains loop IDs to safe path segments and requires state to record the loop ID.
- Root-set discovery requires scanning local loop state when no loop ID is provided. Mitigation: scanning is limited to non-terminal
state.tomlfiles under.govctl/loops/, and ambiguous matches are rejected.
Neutral
- Detailed per-round artifacts are optional;
state.tomlis the required coordination point. - The
.govctl/loops/directory remains local execution state and is not a governed artifact.
Alternatives Considered
Keep work-item-centric execution state storage (rejected)
- Pros: Smallest change to the older local-state direction
- Cons: Multi-WI coordination becomes complex, Resumption requires scanning multiple directories, Cannot represent one loop-level lifecycle for several work items
- Rejected because: A per-work-item state root cannot represent a multi-work-item loop lifecycle, dependency graph, failure propagation, or resumption state.
Use loop-centric execution state storage (accepted)
- Pros: Natural multi-WI support, Shared loop state, Simpler resumption
- Cons: Requires stable loop ID generation and lookup behavior
Use a per-loop execution-log file as the primary state anchor (rejected)
- Pros: Retains the older execution-log naming convention
- Cons: Cannot hold authoritative lifecycle and dependency graph state without becoming a mixed-purpose file, Conflicts with RFC-0006’s state.toml storage contract, Keeps future loop execution tied to legacy execution-history terminology
- Rejected because: Loop execution needs an authoritative state file for lifecycle, dependency graph, work item statuses, and round counts; detailed logs may be separate optional artifacts, but state.toml is the coordination point.
ADR-0047: Remove journal from work item field surface for loop-centric execution state
Status: superseded | Date: 2026-05-31 Superseded by: ADR-0056
References: ADR-0043, ADR-0026, RFC-0006, RFC-0000:C-WORK-DEF
Context
ADR-0026 added a journal field to work items for execution tracking. ADR-0043 proposed removing it entirely and redirecting execution tracking to a work-item-centric .govctl/loops/<WI-ID>/ layout. RFC-0006 then introduced a loop-centric model where .govctl/loops/<loop-id>/state.toml is the state anchor for loop execution.
Three problems with ADR-0043’s “remove and redirect” approach:
- Breaking change: Some work items may contain legacy inline execution-history entries. Removing the field entirely would force immediate migration.
- ADR-0043 is superseded by RFC-0006: Its target path (
.govctl/loops/<WI-ID>/) conflicts with the loop-centric model (.govctl/loops/<loop-id>/). - RFC-0000:C-WORK-DEF mandates journal: Removing it contradicted the normative clause without a proper amendment path at the time this decision was made.
The loop execution model (RFC-0006) makes inline execution-history data obsolete: loop execution state in .govctl/loops/<loop-id>/state.toml is the source of truth for active execution tracking. Any work item’s inline data is legacy compatibility data.
Rather than preserve journal as a separate read-only field, we remove it from the path-addressable work item field surface. Existing inline data may still be parsed so work show and render output can display historical entries without forcing an immediate migration.
Decision
Remove journal from the path-addressable work item field surface. journal MUST NOT be accepted by work get, work add, work edit, work remove, or work tick as a separate field.
For backward compatibility, implementations MAY continue to deserialize legacy inline content.journal entries and render them from work show / work item render output. This compatibility path MUST NOT make journal available as a normal editable or fetchable field.
Loop execution state is stored through the loop-centric state model in RFC-0006 and ADR-0046, not through a work item field.
Consequences
Positive:
- Existing work items with legacy inline data continue to render correctly
- Clear model boundary:
journalis not a Work Item field even though legacy data can render - Historical execution data remains inspectable through work item show/render output when present
- Establishes loop-centric state as the future path for active execution tracking
- Supersedes the conflicting ADR-0043 with a more practical approach
Negative:
- Legacy inline data may persist in external work item files, adding minor file size overhead
- Compatibility parsing remains until the project intentionally removes legacy render support
- No automated migration path for durable insights from legacy inline data to notes (manual process)
Neutral:
govctl checkgains an informational diagnostic for work items with legacy inline dataJournalEntrystruct and render code remain in the codebase for legacy render compatibility- New work items omit
content.journal
Alternatives Considered
Remove journal from field surface while preserving render compatibility (accepted)
- Pros: Clear field model: journal cannot be fetched or edited separately, Historical entries remain visible through show/render, No breaking changes for work items with legacy inline data
- Cons: Legacy journal data persists indefinitely, Render compatibility keeps journal parsing code
Remove journal field entirely and force migration (rejected)
- Pros: Clean break with no legacy compatibility path
- Cons: Requires forced migration; destroys readable history, Breaking change for work items with legacy inline data
- Rejected because: Immediate forced migration is unnecessary; ADR-0043 target path also conflicts with RFC-0006 loop-centric model
ADR-0048: Use local artifact catalog for direct lookup
Status: accepted | Date: 2026-06-04
References: RFC-0002, RFC-0004, ADR-0039
Context
Many govctl commands that operate on one artifact currently load an entire artifact collection and then search in memory for the requested ID. This is simple and correct at small scale, but it makes common commands such as work show, work edit, verify --work, and loop execution pay full-directory scan and parse costs even when the filesystem layout or a small local index could identify the target path directly.
The search feature planned by ADR-0039 needs similar file freshness metadata. If search owns the only cache, core CLI lookup would become accidentally coupled to full-text search. If every command continues to scan independently, search does not solve the broader performance problem.
The key constraint is authority: governed TOML artifacts remain the source of truth. Any cache used for lookup must be derived local state, and commands must still read and validate the target artifact before acting.
Decision
Use a project-local derived artifact catalog for direct artifact lookup.
The catalog records artifact kind, ID, source path, and file freshness metadata. It is stored under .govctl/ as local state and is not a governed artifact. Commands may use the catalog to find a candidate path for an ID, but the catalog never authorizes mutations by itself: the command must read the target file and verify that the artifact’s stored ID matches the requested ID before it acts.
The catalog is conceptually separate from full-text search. Search may reuse the catalog’s path and freshness metadata, but search ranking, snippets, and FTS tables remain search-specific derived data.
For artifact kinds with deterministic source paths, such as RFCs and clauses, commands should resolve paths directly and avoid the catalog when a simple path check is sufficient. For artifact kinds whose filenames are not fully determined by ID, such as work items and ADRs, commands should use the catalog first and fall back to a bounded collection rescan that repairs stale or missing catalog entries.
Consequences
Positive
- Single-artifact commands can avoid full collection scans in the common case.
- Search can reuse shared freshness metadata without owning core CLI lookup.
- Stale cache entries are recoverable because authoritative artifact content is still read from TOML.
- The
.govctl/local-state boundary keeps derived lookup state out of governed artifacts and rendered output.
Negative
- Adds a local cache invalidation path that must be tested carefully.
- Commands that use the catalog must verify ID/path agreement before mutation, or stale entries could become unsafe.
- The first command after a branch switch or large artifact edit may still need a bounded rescan to repair catalog metadata.
Neutral
- Full-project commands such as
check,status, and bulkrenderstill need broad loading. The catalog optimizes targeted lookup, not semantic validation.
Alternatives Considered
Derived local artifact catalog: Maintain a .govctl local-state catalog for ID-to-path lookup and freshness metadata, while still validating the target artifact before any read or mutation result is trusted. (accepted)
Keep full collection scans: Continue loading each whole artifact collection for single-ID commands and rely on search indexing only for search queries. (rejected)
- Rejected because: This preserves correctness but leaves the common single-artifact command path slow and lets search solve only one symptom instead of the shared lookup problem.
ADR-0049: Adopt read-only cockpit model for TUI v2
Status: accepted | Date: 2026-06-06
Tags:
tui
References: RFC-0007, RFC-0003, RFC-0006, RFC-0002
Context
TUI v2 needs to become more useful and more readable for humans working in a governed repository.
Problem Statement
The current TUI is primarily a dashboard plus RFC/ADR/work item browser. It does not expose newer governance concepts such as project-wide search, persisted loop state, dependency DAGs, or check diagnostics. At the same time, govctl already has a mature CLI mutation model for edits, lifecycle transitions, dry-run behavior, diagnostics, and write locking.
Constraints
- RFC-0003 defines the existing TUI browsing baseline.
- RFC-0007 defines TUI v2 behavior for a read-only cockpit.
- RFC-0002 owns CLI resource and search semantics.
- RFC-0006 owns loop state and loop execution semantics.
- First-phase TUI v2 must serve humans, not agents or machine parsing.
Decision
We will build TUI v2 as a read-only human cockpit with loop DAG visualization.
The first phase of TUI v2 will focus on human understanding: project overview, artifact browsing, search, persisted loop state, dependency DAGs, and diagnostics. It will not implement artifact editing, lifecycle transitions, loop execution, migration, rendering, or other mutations.
Consequences
Positive
- TUI v2 gets a coherent product shape instead of another set of isolated list/detail additions.
- Humans can inspect project state, search context, loop progress, DAG dependencies, and diagnostics from one terminal surface.
- The existing CLI remains the single mutation authority for artifact edits, lifecycle transitions, loop execution, rendering, dry-run, and locking.
- The loop DAG view makes dependency readiness and blocked downstream work understandable without reading raw state files.
Negative
- Users who want a full terminal editor must still switch to CLI commands for mutations. Mitigation: TUI v2 can display suggested commands without executing them.
- Visual DAG layout adds complexity that simple lists do not have. Mitigation: keep the layout deterministic, test the data model separately from widget rendering, and provide readable fallbacks for large graphs or narrow terminals.
- Search and diagnostics views may expose more information than fits comfortably on small terminals. Mitigation: prioritize stable summaries, selected-item inspectors, and responsive single-column fallbacks.
Neutral
- This decision does not prevent future write-capable TUI workflows. It requires those workflows to be designed later against the existing edit model, dry-run behavior, diagnostics, and write-lock rules.
- Disposable
.govctlsearch/catalog index refresh remains acceptable when governed by the existing search freshness contract; persisted loop state remains read-only in the TUI.
Alternatives Considered
Keep current TUI and add isolated feature views (rejected)
- Pros: Smallest incremental change, Low initial implementation risk
- Cons: Leaves dashboard/list/detail as the organizing model, Makes search, loops, and diagnostics feel bolted on, Does not establish a coherent human cockpit information architecture
- Rejected because: This would continue the existing pattern of isolated TUI additions rather than solving the product shape problem.
Build a full interactive CRUD TUI editor (rejected)
- Pros: Provides one integrated terminal surface for browsing and editing, Could be attractive for humans who prefer TUI workflows
- Cons: Duplicates CLI edit, lifecycle, dry-run, diagnostics, and lock semantics, Raises risk of a weaker parallel mutation model, Greatly expands first-phase scope before the cockpit model is proven
- Rejected because: First-phase TUI v2 should not create a second mutation surface parallel to the governed CLI.
Build a read-only human cockpit with loop DAG visualization (accepted)
- Pros: Creates one coherent product shape for overview, browsing, search, loops, and diagnostics, Preserves CLI ownership of mutations and lifecycle gates, Makes loop dependency state understandable to humans through a visual DAG, Can be implemented and tested incrementally without weakening artifact authority
- Cons: Users still need to run CLI commands for edits and lifecycle transitions, DAG layout and responsive terminal rendering add UI complexity
ADR-0050: Preserve direct clause supersession chains
Status: accepted | Date: 2026-06-28
Tags:
lifecycle,validation
References: RFC-0001:C-CLAUSE-STATUS, RFC-0002:C-LIFECYCLE-VERBS
Context
RFC-0001:C-CLAUSE-STATUS records the clause that replaced a superseded clause. Existing validation interpreted that reference as a permanently active destination, so a valid A -> B replacement became invalid after B was replaced by C.
Problem Statement
The stored relation needs an unambiguous meaning that supports repeated clause evolution without rewriting or invalidating prior history.
Constraints
- Supersession history must remain auditable.
- A lifecycle transition should update only the clause being transitioned.
- Malformed references and cycles must remain detectable.
- Qualified clause IDs already provide an unambiguous representation for cross-RFC references.
Decision
We will preserve each superseded_by value as the direct replacement selected when its source clause was superseded. Later replacements extend the chain instead of rewriting earlier clauses because:
- Auditability: Direct edges retain the exact sequence of clause evolution.
- Write locality: Each transition changes only its source clause instead of rewriting every predecessor.
- Composability: The same relation represents repeated and cross-RFC replacement without a second storage model.
This separates two concerns: transition-time eligibility determines whether a new replacement edge may be created, while repository validation determines whether persisted history is structurally sound. Cross-RFC replacements use qualified clause IDs so the edge remains unambiguous.
Consequences
Positive
- Historical provenance remains intact across any number of replacements.
- Superseding a clause requires only a local write to that clause.
- The same model supports both same-RFC and qualified cross-RFC replacements.
Negative
- Resolving the latest replacement can require following multiple direct edges.
- Malformed direct-edge histories can contain cycles or unresolved references.
Neutral
- A chain may end at a clause that is no longer active; this describes history rather than asserting that an active replacement currently exists.
Alternatives Considered
Preserve each direct replacement as a historical edge and resolve later replacements by traversing the chain (accepted)
- Pros: Retains the exact sequence of clause evolution, Each transition changes only its source clause
- Cons: Consumers that need the latest replacement must traverse the chain, Validation must detect self-references and cycles
Flatten predecessors to the newest replacement whenever another clause is superseded (rejected)
- Pros: A stored reference always points directly to the latest replacement
- Cons: Destroys the direct replacement history, Requires multi-file rewrites for one lifecycle transition
- Rejected because: The simpler lookup does not justify loss of provenance, wider writes, and additional merge conflicts
Require every stored replacement target to remain active and disallow supersession chains (rejected)
- Pros: Keeps validation and lookup limited to one edge
- Cons: A later replacement invalidates previously valid history, Prevents normal repeated evolution of a clause contract
- Rejected because: It creates the issue being addressed and conflates transition-time eligibility with historical validity
ADR-0051: Scope terminal lifecycle states to revision and release boundaries
Status: accepted | Date: 2026-07-15
Tags:
lifecycle,release
References: ADR-0014, ADR-0016, RFC-0000:C-PHASE-LIFECYCLE, RFC-0000:C-WORK-DEF, RFC-0000:C-RELEASE-DEF, RFC-0001:C-RFC-PHASE, RFC-0001:C-WORK-STATUS, RFC-0002:C-LIFECYCLE-VERBS
Context
RFC-0001 v0.4.2 treated stable as terminal for an RFC, while ADR-0016 allowed a normative RFC to evolve through versioned amendments. A content-bearing version bump therefore left the RFC marked stable even though the new revision had not passed implementation and test gates.
RFC-0001 v0.4.2 also treated done as terminal for a Work Item. That prevented correcting a mistaken completion before release. ADR-0014 records release membership separately but describes every completed Work Item as immutable; this decision narrows that consequence by moving the immutability boundary from completion to release membership.
Problem Statement
The terminal boundaries were attached to long-lived artifact identities instead of the revisions and release records they actually close. We need lifecycle semantics that preserve phase discipline and release history without introducing parallel version or reopening state machines.
Constraints
- RFC amendments must continue to use the existing semantic version and changelog model.
- Phase progression within one RFC version must remain ordered.
- Released work must not re-enter the unreleased changelog under the same Work Item ID.
- Existing
phase, Work Itemstatus, timestamps, and release references should remain the storage model.
Decision
We will scope terminal lifecycle states to the revision or release record they complete while retaining the existing stored fields.
For RFCs, phase describes the current version. A content-bearing version bump starts a new phase progression at spec; stable remains terminal only within the version that reached it. Changelog-only bookkeeping does not start a new phase progression.
For Work Items, done represents a release-ready completion judgment. An unreleased done item may return to active so that judgment can be corrected. Once a release references the Work Item, release membership freezes that lifecycle record and later problems are represented by a new Work Item.
This approach was chosen because:
- Phase accuracy: Each amended RFC version passes through the existing gates instead of inheriting an earlier version’s
stableresult. - Release integrity: A Work Item cannot re-enter a later release under an ID already frozen in release history.
- Minimal state: Existing phase, status, timestamp, and release-reference fields are sufficient; no parallel lifecycle representation is needed.
This decision narrows ADR-0014 only with respect to when Work Item immutability begins: release-referenced Work Items remain immutable lifecycle records, while completed but unreleased Work Items may be reopened.
Consequences
Positive
- Each RFC amendment re-enters the same visible phase discipline without a second version-state representation.
- Pre-release Work Item mistakes can be corrected without fragmenting one unit of work across duplicate items.
- Existing schemas, status values, and resource-first commands remain sufficient.
- Release references provide a deterministic boundary for preserving published history.
Negative
- Even an editorial content bump restarts the RFC at
spec. The friction is bounded to the existing sequential phase transitions, which remain automation-compatible and require no additional state. - Reopening a Work Item requires reading release membership before changing its status. Release references are local canonical data, so the check adds no external dependency.
- The original completion date is no longer present in the current Work Item after reopening; version control retains that history.
- Historical RFC phase progression remains in version control rather than an artifact-local phase log; adding a second history model was rejected as disproportionate.
Neutral
- Existing loop records remain local execution history and are not reopened when a Work Item returns to
active. - Problems found after release continue as new Work Items that can reference the released item.
Alternatives Considered
Keep stable and done terminal for the lifetime of their artifacts (rejected)
- Pros: Preserves the current state machines unchanged
- Cons: RFC phase becomes stale after a stable RFC is amended, Mistaken Work Item completion requires a duplicate follow-up before release
- Rejected because: Artifact-lifetime terminality conflicts with versioned RFC evolution and creates unnecessary Work Items for pre-release corrections
Add persistent per-version phase records and explicit reopened or released Work Item states (rejected)
- Pros: Makes every historical lifecycle transition explicit in artifact data
- Cons: Introduces two additional state models and migration requirements, Duplicates history already available from changelogs, release references, and version control
- Rejected because: The additional storage and transition surface is disproportionate to the two lifecycle corrections
Reuse the current phase and status fields, with RFC bumps and release membership as lifecycle boundaries (accepted)
- Pros: Preserves the existing artifact schemas and command vocabulary, Restarts phase discipline for each amended RFC version, Allows pre-release correction while keeping released Work Items frozen
- Cons: Historical RFC phase transitions remain in version control rather than artifact-local records, Work Item mutability depends on a lookup in release references
ADR-0052: Assign ADR projection structure to canonical authoring surfaces
Status: accepted | Date: 2026-07-15
Tags:
validation
References: RFC-0000:C-ADR-PROJECTION-OWNERSHIP, ADR-0003, ADR-0024, ADR-0027, ADR-0042
Context
The ADR model combines free-form Markdown content fields with structured metadata and alternatives that the renderer projects into a human-readable document. Existing authoring guidance allowed an options subsection in free-form context even though the renderer independently emitted the same discussion from structured alternatives. For example, a context field containing ### Options Considered rendered alongside the generated ## Alternatives Considered inventory.
Problem Statement
When one semantic section can be authored through both prose and structured fields, a source artifact can remain schema-valid while its rendered projection repeats or contradicts itself. Writer prompts and isolated review can reduce this risk but cannot guarantee that it is caught before acceptance.
Constraints
- RFC-0000:C-ADR-PROJECTION-OWNERSHIP defines the observable validation and acceptance behavior.
- Structured alternatives remain the discussion-oriented model established by ADR-0027.
- Rendered Markdown remains a projection of authoritative TOML under ADR-0003.
- Historical ADRs in external repositories must not require semantic rewriting merely to adopt a newer govctl release.
- Inline references in explanatory prose remain useful and are distinct from a generated reference inventory.
Decision
We will assign every rendered ADR section to one canonical authoring surface and enforce that boundary before acceptance.
Free-form context, decision, and consequences fields own their explanatory body prose. Structured refs and content.alternatives own reference and option inventories, while the renderer owns the surrounding document headings and labels.
A deterministic validator will inspect Markdown headings outside fenced code blocks. It will reject conflicts in proposed ADRs and in the acceptance path, where the existing force option remains limited to alternatives completeness. Historical terminal ADRs retain compatibility, while repositories may clean legacy duplication without changing the stored schema.
This approach was chosen because:
- Deterministic prevention: Authoring and isolated review remain useful, but a machine gate prevents the known conflict from reaching acceptance.
- Single semantic owner: Structured alternatives remain the options inventory instead of competing with free-form context.
- Proportional structure: Heading-aware validation preserves useful prose and examples without expanding the ADR schema.
- Historical compatibility: Enforcement closes new violations without requiring semantic rewrites of accepted external ADRs.
Writer and reviewer guidance will mirror the same ownership boundary so agents receive one rule at authoring, review, and validation time.
Consequences
Positive
- Schema-valid ADR sources can no longer introduce new duplicate renderer-owned sections and still pass acceptance.
- Writer, reviewer, validator, and renderer use the same ownership model.
- Heading-aware parsing preserves code examples and inline references.
- Existing external ADR history remains adoptable without semantic migration.
Negative
- Validation must understand enough Markdown structure to distinguish headings from fenced examples; the parser is intentionally limited to heading and fence recognition rather than general Markdown rendering.
- Historical ADR duplication is not automatically eliminated outside repositories that choose to clean it; compatibility is preferred over heuristic rewriting.
- A small set of heading names becomes unavailable for author-defined subsections; the diagnostic directs authors to the corresponding structured field or renderer-owned section.
Neutral
- The ADR schema and renderer output format remain unchanged.
- The existing alternatives-first acceptance gate remains responsible for deliberation completeness.
- Repository-local cleanup of accepted ADR prose is editorial and does not alter prior decisions.
Alternatives Considered
Rely on writer and reviewer guidance only (rejected)
- Pros: No validation or migration work
- Cons: The same contradictory guidance can recur, Review remains probabilistic
- Rejected because: The failure mode already passed both authoring and review guidance
Reject projection conflicts in every ADR status immediately (rejected)
- Pros: Applies one invariant uniformly to the whole repository
- Cons: Existing external repositories can fail after upgrading, Historical prose may require subjective rewriting
- Rejected because: Uniform enforcement does not justify retroactive compatibility breakage
Enforce canonical ownership for proposed ADRs and acceptance while preserving historical compatibility (accepted)
- Pros: Prevents new conflicts at deterministic gates, Keeps structured alternatives as the sole options inventory
- Cons: Historical ADRs can retain legacy duplication until intentionally cleaned
ADR-0053: Use guarded latest-only undo for local release cuts
Status: accepted | Date: 2026-07-15
Tags:
release,lifecycle,safety
References: ADR-0014, ADR-0051, RFC-0000:C-RELEASE-DEF, RFC-0002:C-LIFECYCLE-VERBS, RFC-0004:C-SCOPE
Context
ADR-0014 models a release cut as a new entry prepended to gov/releases.toml, and ADR-0051 uses release membership as the boundary that freezes completed Work Items. An accidental local cut therefore freezes its members even when the release record has not been used for an external publication.
The release command records governance data only. It does not create or remove Git tags, hosted releases, or published packages. A correction mechanism should recover the immediately preceding local governance state without implying that external publication can be reversed.
Problem Statement
We need a narrow way to correct the most recent accidental local release cut while preserving older release history and detecting stale operator intent.
Constraints
- Existing release entries form a newest-first local history.
- Released Work Items remain frozen for as long as their release reference exists.
- Correction must not introduce release states, tombstones, or external-service side effects.
- The normal gov-root write lock and atomic file write remain the concurrency and persistence boundary.
Decision
We will correct an accidental local release cut by removing only the newest release entry after matching an operator-supplied expected version because:
- Head-only correction: Removing the newest entry restores the immediately preceding local release history without selecting or rewriting an older entry.
- Stale-intent rejection: The expected version makes operator intent explicit and prevents delayed automation from undoing a newer release.
- Bounded meaning: The operation changes local governance data only and does not claim to retract externally published software.
This decision narrows ADR-0051 only with respect to the lifetime of release membership: a Work Item is frozen while a release entry references it. Removing the newest entry through this correction removes that membership boundary but does not reopen or otherwise mutate the Work Item.
Git tags, hosted releases, packages, and other publication systems remain outside govctl’s release correction.
Consequences
Positive
- An accidental latest cut can be corrected without creating replacement Work Items.
- Older release history cannot be selected or rewritten by the correction command.
- Version matching makes stale invocations fail instead of undoing a newer release.
- Existing locking, release storage, and atomic-write mechanisms remain sufficient.
Negative
- Once another release is cut, the earlier entry can no longer be corrected through this operation. The older record remains intact, and any corrective implementation is tracked by a new Work Item and later release rather than by rewriting history.
- Local correction does not retract anything already published externally, so operators must handle those systems separately.
- The canonical release file retains no tombstone for the removed cut. Version-control history is the audit trail for the cut and correction.
Neutral
- Work Items referenced by the removed entry remain completed but become unreleased.
- No persistent release lifecycle state is introduced.
Alternatives Considered
Keep every release entry immutable and represent mistakes with later Work Items (rejected)
- Pros: Preserves the existing append-only interpretation
- Cons: Cannot correct an accidental local cut before publication
- Rejected because: It keeps an operational mistake frozen even when no later local release depends on it
Allow deletion of any release entry (rejected)
- Pros: Can correct any selected local release record
- Cons: Rewrites non-head history and can invalidate every later release boundary, Makes stale or mistaken target selection more destructive
- Rejected because: Arbitrary historical deletion breaks the head-only rollback boundary and can invalidate later release history
Remove only the newest local release when its expected version matches (accepted)
- Pros: Restores the immediately preceding local state without rewriting older history, Uses the expected version as an explicit stale-intent guard
- Cons: Cannot correct an older release after another release has been cut
Remove the newest local release without requiring its expected version (rejected)
- Pros: Uses the smallest possible command input
- Cons: A delayed or repeated invocation can remove a newer release than the operator intended
- Rejected because: Position alone cannot detect stale operator or automation intent
Retain corrected releases with a retracted status or tombstone (rejected)
- Pros: Preserves an artifact-local audit trail of the cut and correction
- Cons: Adds persistent release states and requires changelog and Work Item semantics for retracted membership
- Rejected because: Version-control history provides the required audit trail without adding a second release lifecycle model
ADR-0054: Bind RFC version bumps to sealed-version amendments
Status: accepted | Date: 2026-07-20
References: ADR-0016, ADR-0051, RFC-0000:C-STATUS-LIFECYCLE, RFC-0000:C-PHASE-LIFECYCLE, RFC-0000:C-CLAUSE-DEF, RFC-0001:C-RFC-PHASE, RFC-0002:C-CRUD-VERBS, RFC-0002:C-LIFECYCLE-VERBS
Context
Before this decision, the RFC lifecycle treated spec as an open authoring candidate and assigned new Clauses to that current version, while version-changing bump validation still permitted another bump from spec when candidate content differed from the stored signature. The abandoned candidate then remained in changelog history, and Clauses first created there retained its version in since even if no implementation baseline was ever sealed.
The pre-amendment deletion rules also prohibited Clause deletion from every normative RFC regardless of phase. A Clause created accidentally in an open spec candidate therefore could not be removed, which encouraged artificial deprecation or supersession records solely to correct authoring mistakes.
The lifecycle needed one unambiguous version boundary without making since directly editable or adding persistent candidate-version state.
Decision
We will refine ADR-0016 and ADR-0051 by treating spec as the single open authoring candidate for the RFC’s current version. Normal version-changing bumps open a new lifecycle only from a version that has already entered impl, test, or stable and has a sealed amendment signature. Entry from spec to impl establishes that signature; a missing signature in a later phase is rejected as an untrustworthy baseline rather than inferred by bumping.
A Clause first introduced in the open current candidate may be removed before sealing when no other artifact references it. Clauses inherited from an earlier version continue to use deprecation or supersession so established history remains intact. Direct since editing and automatic rewriting across ordinary bumps remain outside the model.
This option was selected because:
- The existing
phase, RFCversion, and Clausesincefields identify the open candidate without another persistent state model. - One bump boundary per version prevents unsealed intermediate candidates from appearing as compatibility history.
- Candidate-only deletion corrects authoring mistakes without weakening the history of Clauses inherited from sealed versions.
If changing an open candidate’s semantic-version level becomes a recurring need, it will be considered separately rather than overloading bump semantics now.
Consequences
Positive
- Each version has one authoring interval and one implementation baseline.
- Clause
sincevalues cannot become stranded on an abandoned intermediate candidate through normal lifecycle commands. - Accidental current-candidate Clauses can be removed without creating false deprecation or supersession history.
- Existing status, phase, version, signature, changelog, and Clause metadata remain sufficient.
Negative
- A user cannot issue another version-changing bump while an RFC is already in
spec. Candidate scope must remain within the selected compatibility level; incompatible additions can be deferred to the next version. - A semantic-version level chosen too early cannot be changed through ordinary lifecycle commands. An unpublished candidate can be corrected in version control before it becomes shared history.
- Clause deletion must distinguish candidate-only Clauses from inherited Clauses. The existing
phase == specandsince == current versioncondition provides that boundary and requires focused regression coverage. - A normative RFC missing its sealed signature after
speccannot bump or advance. The repository must restore that baseline through its migration or version-control history rather than guessing it from possibly amended content.
Neutral
- Changelog-only correction remains independent of the version lifecycle.
sinceremains lifecycle-owned and unavailable through generic editing.
Alternatives Considered
Keep spec-phase rebumping and record abandoned candidates as historical versions (rejected)
- Pros: Requires no command or storage changes
- Cons: Leaves unsealed candidates indistinguishable from implemented version history, Encourages artificial Clause supersession to repair authoring attribution
- Rejected because: Unsealed candidates are authoring state, not useful compatibility history, and synthetic supersession records misrepresent requirement evolution
Treat spec as one open candidate and permit removal of Clauses introduced only in that candidate (accepted)
- Pros: Uses the existing phase and since fields, Keeps one bump boundary per version lifecycle
- Cons: Version level cannot be changed in place after the candidate is opened
Add explicit candidate retargeting or next-version state (rejected)
- Pros: Allows an open candidate version level to change without abandoned versions
- Cons: Adds lifecycle commands and metadata for an uncommon correction, Weakens the simple meaning of lifecycle-owned version fields
- Rejected because: The additional state and command surface is disproportionate when candidate scope can be completed before selecting the next version
ADR-0055: Separate current show projections from archival rendering
Status: accepted | Date: 2026-07-21
Tags:
cli
References: ADR-0022, RFC-0002:C-SHOW-PROJECTION
Context
ADR-0022 established side-effect-free show commands by reusing Markdown renderers. RFC-0002:C-SHOW-PROJECTION now separates the agent-facing current view from the complete archival projection. The implementation must preserve one rendering pipeline, keep generated documentation lossless, and avoid schema changes in structured output.
Decision
We will pass an explicit projection mode through the shared Markdown renderers. File-writing render paths select the archival mode, human-readable show paths select the current mode unless history is requested, and structured output bypasses Markdown projection. This keeps formatting ownership centralized, makes caller intent explicit, and avoids post-processing rendered text.
Consequences
Positive: show and render can differ without duplicating formatting or lifecycle metadata. Negative: a caller selecting the wrong mode can expose obsolete bodies or produce an incomplete archive; focused mode-selection tests mitigate this risk. Neutral: structured serialization remains outside the Markdown projection path, and ADR-0022 remains the authority for providing show commands.
Alternatives Considered
Keep one archival renderer mode for both show and render (rejected)
- Pros: No renderer API change
- Cons: Agent-facing show continues to include obsolete bodies
- Rejected because: It continues exposing obsolete normative text in the default agent-facing read path.
Build separate show renderers or remove bodies after rendering (rejected)
- Pros: Keeps archival renderer signatures unchanged
- Cons: Duplicates formatting rules or relies on fragile post-processing
- Rejected because: It creates a second formatting authority or depends on post-processing rendered text, both of which can drift from archival output.
Pass an explicit projection mode through shared renderers (accepted)
- Pros: Keeps formatting and lifecycle metadata in one rendering pipeline
- Cons: Requires every renderer caller to choose projection intent
ADR-0056: Adopt a canonical-only compatibility boundary
Status: accepted | Date: 2026-07-25
Tags:
cli,editing,schema,migration
References: ADR-0037, ADR-0030, ADR-0034, RFC-0002, RFC-0006, RFC-0002:C-COMPATIBILITY-BOUNDARY, RFC-0002:C-CRUD-VERBS, RFC-0006:C-LOOP-STATE-STORAGE, ADR-0047
Context
ADR-0037 established canonical path-oriented edit while retaining shorthand verbs during migration. ADR-0030 selected strict full-input path parsing while retaining aliases and wire-layout prefixes. ADR-0034 selected canonical TOML with a migration boundary, and ADR-0047 removed journal from the editable Work Item surface while allowing historical rendering. These transitional policies now duplicate command documentation, expand agent choice, preserve silent input tolerance, and require broad compatibility tests. The governing constraints are the canonical resource contract in RFC-0002:C-CRUD-VERBS, the explicit schema-3 boundary and safety diagnostics in RFC-0002:C-COMPATIBILITY-BOUNDARY, the loop-state model in RFC-0006:C-LOOP-STATE-STORAGE, and preservation of conforming governance history.
Decision
We will adopt one canonical-only compatibility boundary in the breaking release because:
- One migration event lets automation move directly to the retained interface instead of crossing several temporary states.
- CLI help, describe metadata, skills, guides, and tests can describe one mutation grammar and one repository baseline.
- Compatibility code can be removed rather than carried through another deprecation cycle.
This decision supplies the rationale for RFC-0002:C-COMPATIBILITY-BOUNDARY; that RFC clause owns the exact accepted syntax, schema baseline, migration eligibility, and diagnostics. We preserve the canonical edit direction from ADR-0037, strict full-input parsing from ADR-0030, canonical TOML from ADR-0034, and the loop-centric Work Item boundary from ADR-0047. We end only their transitional compatibility policies: sibling mutation-verb sugar, path aliases and wire-layout prefixes, pre-baseline migration branches, and legacy inline-journal rendering.
Consequences
Positive
- CLI help, describe metadata, skills, guides, and tests converge on one mutation grammar.
- Repository loading and migration have one documented support baseline.
- Compatibility normalization and silent-tolerance branches leave the runtime instead of remaining permanent maintenance obligations.
Negative
- Existing scripts using aliases, sibling mutation verbs, or resource-specific shortcuts require coordinated updates. The breaking-release notes provide command translations.
- Repositories below the RFC-defined schema baseline require an earlier compatible govctl version before upgrading. The unsupported-schema diagnostic identifies that prerequisite.
- Legacy inline Work Item journal data is not retained by the new binary. Users must export any history they need with a compatible earlier version before crossing the boundary.
Neutral
- Canonical edit semantics, strict path parsing, TOML storage, loop-centric execution state, released changelog content, and conforming historical artifacts remain in force.
- The RFC, rather than this ADR, defines the exact external contract and schema version.
Alternatives Considered
Keep all existing compatibility surfaces indefinitely (rejected)
- Pros: Avoids breaking existing scripts and old repositories
- Cons: Preserves duplicated CLI and storage paths without an end state
- Rejected because: Indefinite compatibility conflicts with the goal of a small canonical interface and keeps migration complexity in every future release
Remove compatibility surfaces gradually across several releases (rejected)
- Pros: Spreads user migration work over time
- Cons: Extends the period where every authoring surface must explain two grammars and multiple storage generations
- Rejected because: A coordinated breaking release gives users one explicit migration event and lets implementation, documentation, and tests converge atomically
Adopt one canonical-only boundary in the breaking release (accepted)
- Pros: Leaves one mutation grammar and one supported repository baseline, Allows help, describe metadata, skills, docs, and tests to teach the same interface
- Cons: Requires users to update scripts and migrate older repositories before upgrading
ADR-0057: Prefer policy-oriented agent guidance
Status: accepted | Date: 2026-07-26
Tags:
skills-agents
References: ADR-0024, ADR-0042, ADR-0056, RFC-0000, ADR-0015
Context
govctl’s bundled agent layer has grown through repeated corrections to workflow skills, writer guidance, project instructions, CLI help, and user guides. The current .claude/skills/*/SKILL.md corpus contains 2,976 lines and more than 350 govctl command references. Several workflow skills exceed the progressive-disclosure limit recorded in ADR-0024, while recent fixes show that detailed instructions can preserve removed commands, trigger duplicate verification, and steer agents into unnecessary lifecycle churn.
Problem Statement
The guidance was optimized for agents that needed explicit procedural sequencing. Newer agents can often infer local steps from repository state, code, and tool feedback, but the repository has not yet demonstrated that less procedural guidance preserves governance compliance across supported capability levels. The design problem is therefore how to reduce duplicated procedure without weakening authority boundaries, hard stops, recovery for weaker agents, or completion evidence.
Constraints
- RFCs remain the source of normative obligations; ADRs explain design choices and consequences.
- ADR-0024 keeps writing guidance in skills and independent review in agents.
- ADR-0042 demonstrates that important structural invariants belong in executable gates rather than prose alone.
- ADR-0056 establishes one canonical CLI and storage surface.
- ADR-0015 establishes self-describing CLI metadata while acknowledging that semantic usage guidance remains manually maintained.
- Skills must remain useful across agent implementations with different capabilities.
- Human guides still need explanatory depth and complete historical context.
- Reducing guidance must not weaken lifecycle authority, approval boundaries, artifact roles, discovery of uncommon safety conditions, or final verification expectations.
Decision
We will make the bundled agent guidance policy-oriented while retaining a compact operational baseline. Every workflow skill will identify its purpose, required preflight or discovery entrypoint, hard stops that require escalation or authorization, policy for choosing the next action, and evidence that defines completion. This baseline keeps weaker agents recoverable without prescribing every intermediate command to stronger agents.
We choose this approach because it gives changing information one owner, adapts to different agent capabilities through explicit discovery rather than duplicated prose, and retains safety-critical guidance according to risk rather than frequency or an arbitrary line count.
The agent layer will use the following information ownership model:
| Content | Owner | Skill treatment |
|---|---|---|
| Normative obligations and lifecycle invariants | RFCs | Reference the governing artifact; keep the hard stop or decision trigger needed for the workflow |
| Design rationale | ADRs | Reference when it constrains a choice; do not reproduce the decision history |
| Repository-specific authority and safety boundaries | Project instructions | Keep concise and always available |
| Task strategy, escalation triggers, discovery route, and completion evidence | Relevant skill | Keep inline as the operational baseline |
| Current syntax, state, validation, and actionable recovery | Canonical CLI help, status/describe output, schemas, diagnostics, and guards | Query only where the surface has been verified to expose the needed information; otherwise retain concise guidance or a stable reference route |
| Explanation, worked examples, and uncommon recovery detail | Human guides or indexed on-demand references | Keep out of the core skill, but name the trigger and stable discovery route when omission would make the material hard to find |
RFCs remain authoritative when these surfaces disagree; executable surfaces enforce or expose obligations but do not replace them. Project authorization boundaries still apply before a lifecycle mutation. Canonical CLI output owns current syntax and repository state, but this decision does not assume that every recovery path is already complete. Missing discovery or recovery capability remains inline or in a stable referenced fallback until separately implemented under any required RFC amendment.
Progressive disclosure will be driven by risk, discoverability, and relevance rather than a fixed line limit. A fact stays inline when omitting it could cause an unsafe or invalid common-path action, when it gates an irreversible or high-cost operation, or when the agent would not reliably discover the owning surface before acting. Other changing syntax, detailed examples, rare branches, and background explanation move to their owning surface only after a stable discovery route exists. If an agent cannot establish authoritative state or reach the named fallback, it stops before mutation rather than inferring permission.
The migration will be staged. Before prior guidance is retired, representative common-path, recovery, and lifecycle-sensitive tasks will be compared across stronger and weaker agent profiles. Completion rate, lifecycle or authorization errors, recovery success, duplicate verification, and tool-call overhead form the evaluation evidence. A new safety-boundary regression blocks that removal and retains or restores the prior guidance while the ownership or discovery gap is corrected.
Remaining executable examples should receive automated drift coverage where practical. Generated command reference remains useful as an on-demand CLI or documentation surface, but not as content injected into every skill invocation.
This decision replaces the fixed 250-line skill constraint in ADR-0024 with the risk, ownership, and discovery test above. The writer-skill and reviewer-agent split from that ADR remains in force.
Consequences
Positive
- Hard governance boundaries receive more attention because they compete with less procedural text.
- Capable agents can choose shorter paths from actual repository state instead of following generic recipes.
- Weaker agents retain a common preflight, explicit escalation triggers, and a stable route to deeper guidance.
- CLI syntax and state recovery have fewer duplicated documentation surfaces.
- Skill maintenance focuses on durable policy and quality judgment rather than command churn.
- Staged comparison makes the premise testable instead of assuming that shorter guidance is safer.
- Independent review remains available for decisions where cognitive isolation adds value.
Negative
- Less capable or poorly tooled agents could miss guidance and cross a lifecycle or authorization boundary (mitigation: keep safety triggers inline, require a stable fallback, compare capability profiles, and block removal on any new safety regression).
- Less capable agents may make more exploratory tool calls (mitigation: every workflow skill retains a discovery entrypoint and verified canonical surfaces provide actionable recovery where available).
- The initial rewrite requires judgment about information ownership (mitigation: classify each retained item with the shared ownership model and review representative workflows before deletion).
- Some uncommon workflows become less immediately visible (mitigation: retain an inline trigger and stable indexed route whenever the material is otherwise hard to discover).
- Drift checks for remaining executable examples add test maintenance (mitigation: retain examples only when they communicate semantics that canonical help does not already expose).
- Future model regressions could change the appropriate balance (mitigation: keep the operational baseline capability-neutral and preserve staged evaluation evidence so guidance can be restored or expanded).
Neutral
- This decision does not change RFC, ADR, Work Item, or lifecycle semantics.
- It does not establish a blanket requirement that current CLI recovery surfaces are complete; missing product behavior requires its own specification and implementation path.
- Human documentation may remain detailed when that depth serves learning or reference use rather than agent control.
- Skill size remains a review signal, but no line-count target substitutes for information ownership, risk, and discoverability.
Alternatives Considered
Procedural guidance: Keep comprehensive step-by-step skills, command references, recovery recipes, and checklists as the primary control mechanism. (rejected)
- Pros: Works predictably with less capable agents, Keeps uncommon recovery procedures immediately visible
- Cons: Duplicates commands and rules across several maintained surfaces, Encourages mechanical execution and repeated validation
- Rejected because: The accumulated drift and execution churn show that exhaustive prose is no longer a reliable control surface.
Policy plus discovery: Keep purpose, a compact safety and discovery baseline, decision policy, and completion conditions in skills; obtain changing syntax and current state from canonical CLI surfaces; retain detailed explanation in human guides or indexed on-demand references. (accepted)
- Pros: Keeps high-value boundaries salient while allowing contextual planning, Moves changing syntax and state-dependent advice to executable sources
- Cons: Requires better CLI diagnostics and discovery surfaces, Very weak agents may need to query more context
Tool-only guidance: Remove most workflow and writer skills, relying almost entirely on model judgment and CLI validation. (rejected)
- Pros: Minimizes prompt size and maintenance cost
- Cons: Leaves authority and approval boundaries too implicit, Makes safe behavior depend heavily on model quality
- Rejected because: Tool validation cannot express every governance judgment, escalation boundary, or artifact-authority distinction.
Always-loaded generated fallback: Keep concise policies plus a comprehensive procedural appendix generated from command metadata in the content loaded for every skill invocation. (rejected)
- Pros: Reduces syntax drift in procedural references, Provides a capability-neutral fallback for weaker agents
- Cons: Command metadata cannot generate governance judgment or cross-command workflow policy, Bundling the generated fallback still consumes attention on every invocation
- Rejected because: Generated command reference is useful as an on-demand discovery surface and is incorporated into the chosen approach in that role. Loading the full generated appendix on every invocation would recreate the prompt competition this decision addresses.
ADR-0058: Use parser-owned CLI introspection
Status: accepted | Date: 2026-07-26
Tags:
cli
References: RFC-0002:C-DESCRIBE-COMMAND, ADR-0015
Context
ADR-0015 coupled CLI discovery to a separately maintained catalogue of workflow advice, examples, and prerequisites. As the command surface and agent skills evolved, its work-first typical sequence contradicted the guide’s RFC-first workflow, while context mode enumerated terminal history that was not actionable. RFC-0002:C-DESCRIBE-COMMAND now defines a versioned low-noise introspection contract.
Decision
Replace ADR-0015 with CLI-parser-owned command discovery and limit context mode to lifecycle counts, non-terminal records, and read-only discovery commands. This retires the separate semantic catalogue, terminal-record enumeration, and state-based transition recommendations. RFCs and installed skills remain the authority for workflow policy.
Consequences
Positive: command changes appear in introspection without catalogue edits, and terminal history no longer scales agent context. Negative: schema v1 consumers must migrate with the coordinated major govctl release, and describe no longer provides task-specific coaching. The schema version makes compatibility explicit, while resource help, RFCs, and installed skills retain syntax and procedural guidance. Neutral: describe remains a CLI-only integration surface.
Alternatives Considered
Derive command discovery from the CLI parser and keep workflow policy in RFCs and skills. (accepted)
- Pros: Eliminates a second command catalogue and its drift., Keeps agent context bounded to current actionable state.
- Cons: Describe no longer provides task-specific coaching.
Continue maintaining semantic command guidance inside describe. (rejected)
- Pros: Provides richer guidance in one response.
- Cons: Duplicates parser metadata and workflow policy that already have authoritative owners.
- Rejected because: The recurring synchronization cost and stale instructions outweigh the extra coaching.
ADR-0059: Use project-root selection with layered ignore rules
Status: accepted | Date: 2026-07-30
Tags:
validation
References: RFC-0009, ADR-0009
Context
ADR-0009 selected source files through configured roots and extensions. Large repositories exposed the cost of enumerating excluded subtrees before applying exclusions, while users also needed familiar precedence and re-inclusion semantics across project defaults and governance-specific overrides. RFC-0009 defines the replacement selection contract.
Decision
Replace ADR-0009 with project-root traversal constrained by positive include patterns and layered gitignore-compatible ignore files. This direction was chosen because it applies exclusion during traversal and gives projects one established rule model for baseline and governance-specific selection.
Consequences
Positive: excluded subtrees can be pruned before enumeration, and repository conventions remain reusable. Negative: selection behavior spans configuration plus ignore files, so debugging precedence requires considering both. Replacing roots, extensions, and exclusions changes the schema and can change the selected file set; RFC-0009:C-IGNORE-MIGRATION owns that compatibility boundary. Neutral: source-reference extraction and validation remain separate from file selection.
Alternatives Considered
Walk the project root using positive include patterns and layered gitignore-compatible rules. (accepted)
- Pros: Prunes irrelevant directories before enumeration., Reuses a familiar precedence and re-inclusion model.
- Cons: Selection now depends on ordered ignore files in addition to configuration.
Retain configured roots and extensions while applying layered gitignore-compatible rules during traversal. (rejected)
- Pros: Keeps explicit coarse traversal bounds and reduces configuration migration.
- Cons: Maintains separate roots, extensions, positive selection, and ignore concepts for one file-selection decision.
- Rejected because: Traversal-time pruning solves the performance issue, but retaining independent roots and extension axes adds configuration surface that positive path patterns already express.
Use project-root positive include patterns with a dedicated .govignore only. (rejected)
- Pros: Keeps governance selection isolated from Git configuration.
- Cons: Duplicates repository-wide exclusions and lets source scanning drift from established project boundaries.
- Rejected because: Reusing .gitignore as a baseline avoids duplicating the dominant repository exclusion policy while .govignore remains an explicit override layer.
ADR-0060: Build releases with Zig and preserve target aliases
Status: accepted | Date: 2026-07-30
Tags:
release
References: RFC-0002:C-SELF-UPDATE, ADR-0041, RFC-0002:C-PRE-1-RELEASE-TARGET-COMPATIBILITY
Context
ADR-0041 aligned self-update and cargo-binstall with five target-specific assets built on native and cross runners. Cross-built candidates for the six targets now governed by RFC-0002:C-PRE-1-RELEASE-TARGET-COMPATIBILITY ran successfully on matching native OS and architecture runners during evaluation. The remaining design question is how to produce those binaries and preserve the pre-1.0 target aliases without retaining duplicate toolchains or obscuring canonical compiler provenance.
Decision
Replace ADR-0041’s build and distribution choice with one pinned Linux Zig build environment for the canonical targets defined by RFC-0002:C-PRE-1-RELEASE-TARGET-COMPATIBILITY. Produce each compatibility alias by repackaging its mapped canonical executable rather than compiling a legacy variant. This direction keeps canonical artifact names aligned with compilation targets while confining pre-1.0 compatibility names to the packaging boundary. Because cross-compilation alone does not establish runtime compatibility, retain native OS and architecture coverage as a risk mitigation.
Consequences
Positive: one build environment reduces runner and toolchain divergence, Linux binaries become portable musl executables, Windows ARM gains a release path, and the RFC-governed aliases preserve pre-1.0 update paths without duplicate builds. Negative: 0.x releases carry four duplicate archives and depend on a pinned Zig container plus an auditable macOS SDK source; native smoke runners remain necessary. Alias filenames describe compatibility identity rather than compiler provenance, which can confuse SBOM, attestation, and debugging consumers; the canonical archive remains the provenance source and byte equality keeps the mapping verifiable. Neutral: macOS target names remain unchanged, and the alias mechanism ends at the RFC’s 1.0 boundary.
Alternatives Considered
Build six canonical Zig targets and publish compatibility alias archives from the same binaries. (accepted)
- Pros: Preserves old updater and cargo-binstall asset resolution without retaining duplicate toolchains., Keeps canonical artifact names truthful to their compilation targets.
- Cons: Adds four duplicate archives to every release.
Replace legacy GNU and MSVC assets with only the new Zig target assets. (rejected)
- Pros: Publishes the smallest possible asset set.
- Cons: Breaks updates from binaries that still request legacy target names.
- Rejected because: An immutable older updater cannot discover a renamed asset in the latest release, so a one-time bridge release is insufficient for users who skip versions.
Retain the existing native and cross-runner release build matrix. (rejected)
- Pros: Preserves the current five asset targets without compatibility packaging.
- Cons: Retains divergent toolchains, scarce macOS build usage, and no Windows ARM artifact.
- Rejected because: The spike demonstrated that one pinned Linux build environment can produce all required binaries while native smoke jobs preserve runtime evidence.
Publish only the established GNU and MSVC asset names and map newly built updaters to those distribution identifiers. (rejected)
- Pros: Avoids duplicate archives while preserving filenames known to older clients.
- Cons: Makes canonical asset names misrepresent the compilation target and requires permanent updater target mapping.
- Rejected because: Keeping truthful canonical target archives makes build provenance inspectable, while temporary duplicate packaging is bounded to pre-1.0 releases by the governing RFC.
ADR-0061: Use one agent integration command with client-specific projections
Status: accepted | Date: 2026-07-31
Tags:
skills-agents,plugin
References: RFC-0002:C-AGENT-INTEGRATION, ADR-0033, ADR-0035
Context
govctl currently offers two disconnected installation paths. Claude users install a native plugin that carries skills, reviewer agents, and hooks, while Codex users run init-skills --format codex to project shared skills and generated TOML reviewer roles. Codex native plugins carry skills and hooks but do not define standalone custom-agent roles, so treating the clients as one package model leaves Codex reviews unavailable or stale. Manual native CLI instructions also duplicate marketplace, preflight, partial-failure, and update handling that the agent-plugin-installer crate already centralizes.
Decision
Use one govctl agent command group as the user-facing facade for doctor, install, and update operations. Materialize the plugin assets bundled with the running binary at a stable user-scoped support path and delegate native marketplace/plugin orchestration to agent-plugin-installer. Both clients receive skills and hooks through their native plugin mechanism. Claude also loads its Markdown reviewer agents from the plugin, while Codex receives reviewer roles through a separate generated TOML projection because its custom-agent contract uses standalone files. Retain init-skills for project-local and custom-directory copies.
Package separate Claude and Codex hook manifests because their event fields and output contracts differ. Route both manifests to a small govctl adapter that owns shared project discovery and context semantics. Keep hooks limited to compact governed-project context at session start and non-blocking guidance before direct edits to lifecycle-managed artifacts; do not use stop hooks for repeated validation.
Consequences
Positive: users get one discoverable workflow, plugin content stays aligned with the running govctl version, native client diagnostics remain structured, and Codex reviewer roles use the format Codex actually loads. Runtime-specific hook manifests avoid accidental protocol compatibility, while the shared adapter keeps governance semantics aligned and stays silent outside governed projects. Negative: Codex installation still has a second projection step behind the facade, update can replace the four govctl-owned reviewer-role files, and the binary gains a small orchestration dependency plus persistent support files. Hook guidance is intentionally advisory and therefore cannot enforce canonical mutation paths. Neutral: Claude and Codex remain different internally, existing manual plugin commands continue to work, direct editing remains available when the CLI lacks an operation, and init-skills remains available for local or non-plugin consumers.
Alternatives Considered
Use one agent integration command with client-specific projections. (accepted)
- Pros: Gives users one workflow while preserving the formats each client actually loads., Keeps bundled plugin assets and generated reviewer roles on the running govctl version.
- Cons: Requires a Codex-specific role projection behind the common facade.
Expand init-skills with native plugin lifecycle flags. (rejected)
- Pros: Reuses an existing command name.
- Cons: Mixes project-local file projection, user-global plugin state, overwrite flags, and lifecycle operations in one option matrix.
- Rejected because: The combined surface makes install and update intent less recoverable and weakens the existing single-purpose init-skills contract.
Rely entirely on each client’s native plugin package. (rejected)
- Pros: Minimizes govctl-side projection code.
- Cons: Codex native plugins do not provide standalone custom-agent TOML roles.
- Rejected because: The approach installs common skills but does not deliver the reviewer agents that are part of the govctl workflow.
ADR-0062: Branch-versioned governance with a shared coordination registry
Status: accepted | Date: 2026-09-08
Tags:
collaboration
References: RFC-0010, RFC-0004, ADR-0020, ADR-0025
Context
Multi-agent parallel development increasingly runs agents in separate working trees of one repository clone — git worktrees or jj workspaces — so that each agent works on its own branch without disturbing the others. govctl’s current design assumes a single checkout in four ways:
- The gov-root lock file adopted in ADR-0025 to satisfy RFC-0004 lives inside the checkout, so it provides no mutual exclusion across working trees; ADR-0025 deliberately scoped it to same-repository concurrent processes.
- Sequential identifiers for RFCs and ADRs collide when two branches create artifacts in parallel. ADR-0020 added collision-safe work item ID strategies, which cover work items across parallel branches and clones, but RFC/ADR numbering remains unaddressed.
- Shared mutable files such as releases.toml and the changelog receive edits from every branch and conflict at merge time.
- Agents in separate working trees cannot see each other’s active work items, so two agents may silently duplicate the same work.
Two requirements pull in opposite directions. Coordination state — ID allocation, active-work visibility, version-change exclusion — wants a single live source shared by all agents. Governance content — RFC and ADR text — must remain versioned with the branch so changes travel through pull request review, which rules out moving gov/ to a shared singleton outside the tree.
Decision drivers: pull-request review of governance content is non-negotiable; the target scenario is same-machine parallel agents sharing version-control metadata; no daemon or network service is acceptable (per ADR-0025); single-checkout behavior must remain unchanged.
The normative behavior decided here is specified in RFC-0010.
Decision
Adopt branch-versioned governance with a shared per-clone coordination registry.
Governance artifacts stay exactly where they are: gov/ remains versioned with the branch, and every content change travels through pull request review. Coordination state moves out of the working tree into a registry stored in VCS-shared repository storage — the git common directory or the jj repository store — namespaced per governed project root, so all working trees of a clone observe and update the same records without a daemon.
The two coordination mechanisms compose by layer: the RFC-0004 concurrency mechanism serializes mutations of the gov tree within one checkout, while the registry coordinates allocation, claims, and presence across working trees of the clone.
Three mechanisms live in the registry. ID reservation binds each newly generated artifact identifier to its owning workspace at creation time, which removes cross-branch numbering collisions by construction. Artifact claims give version-semantics operations on an RFC — bump, finalize, advance, deprecate, supersede — exclusive, expiring ownership, while plain content edits receive only a non-blocking warning; claims can be released or taken over explicitly, and takeovers are recorded. Presence records publish which work items each workspace is actively executing, surfaced through govctl status.
Commands are classified by scope. Read-only and local-execution commands run in any workspace. Content commands run in any workspace subject to reservation and claims. Release cutting and governance-format migration run only in the primary workspace and refuse elsewhere with an actionable diagnostic. When shared storage or the primary workspace cannot be determined, commands degrade to single-checkout behavior with a warning.
Consequences
Positive:
- Parallel agents in separate worktrees can create RFCs, ADRs, and work items without ever colliding on identifiers, so merging parallel branches introduces only new files.
- Two agents can no longer unknowingly bump or finalize the same RFC in parallel, and each agent can see which work items other workspaces are executing.
- Release cutting and format migration gain a single point of execution, replacing a class of merge conflicts on shared files with an explicit, actionable refusal.
- Governance content keeps its pull request review path and its audit link to code history.
Negative:
- The registry is a second coordination mechanism beside the RFC-0004 gov-root lock, with its own atomicity, liveness, and expiry rules to implement and maintain.
- Registry state is not fully derivable from governed artifacts: losing it reverts the system to pre-registry collision risk for unmerged work until new activity repopulates it.
- Claim expiry relies on inactivity periods, so a crashed agent’s claim can block a live claim holder until expiry or an explicit takeover.
- Coordination covers one clone only; cross-clone work items rely on ADR-0020 identifier strategies, while cross-clone RFC/ADR numbering rests on merge discipline alone.
Neutral:
- Work item activation becomes visible immediately through the registry, while the work item file’s status field catches up at merge time; tooling that reads status treats the registry view as the live overlay.
- No merge drivers or post-merge reconciliation commands are introduced, because reservation and trunk-scoping remove the conflicts they would have addressed.
Alternatives Considered
Keep governance artifacts versioned with the branch and add a shared per-clone coordination registry holding ID reservations, artifact claims, and presence records (accepted)
- Pros: Governance content stays in the branch and travels through pull request review unchanged, ID collisions across parallel branches are prevented at creation time, so merges of new artifacts are pure additions, Agents gain cross-workspace visibility of active work and exclusive claims on RFC version-semantics operations, No daemon or network service; the registry lives in VCS-shared storage that already exists, Single-checkout and no-VCS behavior is unchanged apart from a warning
- Cons: Introduces a second coordination mechanism alongside the RFC-0004 gov-root lock, with its own liveness and expiry rules, Work item status is eventually consistent: activation is a live registry record until the branch merge lands the file change, Clone-level coordination only; cross-clone work items rely on ADR-0020 identifier strategies, while cross-clone RFC/ADR numbering rests on merge discipline alone
Share a single governance root across all workspaces of a clone, redirecting every worktree’s gov/ to the primary checkout (rejected)
- Pros: Single live source of truth; the existing gov-root lock becomes global across workspaces with no new mechanism
- Cons: Governance content is no longer versioned with the branch, so pull requests cannot carry or review RFC and ADR changes, Checking out an old branch would show current governance state, breaking the audit link between decisions and code history
- Rejected because: Violates the non-negotiable driver that governance content must remain branch-versioned and reviewable in pull requests.
Split gov/ physically: content artifacts stay branch-versioned while coordination artifacts move to a shared location (rejected)
- Pros: Gives content and coordination state their natural storage without an overlay layer
- Cons: gov/ becomes part local, part redirected, which complicates configuration resolution and the mental model, The content-versus-coordination classification is disputed: work item criteria read like content, while guards must travel with the code they verify
- Rejected because: Split-tree complexity and a contested artifact classification buy little over the registry overlay, which leaves gov/ untouched.
Documentation-only discipline: recommend collision-safe ID strategies and one-agent-per-worktree conventions without tooling changes (rejected)
- Pros: No implementation cost
- Cons: RFC and ADR numbering still collides across branches, and agents still cannot see each other’s active work
- Rejected because: Leaves the collision and invisibility problems in place and depends on every agent consistently following convention.