@heretek-ai/epistemic-swarm 0.7.25 → 1.0.2

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 (350) hide show
  1. package/index.ts +1 -0
  2. package/package.json +63 -139
  3. package/rpc.ts +1 -0
  4. package/server.ts +1 -0
  5. package/src/agents.ts +69 -0
  6. package/src/continue.ts +40 -0
  7. package/src/hooks.ts +283 -0
  8. package/src/panels.tsx +220 -0
  9. package/src/policy.ts +221 -0
  10. package/src/pr.ts +37 -0
  11. package/src/research.ts +63 -0
  12. package/src/rpc-def.ts +136 -0
  13. package/src/rpc.ts +331 -0
  14. package/src/runtime.ts +112 -0
  15. package/src/server.ts +311 -0
  16. package/src/session.ts +61 -0
  17. package/src/tools.ts +61 -0
  18. package/src/tui.tsx +206 -0
  19. package/tui.tsx +1 -0
  20. package/.agents/skills/brainstorming/SKILL.md +0 -19
  21. package/.agents/skills/code_audit/SKILL.md +0 -19
  22. package/.agents/skills/darkharvest/SKILL.md +0 -19
  23. package/.agents/skills/epistemic_search/SKILL.md +0 -19
  24. package/.agents/skills/factory/SKILL.md +0 -19
  25. package/.agents/skills/grilling/SKILL.md +0 -19
  26. package/.agents/skills/oss_scout/SKILL.md +0 -19
  27. package/.agents/skills/research_cache/SKILL.md +0 -19
  28. package/.agents/skills/swarm_config/SKILL.md +0 -19
  29. package/.claude-plugin/marketplace.json +0 -61
  30. package/.claude-plugin/plugin.json +0 -76
  31. package/.omp/README.md +0 -39
  32. package/.omp/SYSTEM.md +0 -17
  33. package/.omp/commands/audit.md +0 -10
  34. package/.omp/commands/brainstorming.md +0 -12
  35. package/.omp/commands/darkharvest.md +0 -11
  36. package/.omp/commands/domainexpansion.md +0 -9
  37. package/.omp/commands/factory.md +0 -9
  38. package/.omp/commands/grill.md +0 -9
  39. package/.omp/commands/scout.md +0 -10
  40. package/.omp/commands/swarm-config.md +0 -10
  41. package/.omp/commands/swarm.md +0 -9
  42. package/.omp/hooks/post/epistemic-audit.ts +0 -16
  43. package/.omp/hooks/pre/epistemic-redirect.ts +0 -21
  44. package/.omp/prompts/brainstorming.md +0 -8
  45. package/.omp/prompts/swarm.md +0 -8
  46. package/LICENSE +0 -126
  47. package/MARKETPLACE.md +0 -130
  48. package/README.md +0 -403
  49. package/bin/cli.js +0 -297
  50. package/config/claude-settings-patch.json +0 -10
  51. package/config/docker-compose.infra.yml +0 -23
  52. package/config/domain_packs/biopharma.json +0 -23
  53. package/config/domain_packs/legal.json +0 -19
  54. package/config/domain_packs/quant.json +0 -19
  55. package/config/mcp-research-servers.json +0 -33
  56. package/config/mcp_launcher.py +0 -153
  57. package/config/opencode-snippet.json +0 -156
  58. package/config/searxng_mcp.py +0 -92
  59. package/extensions/pi/index.js +0 -357
  60. package/hooks/hooks.json +0 -45
  61. package/install.sh +0 -473
  62. package/plugins/antigravity/README.md +0 -72
  63. package/plugins/antigravity/agents/alpha-thesis.md +0 -36
  64. package/plugins/antigravity/agents/beta-antithesis.md +0 -35
  65. package/plugins/antigravity/agents/brainstormer.md +0 -27
  66. package/plugins/antigravity/agents/code-auditor.md +0 -28
  67. package/plugins/antigravity/agents/darkharvester.md +0 -30
  68. package/plugins/antigravity/agents/epistemic-auditor.md +0 -28
  69. package/plugins/antigravity/agents/manager.md +0 -26
  70. package/plugins/antigravity/agents/oss-scout.md +0 -27
  71. package/plugins/antigravity/agents/programmer.md +0 -25
  72. package/plugins/antigravity/agents/qa-a.md +0 -22
  73. package/plugins/antigravity/agents/qa-b.md +0 -22
  74. package/plugins/antigravity/antigravity_hooks.py +0 -265
  75. package/plugins/antigravity/commands/audit.md +0 -11
  76. package/plugins/antigravity/commands/brainstorm.md +0 -9
  77. package/plugins/antigravity/commands/brainstorming.md +0 -10
  78. package/plugins/antigravity/commands/darkharvest.md +0 -12
  79. package/plugins/antigravity/commands/domainexpansion.md +0 -12
  80. package/plugins/antigravity/commands/factory.md +0 -14
  81. package/plugins/antigravity/commands/grill.md +0 -10
  82. package/plugins/antigravity/commands/scout.md +0 -11
  83. package/plugins/antigravity/commands/swarm-config.md +0 -9
  84. package/plugins/antigravity/commands/swarm.md +0 -12
  85. package/plugins/antigravity/hook_bus_bridge.js +0 -352
  86. package/plugins/antigravity/hooks.json +0 -44
  87. package/plugins/antigravity/mcp_config.json +0 -33
  88. package/plugins/antigravity/mcp_launcher.py +0 -58
  89. package/plugins/antigravity/plugin.json +0 -13
  90. package/plugins/antigravity/rules/AGENTS.md +0 -127
  91. package/plugins/antigravity/rules/epistemic-integrity.md +0 -16
  92. package/plugins/antigravity/skills/brainstorming/SKILL.md +0 -19
  93. package/plugins/antigravity/skills/code_audit/SKILL.md +0 -19
  94. package/plugins/antigravity/skills/darkharvest/SKILL.md +0 -19
  95. package/plugins/antigravity/skills/epistemic_search/SKILL.md +0 -19
  96. package/plugins/antigravity/skills/factory/SKILL.md +0 -19
  97. package/plugins/antigravity/skills/grilling/SKILL.md +0 -19
  98. package/plugins/antigravity/skills/oss_scout/SKILL.md +0 -19
  99. package/plugins/antigravity/skills/research_cache/SKILL.md +0 -19
  100. package/plugins/antigravity/skills/swarm_config/SKILL.md +0 -19
  101. package/plugins/codex/AGENTS.md.snippet +0 -10
  102. package/plugins/codex/README.md +0 -37
  103. package/plugins/codex/config.toml.snippet +0 -28
  104. package/plugins/codex/openai.yaml +0 -24
  105. package/plugins/codex/skills/brainstorming/SKILL.md +0 -19
  106. package/plugins/codex/skills/code_audit/SKILL.md +0 -19
  107. package/plugins/codex/skills/darkharvest/SKILL.md +0 -19
  108. package/plugins/codex/skills/epistemic_search/SKILL.md +0 -19
  109. package/plugins/codex/skills/factory/SKILL.md +0 -19
  110. package/plugins/codex/skills/grilling/SKILL.md +0 -19
  111. package/plugins/codex/skills/oss_scout/SKILL.md +0 -19
  112. package/plugins/codex/skills/research_cache/SKILL.md +0 -19
  113. package/plugins/codex/skills/swarm_config/SKILL.md +0 -19
  114. package/plugins/darkharvest/.claude-plugin/plugin.json +0 -15
  115. package/plugins/darkharvest/agents/harvest-proponent.md +0 -22
  116. package/plugins/darkharvest/agents/harvest-redteam.md +0 -20
  117. package/plugins/darkharvest/evals/teardown-verdict/graders/license-line.md +0 -6
  118. package/plugins/darkharvest/evals/teardown-verdict/graders/skill-fired.md +0 -5
  119. package/plugins/darkharvest/evals/teardown-verdict/prompt.md +0 -6
  120. package/plugins/darkharvest/skills/darkharvest/SKILL.md +0 -70
  121. package/plugins/darkharvest/skills/darkharvest/scripts/harvest.py +0 -289
  122. package/plugins/factory/.claude-plugin/plugin.json +0 -15
  123. package/plugins/factory/agents/factory-manager.md +0 -22
  124. package/plugins/factory/agents/programmer.md +0 -16
  125. package/plugins/factory/agents/qa-adversarial.md +0 -17
  126. package/plugins/factory/agents/qa-functional.md +0 -17
  127. package/plugins/factory/evals/gate-halt/graders/gates-first.md +0 -6
  128. package/plugins/factory/evals/gate-halt/graders/skill-fired.md +0 -5
  129. package/plugins/factory/evals/gate-halt/prompt.md +0 -6
  130. package/plugins/factory/skills/factory/SKILL.md +0 -61
  131. package/plugins/factory/skills/factory/scripts/factory.py +0 -300
  132. package/plugins/gemini/GEMINI.md +0 -16
  133. package/plugins/gemini/README.md +0 -20
  134. package/plugins/gemini/commands/audit.toml +0 -6
  135. package/plugins/gemini/commands/brainstorming.toml +0 -10
  136. package/plugins/gemini/commands/darkharvest.toml +0 -8
  137. package/plugins/gemini/commands/domainexpansion.toml +0 -7
  138. package/plugins/gemini/commands/factory.toml +0 -8
  139. package/plugins/gemini/commands/grill.toml +0 -6
  140. package/plugins/gemini/commands/scout.toml +0 -7
  141. package/plugins/gemini/commands/swarm-config.toml +0 -7
  142. package/plugins/gemini/commands/swarm.toml +0 -8
  143. package/plugins/gemini/gemini-extension.json +0 -38
  144. package/plugins/gemini/hooks/hooks.json +0 -11
  145. package/plugins/gemini/skills/brainstorming/SKILL.md +0 -19
  146. package/plugins/gemini/skills/code_audit/SKILL.md +0 -19
  147. package/plugins/gemini/skills/darkharvest/SKILL.md +0 -19
  148. package/plugins/gemini/skills/epistemic_search/SKILL.md +0 -19
  149. package/plugins/gemini/skills/factory/SKILL.md +0 -19
  150. package/plugins/gemini/skills/grilling/SKILL.md +0 -19
  151. package/plugins/gemini/skills/oss_scout/SKILL.md +0 -19
  152. package/plugins/gemini/skills/research_cache/SKILL.md +0 -19
  153. package/plugins/gemini/skills/swarm_config/SKILL.md +0 -19
  154. package/plugins/opencode/analysis-bridge.js +0 -620
  155. package/plugins/opencode/config-io.js +0 -1651
  156. package/plugins/opencode/dep-health.js +0 -1039
  157. package/plugins/opencode/hook-bus.js +0 -496
  158. package/plugins/opencode/index.js +0 -2992
  159. package/plugins/opencode/tui.js +0 -1551
  160. package/plugins/opencode/weight-baseline.json +0 -16
  161. package/plugins/opencode/weight-signals.js +0 -769
  162. package/plugins/research-cache/.claude-plugin/plugin.json +0 -15
  163. package/plugins/research-cache/skills/research_cache/SKILL.md +0 -36
  164. package/plugins/research-cache/skills/research_cache/__init__.py +0 -0
  165. package/plugins/research-cache/skills/research_cache/hasher.py +0 -302
  166. package/plugins/socratic-grilling/.claude-plugin/plugin.json +0 -15
  167. package/plugins/socratic-grilling/skills/grilling/SKILL.md +0 -61
  168. package/plugins/socratic-grilling/skills/grilling/__init__.py +0 -0
  169. package/plugins/socratic-grilling/skills/grilling/socratic_tree.py +0 -363
  170. package/prompts/agent_alpha_thesis.md +0 -70
  171. package/prompts/agent_beta_antithesis.md +0 -78
  172. package/prompts/agent_brainstormer.md +0 -143
  173. package/prompts/agent_code_auditor.md +0 -88
  174. package/prompts/agent_darkharvest.md +0 -140
  175. package/prompts/agent_oss_scout.md +0 -78
  176. package/prompts/antigravity_repo_factcheck.md +0 -143
  177. package/prompts/base_epistemic_system.md +0 -50
  178. package/prompts/epistemic_auditor.md +0 -74
  179. package/prompts/orchestrator.md +0 -70
  180. package/runner/__init__.py +0 -0
  181. package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
  182. package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
  183. package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
  184. package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
  185. package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
  186. package/runner/__pycache__/darkharvest_claims.cpython-311.pyc +0 -0
  187. package/runner/__pycache__/errors.cpython-311.pyc +0 -0
  188. package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
  189. package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
  190. package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
  191. package/runner/__pycache__/path_safety.cpython-311.pyc +0 -0
  192. package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
  193. package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
  194. package/runner/__pycache__/preflight.cpython-311.pyc +0 -0
  195. package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
  196. package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
  197. package/runner/__pycache__/retrieval_log.cpython-311.pyc +0 -0
  198. package/runner/__pycache__/schema_validate.cpython-311.pyc +0 -0
  199. package/runner/__pycache__/schemas.cpython-311.pyc +0 -0
  200. package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
  201. package/runner/antigravity_hooks.py +0 -265
  202. package/runner/auctioneer.py +0 -169
  203. package/runner/auditor_engine.py +0 -711
  204. package/runner/claim_store.py +0 -417
  205. package/runner/claim_witness.py +0 -412
  206. package/runner/darkharvest_claims.py +0 -358
  207. package/runner/errors.py +0 -51
  208. package/runner/living_dossiers.py +0 -395
  209. package/runner/mcp_protocol.py +0 -188
  210. package/runner/mcp_server.py +0 -1447
  211. package/runner/path_safety.py +0 -62
  212. package/runner/pcrb.py +0 -290
  213. package/runner/pcrb_verify.py +0 -267
  214. package/runner/preflight.py +0 -1011
  215. package/runner/refinement.py +0 -580
  216. package/runner/research_swarm.py +0 -1848
  217. package/runner/retrieval_log.py +0 -90
  218. package/runner/schema_validate.py +0 -193
  219. package/runner/schemas.py +0 -630
  220. package/runner/state_machine.py +0 -463
  221. package/runner/tests/__pycache__/test_analysis_bridge.cpython-311.pyc +0 -0
  222. package/runner/tests/__pycache__/test_antigravity_plugin.cpython-311.pyc +0 -0
  223. package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
  224. package/runner/tests/__pycache__/test_backends.cpython-311.pyc +0 -0
  225. package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
  226. package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
  227. package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
  228. package/runner/tests/__pycache__/test_claude_plugin.cpython-311.pyc +0 -0
  229. package/runner/tests/__pycache__/test_config_schema.cpython-311.pyc +0 -0
  230. package/runner/tests/__pycache__/test_contract_tooling.cpython-311.pyc +0 -0
  231. package/runner/tests/__pycache__/test_darkharvest_audit.cpython-311.pyc +0 -0
  232. package/runner/tests/__pycache__/test_dep_health.cpython-311.pyc +0 -0
  233. package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
  234. package/runner/tests/__pycache__/test_dossier_contract.cpython-311.pyc +0 -0
  235. package/runner/tests/__pycache__/test_factory.cpython-311.pyc +0 -0
  236. package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
  237. package/runner/tests/__pycache__/test_frontier_concurrency.cpython-311.pyc +0 -0
  238. package/runner/tests/__pycache__/test_frontier_mirror_standalone.cpython-311.pyc +0 -0
  239. package/runner/tests/__pycache__/test_grounding.cpython-311.pyc +0 -0
  240. package/runner/tests/__pycache__/test_hardening_contract.cpython-311.pyc +0 -0
  241. package/runner/tests/__pycache__/test_hook_bus.cpython-311.pyc +0 -0
  242. package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
  243. package/runner/tests/__pycache__/test_manifest_concurrency.cpython-311.pyc +0 -0
  244. package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
  245. package/runner/tests/__pycache__/test_nk_hardening.cpython-311.pyc +0 -0
  246. package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
  247. package/runner/tests/__pycache__/test_opencode_v2_registrars.cpython-311.pyc +0 -0
  248. package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
  249. package/runner/tests/__pycache__/test_phase08_waiver_reopens.cpython-311.pyc +0 -0
  250. package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
  251. package/runner/tests/__pycache__/test_search_anomaly.cpython-311.pyc +0 -0
  252. package/runner/tests/__pycache__/test_search_provider.cpython-311.pyc +0 -0
  253. package/runner/tests/__pycache__/test_search_provider_plugin.cpython-311.pyc +0 -0
  254. package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
  255. package/runner/tests/__pycache__/test_swarm_config.cpython-311.pyc +0 -0
  256. package/runner/tests/__pycache__/test_sweep_regressions.cpython-311.pyc +0 -0
  257. package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
  258. package/runner/tests/__pycache__/test_weight_signals.cpython-311.pyc +0 -0
  259. package/runner/tests/fixtures/auction_objective.json +0 -35
  260. package/runner/tests/fixtures/borderline_claims.json +0 -27
  261. package/runner/tests/fixtures/config_validation_cases.json +0 -276
  262. package/runner/tests/fixtures/ddg_anomaly_page.html +0 -176
  263. package/runner/tests/fixtures/ddg_results_page.html +0 -28
  264. package/runner/tests/fixtures/divergence_objectives.json +0 -31
  265. package/runner/tests/test_analysis_bridge.py +0 -450
  266. package/runner/tests/test_antigravity_plugin.py +0 -361
  267. package/runner/tests/test_auction_order.py +0 -173
  268. package/runner/tests/test_backends.py +0 -457
  269. package/runner/tests/test_bet1_spike.py +0 -95
  270. package/runner/tests/test_claim_store.py +0 -162
  271. package/runner/tests/test_claim_witness.py +0 -186
  272. package/runner/tests/test_claude_plugin.py +0 -170
  273. package/runner/tests/test_config_schema.py +0 -879
  274. package/runner/tests/test_contract_tooling.py +0 -312
  275. package/runner/tests/test_darkharvest_audit.py +0 -395
  276. package/runner/tests/test_dep_health.py +0 -595
  277. package/runner/tests/test_domain_packs.py +0 -217
  278. package/runner/tests/test_dossier_contract.py +0 -196
  279. package/runner/tests/test_factory.py +0 -258
  280. package/runner/tests/test_fleet_seam.py +0 -113
  281. package/runner/tests/test_frontier_concurrency.py +0 -288
  282. package/runner/tests/test_frontier_mirror_standalone.py +0 -156
  283. package/runner/tests/test_grounding.py +0 -183
  284. package/runner/tests/test_hardening_contract.py +0 -391
  285. package/runner/tests/test_hook_bus.py +0 -956
  286. package/runner/tests/test_living_dossiers.py +0 -204
  287. package/runner/tests/test_manifest_concurrency.py +0 -187
  288. package/runner/tests/test_mcp_server.py +0 -257
  289. package/runner/tests/test_nk_hardening.py +0 -1046
  290. package/runner/tests/test_opencode_ux.py +0 -2438
  291. package/runner/tests/test_opencode_v2_registrars.py +0 -2157
  292. package/runner/tests/test_pcrb.py +0 -240
  293. package/runner/tests/test_phase08_waiver_reopens.py +0 -539
  294. package/runner/tests/test_refinement.py +0 -255
  295. package/runner/tests/test_search_anomaly.py +0 -342
  296. package/runner/tests/test_search_provider.py +0 -1534
  297. package/runner/tests/test_search_provider_plugin.py +0 -401
  298. package/runner/tests/test_swarm.py +0 -444
  299. package/runner/tests/test_swarm_config.py +0 -520
  300. package/runner/tests/test_sweep_regressions.py +0 -453
  301. package/runner/tests/test_webcache.py +0 -271
  302. package/runner/tests/test_weight_signals.py +0 -401
  303. package/schemas/alpha_dossier.schema.json +0 -204
  304. package/schemas/audit_report.schema.json +0 -79
  305. package/schemas/beta_dossier.schema.json +0 -214
  306. package/schemas/config.schema.json +0 -311
  307. package/schemas/frontier.schema.json +0 -61
  308. package/schemas/manifest.schema.json +0 -49
  309. package/schemas/scope_manifest.schema.json +0 -47
  310. package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
  311. package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
  312. package/scripts/__pycache__/check_docs.cpython-311.pyc +0 -0
  313. package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
  314. package/scripts/__pycache__/gen_schemas.cpython-311.pyc +0 -0
  315. package/scripts/auction_experiment.py +0 -188
  316. package/scripts/bet1_advisory_spike.py +0 -442
  317. package/scripts/build_adapters.py +0 -417
  318. package/scripts/check_docs.py +0 -66
  319. package/scripts/divergence_experiment.py +0 -214
  320. package/scripts/gen_schemas.py +0 -69
  321. package/skills/brainstorming/SKILL.md +0 -106
  322. package/skills/brainstorming/__init__.py +0 -1
  323. package/skills/brainstorming/scripts/brainstorm.py +0 -201
  324. package/skills/code_audit/SKILL.md +0 -45
  325. package/skills/darkharvest/SKILL.md +0 -70
  326. package/skills/darkharvest/scripts/harvest.py +0 -289
  327. package/skills/epistemic_search/SKILL.md +0 -67
  328. package/skills/epistemic_search/__init__.py +0 -1
  329. package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
  330. package/skills/epistemic_search/scripts/fetch.py +0 -156
  331. package/skills/epistemic_search/scripts/search.py +0 -551
  332. package/skills/epistemic_search/scripts/webcache.py +0 -339
  333. package/skills/factory/SKILL.md +0 -61
  334. package/skills/factory/scripts/factory.py +0 -300
  335. package/skills/grilling/SKILL.md +0 -61
  336. package/skills/grilling/__init__.py +0 -0
  337. package/skills/grilling/__pycache__/__init__.cpython-311.pyc +0 -0
  338. package/skills/grilling/__pycache__/socratic_tree.cpython-311.pyc +0 -0
  339. package/skills/grilling/socratic_tree.py +0 -363
  340. package/skills/oss_scout/SKILL.md +0 -49
  341. package/skills/research_cache/SKILL.md +0 -36
  342. package/skills/research_cache/__init__.py +0 -0
  343. package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
  344. package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
  345. package/skills/research_cache/hasher.py +0 -302
  346. package/skills/swarm_config/SKILL.md +0 -178
  347. package/skills/swarm_config/__init__.py +0 -35
  348. package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
  349. package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
  350. package/skills/swarm_config/configure.py +0 -1002
