You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vibed/nbd/.beans/nbd-17dp--ascii-graph-rende...

74 lines
2.9 KiB
Markdown

---
# nbd-17dp
title: ASCII graph rendering in display.rs
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-csdh
---
Add `format_graph` and `print_graph` to `src/display.rs` to render a ticket dependency DAG as an ASCII tree.
## Motivation
The `nbd graph` command needs to convert the `TicketGraph` data structure (from `src/graph.rs`) into a human-readable ASCII representation. Rendering belongs in `display.rs` next to `format_list` and `format_ticket`.
## Output format
The graph is a forest of trees. Each root ticket (no in-graph dependencies) starts at column 0. Its dependents (tickets that depend on it) are indented below it using box-drawing characters.
```
a3f9c2 [todo] Fix login bug
├── b7d41e [todo] Add rate limiting
│ └── c9e823 [in_progress] Write tests
└── d1f302 [done] Update docs
e4a781 [todo] New feature (no deps)
```
**Node format per line:**
```
{prefix}{id} [{status}] {title}
```
Where `{prefix}` is built from indentation characters (`│ `, `├── `, `└── `).
**Blocked indicator (optional):** Consider marking tickets that have unresolved (non-done/closed) dependencies with a `[blocked]` tag or `!` prefix so the graph visually distinguishes ready from blocked tickets.
## Signatures
```rust
/// Render the full dependency forest as an ASCII tree string.
pub fn format_graph(graph: &TicketGraph) -> String
/// Print the full dependency forest.
pub fn print_graph(graph: &TicketGraph)
/// Render the subtree rooted at `root_id` as an ASCII tree string.
pub fn format_subtree(graph: &TicketGraph, root_id: &str) -> String
/// Print the subtree rooted at `root_id`.
pub fn print_subtree(graph: &TicketGraph, root_id: &str)
```
## Implementation notes
- Use a recursive helper that tracks a `prefix: String` carrying the accumulated indentation characters.
- For each node's children (its dependents in the graph), iterate:
- If not the last child: prefix extension is `│ `; connector is `├── `.
- If the last child: prefix extension is ` `; connector is `└── `.
- Cycle guard: track a `visited: HashSet<&str>` across the recursion; if a node ID is already visited, render `{prefix}{connector}{id} [cycle]` and stop descending.
- Status is shown as the serde string: `todo`, `in_progress`, `done`, `closed`.
## Files touched
- `src/display.rs``format_graph`, `print_graph`, `format_subtree`, `print_subtree`
## Tests (unit, in `src/tests.rs`)
- `format_graph` on a single ticket with no deps produces a single line.
- `format_graph` on a two-ticket chain shows the child indented with `└──`.
- `format_graph` with a branching parent shows `├──` for all but the last child and `└──` for the last.
- `format_subtree` only shows the specified root's subtree.
- A cycle in the graph does not cause infinite recursion; the repeated node is labelled `[cycle]`.