@heretek-ai/epistemic-swarm 0.2.2 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epistemic-swarm",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
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/README.md CHANGED
@@ -64,20 +64,36 @@ Install directly into Pi via its native package manager:
64
64
  ```bash
65
65
  pi install npm:@heretek-ai/epistemic-swarm
66
66
  ```
67
- - Exposes native `/swarm <objective>` and `/grill` slash commands in the Pi interactive terminal.
68
- - Discovers skills (`skills/grilling`, `skills/research-cache`) and prompts automatically via the `pi` manifest block.
67
+ - **Slash Commands**:
68
+ - `/swarm <objective>`: Run autonomous dialectic research swarm
69
+ - `/grill`: Launch Socratic assumption-inversion and decision trees
70
+ - `/swarm-config`: Inspect or tune search engine, depth (1-4), and mode
71
+ - `/audit <target>`: Run dialectic codebase architecture and security audit
72
+ - `/scout <feature>`: Scout open-source software and clean-room blueprints
73
+ - **Agent Tools**: `iumbtems_config`, `iumbtems_verify_quote`.
74
+ - All commands automatically respect `.research/config.json`.
69
75
 
70
76
  ### 3. OpenCode V2 (`opencode.ai`)
71
- Enable IUMBTEMS in your `~/.config/opencode/opencode.json` or project `opencode.jsonc`:
77
+ Enable IUMBTEMS in your `~/.config/opencode/opencode.json` or project `opencode.jsonc`. You can configure settings declaratively:
72
78
  ```json
73
79
  {
74
80
  "plugin": [
75
- "@heretek-ai/epistemic-swarm"
81
+ [
82
+ "@heretek-ai/epistemic-swarm",
83
+ {
84
+ "search_engine": "duckduckgo",
85
+ "max_iterations": 2,
86
+ "mode": "research"
87
+ }
88
+ ]
76
89
  ]
77
90
  }
78
91
  ```
79
- OpenCode V2 automatically registers:
80
- - `iumbtems_swarm_research`: Dispatches dialectic researcher pairs.
92
+ OpenCode V2 automatically registers the full tool suite:
93
+ - `iumbtems_config`: Inspect or dynamically adjust active parameters in `.research/config.json`.
94
+ - `iumbtems_code_audit`: Dispatches dialectic codebase review (structural architect vs. red-team).
95
+ - `iumbtems_oss_scout`: Scouts open-source libraries, audits licenses, and builds clean-room blueprints.
96
+ - `iumbtems_swarm_research`: Dispatches dialectic researcher pairs (Thesis vs. Antithesis).
81
97
  - `iumbtems_verify_quote`: Audits verbatim citations against the SHA-256 source cache.
82
98
  - `iumbtems_socratic_frontier`: Advances the Socratic decision tree frontier.
83
99
 
