opencode-swarm 6.22.19 → 6.22.21

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -13,8 +13,10 @@ export type CuratorInitRunner = (directory: string, config: CuratorConfig) => Pr
13
13
  * Creates a hook that monitors plan phase transitions and triggers preflight.
14
14
  *
15
15
  * @param directory - Project directory (where .swarm/ lives)
16
- * @param preflightManager - The PreflightTriggerManager to call on phase change
16
+ * @param preflightManager - Optional PreflightTriggerManager to call on phase change.
17
+ * When undefined, preflight checks are skipped but curator initialization still runs
18
+ * at session start (useful when knowledge.enabled but phase_preflight is disabled).
17
19
  * @param curatorRunner - Optional curator init runner (defaults to runCuratorInit; injectable for tests)
18
20
  * @returns A safeHook-wrapped system.transform handler
19
21
  */
20
- export declare function createPhaseMonitorHook(directory: string, preflightManager: PreflightTriggerManager, curatorRunner?: CuratorInitRunner): (input: unknown, output: unknown) => Promise<void>;
22
+ export declare function createPhaseMonitorHook(directory: string, preflightManager?: PreflightTriggerManager, curatorRunner?: CuratorInitRunner): (input: unknown, output: unknown) => Promise<void>;
package/dist/index.js CHANGED
@@ -15792,6 +15792,18 @@ async function updateTaskStatus(directory, taskId, status) {
15792
15792
  throw new Error(`Plan not found in directory: ${directory}`);
15793
15793
  }
15794
15794
  let taskFound = false;
