opencode-swarm 7.23.1 → 7.24.0

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.23.1",
37
+ version: "7.24.0",
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",
@@ -34292,6 +34292,14 @@ function gitExec(args) {
34292
34292
  }
34293
34293
  return result.stdout;
34294
34294
  }
34295
+ function appendRetentionEvent(directory, event) {
34296
+ try {
34297
+ const eventsPath = path9.join(directory, ".swarm", "events.jsonl");
34298
+ const line = `${JSON.stringify({ ...event, timestamp: new Date().toISOString() })}
34299
+ `;
34300
+ fs6.appendFileSync(eventsPath, line);
34301
+ } catch {}
34302
+ }
34295
34303
  function getCurrentSha() {
34296
34304
  const output = gitExec(["rev-parse", "HEAD"]);
34297
34305
  return output.trim();
@@ -34343,6 +34351,17 @@ function handleSave(label, directory) {
34343
34351
  sha: newSha,
34344
34352
  timestamp
34345
34353
  });
34354
+ if (log2.checkpoints.length > maxCheckpoints) {
34355
+ const evicted = log2.checkpoints.splice(0, log2.checkpoints.length - maxCheckpoints);
34356
+ try {
34357
+ appendRetentionEvent(directory, {
34358
+ event: "checkpoint_retention_applied",
34359
+ evicted_labels: evicted.map((e) => e.label),
34360
+ evicted_count: evicted.length,
34361
+ remaining_count: log2.checkpoints.length
34362
+ });
34363
+ } catch {}
34364
+ }
34346
34365
  writeCheckpointLog(log2, directory);
