opencode-swarm 6.39.0 → 6.40.1

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -27,7 +27,7 @@ Most AI coding tools let one model write code and ask that same model whether th
27
27
  ### Key Features
28
28
 
29
29
  - 🏗️ **11 specialized agents** — architect, coder, reviewer, test engineer, critic, critic_sounding_board, critic_drift_verifier, explorer, SME, docs, designer
30
- - 🔒 **Gated pipeline** — code never ships without reviewer + test engineer approval
30
+ - 🔒 **Gated pipeline** — code never ships without reviewer + test engineer approval (bypassed in turbo mode)
31
31
  - 🔄 **Phase completion gates** — completion-verify and drift verifier gates enforced before phase completion (bypassed in turbo mode)
32
32
  - 🔁 **Resumable sessions** — all state saved to `.swarm/`; pick up any project any day
33
33
  - 🌐 **11 languages** — TypeScript, Python, Go, Rust, Java, Kotlin, C#, C/C++, Swift, Dart, Ruby
package/dist/cli/index.js CHANGED
@@ -5,25 +5,43 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
8
13
  var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
9
21
  target = mod != null ? __create(__getProtoOf(mod)) : {};
10
22
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
23
  for (let key of __getOwnPropNames(mod))
12
24
  if (!__hasOwnProp.call(to, key))
13
25
  __defProp(to, key, {
14
- get: () => mod[key],
26
+ get: __accessProp.bind(mod, key),
15
27
  enumerable: true
16
28
  });
29
+ if (canCache)
30
+ cache.set(mod, to);
17
31
  return to;
18
32
  };
19
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __returnValue = (v) => v;
35
+ function __exportSetter(name, newValue) {
36
+ this[name] = __returnValue.bind(null, newValue);
37
+ }
20
38
  var __export = (target, all) => {
21
39
  for (var name in all)
22
40
  __defProp(target, name, {
23
41
  get: all[name],
24
42
  enumerable: true,
25
43
  configurable: true,
26
- set: (newValue) => all[name] = () => newValue
44
+ set: __exportSetter.bind(all, name)
27
45
  });
28
46
  };
29
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -14572,7 +14590,8 @@ var init_plan_schema = __esm(() => {
14572
14590
  id: exports_external.number().int().min(1),
14573
14591
  name: exports_external.string().min(1),
14574
14592
  status: PhaseStatusSchema.default("pending"),
14575
- tasks: exports_external.array(TaskSchema).default([])
14593
+ tasks: exports_external.array(TaskSchema).default([]),
14594
+ required_agents: exports_external.array(exports_external.string()).optional()
14576
14595
  });
