wicked-garden 12.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (640) hide show
  1. package/.claude-plugin/archetypes.json +166 -0
  2. package/.claude-plugin/components.json +75 -0
  3. package/.claude-plugin/marketplace.json +15 -0
  4. package/.claude-plugin/plugin.json +174 -0
  5. package/.claude-plugin/specialist.json +48 -0
  6. package/.claude-plugin/stack-registry.json +96 -0
  7. package/AGENTS.md +13 -0
  8. package/CHANGELOG.md +712 -0
  9. package/CONTRIBUTING.md +99 -0
  10. package/ETHOS.md +83 -0
  11. package/LICENSE +21 -0
  12. package/README.md +115 -0
  13. package/WICKED_GARDEN_BUS_EVENTS.md +149 -0
  14. package/agents/agentic/architect.md +449 -0
  15. package/agents/agentic/performance-analyst.md +702 -0
  16. package/agents/agentic/safety-reviewer.md +662 -0
  17. package/agents/crew/implementer.md +163 -0
  18. package/agents/crew/researcher.md +94 -0
  19. package/agents/crew/reviewer.md +184 -0
  20. package/agents/data/data-engineer.md +227 -0
  21. package/agents/engineering/api-documentarian.md +440 -0
  22. package/agents/engineering/migration-engineer.md +301 -0
  23. package/agents/engineering/solution-architect.md +208 -0
  24. package/agents/jam/brainstorm-facilitator.md +297 -0
  25. package/agents/jam/council.md +322 -0
  26. package/agents/jam/quick-facilitator.md +85 -0
  27. package/agents/persona/persona-agent.md +121 -0
  28. package/agents/platform/compliance-officer.md +266 -0
  29. package/agents/platform/privacy-expert.md +496 -0
  30. package/agents/platform/security-engineer.md +287 -0
  31. package/agents/product/a11y-expert.md +323 -0
  32. package/agents/product/requirements-analyst.md +238 -0
  33. package/agents/product/ui-reviewer.md +180 -0
  34. package/agents/product/ux-designer.md +199 -0
  35. package/agents/product/value-strategist.md +269 -0
  36. package/agents/qe/semantic-reviewer.md +78 -0
  37. package/commands/agentic/audit.md +24 -0
  38. package/commands/agentic/design.md +24 -0
  39. package/commands/agentic/frameworks.md +25 -0
  40. package/commands/agentic/review.md +27 -0
  41. package/commands/archetype/build.md +12 -0
  42. package/commands/archetype/decide.md +12 -0
  43. package/commands/archetype/explore.md +12 -0
  44. package/commands/archetype/incident.md +12 -0
  45. package/commands/archetype/migrate.md +12 -0
  46. package/commands/archetype/modernize.md +12 -0
  47. package/commands/archetype/review.md +14 -0
  48. package/commands/archetype/ship.md +12 -0
  49. package/commands/archetype/specify.md +12 -0
  50. package/commands/archetype/triage.md +12 -0
  51. package/commands/compile.md +37 -0
  52. package/commands/data/analyze.md +18 -0
  53. package/commands/data/data.md +21 -0
  54. package/commands/data/ml.md +18 -0
  55. package/commands/data/ontology.md +22 -0
  56. package/commands/data/pipeline.md +17 -0
  57. package/commands/deliberate.md +181 -0
  58. package/commands/engineering/add-field.md +77 -0
  59. package/commands/engineering/apply.md +58 -0
  60. package/commands/engineering/arch.md +26 -0
  61. package/commands/engineering/debug.md +27 -0
  62. package/commands/engineering/docs.md +27 -0
  63. package/commands/engineering/new-generator.md +257 -0
  64. package/commands/engineering/patch-plan.md +59 -0
  65. package/commands/engineering/plan.md +29 -0
  66. package/commands/engineering/remove.md +48 -0
  67. package/commands/engineering/rename.md +44 -0
  68. package/commands/engineering/review.md +32 -0
  69. package/commands/help.md +128 -0
  70. package/commands/install.md +118 -0
  71. package/commands/intent.md +54 -0
  72. package/commands/jam/brainstorm.md +37 -0
  73. package/commands/jam/council.md +49 -0
  74. package/commands/jam/quick.md +21 -0
  75. package/commands/jam/revisit.md +79 -0
  76. package/commands/persona/as.md +136 -0
  77. package/commands/persona/define.md +24 -0
  78. package/commands/persona/list.md +118 -0
  79. package/commands/platform/actions.md +20 -0
  80. package/commands/platform/assert.md +18 -0
  81. package/commands/platform/audit.md +23 -0
  82. package/commands/platform/compliance.md +20 -0
  83. package/commands/platform/gh.md +22 -0
  84. package/commands/platform/health.md +22 -0
  85. package/commands/platform/incident.md +23 -0
  86. package/commands/platform/infra.md +24 -0
  87. package/commands/platform/peer-health.md +103 -0
  88. package/commands/platform/plugin-health.md +58 -0
  89. package/commands/platform/security.md +38 -0
  90. package/commands/platform/toolchain.md +96 -0
  91. package/commands/platform/traces.md +20 -0
  92. package/commands/product/a11y.md +19 -0
  93. package/commands/product/acceptance.md +19 -0
  94. package/commands/product/align.md +20 -0
  95. package/commands/product/analyze.md +23 -0
  96. package/commands/product/elicit.md +19 -0
  97. package/commands/product/listen.md +24 -0
  98. package/commands/product/mockup.md +20 -0
  99. package/commands/product/screenshot.md +19 -0
  100. package/commands/product/strategy.md +40 -0
  101. package/commands/product/synthesize.md +23 -0
  102. package/commands/product/ux-review.md +42 -0
  103. package/commands/product/ux.md +20 -0
  104. package/commands/product/visual-direction.md +34 -0
  105. package/commands/prove.md +47 -0
  106. package/commands/report-issue.md +243 -0
  107. package/commands/reset.md +144 -0
  108. package/commands/search/blast-radius.md +58 -0
  109. package/commands/search/hotspots.md +55 -0
  110. package/commands/search/index.md +38 -0
  111. package/commands/search/lineage.md +47 -0
  112. package/commands/search/service-map.md +79 -0
  113. package/commands/setup.md +363 -0
  114. package/commands/smaht/briefing.md +200 -0
  115. package/commands/smaht/events-import.md +95 -0
  116. package/commands/smaht/state.md +19 -0
  117. package/commands/where-am-i.md +58 -0
  118. package/docs/README.md +32 -0
  119. package/docs/adr/0001-code-relationship-graph-engine.md +116 -0
  120. package/docs/adr/0002-major-cleanup-keep-cut.md +91 -0
  121. package/docs/adr/0003-peers-gate-required-layers-optin.md +41 -0
  122. package/docs/adr/0004-code-graph-moves-to-wicked-brain.md +47 -0
  123. package/docs/brain-chunk-format.md +135 -0
  124. package/docs/compiler.md +95 -0
  125. package/docs/daemon-api.md +70 -0
  126. package/docs/domains.md +197 -0
  127. package/docs/getting-started.md +208 -0
  128. package/docs/plans/2026-06-08-wicked-loom-conduct.md +1337 -0
  129. package/docs/plans/2026-06-08-wicked-loom-contract.md +638 -0
  130. package/docs/plans/2026-06-08-wicked-loom-cutover.md +1300 -0
  131. package/docs/plans/2026-06-08-wicked-loom-expand-compose.md +843 -0
  132. package/docs/plans/2026-06-08-wicked-loom-flow-cutover.md +403 -0
  133. package/docs/plans/2026-06-10-codegraph-to-brain-phase1a-graph-core.md +838 -0
  134. package/docs/plans/2026-06-10-codegraph-to-brain-phase1b-injected-edges.md +44 -0
  135. package/docs/required-peers.md +60 -0
  136. package/docs/specs/2026-06-08-wicked-loom-extraction.md +225 -0
  137. package/docs/specs/2026-06-10-codegraph-to-brain-migration.md +168 -0
  138. package/docs/v11/archetypes.md +231 -0
  139. package/hooks/hooks.json +275 -0
  140. package/hooks/scripts/bootstrap.py +1797 -0
  141. package/hooks/scripts/invoke.py +62 -0
  142. package/hooks/scripts/notification.py +166 -0
  143. package/hooks/scripts/permission_request.py +223 -0
  144. package/hooks/scripts/post_tool.py +1374 -0
  145. package/hooks/scripts/pre_compact.py +272 -0
  146. package/hooks/scripts/pre_tool.py +1278 -0
  147. package/hooks/scripts/prompt_submit.py +1109 -0
  148. package/hooks/scripts/session_end.py +95 -0
  149. package/hooks/scripts/stop.py +624 -0
  150. package/hooks/scripts/subagent_lifecycle.py +464 -0
  151. package/hooks/scripts/subscribers/on_gate_decided.py +84 -0
  152. package/hooks/scripts/task_completed.py +322 -0
  153. package/hooks/scripts/worktree_guard.py +148 -0
  154. package/hooks/subscriptions/on_gate_decided.json +9 -0
  155. package/install.mjs +128 -0
  156. package/package.json +41 -0
  157. package/pyproject.toml +59 -0
  158. package/schemas/README.md +32 -0
  159. package/schemas/assert_contracts.json +37 -0
  160. package/schemas/health_probe.json +46 -0
  161. package/schemas/plugin_status.json +37 -0
  162. package/scripts/_adapters/__init__.py +166 -0
  163. package/scripts/_adapters/jira_adapter.py +18 -0
  164. package/scripts/_adapters/linear_adapter.py +18 -0
  165. package/scripts/_adapters/miro_adapter.py +18 -0
  166. package/scripts/_adapters/notion_adapter.py +18 -0
  167. package/scripts/_agents.py +357 -0
  168. package/scripts/_brain_ingest/__init__.py +2 -0
  169. package/scripts/_brain_ingest/session_fact_extractor.py +341 -0
  170. package/scripts/_brain_port.py +163 -0
  171. package/scripts/_bus.py +1081 -0
  172. package/scripts/_bus_catalog_gen.py +93 -0
  173. package/scripts/_bus_consumers.json +46 -0
  174. package/scripts/_bus_emit.py +43 -0
  175. package/scripts/_capability_registry.py +334 -0
  176. package/scripts/_capability_resolver.py +322 -0
  177. package/scripts/_domain_store.py +559 -0
  178. package/scripts/_event_log_reader.py +154 -0
  179. package/scripts/_event_schema.py +305 -0
  180. package/scripts/_event_store.py +397 -0
  181. package/scripts/_heavy_cadence.py +324 -0
  182. package/scripts/_integration_resolver.py +321 -0
  183. package/scripts/_logger.py +151 -0
  184. package/scripts/_loom.py +482 -0
  185. package/scripts/_paths.py +133 -0
  186. package/scripts/_python.sh +22 -0
  187. package/scripts/_run.py +137 -0
  188. package/scripts/_session.py +502 -0
  189. package/scripts/_validate_registry.py +1042 -0
  190. package/scripts/_wicked_testing_probe.py +277 -0
  191. package/scripts/agentic/analyze_agents.py +391 -0
  192. package/scripts/agentic/detect_framework.py +420 -0
  193. package/scripts/agentic/issue_taxonomy.py +357 -0
  194. package/scripts/agentic/pattern_scorer.py +434 -0
  195. package/scripts/classify/persist.py +169 -0
  196. package/scripts/compiler/compile.py +552 -0
  197. package/scripts/compiler/phase0/VERDICT.md +60 -0
  198. package/scripts/compiler/phase0/detect.py +292 -0
  199. package/scripts/compiler/phase0/emit.py +228 -0
  200. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.bindings.json +30 -0
  201. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.lint-output.txt +17 -0
  202. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/failing-tests.txt +4 -0
  203. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/honest-tests.txt +2 -0
  204. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-fail.build.md +8 -0
  205. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-missing.build.md +8 -0
  206. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/honest.build.md +8 -0
  207. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/wg_check_claims.py +174 -0
  208. package/scripts/compiler/phase0/evidence/command_iq.bindings.json +45 -0
  209. package/scripts/compiler/phase0/evidence/command_iq.lint-output.txt +17 -0
  210. package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/failing-tests.txt +4 -0
  211. package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/honest-tests.txt +3 -0
  212. package/scripts/compiler/phase0/evidence/command_iq.stage/fab-fail.build.md +8 -0
  213. package/scripts/compiler/phase0/evidence/command_iq.stage/fab-missing.build.md +8 -0
  214. package/scripts/compiler/phase0/evidence/command_iq.stage/honest.build.md +8 -0
  215. package/scripts/compiler/phase0/evidence/command_iq.stage/wg_check_claims.py +174 -0
  216. package/scripts/compiler/phase0/evidence/memos.bindings.json +28 -0
  217. package/scripts/compiler/phase0/evidence/memos.lint-output.txt +17 -0
  218. package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/failing-tests.txt +4 -0
  219. package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/honest-tests.txt +2 -0
  220. package/scripts/compiler/phase0/evidence/memos.stage/fab-fail.build.md +8 -0
  221. package/scripts/compiler/phase0/evidence/memos.stage/fab-missing.build.md +8 -0
  222. package/scripts/compiler/phase0/evidence/memos.stage/honest.build.md +8 -0
  223. package/scripts/compiler/phase0/evidence/memos.stage/wg_check_claims.py +174 -0
  224. package/scripts/compiler/phase0/evidence/verdict.json +104 -0
  225. package/scripts/compiler/phase0/evidence/wicked-bus.bindings.json +29 -0
  226. package/scripts/compiler/phase0/evidence/wicked-bus.lint-output.txt +17 -0
  227. package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/failing-tests.txt +4 -0
  228. package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/honest-tests.txt +3 -0
  229. package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-fail.build.md +8 -0
  230. package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-missing.build.md +8 -0
  231. package/scripts/compiler/phase0/evidence/wicked-bus.stage/honest.build.md +8 -0
  232. package/scripts/compiler/phase0/evidence/wicked-bus.stage/wg_check_claims.py +174 -0
  233. package/scripts/compiler/phase0/evidence/wire-vault-transcript.txt +60 -0
  234. package/scripts/compiler/phase0/run_probe.py +234 -0
  235. package/scripts/compiler/phase0/wire_vault.py +310 -0
  236. package/scripts/crew/__init__.py +0 -0
  237. package/scripts/crew/_task_audit_writer.py +243 -0
  238. package/scripts/crew/_task_reader.py +389 -0
  239. package/scripts/crew/archetypes_v11.py +348 -0
  240. package/scripts/crew/detectors/__init__.py +12 -0
  241. package/scripts/crew/flow_compiler.py +121 -0
  242. package/scripts/crew/phase_manager.py +703 -0
  243. package/scripts/crew/scope_delta.py +264 -0
  244. package/scripts/crew/specialist_resolver.py +218 -0
  245. package/scripts/crew/stack_registry.py +189 -0
  246. package/scripts/data/data_profiler.py +271 -0
  247. package/scripts/data/ontology_recommender.py +231 -0
  248. package/scripts/data/schema_validator.py +267 -0
  249. package/scripts/delivery/drift.py +739 -0
  250. package/scripts/delivery/telemetry.py +614 -0
  251. package/scripts/engineering/patch/codegraph_db.py +125 -0
  252. package/scripts/engineering/patch/generators/__init__.py +56 -0
  253. package/scripts/engineering/patch/generators/base.py +373 -0
  254. package/scripts/engineering/patch/generators/csharp_generator.py +494 -0
  255. package/scripts/engineering/patch/generators/go_generator.py +430 -0
  256. package/scripts/engineering/patch/generators/java_generator.py +928 -0
  257. package/scripts/engineering/patch/generators/jsp_generator.py +454 -0
  258. package/scripts/engineering/patch/generators/kotlin_generator.py +561 -0
  259. package/scripts/engineering/patch/generators/perl_generator.py +510 -0
  260. package/scripts/engineering/patch/generators/php_generator.py +644 -0
  261. package/scripts/engineering/patch/generators/propagation_engine.py +929 -0
  262. package/scripts/engineering/patch/generators/python_generator.py +487 -0
  263. package/scripts/engineering/patch/generators/ruby_generator.py +463 -0
  264. package/scripts/engineering/patch/generators/rust_generator.py +400 -0
  265. package/scripts/engineering/patch/generators/sql_generator.py +594 -0
  266. package/scripts/engineering/patch/generators/typescript_generator.py +439 -0
  267. package/scripts/engineering/patch/patch.py +800 -0
  268. package/scripts/engineering/patch/safety.py +429 -0
  269. package/scripts/jam/__init__.py +0 -0
  270. package/scripts/jam/_bus_consumers.py +271 -0
  271. package/scripts/jam/agentic_cli_registry.py +703 -0
  272. package/scripts/jam/consensus.py +737 -0
  273. package/scripts/jam/detect_clis.py +409 -0
  274. package/scripts/jam/jam.py +283 -0
  275. package/scripts/jam/save_transcript.py +171 -0
  276. package/scripts/loom/__init__.py +22 -0
  277. package/scripts/loom/cli.py +170 -0
  278. package/scripts/loom/compose.py +180 -0
  279. package/scripts/loom/gate.py +120 -0
  280. package/scripts/loom/manifest.py +140 -0
  281. package/scripts/loom/resolve.py +59 -0
  282. package/scripts/persona/__init__.py +0 -0
  283. package/scripts/persona/registry.py +688 -0
  284. package/scripts/platform/guard_pipeline.py +1214 -0
  285. package/scripts/platform/guard_profiles.py +216 -0
  286. package/scripts/platform/observability/assert_contracts.py +434 -0
  287. package/scripts/platform/observability/health_probe.py +915 -0
  288. package/scripts/platform/observability/ops_log_viewer.py +209 -0
  289. package/scripts/platform/prereq_doctor.py +567 -0
  290. package/scripts/qe/conditions_manifest.py +260 -0
  291. package/scripts/qe/content_sanitizer.py +160 -0
  292. package/scripts/qe/coverage_tracker.py +535 -0
  293. package/scripts/qe/discover_scenarios.py +243 -0
  294. package/scripts/qe/evidence_tracker.py +232 -0
  295. package/scripts/qe/prove.py +196 -0
  296. package/scripts/qe/registry_lookup.py +80 -0
  297. package/scripts/qe/registry_store.py +176 -0
  298. package/scripts/qe/semantic_review.py +1005 -0
  299. package/scripts/qe/vault_gate.py +382 -0
  300. package/scripts/qe/verdict_audit.py +175 -0
  301. package/scripts/qe/verdict_schema.py +335 -0
  302. package/scripts/reset.py +220 -0
  303. package/scripts/resolve_path.py +22 -0
  304. package/scripts/sentinel/invariants.py +402 -0
  305. package/scripts/sentinel/pre_push.py +73 -0
  306. package/scripts/setup/__init__.py +1 -0
  307. package/scripts/setup/detect_state.py +114 -0
  308. package/scripts/setup/migrate_legacy.py +67 -0
  309. package/scripts/setup/migrate_v6_projects.py +232 -0
  310. package/scripts/setup/onboarding.py +114 -0
  311. package/scripts/smaht/_bus_consumers.py +98 -0
  312. package/scripts/smaht/adapters/__init__.py +83 -0
  313. package/scripts/smaht/adapters/brain_adapter.py +254 -0
  314. package/scripts/smaht/adapters/context7_adapter.py +438 -0
  315. package/scripts/smaht/adapters/delegation_adapter.py +104 -0
  316. package/scripts/smaht/adapters/domain_adapter.py +206 -0
  317. package/scripts/smaht/adapters/events_adapter.py +231 -0
  318. package/scripts/smaht/adapters/tools_adapter.py +49 -0
  319. package/scripts/smaht/cheatsheet_store.py +236 -0
  320. package/scripts/smaht/context_package.py +386 -0
  321. package/scripts/smaht/knowledge_graph.py +395 -0
  322. package/scripts/smaht/propose_skills.py +856 -0
  323. package/scripts/smaht/test_cheatsheet_store.py +428 -0
  324. package/scripts/statusline.py +151 -0
  325. package/scripts/where_am_i.py +236 -0
  326. package/skills/agentic/agentic-patterns/SKILL.md +91 -0
  327. package/skills/agentic/agentic-patterns/refs/anti-patterns-design.md +283 -0
  328. package/skills/agentic/agentic-patterns/refs/anti-patterns-operational.md +216 -0
  329. package/skills/agentic/agentic-patterns/refs/pattern-catalog.md +329 -0
  330. package/skills/agentic/context-engineering/SKILL.md +142 -0
  331. package/skills/agentic/context-engineering/refs/caching-and-optimization.md +251 -0
  332. package/skills/agentic/context-engineering/refs/compression-techniques.md +171 -0
  333. package/skills/agentic/context-engineering/refs/cost-calculation-budget.md +250 -0
  334. package/skills/agentic/context-engineering/refs/cost-optimization-reporting.md +300 -0
  335. package/skills/agentic/context-engineering/refs/selective-loading.md +179 -0
  336. package/skills/agentic/frameworks/SKILL.md +191 -0
  337. package/skills/agentic/frameworks/refs/framework-profiles-1.md +209 -0
  338. package/skills/agentic/frameworks/refs/framework-profiles-2.md +214 -0
  339. package/skills/agentic/frameworks/refs/migration-patterns-paths.md +267 -0
  340. package/skills/agentic/frameworks/refs/migration-patterns-testing.md +208 -0
  341. package/skills/agentic/refs/audit.md +134 -0
  342. package/skills/agentic/refs/design.md +137 -0
  343. package/skills/agentic/refs/frameworks.md +102 -0
  344. package/skills/agentic/refs/review.md +160 -0
  345. package/skills/agentic/review-methodology/SKILL.md +186 -0
  346. package/skills/agentic/review-methodology/refs/deliverable-templates.md +246 -0
  347. package/skills/agentic/review-methodology/refs/issue-taxonomy-quality-testing.md +277 -0
  348. package/skills/agentic/review-methodology/refs/issue-taxonomy-reliability-safety.md +253 -0
  349. package/skills/agentic/trust-and-safety/SKILL.md +177 -0
  350. package/skills/agentic/trust-and-safety/refs/guardrails-actions.md +246 -0
  351. package/skills/agentic/trust-and-safety/refs/guardrails-input-output.md +238 -0
  352. package/skills/agentic/trust-and-safety/refs/guardrails-resources.md +209 -0
  353. package/skills/agentic/trust-and-safety/refs/safety-checklist-advanced.md +209 -0
  354. package/skills/agentic/trust-and-safety/refs/safety-checklist-core.md +215 -0
  355. package/skills/archetype/SKILL.md +104 -0
  356. package/skills/archetype/refs/build.md +142 -0
  357. package/skills/archetype/refs/decide.md +117 -0
  358. package/skills/archetype/refs/explore.md +66 -0
  359. package/skills/archetype/refs/incident.md +149 -0
  360. package/skills/archetype/refs/migrate.md +170 -0
  361. package/skills/archetype/refs/modernize.md +187 -0
  362. package/skills/archetype/refs/review.md +145 -0
  363. package/skills/archetype/refs/ship.md +117 -0
  364. package/skills/archetype/refs/specify.md +108 -0
  365. package/skills/archetype/refs/triage.md +62 -0
  366. package/skills/classify/SKILL.md +157 -0
  367. package/skills/data/analysis/SKILL.md +125 -0
  368. package/skills/data/analysis/refs/templates.md +170 -0
  369. package/skills/data/data/SKILL.md +118 -0
  370. package/skills/data/data/refs/examples.md +235 -0
  371. package/skills/data/ml/SKILL.md +125 -0
  372. package/skills/data/ml/refs/templates.md +172 -0
  373. package/skills/data/pipeline/SKILL.md +136 -0
  374. package/skills/data/pipeline/refs/templates.md +175 -0
  375. package/skills/data/refs/analyze.md +123 -0
  376. package/skills/data/refs/data.md +95 -0
  377. package/skills/data/refs/ml.md +118 -0
  378. package/skills/data/refs/pipeline.md +92 -0
  379. package/skills/deliberate/SKILL.md +125 -0
  380. package/skills/deliberate/refs/architecture-lens.md +37 -0
  381. package/skills/deliberate/refs/assumptions-lens.md +43 -0
  382. package/skills/deliberate/refs/code-lens.md +38 -0
  383. package/skills/deliberate/refs/content-lens.md +37 -0
  384. package/skills/deliberate/refs/data-lens.md +43 -0
  385. package/skills/deliberate/refs/design-lens.md +37 -0
  386. package/skills/deliberate/refs/opportunity-patterns.md +107 -0
  387. package/skills/deliberate/refs/ops-lens.md +43 -0
  388. package/skills/deliberate/refs/product-lens.md +46 -0
  389. package/skills/deliberate/refs/rethink-framework.md +77 -0
  390. package/skills/deliberate/refs/security-lens.md +47 -0
  391. package/skills/deliberate/refs/testing-lens.md +45 -0
  392. package/skills/deliberate/refs/timing-lens.md +42 -0
  393. package/skills/engineering/architecture/SKILL.md +177 -0
  394. package/skills/engineering/architecture/refs/adr-template.md +268 -0
  395. package/skills/engineering/architecture/refs/architecture-template-deployment.md +176 -0
  396. package/skills/engineering/architecture/refs/architecture-template-design.md +300 -0
  397. package/skills/engineering/architecture/refs/examples-ecommerce-analytics.md +299 -0
  398. package/skills/engineering/architecture/refs/examples-saas-trading.md +291 -0
  399. package/skills/engineering/architecture/refs/patterns-advanced.md +238 -0
  400. package/skills/engineering/architecture/refs/patterns-structural.md +303 -0
  401. package/skills/engineering/backend/SKILL.md +102 -0
  402. package/skills/engineering/backend/refs/checklists.md +146 -0
  403. package/skills/engineering/backend/refs/patterns.md +181 -0
  404. package/skills/engineering/debugging/SKILL.md +99 -0
  405. package/skills/engineering/debugging/refs/patterns.md +248 -0
  406. package/skills/engineering/debugging/refs/process.md +203 -0
  407. package/skills/engineering/docs/SKILL.md +97 -0
  408. package/skills/engineering/engineering/SKILL.md +88 -0
  409. package/skills/engineering/engineering/refs/checklists.md +91 -0
  410. package/skills/engineering/engineering/refs/templates.md +71 -0
  411. package/skills/engineering/frontend/SKILL.md +92 -0
  412. package/skills/engineering/frontend/refs/checklists.md +96 -0
  413. package/skills/engineering/frontend/refs/patterns.md +167 -0
  414. package/skills/engineering/integration/SKILL.md +183 -0
  415. package/skills/engineering/integration/refs/error-handling-best-practices.md +139 -0
  416. package/skills/engineering/integration/refs/error-handling-error-classes-typescript.md +212 -0
  417. package/skills/engineering/integration/refs/error-handling-error-response-format.md +301 -0
  418. package/skills/engineering/integration/refs/error-handling-retry-strategies.md +190 -0
  419. package/skills/engineering/integration/refs/event-schemas-best-practices.md +225 -0
  420. package/skills/engineering/integration/refs/event-schemas-event-naming-conventions.md +303 -0
  421. package/skills/engineering/integration/refs/event-schemas-event-structure.md +288 -0
  422. package/skills/engineering/integration/refs/graphql-best-practices.md +138 -0
  423. package/skills/engineering/integration/refs/graphql-error-handling.md +198 -0
  424. package/skills/engineering/integration/refs/graphql-graphql-basics.md +197 -0
  425. package/skills/engineering/integration/refs/graphql-query-examples.md +226 -0
  426. package/skills/engineering/integration/refs/graphql-schema-design-patterns.md +280 -0
  427. package/skills/engineering/integration/refs/grpc-grpc-overview.md +246 -0
  428. package/skills/engineering/integration/refs/grpc-implementation-examples.md +269 -0
  429. package/skills/engineering/integration/refs/grpc-metadata-headers.md +304 -0
  430. package/skills/engineering/integration/refs/grpc-testing.md +49 -0
  431. package/skills/engineering/integration/refs/openapi-template.yaml +682 -0
  432. package/skills/engineering/integration/refs/resilience-best-practices.md +109 -0
  433. package/skills/engineering/integration/refs/resilience-circuit-breaker-pattern.md +302 -0
  434. package/skills/engineering/integration/refs/resilience-rate-limiting.md +245 -0
  435. package/skills/engineering/integration/refs/resilience-timeout-pattern.md +212 -0
  436. package/skills/engineering/integration/refs/rest-api-fundamentals.md +299 -0
  437. package/skills/engineering/integration/refs/rest-api-responses-security.md +302 -0
  438. package/skills/engineering/integration/refs/versioning-breaking-changes.md +237 -0
  439. package/skills/engineering/integration/refs/versioning-migration-strategies.md +257 -0
  440. package/skills/engineering/integration/refs/versioning-versioning-strategies.md +296 -0
  441. package/skills/engineering/large-scale-migration/SKILL.md +65 -0
  442. package/skills/engineering/patch/SKILL.md +184 -0
  443. package/skills/engineering/refs/arch.md +126 -0
  444. package/skills/engineering/refs/debug.md +142 -0
  445. package/skills/engineering/refs/docs.md +190 -0
  446. package/skills/engineering/refs/plan.md +109 -0
  447. package/skills/engineering/refs/review.md +138 -0
  448. package/skills/engineering/system-design/SKILL.md +154 -0
  449. package/skills/engineering/system-design/refs/anti-patterns-big-ball-of-mud.md +254 -0
  450. package/skills/engineering/system-design/refs/anti-patterns-circular-dependencies.md +241 -0
  451. package/skills/engineering/system-design/refs/anti-patterns-feature-envy.md +168 -0
  452. package/skills/engineering/system-design/refs/anti-patterns-god-object.md +247 -0
  453. package/skills/engineering/system-design/refs/component-template-lifecycle.md +210 -0
  454. package/skills/engineering/system-design/refs/component-template-maintenance.md +219 -0
  455. package/skills/engineering/system-design/refs/component-template-structure.md +276 -0
  456. package/skills/engineering/system-design/refs/dependencies-best-practices.md +260 -0
  457. package/skills/engineering/system-design/refs/dependencies-dependency-principles.md +295 -0
  458. package/skills/engineering/system-design/refs/dependencies-dependency-tracking.md +261 -0
  459. package/skills/engineering/system-design/refs/interface-template-lifecycle.md +211 -0
  460. package/skills/engineering/system-design/refs/interface-template-maintenance.md +212 -0
  461. package/skills/engineering/system-design/refs/interface-template-structure.md +269 -0
  462. package/skills/engineering/system-design/refs/patterns-dependency-injection.md +151 -0
  463. package/skills/engineering/system-design/refs/patterns-facade-pattern.md +257 -0
  464. package/skills/engineering/system-design/refs/patterns-layered-pattern.md +204 -0
  465. package/skills/engineering/system-design/refs/patterns-plugin-architecture.md +229 -0
  466. package/skills/engineering/unit-test-quality/SKILL.md +194 -0
  467. package/skills/ground/SKILL.md +130 -0
  468. package/skills/integration-discovery/SKILL.md +168 -0
  469. package/skills/integration-discovery/refs/capabilities.md +282 -0
  470. package/skills/integration-discovery/refs/cli-detection.md +295 -0
  471. package/skills/integration-discovery/refs/discovery-sources.md +233 -0
  472. package/skills/integration-discovery/refs/task-patterns.md +206 -0
  473. package/skills/jam/SKILL.md +45 -0
  474. package/skills/jam/refs/facilitation-patterns.md +125 -0
  475. package/skills/jam/refs/quick.md +64 -0
  476. package/skills/jam/refs/synthesis-patterns.md +114 -0
  477. package/skills/multi-model/SKILL.md +168 -0
  478. package/skills/multi-model/refs/aichat.md +119 -0
  479. package/skills/multi-model/refs/aider.md +100 -0
  480. package/skills/multi-model/refs/auditability.md +238 -0
  481. package/skills/multi-model/refs/codex.md +169 -0
  482. package/skills/multi-model/refs/context.md +306 -0
  483. package/skills/multi-model/refs/copilot.md +161 -0
  484. package/skills/multi-model/refs/examples.md +224 -0
  485. package/skills/multi-model/refs/gemini.md +185 -0
  486. package/skills/multi-model/refs/goose.md +112 -0
  487. package/skills/multi-model/refs/llm.md +124 -0
  488. package/skills/multi-model/refs/opencode.md +196 -0
  489. package/skills/multi-model/refs/orchestration.md +188 -0
  490. package/skills/multi-model/refs/pi.md +208 -0
  491. package/skills/persona/SKILL.md +144 -0
  492. package/skills/persona/refs/define.md +133 -0
  493. package/skills/platform/actions/refs/actions.md +114 -0
  494. package/skills/platform/audit/SKILL.md +174 -0
  495. package/skills/platform/audit/refs/audit.md +145 -0
  496. package/skills/platform/audit/refs/checklists-evidence-operations.md +144 -0
  497. package/skills/platform/audit/refs/checklists-gdpr-pci-evidence.md +213 -0
  498. package/skills/platform/audit/refs/checklists-soc2-hipaa.md +120 -0
  499. package/skills/platform/audit/refs/frameworks-gdpr-pci.md +225 -0
  500. package/skills/platform/audit/refs/frameworks-soc2-hipaa.md +228 -0
  501. package/skills/platform/compliance/SKILL.md +169 -0
  502. package/skills/platform/compliance/refs/checklists.md +303 -0
  503. package/skills/platform/compliance/refs/compliance.md +117 -0
  504. package/skills/platform/compliance/refs/frameworks.md +282 -0
  505. package/skills/platform/errors/SKILL.md +183 -0
  506. package/skills/platform/errors/refs/patterns.md +271 -0
  507. package/skills/platform/errors/refs/severity.md +264 -0
  508. package/skills/platform/gate-benchmark-rebaseline/SKILL.md +108 -0
  509. package/skills/platform/gh/refs/gh.md +105 -0
  510. package/skills/platform/gh-cli/SKILL.md +120 -0
  511. package/skills/platform/gh-cli/refs/automation.md +63 -0
  512. package/skills/platform/gh-cli/refs/gh-ops.md +103 -0
  513. package/skills/platform/gh-cli/refs/patterns.md +132 -0
  514. package/skills/platform/gh-cli/scripts/gh_ops.py +454 -0
  515. package/skills/platform/github-actions/SKILL.md +159 -0
  516. package/skills/platform/github-actions/refs/security.md +150 -0
  517. package/skills/platform/github-actions/refs/templates.md +230 -0
  518. package/skills/platform/github-actions/refs/troubleshooting.md +174 -0
  519. package/skills/platform/github-actions/scripts/workflow_gen.py +215 -0
  520. package/skills/platform/gitlab-ci/SKILL.md +140 -0
  521. package/skills/platform/gitlab-ci/refs/templates.md +223 -0
  522. package/skills/platform/gitlab-ci/refs/troubleshooting.md +213 -0
  523. package/skills/platform/glab-cli/SKILL.md +133 -0
  524. package/skills/platform/glab-cli/refs/ci-debugging.md +95 -0
  525. package/skills/platform/glab-cli/refs/glab-ops.md +78 -0
  526. package/skills/platform/glab-cli/refs/patterns.md +131 -0
  527. package/skills/platform/glab-cli/scripts/glab_ops.py +313 -0
  528. package/skills/platform/health/SKILL.md +177 -0
  529. package/skills/platform/health/refs/health.md +72 -0
  530. package/skills/platform/health/refs/sources.md +302 -0
  531. package/skills/platform/incident/refs/incident.md +136 -0
  532. package/skills/platform/infra/refs/infra.md +104 -0
  533. package/skills/platform/observability/SKILL.md +128 -0
  534. package/skills/platform/observability/refs/toolchain-discovery.md +243 -0
  535. package/skills/platform/prereq-doctor/SKILL.md +57 -0
  536. package/skills/platform/prereq-doctor/refs/tool-registry.md +58 -0
  537. package/skills/platform/traces/refs/traces.md +101 -0
  538. package/skills/product/acceptance-criteria/SKILL.md +193 -0
  539. package/skills/product/acceptance-criteria/refs/ac-anti-patterns.md +291 -0
  540. package/skills/product/acceptance-criteria/refs/ac-examples.md +277 -0
  541. package/skills/product/accessibility/SKILL.md +197 -0
  542. package/skills/product/accessibility/refs/aria-patterns-basics.md +250 -0
  543. package/skills/product/accessibility/refs/aria-patterns-dynamic.md +187 -0
  544. package/skills/product/accessibility/refs/aria-patterns-interactive.md +246 -0
  545. package/skills/product/accessibility/refs/audit-report-findings.md +248 -0
  546. package/skills/product/accessibility/refs/audit-report-results.md +276 -0
  547. package/skills/product/accessibility/refs/common-violations-html-css.md +270 -0
  548. package/skills/product/accessibility/refs/common-violations-interactive.md +303 -0
  549. package/skills/product/accessibility/refs/keyboard-testing-basics.md +222 -0
  550. package/skills/product/accessibility/refs/keyboard-testing-patterns.md +173 -0
  551. package/skills/product/accessibility/refs/screen-reader-testing-advanced.md +294 -0
  552. package/skills/product/accessibility/refs/screen-reader-testing-commands.md +255 -0
  553. package/skills/product/accessibility/refs/wcag-checklist.md +262 -0
  554. package/skills/product/analyze/SKILL.md +164 -0
  555. package/skills/product/analyze/refs/algorithms.md +238 -0
  556. package/skills/product/analyze/refs/sentiment-patterns.md +180 -0
  557. package/skills/product/imagery/SKILL.md +97 -0
  558. package/skills/product/imagery/alter/SKILL.md +105 -0
  559. package/skills/product/imagery/alter/refs/editing-reference.md +146 -0
  560. package/skills/product/imagery/create/SKILL.md +109 -0
  561. package/skills/product/imagery/create/refs/prompt-engineering.md +112 -0
  562. package/skills/product/imagery/create/refs/provider-reference.md +219 -0
  563. package/skills/product/imagery/review/SKILL.md +101 -0
  564. package/skills/product/imagery/review/refs/analysis-lenses.md +136 -0
  565. package/skills/product/imagery/review/refs/quality-gates.md +153 -0
  566. package/skills/product/imagery/scripts/analyze.sh +23 -0
  567. package/skills/product/imagery/scripts/edit.sh +14 -0
  568. package/skills/product/imagery/scripts/generate.sh +13 -0
  569. package/skills/product/imagery/scripts/provider.py +787 -0
  570. package/skills/product/listen/SKILL.md +175 -0
  571. package/skills/product/listen/refs/channels.md +220 -0
  572. package/skills/product/mockup/SKILL.md +106 -0
  573. package/skills/product/mockup/refs/templates.md +95 -0
  574. package/skills/product/refs/a11y.md +109 -0
  575. package/skills/product/refs/acceptance.md +79 -0
  576. package/skills/product/refs/align.md +67 -0
  577. package/skills/product/refs/analyze.md +77 -0
  578. package/skills/product/refs/elicit.md +67 -0
  579. package/skills/product/refs/listen.md +58 -0
  580. package/skills/product/refs/mockup.md +77 -0
  581. package/skills/product/refs/screenshot.md +59 -0
  582. package/skills/product/refs/strategy.md +77 -0
  583. package/skills/product/refs/synthesize.md +54 -0
  584. package/skills/product/refs/ux-review.md +68 -0
  585. package/skills/product/refs/ux.md +101 -0
  586. package/skills/product/requirements-analysis/SKILL.md +136 -0
  587. package/skills/product/requirements-analysis/refs/requirements-example-auth.md +264 -0
  588. package/skills/product/requirements-analysis/refs/requirements-example-export-integration.md +88 -0
  589. package/skills/product/requirements-analysis/refs/requirements-output-format-template.md +247 -0
  590. package/skills/product/requirements-analysis/refs/user-story-guide.md +296 -0
  591. package/skills/product/requirements-graph/SKILL.md +155 -0
  592. package/skills/product/requirements-graph/refs/examples.md +223 -0
  593. package/skills/product/requirements-graph/refs/schema.md +162 -0
  594. package/skills/product/requirements-migrate/SKILL.md +90 -0
  595. package/skills/product/requirements-navigate/SKILL.md +141 -0
  596. package/skills/product/requirements-navigate/refs/meta-templates.md +141 -0
  597. package/skills/product/screenshot/SKILL.md +147 -0
  598. package/skills/product/strategy/SKILL.md +198 -0
  599. package/skills/product/strategy/refs/frameworks.md +295 -0
  600. package/skills/product/strategy/refs/templates-competitive-market.md +299 -0
  601. package/skills/product/strategy/refs/templates-roi-value.md +207 -0
  602. package/skills/product/synthesize/SKILL.md +116 -0
  603. package/skills/product/synthesize/refs/journey-mapping.md +212 -0
  604. package/skills/product/synthesize/refs/prioritization.md +193 -0
  605. package/skills/product/ux-review/SKILL.md +164 -0
  606. package/skills/product/visual-direction/SKILL.md +137 -0
  607. package/skills/product/visual-review/SKILL.md +131 -0
  608. package/skills/runtime-exec/SKILL.md +138 -0
  609. package/skills/search/codebase-narrator/SKILL.md +131 -0
  610. package/skills/search/codebase-narrator/refs/output-template.md +100 -0
  611. package/skills/smaht/SKILL.md +72 -0
  612. package/skills/smaht/discovery/SKILL.md +65 -0
  613. package/skills/smaht/intent/SKILL.md +89 -0
  614. package/skills/smaht/propose-skills/SKILL.md +142 -0
  615. package/skills/smaht/refs/state.md +76 -0
  616. package/skills/swarm/SKILL.md +132 -0
  617. package/skills/swarm/refs/fan-out.md +104 -0
  618. package/skills/swarm/refs/independent-verification.md +86 -0
  619. package/skills/swarm/refs/receipts-and-evidence.md +69 -0
  620. package/skills/swarm/refs/recon-synthesis.md +87 -0
  621. package/skills/swarm/refs/ship-discipline.md +90 -0
  622. package/skills/wickedizer/SKILL.md +147 -0
  623. package/skills/wickedizer/refs/artifact-types.md +238 -0
  624. package/skills/wickedizer/refs/complexity.md +278 -0
  625. package/skills/wickedizer/refs/de-ai-pass.md +140 -0
  626. package/skills/wickedizer/refs/failure-modes.md +249 -0
  627. package/skills/wickedizer/refs/patterns.md +282 -0
  628. package/skills/wickedizer/refs/review.md +221 -0
  629. package/skills/wickedizer/refs/structure.md +282 -0
  630. package/skills/wickedizer/refs/voice-profile.md +125 -0
  631. package/skills/workflow/SKILL.md +132 -0
  632. package/skills/workflow/refs/archetype-adjustments.md +205 -0
  633. package/skills/workflow/refs/evidence.md +58 -0
  634. package/skills/workflow/refs/integration.md +130 -0
  635. package/skills/workflow/refs/risk-dimension-signals.md +260 -0
  636. package/skills/workflow/refs/scoring-rubric.md +49 -0
  637. package/skills/workflow/refs/signal-keywords.md +176 -0
  638. package/skills/workflow/refs/specialist-routing-rules.md +159 -0
  639. package/skills/worktrees/SKILL.md +87 -0
  640. package/skills/worktrees/refs/recipes.md +96 -0
