opencode-swarm 6.76.0 → 6.77.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 +6 -1
- package/dist/config/schema.d.ts +10 -0
- package/dist/index.js +150 -47
- package/dist/parallel/dispatcher/index.d.ts +10 -0
- package/dist/parallel/dispatcher/parallel-dispatcher.d.ts +18 -0
- package/dist/state.d.ts +26 -0
- package/dist/tools/update-task-status.d.ts +3 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -19414,7 +19414,12 @@ var CouncilConfigSchema = exports_external.object({
|
|
|
19414
19414
|
var ParallelizationConfigSchema = exports_external.object({
|
|
19415
19415
|
enabled: exports_external.boolean().default(false),
|
|
19416
19416
|
maxConcurrentTasks: exports_external.number().int().min(1).max(64).default(1),
|
|
19417
|
-
evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000)
|
|
19417
|
+
evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000),
|
|
19418
|
+
stageB: exports_external.object({
|
|
19419
|
+
parallel: exports_external.object({
|
|
19420
|
+
enabled: exports_external.boolean().default(false)
|
|
19421
|
+
}).default({ enabled: false })
|
|
19422
|
+
}).default({ parallel: { enabled: false } })
|
|
19418
19423
|
});
|
|
19419
19424
|
var PluginConfigSchema = exports_external.object({
|
|
19420
19425
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -530,6 +530,11 @@ export declare const ParallelizationConfigSchema: z.ZodObject<{
|
|
|
530
530
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
531
531
|
maxConcurrentTasks: z.ZodDefault<z.ZodNumber>;
|
|
532
532
|
evidenceLockTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
533
|
+
stageB: z.ZodDefault<z.ZodObject<{
|
|
534
|
+
parallel: z.ZodDefault<z.ZodObject<{
|
|
535
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
536
|
+
}, z.core.$strip>>;
|
|
537
|
+
}, z.core.$strip>>;
|
|
533
538
|
}, z.core.$strip>;
|
|
534
539
|
export type ParallelizationConfig = z.infer<typeof ParallelizationConfigSchema>;
|
|
535
540
|
export declare const PluginConfigSchema: z.ZodObject<{
|
|
@@ -893,6 +898,11 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
893
898
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
894
899
|
maxConcurrentTasks: z.ZodDefault<z.ZodNumber>;
|
|
895
900
|
evidenceLockTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
901
|
+
stageB: z.ZodDefault<z.ZodObject<{
|
|
902
|
+
parallel: z.ZodDefault<z.ZodObject<{
|
|
903
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
904
|
+
}, z.core.$strip>>;
|
|
905
|
+
}, z.core.$strip>>;
|
|
896
906
|
}, z.core.$strip>>;
|
|
897
907
|
turbo_mode: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
898
908
|
full_auto: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -15185,7 +15185,12 @@ var init_schema = __esm(() => {
|
|
|
15185
15185
|
ParallelizationConfigSchema = exports_external.object({
|
|
15186
15186
|
enabled: exports_external.boolean().default(false),
|
|
15187
15187
|
maxConcurrentTasks: exports_external.number().int().min(1).max(64).default(1),
|
|
15188
|
-
evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000)
|
|
15188
|
+
evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000),
|
|
15189
|
+
stageB: exports_external.object({
|
|
15190
|
+
parallel: exports_external.object({
|
|
15191
|
+
enabled: exports_external.boolean().default(false)
|
|
15192
|
+
}).default({ enabled: false })
|
|
15193
|
+
}).default({ parallel: { enabled: false } })
|
|
15189
15194
|
});
|
|
15190
15195
|
PluginConfigSchema = exports_external.object({
|
|
15191
15196
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
@@ -24827,60 +24832,121 @@ function createDelegationGateHook(config2, directory) {
|
|
|
24827
24832
|
if (targetAgent === "test_engineer")
|
|
24828
24833
|
hasTestEngineer = true;
|
|
24829
24834
|
if (!councilActive) {
|
|
24830
|
-
|
|
24831
|
-
|
|
24832
|
-
|
|
24833
|
-
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
|
|
24835
|
+
const stageBParallelEnabled = config2.parallelization?.stageB?.parallel?.enabled === true;
|
|
24836
|
+
if (stageBParallelEnabled) {
|
|
24837
|
+
if ((targetAgent === "reviewer" || targetAgent === "test_engineer") && session.taskWorkflowStates) {
|
|
24838
|
+
const stageBEligibleStates = [
|
|
24839
|
+
"coder_delegated",
|
|
24840
|
+
"pre_check_passed",
|
|
24841
|
+
"reviewer_run"
|
|
24842
|
+
];
|
|
24843
|
+
for (const [taskId, state] of session.taskWorkflowStates) {
|
|
24844
|
+
if (!stageBEligibleStates.includes(state))
|
|
24845
|
+
continue;
|
|
24846
|
+
const eligibleState = state;
|
|
24847
|
+
recordStageBCompletion(session, taskId, targetAgent);
|
|
24848
|
+
if (hasBothStageBCompletions(session, taskId)) {
|
|
24849
|
+
try {
|
|
24850
|
+
if (eligibleState === "coder_delegated" || eligibleState === "pre_check_passed") {
|
|
24851
|
+
advanceTaskState(session, taskId, "reviewer_run");
|
|
24852
|
+
}
|
|
24853
|
+
advanceTaskState(session, taskId, "tests_run");
|
|
24854
|
+
} catch (err2) {
|
|
24855
|
+
console.warn(`[delegation-gate] toolAfter stage-b-parallel: could not advance ${taskId} (${eligibleState}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24856
|
+
}
|
|
24837
24857
|
}
|
|
24838
24858
|
}
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
24859
|
+
const seedTaskId = getSeedTaskId(session);
|
|
24860
|
+
if (seedTaskId) {
|
|
24861
|
+
for (const [, otherSession] of swarmState.agentSessions) {
|
|
24862
|
+
if (otherSession === session)
|
|
24863
|
+
continue;
|
|
24864
|
+
if (!otherSession.taskWorkflowStates)
|
|
24865
|
+
continue;
|
|
24866
|
+
if (!otherSession.taskWorkflowStates.has(seedTaskId)) {
|
|
24867
|
+
otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
|
|
24868
|
+
}
|
|
24869
|
+
const seedState = otherSession.taskWorkflowStates.get(seedTaskId);
|
|
24870
|
+
if (!seedState || !stageBEligibleStates.includes(seedState)) {
|
|
24871
|
+
continue;
|
|
24872
|
+
}
|
|
24873
|
+
const seedEligibleState = seedState;
|
|
24874
|
+
recordStageBCompletion(otherSession, seedTaskId, targetAgent);
|
|
24875
|
+
if (hasBothStageBCompletions(otherSession, seedTaskId)) {
|
|
24876
|
+
try {
|
|
24877
|
+
if (seedEligibleState === "coder_delegated" || seedEligibleState === "pre_check_passed") {
|
|
24878
|
+
advanceTaskState(otherSession, seedTaskId, "reviewer_run");
|
|
24879
|
+
}
|
|
24880
|
+
advanceTaskState(otherSession, seedTaskId, "tests_run");
|
|
24881
|
+
} catch (err2) {
|
|
24882
|
+
console.warn(`[delegation-gate] toolAfter cross-session stage-b-parallel: could not advance ${seedTaskId} (${seedEligibleState}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24883
|
+
}
|
|
24884
|
+
}
|
|
24848
24885
|
}
|
|
24849
24886
|
}
|
|
24850
24887
|
}
|
|
24851
|
-
}
|
|
24852
|
-
|
|
24853
|
-
|
|
24854
|
-
|
|
24855
|
-
|
|
24856
|
-
|
|
24857
|
-
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
|
|
24861
|
-
otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
|
|
24888
|
+
} else {
|
|
24889
|
+
if (targetAgent === "reviewer" && session.taskWorkflowStates) {
|
|
24890
|
+
for (const [taskId, state] of session.taskWorkflowStates) {
|
|
24891
|
+
if (state === "coder_delegated" || state === "pre_check_passed") {
|
|
24892
|
+
try {
|
|
24893
|
+
advanceTaskState(session, taskId, "reviewer_run");
|
|
24894
|
+
} catch (err2) {
|
|
24895
|
+
console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24896
|
+
}
|
|
24862
24897
|
}
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24898
|
+
}
|
|
24899
|
+
}
|
|
24900
|
+
if (targetAgent === "test_engineer" && session.taskWorkflowStates) {
|
|
24901
|
+
for (const [taskId, state] of session.taskWorkflowStates) {
|
|
24902
|
+
if (state === "reviewer_run") {
|
|
24903
|
+
try {
|
|
24904
|
+
advanceTaskState(session, taskId, "tests_run");
|
|
24905
|
+
} catch (err2) {
|
|
24906
|
+
console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24870
24907
|
}
|
|
24871
24908
|
}
|
|
24872
24909
|
}
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24910
|
+
}
|
|
24911
|
+
if (targetAgent === "reviewer" || targetAgent === "test_engineer") {
|
|
24912
|
+
for (const [, otherSession] of swarmState.agentSessions) {
|
|
24913
|
+
if (otherSession === session)
|
|
24914
|
+
continue;
|
|
24915
|
+
if (!otherSession.taskWorkflowStates)
|
|
24916
|
+
continue;
|
|
24917
|
+
if (targetAgent === "reviewer") {
|
|
24918
|
+
const seedTaskId = getSeedTaskId(session);
|
|
24919
|
+
if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
|
|
24920
|
+
otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
|
|
24921
|
+
}
|
|
24922
|
+
for (const [
|
|
24923
|
+
taskId,
|
|
24924
|
+
state
|
|
24925
|
+
] of otherSession.taskWorkflowStates) {
|
|
24926
|
+
if (state === "coder_delegated" || state === "pre_check_passed") {
|
|
24927
|
+
try {
|
|
24928
|
+
advanceTaskState(otherSession, taskId, "reviewer_run");
|
|
24929
|
+
} catch (err2) {
|
|
24930
|
+
console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24931
|
+
}
|
|
24932
|
+
}
|
|
24933
|
+
}
|
|
24877
24934
|
}
|
|
24878
|
-
|
|
24879
|
-
|
|
24880
|
-
|
|
24881
|
-
|
|
24882
|
-
|
|
24883
|
-
|
|
24935
|
+
if (targetAgent === "test_engineer") {
|
|
24936
|
+
const seedTaskId = getSeedTaskId(session);
|
|
24937
|
+
if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
|
|
24938
|
+
otherSession.taskWorkflowStates.set(seedTaskId, "reviewer_run");
|
|
24939
|
+
}
|
|
24940
|
+
for (const [
|
|
24941
|
+
taskId,
|
|
24942
|
+
state
|
|
24943
|
+
] of otherSession.taskWorkflowStates) {
|
|
24944
|
+
if (state === "reviewer_run") {
|
|
24945
|
+
try {
|
|
24946
|
+
advanceTaskState(otherSession, taskId, "tests_run");
|
|
24947
|
+
} catch (err2) {
|
|
24948
|
+
console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
24949
|
+
}
|
|
24884
24950
|
}
|
|
24885
24951
|
}
|
|
24886
24952
|
}
|
|
@@ -25293,9 +25359,11 @@ __export(exports_state, {
|
|
|
25293
25359
|
setSessionEnvironment: () => setSessionEnvironment,
|
|
25294
25360
|
resetSwarmState: () => resetSwarmState,
|
|
25295
25361
|
rehydrateSessionFromDisk: () => rehydrateSessionFromDisk,
|
|
25362
|
+
recordStageBCompletion: () => recordStageBCompletion,
|
|
25296
25363
|
recordPhaseAgentDispatch: () => recordPhaseAgentDispatch,
|
|
25297
25364
|
pruneOldWindows: () => pruneOldWindows,
|
|
25298
25365
|
isCouncilGateActive: () => isCouncilGateActive,
|
|
25366
|
+
hasBothStageBCompletions: () => hasBothStageBCompletions,
|
|
25299
25367
|
hasActiveTurboMode: () => hasActiveTurboMode,
|
|
25300
25368
|
hasActiveFullAuto: () => hasActiveFullAuto,
|
|
25301
25369
|
getTaskState: () => getTaskState,
|
|
@@ -25376,6 +25444,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
|
|
|
25376
25444
|
qaSkipCount: 0,
|
|
25377
25445
|
qaSkipTaskIds: [],
|
|
25378
25446
|
taskWorkflowStates: new Map,
|
|
25447
|
+
stageBCompletion: new Map,
|
|
25379
25448
|
taskCouncilApproved: new Map,
|
|
25380
25449
|
lastGateOutcome: null,
|
|
25381
25450
|
declaredCoderScope: null,
|
|
@@ -25491,6 +25560,9 @@ function ensureAgentSession(sessionId, agentName, directory) {
|
|
|
25491
25560
|
if (!session.taskWorkflowStates) {
|
|
25492
25561
|
session.taskWorkflowStates = new Map;
|
|
25493
25562
|
}
|
|
25563
|
+
if (!session.stageBCompletion) {
|
|
25564
|
+
session.stageBCompletion = new Map;
|
|
25565
|
+
}
|
|
25494
25566
|
if (!session.taskCouncilApproved) {
|
|
25495
25567
|
session.taskCouncilApproved = new Map;
|
|
25496
25568
|
}
|
|
@@ -25667,6 +25739,27 @@ function getTaskState(session, taskId) {
|
|
|
25667
25739
|
}
|
|
25668
25740
|
return session.taskWorkflowStates.get(taskId) ?? "idle";
|
|
25669
25741
|
}
|
|
25742
|
+
function recordStageBCompletion(session, taskId, agent) {
|
|
25743
|
+
if (!isValidTaskId2(taskId))
|
|
25744
|
+
return;
|
|
25745
|
+
if (!session.stageBCompletion) {
|
|
25746
|
+
session.stageBCompletion = new Map;
|
|
25747
|
+
}
|
|
25748
|
+
const existing = session.stageBCompletion.get(taskId);
|
|
25749
|
+
if (existing) {
|
|
25750
|
+
existing.add(agent);
|
|
25751
|
+
} else {
|
|
25752
|
+
session.stageBCompletion.set(taskId, new Set([agent]));
|
|
25753
|
+
}
|
|
25754
|
+
}
|
|
25755
|
+
function hasBothStageBCompletions(session, taskId) {
|
|
25756
|
+
if (!isValidTaskId2(taskId))
|
|
25757
|
+
return false;
|
|
25758
|
+
const completions = session.stageBCompletion?.get(taskId);
|
|
25759
|
+
if (!completions)
|
|
25760
|
+
return false;
|
|
25761
|
+
return completions.has("reviewer") && completions.has("test_engineer");
|
|
25762
|
+
}
|
|
25670
25763
|
function derivePlanIdFromPlan(plan) {
|
|
25671
25764
|
return `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
25672
25765
|
}
|
|
@@ -83764,7 +83857,7 @@ function matchesTier3Pattern(files) {
|
|
|
83764
83857
|
}
|
|
83765
83858
|
return false;
|
|
83766
83859
|
}
|
|
83767
|
-
function checkReviewerGate(taskId, workingDirectory) {
|
|
83860
|
+
function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = false) {
|
|
83768
83861
|
try {
|
|
83769
83862
|
if (hasActiveTurboMode()) {
|
|
83770
83863
|
const resolvedDir2 = workingDirectory;
|
|
@@ -83823,6 +83916,9 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
83823
83916
|
if (state === "tests_run" || state === "complete") {
|
|
83824
83917
|
return { blocked: false, reason: "" };
|
|
83825
83918
|
}
|
|
83919
|
+
if (stageBParallelEnabled && hasBothStageBCompletions(session, taskId)) {
|
|
83920
|
+
return { blocked: false, reason: "" };
|
|
83921
|
+
}
|
|
83826
83922
|
}
|
|
83827
83923
|
if (validSessionCount === 0) {
|
|
83828
83924
|
return { blocked: false, reason: "" };
|
|
@@ -83897,7 +83993,14 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
83897
83993
|
}
|
|
83898
83994
|
}
|
|
83899
83995
|
async function checkReviewerGateWithScope(taskId, workingDirectory) {
|
|
83900
|
-
|
|
83996
|
+
let stageBParallelEnabled = false;
|
|
83997
|
+
if (workingDirectory) {
|
|
83998
|
+
try {
|
|
83999
|
+
const cfg = await loadPluginConfig(workingDirectory);
|
|
84000
|
+
stageBParallelEnabled = cfg.parallelization?.stageB?.parallel?.enabled === true;
|
|
84001
|
+
} catch {}
|
|
84002
|
+
}
|
|
84003
|
+
const result = checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled);
|
|
83901
84004
|
const scopeWarning = await validateDiffScope(taskId, workingDirectory).catch(() => null);
|
|
83902
84005
|
if (!scopeWarning)
|
|
83903
84006
|
return result;
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
export { createNoopDispatcher, type NoopDispatcher, } from './noop-dispatcher.js';
|
|
2
|
+
export { createParallelDispatcher, type ParallelDispatcher, } from './parallel-dispatcher.js';
|
|
2
3
|
export type { DispatchDecision, DispatcherConfig, RunSlot, TaskExecutionHandle, } from './types.js';
|
|
4
|
+
import { type NoopDispatcher } from './noop-dispatcher.js';
|
|
5
|
+
import { type ParallelDispatcher } from './parallel-dispatcher.js';
|
|
6
|
+
import type { DispatcherConfig } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Factory: returns the appropriate dispatcher based on config.
|
|
9
|
+
* When disabled or maxConcurrentTasks <= 1, returns the no-op dispatcher.
|
|
10
|
+
* When enabled and maxConcurrentTasks > 1, returns the parallel dispatcher.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createDispatcher(config: DispatcherConfig): NoopDispatcher | ParallelDispatcher;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel dispatcher — enabled path for Stage B concurrent task execution.
|
|
3
|
+
*
|
|
4
|
+
* Uses p-limit for bounded concurrency. Returns 'dispatch' when a slot is
|
|
5
|
+
* available, 'defer' when at max capacity, 'reject' when disabled.
|
|
6
|
+
*
|
|
7
|
+
* PR 2: implements the enabled dispatcher alongside the existing NoopDispatcher.
|
|
8
|
+
* No production code imports this directly — it is wired in via createDispatcher().
|
|
9
|
+
*/
|
|
10
|
+
import type { DispatchDecision, DispatcherConfig, TaskExecutionHandle } from './types.js';
|
|
11
|
+
export interface ParallelDispatcher {
|
|
12
|
+
readonly config: DispatcherConfig;
|
|
13
|
+
dispatch(taskId: string): DispatchDecision;
|
|
14
|
+
handles(): TaskExecutionHandle[];
|
|
15
|
+
releaseSlot(slotId: string): void;
|
|
16
|
+
shutdown(): void;
|
|
17
|
+
}
|
|
18
|
+
export declare function createParallelDispatcher(config: DispatcherConfig): ParallelDispatcher;
|
package/dist/state.d.ts
CHANGED
|
@@ -103,6 +103,13 @@ export interface AgentSessionState {
|
|
|
103
103
|
qaSkipTaskIds: string[];
|
|
104
104
|
/** Per-task workflow state — taskId → current state */
|
|
105
105
|
taskWorkflowStates: Map<string, TaskWorkflowState>;
|
|
106
|
+
/**
|
|
107
|
+
* PR 2 Stage B barrier: per-task set of completed Stage B agents.
|
|
108
|
+
* Order-independent — either 'reviewer' or 'test_engineer' may complete first.
|
|
109
|
+
* When both are present, the task may advance to tests_run regardless of order.
|
|
110
|
+
* Only populated when parallelization.stageB.parallel.enabled = true.
|
|
111
|
+
*/
|
|
112
|
+
stageBCompletion?: Map<string, Set<'reviewer' | 'test_engineer'>>;
|
|
106
113
|
/** v6.71+ Council mode: per-task council verdict, recorded by delegation-gate when convene_council resolves. */
|
|
107
114
|
taskCouncilApproved?: Map<string, {
|
|
108
115
|
verdict: 'APPROVE' | 'REJECT' | 'CONCERNS';
|
|
@@ -350,6 +357,25 @@ export declare function advanceTaskState(session: AgentSessionState, taskId: str
|
|
|
350
357
|
* @returns Current task workflow state
|
|
351
358
|
*/
|
|
352
359
|
export declare function getTaskState(session: AgentSessionState, taskId: string): TaskWorkflowState;
|
|
360
|
+
/**
|
|
361
|
+
* PR 2 Stage B barrier: record that a Stage B agent has completed for a task.
|
|
362
|
+
* Order-independent — either 'reviewer' or 'test_engineer' may complete first.
|
|
363
|
+
* Initializes the per-task set on first write.
|
|
364
|
+
*
|
|
365
|
+
* @param session - The agent session state
|
|
366
|
+
* @param taskId - The task identifier
|
|
367
|
+
* @param agent - Which Stage B agent completed ('reviewer' or 'test_engineer')
|
|
368
|
+
*/
|
|
369
|
+
export declare function recordStageBCompletion(session: AgentSessionState, taskId: string, agent: 'reviewer' | 'test_engineer'): void;
|
|
370
|
+
/**
|
|
371
|
+
* PR 2 Stage B barrier: returns true iff both 'reviewer' and 'test_engineer' have
|
|
372
|
+
* been recorded for the given task in this session.
|
|
373
|
+
*
|
|
374
|
+
* @param session - The agent session state
|
|
375
|
+
* @param taskId - The task identifier
|
|
376
|
+
* @returns true when both Stage B agents have completed
|
|
377
|
+
*/
|
|
378
|
+
export declare function hasBothStageBCompletions(session: AgentSessionState, taskId: string): boolean;
|
|
353
379
|
/**
|
|
354
380
|
* Returns true iff council is authoritative for the current plan.
|
|
355
381
|
*
|
|
@@ -49,12 +49,14 @@ export interface ReviewerGateResult {
|
|
|
49
49
|
* both reviewer delegation and test_engineer runs have been recorded.
|
|
50
50
|
* @param taskId - The task ID to check gate state for
|
|
51
51
|
* @param workingDirectory - Optional working directory for plan.json fallback
|
|
52
|
+
* @param stageBParallelEnabled - When true, also accept both-markers-present as passing (PR 2 barrier)
|
|
52
53
|
* @returns ReviewerGateResult indicating whether the gate is blocked
|
|
53
54
|
*/
|
|
54
|
-
export declare function checkReviewerGate(taskId: string, workingDirectory?: string): ReviewerGateResult;
|
|
55
|
+
export declare function checkReviewerGate(taskId: string, workingDirectory?: string, stageBParallelEnabled?: boolean): ReviewerGateResult;
|
|
55
56
|
/**
|
|
56
57
|
* Wrapper around checkReviewerGate that appends a diff-scope advisory warning.
|
|
57
58
|
* Keeps checkReviewerGate synchronous for backward compatibility.
|
|
59
|
+
* Also resolves the PR 2 stageB.parallel.enabled flag from config.
|
|
58
60
|
* @param taskId - The task ID to check gate state for
|
|
59
61
|
* @param workingDirectory - Optional working directory for plan.json fallback
|
|
60
62
|
* @returns ReviewerGateResult with optional scope warning appended to reason
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.77.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",
|