@@ -1,9 +1,38 @@
1
1
  {
2
2
  "$schema": "https://opencode.ai/config.json",
3
3
  "plugin": [
4
- "@heretek-ai/epistemic-swarm"
4
+ [
5
+ "@heretek-ai/epistemic-swarm",
6
+ {
7
+ "search_engine": "duckduckgo",
8
+ "max_iterations": 2,
9
+ "mode": "research"
10
+ }
11
+ ]
5
12
  ],
6
13
  "agent": {
14
+ "code-auditor": {
15
+ "description": "IUMBTEMS Codebase Auditor: Dialectic architecture mapping and vulnerability red-teaming with line-level proof.",
16
+ "tools": {
17
+ "read": true,
18
+ "write": true,
19
+ "grep": true,
20
+ "glob": true,
21
+ "iumbtems_code_audit": true,
22
+ "iumbtems_config": true
23
+ }
24
+ },
25
+ "oss-scout": {
26
+ "description": "IUMBTEMS Open Source Scout: Discovers mature OSS packages, audits copyleft licensing, and generates clean-room blueprints.",
27
+ "tools": {
28
+ "read": true,
29
+ "write": true,
30
+ "grep": true,
31
+ "glob": true,
32
+ "iumbtems_oss_scout": true,
33
+ "iumbtems_config": true
34
+ }
35
+ },
7
36
  "alpha-thesis": {
8
37
  "description": "IUMBTEMS Proponent Agent: Gathers corroborating primary sources, benchmark results, and empirical proofs.",
9
38
  "tools": {
@@ -13,7 +42,9 @@
13
42
  "grep": true,
14
43
  "glob": true,
15
44
  "task": true,
16
- "iumbtems_verify_quote": true
45
+ "iumbtems_swarm_research": true,
46
+ "iumbtems_verify_quote": true,
47
+ "iumbtems_config": true
17
48
  }
18
49
  },
19
50
  "beta-redteam": {
@@ -25,6 +56,7 @@
25
56
  "grep": true,
26
57
  "glob": true,
27
58
  "task": true,
59
+ "iumbtems_swarm_research": true,
28
60
  "iumbtems_verify_quote": true
29
61
  }
30
62
  },
@@ -42,7 +74,11 @@
42
74
  "skills": {
43
75
  "paths": [
44
76
  "./skills/grilling",
45
- "./skills/research-cache"
77
+ "./skills/research_cache",
78
+ "./skills/epistemic_search",
79
+ "./skills/swarm_config",
80
+ "./skills/code_audit",
81
+ "./skills/oss_scout"
46
82
  ]
47
83
  }
48
84
  }
@@ -2,7 +2,8 @@
2
2
  * IUMBTEMS: I Use My Brain To Express My Self
3
3
  * Native Extension for Pi (pi.dev)
4
4
  *
5
- * Exposes /grill and /swarm slash commands and epistemic verification tools in Pi.
5
+ * Exposes /swarm, /grill, /swarm-config, /audit, and /scout slash commands
6
+ * along with epistemic verification and configuration tools in Pi.
6
7
  */
7
8
 
8
9
  import { spawnSync } from 'child_process';