34347
34366
  return JSON.stringify({
34348
34367
  action: "save",
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.23.1",
36
+ version: "7.24.0",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -41417,6 +41417,14 @@ function gitExec(args2) {
41417
41417
  }
41418
41418
  return result.stdout;
41419
41419
  }
41420
+ function appendRetentionEvent(directory, event) {
41421
+ try {
41422
+ const eventsPath = path14.join(directory, ".swarm", "events.jsonl");
41423
+ const line = `${JSON.stringify({ ...event, timestamp: new Date().toISOString() })}
41424
+ `;
41425
+ fs11.appendFileSync(eventsPath, line);
41426
+ } catch {}
41427
+ }
41420
41428
  function getCurrentSha() {
41421
41429
  const output = gitExec(["rev-parse", "HEAD"]);
41422
41430
  return output.trim();
@@ -41468,6 +41476,17 @@ function handleSave(label, directory) {
41468
41476
  sha: newSha,
41469
41477
  timestamp
41470
41478
  });
41479
+ if (log2.checkpoints.length > maxCheckpoints) {
41480
+ const evicted = log2.checkpoints.splice(0, log2.checkpoints.length - maxCheckpoints);
41481
+ try {
41482
+ appendRetentionEvent(directory, {
41483
+ event: "checkpoint_retention_applied",
41484
+ evicted_labels: evicted.map((e) => e.label),
41485
+ evicted_count: evicted.length,
41486
+ remaining_count: log2.checkpoints.length
41487
+ });
41488
+ } catch {}
41489
+ }
41471
41490
  writeCheckpointLog(log2, directory);
41472
41491
  return JSON.stringify({
41473
41492
  action: "save",
@@ -62633,7 +62652,17 @@ If the user answered the gate question, immediately follow up with ONE more ques
62633
62652
  - locked: true
62634
62653
  - recorded_at: <ISO timestamp>
62635
62654
  \`\`\`
62636
- If the user accepts the default (1), skip writing this section entirely — serial execution is the default and needs no config.`;
62655
+ If the user accepts the default (1), skip writing this section entirely — serial execution is the default and needs no config.
62656
+
62657
+ After asking the parallelization question (regardless of whether the user chose serial or parallel), immediately follow up with ONE more question: "Commit frequency for completed tasks? (default: phase-level only; optional per-task checkpoint commit after each task completion)".
62658
+
62659
+ If the user chooses per-task commits, write this section to \`.swarm/context.md\`:
62660
+ \`\`\`
62661
+ ## Task Completion Commit Policy
62662
+ - commit_after_each_completed_task: true
62663
+ - recorded_at: <ISO timestamp>
62664
+ \`\`\`
62665
+ If the user keeps the default phase-level behavior, do not write this section.`;
62637
62666
  }
62638
62667
  function buildAvailableToolsList(council) {
62639
62668
  const tools = AGENT_TOOL_MAP.architect ?? [];
@@ -64122,7 +64151,10 @@ save_plan({
64122
64151
  After \`save_plan\` succeeds, read \`.swarm/context.md\`:
64123
64152
  - If a \`## Pending QA Gate Selection\` section exists: parse the gate values, call \`set_qa_gates\` with those flags, confirm with the user ("QA gates applied: <list>"), then remove the section from context.md.
64124
64153
  - If a \`## Pending Parallelization Config\` section also exists: parse the values and call \`save_plan\` again with \`execution_profile\` set to \`{ parallelization_enabled: <parsed>, max_concurrent_tasks: <parsed>, council_parallel: false, locked: true }\`. Then remove the section from context.md. If the plan already had \`execution_profile.locked: true\`, skip this step — the profile is already locked and immutable.
64154
+ - If a \`## Task Completion Commit Policy\` section exists: preserve it in \`.swarm/context.md\` (do NOT remove). This section is execution-time guidance for optional per-task checkpoint commits after \`update_task_status(status="completed")\`.
64125
64155
  - If no pending section exists: {{QA_GATE_DIALOGUE_PLAN}}
64156
+ - If a \`## Task Completion Commit Policy\` section already exists in context.md, honor it as execution-time guidance (do NOT remove).
64157
+ - If no \`## Task Completion Commit Policy\` section exists AND the \`{{QA_GATE_DIALOGUE_PLAN}}\` template was not rendered (pending sections were pre-written), ask the commit-frequency question now. Write the section to context.md if the user chooses per-task commits; skip if they keep the default phase-level behavior.
64126
64158
  <!-- BEHAVIORAL_GUIDANCE_START -->
64127
64159
  INLINE GATE SELECTION — no pending section found in context.md. You MUST ask now.
64128
64160
  ✗ "I'll call set_qa_gates with defaults and move on"
@@ -64407,7 +64439,14 @@ This step supplements (not replaces) the existing regression-sweep and test-drif
64407
64439
  Any blank "value: ___" field = gate was not run = task is NOT complete.
64408
64440
  Filling this checklist from memory ("I think I ran it") is INVALID. Each value must come from actual tool/agent output in this session.
64409
64441
 
64410
- 5o. Call update_task_status with status "completed", proceed to next task.
64442
+ 5p. Call update_task_status with status "completed".
64443
+ 5q. OPTIONAL TASK-COMPLETION COMMIT POLICY: read \`.swarm/context.md\`.
64444
+ - If \`## Task Completion Commit Policy\` contains \`commit_after_each_completed_task: true\`, immediately call:
64445
+ \`checkpoint save task-<task-id>-complete\`
64446
+ - If the section is absent or false, skip this step.
64447
+ - This optional commit policy NEVER bypasses PRE-COMMIT RULE checks above.
64448
+ - If checkpoint save fails with "duplicate label", the task was already checkpointed from a prior completion or retry. Silently skip — the existing checkpoint is valid.
64449
+ 5r. Proceed to next task.
64411
64450
 
64412
64451
  ## ⛔ RETROSPECTIVE GATE
64413
64452
 
@@ -83626,8 +83665,8 @@ ${formattedIndex}
83626
83665
  } else {
83627
83666
  if (existingContent.length > 0 && !existingContent.endsWith(`
83628
83667
  `)) {
83629
- updatedContent = existingContent + `
83630
- ` + newSection;
83668
+ updatedContent = `${existingContent}
83669
+ ${newSection}`;
83631
83670
  } else {
83632
83671
  updatedContent = existingContent + newSection;
83633
83672
  }
@@ -87109,7 +87148,7 @@ ${body2}`);
87109
87148
 
87110
87149
  // src/council/council-evidence-writer.ts
87111
87150
  import {
87112
- appendFileSync as appendFileSync11,
87151
+ appendFileSync as appendFileSync12,
87113
87152
  existsSync as existsSync53,
87114
87153
  mkdirSync as mkdirSync24,
87115
87154
  readFileSync as readFileSync44,
@@ -87193,7 +87232,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
87193
87232
  timestamp: synthesis.timestamp,
87194
87233
  vetoedBy: synthesis.vetoedBy
87195
87234
  });
87196
- appendFileSync11(join83(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
87235
+ appendFileSync12(join83(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
87197
87236
  `);
87198
87237
  } catch (auditError) {
87199
87238
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -104029,9 +104068,9 @@ function recoverTaskStateFromDelegations(taskId, directory) {
104029
104068
  try {
104030
104069
  const evidence = readTaskEvidenceRaw(directory, taskId);
104031
104070
  if (evidence && evidence.gates && Array.isArray(evidence.required_gates)) {
104032
- if (evidence.gates["reviewer"] != null)
104071
+ if (evidence.gates.reviewer != null)
104033
104072
  hasReviewer = true;
104034
- if (evidence.gates["test_engineer"] != null)
104073
+ if (evidence.gates.test_engineer != null)
104035
104074
  hasTestEngineer = true;
104036
104075
  }
104037
104076
  } catch {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.23.1",
3
+ "version": "7.24.0",
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",