@tyroneross/build-loop 0.30.3

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 (389) hide show
  1. package/.agents/plugins/marketplace.json +10 -0
  2. package/.claude-plugin/marketplace.json +38 -0
  3. package/.claude-plugin/plugin.json +30 -0
  4. package/.codex-plugin/plugin.json +41 -0
  5. package/.cursor/rules/build-loop-surface.mdc +22 -0
  6. package/AGENTS.md +498 -0
  7. package/LICENSE +202 -0
  8. package/README.md +403 -0
  9. package/agents/alignment-checker.md +124 -0
  10. package/agents/api-assessor.md +136 -0
  11. package/agents/architecture-scout.md +185 -0
  12. package/agents/assessment-orchestrator.md +163 -0
  13. package/agents/build-orchestrator.md +198 -0
  14. package/agents/database-assessor.md +133 -0
  15. package/agents/design-contract-specialist.md +239 -0
  16. package/agents/fact-checker.md +69 -0
  17. package/agents/fix-critique.md +161 -0
  18. package/agents/frontend-assessor.md +136 -0
  19. package/agents/implementer.md +185 -0
  20. package/agents/independent-auditor.md +143 -0
  21. package/agents/mock-scanner.md +78 -0
  22. package/agents/optimize-runner.md +112 -0
  23. package/agents/overfitting-reviewer.md +96 -0
  24. package/agents/performance-assessor.md +159 -0
  25. package/agents/plan-critic.md +85 -0
  26. package/agents/promotion-reviewer.md +121 -0
  27. package/agents/recurring-pattern-detector.md +248 -0
  28. package/agents/retrospective-synthesizer.md +109 -0
  29. package/agents/root-cause-investigator.md +285 -0
  30. package/agents/scope-auditor.md +121 -0
  31. package/agents/security-reviewer.md +151 -0
  32. package/agents/self-improvement-architect.md +125 -0
  33. package/agents/synthesis-critic.md +99 -0
  34. package/agents/transcript-pattern-miner.md +165 -0
  35. package/agents/ui-validator.md +193 -0
  36. package/codex-skills/build-loop/SKILL.md +20 -0
  37. package/codex-skills/debug-loop/SKILL.md +18 -0
  38. package/codex-skills/handoff/SKILL.md +22 -0
  39. package/codex-skills/knowledge/SKILL.md +21 -0
  40. package/codex-skills/optimize/SKILL.md +18 -0
  41. package/codex-skills/research/SKILL.md +18 -0
  42. package/commands/agent-rally-point.md +301 -0
  43. package/commands/assess.md +41 -0
  44. package/commands/debug.md +20 -0
  45. package/commands/debugger-detail.md +34 -0
  46. package/commands/debugger-scan.md +15 -0
  47. package/commands/debugger-status.md +20 -0
  48. package/commands/debugger.md +32 -0
  49. package/commands/handoff.md +113 -0
  50. package/commands/knowledge-review.md +16 -0
  51. package/commands/optimize.md +31 -0
  52. package/commands/plan-verify.md +39 -0
  53. package/commands/promote-experiment.md +129 -0
  54. package/commands/research.md +22 -0
  55. package/commands/run.md +12 -0
  56. package/commands/self-review.md +51 -0
  57. package/commands/start-prd.md +57 -0
  58. package/commands/test.md +34 -0
  59. package/dist/src/assessment-orchestrator.d.ts +78 -0
  60. package/dist/src/assessment-orchestrator.d.ts.map +1 -0
  61. package/dist/src/assessment-orchestrator.js +304 -0
  62. package/dist/src/assessment-orchestrator.js.map +1 -0
  63. package/dist/src/audit-miner.d.ts +21 -0
  64. package/dist/src/audit-miner.d.ts.map +1 -0
  65. package/dist/src/audit-miner.js +421 -0
  66. package/dist/src/audit-miner.js.map +1 -0
  67. package/dist/src/batch-operations.d.ts +30 -0
  68. package/dist/src/batch-operations.d.ts.map +1 -0
  69. package/dist/src/batch-operations.js +339 -0
  70. package/dist/src/batch-operations.js.map +1 -0
  71. package/dist/src/config.d.ts +83 -0
  72. package/dist/src/config.d.ts.map +1 -0
  73. package/dist/src/config.js +176 -0
  74. package/dist/src/config.js.map +1 -0
  75. package/dist/src/context-engine.d.ts +45 -0
  76. package/dist/src/context-engine.d.ts.map +1 -0
  77. package/dist/src/context-engine.js +135 -0
  78. package/dist/src/context-engine.js.map +1 -0
  79. package/dist/src/debug-wrapper.d.ts +58 -0
  80. package/dist/src/debug-wrapper.d.ts.map +1 -0
  81. package/dist/src/debug-wrapper.js +285 -0
  82. package/dist/src/debug-wrapper.js.map +1 -0
  83. package/dist/src/index.d.ts +31 -0
  84. package/dist/src/index.d.ts.map +1 -0
  85. package/dist/src/index.js +149 -0
  86. package/dist/src/index.js.map +1 -0
  87. package/dist/src/interactive-verifier.d.ts +26 -0
  88. package/dist/src/interactive-verifier.d.ts.map +1 -0
  89. package/dist/src/interactive-verifier.js +435 -0
  90. package/dist/src/interactive-verifier.js.map +1 -0
  91. package/dist/src/lessons.d.ts +59 -0
  92. package/dist/src/lessons.d.ts.map +1 -0
  93. package/dist/src/lessons.js +172 -0
  94. package/dist/src/lessons.js.map +1 -0
  95. package/dist/src/log-reader.d.ts +39 -0
  96. package/dist/src/log-reader.d.ts.map +1 -0
  97. package/dist/src/log-reader.js +291 -0
  98. package/dist/src/log-reader.js.map +1 -0
  99. package/dist/src/logger.d.ts +59 -0
  100. package/dist/src/logger.d.ts.map +1 -0
  101. package/dist/src/logger.js +328 -0
  102. package/dist/src/logger.js.map +1 -0
  103. package/dist/src/parallel-retrieval.d.ts +52 -0
  104. package/dist/src/parallel-retrieval.d.ts.map +1 -0
  105. package/dist/src/parallel-retrieval.js +309 -0
  106. package/dist/src/parallel-retrieval.js.map +1 -0
  107. package/dist/src/pattern-extractor.d.ts +30 -0
  108. package/dist/src/pattern-extractor.d.ts.map +1 -0
  109. package/dist/src/pattern-extractor.js +386 -0
  110. package/dist/src/pattern-extractor.js.map +1 -0
  111. package/dist/src/result-aggregator.d.ts +44 -0
  112. package/dist/src/result-aggregator.d.ts.map +1 -0
  113. package/dist/src/result-aggregator.js +315 -0
  114. package/dist/src/result-aggregator.js.map +1 -0
  115. package/dist/src/retrieval.d.ts +139 -0
  116. package/dist/src/retrieval.d.ts.map +1 -0
  117. package/dist/src/retrieval.js +724 -0
  118. package/dist/src/retrieval.js.map +1 -0
  119. package/dist/src/setup/auto-setup.d.ts +15 -0
  120. package/dist/src/setup/auto-setup.d.ts.map +1 -0
  121. package/dist/src/setup/auto-setup.js +157 -0
  122. package/dist/src/setup/auto-setup.js.map +1 -0
  123. package/dist/src/setup/configure-hooks.d.ts +8 -0
  124. package/dist/src/setup/configure-hooks.d.ts.map +1 -0
  125. package/dist/src/setup/configure-hooks.js +16 -0
  126. package/dist/src/setup/configure-hooks.js.map +1 -0
  127. package/dist/src/setup/create-slash-commands.d.ts +8 -0
  128. package/dist/src/setup/create-slash-commands.d.ts.map +1 -0
  129. package/dist/src/setup/create-slash-commands.js +101 -0
  130. package/dist/src/setup/create-slash-commands.js.map +1 -0
  131. package/dist/src/setup/index.d.ts +8 -0
  132. package/dist/src/setup/index.d.ts.map +1 -0
  133. package/dist/src/setup/index.js +17 -0
  134. package/dist/src/setup/index.js.map +1 -0
  135. package/dist/src/setup/inject-claude-md.d.ts +10 -0
  136. package/dist/src/setup/inject-claude-md.d.ts.map +1 -0
  137. package/dist/src/setup/inject-claude-md.js +150 -0
  138. package/dist/src/setup/inject-claude-md.js.map +1 -0
  139. package/dist/src/setup/uninstall.d.ts +22 -0
  140. package/dist/src/setup/uninstall.d.ts.map +1 -0
  141. package/dist/src/setup/uninstall.js +235 -0
  142. package/dist/src/setup/uninstall.js.map +1 -0
  143. package/dist/src/storage.d.ts +192 -0
  144. package/dist/src/storage.d.ts.map +1 -0
  145. package/dist/src/storage.js +1037 -0
  146. package/dist/src/storage.js.map +1 -0
  147. package/dist/src/string-similarity.d.ts +8 -0
  148. package/dist/src/string-similarity.d.ts.map +1 -0
  149. package/dist/src/string-similarity.js +57 -0
  150. package/dist/src/string-similarity.js.map +1 -0
  151. package/dist/src/traces/adapters/browser.d.ts +69 -0
  152. package/dist/src/traces/adapters/browser.d.ts.map +1 -0
  153. package/dist/src/traces/adapters/browser.js +280 -0
  154. package/dist/src/traces/adapters/browser.js.map +1 -0
  155. package/dist/src/traces/adapters/index.d.ts +23 -0
  156. package/dist/src/traces/adapters/index.d.ts.map +1 -0
  157. package/dist/src/traces/adapters/index.js +67 -0
  158. package/dist/src/traces/adapters/index.js.map +1 -0
  159. package/dist/src/traces/adapters/langchain.d.ts +42 -0
  160. package/dist/src/traces/adapters/langchain.d.ts.map +1 -0
  161. package/dist/src/traces/adapters/langchain.js +151 -0
  162. package/dist/src/traces/adapters/langchain.js.map +1 -0
  163. package/dist/src/traces/adapters/opentelemetry.d.ts +46 -0
  164. package/dist/src/traces/adapters/opentelemetry.d.ts.map +1 -0
  165. package/dist/src/traces/adapters/opentelemetry.js +164 -0
  166. package/dist/src/traces/adapters/opentelemetry.js.map +1 -0
  167. package/dist/src/traces/adapters/sentry.d.ts +58 -0
  168. package/dist/src/traces/adapters/sentry.d.ts.map +1 -0
  169. package/dist/src/traces/adapters/sentry.js +212 -0
  170. package/dist/src/traces/adapters/sentry.js.map +1 -0
  171. package/dist/src/traces/index.d.ts +10 -0
  172. package/dist/src/traces/index.d.ts.map +1 -0
  173. package/dist/src/traces/index.js +45 -0
  174. package/dist/src/traces/index.js.map +1 -0
  175. package/dist/src/traces/storage.d.ts +78 -0
  176. package/dist/src/traces/storage.d.ts.map +1 -0
  177. package/dist/src/traces/storage.js +399 -0
  178. package/dist/src/traces/storage.js.map +1 -0
  179. package/dist/src/traces/summarizer.d.ts +83 -0
  180. package/dist/src/traces/summarizer.d.ts.map +1 -0
  181. package/dist/src/traces/summarizer.js +247 -0
  182. package/dist/src/traces/summarizer.js.map +1 -0
  183. package/dist/src/traces/types.d.ts +365 -0
  184. package/dist/src/traces/types.d.ts.map +1 -0
  185. package/dist/src/traces/types.js +14 -0
  186. package/dist/src/traces/types.js.map +1 -0
  187. package/dist/src/types.d.ts +495 -0
  188. package/dist/src/types.d.ts.map +1 -0
  189. package/dist/src/types.js +27 -0
  190. package/dist/src/types.js.map +1 -0
  191. package/docs/agent-surface-policy.md +45 -0
  192. package/docs/memory-setup.md +226 -0
  193. package/hooks/_arch_scan_bg.py +88 -0
  194. package/hooks/_plugin_drift_check_bg.py +85 -0
  195. package/hooks/_session_start_lib.sh +42 -0
  196. package/hooks/git/pre-push +141 -0
  197. package/hooks/hooks.json +126 -0
  198. package/hooks/post-commit +30 -0
  199. package/hooks/pre-commit +29 -0
  200. package/hooks/pre-edit-apppulse.sh +6 -0
  201. package/hooks/pre-edit-architecture.sh +106 -0
  202. package/hooks/pre-edit-rally-point.sh +92 -0
  203. package/hooks/session-start-apppulse.sh +6 -0
  204. package/hooks/session-start-architecture.sh +10 -0
  205. package/hooks/session-start-git-hooks.sh +12 -0
  206. package/hooks/session-start-plugin-drift.sh +27 -0
  207. package/hooks/session-start-rally-point.sh +44 -0
  208. package/hooks/session-start-retrieval.sh +24 -0
  209. package/hooks/session-start-worktree-gc.sh +105 -0
  210. package/hooks/test_apppulse_hooks.sh +6 -0
  211. package/hooks/test_rally_point_hooks.sh +388 -0
  212. package/hooks/test_sec008_hooks.sh +66 -0
  213. package/package.json +111 -0
  214. package/scripts/README.md +301 -0
  215. package/scripts/_db_url.py +61 -0
  216. package/scripts/_paths.py +445 -0
  217. package/scripts/blm.py +162 -0
  218. package/scripts/blm_api.py +263 -0
  219. package/scripts/check_cache_sync.py +490 -0
  220. package/scripts/embed_backend.py +475 -0
  221. package/scripts/install_memory.py +556 -0
  222. package/scripts/lessons_index/__init__.py +77 -0
  223. package/scripts/lessons_index/__main__.py +135 -0
  224. package/scripts/lessons_index/ingest.py +288 -0
  225. package/scripts/lessons_index/query.py +285 -0
  226. package/scripts/lessons_index/schema.py +114 -0
  227. package/scripts/memory_context/__init__.py +610 -0
  228. package/scripts/memory_graph/__init__.py +393 -0
  229. package/scripts/project_resolver.py +172 -0
  230. package/scripts/prune_codex_plugin_cache.py +23 -0
  231. package/scripts/prune_plugin_cache.py +359 -0
  232. package/scripts/semantic_index/__init__.py +482 -0
  233. package/scripts/semantic_index/_bench_hybrid.py +175 -0
  234. package/scripts/semantic_index/backfill.py +263 -0
  235. package/scripts/semantic_index/hybrid.py +174 -0
  236. package/scripts/semantic_index/test_backfill.py +292 -0
  237. package/scripts/semantic_index/test_hybrid.py +541 -0
  238. package/scripts/sync_navgator_lessons.py +666 -0
  239. package/scripts/sync_plugin_cache.py +388 -0
  240. package/skills/agent-rally-point/SKILL.md +165 -0
  241. package/skills/agent-rally-watcher/SKILL.md +83 -0
  242. package/skills/api-registry-bridge/SKILL.md +59 -0
  243. package/skills/architecture/dead/SKILL.md +56 -0
  244. package/skills/architecture/impact/SKILL.md +88 -0
  245. package/skills/architecture/review/SKILL.md +227 -0
  246. package/skills/architecture/rules/SKILL.md +72 -0
  247. package/skills/architecture/scan/SKILL.md +79 -0
  248. package/skills/architecture/trace/SKILL.md +65 -0
  249. package/skills/attribution-standard/SKILL.md +122 -0
  250. package/skills/authentication/SKILL.md +81 -0
  251. package/skills/authentication/references/better-auth-magic-link.md +135 -0
  252. package/skills/authentication/references/better-auth-setup.md +224 -0
  253. package/skills/authentication/references/google-calendar-sync.md +278 -0
  254. package/skills/authentication/references/google-cloud-console.md +159 -0
  255. package/skills/authentication/references/google-geocoding-directions.md +126 -0
  256. package/skills/authentication/references/google-lessons-example-web-app.md +177 -0
  257. package/skills/authentication/references/google-maps.md +162 -0
  258. package/skills/authentication/references/google-oauth-setup.md +343 -0
  259. package/skills/authentication/references/google-places.md +173 -0
  260. package/skills/authentication/references/lessons-example-web-app-better-auth.md +126 -0
  261. package/skills/authentication/references/resend-email.md +227 -0
  262. package/skills/authentication/references/resend-otp-magic-link.md +153 -0
  263. package/skills/authentication/references/supabase-auth.md +172 -0
  264. package/skills/auto-decision-capture/SKILL.md +419 -0
  265. package/skills/build-loop/SKILL.md +516 -0
  266. package/skills/build-loop/detect-plugins.mjs +82 -0
  267. package/skills/build-loop/eval-guide.md +65 -0
  268. package/skills/build-loop/fallbacks.md +549 -0
  269. package/skills/build-loop/phases/fact-check.md +42 -0
  270. package/skills/build-loop/phases/ui-validation.md +267 -0
  271. package/skills/build-loop/references/apple-native-planning.md +439 -0
  272. package/skills/build-loop/references/capability-routing.md +181 -0
  273. package/skills/build-loop/references/codex-subagents.md +98 -0
  274. package/skills/build-loop/references/coordination.md +161 -0
  275. package/skills/build-loop/references/correction-aware-capture.md +177 -0
  276. package/skills/build-loop/references/independent-auditor.md +72 -0
  277. package/skills/build-loop/references/intent-capability-pack.md +170 -0
  278. package/skills/build-loop/references/intent-exploration-prompts.md +96 -0
  279. package/skills/build-loop/references/leadership.md +72 -0
  280. package/skills/build-loop/references/memory.md +284 -0
  281. package/skills/build-loop/references/modular-systems-pack.md +96 -0
  282. package/skills/build-loop/references/output-style.md +129 -0
  283. package/skills/build-loop/references/pay-it-forward-arch.md +98 -0
  284. package/skills/build-loop/references/phase-1-assess.md +218 -0
  285. package/skills/build-loop/references/phase-2-plan.md +77 -0
  286. package/skills/build-loop/references/phase-3-execute.md +47 -0
  287. package/skills/build-loop/references/phase-4-review.md +310 -0
  288. package/skills/build-loop/references/phase-5-iterate.md +71 -0
  289. package/skills/build-loop/references/phase-6-learn.md +56 -0
  290. package/skills/build-loop/references/recent-design-structures.md +274 -0
  291. package/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
  292. package/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
  293. package/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
  294. package/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
  295. package/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
  296. package/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
  297. package/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
  298. package/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
  299. package/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
  300. package/skills/build-loop/references/self-recursive-dev.md +77 -0
  301. package/skills/build-loop/references/self-review.md +232 -0
  302. package/skills/build-loop/references/ui-io-contract.md +116 -0
  303. package/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
  304. package/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
  305. package/skills/build-loop/templates/backlog-item.md +35 -0
  306. package/skills/build-loop/templates/codex-worker-prompt.md +89 -0
  307. package/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
  308. package/skills/build-loop/templates/ux-fix-plan.md +40 -0
  309. package/skills/building-with-deepagents/SKILL.md +195 -0
  310. package/skills/building-with-deepagents/references/anti-patterns.md +141 -0
  311. package/skills/building-with-deepagents/references/api-quick-reference.md +184 -0
  312. package/skills/capabilities/SKILL.md +91 -0
  313. package/skills/debug-loop/SKILL.md +278 -0
  314. package/skills/debug-loop/references/convergence-rules.md +145 -0
  315. package/skills/debug-loop/references/swiftui-macos-clunky-ui-debugger.html +823 -0
  316. package/skills/debugging/assess/SKILL.md +111 -0
  317. package/skills/debugging/debug-loop/SKILL.md +231 -0
  318. package/skills/debugging/memory/SKILL.md +147 -0
  319. package/skills/debugging/store/SKILL.md +153 -0
  320. package/skills/debugging-memory/SKILL.md +440 -0
  321. package/skills/debugging-memory/examples/incident-example.json +67 -0
  322. package/skills/debugging-memory/references/incident-documentation.md +280 -0
  323. package/skills/debugging-memory/references/ios-notification-alarm-playbook.md +300 -0
  324. package/skills/debugging-memory/references/pattern-extraction.md +163 -0
  325. package/skills/debugging-memory/references/subagent-integration.md +312 -0
  326. package/skills/defenseclaw-bridge/SKILL.md +156 -0
  327. package/skills/defenseclaw-bridge/references/dc-config-mapping.md +162 -0
  328. package/skills/defenseclaw-bridge/references/output-format.md +108 -0
  329. package/skills/handoff/SKILL.md +94 -0
  330. package/skills/ibr-bridge/SKILL.md +68 -0
  331. package/skills/knowledge/SKILL.md +127 -0
  332. package/skills/knowledge/references/recall-integration.md +83 -0
  333. package/skills/knowledge/templates/madr-minimal.md +56 -0
  334. package/skills/knowledge-review/SKILL.md +112 -0
  335. package/skills/logging-tracer/SKILL.md +202 -0
  336. package/skills/logging-tracer/references/log-analysis.md +128 -0
  337. package/skills/logging-tracer/references/stack-templates.md +274 -0
  338. package/skills/logging-tracer-bridge/SKILL.md +70 -0
  339. package/skills/mcp-builder/SKILL.md +278 -0
  340. package/skills/mcp-builder/references/mcp-security.md +106 -0
  341. package/skills/model-tiering/SKILL.md +216 -0
  342. package/skills/native-ax-driver/SKILL.md +220 -0
  343. package/skills/native-ax-driver/scripts/layout_fill.py +222 -0
  344. package/skills/native-ax-driver/scripts/native_driver.py +495 -0
  345. package/skills/native-ax-driver/swift/bl-ax-driver/Package.swift +20 -0
  346. package/skills/native-ax-driver/swift/bl-ax-driver/Sources/main.swift +542 -0
  347. package/skills/optimize/SKILL.md +202 -0
  348. package/skills/optimize/profiles.md +61 -0
  349. package/skills/plan-verify/SKILL.md +115 -0
  350. package/skills/plan-verify/test-fixtures/example-app-v20-findings.json +27 -0
  351. package/skills/plan-verify/test-fixtures/example-app-v20.md +42 -0
  352. package/skills/plan-verify/test-fixtures/example-app-v22-findings.json +15 -0
  353. package/skills/plan-verify/test-fixtures/example-app-v22.md +1608 -0
  354. package/skills/plan-verify/test-fixtures/unrelated-good-plan-findings.json +15 -0
  355. package/skills/plan-verify/test-fixtures/unrelated-good-plan.md +55 -0
  356. package/skills/plugin-builder/SKILL.md +329 -0
  357. package/skills/plugin-builder/references/authoritative-sources.md +104 -0
  358. package/skills/plugin-builder/references/build-loop-phase-guidance.md +94 -0
  359. package/skills/plugin-builder/references/components-guide.md +221 -0
  360. package/skills/plugin-builder/references/distribution.md +317 -0
  361. package/skills/plugin-builder/references/dual-host-claude-codex.md +220 -0
  362. package/skills/plugin-builder/references/hooks-reference.md +210 -0
  363. package/skills/plugin-builder/references/manifest-schema.md +111 -0
  364. package/skills/plugin-builder/references/plugin-hygiene-lessons.md +307 -0
  365. package/skills/plugin-tests/SKILL.md +94 -0
  366. package/skills/prd-bridge/SKILL.md +135 -0
  367. package/skills/research/SKILL.md +80 -0
  368. package/skills/security-methodology/SKILL.md +105 -0
  369. package/skills/security-methodology/references/cross-source-matrix.md +77 -0
  370. package/skills/security-methodology/references/mitre-atlas-starter.md +83 -0
  371. package/skills/security-methodology/references/nist-600-1-mapping.md +119 -0
  372. package/skills/security-methodology/references/owasp-agentic-top-10.md +157 -0
  373. package/skills/security-methodology/references/owasp-llm-top-10.md +144 -0
  374. package/skills/security-methodology/references/owasp-web-top-10.md +65 -0
  375. package/skills/self-improve/SKILL.md +298 -0
  376. package/skills/spec-writing/SKILL.md +548 -0
  377. package/skills/spec-writing/scripts/check_checklist.py +478 -0
  378. package/skills/sync-skills/SKILL.md +132 -0
  379. package/skills/telemetry/SKILL.md +66 -0
  380. package/skills/ui-design/SKILL.md +75 -0
  381. package/skills/ui-design/references/design-patterns-multi.md +165 -0
  382. package/skills/ui-design/references/design-preferences-from-owned-apps.md +150 -0
  383. package/skills/ui-design/references/evidence-capture-policy.md +55 -0
  384. package/skills/ui-design/references/ui-guidance-sources.md +330 -0
  385. package/skills/ui-design/references/universal-design-principles.alt.md +182 -0
  386. package/skills/ui-design/references/universal-design-principles.md +419 -0
  387. package/templates/memory/MEMORY.md.template +55 -0
  388. package/templates/memory/constitution.md.template +64 -0
  389. package/templates/memory/manifest.json +47 -0
