@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
|
@@ -3,10 +3,8 @@ import path from "node:path";
|
|
|
3
3
|
import {
|
|
4
4
|
agentSummaryPathFromStatusPath,
|
|
5
5
|
buildAgentExecutionSummary,
|
|
6
|
-
buildEnvelopeFromLegacySignals,
|
|
7
|
-
buildExecutionSummaryFromEnvelope,
|
|
8
6
|
readAgentExecutionSummary,
|
|
9
|
-
|
|
7
|
+
validateDesignSummary,
|
|
10
8
|
validateContQaSummary,
|
|
11
9
|
validateContEvalSummary,
|
|
12
10
|
validateImplementationSummary,
|
|
@@ -14,8 +12,17 @@ import {
|
|
|
14
12
|
validateSecuritySummary,
|
|
15
13
|
validateIntegrationSummary,
|
|
16
14
|
writeAgentExecutionSummary,
|
|
17
|
-
writeAgentResultEnvelope,
|
|
18
15
|
} from "./agent-state.mjs";
|
|
16
|
+
import {
|
|
17
|
+
projectLegacySummaryFromEnvelope,
|
|
18
|
+
readAgentResultEnvelope,
|
|
19
|
+
readAgentResultEnvelopeForRun,
|
|
20
|
+
resolveRunEnvelopeContext,
|
|
21
|
+
synthesizeLegacyEnvelope,
|
|
22
|
+
validateResultEnvelope,
|
|
23
|
+
writeAgentResultEnvelope,
|
|
24
|
+
writeAgentResultEnvelopeForRun,
|
|
25
|
+
} from "./result-envelope.mjs";
|
|
19
26
|
import {
|
|
20
27
|
REPO_ROOT,
|
|
21
28
|
readFileTail,
|
|
@@ -27,7 +34,10 @@ import {
|
|
|
27
34
|
writeJsonAtomic,
|
|
28
35
|
} from "./shared.mjs";
|
|
29
36
|
import {
|
|
37
|
+
isDocsOnlyDesignAgent,
|
|
30
38
|
isSecurityReviewAgent,
|
|
39
|
+
isDesignAgent,
|
|
40
|
+
resolveDesignReportPath,
|
|
31
41
|
resolveSecurityReviewReportPath,
|
|
32
42
|
isContEvalReportOnlyAgent,
|
|
33
43
|
} from "./role-helpers.mjs";
|
|
@@ -88,9 +98,40 @@ function resolveRunReportPath(wave, runInfo) {
|
|
|
88
98
|
const securityReportPath = resolveSecurityReviewReportPath(runInfo.agent);
|
|
89
99
|
return securityReportPath ? path.resolve(REPO_ROOT, securityReportPath) : null;
|
|
90
100
|
}
|
|
101
|
+
if (isDesignAgent(runInfo.agent)) {
|
|
102
|
+
const designReportPath = resolveDesignReportPath(runInfo.agent);
|
|
103
|
+
return designReportPath ? path.resolve(REPO_ROOT, designReportPath) : null;
|
|
104
|
+
}
|
|
91
105
|
return null;
|
|
92
106
|
}
|
|
93
107
|
|
|
108
|
+
function normalizeReadMode(mode) {
|
|
109
|
+
return String(mode || "compat").trim().toLowerCase() === "live" ? "live" : "compat";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function buildEnvelopeReadOptions(runInfo, wave, statusRecord, reportPath) {
|
|
113
|
+
return {
|
|
114
|
+
agent: runInfo?.agent,
|
|
115
|
+
waveNumber: wave?.wave ?? null,
|
|
116
|
+
attempt: statusRecord?.attempt ?? null,
|
|
117
|
+
logPath: runInfo?.logPath || null,
|
|
118
|
+
reportPath,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function validateEnvelopeForRun(runInfo, envelope, options = {}) {
|
|
123
|
+
const validation = validateResultEnvelope(envelope, {
|
|
124
|
+
agent: runInfo?.agent,
|
|
125
|
+
waveNumber: options.wave?.wave ?? null,
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
valid: validation.valid,
|
|
129
|
+
errors: validation.errors || [],
|
|
130
|
+
detail: validation.valid ? null : validation.errors.join(" "),
|
|
131
|
+
envelope: validation.valid ? envelope : null,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
export function materializeAgentExecutionSummaryForRun(wave, runInfo) {
|
|
95
136
|
const statusRecord = readStatusRecordIfPresent(runInfo.statusPath);
|
|
96
137
|
if (!statusRecord) {
|
|
@@ -104,13 +145,17 @@ export function materializeAgentExecutionSummaryForRun(wave, runInfo) {
|
|
|
104
145
|
reportPath,
|
|
105
146
|
});
|
|
106
147
|
writeAgentExecutionSummary(runInfo.statusPath, summary);
|
|
107
|
-
|
|
108
|
-
runInfo
|
|
109
|
-
|
|
148
|
+
writeAgentResultEnvelopeForRun(
|
|
149
|
+
runInfo,
|
|
150
|
+
wave,
|
|
151
|
+
synthesizeLegacyEnvelope(runInfo.agent, summary, {
|
|
110
152
|
waveNumber: wave?.wave ?? null,
|
|
111
153
|
attempt: statusRecord.attempt ?? null,
|
|
112
154
|
exitCode: typeof statusRecord.code === "number" ? statusRecord.code : 0,
|
|
113
155
|
}),
|
|
156
|
+
{
|
|
157
|
+
statusRecord,
|
|
158
|
+
},
|
|
114
159
|
);
|
|
115
160
|
if (runInfo?.previewPath && fs.existsSync(runInfo.previewPath)) {
|
|
116
161
|
const previewPayload = readJsonOrNull(runInfo.previewPath);
|
|
@@ -141,48 +186,164 @@ export function materializeAgentExecutionSummaryForRun(wave, runInfo) {
|
|
|
141
186
|
return summary;
|
|
142
187
|
}
|
|
143
188
|
|
|
144
|
-
export function
|
|
145
|
-
const
|
|
146
|
-
runInfo?.proofRegistry ? augmentSummaryWithProofRegistry(runInfo.agent, summary, runInfo.proofRegistry) : summary;
|
|
189
|
+
export function readRunResultEnvelope(runInfo, wave = null, options = {}) {
|
|
190
|
+
const mode = normalizeReadMode(options.mode);
|
|
147
191
|
const statusRecord = runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null;
|
|
148
|
-
const reportPath = wave
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
192
|
+
const reportPath = wave ? resolveRunReportPath(wave, runInfo) : null;
|
|
193
|
+
const runEnvelopeContext = resolveRunEnvelopeContext(runInfo, wave, { statusRecord });
|
|
194
|
+
const envelopeReadOptions = buildEnvelopeReadOptions(runInfo, wave, statusRecord, reportPath);
|
|
195
|
+
const synthesizeFromSummary = (summary, source) => {
|
|
196
|
+
if (!summary || mode === "live") {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const envelope = synthesizeLegacyEnvelope(runInfo?.agent, summary, {
|
|
200
|
+
waveNumber: wave?.wave ?? null,
|
|
201
|
+
attempt: statusRecord?.attempt ?? null,
|
|
202
|
+
exitCode:
|
|
203
|
+
typeof statusRecord?.code === "number"
|
|
204
|
+
? statusRecord.code
|
|
205
|
+
: typeof summary?.exitCode === "number"
|
|
206
|
+
? summary.exitCode
|
|
207
|
+
: 0,
|
|
208
|
+
});
|
|
209
|
+
return {
|
|
210
|
+
source,
|
|
211
|
+
...validateEnvelopeForRun(runInfo, envelope, { wave }),
|
|
212
|
+
};
|
|
165
213
|
};
|
|
214
|
+
|
|
166
215
|
if (runInfo?.summary && typeof runInfo.summary === "object") {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
216
|
+
if (runInfo.summary.schemaVersion === 2) {
|
|
217
|
+
return {
|
|
218
|
+
source: "inline-envelope",
|
|
219
|
+
...validateEnvelopeForRun(runInfo, runInfo.summary, { wave }),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const synthesized = synthesizeFromSummary(runInfo.summary, "inline-legacy-summary");
|
|
223
|
+
if (synthesized) {
|
|
224
|
+
return synthesized;
|
|
225
|
+
}
|
|
171
226
|
}
|
|
172
227
|
if (runInfo?.statusPath && fs.existsSync(runInfo.statusPath)) {
|
|
228
|
+
const envelope = readAgentResultEnvelopeForRun(runInfo, wave, { statusRecord });
|
|
229
|
+
if (envelope) {
|
|
230
|
+
const validation = {
|
|
231
|
+
source: "run-envelope",
|
|
232
|
+
...validateEnvelopeForRun(runInfo, envelope, { wave }),
|
|
233
|
+
};
|
|
234
|
+
if (validation.valid || mode === "live") {
|
|
235
|
+
return validation;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (mode !== "live" && runInfo?.statusPath && fs.existsSync(runInfo.statusPath)) {
|
|
173
240
|
const envelope = readAgentResultEnvelope(runInfo.statusPath);
|
|
174
241
|
if (envelope) {
|
|
175
|
-
|
|
242
|
+
const validation = {
|
|
243
|
+
source: "legacy-status-envelope",
|
|
244
|
+
...validateEnvelopeForRun(runInfo, envelope, { wave }),
|
|
245
|
+
};
|
|
246
|
+
if (validation.valid) {
|
|
247
|
+
return validation;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (mode !== "live" && runInfo?.summaryPath && fs.existsSync(runInfo.summaryPath)) {
|
|
252
|
+
const summary = readAgentExecutionSummary(runInfo.summaryPath, {
|
|
253
|
+
agent: runInfo.agent,
|
|
254
|
+
statusPath: runInfo.summaryPath,
|
|
255
|
+
statusRecord,
|
|
256
|
+
logPath: runInfo.logPath,
|
|
257
|
+
reportPath,
|
|
258
|
+
});
|
|
259
|
+
const synthesized = synthesizeFromSummary(summary, "summary-file-legacy");
|
|
260
|
+
if (synthesized) {
|
|
261
|
+
return synthesized;
|
|
176
262
|
}
|
|
177
263
|
}
|
|
264
|
+
if (
|
|
265
|
+
mode !== "live" &&
|
|
266
|
+
runInfo?.statusPath &&
|
|
267
|
+
fs.existsSync(agentSummaryPathFromStatusPath(runInfo.statusPath))
|
|
268
|
+
) {
|
|
269
|
+
const summary = readAgentExecutionSummary(runInfo.statusPath, {
|
|
270
|
+
agent: runInfo.agent,
|
|
271
|
+
statusPath: runInfo.statusPath,
|
|
272
|
+
statusRecord,
|
|
273
|
+
logPath: runInfo.logPath,
|
|
274
|
+
reportPath,
|
|
275
|
+
});
|
|
276
|
+
const synthesized = synthesizeFromSummary(summary, "status-summary-legacy");
|
|
277
|
+
if (synthesized) {
|
|
278
|
+
return synthesized;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (
|
|
282
|
+
mode !== "live" &&
|
|
283
|
+
wave &&
|
|
284
|
+
runInfo?.statusPath &&
|
|
285
|
+
runInfo?.logPath &&
|
|
286
|
+
fs.existsSync(runInfo.statusPath)
|
|
287
|
+
) {
|
|
288
|
+
materializeAgentExecutionSummaryForRun(wave, runInfo);
|
|
289
|
+
const envelope =
|
|
290
|
+
readAgentResultEnvelopeForRun(runInfo, wave, { statusRecord }) ||
|
|
291
|
+
readAgentResultEnvelope(runInfo.statusPath);
|
|
292
|
+
if (envelope) {
|
|
293
|
+
return {
|
|
294
|
+
source: "materialized-legacy-envelope",
|
|
295
|
+
...validateEnvelopeForRun(runInfo, envelope, { wave }),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
source: "missing-envelope",
|
|
301
|
+
valid: false,
|
|
302
|
+
errors: [
|
|
303
|
+
`Missing result envelope for ${runInfo?.agent?.agentId || "unknown-agent"} at ${path.relative(REPO_ROOT, runEnvelopeContext.envelopePath)}.`,
|
|
304
|
+
],
|
|
305
|
+
detail: `Missing result envelope for ${runInfo?.agent?.agentId || "unknown-agent"} at ${path.relative(REPO_ROOT, runEnvelopeContext.envelopePath)}.`,
|
|
306
|
+
envelope: null,
|
|
307
|
+
envelopeReadOptions,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export function readRunExecutionSummary(runInfo, wave = null, options = {}) {
|
|
312
|
+
const mode = normalizeReadMode(options.mode);
|
|
313
|
+
const applyProofRegistry = (summary) =>
|
|
314
|
+
runInfo?.proofRegistry ? augmentSummaryWithProofRegistry(runInfo.agent, summary, runInfo.proofRegistry) : summary;
|
|
315
|
+
const statusRecord = runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null;
|
|
316
|
+
const reportPath = wave ? resolveRunReportPath(wave, runInfo) : null;
|
|
317
|
+
const envelopeReadOptions = buildEnvelopeReadOptions(runInfo, wave, statusRecord, reportPath);
|
|
318
|
+
const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
|
|
319
|
+
if (envelopeResult?.valid && envelopeResult.envelope) {
|
|
320
|
+
return applyProofRegistry(
|
|
321
|
+
projectLegacySummaryFromEnvelope(envelopeResult.envelope, envelopeReadOptions),
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (mode === "live") {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
if (runInfo?.summary && typeof runInfo.summary === "object") {
|
|
328
|
+
return applyProofRegistry(runInfo.summary);
|
|
329
|
+
}
|
|
178
330
|
if (runInfo?.summaryPath && fs.existsSync(runInfo.summaryPath)) {
|
|
179
|
-
return applyProofRegistry(readAgentExecutionSummary(runInfo.summaryPath,
|
|
331
|
+
return applyProofRegistry(readAgentExecutionSummary(runInfo.summaryPath, {
|
|
332
|
+
agent: runInfo.agent,
|
|
333
|
+
statusPath: runInfo.summaryPath,
|
|
334
|
+
statusRecord,
|
|
335
|
+
logPath: runInfo.logPath,
|
|
336
|
+
reportPath,
|
|
337
|
+
}));
|
|
180
338
|
}
|
|
181
339
|
if (runInfo?.statusPath && fs.existsSync(agentSummaryPathFromStatusPath(runInfo.statusPath))) {
|
|
182
|
-
return applyProofRegistry(readAgentExecutionSummary(runInfo.statusPath,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
340
|
+
return applyProofRegistry(readAgentExecutionSummary(runInfo.statusPath, {
|
|
341
|
+
agent: runInfo.agent,
|
|
342
|
+
statusPath: runInfo.statusPath,
|
|
343
|
+
statusRecord,
|
|
344
|
+
logPath: runInfo.logPath,
|
|
345
|
+
reportPath,
|
|
346
|
+
}));
|
|
186
347
|
}
|
|
187
348
|
return null;
|
|
188
349
|
}
|
|
@@ -208,7 +369,18 @@ export function readWaveContQaGate(wave, agentRuns, options = {}) {
|
|
|
208
369
|
logPath: null,
|
|
209
370
|
};
|
|
210
371
|
}
|
|
211
|
-
const
|
|
372
|
+
const envelopeResult = readRunResultEnvelope(contQaRun, wave, { mode });
|
|
373
|
+
const summary = envelopeResult.valid
|
|
374
|
+
? projectLegacySummaryFromEnvelope(
|
|
375
|
+
envelopeResult.envelope,
|
|
376
|
+
buildEnvelopeReadOptions(
|
|
377
|
+
contQaRun,
|
|
378
|
+
wave,
|
|
379
|
+
contQaRun?.statusPath ? readStatusRecordIfPresent(contQaRun.statusPath) : null,
|
|
380
|
+
resolveRunReportPath(wave, contQaRun),
|
|
381
|
+
),
|
|
382
|
+
)
|
|
383
|
+
: readRunExecutionSummary(contQaRun, wave, { mode });
|
|
212
384
|
if (summary) {
|
|
213
385
|
const validation = validateContQaSummary(contQaRun.agent, summary, { mode });
|
|
214
386
|
return {
|
|
@@ -223,8 +395,13 @@ export function readWaveContQaGate(wave, agentRuns, options = {}) {
|
|
|
223
395
|
return {
|
|
224
396
|
ok: false,
|
|
225
397
|
agentId: contQaRun.agent.agentId,
|
|
226
|
-
statusCode:
|
|
227
|
-
|
|
398
|
+
statusCode:
|
|
399
|
+
envelopeResult.source === "missing-envelope"
|
|
400
|
+
? "missing-result-envelope"
|
|
401
|
+
: "invalid-result-envelope",
|
|
402
|
+
detail:
|
|
403
|
+
envelopeResult.detail ||
|
|
404
|
+
`Missing structured cont-QA result envelope for ${contQaRun.agent.agentId}.`,
|
|
228
405
|
logPath: path.relative(REPO_ROOT, contQaRun.logPath),
|
|
229
406
|
};
|
|
230
407
|
}
|
|
@@ -284,7 +461,18 @@ export function readWaveContEvalGate(wave, agentRuns, options = {}) {
|
|
|
284
461
|
logPath: null,
|
|
285
462
|
};
|
|
286
463
|
}
|
|
287
|
-
const
|
|
464
|
+
const envelopeResult = readRunResultEnvelope(contEvalRun, wave, { mode });
|
|
465
|
+
const summary = envelopeResult.valid
|
|
466
|
+
? projectLegacySummaryFromEnvelope(
|
|
467
|
+
envelopeResult.envelope,
|
|
468
|
+
buildEnvelopeReadOptions(
|
|
469
|
+
contEvalRun,
|
|
470
|
+
wave,
|
|
471
|
+
contEvalRun?.statusPath ? readStatusRecordIfPresent(contEvalRun.statusPath) : null,
|
|
472
|
+
resolveRunReportPath(wave, contEvalRun),
|
|
473
|
+
),
|
|
474
|
+
)
|
|
475
|
+
: readRunExecutionSummary(contEvalRun, wave, { mode });
|
|
288
476
|
if (summary) {
|
|
289
477
|
const validation = validateContEvalSummary(contEvalRun.agent, summary, {
|
|
290
478
|
mode,
|
|
@@ -302,8 +490,16 @@ export function readWaveContEvalGate(wave, agentRuns, options = {}) {
|
|
|
302
490
|
return {
|
|
303
491
|
ok: false,
|
|
304
492
|
agentId: contEvalRun.agent.agentId,
|
|
305
|
-
statusCode:
|
|
306
|
-
|
|
493
|
+
statusCode:
|
|
494
|
+
strict && envelopeResult.source !== "missing-envelope"
|
|
495
|
+
? "invalid-result-envelope"
|
|
496
|
+
: strict
|
|
497
|
+
? "missing-result-envelope"
|
|
498
|
+
: "missing-wave-eval",
|
|
499
|
+
detail:
|
|
500
|
+
strict && envelopeResult.detail
|
|
501
|
+
? envelopeResult.detail
|
|
502
|
+
: `Missing [wave-eval] marker for ${contEvalRun.agent.agentId}.`,
|
|
307
503
|
logPath: path.relative(REPO_ROOT, contEvalRun.logPath),
|
|
308
504
|
};
|
|
309
505
|
}
|
|
@@ -315,7 +511,8 @@ export function readWaveEvaluatorGate(wave, agentRuns, options = {}) {
|
|
|
315
511
|
});
|
|
316
512
|
}
|
|
317
513
|
|
|
318
|
-
export function readWaveImplementationGate(wave, agentRuns) {
|
|
514
|
+
export function readWaveImplementationGate(wave, agentRuns, options = {}) {
|
|
515
|
+
const mode = normalizeReadMode(options.mode || "live");
|
|
319
516
|
const contQaAgentId = wave.contQaAgentId || "A0";
|
|
320
517
|
const contEvalAgentId = wave.contEvalAgentId || "E0";
|
|
321
518
|
const integrationAgentId = wave.integrationAgentId || "A8";
|
|
@@ -324,11 +521,37 @@ export function readWaveImplementationGate(wave, agentRuns) {
|
|
|
324
521
|
if (
|
|
325
522
|
[contQaAgentId, integrationAgentId, documentationAgentId].includes(runInfo.agent.agentId) ||
|
|
326
523
|
isContEvalReportOnlyAgent(runInfo.agent, { contEvalAgentId }) ||
|
|
524
|
+
isDocsOnlyDesignAgent(runInfo.agent) ||
|
|
327
525
|
isSecurityReviewAgent(runInfo.agent)
|
|
328
526
|
) {
|
|
329
527
|
continue;
|
|
330
528
|
}
|
|
331
|
-
const
|
|
529
|
+
const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
|
|
530
|
+
if (mode === "live" && !envelopeResult.valid) {
|
|
531
|
+
return {
|
|
532
|
+
ok: false,
|
|
533
|
+
agentId: runInfo.agent.agentId,
|
|
534
|
+
statusCode:
|
|
535
|
+
envelopeResult.source === "missing-envelope"
|
|
536
|
+
? "missing-result-envelope"
|
|
537
|
+
: "invalid-result-envelope",
|
|
538
|
+
detail:
|
|
539
|
+
envelopeResult.detail ||
|
|
540
|
+
`Missing structured implementation result envelope for ${runInfo.agent.agentId}.`,
|
|
541
|
+
logPath: path.relative(REPO_ROOT, runInfo.logPath),
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
const summary = envelopeResult.valid
|
|
545
|
+
? projectLegacySummaryFromEnvelope(
|
|
546
|
+
envelopeResult.envelope,
|
|
547
|
+
buildEnvelopeReadOptions(
|
|
548
|
+
runInfo,
|
|
549
|
+
wave,
|
|
550
|
+
runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
|
|
551
|
+
resolveRunReportPath(wave, runInfo),
|
|
552
|
+
),
|
|
553
|
+
)
|
|
554
|
+
: readRunExecutionSummary(runInfo, wave, { mode });
|
|
332
555
|
const validation = validateImplementationSummary(runInfo.agent, summary);
|
|
333
556
|
if (!validation.ok) {
|
|
334
557
|
return {
|
|
@@ -349,6 +572,65 @@ export function readWaveImplementationGate(wave, agentRuns) {
|
|
|
349
572
|
};
|
|
350
573
|
}
|
|
351
574
|
|
|
575
|
+
export function readWaveDesignGate(wave, agentRuns, options = {}) {
|
|
576
|
+
const mode = normalizeReadMode(options.mode || "live");
|
|
577
|
+
const designRuns = (agentRuns || []).filter((run) => isDesignAgent(run.agent));
|
|
578
|
+
if (designRuns.length === 0) {
|
|
579
|
+
return {
|
|
580
|
+
ok: true,
|
|
581
|
+
agentId: null,
|
|
582
|
+
statusCode: "pass",
|
|
583
|
+
detail: "No design agent declared for this wave.",
|
|
584
|
+
logPath: null,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
for (const runInfo of designRuns) {
|
|
588
|
+
const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
|
|
589
|
+
if (mode === "live" && !envelopeResult.valid) {
|
|
590
|
+
return {
|
|
591
|
+
ok: false,
|
|
592
|
+
agentId: runInfo.agent.agentId,
|
|
593
|
+
statusCode:
|
|
594
|
+
envelopeResult.source === "missing-envelope"
|
|
595
|
+
? "missing-result-envelope"
|
|
596
|
+
: "invalid-result-envelope",
|
|
597
|
+
detail:
|
|
598
|
+
envelopeResult.detail ||
|
|
599
|
+
`Missing structured design result envelope for ${runInfo.agent.agentId}.`,
|
|
600
|
+
logPath: path.relative(REPO_ROOT, runInfo.logPath),
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
const summary = envelopeResult.valid
|
|
604
|
+
? projectLegacySummaryFromEnvelope(
|
|
605
|
+
envelopeResult.envelope,
|
|
606
|
+
buildEnvelopeReadOptions(
|
|
607
|
+
runInfo,
|
|
608
|
+
wave,
|
|
609
|
+
runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
|
|
610
|
+
resolveRunReportPath(wave, runInfo),
|
|
611
|
+
),
|
|
612
|
+
)
|
|
613
|
+
: readRunExecutionSummary(runInfo, wave, { mode });
|
|
614
|
+
const validation = validateDesignSummary(runInfo.agent, summary);
|
|
615
|
+
if (!validation.ok) {
|
|
616
|
+
return {
|
|
617
|
+
ok: false,
|
|
618
|
+
agentId: runInfo.agent.agentId,
|
|
619
|
+
statusCode: validation.statusCode,
|
|
620
|
+
detail: validation.detail,
|
|
621
|
+
logPath: summary?.logPath || path.relative(REPO_ROOT, runInfo.logPath),
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
ok: true,
|
|
627
|
+
agentId: null,
|
|
628
|
+
statusCode: "pass",
|
|
629
|
+
detail: "All design packets are ready for implementation.",
|
|
630
|
+
logPath: null,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
352
634
|
export function analyzePromotedComponentOwners(componentId, agentRuns, summariesByAgentId) {
|
|
353
635
|
const ownerRuns = (agentRuns || []).filter((runInfo) =>
|
|
354
636
|
runInfo.agent.components?.includes(componentId),
|
|
@@ -423,8 +705,12 @@ export function buildSharedComponentSiblingPendingFailure(componentState) {
|
|
|
423
705
|
}
|
|
424
706
|
|
|
425
707
|
export function readWaveComponentGate(wave, agentRuns, options = {}) {
|
|
708
|
+
const mode = normalizeReadMode(options.mode);
|
|
426
709
|
const summariesByAgentId = Object.fromEntries(
|
|
427
|
-
agentRuns.map((runInfo) => [
|
|
710
|
+
agentRuns.map((runInfo) => [
|
|
711
|
+
runInfo.agent.agentId,
|
|
712
|
+
readRunExecutionSummary(runInfo, wave, { mode }),
|
|
713
|
+
]),
|
|
428
714
|
);
|
|
429
715
|
const validation = validateWaveComponentPromotions(wave, summariesByAgentId, options);
|
|
430
716
|
const sharedPending = (wave.componentPromotions || [])
|
|
@@ -493,7 +779,8 @@ export function readWaveComponentMatrixGate(wave, agentRuns, options = {}) {
|
|
|
493
779
|
};
|
|
494
780
|
}
|
|
495
781
|
|
|
496
|
-
export function readWaveDocumentationGate(wave, agentRuns) {
|
|
782
|
+
export function readWaveDocumentationGate(wave, agentRuns, options = {}) {
|
|
783
|
+
const mode = normalizeReadMode(options.mode || "live");
|
|
497
784
|
const documentationAgentId = wave.documentationAgentId || "A9";
|
|
498
785
|
const docRun =
|
|
499
786
|
agentRuns.find((run) => run.agent.agentId === documentationAgentId) ?? null;
|
|
@@ -506,7 +793,32 @@ export function readWaveDocumentationGate(wave, agentRuns) {
|
|
|
506
793
|
logPath: null,
|
|
507
794
|
};
|
|
508
795
|
}
|
|
509
|
-
const
|
|
796
|
+
const envelopeResult = readRunResultEnvelope(docRun, wave, { mode });
|
|
797
|
+
if (mode === "live" && !envelopeResult.valid) {
|
|
798
|
+
return {
|
|
799
|
+
ok: false,
|
|
800
|
+
agentId: docRun.agent.agentId,
|
|
801
|
+
statusCode:
|
|
802
|
+
envelopeResult.source === "missing-envelope"
|
|
803
|
+
? "missing-result-envelope"
|
|
804
|
+
: "invalid-result-envelope",
|
|
805
|
+
detail:
|
|
806
|
+
envelopeResult.detail ||
|
|
807
|
+
`Missing structured documentation result envelope for ${docRun.agent.agentId}.`,
|
|
808
|
+
logPath: path.relative(REPO_ROOT, docRun.logPath),
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
const summary = envelopeResult.valid
|
|
812
|
+
? projectLegacySummaryFromEnvelope(
|
|
813
|
+
envelopeResult.envelope,
|
|
814
|
+
buildEnvelopeReadOptions(
|
|
815
|
+
docRun,
|
|
816
|
+
wave,
|
|
817
|
+
docRun?.statusPath ? readStatusRecordIfPresent(docRun.statusPath) : null,
|
|
818
|
+
resolveRunReportPath(wave, docRun),
|
|
819
|
+
),
|
|
820
|
+
)
|
|
821
|
+
: readRunExecutionSummary(docRun, wave, { mode });
|
|
510
822
|
const validation = validateDocumentationClosureSummary(docRun.agent, summary);
|
|
511
823
|
return {
|
|
512
824
|
ok: validation.ok,
|
|
@@ -517,7 +829,8 @@ export function readWaveDocumentationGate(wave, agentRuns) {
|
|
|
517
829
|
};
|
|
518
830
|
}
|
|
519
831
|
|
|
520
|
-
export function readWaveSecurityGate(wave, agentRuns) {
|
|
832
|
+
export function readWaveSecurityGate(wave, agentRuns, options = {}) {
|
|
833
|
+
const mode = normalizeReadMode(options.mode || "live");
|
|
521
834
|
const securityRuns = (agentRuns || []).filter((run) => isSecurityReviewAgent(run.agent));
|
|
522
835
|
if (securityRuns.length === 0) {
|
|
523
836
|
return {
|
|
@@ -530,7 +843,32 @@ export function readWaveSecurityGate(wave, agentRuns) {
|
|
|
530
843
|
}
|
|
531
844
|
const concernAgentIds = [];
|
|
532
845
|
for (const runInfo of securityRuns) {
|
|
533
|
-
const
|
|
846
|
+
const envelopeResult = readRunResultEnvelope(runInfo, wave, { mode });
|
|
847
|
+
if (mode === "live" && !envelopeResult.valid) {
|
|
848
|
+
return {
|
|
849
|
+
ok: false,
|
|
850
|
+
agentId: runInfo.agent.agentId,
|
|
851
|
+
statusCode:
|
|
852
|
+
envelopeResult.source === "missing-envelope"
|
|
853
|
+
? "missing-result-envelope"
|
|
854
|
+
: "invalid-result-envelope",
|
|
855
|
+
detail:
|
|
856
|
+
envelopeResult.detail ||
|
|
857
|
+
`Missing structured security result envelope for ${runInfo.agent.agentId}.`,
|
|
858
|
+
logPath: path.relative(REPO_ROOT, runInfo.logPath),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
const summary = envelopeResult.valid
|
|
862
|
+
? projectLegacySummaryFromEnvelope(
|
|
863
|
+
envelopeResult.envelope,
|
|
864
|
+
buildEnvelopeReadOptions(
|
|
865
|
+
runInfo,
|
|
866
|
+
wave,
|
|
867
|
+
runInfo?.statusPath ? readStatusRecordIfPresent(runInfo.statusPath) : null,
|
|
868
|
+
resolveRunReportPath(wave, runInfo),
|
|
869
|
+
),
|
|
870
|
+
)
|
|
871
|
+
: readRunExecutionSummary(runInfo, wave, { mode });
|
|
534
872
|
const validation = validateSecuritySummary(runInfo.agent, summary);
|
|
535
873
|
if (!validation.ok) {
|
|
536
874
|
return {
|
|
@@ -564,6 +902,7 @@ export function readWaveSecurityGate(wave, agentRuns) {
|
|
|
564
902
|
}
|
|
565
903
|
|
|
566
904
|
export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
|
|
905
|
+
const mode = normalizeReadMode(options.mode || "live");
|
|
567
906
|
const integrationAgentId =
|
|
568
907
|
options.integrationAgentId || wave.integrationAgentId || "A8";
|
|
569
908
|
const requireIntegration =
|
|
@@ -584,7 +923,32 @@ export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
|
|
|
584
923
|
logPath: null,
|
|
585
924
|
};
|
|
586
925
|
}
|
|
587
|
-
const
|
|
926
|
+
const envelopeResult = readRunResultEnvelope(integrationRun, wave, { mode });
|
|
927
|
+
if (mode === "live" && !envelopeResult.valid) {
|
|
928
|
+
return {
|
|
929
|
+
ok: false,
|
|
930
|
+
agentId: integrationRun.agent.agentId,
|
|
931
|
+
statusCode:
|
|
932
|
+
envelopeResult.source === "missing-envelope"
|
|
933
|
+
? "missing-result-envelope"
|
|
934
|
+
: "invalid-result-envelope",
|
|
935
|
+
detail:
|
|
936
|
+
envelopeResult.detail ||
|
|
937
|
+
`Missing structured integration result envelope for ${integrationRun.agent.agentId}.`,
|
|
938
|
+
logPath: path.relative(REPO_ROOT, integrationRun.logPath),
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
const summary = envelopeResult.valid
|
|
942
|
+
? projectLegacySummaryFromEnvelope(
|
|
943
|
+
envelopeResult.envelope,
|
|
944
|
+
buildEnvelopeReadOptions(
|
|
945
|
+
integrationRun,
|
|
946
|
+
wave,
|
|
947
|
+
integrationRun?.statusPath ? readStatusRecordIfPresent(integrationRun.statusPath) : null,
|
|
948
|
+
resolveRunReportPath(wave, integrationRun),
|
|
949
|
+
),
|
|
950
|
+
)
|
|
951
|
+
: readRunExecutionSummary(integrationRun, wave, { mode });
|
|
588
952
|
const validation = validateIntegrationSummary(integrationRun.agent, summary);
|
|
589
953
|
return {
|
|
590
954
|
ok: validation.ok,
|
|
@@ -737,91 +1101,51 @@ export function buildGateSnapshot({
|
|
|
737
1101
|
validationMode = "compat",
|
|
738
1102
|
readWaveInfraGateFn,
|
|
739
1103
|
}) {
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1104
|
+
const agentResults = Object.fromEntries(
|
|
1105
|
+
(agentRuns || [])
|
|
1106
|
+
.map((runInfo) => [
|
|
1107
|
+
runInfo.agent.agentId,
|
|
1108
|
+
readRunExecutionSummary(runInfo, wave, { mode: validationMode }),
|
|
1109
|
+
])
|
|
1110
|
+
.filter(([, summary]) => Boolean(summary)),
|
|
1111
|
+
);
|
|
1112
|
+
return buildGateSnapshotPure({
|
|
1113
|
+
wave,
|
|
1114
|
+
agentResults,
|
|
1115
|
+
derivedState: {
|
|
1116
|
+
...derivedState,
|
|
1117
|
+
clarificationBarrier:
|
|
1118
|
+
derivedState?.clarificationBarrier || readClarificationBarrier(derivedState),
|
|
1119
|
+
helperAssignmentBarrier:
|
|
1120
|
+
derivedState?.helperAssignmentBarrier || readWaveAssignmentBarrier(derivedState),
|
|
1121
|
+
dependencyBarrier:
|
|
1122
|
+
derivedState?.dependencyBarrier || readWaveDependencyBarrier(derivedState),
|
|
1123
|
+
},
|
|
1124
|
+
validationMode,
|
|
1125
|
+
laneConfig: {
|
|
1126
|
+
contQaAgentId: lanePaths?.contQaAgentId,
|
|
1127
|
+
contEvalAgentId: lanePaths?.contEvalAgentId,
|
|
1128
|
+
integrationAgentId: lanePaths?.integrationAgentId,
|
|
1129
|
+
documentationAgentId: lanePaths?.documentationAgentId,
|
|
1130
|
+
requireIntegrationStewardFromWave: lanePaths?.requireIntegrationStewardFromWave,
|
|
1131
|
+
laneProfile: lanePaths?.laneProfile,
|
|
1132
|
+
benchmarkCatalogPath: lanePaths?.laneProfile?.paths?.benchmarkCatalogPath,
|
|
1133
|
+
componentMatrixPayload,
|
|
1134
|
+
componentMatrixJsonPath,
|
|
1135
|
+
},
|
|
769
1136
|
});
|
|
770
|
-
const infraGate = readWaveInfraGateFn(agentRuns);
|
|
771
|
-
const clarificationBarrier = readClarificationBarrier(derivedState);
|
|
772
|
-
const helperAssignmentBarrier = readWaveAssignmentBarrier(derivedState);
|
|
773
|
-
const dependencyBarrier = readWaveDependencyBarrier(derivedState);
|
|
774
|
-
const orderedGates = [
|
|
775
|
-
["implementationGate", implementationGate],
|
|
776
|
-
["componentGate", componentGate],
|
|
777
|
-
["helperAssignmentBarrier", helperAssignmentBarrier],
|
|
778
|
-
["dependencyBarrier", dependencyBarrier],
|
|
779
|
-
["contEvalGate", contEvalGate],
|
|
780
|
-
["securityGate", securityGate],
|
|
781
|
-
["integrationBarrier", integrationBarrier],
|
|
782
|
-
["documentationGate", documentationGate],
|
|
783
|
-
["componentMatrixGate", componentMatrixGate],
|
|
784
|
-
["contQaGate", contQaGate],
|
|
785
|
-
["infraGate", infraGate],
|
|
786
|
-
["clarificationBarrier", clarificationBarrier],
|
|
787
|
-
];
|
|
788
|
-
const firstFailure = orderedGates.find(([, gate]) => gate?.ok === false);
|
|
789
|
-
return {
|
|
790
|
-
implementationGate,
|
|
791
|
-
componentGate,
|
|
792
|
-
integrationGate,
|
|
793
|
-
integrationBarrier,
|
|
794
|
-
documentationGate,
|
|
795
|
-
componentMatrixGate,
|
|
796
|
-
contEvalGate,
|
|
797
|
-
securityGate,
|
|
798
|
-
contQaGate,
|
|
799
|
-
infraGate,
|
|
800
|
-
clarificationBarrier,
|
|
801
|
-
helperAssignmentBarrier,
|
|
802
|
-
dependencyBarrier,
|
|
803
|
-
overall: firstFailure
|
|
804
|
-
? {
|
|
805
|
-
ok: false,
|
|
806
|
-
gate: firstFailure[0],
|
|
807
|
-
statusCode: firstFailure[1].statusCode,
|
|
808
|
-
detail: firstFailure[1].detail,
|
|
809
|
-
agentId: firstFailure[1].agentId || null,
|
|
810
|
-
}
|
|
811
|
-
: {
|
|
812
|
-
ok: true,
|
|
813
|
-
gate: "pass",
|
|
814
|
-
statusCode: "pass",
|
|
815
|
-
detail: "All replayed wave gates passed.",
|
|
816
|
-
agentId: null,
|
|
817
|
-
},
|
|
818
|
-
};
|
|
819
1137
|
}
|
|
820
1138
|
|
|
821
1139
|
// --- Pure gate variants (no file I/O) ---
|
|
822
1140
|
// These accept agentResults map { agentId: executionSummary } instead of runInfo objects.
|
|
823
1141
|
// Used by the wave-state-reducer for deterministic replay.
|
|
824
1142
|
|
|
1143
|
+
function waveDeclaresAgent(wave, agentId) {
|
|
1144
|
+
return (Array.isArray(wave?.agents) ? wave.agents : []).some(
|
|
1145
|
+
(agent) => agent?.agentId === agentId,
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
825
1149
|
export function readWaveImplementationGatePure(wave, agentResults, options = {}) {
|
|
826
1150
|
const contQaAgentId = options.contQaAgentId || wave.contQaAgentId || "A0";
|
|
827
1151
|
const contEvalAgentId = options.contEvalAgentId || wave.contEvalAgentId || "E0";
|
|
@@ -832,6 +1156,7 @@ export function readWaveImplementationGatePure(wave, agentResults, options = {})
|
|
|
832
1156
|
if (
|
|
833
1157
|
[contQaAgentId, integrationAgentId, documentationAgentId].includes(agent.agentId) ||
|
|
834
1158
|
isContEvalReportOnlyAgent(agent, { contEvalAgentId }) ||
|
|
1159
|
+
isDocsOnlyDesignAgent(agent) ||
|
|
835
1160
|
isSecurityReviewAgent(agent)
|
|
836
1161
|
) {
|
|
837
1162
|
continue;
|
|
@@ -854,6 +1179,40 @@ export function readWaveImplementationGatePure(wave, agentResults, options = {})
|
|
|
854
1179
|
};
|
|
855
1180
|
}
|
|
856
1181
|
|
|
1182
|
+
export function readWaveDesignGatePure(wave, agentResults) {
|
|
1183
|
+
const agents = Array.isArray(wave.agents) ? wave.agents : [];
|
|
1184
|
+
const designAgents = agents.filter((agent) => isDesignAgent(agent));
|
|
1185
|
+
if (designAgents.length === 0) {
|
|
1186
|
+
return {
|
|
1187
|
+
ok: true,
|
|
1188
|
+
agentId: null,
|
|
1189
|
+
statusCode: "pass",
|
|
1190
|
+
detail: "No design agent declared for this wave.",
|
|
1191
|
+
logPath: null,
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
for (const agent of designAgents) {
|
|
1195
|
+
const summary = agentResults?.[agent.agentId] || null;
|
|
1196
|
+
const validation = validateDesignSummary(agent, summary);
|
|
1197
|
+
if (!validation.ok) {
|
|
1198
|
+
return {
|
|
1199
|
+
ok: false,
|
|
1200
|
+
agentId: agent.agentId,
|
|
1201
|
+
statusCode: validation.statusCode,
|
|
1202
|
+
detail: validation.detail,
|
|
1203
|
+
logPath: summary?.logPath || null,
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
return {
|
|
1208
|
+
ok: true,
|
|
1209
|
+
agentId: null,
|
|
1210
|
+
statusCode: "pass",
|
|
1211
|
+
detail: "All design packets are ready for implementation.",
|
|
1212
|
+
logPath: null,
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
|
|
857
1216
|
export function readWaveContQaGatePure(wave, agentResults, options = {}) {
|
|
858
1217
|
const mode = String(options.mode || "live").trim().toLowerCase();
|
|
859
1218
|
const contQaAgentId = options.contQaAgentId || wave.contQaAgentId || "A0";
|
|
@@ -865,24 +1224,24 @@ export function readWaveContQaGatePure(wave, agentResults, options = {}) {
|
|
|
865
1224
|
const agent = { agentId: contQaAgentId };
|
|
866
1225
|
const validation = validateContQaSummary(agent, summary, { mode });
|
|
867
1226
|
return { ok: validation.ok, agentId: contQaAgentId, statusCode: validation.statusCode,
|
|
868
|
-
detail: validation.detail, logPath: summary
|
|
1227
|
+
detail: validation.detail, logPath: summary?.logPath || null };
|
|
869
1228
|
}
|
|
870
1229
|
|
|
871
1230
|
export function readWaveContEvalGatePure(wave, agentResults, options = {}) {
|
|
872
1231
|
const mode = String(options.mode || "live").trim().toLowerCase();
|
|
873
1232
|
const contEvalAgentId = options.contEvalAgentId || wave.contEvalAgentId || "E0";
|
|
874
|
-
|
|
875
|
-
if (!summary) {
|
|
1233
|
+
if (!waveDeclaresAgent(wave, contEvalAgentId)) {
|
|
876
1234
|
return { ok: true, agentId: null, statusCode: "pass",
|
|
877
1235
|
detail: "Wave does not include cont-EVAL.", logPath: null };
|
|
878
1236
|
}
|
|
1237
|
+
const summary = agentResults?.[contEvalAgentId] || null;
|
|
879
1238
|
const agent = { agentId: contEvalAgentId };
|
|
880
1239
|
const validation = validateContEvalSummary(agent, summary, {
|
|
881
1240
|
mode, evalTargets: options.evalTargets || wave.evalTargets,
|
|
882
1241
|
benchmarkCatalogPath: options.benchmarkCatalogPath,
|
|
883
1242
|
});
|
|
884
1243
|
return { ok: validation.ok, agentId: contEvalAgentId, statusCode: validation.statusCode,
|
|
885
|
-
detail: validation.detail, logPath: summary
|
|
1244
|
+
detail: validation.detail, logPath: summary?.logPath || null };
|
|
886
1245
|
}
|
|
887
1246
|
|
|
888
1247
|
export function readWaveEvaluatorGatePure(wave, agentResults, options = {}) {
|
|
@@ -976,15 +1335,15 @@ export function readWaveComponentMatrixGatePure(wave, agentResults, options = {}
|
|
|
976
1335
|
|
|
977
1336
|
export function readWaveDocumentationGatePure(wave, agentResults, options = {}) {
|
|
978
1337
|
const documentationAgentId = options.documentationAgentId || wave.documentationAgentId || "A9";
|
|
979
|
-
|
|
980
|
-
if (!summary) {
|
|
1338
|
+
if (!waveDeclaresAgent(wave, documentationAgentId)) {
|
|
981
1339
|
return { ok: true, agentId: null, statusCode: "pass",
|
|
982
1340
|
detail: "No documentation steward declared for this wave.", logPath: null };
|
|
983
1341
|
}
|
|
1342
|
+
const summary = agentResults?.[documentationAgentId] || null;
|
|
984
1343
|
const agent = { agentId: documentationAgentId };
|
|
985
1344
|
const validation = validateDocumentationClosureSummary(agent, summary);
|
|
986
1345
|
return { ok: validation.ok, agentId: documentationAgentId, statusCode: validation.statusCode,
|
|
987
|
-
detail: validation.detail, logPath: summary
|
|
1346
|
+
detail: validation.detail, logPath: summary?.logPath || null };
|
|
988
1347
|
}
|
|
989
1348
|
|
|
990
1349
|
export function readWaveSecurityGatePure(wave, agentResults, options = {}) {
|
|
@@ -1016,8 +1375,7 @@ export function readWaveIntegrationGatePure(wave, agentResults, options = {}) {
|
|
|
1016
1375
|
const integrationAgentId = options.integrationAgentId || wave.integrationAgentId || "A8";
|
|
1017
1376
|
const requireIntegration = options.requireIntegrationSteward === true ||
|
|
1018
1377
|
(options.requireIntegrationStewardFromWave != null && wave.wave >= options.requireIntegrationStewardFromWave);
|
|
1019
|
-
|
|
1020
|
-
if (!summary) {
|
|
1378
|
+
if (!waveDeclaresAgent(wave, integrationAgentId)) {
|
|
1021
1379
|
return {
|
|
1022
1380
|
ok: !requireIntegration,
|
|
1023
1381
|
agentId: requireIntegration ? integrationAgentId : null,
|
|
@@ -1027,10 +1385,11 @@ export function readWaveIntegrationGatePure(wave, agentResults, options = {}) {
|
|
|
1027
1385
|
logPath: null,
|
|
1028
1386
|
};
|
|
1029
1387
|
}
|
|
1388
|
+
const summary = agentResults?.[integrationAgentId] || null;
|
|
1030
1389
|
const agent = { agentId: integrationAgentId };
|
|
1031
1390
|
const validation = validateIntegrationSummary(agent, summary);
|
|
1032
1391
|
return { ok: validation.ok, agentId: integrationAgentId, statusCode: validation.statusCode,
|
|
1033
|
-
detail: validation.detail, logPath: summary
|
|
1392
|
+
detail: validation.detail, logPath: summary?.logPath || null };
|
|
1034
1393
|
}
|
|
1035
1394
|
|
|
1036
1395
|
const NON_BLOCKING_INFRA_SIGNAL_STATES = new Set([
|
|
@@ -1056,6 +1415,7 @@ export function readWaveInfraGatePure(wave, agentResults, options = {}) {
|
|
|
1056
1415
|
}
|
|
1057
1416
|
|
|
1058
1417
|
export function buildGateSnapshotPure({ wave, agentResults, derivedState, validationMode = "live", laneConfig = {} }) {
|
|
1418
|
+
const designGate = readWaveDesignGatePure(wave, agentResults);
|
|
1059
1419
|
const implementationGate = readWaveImplementationGatePure(wave, agentResults, {
|
|
1060
1420
|
contQaAgentId: laneConfig.contQaAgentId, contEvalAgentId: laneConfig.contEvalAgentId,
|
|
1061
1421
|
integrationAgentId: laneConfig.integrationAgentId, documentationAgentId: laneConfig.documentationAgentId,
|
|
@@ -1107,7 +1467,7 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
|
|
|
1107
1467
|
const helperAssignmentBarrier = derivedState?.helperAssignmentBarrier || { ok: true, statusCode: "pass", detail: "" };
|
|
1108
1468
|
const dependencyBarrier = derivedState?.dependencyBarrier || { ok: true, statusCode: "pass", detail: "" };
|
|
1109
1469
|
const orderedGates = [
|
|
1110
|
-
["implementationGate", implementationGate], ["componentGate", componentGate],
|
|
1470
|
+
["designGate", designGate], ["implementationGate", implementationGate], ["componentGate", componentGate],
|
|
1111
1471
|
["helperAssignmentBarrier", helperAssignmentBarrier], ["dependencyBarrier", dependencyBarrier],
|
|
1112
1472
|
["contEvalGate", contEvalGate], ["securityGate", securityGate],
|
|
1113
1473
|
["integrationBarrier", integrationBarrier], ["documentationGate", documentationGate],
|
|
@@ -1116,7 +1476,7 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
|
|
|
1116
1476
|
];
|
|
1117
1477
|
const firstFailure = orderedGates.find(([, gate]) => gate?.ok === false);
|
|
1118
1478
|
return {
|
|
1119
|
-
implementationGate, componentGate, integrationGate: integrationMarkerGate,
|
|
1479
|
+
designGate, implementationGate, componentGate, integrationGate: integrationMarkerGate,
|
|
1120
1480
|
integrationBarrier, documentationGate, componentMatrixGate,
|
|
1121
1481
|
contEvalGate, securityGate, contQaGate, infraGate,
|
|
1122
1482
|
clarificationBarrier, helperAssignmentBarrier, dependencyBarrier,
|