Op story finder
Searches existing planned work units (BMAD stories by default; spec-kit tasks, markdown backlog, or the layout declared in docs/spec-systems.md) by keyword and reports matches with ID, epic/container, status, and file path. Use before creating new units, to check for duplicate work, find related work in a topic area, or review the backlog by feature or component. Read-only.From its SKILL.md
npx -y skills add rnrn/op --skill op-story-finderAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.9 KB, as published. Nobody here has run it
Story Finder Skill
Find existing stories by keyword search so duplicate work is caught before a new story is created. Also useful for locating related work in a topic area or reviewing the backlog by feature, component, or status.
Read-Only Contract
This skill never creates, modifies, or deletes files. The report goes to the conversation only.
Usage
/op-story-finder "rate limiting"
/op-story-finder "authentication JWT"
/op-story-finder "user registration"
/op-story-finder --audit # audit the backlog against its own declared spec
--audit — backlog-conformance mode (the family audits code, docs, and debt, but the
backlog itself is a corpus too): run the canonical helper over the declared docs root —
node ~/.claude/scripts/lib/unit-status.mjs --root <repo> --dir <docs-root> --check --convention <declared> — and report (a) units whose status is not where the declaration
says, (b) the full status-token vocabulary with UNDECLARED tokens called out (pass the
project-declared extras via --tokens-closed/--tokens-open), (c) ambiguous bodies
(2+ closed tokens). Every finding names the unit heading + file. This is read-only —
fixing the corpus belongs to the user or an op-watch campaign, never to the audit itself.
The only argument is the keyword phrase. Tips:
- Use specific keywords: "JWT authentication" beats just "auth".
- Search by component: "API rate limit", "frontend validation".
- Search by status: add
status: doneto find completed work.
Workflow
- Detect the layout FIRST — never default blindly to the BMAD glob. Read
docs/spec-systems.md(andAGENTS.mdStack Profile /CLAUDE.md/docs/HANDBOOK.md) to learn where this project keeps units, then grep the matching glob:- BMAD →
docs/**/stories/*.md(units# Story X.Y: Title). - spec-kit →
specs/**/tasks.md. - markdown backlog →
docs/tasks/*.md,TODO/BACKLOG. - flat-epic →
docs/EPIC_*.mdwith inline units### Task N. <title> — <status>(also## Task N,- [ ] …); the container is the# EPIC:heading / filename, and anEPIC_*_INDEX.mdhub, when present, holds the authoritative open/done state. This layout is common and the BMAD glob returns zero hits on it. Detection guard (prevents a false "no units"): if the BMAD glob returns 0 files ANDdocs/spec-systems.md(or anydocs/EPIC_*.md) exists, STOP and follow the declared layout before reporting empty. A genuinely empty project isDONE"no units found"; a mis-detected one is a bug. Scope: restrict globs to the declared docs root; exclude non-authoritative copies —.claude/worktrees/**,**/agent_workspaces/**,**/data/**,node_modules/**— or every finding triple-counts. (Tracker systems — beads/issues — are queried by op-planner/op-audit via their CLIs; this read-only finder greps file-based units.)
- BMAD →
- Parse matches (heading/field shapes vary by layout — handle all). Never hand-roll status
parsing — resolve each unit's status with the canonical helper
node ~/.claude/scripts/lib/unit-status.mjs--root <repo> [--dir <docs-root>](heading token → bodyStatus:line → body scan, with ambiguity detection; falls back to the copy shipped in the bundle'sscripts/lib/). An ad-hoc parser against a mixed-convention corpus miscounts open work (field-verified ~2x overstatement). When--check --convention <declared>shows the corpus violating its own declaration, report the mismatch as a finding next to the results — never silently pick one convention:- ID + title:
# Story X.Y: TitleOR### Task N. <title>(unit id =<EPIC-file>:TaskN). - Container/epic:
**Epic:**line OR the# EPIC:heading / the epic filename. - Status:
**Status:**line OR the token(s) after the last—/inside(…)in the heading. A bare priority tag (— P0…— P3) is NOT a status — treat it as open/unspecified and consult anyEPIC_*_INDEX.mdfor the authoritative open/done; never reportP0as a status. - Extract file path.
- ID + title:
- Return structured results to the conversation (see Output).
Integration with the doc-harvester agent — doc-harvester calls this skill before creating each story:
doc-harvester extracts: "Add rate limiting"
→
Calls: /op-story-finder "rate limiting"
→
Found match? → Skip (mark as duplicate)
No match? → Call /op-planner to create story
Output
Each match shows ID, epic, status, and file path:
Found 2 matching stories for "rate limiting":
1. Story 2.3: Add Rate Limiting
Epic: api | Status: backlog
File: docs/api/stories/story-2.3.md
2. Story 5.1: Rate Limit Configuration
Epic: config | Status: done
File: docs/config/stories/story-5.1.md
If no matches:
No existing stories found for: "rate limiting"
Completion Status
Protocol (non-negotiable): the VERY LAST line of every run MUST start with exactly one of these tokens, as plain text — no markdown emphasis or backticks around the token. An optional — <one-line reason> may follow the token; nothing else. Do not invent other status wording:
DONE— search completed (with or without matches, including "no story docs found").DONE_WITH_CONCERNS— search completed but some story files were unparseable; list them.BLOCKED— project root unreadable.NEEDS_CONTEXT— no keyword phrase was provided.