@softspark/ai-toolkit 1.3.13 → 1.3.15

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 (39) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +1 -1
  3. package/README.md +59 -18
  4. package/app/ARCHITECTURE.md +2 -1
  5. package/app/agents/backend-specialist.md +8 -0
  6. package/app/agents/code-reviewer.md +9 -0
  7. package/app/agents/database-architect.md +8 -0
  8. package/app/agents/debugger.md +8 -0
  9. package/app/agents/devops-implementer.md +8 -0
  10. package/app/agents/documenter.md +8 -0
  11. package/app/agents/frontend-specialist.md +8 -0
  12. package/app/agents/performance-optimizer.md +8 -0
  13. package/app/agents/security-auditor.md +25 -1
  14. package/app/agents/test-engineer.md +9 -0
  15. package/app/skills/analyze/SKILL.md +15 -0
  16. package/app/skills/api-patterns/SKILL.md +10 -0
  17. package/app/skills/ci-cd-patterns/SKILL.md +10 -0
  18. package/app/skills/clean-code/SKILL.md +10 -0
  19. package/app/skills/cve-scan/SKILL.md +134 -0
  20. package/app/skills/cve-scan/scripts/cve_scan.py +412 -0
  21. package/app/skills/database-patterns/SKILL.md +10 -0
  22. package/app/skills/debug/SKILL.md +16 -0
  23. package/app/skills/docs/SKILL.md +16 -0
  24. package/app/skills/git-mastery/SKILL.md +10 -0
  25. package/app/skills/onboard/SKILL.md +15 -0
  26. package/app/skills/performance-profiling/SKILL.md +10 -0
  27. package/app/skills/plan/SKILL.md +16 -0
  28. package/app/skills/refactor/SKILL.md +16 -0
  29. package/app/skills/review/SKILL.md +58 -3
  30. package/app/skills/security-patterns/SKILL.md +10 -0
  31. package/app/skills/tdd/SKILL.md +6 -0
  32. package/app/skills/testing-patterns/SKILL.md +10 -0
  33. package/app/skills/workflow/SKILL.md +3 -3
  34. package/kb/reference/architecture-overview.md +20 -3
  35. package/kb/reference/skills-catalog.md +60 -3
  36. package/llms-full.txt +81 -6
  37. package/manifest.json +3 -3
  38. package/package.json +2 -2
  39. package/scripts/check_deps.py +52 -0
