@chllming/wave-orchestration 0.9.0 → 0.9.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 (54) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +119 -18
  3. package/docs/README.md +7 -3
  4. package/docs/architecture/README.md +1498 -0
  5. package/docs/concepts/operating-modes.md +2 -2
  6. package/docs/guides/author-and-run-waves.md +14 -4
  7. package/docs/guides/planner.md +2 -2
  8. package/docs/guides/{recommendations-0.9.0.md → recommendations-0.9.1.md} +8 -7
  9. package/docs/guides/sandboxed-environments.md +158 -0
  10. package/docs/guides/terminal-surfaces.md +14 -12
  11. package/docs/plans/current-state.md +5 -3
  12. package/docs/plans/end-state-architecture.md +3 -1
  13. package/docs/plans/examples/wave-example-design-handoff.md +1 -1
  14. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  15. package/docs/plans/migration.md +46 -19
  16. package/docs/plans/sandbox-end-state-architecture.md +153 -0
  17. package/docs/reference/cli-reference.md +71 -7
  18. package/docs/reference/coordination-and-closure.md +1 -1
  19. package/docs/reference/github-packages-setup.md +1 -1
  20. package/docs/reference/migration-0.2-to-0.5.md +9 -7
  21. package/docs/reference/npmjs-token-publishing.md +53 -0
  22. package/docs/reference/npmjs-trusted-publishing.md +4 -50
  23. package/docs/reference/package-publishing-flow.md +272 -0
  24. package/docs/reference/runtime-config/README.md +2 -2
  25. package/docs/reference/sample-waves.md +5 -5
  26. package/docs/reference/skills.md +1 -1
  27. package/docs/roadmap.md +43 -201
  28. package/package.json +1 -1
  29. package/releases/manifest.json +19 -0
  30. package/scripts/wave-orchestrator/agent-process-runner.mjs +344 -0
  31. package/scripts/wave-orchestrator/agent-state.mjs +0 -1
  32. package/scripts/wave-orchestrator/artifact-schemas.mjs +7 -0
  33. package/scripts/wave-orchestrator/autonomous.mjs +47 -14
  34. package/scripts/wave-orchestrator/closure-engine.mjs +138 -17
  35. package/scripts/wave-orchestrator/control-cli.mjs +42 -5
  36. package/scripts/wave-orchestrator/dashboard-renderer.mjs +115 -43
  37. package/scripts/wave-orchestrator/derived-state-engine.mjs +6 -3
  38. package/scripts/wave-orchestrator/gate-engine.mjs +106 -38
  39. package/scripts/wave-orchestrator/install.mjs +13 -0
  40. package/scripts/wave-orchestrator/launcher-progress.mjs +91 -0
  41. package/scripts/wave-orchestrator/launcher-runtime.mjs +179 -68
  42. package/scripts/wave-orchestrator/launcher.mjs +201 -53
  43. package/scripts/wave-orchestrator/ledger.mjs +7 -2
  44. package/scripts/wave-orchestrator/projection-writer.mjs +13 -1
  45. package/scripts/wave-orchestrator/reducer-snapshot.mjs +6 -0
  46. package/scripts/wave-orchestrator/retry-control.mjs +3 -3
  47. package/scripts/wave-orchestrator/retry-engine.mjs +93 -6
  48. package/scripts/wave-orchestrator/role-helpers.mjs +30 -0
  49. package/scripts/wave-orchestrator/session-supervisor.mjs +94 -85
  50. package/scripts/wave-orchestrator/supervisor-cli.mjs +1306 -0
  51. package/scripts/wave-orchestrator/terminals.mjs +12 -32
  52. package/scripts/wave-orchestrator/tmux-adapter.mjs +300 -0
  53. package/scripts/wave-orchestrator/wave-files.mjs +38 -5
  54. package/scripts/wave.mjs +13 -0
@@ -84,7 +84,13 @@ function readIntegrationContradictionBarrier(derivedState, agentId, logPath) {
84
84
  };
