@chllming/wave-orchestration 0.8.3 → 0.8.5
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 +36 -1
- package/README.md +60 -11
- package/docs/README.md +8 -2
- package/docs/agents/wave-design-role.md +47 -0
- package/docs/concepts/what-is-a-wave.md +11 -7
- package/docs/guides/author-and-run-waves.md +24 -0
- package/docs/guides/planner.md +44 -0
- package/docs/plans/architecture-hardening-migration.md +8 -1
- package/docs/plans/current-state.md +19 -7
- package/docs/plans/end-state-architecture.md +88 -70
- package/docs/plans/examples/wave-example-design-handoff.md +262 -0
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +370 -64
- package/docs/plans/wave-orchestrator.md +49 -13
- package/docs/reference/cli-reference.md +46 -14
- package/docs/reference/coordination-and-closure.md +19 -6
- package/docs/reference/npmjs-trusted-publishing.md +5 -4
- package/docs/reference/sample-waves.md +14 -7
- package/docs/reference/skills.md +10 -0
- package/package.json +1 -1
- package/releases/manifest.json +39 -0
- package/scripts/wave-orchestrator/agent-state.mjs +64 -491
- package/scripts/wave-orchestrator/autonomous.mjs +10 -6
- package/scripts/wave-orchestrator/{launcher-closure.mjs → closure-engine.mjs} +190 -74
- package/scripts/wave-orchestrator/config.mjs +5 -0
- package/scripts/wave-orchestrator/coordination.mjs +42 -1
- package/scripts/wave-orchestrator/{launcher-derived-state.mjs → derived-state-engine.mjs} +34 -146
- package/scripts/wave-orchestrator/{launcher-gates.mjs → gate-engine.mjs} +501 -141
- package/scripts/wave-orchestrator/human-input-resolution.mjs +14 -10
- package/scripts/wave-orchestrator/human-input-workflow.mjs +104 -0
- package/scripts/wave-orchestrator/implementation-engine.mjs +120 -0
- package/scripts/wave-orchestrator/install.mjs +3 -0
- package/scripts/wave-orchestrator/launcher-runtime.mjs +11 -6
- package/scripts/wave-orchestrator/launcher.mjs +324 -723
- package/scripts/wave-orchestrator/ledger.mjs +56 -27
- package/scripts/wave-orchestrator/local-executor.mjs +37 -0
- package/scripts/wave-orchestrator/planner.mjs +24 -4
- package/scripts/wave-orchestrator/projection-writer.mjs +256 -0
- package/scripts/wave-orchestrator/reconcile-format.mjs +32 -0
- package/scripts/wave-orchestrator/reducer-snapshot.mjs +297 -0
- package/scripts/wave-orchestrator/replay.mjs +3 -1
- package/scripts/wave-orchestrator/result-envelope.mjs +620 -0
- package/scripts/wave-orchestrator/retry-control.mjs +22 -2
- package/scripts/wave-orchestrator/{launcher-retry.mjs → retry-engine.mjs} +352 -18
- package/scripts/wave-orchestrator/role-helpers.mjs +124 -1
- package/scripts/wave-orchestrator/{launcher-supervisor.mjs → session-supervisor.mjs} +178 -103
- package/scripts/wave-orchestrator/shared.mjs +2 -0
- package/scripts/wave-orchestrator/skills.mjs +1 -0
- package/scripts/wave-orchestrator/task-entity.mjs +65 -45
- package/scripts/wave-orchestrator/traces.mjs +10 -1
- package/scripts/wave-orchestrator/wave-files.mjs +96 -10
- package/scripts/wave-orchestrator/wave-state-reducer.mjs +76 -12
- package/skills/README.md +7 -0
- package/skills/role-design/SKILL.md +50 -0
- package/skills/role-design/skill.json +36 -0
- package/skills/tui-design/SKILL.md +77 -0
- package/skills/tui-design/references/tui-design.md +259 -0
- package/skills/tui-design/skill.json +36 -0
- package/wave.config.json +15 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
isOpenCoordinationStatus,
|
|
5
|
+
openClarificationLinkedRequests,
|
|
6
|
+
readMaterializedCoordinationState,
|
|
7
|
+
} from "./coordination-store.mjs";
|
|
8
|
+
import { readWaveHumanFeedbackRequests } from "./coordination.mjs";
|
|
9
|
+
import { readControlPlaneEvents } from "./control-plane.mjs";
|
|
10
|
+
import {
|
|
11
|
+
readWaveAssignmentBarrier,
|
|
12
|
+
readWaveDependencyBarrier,
|
|
13
|
+
readRunResultEnvelope,
|
|
14
|
+
} from "./gate-engine.mjs";
|
|
15
|
+
import { buildResumePlan } from "./retry-engine.mjs";
|
|
16
|
+
import { reduceWaveState } from "./wave-state-reducer.mjs";
|
|
17
|
+
import { resolveWaveRoleBindings } from "./role-helpers.mjs";
|
|
18
|
+
import {
|
|
19
|
+
readWaveStateSnapshot,
|
|
20
|
+
writeWaveStateSnapshot,
|
|
21
|
+
} from "./artifact-schemas.mjs";
|
|
22
|
+
import { ensureDirectory } from "./shared.mjs";
|
|
23
|
+
|
|
24
|
+
function normalizeShadowGate(gate) {
|
|
25
|
+
if (!gate || typeof gate !== "object") {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
ok: gate.ok === true,
|
|
30
|
+
agentId: gate.agentId || null,
|
|
31
|
+
componentId: gate.componentId || null,
|
|
32
|
+
statusCode: gate.statusCode || null,
|
|
33
|
+
detail: gate.detail || null,
|
|
34
|
+
waitingOnAgentIds: Array.isArray(gate.waitingOnAgentIds)
|
|
35
|
+
? [...new Set(gate.waitingOnAgentIds.filter(Boolean))].sort()
|
|
36
|
+
: [],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalizeShadowIdList(values) {
|
|
41
|
+
return [...new Set((values || []).filter(Boolean))].sort();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function shadowSlice(compatibility, reducer) {
|
|
45
|
+
return {
|
|
46
|
+
matches: JSON.stringify(compatibility) === JSON.stringify(reducer),
|
|
47
|
+
compatibility,
|
|
48
|
+
reducer,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function contradictionIds(value) {
|
|
53
|
+
if (value instanceof Map) {
|
|
54
|
+
return [...value.keys()];
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(value)) {
|
|
57
|
+
return value.map((entry) => entry?.contradictionId || entry?.id).filter(Boolean);
|
|
58
|
+
}
|
|
59
|
+
if (value && typeof value === "object") {
|
|
60
|
+
return Object.keys(value);
|
|
61
|
+
}
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function compatibilityBlockerIds(derivedState) {
|
|
66
|
+
const coordinationState = derivedState?.coordinationState || {};
|
|
67
|
+
return normalizeShadowIdList([
|
|
68
|
+
...(coordinationState.blockers || [])
|
|
69
|
+
.filter((record) => isOpenCoordinationStatus(record.status))
|
|
70
|
+
.map((record) => record.id),
|
|
71
|
+
...(coordinationState.clarifications || [])
|
|
72
|
+
.filter((record) => isOpenCoordinationStatus(record.status))
|
|
73
|
+
.map((record) => record.id),
|
|
74
|
+
...openClarificationLinkedRequests(coordinationState).map((record) => record.id),
|
|
75
|
+
...(coordinationState.humanFeedback || [])
|
|
76
|
+
.filter((record) => isOpenCoordinationStatus(record.status))
|
|
77
|
+
.map((record) => record.id),
|
|
78
|
+
...(coordinationState.humanEscalations || [])
|
|
79
|
+
.filter((record) => isOpenCoordinationStatus(record.status))
|
|
80
|
+
.map((record) => record.id),
|
|
81
|
+
...((derivedState?.capabilityAssignments || [])
|
|
82
|
+
.filter((assignment) => assignment.blocking)
|
|
83
|
+
.map((assignment) => assignment.requestId || assignment.id)),
|
|
84
|
+
...((derivedState?.dependencySnapshot?.requiredInbound || []).map((record) => record.id)),
|
|
85
|
+
...((derivedState?.dependencySnapshot?.requiredOutbound || []).map((record) => record.id)),
|
|
86
|
+
...((derivedState?.dependencySnapshot?.unresolvedInboundAssignments || []).map((record) => record.id)),
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function buildReducerShadowDiff({
|
|
91
|
+
derivedState,
|
|
92
|
+
compatibilityGateSnapshot = null,
|
|
93
|
+
compatibilityRelaunchResolution = null,
|
|
94
|
+
reducerState,
|
|
95
|
+
resumePlan,
|
|
96
|
+
}) {
|
|
97
|
+
const helperCompatibility = compatibilityGateSnapshot
|
|
98
|
+
? normalizeShadowGate(compatibilityGateSnapshot.helperAssignmentBarrier)
|
|
99
|
+
: normalizeShadowGate(readWaveAssignmentBarrier(derivedState));
|
|
100
|
+
const dependencyCompatibility = compatibilityGateSnapshot
|
|
101
|
+
? normalizeShadowGate(compatibilityGateSnapshot.dependencyBarrier)
|
|
102
|
+
: normalizeShadowGate(readWaveDependencyBarrier(derivedState));
|
|
103
|
+
const overallCompatibility = compatibilityGateSnapshot
|
|
104
|
+
? normalizeShadowGate(compatibilityGateSnapshot.overall)
|
|
105
|
+
: null;
|
|
106
|
+
const retryCompatibility = compatibilityRelaunchResolution
|
|
107
|
+
? {
|
|
108
|
+
selectedAgentIds: normalizeShadowIdList(
|
|
109
|
+
(compatibilityRelaunchResolution.runs || []).map((run) => run.agent.agentId),
|
|
110
|
+
),
|
|
111
|
+
barrier: compatibilityRelaunchResolution.barrier
|
|
112
|
+
? {
|
|
113
|
+
statusCode: compatibilityRelaunchResolution.barrier.statusCode || null,
|
|
114
|
+
detail: compatibilityRelaunchResolution.barrier.detail || null,
|
|
115
|
+
}
|
|
116
|
+
: null,
|
|
117
|
+
}
|
|
118
|
+
: null;
|
|
119
|
+
const blockerCompatibility = compatibilityBlockerIds(derivedState);
|
|
120
|
+
const contradictionCompatibility = normalizeShadowIdList(
|
|
121
|
+
contradictionIds(derivedState?.contradictions),
|
|
122
|
+
);
|
|
123
|
+
const blockerReducer = normalizeShadowIdList(
|
|
124
|
+
(reducerState?.openBlockers || []).map(
|
|
125
|
+
(blocker) => blocker.id || blocker.taskId || blocker.title || blocker.detail,
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
const contradictionReducer = normalizeShadowIdList(
|
|
129
|
+
contradictionIds(reducerState?.contradictions),
|
|
130
|
+
);
|
|
131
|
+
const retryReducer = {
|
|
132
|
+
selectedAgentIds: normalizeShadowIdList(
|
|
133
|
+
reducerState?.retryTargetSet?.agentIds || resumePlan?.invalidatedAgentIds || [],
|
|
134
|
+
),
|
|
135
|
+
barrier:
|
|
136
|
+
reducerState?.gateSnapshot?.helperAssignmentBarrier?.ok === false
|
|
137
|
+
? {
|
|
138
|
+
statusCode: reducerState.gateSnapshot.helperAssignmentBarrier.statusCode || null,
|
|
139
|
+
detail: reducerState.gateSnapshot.helperAssignmentBarrier.detail || null,
|
|
140
|
+
}
|
|
141
|
+
: reducerState?.gateSnapshot?.dependencyBarrier?.ok === false
|
|
142
|
+
? {
|
|
143
|
+
statusCode: reducerState.gateSnapshot.dependencyBarrier.statusCode || null,
|
|
144
|
+
detail: reducerState.gateSnapshot.dependencyBarrier.detail || null,
|
|
145
|
+
}
|
|
146
|
+
: null,
|
|
147
|
+
resumeFromPhase: resumePlan?.resumeFromPhase || null,
|
|
148
|
+
};
|
|
149
|
+
const shadowDiff = {
|
|
150
|
+
helperAssignmentBarrier: shadowSlice(
|
|
151
|
+
helperCompatibility,
|
|
152
|
+
normalizeShadowGate(reducerState?.gateSnapshot?.helperAssignmentBarrier),
|
|
153
|
+
),
|
|
154
|
+
dependencyBarrier: shadowSlice(
|
|
155
|
+
dependencyCompatibility,
|
|
156
|
+
normalizeShadowGate(reducerState?.gateSnapshot?.dependencyBarrier),
|
|
157
|
+
),
|
|
158
|
+
overallGate: shadowSlice(
|
|
159
|
+
overallCompatibility,
|
|
160
|
+
normalizeShadowGate(reducerState?.gateSnapshot?.overall),
|
|
161
|
+
),
|
|
162
|
+
blockers: shadowSlice(blockerCompatibility, blockerReducer),
|
|
163
|
+
contradictions: shadowSlice(contradictionCompatibility, contradictionReducer),
|
|
164
|
+
closureReadiness: shadowSlice(
|
|
165
|
+
overallCompatibility
|
|
166
|
+
? { allGatesPass: overallCompatibility.ok === true }
|
|
167
|
+
: null,
|
|
168
|
+
{
|
|
169
|
+
allGatesPass: reducerState?.closureEligibility?.allGatesPass === true,
|
|
170
|
+
waveMayClose: reducerState?.closureEligibility?.waveMayClose === true,
|
|
171
|
+
pendingAgentIds: normalizeShadowIdList(
|
|
172
|
+
reducerState?.closureEligibility?.pendingAgentIds || [],
|
|
173
|
+
),
|
|
174
|
+
},
|
|
175
|
+
),
|
|
176
|
+
retryPlan: shadowSlice(retryCompatibility, retryReducer),
|
|
177
|
+
};
|
|
178
|
+
const comparedSlices = Object.values(shadowDiff).filter(
|
|
179
|
+
(slice) => slice.compatibility !== null && slice.reducer !== null,
|
|
180
|
+
);
|
|
181
|
+
return {
|
|
182
|
+
comparedSliceCount: comparedSlices.length,
|
|
183
|
+
matches: comparedSlices.every((slice) => slice.matches),
|
|
184
|
+
slices: shadowDiff,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function computeReducerSnapshot({
|
|
189
|
+
lanePaths,
|
|
190
|
+
wave,
|
|
191
|
+
agentRuns,
|
|
192
|
+
derivedState,
|
|
193
|
+
attempt,
|
|
194
|
+
options = {},
|
|
195
|
+
compatibilityGateSnapshot = null,
|
|
196
|
+
compatibilityRelaunchResolution = null,
|
|
197
|
+
}) {
|
|
198
|
+
const agentEnvelopes = {};
|
|
199
|
+
for (const run of agentRuns) {
|
|
200
|
+
const envelopeResult = readRunResultEnvelope(run, wave, { mode: "live" });
|
|
201
|
+
if (envelopeResult?.valid && envelopeResult.envelope) {
|
|
202
|
+
agentEnvelopes[run.agent.agentId] = envelopeResult.envelope;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const controlPlaneLogPath = path.join(
|
|
207
|
+
lanePaths.controlPlaneDir,
|
|
208
|
+
`wave-${wave.wave}.jsonl`,
|
|
209
|
+
);
|
|
210
|
+
const controlPlaneEvents = fs.existsSync(controlPlaneLogPath)
|
|
211
|
+
? readControlPlaneEvents(controlPlaneLogPath)
|
|
212
|
+
: [];
|
|
213
|
+
|
|
214
|
+
const coordinationLogPath = path.join(
|
|
215
|
+
lanePaths.coordinationDir,
|
|
216
|
+
`wave-${wave.wave}.jsonl`,
|
|
217
|
+
);
|
|
218
|
+
const coordinationRecords = fs.existsSync(coordinationLogPath)
|
|
219
|
+
? readMaterializedCoordinationState(coordinationLogPath)
|
|
220
|
+
: null;
|
|
221
|
+
|
|
222
|
+
const feedbackRequests = readWaveHumanFeedbackRequests({
|
|
223
|
+
feedbackRequestsDir: lanePaths.feedbackRequestsDir,
|
|
224
|
+
lane: lanePaths.lane,
|
|
225
|
+
waveNumber: wave.wave,
|
|
226
|
+
agentIds: (agentRuns || []).map((run) => run.agent.agentId),
|
|
227
|
+
orchestratorId: options.orchestratorId,
|
|
228
|
+
});
|
|
229
|
+
const roleBindings = resolveWaveRoleBindings(wave, lanePaths, wave.agents);
|
|
230
|
+
|
|
231
|
+
const reducerState = reduceWaveState({
|
|
232
|
+
controlPlaneEvents,
|
|
233
|
+
coordinationRecords: coordinationRecords?.latestRecords || [],
|
|
234
|
+
agentEnvelopes,
|
|
235
|
+
waveDefinition: wave,
|
|
236
|
+
dependencyTickets: derivedState?.dependencySnapshot || null,
|
|
237
|
+
feedbackRequests: feedbackRequests || [],
|
|
238
|
+
laneConfig: {
|
|
239
|
+
lane: lanePaths.lane,
|
|
240
|
+
contQaAgentId: roleBindings.contQaAgentId,
|
|
241
|
+
contEvalAgentId: roleBindings.contEvalAgentId,
|
|
242
|
+
integrationAgentId: roleBindings.integrationAgentId,
|
|
243
|
+
documentationAgentId: roleBindings.documentationAgentId,
|
|
244
|
+
validationMode: "live",
|
|
245
|
+
evalTargets: wave.evalTargets,
|
|
246
|
+
benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
|
|
247
|
+
laneProfile: lanePaths.laneProfile,
|
|
248
|
+
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
249
|
+
capabilityRouting: lanePaths.capabilityRouting,
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const resumePlan = buildResumePlan(reducerState, {
|
|
254
|
+
waveDefinition: wave,
|
|
255
|
+
lanePaths,
|
|
256
|
+
});
|
|
257
|
+
const shadowDiff = buildReducerShadowDiff({
|
|
258
|
+
derivedState,
|
|
259
|
+
compatibilityGateSnapshot,
|
|
260
|
+
compatibilityRelaunchResolution,
|
|
261
|
+
reducerState,
|
|
262
|
+
resumePlan,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const stateDir = path.join(lanePaths.stateDir, "reducer");
|
|
266
|
+
ensureDirectory(stateDir);
|
|
267
|
+
const snapshotPath = path.join(stateDir, `wave-${wave.wave}.json`);
|
|
268
|
+
writeWaveStateSnapshot(
|
|
269
|
+
snapshotPath,
|
|
270
|
+
{
|
|
271
|
+
...reducerState,
|
|
272
|
+
attempt,
|
|
273
|
+
resumePlan,
|
|
274
|
+
shadowDiff,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
lane: lanePaths.lane,
|
|
278
|
+
wave: wave.wave,
|
|
279
|
+
},
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
reducerState,
|
|
284
|
+
resumePlan,
|
|
285
|
+
shadowDiff,
|
|
286
|
+
snapshotPath,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function readPersistedReducerSnapshot(lanePaths, waveNumber) {
|
|
291
|
+
const stateDir = path.join(lanePaths.stateDir, "reducer");
|
|
292
|
+
const snapshotPath = path.join(stateDir, `wave-${waveNumber}.json`);
|
|
293
|
+
return readWaveStateSnapshot(snapshotPath, {
|
|
294
|
+
lane: lanePaths.lane,
|
|
295
|
+
wave: waveNumber,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { augmentSummaryWithProofRegistry } from "./proof-registry.mjs";
|
|
3
3
|
import { readJsonOrNull } from "./shared.mjs";
|
|
4
|
-
import { buildGateSnapshot } from "./
|
|
4
|
+
import { buildGateSnapshot } from "./gate-engine.mjs";
|
|
5
|
+
import { materializeContradictionsFromControlPlaneEvents } from "./contradiction-entity.mjs";
|
|
5
6
|
import {
|
|
6
7
|
buildQualityMetrics,
|
|
7
8
|
loadTraceBundle,
|
|
@@ -188,6 +189,7 @@ export function replayTraceBundle(dir) {
|
|
|
188
189
|
capabilityAssignments: bundle.capabilityAssignments || [],
|
|
189
190
|
dependencySnapshot: bundle.dependencySnapshot || null,
|
|
190
191
|
integrationSummary: bundle.integrationSummary,
|
|
192
|
+
contradictions: materializeContradictionsFromControlPlaneEvents(bundle.controlPlaneEvents),
|
|
191
193
|
};
|
|
192
194
|
const gateSnapshot = normalizeGateSnapshotForBundle(
|
|
193
195
|
buildGateSnapshot({
|