@chllming/wave-orchestration 0.6.2 → 0.7.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/README.md +44 -8
  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 +48 -11
  39. package/docs/plans/context7-wave-orchestrator.md +20 -0
  40. package/docs/plans/current-state.md +9 -1
  41. package/docs/plans/examples/wave-benchmark-improvement.md +108 -0
  42. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  43. package/docs/plans/examples/wave-example-rollout-fidelity.md +340 -0
  44. package/docs/plans/wave-orchestrator.md +73 -11
  45. package/docs/plans/waves/reviews/wave-1-benchmark-operator.md +118 -0
  46. package/docs/reference/coordination-and-closure.md +436 -0
  47. package/docs/reference/live-proof-waves.md +25 -3
  48. package/docs/reference/npmjs-trusted-publishing.md +3 -3
  49. package/docs/reference/proof-metrics.md +90 -0
  50. package/docs/reference/runtime-config/README.md +61 -0
  51. package/docs/reference/sample-waves.md +29 -18
  52. package/docs/reference/wave-control.md +164 -0
  53. package/docs/reference/wave-planning-lessons.md +131 -0
  54. package/package.json +5 -4
  55. package/releases/manifest.json +33 -0
  56. package/scripts/research/agent-context-archive.mjs +18 -0
  57. package/scripts/research/manifests/agent-context-expanded-2026-03-22.mjs +17 -0
  58. package/scripts/research/sync-planner-context7-bundle.mjs +133 -0
  59. package/scripts/wave-autonomous.mjs +2 -4
  60. package/scripts/wave-orchestrator/adhoc.mjs +32 -11
  61. package/scripts/wave-orchestrator/artifact-schemas.mjs +232 -0
  62. package/scripts/wave-orchestrator/autonomous.mjs +27 -6
  63. package/scripts/wave-orchestrator/benchmark-cases.mjs +374 -0
  64. package/scripts/wave-orchestrator/benchmark-external.mjs +1384 -0
  65. package/scripts/wave-orchestrator/benchmark.mjs +972 -0
  66. package/scripts/wave-orchestrator/clarification-triage.mjs +78 -12
  67. package/scripts/wave-orchestrator/config.mjs +175 -0
  68. package/scripts/wave-orchestrator/control-cli.mjs +1123 -0
  69. package/scripts/wave-orchestrator/control-plane.mjs +697 -0
  70. package/scripts/wave-orchestrator/coord-cli.mjs +360 -2
  71. package/scripts/wave-orchestrator/coordination-store.mjs +211 -9
  72. package/scripts/wave-orchestrator/coordination.mjs +84 -0
  73. package/scripts/wave-orchestrator/dashboard-renderer.mjs +38 -3
  74. package/scripts/wave-orchestrator/dashboard-state.mjs +22 -0
  75. package/scripts/wave-orchestrator/evals.mjs +23 -0
  76. package/scripts/wave-orchestrator/executors.mjs +3 -2
  77. package/scripts/wave-orchestrator/feedback.mjs +55 -0
  78. package/scripts/wave-orchestrator/install.mjs +253 -26
  79. package/scripts/wave-orchestrator/launcher-closure.mjs +4 -1
  80. package/scripts/wave-orchestrator/launcher-runtime.mjs +24 -21
  81. package/scripts/wave-orchestrator/launcher.mjs +800 -35
  82. package/scripts/wave-orchestrator/package-update-notice.mjs +230 -0
  83. package/scripts/wave-orchestrator/package-version.mjs +32 -0
  84. package/scripts/wave-orchestrator/planner-context.mjs +75 -0
  85. package/scripts/wave-orchestrator/planner.mjs +2270 -136
  86. package/scripts/wave-orchestrator/proof-cli.mjs +195 -0
  87. package/scripts/wave-orchestrator/proof-registry.mjs +317 -0
  88. package/scripts/wave-orchestrator/replay.mjs +10 -4
  89. package/scripts/wave-orchestrator/retry-cli.mjs +184 -0
  90. package/scripts/wave-orchestrator/retry-control.mjs +225 -0
  91. package/scripts/wave-orchestrator/shared.mjs +26 -0
  92. package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1004 -0
  93. package/scripts/wave-orchestrator/traces.mjs +157 -2
  94. package/scripts/wave-orchestrator/wave-control-client.mjs +532 -0
  95. package/scripts/wave-orchestrator/wave-control-schema.mjs +309 -0
  96. package/scripts/wave-orchestrator/wave-files.mjs +17 -5
  97. package/scripts/wave.mjs +39 -2
  98. package/skills/repo-coding-rules/SKILL.md +1 -0
  99. package/skills/role-cont-eval/SKILL.md +1 -0
  100. package/skills/role-cont-qa/SKILL.md +13 -6
  101. package/skills/role-deploy/SKILL.md +1 -0
  102. package/skills/role-documentation/SKILL.md +4 -0
  103. package/skills/role-implementation/SKILL.md +4 -0
  104. package/skills/role-infra/SKILL.md +2 -1
  105. package/skills/role-integration/SKILL.md +15 -8
  106. package/skills/role-planner/SKILL.md +39 -0
  107. package/skills/role-planner/skill.json +21 -0
  108. package/skills/role-research/SKILL.md +1 -0
  109. package/skills/role-security/SKILL.md +2 -2
  110. package/skills/runtime-claude/SKILL.md +2 -1
  111. package/skills/runtime-codex/SKILL.md +1 -0
  112. package/skills/runtime-local/SKILL.md +2 -0
  113. package/skills/runtime-opencode/SKILL.md +1 -0
  114. package/skills/wave-core/SKILL.md +25 -6
  115. package/skills/wave-core/references/marker-syntax.md +16 -8
  116. package/wave.config.json +45 -0
