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,409 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ detect_clis.py — detect & probe agentic LLM CLIs for the council.
4
+
5
+ Reads ``agentic_cli_registry.py`` and answers two questions the council needs:
6
+
7
+ 1. Which registered CLIs are INSTALLED on this machine (``shutil.which``)?
8
+ 2. With ``--probe``: which installed CLIs are actually USABLE right now —
9
+ i.e. running their headless form (+ trust flags) on a trivial prompt
10
+ returns a sane reply — vs INSTALLED-BUT-UNUSABLE (auth revoked, no
11
+ provider configured, daemon down, …)?
12
+
13
+ The probe is the difference between "the binary is on PATH" and "the council
14
+ can get a real answer out of it". A CLI can be installed yet 401, or print
15
+ "no provider configured", or fail to reach a local daemon. Those seats must
16
+ NOT be counted toward quorum.
17
+
18
+ Safety / cross-platform contract (mirrors _capability_registry.py + CLAUDE.md):
19
+ * stdlib only — no third-party imports.
20
+ * detection via ``shutil.which``.
21
+ * each probe runs with ``subprocess.run(..., timeout=N, stdin=DEVNULL,
22
+ cwd=<fresh tempdir under tempfile.gettempdir()>)`` so a hanging CLI is
23
+ bounded, nothing reads our stdin, and no CLI mutates the real project.
24
+ * never perl/bash-isms, never a bare ``/tmp``.
25
+
26
+ Modes:
27
+ detect_clis.py # PATH scan, human output
28
+ detect_clis.py --json # PATH scan, JSON
29
+ detect_clis.py --probe # PATH scan + usability probe (JSON-capable)
30
+ detect_clis.py --list # dump the registry (no detection)
31
+ detect_clis.py --list --json # registry dump as JSON
32
+
33
+ Output JSON shape (--probe):
34
+ {
35
+ "detected": [ {key, display_name, binary, resolved_path, category,
36
+ confidence, enabled_for_council, version}, ... ],
37
+ "usable": [ "<key>", ... ],
38
+ "unusable": [ {"cli": "<key>", "reason": "<class>: <detail>"}, ... ],
39
+ "collisions": [ {"binary": "...", "keys": [...]}, ... ]
40
+ }
41
+ """
42
+
43
+ from __future__ import annotations
44
+
45
+ import argparse
46
+ import json
47
+ import re
48
+ import subprocess
49
+ import sys
50
+ import tempfile
51
+ from dataclasses import asdict
52
+ from pathlib import Path
53
+
54
+ # Import the registry. Works both when run as a file from anywhere
55
+ # (sys.path bootstrap) and when imported as a module.
56
+ try:
57
+ from agentic_cli_registry import ( # type: ignore
58
+ AGENTIC_CLI_REGISTRY,
59
+ AgenticCLI,
60
+ detect as registry_detect,
61
+ )
62
+ except ModuleNotFoundError: # pragma: no cover — path bootstrap for direct runs
63
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
64
+ from agentic_cli_registry import ( # type: ignore
65
+ AGENTIC_CLI_REGISTRY,
66
+ AgenticCLI,
67
+ detect as registry_detect,
68
+ )
69
+
70
+
71
+ # Trivial prompt: cheap, deterministic, and the reply is easy to sanity-check.
72
+ PROBE_PROMPT = "Reply with the single word: pong"
73
+
74
+ # Per-CLI probe timeout (seconds). Agentic coders spin up tools/MCP and can be
75
+ # slow on a cold start; this bounds a hang (e.g. cursor-agent `-p`) without
76
+ # starving a legitimately-slow-but-working CLI. Local runners get longer
77
+ # because first-token latency on a cold model load is high.
78
+ DEFAULT_TIMEOUT = 45
79
+ LOCAL_RUNNER_TIMEOUT = 60
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # Error-signature classification.
83
+ # A CLI that is installed-but-unusable fails in a recognisable way. We match
84
+ # stdout+stderr (lower-cased) against these signatures to label WHY a seat is
85
+ # unusable, so the council can tell the user "codex: auth revoked" rather than
86
+ # a generic failure. Order matters: first match wins.
87
+ # ---------------------------------------------------------------------------
88
+
89
+ _UNUSABLE_SIGNATURES: list[tuple[str, re.Pattern[str]]] = [
90
+ (
91
+ "auth",
92
+ re.compile(
93
+ r"\b(401|403|unauthor|authentication (failed|required)|not (logged|signed) in"
94
+ r"|please (log ?in|sign ?in|run .*login)|invalid api key|api key (not|is missing)"
95
+ r"|expired (token|credential)|forbidden|access denied"
96
+ r"|credentials? (not found|missing|expired)|re-?authenticate)\b",
97
+ re.IGNORECASE,
98
+ ),
99
+ ),
100
+ (
101
+ "no-provider",
102
+ re.compile(
103
+ r"\b(no (provider|model) (configured|set|selected|available)"
104
+ r"|no api key|set (the )?\w*_?api_key|missing .*api[_ ]?key"
105
+ r"|configure (a )?(provider|model|api key)|run .*configure"
106
+ r"|no default model|model not (found|configured))\b",
107
+ re.IGNORECASE,
108
+ ),
109
+ ),
110
+ (
111
+ "daemon-down",
112
+ re.compile(
113
+ r"\b(could not connect|connection refused|connection error"
114
+ r"|failed to connect|daemon (not|isn'?t) running|is the server running"
115
+ r"|ollama (server|app) (not|isn'?t) running|dial tcp|econnrefused"
116
+ r"|no such model|model .* not found, try pulling)\b",
117
+ re.IGNORECASE,
118
+ ),
119
+ ),
120
+ (
121
+ "quota",
122
+ re.compile(
123
+ r"\b(quota|rate ?limit|429|insufficient (credit|funds|balance)"
124
+ r"|billing|payment required|402)\b",
125
+ re.IGNORECASE,
126
+ ),
127
+ ),
128
+ ]
129
+
130
+ # If a CLI exits non-zero with no recognised signature, we still mark it
131
+ # unusable but with this generic label so the seat is not silently trusted.
132
+ _GENERIC_UNUSABLE = "error"
133
+
134
+
135
+ def _classify_failure(
136
+ returncode: int | None, combined: str, timed_out: bool
137
+ ) -> tuple[str, str] | None:
138
+ """Classify a probe run. Returns ``(reason_class, matched_line)`` for an
139
+ unusable run, or ``None`` if the run looks usable.
140
+
141
+ ``matched_line`` is the specific line that tripped the signature (e.g. the
142
+ 401 line), so the human-facing reason is honest rather than echoing a
143
+ cosmetic banner line. A run is USABLE only when it did not time out, exited
144
+ 0, and produced non-trivial stdout free of a failure signature (some CLIs
145
+ print the error to stdout yet still exit 0).
146
+ """
147
+ if timed_out:
148
+ return ("timeout", "")
149
+ lines = combined.splitlines()
150
+ for label, pat in _UNUSABLE_SIGNATURES:
151
+ for line in lines:
152
+ if pat.search(line):
153
+ return (label, line.strip())
154
+ # Fall back to a whole-text match (signature spanning the buffer).
155
+ if pat.search(combined):
156
+ return (label, "")
157
+ if returncode not in (0, None):
158
+ return (_GENERIC_UNUSABLE, "")
159
+ return None
160
+
161
+
162
+ def _looks_like_real_reply(stdout: str) -> bool:
163
+ """A sane reply has some printable content beyond whitespace/banners.
164
+
165
+ We do NOT require the literal word 'pong' — models phrase things their own
166
+ way and some CLIs wrap output. We only require that *something* substantive
167
+ came back, since auth/provider/daemon failures produce either empty stdout
168
+ or an error string (already caught by signature matching)."""
169
+ stripped = stdout.strip()
170
+ return len(stripped) >= 2
171
+
172
+
173
+ def _probe_version(cli: AgenticCLI, timeout: int) -> str:
174
+ """Capture the version string (disambiguates binary collisions like grok)."""
175
+ try:
176
+ proc = subprocess.run(
177
+ cli.version_probe,
178
+ stdin=subprocess.DEVNULL,
179
+ capture_output=True,
180
+ text=True,
181
+ timeout=min(timeout, 15),
182
+ )
183
+ out = (proc.stdout or proc.stderr or "").strip()
184
+ # Keep it to the first line — version banners can be multi-line.
185
+ return out.splitlines()[0].strip() if out else ""
186
+ except (subprocess.TimeoutExpired, OSError, ValueError):
187
+ return ""
188
+
189
+
190
+ def _build_probe_argv(cli: AgenticCLI) -> list[str] | None:
191
+ """Build the headless argv for a probe run: rendered template + trust flags.
192
+
193
+ Returns None for CLIs that cannot be safely auto-probed with a trivial
194
+ prompt (e.g. ollama needs a model name we don't know). Those are reported
195
+ as detected but skipped by the probe with an explicit reason.
196
+ """
197
+ if cli.key == "ollama" or "{MODEL}" in cli.headless_invocation:
198
+ # Local runners need a concrete pulled model; we won't guess one.
199
+ return None
200
+
201
+ rendered = cli.render(PROBE_PROMPT)
202
+ try:
203
+ import shlex
204
+
205
+ argv = shlex.split(rendered, posix=(sys.platform != "win32"))
206
+ except ValueError:
207
+ return None
208
+ if not argv:
209
+ return None
210
+ # Append trust flags AFTER the template so headless runs don't block on a
211
+ # permission / trust / git-repo prompt.
212
+ argv.extend(cli.trust_flags)
213
+ return argv
214
+
215
+
216
+ def _probe_one(cli: AgenticCLI) -> dict:
217
+ """Probe a single detected CLI. Returns {usable: bool, reason, version}."""
218
+ timeout = LOCAL_RUNNER_TIMEOUT if cli.category == "local-runner" else DEFAULT_TIMEOUT
219
+ version = _probe_version(cli, timeout)
220
+
221
+ argv = _build_probe_argv(cli)
222
+ if argv is None:
223
+ return {
224
+ "usable": False,
225
+ "reason": "skipped: requires a model/daemon not auto-probeable (e.g. ollama needs a pulled model + running daemon)",
226
+ "version": version,
227
+ }
228
+
229
+ tmpdir = tempfile.mkdtemp(prefix="wg-council-probe-")
230
+ timed_out = False
231
+ returncode: int | None = None
232
+ stdout = ""
233
+ stderr = ""
234
+ try:
235
+ proc = subprocess.run(
236
+ argv,
237
+ stdin=subprocess.DEVNULL,
238
+ capture_output=True,
239
+ text=True,
240
+ timeout=timeout,
241
+ cwd=tmpdir,
242
+ )
243
+ returncode = proc.returncode
244
+ stdout = proc.stdout or ""
245
+ stderr = proc.stderr or ""
246
+ except subprocess.TimeoutExpired as exc:
247
+ timed_out = True
248
+ stdout = (exc.stdout or b"").decode("utf-8", "replace") if isinstance(exc.stdout, bytes) else (exc.stdout or "")
249
+ stderr = (exc.stderr or b"").decode("utf-8", "replace") if isinstance(exc.stderr, bytes) else (exc.stderr or "")
250
+ except (OSError, ValueError) as exc:
251
+ return {"usable": False, "reason": f"error: could not launch ({exc})", "version": version}
252
+ finally:
253
+ # Best-effort cleanup of the scratch cwd (aider et al. drop cache files).
254
+ try:
255
+ import shutil as _sh
256
+
257
+ _sh.rmtree(tmpdir, ignore_errors=True)
258
+ except Exception:
259
+ pass
260
+
261
+ combined = f"{stdout}\n{stderr}"
262
+ classified = _classify_failure(returncode, combined, timed_out)
263
+ if classified is None and _looks_like_real_reply(stdout):
264
+ return {"usable": True, "reason": None, "version": version}
265
+
266
+ if classified is None:
267
+ # Exited 0 but produced nothing substantive — treat as unusable so the
268
+ # council does not seat an empty responder.
269
+ reason, matched = "empty-response", ""
270
+ else:
271
+ reason, matched = classified
272
+
273
+ # Prefer the line that actually matched the failure signature (e.g. the
274
+ # 401 line); fall back to the first non-empty line if nothing matched
275
+ # (timeout / generic non-zero exit).
276
+ detail = matched
277
+ if not detail:
278
+ for line in combined.splitlines():
279
+ s = line.strip()
280
+ if s:
281
+ detail = s
282
+ break
283
+ detail = detail[:160]
284
+ full = f"{reason}: {detail}" if detail else reason
285
+ return {"usable": False, "reason": full, "version": version}
286
+
287
+
288
+ def run_detect(probe: bool) -> dict:
289
+ """Detect installed CLIs and, if ``probe``, classify usable vs unusable."""
290
+ base = registry_detect(probe=False)
291
+ detected = base["detected"]
292
+ collisions = base["collisions"]
293
+
294
+ if not probe:
295
+ return {"detected": detected, "collisions": collisions}
296
+
297
+ usable: list[str] = []
298
+ unusable: list[dict] = []
299
+ for entry in detected:
300
+ key = entry["key"]
301
+ if key == "claude":
302
+ # Claude is the in-process host, not an external seat. Record its
303
+ # version for collision/audit purposes but don't probe it as a CLI.
304
+ cli = AGENTIC_CLI_REGISTRY[key]
305
+ entry["version"] = _probe_version(cli, DEFAULT_TIMEOUT)
306
+ continue
307
+ cli = AGENTIC_CLI_REGISTRY[key]
308
+ result = _probe_one(cli)
309
+ entry["version"] = result["version"]
310
+ if result["usable"]:
311
+ usable.append(key)
312
+ else:
313
+ unusable.append({"cli": key, "reason": result["reason"]})
314
+
315
+ return {
316
+ "detected": detected,
317
+ "usable": usable,
318
+ "unusable": unusable,
319
+ "collisions": collisions,
320
+ }
321
+
322
+
323
+ def list_registry() -> dict:
324
+ """Dump the full registry as plain dicts (for --list)."""
325
+ return {
326
+ "clis": [asdict(cli) for cli in AGENTIC_CLI_REGISTRY.values()],
327
+ "count": len(AGENTIC_CLI_REGISTRY),
328
+ }
329
+
330
+
331
+ # ---------------------------------------------------------------------------
332
+ # Human-readable rendering
333
+ # ---------------------------------------------------------------------------
334
+
335
+ def _emit_human_list(reg: dict) -> None:
336
+ sys.stdout.write(f"agentic CLI registry — {reg['count']} entries\n")
337
+ for cli in reg["clis"]:
338
+ flag = "" if cli["enabled_for_council"] else " [council-disabled]"
339
+ conf = "" if cli["confidence"] == "verified" else f" ({cli['confidence']})"
340
+ sys.stdout.write(
341
+ f" {cli['key']:<14} {cli['category']:<14} {cli['vendor']}{conf}{flag}\n"
342
+ )
343
+
344
+
345
+ def _emit_human_detect(result: dict, probed: bool) -> None:
346
+ detected = result["detected"]
347
+ sys.stdout.write(f"detected {len(detected)} installed CLI(s):\n")
348
+ usable = set(result.get("usable", []))
349
+ unusable_map = {u["cli"]: u["reason"] for u in result.get("unusable", [])}
350
+ for entry in detected:
351
+ key = entry["key"]
352
+ ver = entry.get("version", "")
353
+ ver_s = f" v={ver}" if ver else ""
354
+ if not probed:
355
+ status = ""
356
+ elif key == "claude":
357
+ status = " [in-process host]"
358
+ elif key in usable:
359
+ status = " USABLE"
360
+ elif key in unusable_map:
361
+ status = f" UNUSABLE — {unusable_map[key]}"
362
+ else:
363
+ status = ""
364
+ sys.stdout.write(f" {key:<14} {entry['resolved_path']}{ver_s}{status}\n")
365
+
366
+ if probed:
367
+ sys.stdout.write(
368
+ f"\nquorum: {len(usable)} usable external CLI(s)"
369
+ + (
370
+ " — full council"
371
+ if len(usable) >= 2
372
+ else " — below quorum (fallback to Task() subagent seats)"
373
+ )
374
+ + "\n"
375
+ )
376
+
377
+ if result.get("collisions"):
378
+ sys.stdout.write("\nbinary collisions (disambiguate by version):\n")
379
+ for c in result["collisions"]:
380
+ sys.stdout.write(f" {c['binary']}: {', '.join(c['keys'])}\n")
381
+
382
+
383
+ def main(argv: list[str] | None = None) -> int:
384
+ parser = argparse.ArgumentParser(
385
+ description="Detect & probe agentic LLM CLIs for the wicked-garden council."
386
+ )
387
+ parser.add_argument("--probe", action="store_true", help="run headless usability probe")
388
+ parser.add_argument("--list", action="store_true", help="dump the registry and exit")
389
+ parser.add_argument("--json", action="store_true", help="emit JSON instead of human text")
390
+ args = parser.parse_args(argv)
391
+
392
+ if args.list:
393
+ reg = list_registry()
394
+ if args.json:
395
+ sys.stdout.write(json.dumps(reg, indent=2) + "\n")
396
+ else:
397
+ _emit_human_list(reg)
398
+ return 0
399
+
400
+ result = run_detect(probe=args.probe)
401
+ if args.json:
402
+ sys.stdout.write(json.dumps(result, indent=2) + "\n")
403
+ else:
404
+ _emit_human_detect(result, probed=args.probe)
405
+ return 0
406
+
407
+
408
+ if __name__ == "__main__":
409
+ sys.exit(main())
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ wicked-jam query CLI -- exposes session data for cross-plugin access.
4
+
5
+ All data flows through DomainStore("wicked-jam") which routes to MCP
6
+ integrations when available and falls back to local JSON files.
7
+
8
+ Usage:
9
+ jam.py list-sessions [--query Q] [--limit N] [--json] [--project P]
10
+ jam.py transcript [--session-id ID] [--json]
11
+ jam.py persona <name> [--session-id ID] [--json]
12
+ jam.py thinking [--session-id ID] [--json]
13
+
14
+ Transcript entry schema:
15
+ {
16
+ "session_id": "...",
17
+ "round": 1,
18
+ "persona_name": "Technical Architect",
19
+ "persona_type": "technical", # technical | user | business | process | council
20
+ "raw_text": "...",
21
+ "thinking": "...", # optional: pre-synthesis deliberation (alternatives, trade-offs)
22
+ "timestamp": "...",
23
+ "entry_type": "perspective" # perspective | synthesis | council_response
24
+ }
25
+ """
26
+
27
+ import argparse
28
+ import json
29
+ import sys
30
+ from pathlib import Path
31
+
32
+ # Resolve _domain_store from the parent scripts/ directory
33
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
34
+ from _domain_store import DomainStore
35
+
36
+ _sm = DomainStore("wicked-jam")
37
+
38
+
39
+ def list_sessions(query: str = None, limit: int = 10, project: str = None) -> dict:
40
+ """List recent brainstorming sessions, optionally filtered by query."""
41
+ params = {}
42
+ if query:
43
+ params["q"] = query
44
+ if project:
45
+ params["project"] = project
46
+
47
+ records = _sm.list("sessions", **params)
48
+
49
+ results = []
50
+ query_lower = query.lower() if query else None
51
+
52
+ for session in records:
53
+ topic = session.get("topic", "")
54
+ summary = session.get("synthesis", {}).get("summary", "")
55
+ perspectives = session.get("perspectives", [])
56
+ created = session.get("created", "")
57
+ session_project = session.get("project", "")
58
+
59
+ # Filter by project if specified (in case local fallback doesn't filter)
60
+ if project and session_project and session_project != project:
61
+ continue
62
+
63
+ # Filter by query if specified (in case local fallback doesn't filter)
64
+ if query_lower:
65
+ text = f"{topic} {summary}".lower()
66
+ if not any(word in text for word in query_lower.split() if len(word) > 2):
67
+ continue
68
+
69
+ results.append({
70
+ "id": session.get("id", ""),
71
+ "topic": topic,
72
+ "summary": summary[:300] if summary else "",
73
+ "perspectives_count": len(perspectives) if isinstance(perspectives, list) else 0,
74
+ "created": created,
75
+ })
76
+
77
+ if len(results) >= limit:
78
+ break
79
+
80
+ return {"sessions": results}
81
+
82
+
83
+ def _resolve_session_id(session_id: str = None) -> str:
84
+ """Return the given session_id or derive the most recent one from stored sessions."""
85
+ if session_id:
86
+ return session_id
87
+ records = _sm.list("sessions")
88
+ if not records:
89
+ return None
90
+ # Sessions are expected to be in insertion order; take the last one.
91
+ latest = records[-1]
92
+ return latest.get("id", "")
93
+
94
+
95
+ def get_transcript(session_id: str = None) -> dict:
96
+ """Return the full transcript (all entries) for a session, in chronological order."""
97
+ sid = _resolve_session_id(session_id)
98
+ if not sid:
99
+ return {"session_id": None, "entries": [], "error": "No sessions found."}
100
+
101
+ data = _sm.get("transcripts", sid)
102
+ if not data:
103
+ return {
104
+ "session_id": sid,
105
+ "entries": [],
106
+ "error": f"No transcript found for session: {sid}",
107
+ }
108
+
109
+ entries = data.get("entries", [])
110
+ return {"session_id": sid, "entries": entries}
111
+
112
+
113
+ def get_persona(name: str, session_id: str = None) -> dict:
114
+ """Return all transcript entries from a specific persona (case-insensitive match)."""
115
+ sid = _resolve_session_id(session_id)
116
+ if not sid:
117
+ return {"session_id": None, "persona": name, "entries": [], "error": "No sessions found."}
118
+
119
+ data = _sm.get("transcripts", sid)
120
+ if not data:
121
+ return {
122
+ "session_id": sid,
123
+ "persona": name,
124
+ "entries": [],
125
+ "error": f"No transcript found for session: {sid}",
126
+ }
127
+
128
+ name_lower = name.lower()
129
+ entries = [
130
+ e for e in data.get("entries", [])
131
+ if e.get("persona_name", "").lower() == name_lower
132
+ ]
133
+
134
+ if not entries:
135
+ return {
136
+ "session_id": sid,
137
+ "persona": name,
138
+ "entries": [],
139
+ "error": f"No contributions found for persona: {name}",
140
+ }
141
+
142
+ return {"session_id": sid, "persona": name, "entries": entries}
143
+
144
+
145
+ def get_thinking(session_id: str = None) -> dict:
146
+ """Return all pre-synthesis perspective entries for a session."""
147
+ sid = _resolve_session_id(session_id)
148
+ if not sid:
149
+ return {"session_id": None, "entries": [], "error": "No sessions found."}
150
+
151
+ data = _sm.get("transcripts", sid)
152
+ if not data:
153
+ return {
154
+ "session_id": sid,
155
+ "entries": [],
156
+ "error": f"No transcript found for session: {sid}",
157
+ }
158
+
159
+ entries = [
160
+ e for e in data.get("entries", [])
161
+ if e.get("entry_type") == "perspective"
162
+ ]
163
+ return {"session_id": sid, "entries": entries}
164
+
165
+
166
+ def _print_entry(entry: dict, index: int = None) -> None:
167
+ """Pretty-print a single transcript entry."""
168
+ prefix = f"[{index}] " if index is not None else ""
169
+ round_num = entry.get("round", "?")
170
+ persona = entry.get("persona_name", "Unknown")
171
+ ptype = entry.get("persona_type", "")
172
+ etype = entry.get("entry_type", "")
173
+ timestamp = entry.get("timestamp", "")
174
+
175
+ type_label = f" ({etype})" if etype else ""
176
+ ptype_label = f" [{ptype}]" if ptype else ""
177
+ ts_label = f" {timestamp}" if timestamp else ""
178
+
179
+ print(f"\n{prefix}Round {round_num} — {persona}{ptype_label}{type_label}{ts_label}")
180
+ print("-" * 60)
181
+ thinking = entry.get("thinking", "").strip()
182
+ if thinking:
183
+ print(f"[thinking]\n{thinking}\n")
184
+ print(entry.get("raw_text", "").strip())
185
+
186
+
187
+ def main():
188
+ parser = argparse.ArgumentParser(description="wicked-jam query CLI")
189
+ subparsers = parser.add_subparsers(dest="command")
190
+
191
+ ls_parser = subparsers.add_parser("list-sessions", help="List brainstorming sessions")
192
+ ls_parser.add_argument("--query", "-q", help="Filter by topic/summary text")
193
+ ls_parser.add_argument("--limit", "-n", type=int, default=10, help="Max results")
194
+ ls_parser.add_argument("--json", action="store_true", help="Output as JSON")
195
+ ls_parser.add_argument("--project", "-p", help="Filter by project")
196
+
197
+ tr_parser = subparsers.add_parser("transcript", help="Full conversation transcript")
198
+ tr_parser.add_argument("--session-id", help="Session ID (defaults to most recent)")
199
+ tr_parser.add_argument("--json", action="store_true", help="Output as JSON")
200
+
201
+ pe_parser = subparsers.add_parser("persona", help="Specific persona's contributions")
202
+ pe_parser.add_argument("name", help="Persona name (case-insensitive)")
203
+ pe_parser.add_argument("--session-id", help="Session ID (defaults to most recent)")
204
+ pe_parser.add_argument("--json", action="store_true", help="Output as JSON")
205
+
206
+ th_parser = subparsers.add_parser("thinking", help="All pre-synthesis perspectives")
207
+ th_parser.add_argument("--session-id", help="Session ID (defaults to most recent)")
208
+ th_parser.add_argument("--json", action="store_true", help="Output as JSON")
209
+
210
+ args = parser.parse_args()
211
+
212
+ if not args.command:
213
+ parser.print_help()
214
+ sys.exit(1)
215
+
216
+ if args.command == "list-sessions":
217
+ result = list_sessions(
218
+ query=args.query,
219
+ limit=args.limit,
220
+ project=args.project,
221
+ )
222
+ if getattr(args, "json", False):
223
+ print(json.dumps(result, indent=2))
224
+ else:
225
+ sessions = result["sessions"]
226
+ if not sessions:
227
+ print("No sessions found.")
228
+ return
229
+ for s in sessions:
230
+ print(f" {s['id']}: {s['topic']} ({s['perspectives_count']} perspectives)")
231
+
232
+ elif args.command == "transcript":
233
+ result = get_transcript(session_id=getattr(args, "session_id", None))
234
+ if getattr(args, "json", False):
235
+ print(json.dumps(result, indent=2))
236
+ else:
237
+ error = result.get("error")
238
+ if error and not result["entries"]:
239
+ print(error)
240
+ return
241
+ sid = result.get("session_id", "")
242
+ entries = result["entries"]
243
+ print(f"Transcript — session: {sid} ({len(entries)} entries)")
244
+ for i, entry in enumerate(entries, start=1):
245
+ _print_entry(entry, index=i)
246
+
247
+ elif args.command == "persona":
248
+ result = get_persona(name=args.name, session_id=getattr(args, "session_id", None))
249
+ if getattr(args, "json", False):
250
+ print(json.dumps(result, indent=2))
251
+ else:
252
+ error = result.get("error")
253
+ if error and not result["entries"]:
254
+ print(error)
255
+ return
256
+ sid = result.get("session_id", "")
257
+ entries = result["entries"]
258
+ persona = result.get("persona", args.name)
259
+ print(f"Contributions from: {persona} | session: {sid} ({len(entries)} entries)")
260
+ for i, entry in enumerate(entries, start=1):
261
+ _print_entry(entry, index=i)
262
+
263
+ elif args.command == "thinking":
264
+ result = get_thinking(session_id=getattr(args, "session_id", None))
265
+ if getattr(args, "json", False):
266
+ print(json.dumps(result, indent=2))
267
+ else:
268
+ error = result.get("error")
269
+ if error and not result["entries"]:
270
+ print(error)
271
+ return
272
+ sid = result.get("session_id", "")
273
+ entries = result["entries"]
274
+ print(f"Pre-synthesis perspectives — session: {sid} ({len(entries)} entries)")
275
+ entries_with_thinking = [e for e in entries if e.get("thinking", "").strip()]
276
+ if entries and not entries_with_thinking:
277
+ print("No thinking data available for this session.")
278
+ for i, entry in enumerate(entries, start=1):
279
+ _print_entry(entry, index=i)
280
+
281
+
282
+ if __name__ == "__main__":
283
+ main()