@heretek-ai/epistemic-swarm 0.7.25 → 1.0.3

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 (351) hide show
  1. package/dist/tui.js +793 -0
  2. package/index.ts +1 -0
  3. package/package.json +68 -139
  4. package/rpc.ts +1 -0
  5. package/server.ts +1 -0
  6. package/src/agents.ts +69 -0
  7. package/src/continue.ts +40 -0
  8. package/src/hooks.ts +283 -0
  9. package/src/panels.tsx +220 -0
  10. package/src/policy.ts +221 -0
  11. package/src/pr.ts +37 -0
  12. package/src/research.ts +63 -0
  13. package/src/rpc-def.ts +136 -0
  14. package/src/rpc.ts +331 -0
  15. package/src/runtime.ts +112 -0
  16. package/src/server.ts +311 -0
  17. package/src/session.ts +61 -0
  18. package/src/tools.ts +61 -0
  19. package/src/tui.tsx +206 -0
  20. package/tui.tsx +1 -0
  21. package/.agents/skills/brainstorming/SKILL.md +0 -19
  22. package/.agents/skills/code_audit/SKILL.md +0 -19
  23. package/.agents/skills/darkharvest/SKILL.md +0 -19
  24. package/.agents/skills/epistemic_search/SKILL.md +0 -19
  25. package/.agents/skills/factory/SKILL.md +0 -19
  26. package/.agents/skills/grilling/SKILL.md +0 -19
  27. package/.agents/skills/oss_scout/SKILL.md +0 -19
  28. package/.agents/skills/research_cache/SKILL.md +0 -19
  29. package/.agents/skills/swarm_config/SKILL.md +0 -19
  30. package/.claude-plugin/marketplace.json +0 -61
  31. package/.claude-plugin/plugin.json +0 -76
  32. package/.omp/README.md +0 -39
  33. package/.omp/SYSTEM.md +0 -17
  34. package/.omp/commands/audit.md +0 -10
  35. package/.omp/commands/brainstorming.md +0 -12
  36. package/.omp/commands/darkharvest.md +0 -11
  37. package/.omp/commands/domainexpansion.md +0 -9
  38. package/.omp/commands/factory.md +0 -9
  39. package/.omp/commands/grill.md +0 -9
  40. package/.omp/commands/scout.md +0 -10
  41. package/.omp/commands/swarm-config.md +0 -10
  42. package/.omp/commands/swarm.md +0 -9
  43. package/.omp/hooks/post/epistemic-audit.ts +0 -16
  44. package/.omp/hooks/pre/epistemic-redirect.ts +0 -21
  45. package/.omp/prompts/brainstorming.md +0 -8
  46. package/.omp/prompts/swarm.md +0 -8
  47. package/LICENSE +0 -126
  48. package/MARKETPLACE.md +0 -130
  49. package/README.md +0 -403
  50. package/bin/cli.js +0 -297
  51. package/config/claude-settings-patch.json +0 -10
  52. package/config/docker-compose.infra.yml +0 -23
  53. package/config/domain_packs/biopharma.json +0 -23
  54. package/config/domain_packs/legal.json +0 -19
  55. package/config/domain_packs/quant.json +0 -19
  56. package/config/mcp-research-servers.json +0 -33
  57. package/config/mcp_launcher.py +0 -153
  58. package/config/opencode-snippet.json +0 -156
  59. package/config/searxng_mcp.py +0 -92
  60. package/extensions/pi/index.js +0 -357
  61. package/hooks/hooks.json +0 -45
  62. package/install.sh +0 -473
  63. package/plugins/antigravity/README.md +0 -72
  64. package/plugins/antigravity/agents/alpha-thesis.md +0 -36
  65. package/plugins/antigravity/agents/beta-antithesis.md +0 -35
  66. package/plugins/antigravity/agents/brainstormer.md +0 -27
  67. package/plugins/antigravity/agents/code-auditor.md +0 -28
  68. package/plugins/antigravity/agents/darkharvester.md +0 -30
  69. package/plugins/antigravity/agents/epistemic-auditor.md +0 -28
  70. package/plugins/antigravity/agents/manager.md +0 -26
  71. package/plugins/antigravity/agents/oss-scout.md +0 -27
  72. package/plugins/antigravity/agents/programmer.md +0 -25
  73. package/plugins/antigravity/agents/qa-a.md +0 -22
  74. package/plugins/antigravity/agents/qa-b.md +0 -22
  75. package/plugins/antigravity/antigravity_hooks.py +0 -265
  76. package/plugins/antigravity/commands/audit.md +0 -11
  77. package/plugins/antigravity/commands/brainstorm.md +0 -9
  78. package/plugins/antigravity/commands/brainstorming.md +0 -10
  79. package/plugins/antigravity/commands/darkharvest.md +0 -12
  80. package/plugins/antigravity/commands/domainexpansion.md +0 -12
  81. package/plugins/antigravity/commands/factory.md +0 -14
  82. package/plugins/antigravity/commands/grill.md +0 -10
  83. package/plugins/antigravity/commands/scout.md +0 -11
  84. package/plugins/antigravity/commands/swarm-config.md +0 -9
  85. package/plugins/antigravity/commands/swarm.md +0 -12
  86. package/plugins/antigravity/hook_bus_bridge.js +0 -352
  87. package/plugins/antigravity/hooks.json +0 -44
  88. package/plugins/antigravity/mcp_config.json +0 -33
  89. package/plugins/antigravity/mcp_launcher.py +0 -58
  90. package/plugins/antigravity/plugin.json +0 -13
  91. package/plugins/antigravity/rules/AGENTS.md +0 -127
  92. package/plugins/antigravity/rules/epistemic-integrity.md +0 -16
  93. package/plugins/antigravity/skills/brainstorming/SKILL.md +0 -19
  94. package/plugins/antigravity/skills/code_audit/SKILL.md +0 -19
  95. package/plugins/antigravity/skills/darkharvest/SKILL.md +0 -19
  96. package/plugins/antigravity/skills/epistemic_search/SKILL.md +0 -19
  97. package/plugins/antigravity/skills/factory/SKILL.md +0 -19
  98. package/plugins/antigravity/skills/grilling/SKILL.md +0 -19
  99. package/plugins/antigravity/skills/oss_scout/SKILL.md +0 -19
  100. package/plugins/antigravity/skills/research_cache/SKILL.md +0 -19
  101. package/plugins/antigravity/skills/swarm_config/SKILL.md +0 -19
  102. package/plugins/codex/AGENTS.md.snippet +0 -10
  103. package/plugins/codex/README.md +0 -37
  104. package/plugins/codex/config.toml.snippet +0 -28
  105. package/plugins/codex/openai.yaml +0 -24
  106. package/plugins/codex/skills/brainstorming/SKILL.md +0 -19
  107. package/plugins/codex/skills/code_audit/SKILL.md +0 -19
  108. package/plugins/codex/skills/darkharvest/SKILL.md +0 -19
  109. package/plugins/codex/skills/epistemic_search/SKILL.md +0 -19
  110. package/plugins/codex/skills/factory/SKILL.md +0 -19
  111. package/plugins/codex/skills/grilling/SKILL.md +0 -19
  112. package/plugins/codex/skills/oss_scout/SKILL.md +0 -19
  113. package/plugins/codex/skills/research_cache/SKILL.md +0 -19
  114. package/plugins/codex/skills/swarm_config/SKILL.md +0 -19
  115. package/plugins/darkharvest/.claude-plugin/plugin.json +0 -15
  116. package/plugins/darkharvest/agents/harvest-proponent.md +0 -22
  117. package/plugins/darkharvest/agents/harvest-redteam.md +0 -20
  118. package/plugins/darkharvest/evals/teardown-verdict/graders/license-line.md +0 -6
  119. package/plugins/darkharvest/evals/teardown-verdict/graders/skill-fired.md +0 -5
  120. package/plugins/darkharvest/evals/teardown-verdict/prompt.md +0 -6
  121. package/plugins/darkharvest/skills/darkharvest/SKILL.md +0 -70
  122. package/plugins/darkharvest/skills/darkharvest/scripts/harvest.py +0 -289
  123. package/plugins/factory/.claude-plugin/plugin.json +0 -15
  124. package/plugins/factory/agents/factory-manager.md +0 -22
  125. package/plugins/factory/agents/programmer.md +0 -16
  126. package/plugins/factory/agents/qa-adversarial.md +0 -17
  127. package/plugins/factory/agents/qa-functional.md +0 -17
  128. package/plugins/factory/evals/gate-halt/graders/gates-first.md +0 -6
  129. package/plugins/factory/evals/gate-halt/graders/skill-fired.md +0 -5
  130. package/plugins/factory/evals/gate-halt/prompt.md +0 -6
  131. package/plugins/factory/skills/factory/SKILL.md +0 -61
  132. package/plugins/factory/skills/factory/scripts/factory.py +0 -300
  133. package/plugins/gemini/GEMINI.md +0 -16
  134. package/plugins/gemini/README.md +0 -20
  135. package/plugins/gemini/commands/audit.toml +0 -6
  136. package/plugins/gemini/commands/brainstorming.toml +0 -10
  137. package/plugins/gemini/commands/darkharvest.toml +0 -8
  138. package/plugins/gemini/commands/domainexpansion.toml +0 -7
  139. package/plugins/gemini/commands/factory.toml +0 -8
  140. package/plugins/gemini/commands/grill.toml +0 -6
  141. package/plugins/gemini/commands/scout.toml +0 -7
  142. package/plugins/gemini/commands/swarm-config.toml +0 -7
  143. package/plugins/gemini/commands/swarm.toml +0 -8
  144. package/plugins/gemini/gemini-extension.json +0 -38
  145. package/plugins/gemini/hooks/hooks.json +0 -11
  146. package/plugins/gemini/skills/brainstorming/SKILL.md +0 -19
  147. package/plugins/gemini/skills/code_audit/SKILL.md +0 -19
  148. package/plugins/gemini/skills/darkharvest/SKILL.md +0 -19
  149. package/plugins/gemini/skills/epistemic_search/SKILL.md +0 -19
  150. package/plugins/gemini/skills/factory/SKILL.md +0 -19
  151. package/plugins/gemini/skills/grilling/SKILL.md +0 -19
  152. package/plugins/gemini/skills/oss_scout/SKILL.md +0 -19
  153. package/plugins/gemini/skills/research_cache/SKILL.md +0 -19
  154. package/plugins/gemini/skills/swarm_config/SKILL.md +0 -19
  155. package/plugins/opencode/analysis-bridge.js +0 -620
  156. package/plugins/opencode/config-io.js +0 -1651
  157. package/plugins/opencode/dep-health.js +0 -1039
  158. package/plugins/opencode/hook-bus.js +0 -496
  159. package/plugins/opencode/index.js +0 -2992
  160. package/plugins/opencode/tui.js +0 -1551
  161. package/plugins/opencode/weight-baseline.json +0 -16
  162. package/plugins/opencode/weight-signals.js +0 -769
  163. package/plugins/research-cache/.claude-plugin/plugin.json +0 -15
  164. package/plugins/research-cache/skills/research_cache/SKILL.md +0 -36
  165. package/plugins/research-cache/skills/research_cache/__init__.py +0 -0
  166. package/plugins/research-cache/skills/research_cache/hasher.py +0 -302
  167. package/plugins/socratic-grilling/.claude-plugin/plugin.json +0 -15
  168. package/plugins/socratic-grilling/skills/grilling/SKILL.md +0 -61
  169. package/plugins/socratic-grilling/skills/grilling/__init__.py +0 -0
  170. package/plugins/socratic-grilling/skills/grilling/socratic_tree.py +0 -363
  171. package/prompts/agent_alpha_thesis.md +0 -70
  172. package/prompts/agent_beta_antithesis.md +0 -78
  173. package/prompts/agent_brainstormer.md +0 -143
  174. package/prompts/agent_code_auditor.md +0 -88
  175. package/prompts/agent_darkharvest.md +0 -140
  176. package/prompts/agent_oss_scout.md +0 -78
  177. package/prompts/antigravity_repo_factcheck.md +0 -143
  178. package/prompts/base_epistemic_system.md +0 -50
  179. package/prompts/epistemic_auditor.md +0 -74
  180. package/prompts/orchestrator.md +0 -70
  181. package/runner/__init__.py +0 -0
  182. package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
  183. package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
  184. package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
  185. package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
  186. package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
  187. package/runner/__pycache__/darkharvest_claims.cpython-311.pyc +0 -0
  188. package/runner/__pycache__/errors.cpython-311.pyc +0 -0
  189. package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
  190. package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
  191. package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
  192. package/runner/__pycache__/path_safety.cpython-311.pyc +0 -0
  193. package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
  194. package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
  195. package/runner/__pycache__/preflight.cpython-311.pyc +0 -0
  196. package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
  197. package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
  198. package/runner/__pycache__/retrieval_log.cpython-311.pyc +0 -0
  199. package/runner/__pycache__/schema_validate.cpython-311.pyc +0 -0
  200. package/runner/__pycache__/schemas.cpython-311.pyc +0 -0
  201. package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
  202. package/runner/antigravity_hooks.py +0 -265
  203. package/runner/auctioneer.py +0 -169
  204. package/runner/auditor_engine.py +0 -711
  205. package/runner/claim_store.py +0 -417
  206. package/runner/claim_witness.py +0 -412
  207. package/runner/darkharvest_claims.py +0 -358
  208. package/runner/errors.py +0 -51
  209. package/runner/living_dossiers.py +0 -395
  210. package/runner/mcp_protocol.py +0 -188
  211. package/runner/mcp_server.py +0 -1447
  212. package/runner/path_safety.py +0 -62
  213. package/runner/pcrb.py +0 -290
  214. package/runner/pcrb_verify.py +0 -267
  215. package/runner/preflight.py +0 -1011
  216. package/runner/refinement.py +0 -580
  217. package/runner/research_swarm.py +0 -1848
  218. package/runner/retrieval_log.py +0 -90
  219. package/runner/schema_validate.py +0 -193
  220. package/runner/schemas.py +0 -630
  221. package/runner/state_machine.py +0 -463
  222. package/runner/tests/__pycache__/test_analysis_bridge.cpython-311.pyc +0 -0
  223. package/runner/tests/__pycache__/test_antigravity_plugin.cpython-311.pyc +0 -0
  224. package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
  225. package/runner/tests/__pycache__/test_backends.cpython-311.pyc +0 -0
  226. package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
  227. package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
  228. package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
  229. package/runner/tests/__pycache__/test_claude_plugin.cpython-311.pyc +0 -0
  230. package/runner/tests/__pycache__/test_config_schema.cpython-311.pyc +0 -0
  231. package/runner/tests/__pycache__/test_contract_tooling.cpython-311.pyc +0 -0
  232. package/runner/tests/__pycache__/test_darkharvest_audit.cpython-311.pyc +0 -0
  233. package/runner/tests/__pycache__/test_dep_health.cpython-311.pyc +0 -0
  234. package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
  235. package/runner/tests/__pycache__/test_dossier_contract.cpython-311.pyc +0 -0
  236. package/runner/tests/__pycache__/test_factory.cpython-311.pyc +0 -0
  237. package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
  238. package/runner/tests/__pycache__/test_frontier_concurrency.cpython-311.pyc +0 -0
  239. package/runner/tests/__pycache__/test_frontier_mirror_standalone.cpython-311.pyc +0 -0
  240. package/runner/tests/__pycache__/test_grounding.cpython-311.pyc +0 -0
  241. package/runner/tests/__pycache__/test_hardening_contract.cpython-311.pyc +0 -0
  242. package/runner/tests/__pycache__/test_hook_bus.cpython-311.pyc +0 -0
  243. package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
  244. package/runner/tests/__pycache__/test_manifest_concurrency.cpython-311.pyc +0 -0
  245. package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
  246. package/runner/tests/__pycache__/test_nk_hardening.cpython-311.pyc +0 -0
  247. package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
  248. package/runner/tests/__pycache__/test_opencode_v2_registrars.cpython-311.pyc +0 -0
  249. package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
  250. package/runner/tests/__pycache__/test_phase08_waiver_reopens.cpython-311.pyc +0 -0
  251. package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
  252. package/runner/tests/__pycache__/test_search_anomaly.cpython-311.pyc +0 -0
  253. package/runner/tests/__pycache__/test_search_provider.cpython-311.pyc +0 -0
  254. package/runner/tests/__pycache__/test_search_provider_plugin.cpython-311.pyc +0 -0
  255. package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
  256. package/runner/tests/__pycache__/test_swarm_config.cpython-311.pyc +0 -0
  257. package/runner/tests/__pycache__/test_sweep_regressions.cpython-311.pyc +0 -0
  258. package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
  259. package/runner/tests/__pycache__/test_weight_signals.cpython-311.pyc +0 -0
  260. package/runner/tests/fixtures/auction_objective.json +0 -35
  261. package/runner/tests/fixtures/borderline_claims.json +0 -27
  262. package/runner/tests/fixtures/config_validation_cases.json +0 -276
  263. package/runner/tests/fixtures/ddg_anomaly_page.html +0 -176
  264. package/runner/tests/fixtures/ddg_results_page.html +0 -28
  265. package/runner/tests/fixtures/divergence_objectives.json +0 -31
  266. package/runner/tests/test_analysis_bridge.py +0 -450
  267. package/runner/tests/test_antigravity_plugin.py +0 -361
  268. package/runner/tests/test_auction_order.py +0 -173
  269. package/runner/tests/test_backends.py +0 -457
  270. package/runner/tests/test_bet1_spike.py +0 -95
  271. package/runner/tests/test_claim_store.py +0 -162
  272. package/runner/tests/test_claim_witness.py +0 -186
  273. package/runner/tests/test_claude_plugin.py +0 -170
  274. package/runner/tests/test_config_schema.py +0 -879
  275. package/runner/tests/test_contract_tooling.py +0 -312
  276. package/runner/tests/test_darkharvest_audit.py +0 -395
  277. package/runner/tests/test_dep_health.py +0 -595
  278. package/runner/tests/test_domain_packs.py +0 -217
  279. package/runner/tests/test_dossier_contract.py +0 -196
  280. package/runner/tests/test_factory.py +0 -258
  281. package/runner/tests/test_fleet_seam.py +0 -113
  282. package/runner/tests/test_frontier_concurrency.py +0 -288
  283. package/runner/tests/test_frontier_mirror_standalone.py +0 -156
  284. package/runner/tests/test_grounding.py +0 -183
  285. package/runner/tests/test_hardening_contract.py +0 -391
  286. package/runner/tests/test_hook_bus.py +0 -956
  287. package/runner/tests/test_living_dossiers.py +0 -204
  288. package/runner/tests/test_manifest_concurrency.py +0 -187
  289. package/runner/tests/test_mcp_server.py +0 -257
  290. package/runner/tests/test_nk_hardening.py +0 -1046
  291. package/runner/tests/test_opencode_ux.py +0 -2438
  292. package/runner/tests/test_opencode_v2_registrars.py +0 -2157
  293. package/runner/tests/test_pcrb.py +0 -240
  294. package/runner/tests/test_phase08_waiver_reopens.py +0 -539
  295. package/runner/tests/test_refinement.py +0 -255
  296. package/runner/tests/test_search_anomaly.py +0 -342
  297. package/runner/tests/test_search_provider.py +0 -1534
  298. package/runner/tests/test_search_provider_plugin.py +0 -401
  299. package/runner/tests/test_swarm.py +0 -444
  300. package/runner/tests/test_swarm_config.py +0 -520
  301. package/runner/tests/test_sweep_regressions.py +0 -453
  302. package/runner/tests/test_webcache.py +0 -271
  303. package/runner/tests/test_weight_signals.py +0 -401
  304. package/schemas/alpha_dossier.schema.json +0 -204
  305. package/schemas/audit_report.schema.json +0 -79
  306. package/schemas/beta_dossier.schema.json +0 -214
  307. package/schemas/config.schema.json +0 -311
  308. package/schemas/frontier.schema.json +0 -61
  309. package/schemas/manifest.schema.json +0 -49
  310. package/schemas/scope_manifest.schema.json +0 -47
  311. package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
  312. package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
  313. package/scripts/__pycache__/check_docs.cpython-311.pyc +0 -0
  314. package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
  315. package/scripts/__pycache__/gen_schemas.cpython-311.pyc +0 -0
  316. package/scripts/auction_experiment.py +0 -188
  317. package/scripts/bet1_advisory_spike.py +0 -442
  318. package/scripts/build_adapters.py +0 -417
  319. package/scripts/check_docs.py +0 -66
  320. package/scripts/divergence_experiment.py +0 -214
  321. package/scripts/gen_schemas.py +0 -69
  322. package/skills/brainstorming/SKILL.md +0 -106
  323. package/skills/brainstorming/__init__.py +0 -1
  324. package/skills/brainstorming/scripts/brainstorm.py +0 -201
  325. package/skills/code_audit/SKILL.md +0 -45
  326. package/skills/darkharvest/SKILL.md +0 -70
  327. package/skills/darkharvest/scripts/harvest.py +0 -289
  328. package/skills/epistemic_search/SKILL.md +0 -67
  329. package/skills/epistemic_search/__init__.py +0 -1
  330. package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
  331. package/skills/epistemic_search/scripts/fetch.py +0 -156
  332. package/skills/epistemic_search/scripts/search.py +0 -551
  333. package/skills/epistemic_search/scripts/webcache.py +0 -339
  334. package/skills/factory/SKILL.md +0 -61
  335. package/skills/factory/scripts/factory.py +0 -300
  336. package/skills/grilling/SKILL.md +0 -61
  337. package/skills/grilling/__init__.py +0 -0
  338. package/skills/grilling/__pycache__/__init__.cpython-311.pyc +0 -0
  339. package/skills/grilling/__pycache__/socratic_tree.cpython-311.pyc +0 -0
  340. package/skills/grilling/socratic_tree.py +0 -363
  341. package/skills/oss_scout/SKILL.md +0 -49
  342. package/skills/research_cache/SKILL.md +0 -36
  343. package/skills/research_cache/__init__.py +0 -0
  344. package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
  345. package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
  346. package/skills/research_cache/hasher.py +0 -302
  347. package/skills/swarm_config/SKILL.md +0 -178
  348. package/skills/swarm_config/__init__.py +0 -35
  349. package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
  350. package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
  351. 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,83 @@
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.3",
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": "./dist/tui.js"
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
+ "dist"
37
+ ],
38
+ "scripts": {
39
+ "build": "bun script/build-tui.ts",
40
+ "prepublishOnly": "bun run build",
41
+ "test": "bun test"
20
42
  },
