@chllming/wave-orchestration 0.8.3 → 0.8.4
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 +19 -0
- package/README.md +47 -11
- package/docs/README.md +6 -2
- package/docs/concepts/what-is-a-wave.md +1 -1
- package/docs/plans/architecture-hardening-migration.md +8 -1
- package/docs/plans/current-state.md +15 -7
- package/docs/plans/end-state-architecture.md +82 -69
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +235 -62
- package/docs/plans/wave-orchestrator.md +37 -11
- package/docs/reference/cli-reference.md +34 -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 +4 -4
- package/package.json +1 -1
- package/releases/manifest.json +20 -0
- package/scripts/wave-orchestrator/agent-state.mjs +0 -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/{launcher-derived-state.mjs → derived-state-engine.mjs} +34 -146
- package/scripts/wave-orchestrator/{launcher-gates.mjs → gate-engine.mjs} +395 -139
- 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/launcher-runtime.mjs +5 -6
- package/scripts/wave-orchestrator/launcher.mjs +271 -724
- 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 +589 -0
- package/scripts/wave-orchestrator/retry-control.mjs +5 -0
- package/scripts/wave-orchestrator/{launcher-retry.mjs → retry-engine.mjs} +267 -18
- package/scripts/wave-orchestrator/role-helpers.mjs +51 -0
- package/scripts/wave-orchestrator/{launcher-supervisor.mjs → session-supervisor.mjs} +178 -103
- package/scripts/wave-orchestrator/shared.mjs +1 -0
- package/scripts/wave-orchestrator/traces.mjs +10 -1
- package/scripts/wave-orchestrator/wave-files.mjs +11 -9
- package/scripts/wave-orchestrator/wave-state-reducer.mjs +52 -5
|
@@ -5,8 +5,17 @@ import {
|
|
|
5
5
|
setWaveDashboardAgent,
|
|
6
6
|
updateWaveDashboardMessageBoard,
|
|
7
7
|
} from "./dashboard-state.mjs";
|
|
8
|
+
import {
|
|
9
|
+
materializeAgentExecutionSummaryForRun as materializeAgentExecutionSummaryForRunDefault,
|
|
10
|
+
readWaveComponentMatrixGate as readWaveComponentMatrixGateDefault,
|
|
11
|
+
readWaveContEvalGate as readWaveContEvalGateDefault,
|
|
12
|
+
readWaveContQaGate as readWaveContQaGateDefault,
|
|
13
|
+
readWaveDocumentationGate as readWaveDocumentationGateDefault,
|
|
14
|
+
readWaveIntegrationBarrier as readWaveIntegrationBarrierDefault,
|
|
15
|
+
readWaveSecurityGate as readWaveSecurityGateDefault,
|
|
16
|
+
} from "./gate-engine.mjs";
|
|
8
17
|
import { REPO_ROOT, toIsoTimestamp } from "./shared.mjs";
|
|
9
|
-
import { isSecurityReviewAgent } from "./role-helpers.mjs";
|
|
18
|
+
import { isSecurityReviewAgent, resolveWaveRoleBindings } from "./role-helpers.mjs";
|
|
10
19
|
import { summarizeResolvedSkills } from "./skills.mjs";
|
|
11
20
|
|
|
12
21
|
function failureResultFromGate(gate, fallbackLogPath) {
|
|
@@ -71,76 +80,41 @@ export async function runClosureSweepPhase({
|
|
|
71
80
|
materializeAgentExecutionSummaryForRunFn,
|
|
72
81
|
monitorWaveHumanFeedbackFn,
|
|
73
82
|
}) {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
refreshDerivedState?.(dashboardState?.attempt || 0),
|
|
110
|
-
{
|
|
111
|
-
integrationAgentId,
|
|
112
|
-
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
113
|
-
},
|
|
114
|
-
),
|
|
115
|
-
actionRequested:
|
|
116
|
-
`Lane ${lanePaths.lane} owners should resolve integration contradictions or blockers before documentation and cont-QA closure.`,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
agentId: documentationAgentId,
|
|
120
|
-
label: "Documentation closure",
|
|
121
|
-
runs: closureRuns.filter((run) => run.agent.agentId === documentationAgentId),
|
|
122
|
-
validate: () => {
|
|
123
|
-
const documentationGate = readWaveDocumentationGateFn(wave, closureRuns);
|
|
124
|
-
if (!documentationGate.ok) {
|
|
125
|
-
return documentationGate;
|
|
126
|
-
}
|
|
127
|
-
return readWaveComponentMatrixGateFn(wave, closureRuns, {
|
|
128
|
-
laneProfile: lanePaths.laneProfile,
|
|
129
|
-
documentationAgentId,
|
|
130
|
-
});
|
|
131
|
-
},
|
|
132
|
-
actionRequested:
|
|
133
|
-
`Lane ${lanePaths.lane} owners should resolve the shared-plan or component-matrix closure state before cont-QA progression.`,
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
agentId: contQaAgentId,
|
|
137
|
-
label: "cont-QA gate",
|
|
138
|
-
runs: closureRuns.filter((run) => run.agent.agentId === contQaAgentId),
|
|
139
|
-
validate: () => readWaveContQaGateFn(wave, closureRuns, { contQaAgentId, mode: "live" }),
|
|
140
|
-
actionRequested:
|
|
141
|
-
`Lane ${lanePaths.lane} owners should resolve the cont-QA gate before wave progression.`,
|
|
142
|
-
},
|
|
143
|
-
];
|
|
83
|
+
const materializeSummary =
|
|
84
|
+
typeof materializeAgentExecutionSummaryForRunFn === "function"
|
|
85
|
+
? materializeAgentExecutionSummaryForRunFn
|
|
86
|
+
: materializeAgentExecutionSummaryForRunDefault;
|
|
87
|
+
const monitorHumanFeedback =
|
|
88
|
+
typeof monitorWaveHumanFeedbackFn === "function"
|
|
89
|
+
? monitorWaveHumanFeedbackFn
|
|
90
|
+
: () => false;
|
|
91
|
+
const readContEvalGate =
|
|
92
|
+
typeof readWaveContEvalGateFn === "function"
|
|
93
|
+
? readWaveContEvalGateFn
|
|
94
|
+
: readWaveContEvalGateDefault;
|
|
95
|
+
const readSecurityGate =
|
|
96
|
+
typeof readWaveSecurityGateFn === "function"
|
|
97
|
+
? readWaveSecurityGateFn
|
|
98
|
+
: readWaveSecurityGateDefault;
|
|
99
|
+
const readIntegrationBarrier =
|
|
100
|
+
typeof readWaveIntegrationBarrierFn === "function"
|
|
101
|
+
? readWaveIntegrationBarrierFn
|
|
102
|
+
: readWaveIntegrationBarrierDefault;
|
|
103
|
+
const readDocumentationGate =
|
|
104
|
+
typeof readWaveDocumentationGateFn === "function"
|
|
105
|
+
? readWaveDocumentationGateFn
|
|
106
|
+
: readWaveDocumentationGateDefault;
|
|
107
|
+
const readComponentMatrixGate =
|
|
108
|
+
typeof readWaveComponentMatrixGateFn === "function"
|
|
109
|
+
? readWaveComponentMatrixGateFn
|
|
110
|
+
: readWaveComponentMatrixGateDefault;
|
|
111
|
+
const readContQaGate =
|
|
112
|
+
typeof readWaveContQaGateFn === "function"
|
|
113
|
+
? readWaveContQaGateFn
|
|
114
|
+
: readWaveContQaGateDefault;
|
|
115
|
+
const stagedRuns = planClosureStages({ lanePaths, wave, closureRuns });
|
|
116
|
+
const { contQaAgentId, contEvalAgentId, integrationAgentId, documentationAgentId } =
|
|
117
|
+
resolveWaveRoleBindings(wave, lanePaths);
|
|
144
118
|
for (const stage of stagedRuns) {
|
|
145
119
|
if (stage.runs.length === 0) {
|
|
146
120
|
continue;
|
|
@@ -177,6 +151,11 @@ export async function runClosureSweepPhase({
|
|
|
177
151
|
agentRateLimitBaseDelaySeconds: options.agentRateLimitBaseDelaySeconds,
|
|
178
152
|
agentRateLimitMaxDelaySeconds: options.agentRateLimitMaxDelaySeconds,
|
|
179
153
|
context7Enabled: options.context7Enabled,
|
|
154
|
+
attempt: dashboardState?.attempt || 1,
|
|
155
|
+
controlPlane: {
|
|
156
|
+
waveNumber: wave.wave,
|
|
157
|
+
attempt: dashboardState?.attempt || 1,
|
|
158
|
+
},
|
|
180
159
|
});
|
|
181
160
|
runInfo.lastLaunchAttempt = dashboardState?.attempt || null;
|
|
182
161
|
runInfo.lastPromptHash = launchResult?.promptHash || null;
|
|
@@ -201,7 +180,7 @@ export async function runClosureSweepPhase({
|
|
|
201
180
|
refreshWaveDashboardAgentStates(dashboardState, [runInfo], pendingAgentIds, (event) =>
|
|
202
181
|
recordCombinedEvent(event),
|
|
203
182
|
);
|
|
204
|
-
const feedbackChanged =
|
|
183
|
+
const feedbackChanged = monitorHumanFeedback({
|
|
205
184
|
lanePaths,
|
|
206
185
|
waveNumber: wave.wave,
|
|
207
186
|
agentRuns: [runInfo],
|
|
@@ -217,14 +196,37 @@ export async function runClosureSweepPhase({
|
|
|
217
196
|
updateWaveDashboardMessageBoard(dashboardState, runInfo.messageBoardPath);
|
|
218
197
|
flushDashboards();
|
|
219
198
|
},
|
|
199
|
+
{
|
|
200
|
+
controlPlane: {
|
|
201
|
+
waveNumber: wave.wave,
|
|
202
|
+
attempt: dashboardState?.attempt || 1,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
220
205
|
);
|
|
221
|
-
|
|
206
|
+
materializeSummary(wave, runInfo);
|
|
222
207
|
refreshDerivedState?.(dashboardState?.attempt || 0);
|
|
223
208
|
if (result.failures.length > 0) {
|
|
224
209
|
return result;
|
|
225
210
|
}
|
|
226
211
|
}
|
|
227
|
-
const gate =
|
|
212
|
+
const gate = evaluateClosureStage({
|
|
213
|
+
stage,
|
|
214
|
+
wave,
|
|
215
|
+
closureRuns,
|
|
216
|
+
lanePaths,
|
|
217
|
+
dashboardState,
|
|
218
|
+
refreshDerivedState,
|
|
219
|
+
readWaveContEvalGateFn: readContEvalGate,
|
|
220
|
+
readWaveSecurityGateFn: readSecurityGate,
|
|
221
|
+
readWaveIntegrationBarrierFn: readIntegrationBarrier,
|
|
222
|
+
readWaveDocumentationGateFn: readDocumentationGate,
|
|
223
|
+
readWaveComponentMatrixGateFn: readComponentMatrixGate,
|
|
224
|
+
readWaveContQaGateFn: readContQaGate,
|
|
225
|
+
contEvalAgentId,
|
|
226
|
+
integrationAgentId,
|
|
227
|
+
documentationAgentId,
|
|
228
|
+
contQaAgentId,
|
|
229
|
+
});
|
|
228
230
|
if (!gate.ok) {
|
|
229
231
|
recordClosureGateFailure({
|
|
230
232
|
wave,
|
|
@@ -244,6 +246,120 @@ export async function runClosureSweepPhase({
|
|
|
244
246
|
return { failures: [], timedOut: false };
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
export function planClosureStages({ lanePaths, wave, closureRuns }) {
|
|
250
|
+
const { contQaAgentId, contEvalAgentId, integrationAgentId, documentationAgentId } =
|
|
251
|
+
resolveWaveRoleBindings(wave, lanePaths);
|
|
252
|
+
return [
|
|
253
|
+
{
|
|
254
|
+
key: "cont-eval",
|
|
255
|
+
agentId: contEvalAgentId,
|
|
256
|
+
label: "cont-EVAL gate",
|
|
257
|
+
runs: closureRuns.filter((run) => run.agent.agentId === contEvalAgentId),
|
|
258
|
+
actionRequested:
|
|
259
|
+
`Lane ${lanePaths.lane} owners should resolve cont-EVAL tuning gaps before integration closure.`,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "security-review",
|
|
263
|
+
agentId: "security",
|
|
264
|
+
label: "Security review",
|
|
265
|
+
runs: closureRuns.filter((run) => isSecurityReviewAgent(run.agent)),
|
|
266
|
+
actionRequested:
|
|
267
|
+
`Lane ${lanePaths.lane} owners should resolve blocked security findings or missing approvals before integration closure.`,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
key: "integration",
|
|
271
|
+
agentId: integrationAgentId,
|
|
272
|
+
label: "Integration gate",
|
|
273
|
+
runs: closureRuns.filter((run) => run.agent.agentId === integrationAgentId),
|
|
274
|
+
actionRequested:
|
|
275
|
+
`Lane ${lanePaths.lane} owners should resolve integration contradictions or blockers before documentation and cont-QA closure.`,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
key: "documentation",
|
|
279
|
+
agentId: documentationAgentId,
|
|
280
|
+
label: "Documentation closure",
|
|
281
|
+
runs: closureRuns.filter((run) => run.agent.agentId === documentationAgentId),
|
|
282
|
+
actionRequested:
|
|
283
|
+
`Lane ${lanePaths.lane} owners should resolve the shared-plan or component-matrix closure state before cont-QA progression.`,
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
key: "cont-qa",
|
|
287
|
+
agentId: contQaAgentId,
|
|
288
|
+
label: "cont-QA gate",
|
|
289
|
+
runs: closureRuns.filter((run) => run.agent.agentId === contQaAgentId),
|
|
290
|
+
actionRequested:
|
|
291
|
+
`Lane ${lanePaths.lane} owners should resolve the cont-QA gate before wave progression.`,
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function evaluateClosureStage({
|
|
297
|
+
stage,
|
|
298
|
+
wave,
|
|
299
|
+
closureRuns,
|
|
300
|
+
lanePaths,
|
|
301
|
+
dashboardState,
|
|
302
|
+
refreshDerivedState,
|
|
303
|
+
readWaveContEvalGateFn,
|
|
304
|
+
readWaveSecurityGateFn,
|
|
305
|
+
readWaveIntegrationBarrierFn,
|
|
306
|
+
readWaveDocumentationGateFn,
|
|
307
|
+
readWaveComponentMatrixGateFn,
|
|
308
|
+
readWaveContQaGateFn,
|
|
309
|
+
contEvalAgentId,
|
|
310
|
+
integrationAgentId,
|
|
311
|
+
documentationAgentId,
|
|
312
|
+
contQaAgentId,
|
|
313
|
+
}) {
|
|
314
|
+
switch (stage.key) {
|
|
315
|
+
case "cont-eval":
|
|
316
|
+
return readWaveContEvalGateFn(wave, closureRuns, {
|
|
317
|
+
contEvalAgentId,
|
|
318
|
+
mode: "live",
|
|
319
|
+
evalTargets: wave.evalTargets,
|
|
320
|
+
benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
|
|
321
|
+
});
|
|
322
|
+
case "security-review":
|
|
323
|
+
return readWaveSecurityGateFn(wave, closureRuns, { mode: "live" });
|
|
324
|
+
case "integration":
|
|
325
|
+
return readWaveIntegrationBarrierFn(
|
|
326
|
+
wave,
|
|
327
|
+
closureRuns,
|
|
328
|
+
refreshDerivedState?.(dashboardState?.attempt || 0),
|
|
329
|
+
{
|
|
330
|
+
integrationAgentId,
|
|
331
|
+
mode: "live",
|
|
332
|
+
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
case "documentation": {
|
|
336
|
+
const documentationGate = readWaveDocumentationGateFn(wave, closureRuns, {
|
|
337
|
+
mode: "live",
|
|
338
|
+
});
|
|
339
|
+
if (!documentationGate.ok) {
|
|
340
|
+
return documentationGate;
|
|
341
|
+
}
|
|
342
|
+
return readWaveComponentMatrixGateFn(wave, closureRuns, {
|
|
343
|
+
laneProfile: lanePaths.laneProfile,
|
|
344
|
+
documentationAgentId,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
case "cont-qa":
|
|
348
|
+
return readWaveContQaGateFn(wave, closureRuns, {
|
|
349
|
+
contQaAgentId,
|
|
350
|
+
mode: "live",
|
|
351
|
+
});
|
|
352
|
+
default:
|
|
353
|
+
return {
|
|
354
|
+
ok: true,
|
|
355
|
+
agentId: null,
|
|
356
|
+
statusCode: "pass",
|
|
357
|
+
detail: "No closure stage configured.",
|
|
358
|
+
logPath: null,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
247
363
|
const NON_BLOCKING_INFRA_SIGNAL_STATES = new Set([
|
|
248
364
|
"conformant",
|
|
249
365
|
"setup-required",
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
materializeAgentExecutionSummaryForRun,
|
|
5
5
|
materializeAgentExecutionSummaries,
|
|
6
6
|
readRunExecutionSummary,
|
|
7
|
-
} from "./
|
|
7
|
+
} from "./gate-engine.mjs";
|
|
8
8
|
import {
|
|
9
9
|
isOpenCoordinationStatus,
|
|
10
10
|
appendCoordinationRecord,
|
|
@@ -13,9 +13,6 @@ import {
|
|
|
13
13
|
readMaterializedCoordinationState,
|
|
14
14
|
renderCoordinationBoardProjection,
|
|
15
15
|
updateSeedRecords,
|
|
16
|
-
writeCompiledInbox,
|
|
17
|
-
writeCoordinationBoardProjection,
|
|
18
|
-
writeJsonArtifact,
|
|
19
16
|
buildCoordinationResponseMetrics,
|
|
20
17
|
} from "./coordination-store.mjs";
|
|
21
18
|
import { triageClarificationRequests } from "./clarification-triage.mjs";
|
|
@@ -24,29 +21,21 @@ import {
|
|
|
24
21
|
buildRequestAssignments,
|
|
25
22
|
renderDependencySnapshotMarkdown,
|
|
26
23
|
syncAssignmentRecords,
|
|
27
|
-
writeDependencySnapshotMarkdown,
|
|
28
24
|
} from "./routing-state.mjs";
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} from "./artifact-schemas.mjs";
|
|
33
|
-
import { deriveWaveLedger, readWaveLedger, writeWaveLedger } from "./ledger.mjs";
|
|
34
|
-
import { buildDocsQueue, readDocsQueue, writeDocsQueue } from "./docs-queue.mjs";
|
|
35
|
-
import {
|
|
36
|
-
parseStructuredSignalsFromLog,
|
|
37
|
-
} from "./dashboard-state.mjs";
|
|
25
|
+
import { deriveWaveLedger, readWaveLedger } from "./ledger.mjs";
|
|
26
|
+
import { buildDocsQueue, readDocsQueue } from "./docs-queue.mjs";
|
|
27
|
+
import { parseStructuredSignalsFromLog } from "./dashboard-state.mjs";
|
|
38
28
|
import {
|
|
39
29
|
isSecurityReviewAgent,
|
|
40
30
|
resolveSecurityReviewReportPath,
|
|
41
31
|
isContEvalImplementationOwningAgent,
|
|
32
|
+
resolveWaveRoleBindings,
|
|
42
33
|
} from "./role-helpers.mjs";
|
|
43
34
|
import {
|
|
44
35
|
REPO_ROOT,
|
|
45
36
|
compactSingleLine,
|
|
46
|
-
ensureDirectory,
|
|
47
37
|
readJsonOrNull,
|
|
48
38
|
toIsoTimestamp,
|
|
49
|
-
writeTextAtomic,
|
|
50
39
|
} from "./shared.mjs";
|
|
51
40
|
import {
|
|
52
41
|
validateContEvalSummary,
|
|
@@ -307,27 +296,6 @@ export function buildWaveSecuritySummary({
|
|
|
307
296
|
};
|
|
308
297
|
}
|
|
309
298
|
|
|
310
|
-
function renderWaveSecuritySummaryMarkdown(securitySummary) {
|
|
311
|
-
return [
|
|
312
|
-
`# Wave ${securitySummary.wave} Security Summary`,
|
|
313
|
-
"",
|
|
314
|
-
`- State: ${securitySummary.overallState || "unknown"}`,
|
|
315
|
-
`- Detail: ${securitySummary.detail || "n/a"}`,
|
|
316
|
-
`- Total findings: ${securitySummary.totalFindings || 0}`,
|
|
317
|
-
`- Total approvals: ${securitySummary.totalApprovals || 0}`,
|
|
318
|
-
`- Reviewers: ${(securitySummary.agents || []).length}`,
|
|
319
|
-
"",
|
|
320
|
-
"## Reviews",
|
|
321
|
-
...((securitySummary.agents || []).length > 0
|
|
322
|
-
? securitySummary.agents.map(
|
|
323
|
-
(entry) =>
|
|
324
|
-
`- ${entry.agentId}: state=${entry.state || "unknown"} findings=${entry.findings || 0} approvals=${entry.approvals || 0}${entry.reportPath ? ` report=${entry.reportPath}` : ""}${entry.detail ? ` detail=${entry.detail}` : ""}`,
|
|
325
|
-
)
|
|
326
|
-
: ["- None."]),
|
|
327
|
-
"",
|
|
328
|
-
].join("\n");
|
|
329
|
-
}
|
|
330
|
-
|
|
331
299
|
function padReportedEntries(entries, minimumCount, label) {
|
|
332
300
|
const padded = [...entries];
|
|
333
301
|
for (let index = padded.length + 1; index <= minimumCount; index += 1) {
|
|
@@ -339,6 +307,7 @@ function padReportedEntries(entries, minimumCount, label) {
|
|
|
339
307
|
function buildIntegrationEvidence({
|
|
340
308
|
lanePaths,
|
|
341
309
|
wave,
|
|
310
|
+
roleBindings = resolveWaveRoleBindings(wave, lanePaths),
|
|
342
311
|
coordinationState,
|
|
343
312
|
summariesByAgentId,
|
|
344
313
|
docsQueue,
|
|
@@ -404,14 +373,14 @@ function buildIntegrationEvidence({
|
|
|
404
373
|
for (const agent of wave.agents || []) {
|
|
405
374
|
const summary = summariesByAgentId?.[agent.agentId] || null;
|
|
406
375
|
const contEvalImplementationOwning =
|
|
407
|
-
agent.agentId ===
|
|
376
|
+
agent.agentId === roleBindings.contEvalAgentId &&
|
|
408
377
|
isContEvalImplementationOwningAgent(agent, {
|
|
409
|
-
contEvalAgentId:
|
|
378
|
+
contEvalAgentId: roleBindings.contEvalAgentId,
|
|
410
379
|
});
|
|
411
380
|
if (isSecurityReviewAgent(agent)) {
|
|
412
381
|
continue;
|
|
413
382
|
}
|
|
414
|
-
if (agent.agentId ===
|
|
383
|
+
if (agent.agentId === roleBindings.contEvalAgentId) {
|
|
415
384
|
const validation = validateContEvalSummary(agent, summary, {
|
|
416
385
|
mode: "live",
|
|
417
386
|
evalTargets: wave.evalTargets,
|
|
@@ -425,11 +394,11 @@ function buildIntegrationEvidence({
|
|
|
425
394
|
}
|
|
426
395
|
if (
|
|
427
396
|
![
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
397
|
+
roleBindings.contQaAgentId,
|
|
398
|
+
roleBindings.integrationAgentId,
|
|
399
|
+
roleBindings.documentationAgentId,
|
|
431
400
|
].includes(agent.agentId) &&
|
|
432
|
-
(agent.agentId !==
|
|
401
|
+
(agent.agentId !== roleBindings.contEvalAgentId || contEvalImplementationOwning)
|
|
433
402
|
) {
|
|
434
403
|
const validation = validateImplementationSummary(agent, summary);
|
|
435
404
|
if (!validation.ok) {
|
|
@@ -553,10 +522,12 @@ export function buildWaveIntegrationSummary({
|
|
|
553
522
|
dependencySnapshot = null,
|
|
554
523
|
securitySummary = null,
|
|
555
524
|
}) {
|
|
556
|
-
const
|
|
525
|
+
const roleBindings = resolveWaveRoleBindings(wave, lanePaths);
|
|
526
|
+
const explicitIntegration = summariesByAgentId[roleBindings.integrationAgentId]?.integration || null;
|
|
557
527
|
const evidence = buildIntegrationEvidence({
|
|
558
528
|
lanePaths,
|
|
559
529
|
wave,
|
|
530
|
+
roleBindings,
|
|
560
531
|
coordinationState,
|
|
561
532
|
summariesByAgentId,
|
|
562
533
|
docsQueue,
|
|
@@ -569,7 +540,7 @@ export function buildWaveIntegrationSummary({
|
|
|
569
540
|
return {
|
|
570
541
|
wave: wave.wave,
|
|
571
542
|
lane: lanePaths.lane,
|
|
572
|
-
agentId:
|
|
543
|
+
agentId: roleBindings.integrationAgentId,
|
|
573
544
|
attempt,
|
|
574
545
|
openClaims: padReportedEntries(
|
|
575
546
|
evidence.openClaims,
|
|
@@ -619,63 +590,7 @@ export function buildWaveIntegrationSummary({
|
|
|
619
590
|
};
|
|
620
591
|
}
|
|
621
592
|
|
|
622
|
-
function
|
|
623
|
-
return [
|
|
624
|
-
title,
|
|
625
|
-
...((items || []).length > 0 ? items.map((item) => `- ${item}`) : ["- None."]),
|
|
626
|
-
"",
|
|
627
|
-
];
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
function renderIntegrationSummaryMarkdown(integrationSummary) {
|
|
631
|
-
return [
|
|
632
|
-
`# Wave ${integrationSummary.wave} Integration Summary`,
|
|
633
|
-
"",
|
|
634
|
-
`- Recommendation: ${integrationSummary.recommendation || "unknown"}`,
|
|
635
|
-
`- Detail: ${integrationSummary.detail || "n/a"}`,
|
|
636
|
-
`- Open claims: ${(integrationSummary.openClaims || []).length}`,
|
|
637
|
-
`- Conflicting claims: ${(integrationSummary.conflictingClaims || []).length}`,
|
|
638
|
-
`- Unresolved blockers: ${(integrationSummary.unresolvedBlockers || []).length}`,
|
|
639
|
-
`- Changed interfaces: ${(integrationSummary.changedInterfaces || []).length}`,
|
|
640
|
-
`- Cross-component impacts: ${(integrationSummary.crossComponentImpacts || []).length}`,
|
|
641
|
-
`- Proof gaps: ${(integrationSummary.proofGaps || []).length}`,
|
|
642
|
-
`- Deploy risks: ${(integrationSummary.deployRisks || []).length}`,
|
|
643
|
-
`- Documentation gaps: ${(integrationSummary.docGaps || []).length}`,
|
|
644
|
-
`- Security review: ${integrationSummary.securityState || "not-applicable"}`,
|
|
645
|
-
`- Security findings: ${(integrationSummary.securityFindings || []).length}`,
|
|
646
|
-
`- Security approvals: ${(integrationSummary.securityApprovals || []).length}`,
|
|
647
|
-
`- Inbound dependencies: ${(integrationSummary.inboundDependencies || []).length}`,
|
|
648
|
-
`- Outbound dependencies: ${(integrationSummary.outboundDependencies || []).length}`,
|
|
649
|
-
`- Helper assignments: ${(integrationSummary.helperAssignments || []).length}`,
|
|
650
|
-
"",
|
|
651
|
-
...renderIntegrationSection("## Open Claims", integrationSummary.openClaims),
|
|
652
|
-
...renderIntegrationSection("## Conflicting Claims", integrationSummary.conflictingClaims),
|
|
653
|
-
...renderIntegrationSection("## Unresolved Blockers", integrationSummary.unresolvedBlockers),
|
|
654
|
-
...renderIntegrationSection("## Changed Interfaces", integrationSummary.changedInterfaces),
|
|
655
|
-
...renderIntegrationSection(
|
|
656
|
-
"## Cross-Component Impacts",
|
|
657
|
-
integrationSummary.crossComponentImpacts,
|
|
658
|
-
),
|
|
659
|
-
...renderIntegrationSection("## Proof Gaps", integrationSummary.proofGaps),
|
|
660
|
-
...renderIntegrationSection("## Deploy Risks", integrationSummary.deployRisks),
|
|
661
|
-
...renderIntegrationSection("## Security Findings", integrationSummary.securityFindings),
|
|
662
|
-
...renderIntegrationSection("## Security Approvals", integrationSummary.securityApprovals),
|
|
663
|
-
...renderIntegrationSection("## Inbound Dependencies", integrationSummary.inboundDependencies),
|
|
664
|
-
...renderIntegrationSection("## Outbound Dependencies", integrationSummary.outboundDependencies),
|
|
665
|
-
...renderIntegrationSection("## Helper Assignments", integrationSummary.helperAssignments),
|
|
666
|
-
"## Runtime Assignments",
|
|
667
|
-
...((integrationSummary.runtimeAssignments || []).length > 0
|
|
668
|
-
? integrationSummary.runtimeAssignments.map(
|
|
669
|
-
(assignment) =>
|
|
670
|
-
`- ${assignment.agentId}: executor=${assignment.executorId || "n/a"} role=${assignment.role || "n/a"} profile=${assignment.profile || "none"} fallback_used=${assignment.fallbackUsed ? "yes" : "no"}`,
|
|
671
|
-
)
|
|
672
|
-
: ["- None."]),
|
|
673
|
-
"",
|
|
674
|
-
...renderIntegrationSection("## Documentation Gaps", integrationSummary.docGaps),
|
|
675
|
-
].join("\n");
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
export function writeWaveDerivedState({
|
|
593
|
+
export function buildWaveDerivedState({
|
|
679
594
|
lanePaths,
|
|
680
595
|
wave,
|
|
681
596
|
agentRuns = [],
|
|
@@ -684,6 +599,7 @@ export function writeWaveDerivedState({
|
|
|
684
599
|
attempt = 0,
|
|
685
600
|
orchestratorId = null,
|
|
686
601
|
}) {
|
|
602
|
+
const roleBindings = resolveWaveRoleBindings(wave, lanePaths);
|
|
687
603
|
const coordinationLogPath = waveCoordinationLogPath(lanePaths, wave.wave);
|
|
688
604
|
const existingDocsQueue = readDocsQueue(waveDocsQueuePath(lanePaths, wave.wave));
|
|
689
605
|
const existingIntegrationSummary = readJsonOrNull(waveIntegrationPath(lanePaths, wave.wave));
|
|
@@ -694,10 +610,10 @@ export function writeWaveDerivedState({
|
|
|
694
610
|
agents: wave.agents,
|
|
695
611
|
componentPromotions: wave.componentPromotions,
|
|
696
612
|
sharedPlanDocs: lanePaths.sharedPlanDocs,
|
|
697
|
-
contQaAgentId:
|
|
698
|
-
contEvalAgentId:
|
|
699
|
-
integrationAgentId:
|
|
700
|
-
documentationAgentId:
|
|
613
|
+
contQaAgentId: roleBindings.contQaAgentId,
|
|
614
|
+
contEvalAgentId: roleBindings.contEvalAgentId,
|
|
615
|
+
integrationAgentId: roleBindings.integrationAgentId,
|
|
616
|
+
documentationAgentId: roleBindings.documentationAgentId,
|
|
701
617
|
feedbackRequests,
|
|
702
618
|
});
|
|
703
619
|
let coordinationState = readMaterializedCoordinationState(coordinationLogPath);
|
|
@@ -738,18 +654,6 @@ export function writeWaveDerivedState({
|
|
|
738
654
|
ledger: existingLedger,
|
|
739
655
|
capabilityRouting: lanePaths.capabilityRouting,
|
|
740
656
|
});
|
|
741
|
-
writeAssignmentSnapshot(waveAssignmentsPath(lanePaths, wave.wave), capabilityAssignments, {
|
|
742
|
-
lane: lanePaths.lane,
|
|
743
|
-
wave: wave.wave,
|
|
744
|
-
});
|
|
745
|
-
writeDependencySnapshot(waveDependencySnapshotPath(lanePaths, wave.wave), dependencySnapshot, {
|
|
746
|
-
lane: lanePaths.lane,
|
|
747
|
-
wave: wave.wave,
|
|
748
|
-
});
|
|
749
|
-
writeDependencySnapshotMarkdown(
|
|
750
|
-
waveDependencySnapshotMarkdownPath(lanePaths, wave.wave),
|
|
751
|
-
dependencySnapshot,
|
|
752
|
-
);
|
|
753
657
|
const runtimeAssignments = wave.agents.map((agent) => ({
|
|
754
658
|
agentId: agent.agentId,
|
|
755
659
|
role: agent.executorResolved?.role || null,
|
|
@@ -772,18 +676,12 @@ export function writeWaveDerivedState({
|
|
|
772
676
|
componentPromotions: wave.componentPromotions,
|
|
773
677
|
runtimeAssignments,
|
|
774
678
|
});
|
|
775
|
-
writeDocsQueue(waveDocsQueuePath(lanePaths, wave.wave), docsQueue);
|
|
776
679
|
const securitySummary = buildWaveSecuritySummary({
|
|
777
680
|
lanePaths,
|
|
778
681
|
wave,
|
|
779
682
|
attempt,
|
|
780
683
|
summariesByAgentId,
|
|
781
684
|
});
|
|
782
|
-
writeJsonArtifact(waveSecurityPath(lanePaths, wave.wave), securitySummary);
|
|
783
|
-
writeTextAtomic(
|
|
784
|
-
waveSecurityMarkdownPath(lanePaths, wave.wave),
|
|
785
|
-
`${renderWaveSecuritySummaryMarkdown(securitySummary)}\n`,
|
|
786
|
-
);
|
|
787
685
|
const integrationSummary = buildWaveIntegrationSummary({
|
|
788
686
|
lanePaths,
|
|
789
687
|
wave,
|
|
@@ -797,11 +695,6 @@ export function writeWaveDerivedState({
|
|
|
797
695
|
dependencySnapshot,
|
|
798
696
|
securitySummary,
|
|
799
697
|
});
|
|
800
|
-
writeJsonArtifact(waveIntegrationPath(lanePaths, wave.wave), integrationSummary);
|
|
801
|
-
writeTextAtomic(
|
|
802
|
-
waveIntegrationMarkdownPath(lanePaths, wave.wave),
|
|
803
|
-
`${renderIntegrationSummaryMarkdown(integrationSummary)}\n`,
|
|
804
|
-
);
|
|
805
698
|
const ledger = deriveWaveLedger({
|
|
806
699
|
lane: lanePaths.lane,
|
|
807
700
|
wave,
|
|
@@ -810,17 +703,15 @@ export function writeWaveDerivedState({
|
|
|
810
703
|
integrationSummary,
|
|
811
704
|
docsQueue,
|
|
812
705
|
attempt,
|
|
813
|
-
contQaAgentId:
|
|
814
|
-
contEvalAgentId:
|
|
815
|
-
integrationAgentId:
|
|
816
|
-
documentationAgentId:
|
|
706
|
+
contQaAgentId: roleBindings.contQaAgentId,
|
|
707
|
+
contEvalAgentId: roleBindings.contEvalAgentId,
|
|
708
|
+
integrationAgentId: roleBindings.integrationAgentId,
|
|
709
|
+
documentationAgentId: roleBindings.documentationAgentId,
|
|
817
710
|
benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
|
|
818
711
|
capabilityAssignments,
|
|
819
712
|
dependencySnapshot,
|
|
820
713
|
});
|
|
821
|
-
writeWaveLedger(waveLedgerPath(lanePaths, wave.wave), ledger);
|
|
822
714
|
const inboxDir = waveInboxDir(lanePaths, wave.wave);
|
|
823
|
-
ensureDirectory(inboxDir);
|
|
824
715
|
const sharedSummary = compileSharedSummary({
|
|
825
716
|
wave,
|
|
826
717
|
state: coordinationState,
|
|
@@ -830,7 +721,6 @@ export function writeWaveDerivedState({
|
|
|
830
721
|
dependencySnapshot,
|
|
831
722
|
});
|
|
832
723
|
const sharedSummaryPath = path.join(inboxDir, "shared-summary.md");
|
|
833
|
-
writeCompiledInbox(sharedSummaryPath, sharedSummary.text);
|
|
834
724
|
const inboxesByAgentId = {};
|
|
835
725
|
for (const agent of wave.agents) {
|
|
836
726
|
const inbox = compileAgentInbox({
|
|
@@ -844,7 +734,6 @@ export function writeWaveDerivedState({
|
|
|
844
734
|
dependencySnapshot,
|
|
845
735
|
});
|
|
846
736
|
const inboxPath = path.join(inboxDir, `${agent.agentId}.md`);
|
|
847
|
-
writeCompiledInbox(inboxPath, inbox.text);
|
|
848
737
|
inboxesByAgentId[agent.agentId] = { path: inboxPath, text: inbox.text, truncated: inbox.truncated };
|
|
849
738
|
}
|
|
850
739
|
const boardText = renderCoordinationBoardProjection({
|
|
@@ -857,26 +746,25 @@ export function writeWaveDerivedState({
|
|
|
857
746
|
});
|
|
858
747
|
const responseMetrics = buildCoordinationResponseMetrics(coordinationState);
|
|
859
748
|
const messageBoardPath = path.join(lanePaths.messageboardsDir, `wave-${wave.wave}.md`);
|
|
860
|
-
writeCoordinationBoardProjection(messageBoardPath, {
|
|
861
|
-
wave: wave.wave,
|
|
862
|
-
waveFile: wave.file,
|
|
863
|
-
agents: wave.agents,
|
|
864
|
-
state: coordinationState,
|
|
865
|
-
capabilityAssignments,
|
|
866
|
-
dependencySnapshot,
|
|
867
|
-
});
|
|
868
749
|
return {
|
|
869
750
|
coordinationLogPath,
|
|
870
751
|
coordinationState,
|
|
871
752
|
clarificationTriage,
|
|
872
753
|
docsQueue,
|
|
754
|
+
docsQueuePath: waveDocsQueuePath(lanePaths, wave.wave),
|
|
873
755
|
capabilityAssignments,
|
|
756
|
+
assignmentSnapshotPath: waveAssignmentsPath(lanePaths, wave.wave),
|
|
874
757
|
dependencySnapshot,
|
|
758
|
+
dependencySnapshotPath: waveDependencySnapshotPath(lanePaths, wave.wave),
|
|
759
|
+
dependencySnapshotMarkdownPath: waveDependencySnapshotMarkdownPath(lanePaths, wave.wave),
|
|
875
760
|
securitySummary,
|
|
761
|
+
securitySummaryPath: waveSecurityPath(lanePaths, wave.wave),
|
|
876
762
|
integrationSummary,
|
|
763
|
+
integrationSummaryPath: waveIntegrationPath(lanePaths, wave.wave),
|
|
877
764
|
integrationMarkdownPath: waveIntegrationMarkdownPath(lanePaths, wave.wave),
|
|
878
765
|
securityMarkdownPath: waveSecurityMarkdownPath(lanePaths, wave.wave),
|
|
879
766
|
ledger,
|
|
767
|
+
ledgerPath: waveLedgerPath(lanePaths, wave.wave),
|
|
880
768
|
responseMetrics,
|
|
881
769
|
sharedSummaryPath,
|
|
882
770
|
sharedSummaryText: sharedSummary.text,
|