@qball-inc/the-bulwark 1.0.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 (175) hide show
  1. package/.claude-plugin/plugin.json +43 -0
  2. package/agents/bulwark-fix-validator.md +633 -0
  3. package/agents/bulwark-implementer.md +391 -0
  4. package/agents/bulwark-issue-analyzer.md +308 -0
  5. package/agents/bulwark-standards-reviewer.md +221 -0
  6. package/agents/plan-creation-architect.md +323 -0
  7. package/agents/plan-creation-eng-lead.md +352 -0
  8. package/agents/plan-creation-po.md +300 -0
  9. package/agents/plan-creation-qa-critic.md +334 -0
  10. package/agents/product-ideation-competitive-analyzer.md +298 -0
  11. package/agents/product-ideation-idea-validator.md +268 -0
  12. package/agents/product-ideation-market-researcher.md +292 -0
  13. package/agents/product-ideation-pattern-documenter.md +308 -0
  14. package/agents/product-ideation-segment-analyzer.md +303 -0
  15. package/agents/product-ideation-strategist.md +259 -0
  16. package/agents/statusline-setup.md +97 -0
  17. package/hooks/hooks.json +59 -0
  18. package/package.json +45 -0
  19. package/scripts/hooks/cleanup-stale.sh +13 -0
  20. package/scripts/hooks/enforce-quality.sh +166 -0
  21. package/scripts/hooks/implementer-quality.sh +256 -0
  22. package/scripts/hooks/inject-protocol.sh +52 -0
  23. package/scripts/hooks/suggest-pipeline.sh +175 -0
  24. package/scripts/hooks/track-pipeline-start.sh +37 -0
  25. package/scripts/hooks/track-pipeline-stop.sh +52 -0
  26. package/scripts/init-rules.sh +35 -0
  27. package/scripts/init.sh +151 -0
  28. package/skills/anthropic-validator/SKILL.md +607 -0
  29. package/skills/anthropic-validator/references/agents-checklist.md +131 -0
  30. package/skills/anthropic-validator/references/commands-checklist.md +102 -0
  31. package/skills/anthropic-validator/references/hooks-checklist.md +151 -0
  32. package/skills/anthropic-validator/references/mcp-checklist.md +136 -0
  33. package/skills/anthropic-validator/references/plugins-checklist.md +148 -0
  34. package/skills/anthropic-validator/references/skills-checklist.md +85 -0
  35. package/skills/assertion-patterns/SKILL.md +296 -0
  36. package/skills/bug-magnet-data/SKILL.md +284 -0
  37. package/skills/bug-magnet-data/context/cli-args.md +91 -0
  38. package/skills/bug-magnet-data/context/db-query.md +104 -0
  39. package/skills/bug-magnet-data/context/file-contents.md +103 -0
  40. package/skills/bug-magnet-data/context/http-body.md +91 -0
  41. package/skills/bug-magnet-data/context/process-spawn.md +123 -0
  42. package/skills/bug-magnet-data/data/booleans/boundaries.yaml +143 -0
  43. package/skills/bug-magnet-data/data/collections/arrays.yaml +114 -0
  44. package/skills/bug-magnet-data/data/collections/objects.yaml +123 -0
  45. package/skills/bug-magnet-data/data/concurrency/race-conditions.yaml +118 -0
  46. package/skills/bug-magnet-data/data/concurrency/state-machines.yaml +115 -0
  47. package/skills/bug-magnet-data/data/dates/boundaries.yaml +137 -0
  48. package/skills/bug-magnet-data/data/dates/invalid.yaml +132 -0
  49. package/skills/bug-magnet-data/data/dates/timezone.yaml +118 -0
  50. package/skills/bug-magnet-data/data/encoding/charset.yaml +79 -0
  51. package/skills/bug-magnet-data/data/encoding/normalization.yaml +105 -0
  52. package/skills/bug-magnet-data/data/formats/email.yaml +154 -0
  53. package/skills/bug-magnet-data/data/formats/json.yaml +187 -0
  54. package/skills/bug-magnet-data/data/formats/url.yaml +165 -0
  55. package/skills/bug-magnet-data/data/language-specific/javascript.yaml +182 -0
  56. package/skills/bug-magnet-data/data/language-specific/python.yaml +174 -0
  57. package/skills/bug-magnet-data/data/language-specific/rust.yaml +148 -0
  58. package/skills/bug-magnet-data/data/numbers/boundaries.yaml +161 -0
  59. package/skills/bug-magnet-data/data/numbers/precision.yaml +89 -0
  60. package/skills/bug-magnet-data/data/numbers/special.yaml +69 -0
  61. package/skills/bug-magnet-data/data/strings/boundaries.yaml +109 -0
  62. package/skills/bug-magnet-data/data/strings/injection.yaml +208 -0
  63. package/skills/bug-magnet-data/data/strings/special-chars.yaml +190 -0
  64. package/skills/bug-magnet-data/data/strings/unicode.yaml +139 -0
  65. package/skills/bug-magnet-data/references/external-lists.md +115 -0
  66. package/skills/bulwark-brainstorm/SKILL.md +563 -0
  67. package/skills/bulwark-brainstorm/references/at-teammate-prompts.md +60 -0
  68. package/skills/bulwark-brainstorm/references/role-critical-analyst.md +78 -0
  69. package/skills/bulwark-brainstorm/references/role-development-lead.md +66 -0
  70. package/skills/bulwark-brainstorm/references/role-product-delivery-lead.md +79 -0
  71. package/skills/bulwark-brainstorm/references/role-product-manager.md +62 -0
  72. package/skills/bulwark-brainstorm/references/role-project-sme.md +59 -0
  73. package/skills/bulwark-brainstorm/references/role-technical-architect.md +66 -0
  74. package/skills/bulwark-research/SKILL.md +298 -0
  75. package/skills/bulwark-research/references/viewpoint-contrarian.md +63 -0
  76. package/skills/bulwark-research/references/viewpoint-direct-investigation.md +62 -0
  77. package/skills/bulwark-research/references/viewpoint-first-principles.md +65 -0
  78. package/skills/bulwark-research/references/viewpoint-practitioner.md +62 -0
  79. package/skills/bulwark-research/references/viewpoint-prior-art.md +66 -0
  80. package/skills/bulwark-scaffold/SKILL.md +330 -0
  81. package/skills/bulwark-statusline/SKILL.md +161 -0
  82. package/skills/bulwark-statusline/scripts/statusline.sh +144 -0
  83. package/skills/bulwark-verify/SKILL.md +519 -0
  84. package/skills/code-review/SKILL.md +428 -0
  85. package/skills/code-review/examples/anti-patterns/linting.ts +181 -0
  86. package/skills/code-review/examples/anti-patterns/security.ts +91 -0
  87. package/skills/code-review/examples/anti-patterns/standards.ts +195 -0
  88. package/skills/code-review/examples/anti-patterns/type-safety.ts +108 -0
  89. package/skills/code-review/examples/recommended/linting.ts +195 -0
  90. package/skills/code-review/examples/recommended/security.ts +154 -0
  91. package/skills/code-review/examples/recommended/standards.ts +231 -0
  92. package/skills/code-review/examples/recommended/type-safety.ts +181 -0
  93. package/skills/code-review/frameworks/angular.md +218 -0
  94. package/skills/code-review/frameworks/django.md +235 -0
  95. package/skills/code-review/frameworks/express.md +207 -0
  96. package/skills/code-review/frameworks/flask.md +298 -0
  97. package/skills/code-review/frameworks/generic.md +146 -0
  98. package/skills/code-review/frameworks/react.md +152 -0
  99. package/skills/code-review/frameworks/vue.md +244 -0
  100. package/skills/code-review/references/linting-patterns.md +221 -0
  101. package/skills/code-review/references/security-patterns.md +125 -0
  102. package/skills/code-review/references/standards-patterns.md +246 -0
  103. package/skills/code-review/references/type-safety-patterns.md +130 -0
  104. package/skills/component-patterns/SKILL.md +131 -0
  105. package/skills/component-patterns/references/pattern-cli-command.md +118 -0
  106. package/skills/component-patterns/references/pattern-database.md +166 -0
  107. package/skills/component-patterns/references/pattern-external-api.md +139 -0
  108. package/skills/component-patterns/references/pattern-file-parser.md +168 -0
  109. package/skills/component-patterns/references/pattern-http-server.md +162 -0
  110. package/skills/component-patterns/references/pattern-process-spawner.md +133 -0
  111. package/skills/continuous-feedback/SKILL.md +327 -0
  112. package/skills/continuous-feedback/references/collect-instructions.md +81 -0
  113. package/skills/continuous-feedback/references/specialize-code-review.md +82 -0
  114. package/skills/continuous-feedback/references/specialize-general.md +98 -0
  115. package/skills/continuous-feedback/references/specialize-test-audit.md +81 -0
  116. package/skills/create-skill/SKILL.md +359 -0
  117. package/skills/create-skill/references/agent-conventions.md +194 -0
  118. package/skills/create-skill/references/agent-template.md +195 -0
  119. package/skills/create-skill/references/content-guidance.md +291 -0
  120. package/skills/create-skill/references/decision-framework.md +124 -0
  121. package/skills/create-skill/references/template-pipeline.md +217 -0
  122. package/skills/create-skill/references/template-reference-heavy.md +111 -0
  123. package/skills/create-skill/references/template-research.md +210 -0
  124. package/skills/create-skill/references/template-script-driven.md +172 -0
  125. package/skills/create-skill/references/template-simple.md +80 -0
  126. package/skills/create-subagent/SKILL.md +353 -0
  127. package/skills/create-subagent/references/agent-conventions.md +268 -0
  128. package/skills/create-subagent/references/content-guidance.md +232 -0
  129. package/skills/create-subagent/references/decision-framework.md +134 -0
  130. package/skills/create-subagent/references/template-single-agent.md +192 -0
  131. package/skills/fix-bug/SKILL.md +241 -0
  132. package/skills/governance-protocol/SKILL.md +116 -0
  133. package/skills/init/SKILL.md +341 -0
  134. package/skills/issue-debugging/SKILL.md +385 -0
  135. package/skills/issue-debugging/references/anti-patterns.md +245 -0
  136. package/skills/issue-debugging/references/debug-report-schema.md +227 -0
  137. package/skills/mock-detection/SKILL.md +511 -0
  138. package/skills/mock-detection/references/false-positive-prevention.md +402 -0
  139. package/skills/mock-detection/references/stub-patterns.md +236 -0
  140. package/skills/pipeline-templates/SKILL.md +215 -0
  141. package/skills/pipeline-templates/references/code-change-workflow.md +277 -0
  142. package/skills/pipeline-templates/references/code-review.md +336 -0
  143. package/skills/pipeline-templates/references/fix-validation.md +421 -0
  144. package/skills/pipeline-templates/references/new-feature.md +335 -0
  145. package/skills/pipeline-templates/references/research-brainstorm.md +161 -0
  146. package/skills/pipeline-templates/references/research-planning.md +257 -0
  147. package/skills/pipeline-templates/references/test-audit.md +389 -0
  148. package/skills/pipeline-templates/references/test-execution-fix.md +238 -0
  149. package/skills/plan-creation/SKILL.md +497 -0
  150. package/skills/product-ideation/SKILL.md +372 -0
  151. package/skills/product-ideation/references/analysis-frameworks.md +161 -0
  152. package/skills/session-handoff/SKILL.md +139 -0
  153. package/skills/session-handoff/references/examples.md +223 -0
  154. package/skills/setup-lsp/SKILL.md +312 -0
  155. package/skills/setup-lsp/references/server-registry.md +85 -0
  156. package/skills/setup-lsp/references/troubleshooting.md +135 -0
  157. package/skills/subagent-output-templating/SKILL.md +415 -0
  158. package/skills/subagent-output-templating/references/examples.md +440 -0
  159. package/skills/subagent-prompting/SKILL.md +364 -0
  160. package/skills/subagent-prompting/references/examples.md +342 -0
  161. package/skills/test-audit/SKILL.md +531 -0
  162. package/skills/test-audit/references/known-limitations.md +41 -0
  163. package/skills/test-audit/references/priority-classification.md +30 -0
  164. package/skills/test-audit/references/prompts/deep-mode-detection.md +83 -0
  165. package/skills/test-audit/references/prompts/synthesis.md +57 -0
  166. package/skills/test-audit/references/rewrite-instructions.md +46 -0
  167. package/skills/test-audit/references/schemas/audit-output.yaml +100 -0
  168. package/skills/test-audit/references/schemas/diagnostic-output.yaml +49 -0
  169. package/skills/test-audit/scripts/data-flow-analyzer.ts +509 -0
  170. package/skills/test-audit/scripts/integration-mock-detector.ts +462 -0
  171. package/skills/test-audit/scripts/package.json +20 -0
  172. package/skills/test-audit/scripts/skip-detector.ts +211 -0
  173. package/skills/test-audit/scripts/verification-counter.ts +295 -0
  174. package/skills/test-classification/SKILL.md +310 -0
  175. package/skills/test-fixture-creation/SKILL.md +295 -0
