@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
@@ -351,6 +351,12 @@ export function loadBenchmarkCatalog(options = {}) {
351
351
  id: benchmarkId,
352
352
  title: cleanText(benchmark.title) || benchmarkId,
353
353
  summary: cleanText(benchmark.summary) || null,
354
+ localCases: normalizeStringArray(
355
+ benchmark.localCases,
356
+ `families.${familyId}.benchmarks.${benchmarkId}.localCases`,
357
+ ).map((entry, index) =>
358
+ normalizeEvalTargetId(entry, `families.${familyId}.benchmarks.${benchmarkId}.localCases[${index}]`),
359
+ ),
354
360
  goal: cleanText(benchmark.goal) || null,
355
361
  failureModes: normalizeStringArray(
356
362
  benchmark.failureModes,
@@ -380,6 +386,12 @@ export function loadBenchmarkCatalog(options = {}) {
380
386
  id: familyId,
381
387
  title: cleanText(rawFamily.title) || familyId,
382
388
  summary: cleanText(rawFamily.summary) || null,
389
+ localCases: normalizeStringArray(
390
+ rawFamily.localCases,
391
+ `families.${familyId}.localCases`,
392
+ ).map((entry, index) =>
393
+ normalizeEvalTargetId(entry, `families.${familyId}.localCases[${index}]`),
394
+ ),
383
395
  category: cleanText(rawFamily.category) || null,
384
396
  coordinationModel: cleanText(rawFamily.coordinationModel) || null,
385
397
  primaryMetric: familyPrimaryMetric,
@@ -395,6 +407,17 @@ export function loadBenchmarkCatalog(options = {}) {
395
407
  absolutePath,
396
408
  families,
397
409
  benchmarkIndex,
410
+ localCaseIndex: Object.fromEntries(
411
+ Object.values(families).flatMap((family) => [
412
+ ...(family.localCases || []).map((caseId) => [caseId, { familyId: family.id, benchmarkId: null }]),
413
+ ...Object.values(family.benchmarks).flatMap((benchmark) =>
414
+ (benchmark.localCases || []).map((caseId) => [
415
+ caseId,
416
+ { familyId: family.id, benchmarkId: benchmark.id },
417
+ ]),
418
+ ),
419
+ ]),
420
+ ),
398
421
  };
399
422
  }
400
423
 
@@ -210,7 +210,8 @@ function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
210
210
  systemPromptPath,
211
211
  `${renderHarnessSystemPrompt(agent, "claude")}${skillText ? `\n\n${skillText}` : ""}\n`,
212
212
  );
213
- const tokens = [executor.claude.command, "-p", "--no-session-persistence"];
213
+ const command = executor?.claude?.command || "claude";
214
+ const tokens = [command, "-p", "--no-session-persistence"];
214
215
  const settingsPath = buildClaudeSettingsPath(executor, overlayDir);
215
216
  appendSingleValueFlag(tokens, "--output-format", executor.claude.outputFormat || "text");
216
217
  appendSingleValueFlag(tokens, "--model", executor.claude.model || executor.model);
@@ -234,7 +235,7 @@ function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
234
235
  );
