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,151 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ _logger.py — Structured operational logging for wicked-garden hook scripts.
4
+
5
+ Writes one JSONL line per call to $TMPDIR/wicked-ops-{session_id}.jsonl.
6
+ Fail-silent: never raises, never crashes the caller.
7
+
8
+ Usage:
9
+ from _logger import log
10
+
11
+ log("bootstrap", "normal", "onboarding.status", ok=True, detail={"has_memories": True})
12
+ log("smaht", "verbose", "prompt.routed", detail={"path": "fast", "turn": 1})
13
+ log("post_tool", "debug", "hook.end", ms=1.23)
14
+
15
+ Level hierarchy: normal (0) < verbose (1) < debug (2)
16
+ Effective level is resolved from: WICKED_LOG_LEVEL env var > SessionState.log_level > "normal"
17
+ """
18
+
19
+ import json
20
+ import os
21
+ from datetime import datetime, timezone
22
+ from pathlib import Path
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # Level constants
26
+ # ---------------------------------------------------------------------------
27
+
28
+ _LEVELS = {"normal": 0, "verbose": 1, "debug": 2}
29
+
30
+
31
+ # ---------------------------------------------------------------------------
32
+ # Internal helpers
33
+ # ---------------------------------------------------------------------------
34
+
35
+
36
+ def _get_session_id() -> str:
37
+ """Read and sanitize CLAUDE_SESSION_ID for use in filenames."""
38
+ import re
39
+ raw = os.environ.get("CLAUDE_SESSION_ID", "unknown")
40
+ safe = re.sub(r"[^a-zA-Z0-9\-_]", "_", raw)
41
+ return safe or "unknown"
42
+
43
+
44
+ def _log_file(session_id: str) -> Path:
45
+ """Return path to the ops JSONL log file for the given session."""
46
+ tmpdir = os.environ.get("TMPDIR") or __import__("tempfile").gettempdir()
47
+ return Path(tmpdir) / f"wicked-ops-{session_id}.jsonl"
48
+
49
+
50
+ def _resolve_level() -> str:
51
+ """Determine the effective log level.
52
+
53
+ Priority order:
54
+ 1. WICKED_LOG_LEVEL environment variable
55
+ 2. SessionState.log_level (read directly from raw JSON — no import)
56
+ 3. Default: "normal"
57
+ """
58
+ # 1. Environment variable (highest priority)
59
+ env = os.environ.get("WICKED_LOG_LEVEL", "").strip().lower()
60
+ if env in _LEVELS:
61
+ return env
62
+
63
+ # 2. SessionState JSON file (avoid circular import: read raw JSON directly)
64
+ try:
65
+ import json as _json
66
+ _sid = _get_session_id()
67
+ _tmpdir = os.environ.get("TMPDIR") or __import__("tempfile").gettempdir()
68
+ _state_path = Path(_tmpdir) / f"wicked-garden-session-{_sid}.json"
69
+ if _state_path.exists():
70
+ _data = _json.loads(_state_path.read_text(encoding="utf-8"))
71
+ _level = _data.get("log_level", "").strip().lower()
72
+ if _level in _LEVELS:
73
+ return _level
74
+ except Exception:
75
+ pass # Fail open — use default
76
+
77
+ # 3. Default
78
+ return "normal"
79
+
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # Public API
83
+ # ---------------------------------------------------------------------------
84
+
85
+
86
+ def log(
87
+ domain: str,
88
+ level: str,
89
+ event: str,
90
+ ok: bool = True,
91
+ ms: float | None = None,
92
+ detail: dict | None = None,
93
+ ) -> None:
94
+ """Write a structured log entry to the session ops JSONL file.
95
+
96
+ Args:
97
+ domain: Source domain, e.g. "bootstrap", "smaht", "crew"
98
+ level: Log level — "normal", "verbose", or "debug"
99
+ event: Dot-separated event name, e.g. "onboarding.status"
100
+ ok: Outcome indicator (default True)
101
+ ms: Elapsed milliseconds, rounded to 2 decimal places (optional)
102
+ detail: Arbitrary JSON-safe payload dict (optional)
103
+
104
+ This function never raises. All exceptions are silently swallowed.
105
+ """
106
+ try:
107
+ # Resolve effective level and filter
108
+ effective_level = _resolve_level()
109
+ event_rank = _LEVELS.get(level, 2) # Unknown levels treated as debug (most permissive)
110
+ effective_rank = _LEVELS.get(effective_level, 0)
111
+
112
+ if event_rank > effective_rank:
113
+ return # Silently discard — event is more verbose than the threshold
114
+
115
+ # Build the log entry
116
+ session_id = _get_session_id()
117
+ ts = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
118
+ ms_val = round(ms, 2) if ms is not None else None
119
+
120
+ # Serialize detail safely
121
+ detail_val: dict | None
122
+ if detail is None:
123
+ detail_val = None
124
+ else:
125
+ try:
126
+ json.dumps(detail) # Probe serializability
127
+ detail_val = detail
128
+ except (TypeError, ValueError):
129
+ detail_val = {"_raw": str(detail)}
130
+
131
+ entry = {
132
+ "ts": ts,
133
+ "session": session_id,
134
+ "domain": domain,
135
+ "level": level,
136
+ "event": event,
137
+ "ok": ok,
138
+ "ms": ms_val,
139
+ "detail": detail_val,
140
+ }
141
+
142
+ # Write one JSONL line — append mode, no fsync
143
+ log_path = _log_file(session_id)
144
+ try:
145
+ with log_path.open("a", encoding="utf-8") as fh:
146
+ fh.write(json.dumps(entry) + "\n")
147
+ except OSError:
148
+ pass # I/O errors are silently swallowed
149
+
150
+ except Exception:
151
+ pass # Outer catch — logger must never crash the caller
@@ -0,0 +1,482 @@
1
+ #!/usr/bin/env python3
2
+ """_loom.py — wicked-loom peer-resolution runtime (absorbed, Phase B).
3
+
4
+ After the wicked-* ecosystem rationalization (ECOSYSTEM-RATIONALIZATION.md
5
+ §5a Phase B), wicked-loom's peer-resolution capabilities are absorbed into
6
+ wicked-garden as ``scripts/loom/``. The standalone ``wicked-loom`` npm
7
+ package is no longer required — this module dispatches to the internal Python
8
+ modules in-process (no subprocess for loom itself).
9
+
10
+ The external interface is UNCHANGED — all callers (vault_gate.py,
11
+ phase_manager.py, bootstrap.py) continue to call resolve_loom(),
12
+ run_json(), use_loom(), loom_available() exactly as before.
13
+
14
+ RETIRED (not callable through this shim):
15
+ loom flow run / status / resume — replaced by wicked-crew.
16
+
17
+ ABSORBED (available in-process):
18
+ loom resolve <peer> -> scripts/loom/resolve.py
19
+ loom doctor [--strict] -> scripts/loom/compose.py
20
+ loom compose install [--peer X] -> scripts/loom/compose.py
21
+ loom gate <produces> [--scope S]-> scripts/loom/gate.py
22
+
23
+ Resolution notes
24
+ ----------------
25
+ The ``WICKED_LOOM_BIN`` env var is still respected as the highest-priority
26
+ override (env override beats internal), so debugging with a custom binary
27
+ still works. ``WICKED_LOOM_CUTOVER=off`` is the kill-switch — it disables
28
+ loom entirely (gates fail closed, peer resolution unavailable), identical to
29
+ the pre-absorption kill-switch. The internal path is selected by default
30
+ when the ``scripts/loom/`` package is importable (always true in a garden
31
+ install); the external subprocess fallback is used only when the internal
32
+ package is absent or ``_run`` is injected by tests.
33
+
34
+ Stdlib-only (plus the absorbed scripts/loom/ package). Cross-platform
35
+ (argv lists, shutil.which, no shell).
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ import json
41
+ import os
42
+ import shutil
43
+ import subprocess # noqa: S404 — argv lists only, shell=False
44
+ import sys
45
+ from pathlib import Path
46
+ from typing import Any, Callable, Dict, List, Optional
47
+
48
+ _CONFIG_PATH = Path.home() / ".something-wicked" / "wicked-garden" / "config.json"
49
+ _DEFAULT_TIMEOUT = 120
50
+ _CUTOVER_MODES = ("auto", "on", "off")
51
+ _PACKAGE = "wicked-loom"
52
+ _ENV_BIN = "WICKED_LOOM_BIN"
53
+ _ENV_FLAG = "WICKED_LOOM_CUTOVER"
54
+
55
+ # ---------------------------------------------------------------------------
56
+ # Internal module import (absorbed loom package)
57
+ # ---------------------------------------------------------------------------
58
+ # Add scripts/ to sys.path so ``import loom`` finds scripts/loom/ regardless
59
+ # of which directory the caller is running from.
60
+ _SCRIPTS_DIR = str(Path(__file__).resolve().parent)
61
+ if _SCRIPTS_DIR not in sys.path:
62
+ sys.path.insert(0, _SCRIPTS_DIR)
63
+
64
+ try:
65
+ from loom import resolve as _loom_resolve_mod
66
+ from loom import compose as _loom_compose_mod
67
+ from loom import gate as _loom_gate_mod
68
+ from loom import manifest as _loom_manifest_mod
69
+ _HAVE_INTERNAL = True
70
+ except ImportError: # pragma: no cover — only absent if scripts/loom/ is missing
71
+ _HAVE_INTERNAL = False
72
+
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Resolution ladder (for the external CLI fallback)
76
+ # ---------------------------------------------------------------------------
77
+
78
+ def _argv_for(target: str) -> List[str]:
79
+ """A .mjs/.js path is a script -> invoke via node; else run directly."""
80
+ if target.endswith((".mjs", ".js")):
81
+ return ["node", target]
82
+ return [target]
83
+
84
+
85
+ def _read_config_preference(key: str) -> Optional[str]:
86
+ """Read ``tool_preferences.{key}`` from config.json; None on any error."""
87
+ try:
88
+ if not _CONFIG_PATH.exists():
89
+ return None
90
+ data = json.loads(_CONFIG_PATH.read_text(encoding="utf-8"))
91
+ prefs = data.get("tool_preferences")
92
+ if isinstance(prefs, dict):
93
+ value = prefs.get(key)
94
+ if isinstance(value, str) and value.strip():
95
+ return value.strip()
96
+ return None
97
+ except (json.JSONDecodeError, OSError):
98
+ return None
99
+
100
+
101
+ def resolve_loom(*, allow_npx: bool = True,
102
+ project_dir: Optional[Path] = None) -> Optional[List[str]]:
103
+ """Return the argv prefix that invokes wicked-loom, or None.
104
+
105
+ After absorption the primary path is the internal Python module
106
+ (``_HAVE_INTERNAL``), not a subprocess. ``resolve_loom()`` now reflects
107
+ that: it returns a sentinel ``["_internal"]`` when the absorbed package is
108
+ importable, and falls back to the external CLI ladder only when it is not.
109
+
110
+ The ``WICKED_LOOM_BIN`` env override still takes highest priority — an
111
+ explicit override or kill-switch beats everything including the internal
112
+ module. This preserves the debugging escape hatch and the empty-string
113
+ kill-switch semantics.
114
+
115
+ Ladder (first hit wins):
116
+ 1. WICKED_LOOM_BIN env. Set-but-empty is the kill-switch -> None.
117
+ 2. Internal absorbed module (scripts/loom/) -> ["_internal"] sentinel.
118
+ 3. tool_preferences.wicked-loom in config.json.
119
+ 4. wicked-loom on PATH.
120
+ 5. project-local node_modules/.bin/wicked-loom.
121
+ 6. npx --yes wicked-loom (only when allow_npx).
122
+ """
123
+ # Step 1: explicit env override / kill-switch (highest priority)
124
+ if _ENV_BIN in os.environ:
125
+ env = os.environ[_ENV_BIN].strip()
126
+ return _argv_for(env) if env else None # empty == kill-switch
127
+
128
+ # Step 2: absorbed internal module (always available in a garden install)
129
+ if _HAVE_INTERNAL:
130
+ return ["_internal"]
131
+
132
+ # Steps 3-6: external CLI fallback
133
+ pref = _read_config_preference(_PACKAGE)
134
+ if pref:
135
+ return _argv_for(pref)
136
+
137
+ found = shutil.which(_PACKAGE)
138
+ if found:
139
+ return [found]
140
+
141
+ base = Path(project_dir) if project_dir else Path.cwd()
142
+ local = base / "node_modules" / ".bin" / _PACKAGE
143
+ if local.exists():
144
+ return [str(local)]
145
+
146
+ if allow_npx and shutil.which("npx"):
147
+ return ["npx", "--yes", _PACKAGE]
148
+
149
+ return None
150
+
151
+
152
+ def loom_available(project_dir: Optional[Path] = None) -> bool:
153
+ """True iff loom is concretely available — internal module or external install.
154
+
155
+ After absorption this returns True whenever the internal module is
156
+ importable (i.e., always in a properly installed wicked-garden). The
157
+ ``allow_npx=False`` semantics from before absorption: the npx last-resort
158
+ is excluded. The internal module is a concrete install by definition.
159
+ """
160
+ if _HAVE_INTERNAL:
161
+ return True
162
+ # External concrete probe (no npx)
163
+ return resolve_loom(allow_npx=False, project_dir=project_dir) is not None
164
+
165
+
166
+ # ---------------------------------------------------------------------------
167
+ # Internal dispatch (in-process, no subprocess for loom itself)
168
+ # ---------------------------------------------------------------------------
169
+
170
+ def _fmt(exit_code: int, payload: dict) -> Dict[str, Any]:
171
+ """Wrap an internal result in the standard run_json return shape."""
172
+ raw = json.dumps(payload)
173
+ return {"exit_code": exit_code, "json": payload, "stdout": raw,
174
+ "stderr": "", "error": None}
175
+
176
+
177
+ def _internal_resolve(args: List[str],
178
+ project_dir: Optional[Path] = None) -> Dict[str, Any]:
179
+ """``loom resolve <peer>`` — in-process via loom.resolve."""
180
+ if not args:
181
+ payload = {"error": "usage: loom resolve <peer>"}
182
+ return {"exit_code": 2, "json": payload, "stdout": json.dumps(payload),
183
+ "stderr": "", "error": None}
184
+ peer_name = args[0]
185
+ cmd = _loom_resolve_mod.resolve(peer_name)
186
+ payload = {"peer": peer_name, "command": cmd}
187
+ return _fmt(0 if cmd is not None else 1, payload)
188
+
189
+
190
+ def _internal_doctor(args: List[str]) -> Dict[str, Any]:
191
+ """``loom doctor [--strict]`` — in-process via loom.compose."""
192
+ strict = "--strict" in args
193
+ rows = _loom_compose_mod.check_all()
194
+ all_reachable = all(r.get("status") == "ok" for r in rows)
195
+ not_capable = [r.get("peer") for r in rows if not r.get("capability_ok")]
196
+ all_capable = not not_capable
197
+ payload = {
198
+ "peers": rows,
199
+ "all_reachable": all_reachable,
200
+ "all_capable": all_capable,
201
+ "not_capable": not_capable,
202
+ "strict": strict,
203
+ }
204
+ ok = all_reachable and (all_capable if strict else True)
205
+ return _fmt(0 if ok else 1, payload)
206
+
207
+
208
+ def _internal_compose(args: List[str]) -> Dict[str, Any]:
209
+ """``loom compose install [--peer X]`` — in-process via loom.compose."""
210
+ if not args or args[0] != "install":
211
+ payload = {"error": "usage: loom compose install [--peer <name>]"}
212
+ return {"exit_code": 2, "json": payload, "stdout": json.dumps(payload),
213
+ "stderr": "", "error": None}
214
+ target: Optional[str] = None
215
+ if "--peer" in args:
216
+ i = args.index("--peer")
217
+ if i + 1 < len(args):
218
+ target = args[i + 1]
219
+ names = [target] if target else list(_loom_manifest_mod.PEERS)
220
+ results = [_loom_compose_mod.install_peer(n) for n in names]
221
+ payload = {"results": results}
222
+ all_ok = all(r.get("status") == "installed" for r in results)
223
+ return _fmt(0 if all_ok else 1, payload)
224
+
225
+
226
+ def _internal_gate(args: List[str],
227
+ project_dir: Optional[Path] = None) -> Dict[str, Any]:
228
+ """``loom gate <produces> [--scope S] [--with-attestations]`` — in-process.
229
+
230
+ CWD preservation: the external loom subprocess path ran loom in
231
+ ``project_dir``, so vault (spawned by loom) also ran in that directory.
232
+ The internal path skips the loom subprocess, so we must forward
233
+ ``project_dir`` as the vault subprocess's CWD explicitly. Without this,
234
+ vault runs in the parent process CWD and cannot find the project's
235
+ ``.wicked/`` store — "no contract declared" (the #891 cwd regression,
236
+ re-introduced at the in-process boundary).
237
+ """
238
+ # Replicate cli.py's _positionals / _opt without importing cli (avoid
239
+ # circular dep; the cli module imports from loom.* not from _loom).
240
+ _value_opts = ("--scope", "--verifier-spec")
241
+
242
+ def _positionals(a: list) -> list:
243
+ out, i, n = [], 0, len(a)
244
+ while i < n:
245
+ tok = a[i]
246
+ if tok in _value_opts:
247
+ i += 2
248
+ continue
249
+ if tok.startswith("--"):
250
+ i += 1
251
+ continue
252
+ out.append(tok)
253
+ i += 1
254
+ return out
255
+
256
+ def _opt(a: list, name: str) -> Optional[str]:
257
+ if name in a:
258
+ idx = a.index(name)
259
+ if idx + 1 < len(a):
260
+ return a[idx + 1]
261
+ return None
262
+
263
+ scope = _opt(args, "--scope") or "default"
264
+ verifier_spec = _opt(args, "--verifier-spec")
265
+ positional = _positionals(args)
266
+ produces = positional[0] if positional else None
267
+
268
+ if produces is None:
269
+ payload = {"error": "usage: loom gate <produces> [--scope S] "
270
+ "[--verifier-spec PATH] [--with-attestations]"}
271
+ return {"exit_code": 2, "json": payload, "stdout": json.dumps(payload),
272
+ "stderr": "", "error": None}
273
+
274
+ # Build a runner that honours project_dir as the vault subprocess CWD.
275
+ # gate.run_gate shells wicked-vault (still external); only the loom layer
276
+ # moved in-process. When project_dir is provided we inject a custom runner
277
+ # so vault runs in the project directory — mirroring how the old external
278
+ # loom subprocess ran in project_dir and its own vault call inherited it.
279
+ if project_dir is not None:
280
+ _cwd = str(project_dir)
281
+
282
+ def _project_run(cmd: list, timeout: int = 30): # type: ignore[override]
283
+ from loom.compose import RunResult
284
+ p = subprocess.run( # noqa: S603
285
+ cmd, capture_output=True, text=True,
286
+ timeout=timeout, cwd=_cwd,
287
+ )
288
+ return RunResult(returncode=p.returncode,
289
+ stdout=p.stdout, stderr=p.stderr)
290
+
291
+ run_kwarg: Dict[str, Any] = {"run": _project_run}
292
+ else:
293
+ run_kwarg = {}
294
+
295
+ verdict = _loom_gate_mod.run_gate(
296
+ produces, scope=scope, verifier_spec=verifier_spec,
297
+ with_attestations="--with-attestations" in args,
298
+ **run_kwarg,
299
+ )
300
+ payload = {"gate": verdict}
301
+ return _fmt(0 if verdict.get("satisfied") else 1, payload)
302
+
303
+
304
+ def _dispatch_internal(args: List[str],
305
+ project_dir: Optional[Path] = None) -> Dict[str, Any]:
306
+ """Dispatch a loom command to the absorbed in-process modules.
307
+
308
+ Returns the same {exit_code, json, stdout, stderr, error} shape as the
309
+ external subprocess path so all callers are unchanged.
310
+ """
311
+ if not args:
312
+ payload = {"commands": ["resolve", "doctor", "compose", "gate"]}
313
+ return _fmt(0, payload)
314
+ cmd = args[0]
315
+ rest = args[1:]
316
+ if cmd == "resolve":
317
+ return _internal_resolve(rest, project_dir=project_dir)
318
+ if cmd == "doctor":
319
+ return _internal_doctor(rest)
320
+ if cmd == "compose":
321
+ return _internal_compose(rest)
322
+ if cmd == "gate":
323
+ return _internal_gate(rest, project_dir=project_dir)
324
+ if cmd == "flow":
325
+ payload = {
326
+ "error": "loom flow is retired",
327
+ "detail": (
328
+ "loom flow run/status/resume was the loom conduct surface, "
329
+ "replaced by wicked-crew + wicked-orchestration "
330
+ "(ECOSYSTEM-RATIONALIZATION.md §5a Phase B)."
331
+ ),
332
+ }
333
+ return {"exit_code": 2, "json": payload, "stdout": json.dumps(payload),
334
+ "stderr": "", "error": "loom flow is retired"}
335
+ payload = {"error": f"unknown command: {cmd}",
336
+ "commands": ["resolve", "doctor", "compose", "gate"]}
337
+ return {"exit_code": 2, "json": payload, "stdout": json.dumps(payload),
338
+ "stderr": "", "error": f"unknown loom command: {cmd}"}
339
+
340
+
341
+ # ---------------------------------------------------------------------------
342
+ # External subprocess runner (fallback / test injection)
343
+ # ---------------------------------------------------------------------------
344
+
345
+ def _default_run(prefix: List[str], args: List[str], timeout: int,
346
+ cwd: Optional[str] = None) -> Dict[str, Any]:
347
+ try:
348
+ proc = subprocess.run( # noqa: S603 — argv list, shell=False
349
+ prefix + args, capture_output=True, text=True, timeout=timeout,
350
+ cwd=cwd,
351
+ )
352
+ return {"exit_code": proc.returncode, "stdout": proc.stdout,
353
+ "stderr": proc.stderr, "error": None}
354
+ except FileNotFoundError:
355
+ return {"exit_code": None, "stdout": "", "stderr": "",
356
+ "error": "loom executable not found"}
357
+ except subprocess.TimeoutExpired:
358
+ return {"exit_code": None, "stdout": "", "stderr": "",
359
+ "error": f"loom call exceeded {timeout}s"}
360
+
361
+
362
+ Runner = Callable[..., Dict[str, Any]]
363
+
364
+
365
+ def run_json(args: List[str], *, timeout: int = _DEFAULT_TIMEOUT,
366
+ project_dir: Optional[Path] = None,
367
+ _run: Optional[Runner] = None) -> Dict[str, Any]:
368
+ """Run ``loom <args>``; return {exit_code, json, stdout, stderr, error}.
369
+
370
+ Never raises (R4). json is the parsed result or None (unresolvable,
371
+ not-found, timeout, non-JSON, or retired command).
372
+
373
+ Dispatch order:
374
+ 1. WICKED_LOOM_BIN env override (highest priority — beats even internal):
375
+ - Empty string -> kill-switch; return "not resolvable" immediately.
376
+ - Non-empty str -> use the specified external binary (debugging escape hatch).
377
+ 2. Internal absorbed modules (in-process) — when _HAVE_INTERNAL is True
378
+ and no _run override is injected AND no WICKED_LOOM_BIN is set.
379
+ This is the post-absorption default for normal operation.
380
+ 3. External subprocess — when _run is injected (tests), when the
381
+ internal package is absent, or when WICKED_LOOM_BIN is explicitly set.
382
+
383
+ ``_run`` is the injected subprocess runner (tests pass a fake). When
384
+ None AND _HAVE_INTERNAL (and WICKED_LOOM_BIN is unset), the internal
385
+ path is used (no subprocess for loom). When None AND not _HAVE_INTERNAL,
386
+ resolves _default_run at call time — so monkeypatching
387
+ ``_loom._default_run`` (the documented test seam) takes effect; binding
388
+ it as a default-arg value would freeze it at def-time.
389
+ """
390
+ # Step 1: explicit WICKED_LOOM_BIN env override (beats internal module).
391
+ # Non-empty -> debugging escape hatch: use that binary, skip internal.
392
+ # Empty -> deliberate kill-switch: no loom at all.
393
+ _env_override = os.environ.get(_ENV_BIN)
394
+ if _env_override is not None:
395
+ if not _env_override.strip():
396
+ return {"exit_code": None, "json": None, "stdout": "", "stderr": "",
397
+ "error": "wicked-loom not resolvable"}
398
+ # Non-empty override: fall through to external subprocess below.
399
+ elif _HAVE_INTERNAL and _run is None:
400
+ # Step 2: internal path — env override unset, internal modules available,
401
+ # no test injection.
402
+ return _dispatch_internal(args, project_dir=project_dir)
403
+
404
+ # External subprocess path (env override / test injection / no internal).
405
+ prefix = resolve_loom(project_dir=project_dir)
406
+ if prefix is None or prefix == ["_internal"]:
407
+ # "_internal" sentinel: internal was selected but _run was injected
408
+ # for testing; fall back to "not resolvable" in that edge case so
409
+ # tests that inject _run and expect the external path still work.
410
+ # (Normally _run injection only happens in tests that also mock
411
+ # resolve_loom, so this path is rarely hit in practice.)
412
+ if prefix == ["_internal"] and _run is not None:
413
+ # Test is injecting _run to exercise the subprocess path; honour it.
414
+ pass # fall through to the _run invocation below with a dummy prefix
415
+ else:
416
+ return {"exit_code": None, "json": None, "stdout": "", "stderr": "",
417
+ "error": "wicked-loom not resolvable"}
418
+
419
+ if _run is not None:
420
+ # Test seam: injected runner, use whatever prefix resolve_loom returned
421
+ # (or a mock prefix from patch.object).
422
+ effective_prefix = prefix if prefix and prefix != ["_internal"] else [_PACKAGE]
423
+ run_result = _run(effective_prefix, args, timeout)
424
+ else:
425
+ cwd = str(project_dir) if project_dir is not None else None
426
+ run_result = _default_run(prefix, args, timeout, cwd=cwd)
427
+
428
+ if run_result["error"] is not None:
429
+ return {"exit_code": None, "json": None, "stdout": "", "stderr": "",
430
+ "error": run_result["error"]}
431
+ try:
432
+ parsed = json.loads(run_result["stdout"]) if (run_result["stdout"] or "").strip() else {}
433
+ except json.JSONDecodeError:
434
+ return {"exit_code": run_result["exit_code"], "json": None,
435
+ "stdout": run_result["stdout"], "stderr": run_result["stderr"],
436
+ "error": "loom returned non-JSON output"}
437
+ return {"exit_code": run_result["exit_code"], "json": parsed,
438
+ "stdout": run_result["stdout"], "stderr": run_result["stderr"],
439
+ "error": None}
440
+
441
+
442
+ # ---------------------------------------------------------------------------
443
+ # Feature flag
444
+ # ---------------------------------------------------------------------------
445
+
446
+ def cutover_mode() -> str:
447
+ """The WICKED_LOOM_CUTOVER flag, normalized. Unknown -> 'auto'.
448
+
449
+ After absorption: 'auto' always uses loom (internal module is always
450
+ available). 'off' remains the kill-switch — disables loom entirely and
451
+ causes gates to fail closed. 'on' is unchanged.
452
+ """
453
+ raw = os.environ.get(_ENV_FLAG, "").strip().lower()
454
+ return raw if raw in _CUTOVER_MODES else "auto"
455
+
456
+
457
+ def use_loom(*, project_dir: Optional[Path] = None) -> bool:
458
+ """Should this call go through loom?
459
+
460
+ off -> never (emergency kill-switch; gate fails closed).
461
+ on -> always.
462
+ auto -> True when internal module is available (always in garden install),
463
+ OR when the external CLI resolves (backward compat for environments
464
+ without the absorbed package).
465
+
466
+ After absorption: auto is effectively always True in a garden install
467
+ because _HAVE_INTERNAL is True. The kill-switch (off) is preserved for
468
+ emergency disable.
469
+ """
470
+ mode = cutover_mode()
471
+ if mode == "off":
472
+ return False
473
+ if mode == "on":
474
+ return True
475
+ # auto: internal (absorbed) takes priority over external CLI check
476
+ if _HAVE_INTERNAL:
477
+ return True
478
+ return resolve_loom(project_dir=project_dir) is not None
479
+
480
+
481
+ __all__ = ["resolve_loom", "loom_available", "run_json",
482
+ "cutover_mode", "use_loom", "_HAVE_INTERNAL"]