opencode-swarm 7.23.0 → 7.23.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/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.
|
|
37
|
+
version: "7.23.1",
|
|
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",
|
|
@@ -43447,7 +43447,7 @@ var init_handoff_service = __esm(() => {
|
|
|
43447
43447
|
});
|
|
43448
43448
|
|
|
43449
43449
|
// src/session/snapshot-writer.ts
|
|
43450
|
-
import { mkdirSync as mkdirSync10, renameSync as renameSync6 } from "fs";
|
|
43450
|
+
import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync10, openSync as openSync3, renameSync as renameSync6 } from "fs";
|
|
43451
43451
|
import * as path27 from "path";
|
|
43452
43452
|
function serializeAgentSession(s) {
|
|
43453
43453
|
const gateLog = {};
|
|
@@ -43464,6 +43464,12 @@ function serializeAgentSession(s) {
|
|
|
43464
43464
|
const catastrophicPhaseWarnings = Array.from(s.catastrophicPhaseWarnings ?? new Set);
|
|
43465
43465
|
const phaseAgentsDispatched = Array.from(s.phaseAgentsDispatched ?? new Set);
|
|
43466
43466
|
const lastCompletedPhaseAgentsDispatched = Array.from(s.lastCompletedPhaseAgentsDispatched ?? new Set);
|
|
43467
|
+
const stageBCompletion = {};
|
|
43468
|
+
if (s.stageBCompletion) {
|
|
43469
|
+
for (const [taskId, agents] of s.stageBCompletion) {
|
|
43470
|
+
stageBCompletion[taskId] = Array.from(agents);
|
|
43471
|
+
}
|
|
43472
|
+
}
|
|
43467
43473
|
const windows = {};
|
|
43468
43474
|
const rawWindows = s.windows ?? {};
|
|
43469
43475
|
for (const [key, win] of Object.entries(rawWindows)) {
|
|
@@ -43520,7 +43526,8 @@ function serializeAgentSession(s) {
|
|
|
43520
43526
|
fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
|
|
43521
43527
|
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
43522
43528
|
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
43523
|
-
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
43529
|
+
sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
|
|
43530
|
+
...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
|
|
43524
43531
|
};
|
|
43525
43532
|
}
|
|
43526
43533
|
async function writeSnapshot(directory, state) {
|
|
@@ -43542,6 +43549,14 @@ async function writeSnapshot(directory, state) {
|
|
|
43542
43549
|
mkdirSync10(dir, { recursive: true });
|
|
43543
43550
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
43544
43551
|
await bunWrite(tempPath, content);
|
|
43552
|
+
try {
|
|
43553
|
+
const fd = openSync3(tempPath, "r+");
|
|
43554
|
+
try {
|
|
43555
|
+
fsyncSync2(fd);
|
|
43556
|
+
} finally {
|
|
43557
|
+
closeSync3(fd);
|
|
43558
|
+
}
|
|
43559
|
+
} catch {}
|
|
43545
43560
|
renameSync6(tempPath, resolvedPath);
|
|
43546
43561
|
} catch (error93) {
|
|
43547
43562
|
log("[snapshot-writer] write failed", {
|
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.
|
|
36
|
+
version: "7.23.1",
|
|
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",
|
|
@@ -52386,7 +52386,7 @@ var init_handoff_service = __esm(() => {
|
|
|
52386
52386
|
});
|
|
52387
52387
|
|
|
52388
52388
|
// src/session/snapshot-writer.ts
|
|
52389
|
-
import { mkdirSync as mkdirSync13, renameSync as renameSync9 } from "node:fs";
|
|
52389
|
+
import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync13, openSync as openSync3, renameSync as renameSync9 } from "node:fs";
|
|
52390
52390
|
import * as path33 from "node:path";
|
|
52391
52391
|
function serializeAgentSession(s) {
|
|
52392
52392
|
const gateLog = {};
|
|
@@ -52403,6 +52403,12 @@ function serializeAgentSession(s) {
|
|
|
52403
52403
|
const catastrophicPhaseWarnings = Array.from(s.catastrophicPhaseWarnings ?? new Set);
|
|
52404
52404
|
const phaseAgentsDispatched = Array.from(s.phaseAgentsDispatched ?? new Set);
|
|
52405
52405
|
const lastCompletedPhaseAgentsDispatched = Array.from(s.lastCompletedPhaseAgentsDispatched ?? new Set);
|
|
52406
|
+
const stageBCompletion = {};
|
|
52407
|
+
if (s.stageBCompletion) {
|
|
52408
|
+
for (const [taskId, agents] of s.stageBCompletion) {
|
|
52409
|
+
stageBCompletion[taskId] = Array.from(agents);
|
|
52410
|
+
}
|
|
52411
|
+
}
|
|
52406
52412
|
const windows = {};
|
|
52407
52413
|
const rawWindows = s.windows ?? {};
|
|
52408
52414
|
for (const [key, win] of Object.entries(rawWindows)) {
|
|
@@ -52459,7 +52465,8 @@ function serializeAgentSession(s) {
|
|
|
52459
52465
|
fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
|
|
52460
52466
|
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
52461
52467
|
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
52462
|
-
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
52468
|
+
sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
|
|
52469
|
+
...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
|
|
52463
52470
|
};
|
|
52464
52471
|
}
|
|
52465
52472
|
async function writeSnapshot(directory, state) {
|
|
@@ -52481,6 +52488,14 @@ async function writeSnapshot(directory, state) {
|
|
|
52481
52488
|
mkdirSync13(dir, { recursive: true });
|
|
52482
52489
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
52483
52490
|
await bunWrite(tempPath, content);
|
|
52491
|
+
try {
|
|
52492
|
+
const fd = openSync3(tempPath, "r+");
|
|
52493
|
+
try {
|
|
52494
|
+
fsyncSync2(fd);
|
|
52495
|
+
} finally {
|
|
52496
|
+
closeSync3(fd);
|
|
52497
|
+
}
|
|
52498
|
+
} catch {}
|
|
52484
52499
|
renameSync9(tempPath, resolvedPath);
|
|
52485
52500
|
} catch (error93) {
|
|
52486
52501
|
log("[snapshot-writer] write failed", {
|
|
@@ -85196,6 +85211,12 @@ function deserializeAgentSession(s) {
|
|
|
85196
85211
|
const catastrophicPhaseWarnings = new Set(s.catastrophicPhaseWarnings ?? []);
|
|
85197
85212
|
const phaseAgentsDispatched = new Set(s.phaseAgentsDispatched ?? []);
|
|
85198
85213
|
const lastCompletedPhaseAgentsDispatched = new Set(s.lastCompletedPhaseAgentsDispatched ?? []);
|
|
85214
|
+
const stageBCompletion = new Map;
|
|
85215
|
+
if (s.stageBCompletion) {
|
|
85216
|
+
for (const [taskId, agents] of Object.entries(s.stageBCompletion)) {
|
|
85217
|
+
stageBCompletion.set(taskId, new Set(agents));
|
|
85218
|
+
}
|
|
85219
|
+
}
|
|
85199
85220
|
const windows = {};
|
|
85200
85221
|
for (const [key, win] of Object.entries(s.windows ?? {})) {
|
|
85201
85222
|
windows[key] = {
|
|
@@ -85250,7 +85271,8 @@ function deserializeAgentSession(s) {
|
|
|
85250
85271
|
prmLastPatternDetected: null,
|
|
85251
85272
|
prmTrajectoryStep: 0,
|
|
85252
85273
|
prmHardStopPending: false,
|
|
85253
|
-
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
85274
|
+
sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
|
|
85275
|
+
stageBCompletion
|
|
85254
85276
|
};
|
|
85255
85277
|
}
|
|
85256
85278
|
async function readSnapshot(directory) {
|
|
@@ -103946,7 +103968,27 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
103946
103968
|
}
|
|
103947
103969
|
}
|
|
103948
103970
|
const currentStateStr = stateEntries.length > 0 ? stateEntries.join(", ") : "no active sessions";
|
|
103949
|
-
const
|
|
103971
|
+
const chainEntries = [];
|
|
103972
|
+
for (const [sessionId, chain] of swarmState.delegationChains) {
|
|
103973
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
103974
|
+
if (session && (session.currentTaskId === taskId || session.lastCoderDelegationTaskId === taskId)) {
|
|
103975
|
+
const targets = chain.map((d) => stripKnownSwarmPrefix(d.to));
|
|
103976
|
+
chainEntries.push(`${sessionId}: [${targets.join(", ")}]`);
|
|
103977
|
+
}
|
|
103978
|
+
}
|
|
103979
|
+
const chainSummary = chainEntries.length > 0 ? chainEntries.join("; ") : "no chains for this task";
|
|
103980
|
+
const rehydratedSessionCount = [
|
|
103981
|
+
...swarmState.agentSessions.values()
|
|
103982
|
+
].filter((s) => s.sessionRehydratedAt > 0).length;
|
|
103983
|
+
const finalReason = [
|
|
103984
|
+
`Task ${taskId} has not passed QA gates.`,
|
|
103985
|
+
` Session states: [${currentStateStr}].`,
|
|
103986
|
+
` Delegation chains: [${chainSummary}].`,
|
|
103987
|
+
` Evidence: [${evidenceIncompleteReason ?? "no evidence file found"}].`,
|
|
103988
|
+
` Rehydrated sessions: ${rehydratedSessionCount}.`,
|
|
103989
|
+
` Missing required state: tests_run or complete.`
|
|
103990
|
+
].join(`
|
|
103991
|
+
`);
|
|
103950
103992
|
telemetry.gateFailed("", "qa_gate", taskId, evidenceIncompleteReason ? `Missing gates: evidence incomplete` : `Missing state: tests_run or complete`);
|
|
103951
103993
|
return {
|
|
103952
103994
|
blocked: true,
|
|
@@ -103968,7 +104010,7 @@ async function checkReviewerGateWithScope(taskId, workingDirectory, sessionID) {
|
|
|
103968
104010
|
${scopeWarning}` : scopeWarning
|
|
103969
104011
|
};
|
|
103970
104012
|
}
|
|
103971
|
-
function recoverTaskStateFromDelegations(taskId) {
|
|
104013
|
+
function recoverTaskStateFromDelegations(taskId, directory) {
|
|
103972
104014
|
let hasReviewer = false;
|
|
103973
104015
|
let hasTestEngineer = false;
|
|
103974
104016
|
for (const [sessionId, chain] of swarmState.delegationChains) {
|
|
@@ -103983,8 +104025,24 @@ function recoverTaskStateFromDelegations(taskId) {
|
|
|
103983
104025
|
}
|
|
103984
104026
|
}
|
|
103985
104027
|
}
|
|
104028
|
+
if ((!hasReviewer || !hasTestEngineer) && directory) {
|
|
104029
|
+
try {
|
|
104030
|
+
const evidence = readTaskEvidenceRaw(directory, taskId);
|
|
104031
|
+
if (evidence && evidence.gates && Array.isArray(evidence.required_gates)) {
|
|
104032
|
+
if (evidence.gates["reviewer"] != null)
|
|
104033
|
+
hasReviewer = true;
|
|
104034
|
+
if (evidence.gates["test_engineer"] != null)
|
|
104035
|
+
hasTestEngineer = true;
|
|
104036
|
+
}
|
|
104037
|
+
} catch {}
|
|
104038
|
+
}
|
|
103986
104039
|
if (!hasReviewer && !hasTestEngineer)
|
|
103987
104040
|
return;
|
|
104041
|
+
if (swarmState.agentSessions.size === 0) {
|
|
104042
|
+
try {
|
|
104043
|
+
startAgentSession("recovery-session", "architect");
|
|
104044
|
+
} catch {}
|
|
104045
|
+
}
|
|
103988
104046
|
for (const [, session] of swarmState.agentSessions) {
|
|
103989
104047
|
if (!(session.taskWorkflowStates instanceof Map))
|
|
103990
104048
|
continue;
|
|
@@ -104128,7 +104186,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
104128
104186
|
} catch {}
|
|
104129
104187
|
}
|
|
104130
104188
|
if (args2.status === "completed") {
|
|
104131
|
-
recoverTaskStateFromDelegations(args2.task_id);
|
|
104189
|
+
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
104132
104190
|
let phaseRequiresReviewer = true;
|
|
104133
104191
|
try {
|
|
104134
104192
|
const planPath = path137.join(directory, ".swarm", "plan.json");
|
|
@@ -59,6 +59,8 @@ export interface SerializedAgentSession {
|
|
|
59
59
|
fullAutoLastQuestionHash?: string | null;
|
|
60
60
|
/** Timestamp when session was rehydrated from snapshot (0 if never rehydrated) */
|
|
61
61
|
sessionRehydratedAt?: number;
|
|
62
|
+
/** Stage B completion tracking: per-task set of completed Stage B agents. Optional for backward compat with old snapshots. */
|
|
63
|
+
stageBCompletion?: Record<string, string[]>;
|
|
62
64
|
}
|
|
63
65
|
/**
|
|
64
66
|
* Minimal interface for serialized InvocationWindow
|
|
@@ -71,9 +71,14 @@ export declare function checkReviewerGateWithScope(taskId: string, workingDirect
|
|
|
71
71
|
* missing), this function advances the task state so that checkReviewerGate can
|
|
72
72
|
* make an accurate decision without attributing unrelated delegation activity.
|
|
73
73
|
*
|
|
74
|
+
* Falls back to reading durable evidence files when delegation chains are empty
|
|
75
|
+
* (e.g., after a crash or session restart without snapshot). This ensures
|
|
76
|
+
* recovery works even when no in-memory delegation history exists.
|
|
77
|
+
*
|
|
74
78
|
* @param taskId - The task ID to recover state for
|
|
79
|
+
* @param directory - Optional project directory for evidence file fallback
|
|
75
80
|
*/
|
|
76
|
-
export declare function recoverTaskStateFromDelegations(taskId: string): void;
|
|
81
|
+
export declare function recoverTaskStateFromDelegations(taskId: string, directory?: string): void;
|
|
77
82
|
/**
|
|
78
83
|
* Result of the council-gate check used when transitioning to 'completed'.
|
|
79
84
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.23.
|
|
3
|
+
"version": "7.23.1",
|
|
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",
|