235
236
  return {
236
237
  executorId: "claude",
237
- command: executor.claude.command,
238
+ command,
238
239
  useRateLimitRetries: true,
239
240
  invocationLines: [
240
241
  `task_prompt=$(cat ${shellQuote(promptPath)})`,
@@ -21,6 +21,7 @@ import {
21
21
  truncate,
22
22
  writeJsonAtomic,
23
23
  } from "./shared.mjs";
24
+ import { safeQueueWaveControlEvent } from "./wave-control-client.mjs";
24
25
 
25
26
  function sanitizeToken(value) {
26
27
  const token = String(value || "")
@@ -59,6 +60,7 @@ export function createFeedbackRequest({
59
60
  orchestratorId,
60
61
  question,
61
62
  context,
63
+ recordTelemetry = false,
62
64
  }) {
63
65
  ensureDirectory(feedbackRequestsDir);
64
66
  const requestId = buildRequestId({ lane, wave, agentId });
@@ -83,6 +85,31 @@ export function createFeedbackRequest({
83
85
  }
84
86
  writeJsonAtomic(filePath, payload);
85
87
  });
88
+ if (recordTelemetry) {
89
+ try {
90
+ const lanePaths = buildLanePaths(lane);
91
+ safeQueueWaveControlEvent(lanePaths, {
92
+ category: "feedback",
93
+ entityType: "human_input",
94
+ entityId: requestId,
95
+ action: "requested",
96
+ source: "orchestrator",
97
+ actor: orchestratorId || "orchestrator",
98
+ recordedAt: now,
99
+ identity: {
100
+ lane,
101
+ wave,
102
+ agentId,
103
+ runKind: lanePaths.runKind,
104
+ runId: lanePaths.runId,
105
+ },
106
+ tags: ["feedback", "human-input"],
107
+ data: payload,
108
+ });
109
+ } catch {
110
+ // Best-effort telemetry only.
111
+ }
112
+ }
86
113
  return { requestId, filePath, payload };
87
114
  }
88
115
 
@@ -93,6 +120,7 @@ export function answerFeedbackRequest({
93
120
  response,
94
121
  operator = "human-operator",
95
122
  force = false,
123
+ recordTelemetry = false,
96
124
  }) {
97
125
  const lockPath = path.join(feedbackStateDir, "requests.lock");
98
126
  let answeredPayload = null;
@@ -117,6 +145,31 @@ export function answerFeedbackRequest({
117
145
  };
118
146
  writeJsonAtomic(filePath, answeredPayload);
119
147
  });
148
+ if (recordTelemetry) {
149
+ try {
150
+ const lanePaths = buildLanePaths(answeredPayload?.lane || DEFAULT_WAVE_LANE);
151
+ safeQueueWaveControlEvent(lanePaths, {
152
+ category: "feedback",
153
+ entityType: "human_input",
154
+ entityId: answeredPayload.id,
155
+ action: "answered",
156
+ source: "operator",
157
+ actor: operator,
158
+ recordedAt: answeredPayload?.updatedAt || toIsoTimestamp(),
159
+ identity: {
160
+ lane: answeredPayload?.lane || DEFAULT_WAVE_LANE,
161
+ wave: answeredPayload?.wave ?? null,
162
+ agentId: answeredPayload?.agentId || null,
163
+ runKind: lanePaths.runKind,
164
+ runId: lanePaths.runId,
165
+ },
166
+ tags: ["feedback", "human-input", "answered"],
167
+ data: answeredPayload,
168
+ });
169
+ } catch {
170
+ // Best-effort telemetry only.
171
+ }
172
+ }
120
173
  return answeredPayload;
121
174
  }
122
175
 
@@ -292,6 +345,7 @@ export async function runFeedbackCli(argv) {
292
345
  orchestratorId: options.orchestratorId,
293
346
  question: options.question,
294
347
  context: options.context,
348
+ recordTelemetry: true,
295
349
  });
296
350
  console.log(`[wave-human-feedback] created ${result.requestId}`);
297
351
  console.log(`file: ${path.relative(REPO_ROOT, result.filePath)}`);
@@ -316,6 +370,7 @@ export async function runFeedbackCli(argv) {
316
370
  response: options.response,
317
371
  operator: options.operator,
318
372
  force: options.force,
373
+ recordTelemetry: true,
319
374
  });
320
375
  console.log(`[wave-human-feedback] answered ${options.id}`);
321
376
  return;
@@ -5,6 +5,9 @@ import {
5
5
  applyContext7SelectionsToWave,
6
6
  loadContext7BundleIndex,
7
7
  } from "./context7.mjs";
8
+ import {
9
+ PLANNER_CONTEXT7_TEMPLATE_PATHS,
10
+ } from "./planner-context.mjs";
8
11
  import { buildLanePaths, ensureDirectory, PACKAGE_ROOT, readJsonOrNull, REPO_ROOT, writeJsonAtomic } from "./shared.mjs";
9
12
  import { fetchLatestPackageVersion } from "./package-update-notice.mjs";
