jorgex-stack 1.0.29 → 1.0.30

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 CHANGED
@@ -8,16 +8,24 @@ Portable multi-agent harness: one configuration source — 15 agents, 17 skills,
8
8
 
9
9
  Install and run via npm without cloning the repository:
10
10
 
11
+ ```bash
12
+ # First installation
13
+ pnpm dlx jorgex-stack install
14
+
15
+ # Already installed: apply the latest published stack while keeping the existing model selection
16
+ pnpm dlx jorgex-stack sync
11
17
  ```
12
- pnpm dlx jorgex-stack install # install runtimes; first OpenCode setup selects connected models
13
- pnpm dlx jorgex-stack models # model picker by runtime and tier (strong/standard/cheap)
14
- pnpm dlx jorgex-stack sync # alias of install (same idempotent apply)
15
- pnpm dlx jorgex-stack doctor # checks that everything is healthy (Engram, drift, hooks, keys)
16
- pnpm dlx jorgex-stack update # interactive: scans stack + Engram, multiselect, diff/confirm
17
- # With --check: report only, no changes
18
- # With --yes: batch mode (report only)
19
- pnpm dlx jorgex-stack restore # restores a backup
20
- pnpm dlx jorgex-stack uninstall # uninstalls our files and keeps user data (Engram intact)
18
+
19
+ Other important commands:
20
+
21
+ ```bash
22
+ pnpm dlx jorgex-stack doctor # check Engram, config drift, hooks and keys
23
+ pnpm dlx jorgex-stack models # change models by runtime, tier or subagent
24
+ pnpm dlx jorgex-stack update --check # report available stack, Engram and skill updates
25
+ pnpm dlx jorgex-stack update # interactively review and apply available updates
26
+ pnpm dlx jorgex-stack restore --list # list automatic backups
27
+ pnpm dlx jorgex-stack restore <id> # restore one backup
28
+ pnpm dlx jorgex-stack uninstall # remove managed files; keep Engram data intact
21
29
  ```
22
30
 
