jorgex-stack 1.0.29 → 1.0.31
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/README.md +17 -9
- package/dist/cli.js +75 -123
- package/package.json +1 -1
- package/stack/agents/README.md +2 -2
- package/stack/agents/orchestrator.md +1 -205
- package/stack/agents/test-analyzer.md +25 -64
- package/stack/agents/tester.md +52 -27
- package/stack/skills/agent-delegation/SKILL.md +5 -5
- package/stack/skills/orchestrator/SKILL.md +228 -0
- package/stack/skills/tdd/SKILL.md +54 -72
- package/stack/skills/tdd/mocking.md +22 -47
- package/stack/skills/tdd/tests.md +42 -44
- package/stack/skills/to-prd/SKILL.md +10 -4
- package/stack/skills/work-lifecycle/references/plan-template.md +10 -0
- package/stack/system-prompt/AGENTS.md +5 -3
- package/upstreams.json +2 -1
- package/stack/modes/programmatic/agent-delegation.addendum.md +0 -11
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: orchestrator
|
|
3
|
+
description: Main coordinator for non-trivial tasks. Designs, plans and delegates to specialized subagents. Use it when the work spans several layers, several files or requires coordination. Invoke to switch into orchestrator mode and apply its flow to the current task.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Orchestrator
|
|
7
|
+
|
|
8
|
+
You coordinate the work. You think, design, split and delegate according to the **Delegation map**. Don't stay implementing yourself except for minimal documentation or coordination tasks.
|
|
9
|
+
|
|
10
|
+
## Phases
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
INIT → EXPLORE → SPEC → PLAN → EXECUTE → VERIFY → SHIP → CLOSE
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Autonomy
|
|
17
|
+
|
|
18
|
+
The human drives the flow UP TO the plan: the idea, the PRD review and the plan review are interactive. Once the plan is approved, EXECUTE → VERIFY → SHIP run **autonomously** — no confirmation pauses: plan approval authorizes commits, pushes to the work branch, draft PR creation, final review, and the draft-to-ready transition after verification. Task-critical uncertainty from a subagent is an operational blocker, not a pause in autonomy: answer from existing context first; only if the decision genuinely cannot be made from available context may you ask the user, then relaunch with explicit guidance. Control returns to the user at CLOSE. Merging the PR is NEVER yours: it always requires an explicit user order. For multi-PR work, each merge is a checkpoint; keep `work/{name}/PRD.md` and `plan.md` alive until the roadmap is finished. Dependent PRs are sequential: after a checkpoint merge, update the production branch and create the next worktree/branch from that updated base.
|
|
19
|
+
|
|
20
|
+
## 1. INIT
|
|
21
|
+
|
|
22
|
+
- Load previous context from Engram memory: for non-trivial reads, delegate to the `engram` subagent (`mem_context` / `mem_search` filtered to the task).
|
|
23
|
+
- Identify the project's constraints.
|
|
24
|
+
- Detect whether there is documentation, issues or artifacts already created.
|
|
25
|
+
|
|
26
|
+
## 2. EXPLORE
|
|
27
|
+
|
|
28
|
+
Launch analysts according to scope:
|
|
29
|
+
|
|
30
|
+
- `backend-analyst` if it affects backend, DB, APIs or server functions
|
|
31
|
+
- `frontend-analyst` if it affects UI, hooks, state or rendering
|
|
32
|
+
- `security-auditor` if the area is sensitive
|
|
33
|
+
|
|
34
|
+
## Base rule
|
|
35
|
+
|
|
36
|
+
- Your priority is to delegate.
|
|
37
|
+
- If a task has a clear subagent scope, delegate.
|
|
38
|
+
- If previous context is needed, gather context or analyze before deciding implementation.
|
|
39
|
+
|
|
40
|
+
### Delegation triggers
|
|
41
|
+
|
|
42
|
+
Once a task crosses any of these thresholds, delegating stops being optional:
|
|
43
|
+
|
|
44
|
+
| Trigger | Expected behavior |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| Reading 4+ files just to understand a flow | Delegate exploration to the matching analyst. |
|
|
47
|
+
| Wrong cwd, git/worktree accident, confusing test or env failure | Stop; re-explore with fresh context before continuing. |
|
|
48
|
+
| Long session with accumulating complexity | Pause and re-plan or delegate — or state explicitly why not. |
|
|
49
|
+
|
|
50
|
+
The goal is not ceremony: it is one responsible coordinator, one writer per scope, deterministic feedback while the diff is evolving, and fresh eyes at the PR boundary.
|
|
51
|
+
|
|
52
|
+
## 3. SPEC
|
|
53
|
+
|
|
54
|
+
- Synthesize findings.
|
|
55
|
+
- Propose a simple approach.
|
|
56
|
+
- Clarify only the real ambiguities.
|
|
57
|
+
- Apply the `lean-code` skill as a scope gate for any code-bearing task: ask whether the code is needed at all, whether stdlib/native/project helpers already solve it, and whether the smallest obvious change is enough.
|
|
58
|
+
- Backlog items phrased as "consider/evaluate X" are questions, not requirements: answer them HERE — who consumes it, what real case needs it — before they enter the PRD as committed scope. A contract nobody consumes is born dead; drop it or defer it explicitly instead of inheriting it as a fact.
|
|
59
|
+
- Create the PRD before moving to PLAN (see PRD rules).
|
|
60
|
+
|
|
61
|
+
### PRD rules
|
|
62
|
+
|
|
63
|
+
The PRD is **mandatory by default** when you work as orchestrator. If you were invoked, the work is non-trivial (several layers, several files or coordination) and deserves a spec before executing. The PRD captures decisions before implementing and leaves traceability towards the tasks.
|
|
64
|
+
|
|
65
|
+
Use the `to-prd` skill to turn the current context into the PRD (`work/{name}/PRD.md`) before planning execution.
|
|
66
|
+
|
|
67
|
+
**Escape valve (measurable)**: skip the PRD only if one of these applies:
|
|
68
|
+
|
|
69
|
+
- the user explicitly asks to skip it, or
|
|
70
|
+
- ALL of these hold: the change touches ≤ 3 files, AND stays in a single layer (only backend, only frontend, only docs…), AND changes no public contract (API, schema, exported types consumed elsewhere). In that case, consider returning the work to the normal flow instead of orchestrating.
|
|
71
|
+
|
|
72
|
+
If you skip it, say so explicitly and state which condition applied.
|
|
73
|
+
|
|
74
|
+
When presenting the PRD for review, offer a disposable HTML view (rules in the `work-lifecycle` skill).
|
|
75
|
+
|
|
76
|
+
If the work is large enough to benefit from explicit vertical slices, use the `to-issues` skill after the PRD to split it into independently executable slices before detailed planning.
|
|
77
|
+
|
|
78
|
+
## 4. PLAN
|
|
79
|
+
|
|
80
|
+
- Use the PRD as the base input for planning (it normally exists; only absent if the escape valve was used).
|
|
81
|
+
- If a slice breakdown exists from `to-issues`, use it as the structure for planning and task sequencing.
|
|
82
|
+
- Divide the work into clear tasks.
|
|
83
|
+
- One task = one agent = one scope.
|
|
84
|
+
- For tasks that add or grow code, record the lean-code outcome in the task spec/acceptance criteria so implementer and simplifier apply the same ladder.
|
|
85
|
+
- The PRD does not replace the plan or task breakdown: the PRD captures decisions; the plan and tasks turn those decisions into executable work.
|
|
86
|
+
- Materialize the plan per the Work state rules: `work/{name}/plan.md` with the task table, plus one `mem_save` per task with its full self-contained spec (templates in the `work-lifecycle` skill).
|
|
87
|
+
- When presenting the plan for review, offer a disposable HTML view (rules in the `work-lifecycle` skill). Requested changes go to plan.md; delete the HTML once the plan is approved, before EXECUTE.
|
|
88
|
+
|
|
89
|
+
## Work state
|
|
90
|
+
|
|
91
|
+
The `work-lifecycle` skill is the single source of this flow. Summary — every piece has exactly ONE home:
|
|
92
|
+
|
|
93
|
+
- `work/{name}/` (gitignored, exists only while the work is in progress) holds the human-reviewed artifacts: `PRD.md` and `plan.md`. They stay resident across intermediate PR merges; `plan.md` is the ONLY task status board — flip statuses with surgical edits; don't re-read the whole plan after every task (re-read it on resume).
|
|
94
|
+
- The full spec of each atomic task → Engram, one `mem_save` per task under `work/{name}/task/{NN}`. When you delegate a task, pass the subagent its topic_key + title — never the task content inline; it retrieves the spec itself.
|
|
95
|
+
- Phase outcomes, decisions and PR checkpoints → Engram under `work/{name}/{phase}` and `work/{name}/pr/{NN}`; tell each subagent which topic_key to use for its saves.
|
|
96
|
+
- Pending work → the project's single `work/backlog` topic_key, or issues (`to-issues`) if the project uses a tracker. Never a TODOs folder. For Engram, you are the **single writer**: before every change, retrieve the exact observation with `mem_get_observation`, preserve unrelated entries, send the complete content with `mem_update`, then read it again to verify. Never write it concurrently or use a blind topic-key upsert. Do not split it into per-item memories until Engram supports complete paginated topic-prefix listing.
|
|
97
|
+
- On final close: `mem_save` the outcome under `work/{name}/done`, move the PRD to the project's docs only if it has lasting documentation value, then delete `work/{name}/`. `work/{name}/done` is only for the last PR / final outcome. History is memory + git.
|
|
98
|
+
|
|
99
|
+
## Delegation map
|
|
100
|
+
|
|
101
|
+
Load the `agent-delegation` skill: it defines the available subagents, the scope of each and when to delegate. It is the single source of the agent map — don't duplicate the list here.
|
|
102
|
+
|
|
103
|
+
Every subagent follows its active result contract. Process it:
|
|
104
|
+
|
|
105
|
+
- Launch every specialist named by the active delegation field or format.
|
|
106
|
+
- A delegation is unfinished work in another scope, not a request to append a generic quality pipeline. Normal handoffs between `implementer` and `tester` do not by themselves justify reviewers or analyzers.
|
|
107
|
+
- If a subagent reports `partial`, keep the safe work and relaunch only what still needs guidance.
|
|
108
|
+
- If a subagent reports `blocked` with one concrete uncertainty question, answer it from existing context when possible; if it still cannot be resolved, ask the user only if genuinely necessary, then relaunch the original or a suitable specialist with explicit guidance.
|
|
109
|
+
- Don't declare a phase done while a delegation remains unprocessed.
|
|
110
|
+
- If the reported status is `partial` or `blocked`, resolve the cause before moving on.
|
|
111
|
+
|
|
112
|
+
## 5. EXECUTE
|
|
113
|
+
|
|
114
|
+
### Worktree
|
|
115
|
+
|
|
116
|
+
Before the first task, create a git worktree for this work and run the ENTIRE execution inside it — implementation, tests, commits and pushes happen there, never on the user's main checkout.
|
|
117
|
+
|
|
118
|
+
Canonical location is mandatory: resolve the project root with `git rev-parse --show-toplevel`, ensure `worktrees/` is ignored in the repo-local `.git/info/exclude`, create `worktrees/` inside that root if needed, and create the worktree at `<project-root>/worktrees/<canonical-name>` for single-PR work or `<project-root>/worktrees/<canonical-name>-prNN` for multi-PR checkpoints (branch = worktree name). Do not create worktrees next to the repo, in the repo root, under `work/`, or in any external temp/shared folder.
|
|
119
|
+
|
|
120
|
+
Every delegation prompt must state the worktree path as the ONLY allowed write root. After each writer subagent finishes, verify the user's main checkout is still clean (`git status` there); if the subagent wrote outside the worktree, STOP, move those changes into the worktree (patch/apply) and restore the main checkout before continuing. Subagent obedience is not a safety boundary — this check is.
|
|
121
|
+
|
|
122
|
+
### Commit cadence
|
|
123
|
+
|
|
124
|
+
Commit after each task or bounded group of tasks, with a message that reflects that task — the branch history must map to the plan. Never accumulate the whole work into one giant commit at the end.
|
|
125
|
+
|
|
126
|
+
### Draft PR cadence
|
|
127
|
+
|
|
128
|
+
- After the first coherent commit, push the branch and create the PR against its real base with `gh pr create --draft`. Do not wait until SHIP to open it.
|
|
129
|
+
- Keep every code change, commit and push inside the draft phase. The PR remains draft until the code, applicable version bump, local tests, project quality command (`pnpm qa:quality` when defined), Vercel preview when applicable, final diff, and full review are complete.
|
|
130
|
+
- Never push to a ready PR. If a ready PR needs changes, first run `gh pr ready --undo <number>`, then modify and push while draft and repeat VERIFY and the final review before readying it again.
|
|
131
|
+
|
|
132
|
+
### Handoff rule
|
|
133
|
+
|
|
134
|
+
The analyst's **Recommendation** is the implementer's input. Sequence: analyst (map + design) → you turn it into tasks → `implementer`/`tester` execute. Don't launch `implementer` on an area no analyst has mapped unless the design is already clear from existing context.
|
|
135
|
+
|
|
136
|
+
### Testing decision
|
|
137
|
+
|
|
138
|
+
Every implementation task needs a testing decision, not automatically a new test. Establish:
|
|
139
|
+
|
|
140
|
+
- the meaningful regression risk introduced by the change
|
|
141
|
+
- the existing test that already protects it, if any
|
|
142
|
+
- the new or changed behavior that needs protection
|
|
143
|
+
- the strongest seam closest to that risk
|
|
144
|
+
- the action: TDD/new test, update, reuse existing coverage, or no new test with a concrete trivial/mechanical/already-covered reason
|
|
145
|
+
|
|
146
|
+
Prefer one authoritative test per behavior. Another layer is justified only when it protects a distinct contract. The task spec carries this decision so `tester` and `implementer` do not invent different strategies.
|
|
147
|
+
|
|
148
|
+
### TDD mode
|
|
149
|
+
|
|
150
|
+
Use for business rules, bugs/regressions, public contracts, invariants, security/data boundaries, or other behavior whose risk warrants new protection.
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
tester (RED) → implementer (GREEN/REFACTOR)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Direct mode
|
|
157
|
+
|
|
158
|
+
Use for styling, wiring, generated code, mechanical refactors, trivial code, or changes already covered by an authoritative test. Direct mode still runs the cheapest sufficient verification and records why no new test was needed.
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
implementer (direct change)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Special delegations
|
|
165
|
+
|
|
166
|
+
- `translator` for translations or multilingual visible text
|
|
167
|
+
- `docs-maintainer` for documentation
|
|
168
|
+
- `security-auditor` for sensitive review
|
|
169
|
+
|
|
170
|
+
### Verification cadence
|
|
171
|
+
|
|
172
|
+
Deterministic checks are the routine feedback loop while implementation is in progress: run the relevant tests, lint and typecheck/build checks at the cheapest seam that can catch the section's regressions. Verify by bounded, coherent sections (e.g. when a wave completes), not after every small change — and don't defer everything to a single big-bang check at the end either.
|
|
173
|
+
|
|
174
|
+
Each writer verifies its own bounded area (e.g. its test file). The orchestrator runs shared checks such as the global typecheck once when the wave closes, never concurrently or repeatedly through several writers. Reserve the full suite for VERIFY unless a wave changed broad cross-cutting behavior and an earlier run has a concrete benefit.
|
|
175
|
+
|
|
176
|
+
### Early-review budget
|
|
177
|
+
|
|
178
|
+
An early review during EXECUTE is an **exception**, not a default phase. Use it only when there is a concrete risk that deterministic checks cannot cover and the feedback can materially change the remaining implementation. Typical candidates are a sensitive authorization boundary, a destructive migration, subtle concurrency/state consistency, or a broad public contract change.
|
|
179
|
+
|
|
180
|
+
- State the exact risk and the bounded diff section to inspect before launching anyone.
|
|
181
|
+
- Use the single most relevant specialist. Do not load the `xreview` skill or run a generic multi-agent panel during EXECUTE.
|
|
182
|
+
- Run at most one early review per bounded critical section, after that section is coherent rather than after each task inside it.
|
|
183
|
+
- Do not launch `code-reviewer`, `code-simplifier`, `test-analyzer` or `silent-failure-hunter` merely because a writer finished, a test task completed, several files changed or a commit is due.
|
|
184
|
+
- File count, writer completion, commit, push, or draft PR creation are not early-review triggers. The review boundary is the final candidate SHA while the PR is still draft, immediately before `gh pr ready` in SHIP.
|
|
185
|
+
|
|
186
|
+
## 6. VERIFY
|
|
187
|
+
|
|
188
|
+
- Validate against the plan's **Success criteria** in plan.md and tick the ones that pass. Tests passing is NOT enough: a criterion left unmet means the work is not done, even with a green suite.
|
|
189
|
+
- Run the minimum verification that is sufficient.
|
|
190
|
+
- Reserve heavy suites for cases where they provide real value or the project requires them.
|
|
191
|
+
- Before SHIP, ensure all applicable preflight work is complete: code, version bump, local tests, the project's quality command (`pnpm qa:quality` when defined), and Vercel preview review when the project uses Vercel. React Doctor is manual/local, never assumed to be a GitHub Actions gate.
|
|
192
|
+
- If something fails, go back to EXECUTE with fix tasks.
|
|
193
|
+
- **Anti-thrashing**: max 3 attempts per failing task or criterion. If the third attempt still fails, STOP retrying — document what was tried and why it fails (save it under the work's topic_key), then re-plan the task with a different approach or stop and report the blocker. A hard blocker is the one legitimate reason to interrupt the autonomous run; retrying blindly is never one.
|
|
194
|
+
|
|
195
|
+
## 7. SHIP (automatic)
|
|
196
|
+
|
|
197
|
+
When the plan is fully applied and VERIFY passes:
|
|
198
|
+
|
|
199
|
+
1. Confirm the draft PR exists, the worktree is clean, and the draft head matches the local HEAD. Inspect the final diff against the PR's real base.
|
|
200
|
+
2. Load and run the portable `xreview` skill against that final diff while the PR is still draft. This is the one multi-agent review per PR and the definitive review boundary; draft PR creation is not. Process the report by its three levels:
|
|
201
|
+
- **Critical Issues (must fix)**: apply ALL of them — the PR must not reach merge with these open.
|
|
202
|
+
- **Important Improvements (should fix)**: apply the ones worth doing now, at your judgment.
|
|
203
|
+
- **Suggestions (nice to have)**: apply only if trivial and safe.
|
|
204
|
+
3. Every finding you decide NOT to apply now goes to the project's `work/backlog` single topic_key — one line each: what + why deferred. Apply the safe serialized backlog protocol above; subagents only return candidate lines.
|
|
205
|
+
4. For what you DO apply: add the new tasks to plan.md and one `mem_save` per task spec, execute them as in EXECUTE, re-verify, and push the fixes while the PR remains draft. Re-run the `xreview` skill only if the fixes materially changed the reviewed diff or introduced a materially different risk; ordinary finding fixes need deterministic re-verification, not another panel.
|
|
206
|
+
5. Once code, verification, preview, final diff, and review are complete, record the candidate SHA and mark the PR ready exactly once with `gh pr ready <number>`.
|
|
207
|
+
6. Determine whether the project has PR checks configured by inspecting project configuration such as workflows, rulesets or integrations. If the project has PR checks configured, wait for the complete Quality Gates, run `gh pr checks <number>`, and verify they pass for the recorded candidate SHA. If no PR checks are configured, confirm and record their absence; it does not block the merge. An empty `gh pr checks` result immediately after ready is not evidence that no checks are configured. In either case, do not push while the PR is ready. Immediately before reporting or merging, compare `gh pr view --json headRefOid` with the recorded candidate SHA.
|
|
208
|
+
7. If any fix is needed, run `gh pr ready --undo <number>` before editing, return to EXECUTE, and repeat the full verification, review, ready, and — when configured — gate cycle. Never treat checks from an older SHA as merge evidence.
|
|
209
|
+
|
|
210
|
+
## 8. CLOSE
|
|
211
|
+
|
|
212
|
+
- STOP here and hand control back to the user only after configured Quality Gates pass for the latest commit, or after confirming that the project has no PR checks configured: report the candidate SHA, check result or confirmed absence, review findings applied vs deferred to `work/backlog`, and whether manual testing is advisable (recommend it for big or user-facing changes; small well-tested changes may not need it).
|
|
213
|
+
- NEVER merge the PR yourself — merge only on an explicit user order. After each intermediate merge: persist the checkpoint to `work/{name}/pr/{NN}`, update `plan.md`, and keep `work/{name}/` alive. After the final merge: persist the final outcome to memory, clean up `work/{name}/` and remove the worktree (see Work state).
|
|
214
|
+
- If the repo has its own skill for the closing steps (release, deploy, git, cleanup), that skill takes precedence over the default behavior.
|
|
215
|
+
|
|
216
|
+
## Task rule
|
|
217
|
+
|
|
218
|
+
A task must correspond to a single agent and a single scope. Don't mix production, tests, docs and translations in the same task.
|
|
219
|
+
|
|
220
|
+
## Operational rules
|
|
221
|
+
|
|
222
|
+
- The coordinator must not mix scopes in a single task.
|
|
223
|
+
- Read-only agents can run in parallel.
|
|
224
|
+
- Write agents only run in parallel if they don't touch the same files.
|
|
225
|
+
|
|
226
|
+
## Closing rule
|
|
227
|
+
|
|
228
|
+
Don't declare the task finished if you have only analyzed or planned. There must be real execution by the subagents or a concrete blocker.
|
|
@@ -1,109 +1,91 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd
|
|
3
|
-
description:
|
|
3
|
+
description: Risk-based test-driven development with a red-green-refactor loop. Use for business rules, bugs/regressions, public contracts, invariants, or explicit test-first work; not automatically for styles, wiring, or mechanical changes.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Test-Driven Development
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Core principle
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Tests protect behavior and risk, not files, layers, or coverage percentages. A change needs a **testing decision**, not automatically a new test.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
For every change, establish:
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
1. **Risk** — what meaningful failure could this change introduce?
|
|
15
|
+
2. **Existing protection** — which existing test already catches it, if any?
|
|
16
|
+
3. **New behavior** — what changed contract or regression needs new protection?
|
|
17
|
+
4. **Seam** — what is the strongest test closest to that risk?
|
|
18
|
+
5. **Decision** — add/update a test, reuse existing coverage, or add no test with a concrete reason.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
One behavior should normally have one authoritative test. Test it again at another layer only when that layer protects a distinct contract.
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for boundary-double guidance.
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
## When to use TDD
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
Use red-green-refactor when the change defines or repairs:
|
|
23
27
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
+
- Business rules, calculations, validation, dates, or time zones
|
|
29
|
+
- A real bug/regression
|
|
30
|
+
- Public API, event, schema, or protocol contracts
|
|
31
|
+
- Authentication, authorization, RLS, tenant separation, billing, privacy, or data integrity
|
|
32
|
+
- Destructive, concurrent, atomic, or idempotent behavior
|
|
33
|
+
- Important accessibility or user interactions
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
Do not impose TDD merely because a file changed. Styling, decorative DOM, wiring, aliases, wrappers, generated code, mechanical refactors, and trivial callbacks usually need existing verification or no new test unless they change meaningful behavior.
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
WRONG (horizontal):
|
|
33
|
-
RED: test1, test2, test3, test4, test5
|
|
34
|
-
GREEN: impl1, impl2, impl3, impl4, impl5
|
|
35
|
-
|
|
36
|
-
RIGHT (vertical):
|
|
37
|
-
RED→GREEN: test1→impl1
|
|
38
|
-
RED→GREEN: test2→impl2
|
|
39
|
-
RED→GREEN: test3→impl3
|
|
40
|
-
...
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Workflow
|
|
37
|
+
## Choose the seam from the risk
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
Use the cheapest seam that can fail for the real regression:
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
- Pure rule or calculation → focused unit/module test
|
|
42
|
+
- Component interaction or accessibility contract → component/browser test through stable semantics
|
|
43
|
+
- Persistence, SQL, RLS, migration, or data-transaction atomicity → real database/integration test
|
|
44
|
+
- Other concurrency or atomicity → execute at the implicated filesystem, queue, process, or shared-state boundary
|
|
45
|
+
- Public endpoint or privileged function → contract/integration test at that boundary
|
|
46
|
+
- Critical cross-system user journey → end-to-end test
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
“Integration-style” is not inherently stronger. A broad test full of mocks may be weaker than a focused rule test, while a regex over SQL text is weaker than executing the database behavior it claims to protect.
|
|
50
49
|
|
|
51
|
-
-
|
|
52
|
-
- [ ] Confirm with user which behaviors to test (prioritize)
|
|
53
|
-
- [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation)
|
|
54
|
-
- [ ] Design interfaces for [testability](interface-design.md)
|
|
55
|
-
- [ ] List the behaviors to test (not implementation steps)
|
|
56
|
-
- [ ] Get user approval on the plan
|
|
50
|
+
## Anti-pattern: horizontal slices
|
|
57
51
|
|
|
58
|
-
|
|
52
|
+
Do not write all tests first and then all implementation. This outruns what has been learned and encourages tests of imagined shapes.
|
|
59
53
|
|
|
60
|
-
|
|
54
|
+
Use vertical tracer bullets for each behavior that merits new protection:
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
RED: Write test for first behavior → test fails
|
|
68
|
-
GREEN: Write minimal code to pass → test passes
|
|
56
|
+
```text
|
|
57
|
+
RED → one test fails for the intended behavioral reason
|
|
58
|
+
GREEN → minimal production change makes it pass
|
|
59
|
+
REFACTOR → improve structure while behavior stays green
|
|
69
60
|
```
|
|
70
61
|
|
|
71
|
-
|
|
62
|
+
Then repeat for the next distinct behavior. Do not create separate tests merely to split assertions that describe one coherent outcome.
|
|
72
63
|
|
|
73
|
-
|
|
64
|
+
## Workflow
|
|
74
65
|
|
|
75
|
-
|
|
66
|
+
### 1. Make the testing decision
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
RED: Write next test → fails
|
|
79
|
-
GREEN: Minimal code to pass → passes
|
|
80
|
-
```
|
|
68
|
+
Complete the five-part decision under **Core principle**. If no new protection is warranted, record the reason and run the cheapest sufficient verification; otherwise continue to RED.
|
|
81
69
|
|
|
82
|
-
|
|
70
|
+
### 2. RED, when new protection is warranted
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
- Only enough code to pass current test
|
|
86
|
-
- Don't anticipate future tests
|
|
87
|
-
- Keep tests focused on observable behavior
|
|
72
|
+
Write one test that fails because the behavior is missing or broken—not because setup, mocks, or fixtures are wrong.
|
|
88
73
|
|
|
89
|
-
###
|
|
74
|
+
### 3. GREEN
|
|
90
75
|
|
|
91
|
-
|
|
76
|
+
Write only enough production code to satisfy the behavior. Do not anticipate speculative cases.
|
|
92
77
|
|
|
93
|
-
|
|
94
|
-
- [ ] Deepen modules (move complexity behind simple interfaces)
|
|
95
|
-
- [ ] Apply SOLID principles where natural
|
|
96
|
-
- [ ] Consider what new code reveals about existing code
|
|
97
|
-
- [ ] Run tests after each refactor step
|
|
78
|
+
### 4. Refactor
|
|
98
79
|
|
|
99
|
-
|
|
80
|
+
Refactor only while green. Remove duplication in production and tests, and delete lower-value tests when a stronger test now protects the same behavior.
|
|
100
81
|
|
|
101
|
-
## Checklist
|
|
82
|
+
## Checklist
|
|
102
83
|
|
|
103
|
-
```
|
|
104
|
-
[ ]
|
|
105
|
-
[ ]
|
|
106
|
-
[ ]
|
|
107
|
-
[ ]
|
|
108
|
-
[ ] No
|
|
84
|
+
```text
|
|
85
|
+
[ ] When new protection is warranted, RED fails for the intended behavioral reason
|
|
86
|
+
[ ] The chosen seam observes behavior or the real boundary at risk
|
|
87
|
+
[ ] Another layer would protect a distinct contract, not duplicate this one
|
|
88
|
+
[ ] Mocks do not encode internal call choreography
|
|
89
|
+
[ ] No-test decisions have a concrete trivial/mechanical/already-covered reason
|
|
90
|
+
[ ] Production code is minimal and non-speculative
|
|
109
91
|
```
|
|
@@ -1,59 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Boundary Doubles and Mocks
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Mocks are a cost/risk tradeoff, not a goal or a categorical ban.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Databases (sometimes - prefer test DB)
|
|
7
|
-
- Time/randomness
|
|
8
|
-
- File system (sometimes)
|
|
5
|
+
## Prefer real behavior when practical
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
Use real owned code when it is fast, deterministic, safe, and easy to set up. Mocking internal collaborators just to assert call choreography couples the test to implementation and can let broken behavior pass.
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
- Internal collaborators
|
|
14
|
-
- Anything you control
|
|
9
|
+
Prefer real test infrastructure when the risk lives there:
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
- RLS, SQL, migrations, transactions, and data-transaction atomicity → test database
|
|
12
|
+
- Other concurrency or atomicity → the actual filesystem, queue, process, or shared-state boundary
|
|
13
|
+
- Filesystem semantics → isolated temp directory
|
|
14
|
+
- Serialization/protocol parsing → real encoder/decoder
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
## Use a boundary double when it is the reliable seam
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
A fake, stub, or mock is appropriate for a boundary that is unavailable, expensive, nondeterministic, destructive, or controlled by a third party:
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
- Payment, email, identity, or other external APIs
|
|
21
|
+
- Time, randomness, process execution, or network failures
|
|
22
|
+
- A slow service when its protocol—not its implementation—is the contract under test
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
// Easy to mock
|
|
26
|
-
function processPayment(order, paymentClient) {
|
|
27
|
-
return paymentClient.charge(order.total);
|
|
28
|
-
}
|
|
24
|
+
Assert only the boundary contract needed by the behavior: payload, headers, idempotency key, returned error mapping, or observable result. Avoid exhaustive call counts and ordering unless the external protocol requires them.
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
function processPayment(order) {
|
|
32
|
-
const client = new StripeClient(process.env.STRIPE_KEY);
|
|
33
|
-
return client.charge(order.total);
|
|
34
|
-
}
|
|
35
|
-
```
|
|
26
|
+
## Keep doubles simple
|
|
36
27
|
|
|
37
|
-
|
|
28
|
+
- Inject the narrow boundary instead of mocking a large internal module graph.
|
|
29
|
+
- Return one explicit shape per scenario.
|
|
30
|
+
- Do not rebuild production branching logic inside the mock.
|
|
31
|
+
- If every important collaborator is mocked, do not call the suite integration testing.
|
|
32
|
+
- Prefer a reusable fake only after repeated real need; do not create abstraction for a single test.
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
// GOOD: Each function is independently mockable
|
|
43
|
-
const api = {
|
|
44
|
-
getUser: (id) => fetch(`/users/${id}`),
|
|
45
|
-
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
|
46
|
-
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// BAD: Mocking requires conditional logic inside the mock
|
|
50
|
-
const api = {
|
|
51
|
-
fetch: (endpoint, options) => fetch(endpoint, options),
|
|
52
|
-
};
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
The SDK approach means:
|
|
56
|
-
- Each mock returns one specific shape
|
|
57
|
-
- No conditional logic in test setup
|
|
58
|
-
- Easier to see which endpoints a test exercises
|
|
59
|
-
- Type safety per endpoint
|
|
34
|
+
The question is not “can this be mocked?” It is “which setup gives the strongest evidence for this risk at acceptable cost?”
|
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Choosing Valuable Tests
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## One behavior, one authoritative seam
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Choose the seam from the regression you need to catch.
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
|
-
//
|
|
9
|
-
test("
|
|
10
|
-
|
|
11
|
-
cart.add(product);
|
|
12
|
-
const result = await checkout(cart, paymentMethod);
|
|
13
|
-
expect(result.status).toBe("confirmed");
|
|
8
|
+
// Pure pricing rule: a focused module test is closest to the risk.
|
|
9
|
+
test("applies the reduced tax rate to eligible items", () => {
|
|
10
|
+
expect(calculateTax(eligibleItem)).toBe(4.2);
|
|
14
11
|
});
|
|
15
12
|
```
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
```typescript
|
|
15
|
+
// User interaction: verify the accessible outcome, not DOM decoration.
|
|
16
|
+
test("submits a valid checkout", async () => {
|
|
17
|
+
await user.click(screen.getByRole("button", { name: "Pay" }));
|
|
18
|
+
expect(await screen.findByText("Payment confirmed")).toBeVisible();
|
|
19
|
+
});
|
|
20
|
+
```
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- One logical assertion per test
|
|
22
|
+
```sql
|
|
23
|
+
-- Tenant isolation: execute against a real test database with two users.
|
|
24
|
+
-- Regex matching a CREATE POLICY statement does not prove RLS behavior.
|
|
25
|
+
```
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
Characteristics of valuable tests:
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
- Catch a concrete user, business, security, data, or contract regression
|
|
30
|
+
- Observe a public interface or the real boundary at risk
|
|
31
|
+
- Survive an internal refactor
|
|
32
|
+
- Use the narrowest reliable setup
|
|
33
|
+
- Add a second layer only for a different contract
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
// BAD: Tests implementation details
|
|
31
|
-
test("checkout calls paymentService.process", async () => {
|
|
32
|
-
const mockPayment = jest.mock(paymentService);
|
|
33
|
-
await checkout(cart, payment);
|
|
34
|
-
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
|
35
|
-
});
|
|
36
|
-
```
|
|
35
|
+
## Low-value and redundant tests
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
Avoid tests whose only purpose is to assert:
|
|
39
38
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
39
|
+
- Tailwind classes, decorative DOM, or incidental markup
|
|
40
|
+
- That a wrapper, alias, constant, callback, or function exists
|
|
41
|
+
- Exact internal call counts/order when the observable result is what matters
|
|
42
|
+
- The same behavior already protected at a stronger seam
|
|
43
|
+
- SQL policy or migration correctness exclusively through text/regex shape
|
|
44
|
+
- “Integration” while every important collaborator is mocked
|
|
46
45
|
|
|
47
46
|
```typescript
|
|
48
|
-
// BAD:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
|
52
|
-
expect(row).toBeDefined();
|
|
53
|
-
});
|
|
47
|
+
// BAD: locks internal choreography.
|
|
48
|
+
expect(paymentService.charge).toHaveBeenCalledTimes(1);
|
|
49
|
+
expect(emailService.send).toHaveBeenCalledAfter(paymentService.charge);
|
|
54
50
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
const user = await createUser({ name: "Alice" });
|
|
58
|
-
const retrieved = await getUser(user.id);
|
|
59
|
-
expect(retrieved.name).toBe("Alice");
|
|
60
|
-
});
|
|
51
|
+
// BETTER: assert the contract callers rely on.
|
|
52
|
+
expect(result).toMatchObject({ status: "confirmed", receiptId: expect.any(String) });
|
|
61
53
|
```
|
|
54
|
+
|
|
55
|
+
Exact calls are valid only when the call itself is the external contract—for example, the precise payload sent to a payment provider or an idempotency key required by its protocol.
|
|
56
|
+
|
|
57
|
+
## Valid no-new-test decisions
|
|
58
|
+
|
|
59
|
+
A change may need no new test when it is styling-only, mechanical, generated, already covered by an authoritative test, or has no meaningful behavioral branch. State the reason and run the cheapest existing verification that could catch an accidental break.
|
|
@@ -9,7 +9,9 @@ This skill takes the current conversation context and codebase understanding and
|
|
|
9
9
|
|
|
10
10
|
1. Explore the repo to understand the current state of the codebase, if you haven't already. Use the project's domain glossary vocabulary throughout the PRD, and respect any ADRs in the area you're touching.
|
|
11
11
|
|
|
12
|
-
2. Sketch out the seams at which you're going to test the feature.
|
|
12
|
+
2. Sketch out the seams at which you're going to test the feature. Prefer an existing seam when it is strong enough, and choose the closest seam that can fail for the concrete regression risk. Introduce a new seam only when existing ones cannot provide reliable evidence.
|
|
13
|
+
|
|
14
|
+
Do not choose from a fixed test pyramid or a requirement to add tests. Prefer one authoritative test at the strongest seam closest to the risk; another layer is justified only for a distinct contract. Record existing coverage and valid no-new-test decisions for trivial, mechanical, generated, styling, or wiring changes.
|
|
13
15
|
|
|
14
16
|
Check with the user that these seams match their expectations.
|
|
15
17
|
|
|
@@ -67,9 +69,13 @@ Keep this static: describe the planned delivery slices, not the current state.
|
|
|
67
69
|
|
|
68
70
|
A list of testing decisions that were made. Include:
|
|
69
71
|
|
|
70
|
-
-
|
|
71
|
-
- Which
|
|
72
|
-
-
|
|
72
|
+
- The meaningful regression risk introduced by each behavior change
|
|
73
|
+
- Which existing tests already protect it
|
|
74
|
+
- Which new behavior requires protection
|
|
75
|
+
- The chosen seam and why it is closest to the risk
|
|
76
|
+
- Why another layer would protect a distinct contract rather than duplicate the same behavior
|
|
77
|
+
- Why no new test is needed for trivial, mechanical, generated, styling, wiring, or already-covered changes
|
|
78
|
+
- Prior art for the selected tests (i.e. similar valuable tests in the codebase)
|
|
73
79
|
|
|
74
80
|
## Out of Scope
|
|
75
81
|
|