add-epic, every time an ask arrives — an issue you are about to mirror, a request in conversation, a line off a roadmap doc.
The gap it closes
The conductor has always accepted work. It did not triage it.add-epic validates the id, the lane and the priority, refuses a duplicate externalId, and appends.
The only dedup that existed was identity-based — same id, or same externalUrl. That correctly stops /pm:sync from mirroring one issue twice, and it does nothing at all about the same ask arriving under a different name. That failure has exactly one symptom: the backlog only ever grows, and every entry looks equally legitimate.
Measured in PM’s own repository: the
change-registered-under-two-lanes integrity check reports four live pairs that are one change registered twice, under different lanes and different names. Identity dedup found none of them. A human reading the backlog did.Getting the candidate set
--limit N (default 5) bounds how many candidates come back. It must be a positive integer — a valueless or non-numeric --limit is refused rather than coerced, and any other flag is rejected by name. A wrong bound on a recall device silently hides the twin the whole command exists to surface.
The engine computes candidates and never a verdict
This is the line the whole design turns on, and the command states it in its own output:verdict is always null.
PM is an instruction layer. An engine that decided two asks were “the same” would be making a semantic judgment on prose, which is exactly the thing it must not do — so it hands you a ranked, auditable candidate set and stops.
Why the ranking has no stoplist
Scoring is IDF over the backlog itself —ln((N+1)/df). A term’s weight comes from how rare it is in your own epics, so house vocabulary self-neutralizes: “Implementation Plan” in a title does not drag half the index in, and nobody maintains a curated stopword list that goes stale.
Every candidate carries the tokens that earned its score. That is what makes a lexical surface auditable rather than an oracle — you can see at a glance that a match is real, or that it rode in on one shared word.
Declining an ask
An ask you screen and decide against ends the way all work in PM ends — with a recorded disposition carrying its reason, never by deletion:declined is a terminal outcome, not a status — archived already means terminal, so nothing about status-driven behavior changes. It records that a judgment was made, which is precisely what deletion destroys.
Epics & Lanes
What happens to an ask once you decide to register it.

