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.
106 lines
3.7 KiB
Markdown
106 lines
3.7 KiB
Markdown
---
|
|
# nbd-kq6o
|
|
title: Scope nbd next and nbd ready by dependency subtree
|
|
status: completed
|
|
type: feature
|
|
priority: normal
|
|
created_at: 2026-03-10T23:30:30Z
|
|
updated_at: 2026-03-10T23:30:30Z
|
|
---
|
|
|
|
## Summary
|
|
|
|
Add an optional positional `<id>` argument to `nbd next` and `nbd ready` that scopes
|
|
the results to the dependency subtree of the given ticket.
|
|
|
|
## Motivation
|
|
|
|
When a project has many tickets, you often want to focus on tickets that directly
|
|
unblock a specific goal ticket. Currently `nbd next` and `nbd ready` operate over
|
|
the entire ticket store, with no way to narrow by project/feature scope except
|
|
through `--filter` expressions that don't understand the dependency graph.
|
|
|
|
## Desired behaviour
|
|
|
|
```sh
|
|
# Highest-priority ready ticket that is a dependency of abc123 (directly or transitively)
|
|
nbd next abc123
|
|
nbd next abc123 --json
|
|
|
|
# All ready tickets that are dependencies of abc123 (directly or transitively)
|
|
nbd ready abc123
|
|
nbd ready abc123 --json
|
|
|
|
# Both commands still accept --filter alongside the scoping ID
|
|
nbd next abc123 --filter type=bug
|
|
nbd ready abc123 --filter priority=8
|
|
```
|
|
|
|
The root ticket itself (abc123) is *not* included in the results — only its
|
|
dependencies (the tickets it is waiting on).
|
|
|
|
## Implementation plan
|
|
|
|
### 1. CLI changes (`src/main.rs`)
|
|
|
|
In `Commands::Next` and `Commands::Ready`, add an optional positional argument:
|
|
|
|
```rust
|
|
id: Option<String>, // Optional ticket ID or prefix to scope results
|
|
```
|
|
|
|
Update `dispatch` to pass the new argument to `cmd_next` and `cmd_ready`.
|
|
|
|
Update the CLI doc-comments for both subcommands to mention the scoping
|
|
behaviour.
|
|
|
|
### 2. Logic changes (`src/main.rs`)
|
|
|
|
In `cmd_next` and `cmd_ready`, after loading all tickets, if `scope_id` is
|
|
`Some`:
|
|
|
|
1. Resolve the prefix to a full ID using `resolve_id`.
|
|
2. Build a `TicketGraph` from all tickets (the full list, not filtered).
|
|
3. Call `graph.subtree(&resolved_id)` to get the set of all dependency IDs
|
|
reachable from the root (this already excludes the root itself when it is
|
|
not in its own dependency list).
|
|
4. Convert the subtree IDs into a `HashSet`.
|
|
5. Restrict the ready/next candidate pool to tickets whose ID is in that set
|
|
*and* whose ID is not the scoping ticket itself (the root should never be
|
|
returned as a "what to do next" result when it is the scope target).
|
|
|
|
`TicketGraph::subtree` is already implemented in `src/graph.rs` and handles
|
|
cycles correctly via a visited set.
|
|
|
|
### 3. Test coverage (`tests/integration.rs`)
|
|
|
|
Add integration tests (using `tempdir`):
|
|
|
|
- **`test_next_scoped_by_id`**: create a project ticket P with deps [A, B],
|
|
where A has dep [C]. Mark C as done. Verify `nbd next P` returns A (the
|
|
highest-priority ready dep of P), not P itself or any unrelated ticket.
|
|
- **`test_ready_scoped_by_id`**: same setup; verify `nbd ready P` returns
|
|
[A] (B is blocked because... actually B has no deps so it's also ready).
|
|
Adjust setup so exactly the expected set is returned.
|
|
- **`test_next_scoped_no_ready`**: all deps of P are done; verify `nbd next P`
|
|
returns no ticket (`{"next": null}` in JSON mode).
|
|
- **`test_ready_scoped_with_filter`**: verify `--filter` still narrows within
|
|
the scoped set.
|
|
|
|
### 4. Relevant files
|
|
|
|
| File | Change |
|
|
|---|---|
|
|
| `src/main.rs:135-156` | `Commands::Ready` and `Commands::Next` — add `id: Option<String>` |
|
|
| `src/main.rs:308-310` | `dispatch` arms for `Next` and `Ready` — pass new arg |
|
|
| `src/main.rs:473-511` | `cmd_ready` — add subtree scoping logic |
|
|
| `src/main.rs:522-566` | `cmd_next` — add subtree scoping logic |
|
|
| `src/graph.rs:165-172` | `TicketGraph::subtree` — already correct, no change needed |
|
|
| `tests/integration.rs` | Add 4 new scoped-by-id tests |
|
|
|
|
### 5. Validation
|
|
|
|
```sh
|
|
cargo fmt && cargo check && cargo clippy && cargo test
|
|
```
|