@lemoncode/lemony 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PRIVACY.md +147 -0
- package/README.md +189 -0
- package/catalog/VERSION +1 -0
- package/catalog/agents/README.md +29 -0
- package/catalog/agents/architect.md +81 -0
- package/catalog/agents/fit-assessment.md +94 -0
- package/catalog/agents/implementer.md +67 -0
- package/catalog/agents/orchestrator.md +627 -0
- package/catalog/agents/reviewer.md +124 -0
- package/catalog/agents/spec-author.md +69 -0
- package/catalog/agents/ui-designer.md +25 -0
- package/catalog/commands/add-capability.md +69 -0
- package/catalog/commands/bypass.md +40 -0
- package/catalog/commands/define.md +24 -0
- package/catalog/commands/hotfix.md +47 -0
- package/catalog/commands/pause.md +52 -0
- package/catalog/commands/resume.md +56 -0
- package/catalog/commands/spinoff.md +59 -0
- package/catalog/commands/triage.md +24 -0
- package/catalog/harness.config.schema.json +116 -0
- package/catalog/hooks/README.md +56 -0
- package/catalog/hooks/init.sh +281 -0
- package/catalog/hooks/lib/lemony.sh +41 -0
- package/catalog/hooks/lib/playbook-scan.sh +394 -0
- package/catalog/hooks/lib/transcript-grep.sh +56 -0
- package/catalog/hooks/require-playbook.sh +97 -0
- package/catalog/hooks/session-close.sh +232 -0
- package/catalog/hooks/suggest-playbook.sh +72 -0
- package/catalog/playbook-format.md +198 -0
- package/catalog/schemas/README.md +13 -0
- package/catalog/schemas/tier2-events-history.md +104 -0
- package/catalog/schemas/tier2-events.md +286 -0
- package/catalog/skills/README.md +62 -0
- package/catalog/skills/bootstrap-architecture/SKILL.md +78 -0
- package/catalog/skills/code-explorer/SKILL.md +76 -0
- package/catalog/skills/grill-with-docs/ADR-FORMAT.md +49 -0
- package/catalog/skills/grill-with-docs/CONTEXT-FORMAT.md +77 -0
- package/catalog/skills/grill-with-docs/SKILL.md +270 -0
- package/catalog/skills/grill-with-docs/reference.md +236 -0
- package/catalog/skills/mutation-testing/SKILL.md +84 -0
- package/catalog/skills/note-side-finding/SKILL.md +89 -0
- package/catalog/skills/playbook-iterate/SKILL.md +78 -0
- package/catalog/skills/prd-to-spec/SKILL.md +181 -0
- package/catalog/skills/raise-discovery/SKILL.md +112 -0
- package/catalog/skills/resolve-discovery/SKILL.md +123 -0
- package/catalog/skills/review-pr/SKILL.md +106 -0
- package/catalog/skills/review-pr/reference.md +105 -0
- package/catalog/skills/security-review/SKILL.md +90 -0
- package/catalog/skills/senior-review/SKILL.md +99 -0
- package/catalog/skills/silent-failure-hunter/SKILL.md +76 -0
- package/catalog/skills/spec-compliance-check/SKILL.md +74 -0
- package/catalog/skills/spec-to-issue/SKILL.md +88 -0
- package/catalog/skills/task-closeout/SKILL.md +229 -0
- package/catalog/skills/tdd/SKILL.md +171 -0
- package/catalog/skills/test-gap-report/SKILL.md +71 -0
- package/catalog/skills/triage-issue/SKILL.md +102 -0
- package/catalog/skills/update-architecture/SKILL.md +69 -0
- package/catalog/skills/verify/SKILL.md +90 -0
- package/catalog/skills/write-adr/SKILL.md +77 -0
- package/catalog/templates/README.md +32 -0
- package/catalog/templates/claude-code/.claude/settings.json.tpl +34 -0
- package/catalog/templates/claude-code/agents.md.tpl +109 -0
- package/catalog/templates/claude-code/docs/playbooks/README.md.tpl +96 -0
- package/catalog/templates/claude-code/harness.config.yml.tpl +59 -0
- package/catalog/templates/claude-code/state/history.md.tpl +6 -0
- package/dist/cli.mjs +5691 -0
- package/package.json +80 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: note-side-finding
|
|
3
|
+
description: Surface an independent, non-blocking defect you spotted mid-task in your return summary instead of pausing or fixing it. Use when a sub-agent (Spec Author, Implementer, Reviewer, Architect) notices a real bug that is unrelated to its current task — the task finishes fine without touching it — so it should be parked for later, not escalated. The non-pausing sibling of raise-discovery.
|
|
4
|
+
origin: vendor
|
|
5
|
+
vendor_version: '{{vendor_version}}'
|
|
6
|
+
invoked-by: [spec-author, implementer, reviewer, architect]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Note Side-Finding
|
|
10
|
+
|
|
11
|
+
## Core Principle
|
|
12
|
+
|
|
13
|
+
While doing your task with fresh context, you sometimes spot a **real defect that has
|
|
14
|
+
nothing to do with the task you were given** — the task finishes correctly without
|
|
15
|
+
touching it ("while implementing the parser I noticed the unrelated CSV export drops
|
|
16
|
+
the last row"). You **cannot interrupt** the human (you run via `Task`, not in the
|
|
17
|
+
hat's conversation) and you should **not** silently fix it (it is outside your task's
|
|
18
|
+
scope) or pause for it (it is not blocking you). So you do neither: you **note it in
|
|
19
|
+
your return summary and keep going**. The Orchestrator collects it and offers the human
|
|
20
|
+
a `/spinoff` capture — nothing is lost, nothing is context-switched.
|
|
21
|
+
|
|
22
|
+
This is the **non-pausing** half of the discovery family. You write one bullet and
|
|
23
|
+
return; you do not create an issue, flip a label, write to `discoveries.md`, or stop.
|
|
24
|
+
|
|
25
|
+
## Which channel — side-finding vs discovery vs just-do-it
|
|
26
|
+
|
|
27
|
+
Pick by **two questions: does it block your task, and is it in your task's scope?**
|
|
28
|
+
|
|
29
|
+
| Situation | Channel | What you do |
|
|
30
|
+
| --------------------------------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------- |
|
|
31
|
+
| Defect is **in scope** for your task (your change touches it) | **Just fix it** | Fix it in your normal work — no note, no escalation. |
|
|
32
|
+
| Defect **blocks** your task / the plan forces it (T1–T6) | **`raise-discovery`** | Pause: write `discoveries.md`, return one line, stop. |
|
|
33
|
+
| Defect is **independent and non-blocking** (task finishes fine) | **note-side-finding** | Add a `## Side-findings` bullet, **keep working**. |
|
|
34
|
+
| A feature **idea** (not a defect) | mention it in prose | No capture channel here — drop it in your summary prose; the human may pick it up and `/define` it. |
|
|
35
|
+
|
|
36
|
+
The discriminator against `raise-discovery` is **blocking**: if you can complete your
|
|
37
|
+
task without the defect being touched, it is a side-finding (note and continue), never a
|
|
38
|
+
discovery (pause and stop). When genuinely unsure whether it blocks you, prefer
|
|
39
|
+
`raise-discovery` — a wrong pause is cheaper than coding past a real contradiction.
|
|
40
|
+
|
|
41
|
+
The same channel covers **architecturally-significant drift in `docs/architecture.md`**
|
|
42
|
+
(ADR 0011) — when you read the map to orient and find it states a boundary/seam the code no
|
|
43
|
+
longer matches, in an area your task doesn't touch. That is a defect of the _map_, not the
|
|
44
|
+
code: non-blocking and out of your scope, so it rides here. Tag such a bullet `kind: drift`
|
|
45
|
+
(see the contract below) so the Orchestrator routes it to the Architect's
|
|
46
|
+
`update-architecture` rather than a generic follow-up; don't fix the map yourself and don't
|
|
47
|
+
silently trust one side.
|
|
48
|
+
|
|
49
|
+
## The contract
|
|
50
|
+
|
|
51
|
+
When you have one or more independent non-blocking defects, append **one** section to
|
|
52
|
+
the **end of your return summary** to the Orchestrator (omit it entirely when you have
|
|
53
|
+
none — never emit an empty block):
|
|
54
|
+
|
|
55
|
+
```markdown
|
|
56
|
+
## Side-findings
|
|
57
|
+
|
|
58
|
+
- **symptom:** <one line — what is wrong>
|
|
59
|
+
**location:** <file:line or the area you saw it>
|
|
60
|
+
**severity:** <low | medium | high | critical — optional>
|
|
61
|
+
**kind:** <drift — optional; only for architecture.md drift>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
One bullet per finding. `symptom` and `location` are required; `severity` is your
|
|
65
|
+
optional read. `kind` is optional and, today, only takes the value `drift` — set it
|
|
66
|
+
**only** for `docs/architecture.md` map staleness (above), so the Orchestrator routes the
|
|
67
|
+
stub to `update-architecture`; omit it for an ordinary code defect. Keep each to the
|
|
68
|
+
symptom + where you saw it — do **not** root-cause or propose a fix (the capture is
|
|
69
|
+
deliberately shallow; investigation happens at pickup). Everything else in your return
|
|
70
|
+
summary stays exactly as it was — the section is an addition, not a replacement.
|
|
71
|
+
|
|
72
|
+
Then **continue your task to its normal end** (or, if you were already done, just
|
|
73
|
+
return). Do not wait for a reply, do not act on the finding, do not open anything.
|
|
74
|
+
|
|
75
|
+
## What the Orchestrator does with it
|
|
76
|
+
|
|
77
|
+
It reads the `## Side-findings` block from your summary and, for each entry, makes the
|
|
78
|
+
same single-line `/spinoff` offer it makes for a human-mentioned defect — lean toward
|
|
79
|
+
offering, one-tap dismissal, never re-offered twice, never pausing. The active task is
|
|
80
|
+
recorded as the parent. You are not involved past returning the bullet.
|
|
81
|
+
|
|
82
|
+
## Uncontemplated Scenarios
|
|
83
|
+
|
|
84
|
+
When a scenario doesn't clearly fit these rules:
|
|
85
|
+
|
|
86
|
+
1. Apply the closest matching channel with reasoning (when torn between side-finding and
|
|
87
|
+
discovery, default to `raise-discovery` — blocking is the safe assumption).
|
|
88
|
+
2. **Flag it**: "This didn't clearly fit note-side-finding. I [noted it / raised it]
|
|
89
|
+
because [reason]. Want to refine the skill?"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playbook-iterate
|
|
3
|
+
description: Propose changes to a client playbook — or extract a new one from the codebase — when the spec collides with a documented pattern (a T6 PLAYBOOK_CONFLICT) or the client asks. Playbooks are client-owned (decision #8); the Architect proposes and the human decides. Use when the Orchestrator routes a T6 discovery resolution to the Architect, or on an explicit "capture how we do X" request.
|
|
4
|
+
origin: vendor
|
|
5
|
+
vendor_version: '{{vendor_version}}'
|
|
6
|
+
invoked-by: [architect]
|
|
7
|
+
trigger-condition: a T6 PLAYBOOK_CONFLICT needs the playbook changed, or the client asks to extract/iterate one
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Playbook Iterate
|
|
11
|
+
|
|
12
|
+
## Core Principle
|
|
13
|
+
|
|
14
|
+
A **playbook** describes _how to build_ a category of software (a backend service, an
|
|
15
|
+
SPA, a testing strategy) in **project-agnostic** terms — placeholder names, never a real
|
|
16
|
+
codebase's symbols. Playbooks are **client-owned** (decision #8): the vendor ships the
|
|
17
|
+
_format_ and the _lookup convention_, never the content. So this skill **proposes**; the
|
|
18
|
+
human **decides**. The Architect never rewrites a client playbook unilaterally.
|
|
19
|
+
|
|
20
|
+
## Where playbooks live (the lookup convention)
|
|
21
|
+
|
|
22
|
+
Two layers, discovered by convention `<topic>.md` — **no index** (an index drifts):
|
|
23
|
+
|
|
24
|
+
1. **Project-local** — `docs/playbooks/<topic>.md`. Harness-managed home, committed.
|
|
25
|
+
2. **User-global** — `~/.claude/playbooks/<topic>.md`. The developer's own generic playbooks.
|
|
26
|
+
|
|
27
|
+
(Both locations are configurable via `paths.playbooks` / `paths.playbooks_global`
|
|
28
|
+
in `harness.config.yml`; the defaults above apply when those keys are unset.)
|
|
29
|
+
|
|
30
|
+
Lookup is **local → global**, and the **local entry overrides** the global one for the
|
|
31
|
+
same topic. A missing playbook is not an error — degrade gracefully. New project-local
|
|
32
|
+
playbooks land in `docs/playbooks/`.
|
|
33
|
+
|
|
34
|
+
## Mode A — resolve a T6 PLAYBOOK_CONFLICT
|
|
35
|
+
|
|
36
|
+
The Orchestrator routes you here when a discovery resolution decided that honoring the
|
|
37
|
+
spec means the **playbook** should change (the playbook is the artifact being updated).
|
|
38
|
+
|
|
39
|
+
1. **Read both sides.** The playbook section in conflict and the spec requirement that
|
|
40
|
+
collides with it. State the contradiction precisely.
|
|
41
|
+
2. **Propose the smallest change** that resolves it, framed as a diff to the playbook
|
|
42
|
+
prose — and note the alternative (change the spec instead). The human already chose
|
|
43
|
+
the direction during `resolve-discovery`; you render that choice into the playbook.
|
|
44
|
+
3. **Edit the project-local playbook** (`docs/playbooks/<topic>.md`), keeping it
|
|
45
|
+
project-agnostic — placeholder names, no symbols from this codebase. A rule that is
|
|
46
|
+
really project-specific belongs in `CLAUDE.md` / an ADR / `CONTEXT.md`, **not** a
|
|
47
|
+
playbook; say so if that's what the conflict actually reveals.
|
|
48
|
+
4. **Return** the updated playbook path and a one-line summary to the Orchestrator, so it
|
|
49
|
+
can record the resolution and resume the paused sub-agent against the corrected source.
|
|
50
|
+
|
|
51
|
+
## Mode B — extract a playbook from the codebase (client-triggered)
|
|
52
|
+
|
|
53
|
+
On an explicit request ("capture how we do X here"):
|
|
54
|
+
|
|
55
|
+
1. **Find the pattern** in the code — the repeated shape, the convention the codebase
|
|
56
|
+
already follows (use `code-explorer` first if the codebase is unfamiliar).
|
|
57
|
+
2. **Generalize it.** Strip the project's real names down to placeholders; describe the
|
|
58
|
+
_pattern_, not the instance. If it can't be generalized, it's project-specific and
|
|
59
|
+
doesn't belong in a playbook.
|
|
60
|
+
3. **Write** `docs/playbooks/<topic>.md` following the playbook conventions documented
|
|
61
|
+
in `docs/playbooks/README.md` (project-agnostic, placeholder names), and report it for
|
|
62
|
+
the human to review.
|
|
63
|
+
|
|
64
|
+
## Report
|
|
65
|
+
|
|
66
|
+
Return to the Orchestrator: the playbook path written/changed, a one-line summary, and —
|
|
67
|
+
for Mode A — confirmation it resolves the cited T6. If the change turned out to be
|
|
68
|
+
project-specific (belongs in `CLAUDE.md`/ADR, not a playbook), report that instead and
|
|
69
|
+
make no playbook edit.
|
|
70
|
+
|
|
71
|
+
## Uncontemplated Scenarios
|
|
72
|
+
|
|
73
|
+
When a case doesn't clearly fit:
|
|
74
|
+
|
|
75
|
+
1. Apply the closest matching approach with reasoning.
|
|
76
|
+
2. **Flag it**: "This isn't covered by the playbook-iterate skill. I did [approach]
|
|
77
|
+
because [reason]. Want to refine the skill?"
|
|
78
|
+
3. Offer to add a rule for the case.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: prd-to-spec
|
|
3
|
+
description: Turn a completed PRD into a task spec — requirements.md (EARS), design.md, and tasks.md. Use when the Spec Author decomposes a PRD into an implementable specification, mentions "write the spec", "EARS requirements", or "requirements/design/tasks".
|
|
4
|
+
origin: vendor
|
|
5
|
+
vendor_version: '{{vendor_version}}'
|
|
6
|
+
phase: pre-implementation
|
|
7
|
+
invoked-by: [spec-author]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PRD to Spec
|
|
11
|
+
|
|
12
|
+
## Core Principle
|
|
13
|
+
|
|
14
|
+
A spec is a contract, not a diff. It says **what** must be true and **why**, never
|
|
15
|
+
**how** line by line. The PRD captured intent through grilling; this skill turns that
|
|
16
|
+
intent into three artifacts an Implementer can build against and a Reviewer can check
|
|
17
|
+
against — without re-interviewing the human.
|
|
18
|
+
|
|
19
|
+
The Spec Author runs with **fresh context**. That is the point: if the PRD is too
|
|
20
|
+
vague to write a testable requirement from, the PRD is not done. Do not paper over
|
|
21
|
+
the gap by guessing — surface it (see "When the PRD is insufficient").
|
|
22
|
+
|
|
23
|
+
## Inputs and outputs
|
|
24
|
+
|
|
25
|
+
- **Input**: a PRD at `docs/prds/<topic>-<date>.md` (owned by the Orchestrator via
|
|
26
|
+
`grill-with-docs`). This skill **consumes** the PRD — it never edits or closes it.
|
|
27
|
+
- **Output**: three files under `.claude/state/tasks/<id>/spec/`. The Orchestrator
|
|
28
|
+
created the issue and the task branch before invoking the Spec Author, so `<id>` is
|
|
29
|
+
real from the start — there is no `draft-<slug>` holder:
|
|
30
|
+
- `requirements.md` — EARS requirements with acceptance criteria
|
|
31
|
+
- `design.md` — files, functions, approach, edge cases, testing
|
|
32
|
+
- `tasks.md` — atomic, ordered, checkbox tasks
|
|
33
|
+
|
|
34
|
+
## Process
|
|
35
|
+
|
|
36
|
+
### 1. Read the PRD in full
|
|
37
|
+
|
|
38
|
+
Read the whole PRD, plus any `CONTEXT.md` glossary terms and `docs/adr/` it
|
|
39
|
+
references. Identify: the user stories, the decisions already closed, what's
|
|
40
|
+
explicitly out of scope, and the assumptions/risks flagged. The closed decisions are
|
|
41
|
+
constraints — the spec must honor them, not relitigate them.
|
|
42
|
+
|
|
43
|
+
### 2. Write `requirements.md` (EARS)
|
|
44
|
+
|
|
45
|
+
Express every requirement in **EARS** (Easy Approach to Requirements Syntax). EARS is
|
|
46
|
+
five sentence patterns — pick the one that fits each requirement:
|
|
47
|
+
|
|
48
|
+
| Pattern | Template | Use for |
|
|
49
|
+
| --------------------- | ------------------------------------------------------------------ | ------------------------------------------------- |
|
|
50
|
+
| **Ubiquitous** | The `<system>` shall `<response>`. | Always-active properties, invariants |
|
|
51
|
+
| **Event-driven** | When `<trigger>`, the `<system>` shall `<response>`. | A response to a specific event/input |
|
|
52
|
+
| **State-driven** | While `<state>`, the `<system>` shall `<response>`. | Behavior that holds during a state |
|
|
53
|
+
| **Optional-feature** | Where `<feature>`, the `<system>` shall `<response>`. | Behavior that exists only if a feature is present |
|
|
54
|
+
| **Unwanted-behavior** | If `<unwanted condition>`, then the `<system>` shall `<response>`. | Error handling, invalid input, failure paths |
|
|
55
|
+
|
|
56
|
+
Complex requirements combine patterns, outer-clause first:
|
|
57
|
+
_"While `<state>`, when `<trigger>`, the system shall `<response>`."_
|
|
58
|
+
|
|
59
|
+
Rules:
|
|
60
|
+
|
|
61
|
+
- **Number every requirement** (`R1`, `R2`, …) so design and tasks can reference them.
|
|
62
|
+
- **Always include the unwanted-behavior path.** A spec with no `If … then …`
|
|
63
|
+
requirements is almost always incomplete — error and invalid-input handling is
|
|
64
|
+
where bugs live.
|
|
65
|
+
- **One requirement, one shall.** Split compound sentences.
|
|
66
|
+
- **Testable, not vague.** "shall respond quickly" is not a requirement; "shall
|
|
67
|
+
respond within 200ms" is.
|
|
68
|
+
- Group requirements under the user story or capability they serve.
|
|
69
|
+
- Add a short **Acceptance criteria** list per capability — the observable facts a
|
|
70
|
+
Reviewer checks.
|
|
71
|
+
|
|
72
|
+
Template:
|
|
73
|
+
|
|
74
|
+
```markdown
|
|
75
|
+
# Requirements — <topic>
|
|
76
|
+
|
|
77
|
+
> Source PRD: docs/prds/<topic>-<date>.md
|
|
78
|
+
|
|
79
|
+
## <Capability / user story>
|
|
80
|
+
|
|
81
|
+
- **R1** (event): When <trigger>, the system shall <response>.
|
|
82
|
+
- **R2** (unwanted): If <invalid condition>, then the system shall <response>.
|
|
83
|
+
- **R3** (ubiquitous): The system shall <invariant>.
|
|
84
|
+
|
|
85
|
+
### Acceptance criteria
|
|
86
|
+
|
|
87
|
+
- [ ] <observable fact a reviewer can verify>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Write `design.md`
|
|
91
|
+
|
|
92
|
+
The _how_, at the level a competent implementer needs — not a transcript of the code.
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
# Design — <topic>
|
|
96
|
+
|
|
97
|
+
## Approach
|
|
98
|
+
|
|
99
|
+
<2–5 sentences: the shape of the solution and why, honoring the PRD's closed decisions.>
|
|
100
|
+
|
|
101
|
+
## Files
|
|
102
|
+
|
|
103
|
+
- `path/to/file.ts` — <created|modified> — <what it holds>
|
|
104
|
+
|
|
105
|
+
## Functions / interfaces
|
|
106
|
+
|
|
107
|
+
- `functionName(args): ReturnType` — <contract: what it guarantees, which Rs it serves>
|
|
108
|
+
|
|
109
|
+
## Edge cases
|
|
110
|
+
|
|
111
|
+
- <edge case> → <intended behavior> (maps to R#)
|
|
112
|
+
|
|
113
|
+
## Testing approach
|
|
114
|
+
|
|
115
|
+
- <what to test and at which level — unit / integration; what NOT to test and why>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Honor the project's playbooks (looked up by topic — `docs/playbooks/<topic>.md`, then
|
|
119
|
+
the global layer) and `coding-conventions` for structure, naming, and the testing
|
|
120
|
+
pyramid. If the design would contradict a playbook, that's a discovery, not a silent
|
|
121
|
+
deviation (T6).
|
|
122
|
+
|
|
123
|
+
### 4. Write `tasks.md`
|
|
124
|
+
|
|
125
|
+
Atomic, ordered checkboxes. Each task is a **vertical slice** (a behavior, not a
|
|
126
|
+
layer) so the Implementer can run TDD red→green per task. Reference the requirements
|
|
127
|
+
each task satisfies.
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
# Tasks — <topic>
|
|
131
|
+
|
|
132
|
+
- [ ] T1 — <smallest behavior that proves the path end-to-end> (R1)
|
|
133
|
+
- [ ] T2 — <next behavior> (R2)
|
|
134
|
+
- [ ] T3 — <error path> (R2, R3)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Rules: order so the first task is a tracer bullet; never "write all tests" then
|
|
138
|
+
"write all code"; keep each task small enough to verify on its own.
|
|
139
|
+
|
|
140
|
+
### 5. Self-check before handing off
|
|
141
|
+
|
|
142
|
+
- [ ] Every PRD user story maps to at least one requirement.
|
|
143
|
+
- [ ] Every requirement is EARS-formatted and testable.
|
|
144
|
+
- [ ] At least one unwanted-behavior (`If … then …`) requirement exists.
|
|
145
|
+
- [ ] Every requirement is covered by at least one task.
|
|
146
|
+
- [ ] No closed PRD decision is contradicted.
|
|
147
|
+
|
|
148
|
+
### 6. Emit `spec_created`
|
|
149
|
+
|
|
150
|
+
Telemetry — record that the spec landed. Count the EARS requirements in
|
|
151
|
+
`requirements.md` (each `R<N>` entry, e.g. `R1`, `R2`, …) and emit via Bash:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
.claude/hooks/lib/lemony.sh emit spec_created \
|
|
155
|
+
--task-id="<id>" \
|
|
156
|
+
--topic="<slug>" \
|
|
157
|
+
--requirements=<count>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`<slug>` is the topic part of the task branch (`harness/<id>-<slug>`). The CLI
|
|
161
|
+
Zod-validates the line and appends it to `.claude/state/events.jsonl`.
|
|
162
|
+
|
|
163
|
+
Then hand off to `spec-to-issue` to fill the issue body with the externalized spec.
|
|
164
|
+
|
|
165
|
+
## When the PRD is insufficient
|
|
166
|
+
|
|
167
|
+
If a requirement can't be written without choosing between >1 valid option the PRD
|
|
168
|
+
left open, that's a **T2 UNSPECIFIED_DECISION** discovery — the spec cannot be
|
|
169
|
+
self-sufficient. Do not guess. **Run the `raise-discovery` skill**: write the entry to
|
|
170
|
+
`discoveries.md`, return the one-line summary, and stop. The Orchestrator mediates the
|
|
171
|
+
question with the human, the PRD/spec improves, and you are re-invoked with the
|
|
172
|
+
decision.
|
|
173
|
+
|
|
174
|
+
## Uncontemplated Scenarios
|
|
175
|
+
|
|
176
|
+
When a scenario doesn't clearly fit these rules:
|
|
177
|
+
|
|
178
|
+
1. Apply the closest matching approach with reasoning.
|
|
179
|
+
2. **Flag it**: "This scenario isn't covered by the prd-to-spec skill. I applied
|
|
180
|
+
[approach] because [reason]. Want to update the skill?"
|
|
181
|
+
3. Offer to add a new rule for the case.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: raise-discovery
|
|
3
|
+
description: Pause the task and escalate when reality contradicts or exceeds the plan, instead of improvising. Use when a sub-agent (Spec Author, Implementer, Reviewer, Architect) hits a T1–T6 case — a contradiction, an unspecified decision, scope drift, an existing solution, an infeasibility, or a playbook conflict — and needs a human decision before continuing.
|
|
4
|
+
origin: vendor
|
|
5
|
+
vendor_version: '{{vendor_version}}'
|
|
6
|
+
invoked-by: [spec-author, implementer, reviewer, architect]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Raise Discovery
|
|
10
|
+
|
|
11
|
+
## Core Principle
|
|
12
|
+
|
|
13
|
+
A sub-agent does **not** improvise when reality contradicts or exceeds the plan. It
|
|
14
|
+
**escalates to the human** through the Orchestrator — like a compiler stopping on a
|
|
15
|
+
type error instead of guessing what you meant. The fresh-context sub-agent is the
|
|
16
|
+
sensor; the human is the arbiter. Guessing past a real ambiguity is how a confident,
|
|
17
|
+
wrong implementation gets built.
|
|
18
|
+
|
|
19
|
+
This skill is the **raising** half of the protocol. You write one entry, return a
|
|
20
|
+
one-line summary, and **stop**. You do not flip labels, you do not dialogue with the
|
|
21
|
+
human, and you do not resume yourself — the Orchestrator owns all of that (it runs
|
|
22
|
+
`resolve-discovery`) and will re-invoke you with the decision when it's settled.
|
|
23
|
+
|
|
24
|
+
## When to raise — the taxonomy (T1–T6)
|
|
25
|
+
|
|
26
|
+
| Tag | Type | Raise when… |
|
|
27
|
+
| ------ | -------------------- | ---------------------------------------------------------- |
|
|
28
|
+
| **T1** | CONTRADICTION | Existing code/env contradicts the plan or spec. |
|
|
29
|
+
| **T2** | UNSPECIFIED_DECISION | The plan is silent and **>1 valid option** exists. |
|
|
30
|
+
| **T3** | SCOPE_DRIFT | Implementing the plan requires touching out-of-scope work. |
|
|
31
|
+
| **T4** | EXISTING_SOLUTION | The plan assumes building something that already exists. |
|
|
32
|
+
| **T5** | INFEASIBILITY | The plan is not implementable as written. |
|
|
33
|
+
| **T6** | PLAYBOOK_CONFLICT | Honoring the spec would contradict a client playbook. |
|
|
34
|
+
|
|
35
|
+
## When NOT to raise (resolve it yourself)
|
|
36
|
+
|
|
37
|
+
Escalation is for decisions with architectural or scope impact, not for everything
|
|
38
|
+
unstated. Decide these yourself and note them in your normal output:
|
|
39
|
+
|
|
40
|
+
- Local naming, formatting, file layout with no downstream impact.
|
|
41
|
+
- Cases already covered by a playbook or `coding-conventions` — follow it.
|
|
42
|
+
- A single obviously-correct option (no genuine fork).
|
|
43
|
+
|
|
44
|
+
The bar for **T2** is the sharpest: raise only when the options are genuinely
|
|
45
|
+
different _and_ the choice has consequences a human would want to make. "The spec
|
|
46
|
+
didn't name the variable" is not a discovery; "the spec didn't say whether an empty
|
|
47
|
+
input errors or defaults, and both are defensible" is.
|
|
48
|
+
|
|
49
|
+
## Process
|
|
50
|
+
|
|
51
|
+
### 1. Confirm it's a real discovery
|
|
52
|
+
|
|
53
|
+
Re-read the relevant spec / PRD / playbook section. If it actually answers the
|
|
54
|
+
question, you don't have a discovery — proceed. If, and only if, it leaves a
|
|
55
|
+
consequential fork open, continue.
|
|
56
|
+
|
|
57
|
+
### 2. Append an entry to `discoveries.md`
|
|
58
|
+
|
|
59
|
+
The file is `.claude/state/tasks/<id>/discoveries.md`, **append-only**. Create it with
|
|
60
|
+
an `# Discoveries — task <id>` heading if it doesn't exist yet. Read any existing
|
|
61
|
+
entries to pick the next sequential id (`D001`, `D002`, …). Append a new section —
|
|
62
|
+
never edit or delete a prior one:
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
## D001 — T2 UNSPECIFIED_DECISION · raised <YYYY-MM-DD>
|
|
66
|
+
|
|
67
|
+
- **Subtask context:** <which agent + which subtask/step you were on>
|
|
68
|
+
- **Plan says:** <what the spec/PRD/plan states — quote or cite the line>
|
|
69
|
+
- **Reality:** <what you found that contradicts or exceeds it>
|
|
70
|
+
- **Proposed:** <the option(s) you see, with a one-line trade-off each>
|
|
71
|
+
- **Question:** <the single, precise decision the human must make>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Fill **every** field. The entry must be self-sufficient: the Orchestrator and the
|
|
75
|
+
human resolve from this file alone, without your context. Leave the `**Resolution**`
|
|
76
|
+
block out — the Orchestrator appends it under this same header when the decision is
|
|
77
|
+
made. Leave `paused_from` out too: the Orchestrator records the state being left when
|
|
78
|
+
it pauses the task; that is its job, not yours.
|
|
79
|
+
|
|
80
|
+
### 3. Return a one-line summary and stop
|
|
81
|
+
|
|
82
|
+
Return to the Orchestrator exactly this shape, nothing more:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Discovery D001 (T2/UNSPECIFIED_DECISION) raised — see tasks/<id>/discoveries.md
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then **stop**. Do not keep working, do not pick an option, do not transition labels.
|
|
89
|
+
The Orchestrator will move the task to `paused_for_clarification`, add the
|
|
90
|
+
`harness:discovery:T*` label, mediate with the human, and re-invoke you with the
|
|
91
|
+
resolution. (The issue exists from the start of `spec-in-progress`, before any
|
|
92
|
+
sub-agent runs, so there is always an issue to label.) When it does, you resume from
|
|
93
|
+
the decision in the entry's `**Resolution**` block — the `paused_from` state the
|
|
94
|
+
Orchestrator records at pause time tells it where you left off.
|
|
95
|
+
|
|
96
|
+
## Scope note
|
|
97
|
+
|
|
98
|
+
T6 PLAYBOOK_CONFLICT (and any resolution that updates an ADR, `docs/architecture.md`,
|
|
99
|
+
or a client playbook) is owned by the **Architect**: raise it normally, and the
|
|
100
|
+
Orchestrator routes the artifact update to the on-demand Architect (`write-adr` /
|
|
101
|
+
`update-architecture` / `playbook-iterate`) before resuming you. Telemetry for
|
|
102
|
+
discoveries (a `discovery_raised` event) is deferred to a later phase; in this build the
|
|
103
|
+
durable record is `discoveries.md` plus the issue label.
|
|
104
|
+
|
|
105
|
+
## Uncontemplated Scenarios
|
|
106
|
+
|
|
107
|
+
When a scenario doesn't clearly fit these rules:
|
|
108
|
+
|
|
109
|
+
1. Apply the closest matching approach with reasoning.
|
|
110
|
+
2. **Flag it**: "This scenario isn't covered by the raise-discovery skill. I applied
|
|
111
|
+
[approach] because [reason]. Want to update the skill?"
|
|
112
|
+
3. Offer to add a new rule for the case.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: resolve-discovery
|
|
3
|
+
description: Mediate a raised discovery with the human and resume the paused sub-agent. Use when the Orchestrator receives a "Discovery D00x raised" summary — it pauses the task, arbitrates the T1–T6 question with the human, routes the artifact update to its owner, records the resolution, and re-invokes the paused sub-agent with the decision.
|
|
4
|
+
origin: vendor
|
|
5
|
+
vendor_version: '{{vendor_version}}'
|
|
6
|
+
invoked-by: [orchestrator]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Resolve Discovery
|
|
10
|
+
|
|
11
|
+
## Core Principle
|
|
12
|
+
|
|
13
|
+
This is the **resolving** half of the interrupt-on-discovery protocol; the sub-agent
|
|
14
|
+
side is `raise-discovery`. The Orchestrator is the only one who talks to the human and
|
|
15
|
+
the only one who moves labels, so it owns mediation end to end: pause the task,
|
|
16
|
+
arbitrate, route the fix to whoever owns the artifact, record the decision, and resume
|
|
17
|
+
the sub-agent that stopped. The discovery is not closed until the paused sub-agent has
|
|
18
|
+
been re-invoked with the decision.
|
|
19
|
+
|
|
20
|
+
You run this when a sub-agent returns a summary of the shape
|
|
21
|
+
`Discovery D001 (T2/UNSPECIFIED_DECISION) raised — see tasks/<id>/discoveries.md`.
|
|
22
|
+
|
|
23
|
+
## Process
|
|
24
|
+
|
|
25
|
+
### 1. Pause the task
|
|
26
|
+
|
|
27
|
+
The sub-agent already wrote the entry and stopped. Record where it stopped and flip
|
|
28
|
+
state:
|
|
29
|
+
|
|
30
|
+
1. In the discovery's section in `.claude/state/tasks/<id>/discoveries.md`, add a
|
|
31
|
+
`paused_from:` line capturing the status the task is leaving (`spec-in-progress`,
|
|
32
|
+
`in-progress`, or `in-review`) — this is the state you'll resume to. You write this,
|
|
33
|
+
not the sub-agent.
|
|
34
|
+
2. Reflect the pause onto the GitHub issue with the `discovery` CLI verb. In one
|
|
35
|
+
fail-loud call it flips the status label (mutually exclusive)
|
|
36
|
+
`harness:status:<current> → harness:status:paused-for-clarification`, adds the
|
|
37
|
+
discovery flag `harness:discovery:T<n>` (presence-based, multiple allowed), and posts
|
|
38
|
+
a comment with the entry so the pause is visible on GitHub, not just in local state:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
.claude/hooks/lib/lemony.sh discovery pause \
|
|
42
|
+
--task-id=<id> --tier=T<n> --status=<current> \
|
|
43
|
+
--note="<one-line gist of the question>"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Keep `--note` to a single line — the full `Plan says / Reality / Question` entry
|
|
47
|
+
lives in `discoveries.md`; the comment only needs a pointer-gist (omit `--note`
|
|
48
|
+
entirely and it links to the file). The label flip is **load-bearing**: a non-zero
|
|
49
|
+
exit means it did not land — surface it and retry, do **not** proceed as if the task
|
|
50
|
+
were paused. The comment is best-effort; if only it fails you'll see a `Warning:` but
|
|
51
|
+
the pause still stands. The Orchestrator creates the issue at the start of
|
|
52
|
+
`spec-in-progress`, before any sub-agent runs, so the issue always exists by the time
|
|
53
|
+
a discovery is raised — even a spec-time T2 during `prd-to-spec`.
|
|
54
|
+
|
|
55
|
+
### 2. Mediate with the human
|
|
56
|
+
|
|
57
|
+
Read the entry. Present it faithfully — the `Plan says` / `Reality` / `Proposed` /
|
|
58
|
+
`Question` — and ask the human the single question it poses. Add your own read if it
|
|
59
|
+
helps, but **do not decide for them**: a discovery exists precisely because the choice
|
|
60
|
+
has consequences worth a human's call. If the human's answer raises a _new_ fork, that
|
|
61
|
+
is a second discovery — append it, don't fold it in.
|
|
62
|
+
|
|
63
|
+
### 3. Route the artifact update to its owner
|
|
64
|
+
|
|
65
|
+
The agent that **created** an artifact is the one that updates it. Map the decision to
|
|
66
|
+
the artifact it changes, then invoke that owner (fresh context, Task tool) with the
|
|
67
|
+
decision + the entry as context:
|
|
68
|
+
|
|
69
|
+
| Artifact changed by the decision | Owner to invoke |
|
|
70
|
+
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `spec/requirements.md`, `spec/design.md`, `spec/tasks.md` | **Spec Author** |
|
|
72
|
+
| Implementation code, `progress.md`, `notes.md` | **Implementer** (often just the resumed sub-agent) |
|
|
73
|
+
| `docs/adr/NNNN-<slug>.md`, `docs/architecture.md`, `docs/playbooks/` | **Architect** (on-demand) — `write-adr` to record the decision, `update-architecture` to keep the map true, `playbook-iterate` for a `T6 PLAYBOOK_CONFLICT` |
|
|
74
|
+
|
|
75
|
+
Not every resolution needs an artifact update first. If the decision is simply "do X"
|
|
76
|
+
with no change to the contract, skip straight to recording it and resuming. If it
|
|
77
|
+
changes the contract (a spec requirement, an ADR), the owner updates the artifact
|
|
78
|
+
**before** the paused sub-agent resumes, so it resumes against the corrected source.
|
|
79
|
+
|
|
80
|
+
### 4. Record the resolution
|
|
81
|
+
|
|
82
|
+
Append a `**Resolution**` block under the discovery's existing header (append-only —
|
|
83
|
+
do not edit the raise fields):
|
|
84
|
+
|
|
85
|
+
```markdown
|
|
86
|
+
**Resolution** (Orchestrator)
|
|
87
|
+
|
|
88
|
+
- **Decision:** <the human's call, stated plainly>
|
|
89
|
+
- **Artifact updated:** <file + owner who changed it, or "none — decision only">
|
|
90
|
+
- **Resumed at:** <YYYY-MM-DD> — <agent> re-invoked from `paused_from: <state>`
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 5. Resume and clear the flag
|
|
94
|
+
|
|
95
|
+
1. Reflect the resume onto the issue with the same `discovery` CLI verb — it removes
|
|
96
|
+
the `harness:discovery:T<n>` flag and flips the status back to `paused_from`
|
|
97
|
+
(`in-progress`, `in-review`, or `spec-in-progress`):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
.claude/hooks/lib/lemony.sh discovery resume \
|
|
101
|
+
--task-id=<id> --tier=T<n> --status=<paused_from>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Same fail-loud contract: a non-zero exit means the flag/status did not flip back.
|
|
105
|
+
|
|
106
|
+
2. Re-invoke the paused sub-agent (fresh context) with: the issue, the task-state
|
|
107
|
+
paths, the decision, and the updated artifact. It picks up from where it stopped.
|
|
108
|
+
|
|
109
|
+
## Closeout invariant
|
|
110
|
+
|
|
111
|
+
At `task-closeout`, **no `discoveries.md` entry may lack a `Resolution` block** with
|
|
112
|
+
`Decision` / `Resumed at` filled, and **no `harness:discovery:*` label may remain** on
|
|
113
|
+
the issue. An unresolved discovery means a sub-agent is still paused — the task is not
|
|
114
|
+
done. If you find one at closeout, resolve it first.
|
|
115
|
+
|
|
116
|
+
## Uncontemplated Scenarios
|
|
117
|
+
|
|
118
|
+
When a scenario doesn't clearly fit these rules:
|
|
119
|
+
|
|
120
|
+
1. Apply the closest matching approach with reasoning.
|
|
121
|
+
2. **Flag it**: "This scenario isn't covered by the resolve-discovery skill. I applied
|
|
122
|
+
[approach] because [reason]. Want to update the skill?"
|
|
123
|
+
3. Offer to add a new rule for the case.
|