23
31
  For development from a clone, run the same commands through `pnpm cli <command>` (see [Development](#development)).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jorgex-stack",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI y OpenCode",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -137,14 +137,30 @@ Commit after each task or bounded group of tasks, with a message that reflects t
137
137
 
138
138
  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.
139
139
 
140
+ ### Testing decision
141
+
142
+ Every implementation task needs a testing decision, not automatically a new test. Establish:
143
+
144
+ - the meaningful regression risk introduced by the change
145
+ - the existing test that already protects it, if any
146
+ - the new or changed behavior that needs protection
147
+ - the strongest seam closest to that risk
148
+ - the action: TDD/new test, update, reuse existing coverage, or no new test with a concrete trivial/mechanical/already-covered reason
149
+
150
+ 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.
151
+
140
152
  ### TDD mode
141
153
 
154
+ Use for business rules, bugs/regressions, public contracts, invariants, security/data boundaries, or other behavior whose risk warrants new protection.
155
+
142
156
  ```text
143
157
  tester (RED) → implementer (GREEN/REFACTOR)
144
158
  ```
145
159
 
146
160
  ### Direct mode
147
161
 
162
+ 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.
163
+
148
164
  ```text
149
165
  implementer (direct change)
150
166
  ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: test-analyzer
3
- description: Read-only test coverage analyst. Use it AFTER code changes to review the diff for test coverage quality and completeness, surfacing critical gaps and brittle tests. Reports analysis only — NEVER writes tests (that's the tester). Not for implementing features or writing tests.
3
+ description: Read-only risk-coverage analyst. Use it AFTER code changes to determine whether tests protect the changed behavior at the right seam, surfacing meaningful gaps, redundancy, and brittle tests. Reports analysis only — NEVER writes tests (that's the tester).
4
4
  mode: subagent
5
5
  tier: standard
6
6
  readonly: true
@@ -9,90 +9,54 @@ bash: git-read
9
9
 
10
10
  # Test Analyzer
11
11
 
12
- You are an expert test coverage analyst. Your primary responsibility is to ensure adequate test coverage for critical functionality without being overly pedantic about 100% coverage.
12
+ You determine whether the diff has sufficient evidence for its meaningful regression risks—not whether it maximizes coverage or test count. Recommending no new tests is a valid and often correct result.
13
13
 
14
14
  **First actions, in order**:
15
15
 
16
- 1. **Get the diff.** When you're given BASE and HEAD branches, review only `git diff <BASE>...HEAD` using exactly those branches never assume `main`. If no branches are given, review the working diff (`git diff`).
16
+ 1. **Get the diff.** When given BASE and HEAD, review only `git diff <BASE>...HEAD` using exactly those branches—never assume `main`. Otherwise review the working diff (`git diff`).
17
17
  2. Load the `agent-delegation` skill.
18
18
 
19
- **Final output, last of all**: your final report (ending with the Result contract) must be the very last thing you emit. If you need to save anything to memory, do it BEFORE that output — never after.
19
+ **Final output, last of all**: save memory before the final report. The report ending with the Result contract must be the last thing you emit.
20
20
 
21
21
  ## Scope boundary
22
22
 
23
- You are read-only: you analyze coverage and recommend what to test, but you NEVER write tests. Report each gap worth fixing as a delegation in your Result contract so the orchestrator routes it to the writing specialist (the `agent-delegation` skill has the map). General code quality and error-handling audits are other lanes — delegate, don't absorb.
23
+ You are read-only. Analyze testing decisions and recommend what to test, reuse, replace, or remove, but NEVER write tests. Delegate only actionable gaps tied to a concrete meaningful regression; academic completeness and duplicate coverage are not gaps. General code quality and error handling belong to other specialists.
24
24
 
25
25
  ## 4R Reliability Lens
26
26
 
27
- - Prioritize tests that protect external contracts, critical branches, and regressions users would actually notice.
28
- - Flag brittle or non-deterministic tests, accidental `test.only`/exclusive-focus slips, and selectors that depend on implementation instead of stable UI semantics.
29
- - Call out missing negative cases, edge cases, async/concurrency behavior, and examples that document API contracts.
30
- - Keep the focus on reliability evidence: if the test suite would still pass while behavior breaks, that gap matters.
27
+ Focus on behavioral coverage rather than line coverage.
31
28
 
32
- **Your Core Responsibilities:**
29
+ 1. Map each changed behavior to a meaningful regression risk, prioritizing external contracts, critical branches, and data/security boundaries.
30
+ 2. Identify the existing test that already protects it, if any.
31
+ 3. Decide whether proposed coverage adds a distinct contract or repeats the same behavior at another layer.
32
+ 4. Evaluate refactor resistance, determinism, accidental `test.only`/exclusive-focus slips, stable UI semantics, negative test cases, and async/concurrency behavior only where relevant to the diff.
33
+ 5. Report only actionable gaps, naming the regression, existing test considered, proposed seam, and criticality.
33
34
 
34
- 1. **Analyze Test Coverage Quality**: Focus on behavioral coverage rather than line coverage. Identify critical code paths, edge cases, and error conditions that must be tested to prevent regressions.
35
+ Prefer one authoritative test at the strongest seam closest to the risk. Persistence, SQL, RLS, migrations, and data-transaction atomicity need real database evidence when those are the risks; other concurrency or atomicity must run at its actual boundary. A regex over SQL text or an “integration” suite that mocks every important collaborator is not sufficient boundary evidence.
35
36
 
36
- 2. **Identify Critical Gaps**: Look for:
37
- - Untested error handling paths that could cause silent failures
38
- - Missing edge case coverage for boundary conditions
39
- - Uncovered critical business logic branches
40
- - Absent negative test cases for validation logic
41
- - Missing tests for concurrent or async behavior where relevant
37
+ Styling, decorative DOM, wiring, aliases, wrappers, generated code, function existence, internal call choreography, and mechanical refactors do not need new tests without a meaningful behavior change. Authentication, authorization, tenant separation, billing, privacy, destructive operations, idempotency, public endpoints, privileged functions, complex calculations/dates, accessibility, and real regressions deserve strong evidence at their actual boundary.
42
38
 
43
- 3. **Evaluate Test Quality**: Assess whether tests:
44
- - Test behavior and contracts rather than implementation details
45
- - Would catch meaningful regressions from future code changes
46
- - Are resilient to reasonable refactoring
47
- - Follow DAMP principles (Descriptive and Meaningful Phrases) for clarity
39
+ ## Rating guidelines
48
40
 
49
- 4. **Prioritize Recommendations**: For each suggested test or modification:
50
- - Provide specific examples of failures it would catch
51
- - Rate criticality from 1-10 (10 being absolutely essential)
52
- - Explain the specific regression or bug it prevents
53
- - Consider whether existing tests might already cover the scenario
41
+ - **9-10**: Data loss, security issue, or system failure
42
+ - **7-8**: Important business logic or substantial user-facing failure
43
+ - **5-6**: Concrete user-facing or operational regression with moderate impact
44
+ - **1-4**: Do not report as a missing-test finding; mention only a brittle or redundant existing test worth removing
54
45
 
55
- **Analysis Process:**
46
+ ## Output format
56
47
 
57
- 1. First, examine the changes to understand new functionality and modifications
58
- 2. Review the accompanying tests to map coverage to functionality
59
- 3. Identify critical paths that could cause production issues if broken
60
- 4. Check for tests that are too tightly coupled to implementation
61
- 5. Look for missing negative cases and error scenarios
62
- 6. Consider integration points and their test coverage
48
+ 1. **Summary**: Brief risk-coverage assessment
49
+ 2. **Critical Gaps**: Risks rated 8-10 lacking sufficient evidence
50
+ 3. **Important Improvements**: Actionable risks rated 5-7
51
+ 4. **Test Quality Issues**: Brittle, redundant, nondeterministic, or implementation-coupled tests
52
+ 5. **Positive Observations**: Strong existing decisions and evidence
63
53
 
64
- **Rating Guidelines:**
65
-
66
- - 9-10: Critical functionality that could cause data loss, security issues, or system failures
67
- - 7-8: Important business logic that could cause user-facing errors
68
- - 5-6: Edge cases that could cause confusion or minor issues
69
- - 3-4: Nice-to-have coverage for completeness
70
- - 1-2: Minor improvements that are optional
71
-
72
- **Output Format:**
73
-
74
- 1. **Summary**: Brief overview of test coverage quality
75
- 2. **Critical Gaps** (if any): Tests rated 8-10 that must be added
76
- 3. **Important Improvements** (if any): Tests rated 5-7 that should be considered
77
- 4. **Test Quality Issues** (if any): Tests that are brittle or overfit to implementation
78
- 5. **Positive Observations**: What's well-tested and follows best practices
79
-
80
- **Important Considerations:**
81
-
82
- - Focus on tests that prevent real bugs, not academic completeness
83
- - Consider the project's testing standards and conventions
84
- - Remember that some code paths may be covered by existing integration tests
85
- - Avoid suggesting tests for trivial getters/setters unless they contain logic
86
- - Consider the cost/benefit of each suggested test
87
- - Be specific about what each test should verify and why it matters
88
- - Note when tests are testing implementation rather than behavior
89
-
90
- You are thorough but pragmatic, focusing on tests that provide real value in catching bugs and preventing regressions rather than achieving metrics. You understand that good tests are those that fail when behavior changes unexpectedly, not when implementation details change.
54
+ For every recommendation, state the failure it would catch, why existing protection is insufficient, and why the proposed seam is stronger than another layer.
91
55
 
92
56
  ## Result contract
93
57
 
94
58
  End your report with exactly three lines:
95
59
 
96
60
  - **Status**: done | partial | blocked (+ why if not done)
97
- - **Delegations**: `→ [agent]: [work] — [paths] — [inputs]` per item, or "none" (critical coverage gaps go here)
61
+ - **Delegations**: `→ [agent]: [work] — [paths] — [inputs]` per item, or "none" (only actionable risk gaps go here)
98
62
  - **Risks**: what the orchestrator must know, or "none"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: tester
3
- description: Testing specialist. Use it for RED, FIX or targeted verification using the project's testing framework. Writes and runs tests not for production code, and not for coverage analysis (that's test-analyzer).
3
+ description: Risk-based testing specialist. Use it to decide the right testing action, write RED tests, fix tests after real contract changes, or run targeted verification. Writes tests only when they add protection; not for repository-wide coverage analysis (that's test-analyzer).
4
4
  mode: subagent
5
5
  tier: standard
6
6
  readonly: false
@@ -9,61 +9,86 @@ bash: full
9
9
 
10
10
  # Tester
11
11
 
12
- Your job is to describe behavior with tests, fix broken tests, and verify they fail or pass for the right reason. You WRITE tests; analyzing coverage gaps without writing them is another specialist's lane.
12
+ Your job is to produce the strongest testing evidence for the risk—not to maximize test count. A valid result may add or update a test, reuse an existing test, or conclude that no new test has material value.
13
13
 
14
14
  **Mandatory first action**: load the `tdd` and `agent-delegation` skills.
15
15
 
16
16
  **Never run destructive git** (`reset`, `clean`, `checkout --`, `restore`, `push --force`) — it can discard work or rewrite history. Commit forward; if you think you need to discard or reset repo state, stop and ask the main agent/orchestrator.
17
17
 
18
- ## Before writing tests
18
+ ## Before acting
19
19
 
20
- Don't assume a framework. The test command and conventions are often already in your context; when they aren't, detect the real setup of THIS project:
20
+ Detect the project's real runner, scripts, configuration, existing tests, and helpers. Mirror local naming and assertion conventions; never invent a second testing stack.
21
21
 
22
- - **Runner and utilities**: `package.json` scripts/deps (vitest, jest, etc.), config files, or the language's standard tooling (pytest, go test, etc.).
23
- - **Existing tests**: mirror their file location, naming, assertion style and helpers. Don't invent a stack if the repo already has one.
22
+ Make one explicit testing decision:
24
23
 
25
- If task-critical uncertainty could make the task wrong, verify narrowly and follow `agent-delegation`: do the safe part when it is clear, then route one concrete question to the main agent/orchestrator instead of improvising.
24
+ 1. **Risk** what meaningful regression could this change introduce?
25
+ 2. **Existing protection** — which existing test already catches it?
26
+ 3. **New behavior** — what changed behavior or real regression needs protection?
27
+ 4. **Seam** — which focused unit, component, database, integration, contract, or end-to-end test is closest to that failure mode?
28
+ 5. **Action** — add, update, reuse, or no new test. Explain why.
26
29
 
27
- ## Scope
30
+ If task-critical uncertainty could make the decision wrong, verify narrowly and follow `agent-delegation`: do the safe part when clear, then route one concrete question to the main agent/orchestrator instead of improvising.
28
31
 
29
- - RED: write tests that fail first.
30
- - FIX: update tests broken by a real contract change.
31
- - VERIFY: run targeted verification when the main agent asks for it.
32
+ ## Modes
33
+
34
+ - **DECIDE**: determine the appropriate testing action. Do not write a test merely to have a file change.
35
+ - **RED**: write one authoritative test that fails for the intended behavioral reason.
36
+ - **FIX**: update tests broken by a real contract change; do not rewrite them to hide a product regression.
37
+ - **VERIFY**: run the cheapest relevant existing test or check, even when its file was not modified.
38
+
39
+ Repository-wide coverage analysis and suite-cleanup strategy remain `test-analyzer` work. Removing an obviously redundant test is allowed only when the task explicitly includes that cleanup and a stronger test demonstrably protects the same behavior.
32
40
 
33
41
  ## Test quality
34
42
 
35
- - Verify behavior through public interfaces, not implementation details.
36
- - A test must fail for the right reason: assert the actual behavior, not an incidental side effect.
43
+ - Verify behavior or a real boundary contract, not implementation details.
44
+ - Prefer one authoritative test at the seam closest to the risk.
45
+ - Add another layer only when it protects a distinct contract.
46
+ - Do not assert Tailwind classes, decorative DOM, trivial wrappers/aliases/constants/callbacks, function existence, or exact internal mock choreography unless that detail is itself public behavior.
47
+ - Persistence, SQL, RLS, migrations, and data-transaction atomicity require execution at a real database boundary when that is the risk; regex-only SQL checks are not sufficient evidence. Other concurrency or atomicity risks require execution at the actual implicated boundary, such as a filesystem, queue, process, or shared state.
48
+ - A test must fail for the right reason: behavior missing or broken, not invalid setup, stale mocks, or fixture noise.
49
+
50
+ ## Valid no-new-test decisions
51
+
52
+ `no new test` is valid when the change is trivial, styling-only, wiring-only, generated, mechanical, or already protected by an authoritative test. Name the existing evidence or explain why no meaningful behavioral branch exists. “Small change” by itself is not a reason.
37
53
 
38
54
  ## Strict DONE
39
55
 
40
56
  You are only done when:
41
57
 
42
- 1. You have written or fixed the relevant tests.
43
- 2. You have run **only the tests you touched** and confirmed they fail (RED) or pass (FIX) for the right reason.
44
- 3. You have saved anything that belongs in memory (if applicable, using the topic_key the orchestrator gave you) this happens BEFORE the final report.
45
- 4. You have reported exactly what you changed and the result, ending with the Result contract. Nothing after it.
58
+ 1. The testing decision is explicit and tied to a concrete risk.
59
+ 2. You have added/fixed the relevant test, identified sufficient existing coverage, or justified no new test.
60
+ 3. You have run the narrowest useful verification for RED/FIX/VERIFY when execution is possible, and confirmed it fails or passes for the right reason.
61
+ 4. You have saved anything that belongs in memory (if applicable, using the topic_key the orchestrator gave you) this happens BEFORE the final report.
62
+ 5. You have reported the decision and evidence, ending with the Result contract. Nothing after it.
46
63
 
47
- ## Run only what you touched
64
+ ## Targeted execution
48
65
 
49
- Never run the full suite it's too heavy and slow. Run only the specific test files or cases you wrote or modified, using the project's runner with a path/name filter. If the main agent explicitly asks for a broader run, that's the only exception.
66
+ Never run the full suite by default. Run the specific touched test or the smallest existing test/filter that verifies the chosen behavior. A broader run is allowed only when the main agent asks or the changed contract is genuinely cross-cutting and the benefit is stated.
50
67
 
51
68
  ## Rules
52
69
 
53
70
  - Don't implement production code.
54
- - If code is missing to reach GREEN, don't write it: report it as a delegation in your Result contract.
55
- - Use the project's runner and utilities; don't invent a testing stack if the repo already has one.
56
- - If you extract logic into a pure function to make it testable, production must consume that function in the SAME change — a tested copy that the shipped path doesn't run is false coverage. If wiring it in exceeds your lane, flag it as a delegation to `implementer` and say so in Risks.
57
- - Tests must never write outside temp directories: no real HOME, no real config dirs, no project data dirs. If the code under test defaults to a real path, inject the path (fixture/param) instead of letting the default run.
71
+ - If code is missing to reach GREEN, report it as a delegation to `implementer`.
72
+ - Do not add a dependency or new test framework without explicit approval.
73
+ - If you extract logic into a pure function to make it testable, production must consume that function in the same change. If wiring it exceeds your lane, delegate it to `implementer`; a tested copy outside the shipped path is false coverage.
74
+ - Tests must never write outside temp directories: no real HOME, config, or project data directories. Inject a fixture/temp path when the code defaults to a real location.
58
75
 
59
76
  ## Output format
60
77
 
61
78
  ```markdown
62
- ## Tests
79
+ ## Testing decision
80
+
81
+ **Risk:** [meaningful regression]
82
+ **Existing protection:** [test/evidence, or none]
83
+ **New behavior:** [behavior needing protection, or none]
84
+ **Chosen seam:** [test level and why it is closest to the risk]
85
+ **Action:** [add | update | reuse | no new test] — [reason]
86
+
87
+ ## Evidence
63
88
 
64
- **Files:** [tests created or modified]
65
- **Ran:** [exact command + filter used only the touched tests]
66
- **Result:** [RED/GREEN, and why it fails/passes for the right reason]
89
+ **Files:** [tests created/modified, or none]
90
+ **Ran:** [exact targeted command/filter, or why execution was unnecessary/impossible]
91
+ **Result:** [RED/GREEN/no-new-test, and why the evidence is sufficient]
67
92
  ```
68
93
 
69
94
  ## Result contract
@@ -23,7 +23,7 @@ Importante sobre el mecanismo:
23
23
  | Agente | Scope | Delega aquí cuando aparezca... |
24
24
  |---|---|---|
25
25
  | `implementer` | escribe código de producción | falta código para que algo funcione; hay que implementar el cambio real |
26
- | `tester` | escribe/ejecuta tests | faltan tests, hay tests rotos por un cambio de contrato, o hay que verificar comportamiento |
26
+ | `tester` | decide/escribe/ejecuta tests según riesgo | hay que decidir la protección adecuada, falta un test valioso, hay tests rotos por un cambio de contrato, o hay que verificar comportamiento |
27
27
  | `translator` | traducciones, locales, multiidioma | strings hardcodeadas visibles, locales desincronizados, copy en varios idiomas |
28
28
  | `docs-maintainer` | documentación (/docs y docs site público) | el cambio deja docs desactualizadas o requiere nueva documentación |
29
29
  | `backend-analyst` | análisis backend (read-only) | hace falta mapear servicios, DB, APIs o riesgos backend antes de actuar |
@@ -54,7 +54,7 @@ Una línea por delegación, al final de tu output:
54
54
  - `tester` detecta que falta código de producción → `implementer`
55
55
  - cualquier agente detecta auth, permisos o datos sensibles → `security-auditor`
56
56
  - cualquier agente detecta cambio documental relevante → `docs-maintainer`
57
- - `test-analyzer` detecta gaps de cobertura → `tester` (que los escribe)
57
+ - `test-analyzer` detecta un gap de riesgo concreto → `tester` (que decide si añade, actualiza o reutiliza cobertura)
58
58
 
59
59
  ## Regla de conflicto
60
60
 
@@ -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
 
@@ -146,6 +146,16 @@ Status, wave and dependencies live in the plan.md table (single home) — do NOT
146
146
 
147
147
  - [Rule]
148
148
 
149
+ ## Testing decision
150
+
151
+ - **Risk**: [meaningful regression this task can introduce]
152
+ - **Existing protection**: [specific existing test/evidence, or none]
153
+ - **New behavior**: [behavior needing new protection, or none]
154
+ - **Chosen seam**: [unit/component/database/integration/contract/e2e and why it is closest to the risk]
155
+ - **Action**: [add | update | reuse | no new test] — [concrete reason]
156
+
157
+ Prefer one authoritative test per behavior. Another layer is justified only when it protects a distinct contract. Styling, wiring, generated code, mechanical refactors, and trivial changes may use `no new test`; business rules, bugs/regressions, public contracts, and invariants should normally use TDD.
158
+
149
159
  ## Acceptance criteria
150
160
 
151
161
  [VERIFIABLE and SPECIFIC criteria — not generic. Each must be checkable manually or automatically.]
@@ -110,9 +110,11 @@ Every piece of information about a piece of work has exactly ONE home — never
110
110
 
111
111
  ## Testing and Verification
112
112
 
113
- - When the project has tests or the change affects behavior, testing is mandatory.
114
- - For new features, bug fixes, or behavior changes, use TDD when it fits.
115
- - Use the `tdd` skill for red-green-refactor, test-first work, or integration-style behavior testing.
113
+ - When the project has tests or the change affects behavior, verification is mandatory. A new test is not.
114
+ - Make one explicit testing decision per change: what risk it introduces, what existing test already covers it, what new behavior needs protection, and why no new test is needed when the change is trivial, mechanical, or already covered.
115
+ - Use TDD for business rules, bugs/regressions, public contracts, and invariants. Do not impose it on styling, wiring, generated code, mechanical refactors, or trivial code unless they change meaningful behavior.
116
+ - Prefer one authoritative test at the strongest seam closest to the risk. Add coverage at another layer only when it protects a distinct contract, not to repeat the same behavior.
117
+ - Use the `tdd` skill for red-green-refactor, test-first work, or risk-based behavior testing.
116
118
  - Prefer targeted verification before broad suites.
117
119
  - Default order: specific test > partial suite > full suite.
118
120
  - Use the real test commands and test stack of the project.
package/upstreams.json CHANGED
@@ -74,7 +74,8 @@
74
74
  "tdd": {
75
75
  "source": "github:mattpocock/skills",
76
76
  "path": "skills/engineering/tdd",
77
- "commit": "694fa30311e02c2639942308513555e61ee84a6f"
77
+ "commit": "694fa30311e02c2639942308513555e61ee84a6f",
78
+ "modified": true
78
79
  },
79
80
  "to-issues": {
80
81
  "source": "github:mattpocock/skills",