Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.json + clauses/
├── adr/                  # ADR-NNNN-*.toml
└── work/                 # WI-YYYY-MM-DD-NNN-*.toml

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

  1. Read RFC-0000 to understand the governance model
  2. Follow the Getting Started guide to install and initialize
  3. 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.85+ (uses edition 2024)

Installation

# From crates.io
cargo install govctl

# With TUI dashboard feature
cargo install govctl --features tui

# Or build from source
git clone https://github.com/govctl-org/govctl
cd govctl
cargo build --release
# Binary at ./target/release/govctl

# Build with TUI
cargo build --release --features tui

Optional Features

FeatureDescriptionDependencies
tuiInteractive terminal dashboard (govctl tui)ratatui, crossterm

Initialize a Project

govctl init

This creates the governance directory structure:

gov/
├── config.toml       # Configuration
├── rfc/              # RFC sources
├── adr/              # ADR sources
├── work/             # Work item sources
├── schema/           # JSON schemas
└── templates/        # New artifact templates

Create Your First RFC

govctl new rfc "Feature Title"

This creates gov/rfc/RFC-0000/rfc.json with the RFC metadata.

Add a Clause

RFCs are composed of clauses — atomic units of specification:

govctl new clause RFC-0000:C-SCOPE "Scope" -s "Specification" -k normative

Edit Clause Content

govctl edit RFC-0000:C-SCOPE --stdin <<'EOF'
The feature MUST do X.
The feature SHOULD do Y.
EOF

Validate Everything

govctl check

This validates all governance artifacts against the schema and phase rules.

Render to Markdown

govctl render

Generates human-readable markdown in docs/rfc/RFC-0000.md.

Next Steps

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 new rfc "Feature Title"

# Specify ID manually
govctl new rfc "Feature Title" --id RFC-0010

RFC Structure

An RFC consists of:

  • Metadata (rfc.json) — ID, title, status, phase, version
  • Clauses — Atomic units of specification

Working with Clauses

Create a Clause

govctl new clause RFC-0010:C-SCOPE "Scope" -s "Specification" -k normative

Options:

  • -s, --section — Section name (e.g., “Specification”, “Rationale”)
  • -k, --kindnormative (binding) or informative (explanatory)

Edit Clause Text

# From stdin
govctl edit RFC-0010:C-SCOPE --stdin <<'EOF'
The system MUST validate all inputs.
The system SHOULD log validation failures.
EOF

# Open in editor
govctl edit RFC-0010:C-SCOPE

List Clauses

govctl list clause
govctl list clause --rfc RFC-0010

Status Lifecycle

RFCs have three statuses:

draft → normative → deprecated

Finalize to Normative

When the spec is complete and approved:

govctl finalize RFC-0010 normative

This makes the RFC binding — implementation must conform to it.

Deprecate

When an RFC is superseded or obsolete:

govctl finalize RFC-0010 deprecated

Phase Lifecycle

RFCs progress through four phases:

spec → impl → test → stable

Advance Phase

govctl advance RFC-0010 impl    # Ready for implementation
govctl advance RFC-0010 test    # Implementation complete, ready for testing
govctl advance RFC-0010 stable  # Tested, ready for production

Phase transitions are gated:

  • spec → impl requires status = normative
  • Each phase has invariants that must be satisfied

Versioning

RFCs use semantic versioning:

# Bump version with changelog entry
govctl bump RFC-0010 --patch -m "Fix typo in clause C-SCOPE"
govctl bump RFC-0010 --minor -m "Add new clause for edge case"
govctl bump RFC-0010 --major -m "Breaking change to API contract"

Listing RFCs

govctl list rfc
govctl list rfc --status normative
govctl list rfc --phase impl

Working with ADRs

ADRs (Architectural Decision Records) document significant design choices. They explain why things are built a certain way.

Creating ADRs

govctl new adr "Use Redis for caching"

This creates a TOML file in gov/adr/ with the decision context.

ADR Structure

ADRs contain:

  • Context — The situation requiring a decision
  • Decision — What was decided
  • Consequences — Expected outcomes (positive and negative)
  • Statusproposed, accepted, deprecated, or superseded

Editing ADRs

ADRs are TOML files — edit them directly or use govctl:

govctl edit ADR-0003

Status Lifecycle

proposed → accepted → deprecated
                   ↘ superseded