@@ -1,450 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Tests for Phase 02-lsp-bridge: CLI-based JS/TS analysis behind the hook bus.
3
-
4
- Mock-host only (no live TUI, no real Biome spawn): the analyzer is an
5
- injected mock, every budget is tens of milliseconds, at most zero MCP
6
- spawns. Pins: dirty-file advisory (findings + allowed:true), clean-file
7
- empty, analyzer-missing skip (single audit entry, silent), never-deny
8
- (severe findings still allow), audit-shape (tool/eventId keys on every
9
- annotation), slow-overrun (timeout annotation, caller unblocked), and the
10
- setup adopt/dispose wiring in plugins/opencode/index.js.
11
-
12
- Phase evidence cited in-code per brief:
13
- [VERIFIED: sha256:f2c0843b598ba6f19cc0e208f8d02e0250c70615e3c484474d50635d0b5cdef8]
14
- [VERIFIED: sha256:640ab94a0408cef8cc14fb2cbf52f041021a1ce012590b41e8063075a21b2c8f]
15
- [VERIFIED: sha256:69cacc4b62c2c1fccd5f5f3cf4d78398eb7310ceeb36e9ef423868e530771d90]
16
- [VERIFIED: sha256:2b08ae78a2475e7d3b3427ba089542f8bd76635b87ab397066af8c0355651fbd]
17
- [VERIFIED: sha256:7cbceba66852b3d8405d78833d0ce1dad7a25423af59cbacdea2790ba83e4b2a]
18
- """
19
-
20
- import json
21
- import subprocess
22
- import sys
23
- import unittest
24
- from pathlib import Path
25
-
26
- PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
27
- if str(PROJECT_ROOT) not in sys.path:
28
- sys.path.insert(0, str(PROJECT_ROOT))
29
-
30
-
31
- def run_node(code):
32
- return subprocess.run(
33
- ["node", "--input-type=module", "-e", code],
34
- capture_output=True,
35
- text=True,
36
- cwd=str(PROJECT_ROOT),
37
- )
38
-
39
-
40
- def last_json_object(stdout):
41
- lines = [
42
- line.strip()
43
- for line in stdout.strip().split("\n")
44
- if line.strip().startswith("{")
45
- ]
46
- return json.loads(lines[-1])
47
-
48
-
49
- BRIDGE_IMPORT = (
50
- 'import { createHookBus } from "./plugins/opencode/hook-bus.js";\n'
51
- 'import { analyzePayload, collectTargets, createBridgeHandler, registerAnalysisBridge } from "./plugins/opencode/analysis-bridge.js";\n'
52
- )
53
-
54
- MOCK_TWO_FINDINGS = """
55
- const runAnalyzer = async (files) => ({
56
- status: "ok",
57
- findings: [
58
- { rule: "lint/suspicious/noDebugger", file: files[0], line: 3, message: "Unexpected debugger statement.", severity: "error" },
59
- { rule: "lint/style/useConst", file: files[0], line: 1, message: "This let could be const.", severity: "warning" },
60
- ],
61
- });
62
- """
63
-
64
- SETUP_BRIDGE = """
65
- const bus = createHookBus();
66
- const notices = [];
67
- const notify = (s) => { notices.push(s); };
68
- const reg = await registerAnalysisBridge(null, { bus, runAnalyzer, notify, timeoutMs: 200 });
69
- """
70
-
71
-
72
- class TestDirtyFileAdvisory(unittest.TestCase):
73
- def test_dirty_file_yields_findings_and_allows(self):
74
- res = run_node(
75
- BRIDGE_IMPORT
76
- + MOCK_TWO_FINDINGS
77
- + SETUP_BRIDGE
78
- + """
79
- const r = await bus.emit("pre-tool-use", {tool: "edit", eventId: "e-dirty", file: "src/app.ts"});
80
- const audit = bus.getAuditLog();
81
- const findingAudits = audit.filter((a) => a.event === "notification" && a.tool === "edit" && a.eventId === "e-dirty");
82
- console.log(JSON.stringify({
83
- allowed: r.allowed,
84
- notices: notices.length,
85
- notice: notices[0] && notices[0].message,
86
- findingAudits: findingAudits.length,
87
- reasons: findingAudits.map((a) => a.reason || ""),
88
- }));
89
- """
90
- )
91
- self.assertEqual(res.returncode, 0, f"dirty advisory test failed: {res.stderr}")
92
- data = last_json_object(res.stdout)
93
- self.assertTrue(data["allowed"], "dirty file must still allow (all-advisory)")
94
- self.assertEqual(data["notices"], 1, "exactly one toast summary per analysis")
95
- self.assertIn("2 finding", data["notice"])
96
- # Toast summarizes counts only: no rule ids, no finding text.
97
- self.assertNotIn("noDebugger", data["notice"])
98
- self.assertNotIn("debugger statement", data["notice"])
99
- self.assertEqual(
100
- data["findingAudits"], 2, "every finding audit-logged on the bus"
101
- )
102
- self.assertTrue(
103
- any("lint/suspicious/noDebugger" in reason for reason in data["reasons"]),
104
- "finding rule must ride in the audit entry reason",
105
- )
106
- self.assertTrue(
107
- any("lint/style/useConst" in reason for reason in data["reasons"]),
108
- "every finding rule must be audit-logged",
109
- )
110
-
111
-
112
- class TestCleanFileEmpty(unittest.TestCase):
113
- def test_clean_file_no_annotations(self):
114
- res = run_node(
115
- BRIDGE_IMPORT
116
- + """
117
- const runAnalyzer = async () => ({status: "ok", findings: []});
118
- """
119
- + SETUP_BRIDGE
120
- + """
121
- const direct = await analyzePayload({tool: "edit", eventId: "e-clean", file: "src/ok.ts"}, {runAnalyzer, timeoutMs: 200});
122
- const r = await bus.emit("post-tool-use", {tool: "edit", eventId: "e-clean", file: "src/ok.ts"});
123
- console.log(JSON.stringify({
124
- allowed: direct.allowed, annotations: direct.annotations,
125
- emitAllowed: r.allowed, notices: notices.length,
126
- }));
127
- """
128
- )
129
- self.assertEqual(res.returncode, 0, f"clean test failed: {res.stderr}")
130
- data = last_json_object(res.stdout)
131
- self.assertTrue(data["allowed"])
132
- self.assertEqual(data["annotations"], [])
133
- self.assertTrue(data["emitAllowed"])
134
- self.assertEqual(data["notices"], 0, "clean file must not toast")
135
-
136
-
137
- class TestAnalyzerMissingSkip(unittest.TestCase):
138
- def test_missing_analyzer_single_audit_silent_skip(self):
139
- res = run_node(
140
- BRIDGE_IMPORT
141
- + """
142
- const runAnalyzer = async () => ({status: "missing"});
143
- """
144
- + SETUP_BRIDGE
145
- + """
146
- const mark = bus.getAuditLog().length;
147
- let threw = false;
148
- let r = null;
149
- try {
150
- r = await bus.emit("pre-tool-use", {tool: "edit", eventId: "e-miss", file: "src/app.ts"});
151
- } catch { threw = true; }
152
- const fresh = bus.getAuditLog().slice(mark);
153
- console.log(JSON.stringify({
154
- threw, allowed: r && r.allowed,
155
- fresh: fresh.length,
156
- outcomes: fresh.map((a) => a.outcome),
157
- reasons: fresh.map((a) => a.reason || ""),
158
- notices: notices.length,
159
- }));
160
- """
161
- )
162
- self.assertEqual(res.returncode, 0, f"missing test failed: {res.stderr}")
163
- data = last_json_object(res.stdout)
164
- self.assertFalse(data["threw"], "analyzer-missing must never throw")
165
- self.assertTrue(data["allowed"], "analyzer-missing must fail open")
166
- self.assertEqual(data["fresh"], 1, "exactly one audit entry for the skip")
167
- self.assertEqual(data["outcomes"], ["allow"])
168
- self.assertTrue(any("analyzer" in reason for reason in data["reasons"]))
169
- self.assertEqual(
170
- data["notices"], 0, "missing analyzer must stay silent (no toast)"
171
- )
172
-
173
-
174
- class TestNeverDeny(unittest.TestCase):
175
- def test_severe_findings_still_allow(self):
176
- res = run_node(
177
- BRIDGE_IMPORT
178
- + """
179
- const runAnalyzer = async (files) => ({
180
- status: "ok",
181
- findings: [
182
- { rule: "biome/critical-sev", file: files[0], line: 1, message: "catastrophic", severity: "error" },
183
- { rule: "biome/blocker", file: files[0], line: 2, message: "deny-shaped", severity: "error" },
184
- ],
185
- });
186
- const bus = createHookBus();
187
- const handler = createBridgeHandler(bus, {runAnalyzer, timeoutMs: 200});
188
- bus.on("pre-tool-use", handler, {tier: "fast", name: "analysis-bridge"});
189
- const direct = await handler({tool: "edit", eventId: "e-sev", file: "src/app.ts"});
190
- const r = await bus.emit("pre-commit", {tool: "edit", eventId: "e-sev", file: "src/app.ts"});
191
- const verdict = typeof direct === "string" ? direct : direct && direct.verdict;
192
- console.log(JSON.stringify({
193
- directAllowed: direct !== false && verdict !== "deny",
194
- verdict, emitAllowed: r.allowed,
195
- }));
196
- """
197
- )
198
- self.assertEqual(res.returncode, 0, f"never-deny test failed: {res.stderr}")
199
- data = last_json_object(res.stdout)
200
- self.assertTrue(data["directAllowed"], "bridge handler must never return deny")
201
- self.assertNotEqual(data["verdict"], "deny")
202
- self.assertNotEqual(data["verdict"], False)
203
- self.assertTrue(
204
- data["emitAllowed"], "severe findings must not block the caller"
205
- )
206
-
207
-
208
- class TestAuditShape(unittest.TestCase):
209
- def test_every_annotation_carries_required_keys(self):
210
- res = run_node(
211
- BRIDGE_IMPORT
212
- + MOCK_TWO_FINDINGS
213
- + """
214
- const direct = await analyzePayload(
215
- {tool: "edit", eventId: "e-shape", file: "src/app.ts"},
216
- {runAnalyzer, timeoutMs: 200},
217
- );
218
- const keys = direct.annotations.map((a) => Object.keys(a).sort());
219
- const bus2 = createHookBus();
220
- await registerAnalysisBridge(null, {bus: bus2, runAnalyzer, notify: () => {}, timeoutMs: 200});
221
- await bus2.emit("pre-tool-use", {tool: "edit", eventId: "e-shape", file: "src/app.ts"});
222
- const records = bus2.getAuditLog().filter((a) => a.event === "notification");
223
- console.log(JSON.stringify({
224
- allowed: direct.allowed, keys,
225
- annotations: direct.annotations,
226
- recordKeys: records.map((a) => Object.keys(a).sort()),
227
- recordTools: records.map((a) => [a.tool, a.eventId]),
228
- }));
229
- """
230
- )
231
- self.assertEqual(res.returncode, 0, f"audit-shape test failed: {res.stderr}")
232
- data = last_json_object(res.stdout)
233
- self.assertTrue(data["allowed"])
234
- required = {"tool", "eventId", "rule", "file", "line", "message", "severity"}
235
- self.assertEqual(len(data["annotations"]), 2)
236
- for key_set in data["keys"]:
237
- self.assertTrue(
238
- required.issubset(set(key_set)),
239
- f"annotation missing keys: {required - set(key_set)}",
240
- )
241
- for ann in data["annotations"]:
242
- self.assertEqual(ann["tool"], "edit")
243
- self.assertEqual(ann["eventId"], "e-shape")
244
- self.assertEqual(len(data["recordKeys"]), 2, "both findings audit-logged")
245
- for key_set in data["recordKeys"]:
246
- self.assertIn("tool", key_set)
247
- self.assertIn("eventId", key_set)
248
- for tool, event_id in data["recordTools"]:
249
- self.assertEqual(tool, "edit")
250
- self.assertEqual(event_id, "e-shape")
251
-
252
-
253
- class TestSlowOverrun(unittest.TestCase):
254
- def test_overrun_degrades_to_timeout_caller_unblocked(self):
255
- res = run_node(
256
- BRIDGE_IMPORT
257
- + """
258
- const runAnalyzer = () => new Promise(() => {});
259
- const t0 = Date.now();
260
- const direct = await analyzePayload(
261
- {tool: "edit", eventId: "e-slow", file: "src/app.ts"},
262
- {runAnalyzer, timeoutMs: 60},
263
- );
264
- const elapsed = Date.now() - t0;
265
- const bus2 = createHookBus();
266
- const handler = createBridgeHandler(bus2, {runAnalyzer, timeoutMs: 60, notify: () => {}});
267
- bus2.on("pre-tool-use", handler, {tier: "fast", name: "analysis-bridge"});
268
- const t1 = Date.now();
269
- const r = await bus2.emit("pre-tool-use", {tool: "edit", eventId: "e-slow2", file: "src/app.ts"}, {fastTimeoutMs: 300});
270
- const emitElapsed = Date.now() - t1;
271
- console.log(JSON.stringify({
272
- allowed: direct.allowed, elapsed,
273
- rules: direct.annotations.map((a) => a.rule),
274
- keys: direct.annotations.length ? Object.keys(direct.annotations[0]).sort() : [],
275
- emitAllowed: r.allowed, emitElapsed,
276
- }));
277
- """
278
- )
279
- self.assertEqual(res.returncode, 0, f"overrun test failed: {res.stderr}")
280
- data = last_json_object(res.stdout)
281
- self.assertTrue(data["allowed"], "overrun must fail open")
282
- self.assertLess(
283
- data["elapsed"], 2000, "analyzer overrun must resolve near the fast budget"
284
- )
285
- self.assertEqual(data["rules"], ["analysis-bridge/timeout"])
286
- self.assertTrue(
287
- {"tool", "eventId", "rule", "file", "line", "message", "severity"}.issubset(
288
- set(data["keys"])
289
- )
290
- )
291
- self.assertTrue(data["emitAllowed"], "bus caller stays unblocked on overrun")
292
- self.assertLess(data["emitElapsed"], 2000)
293
-
294
-
295
- class TestSetupAdoptsBridge(unittest.TestCase):
296
- def test_setup_adopts_and_disposes_bridge(self):
297
- res = run_node(
298
- """
299
- import plugin, { hookBus } from "./plugins/opencode/index.js";
300
- const before = {
301
- pre: hookBus.handlerCount("pre-tool-use"),
302
- post: hookBus.handlerCount("post-tool-use"),
303
- commit: hookBus.handlerCount("pre-commit"),
304
- };
305
- const host = {
306
- options: {},
307
- command: {
308
- list: async () => ({data: []}),
309
- transform: async (fn) => { fn({add: () => {}}); return {dispose: async () => {}}; }
310
- },
311
- tool: {
312
- transform: async (fn) => { fn({add: () => {}}); return {dispose: async () => {}}; }
313
- },
314
- session: { prompt: async () => ({}) }
315
- };
316
- const cleanup = await plugin.setup(host);
317
- const after = {
318
- pre: hookBus.handlerCount("pre-tool-use"),
319
- post: hookBus.handlerCount("post-tool-use"),
320
- commit: hookBus.handlerCount("pre-commit"),
321
- };
322
- const attached = !!host.iumbtemsAnalysisBridge;
323
- await cleanup();
324
- const closed = {
325
- pre: hookBus.handlerCount("pre-tool-use"),
326
- post: hookBus.handlerCount("post-tool-use"),
327
- commit: hookBus.handlerCount("pre-commit"),
328
- };
329
- console.log(JSON.stringify({before, after, attached, closed}));
330
- """
331
- )
332
- self.assertEqual(res.returncode, 0, f"adopt test failed: {res.stderr}")
333
- data = last_json_object(res.stdout)
334
- self.assertTrue(data["attached"], "bridge must be adopted on setup")
335
- self.assertGreater(
336
- data["after"]["pre"],
337
- data["before"]["pre"],
338
- "pre-tool-use bridge handler subscribed",
339
- )
340
- self.assertGreater(
341
- data["after"]["post"],
342
- data["before"]["post"],
343
- "post-tool-use bridge handler subscribed",
344
- )
345
- self.assertGreater(
346
- data["after"]["commit"],
347
- data["before"]["commit"],
348
- "pre-commit bridge handler subscribed",
349
- )
350
- self.assertEqual(
351
- data["closed"], data["before"], "cleanup must dispose bridge subscriptions"
352
- )
353
-
354
-
355
- class TestTargetHardeningAndArgv(unittest.TestCase):
356
- def test_option_like_and_out_of_root_targets_rejected(self):
357
- res = run_node(
358
- BRIDGE_IMPORT
359
- + """
360
- const skipped = [];
361
- const targets = collectTargets({
362
- tool: "edit",
363
- args: {
364
- flag1: "--config-path=/tmp/evil.js",
365
- flag2: "-x.js",
366
- normal: "src/valid.ts",
367
- outside: "/etc/passwd.js",
368
- traversal: "../../outside.ts",
369
- nullbyte: "bad\\0file.ts",
370
- }
371
- }, { root: "/repo", skipped });
372
- console.log(JSON.stringify({ targets, skipped }));
373
- """
374
- )
375
- self.assertEqual(res.returncode, 0, f"collectTargets test failed: {res.stderr}")
376
- data = last_json_object(res.stdout)
377
- self.assertEqual(data["targets"], ["src/valid.ts"])
378
- self.assertIn("/etc/passwd.js", data["skipped"])
379
- self.assertIn("../../outside.ts", data["skipped"])
380
- self.assertNotIn("--config-path=/tmp/evil.js", data["targets"])
381
- self.assertNotIn("-x.js", data["targets"])
382
- self.assertNotIn("--config-path=/tmp/evil.js", data["skipped"])
383
-
384
- def test_out_of_root_yields_skipped_annotation(self):
385
- res = run_node(
386
- BRIDGE_IMPORT
387
- + """
388
- const direct = await analyzePayload(
389
- { tool: "edit", eventId: "e-skip", file: "/etc/passwd.js" },
390
- { root: "/repo", runAnalyzer: async () => ({ status: "ok", findings: [] }) }
391
- );
392
- const bus = createHookBus();
393
- const notices = [];
394
- const notify = (s) => { notices.push(s); };
395
- const reg = await registerAnalysisBridge(null, {
396
- bus,
397
- runAnalyzer: async () => ({ status: "ok", findings: [] }),
398
- notify,
399
- root: "/repo",
400
- });
401
- const r = await bus.emit("pre-tool-use", {
402
- tool: "edit",
403
- eventId: "e-skip",
404
- file: "/etc/passwd.js"
405
- });
406
- const audit = bus.getAuditLog();
407
- const skippedAudit = audit.filter((a) => a.event === "notification" && a.reason && a.reason.includes("skipped"));
408
- console.log(JSON.stringify({
409
- allowed: r.allowed,
410
- notices: notices.length,
411
- directAnnotations: direct.annotations,
412
- skippedAudit: skippedAudit.length,
413
- }));
414
- """
415
- )
416
- self.assertEqual(res.returncode, 0, f"skipped annotation test failed: {res.stderr}")
417
- data = last_json_object(res.stdout)
418
- self.assertTrue(data["allowed"])
419
- self.assertEqual(data["notices"], 0, "skipped target must not trigger finding toast")
420
- self.assertGreaterEqual(len(data["directAnnotations"]), 1)
421
- self.assertEqual(data["directAnnotations"][0]["rule"], "analysis-bridge/skipped-target")
422
- self.assertGreaterEqual(data["skippedAudit"], 1)
423
-
424
- def test_malformed_findings_entries_filtered(self):
425
- res = run_node(
426
- BRIDGE_IMPORT
427
- + """
428
- const runAnalyzer = async () => ({
429
- status: "ok",
430
- findings: [null, 1, "junk", { rule: "rule1", file: "src/app.ts", message: "ok" }]
431
- });
432
- const direct = await analyzePayload(
433
- { tool: "edit", eventId: "e-filter", file: "src/app.ts" },
434
- { runAnalyzer }
435
- );
436
- console.log(JSON.stringify({
437
- allowed: direct.allowed,
438
- annotations: direct.annotations
439
- }));
440
- """
441
- )
442
- self.assertEqual(res.returncode, 0, f"findings filter test failed: {res.stderr}")
443
- data = last_json_object(res.stdout)
444
- self.assertTrue(data["allowed"])
445
- self.assertEqual(len(data["annotations"]), 1)
446
- self.assertEqual(data["annotations"][0]["rule"], "rule1")
447
-
448
-
449
- if __name__ == "__main__":
450
- unittest.main()