@@ -0,0 +1,412 @@
1
+ #!/usr/bin/env python3
2
+ """CVE dependency scanner — detect ecosystems and run native audit tools.
3
+
4
+ Stdlib only. No external dependencies.
5
+ """
6
+
7
+ import json
8
+ import os
9
+ import shutil
10
+ import subprocess
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ ECOSYSTEMS = {
15
+ "npm": {
16
+ "manifests": ["package.json"],
17
+ "locks": ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
18
+ "tool": "npm",
19
+ "audit_cmd": ["npm", "audit", "--json"],
20
+ "fix_cmd": ["npm", "audit", "fix"],
21
+ "install_hint": "npm is bundled with Node.js",
22
+ },
23
+ "pip": {
24
+ "manifests": ["requirements.txt", "pyproject.toml", "setup.py", "setup.cfg"],
25
+ "locks": ["requirements.txt"],
26
+ "tool": "pip-audit",
27
+ "audit_cmd": ["pip-audit", "--format=json", "--output=-"],
28
+ "fix_cmd": ["pip-audit", "--fix"],
29
+ "install_hint": "pip install pip-audit",
30
+ },
31
+ "composer": {
32
+ "manifests": ["composer.json"],
33
+ "locks": ["composer.lock"],
34
+ "tool": "composer",
35
+ "audit_cmd": ["composer", "audit", "--format=json"],
36
+ "fix_cmd": ["composer", "update"],
37
+ "install_hint": "https://getcomposer.org/download/",
38
+ },
39
+ "cargo": {
40
+ "manifests": ["Cargo.toml"],
41
+ "locks": ["Cargo.lock"],
42
+ "tool": "cargo-audit",
43
+ "audit_cmd": ["cargo", "audit", "--json"],
44
+ "fix_cmd": ["cargo", "audit", "fix"],
45
+ "install_hint": "cargo install cargo-audit",
46
+ },
47
+ "go": {
48
+ "manifests": ["go.mod"],
49
+ "locks": ["go.sum"],
50
+ "tool": "govulncheck",
51
+ "audit_cmd": ["govulncheck", "-json", "./..."],
52
+ "fix_cmd": ["go", "get", "-u", "./..."],
53
+ "install_hint": "go install golang.org/x/vuln/cmd/govulncheck@latest",
54
+ },
55
+ "ruby": {
56
+ "manifests": ["Gemfile"],
57
+ "locks": ["Gemfile.lock"],
58
+ "tool": "bundle-audit",
59
+ "audit_cmd": ["bundle-audit", "check", "--format=json"],
60
+ "fix_cmd": ["bundle-audit", "update"],
61
+ "install_hint": "gem install bundler-audit",
62
+ },
63
+ "dart": {
64
+ "manifests": ["pubspec.yaml"],
65
+ "locks": ["pubspec.lock"],
66
+ "tool": "dart",
67
+ "audit_cmd": ["dart", "pub", "outdated", "--json"],
68
+ "fix_cmd": ["dart", "pub", "upgrade"],
69
+ "install_hint": "https://dart.dev/get-dart",
70
+ },
71
+ }
72
+
73
+
74
+ def detect_ecosystems(root: Path) -> list[dict]:
75
+ """Detect which package ecosystems are present in the project."""
76
+ found = []
77
+ for name, eco in ECOSYSTEMS.items():
78
+ detected_files = []
79
+ has_lock = False
80
+ for m in eco["manifests"]:
81
+ if (root / m).exists():
82
+ detected_files.append(m)
83
+ for m in eco["locks"]:
84
+ if (root / m).exists():
85
+ detected_files.append(m)
86
+ has_lock = True
87
+ # Deduplicate (requirements.txt is both manifest and lock)
88
+ detected_files = list(dict.fromkeys(detected_files))
89
+ if detected_files:
90
+ tool_path = shutil.which(eco["tool"])
91
+ found.append({
92
+ "name": name,
93
+ "files": detected_files,
94
+ "has_lock": has_lock,
95
+ "tool": eco["tool"],
96
+ "tool_available": tool_path is not None,
97
+ "install_hint": eco["install_hint"],
98
+ "audit_cmd": eco["audit_cmd"],
99
+ "fix_cmd": eco["fix_cmd"],
100
+ })
101
+ return found
102
+
103
+
104
+ def run_audit(eco: dict, root: Path, fix: bool = False) -> dict:
105
+ """Run the native audit command for an ecosystem."""
106
+ cmd = eco["fix_cmd"] if fix else eco["audit_cmd"]
107
+ result = {
108
+ "ecosystem": eco["name"],
109
+ "tool": eco["tool"],
110
+ "command": " ".join(cmd),
111
+ "success": False,
112
+ "raw_output": "",
113
+ "error": "",
114
+ }
115
+
116
+ if not eco["tool_available"]:
117
+ result["error"] = f"Tool '{eco['tool']}' not installed. Install: {eco['install_hint']}"
118
+ return result
119
+
120
+ if not eco.get("has_lock", True) and eco["name"] in ("npm",):
121
+ result["warning"] = "No lock file — run `npm install` first"
122
+ result["success"] = True
123
+ return result
124
+
125
+ try:
126
+ proc = subprocess.run(
127
+ cmd,
128
+ cwd=str(root),
129
+ capture_output=True,
130
+ text=True,
131
+ timeout=120,
132
+ )
133
+ result["raw_output"] = proc.stdout
134
+ result["error"] = proc.stderr if proc.returncode not in (0, 1) else ""
135
+ # npm audit returns 1 when vulnerabilities found — that's not an error
136
+ result["success"] = True
137
+ except FileNotFoundError:
138
+ result["error"] = f"Tool '{eco['tool']}' not found in PATH"
139
+ except subprocess.TimeoutExpired:
140
+ result["error"] = f"Audit command timed out after 120s"
141
+
142
+ return result
143
+
144
+
145
+ def parse_npm_audit(raw: str) -> list[dict]:
146
+ """Parse npm audit JSON output into unified findings."""
147
+ findings = []
148
+ try:
149
+ data = json.loads(raw)
150
+ except (json.JSONDecodeError, ValueError):
151
+ return findings
152
+
153
+ vulns = data.get("vulnerabilities", {})
154
+ for pkg_name, info in vulns.items():
155
+ for via in info.get("via", []):
156
+ if isinstance(via, dict):
157
+ severity = via.get("severity", "unknown").upper()
158
+ findings.append({
159
+ "severity": severity,
160
+ "package": pkg_name,
161
+ "installed": info.get("range", "unknown"),
162
+ "cve": via.get("cve", [via.get("url", "N/A")]),
163
+ "title": via.get("title", "Unknown"),
164
+ "url": via.get("url", ""),
165
+ "fixed_in": info.get("fixAvailable", {}).get("version", "unknown") if isinstance(info.get("fixAvailable"), dict) else "unknown",
166
+ })
167
+ return findings
168
+
169
+
170
+ def parse_pip_audit(raw: str) -> list[dict]:
171
+ """Parse pip-audit JSON output into unified findings."""
172
+ findings = []
173
+ try:
174
+ data = json.loads(raw)
175
+ except (json.JSONDecodeError, ValueError):
176
+ return findings
177
+
178
+ for dep in data.get("dependencies", []):
179
+ for vuln in dep.get("vulns", []):
180
+ vuln_id = vuln.get("id", "N/A")
181
+ aliases = vuln.get("aliases", [])
182
+ # Use GHSA link if available, otherwise OSV
183
+ url = ""
184
+ for alias in aliases:
185
+ if alias.startswith("GHSA-"):
186
+ url = f"https://github.com/advisories/{alias}"
187
+ break
188
+ if not url:
189
+ url = f"https://osv.dev/vulnerability/{vuln_id}"
190
+
191
+ fix_versions = vuln.get("fix_versions", [])
192
+ # Determine severity from CVE ID prefix heuristic — pip-audit
193
+ # doesn't provide severity directly, so we mark as HIGH by default
194
+ severity = "HIGH"
195
+
196
+ findings.append({
197
+ "severity": severity,
198
+ "package": f"{dep['name']}@{dep['version']}",
199
+ "installed": dep.get("version", "unknown"),
200
+ "cve": vuln_id,
201
+ "title": vuln.get("description", "")[:120] + ("..." if len(vuln.get("description", "")) > 120 else ""),
202
+ "url": url,
203
+ "fixed_in": ", ".join(fix_versions) if fix_versions else "unknown",
204
+ })
205
+ return findings
206
+
207
+
208
+ def parse_cargo_audit(raw: str) -> list[dict]:
209
+ """Parse cargo audit JSON output into unified findings."""
210
+ findings = []
211
+ try:
212
+ data = json.loads(raw)
213
+ except (json.JSONDecodeError, ValueError):
214
+ return findings
215
+
216
+ for vuln in data.get("vulnerabilities", {}).get("list", []):
217
+ advisory = vuln.get("advisory", {})
218
+ pkg = vuln.get("package", {})
219
+ findings.append({
220
+ "severity": "HIGH",
221
+ "package": f"{pkg.get('name', 'unknown')}@{pkg.get('version', 'unknown')}",
222
+ "installed": pkg.get("version", "unknown"),
223
+ "cve": advisory.get("id", "N/A"),
224
+ "title": advisory.get("title", "Unknown"),
225
+ "url": advisory.get("url", ""),
226
+ "fixed_in": ", ".join(vuln.get("versions", {}).get("patched", [])) or "unknown",
227
+ })
228
+ return findings
229
+
230
+
231
+ def _table(headers: list[str], rows: list[list[str]]) -> list[str]:
232
+ """Render an aligned plain-text table with box-drawing borders."""
233
+ widths = [len(h) for h in headers]
234
+ for row in rows:
235
+ for i, cell in enumerate(row):
236
+ widths[i] = max(widths[i], len(cell))
237
+
238
+ sep = "├" + "┼".join("─" * (w + 2) for w in widths) + "┤"
239
+ top = "┌" + "┬".join("─" * (w + 2) for w in widths) + "┐"
240
+ bot = "└" + "┴".join("─" * (w + 2) for w in widths) + "┘"
241
+
242
+ def fmt_row(cells: list[str]) -> str:
243
+ parts = []
244
+ for i, cell in enumerate(cells):
245
+ parts.append(f" {cell:<{widths[i]}} ")
246
+ return "│" + "│".join(parts) + "│"
247
+
248
+ lines = [top, fmt_row(headers), sep]
249
+ for row in rows:
250
+ lines.append(fmt_row(row))
251
+ lines.append(bot)
252
+ return lines
253
+
254
+
255
+ def format_text_report(ecosystems: list[dict], results: list[dict], all_findings: list[dict]) -> str:
256
+ """Format findings as a terminal-friendly report."""
257
+ lines = ["", "═══ CVE Scan Report ═══", ""]
258
+
259
+ # Ecosystems detected
260
+ eco_rows = []
261
+ for eco in ecosystems:
262
+ status = "✓" if eco["tool_available"] else "⚠ not installed"
263
+ files = ", ".join(eco["files"])
264
+ eco_rows.append([eco["name"], files, eco["tool"], status])
265
+ lines.extend(_table(["Ecosystem", "Files", "Tool", "Status"], eco_rows))
266
+ lines.append("")
267
+
268
+ # Summary
269
+ severity_counts = {"CRITICAL": 0, "HIGH": 0, "MODERATE": 0, "MEDIUM": 0, "LOW": 0}
270
+ for f in all_findings:
271
+ sev = f["severity"].upper()
272
+ if sev in severity_counts:
273
+ severity_counts[sev] += 1
274
+ else:
275
+ severity_counts[sev] = severity_counts.get(sev, 0) + 1
276
+
277
+ # Merge MODERATE into MEDIUM for display
278
+ severity_counts["MEDIUM"] += severity_counts.pop("MODERATE", 0)
279
+
280
+ total = sum(severity_counts.values())
281
+ summary_rows = []
282
+ for sev in ["CRITICAL", "HIGH", "MEDIUM", "LOW"]:
283
+ if severity_counts.get(sev, 0) > 0:
284
+ summary_rows.append([sev, str(severity_counts[sev])])
285
+ summary_rows.append(["TOTAL", str(total)])
286
+ lines.extend(_table(["Severity", "Count"], summary_rows))
287
+ lines.append("")
288
+
289
+ if not all_findings:
290
+ lines.append("✓ No known vulnerabilities found.")
291
+ lines.append("")
292
+
293
+ # Findings by severity
294
+ if all_findings:
295
+ severity_order = {"CRITICAL": 0, "HIGH": 1, "MODERATE": 2, "MEDIUM": 2, "LOW": 3}
296
+ sorted_findings = sorted(all_findings, key=lambda f: severity_order.get(f["severity"].upper(), 9))
297
+
298
+ finding_rows = []
299
+ for f in sorted_findings:
300
+ sev = f["severity"].upper()
301
+ if sev == "MODERATE":
302
+ sev = "MEDIUM"
303
+ cve = f["cve"] if isinstance(f["cve"], str) else ", ".join(f["cve"]) if f["cve"] else "N/A"
304
+ title = f["title"][:60] + ("..." if len(f["title"]) > 60 else "")
305
+ finding_rows.append([sev, f["package"], cve, f["fixed_in"], title])
306
+
307
+ lines.extend(_table(["Severity", "Package", "CVE", "Fix", "Title"], finding_rows))
308
+ lines.append("")
309
+
310
+ # Detailed advisory links
311
+ lines.append("Advisory links:")
312
+ for f in sorted_findings:
313
+ if f.get("url"):
314
+ cve = f["cve"] if isinstance(f["cve"], str) else ", ".join(f["cve"]) if f["cve"] else "N/A"
315
+ lines.append(f" {cve}: {f['url']}")
316
+ lines.append("")
317
+
318
+ # Install hints for missing tools
319
+ missing = [e for e in ecosystems if not e["tool_available"]]
320
+ if missing:
321
+ lines.append("Missing tools:")
322
+ for eco in missing:
323
+ lines.append(f" {eco['name']}: install with: {eco['install_hint']}")
324
+ lines.append("")
325
+
326
+ # Warnings (non-fatal issues like missing lock files)
327
+ warnings = [r for r in results if r.get("warning")]
328
+ if warnings:
329
+ for r in warnings:
330
+ lines.append(f"⚠ {r['ecosystem']}: {r['warning']}")
331
+ lines.append("")
332
+
333
+ # Errors (fatal issues)
334
+ errors = [r for r in results if r.get("error")]
335
+ if errors:
336
+ for r in errors:
337
+ lines.append(f"✗ {r['ecosystem']}: {r['error']}")
338
+ lines.append("")
339
+
340
+ return "\n".join(lines)
341
+
342
+
343
+ def main():
344
+ import argparse
345
+
346
+ parser = argparse.ArgumentParser(description="CVE dependency scanner")
347
+ parser.add_argument("--json", action="store_true", help="JSON output")
348
+ parser.add_argument("--fix", action="store_true", help="Auto-fix vulnerabilities")
349
+ parser.add_argument("--ecosystem", type=str, help="Scan specific ecosystem only")
350
+ parser.add_argument("path", nargs="?", default=".", help="Project root path")
351
+ args = parser.parse_args()
352
+
353
+ root = Path(args.path).resolve()
354
+ if not root.is_dir():
355
+ print(f"Error: {root} is not a directory", file=sys.stderr)
356
+ sys.exit(1)
357
+
358
+ # Detect
359
+ ecosystems = detect_ecosystems(root)
360
+ if args.ecosystem:
361
+ ecosystems = [e for e in ecosystems if e["name"] == args.ecosystem]
362
+
363
+ if not ecosystems:
364
+ msg = "No supported package ecosystems detected."
365
+ if args.json:
366
+ print(json.dumps({"ecosystems": [], "findings": [], "message": msg}))
367
+ else:
368
+ print(msg)
369
+ sys.exit(0)
370
+
371
+ # Run audits
372
+ results = []
373
+ all_findings = []
374
+ for eco in ecosystems:
375
+ result = run_audit(eco, root, fix=args.fix)
376
+ results.append(result)
377
+
378
+ # Parse results with ecosystem-specific parsers
379
+ if result["success"] and result["raw_output"]:
380
+ parsers = {
381
+ "npm": parse_npm_audit,
382
+ "pip": parse_pip_audit,
383
+ "cargo": parse_cargo_audit,
384
+ }
385
+ parser = parsers.get(eco["name"])
386
+ if parser:
387
+ findings = parser(result["raw_output"])
388
+ for f in findings:
389
+ f["ecosystem"] = eco["name"]
390
+ all_findings.extend(findings)
391
+
392
+ # Output
393
+ if args.json:
394
+ output = {
395
+ "ecosystems": [{"name": e["name"], "files": e["files"], "tool_available": e["tool_available"]} for e in ecosystems],
396
+ "results": results,
397
+ "findings": all_findings,
398
+ "total_findings": len(all_findings),
399
+ }
400
+ print(json.dumps(output, indent=2))
401
+ else:
402
+ report = format_text_report(ecosystems, results, all_findings)
403
+ print(report)
404
+
405
+ # Exit code: non-zero if CRITICAL or HIGH found
406
+ high_or_critical = [f for f in all_findings if f["severity"].upper() in ("CRITICAL", "HIGH")]
407
+ if high_or_critical:
408
+ sys.exit(1)
409
+
410
+
411
+ if __name__ == "__main__":
412
+ main()
@@ -296,3 +296,13 @@ client.create_payload_index(
296
296
  | COSINE | Text embeddings | Yes |
297
297
  | EUCLID | Image embeddings | No |
298
298
  | DOT | When vectors pre-normalized | Yes |
299
+
300
+ ## Common Rationalizations
301
+
302
+ | Excuse | Why It's Wrong |
303
+ |--------|----------------|
304
+ | "We'll add indexes later when it's slow" | Missing indexes on production tables cause outages, not slowdowns — index from design |
305
+ | "The ORM handles performance" | ORMs generate queries, they don't optimize them — always check the query plan |
306
+ | "NoSQL is faster" | NoSQL trades consistency for speed — if you need joins, use a relational DB |
307
+ | "We don't need migrations, we'll update the schema directly" | Direct schema changes are irreversible and untestable — migrations are the safety net |
308
+ | "One big table is simpler" | Denormalization without measurement creates update anomalies — normalize first, denormalize with data |
@@ -144,6 +144,16 @@ Have them talk to each other to challenge each other's theories.
144
144
  Report consensus when done.
145
145
  ```
146
146
 
147
+ ## Common Rationalizations
148
+
149
+ | Excuse | Why It's Wrong |
150
+ |--------|----------------|
151
+ | "It works on my machine" | Environment differences are the #1 cause of production bugs — reproduce in prod-like env |
152
+ | "It must be a library bug" | 95% of the time it's your code — exhaust local hypotheses first |
153
+ | "I'll just add more logging and wait" | Passive debugging wastes hours — form a hypothesis and test it actively |
154
+ | "The error message says X, so it must be X" | Error messages often describe symptoms, not root causes — trace the full chain |
155
+ | "It only happens sometimes, probably a fluke" | Intermittent bugs are race conditions or state leaks — they get worse, not better |
156
+
147
157
  ## Debug Checklist
148
158
 
149
159
  - [ ] Identified error/symptom
@@ -152,3 +162,9 @@ Report consensus when done.
152
162
  - [ ] Reproduced issue
153
163
  - [ ] Formed hypothesis
154
164
  - [ ] Tested fix
165
+
166
+ ## Related Skills
167
+ - Bug fixed? → `/review` to verify the fix quality
168
+ - Need a regression test? → `/tdd` to write it test-first
169
+ - Performance issue? → `/analyze --type=complexity` for hotspot analysis
170
+ - Incident in production? → `/workflow incident-response` for full response
@@ -113,6 +113,16 @@ Proposed
113
113
  - [ ] Commit changes
114
114
  ```
115
115
 
116
+ ## Common Rationalizations
117
+
118
+ | Excuse | Why It's Wrong |
119
+ |--------|----------------|
120
+ | "The code is self-documenting" | Code shows how, not why — decisions, constraints, and context need prose |
121
+ | "Nobody reads docs anyway" | People don't read bad docs — good docs are the first thing consulted |
122
+ | "I'll document it when it's stable" | Unstable code needs docs most — document intent so others can contribute |
123
+ | "Comments get stale" | That's an argument for maintaining docs, not skipping them |
124
+ | "The tests are the documentation" | Tests verify behavior but don't explain architecture, trade-offs, or setup |
125
+
116
126
  ## Configuration
117
127
 
118
128
  Documentation settings in:
@@ -143,3 +153,9 @@ Create an agent team for documentation:
143
153
  - Teammate 3 (documenter): "Generate README sections: installation, usage, API reference." Use Opus.
144
154
  Teammates should NOT overlap — each owns their assigned scope.
145
155
  ```
156
+
157
+ ## Related Skills
158
+ - Documenting an architecture decision? → `/council` for multi-perspective analysis first
159
+ - Need to explore the codebase? → `/explore` to understand structure before documenting
160
+ - Writing a PRD? → `/write-a-prd` for structured product requirements
161
+ - Auditing existing docs? → `/analyze` for coverage gaps
@@ -68,3 +68,13 @@ git cherry-pick --continue
68
68
  - `perf:` Performance improvement
69
69
  - `test:` Adding missing tests
70
70
  - `chore:` Build process/auxiliary tools
71
+
72
+ ## Common Rationalizations
73
+
74
+ | Excuse | Why It's Wrong |
75
+ |--------|----------------|
76
+ | "I'll clean up commits later" | Later means never — write clean commits as you go |
77
+ | "Force push is fine on my branch" | Others may have fetched your branch — use --force-with-lease |
78
+ | "One big commit is simpler" | Big commits are impossible to review, bisect, or revert — keep them atomic |
79
+ | "Merge conflicts mean someone else's problem" | Conflicts mean you diverged too long — rebase frequently to stay aligned |
80
+ | "Commit messages don't matter" | Messages are documentation — future you needs to understand why, not just what |
@@ -17,6 +17,21 @@ Guide the user through setting up the ai-toolkit in their project, including con
17
17
 
18
18
  ## Setup Steps
19
19
 
20
+ ### Step 0: Intent Capture Interview
21
+
22
+ Before setting up tooling, understand the project's undocumented context. Ask the developer these questions (adapt based on what the codebase scan reveals):
23
+
24
+ 1. **What's the one thing a new contributor always gets wrong?** — This reveals the biggest documentation gap
25
+ 2. **Are there files or directories that should NOT be modified?** — Identifies protected areas (legacy, generated, vendor)
26
+ 3. **What's the deployment model?** — Monolith, microservices, serverless, edge — shapes which agents and skills are most relevant
27
+ 4. **Are there non-obvious constraints?** — Compliance requirements, performance budgets, browser support matrix
28
+ 5. **What's the team's review culture?** — Strict PR reviews, trunk-based, pair programming — configures `/review` behavior
29
+
30
+ Use answers to:
31
+ - Customize the generated `CLAUDE.md` with project-specific warnings and conventions
32
+ - Select the right `--profile` (minimal/standard/strict) automatically
33
+ - Pre-configure relevant language rules
34
+
20
35
  ### Step 1: Prerequisites Check
21
36
  - [ ] Claude Code CLI installed
22
37
  - [ ] ai-toolkit repository cloned
@@ -57,3 +57,13 @@ Always measure -> change -> measure.
57
57
  2. **Algorithm**: (O(n²) -> O(n log n))
58
58
  3. **Memory**: (Allocation churn, GC pressure)
59
59
  4. **Micro-optimization**: (Loop unrolling, etc.) - *Smallest Gains*
60
+
61
+ ## Common Rationalizations
62
+
63
+ | Excuse | Why It's Wrong |
64
+ |--------|----------------|
65
+ | "It feels slow, let me optimize this function" | Feelings aren't data — profile first, then optimize the actual bottleneck |
66
+ | "We should optimize everything" | Premature optimization is the root of all evil — focus on the critical path |
67
+ | "Caching will fix it" | Caching masks problems and adds complexity — fix the root cause first |
68
+ | "It's fast enough in dev" | Dev has 1 user — production has thousands and cold caches |
69
+ | "We'll optimize later" | Performance debt compounds — a 100ms regression per sprint = 5s in a year |
@@ -95,6 +95,16 @@ During planning:
95
95
  - NO code writing
96
96
  - NO file creation (except plan)
97
97
 
98
+ ## Common Rationalizations
99
+
100
+ | Excuse | Why It's Wrong |
101
+ |--------|----------------|
102
+ | "We already know what to build" | Assumed requirements lead to rework — validate assumptions explicitly |
103
+ | "Planning is wasted time, just start coding" | Unplanned work has 3-5x more rework — 30 min planning saves days |
104
+ | "The requirements will change anyway" | Plans adapt — without one, you can't assess impact of changes |
105
+ | "It's a small feature, no plan needed" | Small features in complex systems have hidden dependencies — map them |
106
+ | "We'll figure it out as we go" | Discovery without structure leads to scope creep and missed edge cases |
107
+
98
108
  ## Next Steps
99
109
 
100
110
  After plan approval:
@@ -108,3 +118,9 @@ Before planning:
108
118
  smart_query("project template: {type}")
109
119
  hybrid_search_kb("architecture {pattern}")
110
120
  ```
121
+
122
+ ## Related Skills
123
+ - Plan approved? → `/orchestrate` or `/workflow` to execute with agents
124
+ - Need requirements first? → `/write-a-prd` for structured product requirements
125
+ - Want to stress-test the plan? → `/grill-me` for Socratic questioning
126
+ - Ready to break into issues? → `/prd-to-plan` → `/triage-issue`
@@ -81,6 +81,16 @@ Before executing:
81
81
  - [ ] Tests passing
82
82
  - [ ] Backup created
83
83
 
84
+ ## Common Rationalizations
85
+
86
+ | Excuse | Why It's Wrong |
87
+ |--------|----------------|
88
+ | "It works, don't touch it" | Working code that's hard to maintain slows every future change |
89
+ | "We'll refactor it later" | Later never comes — refactor when the pain is fresh and context is loaded |
90
+ | "It's too risky to change" | That's exactly why it needs refactoring — risk compounds with complexity |
91
+ | "Just one more hack won't hurt" | Each hack makes the next one easier to justify — break the cycle now |
92
+ | "We need to rewrite from scratch" | Incremental refactoring is safer and delivers value continuously |
93
+
84
94
  ## READ BEFORE WRITE
85
95
 
86
96
  This command analyzes and plans first.
@@ -122,3 +132,9 @@ Create an agent team for refactoring:
122
132
  - Teammate 2 (backend-specialist): "Implement the refactoring changes identified by the reviewer." Use Opus.
123
133
  Teammate 1 completes first, then Teammate 2 acts on the plan.
124
134
  ```
135
+
136
+ ## Related Skills
137
+ - Need a safe refactor plan? → `/refactor-plan` for incremental steps as GitHub RFC
138
+ - Want to validate architecture? → `/analyze` for code quality metrics
139
+ - Need tests before refactoring? → `/tdd` to build safety net first
140
+ - Architecture decision needed? → `/council` for multi-perspective evaluation
@@ -117,17 +117,40 @@ After all reviewers complete:
117
117
  - **Lines Added**: [+count]
118
118
  - **Lines Removed**: [-count]
119
119
  - **Issues Found**: [count]
120
+ - **Overall Confidence**: [1-10] — how confident the reviewer is in the assessment
120
121
 
121
122
  ### Findings
122
123
 
123
124
  #### Critical
124
125
  - **[file:line]**: [issue]
125
- - [explanation]
126
+ - Severity: critical | Confidence: [1-10]
127
+ - Evidence: [specific code reference and reasoning]
126
128
  - Suggested fix: [code]
127
129
 
128
- #### Suggestions
130
+ #### Major
131
+ - **[file:line]**: [issue]
132
+ - Severity: major | Confidence: [1-10]
133
+ - Evidence: [specific code reference and reasoning]
134
+ - Suggested fix: [code]
135
+
136
+ #### Minor
137
+ - **[file:line]**: [issue]
138
+ - Severity: minor | Confidence: [1-10]
139
+ - Evidence: [line number + reasoning]
140
+
141
+ #### Nit
129
142
  - **[file:line]**: [suggestion]
130
- - [explanation]
143
+ - Severity: nit | Confidence: [1-10]
144
+
145
+ ### Confidence Guide
146
+
147
+ | Score | Meaning |
148
+ |-------|---------|
149
+ | 9-10 | Certain — verified via code, tests, or documentation |
150
+ | 7-8 | High — strong evidence, minor assumptions |
151
+ | 5-6 | Medium — plausible issue, needs author confirmation |
152
+ | 3-4 | Low — speculative, based on patterns not proof |
153
+ | 1-2 | Guess — flag for discussion, don't block on this |
131
154
 
132
155
  ### Positive Notes
133
156
  - [What's good about the code]
@@ -136,6 +159,38 @@ After all reviewers complete:
136
159
  [APPROVE / REQUEST_CHANGES / NEEDS_DISCUSSION]
137
160
  ```
138
161
 
162
+ ## Common Rationalizations
163
+
164
+ | Excuse | Why It's Wrong |
165
+ |--------|----------------|
166
+ | "Small change, quick scan is enough" | Small changes introduce subtle bugs — apply consistent review regardless of size |
167
+ | "Tests pass, so the code is correct" | Tests validate specific scenarios, not all behaviors — verify missing coverage |
168
+ | "It's just a refactor, no need for deep review" | Refactors change invariants — verify behavior preservation, not just compilation |
169
+ | "The author is senior, they know what they're doing" | Seniority doesn't prevent mistakes — review the code, not the person |
170
+ | "We're in a hurry, ship it" | Rushed reviews create tech debt that costs 10x more to fix later |
171
+
172
+ ## Self-Evaluation (LLM-as-Judge)
173
+
174
+ After completing the review, perform a self-evaluation pass:
175
+
176
+ ### Check for Blind Spots
177
+ 1. **Did I verify, or assume?** — For each finding, confirm you read the actual code (not inferred from context)
178
+ 2. **Did I miss the inverse?** — If you flagged X as a problem, did you check if NOT doing X is also a problem elsewhere?
179
+ 3. **Did I anchor on the first issue?** — Review whether early findings biased you toward similar patterns, missing different issue classes
180
+ 4. **Did I check the unhappy path?** — Error handling, edge cases, failure modes — not just the golden path
181
+ 5. **Did I flag uncertainty?** — Findings with confidence < 6 should be clearly marked as "needs author input"
182
+
183
+ ### Calibrate Confidence
184
+ - If all findings are confidence 7+, you may be overconfident — re-examine the weakest finding
185
+ - If any finding lacks a file:line reference, downgrade it or remove it
186
+ - If you found zero issues, state what you specifically checked (not "looks good")
187
+
139
188
  ## READ-ONLY
140
189
 
141
190
  This skill only analyzes. It does NOT modify any files.
191
+
192
+ ## Related Skills
193
+ - Issues found? → `/debug` to trace root causes
194
+ - Missing tests? → `/tdd` to add test-first coverage
195
+ - Security findings? → `/cve-scan` for dependency vulnerabilities
196
+ - Architecture concerns? → `/analyze` for deeper code quality metrics