@chllming/wave-orchestration 0.6.3 → 0.7.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +82 -1
  2. package/README.md +40 -7
  3. package/docs/agents/wave-orchestrator-role.md +50 -0
  4. package/docs/agents/wave-planner-role.md +39 -0
  5. package/docs/context7/bundles.json +9 -0
  6. package/docs/context7/planner-agent/README.md +25 -0
  7. package/docs/context7/planner-agent/manifest.json +83 -0
  8. package/docs/context7/planner-agent/papers/cooperbench-why-coding-agents-cannot-be-your-teammates-yet.md +3283 -0
  9. package/docs/context7/planner-agent/papers/dova-deliberation-first-multi-agent-orchestration-for-autonomous-research-automation.md +1699 -0
  10. package/docs/context7/planner-agent/papers/dpbench-large-language-models-struggle-with-simultaneous-coordination.md +2251 -0
  11. package/docs/context7/planner-agent/papers/incremental-planning-to-control-a-blackboard-based-problem-solver.md +1729 -0
  12. package/docs/context7/planner-agent/papers/silo-bench-a-scalable-environment-for-evaluating-distributed-coordination-in-multi-agent-llm-systems.md +3747 -0
  13. package/docs/context7/planner-agent/papers/todoevolve-learning-to-architect-agent-planning-systems.md +1675 -0
  14. package/docs/context7/planner-agent/papers/verified-multi-agent-orchestration-a-plan-execute-verify-replan-framework-for-complex-query-resolution.md +1173 -0
  15. package/docs/context7/planner-agent/papers/why-do-multi-agent-llm-systems-fail.md +5211 -0
  16. package/docs/context7/planner-agent/topics/planning-and-orchestration.md +24 -0
  17. package/docs/evals/README.md +96 -1
  18. package/docs/evals/arm-templates/README.md +13 -0
  19. package/docs/evals/arm-templates/full-wave.json +15 -0
  20. package/docs/evals/arm-templates/single-agent.json +15 -0
  21. package/docs/evals/benchmark-catalog.json +7 -0
  22. package/docs/evals/cases/README.md +47 -0
  23. package/docs/evals/cases/wave-blackboard-inbox-targeting.json +73 -0
  24. package/docs/evals/cases/wave-contradiction-conflict.json +104 -0
  25. package/docs/evals/cases/wave-expert-routing-preservation.json +69 -0
  26. package/docs/evals/cases/wave-hidden-profile-private-evidence.json +81 -0
  27. package/docs/evals/cases/wave-premature-closure-guard.json +71 -0
  28. package/docs/evals/cases/wave-silo-cross-agent-state.json +77 -0
  29. package/docs/evals/cases/wave-simultaneous-lockstep.json +92 -0
  30. package/docs/evals/cooperbench/real-world-mitigation.md +341 -0
  31. package/docs/evals/external-benchmarks.json +85 -0
  32. package/docs/evals/external-command-config.sample.json +9 -0
  33. package/docs/evals/external-command-config.swe-bench-pro.json +8 -0
  34. package/docs/evals/pilots/README.md +47 -0
  35. package/docs/evals/pilots/swe-bench-pro-public-full-wave-review-10.json +64 -0
  36. package/docs/evals/pilots/swe-bench-pro-public-pilot.json +111 -0
  37. package/docs/evals/wave-benchmark-program.md +302 -0
  38. package/docs/guides/planner.md +67 -11
  39. package/docs/guides/terminal-surfaces.md +12 -0
  40. package/docs/plans/context7-wave-orchestrator.md +20 -0
  41. package/docs/plans/current-state.md +8 -1
  42. package/docs/plans/examples/wave-benchmark-improvement.md +108 -0
  43. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  44. package/docs/plans/examples/wave-example-rollout-fidelity.md +340 -0
  45. package/docs/plans/migration.md +26 -0
  46. package/docs/plans/wave-orchestrator.md +60 -12
  47. package/docs/plans/waves/reviews/wave-1-benchmark-operator.md +118 -0
  48. package/docs/reference/cli-reference.md +547 -0
  49. package/docs/reference/coordination-and-closure.md +436 -0
  50. package/docs/reference/live-proof-waves.md +25 -3
  51. package/docs/reference/npmjs-trusted-publishing.md +3 -3
  52. package/docs/reference/proof-metrics.md +90 -0
  53. package/docs/reference/runtime-config/README.md +63 -2
  54. package/docs/reference/runtime-config/codex.md +2 -1
  55. package/docs/reference/sample-waves.md +29 -18
  56. package/docs/reference/wave-control.md +164 -0
  57. package/docs/reference/wave-planning-lessons.md +131 -0
  58. package/package.json +5 -4
  59. package/releases/manifest.json +40 -0
  60. package/scripts/research/agent-context-archive.mjs +18 -0
  61. package/scripts/research/manifests/agent-context-expanded-2026-03-22.mjs +17 -0
  62. package/scripts/research/sync-planner-context7-bundle.mjs +133 -0
  63. package/scripts/wave-orchestrator/agent-state.mjs +11 -2
  64. package/scripts/wave-orchestrator/artifact-schemas.mjs +232 -0
  65. package/scripts/wave-orchestrator/autonomous.mjs +7 -0
  66. package/scripts/wave-orchestrator/benchmark-cases.mjs +374 -0
  67. package/scripts/wave-orchestrator/benchmark-external.mjs +1384 -0
  68. package/scripts/wave-orchestrator/benchmark.mjs +972 -0
  69. package/scripts/wave-orchestrator/clarification-triage.mjs +78 -12
  70. package/scripts/wave-orchestrator/config.mjs +175 -0
  71. package/scripts/wave-orchestrator/control-cli.mjs +1216 -0
  72. package/scripts/wave-orchestrator/control-plane.mjs +697 -0
  73. package/scripts/wave-orchestrator/coord-cli.mjs +360 -2
  74. package/scripts/wave-orchestrator/coordination-store.mjs +211 -9
  75. package/scripts/wave-orchestrator/coordination.mjs +84 -0
  76. package/scripts/wave-orchestrator/dashboard-renderer.mjs +120 -5
  77. package/scripts/wave-orchestrator/dashboard-state.mjs +22 -0
  78. package/scripts/wave-orchestrator/evals.mjs +23 -0
  79. package/scripts/wave-orchestrator/executors.mjs +3 -2
  80. package/scripts/wave-orchestrator/feedback.mjs +55 -0
  81. package/scripts/wave-orchestrator/install.mjs +151 -2
  82. package/scripts/wave-orchestrator/launcher-closure.mjs +4 -1
  83. package/scripts/wave-orchestrator/launcher-runtime.mjs +33 -30
  84. package/scripts/wave-orchestrator/launcher.mjs +884 -36
  85. package/scripts/wave-orchestrator/planner-context.mjs +75 -0
  86. package/scripts/wave-orchestrator/planner.mjs +2270 -136
  87. package/scripts/wave-orchestrator/proof-cli.mjs +195 -0
  88. package/scripts/wave-orchestrator/proof-registry.mjs +317 -0
  89. package/scripts/wave-orchestrator/replay.mjs +10 -4
  90. package/scripts/wave-orchestrator/retry-cli.mjs +184 -0
  91. package/scripts/wave-orchestrator/retry-control.mjs +225 -0
  92. package/scripts/wave-orchestrator/shared.mjs +26 -0
  93. package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1004 -0
  94. package/scripts/wave-orchestrator/terminals.mjs +1 -1
  95. package/scripts/wave-orchestrator/traces.mjs +157 -2
  96. package/scripts/wave-orchestrator/wave-control-client.mjs +532 -0
  97. package/scripts/wave-orchestrator/wave-control-schema.mjs +309 -0
  98. package/scripts/wave-orchestrator/wave-files.mjs +144 -23
  99. package/scripts/wave.mjs +27 -0
  100. package/skills/repo-coding-rules/SKILL.md +1 -0
  101. package/skills/role-cont-eval/SKILL.md +1 -0
  102. package/skills/role-cont-qa/SKILL.md +13 -6
  103. package/skills/role-deploy/SKILL.md +1 -0
  104. package/skills/role-documentation/SKILL.md +4 -0
  105. package/skills/role-implementation/SKILL.md +4 -0
  106. package/skills/role-infra/SKILL.md +2 -1
  107. package/skills/role-integration/SKILL.md +15 -8
  108. package/skills/role-planner/SKILL.md +39 -0
  109. package/skills/role-planner/skill.json +21 -0
  110. package/skills/role-research/SKILL.md +1 -0
  111. package/skills/role-security/SKILL.md +2 -2
  112. package/skills/runtime-claude/SKILL.md +2 -1
  113. package/skills/runtime-codex/SKILL.md +1 -0
  114. package/skills/runtime-local/SKILL.md +2 -0
  115. package/skills/runtime-opencode/SKILL.md +1 -0
  116. package/skills/wave-core/SKILL.md +25 -6
  117. package/skills/wave-core/references/marker-syntax.md +16 -8
  118. package/wave.config.json +45 -0