@@ -0,0 +1,464 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SubagentStart / SubagentStop hook — wicked-garden agent lifecycle tracking.
4
+
5
+ Issue #330: Track subagent start/stop events for observability and crew coordination.
6
+ Issue #365: Record specialist engagement for approve-command gate enforcement.
7
+
8
+ Receives the lifecycle phase as the first CLI argument ("start" or "stop").
9
+ Reads the hook payload from stdin (JSON with agent metadata).
10
+
11
+ Responsibilities:
12
+ SubagentStart:
13
+ - Log agent launch to ops logger
14
+ - Track active subagent count in session state
15
+ - Record agent start time for duration tracking
16
+ SubagentStop:
17
+ - Log agent completion to ops logger
18
+ - Decrement active subagent count
19
+ - Calculate and record duration
20
+ - Write trace entry for the subagent execution
21
+ - Record specialist engagement to phases/{phase}/specialist-engagement.json
22
+
23
+ Always fails open — any unhandled exception returns {"continue": true}.
24
+ """
25
+
26
+ import json
27
+ import os
28
+ import sys
29
+ import time
30
+ from datetime import datetime, timezone
31
+ from pathlib import Path
32
+
33
+ # Add shared scripts directory to path
34
+ _PLUGIN_ROOT = Path(os.environ.get("CLAUDE_PLUGIN_ROOT", Path(__file__).resolve().parents[2]))
35
+ sys.path.insert(0, str(_PLUGIN_ROOT / "scripts"))
36
+
37
+
38
+ # Map from task metadata.event_type to procedure bundle injected at SubagentStart
39
+ _EVENT_TYPE_PROCEDURES: dict = {
40
+ "coding-task": (
41
+ "[Bulletproof Coding Standards] R1: No dead code. R2: No bare panics — "
42
+ "all errors handled and logged. R3: No magic values — use named constants. "
43
+ "R4: No swallowed errors — propagate or log with context. "
44
+ "R5: No unbounded ops — all loops/queries have limits. "
45
+ "R6: No god functions — max 50 lines, single responsibility."
46
+ ),
47
+ "gate-finding": (
48
+ "[Gate Finding Protocol] Document the finding with: what was observed, "
49
+ "what standard was violated, severity (BLOCK/WARN/INFO), and suggested fix. "
50
+ "Reference the specific requirement or quality rule that applies."
51
+ ),
52
+ "phase-transition": (
53
+ "[Phase Transition Protocol] Verify all gate conditions are met before "
54
+ "advancing. Write a transition summary: what was completed, what evidence "
55
+ "exists, what the next phase expects as input."
56
+ ),
57
+ "subtask": (
58
+ "[Subtask Execution] You are executing a subtask. Scope is narrow — "
59
+ "complete exactly what was assigned. Report back with structured output: "
60
+ "what was done, what evidence exists, any blockers found."
61
+ ),
62
+ "procedure-trigger": (
63
+ "[Procedure Execution] Follow the procedure exactly as specified. "
64
+ "Do not improvise or skip steps. Record each step's outcome."
65
+ ),
66
+ }
67
+
68
+
69
+ # ---------------------------------------------------------------------------
70
+ # Active task event_type reader — routed via _task_reader (#596 v8-PR-2)
71
+ # ---------------------------------------------------------------------------
72
+ #
73
+ # WG_DAEMON_ENABLED=false (default): direct file read, bit-identical to pre-PR-2.
74
+ # WG_DAEMON_ENABLED=true: daemon HTTP with 45ms timeout + file fallback.
75
+ # WG_DAEMON_ENABLED=always: daemon HTTP only.
76
+ #
77
+ # _task_reader is stdlib-only and imported lazily so this hook remains
78
+ # fail-open even if the scripts/ directory is not on sys.path yet.
79
+
80
+
81
+ def _get_active_task_event_type(session_id: str) -> "str | None":
82
+ """Return event_type of the most-recently-modified in-progress native task.
83
+
84
+ Fail-silent — never blocks the hook. Routing is delegated to
85
+ scripts/crew/_task_reader.py per #596.
86
+ """
87
+ if not session_id:
88
+ return None
89
+ try:
90
+ from crew._task_reader import get_active_task_event_type # type: ignore[import]
91
+ return get_active_task_event_type(session_id)
92
+ except Exception:
93
+ return None
94
+
95
+
96
+ # ---------------------------------------------------------------------------
97
+ # Ops logger wrapper — fail-silent, never crashes the hook
98
+ # ---------------------------------------------------------------------------
99
+
100
+ def _log(domain, level, event, ok=True, ms=None, detail=None):
101
+ """Ops logger — fail-silent, never crashes the hook."""
102
+ try:
103
+ from _logger import log
104
+ log(domain, level, event, ok=ok, ms=ms, detail=detail)
105
+ except Exception:
106
+ pass
107
+
108
+
109
+ def _now_iso() -> str:
110
+ return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
111
+
112
+
113
+ def _sanitize_session_id(raw: str) -> str:
114
+ """Strip path separators and traversal sequences from session ID."""
115
+ sanitized = raw.replace("/", "_").replace("\\", "_").replace("..", "_")
116
+ return sanitized if sanitized else "default"
117
+
118
+
119
+ def _get_session_id() -> str:
120
+ return _sanitize_session_id(os.environ.get("CLAUDE_SESSION_ID", "default"))
121
+
122
+
123
+ # ---------------------------------------------------------------------------
124
+ # Trace writer — append JSONL to session trace file
125
+ # ---------------------------------------------------------------------------
126
+
127
+ def _write_trace(entry: dict) -> None:
128
+ """Append a trace entry to the session JSONL trace file."""
129
+ try:
130
+ import tempfile
131
+ session_id = _get_session_id()
132
+ trace_dir = Path(tempfile.gettempdir()) / "wicked-garden" / "traces"
133
+ trace_dir.mkdir(parents=True, exist_ok=True)
134
+ trace_file = trace_dir / f"{session_id}.jsonl"
135
+ with open(trace_file, "a") as f:
136
+ f.write(json.dumps(entry) + "\n")
137
+ except Exception:
138
+ pass
139
+
140
+
141
+ # ---------------------------------------------------------------------------
142
+ # Specialist engagement tracking (Issue #365)
143
+ # ---------------------------------------------------------------------------
144
+
145
+ def _load_specialist_domains() -> set:
146
+ """Return the set of specialist domain names from specialist.json.
147
+
148
+ Reads .claude-plugin/specialist.json relative to CLAUDE_PLUGIN_ROOT.
149
+ Returns an empty set on any error so the hook stays fail-open.
150
+ """
151
+ try:
152
+ specialist_path = _PLUGIN_ROOT / ".claude-plugin" / "specialist.json"
153
+ data = json.loads(specialist_path.read_text(encoding="utf-8"))
154
+ return {s["name"] for s in data.get("specialists", []) if "name" in s}
155
+ except Exception:
156
+ return set()
157
+
158
+
159
+ def _parse_specialist_from_agent_type(agent_type: str, specialist_domains: set):
160
+ """Parse domain and agent name from a subagent identifier (Issue #573).
161
+
162
+ Two accepted forms:
163
+
164
+ * Fully-qualified: ``wicked-garden:{domain}:{agent-name}`` — parsed in
165
+ place, no resolver needed. The domain must be a known specialist
166
+ domain (``specialist_domains`` from ``specialist.json``) for the
167
+ engagement tracker to accept it.
168
+ * Bare role: ``requirements-analyst`` — expanded to the full form by
169
+ :mod:`crew.specialist_resolver`, which walks ``agents/**/*.md``
170
+ frontmatter. This is the path the facilitator emits by default.
171
+
172
+ Returns ``(domain, agent_name)`` on success, ``(None, None)`` when
173
+ the name cannot be resolved. The hook remains fail-open on any
174
+ resolver import / walk error (engagement tracking is best-effort).
175
+ """
176
+ if not agent_type:
177
+ return None, None
178
+
179
+ if agent_type.startswith("wicked-garden:"):
180
+ parts = agent_type.split(":")
181
+ # Expect at least 3 parts: "wicked-garden", domain, agent-name
182
+ if len(parts) < 3:
183
+ return None, None
184
+
185
+ domain = parts[1]
186
+ agent_name = ":".join(parts[2:]) # preserve any colons in agent name
187
+
188
+ if domain not in specialist_domains:
189
+ return None, None
190
+
191
+ return domain, agent_name
192
+
193
+ # Bare-role path (Issue #573): resolve via agents/**/*.md frontmatter.
194
+ # Fail-closed to the old behavior on any resolver error — engagement
195
+ # tracking is best-effort and the hook must never block the agent.
196
+ try:
197
+ from crew.specialist_resolver import build_resolver, resolve_role
198
+
199
+ resolver = build_resolver(_PLUGIN_ROOT)
200
+ domain, subagent_type = resolve_role(agent_type, resolver)
201
+ if domain is None or subagent_type is None:
202
+ return None, None
203
+ if domain not in specialist_domains:
204
+ return None, None
205
+ # The tracker stores bare role as the agent_name — callers feed
206
+ # it straight into the engagement ledger, matching the existing
207
+ # wicked-garden:{domain}:{role} parsing shape.
208
+ return domain, agent_type
209
+ except Exception:
210
+ return None, None
211
+
212
+
213
+ def _record_specialist_engagement(domain: str, agent_name: str) -> None:
214
+ """Append a specialist engagement entry to the active phase directory.
215
+
216
+ Writes to:
217
+ {project_dir}/phases/{current_phase}/specialist-engagement.jsonl
218
+
219
+ Site W9 of bus-cutover wave-2 (#746):
220
+ * W9a refactor (this PR): switched from JSON array (read-modify-write)
221
+ to JSONL (append-only). The append-only form aligns with the
222
+ bus-as-truth premise — events are append-only, so the on-disk
223
+ projection should be too. Read-modify-write the JSON array
224
+ contradicted that premise and was a pre-bus design choice.
225
+ * W9b cutover (this PR): fires ``wicked.subagent.engaged`` BEFORE
226
+ the JSONL append so the projector handler can replay the same
227
+ line. Gated on WG_BUS_AS_TRUTH_SUBAGENT_ENGAGEMENT.
228
+
229
+ Backward compatibility: legacy ``specialist-engagement.json`` files
230
+ in production projects are handled by the reader (see
231
+ ``hooks/scripts/pre_tool.py``) — JSONL preferred, .json fallback on
232
+ miss. No migration tool needed; the next engagement append starts
233
+ the JSONL file fresh.
234
+
235
+ All errors are silently swallowed so the hook never blocks on I/O failures.
236
+ """
237
+ try:
238
+ from _session import SessionState
239
+ from _paths import get_local_path
240
+
241
+ state = SessionState.load()
242
+
243
+ # Resolve current phase — prefer the cached active_project dict, fall
244
+ # back to loading the project state file directly.
245
+ current_phase: str | None = None
246
+ project_id: str | None = state.active_project_id
247
+
248
+ if state.active_project and isinstance(state.active_project, dict):
249
+ current_phase = state.active_project.get("current_phase")
250
+
251
+ if not current_phase and project_id:
252
+ try:
253
+ import re
254
+ if re.match(r'^[a-zA-Z0-9_-]{1,64}$', project_id):
255
+ base = get_local_path("wicked-crew", "projects")
256
+ project_json = base / project_id / "project.json"
257
+ if project_json.exists():
258
+ pdata = json.loads(project_json.read_text(encoding="utf-8"))
259
+ current_phase = pdata.get("current_phase")
260
+ except Exception:
261
+ pass
262
+
263
+ if not current_phase or not project_id:
264
+ # No active crew project — nothing to record
265
+ return
266
+
267
+ # Validate project_id before using it in a path
268
+ import re
269
+ if not re.match(r'^[a-zA-Z0-9_-]{1,64}$', project_id):
270
+ return
271
+
272
+ base = get_local_path("wicked-crew", "projects")
273
+ phase_dir = base / project_id / "phases" / current_phase
274
+ phase_dir.mkdir(parents=True, exist_ok=True)
275
+ engagement_file = phase_dir / "specialist-engagement.jsonl"
276
+
277
+ entry = {
278
+ "domain": domain,
279
+ "agent": agent_name,
280
+ "completed_at": _now_iso(),
281
+ }
282
+ line = json.dumps(entry, sort_keys=False) + "\n"
283
+
284
+ # W9b emit BEFORE the disk append so the projector can replay the
285
+ # same line. chain_id includes the agent_name + completed_at so
286
+ # multiple engagements in the same phase are uniquely identifiable
287
+ # downstream (per memory/bus-chain-id-must-include-uniqueness-segment-gotcha).
288
+ # Fail-open: bus unavailable must NOT block the append.
289
+ try:
290
+ import sys as _sys
291
+ from pathlib import Path as _Path
292
+ _scripts_root = str(_Path(__file__).resolve().parents[2] / "scripts")
293
+ if _scripts_root not in _sys.path:
294
+ _sys.path.insert(0, _scripts_root)
295
+ from _bus import emit_event # type: ignore[import]
296
+ ts_compact = "".join(ch for ch in entry["completed_at"] if ch.isdigit())[:14] or "noid"
297
+ emit_event(
298
+ "wicked.subagent.engaged",
299
+ {
300
+ "project_id": project_id,
301
+ "phase": current_phase,
302
+ "domain": domain,
303
+ "agent": agent_name,
304
+ "raw_payload": line,
305
+ },
306
+ chain_id=f"{project_id}.{current_phase}.{agent_name}-{ts_compact}",
307
+ )
308
+ except Exception: # noqa: BLE001 — fail-open per Decision #8
309
+ pass # bus unavailable — projector handler replays on reconnect
310
+
311
+ except Exception as exc:
312
+ print(f"[wicked-garden] specialist engagement record error: {exc}", file=sys.stderr)
313
+
314
+
315
+ # ---------------------------------------------------------------------------
316
+ # Handler: SubagentStart
317
+ # ---------------------------------------------------------------------------
318
+
319
+ def _handle_start(payload: dict) -> "str | None":
320
+ """Track a subagent starting. Returns active event_type if any."""
321
+ agent_name = payload.get("agent_name", payload.get("subagent_type", "unknown"))
322
+ agent_id = payload.get("agent_id", "")
323
+
324
+ _log("subagent", "normal", "subagent.start",
325
+ detail={"agent": agent_name, "agent_id": agent_id})
326
+
327
+ # Track in session state
328
+ try:
329
+ from _session import SessionState
330
+ state = SessionState.load()
331
+ active_agents = state.active_subagents or {}
332
+ active_agents[agent_id or agent_name] = {
333
+ "name": agent_name,
334
+ "started_at": _now_iso(),
335
+ "started_mono": time.monotonic(),
336
+ }
337
+ active_count = state.active_subagent_count or 0
338
+ state.update(
339
+ active_subagents=active_agents,
340
+ active_subagent_count=active_count + 1,
341
+ total_subagents_launched=(state.total_subagents_launched or 0) + 1,
342
+ )
343
+ except Exception:
344
+ pass
345
+
346
+ session_id = _get_session_id()
347
+
348
+ # Write trace entry
349
+ _write_trace({
350
+ "event": "subagent_start",
351
+ "agent_name": agent_name,
352
+ "agent_id": agent_id,
353
+ "timestamp": _now_iso(),
354
+ "session_id": session_id,
355
+ })
356
+
357
+ # Get active task event_type from native on-disk task store
358
+ return _get_active_task_event_type(session_id)
359
+
360
+
361
+ # ---------------------------------------------------------------------------
362
+ # Handler: SubagentStop
363
+ # ---------------------------------------------------------------------------
364
+
365
+ def _handle_stop(payload: dict) -> None:
366
+ """Track a subagent stopping."""
367
+ agent_name = payload.get("agent_name", payload.get("subagent_type", "unknown"))
368
+ agent_id = payload.get("agent_id", "")
369
+
370
+ # Calculate duration from session state
371
+ duration_ms = None
372
+ try:
373
+ from _session import SessionState
374
+ state = SessionState.load()
375
+ active_agents = state.active_subagents or {}
376
+ agent_key = agent_id or agent_name
377
+
378
+ if agent_key in active_agents:
379
+ started_mono = active_agents[agent_key].get("started_mono")
380
+ if started_mono is not None:
381
+ duration_ms = int((time.monotonic() - started_mono) * 1000)
382
+ del active_agents[agent_key]
383
+
384
+ active_count = max(0, (state.active_subagent_count or 1) - 1)
385
+ state.update(
386
+ active_subagents=active_agents,
387
+ active_subagent_count=active_count,
388
+ )
389
+ except Exception:
390
+ pass
391
+
392
+ _log("subagent", "normal", "subagent.stop",
393
+ ms=duration_ms,
394
+ detail={"agent": agent_name, "agent_id": agent_id})
395
+
396
+ # Write trace entry
397
+ _write_trace({
398
+ "event": "subagent_stop",
399
+ "agent_name": agent_name,
400
+ "agent_id": agent_id,
401
+ "duration_ms": duration_ms,
402
+ "timestamp": _now_iso(),
403
+ "session_id": _get_session_id(),
404
+ })
405
+
406
+ # Record specialist engagement (Issue #365)
407
+ # subagent_type is the canonical identifier; agent_name may be a display name.
408
+ agent_type = payload.get("subagent_type", agent_name)
409
+ try:
410
+ specialist_domains = _load_specialist_domains()
411
+ domain, specialist_agent = _parse_specialist_from_agent_type(agent_type, specialist_domains)
412
+ if domain is not None:
413
+ _record_specialist_engagement(domain, specialist_agent)
414
+ except Exception as exc:
415
+ print(f"[wicked-garden] specialist engagement check error: {exc}", file=sys.stderr)
416
+
417
+
418
+ # ---------------------------------------------------------------------------
419
+ # Main
420
+ # ---------------------------------------------------------------------------
421
+
422
+ def main():
423
+ # Determine phase from CLI argument
424
+ phase = sys.argv[1] if len(sys.argv) > 1 else "unknown"
425
+
426
+ try:
427
+ raw = sys.stdin.read()
428
+ payload = json.loads(raw) if raw.strip() else {}
429
+ except Exception:
430
+ payload = {}
431
+
432
+ event_type = None
433
+ try:
434
+ if phase == "start":
435
+ event_type = _handle_start(payload)
436
+ elif phase == "stop":
437
+ _handle_stop(payload)
438
+ else:
439
+ _log("subagent", "warn", "subagent.unknown_phase",
440
+ detail={"phase": phase})
441
+ except Exception as e:
442
+ print(f"[wicked-garden] subagent_lifecycle error: {e}", file=sys.stderr)
443
+
444
+ # Always succeed — lifecycle tracking should never block
445
+ output = {"continue": True}
446
+
447
+ if phase == "start":
448
+ tool_discovery = (
449
+ "[Tool Discovery] Before claiming you cannot do something, "
450
+ "review your available skills and tools. You have capabilities for "
451
+ "browser automation, visual testing, accessibility auditing, "
452
+ "API testing, code search, memory, and more. Use them."
453
+ )
454
+ procedure_bundle = _EVENT_TYPE_PROCEDURES.get(event_type, "") if event_type else ""
455
+ if procedure_bundle:
456
+ output["systemMessage"] = f"{tool_discovery}\n\n{procedure_bundle}"
457
+ else:
458
+ output["systemMessage"] = tool_discovery
459
+
460
+ print(json.dumps(output))
461
+
462
+
463
+ if __name__ == "__main__":
464
+ main()
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Bus-grain subscriber: react to wicked.gate.decided events.
4
+
5
+ Issue #592 (v8 PR-8) — migrated from Claude-lifecycle pattern.
6
+
7
+ Grain: BUS-GRAIN — this handler fires on wicked.gate.decided events that may
8
+ have been emitted by a different session hours ago. It does NOT use Claude's
9
+ prompt / tool lifecycle hooks because Claude cannot see cross-session bus events.
10
+
11
+ Handler contract:
12
+ - Receives full event JSON on stdin.
13
+ - Emits {"status": "ok"|"error", "message": str, "emit_events": list} on stdout.
14
+
15
+ Responsibilities:
16
+ 1. Validate the gate-decided event has required fields.
17
+ 2. Log the gate decision for observability.
18
+ 3. Optionally emit a follow-on wicked.hook.gate_decided_processed event
19
+ (hook chaining example).
20
+
21
+ Always fails open — any unhandled exception returns {"status": "error", ...}.
22
+ """
23
+
24
+ import json
25
+ import sys
26
+
27
+
28
+ def main() -> None:
29
+ try:
30
+ raw = sys.stdin.read()
31
+ event = json.loads(raw) if raw.strip() else {}
32
+ except (json.JSONDecodeError, UnicodeDecodeError) as exc:
33
+ sys.stdout.write(json.dumps({
34
+ "status": "error",
35
+ "message": f"Failed to parse event JSON: {exc}",
36
+ "emit_events": [],
37
+ }))
38
+ return
39
+
40
+ payload = event.get("payload", {})
41
+ project_id = payload.get("project_id") or payload.get("project") or ""
42
+ phase = payload.get("phase") or ""
43
+ verdict = payload.get("result") or payload.get("verdict") or ""
44
+ score = payload.get("score")
45
+
46
+ if not project_id or not phase:
47
+ sys.stdout.write(json.dumps({
48
+ "status": "error",
49
+ "message": f"gate.decided event missing project_id or phase: {payload!r}",
50
+ "emit_events": [],
51
+ }))
52
+ return
53
+
54
+ # Emit a processed event for hook chaining (optional — downstream subscribers
55
+ # can react to this synthetic event).
56
+ emit_events = [
57
+ {
58
+ "event_type": "wicked.hook.gate_decided_processed",
59
+ "payload": {
60
+ "project_id": project_id,
61
+ "phase": phase,
62
+ "verdict": verdict,
63
+ "score": score,
64
+ "source_event_id": event.get("event_id", 0),
65
+ },
66
+ }
67
+ ]
68
+
69
+ sys.stdout.write(json.dumps({
70
+ "status": "ok",
71
+ "message": f"gate.decided processed: project={project_id} phase={phase} verdict={verdict}",
72
+ "emit_events": emit_events,
73
+ }))
74
+
75
+
76
+ if __name__ == "__main__":
77
+ try:
78
+ main()
79
+ except Exception as exc: # noqa: BLE001 — handler must never crash; always emit a result
80
+ sys.stdout.write(json.dumps({
81
+ "status": "error",
82
+ "message": f"Unhandled exception in on_gate_decided: {exc}",
83
+ "emit_events": [],
84
+ }))