opencode-swarm 6.86.2 → 6.86.3

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
@@ -15059,7 +15059,15 @@ ${markdown}`;
15059
15059
  } catch {}
15060
15060
  }
15061
15061
  } catch (mdError) {
15062
- warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${mdError instanceof Error ? mdError.message : String(mdError)}`);
15062
+ const message = mdError instanceof Error ? mdError.message : String(mdError);
15063
+ warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${message}`);
15064
+ try {
15065
+ emit("plan_md_write_failed", {
15066
+ directory,
15067
+ error: message,
15068
+ timestamp: new Date().toISOString()
15069
+ });
15070
+ } catch {}
15063
15071
  }
15064
15072
  try {
15065
15073
  const markerPath = path3.join(swarmDir, ".plan-write-marker");
@@ -15108,7 +15116,9 @@ function derivePlanMarkdown(plan) {
15108
15116
  pending: "PENDING",
15109
15117
  in_progress: "IN PROGRESS",
15110
15118
  complete: "COMPLETE",
15111
- blocked: "BLOCKED"
15119
+ completed: "COMPLETE",
15120
+ blocked: "BLOCKED",
15121
+ closed: "CLOSED"
15112
15122
  };
15113
15123
  const now = new Date().toISOString();
15114
15124
  const currentPhase = plan.current_phase ?? 1;
package/dist/index.js CHANGED
@@ -16987,7 +16987,15 @@ ${markdown}`;
16987
16987
  } catch {}
16988
16988
  }
16989
16989
  } catch (mdError) {
16990
- warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${mdError instanceof Error ? mdError.message : String(mdError)}`);
16990
+ const message = mdError instanceof Error ? mdError.message : String(mdError);
16991
+ warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${message}`);
16992
+ try {
16993
+ emit("plan_md_write_failed", {
16994
+ directory,
16995
+ error: message,
16996
+ timestamp: new Date().toISOString()
16997
+ });
16998
+ } catch {}
16991
16999
  }
16992
17000
  try {
16993
17001
  const markerPath = path5.join(swarmDir, ".plan-write-marker");
@@ -17088,7 +17096,9 @@ function derivePlanMarkdown(plan) {
17088
17096
  pending: "PENDING",
17089
17097
  in_progress: "IN PROGRESS",
17090
17098
  complete: "COMPLETE",
17091
- blocked: "BLOCKED"
17099
+ completed: "COMPLETE",
17100
+ blocked: "BLOCKED",
17101
+ closed: "CLOSED"
17092
17102
  };
17093
17103
  const now = new Date().toISOString();
17094
17104
  const currentPhase = plan.current_phase ?? 1;
@@ -24990,7 +25000,7 @@ function createDelegationGateHook(config2, directory) {
24990
25000
  });
