@chllming/wave-orchestration 0.7.3 → 0.8.0
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 +18 -0
- package/README.md +14 -13
- package/docs/README.md +3 -1
- package/docs/agents/wave-cont-qa-role.md +1 -0
- package/docs/agents/wave-integration-role.md +1 -0
- package/docs/agents/wave-launcher-role.md +4 -1
- package/docs/agents/wave-orchestrator-role.md +5 -3
- package/docs/concepts/operating-modes.md +1 -1
- package/docs/concepts/runtime-agnostic-orchestration.md +5 -4
- package/docs/concepts/what-is-a-wave.md +12 -10
- package/docs/guides/author-and-run-waves.md +3 -3
- package/docs/plans/architecture-hardening-migration.md +206 -0
- package/docs/plans/current-state.md +5 -3
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/master-plan.md +2 -2
- package/docs/plans/migration.md +12 -2
- package/docs/plans/wave-orchestrator.md +10 -8
- package/docs/reference/coordination-and-closure.md +8 -4
- package/docs/reference/npmjs-trusted-publishing.md +2 -2
- package/docs/reference/sample-waves.md +4 -4
- package/docs/reference/skills.md +3 -0
- package/docs/reference/wave-control.md +4 -2
- package/docs/research/coordination-failure-review.md +4 -4
- package/docs/roadmap.md +1 -1
- package/package.json +1 -1
- package/releases/manifest.json +19 -0
- package/scripts/wave-orchestrator/agent-state.mjs +405 -89
- package/scripts/wave-orchestrator/contradiction-entity.mjs +487 -0
- package/scripts/wave-orchestrator/launcher-gates.mjs +79 -11
- package/scripts/wave-orchestrator/launcher-retry.mjs +36 -6
- package/scripts/wave-orchestrator/launcher.mjs +163 -2
- package/scripts/wave-orchestrator/task-entity.mjs +425 -51
- package/scripts/wave-orchestrator/wave-control-schema.mjs +2 -0
- package/scripts/wave-orchestrator/wave-state-reducer.mjs +260 -111
- package/skills/README.md +3 -0
- package/skills/repo-coding-rules/SKILL.md +1 -1
- package/skills/role-cont-qa/SKILL.md +2 -2
- package/skills/role-deploy/SKILL.md +1 -1
- package/skills/role-documentation/SKILL.md +1 -1
- package/skills/role-implementation/SKILL.md +1 -1
- package/skills/role-infra/SKILL.md +1 -1
- package/skills/role-integration/SKILL.md +2 -2
- package/skills/role-security/SKILL.md +1 -1
- package/skills/runtime-claude/SKILL.md +1 -1
- package/skills/runtime-codex/SKILL.md +1 -1
- package/skills/runtime-opencode/SKILL.md +1 -1
- package/skills/wave-core/SKILL.md +14 -6
- package/skills/wave-core/references/marker-syntax.md +1 -1
|
@@ -1182,13 +1182,93 @@ export function validateContQaSummary(agent, summary, options = {}) {
|
|
|
1182
1182
|
}
|
|
1183
1183
|
|
|
1184
1184
|
// ---------------------------------------------------------------------------
|
|
1185
|
-
// Agent Result Envelope —
|
|
1185
|
+
// Agent Result Envelope — P1-6 End-State (schemaVersion 2)
|
|
1186
1186
|
// ---------------------------------------------------------------------------
|
|
1187
1187
|
|
|
1188
1188
|
import { toIsoTimestamp } from "./shared.mjs";
|
|
1189
1189
|
|
|
1190
1190
|
/**
|
|
1191
|
-
*
|
|
1191
|
+
* Valid roles for the agent result envelope.
|
|
1192
|
+
*/
|
|
1193
|
+
export const ENVELOPE_VALID_ROLES = [
|
|
1194
|
+
"implementation",
|
|
1195
|
+
"integration",
|
|
1196
|
+
"documentation",
|
|
1197
|
+
"cont-qa",
|
|
1198
|
+
"cont-eval",
|
|
1199
|
+
"security",
|
|
1200
|
+
"deploy",
|
|
1201
|
+
];
|
|
1202
|
+
|
|
1203
|
+
function inferEnvelopeRole(agent, summary) {
|
|
1204
|
+
const candidate = String(agent?.role || summary?.role || "").trim().toLowerCase();
|
|
1205
|
+
if (candidate && ENVELOPE_VALID_ROLES.includes(candidate)) {
|
|
1206
|
+
return candidate;
|
|
1207
|
+
}
|
|
1208
|
+
if (summary?.integration) {
|
|
1209
|
+
return "integration";
|
|
1210
|
+
}
|
|
1211
|
+
if (summary?.docClosure) {
|
|
1212
|
+
return "documentation";
|
|
1213
|
+
}
|
|
1214
|
+
if (summary?.eval) {
|
|
1215
|
+
return "cont-eval";
|
|
1216
|
+
}
|
|
1217
|
+
if (summary?.security) {
|
|
1218
|
+
return "security";
|
|
1219
|
+
}
|
|
1220
|
+
if (summary?.gate || summary?.verdict) {
|
|
1221
|
+
return "cont-qa";
|
|
1222
|
+
}
|
|
1223
|
+
if (summary?.deploy) {
|
|
1224
|
+
return "deploy";
|
|
1225
|
+
}
|
|
1226
|
+
if (summary?.proof || summary?.docDelta || Array.isArray(summary?.components)) {
|
|
1227
|
+
return "implementation";
|
|
1228
|
+
}
|
|
1229
|
+
return null;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
function toSummaryRelativePath(filePath) {
|
|
1233
|
+
const normalized = String(filePath || "").trim();
|
|
1234
|
+
if (!normalized) {
|
|
1235
|
+
return null;
|
|
1236
|
+
}
|
|
1237
|
+
return path.isAbsolute(normalized) ? path.relative(REPO_ROOT, normalized) : normalized;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function toLegacyProofState(state) {
|
|
1241
|
+
if (state === "satisfied") {
|
|
1242
|
+
return "met";
|
|
1243
|
+
}
|
|
1244
|
+
if (state === "partial") {
|
|
1245
|
+
return "gap";
|
|
1246
|
+
}
|
|
1247
|
+
if (state === "failed") {
|
|
1248
|
+
return "failed";
|
|
1249
|
+
}
|
|
1250
|
+
return "not_applicable";
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* Compute the attempt-scoped canonical envelope path.
|
|
1255
|
+
*
|
|
1256
|
+
* End-state path: .tmp/<lane>/results/wave-<N>/attempt-<A>/<agentId>.json
|
|
1257
|
+
*
|
|
1258
|
+
* @param {object} options - { lane, waveNumber, attempt, agentId }
|
|
1259
|
+
* @returns {string} The envelope file path
|
|
1260
|
+
*/
|
|
1261
|
+
export function agentEnvelopePath({ lane, waveNumber, attempt, agentId }) {
|
|
1262
|
+
const safeLane = lane || "main";
|
|
1263
|
+
const safeWave = waveNumber ?? 0;
|
|
1264
|
+
const safeAttempt = attempt ?? 1;
|
|
1265
|
+
const safeAgent = agentId || "unknown";
|
|
1266
|
+
return `.tmp/${safeLane}-wave-launcher/results/wave-${safeWave}/attempt-${safeAttempt}/${safeAgent}.json`;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Legacy path derivation from status path.
|
|
1271
|
+
* Retained for backward compatibility during migration.
|
|
1192
1272
|
*
|
|
1193
1273
|
* @param {string} statusPath - Path to the .status or .summary file
|
|
1194
1274
|
* @returns {string} The envelope file path
|
|
@@ -1207,129 +1287,365 @@ export function agentEnvelopePathFromStatusPath(statusPath) {
|
|
|
1207
1287
|
* Build a structured result envelope from an already-parsed execution summary.
|
|
1208
1288
|
* Pure function — the envelope is a normalized projection of the summary.
|
|
1209
1289
|
*
|
|
1210
|
-
*
|
|
1290
|
+
* End-state P1-6: common header + role-specific typed optional payloads.
|
|
1291
|
+
* Absent role sections are NOT included (not null, not empty object).
|
|
1292
|
+
*
|
|
1293
|
+
* @param {object} agent - Agent definition from wave (must include .role)
|
|
1211
1294
|
* @param {object} summary - Execution summary from buildAgentExecutionSummary
|
|
1212
|
-
* @
|
|
1295
|
+
* @param {object} [options] - { waveNumber, attempt, exitCode }
|
|
1296
|
+
* @returns {object} AgentResultEnvelope (schemaVersion 2)
|
|
1213
1297
|
*/
|
|
1214
|
-
export function buildAgentResultEnvelope(agent, summary) {
|
|
1298
|
+
export function buildAgentResultEnvelope(agent, summary, options = {}) {
|
|
1215
1299
|
const safeAgent = agent || {};
|
|
1216
1300
|
const safeSummary = summary || {};
|
|
1301
|
+
const safeOptions = options || {};
|
|
1217
1302
|
|
|
1218
|
-
|
|
1303
|
+
const agentId = safeAgent.agentId || safeSummary.agentId || null;
|
|
1304
|
+
const role = inferEnvelopeRole(safeAgent, safeSummary);
|
|
1305
|
+
|
|
1306
|
+
// --- Common header ---
|
|
1219
1307
|
const proof = safeSummary.proof || {};
|
|
1220
|
-
const
|
|
1221
|
-
|
|
1308
|
+
const proofSection = {
|
|
1309
|
+
state: proof.state === "met" ? "satisfied"
|
|
1310
|
+
: proof.state === "gap" ? "partial"
|
|
1311
|
+
: proof.state === "failed" ? "failed"
|
|
1312
|
+
: "not_applicable",
|
|
1222
1313
|
completion: proof.completion || null,
|
|
1223
1314
|
durability: proof.durability || null,
|
|
1224
|
-
|
|
1225
|
-
|
|
1315
|
+
proofLevel: proof.proof || null,
|
|
1316
|
+
detail: proof.detail || null,
|
|
1226
1317
|
};
|
|
1227
1318
|
|
|
1228
|
-
//
|
|
1319
|
+
// Deliverables — with sha256
|
|
1320
|
+
const deliverables = Array.isArray(safeSummary.deliverables)
|
|
1321
|
+
? safeSummary.deliverables.map((d) => ({
|
|
1322
|
+
path: d.path || null,
|
|
1323
|
+
exists: d.exists === true,
|
|
1324
|
+
sha256: d.sha256 || null,
|
|
1325
|
+
}))
|
|
1326
|
+
: [];
|
|
1327
|
+
|
|
1328
|
+
// Proof artifacts — with sha256 and requiredFor
|
|
1229
1329
|
const proofArtifacts = Array.isArray(safeSummary.proofArtifacts)
|
|
1230
1330
|
? safeSummary.proofArtifacts.map((artifact) => ({
|
|
1231
1331
|
path: artifact.path || null,
|
|
1232
1332
|
kind: artifact.kind || null,
|
|
1233
|
-
sha256: artifact.sha256 || null,
|
|
1234
1333
|
exists: artifact.exists === true,
|
|
1334
|
+
sha256: artifact.sha256 || null,
|
|
1335
|
+
requiredFor: artifact.requiredFor || null,
|
|
1235
1336
|
}))
|
|
1236
1337
|
: [];
|
|
1237
1338
|
|
|
1238
|
-
//
|
|
1239
|
-
const
|
|
1240
|
-
? safeSummary.
|
|
1241
|
-
|
|
1242
|
-
|
|
1339
|
+
// Gaps
|
|
1340
|
+
const gaps = Array.isArray(safeSummary.gaps)
|
|
1341
|
+
? safeSummary.gaps.map((g) => ({
|
|
1342
|
+
kind: g.kind || null,
|
|
1343
|
+
detail: g.detail || null,
|
|
1243
1344
|
}))
|
|
1244
1345
|
: [];
|
|
1245
1346
|
|
|
1246
|
-
//
|
|
1247
|
-
const
|
|
1248
|
-
? safeSummary.
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1347
|
+
// Unresolved blockers
|
|
1348
|
+
const unresolvedBlockers = Array.isArray(safeSummary.unresolvedBlockers)
|
|
1349
|
+
? safeSummary.unresolvedBlockers.map((b) =>
|
|
1350
|
+
typeof b === "object" ? { kind: b.kind || null, detail: b.detail || null, blocking: b.blocking || null } : { kind: null, detail: String(b), blocking: null },
|
|
1351
|
+
)
|
|
1352
|
+
: [];
|
|
1353
|
+
|
|
1354
|
+
// Risk notes
|
|
1355
|
+
const riskNotes = Array.isArray(safeSummary.riskNotes) ? safeSummary.riskNotes : [];
|
|
1356
|
+
|
|
1357
|
+
// Facts
|
|
1358
|
+
const facts = Array.isArray(safeSummary.facts)
|
|
1359
|
+
? safeSummary.facts.map((f) => ({
|
|
1360
|
+
factId: f.factId || null,
|
|
1361
|
+
kind: f.kind || null,
|
|
1362
|
+
content: f.content || null,
|
|
1252
1363
|
}))
|
|
1253
1364
|
: [];
|
|
1254
1365
|
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1366
|
+
const envelope = {
|
|
1367
|
+
schemaVersion: 2,
|
|
1368
|
+
agentId,
|
|
1369
|
+
waveNumber: safeOptions.waveNumber ?? safeSummary.waveNumber ?? null,
|
|
1370
|
+
attempt: safeOptions.attempt ?? safeSummary.attempt ?? null,
|
|
1371
|
+
completedAt: safeOptions.completedAt || toIsoTimestamp(),
|
|
1372
|
+
exitCode: typeof safeOptions.exitCode === "number" ? safeOptions.exitCode : (typeof safeSummary.exitCode === "number" ? safeSummary.exitCode : 0),
|
|
1373
|
+
role,
|
|
1374
|
+
proof: proofSection,
|
|
1375
|
+
deliverables,
|
|
1376
|
+
proofArtifacts,
|
|
1377
|
+
gaps,
|
|
1378
|
+
unresolvedBlockers,
|
|
1379
|
+
riskNotes,
|
|
1380
|
+
facts,
|
|
1381
|
+
};
|
|
1382
|
+
|
|
1383
|
+
// --- Role-specific typed payloads (absent when not applicable) ---
|
|
1384
|
+
|
|
1385
|
+
if (role === "implementation") {
|
|
1386
|
+
const docDelta = safeSummary.docDelta || {};
|
|
1387
|
+
const components = Array.isArray(safeSummary.components)
|
|
1388
|
+
? safeSummary.components.map((c) => ({
|
|
1389
|
+
componentId: c.componentId || null,
|
|
1390
|
+
level: c.level || null,
|
|
1391
|
+
state: c.state || null,
|
|
1392
|
+
detail: c.detail || null,
|
|
1393
|
+
}))
|
|
1394
|
+
: [];
|
|
1395
|
+
envelope.implementation = {
|
|
1396
|
+
docDelta: {
|
|
1397
|
+
state: docDelta.state || "none",
|
|
1398
|
+
paths: Array.isArray(docDelta.paths) ? docDelta.paths : [],
|
|
1399
|
+
detail: docDelta.detail || null,
|
|
1400
|
+
},
|
|
1401
|
+
components,
|
|
1402
|
+
};
|
|
1268
1403
|
}
|
|
1269
1404
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1405
|
+
if (role === "integration") {
|
|
1406
|
+
const integ = safeSummary.integration || {};
|
|
1407
|
+
envelope.integration = {
|
|
1408
|
+
state: integ.state || null,
|
|
1409
|
+
claims: integ.claims || 0,
|
|
1410
|
+
conflicts: integ.conflicts || 0,
|
|
1411
|
+
blockers: integ.blockers || 0,
|
|
1412
|
+
detail: integ.detail || null,
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1275
1415
|
|
|
1276
|
-
|
|
1277
|
-
|
|
1416
|
+
if (role === "documentation") {
|
|
1417
|
+
const docDelta = safeSummary.docDelta || safeSummary.docClosure || {};
|
|
1418
|
+
envelope.documentation = {
|
|
1419
|
+
docClosure: {
|
|
1420
|
+
state: docDelta.state || "no-change",
|
|
1421
|
+
paths: Array.isArray(docDelta.paths) ? docDelta.paths : [],
|
|
1422
|
+
detail: docDelta.detail || null,
|
|
1423
|
+
},
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1278
1426
|
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1427
|
+
if (role === "cont-qa") {
|
|
1428
|
+
const verdict = safeSummary.verdict || {};
|
|
1429
|
+
const gate = safeSummary.gate || {};
|
|
1430
|
+
envelope.contQa = {
|
|
1431
|
+
verdict: {
|
|
1432
|
+
verdict: verdict.verdict || null,
|
|
1433
|
+
detail: verdict.detail || null,
|
|
1434
|
+
},
|
|
1435
|
+
gateClaims: {
|
|
1436
|
+
architecture: gate.architecture || null,
|
|
1437
|
+
integration: gate.integration || null,
|
|
1438
|
+
durability: gate.durability || null,
|
|
1439
|
+
live: gate.live || null,
|
|
1440
|
+
docs: gate.docs || null,
|
|
1441
|
+
},
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1283
1444
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1445
|
+
if (role === "cont-eval") {
|
|
1446
|
+
const evalSection = safeSummary.eval || {};
|
|
1447
|
+
envelope.contEval = {
|
|
1448
|
+
state: evalSection.state || null,
|
|
1449
|
+
targets: evalSection.targets || 0,
|
|
1450
|
+
benchmarks: evalSection.benchmarks || 0,
|
|
1451
|
+
regressions: evalSection.regressions || 0,
|
|
1452
|
+
targetIds: Array.isArray(evalSection.targetIds) ? evalSection.targetIds : [],
|
|
1453
|
+
benchmarkIds: Array.isArray(evalSection.benchmarkIds) ? evalSection.benchmarkIds : [],
|
|
1454
|
+
detail: evalSection.detail || null,
|
|
1455
|
+
};
|
|
1292
1456
|
}
|
|
1293
1457
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
});
|
|
1458
|
+
if (role === "security") {
|
|
1459
|
+
const sec = safeSummary.security || {};
|
|
1460
|
+
envelope.security = {
|
|
1461
|
+
state: sec.state || null,
|
|
1462
|
+
findings: sec.findings || 0,
|
|
1463
|
+
approvals: sec.approvals || 0,
|
|
1464
|
+
detail: sec.detail || null,
|
|
1465
|
+
};
|
|
1303
1466
|
}
|
|
1304
1467
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
});
|
|
1468
|
+
if (role === "deploy") {
|
|
1469
|
+
const dep = safeSummary.deploy || {};
|
|
1470
|
+
envelope.deploy = {
|
|
1471
|
+
state: dep.state || "not_applicable",
|
|
1472
|
+
environment: dep.environment || null,
|
|
1473
|
+
healthCheck: dep.healthCheck || null,
|
|
1474
|
+
rolloutArtifact: dep.rolloutArtifact || null,
|
|
1475
|
+
detail: dep.detail || null,
|
|
1476
|
+
};
|
|
1315
1477
|
}
|
|
1316
1478
|
|
|
1317
|
-
return
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1479
|
+
return envelope;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
/**
|
|
1483
|
+
* Build a v2 envelope from legacy parsed log markers.
|
|
1484
|
+
* Migration adapter: synthesizes the end-state envelope shape from the
|
|
1485
|
+
* output of buildAgentExecutionSummary (which parses log markers).
|
|
1486
|
+
*
|
|
1487
|
+
* This exists so the gate engine always sees a consistent v2 shape,
|
|
1488
|
+
* even when the agent emitted legacy log markers rather than a structured envelope.
|
|
1489
|
+
*
|
|
1490
|
+
* @param {object} agent - Agent definition (must include .agentId, .role)
|
|
1491
|
+
* @param {object} legacySummary - Result from buildAgentExecutionSummary
|
|
1492
|
+
* @param {object} [options] - { waveNumber, attempt, exitCode }
|
|
1493
|
+
* @returns {object} AgentResultEnvelope (schemaVersion 2)
|
|
1494
|
+
*/
|
|
1495
|
+
export function buildEnvelopeFromLegacySignals(agent, legacySummary, options = {}) {
|
|
1496
|
+
const envelope = buildAgentResultEnvelope(agent, legacySummary, options);
|
|
1497
|
+
envelope._synthesizedFromLegacy = true;
|
|
1498
|
+
return envelope;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
export function buildExecutionSummaryFromEnvelope(envelope, options = {}) {
|
|
1502
|
+
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
1503
|
+
return null;
|
|
1504
|
+
}
|
|
1505
|
+
const role = inferEnvelopeRole(options.agent || {}, envelope);
|
|
1506
|
+
const proof = envelope.proof && typeof envelope.proof === "object"
|
|
1507
|
+
? {
|
|
1508
|
+
state: toLegacyProofState(envelope.proof.state),
|
|
1509
|
+
completion: envelope.proof.completion || null,
|
|
1510
|
+
durability: envelope.proof.durability || null,
|
|
1511
|
+
proof: envelope.proof.proofLevel || null,
|
|
1512
|
+
detail: envelope.proof.detail || null,
|
|
1513
|
+
}
|
|
1514
|
+
: null;
|
|
1515
|
+
const summary = {
|
|
1516
|
+
agentId: envelope.agentId || options.agent?.agentId || null,
|
|
1517
|
+
role,
|
|
1518
|
+
waveNumber: envelope.waveNumber ?? options.waveNumber ?? null,
|
|
1519
|
+
attempt: envelope.attempt ?? options.attempt ?? null,
|
|
1520
|
+
completedAt: envelope.completedAt || null,
|
|
1521
|
+
exitCode: typeof envelope.exitCode === "number" ? envelope.exitCode : 0,
|
|
1522
|
+
logPath: toSummaryRelativePath(options.logPath),
|
|
1523
|
+
reportPath: toSummaryRelativePath(options.reportPath),
|
|
1524
|
+
proof,
|
|
1525
|
+
deliverables: Array.isArray(envelope.deliverables)
|
|
1526
|
+
? envelope.deliverables.map((deliverable) => ({
|
|
1527
|
+
path: deliverable.path || null,
|
|
1528
|
+
exists: deliverable.exists === true,
|
|
1529
|
+
sha256: deliverable.sha256 || null,
|
|
1530
|
+
}))
|
|
1531
|
+
: [],
|
|
1532
|
+
proofArtifacts: Array.isArray(envelope.proofArtifacts)
|
|
1533
|
+
? envelope.proofArtifacts.map((artifact) => ({
|
|
1534
|
+
path: artifact.path || null,
|
|
1535
|
+
kind: artifact.kind || null,
|
|
1536
|
+
exists: artifact.exists === true,
|
|
1537
|
+
sha256: artifact.sha256 || null,
|
|
1538
|
+
requiredFor: artifact.requiredFor || null,
|
|
1539
|
+
}))
|
|
1540
|
+
: [],
|
|
1541
|
+
gaps: Array.isArray(envelope.gaps)
|
|
1542
|
+
? envelope.gaps.map((gap) => ({
|
|
1543
|
+
kind: gap.kind || null,
|
|
1544
|
+
detail: gap.detail || null,
|
|
1545
|
+
}))
|
|
1546
|
+
: [],
|
|
1547
|
+
unresolvedBlockers: Array.isArray(envelope.unresolvedBlockers)
|
|
1548
|
+
? envelope.unresolvedBlockers.map((blocker) => ({
|
|
1549
|
+
kind: blocker.kind || null,
|
|
1550
|
+
detail: blocker.detail || null,
|
|
1551
|
+
blocking: blocker.blocking ?? null,
|
|
1552
|
+
}))
|
|
1553
|
+
: [],
|
|
1554
|
+
riskNotes: Array.isArray(envelope.riskNotes) ? envelope.riskNotes.slice() : [],
|
|
1555
|
+
facts: Array.isArray(envelope.facts)
|
|
1556
|
+
? envelope.facts.map((fact) => ({
|
|
1557
|
+
factId: fact.factId || null,
|
|
1558
|
+
kind: fact.kind || null,
|
|
1559
|
+
content: fact.content || null,
|
|
1560
|
+
}))
|
|
1561
|
+
: [],
|
|
1332
1562
|
};
|
|
1563
|
+
|
|
1564
|
+
if (envelope.implementation) {
|
|
1565
|
+
summary.docDelta = {
|
|
1566
|
+
state: envelope.implementation.docDelta?.state || "none",
|
|
1567
|
+
paths: Array.isArray(envelope.implementation.docDelta?.paths)
|
|
1568
|
+
? envelope.implementation.docDelta.paths
|
|
1569
|
+
: [],
|
|
1570
|
+
detail: envelope.implementation.docDelta?.detail || null,
|
|
1571
|
+
};
|
|
1572
|
+
summary.components = Array.isArray(envelope.implementation.components)
|
|
1573
|
+
? envelope.implementation.components.map((component) => ({
|
|
1574
|
+
componentId: component.componentId || null,
|
|
1575
|
+
level: component.level || null,
|
|
1576
|
+
state: component.state || null,
|
|
1577
|
+
detail: component.detail || null,
|
|
1578
|
+
}))
|
|
1579
|
+
: [];
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
if (envelope.documentation?.docClosure) {
|
|
1583
|
+
summary.docClosure = {
|
|
1584
|
+
state: envelope.documentation.docClosure.state || "no-change",
|
|
1585
|
+
paths: Array.isArray(envelope.documentation.docClosure.paths)
|
|
1586
|
+
? envelope.documentation.docClosure.paths
|
|
1587
|
+
: [],
|
|
1588
|
+
detail: envelope.documentation.docClosure.detail || null,
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
if (envelope.integration) {
|
|
1593
|
+
summary.integration = {
|
|
1594
|
+
state: envelope.integration.state || null,
|
|
1595
|
+
claims: envelope.integration.claims || 0,
|
|
1596
|
+
conflicts: envelope.integration.conflicts || 0,
|
|
1597
|
+
blockers: envelope.integration.blockers || 0,
|
|
1598
|
+
detail: envelope.integration.detail || null,
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
if (envelope.contEval) {
|
|
1603
|
+
summary.eval = {
|
|
1604
|
+
state: envelope.contEval.state || null,
|
|
1605
|
+
targets: envelope.contEval.targets || 0,
|
|
1606
|
+
benchmarks: envelope.contEval.benchmarks || 0,
|
|
1607
|
+
regressions: envelope.contEval.regressions || 0,
|
|
1608
|
+
targetIds: Array.isArray(envelope.contEval.targetIds) ? envelope.contEval.targetIds : [],
|
|
1609
|
+
benchmarkIds: Array.isArray(envelope.contEval.benchmarkIds) ? envelope.contEval.benchmarkIds : [],
|
|
1610
|
+
detail: envelope.contEval.detail || null,
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
if (envelope.contQa) {
|
|
1615
|
+
summary.gate = {
|
|
1616
|
+
architecture: envelope.contQa.gateClaims?.architecture || null,
|
|
1617
|
+
integration: envelope.contQa.gateClaims?.integration || null,
|
|
1618
|
+
durability: envelope.contQa.gateClaims?.durability || null,
|
|
1619
|
+
live: envelope.contQa.gateClaims?.live || null,
|
|
1620
|
+
docs: envelope.contQa.gateClaims?.docs || null,
|
|
1621
|
+
detail: envelope.contQa.gateClaims?.detail || null,
|
|
1622
|
+
};
|
|
1623
|
+
summary.verdict = {
|
|
1624
|
+
verdict: envelope.contQa.verdict?.verdict || null,
|
|
1625
|
+
detail: envelope.contQa.verdict?.detail || null,
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
if (envelope.security) {
|
|
1630
|
+
summary.security = {
|
|
1631
|
+
state: envelope.security.state || null,
|
|
1632
|
+
findings: envelope.security.findings || 0,
|
|
1633
|
+
approvals: envelope.security.approvals || 0,
|
|
1634
|
+
detail: envelope.security.detail || null,
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
if (envelope.deploy) {
|
|
1639
|
+
summary.deploy = {
|
|
1640
|
+
state: envelope.deploy.state || "not_applicable",
|
|
1641
|
+
environment: envelope.deploy.environment || null,
|
|
1642
|
+
healthCheck: envelope.deploy.healthCheck || null,
|
|
1643
|
+
rolloutArtifact: envelope.deploy.rolloutArtifact || null,
|
|
1644
|
+
detail: envelope.deploy.detail || null,
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
return summary;
|
|
1333
1649
|
}
|
|
1334
1650
|
|
|
1335
1651
|
/**
|