opencode-swarm 7.29.1 → 7.29.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.
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.29.1",
37
+ version: "7.29.3",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -505,9 +505,7 @@ function bunSpawn(cmd, options) {
505
505
  return proc.exitCode;
506
506
  },
507
507
  kill(signal) {
508
- try {
509
- killChild(signal);
510
- } catch {}
508
+ killChild(signal);
511
509
  }
512
510
  };
513
511
  }
@@ -46282,7 +46280,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46282
46280
  const coverage = opts.coverage ?? false;
46283
46281
  switch (framework) {
46284
46282
  case "bun": {
46285
- const args = ["bun", "--smol", "test"];
46283
+ const args = ["bun", "test"];
46286
46284
  if (coverage)
46287
46285
  args.push("--coverage");
46288
46286
  if (scope !== "all" && files.length > 0)
@@ -48715,7 +48713,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
48715
48713
  function buildTestCommand2(framework, scope, files, coverage, baseDir) {
48716
48714
  switch (framework) {
48717
48715
  case "bun": {
48718
- const args = ["bun", "--smol", "test"];
48716
+ const args = ["bun", "test"];
48719
48717
  if (coverage)
48720
48718
  args.push("--coverage");
48721
48719
  if (scope !== "all" && files.length > 0) {
@@ -49252,24 +49250,17 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49252
49250
  const proc = bunSpawn(command, {
49253
49251
  stdout: "pipe",
49254
49252
  stderr: "pipe",
49255
- stdin: "ignore",
49256
- cwd,
49257
- killProcessTree: true
49258
- });
49259
- let timeoutHandle;
49260
- const timeoutPromise = new Promise((resolve14) => {
49261
- timeoutHandle = setTimeout(() => {
49262
- proc.kill();
49263
- resolve14(-1);
49264
- }, timeout_ms);
49253
+ cwd
49265
49254
  });
49255
+ const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
49256
+ proc.kill();
49257
+ resolve14(-1);
49258
+ }, timeout_ms));
49266
49259
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
49267
49260
  Promise.race([proc.exited, timeoutPromise]),
49268
49261
  readBoundedStream(proc.stdout, MAX_OUTPUT_BYTES3),
49269
49262
  readBoundedStream(proc.stderr, MAX_OUTPUT_BYTES3)
49270
49263
  ]);
49271
- if (timeoutHandle !== undefined)
49272
- clearTimeout(timeoutHandle);
49273
49264
  const duration_ms = Date.now() - startTime;
49274
49265
  let output = stdoutResult.text;
49275
49266
  if (stderrResult.text) {
@@ -49572,6 +49563,7 @@ var init_test_runner = __esm(() => {
49572
49563
  files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
49573
49564
  coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
49574
49565
  timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
49566
+ allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
49575
49567
  working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
49576
49568
  },
49577
49569
  async execute(args, directory) {
@@ -49645,8 +49637,7 @@ var init_test_runner = __esm(() => {
49645
49637
  }
49646
49638
  const scope = args.scope || "all";
49647
49639
  if (scope === "all") {
49648
- const fullSuiteAllowed = process.env.SWARM_ALLOW_FULL_SUITE === "1" || process.env.SWARM_ALLOW_FULL_SUITE === "true";
49649
- if (!fullSuiteAllowed) {
49640
+ if (!process.env.SWARM_ALLOW_FULL_SUITE) {
49650
49641
  const errorResult = {
49651
49642
  success: false,
49652
49643
  framework: "none",
package/dist/index.js CHANGED
@@ -48,7 +48,7 @@ var package_default;
48
48
  var init_package = __esm(() => {
49
49
  package_default = {
50
50
  name: "opencode-swarm",
51
- version: "7.29.1",
51
+ version: "7.29.3",
52
52
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
53
53
  main: "dist/index.js",
54
54
  types: "dist/index.d.ts",
@@ -16715,9 +16715,7 @@ function bunSpawn(cmd, options) {
16715
16715
  return proc.exitCode;
16716
16716
  },
16717
16717
  kill(signal) {
16718
- try {
16719
- killChild(signal);
16720
- } catch {}
16718
+ killChild(signal);
16721
16719
  }
16722
16720
  };
16723
16721
  }
@@ -16969,6 +16967,13 @@ var init_telemetry = __esm(() => {
16969
16967
  gatePassed(sessionId, gate, taskId) {
16970
16968
  _internals4.emit("gate_passed", { sessionId, gate, taskId });
16971
16969
  },
16970
+ gateParseError(taskId, error49) {
16971
+ _internals4.emit("gate_parse_error", {
16972
+ taskId,
16973
+ errorName: error49.name,
16974
+ errorMessage: error49.message.slice(0, 200)
16975
+ });
16976
+ },
16972
16977
  gateFailed(sessionId, gate, taskId, reason) {
16973
16978
  _internals4.emit("gate_failed", { sessionId, gate, taskId, reason });
16974
16979
  },
@@ -38741,12 +38746,15 @@ function getEvidencePath(directory, taskId) {
38741
38746
  assertValidTaskId(taskId);
38742
38747
  return path12.join(getEvidenceDir(directory), `${taskId}.json`);
38743
38748
  }
38744
- function readExisting(evidencePath) {
38749
+ function readExisting(evidencePath, taskId) {
38745
38750
  try {
38746
38751
  const raw = readFileSync5(evidencePath, "utf-8");
38747
38752
  return TaskEvidenceSchema.parse(JSON.parse(raw));
38748
- } catch {
38749
- return null;
38753
+ } catch (error49) {
38754
+ if (error49.code === "ENOENT")
38755
+ return null;
38756
+ telemetry.gateParseError(taskId, error49);
38757
+ throw error49;
38750
38758
  }
38751
38759
  }
38752
38760
  async function atomicWrite2(targetPath, content) {
@@ -38767,7 +38775,13 @@ async function recordGateEvidence(directory, taskId, gate, sessionId, turbo) {
38767
38775
  const lockRelPath = path12.join("evidence", `${taskId}.json`);
38768
38776
  await withEvidenceLock(directory, lockRelPath, gate, taskId, async () => {
38769
38777
  const evidencePath = getEvidencePath(directory, taskId);
38770
- const existing = readExisting(evidencePath);
38778
+ let existing = null;
38779
+ try {
38780
+ existing = readExisting(evidencePath, taskId);
38781
+ } catch (error49) {
38782
+ telemetry.gateParseError(taskId, error49);
38783
+ throw error49;
38784
+ }
38771
38785
  const requiredGates = existing ? expandRequiredGates(existing.required_gates, gate) : deriveRequiredGates(gate);
38772
38786
  const updated = {
38773
38787
  taskId,
@@ -38793,7 +38807,13 @@ async function recordAgentDispatch(directory, taskId, agentType, turbo) {
38793
38807
  const lockRelPath = path12.join("evidence", `${taskId}.json`);
38794
38808
  await withEvidenceLock(directory, lockRelPath, agentType, taskId, async () => {
38795
38809
  const evidencePath = getEvidencePath(directory, taskId);
38796
- const existing = readExisting(evidencePath);
38810
+ let existing = null;
38811
+ try {
38812
+ existing = readExisting(evidencePath, taskId);
38813
+ } catch (error49) {
38814
+ telemetry.gateParseError(taskId, error49);
38815
+ throw error49;
38816
+ }
38797
38817
  const requiredGates = existing ? expandRequiredGates(existing.required_gates, agentType) : deriveRequiredGates(agentType);
38798
38818
  const updated = {
38799
38819
  taskId,
@@ -38807,7 +38827,7 @@ async function recordAgentDispatch(directory, taskId, agentType, turbo) {
38807
38827
  async function readTaskEvidence(directory, taskId) {
38808
38828
  try {
38809
38829
  assertValidTaskId(taskId);
38810
- return readExisting(getEvidencePath(directory, taskId));
38830
+ return readExisting(getEvidencePath(directory, taskId), taskId);
38811
38831
  } catch {
38812
38832
  return null;
38813
38833
  }
@@ -67375,7 +67395,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
67375
67395
  const coverage = opts.coverage ?? false;
67376
67396
  switch (framework) {
67377
67397
  case "bun": {
67378
- const args2 = ["bun", "--smol", "test"];
67398
+ const args2 = ["bun", "test"];
67379
67399
  if (coverage)
67380
67400
  args2.push("--coverage");
67381
67401
  if (scope !== "all" && files.length > 0)
@@ -69808,7 +69828,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
69808
69828
  function buildTestCommand2(framework, scope, files, coverage, baseDir) {
69809
69829
  switch (framework) {
69810
69830
  case "bun": {
69811
- const args2 = ["bun", "--smol", "test"];
69831
+ const args2 = ["bun", "test"];
69812
69832
  if (coverage)
69813
69833
  args2.push("--coverage");
69814
69834
  if (scope !== "all" && files.length > 0) {
@@ -70345,24 +70365,17 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
70345
70365
  const proc = bunSpawn(command, {
70346
70366
  stdout: "pipe",
70347
70367
  stderr: "pipe",
70348
- stdin: "ignore",
70349
- cwd,
70350
- killProcessTree: true
70351
- });
70352
- let timeoutHandle;
70353
- const timeoutPromise = new Promise((resolve16) => {
70354
- timeoutHandle = setTimeout(() => {
70355
- proc.kill();
70356
- resolve16(-1);
70357
- }, timeout_ms);
70368
+ cwd
70358
70369
  });
70370
+ const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
70371
+ proc.kill();
70372
+ resolve16(-1);
70373
+ }, timeout_ms));
70359
70374
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
70360
70375
  Promise.race([proc.exited, timeoutPromise]),
70361
70376
  readBoundedStream(proc.stdout, MAX_OUTPUT_BYTES3),
70362
70377
  readBoundedStream(proc.stderr, MAX_OUTPUT_BYTES3)
70363
70378
  ]);
70364
- if (timeoutHandle !== undefined)
70365
- clearTimeout(timeoutHandle);
70366
70379
  const duration_ms = Date.now() - startTime;
70367
70380
  let output = stdoutResult.text;
70368
70381
  if (stderrResult.text) {
@@ -70665,6 +70678,7 @@ var init_test_runner = __esm(() => {
70665
70678
  files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
70666
70679
  coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
70667
70680
  timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
70681
+ allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
70668
70682
  working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
70669
70683
  },
70670
70684
  async execute(args2, directory) {
@@ -70738,8 +70752,7 @@ var init_test_runner = __esm(() => {
70738
70752
  }
70739
70753
  const scope = args2.scope || "all";
70740
70754
  if (scope === "all") {
70741
- const fullSuiteAllowed = process.env.SWARM_ALLOW_FULL_SUITE === "1" || process.env.SWARM_ALLOW_FULL_SUITE === "true";
70742
- if (!fullSuiteAllowed) {
70755
+ if (!process.env.SWARM_ALLOW_FULL_SUITE) {
70743
70756
  const errorResult = {
70744
70757
  success: false,
70745
70758
  framework: "none",
@@ -75931,8 +75944,6 @@ SECURITY_KEYWORDS: password, secret, token, credential, auth, login, encryption,
75931
75944
  {{AGENT_PREFIX}}test_engineer - Test generation AND execution (writes tests, runs them, reports PASS/FAIL)
75932
75945
  {{AGENT_PREFIX}}critic - Plan review gate (reviews plan BEFORE implementation)
75933
75946
  {{AGENT_PREFIX}}critic_sounding_board - Pre-escalation pushback (honest engineer review before user contact)
75934
- {{AGENT_PREFIX}}skill_improver - Low-frequency skill / knowledge / prompt improvement adviser
75935
- {{AGENT_PREFIX}}spec_writer - .swarm/spec.md authoring via spec_write
75936
75947
  {{AGENT_PREFIX}}docs - Documentation updates (README, API docs, guides — NOT .swarm/ files)
75937
75948
  {{AGENT_PREFIX}}designer - UI/UX design specs (scaffold generation for UI components — runs BEFORE coder on UI tasks)
75938
75949
 
@@ -75983,20 +75994,30 @@ For every applicable directive in the block:
75983
75994
 
75984
75995
  You may also call the \`knowledge_ack\` tool to record an outcome explicitly when chat-text markers would be ambiguous (e.g. inside structured tool args).
75985
75996
 
75986
- ## SKILL IMPROVER
75997
+ ## SKILL IMPROVER (low-frequency, expensive-model adviser)
75987
75998
 
75988
- \`{{AGENT_PREFIX}}skill_improver\` / \`skill_improve\`: rare, quota-bounded,
75989
- disabled by default, proposal-only. Use for repeated rejections,
75990
- \`KNOWLEDGE_IGNORED\`, stale skills, or spec drift.
75999
+ The \`skill_improver\` agent and the \`skill_improve\` tool exist for rare, deep
76000
+ review of accumulated knowledge / skills / spec / architect prompt. They are
76001
+ quota-bounded (default 10 calls/day) and disabled by default. Suggest running
76002
+ \`skill_improve\` only after one of:
76003
+ - repeated reviewer rejections in a row,
76004
+ - many \`KNOWLEDGE_IGNORED\` outcomes for the same cluster,
76005
+ - stale skills (no updates while their target area changed),
76006
+ - a fresh spec mismatch with shipped behaviour.
75991
76007
 
75992
76008
  When \`skill_improver.require_user_approval\` is true (default), ASK the user
75993
76009
  before running. Default outputs are proposals only — they never modify source.
75994
76010
 
75995
76011
  ## SPEC WRITER
75996
76012
 
75997
- For substantial spec authoring/revision, prefer \`{{AGENT_PREFIX}}spec_writer\`;
75998
- it writes via \`spec_write\`. Use for major specs or non-trivial
75999
- decomposition. Handle small touch-ups.
76013
+ For substantial spec authoring or revision, prefer delegating to the
76014
+ \`spec_writer\` agent (independent model from architect). It writes only via
76015
+ the safe \`spec_write\` tool. Use it when:
76016
+ - the user requests a new spec or major spec revision,
76017
+ - requirements decomposition is non-trivial,
76018
+ - you would otherwise inline-author \`.swarm/spec.md\` yourself.
76019
+
76020
+ Continue handling small touch-ups (typos, cross-references) inline.
76000
76021
 
76001
76022
  ### ANTI-RATIONALIZATION
76002
76023
  - ✗ "The coder already knows these conventions" → Skills contain project-specific rules the model cannot know from training. Always pass.
@@ -76177,12 +76198,11 @@ MODE: BRAINSTORM runs seven phases in strict order. Do not skip phases. Do not c
76177
76198
  - Exit with a design outline the user can skim in under two minutes.
76178
76199
 
76179
76200
  **Phase 5: SPEC WRITE + SELF-REVIEW (architect + reviewer).**
76180
- - Delegate substantial spec drafting to \`{{AGENT_PREFIX}}spec_writer\` with the chosen design, dialogue notes, SME context, and SPEC CONTENT RULES. The spec writer must persist \`.swarm/spec.md\` through \`spec_write\`.
76181
- - The spec must follow the same SPEC CONTENT RULES that MODE: SPECIFY uses: WHAT/WHY only, no tech stack, no implementation details, FR-### / SC-### numbering, Given/When/Then scenarios, \`[NEEDS CLARIFICATION]\` markers (max 3).
76201
+ - Generate \`.swarm/spec.md\` following the same SPEC CONTENT RULES that MODE: SPECIFY uses: WHAT/WHY only, no tech stack, no implementation details, FR-### / SC-### numbering, Given/When/Then scenarios, \`[NEEDS CLARIFICATION]\` markers (max 3).
76182
76202
  - Cross-reference design sections by name where relevant context helps (but keep HOW out of the spec).
76183
76203
  - Delegate to \`{{AGENT_PREFIX}}reviewer\` for an independent review of the draft spec. Reviewer must flag: requirements that encode HOW, untestable requirements, missing edge cases, silent assumptions.
76184
76204
  - Apply reviewer feedback. If reviewer rejects, iterate once and re-review. After two rounds, surface remaining disagreements to the user.
76185
- - Read back and lint the final spec after \`{{AGENT_PREFIX}}spec_writer\` writes it.
76205
+ - Write the final spec to \`.swarm/spec.md\`.
76186
76206
  - Exit when reviewer signs off (or user explicitly accepts remaining disagreements).
76187
76207
 
76188
76208
  **Phase 6: QA GATE SELECTION (architect, dialogue only).**
@@ -76254,7 +76274,7 @@ Activates when: user asks to "specify", "define requirements", "write a spec", o
76254
76274
  1b. Run CODEBASE REALITY CHECK for any codebase references mentioned by the user or implied by the feature. Skip if work is purely greenfield (no existing codebase to check). Report discrepancies before proceeding to explorer.
76255
76275
  2. Delegate to \`{{AGENT_PREFIX}}explorer\` to scan the codebase for relevant context (existing patterns, related code, affected areas).
76256
76276
  3. Delegate to \`{{AGENT_PREFIX}}sme\` for domain research on the feature area to surface known constraints, best practices, and integration concerns.
76257
- 4. Delegate substantial spec drafting to \`{{AGENT_PREFIX}}spec_writer\`. Include the user requirements, explorer findings, SME constraints, and these required contents:
76277
+ 4. Generate \`.swarm/spec.md\` capturing:
76258
76278
  - First line must be: \`# Specification: <feature-name>\`
76259
76279
  - Feature description: WHAT users need and WHY — never HOW to implement
76260
76280
  - User scenarios with acceptance criteria (Given/When/Then format)
@@ -76263,7 +76283,7 @@ Activates when: user asks to "specify", "define requirements", "write a spec", o
76263
76283
  - Key entities if data is involved (no schema or field definitions — entity names only)
76264
76284
  - Edge cases and known failure modes
76265
76285
  - \`[NEEDS CLARIFICATION]\` markers (max 3) for items where uncertainty could change scope, security, or core behavior; prefer informed defaults over asking
76266
- 5. Require \`{{AGENT_PREFIX}}spec_writer\` to write the spec via \`spec_write\`, then read back and lint \`.swarm/spec.md\`.
76286
+ 5. Write the spec to \`.swarm/spec.md\`.
76267
76287
  5b. **QA GATE SELECTION (dialogue only).**
76268
76288
  {{QA_GATE_DIALOGUE_SPECIFY}}
76269
76289
 
@@ -79466,24 +79486,8 @@ function createSwarmAgents(swarmId, swarmConfig, isDefault, pluginConfig, projec
79466
79486
  const swarmIdentity = isDefault ? "default" : swarmId;
79467
79487
  const agentPrefix = prefix;
79468
79488
  architect.config.prompt = architect.config.prompt?.replace(/\{\{SWARM_ID\}\}/g, swarmIdentity).replace(/\{\{AGENT_PREFIX\}\}/g, agentPrefix).replace(/\{\{QA_RETRY_LIMIT\}\}/g, String(qaRetryLimit)).replace(/\{\{PROJECT_LANGUAGE\}\}/g, projectContext.PROJECT_LANGUAGE).replace(/\{\{PROJECT_FRAMEWORK\}\}/g, projectContext.PROJECT_FRAMEWORK).replace(/\{\{BUILD_CMD\}\}/g, projectContext.BUILD_CMD).replace(/\{\{TEST_CMD\}\}/g, projectContext.TEST_CMD).replace(/\{\{LINT_CMD\}\}/g, projectContext.LINT_CMD).replace(/\{\{ENTRY_POINTS\}\}/g, projectContext.ENTRY_POINTS).replace(/\{\{CODER_CONSTRAINTS\}\}/g, projectContext.CODER_CONSTRAINTS).replace(/\{\{TEST_CONSTRAINTS\}\}/g, projectContext.TEST_CONSTRAINTS).replace(/\{\{REVIEWER_CHECKLIST\}\}/g, projectContext.REVIEWER_CHECKLIST).replace(/\{\{PROJECT_CONTEXT_SECONDARY_LANGUAGES\}\}/g, projectContext.PROJECT_CONTEXT_SECONDARY_LANGUAGES);
79469
- const skillImproverEnabled = !isAgentDisabled("skill_improver", swarmAgents, swarmPrefix);
79470
- const specWriterEnabled = !isAgentDisabled("spec_writer", swarmAgents, swarmPrefix);
79471
- if (!skillImproverEnabled) {
79472
- architect.config.prompt = architect.config.prompt?.replace(`, ${agentPrefix}skill_improver`, "").replace(`
79473
- ${agentPrefix}skill_improver - Low-frequency skill / knowledge / prompt improvement adviser`, "").replace(/\n## SKILL IMPROVER[\s\S]*?(?=\n\n## SPEC WRITER)/, "");
79474
- }
79475
- if (!specWriterEnabled) {
79476
- const escapedAgentPrefix = agentPrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
79477
- architect.config.prompt = architect.config.prompt?.replace(`, ${agentPrefix}spec_writer`, "").replace(`
79478
- ${agentPrefix}spec_writer - .swarm/spec.md authoring via spec_write`, "").replace(/\n## SPEC WRITER[\s\S]*?(?=\n\n### ANTI-RATIONALIZATION)/, "").replace(new RegExp(`- Delegate substantial spec drafting to \`${escapedAgentPrefix}spec_writer\`[^\\n]*\\n`, "g"), "- spec_writer is disabled. Ask the user to enable the spec_writer agent before creating or revising `.swarm/spec.md`.\n").replace(new RegExp(`4\\. Delegate substantial spec drafting to \`${escapedAgentPrefix}spec_writer\`[^\\n]*`), "4. spec_writer is disabled. Ask the user to enable the spec_writer agent before creating or revising `.swarm/spec.md`.").replace(new RegExp(`5\\. Require \`${escapedAgentPrefix}spec_writer\` to write the spec via \`spec_write\`, then read back and lint \`\\.swarm/spec\\.md\`\\.`), "5. Do not continue SPECIFY until spec_writer is available.").replace(new RegExp(`- Read back and lint the final spec after \`${escapedAgentPrefix}spec_writer\` writes it\\.`), "- Do not continue BRAINSTORM spec writing until spec_writer is available.");
79479
- }
79480
79489
  if (!isDefault) {
79481
79490
  architect.description = `[${swarmName}] ${architect.description}`;
79482
- const optionalAgentLines = [
79483
- skillImproverEnabled ? `- @${swarmId}_skill_improver (not @skill_improver)` : undefined,
79484
- specWriterEnabled ? `- @${swarmId}_spec_writer (not @spec_writer)` : undefined
79485
- ].filter((line) => Boolean(line)).join(`
79486
- `);
79487
79491
  const swarmHeader = `## ⚠️ YOU ARE THE ${swarmName.toUpperCase()} SWARM ARCHITECT
79488
79492
 
79489
79493
  Your swarm ID is "${swarmId}". ALL your agents have the "${swarmId}_" prefix:
@@ -79491,8 +79495,8 @@ Your swarm ID is "${swarmId}". ALL your agents have the "${swarmId}_" prefix:
79491
79495
  - @${swarmId}_coder (not @coder)
79492
79496
  - @${swarmId}_sme (not @sme)
79493
79497
  - @${swarmId}_reviewer (not @reviewer)
79494
- ${optionalAgentLines ? `${optionalAgentLines}
79495
- ` : ""}- etc.
79498
+ - @${swarmId}_spec_writer (not @spec_writer)
79499
+ - etc.
79496
79500
 
79497
79501
  CRITICAL: Agents without the "${swarmId}_" prefix DO NOT EXIST or belong to a DIFFERENT swarm.
79498
79502
  If you call @coder instead of @${swarmId}_coder, the call will FAIL or go to the wrong swarm.
@@ -1,4 +1,4 @@
1
- export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'plan_md_write_failed' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
1
+ export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'gate_parse_error' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'plan_md_write_failed' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
2
2
  export type TelemetryListener = (event: TelemetryEvent, data: Record<string, unknown>) => void;
3
3
  /** @internal - For testing only */
4
4
  export declare function resetTelemetryForTesting(): void;
@@ -39,6 +39,7 @@ export declare const telemetry: {
39
39
  delegationEnd(sessionId: string, agentName: string, taskId: string, result: string): void;
40
40
  taskStateChanged(sessionId: string, taskId: string, newState: string, oldState?: string): void;
41
41
  gatePassed(sessionId: string, gate: string, taskId: string): void;
42
+ gateParseError(taskId: string, error: Error): void;
42
43
  gateFailed(sessionId: string, gate: string, taskId: string, reason: string): void;
43
44
  phaseChanged(sessionId: string, oldPhase: number, newPhase: number): void;
44
45
  budgetUpdated(sessionId: string, budgetPct: number, agentName: string): void;
@@ -23,6 +23,7 @@ export interface TestRunnerArgs {
23
23
  files?: string[];
24
24
  coverage?: boolean;
25
25
  timeout_ms?: number;
26
+ allow_full_suite?: boolean;
26
27
  }
27
28
  export type RegressionOutcome = 'pass' | 'skip' | 'regression' | 'scope_exceeded' | 'error';
28
29
  export interface TestTotals {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.29.1",
3
+ "version": "7.29.3",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",