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.
@@ -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: Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.
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
- ## Philosophy
8
+ ## Core principle
9
9
 
10
- **Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
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
- **Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.
12
+ For every change, establish:
13
13
 
14
- **Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.
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
- See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.
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
- ## Anti-Pattern: Horizontal Slices
22
+ See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for boundary-double guidance.
19
23
 
20
- **DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code."
24
+ ## When to use TDD
21
25
 
22
- This produces **crap tests**:
26
+ Use red-green-refactor when the change defines or repairs:
23
27
 
24
- - Tests written in bulk test _imagined_ behavior, not _actual_ behavior
25
- - You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior
26
- - Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine
27
- - You outrun your headlights, committing to test structure before understanding the implementation
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
- **Correct approach**: Vertical slices via tracer bullets. One test one implementation repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.
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
- ### 1. Planning
39
+ Use the cheapest seam that can fail for the real regression:
46
40
 
47
- When exploring the codebase, use the project's domain glossary so that test names and interface vocabulary match the project's language, and respect ADRs in the area you're touching.
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
- Before writing any code:
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
- - [ ] Confirm with user what interface changes are needed
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
- Ask: "What should the public interface look like? Which behaviors are most important to test?"
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
- **You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case.
54
+ Use vertical tracer bullets for each behavior that merits new protection:
61
55
 
62
- ### 2. Tracer Bullet
63
-
64
- Write ONE test that confirms ONE thing about the system:
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
- This is your tracer bullet - proves the path works end-to-end.
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
- ### 3. Incremental Loop
64
+ ## Workflow
74
65
 
75
- For each remaining behavior:
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
- Rules:
70
+ ### 2. RED, when new protection is warranted
83
71
 
84
- - One test at a time
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
- ### 4. Refactor
74
+ ### 3. GREEN
90
75
 
91
- After all tests pass, look for [refactor candidates](refactoring.md):
76
+ Write only enough production code to satisfy the behavior. Do not anticipate speculative cases.
92
77
 
93
- - [ ] Extract duplication
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
- **Never refactor while RED.** Get to GREEN first.
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 Per Cycle
82
+ ## Checklist
102
83
 
103
- ```
104
- [ ] Test describes behavior, not implementation
105
- [ ] Test uses public interface only
106
- [ ] Test would survive internal refactor
107
- [ ] Code is minimal for this test
108
- [ ] No speculative features added
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
- # When to Mock
1
+ # Boundary Doubles and Mocks
2
2
 
3
- Mock at **system boundaries** only:
3
+ Mocks are a cost/risk tradeoff, not a goal or a categorical ban.
4
4
 
5
- - External APIs (payment, email, etc.)
6
- - Databases (sometimes - prefer test DB)
7
- - Time/randomness
8
- - File system (sometimes)
5
+ ## Prefer real behavior when practical
9
6
 
10
- Don't mock:
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
- - Your own classes/modules
13
- - Internal collaborators
14
- - Anything you control
9
+ Prefer real test infrastructure when the risk lives there:
15
10
 
16
- ## Designing for Mockability
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
- At system boundaries, design interfaces that are easy to mock:
16
+ ## Use a boundary double when it is the reliable seam
19
17
 
20
- **1. Use dependency injection**
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
- Pass external dependencies in rather than creating them internally:
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
- ```typescript
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
- // Hard to mock
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
- **2. Prefer SDK-style interfaces over generic fetchers**
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
- Create specific functions for each external operation instead of one generic function with conditional logic:
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
- # Good and Bad Tests
1
+ # Choosing Valuable Tests
2
2
 
3
- ## Good Tests
3
+ ## One behavior, one authoritative seam
4
4
 
5
- **Integration-style**: Test through real interfaces, not mocks of internal parts.
5
+ Choose the seam from the regression you need to catch.
6
6
 
7
7
  ```typescript
8
- // GOOD: Tests observable behavior
9
- test("user can checkout with valid cart", async () => {
10
- const cart = createCart();
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
- Characteristics:
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
- - Tests behavior users/callers care about
20
- - Uses public API only
21
- - Survives internal refactors
22
- - Describes WHAT, not HOW
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
- ## Bad Tests
27
+ Characteristics of valuable tests:
26
28
 
27
- **Implementation-detail tests**: Coupled to internal structure.
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
- ```typescript
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
- Red flags:
37
+ Avoid tests whose only purpose is to assert:
39
38
 
40
- - Mocking internal collaborators
41
- - Testing private methods
42
- - Asserting on call counts/order
43
- - Test breaks when refactoring without behavior change
44
- - Test name describes HOW not WHAT
45
- - Verifying through external means instead of interface
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: Bypasses interface to verify
49
- test("createUser saves to database", async () => {
50
- await createUser({ name: "Alice" });
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
- // GOOD: Verifies through interface
56
- test("createUser makes user retrievable", async () => {
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. Existing seams should be preferred to new ones. Use the highest seam possible. If new seams are needed, propose them at the highest point you can.
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
- - A description of what makes a good test (only test external behavior, not implementation details)
71
- - Which modules will be tested
72
- - Prior art for the tests (i.e. similar types of tests in the codebase)
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