Accept a Decision

When consensus is reached:

govctl accept ADR-0003

Deprecate

When a decision is no longer relevant:

govctl deprecate ADR-0003

Supersede

When a new decision replaces an old one:

govctl supersede ADR-0001 --by ADR-0005

This marks ADR-0001 as superseded and records ADR-0005 as its replacement.

Listing ADRs

govctl list adr
govctl list adr --status accepted

Why TOML?

ADRs use TOML (not JSON or YAML) because:

  • Comments allowed — Humans can annotate inline
  • Multi-line strings — Clean """ blocks for prose
  • No YAML ambiguityNO stays NO, not false
  • Round-trip stable — Deterministic serialization

Working with Work Items

Work Items track units of work from inception to completion. They provide an audit trail of what was done and when.

Creating Work Items

# Create in queue (pending)
govctl new work "Implement caching layer"

# Create and activate immediately
govctl new work --active "Urgent bug fix"

Work items are automatically assigned IDs like WI-2026-01-17-001.

Work Item Structure

Work items contain:

  • Title — Brief description
  • Notes — Detailed context (array of strings)
  • Acceptance Criteria — Checkable completion criteria
  • Refs — Links to related RFCs, ADRs, or external resources

Status Lifecycle

queue → active → done
              ↘ blocked
              ↘ cancelled

Move Between States

# By ID
govctl mv WI-2026-01-17-001 active
govctl mv WI-2026-01-17-001 done

# By filename (without path)
govctl mv implement-caching.toml active

Acceptance Criteria

Add Criteria

govctl add WI-2026-01-17-001 acceptance_criteria "Unit tests pass"
govctl add WI-2026-01-17-001 acceptance_criteria "Documentation updated"

Mark Criteria Complete

govctl tick WI-2026-01-17-001 acceptance_criteria "Unit tests" -s done

The pattern matches case-insensitively by substring.

Notes

Add context or progress notes:

govctl add WI-2026-01-17-001 notes "Discovered edge case in validation"

Removing Items

Remove items from array fields using flexible matching:

# Substring match (default, case-insensitive)
govctl remove WI-2026-01-17-001 notes "edge case"

# Exact match
govctl remove WI-2026-01-17-001 notes "Discovered edge case in validation" --exact

# By index (0-based)
govctl remove WI-2026-01-17-001 notes --at 0

# Negative index (from end)
govctl remove WI-2026-01-17-001 notes --at -1

# Regex pattern
govctl remove WI-2026-01-17-001 refs "RFC-.*" --regex

# Remove all matches
govctl remove WI-2026-01-17-001 refs "obsolete" --all

Listing Work Items

govctl list work
govctl list work queue      # Pending items
govctl list work active     # In progress
govctl list work done       # Completed

Why TOML?

Like ADRs, work items use TOML for human-friendly editing with comments and clean multi-line strings.

Validation & Rendering

govctl provides tools to validate governance artifacts and render them to human-readable formats.

Validation

Check All Artifacts

govctl check

This validates:

  • Schema conformance (all required fields present)
  • Phase discipline (no invalid state transitions)
  • Cross-references (refs point to existing artifacts)
  • Clause structure (normative clauses in spec sections)

Check Specific Types

govctl check rfc
govctl check adr
govctl check work

Exit Codes

  • 0 — All validations passed
  • 1 — Validation errors found

Rendering

Render governance artifacts to markdown for documentation.

Render RFCs

# All RFCs (committed to repo)
govctl render

# Specific RFC
govctl render --rfc-id RFC-0010

Output goes to docs/rfc/RFC-NNNN.md.

Render Other Artifacts

ADRs and work items render to .gitignored local files by default:

govctl render adr      # → docs/adr/
govctl render work     # → docs/work/
govctl render all      # Everything

Hash Signatures

Rendered markdown includes a SHA-256 signature for tampering detection:

<!-- govctl:signature sha256:abc123... -->

If the source changes, the signature won’t match — indicating the rendered doc is stale.

Statistics

Get a summary of your governance state:

govctl stat

Shows:

  • RFC counts by status and phase
  • ADR counts by status
  • Work item counts by status
  • Any validation warnings

Building Documentation

For mdbook integration:

./scripts/build-book.sh          # Build static site
./scripts/build-book.sh --serve  # Live preview

This renders all artifacts and generates the book structure.

RFC-0000: govctl Governance Framework

Version: 1.0.0 | Status: normative | Phase: stable


1. Summary

[RFC-0000:C-SUMMARY] Framework Summary (Informative)

govctl is a governance CLI that manages four 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

All artifacts follow explicit lifecycle states and phase gates to ensure disciplined development.

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.

Every RFC MUST be stored as a JSON file (rfc.json) containing:

  • rfc_id: Unique identifier (e.g., RFC-0001)
  • title: Human-readable title
  • version: Semantic version (MAJOR.MINOR.PATCH)
  • status: Lifecycle state (draft | normative | deprecated)
  • phase: Work stage (spec | impl | test | stable)
  • owners: List of responsible parties
  • sections: Ordered list of sections with clause references
  • changelog: Version history

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: Frozen and ratified. Implementation MUST conform to normative RFCs.

deprecated: Superseded or obsolete. Implementation SHOULD migrate away.

Transition rules:

  • draft → normative: Requires explicit finalization
  • normative → deprecated: Requires a superseding RFC or explicit deprecation
  • Reverse transitions are FORBIDDEN

Since: v1.0.0

[RFC-0000:C-PHASE-LIFECYCLE] RFC Phase Lifecycle (Normative)

RFC phase follows this lifecycle:

spec → impl → test → stable

spec: Defining what will be built. No implementation work permitted.

impl: Building what was specified. Implementation proceeds per spec.

test: Verifying implementation matches specification.

stable: Released for production use.

Phase rules:

  • Phases MUST proceed in order; skipping is FORBIDDEN
  • Each phase transition requires the previous phase gate to pass
  • draft + stable is FORBIDDEN (cannot stabilize unratified work)
  • deprecated + impl/test is FORBIDDEN (no new work on deprecated specs)

Since: v1.0.0


3. Clause Specification

[RFC-0000:C-CLAUSE-DEF] Clause Definition (Normative)

A clause is an individual requirement or statement within an RFC.

Every clause MUST be stored as a JSON file containing:

  • clause_id: Unique identifier within the RFC (e.g., C-PHASE-ORDER)
  • title: Human-readable title
  • kind: normative | informative
  • status: active | superseded | deprecated
  • text: The clause content
  • since: Version when the clause was introduced

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.

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
  • [content] section with: context, decision, consequences

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.

Since: v1.0.0


5. Work Item Specification

[RFC-0000:C-WORK-DEF] Work Item Definition (Normative)

A Work Item tracks a unit of work from inception to completion.

Every Work Item MUST be stored as a TOML file containing:

  • [govctl] section with: id, title, status, refs
  • [content] section with: description, acceptance_criteria, decisions, notes

Work Item status lifecycle:

queue → active → done
    ↘        ↘ cancelled

queue: Planned but not started.

active: Currently in progress. Only one active item recommended per focus area.

done: Completed. All acceptance criteria met.

cancelled: Abandoned from queue or active. Reason documented in notes.

A Work Item MUST NOT transition to done if any acceptance_criteria are pending.

Since: v1.0.0


Changelog

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.1.0 | Status: normative | Phase: stable


1. Summary

[RFC-0001:C-SUMMARY] Summary (Informative)

This RFC defines the lifecycle state machines for all governed artifacts in govctl.

Each artifact type has a finite state machine that governs its lifecycle:

  • RFC: status (draft/normative/deprecated) and phase (spec/impl/test/stable)
  • Work Item: status (queue/active/done/cancelled)
  • ADR: status (proposed/accepted/superseded)
  • Clause: status (active/deprecated/superseded)

Key principles:

  1. State machines are acyclic (no going backward)
  2. Terminal states are final (done, cancelled, superseded, stable)
  3. Transitions may have gate conditions beyond state validity
  4. All transitions are explicit commands (no implicit state changes)

This specification documents what is already implemented in govctl v0.1.0.

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:

  1. draft — Initial state. The RFC is under development and not yet binding.
  2. normative — The RFC defines required behavior. Implementations MUST conform.
  3. 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 finalize command)
  • normative → deprecated (via deprecate command)

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)

Since: v0.1.0

[RFC-0001:C-RFC-PHASE] RFC Phase Transitions (Normative)

An RFC MUST have exactly one of the following phase values:

  1. spec — Specification phase. The RFC text is being written. No implementation work.
  2. impl — Implementation phase. Code is being written to conform to the RFC.
  3. test — Testing phase. Implementation is complete; tests are being written and validated.
  4. stable — Stable phase. Implementation and tests are complete. No further changes expected.

Valid transitions (forward only, via advance command):

  • spec → impl
  • impl → test
  • test → stable

Invalid transitions (MUST be rejected):

  • Any backward transition (e.g., impl → spec)
  • Any skip (e.g., spec → test, spec → stable)
  • stable → any (stable is terminal for phase)

Rationale: Phase discipline ensures specification precedes implementation, and testing validates implementation before stabilization.

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:

  1. queue — Initial state. The work item is defined but not yet started.
  2. active — The work item is currently being worked on.
  3. done — The work item is complete. All acceptance criteria are satisfied.
  4. cancelled — The work item was abandoned. No further work will be done.

Valid transitions (via move command):

  • queue → active (start work)
  • queue → cancelled (abandon before starting)
  • active → done (complete work)
  • active → cancelled (abandon in progress)

Invalid transitions (MUST be rejected):

  • done → any (done is terminal)
  • cancelled → any (cancelled is terminal)
  • queue → done (cannot complete without being active)
  • active → queue (no “un-start”)

Timestamp behavior:

  • queue → active: Sets started date if not already set
  • active → done: Sets completed date
  • active → cancelled: Sets completed date

Since: v0.1.0

[RFC-0001:C-ADR-STATUS] ADR Status Transitions (Normative)

An ADR MUST have exactly one of the following status values:

  1. proposed — Initial state. The decision is under consideration.
  2. accepted — The decision has been accepted and is in effect.
  3. superseded — The decision has been replaced by another ADR.

Valid transitions:

  • proposed → accepted (via accept command)
  • accepted → superseded (via supersede command, requires --by to specify replacement)

Invalid transitions (MUST be rejected):

  • proposed → superseded (cannot supersede without first accepting)
  • accepted → proposed (no “un-accept”)
  • superseded → any (superseded is terminal)

When an ADR is superseded:

  • The superseded_by field MUST be set to the ID of the replacing ADR
  • The replacing ADR SHOULD reference the superseded ADR

Since: v0.1.0

[RFC-0001:C-CLAUSE-STATUS] Clause Status Transitions (Normative)

A Clause MUST have exactly one of the following status values:

  1. active — Default state. The clause is in effect.
  2. deprecated — The clause is no longer recommended but still valid.
  3. superseded — The clause has been replaced by another clause.

Valid transitions:

  • active → deprecated (via deprecate command)
  • active → superseded (via supersede command, requires replacement clause)
  • deprecated → superseded (already deprecated, now replaced)

Invalid transitions (MUST be rejected):

  • deprecated → active (no resurrection)
  • superseded → any (superseded is terminal)

When a clause is superseded:

  • The superseded_by field MUST be set to the ID of the replacing clause
  • The replacing clause SHOULD have a since field indicating the version it was introduced

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:

  1. The work item MUST have at least one acceptance criterion defined
  2. All acceptance criteria MUST have status “done” or “cancelled” (no “pending”)

Rationale: Prevents marking work as complete without defined success criteria.

RFC draft → normative:

  • No additional gates (policy decision, not structural)

RFC phase spec → impl:

  • RFC status SHOULD be normative (warning if draft)

Rationale: Implementation should follow finalized 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.

Since: v0.1.0


Changelog

v0.1.0 (2026-01-17)

Initial draft

ADR-0001: Use TOML for ADRs and Work Items

Status: accepted | Date: 2026-01-17

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

References: RFC-0000

Context

Analysis of the artifact lifecycle state machines revealed several design flaws:

  1. Clause kind vs status duplication: The kind enum includes deprecated alongside normative and informative, but status also has deprecated. This creates confusion about where deprecation state belongs.

  2. ADR missing rejected state: The ADR lifecycle is proposed → accepted → superseded. If a proposal is rejected rather than accepted, there is no state to record this outcome. The alternative is leaving it as proposed forever or deleting it, both of which lose information.

  3. Work Item forced activation before cancellation: The lifecycle queue → active → done|cancelled implies you must start work before abandoning it. This is illogical - planned work can be abandoned before starting.

  4. 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:

  1. Remove deprecated from Clause kind: The kind field should only contain semantic categories (normative, informative). Deprecation is a lifecycle state that belongs in status.

  2. Add rejected to ADR lifecycle: The new lifecycle becomes:

    proposed → accepted → superseded
             → rejected
    

    This allows recording when a proposal was considered but declined.

  3. Allow Work Item queue → cancelled: The new lifecycle becomes:

    queue → active → done
        ↘        ↘ cancelled
    

    Work can be abandoned at any stage.

  4. 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: deprecated will need updating
  • Schema version bump required for breaking changes

Migration:

  • Any clause with kind: deprecated should change to kind: 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

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:

  1. Be overwritten on next govctl render
  2. Create confusion about which version is authoritative
  3. 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:

  1. Collect all source JSON content (RFC metadata + clauses, or ADR/Work Item TOML)
  2. Canonicalize JSON/TOML: sort object keys recursively, normalize whitespace
  3. For RFCs: sort clauses by clause_id before hashing
  4. Compute SHA-256 of the canonical representation
  5. 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 check extracts 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 render to 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

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

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

References: RFC-0000:C-WORK-DEF

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: accepted | Date: 2026-01-17

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

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:

  1. RFCs cannot declare dependencies on ADRs that informed their design
  2. No way to trace which ADRs led to an RFC’s creation
  3. Validation cannot check RFC references for consistency
  4. 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:

  1. Add refs: Vec<String> to RfcSpec model (serde skip_serializing_if empty)
  2. Add diagnostic code E0105RfcRefNotFound for validation errors
  3. Extend validate_artifact_refs() to include RFC refs validation
  4. Support add/remove/get refs operations in edit commands for RFCs
  5. 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: accepted | Date: 2026-01-17

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:

  1. 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)
  2. Default pattern matches RFC-0001:C-NAME and ADR-0001 style references

  3. Scanner walks configured directories, applies pattern, validates extracted IDs against ProjectIndex

  4. New diagnostics: E0107SourceRefUnknown (error), W0107SourceRefOutdated (warning for deprecated/superseded)

  5. 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

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:

  1. Description matches the exact template text
  2. Description is empty or whitespace-only
  3. 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 check until 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

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:

  1. The source_scan feature uses [[artifact-id]] pattern to detect references in source code
  2. Users might expect the same pattern to work in content fields
  3. 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:

  1. Use the same pattern from source_scan.pattern config (defaults to [[RFC-NNNN]] format)
  2. Expand matched references using existing ref_link() function
  3. Apply to: description, context, decision, consequences, notes, acceptance_criteria text
  4. 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_scan pattern 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

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

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)
  • Add category field to ChecklistItem (criterion level) with prefix parsing

ADR-0014: Release management with releases.toml

Status: accepted | Date: 2026-01-17

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-2026-01-17-029", "WI-2026-01-17-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
  • Store releases in single gov/releases.toml with explicit refs

ADR-0015: Context-aware self-describing CLI for agent discoverability

Status: accepted | Date: 2026-01-18

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:

  1. MCP (Model Context Protocol) — adds structured tool definitions, but requires server setup, process management, and creates a parallel interface to maintain
  2. Agent guide files (.claude/CLAUDE.md) — static, requires manual updates, doesn’t reflect current project state
  3. --help output — 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 version
  • purpose: one-line description of govctl’s role
  • philosophy: core principles (RFC supremacy, phase discipline)
  • commands[]: for each command:
    • name: command name (e.g., “new rfc”, “advance”)
    • purpose: what it does
    • when_to_use: semantic guidance on when to invoke
    • example: concrete usage
    • prerequisites: 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/phases
  • suggested_actions[]: contextually relevant commands with reasons
    • Example: “RFC-0001 is in impl phase. If implementation complete, run govctl advance RFC-0001 test
  • 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 status and list logic 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 describe output stays in sync with actual commands
  • Distribution unchanged: cargo install govctl is 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 describe once per session (cacheable)
  • Plain --help remains available for human users
  • Does not preclude future MCP integration if demand materializes

Comparison to MCP:

Aspectgovctl describeMCP
Distributioncargo install govctlServer config + process mgmt
Agent compatibilityAny shell-capable agentMCP-compatible agents only
MaintenanceSingle codebaseCLI + MCP server
Context awarenessBuilt-inSeparate implementation
Works offlineYesDepends