@@ -0,0 +1,402 @@
1
+ # False Positive Prevention Reference
2
+
3
+ Two-tier allowlist and decision tree for mock-detection Stage 2 analysis. Prevents flagging legitimate test patterns as T1-T4 violations.
4
+
5
+ ---
6
+
7
+ ## Tier 1: Universal Safe (Never Flag)
8
+
9
+ These patterns are safe regardless of test type. Do not flag as violations.
10
+
11
+ ### Test Framework Primitives
12
+
13
+ | Pattern | Why Safe |
14
+ |---------|----------|
15
+ | `describe()`, `it()`, `test()` | Test structure, not test doubles |
16
+ | `beforeEach()`, `afterEach()` | Lifecycle hooks |
17
+ | `beforeAll()`, `afterAll()` | Suite-level setup/teardown |
18
+ | `expect()`, `assert()` | Assertion primitives |
19
+ | `jest.setTimeout()`, `vi.setConfig()` | Framework configuration |
20
+ | `jest.useFakeTimers()` | Timer control (not mocking SUT) |
21
+ | `jest.clearAllMocks()` | Cleanup utility |
22
+
23
+ ### Test Data Construction
24
+
25
+ | Pattern | Why Safe |
26
+ |---------|----------|
27
+ | `*Builder` classes | Construct input data, not replacement behavior |
28
+ | `*Factory` functions | `UserFactory.create()`, `OrderFactory.build()` |
29
+ | `create*()` data factories | `createTestUser()`, `createSampleOrder()` |
30
+ | `build*()` data factories | `buildConfig()`, `buildPayload()` |
31
+ | `make*()` data factories | `makeUser()`, `makeRequest()` |
32
+ | `generate*()` data factories | `generateToken()`, `generateId()` |
33
+ | Faker/Chance libraries | `faker.person.fullName()`, `chance.email()` |
34
+ | Literal test data | `const input = { name: 'Alice', age: 30 }` in unit tests |
35
+
36
+ ### Assertion Utilities
37
+
38
+ | Pattern | Why Safe |
39
+ |---------|----------|
40
+ | Custom matchers | `expect.extend({ toBeValidEmail })` |
41
+ | Snapshot utilities | `expect(result).toMatchSnapshot()` |
42
+ | `supertest` / `pactum` | HTTP assertion libraries (test real endpoints) |
43
+ | `testing-library` queries | `screen.getByText()`, `render()` |
44
+
45
+ ### Logging and Instrumentation
46
+
47
+ | Pattern | Why Safe |
48
+ |---------|----------|
49
+ | Test loggers | `const logger = createTestLogger()` — observability, not behavior replacement |
50
+ | Console suppression | `jest.spyOn(console, 'error').mockImplementation(() => {})` — noise reduction |
51
+ | Performance timers | `performance.mark()`, `performance.measure()` |
52
+
53
+ **Exception for console suppression**: If a test asserts on console output (e.g., `expect(console.error).toHaveBeenCalledWith('specific message')`), this becomes a T2 pattern. Flag only if there is no accompanying result assertion.
54
+
55
+ ---
56
+
57
+ ## Tier 2: Context-Dependent (Check Test Type)
58
+
59
+ These patterns require evaluating the test type before deciding.
60
+
61
+ ### HTTP Interception (nock / MSW)
62
+
63
+ ```typescript
64
+ // MSW setup
65
+ const server = setupServer(
66
+ rest.get('https://api.external.com/users', (req, res, ctx) => {
67
+ return res(ctx.json([{ id: 1, name: 'Alice' }]));
68
+ })
69
+ );
70
+ ```
71
+
72
+ | Test Type | Verdict | Rationale |
73
+ |-----------|---------|-----------|
74
+ | Unit test | Safe | Isolating external HTTP is expected |
75
+ | Integration test (external API) | Safe | Mocking third-party APIs you don't control is acceptable |
76
+ | Integration test (own services) | **Flag T3** | Mocking your own service boundaries defeats integration testing |
77
+ | E2E test | **Flag** | E2E should hit real endpoints |
78
+
79
+ **Decision rule**: Check the intercepted URL. If it points to an external third-party service, safe. If it points to the application's own API or internal services, flag.
80
+
81
+ ### InMemory* Fakes
82
+
83
+ ```typescript
84
+ class InMemoryUserRepository implements UserRepository {
85
+ private users = new Map<string, User>();
86
+ async findById(id: string) { return this.users.get(id); }
87
+ async save(user: User) { this.users.set(user.id, user); }
88
+ }
89
+ ```
90
+
91
+ | Test Type | Verdict | Rationale |
92
+ |-----------|---------|-----------|
93
+ | Unit test | Safe | Isolating persistence for unit logic is expected |
94
+ | Integration test (repo layer) | **Flag T3** | If testing repository integration, use real database |
95
+ | Integration test (service layer) | Context-dependent | OK if repo isn't the boundary under test |
96
+
97
+ **Decision rule**: Is the InMemory replacement sitting at the integration boundary the test claims to verify? If yes, flag. If it's a supporting dependency not under test, safe.
98
+
99
+ ### Dependency Injection Test Doubles
100
+
101
+ ```typescript
102
+ // Test provides a mock via DI
103
+ const service = new OrderService(mockPaymentGateway, mockInventory);
104
+ ```
105
+
106
+ | Test Type | Verdict | Rationale |
107
+ |-----------|---------|-----------|
108
+ | Unit test | Safe | DI-based isolation is textbook unit testing |
109
+ | Integration test | **Evaluate** | Which dependencies are mocked? Are they the integration boundaries? |
110
+ | E2E test | **Flag** | DI should use real implementations |
111
+
112
+ **Decision rule**: In integration tests, flag DI mocks only for the specific boundaries the test claims to integrate. Supporting dependencies that aren't part of the integration scope are acceptable.
113
+
114
+ ### Test Containers
115
+
116
+ ```typescript
117
+ const pgContainer = await new PostgreSqlContainer().start();
118
+ const redisContainer = await new GenericContainer('redis:7').start();
119
+ ```
120
+
121
+ | Test Type | Verdict | Rationale |
122
+ |-----------|---------|-----------|
123
+ | All types | **Always safe** | Real infrastructure, not a test double |
124
+
125
+ ### Environment/Config Overrides
126
+
127
+ ```typescript
128
+ process.env.DATABASE_URL = 'postgres://localhost:5432/test';
129
+ process.env.API_KEY = 'test-key-not-real';
130
+ ```
131
+
132
+ | Test Type | Verdict | Rationale |
133
+ |-----------|---------|-----------|
134
+ | All types | Safe | Configuration, not behavior replacement |
135
+
136
+ ---
137
+
138
+ ## Decision Tree
139
+
140
+ Use this tree to evaluate whether a detected pattern is a violation.
141
+
142
+ ```
143
+ Is it a test framework primitive or assertion utility?
144
+ YES -> SAFE (Tier 1)
145
+ NO -> continue
146
+
147
+ Is it test data construction (factory, builder, literal)?
148
+ YES -> SAFE (Tier 1)
149
+ NO -> continue
150
+
151
+ Is it a test container or real infrastructure?
152
+ YES -> SAFE (Tier 1)
153
+ NO -> continue
154
+
155
+ Is it console/logging suppression without assertion on output?
156
+ YES -> SAFE (Tier 1)
157
+ NO -> continue
158
+
159
+ --- Beyond this point: context-dependent (Tier 2) ---
160
+
161
+ Identify the TEST TYPE (unit / integration / E2E):
162
+ - File name contains `.unit.` or is in `__tests__/unit/` -> UNIT
163
+ - File name contains `.integration.` or `.int.` -> INTEGRATION
164
+ - File name contains `.e2e.` or `.spec.` with E2E markers -> E2E
165
+ - Otherwise -> infer from test content (imports, setup patterns)
166
+
167
+ Is it HTTP interception (nock, MSW, fetch mock)?
168
+ UNIT test -> SAFE
169
+ INTEGRATION test -> Is the intercepted URL your own service?
170
+ YES -> FLAG T3 (mocking own integration boundary)
171
+ NO -> SAFE (external API mock is acceptable)
172
+ E2E test -> FLAG
173
+
174
+ Is it an InMemory*/Fake* class?
175
+ UNIT test -> SAFE
176
+ INTEGRATION test -> Does it replace the boundary under test?
177
+ YES -> FLAG T3
178
+ NO -> SAFE (supporting dependency)
179
+ E2E test -> FLAG
180
+
181
+ Is it a DI-injected mock?
182
+ UNIT test -> SAFE
183
+ INTEGRATION test -> Is the mocked dependency an integration boundary?
184
+ YES -> FLAG T3
185
+ NO -> SAFE
186
+ E2E test -> FLAG
187
+
188
+ Is it jest.mock()/vi.mock() on a module?
189
+ Does it mock the module under test?
190
+ YES -> FLAG T1 (mocking SUT)
191
+ NO -> Is this an integration test mocking an integration boundary?
192
+ YES -> FLAG T3
193
+ NO -> SAFE (isolating irrelevant dependency)
194
+
195
+ None of the above matched?
196
+ -> FLAG as confidence: medium, recommend manual review
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Decision Tree (YAML Encoding)
202
+
203
+ For structured consumption by the detection agent:
204
+
205
+ ```yaml
206
+ decision_tree:
207
+ - check: "test_framework_primitive"
208
+ description: "describe/it/test/expect/beforeEach/afterEach/beforeAll/afterAll"
209
+ verdict: safe
210
+ tier: 1
211
+
212
+ - check: "test_data_construction"
213
+ description: "*Builder, *Factory, create*/build*/make*/generate*, faker, literal input data"
214
+ verdict: safe
215
+ tier: 1
216
+
217
+ - check: "test_container_or_real_infra"
218
+ description: "testcontainers, real database connections, real servers"
219
+ verdict: safe
220
+ tier: 1
221
+
222
+ - check: "console_logging_suppression"
223
+ description: "jest.spyOn(console, ...) without assertion on output"
224
+ verdict: safe
225
+ tier: 1
226
+
227
+ - check: "http_interception"
228
+ description: "nock, MSW, jest.mock('node-fetch')"
229
+ conditions:
230
+ - test_type: unit
231
+ verdict: safe
232
+ - test_type: integration
233
+ sub_check: "intercepted URL is own service?"
234
+ if_yes: "flag_T3"
235
+ if_no: "safe"
236
+ - test_type: e2e
237
+ verdict: flag
238
+
239
+ - check: "inmemory_fake_class"
240
+ description: "InMemory*, Fake* implements Interface"
241
+ conditions:
242
+ - test_type: unit
243
+ verdict: safe
244
+ - test_type: integration
245
+ sub_check: "replaces boundary under test?"
246
+ if_yes: "flag_T3"
247
+ if_no: "safe"
248
+ - test_type: e2e
249
+ verdict: flag
250
+
251
+ - check: "di_injected_mock"
252
+ description: "new Service(mockDep, fakeDep)"
253
+ conditions:
254
+ - test_type: unit
255
+ verdict: safe
256
+ - test_type: integration
257
+ sub_check: "mocked dep is integration boundary?"
258
+ if_yes: "flag_T3"
259
+ if_no: "safe"
260
+ - test_type: e2e
261
+ verdict: flag
262
+
263
+ - check: "module_mock"
264
+ description: "jest.mock('./module'), vi.mock('./module')"
265
+ conditions:
266
+ - sub_check: "mocks module under test?"
267
+ if_yes: "flag_T1"
268
+ if_no:
269
+ sub_check: "integration test mocking boundary?"
270
+ if_yes: "flag_T3"
271
+ if_no: "safe"
272
+
273
+ - check: "unmatched_pattern"
274
+ description: "Pattern not covered by above rules"
275
+ verdict: "flag_medium_confidence"
276
+ note: "Recommend manual review"
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Common False Positive Scenarios
282
+
283
+ These patterns have been observed to trigger false positives. The detection agent should recognize and skip them.
284
+
285
+ ### 1. Supertest / Pactum Request Chains
286
+
287
+ ```typescript
288
+ // NOT a violation - supertest creates real HTTP requests to real server
289
+ const response = await request(app)
290
+ .get('/api/users')
291
+ .expect(200)
292
+ .expect('Content-Type', /json/);
293
+ ```
294
+
295
+ **Why flagged incorrectly**: `request(app)` looks like it might be wrapping the app in a test double. It's actually creating a real HTTP connection.
296
+
297
+ ### 2. React Testing Library Render
298
+
299
+ ```typescript
300
+ // NOT a violation - renders real component in real DOM
301
+ const { getByText, getByRole } = render(<LoginForm onSubmit={mockSubmit} />);
302
+ ```
303
+
304
+ **Why flagged incorrectly**: `render()` might look like it creates a fake DOM. It uses jsdom, which is real DOM behavior. The `mockSubmit` callback is an acceptable mock for a unit test.
305
+
306
+ ### 3. Timer Mocking
307
+
308
+ ```typescript
309
+ jest.useFakeTimers();
310
+ // ... test code ...
311
+ jest.advanceTimersByTime(1000);
312
+ ```
313
+
314
+ **Why flagged incorrectly**: "Fake" in the method name. Timer mocking is framework-supported test control, not SUT mocking.
315
+
316
+ ### 4. Module Re-exports in Test Utilities
317
+
318
+ ```typescript
319
+ // test-utils.ts
320
+ export { render, screen } from '@testing-library/react';
321
+ export { userEvent } from '@testing-library/user-event';
322
+ export const testDb = createTestDatabase();
323
+ ```
324
+
325
+ **Why flagged incorrectly**: Test utility file might look like a mock factory. It's re-exporting real libraries.
326
+
327
+ ### 5. Snapshot Testing
328
+
329
+ ```typescript
330
+ expect(component).toMatchInlineSnapshot(`
331
+ <div class="user-card">
332
+ <span>Alice</span>
333
+ </div>
334
+ `);
335
+ ```
336
+
337
+ **Why flagged incorrectly**: Inline snapshots contain hardcoded HTML that might look like manually constructed test data. Snapshots verify real output.
338
+
339
+ ---
340
+
341
+ ## Worked Example: Mixed-Type File
342
+
343
+ A single test file may contain both unit and integration sections. The **same mock pattern** can be safe or a violation depending on which section it appears in.
344
+
345
+ ### Scenario
346
+
347
+ `error-handler.test.ts` contains:
348
+ - **Lines 1-100**: Unit tests for `categorizeError`, `calculateBackoff`, `withRetry`, `ErrorHandlerService`
349
+ - **Lines 105-150**: Integration tests under `describe('Error Handling Integration', ...)`
350
+
351
+ ### The Pattern: `jest.fn().mockResolvedValue()`
352
+
353
+ **In the unit section (SAFE — no violation):**
354
+ ```typescript
355
+ describe('Retry Mechanism', () => {
356
+ it('should succeed on first attempt', async () => {
357
+ const operation = jest.fn().mockResolvedValue('success');
358
+ const result = await withRetry(operation, { maxAttempts: 3 });
359
+ expect(result).toBe('success');
360
+ });
361
+ });
362
+ ```
363
+ - `operation` is an **injected dependency** (callback parameter to `withRetry`)
364
+ - The SUT is `withRetry`, not `operation`
365
+ - Mocking injected deps in unit tests is appropriate
366
+ - **Verdict: SAFE** (Tier 1 Universal Safe — injected dependency in unit test)
367
+
368
+ **In the integration section (T3 VIOLATION):**
369
+ ```typescript
370
+ describe('Error Handling Integration', () => {
371
+ it('should handle transient errors with retry and recovery', async () => {
372
+ const operation = jest.fn()
373
+ .mockRejectedValueOnce(new Error('ECONNRESET'))
374
+ .mockResolvedValue({ data: 'recovered' });
375
+ const result = await service.executeWithRetry(operation, { maxAttempts: 3 });
376
+ expect(result).toEqual({ data: 'recovered' });
377
+ });
378
+ });
379
+ ```
380
+ - `operation` is the **integration boundary** — the external system call
381
+ - Integration tests exist to verify real system interactions
382
+ - Mocking the boundary defeats the purpose of the integration test
383
+ - **Verdict: T3 VIOLATION** (Mock at integration boundary)
384
+
385
+ ### Key Takeaway
386
+
387
+ Never classify an entire file as one test type. Evaluate each describe block independently against the rubric for **its** test type.
388
+
389
+ If AST integration-mock metadata is available (from `just integration-mocks`), it provides ground truth for section boundaries and mock locations within integration/e2e blocks.
390
+
391
+ ---
392
+
393
+ ## Summary for LLM Agent
394
+
395
+ When evaluating a potential violation:
396
+
397
+ 1. **Check Tier 1 first** — if the pattern matches Universal Safe, skip immediately
398
+ 2. **Identify test type** — unit, integration, or E2E (file name, directory, or content)
399
+ 3. **Walk the decision tree** for Tier 2 patterns — context determines the verdict
400
+ 4. **When uncertain**, flag as `confidence: medium` with a note explaining the ambiguity
401
+ 5. **Never flag** test data factories, test containers, or framework primitives
402
+ 6. **Always flag** mocking the system under test (T1) regardless of test type
@@ -0,0 +1,236 @@
1
+ # Stub Patterns Reference
2
+
3
+ Extended test double detection patterns for mock-detection Stage 2 analysis. Covers the Meszaros test double taxonomy beyond basic `jest.mock()` / `vi.mock()` patterns.
4
+
5
+ ---
6
+
7
+ ## Meszaros Test Double Taxonomy
8
+
9
+ | Type | Purpose | Detection Priority |
10
+ |------|---------|-------------------|
11
+ | **Dummy** | Fills parameter lists, never used | Low (rarely harmful) |
12
+ | **Stub** | Returns canned answers | Medium (may hide real behavior) |
13
+ | **Spy** | Records calls for later verification | Medium (T2 risk if no result check) |
14
+ | **Mock** | Pre-programmed expectations | High (T1/T3 risk) |
15
+ | **Fake** | Working implementation with shortcuts | Context-dependent |
16
+
17
+ ---
18
+
19
+ ## Naming Convention Patterns
20
+
21
+ ### Direct Name Matches
22
+
23
+ These naming patterns indicate test doubles. When found in integration tests, evaluate whether they break the integration chain.
24
+
25
+ | Pattern | Regex | Examples |
26
+ |---------|-------|----------|
27
+ | `Mock*` | `/^[Mm]ock[A-Z]/` | `MockDatabase`, `mockUserService`, `MockHttpClient` |
28
+ | `Stub*` | `/^[Ss]tub[A-Z]/` | `StubRepository`, `stubAuthProvider`, `StubCache` |
29
+ | `Fake*` | `/^[Ff]ake[A-Z]/` | `FakeFileSystem`, `fakeEmailSender`, `FakeQueue` |
30
+ | `InMemory*` | `/^[Ii]n[Mm]emory[A-Z]/` | `InMemoryDatabase`, `InMemoryCache`, `InMemoryEventBus` |
31
+ | `Dummy*` | `/^[Dd]ummy[A-Z]/` | `DummyLogger`, `dummyConfig`, `DummyTransport` |
32
+ | `Spy*` | `/^[Ss]py[A-Z]/` | `SpyLogger`, `spyNotifier` |
33
+ | `*Builder` | `/[A-Z]\w+Builder$/` | `UserBuilder`, `OrderBuilder`, `ConfigBuilder` |
34
+ | `Test*` | `/^[Tt]est[A-Z]/` | `TestServer`, `TestDatabase`, `TestHelper` |
35
+
36
+ ### Counter-Examples (NOT test doubles)
37
+
38
+ These match naming patterns but are NOT test doubles:
39
+
40
+ | Name | Why It's Not a Double |
41
+ |------|----------------------|
42
+ | `mockImplementation()` | Jest API method, not a variable |
43
+ | `InMemoryCache` in production code | Real implementation choice, not a test shortcut |
44
+ | `TestUtils.formatDate()` | Test utility, not a replacement for production code |
45
+ | `buildUser()` in a factory module | Production factory, not test-only builder |
46
+ | `stubborn`, `mockingbird` | English words, not test double prefixes |
47
+
48
+ **Rule**: Match on PascalCase/camelCase boundaries only. `mockUser` matches; `mockingbird` does not.
49
+
50
+ ---
51
+
52
+ ## Class Hierarchy Detection
53
+
54
+ ### Implements/Extends Patterns
55
+
56
+ Classes that implement interfaces or extend base classes as test replacements:
57
+
58
+ ```typescript
59
+ // DETECT: Class implements interface with test-double name
60
+ class FakeDatabase implements DatabasePort {
61
+ private data = new Map<string, unknown>();
62
+ async get(key: string) { return this.data.get(key); }
63
+ async set(key: string, value: unknown) { this.data.set(key, value); }
64
+ }
65
+
66
+ // DETECT: Class extends base with override
67
+ class StubEmailService extends EmailService {
68
+ override async send() { return { sent: true }; }
69
+ }
70
+
71
+ // DETECT: Abstract test base
72
+ class TestRepository<T> implements Repository<T> {
73
+ protected items: T[] = [];
74
+ async findAll() { return this.items; }
75
+ }
76
+ ```
77
+
78
+ **Detection signals** (AST-level):
79
+ 1. Class name matches a test double naming pattern (Fake*, Stub*, Mock*, Test*, InMemory*)
80
+ 2. Class implements an interface OR extends a base class
81
+ 3. Class defined in a test file or `__tests__/` directory
82
+
83
+ **Violation evaluation**:
84
+ - In unit tests: Generally acceptable (isolating external dependencies)
85
+ - In integration tests: Flag if the class replaces an integration boundary the test claims to verify
86
+
87
+ ### Manual Stub Without Naming Convention
88
+
89
+ Some developers create test doubles without naming conventions:
90
+
91
+ ```typescript
92
+ // No Fake/Stub/Mock prefix, but still a test double
93
+ const database = {
94
+ query: async () => [{ id: 1, name: 'test' }],
95
+ insert: async () => ({ id: 1 }),
96
+ delete: async () => true,
97
+ };
98
+
99
+ // Replacement object matching an interface shape
100
+ const logger = {
101
+ info: () => {},
102
+ warn: () => {},
103
+ error: () => {},
104
+ };
105
+ ```
106
+
107
+ **Detection signals**:
108
+ 1. Object literal assigned to variable with interface-matching shape
109
+ 2. All methods are no-ops (`() => {}`) or return hardcoded values
110
+ 3. Variable used where a dependency injection parameter is expected
111
+
112
+ **Note**: These are harder to detect deterministically. Flag as `confidence: medium` for LLM review.
113
+
114
+ ---
115
+
116
+ ## Factory Function Patterns
117
+
118
+ ### Test Data Factories (Usually Safe)
119
+
120
+ Factory functions that create test input data are generally NOT violations:
121
+
122
+ ```typescript
123
+ // SAFE: Creates input data for the system under test
124
+ function createTestUser(overrides = {}) {
125
+ return { id: 'user-1', name: 'Test User', email: 'test@example.com', ...overrides };
126
+ }
127
+
128
+ // SAFE: Builder pattern for test data
129
+ const user = new UserBuilder().withName('Alice').withRole('admin').build();
130
+
131
+ // SAFE: Faker/factory-based generation
132
+ const order = OrderFactory.create({ status: 'pending' });
133
+ ```
134
+
135
+ **Why safe**: These create *input data*, not *replacement behavior*. The system under test still processes this data through real code paths.
136
+
137
+ ### Test Infrastructure Factories (Context-Dependent)
138
+
139
+ Factory functions that create test infrastructure need evaluation:
140
+
141
+ ```typescript
142
+ // CONTEXT-DEPENDENT: Creates a test server
143
+ function createTestServer(routes) {
144
+ const app = express();
145
+ routes.forEach(r => app.get(r.path, r.handler));
146
+ return app.listen(0); // Random port
147
+ }
148
+
149
+ // CONTEXT-DEPENDENT: Creates an in-memory database
150
+ function createTestDatabase(seed = []) {
151
+ const db = new Map();
152
+ seed.forEach(item => db.set(item.id, item));
153
+ return { get: (id) => db.get(id), set: (id, v) => db.set(id, v) };
154
+ }
155
+ ```
156
+
157
+ **Evaluation rule**: If the factory replaces a real dependency that the test claims to verify integration with, it's a violation. If it provides supporting infrastructure (e.g., a test HTTP server to receive real requests), it's acceptable.
158
+
159
+ ### Factory Naming Conventions
160
+
161
+ | Pattern | Regex | Typically Safe? |
162
+ |---------|-------|-----------------|
163
+ | `create*` | `/^create[A-Z]/` | Yes (data factory) |
164
+ | `build*` | `/^build[A-Z]/` | Yes (builder pattern) |
165
+ | `make*` | `/^make[A-Z]/` | Yes (data factory) |
166
+ | `generate*` | `/^generate[A-Z]/` | Yes (data factory) |
167
+ | `setup*` | `/^setup[A-Z]/` | Evaluate (infrastructure) |
168
+ | `createTest*` | `/^createTest[A-Z]/` | Evaluate (test infrastructure) |
169
+ | `buildMock*` | `/^buildMock[A-Z]/` | Flag (explicit mock factory) |
170
+ | `createFake*` | `/^createFake[A-Z]/` | Flag (explicit fake factory) |
171
+
172
+ ---
173
+
174
+ ## Framework-Specific Patterns
175
+
176
+ ### Jest / Vitest
177
+
178
+ ```typescript
179
+ // Already detected by mock-detection core patterns:
180
+ jest.mock('./module');
181
+ jest.spyOn(object, 'method');
182
+ vi.mock('./module');
183
+ vi.spyOn(object, 'method');
184
+
185
+ // Extended patterns (detect via this reference):
186
+ jest.fn().mockReturnValue(value); // Inline mock function
187
+ jest.fn().mockResolvedValue(value); // Async mock
188
+ jest.fn().mockImplementation(fn); // Custom implementation mock
189
+ ```
190
+
191
+ ### Sinon
192
+
193
+ ```typescript
194
+ sinon.stub(object, 'method').returns(value);
195
+ sinon.mock(object).expects('method');
196
+ sinon.fake.returns(value);
197
+ sinon.spy(object, 'method');
198
+ ```
199
+
200
+ ### Test Containers / Real Infrastructure
201
+
202
+ ```typescript
203
+ // NOT a test double - real infrastructure for integration tests
204
+ const container = await new GenericContainer('postgres:15').start();
205
+ const redis = await new GenericContainer('redis:7').start();
206
+
207
+ // NOT a test double - real HTTP interception for external APIs
208
+ const server = setupServer(
209
+ rest.get('/api/users', (req, res, ctx) => res(ctx.json(users)))
210
+ );
211
+ ```
212
+
213
+ **Rule**: Test containers and MSW/nock interceptors for *external* APIs are legitimate test infrastructure, not violations. See `false-positive-prevention.md` for the full allowlist.
214
+
215
+ ---
216
+
217
+ ## Detection Priority by Test Type
218
+
219
+ | Test Type | What to Flag | What to Allow |
220
+ |-----------|-------------|---------------|
221
+ | **Unit** | T1 (mock SUT), T2 (call-only assert) | External dep mocks, data factories |
222
+ | **Integration** | T3 (mock boundary), T3+ (broken chain), manual stubs replacing integration points | Data factories, test containers, external API mocks |
223
+ | **E2E** | Any mock/stub/fake that shortcuts the flow | Seed data, test user factories |
224
+
225
+ ---
226
+
227
+ ## Summary for LLM Agent
228
+
229
+ When analyzing a test file:
230
+
231
+ 1. **Scan for naming patterns** from the tables above
232
+ 2. **Check class hierarchies** for implements/extends with test-double names
233
+ 3. **Identify factory functions** and classify as data factory (safe) vs infrastructure factory (evaluate)
234
+ 4. **Cross-reference with test type** (unit vs integration vs E2E)
235
+ 5. **Apply the mock appropriateness rubric** from mock-detection SKILL.md
236
+ 6. **Consult false-positive-prevention.md** before flagging borderline patterns