@@ -17,8 +18,9 @@ export default function initPiExtension(pi) {
17
18
  // Check if Pi extension API is available
18
19
  if (!pi) return;
19
20
 
20
- // 1. Register /swarm slash command
21
+ // 1. Register Slash Commands
21
22
  if (typeof pi.registerCommand === 'function') {
23
+ // /swarm: autonomous dialectic research
22
24
  pi.registerCommand('swarm', {
23
25
  description: 'Run IUMBTEMS dialectic research swarm on an objective',
24
26
  usage: '/swarm <objective>',
@@ -46,7 +48,7 @@ export default function initPiExtension(pi) {
46
48
  }
47
49
  });
48
50
 
49
- // 2. Register /grill slash command
51
+ // /grill: Socratic assumption-inversion
50
52
  pi.registerCommand('grill', {
51
53
  description: 'Launch Socratic grilling and decision tree frontier exploration',
52
54
  usage: '/grill [--objective <text>]',
@@ -61,10 +63,75 @@ export default function initPiExtension(pi) {
61
63
  ctx.output?.(res.stdout || res.stderr);
62
64
  }
63
65
  });
66
+
67
+ // /swarm-config: Inspect and tune research parameters
68
+ pi.registerCommand('swarm-config', {
69
+ description: 'Inspect or update Epistemic Swarm parameters (engine, depth, mode)',
70
+ usage: '/swarm-config [--engine <e>] [--depth <d>] [--mode <m>] [--show]',
71
+ handler: async (args, ctx) => {
72
+ const configScript = path.join(PKG_ROOT, 'skills/swarm_config/configure.py');
73
+ const rawArgs = args.trim() ? args.trim().split(/\s+/) : ['--show'];
74
+ const res = spawnSync('python3', [configScript, ...rawArgs], {
75
+ encoding: 'utf-8',
76
+ cwd: ctx.cwd || process.cwd(),
77
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
78
+ });
79
+ ctx.output?.(res.stdout || res.stderr);
80
+ }
81
+ });
82
+
83
+ // /audit: Dialectic codebase architecture & security audit
84
+ pi.registerCommand('audit', {
85
+ description: 'Run dialectic codebase architectural and security audit with line-level proof',
86
+ usage: '/audit <target_path_or_scope>',
87
+ handler: async (args, ctx) => {
88
+ const target = args.trim() || 'Full repository architecture and vulnerability audit';
89
+ ctx.output?.(`🛡️ [IUMBTEMS Audit] Launching Codebase Audit for: "${target}"...`);
90
+ const runnerPath = path.join(PKG_ROOT, 'runner/research_swarm.py');
91
+ const res = spawnSync('python3', [runnerPath, '--mode', 'audit', '--objective', target], {
92
+ encoding: 'utf-8',
93
+ cwd: ctx.cwd || process.cwd(),
94
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
95
+ });
96
+ if (res.status === 0) {
97
+ ctx.output?.(res.stdout);
98
+ ctx.output?.('\n✅ Audit complete! Report written to .research/code_audit_report.md');
99
+ } else {
100
+ ctx.output?.(`❌ Audit failed:\n${res.stderr || res.stdout}`);
101
+ }
102
+ }
103
+ });
104
+
105
+ // /scout: Open-source software discovery & clean-room harvesting
106
+ pi.registerCommand('scout', {
107
+ description: 'Scout open-source software libraries, audit copyleft licenses & generate clean-room blueprints',
108
+ usage: '/scout <feature_or_algorithm>',
109
+ handler: async (args, ctx) => {
110
+ const feature = args.trim();
111
+ if (!feature) {
112
+ ctx.output?.('⚠️ Please provide a feature to scout. Example: /scout "Zero-dependency Raft consensus in Rust"');
113
+ return;
114
+ }
115
+ ctx.output?.(`🔭 [IUMBTEMS Scout] Scouting open-source solutions for: "${feature}"...`);
116
+ const runnerPath = path.join(PKG_ROOT, 'runner/research_swarm.py');
117
+ const res = spawnSync('python3', [runnerPath, '--mode', 'scout', '--objective', feature], {
118
+ encoding: 'utf-8',
119
+ cwd: ctx.cwd || process.cwd(),
120
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
121
+ });
122
+ if (res.status === 0) {
123
+ ctx.output?.(res.stdout);
124
+ ctx.output?.('\n✅ Scout complete! Blueprint written to .research/oss_scout_report.md');
125
+ } else {
126
+ ctx.output?.(`❌ Scout failed:\n${res.stderr || res.stdout}`);
127
+ }
128
+ }
129
+ });
64
130
  }
65
131
 
66
- // 3. Register tool for epistemic quote verification
132
+ // 2. Register Agent Tools
67
133
  if (typeof pi.registerTool === 'function') {
134
+ // Tool: iumbtems_verify_quote
68
135
  pi.registerTool({
69
136
  name: 'iumbtems_verify_quote',
70
137
  description: 'Verify that an empirical claim quote matches verbatim text in the source cache',
@@ -86,5 +153,41 @@ export default function initPiExtension(pi) {
86
153
  };
87
154
  }
88
155
  });
156
+
157
+ // Tool: iumbtems_config
158
+ pi.registerTool({
159
+ name: 'iumbtems_config',
160
+ description: 'Inspect or modify Epistemic Swarm configuration parameters (search engine, depth, mode) in .research/config.json',
161
+ parameters: {
162
+ type: 'object',
163
+ properties: {
164
+ search_engine: { type: 'string', enum: ['duckduckgo', 'brave', 'firecrawl', 'searxng'] },
165
+ max_iterations: { type: 'integer', minimum: 1, maximum: 4 },
166
+ mode: { type: 'string', enum: ['research', 'audit', 'scout', 'hybrid'] },
167
+ divergence_threshold: { type: 'number', minimum: 0, maximum: 1 },
168
+ show: { type: 'boolean', default: false }
169
+ }
170
+ },
171
+ execute: async (args = {}) => {
172
+ const configScript = path.join(PKG_ROOT, 'skills/swarm_config/configure.py');
173
+ const cmdArgs = [configScript];
174
+ if (args.show || (!args.search_engine && !args.max_iterations && !args.mode && args.divergence_threshold === undefined)) {
175
+ cmdArgs.push('--show');
176
+ } else {
177
+ if (args.search_engine) cmdArgs.push('--engine', args.search_engine);
178
+ if (args.max_iterations) cmdArgs.push('--depth', String(args.max_iterations));
179
+ if (args.mode) cmdArgs.push('--mode', args.mode);
180
+ if (args.divergence_threshold !== undefined) cmdArgs.push('--divergence', String(args.divergence_threshold));
181
+ }
182
+
183
+ const res = spawnSync('python3', cmdArgs, {
184
+ encoding: 'utf-8',
185
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
186
+ });
187
+ return {
188
+ content: [{ type: 'text', text: res.stdout || res.stderr }]
189
+ };
190
+ }
191
+ });
89
192
  }
