fix: Fix exact-ID resolution precedence in single-idea subcommands#23
fix: Fix exact-ID resolution precedence in single-idea subcommands#23sahil-noon wants to merge 3 commits into
Conversation
RequireSingle now short-circuits on an exact case-insensitive ID match (respecting the active FilterKind) before falling back to substring matching, so an idea is always reachable by its own exact ID even when that ID appears as a substring inside another idea's text. Fixes the "Multiple matches" error for show/done/reopen/edit/rm via the shared seam. Adds table-driven regression tests.
There was a problem hiding this comment.
Pull request overview
Fixes single-idea subcommand resolution so a case-insensitive exact ID match is selected before substring matching, preventing “Multiple matches” when an idea’s ID appears inside another idea’s text (e.g., cross-references like [jznd]). This change is implemented at the shared RequireSingle() seam so it applies uniformly across show/done/reopen/edit/rm, and is documented in the CLI/spec docs.
Changes:
- Add exact-ID short-circuit (case-insensitive, FilterKind-respecting) to
RequireSingle()before substring matching. - Add table-driven regression tests covering exact-ID precedence, case-insensitivity, FilterKind gating, and substring fallback no-regressions.
- Document the exact-ID precedence rule in
docs/specs/overview.mdand CLI memory docs.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/internal/idea/idea.go | Adds exact-ID precedence logic to RequireSingle() while leaving substring matching (Match/FindAll) intact. |
| src/internal/idea/idea_test.go | Adds regression tests for exact-ID precedence and fallback behavior. |
| docs/specs/overview.md | Documents exact-ID-wins query semantics for single-idea subcommands. |
| docs/memory/cli/structure.md | Records resolver/query semantics in CLI memory documentation. |
| docs/memory/cli/index.md | Regenerated memory index entry to reflect updated structure.md description. |
| fab/changes/260615-m2qx-exact-id-resolution-precedence/plan.md | Captures implementation plan and acceptance criteria for the change. |
| fab/changes/260615-m2qx-exact-id-resolution-precedence/intake.md | Captures problem statement, rationale, and design decisions. |
| fab/changes/260615-m2qx-exact-id-resolution-precedence/.status.yaml | Tracks fab stage/status metadata for the change. |
| fab/changes/260615-m2qx-exact-id-resolution-precedence/.history.jsonl | Records fab stage transition history for the change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Closing as a duplicate of #22, which merged the same exact-ID-precedence fix to The one genuinely additive piece from this branch — the |
Meta
Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Impact: +180/−0 code (excluding
fab/,docs/) · +505/−3 totalSummary
The shared single-idea resolver
RequireSingle()ORed an ID-substring check with a text-substring check and treated >1 hit as ambiguous, with no precedence between match kinds. So when an exact 4-char ID also appeared as a substring inside another idea's body text (e.g. a[jznd]cross-reference), passing that exact ID errored "Multiple matches" — leaving the idea unreachable by its own primary key for all five single-idea subcommands (show/done/reopen/edit/rm). This adds exact-ID precedence: a case-insensitive exact ID match (respecting the active FilterKind) short-circuits before substring matching. IDs are unique per backlog (Constitution VI), so this is unambiguous and fixes all five subcommands via the one shared seam.Changes
src/internal/idea/idea.go— exact-ID short-circuit at the top ofRequireSingle: if exactly one filter-passing idea's ID equals the query (strings.EqualFold), return it immediately; otherwise fall through to the unchanged substring loop.Match/FindAll/matchesFilteruntouched. Defensive fall-through if two ideas somehow share an ID under the active filter.src/internal/idea/idea_test.go— table-driven regression tests (real temp files): primary jznd/qg64-style repro, case-insensitivity, FilterKind precedence (done ID not resolved on an open-only path), and no-regression in the substring fallback.