Skip to content

deps: a CLI verb to remove a single dependency edge - #109

Merged
MJohnson459 merged 1 commit into
mainfrom
deps-unlink-cli
Aug 1, 2026
Merged

deps: a CLI verb to remove a single dependency edge#109
MJohnson459 merged 1 commit into
mainfrom
deps-unlink-cli

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

remove_dep has been kind-aware since the deps-key change (task 311), but no
CLI verb reached it, so an edge authored by mistake — a related typed where
blocks was meant, a discovered-from linking the wrong parent — was
removable only with raw SQL against the database. --blocked-by could clear
the blocker set wholesale, which left every other kind, and the ability to
drop one edge of a pair carrying two, with no spelling at all.

What changed

voro set <id> --unlink <kind>:<other-id> drops exactly one dependency edge.
The edge is named in the direction voro show prints it — it belongs to the
task being edited — so set 2 --unlink blocks:1 removes what show 2 lists
as dep: blocked by #1, and set 2 --unlink discovered-from:1 removes the
provenance edge beside it without touching the blocker. The flag repeats for
several edges in one call.

The echo reads the kind the way show does — task 2 no longer blocked by #1, never the kind backwards — and because dropping a blocker reconciles
readiness in the store, the promotion that can follow is echoed beside it
(— #3 promoted to ready), symmetrically with how --blocks echoes its
demotion. The trailing task N updated (state) is read back after the edit
rather than reported from before it, so a promotion is not printed as
(parked).

Naming an edge that is not there fails with the store's own message
(#2 has no related dependency on #1) rather than reporting a success it did
not perform; an unknown kind and a malformed KIND:ID fail in the parser.

No core logic changed — the store call and its refusal already existed. This
is CLI surface, its help text, and tests. docs/DESIGN.md §5 gains a clause
naming the operator-facing spelling beside the store semantics it already
described; the voro-cli skill and the changelog document the flag.

A behaviour worth naming

Unlinking the last blocker leaves the task parked. That is DESIGN.md §5 as
written — a parked task with no blockers is deliberately deferred, and
auto-promotion applies only to parked tasks that have blockers — and it is
exactly what --blocked-by with an empty set already does, since both go
through reconcile_readiness. unpark remains the manual escape. Pinned with
its own test so the asymmetry is deliberate rather than discovered later.

Verification

cargo test --workspace passes (273 tests, 5 new), cargo clippy --workspace --all-targets -- -D warnings clean, cargo fmt --all applied. Also smoke-run
against a scratch database: authored a discovered-from + blocks pair with
propose --from and set --blocked-by, unlinked the blocker, confirmed
show still lists dep: discovered-from 1 alone, and confirmed the absent
related:1 edge fails with the store's message and a non-zero exit.

The new CLI tests cover each acceptance criterion: one kind of a pair
surviving the other's removal (both directions), the refusal on an absent
edge with the surviving edge intact, readiness reconciling on a blocks
removal, the deliberate non-promotion above, and the repeated flag.

`remove_dep` has been kind-aware since the deps-key change, but no verb
reached it, so an edge authored by mistake — a `related` typed where
`blocks` was meant, a `discovered-from` linking the wrong parent — was
removable only with raw SQL against the database. `--blocked-by` could
clear the blocker set wholesale, which left every other kind, and the
ability to drop one edge of a pair carrying two, with no spelling at all.

`voro set <id> --unlink <kind>:<other-id>` names one edge in the direction
`show` prints it — the edge belongs to the task being edited — and drops
exactly that one. The flag repeats for several. The echo reads the kind the
way `show` does (`no longer blocked by #9`, never the kind backwards), and
because dropping a blocker reconciles readiness in the store, the promotion
that can follow is echoed beside it, symmetrically with `--blocks`' demotion
echo; the trailing state is read back after the edit rather than reported
from before it.

No core logic changed: the store call and its refusal of an absent edge
already existed. Covered at the CLI level — one kind of a pair surviving the
other's removal, the refusal, the promotion, and the deliberate non-promotion
when the last blocker goes (a parked task with no blockers is deferred by
choice, DESIGN.md §5, so `unpark` stays the manual escape).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxkK1vKA77ewc7vgnRTT9R
@MJohnson459
MJohnson459 merged commit 3881304 into main Aug 1, 2026
6 checks passed
@MJohnson459
MJohnson459 deleted the deps-unlink-cli branch August 1, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant