@complexthings/superpowers-agent 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.agents/docs/SUPERPOWERS.md +108 -0
  2. package/.agents/prompts/001-copilot-tool-mapping-do/001-copilot-tool-mapping-do.md +116 -0
  3. package/.agents/prompts/001-copilot-tool-mapping-do/SUMMARY.md +72 -0
  4. package/.agents/prompts/001-copilot-tool-mapping-do/copilot-tool-mapping-do-output.md +83 -0
  5. package/.agents/prompts/001-release-management-do/001-release-management-do.md +161 -0
  6. package/.agents/prompts/001-release-management-do/SUMMARY.md +19 -0
  7. package/.agents/prompts/001-release-management-do/completed/001-release-management-do.md +161 -0
  8. package/.agents/prompts/002-pull-command-do/SUMMARY.md +28 -0
  9. package/.agents/prompts/002-pull-command-do/completed/002-pull-command-do.md +122 -0
  10. package/.agents/prompts/002-pull-command-do/pull-command-do-output.md +174 -0
  11. package/.agents/prompts/command_updates_prompt.md +69 -0
  12. package/.agents/prompts/current_prompt.md +8 -0
  13. package/.agents/prompts/refactor.prompt.md +57 -0
  14. package/.agents/skills/.gitkeep +0 -0
  15. package/.agents/superpowers-agent +355 -0
  16. package/.agents/superpowers-bootstrap.md +42 -0
  17. package/.agents/templates/AGENTS.md.template +40 -0
  18. package/.agents/templates/SUPERPOWERS.md.template +108 -0
  19. package/.agents/templates/TOOLS.md.template +15 -0
  20. package/.github/workflows/main.yaml +32 -0
  21. package/AGENTS.md +60 -0
  22. package/LICENSE +21 -0
  23. package/README.md +724 -0
  24. package/hooks/hooks.json +15 -0
  25. package/hooks/session-start.sh +27 -0
  26. package/package.json +51 -0
  27. package/skills/architecture/ABOUT.md +20 -0
  28. package/skills/architecture/preserving-productive-tensions/SKILL.md +146 -0
  29. package/skills/architecture/preserving-productive-tensions/skill.json +9 -0
  30. package/skills/collaboration/brainstorming/SKILL.md +166 -0
  31. package/skills/collaboration/brainstorming/skill.json +9 -0
  32. package/skills/collaboration/brainstorming/spec-document-reviewer-prompt.md +50 -0
  33. package/skills/collaboration/brainstorming/visual-companion.md +277 -0
  34. package/skills/collaboration/dispatching-parallel-agents/SKILL.md +174 -0
  35. package/skills/collaboration/dispatching-parallel-agents/skill.json +9 -0
  36. package/skills/collaboration/executing-plans/SKILL.md +130 -0
  37. package/skills/collaboration/executing-plans/skill.json +9 -0
  38. package/skills/collaboration/finishing-a-development-branch/SKILL.md +261 -0
  39. package/skills/collaboration/finishing-a-development-branch/skill.json +9 -0
  40. package/skills/collaboration/leveraging-cli-tools/SKILL.md +132 -0
  41. package/skills/collaboration/leveraging-cli-tools/skill.json +9 -0
  42. package/skills/collaboration/receiving-code-review/SKILL.md +233 -0
  43. package/skills/collaboration/receiving-code-review/skill.json +9 -0
  44. package/skills/collaboration/requesting-code-review/SKILL.md +110 -0
  45. package/skills/collaboration/requesting-code-review/code-reviewer.md +146 -0
  46. package/skills/collaboration/requesting-code-review/skill.json +12 -0
  47. package/skills/collaboration/subagent-driven-development/SKILL.md +255 -0
  48. package/skills/collaboration/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
  49. package/skills/collaboration/subagent-driven-development/implementer-prompt.md +113 -0
  50. package/skills/collaboration/subagent-driven-development/skill.json +15 -0
  51. package/skills/collaboration/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  52. package/skills/collaboration/using-git-worktrees/SKILL.md +366 -0
  53. package/skills/collaboration/using-git-worktrees/skill.json +9 -0
  54. package/skills/collaboration/writing-plans/SKILL.md +121 -0
  55. package/skills/collaboration/writing-plans/plan-document-reviewer-prompt.md +52 -0
  56. package/skills/collaboration/writing-plans/skill.json +9 -0
  57. package/skills/debugging/defense-in-depth/SKILL.md +380 -0
  58. package/skills/debugging/defense-in-depth/skill.json +9 -0
  59. package/skills/debugging/root-cause-tracing/SKILL.md +361 -0
  60. package/skills/debugging/root-cause-tracing/find-polluter.sh +63 -0
  61. package/skills/debugging/root-cause-tracing/skill.json +12 -0
  62. package/skills/debugging/systematic-debugging/SKILL.md +299 -0
  63. package/skills/debugging/systematic-debugging/condition-based-waiting-example.ts +158 -0
  64. package/skills/debugging/systematic-debugging/condition-based-waiting.md +115 -0
  65. package/skills/debugging/systematic-debugging/defense-in-depth.md +122 -0
  66. package/skills/debugging/systematic-debugging/find-polluter.sh +63 -0
  67. package/skills/debugging/systematic-debugging/root-cause-tracing.md +169 -0
  68. package/skills/debugging/systematic-debugging/skill.json +9 -0
  69. package/skills/debugging/systematic-debugging/test-academic.md +14 -0
  70. package/skills/debugging/systematic-debugging/test-pressure-1.md +58 -0
  71. package/skills/debugging/systematic-debugging/test-pressure-2.md +68 -0
  72. package/skills/debugging/systematic-debugging/test-pressure-3.md +69 -0
  73. package/skills/debugging/verification-before-completion/SKILL.md +143 -0
  74. package/skills/debugging/verification-before-completion/skill.json +9 -0
  75. package/skills/finding-skills/SKILL.md +101 -0
  76. package/skills/finding-skills/skill.json +8 -0
  77. package/skills/meta/create-skill-json/SKILL.md +370 -0
  78. package/skills/meta/create-skill-json/skill.json +9 -0
  79. package/skills/meta/create-skill-json/test-scenarios.md +29 -0
  80. package/skills/meta/creating-prompts/SKILL.md +349 -0
  81. package/skills/meta/creating-prompts/examples/do-example.md +65 -0
  82. package/skills/meta/creating-prompts/examples/plan-example.md +75 -0
  83. package/skills/meta/creating-prompts/examples/refine-example.md +65 -0
  84. package/skills/meta/creating-prompts/examples/research-example.md +63 -0
  85. package/skills/meta/creating-prompts/scripts/get-next-number.sh +27 -0
  86. package/skills/meta/creating-prompts/skill.json +20 -0
  87. package/skills/meta/creating-prompts/templates/do-template.md +59 -0
  88. package/skills/meta/creating-prompts/templates/plan-template.md +58 -0
  89. package/skills/meta/creating-prompts/templates/refine-template.md +54 -0
  90. package/skills/meta/creating-prompts/templates/research-template.md +56 -0
  91. package/skills/meta/using-superpowers/SKILL.md +122 -0
  92. package/skills/meta/using-superpowers/skill.json +5 -0
  93. package/skills/meta/writing-prompts/SKILL.md +345 -0
  94. package/skills/meta/writing-prompts/skill.json +9 -0
  95. package/skills/problem-solving/ABOUT.md +40 -0
  96. package/skills/problem-solving/collision-zone-thinking/SKILL.md +188 -0
  97. package/skills/problem-solving/collision-zone-thinking/references/historical-examples.md +393 -0
  98. package/skills/problem-solving/collision-zone-thinking/skill.json +9 -0
  99. package/skills/problem-solving/inversion-exercise/SKILL.md +174 -0
  100. package/skills/problem-solving/inversion-exercise/skill.json +9 -0
  101. package/skills/problem-solving/meta-pattern-recognition/SKILL.md +116 -0
  102. package/skills/problem-solving/meta-pattern-recognition/skill.json +9 -0
  103. package/skills/problem-solving/scale-game/SKILL.md +222 -0
  104. package/skills/problem-solving/scale-game/skill.json +9 -0
  105. package/skills/problem-solving/simplification-cascades/SKILL.md +113 -0
  106. package/skills/problem-solving/simplification-cascades/skill.json +9 -0
  107. package/skills/problem-solving/when-stuck/SKILL.md +69 -0
  108. package/skills/problem-solving/when-stuck/skill.json +9 -0
  109. package/skills/research/ABOUT.md +20 -0
  110. package/skills/research/tracing-knowledge-lineages/SKILL.md +241 -0
  111. package/skills/research/tracing-knowledge-lineages/skill.json +9 -0
  112. package/skills/setup-skills/SKILL.md +47 -0
  113. package/skills/testing/condition-based-waiting/SKILL.md +359 -0
  114. package/skills/testing/condition-based-waiting/example.ts +158 -0
  115. package/skills/testing/condition-based-waiting/skill.json +12 -0
  116. package/skills/testing/test-driven-development/SKILL.md +434 -0
  117. package/skills/testing/test-driven-development/skill.json +9 -0
  118. package/skills/testing/testing-anti-patterns/SKILL.md +298 -0
  119. package/skills/testing/testing-anti-patterns/skill.json +9 -0
  120. package/skills/testing/verification-before-completion/SKILL.md +246 -0
  121. package/skills/testing/verification-before-completion/skill.json +10 -0
  122. package/skills/using-a-skill/SKILL.md +101 -0
  123. package/skills/using-a-skill/skill.json +8 -0