@@ -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;
@@ -1,10 +1,20 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { spawnSync } from "node:child_process";
3
4
  import {
4
5
  applyContext7SelectionsToWave,
5
6
  loadContext7BundleIndex,
6
7
  } from "./context7.mjs";
8
+ import {
9
+ PLANNER_CONTEXT7_TEMPLATE_PATHS,
10
+ } from "./planner-context.mjs";
7
11
  import { buildLanePaths, ensureDirectory, PACKAGE_ROOT, readJsonOrNull, REPO_ROOT, writeJsonAtomic } from "./shared.mjs";
12
+ import { fetchLatestPackageVersion } from "./package-update-notice.mjs";
13
+ import {
14
+ compareVersions,
15
+ readInstalledPackageMetadata,
16
+ WAVE_PACKAGE_NAME,
17
+ } from "./package-version.mjs";
8
18
  import { loadWaveConfig } from "./config.mjs";
9
19
  import { applyExecutorSelectionsToWave, parseWaveFiles, validateWaveDefinition } from "./wave-files.mjs";
10
20
  import { validateLaneSkillConfiguration } from "./skills.mjs";
@@ -14,7 +24,7 @@ export const INSTALL_STATE_DIR = ".wave";
14
24
  export const INSTALL_STATE_PATH = path.join(REPO_ROOT, INSTALL_STATE_DIR, "install-state.json");
15
25
  export const UPGRADE_HISTORY_DIR = path.join(REPO_ROOT, INSTALL_STATE_DIR, "upgrade-history");
16
26
  export const CHANGELOG_MANIFEST_PATH = path.join(PACKAGE_ROOT, "releases", "manifest.json");