@@ -0,0 +1,307 @@
1
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
2
+
3
+ # Plugin Hygiene — Lessons Learned
4
+
5
+ Real-world incidents from building and maintaining the `rosslabs-ai-toolkit` marketplace. Each lesson names the specific failure mode and the rule that prevents recurrence.
6
+
7
+ ## 1. Duplicate hook declarations produce `/doctor` errors
8
+
9
+ **What happened.** Four plugins (research, spectra, showcase, replit-migrate) declared `"hooks": "./hooks/hooks.json"` in `plugin.json`. Claude Code auto-loads `hooks/hooks.json` by convention, so the explicit declaration registered the file twice, producing:
10
+
11
+ > Hook load failed: Duplicate hooks file detected: ./hooks/hooks.json resolves to already-loaded file …
12
+
13
+ **Rule.** Only declare `hooks` in the manifest when the file is at a non-standard path. Same for `mcpServers` (`.mcp.json` auto-loads) and `lsp` (`.lsp.json` auto-loads). Explicit declarations *supplement* auto-discovery, they do not replace it — declaring a default-path file guarantees duplication.
14
+
15
+ ## 2. `type: "prompt"` on `PostToolUse:Bash` is always wrong
16
+
17
+ **What happened.** `showcase` plugin shipped a PostToolUse:Bash hook with `type: "prompt"` intended to suggest `/showcase:capture` after successful builds. In practice, Claude Code evaluated the prompt after every bash command — `ls`, `grep`, `cat` — producing a stream of "PostToolUse:Bash hook stopped continuation" messages tied to the negative condition ("this isn't a build so don't mention capture"). The user perceived it as aggressive blocking.
18
+
19
+ **Rule.** `PostToolUse:Bash` fires on every shell command. A `type: "prompt"` hook there turns every command into an LLM evaluation step — expensive in tokens, disruptive in UX. Use `type: "command"` with silent `exit 0` for conditional reminders, or move the reminder to `SessionStart` where it fires once per session. Reserve `type: "prompt"` for truly low-frequency events.
20
+
21
+ Applies equally to: `UserPromptSubmit`, `PreToolUse:Bash`, any matcher that fires per-turn.
22
+
23
+ ## 3. Marketplace renames leave install records behind forever
24
+
25
+ **What happened.** The marketplace `RossLabs-claude-plugins` was renamed to `rosslabs-ai-toolkit` (kebab-case is required by Claude Code's marketplace schema, 2026-04-20). Plugins previously installed from the old name kept their install records in `~/.claude/plugins/installed_plugins.json` pointing at cache paths under `RossLabs-claude-plugins/` that no longer received updates. The resulting state:
26
+ - Same plugin, two install keys (old + new)
27
+ - Stop hooks from the old install pointing at paths like `/Users/.../claude-code-debugger/claude-code-debugger/1.8.0` that didn't exist
28
+ - `/plugin` UI showed both as "installed"
29
+
30
+ **Rule.** Renaming a marketplace is a full migration, not a metadata change. Checklist:
31
+ 1. `/plugin` → uninstall every plugin from the old marketplace name
32
+ 2. Remove the old marketplace from `extraKnownMarketplaces` in `settings.json`
33
+ 3. Re-add the new marketplace
34
+ 4. Reinstall each plugin from the new name
35
+ 5. Audit `installed_plugins.json` for any remaining old-name keys — remove them only if the uninstall didn't
36
+
37
+ Document the rename in a feedback memory so future sessions handle it correctly.
38
+
39
+ ## 4. `@local` and `@marketplace` for the same plugin is a footgun
40
+
41
+ **What happened.** Local development on `bookmark`, `showcase`, `mockup-gallery`, and `NavGator` registered each as `@local` directory installs. The same plugins also existed in the `rosslabs-ai-toolkit` marketplace. Both installs stayed "enabled" simultaneously — both MCP servers started, duplicate slash commands registered, hooks fired twice. The Installed view showed "bookmark MCP · failed" twice, one per copy.
42
+
43
+ **Rule.** Pick one at a time. When iterating on source, disable the marketplace install. When consuming normally, disable the `@local`. The `enabledPlugins` map in `settings.json` is the source of truth — set the non-active source to `false`.
44
+
45
+ Better: use `EnterWorktree` or a separate test project directory for plugin development, so the live user environment is not polluted with dev installs.
46
+
47
+ ## 5. Cache directories are downstream; commit source before expecting changes to persist
48
+
49
+ **What happened.** Editing hook files under `~/.claude/plugins/cache/rosslabs-ai-toolkit/showcase/0.1.1/hooks/hooks.json` took effect immediately, but the next marketplace sync (pulling the GitHub repo) overwrote the edit with the repo's original file. Hours of debugging lost to the illusion of a persistent fix.
50
+
51
+ **Rule.** Cache is regenerated from the marketplace's upstream repo. Always edit the source (`~/Desktop/git-folder/RossLabs-AI-Toolkit/plugins/<plugin>/…`), commit, push. If you need an immediate fix in the current session, edit both the source and the cache — the cache copy keeps the session alive until you push, then the next sync reconciles.
52
+
53
+ The marketplace repo is the source of truth. Nothing under `~/.claude/plugins/cache/` is authored — it's all generated.
54
+
55
+ ## 5a. The reverse trap: source-only edits don't take effect at runtime
56
+
57
+ **What happened (2026-04-22, build-loop).** Edited `~/Desktop/git-folder/build-loop/scripts/write_run_entry.py` in the source repo and updated the orchestrator prose to invoke `${CLAUDE_PLUGIN_ROOT}/scripts/write_run_entry.py`. Tests passed. Claimed success. The orchestrator never saw the new script because `${CLAUDE_PLUGIN_ROOT}` resolves to `~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/` — a frozen snapshot that only updates on marketplace sync. Source-only edit = runtime silently runs the old version (or in this case, returns "file not found" and the orchestrator falls back to hand-writing JSON, if it remembers to).
58
+
59
+ **Rule.** The full sync cycle is **source → commit → push → marketplace sync → cache**. Any link that breaks leaves the cache stale.
60
+
61
+ For the current session you need BOTH: edit source (for persistence) AND copy to cache (for immediate effect). Scripts for doing this safely:
62
+
63
+ ```bash
64
+ # Sync single plugin's source → cache (run from source repo root)
65
+ PLUGIN=build-loop
66
+ MARKET=rosslabs-ai-toolkit
67
+ VERSION=$(jq -r .version .claude-plugin/plugin.json)
68
+ CACHE=~/.claude/plugins/cache/$MARKET/$PLUGIN/$VERSION
69
+ rsync -av --delete --exclude=.git --exclude=node_modules --exclude='__pycache__' ./ "$CACHE/"
70
+ ```
71
+
72
+ This rule applies to EVERY path referenced via `${CLAUDE_PLUGIN_ROOT}/...`: hooks, manifests, SKILL.md, agent definitions, scripts, references, MCP servers, command .md files. Not just the originally-documented hooks + dist/.
73
+
74
+ **Detection script.** Build-loop ships `scripts/check_cache_sync.py` that greps the source repo for `${CLAUDE_PLUGIN_ROOT}/` references, resolves each, diffs against the cache, and fails with a list of out-of-sync paths. Review-D (Fact-Check) runs it automatically when Phase 1 detects "plugin work" on the target repo.
75
+
76
+ **Why this class of bug is easy to miss.** Local tests pass (they use the source path directly). Orchestrator-driven use fails silently (cache path returns stale or missing file). The mismatch only surfaces when the orchestrator and the developer use different resolved paths for the same logical file.
77
+
78
+ ## 6. Aggregator marketplaces hide their own update failures
79
+
80
+ **What happened.** When a plugin inside `rosslabs-ai-toolkit` ships a fix, the user has to run `/plugin` update on the aggregator, not on the individual plugin. Updates to individual plugins in the aggregator are not auto-pulled when only the plugin's version bumps — the aggregator's own marketplace.json must reflect the new version. Forgetting to update `marketplace.json` means users install stale plugin versions even though the GitHub repo has the fix.
81
+
82
+ **Rule.** When shipping a plugin in an aggregator marketplace, always update three things: (a) the plugin's own `version` in `plugin.json`, (b) the marketplace entry for that plugin in `.claude-plugin/marketplace.json`, (c) the README.md list showing installed plugins. If any of the three are missing, users get inconsistent views. See `feedback_rosslabs_toolkit_sync.md` for the full skill.
83
+
84
+ ## 7. `.mcp.json` MUST wrap servers in `"mcpServers"`
85
+
86
+ **What happened.** `navgator` and `showcase` shipped a flat `.mcp.json`:
87
+ ```json
88
+ { "navgator": { "command": "node", "args": [...] } }
89
+ ```
90
+ instead of the required wrapped form:
91
+ ```json
92
+ { "mcpServers": { "navgator": { "command": "node", "args": [...] } } }
93
+ ```
94
+ The flat form silently loaded without errors in `/doctor`, but the MCP server never started. `/mcp` showed "plugin:gator:navgator · failed" with no helpful error. Node would try to launch and immediately fail because Claude Code couldn't locate the server definition.
95
+
96
+ **Rule.** `.mcp.json` top-level must be `{"mcpServers": {...}}`. Inline manifest declarations (`"mcpServers": {...}` in `plugin.json`) use the same structure minus the outer object. Only `/mcp` shows this failure, not `/doctor` — always open both when verifying plugin health.
97
+
98
+ ## 8. Marketplace sync omits `dist/` and `node_modules/`
99
+
100
+ **What happened.** Plugins that require a TypeScript build (`tsc` producing `dist/mcp/server.js`) were synced into `~/.claude/plugins/cache/` without their `dist/` directories. The cached `plugin.json` pointed at `${CLAUDE_PLUGIN_ROOT}/dist/mcp/server.js` which didn't exist. MCP failed silently at startup. Same for `node_modules/` needed by the compiled output.
101
+
102
+ **Rule.** Either:
103
+ - Ship pre-bundled output (e.g. `tsup` producing a single file that bundles all deps) so the plugin doesn't need `node_modules`
104
+ - OR ensure the marketplace publish process includes `dist/` in the plugin's repo (not gitignored) and runs `npm install --production` as a postinstall step in the plugin's cache directory
105
+ - OR use a postinstall hook that rebuilds on install (acceptable but slow)
106
+
107
+ ibr uses `tsup` and ships a 525KB bundled `dist/mcp/server.js` that runs standalone — this is the cleanest pattern. showcase, navgator, spectra use `tsc` which requires `node_modules/` at runtime — fragile.
108
+
109
+ ## 9. `/doctor` catches manifest issues; `/plugin` and `/mcp` catch install/runtime issues
110
+
111
+ Use both. `/doctor` surfaces load-time failures (bad hooks, broken manifests, missing commands). `/plugin` (Installed tab) surfaces runtime issues (MCP servers that won't start, duplicate installs). They report different layers and will not overlap.
112
+
113
+ ## 8. Never commit `settings.json` changes to a plugin
114
+
115
+ **Relevant to plugin authors.** A plugin's `settings.json` sets *default* settings — values Claude Code merges into the user's config. Writing absolute paths, your local API keys, or your personal `enabledPlugins` map into a plugin's `settings.json` ships your machine's state to every user. Plugin-level `settings.json` should only contain defaults the user is expected to override (usually empty or near-empty).
116
+
117
+ ## 9. Removing a marketplace from `known_marketplaces.json` is not enough
118
+
119
+ **What happened (2026-04-21).** After a marketplace consolidation, editing `~/.claude/plugins/known_marketplaces.json` and running `/reload-plugins` made the removed marketplaces come right back. Five "zombie" marketplaces kept auto-re-registering on every reload: `bookmark`, `interface-built-right`, `mockup-gallery`, `navgator`, `build-loop`.
120
+
121
+ **Rule.** Claude Code re-seeds `known_marketplaces.json` from multiple persistent sources on every reload. To fully remove a marketplace, clean all of:
122
+
123
+ | Location | What it does | How to clean |
124
+ |---|---|---|
125
+ | `~/.claude/settings.json` → `extraKnownMarketplaces` | User-level persistent marketplace definitions. Re-registers on every reload. | Delete the entry. Highest-priority cleanup target. |
126
+ | `~/.claude/settings.json` → `enabledPlugins` | Keys like `"plugin@marketplace": true` also re-register the marketplace implicitly. | Delete dead entries. |
127
+ | `~/.claude/settings.json` → top-level `plugins` array (deprecated) | Legacy paths like `".../bookmark/.claude-plugin"` re-add plugins and their marketplace. | Remove or replace with empty array. |
128
+ | `~/.claude/plugins/.install-manifests/<plugin>@<marketplace>.json` | Per-install manifests with hashes. Each file implicitly keeps its marketplace registered. | Archive or delete the manifest files. |
129
+ | `~/.claude/plugins/marketplaces/<name>/` | Physical clone of a git-sourced marketplace. Presence can trigger auto-registration. | Archive the directory. |
130
+ | Project-scope `.claude/settings.json` → `extraKnownMarketplaces` | Team-level injection that re-registers when you trust the folder. | Audit `git-folder/*/.claude/settings.json`. |
131
+ | `~/.claude/plugins/known_marketplaces.json` | The runtime registry. Rewritten each reload from the sources above. | Clean this LAST so there's nothing to rewrite it from. |
132
+
133
+ Cleanup ordering matters: purge the re-seeding sources first, only then rewrite `known_marketplaces.json`. Otherwise the next reload resurrects everything.
134
+
135
+ ## 10. Partial cache dirs from interrupted updates confuse plugin resolution
136
+
137
+ **What happened.** Plugins had two cache directories for the same plugin, e.g. `claude-code-debugger/1.8.0/` (complete) and `claude-code-debugger/1.8.1/` (partial — missing `dist/` and `node_modules/`). Claude Code saw 1.8.1 as the "installed version" per `installed_plugins.json` but the `installPath` still pointed at 1.8.0. Additionally, the newer directory was incomplete so even if Claude tried to use it, the MCP server failed to start.
138
+
139
+ **Rule.**
140
+ - **Verify `installed_plugins.json` version matches installPath** — if `version: "1.8.1"` but installPath ends in `/1.8.0/`, something is stale. Align them.
141
+ - **Audit for incomplete cache dirs:** for each `<plugin>/<version>/`, check `dist/` and `node_modules/` presence if the plugin needs them. Missing = delete the incomplete dir.
142
+ - **Do not manually `cp` files between version dirs.** Either let `/plugin update` regenerate cleanly, or remove the bad version and let Claude Code re-fetch.
143
+
144
+ Quick audit:
145
+ ```bash
146
+ for p in ~/.claude/plugins/cache/*/*/; do
147
+ name=$(basename $(dirname $p))
148
+ ver=$(basename $p)
149
+ nm=$([ -d "$p/node_modules" ] && echo y || echo n)
150
+ dist=$([ -d "$p/dist" ] && echo y || echo n)
151
+ echo "$name/$ver: node_modules=$nm dist=$dist"
152
+ done
153
+ ```
154
+
155
+ ## 11. `${CLAUDE_PLUGIN_DATA}` is the right home for build artifacts
156
+
157
+ **Context.** TypeScript plugins that bundle with `tsc` need `node_modules/` at runtime. The marketplace sync doesn't include `node_modules/`, so cached plugins arrive without dependencies and MCP servers fail at startup.
158
+
159
+ **Rule.** Three correct patterns, in order of preference:
160
+
161
+ 1. **Bundle with `tsup`** — single-file `dist/mcp/server.js` that embeds all deps. No `node_modules/` needed at runtime. IBR follows this pattern. Ship `dist/` in git (don't gitignore it).
162
+ 2. **SessionStart hook with `${CLAUDE_PLUGIN_DATA}`** — install deps once into the persistent data dir, not the cache. Survives plugin updates.
163
+ ```json
164
+ {
165
+ "hooks": {
166
+ "SessionStart": [{
167
+ "hooks": [{
168
+ "type": "command",
169
+ "command": "diff -q \"${CLAUDE_PLUGIN_ROOT}/package.json\" \"${CLAUDE_PLUGIN_DATA}/package.json\" >/dev/null 2>&1 || (cd \"${CLAUDE_PLUGIN_DATA}\" && cp \"${CLAUDE_PLUGIN_ROOT}/package.json\" . && npm install)"
170
+ }]
171
+ }]
172
+ }
173
+ }
174
+ ```
175
+ Then point MCP at the bundled script with `NODE_PATH=${CLAUDE_PLUGIN_DATA}/node_modules`.
176
+ 3. **Commit `dist/` + use pure-stdlib server** — smallest deliverable but only viable for servers with zero runtime deps.
177
+
178
+ `${CLAUDE_PLUGIN_ROOT}` changes on every plugin update; data there doesn't survive. `${CLAUDE_PLUGIN_DATA}` persists at `~/.claude/plugins/data/<id>/`.
179
+
180
+ ## 12. Reserved marketplace names
181
+
182
+ **Context.** Claude Code rejects these names at publish/sync time:
183
+ - `claude-code-marketplace`, `claude-code-plugins`, `claude-plugins-official`
184
+ - `anthropic-marketplace`, `anthropic-plugins`
185
+ - `agent-skills`, `knowledge-work-plugins`, `life-sciences`
186
+ - Any name that impersonates the above (`official-claude-plugins`, `anthropic-tools-v2`, etc.)
187
+
188
+ **Rule.** Use a clearly-original kebab-case name that identifies you or your team. Validate before publishing: the `claude.ai` marketplace sync rejects non-kebab-case names silently even when the local `/plugin` flow accepts them.
189
+
190
+ ## 13. Testing an MCP server without Claude Code
191
+
192
+ **Rule.** You can verify a Claude Code plugin's MCP server is healthy without any plugin machinery by sending the `initialize` RPC directly:
193
+
194
+ ```bash
195
+ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | \
196
+ CLAUDE_PLUGIN_ROOT=/path/to/plugin \
197
+ node /path/to/plugin/dist/mcp/server.js
198
+ ```
199
+
200
+ A healthy server responds with a single-line JSON-RPC `result` containing `protocolVersion`, `serverInfo.name`, `serverInfo.version`, and `capabilities`. If you see nothing, a stack trace, or `EACCES`/`MODULE_NOT_FOUND`, the server has a real failure.
201
+
202
+ This distinguishes "server works but Claude Code's UI shows stale failure" from "server actually broken." Extremely useful for debugging the `/plugin` "Needs attention" pane — which sometimes caches failure status across reloads.
203
+
204
+ ## 14. Kebab-case and reserved-name checks happen at different stages
205
+
206
+ **Rule.** Anthropic's `claude.ai` marketplace sync is stricter than the local `/plugin` install flow:
207
+ - Local flow: accepts `UpperCase`, `under_scores`, even short paths. Shows warnings but loads.
208
+ - claude.ai sync: rejects non-kebab-case plugin or marketplace names with no override.
209
+
210
+ Check kebab-case for both `marketplace.json.name` and every `plugins[].name` before publishing. The fastest way to catch this: run `claude plugin validate .` in the marketplace root.
211
+
212
+ ## 15. Never delete a cache version dir while Claude Code is running
213
+
214
+ **What happened (2026-04-21).** During mid-session cleanup, I archived `~/.claude/plugins/cache/rosslabs-ai-toolkit/ibr/1.0.1/` (a partial dir left from an interrupted update). The live Claude Code session had loaded ibr's hooks at startup with `${CLAUDE_PLUGIN_ROOT}` resolved to `.../ibr/1.0.1/`. Hook paths are cached in memory at session start — `/reload-plugins` does not rebuild them. On next `Stop` event:
215
+
216
+ > Stop hook error: Failed to run: Plugin directory does not exist: /Users/.../ibr/1.0.1 (ibr@rosslabs-ai-toolkit — run /plugin to reinstall)
217
+
218
+ `installed_plugins.json` correctly pointed at `1.0.0`, but the in-memory hook registry still held `1.0.1`.
219
+
220
+ **Rule.** Cache-directory cleanup must follow session state:
221
+
222
+ | Action | When safe |
223
+ |---|---|
224
+ | Edit `installed_plugins.json` version/installPath | Anytime |
225
+ | Archive/delete an *unused* version dir | Only when no live session holds a hook from it |
226
+ | Archive/delete the *active* `installPath` dir | Never while Claude Code is running — will break hooks, MCP, and commands immediately |
227
+
228
+ **Recovery without restart.** Symlink the missing dir back to the active version:
229
+ ```bash
230
+ ln -s ~/.claude/plugins/cache/<mkt>/<plugin>/<active-version> \
231
+ ~/.claude/plugins/cache/<mkt>/<plugin>/<missing-version>
232
+ ```
233
+ The symlink satisfies the stale path until the session restarts and re-resolves `${CLAUDE_PLUGIN_ROOT}`.
234
+
235
+ **Safe sequence for mid-session cache cleanup.**
236
+ 1. Align `installed_plugins.json` `version` + `installPath` for the plugin.
237
+ 2. Leave all cache version dirs in place.
238
+ 3. Have the user `/exit` and relaunch Claude Code.
239
+ 4. On the fresh session, archive or delete the orphaned version dirs.
240
+
241
+ **For plugin authors.** If your plugin registers hooks that reference `${CLAUDE_PLUGIN_ROOT}`, document that plugin updates require a Claude Code restart (not just `/reload-plugins`) for the hook paths to refresh. Consider writing hook scripts that resolve their own path at runtime (e.g. `realpath "$0"` inside the script) rather than relying on the registered command's frozen `${CLAUDE_PLUGIN_ROOT}`.
242
+
243
+ ## 16. `/plugin` "Needs attention" badges persist beyond the failure
244
+
245
+ **What happened (2026-04-21).** After fixing the `.mcp.json` schema for bookmark, debugger, and ibr — verified healthy via direct JSON-RPC `initialize` handshake — the `/plugin` UI kept showing the red "✗ failed" badge after `/reload-plugins`. `/reload-plugins` correctly reported "7 plugin MCP servers" loaded, matching the expected count, so all servers were in fact running. Only the UI status was stale.
246
+
247
+ **Rule.** Claude Code's `/plugin` panel caches per-session MCP connection status. When an MCP fails at startup, the panel latches the red badge for the life of the session. `/reload-plugins` re-runs plugin discovery but does **not** re-probe existing MCP health. Same staleness pattern as § 15 (hook `${CLAUDE_PLUGIN_ROOT}` paths).
248
+
249
+ **Ways to clear stale badges, in order of disruption:**
250
+
251
+ | Method | Disruption | Reliability |
252
+ |---|---|---|
253
+ | `/exit` and relaunch Claude Code | High — full restart | 100% — fresh process |
254
+ | Toggle each plugin off then on in `/plugin` UI | Medium | ~95% — forces MCP reconnect |
255
+ | Toggle `enabledPlugins` in `settings.json` + `/reload-plugins` | Low | ~70% |
256
+ | Wait — do nothing | None | 0% during session, 100% next launch |
257
+
258
+ **Diagnostic rule: do not trust UI badges over direct evidence.** When a badge says failed but the server tests healthy, the badge is the lie. Checks that trump the UI:
259
+
260
+ 1. **Direct handshake test** — if the server responds to `initialize` RPC with a valid result, it's healthy:
261
+ ```bash
262
+ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' | \
263
+ CLAUDE_PLUGIN_ROOT=<path> node <path>/dist/mcp/server.js
264
+ ```
265
+ 2. **Reload loaded count** — if `/reload-plugins` reports N plugin MCP servers loaded and N matches the enabled count, the servers are running regardless of UI.
266
+ 3. **Invoke a tool** — call a slash command or tool that depends on the MCP (e.g. `/bookmark:snapshot`). Success = server live.
267
+
268
+ **For plugin authors.** Don't treat user bug reports of "MCP failed in /plugin" as gospel. Ask them to (a) run the standalone handshake, (b) try an actual tool invocation. Stale UI badges generate false bug reports.
269
+
270
+ ## 17. Out-of-tree hook wrappers desync silently; hooks must fail-open under a minimal PATH
271
+
272
+ **What happened (2026-06-06, agent-rally-point).** Codex sessions spammed `PreToolUse hook (failed) error: hook exited with code 127` and `Stop hook (failed) error: hook exited with code 127` on every tool call. Two compounding defects:
273
+
274
+ 1. **Out-of-tree wrapper desync.** `~/.codex/rally-hook.sh` (installed once, *not* version-controlled) called `rally start` / `rally hook before-write` — subcommands the Rust rewrite had **removed**. The in-repo fix (a version-controlled canonical hook + an installer that repoints the wrapper to a thin `exec` shim) had shipped, but this machine's pre-rewrite global wrapper was never migrated. The repo *said* "fixed, advisory-only"; ground truth on disk was a months-old enforcing wrapper. A loose installed file cannot be caught by the repo's tests or CI — it drifts the moment the code it calls changes.
275
+
276
+ 2. **`set -e` + bare binary on the hook's minimal PATH → exit 127.** Hook subprocesses inherit `/usr/bin:/bin`, **not** the login PATH. The wrapper's line 6 ran `node` in a command substitution *before any guard*, under `set -euo pipefail`. `node` (in a version-manager dir) and `rally` (in `~/.local/bin`) were both absent → the substitution returned 127 → `set -e` aborted the whole script with 127, before it ever reached the removed subcommand. The lone `2>/dev/null || true` guarded a *different* line. Verified: `env -i PATH=/usr/bin:/bin bash stale-wrapper.sh before-write` → exit 127; the hardened in-repo hook under the same env → exit 0.
277
+
278
+ A third latent hazard: the stale wrapper mapped `severity=="stop"` → `permissionDecision:"deny"` / `decision:"block"`. Had someone "fixed" only the PATH, the wrapper would have started **blocking tool calls** — violating the facilitator/never-block charter.
279
+
280
+ **Rules.**
281
+
282
+ - **Version-control the hook in-repo; make any host-side wrapper a thin shim.** The wrapper at `~/.codex/…` or `~/.claude/settings.json` should `exec "<repo>/hooks/<hook>.sh" "$@"`, never contain logic. Logic in-tree = tested, CI-guarded, can't silently desync from the CLI it drives. Ship an idempotent installer with `--uninstall` that backs up the prior wrapper to `.bak`.
283
+ - **Hooks run with a minimal PATH. Resolve binaries absolutely or `command -v`-guard every call**, and **fail-open (`exit 0`) on any missing binary / timeout / parse error.** Guarding one line is not fail-open when `set -e` is on — an unguarded later command still aborts. Add a test that runs the hook under `env -i PATH=/usr/bin:/bin` and asserts `exit 0` + no `deny`/`block`. This catches the whole 127 class in CI.
284
+ - **Advisory/coordination hooks never enforce by default.** Emit `additionalContext`/`systemMessage`; reserve `deny`/`block`/`exit 2` for explicit safety/security/integrity gates, gated behind an opt-in env flag.
285
+ - **When a hook's backend changes, repoint or remove the installed wrapper** — don't leave an orphan. Treat "the repo shipped the fix" and "this machine runs the fix" as separate facts; verify the second on disk (`trust ground truth over artifacts`).
286
+ - **Coordination caveat:** repointing/disabling a hook changes behavior for *live* peer agents. Hooks are read per-invocation (not cached like plugin `${CLAUDE_PLUGIN_ROOT}` paths in §15), so no restart is needed — but in a multi-agent room, prefer the least-disruptive relief (a clean fail-open shim) over one that introduces new behavior (e.g. auto-claim) mid-session.
287
+
288
+ ## Preflight checklist before shipping a plugin change
289
+
290
+ - [ ] `plugin.json` declares only non-default paths for `hooks`, `mcpServers`, `lsp`
291
+ - [ ] `plugin.json` lives at `.claude-plugin/plugin.json` (not plugin root)
292
+ - [ ] Version bumped in `plugin.json`
293
+ - [ ] No `type: "prompt"` hooks on per-turn events (PostToolUse:Bash, UserPromptSubmit, PreToolUse:Bash)
294
+ - [ ] No absolute paths — use `${CLAUDE_PLUGIN_ROOT}`
295
+ - [ ] No personal values in `settings.json`
296
+ - [ ] `.mcp.json` uses `{"mcpServers": {...}}` wrapper (not flat form)
297
+ - [ ] MCP server responds to `initialize` RPC when launched directly
298
+ - [ ] `dist/` is in git (not gitignored) OR bundled via `tsup` OR rebuilt via SessionStart hook with `${CLAUDE_PLUGIN_DATA}`
299
+ - [ ] Plugin name and marketplace name are kebab-case
300
+ - [ ] If in an aggregator: marketplace.json version matches plugin.json, README.md updated
301
+ - [ ] Test with `claude --plugin-dir ./my-plugin` in a scratch directory before committing
302
+ - [ ] `claude plugin validate .` passes in the marketplace root
303
+ - [ ] `jq` the `installed_plugins.json` audit command on your own machine — no duplicates for this plugin
304
+ - [ ] Hook scripts live in-repo; any host wrapper (`~/.codex/…`, settings.json) is a thin `exec` shim, not logic (§17)
305
+ - [ ] Every external binary in a hook is absolute-path-resolved or `command -v`-guarded; hook fails open (`exit 0`) on missing binary (§17)
306
+ - [ ] Hook tested under `env -i PATH=/usr/bin:/bin` → exits 0, no `deny`/`block` unless an explicit safety gate (§17)
307
+ - [ ] `python3 scripts/hook_hygiene_lint.py --hooks hooks/hooks.json --json` returns exit 0 (no `HH001` bare-binary / `HH002` strict-mode-subst / `HH003` no-fail-open / `HH004` advisory-deny findings). Operationalizes §17. WARN-level — surfaces in the run report, never blocks. Build-loop's own `hooks/hooks.json` is the passing reference fixture.
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: plugin-tests
3
+ description: Static-analysis test harness for Claude Code plugins. Triggers on "test plugin", "validate plugin", "check skill resolution", "run plugin tests", "lint plugin", "verify manifest", "namesake collision", "MCP registration check". Runs Python stdlib pytest scripts that catch namesake collisions, manifest drift, MCP misregistration, trigger-phrase coverage gaps, bridge pre-flight gaps, agent-surface drift, and cache-prune regressions. Routed as build-loop's 4th orchestrator mode (Build / Optimize / Research / Test).
4
+ version: 0.1.0
5
+ user-invocable: false
6
+ ---
7
+
8
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
9
+
10
+ # Plugin Tests — Static-Analysis Harness
11
+
12
+ A pytest-stdlib test suite that validates a Claude Code plugin's structure, manifest, MCP wiring, skill descriptions, and bridge preflights. Designed to catch the bug classes that have actually shipped through build-loop's history (namesake collisions, manifest version drift, missing frontmatter on commands, bare MCP server names).
13
+
14
+ This is the **static** tier — pure text/JSON validation, zero runtime dependencies, runs in under a second. Runtime tests (live MCP round-trip, real bridge delegation) are out of scope here and live in the orchestrator's Phase 4 Review-B Validate.
15
+
16
+ ## When this skill fires
17
+
18
+ - **User direct** — `/build-loop:test [test-name]` or any of: "test plugin", "validate plugin", "lint plugin", "verify manifest", "check skill resolution", "run plugin tests"
19
+ - **Orchestrator intent routing** — TEST mode (4th mode alongside Build / Optimize / Research) — `agents/build-orchestrator.md` §Intent Routing
20
+ - **Orchestrator auto-dispatch in Phase 4 Review-B Validate** (always on, since v0.7.3; advisory-not-blocking since v0.7.4) — when Phase 3 Execute's diff touches any plugin metadata path: `*.claude-plugin/*.json`, `commands/*.md`, `skills/*/SKILL.md`, `agents/*.md`, `.mcp.json`, `hooks/hooks.json`, or any path referenced by `mcpServers`. Findings are written to `.build-loop/state.json.pluginTests` and surfaced in the Review-F Report — they do NOT block the build or auto-route to Iterate. Static-analysis is heuristic (regex over markdown frontmatter); the user decides whether each finding is a real defect or a false positive.
21
+ - **Pre-publish gate** when bumping a plugin version (the human-driven equivalent of the auto-dispatch — run `/build-loop:test --strict` before pushing)
22
+
23
+ ## What's tested
24
+
25
+ | Script | What it catches | Reference defects |
26
+ |---|---|---|
27
+ | `scripts/test_skill_resolution.py` | Namesake collisions (commands/X.md + skills/X/SKILL.md), frontmatter `name:` drift from dir name | `build-loop:build-loop` collision (shipped through 6 versions undetected before 0.4.1) |
28
+ | `scripts/test_plugin_manifest.py` | Required manifest fields, version sync between plugin.json and marketplace.json, MCP path resolution, every command has frontmatter, skill name uniqueness | 0.4.0/0.3.2 marketplace drift; missing frontmatter on `commands/debugger-detail.md` |
29
+ | `scripts/test_mcp_registration.py` | `.mcp.json` shape, referenced binaries exist, server-name hygiene (warns on bare names that collide across plugins) | Historical `debugger` bare-name collision risk; Build Loop now skips this test because it does not ship an MCP server |
30
+ | `scripts/test_trigger_phrases.py` | Curated (skill, phrase) coverage in skill `description:` fields | Trigger-phrase gaps after the multi-provider auth audit |
31
+ | `scripts/test_bridge_preflight.py` | Every `*-bridge/SKILL.md` has an availability/absence check + `user-invocable: false` | api-registry-bridge missing `user-invocable: false`; bridges that hard-fail when their target plugin isn't installed |
32
+ | `scripts/test_agent_surface_policy.py` | Codex public wrappers, Claude `user-invocable` flags, and host-neutral Cursor/AGENTS policy stay aligned | Helper skills crowding Codex/ChatGPT `#` picker while Claude internals still need the full tree |
33
+ | `scripts/test_prune_plugin_cache.py` | Host-aware stale cache pruning for Claude Code and Codex | Old Build Loop versions staying visible after a new version is installed |
34
+ | `scripts/test_prune_codex_plugin_cache.py` | Backward-compatible Codex-only cache pruning wrapper | Existing `codex:prune-cache` workflow breaking after host-aware pruning was added |
35
+
36
+ ## How to run
37
+
38
+ From the plugin repo root:
39
+
40
+ ```bash
41
+ # Run all 8
42
+ for t in scripts/test_skill_resolution.py scripts/test_plugin_manifest.py \
43
+ scripts/test_mcp_registration.py scripts/test_trigger_phrases.py \
44
+ scripts/test_bridge_preflight.py scripts/test_agent_surface_policy.py \
45
+ scripts/test_prune_plugin_cache.py scripts/test_prune_codex_plugin_cache.py; do
46
+ echo "=== $t ==="
47
+ python3 "$t"
48
+ done
49
+
50
+ # Or via the slash command
51
+ /build-loop:test
52
+ ```
53
+
54
+ Each script is independent — running one without the others is fine. Each follows the build-loop pytest-stdlib convention from `scripts/test_plan_verify.py` (subprocess-against-sibling-script + tempfile fixtures + `unittest.TestCase`).
55
+
56
+ ## Exit codes
57
+
58
+ - `0` — all tests pass
59
+ - `1` — at least one test failed (advisory in Review-B; hard CI gate when invoked via `/build-loop:test --strict` or run directly in CI)
60
+ - `2` — runner error (test script itself crashed)
61
+
62
+ The orchestrator records findings under `.build-loop/state.json.pluginTests` and surfaces a one-line summary in the Review-F Report. **It does not gate the build on plugin-tests results.** Why: static-analysis findings are heuristic (regex/pattern matches over markdown frontmatter) and false positives are common — 3 hit on initial rollout (legitimate user-invocable bridge, filesystem-based pre-flight, PRD-absence prose). A blocking gate that flaps gets disabled, which destroys the value. Surfacing as advisory keeps the signal alive while letting the user judge edge cases.
63
+
64
+ For pre-publish checks, run with `--strict` to make the CLI exit non-zero on any finding (without involving the orchestrator).
65
+
66
+ ## Adding new tests
67
+
68
+ When a new bug class ships through, add a test that would have caught it. Pattern:
69
+
70
+ 1. Write `scripts/test_<bug_class>.py` matching the existing pattern (stdlib only, `unittest.TestCase`, subprocess against any helper script)
71
+ 2. Add a row to the table in §"What's tested" above
72
+ 3. Add the script to the runner in §"How to run"
73
+ 4. Add a `(skill, phrase)` to `EXPECTED_TRIGGERS` in `test_trigger_phrases.py` if the new test covers a class that should be discoverable by user phrasing
74
+
75
+ Don't migrate to pytest, vitest, or Playwright. The stdlib pattern keeps the harness portable, zero-install, and CI-friendly. (See the testing survey at the head of `KNOWN-ISSUES.md` 2026-05-02 entry — IBR's vitest, example-app's Jest+Playwright, prompt-test-lab's Playwright stratification all have their place; for plugin metadata validation specifically, stdlib Python wins.)
76
+
77
+ ## What this skill does NOT do
78
+
79
+ - Runtime testing (live MCP calls, actual `Skill()` invocation) — that's Review-B Validate's job, executed by the orchestrator with the live runtime
80
+ - UI testing — for plugins that build UIs, use the orchestrator's build-loop-owned UI validation route (`ui-validator`, project-native tests, screenshots/static scanner). Dispatch IBR only when the user explicitly asks for IBR / Interface Built Right / `.ibr-test.json`.
81
+ - Performance / Lighthouse — separate concern, not a plugin metadata issue
82
+ - Cross-plugin integration — that's the bridge skills' job at runtime
83
+
84
+ ## Cross-references
85
+
86
+ - `agents/build-orchestrator.md` §Intent Routing — TEST mode classification
87
+ - `commands/test.md` — slash-command surface (`/build-loop:test`)
88
+ - `scripts/collision_scan.py` — the static detector that `test_skill_resolution.py` wraps
89
+ - `KNOWN-ISSUES.md` 2026-05-02 entry — testing survey across 13 projects that informed this design
90
+ - `agents/ui-validator.md` and `skills/build-loop/phases/ui-validation.md` — default UI validation route. IBR's `.ibr-test.json` remains an explicit-only auxiliary format.
91
+
92
+ ## History
93
+
94
+ - 2026-05-02 — initial release with 5 static-analysis scripts. Caught 2 real defects on first run (debugger-detail frontmatter, api-registry-bridge user-invocable). Pattern borrowed from build-loop's existing `scripts/test_plan_verify.py` + survey of test setups across 13 user projects.
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: build-loop:prd-bridge
3
+ description: Use when Phase 1 Assess runs, the user mentions a PRD, or asks to "ground the build in product strategy". Surfaces always-true principles and Navigation Map from the project PRD so subsequent phases reason from strategic frame; recommends prd-builder if none exists.
4
+ version: 0.1.0
5
+ user-invocable: false
6
+ ---
7
+
8
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
9
+
10
+ # PRD Bridge
11
+
12
+ Lets build-loop ground every phase decision in a project's strategic frame (its PRD) when one exists, and surfaces a recommendation when one doesn't. The PRD is the source of strategic truth; this bridge consumes it without coupling to its content.
13
+
14
+ **Use:**
15
+ - **Phase 1 Assess** — load PRD frontmatter and Navigation Map; mirror always-true principles into `.build-loop/state.json.prd`. Phase 2 Plan and Phase 5 Review consult this for scoping, criterion design, and "is this on-vision" gates.
16
+ - **Phase 5 Review-D Fact-Check** — verify the build doesn't violate any PRD `core_principles` (e.g., a change that exposes admin-only complexity to regular users when the PRD's complexity stance forbids that).
17
+ - **Phase 6 Learn (optional)** — flag if the build's lessons contradict a PRD principle. The user decides: was the principle wrong (update PRD), or was the build off-vision (don't promote learning)?
18
+
19
+ ## Cherry-pick principle
20
+
21
+ **The PRD remains owned by the project, not by build-loop.** This bridge does not author, modify, or shadow PRDs — it only consumes the relevant fields:
22
+
23
+ - Reads `docs/prd-*.md` frontmatter (`core_principles`, `load_when`, `evolves_when`, `revision`, `status`) — file-only
24
+ - Reads the body's "LLM Navigation Map" and "Section Index" tables to enable targeted offset/limit reads in later phases
25
+ - Writes to `.build-loop/state.json.prd.*` — bridge's own namespace
26
+ - Surfaces a one-line recommendation when no PRD exists; does not auto-create one
27
+
28
+ What this bridge does NOT do:
29
+ - Write or edit the PRD
30
+ - Cache PRD content (always reads live from disk)
31
+ - Resolve ambiguous principles by interpretation (if a principle is unclear, surface it as a question for Phase 2 Plan)
32
+ - Block the build when a PRD is missing — only recommends one
33
+
34
+ ## Pre-flight
35
+
36
+ Before phase logic runs, check:
37
+
38
+ ```bash
39
+ ls docs/prd-*.md 2>/dev/null | head -1 && echo "HAVE_PRD" || echo "NO_PRD"
40
+ ```
41
+
42
+ If `HAVE_PRD`, run the steps below.
43
+
44
+ If `NO_PRD`, surface this one-line note in `state.json.prd.recommendation`:
45
+
46
+ > No PRD found. Tactical decisions during this build will lack strategic grounding. Consider running the **`prd-builder`** skill from RossLabs-AI-Toolkit (or `/build-loop:start-prd`) to draft a living PRD before iterating further. This is a recommendation, not a blocker.
47
+
48
+ The note appears in Phase 5 Report's "Open recommendations" section so the user can act between builds.
49
+
50
+ ## Phase 1 Assess — Load PRD into state
51
+
52
+ When a PRD is present:
53
+
54
+ 1. **Read frontmatter** with a YAML parser (or grep for the documented fields). Extract:
55
+ - `name`
56
+ - `status`
57
+ - `revision`
58
+ - `last_updated`
59
+ - `load_when` (array)
60
+ - `evolves_when` (array)
61
+ - `core_principles` (array of 1-line statements)
62
+
63
+ 2. **Read the Navigation Map table** if present. Parse rows into `{decision_type: section_name}` mapping. This is what Phase 2 Plan and Phase 5 Review consult to load only the relevant section.
64
+
65
+ 3. **Read the Section Index table** if present. Parse rows into `{section_name: line_range}`. This enables targeted `Read --offset --limit` calls.
66
+
67
+ 4. **Write to `.build-loop/state.json.prd`:**
68
+ ```json
69
+ {
70
+ "path": "docs/prd-example-app.md",
71
+ "status": "living",
72
+ "revision": "0.1",
73
+ "last_updated": "2026-05-01",
74
+ "core_principles": ["..."],
75
+ "load_when": ["..."],
76
+ "navigation_map": {
77
+ "should_i_add_this_feature": "Persona + Outcome + Methodology",
78
+ "...": "..."
79
+ },
80
+ "section_index": {
81
+ "intent": [95, 98],
82
+ "...": [0, 0]
83
+ }
84
+ }
85
+ ```
86
+
87
+ 5. **Surface staleness signals**:
88
+ - If `last_updated` is more than 90 days old AND `status: living` → flag `prd_stale: true` so Phase 5 Report includes a "PRD review due" note.
89
+ - If `status: pivoting` → flag `prd_pivoting: true` so Phase 2 Plan asks the user before locking scope.
90
+ - If any `evolves_when` trigger condition is true (best-effort detection) → surface as a "PRD review recommended" note.
91
+
92
+ ## Phase 2 Plan — Consult navigation map
93
+
94
+ When Phase 2 is about to lock scope:
95
+
96
+ 1. Identify the **decision type** the build represents (new feature, UX change, architectural choice, rubric/scoring change, etc.).
97
+ 2. Look up the matching row in `state.json.prd.navigation_map`.
98
+ 3. Read the indicated section(s) using `Read --offset --limit` per `section_index`.
99
+ 4. Cite the section in the plan's rationale (e.g., *"per Persona, Director+ users won't tolerate hidden-required complexity, so this UI surfaces the toggle by default"*).
100
+
101
+ If no row matches the decision type, default to **Persona + Outcome** (the universal fallback per most PRDs).
102
+
103
+ ## Phase 5 Review-D Fact-Check — Principle violation check
104
+
105
+ After implementation, scan the diff for changes that contradict any `core_principles`:
106
+
107
+ 1. For each `core_principle`, attempt a lightweight grep against the diff for keywords that suggest a violation. Examples:
108
+ - Principle: *"Hide complexity from regular users"* → grep diff for new public Settings UI with admin-tier features
109
+ - Principle: *"On-device first; cloud fallback only when..."* → grep diff for new always-cloud calls
110
+ - Principle: *"Don't add new drills next; polish, fold, kill"* → grep diff for new drill ViewModel/View pairs
111
+ 2. **Heuristic only** — surface findings as `principle_check_findings` for human review, not auto-block.
112
+ 3. If any finding suggests a principle violation, route to Phase 5 Report with the principle citation + the diff hunk that triggered it.
113
+
114
+ If the heuristics produce no findings, write `principle_check: clean`. The clean-result is honest: "no obvious contradictions; not a guarantee."
115
+
116
+ ## Standalone fallback
117
+
118
+ If `${CLAUDE_PLUGIN_ROOT}/skills/build-loop/fallbacks.md` `#prd` exists, follow its degraded recipe. Otherwise:
119
+
120
+ - **If no PRD frontmatter parser is available** → grep `^- ` lines under `core_principles:` (works for simple list format), surface as raw text.
121
+ - **If no Navigation Map exists in PRD** → fall back to reading the entire body once and asking Phase 2 Plan to derive the relevant section by reading section headers.
122
+ - **If no Section Index exists** → fall back to reading the section by `grep -n '^## '` to find line ranges.
123
+
124
+ The fallback degrades gracefully — partial signal is better than no signal.
125
+
126
+ ## Files referenced
127
+
128
+ - `docs/prd-*.md` (project-level PRD; pattern allows multi-app monorepos)
129
+ - `.build-loop/state.json.prd` (bridge output)
130
+ - `.build-loop/issues/principle-violations.md` (Phase 5 fact-check findings, when populated)
131
+
132
+ ## Related
133
+
134
+ - `prd-builder` skill (RossLabs-AI-Toolkit) — drafts a new PRD from 3-5 strategic questions when none exists.
135
+ - `/build-loop:start-prd` command — explicit invocation path; loads `prd-builder` from the toolkit if installed.
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: research
3
+ description: Use when the user asks to "research", "investigate", "evaluate options", or "find out about" a topic. Generate a repo-grounded research packet before deciding whether/how to build — pre-decision analysis with risks, best path, confidence, next action.
4
+ user-invocable: true
5
+ ---
6
+
7
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
8
+
9
+ # Research — Pre-Decision Analysis
10
+
11
+ Produces a repo-grounded research packet without committing to implementation. Use when evaluating approaches, comparing options, or preparing a handoff.
12
+
13
+ ## When to Use
14
+
15
+ - "Should I use X or Y?"
16
+ - "What's the best way to add Z?"
17
+ - "Evaluate this approach before I commit"
18
+ - "Research this before we build"
19
+ - The orchestrator routes here when intent is exploratory, not implementational
20
+
21
+ ## Process
22
+
23
+ 1. **Scan the repo**: Run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/research_packet.py --scan --workdir "$PWD" --focus "<topic>"` to get repo context (manifests, entrypoints, focus hits, validation commands)
24
+
25
+ 2. **Classify the task**: product, feature, algorithm, prompt, bugfix, or refactor
26
+
27
+ 3. **Build the packet**: Run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/research_packet.py --packet --workdir "$PWD" --task "<full request>" --mode balanced` to generate the structured research packet
28
+
29
+ 4. **Review and present**: Read the generated packet, verify claims against the actual repo, adjust confidence if needed
30
+
31
+ 5. **Archive**: Save to `.build-loop/research/YYYY-MM-DD-<topic>.md`
32
+
33
+ ## Output Format
34
+
35
+ ```
36
+ # Research Packet
37
+
38
+ ## Bottom line
39
+ [One sentence: what this is and the recommended path]
40
+
41
+ ## What I found
42
+ - project kind, manifests, entrypoints, validation commands
43
+ - focus hits (files relevant to the topic)
44
+ - integration surfaces (APIs, auth, payments, deployment)
45
+
46
+ ## Best path
47
+ [Recommended approach with reasoning]
48
+
49
+ ## Why this path
50
+ [Evidence from repo analysis and domain knowledge]
51
+
52
+ ## Risks / unknowns
53
+ [What could go wrong, what's uncertain]
54
+
55
+ ## Confidence
56
+ - Context coverage: high/medium/low
57
+ - Verification coverage: high/medium/low
58
+ - Evidence quality: high/medium/low
59
+ - Overall: high/medium/low
60
+
61
+ ## Next action
62
+ [Concrete first step — could be "run /build-loop" or "investigate X further"]
63
+ ```
64
+
65
+ ## Modes
66
+
67
+ - `quick` — repo scan only, no external research, fast
68
+ - `balanced` — repo scan + selective external research when current facts matter
69
+ - `max_accuracy` — deep scan + external research + self-debug pass
70
+
71
+ ## Integration
72
+
73
+ - Standalone: `/build-loop:research [topic]`
74
+ - From build-loop: orchestrator routes RESEARCH-intent requests here instead of the full loop
75
+ - During normal build-loop runs: `scripts/research_trigger.py` decides whether this skill should run, which depth to use, where to persist the packet, and whether current/external claims are blocked until cited. See `references/research-trigger-policy.md`.
76
+ - After packet: user decides — `/build-loop:run` to implement, `/build-loop:optimize` to optimize, or shelve
77
+
78
+ ## State
79
+
80
+ Packets archived to `.build-loop/research/YYYY-MM-DD-<topic>.md` with JSON frontmatter (confidence scores, mode, task type, timestamp).