RFC-0002: CLI Resource Model and Command Architecture
Version: 0.2.0 | Status: normative | Phase: impl
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, and verb semantics 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
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 of the form:
govctl <resource> <verb> [arguments] [flags]
Where:
<resource>is a governance artifact type (rfc, adr, work, clause, release)<verb>is an operation on that resource (new, list, get, edit, delete, or resource-specific lifecycle operations)[arguments]are positional parameters (typically IDs, titles, or values)[flags]are optional modifiers (–filter, –output, –stdin, etc.)
Rationale:
The resource-first structure (noun-first) provides several advantages over verb-first (operation-first):
- Scoped Discovery:
govctl rfc --helpshows only RFC operations, not all 30+ global commands - Namespace Clarity:
govctl rfc finalizeis unambiguous;govctl finalizerequires knowing it only applies to RFCs - Mental Model Alignment: Users think “I want to work with RFCs” then “What can I do?”, not “I want to finalize something, what can be finalized?”
- Extensibility: Adding
govctl rfc validatedoesn’t pollute the global namespace - Industry Convention: Docker, kubectl, git, cargo all use resource-scoping or similar patterns
Exceptions:
Commands that operate across all resource types (init, check, status, render) remain at the global level as they don’t belong to a specific resource namespace.
Implementation Note:
For backwards compatibility during migration, verb-first aliases MAY be supported but MUST emit deprecation warnings. Full verb-first syntax MUST be removed in a major version release.
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-0001) - 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-2026-01-19-001) - 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.json) while maintaining the flat CLI command structure (govctl clause get RFC-0001:C-NAME).
5. release - Release Version
Manages release versions and changelogs.
- ID Format: Semantic version (e.g., 1.0.0)
- No lifecycle (immutable once created)
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)
Timestamp Format:
All timestamps in resource metadata (created, updated, started, completed) MUST use ISO 8601 date format (YYYY-MM-DD) in UTC timezone.
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]].
Since: v0.1.0
[RFC-0002:C-CRUD-VERBS] Universal CRUD Verbs (Normative)
All resource types MUST support the following CRUD (Create, Read, Update, Delete) verbs where applicable:
1. new - Create Resource
Syntax: govctl <resource> new <arguments>
Creates a new instance of the resource. Required arguments vary by resource type but typically include a title or primary identifier.
MUST support for: rfc, adr, work, clause, release Behavior:
- Generates unique ID if not provided
- Initializes resource with default values
- Creates necessary filesystem structure
- Validates inputs per resource schema
2. list - List Resources
Syntax: govctl <resource> list [filter]
Lists all instances of the resource type. Optional filter narrows results.
MUST support for: rfc, adr, work, clause, release Behavior:
- Returns tabular output by default
- Supports filtering (exact match or substring)
- Sorted by ID (lexicographic order)
- MUST respect [[RFC-0002:C-OUTPUT-FORMAT]] flags
3. get - Read Resource
Syntax: govctl <resource> get <id> [field]
Retrieves a resource by ID. If field is specified, returns only that field value.
MUST support for: rfc, adr, work, clause Behavior:
- Returns full resource if no field specified
- Returns field value if field specified
- MUST respect [[RFC-0002:C-OUTPUT-FORMAT]] flags
- MUST error if resource or field does not exist
Field Name Stability:
Field names exposed via get <id> <field> MUST be stable identifiers defined by the resource schema. Field names MAY NOT be renamed without a major version bump of govctl.
4. edit - Update Resource
Syntax: govctl <resource> edit <id> <field> [value]
Updates a single field on a resource. Value can be provided as argument or via stdin.
MUST support for: rfc, adr, work, clause Behavior:
- Simple fields: replace value
- Array fields: special syntax (see ADR-0017 for implementation details)
- MUST validate field names per resource schema
- MUST validate values per field type
- MUST support
--stdinflag for multiline content
5. delete - Delete Resource
Syntax: govctl <resource> delete <id>
Removes a resource permanently.
MUST support for: work, clause MUST NOT support for: rfc, adr (use lifecycle verbs instead)
Deletion Safety Constraints:
For clauses:
- MUST only allow deletion if containing RFC is in
draftstatus - MUST verify no other artifacts reference the clause ID before deletion
- MUST error with list of referencing artifacts if references exist
For work items:
- MUST only allow deletion if status is
queue - MUST verify no other artifacts reference the work item ID before deletion
- MUST error with list of referencing artifacts if references exist
General Deletion Behavior:
- SHOULD require confirmation unless
--forceflag provided - MUST be atomic (either fully succeeds or fully fails)
Rationale: Permanent deletion breaks referential integrity. These constraints ensure deletions are safe and don’t leave dangling references in the governance graph.
Consistency Requirements:
- All CRUD verbs MUST use the same flag names across resource types
- Error messages MUST follow the same format across all verbs
- Exit codes MUST be consistent (0 = success, non-zero = error)
- Stdin handling MUST work identically across all verbs that accept it
Forbidden Variations:
- MUST NOT use different verb names for the same operation (e.g., “show” vs “get”)
- MUST NOT reorder arguments between resource types (ID always comes before field)
- MUST NOT have resource-specific flags for universal operations
Since: v0.1.0
[RFC-0002:C-LIFECYCLE-VERBS] Resource-Specific Lifecycle Verbs (Normative)
Resource-specific lifecycle verbs implement state transitions defined in [[RFC-0001]]. These verbs MUST be scoped to their resource namespace.
RFC Lifecycle Verbs:
-
govctl rfc finalize <id> <normative|deprecated>- Implements [[RFC-0001:C-RFC-STATUS]] transitions
- draft → normative or draft → deprecated
-
govctl rfc advance <id> <spec|impl|test|stable>- Implements [[RFC-0001:C-RFC-PHASE]] transitions
- Forward-only phase progression
-
govctl rfc bump <id> <patch|minor|major> -m <message>- Version bumping per semantic versioning
- Updates changelog automatically
- Optional:
--change <description>for additional changelog entries
-
govctl rfc supersede <id> --by <replacement-id>- Marks RFC as superseded by another RFC
- Both RFCs must exist
ADR Lifecycle Verbs:
-
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 Verbs:
govctl work move <id> <queue|active|done|cancelled>- Implements [[RFC-0001:C-WORK-STATUS]] transitions
- Validates gate conditions (e.g., acceptance criteria for done)
- Updates timestamp fields automatically
Clause Lifecycle Verbs:
-
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 verbs MUST validate transitions per [[RFC-0001]]
- All lifecycle verbs MUST update timestamp fields where applicable
- All lifecycle verbs MUST be atomic (no partial state changes)
- All lifecycle verbs MUST support global
--dry-runflag - Invalid transitions MUST error with clear explanation of valid transitions
Rationale:
Lifecycle verbs 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)
- Each resource has different valid transitions
Scoping these verbs to resources makes their applicability explicit and prevents confusion.
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 ADRs and Work Items)
- MUST be parseable by standard TOML tools
- Only applicable where TOML is the source format
-
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.
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 editing (toml for ADRs/work items)
This pattern follows kubectl and Docker conventions where -o json works on all read operations.
Since: v0.1.0
[RFC-0002:C-GLOBAL-COMMANDS] Global Commands (Normative)
The following commands operate across all resources and MUST remain at the global namespace level:
1. govctl init
Initializes a new govctl project in the current directory.
Syntax: govctl init [--force]
Behavior:
- Creates
gov/directory structure - Generates
gov/config.toml - Creates subdirectories for rfcs, adrs, work items
- Optionally creates
.claude/commands/with workflow templates - MUST error if already initialized (unless
--force)
2. govctl check
Validates all governance artifacts across the project.
Syntax: govctl check [--deny-warnings]
Behavior:
- Validates RFCs, ADRs, clauses, work items
- Checks state machine invariants
- Verifies cross-references
- Scans source code for references (if enabled in config)
- 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 TOML/JSON.
Syntax: govctl render [targets...] [--output-dir PATH] [--dry-run]
Behavior:
- Renders RFCs from JSON 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
- Default: renders RFCs only
- With targets:
rfc,adr,work,changelog,all - MUST validate before rendering
5. govctl describe
Outputs machine-readable CLI metadata for agent/tool integration.
Syntax: govctl describe [--context]
Behavior:
- Outputs JSON with command catalog
- Includes workflow information
- With
--context: adds current project state and suggested actions - Enables AI agents to discover capabilities (per [[ADR-0015]])
Stability Contract:
The JSON schema of govctl describe output MUST be versioned. The schema version MUST be included in the output. Backward-incompatible changes to the schema require a major version bump of govctl.
This ensures agents and automation tools can rely on stable introspection.
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
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”
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
Since: v0.1.0
Changelog
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