17
- export const PACKAGE_METADATA_PATH = path.join(PACKAGE_ROOT, "package.json");
27
+ export const WORKSPACE_PACKAGE_JSON_PATH = path.join(REPO_ROOT, "package.json");
18
28
  export const STARTER_TEMPLATE_PATHS = [
19
29
  "wave.config.json",
20
30
  "docs/README.md",
@@ -22,6 +32,7 @@ export const STARTER_TEMPLATE_PATHS = [
22
32
  "docs/agents/wave-cont-qa-role.md",
23
33
  "docs/agents/wave-cont-eval-role.md",
24
34
  "docs/agents/wave-integration-role.md",
35
+ "docs/agents/wave-planner-role.md",
25
36
  "docs/agents/wave-security-role.md",
26
37
  "docs/concepts/context7-vs-skills.md",
27
38
  "docs/concepts/operating-modes.md",
@@ -29,23 +40,48 @@ export const STARTER_TEMPLATE_PATHS = [
29
40
  "docs/concepts/what-is-a-wave.md",
30
41
  "docs/context7/bundles.json",
31
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",
32
61
  "docs/guides/planner.md",
33
62
  "docs/guides/terminal-surfaces.md",
34
63
  "docs/plans/component-cutover-matrix.json",
35
64
  "docs/plans/component-cutover-matrix.md",
36
65
  "docs/plans/context7-wave-orchestrator.md",
37
66
  "docs/plans/current-state.md",
67
+ "docs/plans/examples/wave-example-live-proof.md",
38
68
  "docs/plans/master-plan.md",
39
69
  "docs/plans/migration.md",
40
70
  "docs/plans/wave-orchestrator.md",
41
71
  "docs/plans/waves/wave-0.md",
72
+ "docs/reference/live-proof-waves.md",
42
73
  "docs/reference/repository-guidance.md",
74
+ "docs/reference/sample-waves.md",
43
75
  "docs/reference/skills.md",
76
+ "docs/reference/wave-planning-lessons.md",
44
77
  "docs/reference/runtime-config/README.md",
45
78
  "docs/reference/runtime-config/codex.md",
46
79
  "docs/reference/runtime-config/claude.md",
47
80
  "docs/reference/runtime-config/opencode.md",
81
+ "docs/research/coordination-failure-review.md",
48
82
  "docs/research/agent-context-sources.md",
83
+ "docs/plans/examples/wave-benchmark-improvement.md",
84
+ ...PLANNER_CONTEXT7_TEMPLATE_PATHS,
49
85
  ];
50
86
  const REQUIRED_GITIGNORE_ENTRIES = [
51
87
  ".tmp/",
@@ -69,11 +105,7 @@ function collectDeclaredDeployKinds(waves = []) {
69
105
  }
70
106
 
71
107
  function packageMetadata() {
72
- const payload = readJsonOrNull(PACKAGE_METADATA_PATH);
73
- if (!payload?.name || !payload?.version) {
74
- throw new Error(`Invalid package metadata: ${PACKAGE_METADATA_PATH}`);
75
- }
76
- return payload;
108
+ return readInstalledPackageMetadata();
77
109
  }
78
110
 
79
111
  function readInstallState() {
@@ -149,25 +181,6 @@ function nextHistoryRecord(existingState, entry) {
149
181
  return history;
150
182
  }
151
183
 
152
- function normalizeVersionParts(version) {
153
- return String(version || "")
154
- .split(".")
155
- .map((part) => Number.parseInt(part.replace(/[^0-9].*$/, ""), 10) || 0);
156
- }
157
-
158
- function compareVersions(a, b) {
159
- const left = normalizeVersionParts(a);
160
- const right = normalizeVersionParts(b);
161
- const length = Math.max(left.length, right.length);
162
- for (let index = 0; index < length; index += 1) {
163
- const diff = (left[index] || 0) - (right[index] || 0);
164
- if (diff !== 0) {
165
- return diff;
166
- }
167
- }
168
- return 0;
169
- }
170
-
171
184
  function readChangelogManifest() {
172
185
  const payload = readJsonOrNull(CHANGELOG_MANIFEST_PATH);
173
186
  if (!payload?.releases || !Array.isArray(payload.releases)) {
@@ -249,6 +262,19 @@ function gitignoreWarnings() {
249
262
  );
250
263
  }
251
264
 
265
+ function plannerRequiredPaths() {
266
+ return Array.from(
267
+ new Set(
268
+ [
269
+ "docs/agents/wave-planner-role.md",
270
+ "docs/reference/wave-planning-lessons.md",
271
+ "skills/role-planner/SKILL.md",
272
+ ...PLANNER_CONTEXT7_TEMPLATE_PATHS,
273
+ ].filter(Boolean),
274
+ ),
275
+ ).sort();
276
+ }
277
+
252
278
  export function runDoctor() {
253
279
  const errors = [];
254
280
  const warnings = [];
@@ -293,9 +319,21 @@ export function runDoctor() {
293
319
  errors.push(`Missing required Wave file: ${relPath}`);
294
320
  }
295
321
  }
322
+ const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
323
+ const plannerPaths = plannerRequiredPaths();
324
+ for (const relPath of plannerPaths) {
325
+ if (!fs.existsSync(path.join(REPO_ROOT, relPath))) {
326
+ errors.push(`Missing planner file: ${relPath}`);
327
+ }
328
+ }
329
+ const plannerBundleId = String(config.planner?.agentic?.context7Bundle || "").trim();
330
+ if (plannerBundleId && !context7BundleIndex.bundles[plannerBundleId]) {
331
+ errors.push(
332
+ `planner.agentic.context7Bundle references unknown bundle "${plannerBundleId}".`,
333
+ );
334
+ }
296
335
  let parsedWaves = [];
297
336
  if (fs.existsSync(lanePaths.wavesDir)) {
298
- const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
299
337
  parsedWaves = parseWaveFiles(lanePaths.wavesDir, { laneProfile: lanePaths.laneProfile })
300
338
  .map((wave) =>
301
339
  applyExecutorSelectionsToWave(wave, {
@@ -478,6 +516,186 @@ export function upgradeWorkspace() {
478
516
  };
479
517
  }
480
518
 
519
+ function readWorkspacePackageManifest(workspaceRoot = REPO_ROOT) {
520
+ const payload = readJsonOrNull(path.join(workspaceRoot, "package.json"));
521
+ if (!payload || typeof payload !== "object") {
522
+ throw new Error(`Missing package.json at ${path.join(workspaceRoot, "package.json")}`);
523
+ }
524
+ return payload;
525
+ }
526
+
527
+ function readInstallStateForWorkspace(workspaceRoot = REPO_ROOT) {
528
+ const payload = readJsonOrNull(path.join(workspaceRoot, INSTALL_STATE_DIR, "install-state.json"));
529
+ return payload && typeof payload === "object" ? payload : null;
530
+ }
531
+
532
+ function parsePackageManagerId(value) {
533
+ const normalized = String(value || "")
534
+ .trim()
535
+ .toLowerCase();
536
+ if (!normalized) {
537
+ return null;
538
+ }
539
+ if (normalized.startsWith("pnpm@")) {
540
+ return "pnpm";
541
+ }
542
+ if (normalized.startsWith("npm@")) {
543
+ return "npm";
544
+ }
545
+ if (normalized.startsWith("yarn@")) {
546
+ return "yarn";
547
+ }
548
+ if (normalized.startsWith("bun@")) {
549
+ return "bun";
550
+ }
551
+ return null;
552
+ }
553
+
554
+ export function detectWorkspacePackageManager(workspaceRoot = REPO_ROOT) {
555
+ const manifest = readWorkspacePackageManifest(workspaceRoot);
556
+ const packageManagerFromManifest = parsePackageManagerId(manifest.packageManager);
557
+ if (packageManagerFromManifest) {
558
+ return {
559
+ id: packageManagerFromManifest,
560
+ source: "packageManager",
561
+ raw: manifest.packageManager,
562
+ };
563
+ }
564
+ for (const [fileName, id] of [
565
+ ["pnpm-lock.yaml", "pnpm"],
566
+ ["package-lock.json", "npm"],
567
+ ["npm-shrinkwrap.json", "npm"],
568
+ ["yarn.lock", "yarn"],
569
+ ["bun.lockb", "bun"],
570
+ ["bun.lock", "bun"],
571
+ ]) {
572
+ if (fs.existsSync(path.join(workspaceRoot, fileName))) {
573
+ return {
574
+ id,
575
+ source: "lockfile",
576
+ raw: fileName,
577
+ };
578
+ }
579
+ }
580
+ return {
581
+ id: "npm",
582
+ source: "default",
583
+ raw: null,
584
+ };
585
+ }
586
+
587
+ function packageManagerCommands(managerId, packageName = WAVE_PACKAGE_NAME) {
588
+ if (managerId === "pnpm") {
589
+ return {
590
+ install: ["pnpm", ["add", "-D", `${packageName}@latest`]],
591
+ execWave: (args) => ["pnpm", ["exec", "wave", ...args]],
592
+ };
593
+ }
594
+ if (managerId === "npm") {
595
+ return {
596
+ install: ["npm", ["install", "--save-dev", `${packageName}@latest`]],
597
+ execWave: (args) => ["npm", ["exec", "--", "wave", ...args]],
598
+ };
599
+ }
600
+ if (managerId === "yarn") {
601
+ return {
602
+ install: ["yarn", ["add", "-D", `${packageName}@latest`]],
603
+ execWave: (args) => ["yarn", ["exec", "wave", ...args]],
604
+ };
605
+ }
606
+ if (managerId === "bun") {
607
+ return {
608
+ install: ["bun", ["add", "-d", `${packageName}@latest`]],
609
+ execWave: (args) => ["bun", ["x", "wave", ...args]],
610
+ };
611
+ }
612
+ throw new Error(`Unsupported package manager: ${managerId}`);
613
+ }
614
+
615
+ function runCommandOrThrow(command, args, options = {}) {
616
+ const spawnImpl = options.spawnImpl || spawnSync;
617
+ const result = spawnImpl(command, args, {
618
+ cwd: options.workspaceRoot || REPO_ROOT,
619
+ stdio: options.stdio || "inherit",
620
+ env: options.env || process.env,
621
+ encoding: "utf8",
622
+ });
623
+ const status = Number.isInteger(result?.status) ? result.status : 1;
624
+ if (status !== 0) {
625
+ throw new Error(`${command} ${args.join(" ")} failed with status ${status}`);
626
+ }
627
+ return result;
628
+ }
629
+
630
+ export async function selfUpdateWorkspace(options = {}) {
631
+ const workspaceRoot = options.workspaceRoot || REPO_ROOT;
632
+ const metadata = options.packageMetadata || packageMetadata();
633
+ const installState = readInstallStateForWorkspace(workspaceRoot);
634
+ const packageManager = detectWorkspacePackageManager(workspaceRoot);
635
+ const commands = packageManagerCommands(packageManager.id, metadata.name || WAVE_PACKAGE_NAME);
636
+ const emit = options.emit || console.log;
637
+ let latestVersion = null;
638
+
639
+ try {
640
+ latestVersion = await fetchLatestPackageVersion(metadata.name || WAVE_PACKAGE_NAME, {
641
+ fetchImpl: options.fetchImpl,
642
+ timeoutMs: options.timeoutMs,
643
+ });
644
+ } catch {
645
+ latestVersion = null;
646
+ }
647
+
648
+ const currentVersion = String(metadata.version || "").trim();
649
+ const recordedVersion = String(installState?.installedVersion || "").trim() || null;
650
+ const needsUpgradeOnly = recordedVersion && compareVersions(currentVersion, recordedVersion) !== 0;
651
+
652
+ emit(`[wave:self-update] package_manager=${packageManager.id}`);
653
+
654
+ if (latestVersion && compareVersions(latestVersion, currentVersion) <= 0) {
655
+ if (!needsUpgradeOnly) {
656
+ emit(`[wave:self-update] ${metadata.name} is already current at ${currentVersion}.`);
657
+ return {
658
+ mode: "already-current",
659
+ packageManager: packageManager.id,
660
+ currentVersion,
661
+ latestVersion,
662
+ };
663
+ }
664
+ emit(
665
+ `[wave:self-update] dependency is already at ${currentVersion}; recording workspace upgrade state.`,
666
+ );
667
+ const [upgradeCommand, upgradeArgs] = commands.execWave(["upgrade"]);
668
+ runCommandOrThrow(upgradeCommand, upgradeArgs, options);
669
+ return {
670
+ mode: "upgrade-only",
671
+ packageManager: packageManager.id,
672
+ currentVersion,
673
+ latestVersion,
674
+ };
675
+ }
676
+
677
+ emit(
678
+ `[wave:self-update] updating ${metadata.name} from ${currentVersion}${latestVersion ? ` to ${latestVersion}` : " to the latest published version"}.`,
679
+ );
680
+ const [installCommand, installArgs] = commands.install;
681
+ runCommandOrThrow(installCommand, installArgs, options);
682
+
683
+ emit("[wave:self-update] release notes since the recorded install:");
684
+ const [changelogCommand, changelogArgs] = commands.execWave(["changelog", "--since-installed"]);
685
+ runCommandOrThrow(changelogCommand, changelogArgs, options);
686
+
687
+ emit("[wave:self-update] recording install-state and upgrade report:");
688
+ const [upgradeCommand, upgradeArgs] = commands.execWave(["upgrade"]);
689
+ runCommandOrThrow(upgradeCommand, upgradeArgs, options);
690
+
691
+ return {
692
+ mode: "updated",
693
+ packageManager: packageManager.id,
694
+ currentVersion,
695
+ latestVersion,
696
+ };
697
+ }
698
+
481
699
  function printJson(payload) {
482
700
  console.log(JSON.stringify(payload, null, 2));
483
701
  }
@@ -486,6 +704,7 @@ function printHelp() {
486
704
  console.log(`Usage:
487
705
  wave init [--adopt-existing] [--json]
488
706
  wave upgrade [--json]
707
+ wave self-update
489
708
  wave changelog [--since-installed] [--json]
490
709
  wave doctor [--json]
491
710
  `);
@@ -562,6 +781,14 @@ export async function runInstallCli(argv) {
562
781
  return;
563
782
  }
564
783
 
784
+ if (subcommand === "self-update") {
785
+ if (options.json) {
786
+ throw new Error("`wave self-update` does not support --json.");
787
+ }
788
+ await selfUpdateWorkspace();
789
+ return;
790
+ }
791
+
565
792
  if (subcommand === "changelog") {
566
793
  const result = readChangelog({ sinceInstalled: options.sinceInstalled });
567
794
  if (options.json) {
@@ -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({