85
85
  }
86
86
 
87
- function resolveRunReportPath(wave, runInfo) {
87
+ function isSecurityReviewAgentWithOptions(agent, options = {}) {
88
+ return isSecurityReviewAgent(agent, {
89
+ securityRolePromptPath: options.securityRolePromptPath,
90
+ });
91
+ }
92
+
93
+ function resolveRunReportPath(wave, runInfo, options = {}) {
88
94
  if (!wave || !runInfo?.agent) {
89
95
  return null;
90
96
  }
@@ -94,7 +100,7 @@ function resolveRunReportPath(wave, runInfo) {
94
100
  if (runInfo.agent.agentId === (wave.contEvalAgentId || "E0") && wave.contEvalReportPath) {
95
101
  return path.resolve(REPO_ROOT, wave.contEvalReportPath);
96
102
  }
97
- if (isSecurityReviewAgent(runInfo.agent)) {
103
+ if (isSecurityReviewAgentWithOptions(runInfo.agent, options)) {
98
104
  const securityReportPath = resolveSecurityReviewReportPath(runInfo.agent);
99
105
  return securityReportPath ? path.resolve(REPO_ROOT, securityReportPath) : null;
100
106
  }
@@ -132,12 +138,12 @@ function validateEnvelopeForRun(runInfo, envelope, options = {}) {
132
138
  };
133
139
  }
134
140
 
135
- export function materializeAgentExecutionSummaryForRun(wave, runInfo) {
141
+ export function materializeAgentExecutionSummaryForRun(wave, runInfo, options = {}) {
136
142
  const statusRecord = readStatusRecordIfPresent(runInfo.statusPath);
137
143
  if (!statusRecord) {
138
144
  return null;
139
145
  }
140
- const reportPath = resolveRunReportPath(wave, runInfo);
146
+ const reportPath = resolveRunReportPath(wave, runInfo, options);
141
147
  const summary = buildAgentExecutionSummary({
142
148
  agent: runInfo.agent,
143
149
  statusRecord,
@@ -189,7 +195,7 @@ export function materializeAgentExecutionSummaryForRun(wave, runInfo) {
189
195
  export function readRunResultEnvelope(runInfo, wave = null, options = {}) {
190
196
  const mode = normalizeReadMode(options.mode);
191
197
  const statusRecord = runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null;
192
- const reportPath = wave ? resolveRunReportPath(wave, runInfo) : null;
198
+ const reportPath = wave ? resolveRunReportPath(wave, runInfo, options) : null;
193
199
  const runEnvelopeContext = resolveRunEnvelopeContext(runInfo, wave, { statusRecord });
194
200
  const envelopeReadOptions = buildEnvelopeReadOptions(runInfo, wave, statusRecord, reportPath);
195
201
  const synthesizeFromSummary = (summary, source) => {
@@ -285,7 +291,7 @@ export function readRunResultEnvelope(runInfo, wave = null, options = {}) {
285
291
  runInfo?.logPath &&
286
292
  fs.existsSync(runInfo.statusPath)
287
293
  ) {
288
- materializeAgentExecutionSummaryForRun(wave, runInfo);
294
+ materializeAgentExecutionSummaryForRun(wave, runInfo, options);
289
295
  const envelope =
290
296
  readAgentResultEnvelopeForRun(runInfo, wave, { statusRecord }) ||
291
297
  readAgentResultEnvelope(runInfo.statusPath);
@@ -313,9 +319,12 @@ export function readRunExecutionSummary(runInfo, wave = null, options = {}) {
313
319
  const applyProofRegistry = (summary) =>
314
320
  runInfo?.proofRegistry ? augmentSummaryWithProofRegistry(runInfo.agent, summary, runInfo.proofRegistry) : summary;
315
321
  const statusRecord = runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null;
316
- const reportPath = wave ? resolveRunReportPath(wave, runInfo) : null;
322
+ const reportPath = wave ? resolveRunReportPath(wave, runInfo, options) : null;
317
323
  const envelopeReadOptions = buildEnvelopeReadOptions(runInfo, wave, statusRecord, reportPath);
318
- const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
324
+ const envelopeResult = readRunResultEnvelope(runInfo, wave, {
325
+ mode,
326
+ securityRolePromptPath: options.securityRolePromptPath,
327
+ });
319
328
  if (envelopeResult?.valid && envelopeResult.envelope) {
320
329
  return applyProofRegistry(
321
330
  projectLegacySummaryFromEnvelope(envelopeResult.envelope, envelopeReadOptions),
@@ -348,9 +357,12 @@ export function readRunExecutionSummary(runInfo, wave = null, options = {}) {
348
357
  return null;
349
358
  }
350
359
 
351
- export function materializeAgentExecutionSummaries(wave, agentRuns) {
360
+ export function materializeAgentExecutionSummaries(wave, agentRuns, options = {}) {
352
361
  return Object.fromEntries(
353
- agentRuns.map((runInfo) => [runInfo.agent.agentId, materializeAgentExecutionSummaryForRun(wave, runInfo)]),
362
+ agentRuns.map((runInfo) => [
363
+ runInfo.agent.agentId,
364
+ materializeAgentExecutionSummaryForRun(wave, runInfo, options),
365
+ ]),
354
366
  );
355
367
  }
356
368
 
@@ -369,7 +381,10 @@ export function readWaveContQaGate(wave, agentRuns, options = {}) {
369
381
  logPath: null,
370
382
  };
371
383
  }
372
- const envelopeResult = readRunResultEnvelope(contQaRun, wave, { mode });
384
+ const envelopeResult = readRunResultEnvelope(contQaRun, wave, {
385
+ mode,
386
+ securityRolePromptPath: options.securityRolePromptPath,
387
+ });
373
388
  const summary = envelopeResult.valid
374
389
  ? projectLegacySummaryFromEnvelope(
375
390
  envelopeResult.envelope,
@@ -377,10 +392,13 @@ export function readWaveContQaGate(wave, agentRuns, options = {}) {
377
392
  contQaRun,
378
393
  wave,
379
394
  contQaRun?.statusPath ? readStatusRecordIfPresent(contQaRun.statusPath) : null,
380
- resolveRunReportPath(wave, contQaRun),
395
+ resolveRunReportPath(wave, contQaRun, options),
381
396
  ),
382
397
  )
383
- : readRunExecutionSummary(contQaRun, wave, { mode });
398
+ : readRunExecutionSummary(contQaRun, wave, {
399
+ mode,
400
+ securityRolePromptPath: options.securityRolePromptPath,
401
+ });
384
402
  if (summary) {
385
403
  const validation = validateContQaSummary(contQaRun.agent, summary, { mode });
386
404
  return {
@@ -461,7 +479,10 @@ export function readWaveContEvalGate(wave, agentRuns, options = {}) {
461
479
  logPath: null,
462
480
  };
463
481
  }
464
- const envelopeResult = readRunResultEnvelope(contEvalRun, wave, { mode });
482
+ const envelopeResult = readRunResultEnvelope(contEvalRun, wave, {
483
+ mode,
484
+ securityRolePromptPath: options.securityRolePromptPath,
485
+ });
465
486
  const summary = envelopeResult.valid
466
487
  ? projectLegacySummaryFromEnvelope(
467
488
  envelopeResult.envelope,
@@ -469,10 +490,13 @@ export function readWaveContEvalGate(wave, agentRuns, options = {}) {
469
490
  contEvalRun,
470
491
  wave,
471
492
  contEvalRun?.statusPath ? readStatusRecordIfPresent(contEvalRun.statusPath) : null,
472
- resolveRunReportPath(wave, contEvalRun),
493
+ resolveRunReportPath(wave, contEvalRun, options),
473
494
  ),
474
495
  )
475
- : readRunExecutionSummary(contEvalRun, wave, { mode });
496
+ : readRunExecutionSummary(contEvalRun, wave, {
497
+ mode,
498
+ securityRolePromptPath: options.securityRolePromptPath,
499
+ });
476
500
  if (summary) {
477
501
  const validation = validateContEvalSummary(contEvalRun.agent, summary, {
478
502
  mode,
@@ -522,11 +546,14 @@ export function readWaveImplementationGate(wave, agentRuns, options = {}) {
522
546
  [contQaAgentId, integrationAgentId, documentationAgentId].includes(runInfo.agent.agentId) ||
523
547
  isContEvalReportOnlyAgent(runInfo.agent, { contEvalAgentId }) ||
524
548
  isDocsOnlyDesignAgent(runInfo.agent) ||
525
- isSecurityReviewAgent(runInfo.agent)
549
+ isSecurityReviewAgentWithOptions(runInfo.agent, options)
526
550
  ) {
527
551
  continue;
528
552
  }
529
- const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
553
+ const envelopeResult = readRunResultEnvelope(runInfo, wave, {
554
+ mode,
555
+ securityRolePromptPath: options.securityRolePromptPath,
556
+ });
530
557
  if (mode === "live" && !envelopeResult.valid) {
531
558
  return {
532
559
  ok: false,
@@ -548,10 +575,13 @@ export function readWaveImplementationGate(wave, agentRuns, options = {}) {
548
575
  runInfo,
549
576
  wave,
550
577
  runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
551
- resolveRunReportPath(wave, runInfo),
578
+ resolveRunReportPath(wave, runInfo, options),
552
579
  ),
553
580
  )
554
- : readRunExecutionSummary(runInfo, wave, { mode });
581
+ : readRunExecutionSummary(runInfo, wave, {
582
+ mode,
583
+ securityRolePromptPath: options.securityRolePromptPath,
584
+ });
555
585
  const validation = validateImplementationSummary(runInfo.agent, summary);
556
586
  if (!validation.ok) {
557
587
  return {
@@ -585,7 +615,10 @@ export function readWaveDesignGate(wave, agentRuns, options = {}) {
585
615
  };
586
616
  }
587
617
  for (const runInfo of designRuns) {
588
- const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
618
+ const envelopeResult = readRunResultEnvelope(runInfo, wave, {
619
+ mode,
620
+ securityRolePromptPath: options.securityRolePromptPath,
621
+ });
589
622
  if (mode === "live" && !envelopeResult.valid) {
590
623
  return {
591
624
  ok: false,
@@ -607,10 +640,13 @@ export function readWaveDesignGate(wave, agentRuns, options = {}) {
607
640
  runInfo,
608
641
  wave,
609
642
  runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
610
- resolveRunReportPath(wave, runInfo),
643
+ resolveRunReportPath(wave, runInfo, options),
611
644
  ),
612
645
  )
613
- : readRunExecutionSummary(runInfo, wave, { mode });
646
+ : readRunExecutionSummary(runInfo, wave, {
647
+ mode,
648
+ securityRolePromptPath: options.securityRolePromptPath,
649
+ });
614
650
  const validation = validateDesignSummary(runInfo.agent, summary);
615
651
  if (!validation.ok) {
616
652
  return {
@@ -709,7 +745,10 @@ export function readWaveComponentGate(wave, agentRuns, options = {}) {
709
745
  const summariesByAgentId = Object.fromEntries(
710
746
  agentRuns.map((runInfo) => [
711
747
  runInfo.agent.agentId,
712
- readRunExecutionSummary(runInfo, wave, { mode }),
748
+ readRunExecutionSummary(runInfo, wave, {
749
+ mode,
750
+ securityRolePromptPath: options.securityRolePromptPath,
751
+ }),
713
752
  ]),
714
753
  );
715
754
  const validation = validateWaveComponentPromotions(wave, summariesByAgentId, options);
@@ -793,7 +832,10 @@ export function readWaveDocumentationGate(wave, agentRuns, options = {}) {
793
832
  logPath: null,
794
833
  };
795
834
  }
796
- const envelopeResult = readRunResultEnvelope(docRun, wave, { mode });
835
+ const envelopeResult = readRunResultEnvelope(docRun, wave, {
836
+ mode,
837
+ securityRolePromptPath: options.securityRolePromptPath,
838
+ });
797
839
  if (mode === "live" && !envelopeResult.valid) {
798
840
  return {
799
841
  ok: false,
@@ -815,10 +857,13 @@ export function readWaveDocumentationGate(wave, agentRuns, options = {}) {
815
857
  docRun,
816
858
  wave,
817
859
  docRun?.statusPath ? readStatusRecordIfPresent(docRun.statusPath) : null,
818
- resolveRunReportPath(wave, docRun),
860
+ resolveRunReportPath(wave, docRun, options),
819
861
  ),
820
862
  )
821
- : readRunExecutionSummary(docRun, wave, { mode });
863
+ : readRunExecutionSummary(docRun, wave, {
864
+ mode,
865
+ securityRolePromptPath: options.securityRolePromptPath,
866
+ });
822
867
  const validation = validateDocumentationClosureSummary(docRun.agent, summary);
823
868
  return {
824
869
  ok: validation.ok,
@@ -831,7 +876,9 @@ export function readWaveDocumentationGate(wave, agentRuns, options = {}) {
831
876
 
832
877
  export function readWaveSecurityGate(wave, agentRuns, options = {}) {
833
878
  const mode = normalizeReadMode(options.mode || "live");
834
- const securityRuns = (agentRuns || []).filter((run) => isSecurityReviewAgent(run.agent));
879
+ const securityRuns = (agentRuns || []).filter((run) =>
880
+ isSecurityReviewAgentWithOptions(run.agent, options),
881
+ );
835
882
  if (securityRuns.length === 0) {
836
883
  return {
837
884
  ok: true,
@@ -843,7 +890,10 @@ export function readWaveSecurityGate(wave, agentRuns, options = {}) {
843
890
  }
844
891
  const concernAgentIds = [];
845
892
  for (const runInfo of securityRuns) {
846
- const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
893
+ const envelopeResult = readRunResultEnvelope(runInfo, wave, {
894
+ mode,
895
+ securityRolePromptPath: options.securityRolePromptPath,
896
+ });
847
897
  if (mode === "live" && !envelopeResult.valid) {
848
898
  return {
849
899
  ok: false,
@@ -865,10 +915,13 @@ export function readWaveSecurityGate(wave, agentRuns, options = {}) {
865
915
  runInfo,
866
916
  wave,
867
917
  runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
868
- resolveRunReportPath(wave, runInfo),
918
+ resolveRunReportPath(wave, runInfo, options),
869
919
  ),
870
920
  )
871
- : readRunExecutionSummary(runInfo, wave, { mode });
921
+ : readRunExecutionSummary(runInfo, wave, {
922
+ mode,
923
+ securityRolePromptPath: options.securityRolePromptPath,
924
+ });
872
925
  const validation = validateSecuritySummary(runInfo.agent, summary);
873
926
  if (!validation.ok) {
874
927
  return {
@@ -923,7 +976,10 @@ export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
923
976
  logPath: null,
924
977
  };
925
978
  }
926
- const envelopeResult = readRunResultEnvelope(integrationRun, wave, { mode });
979
+ const envelopeResult = readRunResultEnvelope(integrationRun, wave, {
980
+ mode,
981
+ securityRolePromptPath: options.securityRolePromptPath,
982
+ });
927
983
  if (mode === "live" && !envelopeResult.valid) {
928
984
  return {
929
985
  ok: false,
@@ -945,10 +1001,13 @@ export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
945
1001
  integrationRun,
946
1002
  wave,
947
1003
  integrationRun?.statusPath ? readStatusRecordIfPresent(integrationRun.statusPath) : null,
948
- resolveRunReportPath(wave, integrationRun),
1004
+ resolveRunReportPath(wave, integrationRun, options),
949
1005
  ),
950
1006
  )
951
- : readRunExecutionSummary(integrationRun, wave, { mode });
1007
+ : readRunExecutionSummary(integrationRun, wave, {
1008
+ mode,
1009
+ securityRolePromptPath: options.securityRolePromptPath,
1010
+ });
952
1011
  const validation = validateIntegrationSummary(integrationRun.agent, summary);
953
1012
  return {
954
1013
  ok: validation.ok,
@@ -1105,7 +1164,10 @@ export function buildGateSnapshot({
1105
1164
  (agentRuns || [])
1106
1165
  .map((runInfo) => [
1107
1166
  runInfo.agent.agentId,
1108
- readRunExecutionSummary(runInfo, wave, { mode: validationMode }),
1167
+ readRunExecutionSummary(runInfo, wave, {
1168
+ mode: validationMode,
1169
+ securityRolePromptPath: lanePaths?.securityRolePromptPath,
1170
+ }),
1109
1171
  ])
1110
1172
  .filter(([, summary]) => Boolean(summary)),
1111
1173
  );
@@ -1127,6 +1189,7 @@ export function buildGateSnapshot({
1127
1189
  contEvalAgentId: lanePaths?.contEvalAgentId,
1128
1190
  integrationAgentId: lanePaths?.integrationAgentId,
1129
1191
  documentationAgentId: lanePaths?.documentationAgentId,
1192
+ securityRolePromptPath: lanePaths?.securityRolePromptPath,
1130
1193
  requireIntegrationStewardFromWave: lanePaths?.requireIntegrationStewardFromWave,
1131
1194
  laneProfile: lanePaths?.laneProfile,
1132
1195
  benchmarkCatalogPath: lanePaths?.laneProfile?.paths?.benchmarkCatalogPath,
@@ -1157,7 +1220,7 @@ export function readWaveImplementationGatePure(wave, agentResults, options = {})
1157
1220
  [contQaAgentId, integrationAgentId, documentationAgentId].includes(agent.agentId) ||
1158
1221
  isContEvalReportOnlyAgent(agent, { contEvalAgentId }) ||
1159
1222
  isDocsOnlyDesignAgent(agent) ||
1160
- isSecurityReviewAgent(agent)
1223
+ isSecurityReviewAgentWithOptions(agent, options)
1161
1224
  ) {
1162
1225
  continue;
1163
1226
  }
@@ -1348,7 +1411,9 @@ export function readWaveDocumentationGatePure(wave, agentResults, options = {})
1348
1411
 
1349
1412
  export function readWaveSecurityGatePure(wave, agentResults, options = {}) {
1350
1413
  const agents = Array.isArray(wave.agents) ? wave.agents : [];
1351
- const securityAgents = agents.filter((agent) => isSecurityReviewAgent(agent));
1414
+ const securityAgents = agents.filter((agent) =>
1415
+ isSecurityReviewAgentWithOptions(agent, options),
1416
+ );
1352
1417
  if (securityAgents.length === 0) {
1353
1418
  return { ok: true, agentId: null, statusCode: "pass",
1354
1419
  detail: "No security reviewer declared for this wave.", logPath: null };
@@ -1419,6 +1484,7 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
1419
1484
  const implementationGate = readWaveImplementationGatePure(wave, agentResults, {
1420
1485
  contQaAgentId: laneConfig.contQaAgentId, contEvalAgentId: laneConfig.contEvalAgentId,
1421
1486
  integrationAgentId: laneConfig.integrationAgentId, documentationAgentId: laneConfig.documentationAgentId,
1487
+ securityRolePromptPath: laneConfig.securityRolePromptPath,
1422
1488
  });
1423
1489
  const componentGate = readWaveComponentGatePure(wave, agentResults, { laneProfile: laneConfig.laneProfile });
1424
1490
  const integrationMarkerGate = readWaveIntegrationGatePure(wave, agentResults, {
@@ -1459,7 +1525,9 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
1459
1525
  const contEvalGate = readWaveContEvalGatePure(wave, agentResults, {
1460
1526
  contEvalAgentId: laneConfig.contEvalAgentId, mode: validationMode,
1461
1527
  evalTargets: wave.evalTargets, benchmarkCatalogPath: laneConfig.benchmarkCatalogPath });
1462
- const securityGate = readWaveSecurityGatePure(wave, agentResults);
1528
+ const securityGate = readWaveSecurityGatePure(wave, agentResults, {
1529
+ securityRolePromptPath: laneConfig.securityRolePromptPath,
1530
+ });
1463
1531
  const contQaGate = readWaveContQaGatePure(wave, agentResults, {
1464
1532
  contQaAgentId: laneConfig.contQaAgentId, mode: validationMode });
1465
1533
  const infraGate = readWaveInfraGatePure(wave, agentResults);
@@ -26,6 +26,7 @@ export const UPGRADE_HISTORY_DIR = path.join(REPO_ROOT, INSTALL_STATE_DIR, "upgr
26
26
  export const CHANGELOG_MANIFEST_PATH = path.join(PACKAGE_ROOT, "releases", "manifest.json");
27
27
  export const WORKSPACE_PACKAGE_JSON_PATH = path.join(REPO_ROOT, "package.json");
28
28
  export const STARTER_TEMPLATE_PATHS = [
29
+ "CHANGELOG.md",
29
30
  "wave.config.json",
30
31
  "scripts/wave-status.sh",
31
32
  "scripts/wave-watch.sh",
@@ -61,18 +62,30 @@ export const STARTER_TEMPLATE_PATHS = [
61
62
  "docs/evals/cases/wave-contradiction-conflict.json",
62
63
  "docs/evals/cases/wave-simultaneous-lockstep.json",
63
64
  "docs/evals/cases/wave-expert-routing-preservation.json",
65
+ "docs/guides/author-and-run-waves.md",
66
+ "docs/guides/monorepo-projects.md",
64
67
  "docs/guides/planner.md",
68
+ "docs/guides/recommendations-0.9.1.md",
69
+ "docs/guides/sandboxed-environments.md",
70
+ "docs/guides/signal-wrappers.md",
65
71
  "docs/guides/terminal-surfaces.md",
72
+ "docs/plans/architecture-hardening-migration.md",
66
73
  "docs/plans/component-cutover-matrix.json",
67
74
  "docs/plans/component-cutover-matrix.md",
68
75
  "docs/plans/context7-wave-orchestrator.md",
69
76
  "docs/plans/current-state.md",
77
+ "docs/plans/end-state-architecture.md",
70
78
  "docs/plans/examples/wave-example-live-proof.md",
71
79
  "docs/plans/master-plan.md",
72
80
  "docs/plans/migration.md",
81
+ "docs/plans/sandbox-end-state-architecture.md",
73
82
  "docs/plans/wave-orchestrator.md",
74
83
  "docs/plans/waves/wave-0.md",
84
+ "docs/reference/cli-reference.md",
75
85
  "docs/reference/live-proof-waves.md",
86
+ "docs/reference/npmjs-token-publishing.md",
87
+ "docs/reference/npmjs-trusted-publishing.md",
88
+ "docs/reference/package-publishing-flow.md",
76
89
  "docs/reference/repository-guidance.md",
77
90
  "docs/reference/sample-waves.md",
78
91
  "docs/reference/skills.md",
@@ -0,0 +1,91 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import {
4
+ ensureDirectory,
5
+ readJsonOrNull,
6
+ toIsoTimestamp,
7
+ writeJsonAtomic,
8
+ } from "./shared.mjs";
9
+
10
+ function normalizeStringArray(values) {
11
+ return Array.from(
12
+ new Set(
13
+ (Array.isArray(values) ? values : [])
14
+ .map((value) => String(value || "").trim())
15
+ .filter(Boolean),
16
+ ),
17
+ );
18
+ }
19
+
20
+ export function launcherProgressPathForRun(lanePaths, runId) {
21
+ if (!lanePaths?.controlDir || !runId) {
22
+ return null;
23
+ }
24
+ return path.join(lanePaths.controlDir, "supervisor", "runs", runId, "launcher-progress.json");
25
+ }
26
+
27
+ export function normalizeLauncherProgress(payload, defaults = {}) {
28
+ const source = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
29
+ return {
30
+ runId: String(source.runId || defaults.runId || "").trim() || null,
31
+ waveNumber: Number.isFinite(Number(source.waveNumber))
32
+ ? Number(source.waveNumber)
33
+ : Number.isFinite(Number(defaults.waveNumber))
34
+ ? Number(defaults.waveNumber)
35
+ : null,
36
+ attemptNumber: Number.isFinite(Number(source.attemptNumber))
37
+ ? Number(source.attemptNumber)
38
+ : Number.isFinite(Number(defaults.attemptNumber))
39
+ ? Number(defaults.attemptNumber)
40
+ : null,
41
+ phase: String(source.phase || defaults.phase || "").trim() || null,
42
+ selectedAgentIds: normalizeStringArray(source.selectedAgentIds),
43
+ launchedAgentIds: normalizeStringArray(source.launchedAgentIds),
44
+ completedAgentIds: normalizeStringArray(source.completedAgentIds),
45
+ resumeFromPhase: String(source.resumeFromPhase || defaults.resumeFromPhase || "").trim() || null,
46
+ forwardedClosureGaps: Array.isArray(source.forwardedClosureGaps)
47
+ ? JSON.parse(JSON.stringify(source.forwardedClosureGaps))
48
+ : [],
49
+ gateSnapshotSummary:
50
+ source.gateSnapshotSummary && typeof source.gateSnapshotSummary === "object"
51
+ ? JSON.parse(JSON.stringify(source.gateSnapshotSummary))
52
+ : null,
53
+ finalized: source.finalized === true,
54
+ finalDisposition: String(source.finalDisposition || defaults.finalDisposition || "").trim() || null,
55
+ exitCode: Number.isInteger(source.exitCode) ? source.exitCode : null,
56
+ updatedAt: String(source.updatedAt || defaults.updatedAt || "").trim() || toIsoTimestamp(),
57
+ };
58
+ }
59
+
60
+ export function readLauncherProgress(filePath, defaults = {}) {
61
+ if (!filePath || !fs.existsSync(filePath)) {
62
+ return null;
63
+ }
64
+ return normalizeLauncherProgress(readJsonOrNull(filePath), defaults);
65
+ }
66
+
67
+ export function writeLauncherProgress(filePath, payload, defaults = {}) {
68
+ if (!filePath) {
69
+ return null;
70
+ }
71
+ ensureDirectory(path.dirname(filePath));
72
+ const normalized = normalizeLauncherProgress(payload, defaults);
73
+ writeJsonAtomic(filePath, normalized);
74
+ return normalized;
75
+ }
76
+
77
+ export function updateLauncherProgress(filePath, patch, defaults = {}) {
78
+ if (!filePath) {
79
+ return null;
80
+ }
81
+ const current = readLauncherProgress(filePath, defaults) || normalizeLauncherProgress({}, defaults);
82
+ return writeLauncherProgress(
83
+ filePath,
84
+ {
85
+ ...current,
86
+ ...patch,
87
+ updatedAt: toIsoTimestamp(),
88
+ },
89
+ defaults,
90
+ );
91
+ }