90
193
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heretek-ai/epistemic-swarm",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "IUMBTEMS: I Use My Brain To Express My Self — High-Integrity Dialectic Research Agent Harness for Claude Code, Pi (pi.dev), and OpenCode V2",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -2,8 +2,8 @@
2
2
  * IUMBTEMS: I Use My Brain To Express My Self
3
3
  * Native Plugin for OpenCode V2 (opencode.ai)
4
4
  *
5
- * Exposes dialectic swarm research tools, Socratic decision frontier calculation,
6
- * and content-addressed quote verification directly into OpenCode V2 agents.
5
+ * Exposes dialectic swarm research tools, codebase auditing, open-source scouting,
6
+ * configuration management, and content-addressed quote verification directly into OpenCode V2 agents.
7
7
  */
8
8
 
9
9
  import { spawnSync } from 'child_process';
@@ -18,10 +18,150 @@ export function createOpenCodePlugin(context = {}) {
18
18
  return {
19
19
  id: "heretek.iumbtems.epistemic-swarm",
20
20
  name: "IUMBTEMS Epistemic Swarm",
21
- version: "0.1.0",
22
- description: "I Use My Brain To Express My Self: Dialectic research swarm enforcing empirical verification",
21
+ version: "0.2.3",
22
+ description: "I Use My Brain To Express My Self: High-integrity dialectic research, code audits, and open-source scouting",
23
23
 
24
24
  server: (toolContext) => [
25
+ {
26
+ name: "iumbtems_config",
27
+ description: "Inspect or modify the active Epistemic Swarm configuration (search engine, depth/iterations, operating mode, divergence threshold) in .research/config.json.",
28
+ input: {
29
+ type: "object",
30
+ properties: {
31
+ search_engine: {
32
+ type: "string",
33
+ enum: ["duckduckgo", "brave", "firecrawl", "searxng"],
34
+ description: "Primary search engine (duckduckgo is the zero-key free default)"
35
+ },
36
+ max_iterations: {
37
+ type: "integer",
38
+ minimum: 1,
39
+ maximum: 4,
40
+ description: "Maximum dialectic research iterations / depth (1-4)"
41
+ },
42
+ mode: {
43
+ type: "string",
44
+ enum: ["research", "audit", "scout", "hybrid"],
45
+ description: "Operating mode: research (literature), audit (codebase), scout (OSS), hybrid"
46
+ },
47
+ divergence_threshold: {
48
+ type: "number",
49
+ minimum: 0.0,
50
+ maximum: 1.0,
51
+ description: "Auditor divergence threshold (default 0.75)"
52
+ },
53
+ show: {
54
+ type: "boolean",
55
+ description: "Just inspect current configuration without modifying",
56
+ default: false
57
+ }
58
+ }
59
+ },
60
+ options: { codemode: false },
61
+ execute: async (args = {}) => {
62
+ const configScript = path.join(PKG_ROOT, "skills/swarm_config/configure.py");
63
+ const cmdArgs = [configScript];
64
+
65
+ if (args.show || (!args.search_engine && !args.max_iterations && !args.mode && args.divergence_threshold === undefined)) {
66
+ cmdArgs.push("--show");
67
+ } else {
68
+ if (args.search_engine) cmdArgs.push("--engine", args.search_engine);
69
+ if (args.max_iterations) cmdArgs.push("--depth", String(args.max_iterations));
70
+ if (args.mode) cmdArgs.push("--mode", args.mode);
71
+ if (args.divergence_threshold !== undefined) cmdArgs.push("--divergence", String(args.divergence_threshold));
72
+ }
73
+
74
+ const res = spawnSync("python3", cmdArgs, {
75
+ encoding: "utf-8",
76
+ cwd: toolContext?.cwd || process.cwd(),
77
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
78
+ });
79
+
80
+ return {
81
+ content: res.stdout || res.stderr,
82
+ status: res.status === 0 ? "success" : "error"
83
+ };
84
+ }
85
+ },
86
+
87
+ {
88
+ name: "iumbtems_code_audit",
89
+ description: "Run a dialectic codebase architectural and security audit pairing a structural architect with an adversarial red-teamer.",
90
+ input: {
91
+ type: "object",
92
+ properties: {
93
+ target: {
94
+ type: "string",
95
+ description: "Target directory, file, or architectural component to audit"
96
+ },
97
+ mock_mode: {
98
+ type: "boolean",
99
+ description: "Run in mock mode without invoking LLM tokens",
100
+ default: false
101
+ }
102
+ },
103
+ required: ["target"]
104
+ },
105
+ options: { codemode: false },
106
+ execute: async (args) => {
107
+ const runnerPath = path.join(PKG_ROOT, "runner/research_swarm.py");
108
+ const cmdArgs = [runnerPath, "--mode", "audit", "--objective", args.target];
109
+ if (args.mock_mode) {
110
+ cmdArgs.push("--mock-claude");
111
+ }
112
+
113
+ const res = spawnSync("python3", cmdArgs, {
114
+ encoding: "utf-8",
115
+ cwd: toolContext?.cwd || process.cwd(),
116
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
117
+ });
118
+
119
+ return {
120
+ content: res.stdout || res.stderr,
121
+ status: res.status === 0 ? "success" : "error"
122
+ };
123
+ }
124
+ },
125
+
126
+ {
127
+ name: "iumbtems_oss_scout",
128
+ description: "Scout open-source software libraries, benchmark candidate implementations, red-team viral copyleft (GPL/AGPL), and produce clean-room implementation blueprints.",
129
+ input: {
130
+ type: "object",
131
+ properties: {
132
+ feature: {
133
+ type: "string",
134
+ description: "The feature, algorithm, or capability to scout in open source"
135
+ },
136
+ mock_mode: {
137
+ type: "boolean",
138
+ description: "Run in mock mode without invoking LLM tokens",
139
+ default: false
140
+ }
141
+ },
142
+ required: ["feature"]
143
+ },
144
+ options: { codemode: false },
145
+ execute: async (args) => {
146
+ const runnerPath = path.join(PKG_ROOT, "runner/research_swarm.py");
147
+ const cmdArgs = [runnerPath, "--mode", "scout", "--objective", args.feature];
148
+ if (args.mock_mode) {
149
+ cmdArgs.push("--mock-claude");
150
+ }
151
+
152
+ const res = spawnSync("python3", cmdArgs, {
153
+ encoding: "utf-8",
154
+ cwd: toolContext?.cwd || process.cwd(),
155
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
156
+ });
157
+
158
+ return {
159
+ content: res.stdout || res.stderr,
160
+ status: res.status === 0 ? "success" : "error"
161
+ };
162
+ }
163
+ },
164
+
25
165
  {
26
166
  name: "iumbtems_swarm_research",
27
167
  description: "Execute an autonomous dialectic research swarm on an objective using Agent Alpha (Thesis) and Agent Beta (Red Team).",
@@ -139,7 +279,21 @@ export function createOpenCodePlugin(context = {}) {
139
279
  ],
140
280
 
141
281
  setup: async (appContext) => {
142
- // OpenCode V2 lifecycle hook
282
+ const opts = context.options || appContext?.options;
283
+ if (opts && typeof opts === "object") {
284
+ const configScript = path.join(PKG_ROOT, "skills/swarm_config/configure.py");
285
+ const cmdArgs = [configScript];
286
+ if (opts.search_engine) cmdArgs.push("--engine", opts.search_engine);
287
+ if (opts.max_iterations) cmdArgs.push("--depth", String(opts.max_iterations));
288
+ if (opts.mode) cmdArgs.push("--mode", opts.mode);
289
+ if (opts.divergence_threshold !== undefined) cmdArgs.push("--divergence", String(opts.divergence_threshold));
290
+ if (cmdArgs.length > 1) {
291
+ spawnSync("python3", cmdArgs, {
292
+ cwd: appContext?.cwd || toolContext?.cwd || process.cwd(),
293
+ env: { ...process.env, PYTHONPATH: PKG_ROOT }
294
+ });
295
+ }
296
+ }
143
297
  return { initialized: true, platform: "opencode-v2" };
144
298
  }
145
299
  };
@@ -237,8 +237,59 @@ In our experiments, the 70B parameter model was trained on 15.0 trillion tokens.
237
237
  content = f.read()
238
238
  self.assertIn("Open-Source Software Discovery", content)
239
239
 
240
+ def test_opencode_and_pi_extension_interfaces(self):
241
+ import subprocess
242
+ # 1. Test OpenCode Plugin registration
243
+ node_code_oc = """
244
+ import plugin from "./plugins/opencode/index.js";
245
+ const tools = plugin.server();
246
+ const names = tools.map(t => t.name);
247
+ console.log(JSON.stringify(names));
248
+ """
249
+ res_oc = subprocess.run(
250
+ ["node", "--input-type=module", "-e", node_code_oc],
251
+ capture_output=True,
252
+ text=True,
253
+ cwd=str(PROJECT_ROOT)
254
+ )
255
+ self.assertEqual(res_oc.returncode, 0, f"OpenCode plugin test failed: {res_oc.stderr}")
256
+ lines = [line.strip() for line in res_oc.stdout.strip().split("\n") if line.strip().startswith("[")]
257
+ tools = json.loads(lines[-1])
258
+ expected_tools = [
259
+ "iumbtems_config", "iumbtems_code_audit", "iumbtems_oss_scout",
260
+ "iumbtems_swarm_research", "iumbtems_verify_quote", "iumbtems_socratic_frontier"
261
+ ]
262
+ for t in expected_tools:
263
+ self.assertIn(t, tools)
264
+
265
+ # 2. Test Pi Extension registration
266
+ node_code_pi = """
267
+ import initPi from "./extensions/pi/index.js";
268
+ const commands = [];
269
+ const tools = [];
270
+ initPi({
271
+ registerCommand: (name) => commands.push(name),
272
+ registerTool: (def) => tools.push(def.name)
273
+ });
274
+ console.log(JSON.stringify({ commands, tools }));
275
+ """
276
+ res_pi = subprocess.run(
277
+ ["node", "--input-type=module", "-e", node_code_pi],
278
+ capture_output=True,
279
+ text=True,
280
+ cwd=str(PROJECT_ROOT)
281
+ )
282
+ self.assertEqual(res_pi.returncode, 0, f"Pi extension test failed: {res_pi.stderr}")
283
+ lines = [line.strip() for line in res_pi.stdout.strip().split("\n") if line.strip().startswith("{")]
284
+ data = json.loads(lines[-1])
285
+ for c in ["swarm", "grill", "swarm-config", "audit", "scout"]:
286
+ self.assertIn(c, data["commands"])
287
+ for t in ["iumbtems_verify_quote", "iumbtems_config"]:
288
+ self.assertIn(t, data["tools"])
289
+
240
290
 
241
291
  if __name__ == "__main__":
242
292
  unittest.main()
243
293
 
244
294
 
295
+