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,277 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ _wicked_testing_probe.py — wicked-testing version probe.
4
+
5
+ Checks that `wicked-testing` (npm) is installed and satisfies the semver
6
+ range pinned in .claude-plugin/plugin.json:wicked_testing_version.
7
+
8
+ Public API:
9
+ probe(session_state) -> ProbeResult
10
+ read_pin_from_plugin_json(plugin_json_path: str) -> str
11
+ is_version_in_range(installed: str, pin: str) -> bool
12
+
13
+ Stdlib-only: no third-party imports (packaging, semver, etc.).
14
+
15
+ Escape hatch: WG_SKIP_WICKED_TESTING_CHECK=1 bypasses subprocess entirely and
16
+ returns status "ok". Documented in CONTRIBUTING.md. Do NOT use in production.
17
+
18
+ CH-02 hardening: the exception path in probe() logs actionable detail —
19
+ subprocess stderr, the exact command that was run, and timeout context — not
20
+ just the bare exception string. crew_command_gate() treats a missing probe key
21
+ as a failure (fail-closed), closing the fail-open gap at the crew layer.
22
+ """
23
+
24
+ import json
25
+ import os
26
+ import subprocess
27
+ import sys
28
+ from pathlib import Path
29
+ from typing import Optional
30
+
31
+ try:
32
+ from typing import TypedDict
33
+
34
+ class ProbeResult(TypedDict):
35
+ status: str # "ok" | "missing" | "out-of-range" | "error"
36
+ version: Optional[str]
37
+ pin: str
38
+ error: Optional[str]
39
+
40
+ except ImportError:
41
+ # Python 3.7 fallback — TypedDict not available as class syntax
42
+ ProbeResult = dict # type: ignore
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # Constants
46
+ # ---------------------------------------------------------------------------
47
+
48
+ _PLUGIN_ROOT = Path(os.environ.get("CLAUDE_PLUGIN_ROOT", Path(__file__).resolve().parents[1]))
49
+ _PLUGIN_JSON_PATH = str(_PLUGIN_ROOT / ".claude-plugin" / "plugin.json")
50
+
51
+ # Subprocess command for the probe. Factored out so tests can assert it.
52
+ _PROBE_CMD = ["npx", "wicked-testing", "--version"]
53
+ _PROBE_TIMEOUT_S = 3
54
+
55
+
56
+ # ---------------------------------------------------------------------------
57
+ # Semver-lite caret-range parser (stdlib only, no packaging import)
58
+ # ---------------------------------------------------------------------------
59
+
60
+ def is_version_in_range(installed: str, pin: str) -> bool:
61
+ """Evaluate a caret semver range.
62
+
63
+ Supports:
64
+ - "*" wildcard: accepts any non-empty installed version string.
65
+ - Caret range "^X.Y.Z":
66
+ - X > 0: >=X.Y.Z and <(X+1).0.0
67
+ - X == 0: >=0.Y.Z and <0.(Y+1).0
68
+
69
+ Prerelease tags (e.g. "0.1.1-beta.1") are rejected for caret ranges —
70
+ strip the prerelease suffix from installed before the numeric comparison.
71
+
72
+ Returns False for any malformed input.
73
+ """
74
+ if pin == "*":
75
+ return bool(installed)
76
+
77
+ if not pin.startswith("^"):
78
+ return False
79
+
80
+ pin_bare = pin[1:] # strip "^"
81
+
82
+ def _parse(v: str):
83
+ """Parse "X.Y.Z" (possibly with prerelease tag) → (major, minor, patch) or None."""
84
+ # Strip prerelease tag — "0.1.1-beta.1" → "0.1.1"
85
+ numeric_part = v.split("-")[0]
86
+ parts = numeric_part.split(".")
87
+ if len(parts) != 3:
88
+ return None
89
+ try:
90
+ return tuple(int(p) for p in parts)
91
+ except ValueError:
92
+ return None
93
+
94
+ inst_tuple = _parse(installed)
95
+ pin_tuple = _parse(pin_bare)
96
+
97
+ if inst_tuple is None or pin_tuple is None:
98
+ return False
99
+
100
+ inst_major, inst_minor, inst_patch = inst_tuple
101
+ pin_major, pin_minor, pin_patch = pin_tuple
102
+
103
+ # Reject prerelease tags (original installed string has "-")
104
+ if "-" in installed.split("+")[0]: # ignore build metadata "+" but reject "-"
105
+ return False
106
+
107
+ # Must be >= pin
108
+ if inst_tuple < pin_tuple:
109
+ return False
110
+
111
+ # Upper bound: <(X+1).0.0 when X>0, or <0.(Y+1).0 when X==0
112
+ if pin_major > 0:
113
+ if inst_major >= pin_major + 1:
114
+ return False
115
+ else:
116
+ # pin_major == 0 — locked to minor
117
+ if inst_major != 0:
118
+ return False
119
+ if inst_minor >= pin_minor + 1:
120
+ return False
121
+
122
+ return True
123
+
124
+
125
+ # ---------------------------------------------------------------------------
126
+ # Read pin from plugin.json
127
+ # ---------------------------------------------------------------------------
128
+
129
+ def read_pin_from_plugin_json(plugin_json_path: str) -> str:
130
+ """Read the wicked_testing_version field from plugin.json.
131
+
132
+ Raises ValueError with an actionable message when:
133
+ - The file does not exist or cannot be read.
134
+ - The JSON is malformed.
135
+ - The wicked_testing_version field is absent.
136
+ - The field value is not a string.
137
+ """
138
+ path = Path(plugin_json_path)
139
+ if not path.exists():
140
+ raise ValueError(
141
+ f"plugin.json not found at {plugin_json_path}. "
142
+ "Ensure CLAUDE_PLUGIN_ROOT is set correctly."
143
+ )
144
+ try:
145
+ data = json.loads(path.read_text(encoding="utf-8"))
146
+ except (json.JSONDecodeError, OSError) as e:
147
+ raise ValueError(f"plugin.json unreadable ({plugin_json_path}): {e}") from e
148
+
149
+ value = data.get("wicked_testing_version")
150
+ if value is None:
151
+ raise ValueError(
152
+ f"plugin.json missing wicked_testing_version field ({plugin_json_path}). "
153
+ "Add: \"wicked_testing_version\": \"^0.2.0\""
154
+ )
155
+ if not isinstance(value, str):
156
+ raise ValueError(
157
+ f"plugin.json wicked_testing_version must be a string, "
158
+ f"got {type(value).__name__} ({plugin_json_path})"
159
+ )
160
+ return value
161
+
162
+
163
+ # ---------------------------------------------------------------------------
164
+ # Main probe
165
+ # ---------------------------------------------------------------------------
166
+
167
+ def probe(session_state=None) -> "ProbeResult":
168
+ """Run the wicked-testing availability probe.
169
+
170
+ 1. Check WG_SKIP_WICKED_TESTING_CHECK escape hatch.
171
+ 2. Read version pin from plugin.json.
172
+ 3. Run `npx wicked-testing --version` with a 3s timeout.
173
+ 4. Compare version string against the caret pin.
174
+
175
+ Returns a ProbeResult dict with keys:
176
+ status: "ok" | "missing" | "out-of-range" | "error"
177
+ version: installed version string or None
178
+ pin: required range string (or "skipped")
179
+ error: error detail or None
180
+
181
+ CH-02 hardening: exception paths log subprocess stderr + command + timeout
182
+ context. The caller (_probe_wicked_testing in bootstrap.py) catches any
183
+ exceptions that escape this function and fails-open. crew_command_gate()
184
+ treats an absent probe key as a failure — fail-closed at the crew layer.
185
+ """
186
+ # 1. Escape hatch — for CI / offline dev without npm access.
187
+ if os.environ.get("WG_SKIP_WICKED_TESTING_CHECK", "").strip() == "1":
188
+ print(
189
+ "[wicked-garden] WG_SKIP_WICKED_TESTING_CHECK is set — "
190
+ "wicked-testing version check bypassed (offline dev mode). "
191
+ "Do not use in production.",
192
+ file=sys.stderr,
193
+ )
194
+ return {"status": "ok", "version": "skipped", "pin": "skipped", "error": None}
195
+
196
+ # 2. Read the version pin.
197
+ try:
198
+ pin = read_pin_from_plugin_json(_PLUGIN_JSON_PATH)
199
+ except ValueError as exc:
200
+ return {
201
+ "status": "error",
202
+ "version": None,
203
+ "pin": "unknown",
204
+ "error": str(exc),
205
+ }
206
+
207
+ # 3. Run the probe subprocess.
208
+ try:
209
+ result = subprocess.run(
210
+ _PROBE_CMD,
211
+ capture_output=True,
212
+ text=True,
213
+ timeout=_PROBE_TIMEOUT_S,
214
+ )
215
+ except FileNotFoundError:
216
+ # npx binary not found — Node.js is not installed.
217
+ return {
218
+ "status": "missing",
219
+ "version": None,
220
+ "pin": pin,
221
+ "error": "npx not found — install Node.js",
222
+ }
223
+ except subprocess.TimeoutExpired as exc:
224
+ # CH-02 hardening: include command + timeout context in the log line.
225
+ cmd_str = " ".join(_PROBE_CMD)
226
+ stderr_excerpt = ""
227
+ if exc.stderr:
228
+ raw = exc.stderr if isinstance(exc.stderr, str) else exc.stderr.decode("utf-8", errors="replace")
229
+ stderr_excerpt = raw.strip()[:200]
230
+ print(
231
+ f"[wicked-garden] wicked-testing probe timeout: "
232
+ f"command={cmd_str!r} timeout={_PROBE_TIMEOUT_S}s "
233
+ f"stderr={stderr_excerpt!r}",
234
+ file=sys.stderr,
235
+ )
236
+ return {
237
+ "status": "error",
238
+ "version": None,
239
+ "pin": pin,
240
+ "error": f"probe timeout ({_PROBE_TIMEOUT_S}s)",
241
+ }
242
+ except Exception as exc:
243
+ # CH-02 hardening: include command context in the actionable log line.
244
+ cmd_str = " ".join(_PROBE_CMD)
245
+ print(
246
+ f"[wicked-garden] wicked-testing probe exception: "
247
+ f"command={cmd_str!r} error={exc!r}",
248
+ file=sys.stderr,
249
+ )
250
+ return {
251
+ "status": "error",
252
+ "version": None,
253
+ "pin": pin,
254
+ "error": str(exc),
255
+ }
256
+
257
+ # 4. Non-zero exit → wicked-testing not installed (or broken install).
258
+ if result.returncode != 0:
259
+ stderr_excerpt = result.stderr.strip()[:200] if result.stderr else "non-zero exit"
260
+ return {
261
+ "status": "missing",
262
+ "version": None,
263
+ "pin": pin,
264
+ "error": stderr_excerpt or "non-zero exit",
265
+ }
266
+
267
+ # 5. Parse and validate the version string.
268
+ version = result.stdout.strip().lstrip("v")
269
+ if not is_version_in_range(version, pin):
270
+ return {
271
+ "status": "out-of-range",
272
+ "version": version,
273
+ "pin": pin,
274
+ "error": None,
275
+ }
276
+
277
+ return {"status": "ok", "version": version, "pin": pin, "error": None}
@@ -0,0 +1,391 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Agent topology analysis for agentic codebases.
4
+
5
+ Extracts agent definitions, classifies roles, maps communication patterns,
6
+ and identifies structural characteristics like nesting depth and tool sharing.
7
+
8
+ Usage:
9
+ python3 analyze_agents.py --path DIR [--framework NAME]
10
+ """
11
+
12
+ import ast
13
+ import json
14
+ import os
15
+ import re
16
+ import sys
17
+ import time
18
+ from pathlib import Path
19
+
20
+ EXCLUDE_DIRS = {
21
+ "node_modules", "venv", ".venv", "__pycache__", "dist", "build",
22
+ ".git", ".tox", ".mypy_cache", ".pytest_cache",
23
+ }
24
+
25
+ ROLE_KEYWORDS = {
26
+ "research": ["search", "research", "gather", "find", "retrieve", "scrape"],
27
+ "analysis": ["analyze", "evaluate", "assess", "review", "score", "classify"],
28
+ "coordination": ["supervisor", "manager", "orchestrat", "coordinate", "router", "planner"],
29
+ "execution": ["execute", "perform", "run", "worker", "do", "process"],
30
+ "safety": ["safety", "validate", "check", "guard", "moderate", "filter"],
31
+ "synthesis": ["synthesize", "combine", "summarize", "aggregate", "merge", "report"],
32
+ "creation": ["write", "create", "generate", "compose", "draft", "author"],
33
+ }
34
+
35
+
36
+ def find_python_files(root: str, max_files: int = 500) -> list:
37
+ files = []
38
+ for dirpath, dirnames, filenames in os.walk(root):
39
+ dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
40
+ for f in filenames:
41
+ if f.endswith(".py"):
42
+ files.append(os.path.join(dirpath, f))
43
+ if len(files) >= max_files:
44
+ return files
45
+ return files
46
+
47
+
48
+ def extract_agents_generic(filepath: str) -> list:
49
+ """Extract agent-like class/function definitions from any Python file."""
50
+ agents = []
51
+ try:
52
+ with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
53
+ source = f.read()
54
+ tree = ast.parse(source, filename=filepath)
55
+ except (SyntaxError, ValueError, OSError):
56
+ return agents
57
+
58
+ for node in ast.walk(tree):
59
+ # Classes with "Agent" in the name
60
+ if isinstance(node, ast.ClassDef) and "agent" in node.name.lower():
61
+ agents.append({
62
+ "name": node.name,
63
+ "type": "class",
64
+ "file": filepath,
65
+ "line": node.lineno,
66
+ "role": classify_role(node.name, _get_docstring(node)),
67
+ "tools": _extract_tool_refs(node),
68
+ "confidence": 0.7,
69
+ })
70
+
71
+ # Functions decorated with @agent or similar
72
+ if isinstance(node, ast.FunctionDef):
73
+ decorators = _get_decorator_names(node)
74
+ if any(d in ("agent", "crew", "tool") for d in decorators):
75
+ agents.append({
76
+ "name": node.name,
77
+ "type": "decorated_function",
78
+ "decorator": [d for d in decorators if d in ("agent", "crew", "tool")][0],
79
+ "file": filepath,
80
+ "line": node.lineno,
81
+ "role": classify_role(node.name, _get_docstring(node)),
82
+ "tools": _extract_tool_refs(node),
83
+ "confidence": 0.9,
84
+ })
85
+
86
+ # Functions using AgentExecutor or in agents/ directory
87
+ if isinstance(node, ast.FunctionDef):
88
+ is_agent_function = False
89
+ reason = ""
90
+
91
+ # Check if function name contains agent-related patterns
92
+ name_lower = node.name.lower()
93
+ if any(kw in name_lower for kw in ("agent", "workflow", "pipeline")):
94
+ is_agent_function = True
95
+ reason = "name_pattern"
96
+
97
+ # Check if function body references AgentExecutor
98
+ if not is_agent_function:
99
+ for child in ast.walk(node):
100
+ if isinstance(child, ast.Name) and child.id == "AgentExecutor":
101
+ is_agent_function = True
102
+ reason = "AgentExecutor_usage"
103
+ break
104
+ if isinstance(child, ast.Attribute) and child.attr == "AgentExecutor":
105
+ is_agent_function = True
106
+ reason = "AgentExecutor_usage"
107
+ break
108
+
109
+ # Check if file is in an agents/ directory
110
+ if not is_agent_function and "/agents/" in filepath:
111
+ is_agent_function = True
112
+ reason = "agents_directory"
113
+
114
+ # Skip if already captured as decorated function
115
+ decorators = _get_decorator_names(node)
116
+ if is_agent_function and not any(d in ("agent", "crew", "tool") for d in decorators):
117
+ agents.append({
118
+ "name": node.name,
119
+ "type": "function_agent",
120
+ "detection": reason,
121
+ "file": filepath,
122
+ "line": node.lineno,
123
+ "role": classify_role(node.name, _get_docstring(node)),
124
+ "tools": _extract_tool_refs(node),
125
+ "confidence": 0.6,
126
+ })
127
+
128
+ # Agent() instantiation calls
129
+ if isinstance(node, ast.Call):
130
+ func_name = _get_call_name(node)
131
+ if func_name and "agent" in func_name.lower():
132
+ name = _infer_agent_name(node, source, filepath)
133
+ agents.append({
134
+ "name": name,
135
+ "type": "instantiation",
136
+ "constructor": func_name,
137
+ "file": filepath,
138
+ "line": node.lineno,
139
+ "role": classify_role(name, _extract_kwargs_str(node, "role", "goal", "description")),
140
+ "tools": _extract_tools_kwarg(node),
141
+ "kwargs": _extract_kwargs_str(node, "role", "goal", "backstory", "model"),
142
+ "confidence": 0.8,
143
+ })
144
+
145
+ return agents
146
+
147
+
148
+ def classify_role(name: str, context: str = "") -> str:
149
+ """Classify agent role based on name and context."""
150
+ text = f"{name} {context}".lower()
151
+ scores = {}
152
+ for role, keywords in ROLE_KEYWORDS.items():
153
+ scores[role] = sum(1 for kw in keywords if kw in text)
154
+ if max(scores.values()) == 0:
155
+ return "unknown"
156
+ return max(scores, key=scores.get)
157
+
158
+
159
+ def map_communication(agents: list) -> dict:
160
+ """Build a communication graph from agent references."""
161
+ agent_names = {a["name"].lower() for a in agents}
162
+ edges = []
163
+
164
+ for agent in agents:
165
+ filepath = agent["file"]
166
+ try:
167
+ with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
168
+ source = f.read()
169
+ except OSError:
170
+ continue
171
+
172
+ for other_name in agent_names:
173
+ if other_name == agent["name"].lower():
174
+ continue
175
+ if other_name in source.lower():
176
+ edges.append({
177
+ "from": agent["name"],
178
+ "to": other_name,
179
+ "file": filepath,
180
+ })
181
+
182
+ # Detect patterns
183
+ nodes = [a["name"] for a in agents]
184
+ pattern = "unknown"
185
+ if not edges:
186
+ pattern = "isolated"
187
+ elif _has_cycle(nodes, edges):
188
+ pattern = "circular"
189
+ elif _is_hierarchical(nodes, edges):
190
+ pattern = "hierarchical"
191
+ elif _is_sequential(nodes, edges):
192
+ pattern = "sequential"
193
+ else:
194
+ pattern = "collaborative"
195
+
196
+ return {
197
+ "nodes": nodes,
198
+ "edges": edges,
199
+ "pattern": pattern,
200
+ }
201
+
202
+
203
+ def analyze(root: str, framework: str = None) -> dict:
204
+ """Run full agent analysis."""
205
+ start = time.time()
206
+ root = os.path.abspath(root)
207
+ files = find_python_files(root)
208
+
209
+ all_agents = []
210
+ for f in files:
211
+ all_agents.extend(extract_agents_generic(f))
212
+
213
+ # Deduplicate by name+file
214
+ seen = set()
215
+ unique = []
216
+ for a in all_agents:
217
+ key = (a["name"], a["file"])
218
+ if key not in seen:
219
+ seen.add(key)
220
+ unique.append(a)
221
+
222
+ comm_graph = map_communication(unique)
223
+
224
+ # Collect shared tools
225
+ tool_usage = {}
226
+ for agent in unique:
227
+ for tool in agent.get("tools", []):
228
+ tool_usage.setdefault(tool, []).append(agent["name"])
229
+ shared_tools = {t: agents for t, agents in tool_usage.items() if len(agents) > 1}
230
+
231
+ # Role distribution
232
+ role_dist = {}
233
+ for a in unique:
234
+ role = a.get("role", "unknown")
235
+ role_dist[role] = role_dist.get(role, 0) + 1
236
+
237
+ return {
238
+ "agents": unique,
239
+ "agent_count": len(unique),
240
+ "communication": comm_graph,
241
+ "shared_tools": shared_tools,
242
+ "role_distribution": role_dist,
243
+ "stats": {
244
+ "files_scanned": len(files),
245
+ "duration_ms": int((time.time() - start) * 1000),
246
+ },
247
+ }
248
+
249
+
250
+ # --- Helpers ---
251
+
252
+ def _get_decorator_names(node: ast.FunctionDef) -> list:
253
+ names = []
254
+ for d in node.decorator_list:
255
+ if isinstance(d, ast.Name):
256
+ names.append(d.id)
257
+ elif isinstance(d, ast.Attribute):
258
+ names.append(d.attr)
259
+ elif isinstance(d, ast.Call):
260
+ if isinstance(d.func, ast.Name):
261
+ names.append(d.func.id)
262
+ elif isinstance(d.func, ast.Attribute):
263
+ names.append(d.func.attr)
264
+ return names
265
+
266
+
267
+ def _get_call_name(node: ast.Call) -> str:
268
+ if isinstance(node.func, ast.Name):
269
+ return node.func.id
270
+ if isinstance(node.func, ast.Attribute):
271
+ return node.func.attr
272
+ return None
273
+
274
+
275
+ def _get_docstring(node) -> str:
276
+ if node.body and isinstance(node.body[0], ast.Expr):
277
+ if isinstance(node.body[0].value, ast.Constant) and isinstance(node.body[0].value.value, str):
278
+ return node.body[0].value.value
279
+ return ""
280
+
281
+
282
+ def _extract_tool_refs(node) -> list:
283
+ """Extract tool references from a class or function body."""
284
+ tools = []
285
+ for child in ast.walk(node):
286
+ if isinstance(child, ast.Constant) and isinstance(child.value, str):
287
+ val = child.value.lower()
288
+ if "tool" in val and len(child.value) < 50:
289
+ tools.append(child.value)
290
+ return tools[:10]
291
+
292
+
293
+ def _extract_tools_kwarg(node: ast.Call) -> list:
294
+ """Extract tools from Agent(tools=[...]) kwarg."""
295
+ for kw in node.keywords:
296
+ if kw.arg == "tools":
297
+ if isinstance(kw.value, ast.List):
298
+ items = []
299
+ for elt in kw.value.elts:
300
+ if isinstance(elt, ast.Name):
301
+ items.append(elt.id)
302
+ elif isinstance(elt, ast.Constant):
303
+ items.append(str(elt.value))
304
+ return items
305
+ return []
306
+
307
+
308
+ def _extract_kwargs_str(node: ast.Call, *keys) -> str:
309
+ """Extract string kwargs from a Call node."""
310
+ parts = []
311
+ for kw in node.keywords:
312
+ if kw.arg in keys and isinstance(kw.value, ast.Constant):
313
+ parts.append(str(kw.value.value))
314
+ return " ".join(parts)
315
+
316
+
317
+ def _infer_agent_name(node: ast.Call, source: str, filepath: str) -> str:
318
+ """Try to infer agent name from variable assignment or kwargs."""
319
+ for kw in node.keywords:
320
+ if kw.arg in ("name", "role") and isinstance(kw.value, ast.Constant):
321
+ return str(kw.value.value)
322
+ # Fall back to variable name from assignment context
323
+ lines = source.split("\n")
324
+ if node.lineno <= len(lines):
325
+ line = lines[node.lineno - 1]
326
+ match = re.match(r"(\w+)\s*=", line)
327
+ if match:
328
+ return match.group(1)
329
+ return f"agent_at_{Path(filepath).stem}_{node.lineno}"
330
+
331
+
332
+ def _has_cycle(nodes: list, edges: list) -> bool:
333
+ adj = {n: [] for n in nodes}
334
+ for e in edges:
335
+ if e["from"] in adj:
336
+ adj[e["from"]].append(e["to"])
337
+ visited = set()
338
+ rec_stack = set()
339
+
340
+ def dfs(node):
341
+ visited.add(node)
342
+ rec_stack.add(node)
343
+ for neighbor in adj.get(node, []):
344
+ if neighbor not in visited:
345
+ if dfs(neighbor):
346
+ return True
347
+ elif neighbor in rec_stack:
348
+ return True
349
+ rec_stack.discard(node)
350
+ return False
351
+
352
+ for n in nodes:
353
+ if n not in visited:
354
+ if dfs(n):
355
+ return True
356
+ return False
357
+
358
+
359
+ def _is_hierarchical(nodes: list, edges: list) -> bool:
360
+ in_degree = {n: 0 for n in nodes}
361
+ for e in edges:
362
+ to = e["to"]
363
+ if to in in_degree:
364
+ in_degree[to] += 1
365
+ roots = [n for n, d in in_degree.items() if d == 0]
366
+ return len(roots) == 1 and len(edges) >= len(nodes) - 1
367
+
368
+
369
+ def _is_sequential(nodes: list, edges: list) -> bool:
370
+ if len(edges) != len(nodes) - 1:
371
+ return False
372
+ out_degree = {}
373
+ for e in edges:
374
+ out_degree[e["from"]] = out_degree.get(e["from"], 0) + 1
375
+ return all(d <= 1 for d in out_degree.values())
376
+
377
+
378
+ def main():
379
+ import argparse
380
+
381
+ parser = argparse.ArgumentParser(description="Analyze agent topology")
382
+ parser.add_argument("--path", default=".", help="Directory to scan")
383
+ parser.add_argument("--framework", default=None, help="Framework hint")
384
+ args = parser.parse_args()
385
+
386
+ result = analyze(args.path, framework=args.framework)
387
+ print(json.dumps(result, indent=2, default=str))
388
+
389
+
390
+ if __name__ == "__main__":
391
+ main()