21
43
  "dependencies": {
22
- "solid-js": "1.9.12",
23
- "@opentui/solid": ">=0.4.0 <0.6.0"
44
+ "@heretek-ai/es-core": "1.0.3",
45
+ "@opencode/plugin": "2.0.24"
24
46
  },
25
- "overrides": {
26
- "@babel/core": "^7.29.6"
47
+ "devDependencies": {
48
+ "@babel/core": "7.28.0",
49
+ "@babel/preset-typescript": "7.27.1",
50
+ "@heretek-ai/es-testkit": "1.0.0",
51
+ "@opencode/sdk": "2.0.24",
52
+ "@opentui/core": "0.5.14",
53
+ "@opentui/solid": "0.5.14",
54
+ "babel-preset-solid": "1.9.12",
55
+ "solid-js": "1.9.15"
27
56
  },
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://github.com/Heretek-AI/IUMBTEMS.git"
57
+ "engines": {
58
+ "node": ">=22"
59
+ },
60
+ "peerDependencies": {
61
+ "@opentui/core": ">=0.5.14",
62
+ "@opentui/solid": ">=0.5.14",
63
+ "solid-js": ">=1.9.0"
31
64
  },
32
- "bugs": {
33
- "url": "https://github.com/Heretek-AI/IUMBTEMS/issues"
65
+ "peerDependenciesMeta": {
66
+ "@opentui/core": {
67
+ "optional": true
68
+ },
69
+ "@opentui/solid": {
70
+ "optional": true
71
+ },
72
+ "solid-js": {
73
+ "optional": true
74
+ }
34
75
  },
35
- "homepage": "https://github.com/Heretek-AI/IUMBTEMS#readme",
36
76
  "keywords": [
37
- "iumbtems",
38
- "epistemic-swarm",
39
- "i-use-my-brain-to-express-my-self",
40
- "pi-package",
41
- "omp-package",
42
77
  "opencode",
43
78
  "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
- }
79
+ "ai",
80
+ "agents",
81
+ "factory"
82
+ ]
154
83
  }
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 }