@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
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { default } from "./src/server.ts"
package/package.json CHANGED
@@ -1,154 +1,78 @@
1
1
  {
2
2
  "name": "@heretek-ai/epistemic-swarm",
3
- "version": "0.7.25",
4
- "description": "IUMBTEMS (Epistemic Swarm) \u2014 High-Integrity Dialectic Research Agent Harness for Claude Code, OpenCode V2, Pi (pi.dev), OMP (oh-my-pi), Gemini CLI, Codex CLI, and AntiGravity",
5
- "main": "bin/cli.js",
6
- "bin": {
7
- "iumbtems": "bin/cli.js",
8
- "epistemic-swarm": "bin/cli.js"
3
+ "version": "1.0.2",
4
+ "description": "Epistemic Swarm: an AI build factory for OpenCode v2 — grill, research, spec, build, QA and release, gated mechanically.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Heretek-AI/IUMBTEMS.git",
10
+ "directory": "packages/opencode"
9
11
  },
10
12
  "exports": {
11
- ".": "./bin/cli.js",
12
- "./opencode": "./plugins/opencode/index.js",
13
- "./server": "./plugins/opencode/index.js",
14
- "./tui": "./plugins/opencode/tui.js",
15
- "./pi": "./extensions/pi/index.js",
16
- "./omp": "./extensions/pi/index.js"
13
+ ".": {
14
+ "types": "./index.ts",
15
+ "default": "./index.ts"
16
+ },
17
+ "./server": {
18
+ "types": "./server.ts",
19
+ "default": "./server.ts"
20
+ },
21
+ "./tui": {
22
+ "types": "./tui.tsx",
23
+ "default": "./tui.tsx"
24
+ },
25
+ "./rpc": {
26
+ "types": "./rpc.ts",
27
+ "default": "./rpc.ts"
28
+ }
17
29
  },
18
- "publishConfig": {
19
- "access": "public"
30
+ "files": [
31
+ "index.ts",
32
+ "server.ts",
33
+ "tui.tsx",
34
+ "rpc.ts",
35
+ "src"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsc -b",
39
+ "test": "bun test"
20
40
  },
21
41
  "dependencies": {
22
- "solid-js": "1.9.12",
23
- "@opentui/solid": ">=0.4.0 <0.6.0"
42
+ "@heretek-ai/es-core": "1.0.2",
43
+ "@opencode/plugin": "2.0.24"
24
44
  },
25
- "overrides": {
26
- "@babel/core": "^7.29.6"
45
+ "devDependencies": {
46
+ "@heretek-ai/es-testkit": "1.0.0",
47
+ "@opencode/sdk": "2.0.24",
48
+ "@opentui/core": "0.5.14",
49
+ "@opentui/solid": "0.5.14",
50
+ "solid-js": "1.9.15"
27
51
  },
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://github.com/Heretek-AI/IUMBTEMS.git"
52
+ "engines": {
53
+ "node": ">=22"
54
+ },
55
+ "peerDependencies": {
56
+ "@opentui/core": ">=0.5.14",
57
+ "@opentui/solid": ">=0.5.14",
58
+ "solid-js": ">=1.9.0"
31
59
  },
32
- "bugs": {
33
- "url": "https://github.com/Heretek-AI/IUMBTEMS/issues"
60
+ "peerDependenciesMeta": {
61
+ "@opentui/core": {
62
+ "optional": true
63
+ },
64
+ "@opentui/solid": {
65
+ "optional": true
66
+ },
67
+ "solid-js": {
68
+ "optional": true
69
+ }
34
70
  },
35
- "homepage": "https://github.com/Heretek-AI/IUMBTEMS#readme",
36
71
  "keywords": [
37
- "iumbtems",
38
- "epistemic-swarm",
39
- "i-use-my-brain-to-express-my-self",
40
- "pi-package",
41
- "omp-package",
42
72
  "opencode",
43
73
  "opencode-plugin",
44
- "claude-code",
45
- "gemini-cli",
46
- "codex-cli",
47
- "antigravity",
48
- "oh-my-pi",
49
- "omp",
50
- "ai-agents",
51
- "autonomous-agents",
52
- "multi-agent-systems",
53
- "dialectic-swarm",
54
- "dialectic",
55
- "epistemic-integrity",
56
- "research-harness",
57
- "research-agent",
58
- "mcp",
59
- "model-context-protocol",
60
- "mcp-servers",
61
- "deep-research",
62
- "socratic-grilling",
63
- "socratic-questioning",
64
- "brainstorming",
65
- "lateral-thinking",
66
- "fact-checking",
67
- "red-teaming",
68
- "citation-validation",
69
- "hallucination-prevention",
70
- "swarm-intelligence",
71
- "code-audit",
72
- "oss-scout",
73
- "clean-room-engineering",
74
- "proof-carrying-briefs",
75
- "living-dossiers"
76
- ],
77
- "pi": {
78
- "extensions": [
79
- "./extensions/pi/index.js"
80
- ],
81
- "skills": [
82
- "./skills/grilling",
83
- "./skills/research_cache",
84
- "./skills/epistemic_search",
85
- "./skills/swarm_config",
86
- "./skills/code_audit",
87
- "./skills/oss_scout",
88
- "./skills/brainstorming",
89
- "./skills/darkharvest",
90
- "./skills/factory"
91
- ],
92
- "prompts": [
93
- "./prompts/*.md"
94
- ]
95
- },
96
- "omp": {
97
- "extensions": [
98
- "./extensions/pi/index.js"
99
- ],
100
- "skills": [
101
- "./skills/grilling",
102
- "./skills/research_cache",
103
- "./skills/epistemic_search",
104
- "./skills/swarm_config",
105
- "./skills/code_audit",
106
- "./skills/oss_scout",
107
- "./skills/brainstorming",
108
- "./skills/darkharvest",
109
- "./skills/factory"
110
- ],
111
- "prompts": [
112
- "./prompts/*.md"
113
- ],
114
- "commands": [
115
- "./.omp/commands/*.md"
116
- ]
117
- },
118
- "author": "Heretek AI",
119
- "license": "Apache-2.0",
120
- "files": [
121
- "bin",
122
- "prompts",
123
- "skills",
124
- "schemas",
125
- "hooks",
126
- "config",
127
- "runner",
128
- "extensions",
129
- "plugins",
130
- "scripts",
131
- ".agents",
132
- ".omp",
133
- ".claude-plugin",
134
- "install.sh",
135
- "README.md",
136
- "MARKETPLACE.md",
137
- "LICENSE"
138
- ],
139
- "engines": {
140
- "node": ">=18.0.0"
141
- },
142
- "scripts": {
143
- "test": "python3 -m unittest discover -s runner/tests",
144
- "build:adapters": "python3 scripts/build_adapters.py",
145
- "check:adapters": "python3 scripts/build_adapters.py --check",
146
- "validate:claude": "claude plugin validate --strict .claude-plugin/marketplace.json && claude plugin validate --strict .",
147
- "prepack": "python3 scripts/build_adapters.py && python3 -m unittest discover -s runner/tests",
148
- "install-local": "bash install.sh"
149
- },
150
- "devDependencies": {
151
- "@biomejs/biome": "2.5.15",
152
- "esbuild": "0.28.2"
153
- }
74
+ "ai",
75
+ "agents",
76
+ "factory"
77
+ ]
154
78
  }
package/rpc.ts ADDED
@@ -0,0 +1 @@
1
+ export { EsRpc } from "./src/rpc-def.ts"
package/server.ts ADDED
@@ -0,0 +1 @@
1
+ export { default } from "./src/server.ts"
package/src/agents.ts ADDED
@@ -0,0 +1,69 @@
1
+ // Compile the canonical agent registry into OpenCode v2 agents. Additive only:
2
+ // we add our own agents and never edit built-ins, default_agent or models.
3
+ // Per-agent tool/skill/MCP scoping is expressed as wildcard-deny permission
4
+ // rules (proven in M0: denied tools, MCP tools and skills are not advertised).
5
+ import { AGENTS, type AgentSpec, ALL_ES_TOOLS, loadPrompt } from "@heretek-ai/es-core"
6
+ import type { PluginOptions } from "./runtime.ts"
7
+
8
+ export interface CompiledAgent {
9
+ readonly spec: AgentSpec
10
+ readonly system: string
11
+ readonly permissions: Array<{ action: string; resource: string; effect: "allow" | "deny" | "ask" }>
12
+ readonly model?: { providerID: string; id: string }
13
+ }
14
+
15
+ export function permissionRules(spec: AgentSpec, mcpServers: readonly string[]): CompiledAgent["permissions"] {
16
+ const rules: CompiledAgent["permissions"] = [
17
+ { action: "es_*", resource: "*", effect: "deny" },
18
+ ...spec.tools.map((tool) => ({ action: tool, resource: "*", effect: "allow" as const })),
19
+ { action: "subagent", resource: "*", effect: "deny" },
20
+ ...spec.spawns.map((agent) => ({ action: "subagent", resource: agent, effect: "allow" as const })),
21
+ { action: "skill", resource: "*", effect: "deny" },
22
+ ...spec.skills.map((skill) => ({ action: "skill", resource: skill, effect: "allow" as const })),
23
+ ]
24
+ for (const server of mcpServers)
25
+ if (!spec.mcp.includes(server))
26
+ rules.push({ action: `${server.replace(/[^\w-]/g, "_")}_*`, resource: "*", effect: "deny" })
27
+ if (spec.mode === "subagent") {
28
+ // Autonomous seats never wait on a human: no questions, no paths outside the project except /tmp.
29
+ rules.push({ action: "question", resource: "*", effect: "deny" })
30
+ rules.push({ action: "external_directory", resource: "*", effect: "deny" })
31
+ // Sonar S5443 flags the /tmp literal; it governs creating temp files, while
32
+ // this only grants autonomous seats access to a scratch directory.
33
+ rules.push({ action: "external_directory", resource: "/tmp/*", effect: "allow" }) // NOSONAR
34
+ }
35
+ if (spec.writes.length === 0) rules.push({ action: "edit", resource: "*", effect: "deny" })
36
+ if (spec.lsp === "none") rules.push({ action: "lsp", resource: "*", effect: "deny" })
37
+ if (spec.lsp !== "full") rules.push({ action: "lsp_rename", resource: "*", effect: "deny" })
38
+ return rules
39
+ }
40
+
41
+ function modelFor(spec: AgentSpec, options: PluginOptions) {
42
+ const ref = options.models?.agents?.[spec.id] ?? options.models?.[spec.tier]
43
+ const slash = ref?.indexOf("/") ?? -1
44
+ if (!ref || slash <= 0) return undefined
45
+ return { providerID: ref.slice(0, slash), id: ref.slice(slash + 1) }
46
+ }
47
+
48
+ export async function compileAgents(options: PluginOptions, mcpServers: readonly string[]): Promise<CompiledAgent[]> {
49
+ return Promise.all(
50
+ AGENTS.map(async (spec) => {
51
+ const prompt = await loadPrompt(spec.prompt)
52
+ const model = modelFor(spec, options)
53
+ return {
54
+ spec,
55
+ system: `${prompt.body}\n\n<!-- epistemic-swarm prompt ${prompt.meta.id} v${prompt.meta.version} -->`,
56
+ permissions: permissionRules(spec, mcpServers),
57
+ ...(model ? { model } : {}),
58
+ }
59
+ }),
60
+ )
61
+ }
62
+
63
+ /** es_* tools an agent may see. Agents outside the registry get only the read-only ones. */
64
+ export function visibleEsTools(agentId: string | undefined): readonly string[] {
65
+ const spec = AGENTS.find((agent) => agent.id === agentId)
66
+ return spec ? spec.tools : ["es_status", "es_gates_run"]
67
+ }
68
+
69
+ export { ALL_ES_TOOLS }
@@ -0,0 +1,40 @@
1
+ // Factory continuation: when the factory's own session finishes a turn while
2
+ // work remains (not halted, not waiting on a human approval or the grill), we
3
+ // re-prompt it to continue. Progress-aware: three idle turns without any state
4
+ // change stop the loop so a confused agent cannot spin on budget.
5
+ import { factorySummary, pendingApprovals } from "@heretek-ai/es-core"
6
+ import type { Runtime } from "./runtime.ts"
7
+
8
+ const ACTIVE = new Set(["RESEARCH", "SPEC", "BUILD", "QA", "RELEASE"])
9
+ const STALL_LIMIT = 3
10
+
11
+ export function createFactoryContinuation(
12
+ ctx: { session: { prompt(input: any): Promise<unknown> } },
13
+ runtime: Runtime,
14
+ ) {
15
+ const stalls = new Map<string, { print: string; count: number }>()
16
+ return async (
17
+ event: { type: string; data?: { sessionID?: string } },
18
+ agentOf: (sessionID: string) => Promise<string | undefined>,
19
+ ) => {
20
+ const sessionID = event.data?.sessionID
21
+ if (event.type !== "session.execution.succeeded" || !sessionID) return
22
+ if ((await agentOf(sessionID)) !== "factory") return
23
+ const state = await runtime.factory.read()
24
+ if (!state || !ACTIVE.has(state.stage)) return
25
+ if ((await pendingApprovals(runtime.root)).length) return
26
+ const print = JSON.stringify([
27
+ state.stage,
28
+ state.activePhase,
29
+ state.phases.map((phase) => [phase.status, phase.failures, phase.history.length]),
30
+ ])
31
+ const previous = stalls.get(sessionID)
32
+ const count = previous?.print === print ? previous.count + 1 : 0
33
+ stalls.set(sessionID, { print, count })
34
+ if (count >= STALL_LIMIT) return
35
+ await ctx.session.prompt({
36
+ sessionID,
37
+ text: `${factorySummary(state)}\nThe factory run is not finished. Continue from the current stage (no human is needed unless an approval is due).`,
38
+ })
39
+ }
40
+ }
package/src/hooks.ts ADDED
@@ -0,0 +1,283 @@
1
+ // Hook bridge: Claude Code hooks (from .opencode/hooks.json and
2
+ // .claude/settings*.json) running inside OpenCode v2.
3
+ //
4
+ // PreToolUse ← tool.execute.before (deny blocks; updatedInput rewrites;
5
+ // "ask" defers to the host permission prompt)
6
+ // PostToolUse(Failure)← tool.execute.after (feedback/context appended, output replaced)
7
+ // UserPromptSubmit ← session prompt admission (block rejects, context appended)
8
+ // SessionStart ← first prompt of a session (startup) and after compaction
9
+ // PermissionRequest ← permission.evaluate when the host would ask
10
+ // x-es.ShellPreExec ← shell.create.before
11
+ // Stop (emulated) ← session.execution.succeeded: a block re-prompts the
12
+ // session (8-continuation cap). ADVISORY for plain chat:
13
+ // the host has already ended the turn when we re-prompt.
14
+ import {
15
+ bwrapAvailable,
16
+ fromOpenCode,
17
+ HookEngine,
18
+ permissionActionTool,
19
+ shellQuote,
20
+ toOpenCodeInput,
21
+ } from "@heretek-ai/es-core"
22
+ import { Error as ToolError } from "@opencode/plugin/promise/tool"
23
+ import type { Runtime } from "./runtime.ts"
24
+
25
+ const PERMISSION_CHECKED = new Set([
26
+ "read",
27
+ "write",
28
+ "edit",
29
+ "patch",
30
+ "shell",
31
+ "glob",
32
+ "grep",
33
+ "webfetch",
34
+ "websearch",
35
+ "skill",
36
+ "subagent",
37
+ "question",
38
+ ])
39
+ const STOP_CAP = 8
40
+
41
+ type Ctx = {
42
+ readonly generate: { text(input: any): Promise<{ text: string }> }
43
+ readonly session: {
44
+ prompt(input: any): Promise<unknown>
45
+ context(input: any): Promise<readonly any[]>
46
+ interrupt(input: any): Promise<unknown>
47
+ }
48
+ }
49
+
50
+ export interface HookBridge {
51
+ readonly engine: HookEngine
52
+ before(event: { tool: string; agent: string; id: string; sessionID: string; input: unknown }): Promise<void>
53
+ after(event: {
54
+ tool: string
55
+ agent: string
56
+ id: string
57
+ sessionID: string
58
+ input: unknown
59
+ status: string
60
+ result?: any
61
+ error?: any
62
+ }): Promise<void>
63
+ prompt(event: { sessionID: string; prompt: { text: string } }, agent?: string): Promise<void>
64
+ context(event: { sessionID: string; agent: string; system: any[] }): Promise<void>
65
+ evaluate(event: {
66
+ sessionID: string
67
+ agent?: string
68
+ action: string
69
+ resources: readonly string[]
70
+ effect: string
71
+ message?: string
72
+ source?: { id: string }
73
+ }): Promise<void>
74
+ shell(event: { command: string; cwd: string }): Promise<void>
75
+ onEvent(
76
+ event: { type: string; data?: any },
77
+ agentOf: (sessionID: string) => Promise<string | undefined>,
78
+ ): Promise<void>
79
+ }
80
+
81
+ function lastAssistantText(context: readonly any[]): string {
82
+ for (let i = context.length - 1; i >= 0; i--) {
83
+ const message = context[i]
84
+ if (message?.type !== "assistant") continue
85
+ const text = (message.content ?? [])
86
+ .filter((part: any) => part?.type === "text")
87
+ .map((part: any) => part.text ?? "")
88
+ .join("")
89
+ if (text) return text
90
+ }
91
+ return ""
92
+ }
93
+
94
+ export async function createHookBridge(
95
+ ctx: Ctx,
96
+ runtime: Runtime,
97
+ mcpServers: () => readonly string[],
98
+ ): Promise<HookBridge> {
99
+ const engine = await HookEngine.create({
100
+ root: runtime.root,
101
+ stateDir: runtime.stateDir,
102
+ generate: async (prompt, model) => {
103
+ const slash = model?.indexOf("/") ?? -1
104
+ const ref = model && slash > 0 ? { providerID: model.slice(0, slash), id: model.slice(slash + 1) } : undefined
105
+ return (await ctx.generate.text({ prompt, ...(ref ? { model: ref } : {}) })).text
106
+ },
107
+ })
108
+ const pendingContext = new Map<string, string[]>()
109
+ const pendingAsk = new Map<string, string>()
110
+ const sessionContext = new Map<string, string[]>()
111
+ const startedSessions = new Set<string>()
112
+ const continuations = new Map<string, number>()
113
+ const base = (sessionId: string, agent?: string) => ({ sessionId, ...(agent ? { agent } : {}) })
114
+
115
+ const stash = (map: Map<string, string[]>, key: string, texts: readonly string[]) => {
116
+ if (texts.length) map.set(key, [...(map.get(key) ?? []), ...texts])
117
+ }
118
+
119
+ return {
120
+ engine,
121
+
122
+ async before(event) {
123
+ await engine.refresh()
124
+ if (!engine.has("PreToolUse")) return
125
+ const tool = fromOpenCode(event.tool, event.input, runtime.root, mcpServers())
126
+ const decision = await engine.preToolUse(base(event.sessionID, event.agent), tool, event.id)
127
+ if (decision.stop) {
128
+ await ctx.session.interrupt({ sessionID: event.sessionID }).catch(() => undefined)
129
+ throw new ToolError({ message: `Stopped by a hook: ${decision.stop}` })
130
+ }
131
+ if (decision.decision === "deny") throw new ToolError({ message: decision.reason ?? "Denied by a hook" })
132
+ if (decision.decision === "defer")
133
+ throw new ToolError({ message: `Deferred by a hook${decision.reason ? `: ${decision.reason}` : ""}` })
134
+ if (decision.decision === "ask") {
135
+ const builtIn =
136
+ PERMISSION_CHECKED.has(event.tool) ||
137
+ mcpServers().some((server) => event.tool.startsWith(`${server.replace(/[^\w-]/g, "_")}_`))
138
+ if (!builtIn)
139
+ throw new ToolError({
140
+ message: `A hook asked for approval, but ${event.tool} has no permission prompt to ask with; denied.`,
141
+ })
142
+ pendingAsk.set(event.id, decision.reason ?? "A hook asked to confirm this call")
143
+ }
144
+ if (decision.updatedInput)
145
+ event.input = toOpenCodeInput(event.tool, decision.updatedInput, runtime.root, event.input)
146
+ stash(pendingContext, event.id, [
147
+ ...decision.additionalContext,
148
+ ...decision.systemMessages.map((text) => `Hook message: ${text}`),
149
+ ])
150
+ },
151
+
152
+ async after(event) {
153
+ continuations.delete(event.sessionID)
154
+ pendingAsk.delete(event.id)
155
+ const earlier = pendingContext.get(event.id) ?? []
156
+ pendingContext.delete(event.id)
157
+ const failed = event.status !== "completed"
158
+ const texts = [...earlier]
159
+ let replacement: unknown
160
+ if (engine.has(failed ? "PostToolUseFailure" : "PostToolUse")) {
161
+ const tool = fromOpenCode(event.tool, event.input, runtime.root, mcpServers())
162
+ const response = failed
163
+ ? (event.error?.message ?? "tool failed")
164
+ : (event.result?.output ?? event.result?.content)
165
+ const post = await engine.postToolUse(base(event.sessionID, event.agent), tool, event.id, response, failed)
166
+ texts.push(
167
+ ...post.feedback,
168
+ ...post.additionalContext,
169
+ ...post.systemMessages.map((text) => `Hook message: ${text}`),
170
+ )
171
+ replacement = post.updatedToolOutput
172
+ if (post.stop) await ctx.session.interrupt({ sessionID: event.sessionID }).catch(() => undefined)
173
+ }
174
+ if (failed || (!texts.length && replacement === undefined)) return
175
+ const original =
176
+ replacement === undefined
177
+ ? event.result?.content
178
+ : typeof replacement === "string"
179
+ ? replacement
180
+ : JSON.stringify(replacement)
181
+ const block = texts.length ? `<hook-feedback>\n${texts.join("\n")}\n</hook-feedback>` : ""
182
+ const content =
183
+ typeof original === "string" || original === undefined
184
+ ? [original ?? "", block].filter(Boolean).join("\n\n")
185
+ : [...original, ...(block ? [{ type: "text", text: block }] : [])]
186
+ event.result = { ...event.result, content }
187
+ },
188
+
189
+ async prompt(event, agent) {
190
+ await engine.refresh()
191
+ if (!startedSessions.has(event.sessionID)) {
192
+ startedSessions.add(event.sessionID)
193
+ if (engine.has("SessionStart"))
194
+ stash(
195
+ sessionContext,
196
+ event.sessionID,
197
+ (await engine.sessionStart(base(event.sessionID, agent), "startup")).additionalContext,
198
+ )
199
+ }
200
+ if (!engine.has("UserPromptSubmit")) return
201
+ const decision = await engine.userPromptSubmit(base(event.sessionID, agent), event.prompt.text)
202
+ if (decision.block) throw new Error(`Prompt blocked by a hook: ${decision.block}`)
203
+ const context = [...decision.additionalContext, ...decision.systemMessages.map((text) => `Hook message: ${text}`)]
204
+ if (context.length)
205
+ event.prompt.text = `${event.prompt.text}\n\n<system-reminder>\n${context.join("\n")}\n</system-reminder>`
206
+ },
207
+
208
+ context(event) {
209
+ const texts = sessionContext.get(event.sessionID)
210
+ if (texts?.length)
211
+ event.system.push({ type: "text", text: `<session-start-hooks>\n${texts.join("\n")}\n</session-start-hooks>` })
212
+ return Promise.resolve()
213
+ },
214
+
215
+ async evaluate(event) {
216
+ const asked = event.source ? pendingAsk.get(event.source.id) : undefined
217
+ if (event.effect === "deny") return
218
+ if (asked) {
219
+ event.effect = "ask"
220
+ event.message = asked
221
+ }
222
+ if (event.effect !== "ask" || !engine.has("PermissionRequest")) return
223
+ const tool = {
224
+ name: permissionActionTool(event.action),
225
+ aliases: [permissionActionTool(event.action), event.action],
226
+ input: { resources: [...event.resources] },
227
+ }
228
+ const decision = await engine.permissionRequest(base(event.sessionID, event.agent), tool)
229
+ if (decision.behavior === "deny") {
230
+ event.effect = "deny"
231
+ event.message = decision.message ?? "Denied by a hook"
232
+ } else if (decision.behavior === "allow" && !asked) event.effect = "allow"
233
+ },
234
+
235
+ async shell(event) {
236
+ if (!engine.has("x-es.ShellPreExec")) return
237
+ const decision = await engine.shellPreExec(base(""), { command: event.command, cwd: event.cwd })
238
+ if (decision.deny)
239
+ event.command = `printf '%s\\n' ${shellQuote(`Blocked by a hook: ${decision.deny}`)} >&2; exit 126`
240
+ else if (decision.command) event.command = decision.command
241
+ },
242
+
243
+ async onEvent(event, agentOf) {
244
+ const sessionID = event.data?.sessionID
245
+ if (!sessionID) return
246
+ if (event.type === "session.compaction.ended" && engine.has("SessionStart")) {
247
+ const agent = await agentOf(sessionID)
248
+ stash(
249
+ sessionContext,
250
+ sessionID,
251
+ (await engine.sessionStart(base(sessionID, agent), "compact")).additionalContext,
252
+ )
253
+ return
254
+ }
255
+ if (event.type !== "session.execution.succeeded" || !engine.has("Stop")) return
256
+ const count = continuations.get(sessionID) ?? 0
257
+ if (count >= STOP_CAP) {
258
+ continuations.delete(sessionID)
259
+ return
260
+ }
261
+ const agent = await agentOf(sessionID)
262
+ const context = await ctx.session.context({ sessionID }).catch(() => [] as any[])
263
+ const decision = await engine.stop(base(sessionID, agent), {
264
+ stopHookActive: count > 0,
265
+ lastAssistantMessage: lastAssistantText(context),
266
+ })
267
+ const feedback = [decision.block, ...decision.additionalContext].filter(Boolean)
268
+ if (!feedback.length) {
269
+ continuations.delete(sessionID)
270
+ return
271
+ }
272
+ continuations.set(sessionID, count + 1)
273
+ await ctx.session
274
+ .prompt({
275
+ sessionID,
276
+ text: `<system-reminder>\nStop hook feedback (continuing):\n${feedback.join("\n")}\n</system-reminder>`,
277
+ })
278
+ .catch(() => undefined)
279
+ },
280
+ }
281
+ }
282
+
283
+ export { bwrapAvailable }