Composable operation that harvests inline manual-test findings from an epic's test plan, captures them to the backlog, and turns in-scope ones into a remediation story. Called at the manual-test-pass boundary by /epic-flywheel and /retrospective. Directly invocable as /harvest-findings {N}.
Installs into .claude/skills of the current project.
Are you the author of Harvest Findings?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/rterakedis-harvest-findings)
---
name: harvest-findings
description: Composable operation that harvests inline manual-test findings from an epic's test plan, captures them to the backlog, and turns in-scope ones into a remediation story. Called at the manual-test-pass boundary by /epic-flywheel and /retrospective. Directly invocable as /harvest-findings {N}.
---
# Harvest Findings (Composable)
After an epic's manual test pass, the tester records findings as inline bulleted sub-lists under the scenarios/steps in `docs/epics/epic-{N}-test-plan.md` (generated by `/epic-flywheel` at its boundary). This skill harvests those findings, captures them durably in the backlog, and triages each by **kind** (bug / tweak / enhancement / question / plan-defect) and **disposition** (in-scope / defer). Corrective (bug/tweak) in-scope findings become a new remediation story that flows through the normal flywheel; enhancements are scheduled as backlog candidates; questions are surfaced for a decision; plan-defects fix the plan.
**Iron rule — done stories are immutable (DD-33).** This skill **never** reopens or edits a `status: done` story. Fixes land in a *new* story `{N}.{last+1}`.
Token posture: Steps 1–2 and 4 are cheap file parses/edits; the only model work is triage (Step 2) and the delegated create-story call (Step 3). Idempotent — re-running for the same test-pass date does not duplicate anything.
Directly invocable: `/harvest-findings {N}`. Also called by `/epic-flywheel` (after the manual test pass) and `/retrospective` (before the deferred sweep).
Compose, don't reimplement — this skill orchestrates:
- `skills/deferred/SKILL.md` — **LOG-AND-SCHEDULE** for deferred findings and all enhancements.
- `skills/create-story/SKILL.md` — authoring the remediation story file.
- `skills/github-tracking/SKILL.md` — opening the tracking issue.
- `skills/docs-sync/SKILL.md` — **OPERATIONAL** reconcile of the human guides (referenced in the story's DoD).
---
## Activation
1. **Resolve the epic.** Accept `/harvest-findings {N}`; if no number given, infer the most recently completed epic (latest `docs/epics/epic-{N}-test-plan.md`). Require the test plan to exist:
```bash
test -f docs/epics/epic-{N}-test-plan.md || echo "no test plan"
```
If absent, report "No test plan for Epic {N} — run /epic-flywheel to its boundary first" and stop.
---
## Step 1 — Harvest (read-only parse)
Parse `docs/epics/epic-{N}-test-plan.md`. Its scenario/flow headings (`### Flow: {name}`, `### Edge cases`) hold steps and cases that are always top-level `- [ ]` checkbox lines (`- [ ] {step} → {expected}`), which gives a deterministic finding rule:
> **A finding is any *indented* bullet nested beneath a step/case line that is NOT itself a `- [ ]` checkbox.**
Concretely:
- Generated content = a checkbox item at any depth (`- [ ] …` / `- [x] …`, `-` or `*`). A checked-off step (`- [x]`) is not a finding.
- A finding = an indented sub-bullet under a step with a plain bullet marker and no checkbox: `-` or `*` (either accepted), e.g. ` - shows wrong total` or ` * ❌ crashes when offline`. A leading `❌`/`⚠️` or `FINDING:` is optional — nesting + no-checkbox identifies it.
- A finding is not necessarily a bug — it may be a tweak, an enhancement idea, or a question. Harvest all verbatim; kind is classified in Step 2.
- Multi-line findings: text runs until the next bullet or a dedent to a step/heading; fold continuation lines into the one `finding-text`.
Regex intuition (not a literal grep — depth matters): a line matching `^\s+[-*]\s+(?!\[[ xX]\])\S` sitting under a `^[-*]\s+\[[ xX]\]` step is a finding.
Collect a normalized list, one entry per finding:
`{scenario-id, scenario-title, finding-text}` — where `scenario-id` is a stable anchor (the flow/edge-case heading text, plus the step it hangs under if any).
If no inline findings are found, report `No test findings to harvest.` and stop.
---
## Step 2 — Capture to `docs/epics.md` FIRST (durability before authoring)
Before creating any story, write the harvested + triaged findings into `docs/epics.md` under the Epic {N} section, so they survive a later-step failure and give Step 3 a stable source.
Triage each finding on two axes — kind (what it is) and disposition (now or later).
**Kind:**
- **bug** — delivered behavior is broken or wrong vs. what the epic set out to do.
- **tweak** — basically right but needs a small adjustment (copy, spacing, wording, minor UX) within the epic's existing scope.
- **enhancement** — new capability or scope beyond what this epic delivered; not a fix.
- **question** — an ambiguity or product decision the tester couldn't resolve; needs a human answer.
- **plan-defect** — the step was already automated and passing (the tester notes e.g. `already automated: UpgradeSheetFlow`, or you confirm by grep that a flow/suite/eval asserts exactly this). A defect of the test plan, not the product (DD-32). Log it so the retro can count it; never create a story or AC for it; fix the plan in Step 4.
**Disposition:**
- **[in-scope]** — address in this epic before it's considered done.
- **[defer]** — later work.
Before tagging anything `bug`, check it isn't a `plan-defect`: if the step restates an assertion a passing UI-test flow, unit suite, or `docs/evals/` case already makes, and the tester saw the expected behavior, the finding is that the plan asked for it at all.
Append a checklisted block under the Epic {N} heading (idempotent — see below):
```markdown
### Epic {N} — Post-Test Findings (harvested {date})
- [ ] {finding-text} — _{scenario-title}_ — **bug** · **[in-scope]**
- [ ] {finding-text} — _{scenario-title}_ — **tweak** · **[in-scope]**
- [ ] {finding-text} — _{scenario-title}_ — **enhancement** · **[defer]**
- [ ] {finding-text} — _{scenario-title}_ — **question** · needs decision
- [x] {finding-text} — _{scenario-title}_ — **plan-defect** · already automated ({flow/suite/eval})
```
`plan-defect` rows are written pre-checked (`[x]`): nothing is owed on the product side; the row exists so `/retrospective` can count them.
**Keep this shape stable — it is machine-foldable.** The heading `### Epic {N} — Post-Test Findings (harvested {date})` and the per-finding row (a `- [ ]` checkbox carrying **kind** · **disposition**, or `needs decision`) are exactly what `skills/epic-archive/SKILL.md`'s **CONDENSE** op reads to decide whether the block can fold to one line. Don't drift the heading or drop the kind/disposition tag.
**Idempotency (required):** the block is keyed by `(Epic {N}, harvested {date})`. If a heading for the same date exists, merge — add only findings whose `finding-text` is not already listed; never duplicate the block or a row. A re-run on a different date creates a new dated block.
Use today's date (`date +%Y-%m-%d`).
---
## Step 3 — Route each finding by kind
Routing is by kind first, then disposition:
| Kind | in-scope | defer |
|---|---|---|
| **bug** / **tweak** (corrective) | → AC in the remediation story (below) | → `deferred`/LOG-AND-SCHEDULE (item 5) |
| **enhancement** (additive) | → not a remediation AC — `deferred`/LOG-AND-SCHEDULE as a backlog candidate; if material scope, flag for a product decision (`/correct-course` or `/spec` prd update) in the output | → `deferred`/LOG-AND-SCHEDULE |
| **question** | → surface to the user; do not auto-create a story. Leave its epics.md row `needs decision` until answered, then re-triage | (same) |
| **plan-defect** | → no story, no AC, no deferred item. Fix the plan in Step 4 (move the step to the flow's `Automated — do not re-test:` line) and report the count | (same) |
The **remediation story holds only corrective (bug/tweak) `[in-scope]` findings**; everything else is scheduled or surfaced. Author the story only if there is ≥1 such finding.
1. **Determine the story number.** Read `docs/epics.md`; the new story is `{N}.{last+1}` where `last` is the highest existing story number in Epic {N}.
2. **Author the story via create-story.** Invoke `skills/create-story/SKILL.md` to generate `docs/epics/{N}-{last+1}-post-test-findings.md` with:
- One acceptance criterion per corrective in-scope finding, in Given/When/Then form, each linking back to its source scenario (e.g. "_(source: Flow: Checkout → step 'apply promo code')_"). A `bug` AC asserts the correct behavior; a `tweak` AC asserts the adjusted state ("label reads 'X'", "spacing is 16pt").
- Title: `Post-test corrections — Epic {N}`; marked `*(remediation)*`.
- Dev Notes citing the test plan and the harvested block in `docs/epics.md` as the origin.
- `status: ready-for-dev` in frontmatter (pinned format per create-story).
- **Definition of Done additions** (written into the story so dev-story enforces them at close):
- [ ] Reconcile `docs/architecture.md`, `docs/prd.md`, and `docs/ux/*` for any behavior these changes affect (via `docs-sync` **OPERATIONAL** — an Agent tool call with `subagent_type: "lw-docs-sync"`, Haiku).
- [ ] Reset `docs/epics/epic-{N}-test-plan.md` and fold this story's ACs back into it as new verification steps (Step 4 below) so the plan is clean and re-proves the fix for the next re-test pass.
3. **Append the story row to `docs/epics.md`** under Epic {N}'s stories and bump the epic's story count (mirror the `deferred` skill's new-story entry format). Do this before the tracking step so the issue is filed against a story that exists in the backlog.
4. **Create the tracking issue under Epic {N}'s milestone — required.** The story must be tracked like any other so its status flows `ready-for-dev → in-progress → review → done`. `create-story`'s own **GitHub Tracking** step (item 2) already does this: **ENSURE-MILESTONE** for Epic {N}, then — finding no pre-existing issue for `{N}.{last+1}` — **CREATE-ISSUE** at `ready-for-dev` and write `github_issue: {number}` to the frontmatter.
Do not double-create. If create-story's tracking ran, only verify: `grep '^github_issue:' docs/epics/{N}-{last+1}-post-test-findings.md` is non-zero and the issue sits under Epic {N}'s milestone (`gh issue view {N} --json milestone,labels`). If tracking was skipped or `github_issue:` is still `0`, run **ENSURE-MILESTONE** + **CREATE-ISSUE** from `skills/github-tracking/SKILL.md` now. Skip only if `gh` is unavailable — then note in the output that the story is untracked until `/github-tracking backfill`.
A remediation story goes straight to `ready-for-dev` (not `backlog`) — it's actionable immediately, consistent with `deferred`. From there the flywheels and `gh-track.sh` drive label transitions off `github_issue:`, and `/code-review` closes the issue at done.
5. **Schedule / surface everything not in the remediation story.** For each finding routed away from the story, call **LOG-AND-SCHEDULE** from `skills/deferred/SKILL.md` (`title` = short summary, `detail` = finding-text, `source` = `docs/epics/epic-{N}-test-plan.md` scenario). This covers every `[defer]` bug/tweak and every `enhancement` (both dispositions). It slots each into an existing backlog story or a new remediation/feature story — never into the post-test-corrections story. Capture the returned D-IDs.
- For any enhancement that is material new scope, add a one-line flag in the output recommending `/correct-course` or `/spec` prd update.
- For any question, do not schedule — list it in the output as "needs decision"; leave its epics.md row marked `needs decision`. Once answered, re-run harvest or hand-triage it.
If there is no corrective `[in-scope]` finding, skip story authoring (everything is already routed/surfaced in item 5) and still proceed to Step 4.
---
## Step 4 — Reset the test plan
Remove the harvested inline finding bullets from `docs/epics/epic-{N}-test-plan.md` — leave the scenarios, flows, steps, each flow's **Starting state** block (see `epic-flywheel` → Rolled-up Test Plan), and the physical-device section intact. Only the tester's annotations come out (they now live in `docs/epics.md` and the story).
**Remove plan-defect steps for good.** For each `plan-defect` finding, delete its `- [ ]` step from section A and append the covering flow/suite/eval name to that flow's `**Automated — do not re-test:**` line (add the line if the flow lacks one).
**Fold the remediation story's ACs back in.** For each AC of the story authored in Step 3, add one verification step under the flow/scenario its source finding came from (each AC cites `_(source: Flow: ... → step '...')_`), phrased to prove the AC's asserted behavior rather than repeat the original step. If an AC changed a surface the plan describes (a Starting state, a setup note), update that text too.
This reset — strip and fold-back — is also in the remediation story's DoD (Step 3.2); running it here keeps the plan current, and the DoD item is the backstop before the story closes.
---
## Output
Report one line, broken out by kind:
```
Epic {N}: {n} findings harvested — {c} corrective in-scope → story {N}.{last+1} (issue #{issue});
{s} scheduled ({D-ids}, incl. {e} enhancements); {q} questions need a decision; {p} plan-defects
(already automated — removed from the plan, no story). Test plan reset and folded back with {c}
verification steps.
```
If any enhancement is material new scope, add: `Recommend /correct-course for: {short list}.`
If there are questions, list them so the user can answer.
Zero cases: `No test findings to harvest.` (Step 1 empty), or `{n} findings harvested — 0 corrective in-scope; {s} scheduled ({D-ids}); {q} questions. No remediation story needed. Test plan reset.` (nothing to fold back).
---
## Callers
- **`/epic-flywheel`** — at the manual-test-pass boundary, after the user works through `docs/epics/epic-{N}-test-plan.md`.
- **`/retrospective`** — before the deferred sweep, so findings are captured and scheduled alongside the retro's bookkeeping.