14577
14596
  PlanSchema = exports_external.object({
14578
14597
  schema_version: exports_external.literal("1.0.0"),
@@ -17301,8 +17320,8 @@ function getTaskBlockers(task, summary, status) {
17301
17320
  }
17302
17321
  return blockers;
17303
17322
  }
17304
- async function buildTaskSummary(task, taskId) {
17305
- const result = await loadEvidence(".", taskId);
17323
+ async function buildTaskSummary(directory, task, taskId) {
17324
+ const result = await loadEvidence(directory, taskId);
17306
17325
  const bundle = result.status === "found" ? result.bundle : null;
17307
17326
  const phase = task?.phase ?? 0;
17308
17327
  const status = getTaskStatus(task, bundle);
@@ -17331,18 +17350,18 @@ async function buildTaskSummary(task, taskId) {
17331
17350
  lastEvidenceTimestamp: lastTimestamp
17332
17351
  };
17333
17352
  }
17334
- async function buildPhaseSummary(phase) {
17335
- const taskIds = await listEvidenceTaskIds(".");
17353
+ async function buildPhaseSummary(directory, phase) {
17354
+ const taskIds = await listEvidenceTaskIds(directory);
17336
17355
  const phaseTaskIds = new Set(phase.tasks.map((t) => t.id));
17337
17356
  const taskSummaries = [];
17338
17357
  const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
17339
17358
  for (const task of phase.tasks) {
17340
- const summary = await buildTaskSummary(task, task.id);
17359
+ const summary = await buildTaskSummary(directory, task, task.id);
17341
17360
  taskSummaries.push(summary);
17342
17361
  }
17343
17362
  const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
17344
17363
  for (const taskId of extraTaskIds) {
17345
- const summary = await buildTaskSummary(undefined, taskId);
17364
+ const summary = await buildTaskSummary(directory, undefined, taskId);
17346
17365
  if (summary.phase === phase.id) {
17347
17366
  taskSummaries.push(summary);
17348
17367
  }
@@ -17443,7 +17462,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
17443
17462
  let totalTasks = 0;
17444
17463
  let completedTasks = 0;
17445
17464
  for (const phase of phasesToProcess) {
17446
- const summary = await buildPhaseSummary(phase);
17465
+ const summary = await buildPhaseSummary(directory, phase);
17447
17466
  phaseSummaries.push(summary);
17448
17467
  totalTasks += summary.totalTasks;
17449
17468
  completedTasks += summary.completedTasks;
@@ -18161,8 +18180,8 @@ var PlanCursorConfigSchema = exports_external.object({
18161
18180
  });
18162
18181
  var CheckpointConfigSchema = exports_external.object({
18163
18182
  enabled: exports_external.boolean().default(true),
18164
- auto_checkpoint_threshold: exports_external.number().min(1).max(20).default(3)
18165
- });
18183
+ auto_checkpoint_threshold: exports_external.number().int().min(1).max(20).default(3)
18184
+ }).strict();
18166
18185
  var AutomationModeSchema = exports_external.enum(["manual", "hybrid", "auto"]);
18167
18186
  var AutomationCapabilitiesSchema = exports_external.object({
18168
18187
  plan_sync: exports_external.boolean().default(true),
@@ -18282,7 +18301,8 @@ var PluginConfigSchema = exports_external.object({
18282
18301
  block_on_threshold: exports_external.boolean().default(false).describe("If true, block phase completion when threshold exceeded. Default: advisory only.")
18283
18302
  }).optional(),
18284
18303
  incremental_verify: IncrementalVerifyConfigSchema.optional(),
18285
- compaction_service: CompactionConfigSchema.optional()
18304
+ compaction_service: CompactionConfigSchema.optional(),
18305
+ turbo_mode: exports_external.boolean().default(false).optional()
18286
18306
  });
18287
18307
 
18288
18308
  // src/config/loader.ts
@@ -18385,6 +18405,15 @@ function loadPluginConfig(directory) {
18385
18405
  }
18386
18406
  return result.data;
18387
18407
  }
18408
+ function loadPluginConfigWithMeta(directory) {
18409
+ const userConfigPath = path.join(getUserConfigDir(), "opencode", CONFIG_FILENAME);
18410
+ const projectConfigPath = path.join(directory, ".opencode", CONFIG_FILENAME);
18411
+ const userResult = loadRawConfigFromPath(userConfigPath);
18412
+ const projectResult = loadRawConfigFromPath(projectConfigPath);
18413
+ const loadedFromFile = userResult.fileExisted || projectResult.fileExisted;
18414
+ const config2 = loadPluginConfig(directory);
18415
+ return { config: config2, loadedFromFile };
18416
+ }
18388
18417
 
18389
18418
  // src/commands/archive.ts
18390
18419
  init_manager();
@@ -18807,6 +18836,9 @@ async function handleBenchmarkCommand(directory, args) {
18807
18836
  `);
18808
18837
  }
18809
18838
 
18839
+ // src/commands/checkpoint.ts
18840
+ init_zod();
18841
+
18810
18842
  // src/tools/checkpoint.ts
18811
18843
  import { spawnSync } from "child_process";
18812
18844
  import * as fs3 from "fs";
@@ -31132,6 +31164,10 @@ function tool(input) {
31132
31164
  return input;
31133
31165
  }
31134
31166
  tool.schema = exports_external2;
31167
+
31168
+ // src/config/index.ts
31169
+ init_evidence_schema();
31170
+ init_plan_schema();
31135
31171
  // src/tools/create-tool.ts
31136
31172
  function createSwarmTool(opts) {
31137
31173
  return tool({
@@ -31256,6 +31292,11 @@ function isGitRepo() {
31256
31292
  }
31257
31293
  function handleSave(label, directory) {
31258
31294
  try {
31295
+ let maxCheckpoints = 20;
31296
+ try {
31297
+ const { config: config3 } = loadPluginConfigWithMeta(directory);
31298
+ maxCheckpoints = config3.checkpoint?.auto_checkpoint_threshold ?? maxCheckpoints;
31299
+ } catch {}
31259
31300
  const log2 = readCheckpointLog(directory);
31260
31301
  const existingCheckpoint = log2.checkpoints.find((c) => c.label === label);
31261
31302
  if (existingCheckpoint) {
@@ -31375,7 +31416,7 @@ var checkpoint = createSwarmTool({
31375
31416
  let label;
31376
31417
  try {
31377
31418
  action = String(args.action);
31378
- label = args.label !== undefined ? String(args.label) : undefined;
31419
+ label = args.label !== undefined && args.label !== null ? String(args.label) : undefined;
31379
31420
  } catch {
31380
31421
  return JSON.stringify({
31381
31422
  action: "unknown",
@@ -31428,6 +31469,22 @@ var checkpoint = createSwarmTool({
31428
31469
  });
31429
31470
 
31430
31471
  // src/commands/checkpoint.ts
31472
+ var CheckpointResultSchema = exports_external.object({
31473
+ action: exports_external.string().optional(),
31474
+ success: exports_external.boolean(),
31475
+ error: exports_external.string().optional(),
31476
+ checkpoints: exports_external.array(exports_external.unknown()).optional()
31477
+ }).passthrough();
31478
+ function safeParseResult(result) {
31479
+ const parsed = CheckpointResultSchema.safeParse(JSON.parse(result));
31480
+ if (!parsed.success) {
31481
+ return {
31482
+ success: false,
31483
+ error: `Invalid response: ${parsed.error.message}`
31484
+ };
31485
+ }
31486
+ return parsed.data;
31487
+ }
31431
31488
  async function handleCheckpointCommand(directory, args) {
31432
31489
  const subcommand = args[0] || "list";
31433
31490
  const label = args[1];
@@ -31450,7 +31507,7 @@ async function handleSave2(directory, label) {
31450
31507
  const result = await checkpoint.execute({ action: "save", label }, {
31451
31508
  directory
31452
31509
  });
31453
- const parsed = JSON.parse(result);
31510
+ const parsed = safeParseResult(result);
31454
31511
  if (parsed.success) {
31455
31512
  return `\u2713 Checkpoint saved: "${label}"`;
31456
31513
  } else {
@@ -31469,7 +31526,7 @@ async function handleRestore2(directory, label) {
31469
31526
  const result = await checkpoint.execute({ action: "restore", label }, {
31470
31527
  directory
31471
31528
  });
31472
- const parsed = JSON.parse(result);
31529
+ const parsed = safeParseResult(result);
31473
31530
  if (parsed.success) {
31474
31531
  return `\u2713 Restored to checkpoint: "${label}"`;
31475
31532
  } else {
@@ -31488,7 +31545,7 @@ async function handleDelete2(directory, label) {
31488
31545
  const result = await checkpoint.execute({ action: "delete", label }, {
31489
31546
  directory
31490
31547
  });
31491
- const parsed = JSON.parse(result);
31548
+ const parsed = safeParseResult(result);
31492
31549
  if (parsed.success) {
31493
31550
  return `\u2713 Checkpoint deleted: "${label}"`;
31494
31551
  } else {
@@ -31504,7 +31561,7 @@ async function handleList2(directory) {
31504
31561
  const result = await checkpoint.execute({ action: "list" }, {
31505
31562
  directory
31506
31563
  });
31507
- const parsed = JSON.parse(result);
31564
+ const parsed = safeParseResult(result);
31508
31565
  if (!parsed.success) {
31509
31566
  return `Error: ${parsed.error || "Failed to list checkpoints"}`;
31510
31567
  }
@@ -34202,7 +34259,8 @@ async function extractFromLegacy(directory) {
34202
34259
  mappedStatus = "complete";
34203
34260
  else if (status === "IN PROGRESS")
34204
34261
  mappedStatus = "in_progress";
34205
- const headerLineIndex = lines.indexOf(match[0]);
34262
+ const headerLineIndex = planContent.substring(0, match.index).split(`
34263
+ `).length - 1;
34206
34264
  let completed = 0;
34207
34265
  let total = 0;
34208
34266
  if (headerLineIndex !== -1) {
@@ -34597,9 +34655,9 @@ async function getPlanData(directory, phaseArg) {
34597
34655
  return {
34598
34656
  hasPlan: true,
34599
34657
  fullMarkdown,
34600
- requestedPhase: NaN,
34658
+ requestedPhase: null,
34601
34659
  phaseMarkdown: null,
34602
- errorMessage: null,
34660
+ errorMessage: `Invalid phase number: "${phaseArg}"`,
34603
34661
  isLegacy: false
34604
34662
  };
34605
34663
  }
@@ -34650,9 +34708,9 @@ async function getPlanData(directory, phaseArg) {
34650
34708
  return {
34651
34709
  hasPlan: true,
34652
34710
  fullMarkdown: planContent,
34653
- requestedPhase: NaN,
34711
+ requestedPhase: null,
34654
34712
  phaseMarkdown: null,
34655
- errorMessage: null,
34713
+ errorMessage: `Invalid phase number: "${phaseArg}"`,
34656
34714
  isLegacy: true
34657
34715
  };
34658
34716
  }
@@ -35591,6 +35649,59 @@ LANGUAGE_REGISTRY.register({
35591
35649
  ]
35592
35650
  }
35593
35651
  });
35652
+ LANGUAGE_REGISTRY.register({
35653
+ id: "php",
35654
+ displayName: "PHP",
35655
+ tier: 3,
35656
+ extensions: [".php", ".phtml"],
35657
+ treeSitter: { grammarId: "php", wasmFile: "tree-sitter-php.wasm" },
35658
+ build: {
35659
+ detectFiles: ["composer.json"],
35660
+ commands: []
35661
+ },
35662
+ test: {
35663
+ detectFiles: ["phpunit.xml", "phpunit.xml.dist"],
35664
+ frameworks: [
35665
+ {
35666
+ name: "PHPUnit",
35667
+ detect: "phpunit.xml",
35668
+ cmd: "vendor/bin/phpunit",
35669
+ priority: 1
35670
+ }
35671
+ ]
35672
+ },
35673
+ lint: {
35674
+ detectFiles: [".php-cs-fixer.php", "phpcs.xml"],
35675
+ linters: [
35676
+ {
35677
+ name: "PHP-CS-Fixer",
35678
+ detect: ".php-cs-fixer.php",
35679
+ cmd: "vendor/bin/php-cs-fixer fix --dry-run --diff",
35680
+ priority: 1
35681
+ }
35682
+ ]
35683
+ },
35684
+ audit: {
35685
+ detectFiles: ["composer.lock"],
35686
+ command: "composer audit --format=json",
35687
+ outputFormat: "json"
35688
+ },
35689
+ sast: { nativeRuleSet: "php", semgrepSupport: "ga" },
35690
+ prompts: {
35691
+ coderConstraints: [
35692
+ "Follow PSR-12 coding standards",
35693
+ "Use strict types declaration: declare(strict_types=1)",
35694
+ "Prefer type hints and return type declarations on all functions",
35695
+ "Use dependency injection over static methods and singletons"
35696
+ ],
35697
+ reviewerChecklist: [
35698
+ "Verify no user input reaches SQL queries without parameterised binding",
35699
+ "Check for XSS \u2014 all output must be escaped with htmlspecialchars()",
35700
+ "Confirm no eval(), exec(), or shell_exec() with user-controlled input",
35701
+ "Validate proper error handling \u2014 no bare catch blocks that swallow errors"
35702
+ ]
35703
+ }
35704
+ });
35594
35705
 
35595
35706
  // src/lang/detector.ts
35596
35707
  async function detectProjectLanguages(projectDir) {
@@ -36174,7 +36285,7 @@ async function detectAvailableLinter(directory) {
36174
36285
  async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36175
36286
  const DETECT_TIMEOUT = 2000;
36176
36287
  try {
36177
- const biomeProc = Bun.spawn(["npx", "biome", "--version"], {
36288
+ const biomeProc = Bun.spawn([biomeBin, "--version"], {
36178
36289
  stdout: "pipe",
36179
36290
  stderr: "pipe"
36180
36291
  });
@@ -36188,7 +36299,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
36188
36299
  }
36189
36300
  } catch {}
36190
36301
  try {
36191
- const eslintProc = Bun.spawn(["npx", "eslint", "--version"], {
36302
+ const eslintProc = Bun.spawn([eslintBin, "--version"], {
36192
36303
  stdout: "pipe",
36193
36304
  stderr: "pipe"
36194
36305
  });
@@ -38205,12 +38316,13 @@ async function runLintCheck(dir, linter, timeoutMs) {
38205
38316
  const startTime = Date.now();
38206
38317
  try {
38207
38318
  const lintPromise = runLint(linter, "check", dir);
38319
+ let timeoutId;
38208
38320
  const timeoutPromise = new Promise((_, reject) => {
38209
- setTimeout(() => {
38321
+ timeoutId = setTimeout(() => {
38210
38322
  reject(new Error(`Lint check timed out after ${timeoutMs}ms`));
38211
38323
  }, timeoutMs);
38212
38324
  });
38213
- const result = await Promise.race([lintPromise, timeoutPromise]);
38325
+ const result = await Promise.race([lintPromise, timeoutPromise]).finally(() => clearTimeout(timeoutId));
38214
38326
  if (!result.success) {
38215
38327
  return {
38216
38328
  type: "lint",
@@ -39720,12 +39832,32 @@ function makeInitialState() {
39720
39832
  lastSnapshotAt: null
39721
39833
  };
39722
39834
  }
39723
- var state = makeInitialState();
39724
- function getCompactionMetrics() {
39725
- return {
39726
- compactionCount: state.observationCount + state.reflectionCount + state.emergencyCount,
39727
- lastSnapshotAt: state.lastSnapshotAt
39728
- };
39835
+ var sessionStates = new Map;
39836
+ function getSessionState(sessionId) {
39837
+ let state = sessionStates.get(sessionId);
39838
+ if (!state) {
39839
+ state = makeInitialState();
39840
+ sessionStates.set(sessionId, state);
39841
+ }
39842
+ return state;
39843
+ }
39844
+ function getCompactionMetrics(sessionId) {
39845
+ if (sessionId) {
39846
+ const state = getSessionState(sessionId);
39847
+ return {
39848
+ compactionCount: state.observationCount + state.reflectionCount + state.emergencyCount,
39849
+ lastSnapshotAt: state.lastSnapshotAt
39850
+ };
39851
+ }
39852
+ let total = 0;
39853
+ let lastSnapshot = null;
39854
+ for (const state of sessionStates.values()) {
39855
+ total += state.observationCount + state.reflectionCount + state.emergencyCount;
39856
+ if (state.lastSnapshotAt && (!lastSnapshot || state.lastSnapshotAt > lastSnapshot)) {
39857
+ lastSnapshot = state.lastSnapshotAt;
39858
+ }
39859
+ }
39860
+ return { compactionCount: total, lastSnapshotAt: lastSnapshot };
39729
39861
  }
39730
39862
 
39731
39863
  // src/services/context-budget-service.ts
@@ -39888,6 +40020,7 @@ async function handleTurboCommand(_directory, args, sessionID) {
39888
40020
  }
39889
40021
 
39890
40022
  // src/tools/write-retro.ts
40023
+ init_evidence_schema();
39891
40024
  init_manager();
39892
40025
  async function executeWriteRetro(args, directory) {
39893
40026
  const phase = args.phase;
@@ -40121,8 +40254,9 @@ async function executeWriteRetro(args, directory) {
40121
40254
  };
40122
40255
  const taxonomy = [];
40123
40256
  try {
40124
- for (const taskSuffix of ["1", "2", "3", "4", "5"]) {
40125
- const phaseTaskId = `${phase}.${taskSuffix}`;
40257
+ const allTaskIds = await listEvidenceTaskIds(directory);
40258
+ const phaseTaskIds = allTaskIds.filter((id) => id.startsWith(`${phase}.`));
40259
+ for (const phaseTaskId of phaseTaskIds) {
40126
40260
  const result = await loadEvidence(directory, phaseTaskId);
40127
40261
  if (result.status !== "found")
40128
40262
  continue;
@@ -40156,6 +40290,13 @@ async function executeWriteRetro(args, directory) {
40156
40290
  }
40157
40291
  } catch {}
40158
40292
  retroEntry.error_taxonomy = [...new Set(taxonomy)];
40293
+ const validationResult = RetrospectiveEvidenceSchema.safeParse(retroEntry);
40294
+ if (!validationResult.success) {
40295
+ return JSON.stringify({
40296
+ success: false,
40297
+ error: `Retrospective entry failed validation: ${validationResult.error.message}`
40298
+ }, null, 2);
40299
+ }
40159
40300
  try {
40160
40301
  await saveEvidence(directory, taskId, retroEntry);
40161
40302
  return JSON.stringify({
@@ -40220,7 +40361,7 @@ var write_retro = createSwarmTool({
40220
40361
  }
40221
40362
  });
40222
40363
 
40223
- // src/commands/write_retro.ts
40364
+ // src/commands/write-retro.ts
40224
40365
  async function handleWriteRetroCommand(directory, args) {
40225
40366
  if (args.length === 0 || !args[0] || args[0].trim() === "") {
40226
40367
  return `## Usage: /swarm write-retro <json>
@@ -29,7 +29,7 @@ export { handleSpecifyCommand } from './specify';
29
29
  export { handleStatusCommand } from './status';
30
30
  export { handleSyncPlanCommand } from './sync-plan';
31
31
  export { handleTurboCommand } from './turbo';
32
- export { handleWriteRetroCommand } from './write_retro';
32
+ export { handleWriteRetroCommand } from './write-retro';
33
33
  /**
34
34
  * Creates a command.execute.before handler for /swarm commands.
35
35
  * Uses factory pattern to close over directory and agents.
@@ -91,6 +91,7 @@ export declare const PhaseSchema: z.ZodObject<{
91
91
  evidence_path: z.ZodOptional<z.ZodString>;
92
92
  blocked_reason: z.ZodOptional<z.ZodString>;
93
93
  }, z.core.$strip>>>;
94
+ required_agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
94
95
  }, z.core.$strip>;
95
96
  export type Phase = z.infer<typeof PhaseSchema>;
96
97
  export declare const PlanSchema: z.ZodObject<{
@@ -129,6 +130,7 @@ export declare const PlanSchema: z.ZodObject<{
129
130
  evidence_path: z.ZodOptional<z.ZodString>;
130
131
  blocked_reason: z.ZodOptional<z.ZodString>;
131
132
  }, z.core.$strip>>>;
133
+ required_agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
132
134
  }, z.core.$strip>>;
133
135
  migration_status: z.ZodOptional<z.ZodEnum<{
134
136
  native: "native";
@@ -375,7 +375,7 @@ export type PlanCursorConfig = z.infer<typeof PlanCursorConfigSchema>;
375
375
  export declare const CheckpointConfigSchema: z.ZodObject<{
376
376
  enabled: z.ZodDefault<z.ZodBoolean>;
377
377
  auto_checkpoint_threshold: z.ZodDefault<z.ZodNumber>;
378
- }, z.core.$strip>;
378
+ }, z.core.$strict>;
379
379
  export type CheckpointConfig = z.infer<typeof CheckpointConfigSchema>;
380
380
  export declare const AutomationModeSchema: z.ZodEnum<{
381
381
  auto: "auto";
@@ -699,7 +699,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
699
699
  checkpoint: z.ZodOptional<z.ZodObject<{
700
700
  enabled: z.ZodDefault<z.ZodBoolean>;
701
701
  auto_checkpoint_threshold: z.ZodDefault<z.ZodNumber>;
702
- }, z.core.$strip>>;
702
+ }, z.core.$strict>>;
703
703
  automation: z.ZodOptional<z.ZodType<{
704
704
  mode: "auto" | "manual" | "hybrid";
705
705
  capabilities: {
@@ -785,6 +785,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
785
785
  emergencyThreshold: z.ZodDefault<z.ZodNumber>;
786
786
  preserveLastNTurns: z.ZodDefault<z.ZodNumber>;
787
787
  }, z.core.$strip>>;
788
+ turbo_mode: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
788
789
  }, z.core.$strip>;
789
790
  export type PluginConfig = z.infer<typeof PluginConfigSchema>;
790
791
  export type { AgentName, PipelineAgentName, QAAgentName, } from './constants';