@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.
- package/.claude-plugin/plugin.json +43 -0
- package/agents/bulwark-fix-validator.md +633 -0
- package/agents/bulwark-implementer.md +391 -0
- package/agents/bulwark-issue-analyzer.md +308 -0
- package/agents/bulwark-standards-reviewer.md +221 -0
- package/agents/plan-creation-architect.md +323 -0
- package/agents/plan-creation-eng-lead.md +352 -0
- package/agents/plan-creation-po.md +300 -0
- package/agents/plan-creation-qa-critic.md +334 -0
- package/agents/product-ideation-competitive-analyzer.md +298 -0
- package/agents/product-ideation-idea-validator.md +268 -0
- package/agents/product-ideation-market-researcher.md +292 -0
- package/agents/product-ideation-pattern-documenter.md +308 -0
- package/agents/product-ideation-segment-analyzer.md +303 -0
- package/agents/product-ideation-strategist.md +259 -0
- package/agents/statusline-setup.md +97 -0
- package/hooks/hooks.json +59 -0
- package/package.json +45 -0
- package/scripts/hooks/cleanup-stale.sh +13 -0
- package/scripts/hooks/enforce-quality.sh +166 -0
- package/scripts/hooks/implementer-quality.sh +256 -0
- package/scripts/hooks/inject-protocol.sh +52 -0
- package/scripts/hooks/suggest-pipeline.sh +175 -0
- package/scripts/hooks/track-pipeline-start.sh +37 -0
- package/scripts/hooks/track-pipeline-stop.sh +52 -0
- package/scripts/init-rules.sh +35 -0
- package/scripts/init.sh +151 -0
- package/skills/anthropic-validator/SKILL.md +607 -0
- package/skills/anthropic-validator/references/agents-checklist.md +131 -0
- package/skills/anthropic-validator/references/commands-checklist.md +102 -0
- package/skills/anthropic-validator/references/hooks-checklist.md +151 -0
- package/skills/anthropic-validator/references/mcp-checklist.md +136 -0
- package/skills/anthropic-validator/references/plugins-checklist.md +148 -0
- package/skills/anthropic-validator/references/skills-checklist.md +85 -0
- package/skills/assertion-patterns/SKILL.md +296 -0
- package/skills/bug-magnet-data/SKILL.md +284 -0
- package/skills/bug-magnet-data/context/cli-args.md +91 -0
- package/skills/bug-magnet-data/context/db-query.md +104 -0
- package/skills/bug-magnet-data/context/file-contents.md +103 -0
- package/skills/bug-magnet-data/context/http-body.md +91 -0
- package/skills/bug-magnet-data/context/process-spawn.md +123 -0
- package/skills/bug-magnet-data/data/booleans/boundaries.yaml +143 -0
- package/skills/bug-magnet-data/data/collections/arrays.yaml +114 -0
- package/skills/bug-magnet-data/data/collections/objects.yaml +123 -0
- package/skills/bug-magnet-data/data/concurrency/race-conditions.yaml +118 -0
- package/skills/bug-magnet-data/data/concurrency/state-machines.yaml +115 -0
- package/skills/bug-magnet-data/data/dates/boundaries.yaml +137 -0
- package/skills/bug-magnet-data/data/dates/invalid.yaml +132 -0
- package/skills/bug-magnet-data/data/dates/timezone.yaml +118 -0
- package/skills/bug-magnet-data/data/encoding/charset.yaml +79 -0
- package/skills/bug-magnet-data/data/encoding/normalization.yaml +105 -0
- package/skills/bug-magnet-data/data/formats/email.yaml +154 -0
- package/skills/bug-magnet-data/data/formats/json.yaml +187 -0
- package/skills/bug-magnet-data/data/formats/url.yaml +165 -0
- package/skills/bug-magnet-data/data/language-specific/javascript.yaml +182 -0
- package/skills/bug-magnet-data/data/language-specific/python.yaml +174 -0
- package/skills/bug-magnet-data/data/language-specific/rust.yaml +148 -0
- package/skills/bug-magnet-data/data/numbers/boundaries.yaml +161 -0
- package/skills/bug-magnet-data/data/numbers/precision.yaml +89 -0
- package/skills/bug-magnet-data/data/numbers/special.yaml +69 -0
- package/skills/bug-magnet-data/data/strings/boundaries.yaml +109 -0
- package/skills/bug-magnet-data/data/strings/injection.yaml +208 -0
- package/skills/bug-magnet-data/data/strings/special-chars.yaml +190 -0
- package/skills/bug-magnet-data/data/strings/unicode.yaml +139 -0
- package/skills/bug-magnet-data/references/external-lists.md +115 -0
- package/skills/bulwark-brainstorm/SKILL.md +563 -0
- package/skills/bulwark-brainstorm/references/at-teammate-prompts.md +60 -0
- package/skills/bulwark-brainstorm/references/role-critical-analyst.md +78 -0
- package/skills/bulwark-brainstorm/references/role-development-lead.md +66 -0
- package/skills/bulwark-brainstorm/references/role-product-delivery-lead.md +79 -0
- package/skills/bulwark-brainstorm/references/role-product-manager.md +62 -0
- package/skills/bulwark-brainstorm/references/role-project-sme.md +59 -0
- package/skills/bulwark-brainstorm/references/role-technical-architect.md +66 -0
- package/skills/bulwark-research/SKILL.md +298 -0
- package/skills/bulwark-research/references/viewpoint-contrarian.md +63 -0
- package/skills/bulwark-research/references/viewpoint-direct-investigation.md +62 -0
- package/skills/bulwark-research/references/viewpoint-first-principles.md +65 -0
- package/skills/bulwark-research/references/viewpoint-practitioner.md +62 -0
- package/skills/bulwark-research/references/viewpoint-prior-art.md +66 -0
- package/skills/bulwark-scaffold/SKILL.md +330 -0
- package/skills/bulwark-statusline/SKILL.md +161 -0
- package/skills/bulwark-statusline/scripts/statusline.sh +144 -0
- package/skills/bulwark-verify/SKILL.md +519 -0
- package/skills/code-review/SKILL.md +428 -0
- package/skills/code-review/examples/anti-patterns/linting.ts +181 -0
- package/skills/code-review/examples/anti-patterns/security.ts +91 -0
- package/skills/code-review/examples/anti-patterns/standards.ts +195 -0
- package/skills/code-review/examples/anti-patterns/type-safety.ts +108 -0
- package/skills/code-review/examples/recommended/linting.ts +195 -0
- package/skills/code-review/examples/recommended/security.ts +154 -0
- package/skills/code-review/examples/recommended/standards.ts +231 -0
- package/skills/code-review/examples/recommended/type-safety.ts +181 -0
- package/skills/code-review/frameworks/angular.md +218 -0
- package/skills/code-review/frameworks/django.md +235 -0
- package/skills/code-review/frameworks/express.md +207 -0
- package/skills/code-review/frameworks/flask.md +298 -0
- package/skills/code-review/frameworks/generic.md +146 -0
- package/skills/code-review/frameworks/react.md +152 -0
- package/skills/code-review/frameworks/vue.md +244 -0
- package/skills/code-review/references/linting-patterns.md +221 -0
- package/skills/code-review/references/security-patterns.md +125 -0
- package/skills/code-review/references/standards-patterns.md +246 -0
- package/skills/code-review/references/type-safety-patterns.md +130 -0
- package/skills/component-patterns/SKILL.md +131 -0
- package/skills/component-patterns/references/pattern-cli-command.md +118 -0
- package/skills/component-patterns/references/pattern-database.md +166 -0
- package/skills/component-patterns/references/pattern-external-api.md +139 -0
- package/skills/component-patterns/references/pattern-file-parser.md +168 -0
- package/skills/component-patterns/references/pattern-http-server.md +162 -0
- package/skills/component-patterns/references/pattern-process-spawner.md +133 -0
- package/skills/continuous-feedback/SKILL.md +327 -0
- package/skills/continuous-feedback/references/collect-instructions.md +81 -0
- package/skills/continuous-feedback/references/specialize-code-review.md +82 -0
- package/skills/continuous-feedback/references/specialize-general.md +98 -0
- package/skills/continuous-feedback/references/specialize-test-audit.md +81 -0
- package/skills/create-skill/SKILL.md +359 -0
- package/skills/create-skill/references/agent-conventions.md +194 -0
- package/skills/create-skill/references/agent-template.md +195 -0
- package/skills/create-skill/references/content-guidance.md +291 -0
- package/skills/create-skill/references/decision-framework.md +124 -0
- package/skills/create-skill/references/template-pipeline.md +217 -0
- package/skills/create-skill/references/template-reference-heavy.md +111 -0
- package/skills/create-skill/references/template-research.md +210 -0
- package/skills/create-skill/references/template-script-driven.md +172 -0
- package/skills/create-skill/references/template-simple.md +80 -0
- package/skills/create-subagent/SKILL.md +353 -0
- package/skills/create-subagent/references/agent-conventions.md +268 -0
- package/skills/create-subagent/references/content-guidance.md +232 -0
- package/skills/create-subagent/references/decision-framework.md +134 -0
- package/skills/create-subagent/references/template-single-agent.md +192 -0
- package/skills/fix-bug/SKILL.md +241 -0
- package/skills/governance-protocol/SKILL.md +116 -0
- package/skills/init/SKILL.md +341 -0
- package/skills/issue-debugging/SKILL.md +385 -0
- package/skills/issue-debugging/references/anti-patterns.md +245 -0
- package/skills/issue-debugging/references/debug-report-schema.md +227 -0
- package/skills/mock-detection/SKILL.md +511 -0
- package/skills/mock-detection/references/false-positive-prevention.md +402 -0
- package/skills/mock-detection/references/stub-patterns.md +236 -0
- package/skills/pipeline-templates/SKILL.md +215 -0
- package/skills/pipeline-templates/references/code-change-workflow.md +277 -0
- package/skills/pipeline-templates/references/code-review.md +336 -0
- package/skills/pipeline-templates/references/fix-validation.md +421 -0
- package/skills/pipeline-templates/references/new-feature.md +335 -0
- package/skills/pipeline-templates/references/research-brainstorm.md +161 -0
- package/skills/pipeline-templates/references/research-planning.md +257 -0
- package/skills/pipeline-templates/references/test-audit.md +389 -0
- package/skills/pipeline-templates/references/test-execution-fix.md +238 -0
- package/skills/plan-creation/SKILL.md +497 -0
- package/skills/product-ideation/SKILL.md +372 -0
- package/skills/product-ideation/references/analysis-frameworks.md +161 -0
- package/skills/session-handoff/SKILL.md +139 -0
- package/skills/session-handoff/references/examples.md +223 -0
- package/skills/setup-lsp/SKILL.md +312 -0
- package/skills/setup-lsp/references/server-registry.md +85 -0
- package/skills/setup-lsp/references/troubleshooting.md +135 -0
- package/skills/subagent-output-templating/SKILL.md +415 -0
- package/skills/subagent-output-templating/references/examples.md +440 -0
- package/skills/subagent-prompting/SKILL.md +364 -0
- package/skills/subagent-prompting/references/examples.md +342 -0
- package/skills/test-audit/SKILL.md +531 -0
- package/skills/test-audit/references/known-limitations.md +41 -0
- package/skills/test-audit/references/priority-classification.md +30 -0
- package/skills/test-audit/references/prompts/deep-mode-detection.md +83 -0
- package/skills/test-audit/references/prompts/synthesis.md +57 -0
- package/skills/test-audit/references/rewrite-instructions.md +46 -0
- package/skills/test-audit/references/schemas/audit-output.yaml +100 -0
- package/skills/test-audit/references/schemas/diagnostic-output.yaml +49 -0
- package/skills/test-audit/scripts/data-flow-analyzer.ts +509 -0
- package/skills/test-audit/scripts/integration-mock-detector.ts +462 -0
- package/skills/test-audit/scripts/package.json +20 -0
- package/skills/test-audit/scripts/skip-detector.ts +211 -0
- package/skills/test-audit/scripts/verification-counter.ts +295 -0
- package/skills/test-classification/SKILL.md +310 -0
- package/skills/test-fixture-creation/SKILL.md +295 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Coding Standards Patterns Reference
|
|
2
|
+
|
|
3
|
+
Patterns for the Coding Standards section of code-review skill.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Atomic Principles (from Rules.md)
|
|
8
|
+
|
|
9
|
+
### CS1: Single Responsibility
|
|
10
|
+
|
|
11
|
+
Every function, class, and module should have ONE purpose.
|
|
12
|
+
|
|
13
|
+
| Pattern | Detection | Severity |
|
|
14
|
+
|---------|-----------|----------|
|
|
15
|
+
| Function does multiple things | Multiple comments describing phases | Important |
|
|
16
|
+
| Class with unrelated methods | Methods operating on different data | Important |
|
|
17
|
+
| Module with mixed exports | Utilities + domain logic in same file | Suggestion |
|
|
18
|
+
|
|
19
|
+
**Good Example:**
|
|
20
|
+
```typescript
|
|
21
|
+
// Single purpose: validate email format
|
|
22
|
+
function isValidEmail(email: string): boolean {
|
|
23
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Anti-pattern:**
|
|
28
|
+
```typescript
|
|
29
|
+
// Multiple purposes: validate AND send AND log
|
|
30
|
+
function processEmail(email: string): void {
|
|
31
|
+
if (!isValidEmail(email)) throw new Error('Invalid');
|
|
32
|
+
sendEmail(email);
|
|
33
|
+
logAction('email_sent', email);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### CS2: No Magic
|
|
38
|
+
|
|
39
|
+
No implicit behaviors, hidden dependencies, or undocumented side effects.
|
|
40
|
+
|
|
41
|
+
| Pattern | Detection | Severity |
|
|
42
|
+
|---------|-----------|----------|
|
|
43
|
+
| Magic numbers | Hardcoded values without names | Suggestion |
|
|
44
|
+
| Hidden mutations | Function modifies input object | Important |
|
|
45
|
+
| Implicit globals | Using undeclared global state | Important |
|
|
46
|
+
| Side effects in getters | Property access triggers actions | Important |
|
|
47
|
+
|
|
48
|
+
**Good Example:**
|
|
49
|
+
```typescript
|
|
50
|
+
const MAX_RETRY_ATTEMPTS = 3;
|
|
51
|
+
const TIMEOUT_MS = 5000;
|
|
52
|
+
|
|
53
|
+
async function fetchWithRetry(url: string): Promise<Response> {
|
|
54
|
+
// explicit constants, no hidden behavior
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Anti-pattern:**
|
|
59
|
+
```typescript
|
|
60
|
+
async function fetch(url: string): Promise<Response> {
|
|
61
|
+
// Magic numbers, unclear behavior
|
|
62
|
+
for (let i = 0; i < 3; i++) {
|
|
63
|
+
await sleep(5000);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### CS3: Fail Fast
|
|
69
|
+
|
|
70
|
+
Validate inputs at boundaries, return errors early, no silent failures.
|
|
71
|
+
|
|
72
|
+
| Pattern | Detection | Severity |
|
|
73
|
+
|---------|-----------|----------|
|
|
74
|
+
| Missing input validation | Public function without checks | Important |
|
|
75
|
+
| Silent catch | `catch (e) {}` with no handling | Important |
|
|
76
|
+
| Default on error | Returning default instead of throwing | Suggestion |
|
|
77
|
+
| Deep error propagation | Error handled far from source | Suggestion |
|
|
78
|
+
|
|
79
|
+
**Good Example:**
|
|
80
|
+
```typescript
|
|
81
|
+
function divide(a: number, b: number): number {
|
|
82
|
+
if (b === 0) throw new Error('Division by zero');
|
|
83
|
+
return a / b;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Anti-pattern:**
|
|
88
|
+
```typescript
|
|
89
|
+
function divide(a: number, b: number): number {
|
|
90
|
+
try {
|
|
91
|
+
return a / b;
|
|
92
|
+
} catch {
|
|
93
|
+
return 0; // Silent failure, incorrect result
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### CS4: Clean Code
|
|
99
|
+
|
|
100
|
+
No unused code, no commented-out blocks, complete deletions.
|
|
101
|
+
|
|
102
|
+
| Pattern | Detection | Severity |
|
|
103
|
+
|---------|-----------|----------|
|
|
104
|
+
| Unused imports | Import not referenced in file | Suggestion |
|
|
105
|
+
| Unused variables | Variable declared but never used | Suggestion |
|
|
106
|
+
| Commented-out code | Large blocks of commented code | Important |
|
|
107
|
+
| Dead code | Unreachable code paths | Important |
|
|
108
|
+
|
|
109
|
+
**Detection Note:** Most of these are caught by linters. This section verifies linter was run.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Documentation Patterns
|
|
114
|
+
|
|
115
|
+
### When to Document
|
|
116
|
+
|
|
117
|
+
| Situation | Documentation Required |
|
|
118
|
+
|-----------|----------------------|
|
|
119
|
+
| Public API | Yes - JSDoc with @param, @returns |
|
|
120
|
+
| Complex algorithm | Yes - Explain approach, not code |
|
|
121
|
+
| Non-obvious decision | Yes - Why this approach |
|
|
122
|
+
| Simple getter/setter | No - Self-evident |
|
|
123
|
+
| Internal helper | Optional |
|
|
124
|
+
|
|
125
|
+
### Good Documentation
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
/**
|
|
129
|
+
* Calculate compound interest with monthly compounding.
|
|
130
|
+
*
|
|
131
|
+
* Uses the formula: A = P(1 + r/n)^(nt)
|
|
132
|
+
*
|
|
133
|
+
* @param principal - Initial investment amount
|
|
134
|
+
* @param rate - Annual interest rate (0.05 = 5%)
|
|
135
|
+
* @param years - Investment duration in years
|
|
136
|
+
* @returns Final amount after compound interest
|
|
137
|
+
*/
|
|
138
|
+
function calculateCompoundInterest(
|
|
139
|
+
principal: number,
|
|
140
|
+
rate: number,
|
|
141
|
+
years: number
|
|
142
|
+
): number {
|
|
143
|
+
const n = 12; // Monthly compounding
|
|
144
|
+
return principal * Math.pow(1 + rate / n, n * years);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Anti-pattern Documentation
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// BAD: Describes what, not why
|
|
152
|
+
// This function adds two numbers
|
|
153
|
+
function add(a: number, b: number): number {
|
|
154
|
+
return a + b;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// BAD: Outdated documentation
|
|
158
|
+
/**
|
|
159
|
+
* @deprecated Use newFunction instead
|
|
160
|
+
* @param items - List of items to process
|
|
161
|
+
*/
|
|
162
|
+
function process(items: Item[], config: Config): Result {
|
|
163
|
+
// Config parameter not documented
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Pattern Adherence
|
|
170
|
+
|
|
171
|
+
### Project-Specific Patterns
|
|
172
|
+
|
|
173
|
+
Check for consistency with existing codebase patterns:
|
|
174
|
+
|
|
175
|
+
| Pattern Type | Check |
|
|
176
|
+
|--------------|-------|
|
|
177
|
+
| Error handling | Same error types used? |
|
|
178
|
+
| Async patterns | Consistent Promise vs async/await? |
|
|
179
|
+
| Naming conventions | Follows existing style? |
|
|
180
|
+
| File organization | Matches project structure? |
|
|
181
|
+
|
|
182
|
+
### Common Inconsistencies
|
|
183
|
+
|
|
184
|
+
| Pattern | Example | Fix |
|
|
185
|
+
|---------|---------|-----|
|
|
186
|
+
| Mixed async styles | `then()` and `await` in same file | Pick one |
|
|
187
|
+
| Inconsistent exports | Named vs default exports | Follow project standard |
|
|
188
|
+
| Mixed error types | Custom errors vs plain Error | Use project error classes |
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Architecture Patterns
|
|
193
|
+
|
|
194
|
+
### Layer Violations
|
|
195
|
+
|
|
196
|
+
| Violation | Example | Severity |
|
|
197
|
+
|-----------|---------|----------|
|
|
198
|
+
| UI → Database | Component directly querying DB | Important |
|
|
199
|
+
| Controller → Repository | Skipping service layer | Suggestion |
|
|
200
|
+
| Cross-feature import | Feature A importing Feature B internals | Important |
|
|
201
|
+
|
|
202
|
+
### Dependency Direction
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
┌─────────────────────────────────────────┐
|
|
206
|
+
│ Presentation │
|
|
207
|
+
│ (components, pages) │
|
|
208
|
+
└───────────────────┬─────────────────────┘
|
|
209
|
+
↓
|
|
210
|
+
┌─────────────────────────────────────────┐
|
|
211
|
+
│ Application │
|
|
212
|
+
│ (services, use cases) │
|
|
213
|
+
└───────────────────┬─────────────────────┘
|
|
214
|
+
↓
|
|
215
|
+
┌─────────────────────────────────────────┐
|
|
216
|
+
│ Domain │
|
|
217
|
+
│ (entities, value objects) │
|
|
218
|
+
└───────────────────┬─────────────────────┘
|
|
219
|
+
↓
|
|
220
|
+
┌─────────────────────────────────────────┐
|
|
221
|
+
│ Infrastructure │
|
|
222
|
+
│ (repositories, external APIs) │
|
|
223
|
+
└─────────────────────────────────────────┘
|
|
224
|
+
|
|
225
|
+
Arrows indicate allowed import direction.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Detection Priority
|
|
231
|
+
|
|
232
|
+
1. **Fail fast violations**: Check public function entry points
|
|
233
|
+
2. **Single responsibility**: Look for "and" in function names/descriptions
|
|
234
|
+
3. **Magic values**: Scan for hardcoded numbers, strings
|
|
235
|
+
4. **Documentation gaps**: Check public exports
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## False Positive Prevention
|
|
240
|
+
|
|
241
|
+
**Skip these patterns:**
|
|
242
|
+
- Prototype/experimental code with explicit markers
|
|
243
|
+
- Third-party integration matching external conventions
|
|
244
|
+
- Auto-generated code (migrations, GraphQL schemas)
|
|
245
|
+
- Configuration files with intentional magic values
|
|
246
|
+
- Test files with intentional violations for testing
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Type Safety Patterns Reference
|
|
2
|
+
|
|
3
|
+
Patterns for the Type Safety section of code-review skill.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `any` Usage Patterns
|
|
8
|
+
|
|
9
|
+
### Explicit `any`
|
|
10
|
+
|
|
11
|
+
| Pattern | Detection | Severity | Example |
|
|
12
|
+
|---------|-----------|----------|---------|
|
|
13
|
+
| Parameter typed as `any` | `: any` in function signature | Important | `function process(data: any)` |
|
|
14
|
+
| Return typed as `any` | `: any` as return type | Important | `function fetch(): any` |
|
|
15
|
+
| Variable typed as `any` | `const x: any =` | Important | `const response: any = await fetch()` |
|
|
16
|
+
| Generic constraint `any` | `<T extends any>` | Important | Usually unnecessary |
|
|
17
|
+
|
|
18
|
+
**When `any` is Acceptable:**
|
|
19
|
+
- JSON parsing with immediate schema validation
|
|
20
|
+
- Third-party library interop with no types
|
|
21
|
+
- Type assertions for testing flexibility
|
|
22
|
+
- Gradual migration from JavaScript
|
|
23
|
+
|
|
24
|
+
### Implicit `any`
|
|
25
|
+
|
|
26
|
+
| Pattern | Detection | Severity | Example |
|
|
27
|
+
|---------|-----------|----------|---------|
|
|
28
|
+
| Missing parameter type | No type annotation, no inference | Important | `function process(data)` |
|
|
29
|
+
| Missing return type | Complex function without explicit return | Suggestion | `function calculate() { ... }` |
|
|
30
|
+
| Untyped catch clause | `catch (e)` without type annotation | Suggestion | `catch (error) { console.log(error.message) }` |
|
|
31
|
+
|
|
32
|
+
**tsconfig Recommendation:**
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"compilerOptions": {
|
|
36
|
+
"noImplicitAny": true,
|
|
37
|
+
"strictNullChecks": true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Null/Undefined Handling
|
|
45
|
+
|
|
46
|
+
### Unsafe Patterns
|
|
47
|
+
|
|
48
|
+
| Pattern | Detection | Severity | Example |
|
|
49
|
+
|---------|-----------|----------|---------|
|
|
50
|
+
| Non-null assertion abuse | `!` on potentially null values | Important | `user!.name` when user may be null |
|
|
51
|
+
| Optional chaining gap | Mixed `?.` and `.` on same chain | Important | `user?.profile.name` (profile may be undefined) |
|
|
52
|
+
| Truthy check inadequate | `if (value)` when 0 or "" is valid | Important | `if (count)` when 0 is valid |
|
|
53
|
+
| Missing nullish handling | No `?? defaultValue` for optional | Suggestion | `return config.timeout` without fallback |
|
|
54
|
+
|
|
55
|
+
### Safe Patterns
|
|
56
|
+
|
|
57
|
+
| Pattern | Example |
|
|
58
|
+
|---------|---------|
|
|
59
|
+
| Explicit null check | `if (user !== null && user !== undefined)` |
|
|
60
|
+
| Optional chaining throughout | `user?.profile?.name` |
|
|
61
|
+
| Nullish coalescing | `config.timeout ?? 30000` |
|
|
62
|
+
| Type narrowing | `if ('name' in user)` |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Unsafe Type Assertions
|
|
67
|
+
|
|
68
|
+
### High-Risk Patterns
|
|
69
|
+
|
|
70
|
+
| Pattern | Detection | Severity | Example |
|
|
71
|
+
|---------|-----------|----------|---------|
|
|
72
|
+
| Double assertion | `as unknown as T` | Critical | `value as unknown as SpecificType` |
|
|
73
|
+
| Widening then narrowing | Cast to `any` then to specific | Critical | `(value as any) as ExpectedType` |
|
|
74
|
+
| Non-overlapping assertion | Types share no properties | Important | `string as number` |
|
|
75
|
+
| Assertion without validation | Cast external data without checks | Important | `JSON.parse(input) as Config` |
|
|
76
|
+
|
|
77
|
+
### Safe Assertion Patterns
|
|
78
|
+
|
|
79
|
+
| Pattern | Example |
|
|
80
|
+
|---------|---------|
|
|
81
|
+
| Type guard before assertion | `if (isConfig(data)) { return data as Config }` |
|
|
82
|
+
| Schema validation | `const config = configSchema.parse(input)` |
|
|
83
|
+
| Branded types | `type UserId = string & { readonly brand: unique symbol }` |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Common Bypasses
|
|
88
|
+
|
|
89
|
+
### Library Interop
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// SUSPECTED: Library returns any
|
|
93
|
+
import { externalLib } from 'untyped-lib';
|
|
94
|
+
const result = externalLib.process(data); // any
|
|
95
|
+
|
|
96
|
+
// RECOMMENDED: Wrap with type
|
|
97
|
+
interface ProcessResult { status: string; data: unknown }
|
|
98
|
+
const result: ProcessResult = externalLib.process(data);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### JSON Parsing
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// SUSPECTED: Unvalidated JSON
|
|
105
|
+
const config = JSON.parse(rawConfig); // any
|
|
106
|
+
|
|
107
|
+
// RECOMMENDED: Validate immediately
|
|
108
|
+
const config = JSON.parse(rawConfig);
|
|
109
|
+
if (!isValidConfig(config)) throw new Error('Invalid config');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Detection Priority
|
|
115
|
+
|
|
116
|
+
1. **Explicit `any` annotations**: Direct code search
|
|
117
|
+
2. **Type assertions**: Look for `as` keyword
|
|
118
|
+
3. **Non-null assertions**: Look for `!` not in conditionals
|
|
119
|
+
4. **Implicit any**: Requires type checking context (tsconfig)
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## False Positive Prevention
|
|
124
|
+
|
|
125
|
+
**Skip these patterns:**
|
|
126
|
+
- `any` in test files for mock flexibility
|
|
127
|
+
- `any` with immediate `typeof` or `instanceof` check
|
|
128
|
+
- Type assertions in type definition files (.d.ts)
|
|
129
|
+
- `unknown` usage (proper unknown handling is safe)
|
|
130
|
+
- Assertion in return position with JSDoc validation note
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: component-patterns
|
|
3
|
+
description: Per-component-type verification approaches. Use when generating verification scripts for different component types.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Component Patterns
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Provide verification strategies for different component types. This skill defines how to
|
|
12
|
+
test real behavior for CLIs, servers, parsers, processes, databases, and external APIs.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Load this skill when:
|
|
17
|
+
- Generating verification scripts via bulwark-verify skill
|
|
18
|
+
- Determining how to test a specific component type
|
|
19
|
+
- Implementing test-audit Step 7 rewrites
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Component Type Detection
|
|
24
|
+
|
|
25
|
+
Analyze the code to determine component type based on these indicators:
|
|
26
|
+
|
|
27
|
+
| Indicators | Component Type | Pattern Reference |
|
|
28
|
+
|------------|----------------|-------------------|
|
|
29
|
+
| Imports `child_process`, has `spawn`/`exec`/`execSync` | Process Spawner | `references/pattern-process-spawner.md` |
|
|
30
|
+
| Imports `http`/`https`/`express`/`fastify`/`koa`, has `listen()` | HTTP Server | `references/pattern-http-server.md` |
|
|
31
|
+
| Imports `fs`, reads/parses files, has parse functions | File Parser | `references/pattern-file-parser.md` |
|
|
32
|
+
| Has CLI argument parsing (`process.argv`, `yargs`, `commander`, `argparse`) | CLI Command | `references/pattern-cli-command.md` |
|
|
33
|
+
| Imports database driver (`pg`, `mysql`, `mongoose`, `sqlite`, `prisma`) | Database | `references/pattern-database.md` |
|
|
34
|
+
| Makes outbound HTTP calls (`fetch`, `axios`, `got`, `requests`) | External API | `references/pattern-external-api.md` |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Pattern Reference Files
|
|
39
|
+
|
|
40
|
+
Each pattern reference contains:
|
|
41
|
+
- **Strategy**: High-level approach for testing the component type
|
|
42
|
+
- **Templates**: Ready-to-use verification script templates in Bash, Node/Jest, and Python/pytest
|
|
43
|
+
- **Placeholders**: Variables to substitute with component-specific values
|
|
44
|
+
|
|
45
|
+
### Available Patterns
|
|
46
|
+
|
|
47
|
+
| Pattern | File | Languages |
|
|
48
|
+
|---------|------|-----------|
|
|
49
|
+
| CLI Command | `references/pattern-cli-command.md` | Bash, Node, Python |
|
|
50
|
+
| HTTP Server | `references/pattern-http-server.md` | Bash, Node (supertest), Python |
|
|
51
|
+
| File Parser | `references/pattern-file-parser.md` | Bash, Node, Python |
|
|
52
|
+
| Process Spawner | `references/pattern-process-spawner.md` | Bash, Node |
|
|
53
|
+
| Database | `references/pattern-database.md` | Node, Python, Bash (SQLite) |
|
|
54
|
+
| External API | `references/pattern-external-api.md` | Node (MSW), Python (responses) |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Usage Instructions
|
|
59
|
+
|
|
60
|
+
### Step 1: Detect Component Type
|
|
61
|
+
|
|
62
|
+
Analyze the target component code using the detection table above.
|
|
63
|
+
|
|
64
|
+
### Step 2: Load Pattern Reference
|
|
65
|
+
|
|
66
|
+
Read the appropriate pattern file from `references/`:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Read skills/component-patterns/references/pattern-{type}.md
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Step 3: Select Template
|
|
73
|
+
|
|
74
|
+
Choose the template that matches the project language:
|
|
75
|
+
- **Node projects** (`package.json` present): Use Node/Jest template
|
|
76
|
+
- **Python projects** (`pyproject.toml` or `setup.py` present): Use Python/pytest template
|
|
77
|
+
- **Generic/Other**: Use Bash template
|
|
78
|
+
|
|
79
|
+
### Step 4: Substitute Placeholders
|
|
80
|
+
|
|
81
|
+
Replace all `{placeholder}` values with component-specific information:
|
|
82
|
+
|
|
83
|
+
| Common Placeholders | Description |
|
|
84
|
+
|---------------------|-------------|
|
|
85
|
+
| `{component_name}` | Name of the component being tested |
|
|
86
|
+
| `{component_path}` | Import path to the module |
|
|
87
|
+
| `{port}` | Network port (for servers/processes) |
|
|
88
|
+
| `{expected_value}` | Expected output to verify |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Quick Reference: Component to Pattern
|
|
93
|
+
|
|
94
|
+
| Component Type | Verification Strategy | Key Assertion |
|
|
95
|
+
|----------------|----------------------|---------------|
|
|
96
|
+
| CLI Command | Spawn, capture stdout/stderr | Exit code + output text |
|
|
97
|
+
| HTTP Server | Start, HTTP request, verify response | Status code + response body |
|
|
98
|
+
| File Parser | Create input, parse, check structure | Parsed fields + values |
|
|
99
|
+
| Process Spawner | Spawn, check port/pid, verify behavior | Process alive + responds |
|
|
100
|
+
| Database | Setup DB, execute ops, query state | Records exist/modified |
|
|
101
|
+
| External API | MSW intercept, real fetch, check result | Response data matches |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Key Principle: Real Verification
|
|
106
|
+
|
|
107
|
+
All patterns follow the same principle: **verify observable output, not mock calls**.
|
|
108
|
+
|
|
109
|
+
| Anti-Pattern | Real Pattern |
|
|
110
|
+
|--------------|--------------|
|
|
111
|
+
| `expect(spawn).toHaveBeenCalled()` | `expect(await checkPort(8080)).toBe(true)` |
|
|
112
|
+
| `expect(fs.writeFile).toHaveBeenCalled()` | `expect(fs.existsSync(path)).toBe(true)` |
|
|
113
|
+
| `expect(fetch).toHaveBeenCalledWith(url)` | `const resp = await fetch(url); expect(resp.status).toBe(200)` |
|
|
114
|
+
| `expect(db.save).toHaveBeenCalled()` | `const found = await db.find(id); expect(found).toBeDefined()` |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Diagnostic Output
|
|
119
|
+
|
|
120
|
+
Write diagnostic output to `logs/diagnostics/component-patterns-{YYYYMMDD-HHMMSS}.yaml`:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
skill: component-patterns
|
|
124
|
+
timestamp: {ISO-8601}
|
|
125
|
+
diagnostics:
|
|
126
|
+
component_type_detected: cli|http|file-parser|process|database|api
|
|
127
|
+
pattern_applied: "CLI Command Verification"
|
|
128
|
+
template_language: bash|node|python
|
|
129
|
+
files_analyzed: 1
|
|
130
|
+
completion_status: success
|
|
131
|
+
```
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Pattern 1: CLI Command Verification
|
|
2
|
+
|
|
3
|
+
## Strategy
|
|
4
|
+
|
|
5
|
+
Spawn the CLI as a child process, capture stdout/stderr, verify exit code and output.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Template (Bash)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
#!/bin/bash
|
|
13
|
+
# CLI Verification: {component_name}
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
echo "=== CLI Verification: {component_name} ==="
|
|
17
|
+
|
|
18
|
+
# Test 1: Basic invocation
|
|
19
|
+
echo -n "Test 1: Basic invocation... "
|
|
20
|
+
OUTPUT=$({cli_command} {args} 2>&1)
|
|
21
|
+
EXIT_CODE=$?
|
|
22
|
+
if [ $EXIT_CODE -eq 0 ]; then
|
|
23
|
+
echo "PASS (exit code 0)"
|
|
24
|
+
else
|
|
25
|
+
echo "FAIL (exit code $EXIT_CODE)"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Test 2: Output contains expected text
|
|
30
|
+
echo -n "Test 2: Output validation... "
|
|
31
|
+
if echo "$OUTPUT" | grep -q "{expected_text}"; then
|
|
32
|
+
echo "PASS (found expected text)"
|
|
33
|
+
else
|
|
34
|
+
echo "FAIL (missing expected text)"
|
|
35
|
+
echo "Output was: $OUTPUT"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Test 3: Error handling
|
|
40
|
+
echo -n "Test 3: Error handling... "
|
|
41
|
+
ERROR_OUTPUT=$({cli_command} --invalid-flag 2>&1) || true
|
|
42
|
+
if echo "$ERROR_OUTPUT" | grep -qi "error\|usage\|invalid"; then
|
|
43
|
+
echo "PASS (error message shown)"
|
|
44
|
+
else
|
|
45
|
+
echo "FAIL (no error message)"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
echo "=== All tests passed ==="
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Template (Node/Jest)
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const { execSync, spawn } = require('child_process');
|
|
58
|
+
|
|
59
|
+
describe('{component_name} CLI', () => {
|
|
60
|
+
test('basic invocation succeeds', () => {
|
|
61
|
+
const output = execSync('{cli_command} {args}', { encoding: 'utf8' });
|
|
62
|
+
expect(output).toContain('{expected_text}');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('returns correct exit code on success', (done) => {
|
|
66
|
+
const result = spawn('{cli_command}', ['{args}']);
|
|
67
|
+
result.on('close', (code) => {
|
|
68
|
+
expect(code).toBe(0);
|
|
69
|
+
done();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('shows error on invalid input', () => {
|
|
74
|
+
expect(() => {
|
|
75
|
+
execSync('{cli_command} --invalid', { encoding: 'utf8', stdio: 'pipe' });
|
|
76
|
+
}).toThrow();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Template (Python/pytest)
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import subprocess
|
|
87
|
+
import pytest
|
|
88
|
+
|
|
89
|
+
class TestCLI:
|
|
90
|
+
def test_basic_invocation(self):
|
|
91
|
+
result = subprocess.run(
|
|
92
|
+
['{cli_command}', '{args}'],
|
|
93
|
+
capture_output=True,
|
|
94
|
+
text=True
|
|
95
|
+
)
|
|
96
|
+
assert result.returncode == 0
|
|
97
|
+
assert '{expected_text}' in result.stdout
|
|
98
|
+
|
|
99
|
+
def test_error_handling(self):
|
|
100
|
+
result = subprocess.run(
|
|
101
|
+
['{cli_command}', '--invalid-flag'],
|
|
102
|
+
capture_output=True,
|
|
103
|
+
text=True
|
|
104
|
+
)
|
|
105
|
+
assert result.returncode != 0
|
|
106
|
+
assert 'error' in result.stderr.lower() or 'usage' in result.stderr.lower()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Placeholders
|
|
112
|
+
|
|
113
|
+
| Placeholder | Description |
|
|
114
|
+
|-------------|-------------|
|
|
115
|
+
| `{component_name}` | Name of the CLI component being tested |
|
|
116
|
+
| `{cli_command}` | The CLI command to execute |
|
|
117
|
+
| `{args}` | Command arguments |
|
|
118
|
+
| `{expected_text}` | Text expected in output |
|