@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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This repo now includes a dedicated npmjs publish workflow at [publish-npm.yml](../../.github/workflows/publish-npm.yml).
|
|
4
4
|
|
|
5
|
-
The current `0.8.
|
|
5
|
+
The current `0.8.4` release procedure publishes through a repository Actions secret named `NPM_TOKEN`.
|
|
6
6
|
|
|
7
7
|
## What This Repo Already Does
|
|
8
8
|
|
|
@@ -47,6 +47,7 @@ If this repo later needs private npm dependencies during CI, consider a separate
|
|
|
47
47
|
1. Confirm [publish-npm.yml](../../.github/workflows/publish-npm.yml) is on the default branch.
|
|
48
48
|
2. Confirm `NPM_TOKEN` exists in the GitHub repo secrets.
|
|
49
49
|
3. Confirm the package version has been bumped and committed.
|
|
50
|
-
4.
|
|
51
|
-
5.
|
|
52
|
-
6. Verify
|
|
50
|
+
4. Confirm `README.md`, `CHANGELOG.md`, `releases/manifest.json`, and `docs/plans/migration.md` all describe the same release surface.
|
|
51
|
+
5. Push the release commit and release tag, for example `v0.8.4`.
|
|
52
|
+
6. Verify both `publish-npm.yml` and `publish-package.yml` start from the tag push.
|
|
53
|
+
7. Verify the npmjs publish completes successfully for the tagged source.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Sample Waves"
|
|
3
|
-
summary: "Showcase-first sample waves that demonstrate the current 0.8.
|
|
3
|
+
summary: "Showcase-first sample waves that demonstrate the current 0.8.4 Wave surface."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Sample Waves
|
|
7
7
|
|
|
8
|
-
This guide points to showcase-first sample waves that demonstrate the current `0.8.
|
|
8
|
+
This guide points to showcase-first sample waves that demonstrate the current `0.8.4` authored Wave surface.
|
|
9
9
|
|
|
10
10
|
The examples are intentionally denser than typical production waves. Their job is to teach the current authoring and runtime surface quickly, not to be the smallest possible launch-ready files.
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ The examples are intentionally denser than typical production waves. Their job i
|
|
|
15
15
|
Shows what a good `repo-landed` outcome looks like when one promoted component only closes honestly if desired-state records, reconcile-loop substrate, and cluster-view surfaces land together. It emphasizes maturity discipline, explicit deliverables, and shared-plan closure without drifting into `pilot-live` claims.
|
|
16
16
|
|
|
17
17
|
- [Full modern sample wave](../plans/examples/wave-example-live-proof.md)
|
|
18
|
-
Shows the combined `0.8.
|
|
18
|
+
Shows the combined `0.8.4` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure.
|
|
19
19
|
|
|
20
20
|
## What These Examples Teach
|
|
21
21
|
|
|
@@ -38,7 +38,7 @@ The examples are intentionally denser than typical production waves. Their job i
|
|
|
38
38
|
|
|
39
39
|
## Feature Coverage Map
|
|
40
40
|
|
|
41
|
-
Together these samples cover the main surfaces added or hardened for `0.8.
|
|
41
|
+
Together these samples cover the main surfaces added or hardened for `0.8.4`:
|
|
42
42
|
|
|
43
43
|
- repo-landed maturity discipline and anti-overclaim framing
|
|
44
44
|
- explicit shared-plan closure for future-wave safety
|
package/package.json
CHANGED
package/releases/manifest.json
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "@chllming/wave-orchestration",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.8.4",
|
|
7
|
+
"date": "2026-03-25",
|
|
8
|
+
"summary": "Contradiction replay repair, consistent component-promotion thresholds, projection-writer persistence centralization, and 0.8.4 release-surface alignment.",
|
|
9
|
+
"features": [
|
|
10
|
+
"Hermetic contradiction replay no longer depends on component-matrix parsing when the trace does not declare promoted components.",
|
|
11
|
+
"`requireComponentPromotionsFromWave` now gates both component-promotion proof validation and component-matrix current-level validation consistently across live and replay paths.",
|
|
12
|
+
"Projection persistence is now centralized under `projection-writer.mjs`, while `derived-state-engine.mjs` computes projection payloads without writing them directly.",
|
|
13
|
+
"The operator migration guide now covers fresh adoption plus upgrades from `0.8.3`, `0.8.0`-`0.8.2`, `0.6.x`-`0.7.x`, and `0.5.x` or earlier with explicit repo-owned surface sync guidance.",
|
|
14
|
+
"Shipped package metadata, README, migration guidance, current-state notes, sample-wave docs, and npm publishing instructions now point at the `0.8.4` release surface."
|
|
15
|
+
],
|
|
16
|
+
"manualSteps": [
|
|
17
|
+
"Run `pnpm exec wave doctor` and `pnpm exec wave launch --lane main --dry-run --no-dashboard` after upgrading so the repo validates against the `0.8.4` replay, projection, and component-threshold behavior.",
|
|
18
|
+
"If your adopted repo uses planner workflows and copied the starter planner corpus, sync `docs/agents/wave-planner-role.md`, `skills/role-planner/`, `docs/context7/planner-agent/`, `docs/reference/wave-planning-lessons.md`, and the `planner-agentic` bundle entry in `docs/context7/bundles.json`.",
|
|
19
|
+
"If your repo copied the shipped starter docs or skills, sync the current operator runbook, architecture docs, launcher or orchestrator prompts, planner corpus, and relevant runtime or closure-role starter skills before relying on local runbooks.",
|
|
20
|
+
"If your repo keeps historical replay fixtures, replay at least one contradiction-blocked trace and one promoted-component trace after the upgrade so both code paths stay covered.",
|
|
21
|
+
"If an older adopted repo still carries legacy evaluator wording or pre-control-plane operator docs, complete the repo-owned prompt and runbook migration described in `docs/plans/migration.md` before cutting live waves on `0.8.4`."
|
|
22
|
+
],
|
|
23
|
+
"breaking": false
|
|
24
|
+
},
|
|
5
25
|
{
|
|
6
26
|
"version": "0.8.3",
|
|
7
27
|
"date": "2026-03-24",
|
|
@@ -1180,494 +1180,3 @@ export function validateContQaSummary(agent, summary, options = {}) {
|
|
|
1180
1180
|
detail: summary.verdict.detail || summary.gate.detail || "cont-QA gate passed.",
|
|
1181
1181
|
};
|
|
1182
1182
|
}
|
|
1183
|
-
|
|
1184
|
-
// ---------------------------------------------------------------------------
|
|
1185
|
-
// Agent Result Envelope — P1-6 End-State (schemaVersion 2)
|
|
1186
|
-
// ---------------------------------------------------------------------------
|
|
1187
|
-
|
|
1188
|
-
import { toIsoTimestamp } from "./shared.mjs";
|
|
1189
|
-
|
|
1190
|
-
/**
|
|
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.
|
|
1272
|
-
*
|
|
1273
|
-
* @param {string} statusPath - Path to the .status or .summary file
|
|
1274
|
-
* @returns {string} The envelope file path
|
|
1275
|
-
*/
|
|
1276
|
-
export function agentEnvelopePathFromStatusPath(statusPath) {
|
|
1277
|
-
if (statusPath.endsWith(".summary.json")) {
|
|
1278
|
-
return statusPath.replace(/\.summary\.json$/i, ".envelope.json");
|
|
1279
|
-
}
|
|
1280
|
-
if (statusPath.endsWith(".status")) {
|
|
1281
|
-
return statusPath.replace(/\.status$/i, ".envelope.json");
|
|
1282
|
-
}
|
|
1283
|
-
return `${statusPath}.envelope.json`;
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
/**
|
|
1287
|
-
* Build a structured result envelope from an already-parsed execution summary.
|
|
1288
|
-
* Pure function — the envelope is a normalized projection of the summary.
|
|
1289
|
-
*
|
|
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)
|
|
1294
|
-
* @param {object} summary - Execution summary from buildAgentExecutionSummary
|
|
1295
|
-
* @param {object} [options] - { waveNumber, attempt, exitCode }
|
|
1296
|
-
* @returns {object} AgentResultEnvelope (schemaVersion 2)
|
|
1297
|
-
*/
|
|
1298
|
-
export function buildAgentResultEnvelope(agent, summary, options = {}) {
|
|
1299
|
-
const safeAgent = agent || {};
|
|
1300
|
-
const safeSummary = summary || {};
|
|
1301
|
-
const safeOptions = options || {};
|
|
1302
|
-
|
|
1303
|
-
const agentId = safeAgent.agentId || safeSummary.agentId || null;
|
|
1304
|
-
const role = inferEnvelopeRole(safeAgent, safeSummary);
|
|
1305
|
-
|
|
1306
|
-
// --- Common header ---
|
|
1307
|
-
const proof = safeSummary.proof || {};
|
|
1308
|
-
const proofSection = {
|
|
1309
|
-
state: proof.state === "met" ? "satisfied"
|
|
1310
|
-
: proof.state === "gap" ? "partial"
|
|
1311
|
-
: proof.state === "failed" ? "failed"
|
|
1312
|
-
: "not_applicable",
|
|
1313
|
-
completion: proof.completion || null,
|
|
1314
|
-
durability: proof.durability || null,
|
|
1315
|
-
proofLevel: proof.proof || null,
|
|
1316
|
-
detail: proof.detail || null,
|
|
1317
|
-
};
|
|
1318
|
-
|
|
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
|
|
1329
|
-
const proofArtifacts = Array.isArray(safeSummary.proofArtifacts)
|
|
1330
|
-
? safeSummary.proofArtifacts.map((artifact) => ({
|
|
1331
|
-
path: artifact.path || null,
|
|
1332
|
-
kind: artifact.kind || null,
|
|
1333
|
-
exists: artifact.exists === true,
|
|
1334
|
-
sha256: artifact.sha256 || null,
|
|
1335
|
-
requiredFor: artifact.requiredFor || null,
|
|
1336
|
-
}))
|
|
1337
|
-
: [];
|
|
1338
|
-
|
|
1339
|
-
// Gaps
|
|
1340
|
-
const gaps = Array.isArray(safeSummary.gaps)
|
|
1341
|
-
? safeSummary.gaps.map((g) => ({
|
|
1342
|
-
kind: g.kind || null,
|
|
1343
|
-
detail: g.detail || null,
|
|
1344
|
-
}))
|
|
1345
|
-
: [];
|
|
1346
|
-
|
|
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,
|
|
1363
|
-
}))
|
|
1364
|
-
: [];
|
|
1365
|
-
|
|
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
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
|
|
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
|
-
}
|
|
1415
|
-
|
|
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
|
-
}
|
|
1426
|
-
|
|
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
|
-
}
|
|
1444
|
-
|
|
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
|
-
};
|
|
1456
|
-
}
|
|
1457
|
-
|
|
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
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
|
|
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
|
-
};
|
|
1477
|
-
}
|
|
1478
|
-
|
|
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
|
-
: [],
|
|
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;
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1651
|
-
/**
|
|
1652
|
-
* Write an agent result envelope alongside the summary file.
|
|
1653
|
-
*
|
|
1654
|
-
* @param {string} statusPath - Path to the .status file
|
|
1655
|
-
* @param {object} envelope - Result from buildAgentResultEnvelope
|
|
1656
|
-
*/
|
|
1657
|
-
export function writeAgentResultEnvelope(statusPath, envelope) {
|
|
1658
|
-
const envelopePath = agentEnvelopePathFromStatusPath(statusPath);
|
|
1659
|
-
writeJsonAtomic(envelopePath, envelope);
|
|
1660
|
-
return envelopePath;
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
/**
|
|
1664
|
-
* Read an agent result envelope if it exists.
|
|
1665
|
-
*
|
|
1666
|
-
* @param {string} statusPath - Path to the .status file
|
|
1667
|
-
* @returns {object|null} The envelope or null
|
|
1668
|
-
*/
|
|
1669
|
-
export function readAgentResultEnvelope(statusPath) {
|
|
1670
|
-
const envelopePath = agentEnvelopePathFromStatusPath(statusPath);
|
|
1671
|
-
const payload = readJsonOrNull(envelopePath);
|
|
1672
|
-
return payload && typeof payload === "object" ? payload : null;
|
|
1673
|
-
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_CODEX_SANDBOX_MODE,
|
|
6
|
+
DEFAULT_EXECUTOR_MODE,
|
|
7
|
+
normalizeCodexSandboxMode,
|
|
8
|
+
normalizeExecutorMode,
|
|
9
|
+
SUPPORTED_EXECUTOR_MODES,
|
|
10
|
+
} from "./config.mjs";
|
|
5
11
|
import {
|
|
6
12
|
DEFAULT_AGENT_LAUNCH_STAGGER_MS,
|
|
7
13
|
DEFAULT_AGENT_RATE_LIMIT_BASE_DELAY_SECONDS,
|
|
@@ -17,10 +23,6 @@ import {
|
|
|
17
23
|
parsePositiveInt,
|
|
18
24
|
sanitizeLaneName,
|
|
19
25
|
} from "./shared.mjs";
|
|
20
|
-
import {
|
|
21
|
-
DEFAULT_CODEX_SANDBOX_MODE,
|
|
22
|
-
normalizeCodexSandboxMode,
|
|
23
|
-
} from "./launcher.mjs";
|
|
24
26
|
import {
|
|
25
27
|
maybeAnnouncePackageUpdate,
|
|
26
28
|
WAVE_SUPPRESS_UPDATE_NOTICE_ENV,
|
|
@@ -29,6 +31,8 @@ import { readRunState } from "./wave-files.mjs";
|
|
|
29
31
|
import { readDependencyTickets } from "./coordination-store.mjs";
|
|
30
32
|
import { readWaveLedger } from "./ledger.mjs";
|
|
31
33
|
|
|
34
|
+
const AUTONOMOUS_EXECUTOR_MODES = SUPPORTED_EXECUTOR_MODES.filter((mode) => mode !== "local");
|
|
35
|
+
|
|
32
36
|
function printUsage() {
|
|
33
37
|
console.log(`Usage: pnpm exec wave autonomous [options]
|
|
34
38
|
|
|
@@ -46,7 +50,7 @@ Options:
|
|
|
46
50
|
--agent-launch-stagger-ms <n> Delay between agent launches (default: ${DEFAULT_AGENT_LAUNCH_STAGGER_MS})
|
|
47
51
|
--orchestrator-id <id> Orchestrator ID for coordination board
|
|
48
52
|
--resident-orchestrator Launch a resident orchestrator session for each live wave
|
|
49
|
-
--executor <mode> Default executor passed to launcher: ${
|
|
53
|
+
--executor <mode> Default executor passed to launcher: ${AUTONOMOUS_EXECUTOR_MODES.join(" | ")} (default: lane config)
|
|
50
54
|
--codex-sandbox <mode> Default Codex sandbox mode passed to launcher (default: ${DEFAULT_CODEX_SANDBOX_MODE})
|
|
51
55
|
--dashboard Enable dashboards (default: disabled)
|
|
52
56
|
--keep-sessions Keep tmux sessions between waves
|