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,216 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ guard_profiles.py — Profile definitions + auto-select logic for the
4
+ autonomous session-close guard pipeline (Issue #448).
5
+
6
+ Three tiered profiles govern how much work the guard pipeline does at
7
+ session close or phase checkpoints:
8
+
9
+ scalpel (~1s) — always runs. Regex/line-pattern scans only.
10
+ Debug artifacts + R1-R6 surface-level bulletproof
11
+ heuristics. Cheap enough to run on every Stop hook.
12
+
13
+ standard (~5s) — runs at build-phase close or session close after
14
+ substantial changes. Adds ADR constraint scan,
15
+ spec-drift semantic review (optional), and unresolved
16
+ skip-reeval entries.
17
+
18
+ deep (~30s) — runs on explicit invocation or release-branch sessions.
19
+ Full checks + deeper semantic review pass.
20
+
21
+ Auto-select rules (one-liner per profile):
22
+
23
+ deep — on release/main branch sessions OR explicit WG_GUARD_PROFILE=deep
24
+ standard — build-phase just closed, or >= 10 changed files in diff
25
+ scalpel — everything else (default, fail-open minimum)
26
+
27
+ The selector never raises; every branch falls back to ``scalpel`` on error.
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import os
33
+ import subprocess
34
+ from dataclasses import dataclass, field
35
+ from pathlib import Path
36
+ from typing import Iterable, List, Optional
37
+
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Budgets — seconds
41
+ # ---------------------------------------------------------------------------
42
+
43
+ SCALPEL_BUDGET_SECONDS = 1.0
44
+ STANDARD_BUDGET_SECONDS = 5.0
45
+ DEEP_BUDGET_SECONDS = 30.0
46
+
47
+ # Threshold of changed files that promotes scalpel → standard.
48
+ _SUBSTANTIAL_CHANGE_THRESHOLD = 10
49
+
50
+ # Branch names that auto-promote to deep.
51
+ _RELEASE_BRANCH_NAMES = frozenset({"main", "master", "release", "production"})
52
+
53
+
54
+ # ---------------------------------------------------------------------------
55
+ # Profile definitions
56
+ # ---------------------------------------------------------------------------
57
+
58
+ @dataclass(frozen=True)
59
+ class GuardProfile:
60
+ """Runtime profile for the guard pipeline."""
61
+
62
+ name: str
63
+ budget_seconds: float
64
+ checks: tuple # tuple of check-name strings
65
+ include_semantic_review: bool
66
+ description: str
67
+
68
+
69
+ # Check names — must match keys in guard_pipeline.CHECK_REGISTRY
70
+ _SCALPEL_CHECKS = ("bulletproof_scan", "debug_artifacts")
71
+ _STANDARD_CHECKS = (
72
+ "bulletproof_scan",
73
+ "debug_artifacts",
74
+ "adr_constraints",
75
+ "semantic_review",
76
+ "skip_log",
77
+ )
78
+ _DEEP_CHECKS = _STANDARD_CHECKS # same check set, deeper semantic review
79
+
80
+
81
+ SCALPEL = GuardProfile(
82
+ name="scalpel",
83
+ budget_seconds=SCALPEL_BUDGET_SECONDS,
84
+ checks=_SCALPEL_CHECKS,
85
+ include_semantic_review=False,
86
+ description="Fast regex-only scan (<1s). Always runs.",
87
+ )
88
+
89
+ STANDARD = GuardProfile(
90
+ name="standard",
91
+ budget_seconds=STANDARD_BUDGET_SECONDS,
92
+ checks=_STANDARD_CHECKS,
93
+ include_semantic_review=True,
94
+ description="Build-phase close or substantial changes (~5s).",
95
+ )
96
+
97
+ DEEP = GuardProfile(
98
+ name="deep",
99
+ budget_seconds=DEEP_BUDGET_SECONDS,
100
+ checks=_DEEP_CHECKS,
101
+ include_semantic_review=True,
102
+ description="Release branch or explicit invocation (~30s).",
103
+ )
104
+
105
+ _PROFILES_BY_NAME = {p.name: p for p in (SCALPEL, STANDARD, DEEP)}
106
+
107
+
108
+ def get_profile(name: str) -> GuardProfile:
109
+ """Return the named profile, falling back to scalpel on miss."""
110
+ return _PROFILES_BY_NAME.get((name or "").strip().lower(), SCALPEL)
111
+
112
+
113
+ # ---------------------------------------------------------------------------
114
+ # Auto-select logic
115
+ # ---------------------------------------------------------------------------
116
+
117
+ def _current_branch(cwd: Optional[Path] = None) -> Optional[str]:
118
+ """Return the current git branch, or None on error."""
119
+ try:
120
+ result = subprocess.run(
121
+ ["git", "rev-parse", "--abbrev-ref", "HEAD"],
122
+ cwd=str(cwd) if cwd else None,
123
+ capture_output=True,
124
+ text=True,
125
+ timeout=2,
126
+ )
127
+ if result.returncode == 0:
128
+ branch = result.stdout.strip()
129
+ return branch or None
130
+ except Exception:
131
+ pass # fail open — callers treat None as "unknown branch"
132
+ return None
133
+
134
+
135
+ def _count_changed_files(cwd: Optional[Path] = None) -> int:
136
+ """Count changed files vs HEAD (staged + unstaged + untracked tracked)."""
137
+ try:
138
+ result = subprocess.run(
139
+ ["git", "status", "--porcelain"],
140
+ cwd=str(cwd) if cwd else None,
141
+ capture_output=True,
142
+ text=True,
143
+ timeout=2,
144
+ )
145
+ if result.returncode == 0:
146
+ lines = [l for l in result.stdout.splitlines() if l.strip()]
147
+ return len(lines)
148
+ except Exception:
149
+ pass # fail open — treat unknowable diffs as "zero" (safest profile)
150
+ return 0
151
+
152
+
153
+ def auto_select(
154
+ *,
155
+ build_phase_just_closed: bool = False,
156
+ explicit_profile: Optional[str] = None,
157
+ cwd: Optional[Path] = None,
158
+ ) -> GuardProfile:
159
+ """Auto-select the guard profile based on session context.
160
+
161
+ Args:
162
+ build_phase_just_closed: True if the crew build phase was just approved
163
+ (promotes scalpel → standard).
164
+ explicit_profile: Overrides auto-selection. Takes env var
165
+ ``WG_GUARD_PROFILE`` into account when not supplied.
166
+ cwd: Working directory for git probes. Defaults to process cwd.
167
+
168
+ Returns:
169
+ The selected GuardProfile. Never raises — falls back to SCALPEL on error.
170
+ """
171
+ # Explicit arg wins
172
+ chosen = (explicit_profile or os.environ.get("WG_GUARD_PROFILE") or "").strip().lower()
173
+ if chosen in _PROFILES_BY_NAME:
174
+ return _PROFILES_BY_NAME[chosen]
175
+
176
+ try:
177
+ branch = _current_branch(cwd)
178
+ if branch and branch in _RELEASE_BRANCH_NAMES:
179
+ return DEEP
180
+
181
+ if build_phase_just_closed:
182
+ return STANDARD
183
+
184
+ changed = _count_changed_files(cwd)
185
+ if changed >= _SUBSTANTIAL_CHANGE_THRESHOLD:
186
+ return STANDARD
187
+ except Exception:
188
+ # Any unexpected error → safest (cheapest) profile
189
+ return SCALPEL
190
+
191
+ return SCALPEL
192
+
193
+
194
+ # ---------------------------------------------------------------------------
195
+ # CLI for debugging: `python3 guard_profiles.py --explain`
196
+ # ---------------------------------------------------------------------------
197
+
198
+ if __name__ == "__main__":
199
+ import json
200
+ import sys
201
+
202
+ args = sys.argv[1:]
203
+ if "--explain" in args:
204
+ profile = auto_select(cwd=Path.cwd())
205
+ out = {
206
+ "profile": profile.name,
207
+ "budget_seconds": profile.budget_seconds,
208
+ "checks": list(profile.checks),
209
+ "description": profile.description,
210
+ }
211
+ sys.stdout.write(json.dumps(out, indent=2))
212
+ sys.stdout.write("\n")
213
+ sys.exit(0)
214
+
215
+ sys.stdout.write("Usage: guard_profiles.py --explain\n")
216
+ sys.exit(1)
@@ -0,0 +1,434 @@
1
+ #!/usr/bin/env python3
2
+ """Contract assertion runner — validates subprocess outputs against JSON schemas.
3
+
4
+ Discovers schemas in schemas/{plugin}/{script-name}.json relative to the plugin
5
+ root, runs the corresponding script with --health-check (if supported) or a
6
+ minimal invocation, and validates the output against the schema.
7
+
8
+ Failure classes:
9
+ timeout — script did not complete within 10s
10
+ empty — script produced 0 bytes or empty JSON
11
+ malformed — output failed schema validation
12
+ pass — output validated successfully
13
+
14
+ Results are persisted via DomainStore("wicked-observability").
15
+
16
+ Usage:
17
+ python3 assert_contracts.py
18
+ python3 assert_contracts.py --plugin wicked-smaht
19
+ python3 assert_contracts.py --json
20
+ """
21
+
22
+ import argparse
23
+ import json
24
+ import os
25
+ import subprocess
26
+ import sys
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+
30
+ # Resolve _domain_store from the scripts/ directory.
31
+ # This file lives at scripts/platform/observability/, so scripts/ is parents[2].
32
+ sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
33
+ from _domain_store import DomainStore
34
+
35
+
36
+ # ── Constants ────────────────────────────────────────────────────────────────
37
+
38
+ PLUGIN_ROOT = Path(__file__).resolve().parent.parent.parent.parent # scripts/platform/observability/ → scripts/ → repo root
39
+ SCHEMAS_DIR = PLUGIN_ROOT / "schemas"
40
+ PLUGINS_ROOT = PLUGIN_ROOT.parent # …/plugins/
41
+ TIMEOUT_SECONDS = 10
42
+
43
+ _sm = DomainStore("wicked-observability")
44
+
45
+
46
+ # ── Minimal JSON Schema validator ────────────────────────────────────────────
47
+ # Implements: required, type, enum, properties (recursive), items (array)
48
+ # Does NOT require the jsonschema package.
49
+
50
+ _TYPE_MAP = {
51
+ "string": str,
52
+ "integer": int,
53
+ "number": (int, float),
54
+ "boolean": bool,
55
+ "null": type(None),
56
+ "array": list,
57
+ "object": dict,
58
+ }
59
+
60
+
61
+ def _validate(value, schema: dict, path: str = "$") -> list[dict]:
62
+ """Return a list of violation dicts; empty means valid."""
63
+ violations = []
64
+
65
+ # type check
66
+ expected_type = schema.get("type")
67
+ if expected_type:
68
+ # Python's bool is a subclass of int — reject bools for integer/number
69
+ if expected_type in ("integer", "number") and isinstance(value, bool):
70
+ violations.append({
71
+ "field": path,
72
+ "message": "type mismatch",
73
+ "expected": expected_type,
74
+ "actual": "boolean",
75
+ })
76
+ return violations
77
+ py_type = _TYPE_MAP.get(expected_type)
78
+ if py_type and not isinstance(value, py_type):
79
+ # JSON integers satisfy "number"
80
+ if not (expected_type == "number" and isinstance(value, (int, float))):
81
+ actual = type(value).__name__
82
+ violations.append({
83
+ "field": path,
84
+ "message": "type mismatch",
85
+ "expected": expected_type,
86
+ "actual": actual,
87
+ })
88
+ return violations # no point checking sub-constraints on wrong type
89
+
90
+ # enum check
91
+ enum_values = schema.get("enum")
92
+ if enum_values is not None and value not in enum_values:
93
+ violations.append({
94
+ "field": path,
95
+ "message": "value not in enum",
96
+ "expected": enum_values,
97
+ "actual": value,
98
+ })
99
+
100
+ # object properties + required
101
+ if isinstance(value, dict):
102
+ required = schema.get("required", [])
103
+ for field in required:
104
+ if field not in value:
105
+ violations.append({
106
+ "field": f"{path}.{field}",
107
+ "message": "required field missing",
108
+ "expected": "present",
109
+ "actual": "null",
110
+ })
111
+
112
+ properties = schema.get("properties", {})
113
+ for prop_name, prop_schema in properties.items():
114
+ if prop_name in value:
115
+ violations.extend(
116
+ _validate(value[prop_name], prop_schema, f"{path}.{prop_name}")
117
+ )
118
+
119
+ # array items
120
+ if isinstance(value, list):
121
+ items_schema = schema.get("items")
122
+ if items_schema:
123
+ for i, item in enumerate(value):
124
+ violations.extend(_validate(item, items_schema, f"{path}[{i}]"))
125
+
126
+ return violations
127
+
128
+
129
+ def validate_against_schema(data, schema: dict) -> list[dict]:
130
+ """Validate data against schema; return list of violations."""
131
+ return _validate(data, schema)
132
+
133
+
134
+ # ── Schema discovery ─────────────────────────────────────────────────────────
135
+
136
+
137
+ def discover_schemas(plugin_filter: str | None = None) -> list[dict]:
138
+ """
139
+ Walk SCHEMAS_DIR and yield schema descriptor dicts:
140
+ {plugin, script_name, schema_path, script_path | None}
141
+ """
142
+ if not SCHEMAS_DIR.exists():
143
+ return []
144
+
145
+ descriptors = []
146
+ # Read plugin name from plugin.json (single-plugin repo)
147
+ _plugin_json = PLUGIN_ROOT / ".claude-plugin" / "plugin.json"
148
+ _default_plugin = "wicked-garden"
149
+ if _plugin_json.exists():
150
+ try:
151
+ _default_plugin = json.loads(_plugin_json.read_text()).get("name", _default_plugin)
152
+ except Exception:
153
+ pass # fail open
154
+
155
+ for schema_path in sorted(SCHEMAS_DIR.rglob("*.json")):
156
+ parts = schema_path.relative_to(SCHEMAS_DIR).parts
157
+ if len(parts) == 2:
158
+ # Legacy layout: schemas/{plugin}/{script-name}.json
159
+ plugin_name, schema_file = parts
160
+ elif len(parts) == 1:
161
+ # Flat layout: schemas/{script-name}.json
162
+ plugin_name = _default_plugin
163
+ schema_file = parts[0]
164
+ else:
165
+ continue
166
+ script_name = schema_file[:-5] # strip .json → e.g. "orchestrator"
167
+
168
+ if plugin_filter and plugin_name != plugin_filter:
169
+ continue
170
+
171
+ script_path = _find_script(plugin_name, script_name)
172
+
173
+ descriptors.append({
174
+ "plugin": plugin_name,
175
+ "script_name": script_name + ".py",
176
+ "schema_path": schema_path,
177
+ "script_path": script_path,
178
+ })
179
+
180
+ return descriptors
181
+
182
+
183
+ def _find_script(plugin_name: str, script_name: str) -> Path | None:
184
+ """Locate the target script in the plugin's scripts/ directory.
185
+
186
+ Checks the flat scripts/ directory first, then scripts/v2/, and finally
187
+ searches all subdirectories under scripts/ (e.g. scripts/observability/).
188
+
189
+ Also supports the single-repo layout where this plugin IS the repo root
190
+ (i.e. schemas/wicked-garden/ lives alongside scripts/ at the repo root).
191
+ In that case PLUGINS_ROOT / plugin_name does not exist, so we fall back to
192
+ searching PLUGIN_ROOT / "scripts" directly.
193
+ """
194
+ target = f"{script_name}.py"
195
+
196
+ # Candidates in priority order: multi-repo layout first, single-repo fallback second.
197
+ scripts_dirs: list[Path] = []
198
+
199
+ external_scripts = PLUGINS_ROOT / plugin_name / "scripts"
200
+ if external_scripts.is_dir():
201
+ scripts_dirs.append(external_scripts)
202
+
203
+ # Single-repo fallback: this plugin's own scripts/ directory (e.g. scripts/observability/)
204
+ own_scripts = PLUGIN_ROOT / "scripts"
205
+ if own_scripts.is_dir() and own_scripts not in scripts_dirs:
206
+ scripts_dirs.append(own_scripts)
207
+
208
+ for scripts_dir in scripts_dirs:
209
+ # Direct match: scripts/{script_name}.py
210
+ candidate = scripts_dir / target
211
+ if candidate.exists():
212
+ return candidate
213
+
214
+ # Also check scripts/v2/ sub-directory (wicked-smaht pattern)
215
+ candidate_v2 = scripts_dir / "v2" / target
216
+ if candidate_v2.exists():
217
+ return candidate_v2
218
+
219
+ # Search all subdirectories under scripts/ (e.g. scripts/observability/)
220
+ matches = sorted(
221
+ m for m in scripts_dir.rglob(target)
222
+ if not any(p.startswith((".", "__")) or p == ".venv"
223
+ for p in m.relative_to(scripts_dir).parts)
224
+ )
225
+ if matches:
226
+ return matches[0]
227
+
228
+ return None
229
+
230
+
231
+ # ── Script invocation ────────────────────────────────────────────────────────
232
+
233
+
234
+ def _invoke_script(script_path: Path) -> tuple[str, float]:
235
+ """
236
+ Run script with --health-check; fall back to bare invocation if that flag
237
+ causes a non-zero exit.
238
+
239
+ Returns (stdout_text, duration_ms).
240
+ Raises subprocess.TimeoutExpired on timeout.
241
+ """
242
+ start = datetime.now(timezone.utc).timestamp()
243
+
244
+ def _run(extra_args: list[str]) -> subprocess.CompletedProcess:
245
+ env = {**os.environ, "WICKED_TRACE_ACTIVE": "1"}
246
+ return subprocess.run(
247
+ [sys.executable, str(script_path)] + extra_args,
248
+ capture_output=True,
249
+ text=True,
250
+ timeout=TIMEOUT_SECONDS,
251
+ env=env,
252
+ )
253
+
254
+ result = _run(["--health-check"])
255
+
256
+ # If health-check flag is unrecognised (argparse exits 2) retry without it
257
+ if result.returncode == 2 and "unrecognized arguments" in result.stderr:
258
+ result = _run([])
259
+
260
+ duration_ms = (datetime.now(timezone.utc).timestamp() - start) * 1000
261
+ return result.stdout or "", round(duration_ms, 1)
262
+
263
+
264
+ # ── Assertion logic ──────────────────────────────────────────────────────────
265
+
266
+
267
+ def run_assertion(descriptor: dict) -> dict:
268
+ """Run one contract assertion. Returns a result record."""
269
+ ts = datetime.now(timezone.utc).isoformat(timespec="milliseconds").replace("+00:00", "Z")
270
+ plugin = descriptor["plugin"]
271
+ script_name = descriptor["script_name"]
272
+ schema_path: Path = descriptor["schema_path"]
273
+ script_path: Path | None = descriptor["script_path"]
274
+
275
+ base = {
276
+ "ts": ts,
277
+ "plugin": plugin,
278
+ "script": script_name,
279
+ "result": "pass",
280
+ "violations": [],
281
+ "duration_ms": 0,
282
+ }
283
+
284
+ # Load schema
285
+ try:
286
+ schema = json.loads(schema_path.read_text(encoding="utf-8"))
287
+ except (OSError, json.JSONDecodeError) as exc:
288
+ base["result"] = "malformed"
289
+ base["violations"] = [{"field": "$", "message": f"could not load schema: {exc}",
290
+ "expected": "valid JSON schema", "actual": "error"}]
291
+ return base
292
+
293
+ if script_path is None:
294
+ base["result"] = "malformed"
295
+ base["violations"] = [{
296
+ "field": "$",
297
+ "message": f"script not found in {plugin}/scripts/",
298
+ "expected": f"{script_name}",
299
+ "actual": "missing",
300
+ }]
301
+ return base
302
+
303
+ # Invoke
304
+ try:
305
+ stdout, duration_ms = _invoke_script(script_path)
306
+ except subprocess.TimeoutExpired:
307
+ base["result"] = "timeout"
308
+ base["duration_ms"] = TIMEOUT_SECONDS * 1000
309
+ return base
310
+
311
+ base["duration_ms"] = round(duration_ms, 1)
312
+
313
+ # Empty check
314
+ if not stdout or not stdout.strip():
315
+ base["result"] = "empty"
316
+ base["violations"] = [{"field": "$", "message": "script produced no output",
317
+ "expected": "non-empty JSON", "actual": "empty"}]
318
+ return base
319
+
320
+ # Parse JSON
321
+ try:
322
+ data = json.loads(stdout.strip())
323
+ except json.JSONDecodeError as exc:
324
+ base["result"] = "malformed"
325
+ base["violations"] = [{"field": "$", "message": f"invalid JSON: {exc}",
326
+ "expected": "valid JSON", "actual": stdout[:200]}]
327
+ return base
328
+
329
+ if data is None or (isinstance(data, (dict, list)) and not data
330
+ and schema.get("type") not in ("array", "null")):
331
+ base["result"] = "empty"
332
+ base["violations"] = [{"field": "$", "message": "script returned empty JSON",
333
+ "expected": "non-empty object", "actual": "empty"}]
334
+ return base
335
+
336
+ # Schema validation
337
+ violations = validate_against_schema(data, schema)
338
+ if violations:
339
+ base["result"] = "malformed"
340
+ base["violations"] = violations
341
+
342
+ return base
343
+
344
+
345
+ # ── Output / storage ─────────────────────────────────────────────────────────
346
+
347
+
348
+ def append_result(record: dict) -> None:
349
+ """Persist a single assertion result via DomainStore."""
350
+ try:
351
+ _sm.create("assertions", record)
352
+ except Exception as exc:
353
+ print(f"WARNING: Could not persist assertion result: {exc}", file=sys.stderr)
354
+
355
+
356
+ # ── Formatting ───────────────────────────────────────────────────────────────
357
+
358
+ _RESULT_ICONS = {
359
+ "pass": "pass",
360
+ "timeout": "TIMEOUT",
361
+ "empty": "EMPTY",
362
+ "malformed": "MALFORMED",
363
+ }
364
+
365
+
366
+ def _print_human(results: list[dict]) -> None:
367
+ passed = sum(1 for r in results if r["result"] == "pass")
368
+ failed = len(results) - passed
369
+
370
+ for r in results:
371
+ icon = _RESULT_ICONS.get(r["result"], r["result"].upper())
372
+ label = f"[{icon}]"
373
+ line = f" {label:<12} {r['plugin']}/{r['script']} ({r['duration_ms']:.0f}ms)"
374
+ print(line)
375
+ for v in r.get("violations", []):
376
+ print(f" {v['field']}: {v['message']}"
377
+ f" (expected={v['expected']!r}, actual={v['actual']!r})")
378
+
379
+ print()
380
+ print(f"Results: {passed} passed, {failed} failed ({len(results)} total)")
381
+
382
+
383
+ # ── Main ─────────────────────────────────────────────────────────────────────
384
+
385
+
386
+ def main() -> None:
387
+ # Fast-path: --health-check emits a sample assertion result for contract testing
388
+ if "--health-check" in sys.argv:
389
+ print(json.dumps([{
390
+ "ts": datetime.now(timezone.utc).isoformat(),
391
+ "plugin": "health-check",
392
+ "script": "health-check.py",
393
+ "result": "pass",
394
+ "violations": [],
395
+ "duration_ms": 0.0,
396
+ }]))
397
+ return
398
+
399
+ parser = argparse.ArgumentParser(
400
+ description="Contract assertion runner for wicked-garden plugins")
401
+ parser.add_argument("--plugin", help="Only assert contracts for this plugin")
402
+ parser.add_argument("--json", action="store_true", dest="json_output",
403
+ help="Emit JSON array to stdout instead of human-readable text")
404
+ args = parser.parse_args()
405
+
406
+ descriptors = discover_schemas(plugin_filter=args.plugin)
407
+ if not descriptors:
408
+ target = args.plugin or "any plugin"
409
+ msg = f"No schemas found for {target} under {SCHEMAS_DIR}"
410
+ if args.json_output:
411
+ print(json.dumps({"error": msg, "data": [], "meta": {"total": 0}}))
412
+ else:
413
+ print(msg, file=sys.stderr)
414
+ sys.exit(0)
415
+
416
+ results = []
417
+ for descriptor in descriptors:
418
+ record = run_assertion(descriptor)
419
+ append_result(record)
420
+ results.append(record)
421
+
422
+ if args.json_output:
423
+ print(json.dumps(results, indent=2))
424
+ return
425
+
426
+ _print_human(results)
427
+
428
+ # Exit 1 if any failure so CI scripts can detect problems
429
+ if any(r["result"] != "pass" for r in results):
430
+ sys.exit(1)
431
+
432
+
433
+ if __name__ == "__main__":
434
+ main()