@chllming/wave-orchestration 0.9.11 → 0.9.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +7 -8
- package/docs/README.md +4 -10
- package/docs/architecture/README.md +12 -4
- package/docs/concepts/operating-modes.md +1 -1
- package/docs/guides/author-and-run-waves.md +3 -2
- package/docs/guides/planner.md +3 -3
- package/docs/guides/recommendations-0.9.13.md +49 -0
- package/docs/guides/sandboxed-environments.md +2 -2
- package/docs/guides/terminal-surfaces.md +1 -1
- package/docs/plans/current-state.md +3 -3
- package/docs/plans/end-state-architecture.md +1 -1
- package/docs/plans/examples/wave-example-design-handoff.md +1 -1
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +31 -28
- package/docs/plans/wave-orchestrator.md +1 -1
- package/docs/reference/cli-reference.md +2 -2
- package/docs/reference/coordination-and-closure.md +1 -1
- package/docs/reference/npmjs-token-publishing.md +3 -3
- package/docs/reference/package-publishing-flow.md +12 -12
- package/docs/reference/runtime-config/README.md +2 -2
- package/docs/reference/sample-waves.md +5 -5
- package/docs/reference/skills.md +1 -1
- package/docs/reference/wave-control.md +3 -1
- package/docs/roadmap.md +3 -3
- package/package.json +8 -9
- package/releases/manifest.json +50 -0
- package/scripts/context7-api-check.sh +0 -0
- package/scripts/context7-export-env.sh +0 -0
- package/scripts/wave-autonomous.mjs +0 -0
- package/scripts/wave-dashboard.mjs +0 -0
- package/scripts/wave-human-feedback.mjs +0 -0
- package/scripts/wave-launcher.mjs +0 -0
- package/scripts/wave-local-executor.mjs +0 -0
- package/scripts/wave-orchestrator/agent-process-runner.mjs +24 -0
- package/scripts/wave-orchestrator/agent-state.mjs +4 -4
- package/scripts/wave-orchestrator/autonomous.mjs +2 -2
- package/scripts/wave-orchestrator/closure-engine.mjs +103 -6
- package/scripts/wave-orchestrator/closure-policy.mjs +319 -0
- package/scripts/wave-orchestrator/config.mjs +15 -0
- package/scripts/wave-orchestrator/coordination.mjs +2 -2
- package/scripts/wave-orchestrator/derived-state-engine.mjs +45 -2
- package/scripts/wave-orchestrator/executors.mjs +2 -1
- package/scripts/wave-orchestrator/gate-engine.mjs +72 -4
- package/scripts/wave-orchestrator/install.mjs +1 -1
- package/scripts/wave-orchestrator/launcher.mjs +44 -7
- package/scripts/wave-orchestrator/planner.mjs +4 -3
- package/scripts/wave-orchestrator/shared.mjs +2 -3
- package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1 -1
- package/scripts/wave-orchestrator/traces.mjs +22 -1
- package/scripts/wave-orchestrator/wave-files.mjs +14 -3
- package/scripts/wave-status.sh +0 -0
- package/scripts/wave-watch.sh +0 -0
- package/scripts/wave.mjs +0 -0
- package/wave.config.json +13 -2
|
@@ -97,6 +97,7 @@ import {
|
|
|
97
97
|
markWaveCompleted,
|
|
98
98
|
parseWaveFiles,
|
|
99
99
|
reconcileRunStateFromStatusFiles,
|
|
100
|
+
resolveCompletedWavesForValidation,
|
|
100
101
|
resolveAutoNextWaveStart,
|
|
101
102
|
validateWaveRuntimeMixAssignments,
|
|
102
103
|
validateWaveComponentMatrixCurrentLevels,
|
|
@@ -265,9 +266,9 @@ Options:
|
|
|
265
266
|
--dry-run Parse waves and update manifest only
|
|
266
267
|
--terminal-surface <mode>
|
|
267
268
|
Terminal surface: ${TERMINAL_SURFACES.join(" | ")} (default: ${terminalSurface})
|
|
268
|
-
--no-dashboard Disable per-wave
|
|
269
|
-
--cleanup-sessions
|
|
270
|
-
--keep-sessions Keep lane tmux sessions after each wave
|
|
269
|
+
--no-dashboard Disable the per-wave dashboard projection session
|
|
270
|
+
--cleanup-sessions Clean up lane tmux dashboard/projection sessions after each wave (default: on)
|
|
271
|
+
--keep-sessions Keep lane tmux dashboard/projection sessions after each wave
|
|
271
272
|
--keep-terminals Do not remove temporary terminal entries after each wave
|
|
272
273
|
--orchestrator-id <id> Stable orchestrator identity for cross-lane coordination
|
|
273
274
|
--orchestrator-board <path>
|
|
@@ -477,6 +478,15 @@ function parseArgs(argv) {
|
|
|
477
478
|
return { help: false, lanePaths, options, config };
|
|
478
479
|
}
|
|
479
480
|
|
|
481
|
+
function maybePrintOptionalTmuxNote(options) {
|
|
482
|
+
if (options.dryRun || options.terminalSurface !== "tmux" || options.dashboard) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
console.log(
|
|
486
|
+
"[terminal-surface] tmux is optional here: live agents still run as detached processes, and tmux only affects dashboard/projection attach when dashboards are enabled.",
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
480
490
|
// --- Local wrappers that bind engine calls to launcher scope ---
|
|
481
491
|
|
|
482
492
|
async function runClosureSweepPhase({
|
|
@@ -872,7 +882,7 @@ export async function runLauncherCli(argv) {
|
|
|
872
882
|
terminalSurface: options.terminalSurface,
|
|
873
883
|
});
|
|
874
884
|
const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
|
|
875
|
-
const
|
|
885
|
+
const parsedWaves = parseWaveFiles(lanePaths.wavesDir, { laneProfile: lanePaths.laneProfile })
|
|
876
886
|
.map((wave) =>
|
|
877
887
|
applyExecutorSelectionsToWave(wave, {
|
|
878
888
|
laneProfile: lanePaths.laneProfile,
|
|
@@ -892,8 +902,34 @@ export async function runLauncherCli(argv) {
|
|
|
892
902
|
...resolveWaveRoleBindings(waveWithContext7, lanePaths, waveWithContext7.agents),
|
|
893
903
|
};
|
|
894
904
|
},
|
|
895
|
-
)
|
|
896
|
-
|
|
905
|
+
);
|
|
906
|
+
// Read completed waves before validation so we can skip stale-promotion
|
|
907
|
+
// checks for waves that already ran, including waves recoverable from
|
|
908
|
+
// status files when run-state lags behind after a restart.
|
|
909
|
+
const preValidationCompletedWaves = new Set(
|
|
910
|
+
resolveCompletedWavesForValidation(
|
|
911
|
+
parsedWaves,
|
|
912
|
+
options.runStatePath,
|
|
913
|
+
lanePaths.statusDir,
|
|
914
|
+
{
|
|
915
|
+
logsDir: lanePaths.logsDir,
|
|
916
|
+
coordinationDir: lanePaths.coordinationDir,
|
|
917
|
+
contQaAgentId: lanePaths.contQaAgentId,
|
|
918
|
+
contEvalAgentId: lanePaths.contEvalAgentId,
|
|
919
|
+
integrationAgentId: lanePaths.integrationAgentId,
|
|
920
|
+
documentationAgentId: lanePaths.documentationAgentId,
|
|
921
|
+
requireExitContractsFromWave: lanePaths.requireExitContractsFromWave,
|
|
922
|
+
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
923
|
+
requireComponentPromotionsFromWave: lanePaths.requireComponentPromotionsFromWave,
|
|
924
|
+
laneProfile: lanePaths.laneProfile,
|
|
925
|
+
},
|
|
926
|
+
),
|
|
927
|
+
);
|
|
928
|
+
const allWaves = parsedWaves
|
|
929
|
+
.map((wave) => validateWaveDefinition(wave, {
|
|
930
|
+
laneProfile: lanePaths.laneProfile,
|
|
931
|
+
completedWaves: preValidationCompletedWaves,
|
|
932
|
+
}));
|
|
897
933
|
const reconciliation = reconcileRunStateFromStatusFiles(
|
|
898
934
|
allWaves,
|
|
899
935
|
options.runStatePath,
|
|
@@ -1062,11 +1098,12 @@ export async function runLauncherCli(argv) {
|
|
|
1062
1098
|
console.log(
|
|
1063
1099
|
`[dry-run] prompts and executor overlays written: ${path.relative(REPO_ROOT, lanePaths.executorOverlaysDir)}`,
|
|
1064
1100
|
);
|
|
1065
|
-
console.log("Dry run enabled, skipping
|
|
1101
|
+
console.log("Dry run enabled, skipping live execution and optional dashboard/projection launch.");
|
|
1066
1102
|
return;
|
|
1067
1103
|
}
|
|
1068
1104
|
|
|
1069
1105
|
preflightWavesForExecutorAvailability(filteredWaves, lanePaths);
|
|
1106
|
+
maybePrintOptionalTmuxNote(options);
|
|
1070
1107
|
const terminalRegistryEnabled = terminalSurfaceUsesTerminalRegistry(
|
|
1071
1108
|
options.terminalSurface,
|
|
1072
1109
|
);
|
|
@@ -2944,9 +2944,10 @@ async function runProjectSetupFlow(options = {}) {
|
|
|
2944
2944
|
),
|
|
2945
2945
|
);
|
|
2946
2946
|
|
|
2947
|
-
prompt.describe("\nHow do you want to
|
|
2948
|
-
prompt.describe("
|
|
2949
|
-
prompt.describe("
|
|
2947
|
+
prompt.describe("\nHow do you want to follow live runs?");
|
|
2948
|
+
prompt.describe("Live agent execution stays process-backed either way; this only changes the operator surface.");
|
|
2949
|
+
prompt.describe(" vscode — VS Code gets temporary terminal entries for agent logs and dashboards");
|
|
2950
|
+
prompt.describe(" tmux — terminal-native dashboard and projection surface with no VS Code integration");
|
|
2950
2951
|
const defaultTerminalSurface = normalizeTerminalSurface(
|
|
2951
2952
|
await prompt.askChoice(
|
|
2952
2953
|
"Default terminal surface",
|
|
@@ -277,6 +277,8 @@ export function buildLanePaths(laneInput = DEFAULT_WAVE_LANE, options = {}) {
|
|
|
277
277
|
laneProfile.validation.requireComponentPromotionsFromWave,
|
|
278
278
|
requireAgentComponentsFromWave: laneProfile.validation.requireAgentComponentsFromWave,
|
|
279
279
|
gateModeThresholds: laneProfile.validation.gateModeThresholds,
|
|
280
|
+
closureModeThresholds: laneProfile.validation.closureModeThresholds,
|
|
281
|
+
autoClosure: laneProfile.validation.autoClosure,
|
|
280
282
|
executors: laneProfile.executors,
|
|
281
283
|
skills: laneProfile.skills,
|
|
282
284
|
capabilityRouting: laneProfile.capabilityRouting,
|
|
@@ -428,9 +430,6 @@ export function normalizeWaveVerdict(verdict) {
|
|
|
428
430
|
const normalized = String(verdict || "")
|
|
429
431
|
.trim()
|
|
430
432
|
.toLowerCase();
|
|
431
|
-
if (normalized === "hold") {
|
|
432
|
-
return "concerns";
|
|
433
|
-
}
|
|
434
433
|
if (normalized === "fail") {
|
|
435
434
|
return "blocked";
|
|
436
435
|
}
|
|
@@ -796,7 +796,7 @@ function buildFullWaveSolve(row, taskWorkspace, options) {
|
|
|
796
796
|
});
|
|
797
797
|
assertSuccess(doctor, "wave doctor");
|
|
798
798
|
const launch = runShellCommand(
|
|
799
|
-
`node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard
|
|
799
|
+
`node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard`,
|
|
800
800
|
{
|
|
801
801
|
cwd: taskWorkspace.repoDir,
|
|
802
802
|
timeoutMs: options.maxWallClockMinutes * 60 * 1000,
|
|
@@ -623,6 +623,7 @@ export function normalizeGateSnapshotForBundle(gateSnapshot, agentArtifacts) {
|
|
|
623
623
|
return gateSnapshot;
|
|
624
624
|
}
|
|
625
625
|
const normalized = { ...gateSnapshot };
|
|
626
|
+
const overallGate = String(gateSnapshot.overall?.gate || "").trim();
|
|
626
627
|
for (const key of [
|
|
627
628
|
"implementationGate",
|
|
628
629
|
"componentGate",
|
|
@@ -638,7 +639,27 @@ export function normalizeGateSnapshotForBundle(gateSnapshot, agentArtifacts) {
|
|
|
638
639
|
"evaluatorGate",
|
|
639
640
|
"infraGate",
|
|
640
641
|
]) {
|
|
641
|
-
|
|
642
|
+
const nextValue = normalizeGateLogPath(gateSnapshot[key], agentArtifacts);
|
|
643
|
+
if (key === "documentationGate") {
|
|
644
|
+
normalized[key] =
|
|
645
|
+
overallGate === "documentationGate" && nextValue
|
|
646
|
+
? {
|
|
647
|
+
ok: Boolean(nextValue.ok),
|
|
648
|
+
statusCode: nextValue.statusCode || null,
|
|
649
|
+
}
|
|
650
|
+
: null;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
if (key === "integrationGate" || key === "integrationBarrier") {
|
|
654
|
+
normalized[key] = nextValue
|
|
655
|
+
? {
|
|
656
|
+
ok: Boolean(nextValue.ok),
|
|
657
|
+
statusCode: nextValue.statusCode || null,
|
|
658
|
+
}
|
|
659
|
+
: null;
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
normalized[key] = nextValue;
|
|
642
663
|
}
|
|
643
664
|
return normalized;
|
|
644
665
|
}
|
|
@@ -1534,9 +1534,13 @@ export function validateWaveDefinition(wave, options = {}) {
|
|
|
1534
1534
|
`Wave ${wave.wave} promotes ${componentId} to ${targetLevel}, but ${componentMatrix.jsonPath} declares ${matrixPromotion.target}`,
|
|
1535
1535
|
);
|
|
1536
1536
|
} else if (componentMatrix.levelOrder[targetLevel] < componentMatrix.levelOrder[component.currentLevel]) {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
)
|
|
1537
|
+
// Skip this error for already-completed waves — their promotions may have
|
|
1538
|
+
// been superseded by later waves that advanced the component further.
|
|
1539
|
+
if (!options?.completedWaves?.has(wave.wave)) {
|
|
1540
|
+
errors.push(
|
|
1541
|
+
`Wave ${wave.wave} promotes ${componentId} to ${targetLevel}, but ${componentMatrix.jsonPath} already records currentLevel ${component.currentLevel}`,
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1540
1544
|
}
|
|
1541
1545
|
}
|
|
1542
1546
|
const matrixWavePromotions = Object.entries(componentMatrix.components)
|
|
@@ -3294,6 +3298,13 @@ export function completedWavesFromStatusFiles(allWaves, statusDir, options = {})
|
|
|
3294
3298
|
return normalizeCompletedWaves(completed);
|
|
3295
3299
|
}
|
|
3296
3300
|
|
|
3301
|
+
export function resolveCompletedWavesForValidation(allWaves, runStatePath, statusDir, options = {}) {
|
|
3302
|
+
return normalizeCompletedWaves([
|
|
3303
|
+
...readRunState(runStatePath).completedWaves,
|
|
3304
|
+
...completedWavesFromStatusFiles(allWaves, statusDir, options),
|
|
3305
|
+
]);
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3297
3308
|
export function reconcileRunStateFromStatusFiles(allWaves, runStatePath, statusDir, options = {}) {
|
|
3298
3309
|
const diagnostics = allWaves.map((wave) => ({
|
|
3299
3310
|
wave: wave.wave,
|
package/scripts/wave-status.sh
CHANGED
|
File without changes
|
package/scripts/wave-watch.sh
CHANGED
|
File without changes
|
package/scripts/wave.mjs
CHANGED
|
File without changes
|
package/wave.config.json
CHANGED
|
@@ -276,7 +276,18 @@
|
|
|
276
276
|
"requireExitContractsFromWave": 6,
|
|
277
277
|
"requireIntegrationStewardFromWave": 0,
|
|
278
278
|
"requireComponentPromotionsFromWave": 0,
|
|
279
|
-
"requireAgentComponentsFromWave": 0
|
|
279
|
+
"requireAgentComponentsFromWave": 0,
|
|
280
|
+
"closureModeThresholds": {
|
|
281
|
+
"bootstrap": 0,
|
|
282
|
+
"standard": 4,
|
|
283
|
+
"strict": 10
|
|
284
|
+
},
|
|
285
|
+
"autoClosure": {
|
|
286
|
+
"allowInferredIntegration": true,
|
|
287
|
+
"allowAutoDocNoChange": true,
|
|
288
|
+
"allowAutoDocProjection": false,
|
|
289
|
+
"allowSkipContQaInBootstrap": true
|
|
290
|
+
}
|
|
280
291
|
},
|
|
281
292
|
"capabilityRouting": {
|
|
282
293
|
"preferredAgents": {}
|
|
@@ -309,4 +320,4 @@
|
|
|
309
320
|
}
|
|
310
321
|
}
|
|
311
322
|
}
|
|
312
|
-
}
|
|
323
|
+
}
|