@@ -1,3 +1,4 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
2
3
  import { buildDocsQueue, readDocsQueue, writeDocsQueue } from "./docs-queue.mjs";
3
4
  import { readWaveLedger, writeWaveLedger } from "./ledger.mjs";
@@ -8,8 +9,11 @@ import {
8
9
  } from "./routing-state.mjs";
9
10
  import {
10
11
  appendCoordinationRecord,
12
+ clarificationClosureCondition,
13
+ clarificationLinkedRequests,
11
14
  compileAgentInbox,
12
15
  compileSharedSummary,
16
+ isOpenCoordinationStatus,
13
17
  readJsonArtifact,
14
18
  readMaterializedCoordinationState,
15
19
  serializeCoordinationState,
@@ -18,6 +22,14 @@ import {
18
22
  writeCoordinationBoardProjection,
19
23
  writeJsonArtifact,
20
24
  } from "./coordination-store.mjs";
25
+ import { answerFeedbackRequest } from "./feedback.mjs";
26
+ import { readWaveHumanFeedbackRequests } from "./coordination.mjs";
27
+ import { readWaveProofRegistry } from "./proof-registry.mjs";
28
+ import {
29
+ readWaveRelaunchPlanSnapshot,
30
+ readWaveRetryOverride,
31
+ resolveRetryOverrideAgentIds,
32
+ } from "./retry-control.mjs";
21
33
  import { writeAssignmentSnapshot, writeDependencySnapshot } from "./artifact-schemas.mjs";
22
34
  import {
23
35
  buildLanePaths,
@@ -35,6 +47,8 @@ function printUsage() {
35
47
  wave coord show --lane <lane> --wave <n> [--dry-run] [--json]
36
48
  wave coord render --lane <lane> --wave <n> [--dry-run]
37
49
  wave coord inbox --lane <lane> --wave <n> --agent <id> [--dry-run]
50
+ wave coord explain --lane <lane> --wave <n> [--agent <id>] [--json]
51
+ wave coord act <resolve|dismiss|reroute|reassign|escalate|answer-human> --lane <lane> --wave <n> [options]
38
52
  wave coord <subcommand> --run <id> [--wave 0] ...
39
53
  `);
40
54
  }
@@ -56,9 +70,19 @@ function parseArgs(argv) {
56
70
  dependsOn: [],
57
71
  artifactRefs: [],
58
72
  status: "open",
73
+ id: "",
74
+ to: "",
75
+ response: "",
76
+ operator: "human-operator",
77
+ operation: "",
59
78
  json: false,
60
79
  };
61
- for (let i = 1; i < args.length; i += 1) {
80
+ let startIndex = 1;
81
+ if (subcommand === "act") {
82
+ options.operation = String(args[1] || "").trim().toLowerCase();
83
+ startIndex = 2;
84
+ }
85
+ for (let i = startIndex; i < args.length; i += 1) {
62
86
  const arg = args[i];
63
87
  if (arg === "--lane") {
64
88
  options.lane = String(args[++i] || "").trim();
@@ -84,6 +108,14 @@ function parseArgs(argv) {
84
108
  options.artifactRefs.push(String(args[++i] || "").trim());
85
109
  } else if (arg === "--status") {
86
110
  options.status = String(args[++i] || "").trim();
111
+ } else if (arg === "--id") {
112
+ options.id = String(args[++i] || "").trim();
113
+ } else if (arg === "--to") {
114
+ options.to = String(args[++i] || "").trim();
115
+ } else if (arg === "--response") {
116
+ options.response = String(args[++i] || "").trim();
117
+ } else if (arg === "--operator") {
118
+ options.operator = String(args[++i] || "").trim() || "human-operator";
87
119
  } else if (arg === "--json") {
88
120
  options.json = true;
89
121
  } else if (arg === "--dry-run") {
@@ -144,6 +176,147 @@ function integrationPath(lanePaths, waveNumber) {
144
176
  return path.join(lanePaths.integrationDir, `wave-${waveNumber}.json`);
145
177
  }
146
178
 
179
+ function coordinationTriagePath(lanePaths, waveNumber) {
180
+ return path.join(lanePaths.feedbackTriageDir, `wave-${waveNumber}.jsonl`);
181
+ }
182
+
183
+ function targetAgentId(target) {
184
+ const value = String(target || "").trim();
185
+ if (!value) {
186
+ return "";
187
+ }
188
+ return value.startsWith("agent:") ? value.slice("agent:".length) : value;
189
+ }
190
+
191
+ function recordTargetsAgent(record, agentId) {
192
+ return (
193
+ String(record?.agentId || "").trim() === agentId ||
194
+ (Array.isArray(record?.targets) &&
195
+ record.targets.some((target) => targetAgentId(target) === agentId))
196
+ );
197
+ }
198
+
199
+ function isLauncherSeedRequest(record) {
200
+ return (
201
+ record?.source === "launcher" &&
202
+ record?.kind === "request" &&
203
+ /^wave-\d+-agent-[^-]+-request$/.test(String(record?.id || "")) &&
204
+ (!Array.isArray(record?.dependsOn) || record.dependsOn.length === 0) &&
205
+ !String(record?.closureCondition || "").trim()
206
+ );
207
+ }
208
+
209
+ function summarizeExplainPayload({
210
+ lanePaths,
211
+ wave,
212
+ agentId = "",
213
+ state,
214
+ ledger,
215
+ capabilityAssignments,
216
+ dependencySnapshot,
217
+ feedbackRequests,
218
+ relaunchPlan,
219
+ retryOverride,
220
+ proofRegistry,
221
+ }) {
222
+ const scopedOpenRecords = (state?.openRecords || []).filter((record) =>
223
+ agentId ? recordTargetsAgent(record, agentId) : true,
224
+ );
225
+ const scopedAssignments = (capabilityAssignments || []).filter((assignment) =>
226
+ agentId ? assignment.assignedAgentId === agentId : assignment.blocking,
227
+ );
228
+ const scopedDependencies = [
229
+ ...((dependencySnapshot?.openInbound || []).filter((record) =>
230
+ agentId ? record.assignedAgentId === agentId : true,
231
+ )),
232
+ ...((dependencySnapshot?.openOutbound || []).filter((record) =>
233
+ agentId ? record.agentId === agentId : true,
234
+ )),
235
+ ];
236
+ const scopedFeedback = (feedbackRequests || []).filter((request) =>
237
+ agentId ? request.agentId === agentId : true,
238
+ );
239
+ const scopedProofEntries = (proofRegistry?.entries || []).filter((entry) =>
240
+ agentId ? entry.agentId === agentId : true,
241
+ );
242
+ const blockedBy = [];
243
+ if (
244
+ scopedOpenRecords.some(
245
+ (record) => record.kind === "clarification-request" && isOpenCoordinationStatus(record.status),
246
+ )
247
+ ) {
248
+ blockedBy.push("open clarification chain");
249
+ }
250
+ if (scopedAssignments.some((assignment) => assignment.blocking)) {
251
+ blockedBy.push("blocking helper assignment");
252
+ }
253
+ if (scopedDependencies.length > 0) {
254
+ blockedBy.push("open dependency");
255
+ }
256
+ if (scopedFeedback.some((request) => request.status === "pending")) {
257
+ blockedBy.push("pending human feedback");
258
+ }
259
+ if (
260
+ (state?.humanEscalations || []).some(
261
+ (record) => isOpenCoordinationStatus(record.status) && (!agentId || recordTargetsAgent(record, agentId)),
262
+ )
263
+ ) {
264
+ blockedBy.push("open human escalation");
265
+ }
266
+ if (
267
+ scopedOpenRecords.some(
268
+ (record) =>
269
+ record.kind === "request" &&
270
+ isOpenCoordinationStatus(record.status) &&
271
+ !isLauncherSeedRequest(record),
272
+ )
273
+ ) {
274
+ blockedBy.push("targeted open request");
275
+ }
276
+ return {
277
+ lane: lanePaths.lane,
278
+ wave: wave.wave,
279
+ phase: ledger?.phase || "unknown",
280
+ agentId: agentId || null,
281
+ blockedBy,
282
+ openCoordination: scopedOpenRecords.map((record) => ({
283
+ id: record.id,
284
+ kind: record.kind,
285
+ status: record.status,
286
+ agentId: record.agentId,
287
+ targets: record.targets || [],
288
+ summary: record.summary || record.detail || "",
289
+ })),
290
+ helperAssignments: scopedAssignments,
291
+ dependencies: scopedDependencies,
292
+ humanFeedback: scopedFeedback,
293
+ relaunchPlan,
294
+ retryOverride,
295
+ effectiveRetryTargets: resolveRetryOverrideAgentIds(wave, lanePaths, retryOverride).length > 0
296
+ ? resolveRetryOverrideAgentIds(wave, lanePaths, retryOverride)
297
+ : relaunchPlan?.selectedAgentIds || [],
298
+ proofEntries: scopedProofEntries,
299
+ };
300
+ }
301
+
302
+ function appendCoordinationStatusUpdate(logPath, record, status, options = {}) {
303
+ return appendCoordinationRecord(logPath, {
304
+ ...record,
305
+ status,
306
+ summary: options.summary || record.summary,
307
+ detail: options.detail || record.detail,
308
+ source: options.source || "operator",
309
+ });
310
+ }
311
+
312
+ function appendTriageEscalationUpdateIfPresent(lanePaths, waveNumber, record) {
313
+ const triagePath = coordinationTriagePath(lanePaths, waveNumber);
314
+ if (!fs.existsSync(triagePath) || record?.kind !== "human-escalation") {
315
+ return;
316
+ }
317
+ appendCoordinationRecord(triagePath, record);
318
+ }
319
+
147
320
  export async function runCoordinationCli(argv) {
148
321
  if (argv.includes("--help") || argv.includes("-h")) {
149
322
  printUsage();
@@ -176,13 +349,59 @@ export async function runCoordinationCli(argv) {
176
349
  }
177
350
  return;
178
351
  }
352
+ if (subcommand === "explain") {
353
+ const state = readMaterializedCoordinationState(logPath);
354
+ const ledger = readWaveLedger(ledgerPath(lanePaths, wave.wave)) || { phase: "planned" };
355
+ const capabilityAssignments = buildRequestAssignments({
356
+ coordinationState: state,
357
+ agents: wave.agents,
358
+ ledger,
359
+ capabilityRouting: lanePaths.capabilityRouting,
360
+ });
361
+ const dependencySnapshot = buildDependencySnapshot({
362
+ dirPath: lanePaths.crossLaneDependenciesDir,
363
+ lane: lanePaths.lane,
364
+ waveNumber: wave.wave,
365
+ agents: wave.agents,
366
+ ledger,
367
+ capabilityRouting: lanePaths.capabilityRouting,
368
+ });
369
+ const feedbackRequests = readWaveHumanFeedbackRequests({
370
+ feedbackRequestsDir: lanePaths.feedbackRequestsDir,
371
+ lane: lanePaths.lane,
372
+ waveNumber: wave.wave,
373
+ agentIds: wave.agents.map((agent) => agent.agentId),
374
+ orchestratorId: "",
375
+ });
376
+ const payload = summarizeExplainPayload({
377
+ lanePaths,
378
+ wave,
379
+ agentId: options.agent || "",
380
+ state,
381
+ ledger,
382
+ capabilityAssignments,
383
+ dependencySnapshot,
384
+ feedbackRequests,
385
+ relaunchPlan: readWaveRelaunchPlanSnapshot(lanePaths, wave.wave),
386
+ retryOverride: readWaveRetryOverride(lanePaths, wave.wave),
387
+ proofRegistry: readWaveProofRegistry(lanePaths, wave.wave),
388
+ });
389
+ if (options.json) {
390
+ console.log(JSON.stringify(payload, null, 2));
391
+ } else {
392
+ console.log(JSON.stringify(payload, null, 2));
393
+ }
394
+ return;
395
+ }
179
396
  ensureDirectory(lanePaths.coordinationDir);
397
+ ensureDirectory(lanePaths.controlDir);
180
398
  ensureDirectory(lanePaths.assignmentsDir);
181
399
  ensureDirectory(lanePaths.inboxesDir);
182
400
  ensureDirectory(lanePaths.messageboardsDir);
183
401
  ensureDirectory(lanePaths.docsQueueDir);
184
402
  ensureDirectory(lanePaths.ledgerDir);
185
403
  ensureDirectory(lanePaths.integrationDir);
404
+ ensureDirectory(lanePaths.proofDir);
186
405
  ensureDirectory(lanePaths.dependencySnapshotsDir);
187
406
  updateSeedRecords(logPath, {
188
407
  lane: lanePaths.lane,
@@ -194,7 +413,13 @@ export async function runCoordinationCli(argv) {
194
413
  contEvalAgentId: lanePaths.contEvalAgentId,
195
414
  integrationAgentId: lanePaths.integrationAgentId,
196
415
  documentationAgentId: lanePaths.documentationAgentId,
197
- feedbackRequests: [],
416
+ feedbackRequests: readWaveHumanFeedbackRequests({
417
+ feedbackRequestsDir: lanePaths.feedbackRequestsDir,
418
+ lane: lanePaths.lane,
419
+ waveNumber: wave.wave,
420
+ agentIds: wave.agents.map((agent) => agent.agentId),
421
+ orchestratorId: "",
422
+ }),
198
423
  });
199
424
  if (subcommand === "post") {
200
425
  if (!options.agent || !options.kind || !options.summary) {
@@ -217,6 +442,139 @@ export async function runCoordinationCli(argv) {
217
442
  console.log(JSON.stringify(record, null, 2));
218
443
  return;
219
444
  }
445
+ if (subcommand === "act") {
446
+ if (!options.operation) {
447
+ throw new Error("act requires an operation");
448
+ }
449
+ if (options.operation === "answer-human") {
450
+ if (!options.id || !options.response) {
451
+ throw new Error("answer-human requires --id and --response");
452
+ }
453
+ const answered = answerFeedbackRequest({
454
+ feedbackStateDir: lanePaths.feedbackStateDir,
455
+ feedbackRequestsDir: lanePaths.feedbackRequestsDir,
456
+ requestId: options.id,
457
+ response: options.response,
458
+ operator: options.operator,
459
+ force: true,
460
+ recordTelemetry: true,
461
+ });
462
+ console.log(JSON.stringify(answered, null, 2));
463
+ return;
464
+ }
465
+ if (!options.id) {
466
+ throw new Error("act requires --id");
467
+ }
468
+ const state = readMaterializedCoordinationState(logPath);
469
+ const record = state.byId.get(options.id);
470
+ if (!record) {
471
+ throw new Error(`Coordination record not found: ${options.id}`);
472
+ }
473
+ if (options.operation === "resolve" || options.operation === "dismiss") {
474
+ const nextStatus = options.operation === "resolve" ? "resolved" : "cancelled";
475
+ const updated = appendCoordinationStatusUpdate(logPath, record, nextStatus, {
476
+ detail: options.detail || record.detail,
477
+ summary: options.summary || record.summary,
478
+ });
479
+ if (record.kind === "clarification-request") {
480
+ const linkedRequests = clarificationLinkedRequests(state, record.id).filter((entry) =>
481
+ isOpenCoordinationStatus(entry.status),
482
+ );
483
+ for (const linked of linkedRequests) {
484
+ appendCoordinationStatusUpdate(logPath, linked, nextStatus, {
485
+ detail:
486
+ options.detail ||
487
+ `${options.operation === "resolve" ? "Resolved" : "Cancelled"} via clarification ${record.id}.`,
488
+ summary: linked.summary,
489
+ });
490
+ }
491
+ for (const escalation of (state.humanEscalations || []).filter(
492
+ (entry) =>
493
+ isOpenCoordinationStatus(entry.status) &&
494
+ entry.closureCondition === clarificationClosureCondition(record.id),
495
+ )) {
496
+ const updatedEscalation = appendCoordinationStatusUpdate(logPath, escalation, nextStatus, {
497
+ detail:
498
+ options.detail ||
499
+ `${options.operation === "resolve" ? "Resolved" : "Cancelled"} via clarification ${record.id}.`,
500
+ summary: escalation.summary,
501
+ });
502
+ appendTriageEscalationUpdateIfPresent(lanePaths, wave.wave, updatedEscalation);
503
+ }
504
+ }
505
+ appendTriageEscalationUpdateIfPresent(lanePaths, wave.wave, updated);
506
+ console.log(JSON.stringify(updated, null, 2));
507
+ return;
508
+ }
509
+ if (options.operation === "reroute" || options.operation === "reassign") {
510
+ if (!options.to) {
511
+ throw new Error(`${options.operation} requires --to`);
512
+ }
513
+ const closureCondition =
514
+ record.kind === "clarification-request"
515
+ ? clarificationClosureCondition(record.id)
516
+ : record.closureCondition || "";
517
+ appendCoordinationStatusUpdate(logPath, record, "superseded", {
518
+ detail:
519
+ options.detail ||
520
+ `${record.id} superseded by operator ${options.operation} to ${options.to}.`,
521
+ summary: record.summary,
522
+ });
523
+ const rerouted = appendCoordinationRecord(logPath, {
524
+ lane: lanePaths.lane,
525
+ wave: wave.wave,
526
+ agentId: options.agent || "operator",
527
+ kind: "request",
528
+ targets: [`agent:${options.to}`],
529
+ priority: record.priority,
530
+ artifactRefs: record.artifactRefs,
531
+ dependsOn:
532
+ record.kind === "clarification-request"
533
+ ? [record.id]
534
+ : Array.from(new Set([record.id, ...(record.dependsOn || [])])),
535
+ closureCondition,
536
+ summary: record.summary,
537
+ detail:
538
+ options.detail ||
539
+ `${record.kind === "clarification-request" ? "Clarification" : "Request"} rerouted to ${options.to}.`,
540
+ status: "open",
541
+ source: "operator",
542
+ });
543
+ if (record.kind === "clarification-request") {
544
+ appendCoordinationStatusUpdate(logPath, record, "in_progress", {
545
+ detail: `Awaiting routed follow-up from ${options.to}.`,
546
+ summary: record.summary,
547
+ });
548
+ }
549
+ console.log(JSON.stringify(rerouted, null, 2));
550
+ return;
551
+ }
552
+ if (options.operation === "escalate") {
553
+ const escalation = appendCoordinationRecord(logPath, {
554
+ id: `escalation-${record.id}`,
555
+ lane: lanePaths.lane,
556
+ wave: wave.wave,
557
+ agentId: options.agent || "operator",
558
+ kind: "human-escalation",
559
+ targets: record.targets,
560
+ priority: "high",
561
+ artifactRefs: record.artifactRefs,
562
+ dependsOn: [record.id],
563
+ closureCondition:
564
+ record.kind === "clarification-request"
565
+ ? clarificationClosureCondition(record.id)
566
+ : record.closureCondition || "",
567
+ summary: record.summary,
568
+ detail: options.detail || record.detail,
569
+ status: "open",
570
+ source: "operator",
571
+ });
572
+ appendTriageEscalationUpdateIfPresent(lanePaths, wave.wave, escalation);
573
+ console.log(JSON.stringify(escalation, null, 2));
574
+ return;
575
+ }
576
+ throw new Error(`Unknown coord action: ${options.operation}`);
577
+ }
220
578
  const state = readMaterializedCoordinationState(logPath);
221
579
  const queue =
222
580
  readDocsQueue(docsQueuePath(lanePaths, wave.wave)) ||