Repository navigation
feat(cli): add list subcommand to query and inspect active canons #38
Description
Problem & Motivation
The relationship between Canons and Files is an
- A single canon may govern many files across the repository.
- A single file may be governed by multiple overlapping canons (global, scoped, or tag-based).
As a repository accumulates canons across monorepo packages, developers and AI coding assistants need a fast, deterministic, zero-token CLI interface to inspect this graph in both directions without manual glob evaluation:
- Repository Inventory: "What canons exist across this project, and what are their scopes and tags?"
-
Contextual Applicability (
$F \rightarrow C$ ): "Which canons govern the specific file(s) I am editing right now?" -
Blast Radius / Impact Analysis (
$C \rightarrow F$ ): "If I author or edit canon X, which repository files will it govern?" - Graph Health & Coverage: "Are there orphaned canons matching zero files? Are there critical source files completely uncovered by canons?"
As the anchor issue for CLI initial capabilities, this issue defines the read-only query and inspection suite, establishing full conformance with the dogfood CLI ergonomics canons (packages/cli/.canons/).
Command Capabilities & Invocation Ergonomics
1. Basic Inventory (All Canons)
Scans for **/.canons/**/*.md and outputs the repository inventory:
$ canon-clerk list
ID SCOPE PATHS TITLE
canons-must-be-atomic global **/*.md Canons Must Be Atomic
scripts-must-echo-traces .agents/skills/ **/*.sh Scripts Must Echo Command Traces
cli-must-separate-data-from-diag packages/cli/ **/*.ts CLI Must Separate Data From Diagnostics2. Contextual Applicability ($F \rightarrow C$ : Files to Canons)
Determines which canons pass Stage 0 deterministic path filtering for one or more files:
# Query by specific path
$ canon-clerk list --path packages/cli/src/index.ts
# Query by currently staged git files
$ canon-clerk list --staged
# Unix pipeline composition via stdin (per cli-commands-accepting-collections-must-support-stdin)
$ git diff --name-only origin/main...HEAD | canon-clerk list --stdin3. Blast Radius & Reverse Query ($C \rightarrow F$ : Canon to Files)
Projects a canon's path globs and scope boundaries onto the active repository to list governed files:
# List all files governed by a specific canon ID
$ canon-clerk list --files --canon cli-must-separate-data-from-diagnostics
# List all files governed by a tag across packages
$ canon-clerk list --files --tag cli-ergonomics4. Graph Health & Integrity Diagnostics
Provides audit capabilities to maintain repository hygiene:
# Dead/Orphan Canons: Canons whose paths: match 0 repository files (e.g. stale globs after refactors)
$ canon-clerk list --orphans
# Uncovered Surface Area: Source files matching 0 active canons
$ canon-clerk list --files --uncoveredOutput Formats & Pipeline Contracts
The command strictly complies with our dogfood CLI ergonomics canons:
-
Delimiter-Separated Output (
cli-list-commands-must-emit-delimiter-separated-lines):- When output is piped (non-interactive / non-TTY),
canon-clerk listemits plain newline-delimited IDs (or clean tab-separated lines) without ANSI color escapes or table box-drawing characters:$ canon-clerk list --path packages/cli/src/index.ts | xargs -n1 ... - Formatted tables with column headers are reserved for interactive TTYs or explicit
--tableopt-in.
- When output is piped (non-interactive / non-TTY),
-
Machine-Readable JSON (
cli-output-commands-must-support-json):-
--jsonemits the canonicalized schema for programmatic agent consumption:$ canon-clerk list --json
[ { "id": "cli-must-separate-data-from-diagnostics", "title": "CLI Must Separate Data From Diagnostics", "filePath": "packages/cli/.canons/cli-must-separate-data-from-diagnostics.md", "scope": "packages/cli", "paths": ["packages/cli/**/*.ts"], "tags": ["cli-ergonomics"], "inspect": ["diff"] } ]
-
-
Deterministic Sorting (
cli-collection-outputs-must-be-stably-sorted):- Canon collections are sorted lexicographically by
id. - File collections are sorted lexicographically by relative repository path.
- Canon collections are sorted lexicographically by
-
Query Exit Codes (
cli-queries-must-exit-zero-on-empty-results):- If a query returns 0 matching canons or 0 matching files, the command emits empty output and exits
0. (Exit codes$>0$ are strictly reserved for execution failures percli-must-signal-failure-via-exit-codes).
- If a query returns 0 matching canons or 0 matching files, the command emits empty output and exits
-
Diagnostic Separation (
cli-must-separate-data-from-diagnostics):- Data payload (tables, TSV, JSON) writes exclusively to
stdout. - Informational notices, warnings, and error diagnostics write exclusively to
stderr.
- Data payload (tables, TSV, JSON) writes exclusively to
Acceptance Criteria
- Discovery & Derivation: Discover
**/.canons/**/*.mdand derive metadata (id,title,paths,tags,inspect) perSPEC.mdSection 4. - Path Filtering (
$F \rightarrow C$ ): Support--path <filepath>,--staged, and--stdinfor Stage 0 matching. - Reverse Query (
$C \rightarrow F$ ): Support--files --canon <id>and--files --tag <tag>. - Health Diagnostics: Support
--orphans(unmatched canons) and--files --uncovered(unmatched files). - Output Ergonomics:
- Auto-detect TTY: formatted table for terminals; clean newline/TSV for pipes.
- Support
--jsonwith canonicalized schema. - Stable lexicographical sorting on all collections.
- Exit code
0on empty query results.
- Help & Examples: Provide runnable, copy-pasteable usage examples in
--helppercli-commands-must-provide-runnable-examples.
Activity
docs(readme): reframe as semantic linter and ground content in projec…