feat(nbd): add 'nbd graph' CLI subcommand [9ad11f]
Wires up the graph command in main.rs with cmd_graph(). Supports full dependency forest (nbd graph), subtree by ID/prefix (nbd graph <id>), --filter narrowing, and --json machine-readable output. Fixes tree-rendering indentation bug (child_base vs prefix separation). Updates README.md and CLAUDE.md with graph command documentation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>quotesdb
parent
d5697d5c4e
commit
b0359c4392
@ -0,0 +1,90 @@
|
||||
+++
|
||||
title = "Add 'nbd graph' CLI subcommand"
|
||||
priority = 5
|
||||
status = "done"
|
||||
ticket_type = "feature"
|
||||
dependencies = ["9c9ebe", "e14172"]
|
||||
+++
|
||||
Wire up the `graph` subcommand in `src/main.rs` to expose the ASCII dependency graph and JSON output.
|
||||
|
||||
## Motivation
|
||||
|
||||
With `src/graph.rs` and the rendering functions in `display.rs` implemented, this ticket connects them to the CLI so users (and agents) can invoke `nbd graph`.
|
||||
|
||||
## CLI interface
|
||||
|
||||
```sh
|
||||
nbd graph # full dependency forest (all tickets)
|
||||
nbd graph <id> # subtree rooted at the given ticket ID (or unique prefix)
|
||||
nbd graph --json # machine-readable adjacency list (all tickets)
|
||||
nbd graph <id> --json # machine-readable subtree
|
||||
nbd graph --filter type=bug # forest of only bug tickets and their deps
|
||||
```
|
||||
|
||||
## Clap definition (add to `Commands` enum in main.rs)
|
||||
|
||||
```rust
|
||||
/// Draw an ASCII dependency graph of all tickets, or a subtree rooted at a
|
||||
/// specific ticket.
|
||||
///
|
||||
/// Without an ID, renders every ticket as a dependency forest (roots first,
|
||||
/// dependencies indented below). With an ID, renders only the subtree reachable
|
||||
/// from that ticket via its dependencies.
|
||||
Graph {
|
||||
/// Optional ticket ID or unique prefix to use as the graph root.
|
||||
///
|
||||
/// When omitted, the full dependency forest is rendered.
|
||||
id: Option<String>,
|
||||
|
||||
/// Filter tickets by field before building the graph: repeatable `key=value` pairs.
|
||||
///
|
||||
/// Applied to the full ticket list before graph construction.
|
||||
/// Keys: `status`, `type`, `priority`, `title`. Values support globs.
|
||||
#[arg(long = "filter", value_name = "KEY=VALUE")]
|
||||
filter: Vec<String>,
|
||||
}
|
||||
```
|
||||
|
||||
## Handler: `cmd_graph`
|
||||
|
||||
```rust
|
||||
async fn cmd_graph(id: Option<String>, filter_args: Vec<String>, json: bool) -> store::Result<()>
|
||||
```
|
||||
|
||||
Steps:
|
||||
1. `find_nbd_root()` and `list_tickets(&root).await?`.
|
||||
2. Apply `parse_filters(&filter_args)?` to narrow the ticket list.
|
||||
3. `let graph = TicketGraph::build(&tickets);`
|
||||
4. If `id` is `Some`:
|
||||
a. Resolve `id` via `resolve_id(&root, &id).await?`.
|
||||
b. If `json`: print `graph.to_subtree_json_value(&id)` (or similar — see graph.rs ticket for the JSON shape).
|
||||
c. Else: `display::print_subtree(&graph, &id)`.
|
||||
5. If `id` is `None`:
|
||||
a. If `json`: print `graph.to_json_value()`.
|
||||
b. Else: `display::print_graph(&graph)`.
|
||||
|
||||
## JSON output shapes
|
||||
|
||||
**Full graph (`nbd graph --json`):**
|
||||
```json
|
||||
{
|
||||
"nodes": [
|
||||
{"id": "a3f9c2", "title": "Fix login bug", "status": "todo", "priority": 8, "dependencies": ["b7d41e"]},
|
||||
...
|
||||
],
|
||||
"edges": [
|
||||
{"from": "a3f9c2", "to": "b7d41e"},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Subtree (`nbd graph <id> --json`):**
|
||||
Same shape as full graph but only including nodes and edges reachable from `<id>`.
|
||||
|
||||
## Files touched
|
||||
- `src/main.rs` — `Commands::Graph` variant, `cmd_graph`, dispatch in `dispatch()`
|
||||
|
||||
## Depends on
|
||||
- `9c9ebe` — graph computation module
|
||||
- `e14172` — ASCII rendering functions
|
||||
Loading…
Reference in New Issue