10
13
  import {
@@ -29,6 +32,7 @@ export const STARTER_TEMPLATE_PATHS = [
29
32
  "docs/agents/wave-cont-qa-role.md",
30
33
  "docs/agents/wave-cont-eval-role.md",
31
34
  "docs/agents/wave-integration-role.md",
35
+ "docs/agents/wave-planner-role.md",
32
36
  "docs/agents/wave-security-role.md",
33
37
  "docs/concepts/context7-vs-skills.md",
34
38
  "docs/concepts/operating-modes.md",
@@ -36,23 +40,48 @@ export const STARTER_TEMPLATE_PATHS = [
36
40
  "docs/concepts/what-is-a-wave.md",
37
41
  "docs/context7/bundles.json",
38
42
  "docs/evals/benchmark-catalog.json",
43
+ "docs/evals/external-benchmarks.json",
44
+ "docs/evals/external-command-config.sample.json",
45
+ "docs/evals/external-command-config.swe-bench-pro.json",
46
+ "docs/evals/wave-benchmark-program.md",
47
+ "docs/evals/pilots/README.md",
48
+ "docs/evals/pilots/swe-bench-pro-public-pilot.json",
49
+ "docs/evals/pilots/swe-bench-pro-public-full-wave-review-10.json",
50
+ "docs/evals/arm-templates/README.md",
51
+ "docs/evals/arm-templates/single-agent.json",
52
+ "docs/evals/arm-templates/full-wave.json",
53
+ "docs/evals/cases/README.md",
54
+ "docs/evals/cases/wave-hidden-profile-private-evidence.json",
55
+ "docs/evals/cases/wave-premature-closure-guard.json",
56
+ "docs/evals/cases/wave-silo-cross-agent-state.json",
57
+ "docs/evals/cases/wave-blackboard-inbox-targeting.json",
58
+ "docs/evals/cases/wave-contradiction-conflict.json",
59
+ "docs/evals/cases/wave-simultaneous-lockstep.json",
60
+ "docs/evals/cases/wave-expert-routing-preservation.json",
39
61
  "docs/guides/planner.md",
40
62
  "docs/guides/terminal-surfaces.md",
41
63
  "docs/plans/component-cutover-matrix.json",
42
64
  "docs/plans/component-cutover-matrix.md",
43
65
  "docs/plans/context7-wave-orchestrator.md",
44
66
  "docs/plans/current-state.md",
67
+ "docs/plans/examples/wave-example-live-proof.md",
45
68
  "docs/plans/master-plan.md",
46
69
  "docs/plans/migration.md",
47
70
  "docs/plans/wave-orchestrator.md",
48
71
  "docs/plans/waves/wave-0.md",
72
+ "docs/reference/live-proof-waves.md",
49
73
  "docs/reference/repository-guidance.md",
74
+ "docs/reference/sample-waves.md",
50
75
  "docs/reference/skills.md",
76
+ "docs/reference/wave-planning-lessons.md",
51
77
  "docs/reference/runtime-config/README.md",
52
78
  "docs/reference/runtime-config/codex.md",
53
79
  "docs/reference/runtime-config/claude.md",
54
80
  "docs/reference/runtime-config/opencode.md",
81
+ "docs/research/coordination-failure-review.md",
55
82
  "docs/research/agent-context-sources.md",
83
+ "docs/plans/examples/wave-benchmark-improvement.md",
84
+ ...PLANNER_CONTEXT7_TEMPLATE_PATHS,
56
85
  ];
57
86
  const REQUIRED_GITIGNORE_ENTRIES = [
58
87
  ".tmp/",
@@ -63,6 +92,33 @@ const REQUIRED_GITIGNORE_ENTRIES = [
63
92
  "docs/research/papers/",
64
93
  "docs/research/articles/",
65
94
  ];
95
+ const PLANNER_MIGRATION_REQUIRED_SURFACES = [
96
+ {
97
+ id: "planner-role",
98
+ label: "docs/agents/wave-planner-role.md",
99
+ path: "docs/agents/wave-planner-role.md",
100
+ kind: "file",
101
+ },
102
+ {
103
+ id: "planner-skill",
104
+ label: "skills/role-planner/",
105
+ path: "skills/role-planner",
106
+ kind: "dir",
107
+ },
108
+ {
109
+ id: "planner-context7",
110
+ label: "docs/context7/planner-agent/",
111
+ path: "docs/context7/planner-agent",
112
+ kind: "dir",
113
+ },
114
+ {
115
+ id: "planner-lessons",
116
+ label: "docs/reference/wave-planning-lessons.md",
117
+ path: "docs/reference/wave-planning-lessons.md",
118
+ kind: "file",
119
+ },
120
+ ];
121
+ const PLANNER_REQUIRED_BUNDLE_ID = "planner-agentic";
66
122
 
67
123
  function collectDeclaredDeployKinds(waves = []) {
68
124
  return Array.from(
@@ -193,6 +249,8 @@ function slugifyVersion(value) {
193
249
  }
194
250
 
195
251
  function formatUpgradeReport(report) {
252
+ const plannerMigrationErrors = report.doctor.errors.filter((issue) => isPlannerMigrationIssue(issue));
253
+ const otherDoctorErrors = report.doctor.errors.filter((issue) => !isPlannerMigrationIssue(issue));
196
254
  return [
197
255
  `# Wave Upgrade Report`,
198
256
  "",
@@ -209,12 +267,27 @@ function formatUpgradeReport(report) {
209
267
  "",
210
268
  "- No repo-owned plans, waves, role prompts, or config files were overwritten.",
211
269
  "- New runtime behavior comes from the installed package version.",
270
+ ...(report.initMode === "adopt-existing" && plannerMigrationErrors.length > 0
271
+ ? [
272
+ "",
273
+ "## Adopted Repo Follow-Up",
274
+ "",
275
+ "- This workspace was adopted from an existing repo-owned Wave surface.",
276
+ "- `wave upgrade` does not copy new planner starter docs, skills, or Context7 bundle entries into adopted repos.",
277
+ ...plannerMigrationErrors.map((issue) => `- Error: ${issue}`),
278
+ ]
279
+ : []),
280
+ ...(report.initMode === "adopt-existing" && plannerMigrationErrors.length > 0
281
+ ? [
282
+ "- After syncing that planner surface, rerun `pnpm exec wave doctor` before relying on `wave draft --agentic` or planner-aware validation.",
283
+ ]
284
+ : []),
212
285
  ...(report.doctor.errors.length > 0 || report.doctor.warnings.length > 0
213
286
  ? [
214
287
  "",
215
288
  "## Follow-Up",
216
289
  "",
217
- ...report.doctor.errors.map((issue) => `- Error: ${issue}`),
290
+ ...otherDoctorErrors.map((issue) => `- Error: ${issue}`),
218
291
  ...report.doctor.warnings.map((issue) => `- Warning: ${issue}`),
219
292
  ]
220
293
  : []),
@@ -233,6 +306,61 @@ function gitignoreWarnings() {
233
306
  );
234
307
  }
235
308
 
309
+ function plannerRequiredPaths() {
310
+ return Array.from(
311
+ new Set(
312
+ [
313
+ "docs/agents/wave-planner-role.md",
314
+ "docs/reference/wave-planning-lessons.md",
315
+ "skills/role-planner/SKILL.md",
316
+ ...PLANNER_CONTEXT7_TEMPLATE_PATHS,
317
+ ].filter(Boolean),
318
+ ),
319
+ ).sort();
320
+ }
321
+
322
+ function isPlannerMigrationIssue(issue) {
323
+ return String(issue || "").startsWith("Planner starter surface is incomplete");
324
+ }
325
+
326
+ function missingPlannerMigrationSurfaceLabels() {
327
+ const missing = [];
328
+ for (const surface of PLANNER_MIGRATION_REQUIRED_SURFACES) {
329
+ const targetPath = path.join(REPO_ROOT, surface.path);
330
+ if (!fs.existsSync(targetPath)) {
331
+ missing.push(surface.label);
332
+ continue;
333
+ }
334
+ if (surface.kind === "dir") {
335
+ try {
336
+ if (fs.readdirSync(targetPath).length === 0) {
337
+ missing.push(surface.label);
338
+ }
339
+ } catch {
340
+ missing.push(surface.label);
341
+ }
342
+ }
343
+ }
344
+ return missing;
345
+ }
346
+
347
+ function plannerMigrationIssue(config, context7BundleIndex) {
348
+ const missing = missingPlannerMigrationSurfaceLabels();
349
+ const bundleId = String(config?.planner?.agentic?.context7Bundle || "").trim();
350
+ const bundleEntryMissing =
351
+ bundleId === "" || bundleId === PLANNER_REQUIRED_BUNDLE_ID
352
+ ? !context7BundleIndex?.bundles?.[PLANNER_REQUIRED_BUNDLE_ID]
353
+ : false;
354
+ if (missing.length === 0 && !bundleEntryMissing) {
355
+ return null;
356
+ }
357
+ const remediationItems = missing.slice();
358
+ if (bundleEntryMissing) {
359
+ remediationItems.push(`docs/context7/bundles.json#${PLANNER_REQUIRED_BUNDLE_ID}`);
360
+ }
361
+ return `Planner starter surface is incomplete for 0.7.x workspaces. Sync ${remediationItems.join(", ")} from the packaged release, then rerun \`pnpm exec wave doctor\`.`;
362
+ }
363
+
236
364
  export function runDoctor() {
237
365
  const errors = [];
238
366
  const warnings = [];
@@ -277,9 +405,29 @@ export function runDoctor() {
277
405
  errors.push(`Missing required Wave file: ${relPath}`);
278
406
  }
279
407
  }
408
+ const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
409
+ const plannerMigration = plannerMigrationIssue(config, context7BundleIndex);
410
+ if (plannerMigration) {
411
+ errors.push(plannerMigration);
412
+ }
413
+ const plannerPaths = plannerRequiredPaths();
414
+ for (const relPath of plannerPaths) {
415
+ if (!fs.existsSync(path.join(REPO_ROOT, relPath)) && !plannerMigration) {
416
+ errors.push(`Missing planner file: ${relPath}`);
417
+ }
418
+ }
419
+ const plannerBundleId = String(config.planner?.agentic?.context7Bundle || "").trim();
420
+ if (
421
+ plannerBundleId &&
422
+ !context7BundleIndex.bundles[plannerBundleId] &&
423
+ !(plannerMigration && plannerBundleId === PLANNER_REQUIRED_BUNDLE_ID)
424
+ ) {
425
+ errors.push(
426
+ `planner.agentic.context7Bundle references unknown bundle "${plannerBundleId}".`,
427
+ );
428
+ }
280
429
  let parsedWaves = [];
281
430
  if (fs.existsSync(lanePaths.wavesDir)) {
282
- const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
283
431
  parsedWaves = parseWaveFiles(lanePaths.wavesDir, { laneProfile: lanePaths.laneProfile })
284
432
  .map((wave) =>
285
433
  applyExecutorSelectionsToWave(wave, {
@@ -430,6 +578,7 @@ export function upgradeWorkspace() {
430
578
  previousVersion,
431
579
  currentVersion: metadata.version,
432
580
  generatedAt,
581
+ initMode: existingState.initMode || null,
433
582
  releases,
434
583
  doctor,
435
584
  };
@@ -201,7 +201,7 @@ export async function runClosureSweepPhase({
201
201
  refreshWaveDashboardAgentStates(dashboardState, [runInfo], pendingAgentIds, (event) =>
202
202
  recordCombinedEvent(event),
203
203
  );
204
- monitorWaveHumanFeedbackFn({
204
+ const feedbackChanged = monitorWaveHumanFeedbackFn({
205
205
  lanePaths,
206
206
  waveNumber: wave.wave,
207
207
  agentRuns: [runInfo],
@@ -211,6 +211,9 @@ export async function runClosureSweepPhase({
211
211
  recordCombinedEvent,
212
212
  appendCoordination,
213
213
  });
214
+ if (feedbackChanged) {
215
+ refreshDerivedState?.(dashboardState?.attempt || 0);
216
+ }
214
217
  updateWaveDashboardMessageBoard(dashboardState, runInfo.messageBoardPath);
215
218
  flushDashboards();
216
219
  },
@@ -69,6 +69,7 @@ export async function launchAgentSession(lanePaths, params, { runTmuxFn }) {
69
69
  sharedSummaryText,
70
70
  inboxPath,
71
71
  inboxText,
72
+ promptOverride = "",
72
73
  orchestratorId,
73
74
  agentRateLimitRetries,
74
75
  agentRateLimitBaseDelaySeconds,
@@ -101,27 +102,29 @@ export async function launchAgentSession(lanePaths, params, { runTmuxFn }) {
101
102
  artifacts: skillArtifacts,
102
103
  };
103
104
  }
104
- const prompt = buildExecutionPrompt({
105
- lane: lanePaths.lane,
106
- wave,
107
- agent,
108
- orchestratorId,
109
- messageBoardPath,
110
- messageBoardSnapshot,
111
- sharedSummaryPath,
112
- sharedSummaryText,
113
- inboxPath,
114
- inboxText,
115
- context7,
116
- componentPromotions: resolvedWaveDefinition.componentPromotions,
117
- evalTargets: resolvedWaveDefinition.evalTargets,
118
- benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
119
- sharedPlanDocs: lanePaths.sharedPlanDocs,
120
- contQaAgentId: lanePaths.contQaAgentId,
121
- contEvalAgentId: lanePaths.contEvalAgentId,
122
- integrationAgentId: lanePaths.integrationAgentId,
123
- documentationAgentId: lanePaths.documentationAgentId,
124
- });
105
+ const prompt =
106
+ String(promptOverride || "").trim() ||
107
+ buildExecutionPrompt({
108
+ lane: lanePaths.lane,
109
+ wave,
110
+ agent,
111
+ orchestratorId,
112
+ messageBoardPath,
113
+ messageBoardSnapshot,
114
+ sharedSummaryPath,
115
+ sharedSummaryText,
116
+ inboxPath,
117
+ inboxText,
118
+ context7,
119
+ componentPromotions: resolvedWaveDefinition.componentPromotions,
120
+ evalTargets: resolvedWaveDefinition.evalTargets,
121
+ benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
122
+ sharedPlanDocs: lanePaths.sharedPlanDocs,
123
+ contQaAgentId: lanePaths.contQaAgentId,
124
+ contEvalAgentId: lanePaths.contEvalAgentId,
125
+ integrationAgentId: lanePaths.integrationAgentId,
126
+ documentationAgentId: lanePaths.documentationAgentId,
127
+ });
125
128
  const promptHash = hashAgentPromptFingerprint(agent);
126
129
  fs.writeFileSync(promptPath, `${prompt}\n`, "utf8");
127
130
  const launchSpec = buildExecutorLaunchSpec({
@@ -132,16 +135,16 @@ export async function launchAgentSession(lanePaths, params, { runTmuxFn }) {
132
135
  skillProjection: agent.skillsResolved,
133
136
  });
134
137
  const resolvedExecutorMode = launchSpec.executorId || agent.executorResolved?.id || "codex";
138
+ writeJsonAtomic(path.join(overlayDir, "launch-preview.json"), {
139
+ executorId: resolvedExecutorMode,
140
+ command: launchSpec.command,
141
+ env: launchSpec.env || {},
142
+ useRateLimitRetries: launchSpec.useRateLimitRetries === true,
143
+ invocationLines: launchSpec.invocationLines,
144
+ limits: launchSpec.limits || null,
145
+ skills: summarizeResolvedSkills(agent.skillsResolved),
146
+ });
135
147
  if (dryRun) {
136
- writeJsonAtomic(path.join(overlayDir, "launch-preview.json"), {
137
- executorId: resolvedExecutorMode,
138
- command: launchSpec.command,
139
- env: launchSpec.env || {},
140
- useRateLimitRetries: launchSpec.useRateLimitRetries === true,
141
- invocationLines: launchSpec.invocationLines,
142
- limits: launchSpec.limits || null,
143
- skills: summarizeResolvedSkills(agent.skillsResolved),
144
- });
145
148
  return {
146
149
  promptHash,
147
150
  context7,