24991
25001
  if (councilActive && result.overallVerdict === "APPROVE" && result.allCriteriaMet === true && (result.requiredFixesCount ?? 0) === 0) {
24992
25002
  try {
24993
- advanceTaskState(session, taskId, "complete");
25003
+ await advanceTaskStateAndPersist(session, taskId, "complete", directory);
24994
25004
  } catch (err2) {
24995
25005
  console.warn(`[delegation-gate] toolAfter convene_council: could not advance ${taskId} \u2192 complete: ${err2 instanceof Error ? err2.message : String(err2)}`);
24996
25006
  }
@@ -25377,7 +25387,7 @@ ${trimComment}${after}`;
25377
25387
  pendingCoderScopeByTaskId.delete(currentTaskId);
25378
25388
  }
25379
25389
  try {
25380
- advanceTaskState(session, currentTaskId, "coder_delegated");
25390
+ await advanceTaskStateAndPersist(session, currentTaskId, "coder_delegated", directory);
25381
25391
  } catch (err2) {
25382
25392
  console.warn(`[delegation-gate] state machine warn: ${err2 instanceof Error ? err2.message : String(err2)}`);
25383
25393
  }
@@ -25561,6 +25571,7 @@ __export(exports_state, {
25561
25571
  buildRehydrationCache: () => buildRehydrationCache,
25562
25572
  beginInvocation: () => beginInvocation,
25563
25573
  applyRehydrationCache: () => applyRehydrationCache,
25574
+ advanceTaskStateAndPersist: () => advanceTaskStateAndPersist,
25564
25575
  advanceTaskState: () => advanceTaskState,
25565
25576
  _resetCouncilDisagreementWarnings: () => _resetCouncilDisagreementWarnings,
25566
25577
  AgentRunContext: () => AgentRunContext
@@ -25933,6 +25944,18 @@ function advanceTaskState(session, taskId, newState) {
25933
25944
  session.taskWorkflowStates.set(taskId, newState);
25934
25945
  telemetry.taskStateChanged(session.agentName, taskId, newState, current);
25935
25946
  }
25947
+ async function advanceTaskStateAndPersist(session, taskId, newState, directory) {
25948
+ advanceTaskState(session, taskId, newState);
25949
+ if (newState !== "coder_delegated" && newState !== "complete") {
25950
+ return;
25951
+ }
25952
+ const planStatus = newState === "complete" ? "completed" : "in_progress";
25953
+ try {
25954
+ await updateTaskStatus(directory, taskId, planStatus);
25955
+ } catch (err2) {
25956
+ console.warn(`[advanceTaskStateAndPersist] persist ${taskId} \u2192 ${planStatus} failed (in-memory state still advanced): ${err2 instanceof Error ? err2.message : String(err2)}`);
25957
+ }
25958
+ }
25936
25959
  function getTaskState(session, taskId) {
25937
25960
  if (!isValidTaskId2(taskId)) {
25938
25961
  return "idle";
package/dist/state.d.ts CHANGED
@@ -360,6 +360,24 @@ export declare function recordPhaseAgentDispatch(sessionId: string, agentName: s
360
360
  * @param newState - The requested new state
361
361
  */
362
362
  export declare function advanceTaskState(session: AgentSessionState, taskId: string, newState: TaskWorkflowState): void;
363
+ /**
364
+ * Advance the per-task workflow state machine AND persist the corresponding
365
+ * plan.json status at meaningful workflow boundaries.
366
+ *
367
+ * The two-layer model splits in-memory workflow state (Layer 1, fast, used by
368
+ * gates) from the durable plan (Layer 2, projected to plan.md). Without this
369
+ * bridge, council APPROVE → 'complete' updates Layer 1 only and plan.md goes
370
+ * stale. This helper closes the gap by mapping:
371
+ * - 'coder_delegated' → plan.json status 'in_progress'
372
+ * - 'complete' → plan.json status 'completed'
373
+ * Other transitions are in-memory only (the task is already in_progress on disk
374
+ * once coder_delegated has fired).
375
+ *
376
+ * Persistence errors are logged and swallowed so a transient disk failure does
377
+ * not break the in-memory state machine — matches the existing defensive
378
+ * pattern around advanceTaskState call sites.
379
+ */
380
+ export declare function advanceTaskStateAndPersist(session: AgentSessionState, taskId: string, newState: TaskWorkflowState, directory: string): Promise<void>;
363
381
  /**
364
382
  * Get the current workflow state for a task.
365
383
  * Returns 'idle' if no entry exists.
@@ -1,4 +1,4 @@
1
- export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
1
+ export type TelemetryEvent = 'session_started' | 'session_ended' | 'agent_activated' | 'delegation_begin' | 'delegation_end' | 'task_state_changed' | 'gate_passed' | 'gate_failed' | 'phase_changed' | 'budget_updated' | 'model_fallback' | 'hard_limit_hit' | 'revision_limit_hit' | 'loop_detected' | 'scope_violation' | 'qa_skip_violation' | 'heartbeat' | 'turbo_mode_changed' | 'auto_oversight_escalation' | 'environment_detected' | 'evidence_lock_acquired' | 'evidence_lock_contended' | 'evidence_lock_stale_recovered' | 'plan_ledger_cas_retry' | 'plan_md_write_failed' | 'prm_pattern_detected' | 'prm_course_correction_injected' | 'prm_escalation_triggered' | 'prm_hard_stop';
2
2
  export type TelemetryListener = (event: TelemetryEvent, data: Record<string, unknown>) => void;
3
3
  /** @internal - For testing only */
4
4
  export declare function resetTelemetryForTesting(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.86.2",
3
+ "version": "6.86.3",
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",