@@ -0,0 +1,361 @@
1
+ ---
2
+ name: root-cause-tracing
3
+ description: Systematically trace bugs backward through the call chain to find the original trigger — not just where the error appears. Use this skill when an error surfaces deep in execution, a symptom keeps recurring after fixes, invalid data arrives at a function from an unknown source, or a test fails but the failure point isn't the true cause. Covers synchronous and async traces, cross-process tracing, bisecting regressions, and identifying far-from-origin bug patterns.
4
+ ---
5
+
6
+ # Root Cause Tracing
7
+
8
+ ## Core Principle
9
+
10
+ Bugs manifest where they surface, not where they're born. Fixing the symptom is fast but fragile — the same root cause will produce a different symptom tomorrow.
11
+
12
+ **Trace backward through the call chain until you find the original trigger, then fix at the source.**
13
+
14
+ ## The Tracing Process
15
+
16
+ ### Step 1 — Observe the Symptom
17
+
18
+ Write down exactly what failed and where:
19
+
20
+ ```
21
+ Error: ENOENT: no such file or directory, open '/tmp/undefined/output.json'
22
+ at Object.openSync (node:fs:600:3)
23
+ at writeFileSync (src/reporter.ts:42)
24
+ ```
25
+
26
+ ### Step 2 — Find the Immediate Cause
27
+
28
+ What code directly triggers this? Don't fix it yet — just identify it.
29
+
30
+ ```typescript
31
+ // reporter.ts:42 — writes to outputDir which is somehow 'undefined'
32
+ fs.writeFileSync(path.join(outputDir, 'output.json'), content);
33
+ ```
34
+
35
+ ### Step 3 — Ask "What Called This?" (trace up one level)
36
+
37
+ Follow the call chain backward. Use your IDE's "Find Usages", grep, or add a stack trace:
38
+
39
+ ```typescript
40
+ // Temporary instrumentation — add before the problem line
41
+ console.error('DEBUG reporter:', { outputDir, stack: new Error().stack });
42
+ ```
43
+
44
+ ```
45
+ → reporter.writeOutput(outputDir)
46
+ → Runner.finish(outputDir)
47
+ → CLI.run(config.outputDir)
48
+ → config loaded from parseArgs()
49
+ ```
50
+
51
+ ### Step 4 — Keep Tracing Until You Find the Source
52
+
53
+ At each level, ask: **"Could this function be correct if all its inputs were valid?"**
54
+
55
+ If yes, the bug is upstream — keep tracing. If no, you've found a broken invariant.
56
+
57
+ ```typescript
58
+ // CLI.run receives config.outputDir — where does that come from?
59
+ const config = parseArgs(process.argv);
60
+ // parseArgs returns outputDir as undefined when --output flag is missing —
61
+ // no default value is set, so any downstream use of outputDir becomes 'undefined'
62
+ ```
63
+
64
+ ### Step 5 — Confirm You've Found the Root
65
+
66
+ A true root cause meets all of these:
67
+ - [ ] Removing or fixing this code eliminates **all** instances of the symptom
68
+ - [ ] The code is doing "wrong thing" — not just receiving wrong input
69
+ - [ ] A unit test of just this component would expose the bug
70
+ - [ ] There's no caller upstream that's causing this code to behave badly
71
+
72
+ **Root cause found:** `parseArgs()` returns `undefined` for missing optional flags with no defaults.
73
+
74
+ **Fix at the source:** Set a default in `parseArgs()`, not a guard in `reporter.ts`.
75
+
76
+ ## When You Can't Trace Manually — Add Instrumentation
77
+
78
+ When the call chain isn't obvious from reading code, add temporary debug logging:
79
+
80
+ ```typescript
81
+ // TypeScript/JavaScript — capture full call chain
82
+ async function riskyOperation(directory: string) {
83
+ console.error('DEBUG riskyOperation:', {
84
+ directory,
85
+ cwd: process.cwd(),
86
+ stack: new Error().stack, // shows who called this
87
+ });
88
+ // ... rest of function
89
+ }
90
+ ```
91
+
92
+ ```python
93
+ # Python — capture locals at each stack frame
94
+ import traceback
95
+
96
+ try:
97
+ result = process_data(user_input)
98
+ except Exception as e:
99
+ tb = traceback.TracebackException.from_exception(e, capture_locals=True)
100
+ print(''.join(tb.format()))
101
+ # Shows local variable values at each frame in the traceback
102
+ ```
103
+
104
+ **Key instrumentation rules:**
105
+ - Log **before** the dangerous operation, not after it fails (you won't get there)
106
+ - In tests, use `console.error()` or `stderr` — test runners often suppress `stdout`
107
+ - Include: the value being used, `process.cwd()` or equivalent, and the full stack
108
+ - Remove all instrumentation once the root cause is found
109
+
110
+ ## Tracing Async Bugs
111
+
112
+ Async bugs are harder because the call stack at throw-time shows the event loop, not who scheduled the work.
113
+
114
+ ### Node.js
115
+
116
+ Node 12+ has async stack traces enabled by default. If stacks are truncated:
117
+
118
+ ```bash
119
+ node --stack-trace-limit=50 your-script.js
120
+ ```
121
+
122
+ Capture context *before* the await — this is when you have the scheduling context:
123
+
124
+ ```typescript
125
+ async function fetchUser(id: string) {
126
+ console.error('DEBUG fetchUser scheduled by:', {
127
+ id,
128
+ stack: new Error().stack, // who called fetchUser — this is your trace
129
+ });
130
+ return await db.query('SELECT * FROM users WHERE id = ?', [id]);
131
+ }
132
+ ```
133
+
134
+ Watch for **fire-and-forget** as a common root cause — errors disappear silently:
135
+
136
+ ```typescript
137
+ // BUG: errors from processItem() are swallowed
138
+ items.forEach(item => {
139
+ processItem(item); // not awaited!
140
+ });
141
+
142
+ // FIX: await all promises, surface errors
143
+ await Promise.all(items.map(item => processItem(item)));
144
+ ```
145
+
146
+ ### Python asyncio
147
+
148
+ ```bash
149
+ PYTHONASYNCIODEBUG=1 python your_script.py
150
+ ```
151
+
152
+ Debug mode catches: never-awaited coroutines (with traceback of where they were created), silently-failed tasks, and event loop blocking callbacks.
153
+
154
+ ```python
155
+ import asyncio
156
+ asyncio.run(main(), debug=True) # equivalent in code
157
+ ```
158
+
159
+ ## Tracing Across Process Boundaries
160
+
161
+ When a bug originates in Service A but manifests in Service B, you need trace IDs to correlate logs across services.
162
+
163
+ **Lightweight approach for debugging sessions:**
164
+
165
+ ```typescript
166
+ // Service A — inject a trace ID on outbound calls
167
+ const traceId = crypto.randomUUID();
168
+ console.error('DEBUG outbound:', { traceId, payload, stack: new Error().stack });
169
+
170
+ const response = await fetch('https://service-b/api', {
171
+ method: 'POST',
172
+ headers: { 'X-Trace-Id': traceId },
173
+ body: JSON.stringify(payload),
174
+ });
175
+ ```
176
+
177
+ ```typescript
178
+ // Service B — extract and log the trace ID
179
+ app.use((req, res, next) => {
180
+ const traceId = req.headers['x-trace-id'] ?? crypto.randomUUID();
181
+ console.error('DEBUG inbound:', { traceId, path: req.path });
182
+ req.traceId = traceId;
183
+ next();
184
+ });
185
+ ```
186
+
187
+ Now you can grep both services' logs for the same `traceId` to reconstruct the full chain.
188
+
189
+ For production distributed tracing, use OpenTelemetry — it propagates trace context automatically via the `traceparent` header and lets you reconstruct full call trees across services.
190
+
191
+ ## Finding Which Commit Introduced a Bug
192
+
193
+ When you know something broke between two commits but not which one, use `git bisect`:
194
+
195
+ ```bash
196
+ git bisect start
197
+ git bisect bad # current state is broken
198
+ git bisect good v2.3.0 # last known good state
199
+
200
+ # Git checks out the midpoint. Run your test, then:
201
+ git bisect good # or: git bisect bad
202
+ # Repeat until Git identifies the culprit commit (log2(N) steps)
203
+ git bisect reset # restore HEAD when done
204
+ ```
205
+
206
+ **Fully automated bisect** — pass any script that exits 0 for good, non-zero for bad:
207
+
208
+ ```bash
209
+ git bisect start
210
+ git bisect bad HEAD
211
+ git bisect good v2.3.0
212
+ # For Jest: use --testNamePattern; for Pytest: use -k; adapt to your test runner
213
+ git bisect run npm test -- --testNamePattern="the failing test"
214
+ git bisect reset
215
+ ```
216
+
217
+ Skip untestable commits (e.g., broken build mid-refactor):
218
+
219
+ ```bash
220
+ git bisect skip
221
+ ```
222
+
223
+ ## Finding Which Test Pollutes State
224
+
225
+ When tests pass in isolation but fail in suite, shared mutable state is the cause. To find which test contaminates the environment, run them one-by-one and stop at the first failure:
226
+
227
+ ```bash
228
+ # Run each test file in isolation until one fails (adapt glob for your project)
229
+ for f in $(npx jest --listTests); do
230
+ npx jest "$f" --silent && continue
231
+ echo "POLLUTER: $f"
232
+ break
233
+ done
234
+ ```
235
+
236
+ Or use binary search — halve the test list and narrow down:
237
+
238
+ ```bash
239
+ # Get all test files, run the first half, then the second half
240
+ ALL=$(npx jest --listTests)
241
+ HALF=$(echo "$ALL" | head -n $(( $(echo "$ALL" | wc -l) / 2 )))
242
+ echo "$HALF" | xargs npx jest
243
+ ```
244
+
245
+ ## Common Far-From-Origin Patterns
246
+
247
+ These patterns cause bugs to manifest far from where they were introduced:
248
+
249
+ ### Initialization Order / Top-Level Access
250
+
251
+ ```typescript
252
+ // BUG: context.tempDir is '' at module load time, populated only in beforeEach
253
+ const context = setupCoreTest();
254
+ const project = Project.create('test', context.tempDir); // '' — runs at define time!
255
+
256
+ // FIX: access inside the test body, after beforeEach has run
257
+ it('creates project', () => {
258
+ const project = Project.create('test', context.tempDir); // populated by now
259
+ });
260
+ ```
261
+
262
+ **Signal:** Value is empty/undefined even though setup exists — check *when* the setup runs vs. when the value is read.
263
+
264
+ ### Closure Over Mutable State
265
+
266
+ ```javascript
267
+ // BUG: all callbacks capture the same `i` (var is function-scoped)
268
+ for (var i = 0; i < 3; i++) {
269
+ setTimeout(() => console.log(i), 100); // prints 3, 3, 3
270
+ }
271
+
272
+ // FIX: use let (block-scoped) so each iteration captures its own i
273
+ for (let i = 0; i < 3; i++) {
274
+ setTimeout(() => console.log(i), 100); // prints 0, 1, 2
275
+ }
276
+ ```
277
+
278
+ **Signal:** Callbacks or async handlers all see the same (final) value — check `var` vs `let`, or whether a reference is being mutated after being captured.
279
+
280
+ ### Exhausted Generator / Iterator
281
+
282
+ ```python
283
+ # BUG: generator is exhausted after first iteration
284
+ items = (x * 2 for x in range(10)) # generator expression
285
+ print(list(items)) # [0, 2, 4, ...] works once
286
+ print(list(items)) # [] — exhausted!
287
+
288
+ # FIX: materialize to a list if you need to iterate more than once
289
+ items = list(x * 2 for x in range(10))
290
+ ```
291
+
292
+ **Signal:** Works the first time, empty/wrong on second use — check generators, iterators, lazy sequences.
293
+
294
+ ### Shared Mutable Default Arguments (Python)
295
+
296
+ ```python
297
+ # BUG: the default list [] is created once and shared across ALL calls
298
+ def append_to(item, lst=[]):
299
+ lst.append(item)
300
+ return lst
301
+
302
+ append_to(1) # [1]
303
+ append_to(2) # [1, 2] — not a fresh list!
304
+
305
+ # FIX: use None as sentinel, create fresh default inside the function
306
+ def append_to(item, lst=None):
307
+ if lst is None:
308
+ lst = []
309
+ lst.append(item)
310
+ return lst
311
+ ```
312
+
313
+ **Signal:** State persists unexpectedly between calls with default arguments — check for mutable defaults.
314
+
315
+ ### Object Reference Mutation
316
+
317
+ ```typescript
318
+ // BUG: config mutated after being shared with multiple consumers
319
+ const config = { timeout: 5000 };
320
+ serviceA.init(config);
321
+ serviceB.init(config);
322
+ config.timeout = 1000; // retroactively affects both services
323
+
324
+ // FIX: freeze or clone at handoff
325
+ serviceA.init(Object.freeze({ ...config }));
326
+ serviceB.init(Object.freeze({ ...config }));
327
+ ```
328
+
329
+ **Signal:** Value changes unexpectedly mid-execution — check whether objects are passed by reference and mutated downstream.
330
+
331
+ ## Symptom vs. Root Cause Quick Reference
332
+
333
+ | What you see | Likely root cause |
334
+ |---|---|
335
+ | `TypeError: Cannot read property 'x' of undefined` | Caller passed `undefined` — trace who called with bad args |
336
+ | Database query returns wrong results | Filter/sort applied in wrong order, or data corrupted at write time |
337
+ | Test passes alone, fails in suite | Shared mutable state — find the polluting test |
338
+ | Intermittent `ECONNRESET` | Connection pool exhausted upstream; someone not releasing connections |
339
+ | UI component renders blank | Data fetcher returned `null` — trace the fetch, not the render |
340
+ | `ENOENT` on path containing `undefined` | String interpolation of an `undefined` variable — trace the variable |
341
+
342
+ ## After Finding the Root Cause
343
+
344
+ Fix at the source, then add defense-in-depth to make the bug impossible at multiple layers:
345
+
346
+ ```typescript
347
+ // Root cause fix: set a safe default at the point of origin
348
+ function parseArgs(argv: string[]): Config {
349
+ const args = minimist(argv.slice(2));
350
+ const outputDir = args['output'] ?? './output'; // default instead of undefined
351
+ return { outputDir };
352
+ }
353
+
354
+ // Defense-in-depth: guard at each consumption layer
355
+ function writeOutput(outputDir: string, content: string) {
356
+ if (!outputDir) throw new Error('writeOutput: outputDir is required');
357
+ fs.writeFileSync(path.join(outputDir, 'output.json'), content);
358
+ }
359
+ ```
360
+
361
+ See the `defense-in-depth` skill for a full layered validation approach.
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env bash
2
+ # Bisection script to find which test creates unwanted files/state
3
+ # Usage: ./find-polluter.sh <file_or_dir_to_check> <test_pattern>
4
+ # Example: ./find-polluter.sh '.git' 'src/**/*.test.ts'
5
+
6
+ set -e
7
+
8
+ if [ $# -ne 2 ]; then
9
+ echo "Usage: $0 <file_to_check> <test_pattern>"
10
+ echo "Example: $0 '.git' 'src/**/*.test.ts'"
11
+ exit 1
12
+ fi
13
+
14
+ POLLUTION_CHECK="$1"
15
+ TEST_PATTERN="$2"
16
+
17
+ echo "🔍 Searching for test that creates: $POLLUTION_CHECK"
18
+ echo "Test pattern: $TEST_PATTERN"
19
+ echo ""
20
+
21
+ # Get list of test files
22
+ TEST_FILES=$(find . -path "$TEST_PATTERN" | sort)
23
+ TOTAL=$(echo "$TEST_FILES" | wc -l | tr -d ' ')
24
+
25
+ echo "Found $TOTAL test files"
26
+ echo ""
27
+
28
+ COUNT=0
29
+ for TEST_FILE in $TEST_FILES; do
30
+ COUNT=$((COUNT + 1))
31
+
32
+ # Skip if pollution already exists
33
+ if [ -e "$POLLUTION_CHECK" ]; then
34
+ echo "⚠️ Pollution already exists before test $COUNT/$TOTAL"
35
+ echo " Skipping: $TEST_FILE"
36
+ continue
37
+ fi
38
+
39
+ echo "[$COUNT/$TOTAL] Testing: $TEST_FILE"
40
+
41
+ # Run the test
42
+ npm test "$TEST_FILE" > /dev/null 2>&1 || true
43
+
44
+ # Check if pollution appeared
45
+ if [ -e "$POLLUTION_CHECK" ]; then
46
+ echo ""
47
+ echo "🎯 FOUND POLLUTER!"
48
+ echo " Test: $TEST_FILE"
49
+ echo " Created: $POLLUTION_CHECK"
50
+ echo ""
51
+ echo "Pollution details:"
52
+ ls -la "$POLLUTION_CHECK"
53
+ echo ""
54
+ echo "To investigate:"
55
+ echo " npm test $TEST_FILE # Run just this test"
56
+ echo " cat $TEST_FILE # Review test code"
57
+ exit 1
58
+ fi
59
+ done
60
+
61
+ echo ""
62
+ echo "✅ No polluter found - all tests clean!"
63
+ exit 0
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": "1.1.0",
3
+ "name": "superpowers:debugging/root-cause-tracing",
4
+ "title": "Root Cause Tracing",
5
+ "helpers": [
6
+ "find-polluter.sh"
7
+ ],
8
+ "aliases": [
9
+ "root-cause-tracing",
10
+ "debugging/root-cause-tracing"
11
+ ]
12
+ }