15795
+ const derivePhaseStatusFromTasks = (tasks) => {
15796
+ if (tasks.length > 0 && tasks.every((task) => task.status === "completed")) {
15797
+ return "complete";
15798
+ }
15799
+ if (tasks.some((task) => task.status === "in_progress")) {
15800
+ return "in_progress";
15801
+ }
15802
+ if (tasks.some((task) => task.status === "blocked")) {
15803
+ return "blocked";
15804
+ }
15805
+ return "pending";
15806
+ };
15795
15807
  const updatedPhases = plan.phases.map((phase) => {
15796
15808
  const updatedTasks = phase.tasks.map((task) => {
15797
15809
  if (task.id === taskId) {
@@ -15800,7 +15812,11 @@ async function updateTaskStatus(directory, taskId, status) {
15800
15812
  }
15801
15813
  return task;
15802
15814
  });
15803
- return { ...phase, tasks: updatedTasks };
15815
+ return {
15816
+ ...phase,
15817
+ status: derivePhaseStatusFromTasks(updatedTasks),
15818
+ tasks: updatedTasks
15819
+ };
15804
15820
  });
15805
15821
  if (!taskFound) {
15806
15822
  throw new Error(`Task not found: ${taskId}`);
@@ -39880,8 +39896,8 @@ When writing output consumed by other agents, prefix with:
39880
39896
  [FOR: agent1, agent2] \u2014 relevant to specific agents
39881
39897
  [FOR: ALL] \u2014 relevant to all agents
39882
39898
  Examples:
39883
- [FOR: {{AGENT_PREFIX}}reviewer, {{AGENT_PREFIX}}test_engineer] "Added validation \u2014 needs safety check"
39884
- [FOR: {{AGENT_PREFIX}}architect] "Research: Tree-sitter supports TypeScript AST"
39899
+ [FOR: reviewer, test_engineer] "Added validation \u2014 needs safety check"
39900
+ [FOR: architect] "Research: Tree-sitter supports TypeScript AST"
39885
39901
  [FOR: ALL] "Breaking change: StateManager renamed"
39886
39902
  This tag is informational in v6.19; v6.20 will use for context filtering.
39887
39903
  `;
@@ -48612,6 +48628,9 @@ function extractPlanTaskId(text) {
48612
48628
  }
48613
48629
  return null;
48614
48630
  }
48631
+ function getSeedTaskId(session) {
48632
+ return session.currentTaskId ?? session.lastCoderDelegationTaskId;
48633
+ }
48615
48634
  function createDelegationGateHook(config3) {
48616
48635
  const enabled = config3.hooks?.delegation_gate !== false;
48617
48636
  const delegationMaxChars = config3.hooks?.delegation_max_chars ?? 4000;
@@ -48669,6 +48688,10 @@ function createDelegationGateHook(config3) {
48669
48688
  if (!otherSession.taskWorkflowStates)
48670
48689
  continue;
48671
48690
  if (targetAgent === "reviewer") {
48691
+ const seedTaskId = getSeedTaskId(session);
48692
+ if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
48693
+ otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
48694
+ }
48672
48695
  for (const [taskId, state] of otherSession.taskWorkflowStates) {
48673
48696
  if (state === "coder_delegated" || state === "pre_check_passed") {
48674
48697
  try {
@@ -48680,6 +48703,10 @@ function createDelegationGateHook(config3) {
48680
48703
  }
48681
48704
  }
48682
48705
  if (targetAgent === "test_engineer") {
48706
+ const seedTaskId = getSeedTaskId(session);
48707
+ if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
48708
+ otherSession.taskWorkflowStates.set(seedTaskId, "reviewer_run");
48709
+ }
48683
48710
  for (const [taskId, state] of otherSession.taskWorkflowStates) {
48684
48711
  if (state === "reviewer_run") {
48685
48712
  try {
@@ -48750,6 +48777,10 @@ function createDelegationGateHook(config3) {
48750
48777
  continue;
48751
48778
  if (!otherSession.taskWorkflowStates)
48752
48779
  continue;
48780
+ const seedTaskId = getSeedTaskId(session);
48781
+ if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
48782
+ otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
48783
+ }
48753
48784
  for (const [taskId, state] of otherSession.taskWorkflowStates) {
48754
48785
  if (state === "coder_delegated" || state === "pre_check_passed") {
48755
48786
  try {
@@ -48767,6 +48798,10 @@ function createDelegationGateHook(config3) {
48767
48798
  continue;
48768
48799
  if (!otherSession.taskWorkflowStates)
48769
48800
  continue;
48801
+ const seedTaskId = getSeedTaskId(session);
48802
+ if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
48803
+ otherSession.taskWorkflowStates.set(seedTaskId, "reviewer_run");
48804
+ }
48770
48805
  for (const [taskId, state] of otherSession.taskWorkflowStates) {
48771
48806
  if (state === "reviewer_run") {
48772
48807
  try {
@@ -49221,7 +49256,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
49221
49256
  const phase = plan.phases.find((p) => p.id === previousPhase);
49222
49257
  const completedTasks = phase?.tasks.filter((t) => t.status === "completed").length ?? 0;
49223
49258
  const totalTasks = phase?.tasks.length ?? 0;
49224
- await preflightManager.checkAndTrigger(currentPhase, completedTasks, totalTasks);
49259
+ if (preflightManager) {
49260
+ await preflightManager.checkAndTrigger(currentPhase, completedTasks, totalTasks);
49261
+ }
49225
49262
  }
49226
49263
  };
49227
49264
  return safeHook(handler);
@@ -60913,7 +60950,9 @@ function checkReviewerGate(taskId, workingDirectory) {
60913
60950
  stateEntries.push(`${sessionId}: ${state}`);
60914
60951
  }
60915
60952
  const allIdle = stateEntries.length > 0 && stateEntries.every((e) => e.endsWith(": idle"));
60916
- if (allIdle) {}
60953
+ if (allIdle) {
60954
+ return { blocked: false, reason: "" };
60955
+ }
60917
60956
  try {
60918
60957
  const resolvedDir = workingDirectory ?? process.cwd();
60919
60958
  const planPath = path47.join(resolvedDir, ".swarm", "plan.json");
@@ -60930,7 +60969,7 @@ function checkReviewerGate(taskId, workingDirectory) {
60930
60969
  const currentStateStr = stateEntries.length > 0 ? stateEntries.join(", ") : "no active sessions";
60931
60970
  return {
60932
60971
  blocked: true,
60933
- reason: `Task ${taskId} has not passed QA gates. Current state: [${currentStateStr}]. Required state: tests_run or complete. Do not write directly to plan files \u2014 use update_task_status after running the reviewer and test_engineer agents.`
60972
+ reason: `Task ${taskId} has not passed QA gates. Current state by session: [${currentStateStr}]. Missing required state: tests_run or complete in at least one valid session. Do not write directly to plan files \u2014 use update_task_status after running the reviewer and test_engineer agents.`
60934
60973
  };
60935
60974
  } catch {
60936
60975
  return { blocked: false, reason: "" };
@@ -61030,6 +61069,19 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
61030
61069
  }
61031
61070
  try {
61032
61071
  const updatedPlan = await updateTaskStatus(directory, args2.task_id, args2.status);
61072
+ if (args2.status === "completed") {
61073
+ for (const [_sessionId, session] of swarmState.agentSessions) {
61074
+ if (!(session.taskWorkflowStates instanceof Map)) {
61075
+ continue;
61076
+ }
61077
+ const currentState = getTaskState(session, args2.task_id);
61078
+ if (currentState === "tests_run") {
61079
+ try {
61080
+ advanceTaskState(session, args2.task_id, "complete");
61081
+ } catch {}
61082
+ }
61083
+ }
61084
+ }
61033
61085
  return {
61034
61086
  success: true,
61035
61087
  message: "Task status updated successfully",
@@ -61098,7 +61150,7 @@ var OpenCodeSwarm = async (ctx) => {
61098
61150
  const activityHooks = createAgentActivityHooks(config3, ctx.directory);
61099
61151
  const delegationGateHooks = createDelegationGateHook(config3);
61100
61152
  const delegationSanitizerHook = createDelegationSanitizerHook(ctx.directory);
61101
- const guardrailsFallback = config3.guardrails?.enabled === false ? { ...config3.guardrails, enabled: false } : loadedFromFile ? config3.guardrails ?? {} : config3.guardrails;
61153
+ const guardrailsFallback = config3.guardrails?.enabled === false ? { ...config3.guardrails, enabled: false } : config3.guardrails ?? {};
61102
61154
  const guardrailsConfig = GuardrailsConfigSchema.parse(guardrailsFallback);
61103
61155
  if (loadedFromFile && guardrailsConfig.enabled === false) {
61104
61156
  console.warn("");
@@ -61379,7 +61431,7 @@ var OpenCodeSwarm = async (ctx) => {
61379
61431
  ].filter((fn) => Boolean(fn))),
61380
61432
  "experimental.chat.system.transform": composeHandlers(...[
61381
61433
  systemEnhancerHook["experimental.chat.system.transform"],
61382
- automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager) : undefined
61434
+ automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory) : undefined
61383
61435
  ].filter(Boolean)),
61384
61436
  "experimental.session.compacting": compactionHook["experimental.session.compacting"],
61385
61437
  "command.execute.before": safeHook(commandHandler),
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.22.19",
3
+ "version": "6.22.21",
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",