@heretek-ai/epistemic-swarm 0.4.5 → 0.4.6

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 (37) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/plugins/antigravity/plugin.json +1 -1
  4. package/plugins/gemini/gemini-extension.json +1 -1
  5. package/plugins/opencode/index.js +22 -2
  6. package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
  7. package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
  8. package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
  9. package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
  10. package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
  11. package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
  12. package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
  13. package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
  14. package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
  15. package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
  16. package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
  17. package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
  18. package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
  19. package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
  20. package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
  21. package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
  22. package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
  23. package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
  24. package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
  25. package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
  26. package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
  27. package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
  28. package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
  29. package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
  30. package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
  31. package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
  32. package/runner/tests/test_opencode_ux.py +29 -4
  33. package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
  34. package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
  35. package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
  36. package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
  37. package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epistemic-swarm",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "High-Integrity Dialectic Research Agent Harness for Claude Code enforcing empirical evidence over parametric hallucination.",
5
5
  "author": {
6
6
  "name": "Heretek AI",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heretek-ai/epistemic-swarm",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "IUMBTEMS: I Use My Brain To Express My Self — High-Integrity Dialectic Research Agent Harness for Claude Code, OpenCode V2, Pi, OMP (oh-my-pi), Gemini CLI, Codex CLI, and AntiGravity",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://antigravity.google/schemas/v1/plugin.json",
3
3
  "name": "epistemic-swarm",
4
- "version": "0.4.5",
4
+ "version": "0.4.6",
5
5
  "description": "IUMBTEMS Epistemic Swarm: dialectic research, code audit, OSS scout, and lateral brainstorming for AntiGravity.",
6
6
  "author": "Heretek AI",
7
7
  "license": "Apache-2.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epistemic-swarm",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "IUMBTEMS Epistemic Swarm: dialectic research, code audit, OSS scout, and lateral brainstorming for Gemini CLI.",
5
5
  "mcpServers": {
6
6
  "brave-search": {
@@ -563,6 +563,10 @@ export function buildCompactionContext(root) {
563
563
 
564
564
  const NUDGE_MIN_INTERVAL_MS = 5 * 60 * 1000;
565
565
  const activeNudges = new Map();
566
+ // Cleanup functions for the setup() disposer (a setup that returns a plain
567
+ // object crashes host reload: the host calls the return value as a cleanup
568
+ // function). All setup-owned resources register here.
569
+ const setupCleanups = new Set();
566
570
 
567
571
  /**
568
572
  * Handle one subscribed event: nudge once per ledger change when degraded
@@ -683,7 +687,10 @@ export function createOpenCodePlugin(context = {}) {
683
687
  };
684
688
  const root =
685
689
  host.location?.directory || context.location?.directory;
686
- if (root) startStalenessNudge(nudgeHost, root);
690
+ if (root) {
691
+ const stop = startStalenessNudge(nudgeHost, root);
692
+ if (typeof stop === 'function') setupCleanups.add(stop);
693
+ }
687
694
  }
688
695
  } catch {
689
696
  /* lifecycle hooks are best-effort */
@@ -744,7 +751,20 @@ export function createOpenCodePlugin(context = {}) {
744
751
  } catch {
745
752
  /* tool transform is best-effort */
746
753
  }
747
- return { initialized: true, platform: 'opencode-v2' };
754
+ // Disposer: the host calls setup's return value as a cleanup function
755
+ // on unload/reload. It MUST be a function (returning a plain object
756
+ // crashes host reload with "not a function"). Aborts nudge streams so
757
+ // reloads never stack duplicate subscriptions.
758
+ return () => {
759
+ for (const stop of [...setupCleanups]) {
760
+ setupCleanups.delete(stop);
761
+ try {
762
+ stop();
763
+ } catch {
764
+ /* cleanup is best-effort */
765
+ }
766
+ }
767
+ };
748
768
  },
749
769
  };
750
770
  }
@@ -493,7 +493,7 @@ class TestOpenCodeV2Transforms(unittest.TestCase):
493
493
  self.V2_SETUP
494
494
  % """
495
495
  console.log(JSON.stringify({
496
- ret: ret.initialized,
496
+ cleanupFn: typeof ret === "function",
497
497
  commands: addedCommands.map(c => c.name),
498
498
  cmdExec: typeof addedCommands.find(c => c.name === "swarm").execute,
499
499
  tools: addedTools.map(t => t.name),
@@ -503,7 +503,7 @@ class TestOpenCodeV2Transforms(unittest.TestCase):
503
503
  )
504
504
  self.assertEqual(res.returncode, 0, f"v2 transform test failed: {res.stderr}")
505
505
  data = last_json_object(res.stdout)
506
- self.assertTrue(data["ret"])
506
+ self.assertEqual(data["cleanupFn"], True)
507
507
  for c in [
508
508
  "swarm",
509
509
  "grill",
@@ -556,12 +556,37 @@ class TestOpenCodeV2Transforms(unittest.TestCase):
556
556
  """
557
557
  import plugin from "./plugins/opencode/index.js";
558
558
  const ret = await plugin.setup({});
559
- console.log(JSON.stringify({ret: ret.initialized}));
559
+ ret();
560
+ ret();
561
+ console.log(JSON.stringify({cleanupFn: typeof ret === "function"}));
560
562
  """
561
563
  )
562
564
  self.assertEqual(res.returncode, 0, f"bare setup test failed: {res.stderr}")
563
565
  data = last_json_object(res.stdout)
564
- self.assertTrue(data["ret"])
566
+ self.assertEqual(data["cleanupFn"], True)
567
+
568
+ def test_setup_cleanup_aborts_nudge_streams(self):
569
+ res = run_node(
570
+ """
571
+ import plugin from "./plugins/opencode/index.js";
572
+ const seen = [];
573
+ const host = {
574
+ options: {},
575
+ location: {directory: "/tmp/oc-nudge-cleanup"},
576
+ event: {subscribe: (opts) => { seen.push(opts && opts.signal); return {[Symbol.asyncIterator]() { return {next: async () => ({done: true})}; }}; }},
577
+ session: {prompt: async () => ({})}
578
+ };
579
+ const cleanup = await plugin.setup(host);
580
+ const before = seen.length;
581
+ cleanup();
582
+ console.log(JSON.stringify({subscribed: before > 0, cleanupFn: typeof cleanup === "function", aborted: seen.length > 0 && seen[0].aborted === true}));
583
+ """
584
+ )
585
+ self.assertEqual(res.returncode, 0, f"cleanup test failed: {res.stderr}")
586
+ data = last_json_object(res.stdout)
587
+ self.assertTrue(data["subscribed"])
588
+ self.assertTrue(data["cleanupFn"])
589
+ self.assertTrue(data["aborted"])
565
590
 
566
591
 
567
592
  if __name__ == "__main__":