@chllming/wave-orchestration 0.9.11 → 0.9.12
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 +17 -0
- package/README.md +7 -8
- package/docs/README.md +4 -10
- package/docs/architecture/README.md +12 -4
- package/docs/concepts/operating-modes.md +1 -1
- package/docs/guides/author-and-run-waves.md +3 -2
- package/docs/guides/planner.md +3 -3
- package/docs/guides/recommendations-0.9.12.md +49 -0
- package/docs/guides/sandboxed-environments.md +2 -2
- package/docs/guides/terminal-surfaces.md +1 -1
- package/docs/plans/current-state.md +3 -3
- package/docs/plans/end-state-architecture.md +1 -1
- package/docs/plans/examples/wave-example-design-handoff.md +1 -1
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +32 -28
- package/docs/plans/wave-orchestrator.md +1 -1
- package/docs/reference/cli-reference.md +2 -2
- package/docs/reference/coordination-and-closure.md +1 -1
- package/docs/reference/npmjs-token-publishing.md +2 -2
- package/docs/reference/package-publishing-flow.md +12 -12
- package/docs/reference/runtime-config/README.md +2 -2
- package/docs/reference/sample-waves.md +5 -5
- package/docs/reference/skills.md +1 -1
- package/docs/reference/wave-control.md +3 -1
- package/docs/roadmap.md +3 -3
- package/package.json +8 -9
- package/releases/manifest.json +32 -0
- package/scripts/context7-api-check.sh +0 -0
- package/scripts/context7-export-env.sh +0 -0
- package/scripts/wave-autonomous.mjs +0 -0
- package/scripts/wave-dashboard.mjs +0 -0
- package/scripts/wave-human-feedback.mjs +0 -0
- package/scripts/wave-launcher.mjs +0 -0
- package/scripts/wave-local-executor.mjs +0 -0
- package/scripts/wave-orchestrator/autonomous.mjs +2 -2
- package/scripts/wave-orchestrator/closure-engine.mjs +103 -6
- package/scripts/wave-orchestrator/closure-policy.mjs +319 -0
- package/scripts/wave-orchestrator/config.mjs +15 -0
- package/scripts/wave-orchestrator/derived-state-engine.mjs +45 -2
- package/scripts/wave-orchestrator/gate-engine.mjs +72 -4
- package/scripts/wave-orchestrator/install.mjs +1 -1
- package/scripts/wave-orchestrator/launcher.mjs +14 -4
- package/scripts/wave-orchestrator/planner.mjs +4 -3
- package/scripts/wave-orchestrator/shared.mjs +2 -3
- package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1 -1
- package/scripts/wave-orchestrator/traces.mjs +22 -1
- package/scripts/wave-status.sh +0 -0
- package/scripts/wave-watch.sh +0 -0
- package/scripts/wave.mjs +0 -0
- package/wave.config.json +13 -2
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
function normalizeBoolean(value, fallback = false) {
|
|
2
|
+
if (value === undefined || value === null || value === "") {
|
|
3
|
+
return fallback;
|
|
4
|
+
}
|
|
5
|
+
if (typeof value === "boolean") {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
const normalized = String(value || "")
|
|
9
|
+
.trim()
|
|
10
|
+
.toLowerCase();
|
|
11
|
+
if (["true", "1", "yes", "on"].includes(normalized)) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (["false", "0", "no", "off"].includes(normalized)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return fallback;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function normalizeThreshold(value, fallback) {
|
|
21
|
+
if (value === null || value === undefined || value === "") {
|
|
22
|
+
return fallback;
|
|
23
|
+
}
|
|
24
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
25
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function contradictionList(value) {
|
|
29
|
+
if (!value) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
if (value instanceof Map) {
|
|
33
|
+
return Array.from(value.values());
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "object") {
|
|
39
|
+
return Object.values(value);
|
|
40
|
+
}
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function openCoordinationRecords(records = []) {
|
|
45
|
+
return (Array.isArray(records) ? records : []).filter(
|
|
46
|
+
(record) =>
|
|
47
|
+
!["resolved", "closed", "cancelled", "superseded"].includes(
|
|
48
|
+
String(record?.status || "")
|
|
49
|
+
.trim()
|
|
50
|
+
.toLowerCase(),
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function closureSignalsFromDerivedState(derivedState = {}) {
|
|
56
|
+
const integrationSummary = derivedState?.integrationSummary || {};
|
|
57
|
+
const docsQueueItems = Array.isArray(derivedState?.docsQueue?.items)
|
|
58
|
+
? derivedState.docsQueue.items
|
|
59
|
+
: [];
|
|
60
|
+
const coordinationState = derivedState?.coordinationState || {};
|
|
61
|
+
const clarificationBarrier = derivedState?.clarificationBarrier || { ok: true };
|
|
62
|
+
const helperAssignmentBarrier = derivedState?.helperAssignmentBarrier || { ok: true };
|
|
63
|
+
const dependencyBarrier = derivedState?.dependencyBarrier || { ok: true };
|
|
64
|
+
const securitySummary = derivedState?.securitySummary || null;
|
|
65
|
+
const corridorSummary =
|
|
66
|
+
derivedState?.corridorSummary || derivedState?.securitySummary?.corridor || null;
|
|
67
|
+
const blockingContradictions = contradictionList(derivedState?.contradictions).filter(
|
|
68
|
+
(entry) =>
|
|
69
|
+
["blocking", "high"].includes(String(entry?.severity || "").trim().toLowerCase()) &&
|
|
70
|
+
((Array.isArray(entry?.impactedGates) && entry.impactedGates.includes("integrationBarrier")) ||
|
|
71
|
+
!Array.isArray(entry?.impactedGates) ||
|
|
72
|
+
entry.impactedGates.length === 0) &&
|
|
73
|
+
!["resolved", "closed", "cleared"].includes(
|
|
74
|
+
String(entry?.status || "")
|
|
75
|
+
.trim()
|
|
76
|
+
.toLowerCase(),
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
const openClarifications = openCoordinationRecords(coordinationState?.clarifications);
|
|
80
|
+
const openHuman = [
|
|
81
|
+
...openCoordinationRecords(coordinationState?.humanEscalations),
|
|
82
|
+
...openCoordinationRecords(coordinationState?.humanFeedback),
|
|
83
|
+
];
|
|
84
|
+
const blockingAssignments = (Array.isArray(derivedState?.capabilityAssignments)
|
|
85
|
+
? derivedState.capabilityAssignments
|
|
86
|
+
: []
|
|
87
|
+
).filter((assignment) => assignment?.blocking !== false);
|
|
88
|
+
const openDependencies = [
|
|
89
|
+
...((Array.isArray(derivedState?.dependencySnapshot?.openInbound)
|
|
90
|
+
? derivedState.dependencySnapshot.openInbound
|
|
91
|
+
: []) || []),
|
|
92
|
+
...((Array.isArray(derivedState?.dependencySnapshot?.openOutbound)
|
|
93
|
+
? derivedState.dependencySnapshot.openOutbound
|
|
94
|
+
: []) || []),
|
|
95
|
+
...((Array.isArray(derivedState?.dependencySnapshot?.unresolvedInboundAssignments)
|
|
96
|
+
? derivedState.dependencySnapshot.unresolvedInboundAssignments
|
|
97
|
+
: []) || []),
|
|
98
|
+
];
|
|
99
|
+
const sharedPlanItems = docsQueueItems.filter((item) => item?.kind === "shared-plan");
|
|
100
|
+
const componentMatrixItems = docsQueueItems.filter((item) => item?.kind === "component-matrix");
|
|
101
|
+
return {
|
|
102
|
+
integrationReady:
|
|
103
|
+
integrationSummary?.recommendation === "ready-for-doc-closure",
|
|
104
|
+
openClaims: Array.isArray(integrationSummary?.openClaims) ? integrationSummary.openClaims : [],
|
|
105
|
+
conflictingClaims: Array.isArray(integrationSummary?.conflictingClaims)
|
|
106
|
+
? integrationSummary.conflictingClaims
|
|
107
|
+
: [],
|
|
108
|
+
unresolvedBlockers: Array.isArray(integrationSummary?.unresolvedBlockers)
|
|
109
|
+
? integrationSummary.unresolvedBlockers
|
|
110
|
+
: [],
|
|
111
|
+
changedInterfaces: Array.isArray(integrationSummary?.changedInterfaces)
|
|
112
|
+
? integrationSummary.changedInterfaces
|
|
113
|
+
: [],
|
|
114
|
+
crossComponentImpacts: Array.isArray(integrationSummary?.crossComponentImpacts)
|
|
115
|
+
? integrationSummary.crossComponentImpacts
|
|
116
|
+
: [],
|
|
117
|
+
proofGaps: Array.isArray(integrationSummary?.proofGaps) ? integrationSummary.proofGaps : [],
|
|
118
|
+
docGaps: Array.isArray(integrationSummary?.docGaps) ? integrationSummary.docGaps : [],
|
|
119
|
+
deployRisks: Array.isArray(integrationSummary?.deployRisks)
|
|
120
|
+
? integrationSummary.deployRisks
|
|
121
|
+
: [],
|
|
122
|
+
inboundDependencies: Array.isArray(integrationSummary?.inboundDependencies)
|
|
123
|
+
? integrationSummary.inboundDependencies
|
|
124
|
+
: [],
|
|
125
|
+
outboundDependencies: Array.isArray(integrationSummary?.outboundDependencies)
|
|
126
|
+
? integrationSummary.outboundDependencies
|
|
127
|
+
: [],
|
|
128
|
+
helperAssignments: Array.isArray(integrationSummary?.helperAssignments)
|
|
129
|
+
? integrationSummary.helperAssignments
|
|
130
|
+
: [],
|
|
131
|
+
sharedPlanItems,
|
|
132
|
+
componentMatrixItems,
|
|
133
|
+
blockingContradictions,
|
|
134
|
+
openClarifications,
|
|
135
|
+
openHuman,
|
|
136
|
+
blockingAssignments,
|
|
137
|
+
openDependencies,
|
|
138
|
+
clarificationBarrier,
|
|
139
|
+
helperAssignmentBarrier,
|
|
140
|
+
dependencyBarrier,
|
|
141
|
+
securityState:
|
|
142
|
+
integrationSummary?.securityState || securitySummary?.overallState || "not-applicable",
|
|
143
|
+
corridorSummary,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function resolveClosureMode(waveNumber, thresholds) {
|
|
148
|
+
if (!thresholds) {
|
|
149
|
+
return "strict";
|
|
150
|
+
}
|
|
151
|
+
const bootstrapStart = normalizeThreshold(thresholds.bootstrap, 0);
|
|
152
|
+
const standardStart = Math.max(
|
|
153
|
+
bootstrapStart,
|
|
154
|
+
normalizeThreshold(thresholds.standard, 4),
|
|
155
|
+
);
|
|
156
|
+
const strictStart = Math.max(
|
|
157
|
+
standardStart,
|
|
158
|
+
normalizeThreshold(thresholds.strict, 10),
|
|
159
|
+
);
|
|
160
|
+
if (waveNumber >= strictStart) {
|
|
161
|
+
return "strict";
|
|
162
|
+
}
|
|
163
|
+
if (waveNumber >= standardStart) {
|
|
164
|
+
return "standard";
|
|
165
|
+
}
|
|
166
|
+
return "bootstrap";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function resolveClosurePolicyConfig(source = {}) {
|
|
170
|
+
const validation = source?.laneProfile?.validation || source?.validation || {};
|
|
171
|
+
const rawThresholds =
|
|
172
|
+
source?.closureModeThresholds || validation?.closureModeThresholds || null;
|
|
173
|
+
const rawAutoClosure = source?.autoClosure || validation?.autoClosure || {};
|
|
174
|
+
return {
|
|
175
|
+
closureModeThresholds: {
|
|
176
|
+
bootstrap: normalizeThreshold(rawThresholds?.bootstrap, 0),
|
|
177
|
+
standard: normalizeThreshold(rawThresholds?.standard, 4),
|
|
178
|
+
strict: normalizeThreshold(rawThresholds?.strict, 10),
|
|
179
|
+
},
|
|
180
|
+
autoClosure: {
|
|
181
|
+
allowInferredIntegration: normalizeBoolean(
|
|
182
|
+
rawAutoClosure?.allowInferredIntegration,
|
|
183
|
+
false,
|
|
184
|
+
),
|
|
185
|
+
allowAutoDocNoChange: normalizeBoolean(
|
|
186
|
+
rawAutoClosure?.allowAutoDocNoChange,
|
|
187
|
+
false,
|
|
188
|
+
),
|
|
189
|
+
allowAutoDocProjection: normalizeBoolean(
|
|
190
|
+
rawAutoClosure?.allowAutoDocProjection,
|
|
191
|
+
false,
|
|
192
|
+
),
|
|
193
|
+
allowSkipContQaInBootstrap: normalizeBoolean(
|
|
194
|
+
rawAutoClosure?.allowSkipContQaInBootstrap,
|
|
195
|
+
false,
|
|
196
|
+
),
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function classifyClosureComplexity(derivedState = {}) {
|
|
202
|
+
const signals = closureSignalsFromDerivedState(derivedState);
|
|
203
|
+
const hasStrictSignals =
|
|
204
|
+
signals.blockingContradictions.length > 0 ||
|
|
205
|
+
signals.openClarifications.length > 0 ||
|
|
206
|
+
signals.openHuman.length > 0 ||
|
|
207
|
+
signals.clarificationBarrier?.ok === false ||
|
|
208
|
+
signals.helperAssignmentBarrier?.ok === false ||
|
|
209
|
+
signals.dependencyBarrier?.ok === false ||
|
|
210
|
+
signals.securityState === "blocked" ||
|
|
211
|
+
signals.corridorSummary?.blocking === true ||
|
|
212
|
+
(signals.corridorSummary?.ok === false &&
|
|
213
|
+
signals.corridorSummary?.requiredAtClosure !== false);
|
|
214
|
+
if (hasStrictSignals) {
|
|
215
|
+
return "strict-full-closure";
|
|
216
|
+
}
|
|
217
|
+
const hasSemanticIntegrationSignals =
|
|
218
|
+
signals.openClaims.length > 0 ||
|
|
219
|
+
signals.conflictingClaims.length > 0 ||
|
|
220
|
+
signals.unresolvedBlockers.length > 0 ||
|
|
221
|
+
signals.changedInterfaces.length > 0 ||
|
|
222
|
+
signals.crossComponentImpacts.length > 0 ||
|
|
223
|
+
signals.proofGaps.length > 0 ||
|
|
224
|
+
signals.deployRisks.length > 0 ||
|
|
225
|
+
signals.helperAssignments.length > 0 ||
|
|
226
|
+
signals.inboundDependencies.length > 0 ||
|
|
227
|
+
signals.outboundDependencies.length > 0 ||
|
|
228
|
+
signals.blockingAssignments.length > 0 ||
|
|
229
|
+
signals.openDependencies.length > 0;
|
|
230
|
+
if (hasSemanticIntegrationSignals) {
|
|
231
|
+
return "semantic-integration";
|
|
232
|
+
}
|
|
233
|
+
if (signals.sharedPlanItems.length > 0) {
|
|
234
|
+
return "semantic-docs";
|
|
235
|
+
}
|
|
236
|
+
return "low-entropy";
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function evaluateInferredIntegrationClosure(derivedState = {}, source = {}) {
|
|
240
|
+
const policy = resolveClosurePolicyConfig(source);
|
|
241
|
+
if (!policy.autoClosure.allowInferredIntegration) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
const signals = closureSignalsFromDerivedState(derivedState);
|
|
245
|
+
if (!signals.integrationReady) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
const hasSemanticSignals =
|
|
249
|
+
signals.openClaims.length > 0 ||
|
|
250
|
+
signals.conflictingClaims.length > 0 ||
|
|
251
|
+
signals.unresolvedBlockers.length > 0 ||
|
|
252
|
+
signals.changedInterfaces.length > 0 ||
|
|
253
|
+
signals.crossComponentImpacts.length > 0 ||
|
|
254
|
+
signals.proofGaps.length > 0 ||
|
|
255
|
+
signals.deployRisks.length > 0 ||
|
|
256
|
+
signals.helperAssignments.length > 0 ||
|
|
257
|
+
signals.inboundDependencies.length > 0 ||
|
|
258
|
+
signals.outboundDependencies.length > 0 ||
|
|
259
|
+
signals.blockingContradictions.length > 0 ||
|
|
260
|
+
signals.openClarifications.length > 0 ||
|
|
261
|
+
signals.openHuman.length > 0 ||
|
|
262
|
+
signals.clarificationBarrier?.ok === false ||
|
|
263
|
+
signals.helperAssignmentBarrier?.ok === false ||
|
|
264
|
+
signals.dependencyBarrier?.ok === false ||
|
|
265
|
+
signals.blockingAssignments.length > 0 ||
|
|
266
|
+
signals.openDependencies.length > 0 ||
|
|
267
|
+
signals.securityState === "blocked" ||
|
|
268
|
+
signals.corridorSummary?.blocking === true ||
|
|
269
|
+
(signals.corridorSummary?.ok === false &&
|
|
270
|
+
signals.corridorSummary?.requiredAtClosure !== false);
|
|
271
|
+
if (hasSemanticSignals) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
ok: true,
|
|
276
|
+
state: "inferred",
|
|
277
|
+
statusCode: "pass",
|
|
278
|
+
detail:
|
|
279
|
+
"Integration closure was inferred from derived state; no semantic integration contradictions or blockers remain.",
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function evaluateDocumentationAutoClosure(
|
|
284
|
+
derivedState = {},
|
|
285
|
+
source = {},
|
|
286
|
+
options = {},
|
|
287
|
+
) {
|
|
288
|
+
const policy = resolveClosurePolicyConfig(source);
|
|
289
|
+
const signals = closureSignalsFromDerivedState(derivedState);
|
|
290
|
+
const componentMatrixGate = options.componentMatrixGate || { ok: true };
|
|
291
|
+
if (
|
|
292
|
+
policy.autoClosure.allowAutoDocNoChange &&
|
|
293
|
+
signals.sharedPlanItems.length === 0 &&
|
|
294
|
+
signals.componentMatrixItems.length === 0
|
|
295
|
+
) {
|
|
296
|
+
return {
|
|
297
|
+
ok: true,
|
|
298
|
+
state: "no-change",
|
|
299
|
+
statusCode: "pass",
|
|
300
|
+
detail:
|
|
301
|
+
"Documentation closure was auto-satisfied because derived state shows no shared-plan or component-matrix delta.",
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
if (
|
|
305
|
+
policy.autoClosure.allowAutoDocProjection &&
|
|
306
|
+
signals.sharedPlanItems.length === 0 &&
|
|
307
|
+
signals.componentMatrixItems.length > 0 &&
|
|
308
|
+
componentMatrixGate.ok
|
|
309
|
+
) {
|
|
310
|
+
return {
|
|
311
|
+
ok: true,
|
|
312
|
+
state: "auto-closed",
|
|
313
|
+
statusCode: "pass",
|
|
314
|
+
detail:
|
|
315
|
+
"Documentation closure was auto-satisfied because only mechanical component-matrix reconciliation remained and the canonical matrix is already current.",
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
@@ -536,6 +536,21 @@ function normalizeValidation(rawValidation = {}) {
|
|
|
536
536
|
standard: rawValidation.gateModeThresholds?.standard ?? 4,
|
|
537
537
|
strict: rawValidation.gateModeThresholds?.strict ?? 10,
|
|
538
538
|
},
|
|
539
|
+
closureModeThresholds: {
|
|
540
|
+
bootstrap: rawValidation.closureModeThresholds?.bootstrap ?? 0,
|
|
541
|
+
standard: rawValidation.closureModeThresholds?.standard ?? 4,
|
|
542
|
+
strict: rawValidation.closureModeThresholds?.strict ?? 10,
|
|
543
|
+
},
|
|
544
|
+
autoClosure: {
|
|
545
|
+
allowInferredIntegration:
|
|
546
|
+
normalizeOptionalBoolean(rawValidation.autoClosure?.allowInferredIntegration, false),
|
|
547
|
+
allowAutoDocNoChange:
|
|
548
|
+
normalizeOptionalBoolean(rawValidation.autoClosure?.allowAutoDocNoChange, false),
|
|
549
|
+
allowAutoDocProjection:
|
|
550
|
+
normalizeOptionalBoolean(rawValidation.autoClosure?.allowAutoDocProjection, false),
|
|
551
|
+
allowSkipContQaInBootstrap:
|
|
552
|
+
normalizeOptionalBoolean(rawValidation.autoClosure?.allowSkipContQaInBootstrap, false),
|
|
553
|
+
},
|
|
539
554
|
bootstrapPassConditions: {
|
|
540
555
|
requireA0Verdict: rawValidation.bootstrapPassConditions?.requireA0Verdict ?? false,
|
|
541
556
|
requireProofSignals: rawValidation.bootstrapPassConditions?.requireProofSignals ?? false,
|
|
@@ -3,7 +3,10 @@ import path from "node:path";
|
|
|
3
3
|
import {
|
|
4
4
|
materializeAgentExecutionSummaryForRun,
|
|
5
5
|
materializeAgentExecutionSummaries,
|
|
6
|
+
readClarificationBarrier,
|
|
6
7
|
readRunExecutionSummary,
|
|
8
|
+
readWaveAssignmentBarrier,
|
|
9
|
+
readWaveDependencyBarrier,
|
|
7
10
|
} from "./gate-engine.mjs";
|
|
8
11
|
import {
|
|
9
12
|
isOpenCoordinationStatus,
|
|
@@ -51,6 +54,11 @@ import {
|
|
|
51
54
|
readWaveCorridorContext,
|
|
52
55
|
waveCorridorContextPath,
|
|
53
56
|
} from "./corridor.mjs";
|
|
57
|
+
import {
|
|
58
|
+
classifyClosureComplexity,
|
|
59
|
+
resolveClosureMode,
|
|
60
|
+
resolveClosurePolicyConfig,
|
|
61
|
+
} from "./closure-policy.mjs";
|
|
54
62
|
|
|
55
63
|
export function waveCoordinationLogPath(lanePaths, waveNumber) {
|
|
56
64
|
return path.join(lanePaths.coordinationDir, `wave-${waveNumber}.jsonl`);
|
|
@@ -717,12 +725,13 @@ export function buildWaveDerivedState({
|
|
|
717
725
|
componentPromotions: wave.componentPromotions,
|
|
718
726
|
runtimeAssignments,
|
|
719
727
|
});
|
|
728
|
+
const corridorSummary = readWaveCorridorContext(lanePaths, wave.wave);
|
|
720
729
|
const securitySummary = buildWaveSecuritySummary({
|
|
721
730
|
lanePaths,
|
|
722
731
|
wave,
|
|
723
732
|
attempt,
|
|
724
733
|
summariesByAgentId,
|
|
725
|
-
corridorSummary
|
|
734
|
+
corridorSummary,
|
|
726
735
|
});
|
|
727
736
|
const integrationSummary = buildWaveIntegrationSummary({
|
|
728
737
|
lanePaths,
|
|
@@ -737,6 +746,35 @@ export function buildWaveDerivedState({
|
|
|
737
746
|
dependencySnapshot,
|
|
738
747
|
securitySummary,
|
|
739
748
|
});
|
|
749
|
+
const closurePolicy = resolveClosurePolicyConfig(lanePaths);
|
|
750
|
+
const closureMode = resolveClosureMode(wave.wave, closurePolicy.closureModeThresholds);
|
|
751
|
+
const clarificationBarrier = readClarificationBarrier({
|
|
752
|
+
coordinationState,
|
|
753
|
+
});
|
|
754
|
+
const helperAssignmentBarrier = readWaveAssignmentBarrier(
|
|
755
|
+
{
|
|
756
|
+
capabilityAssignments,
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
gateMode: closureMode,
|
|
760
|
+
},
|
|
761
|
+
);
|
|
762
|
+
const dependencyBarrier = readWaveDependencyBarrier({
|
|
763
|
+
dependencySnapshot,
|
|
764
|
+
});
|
|
765
|
+
const closureComplexity = classifyClosureComplexity({
|
|
766
|
+
contradictions: coordinationState?.contradictions || [],
|
|
767
|
+
coordinationState,
|
|
768
|
+
docsQueue,
|
|
769
|
+
capabilityAssignments,
|
|
770
|
+
dependencySnapshot,
|
|
771
|
+
securitySummary,
|
|
772
|
+
corridorSummary,
|
|
773
|
+
integrationSummary,
|
|
774
|
+
clarificationBarrier,
|
|
775
|
+
helperAssignmentBarrier,
|
|
776
|
+
dependencyBarrier,
|
|
777
|
+
});
|
|
740
778
|
const ledger = deriveWaveLedger({
|
|
741
779
|
lane: lanePaths.lane,
|
|
742
780
|
wave,
|
|
@@ -802,12 +840,17 @@ export function buildWaveDerivedState({
|
|
|
802
840
|
dependencySnapshotMarkdownPath: waveDependencySnapshotMarkdownPath(lanePaths, wave.wave),
|
|
803
841
|
securitySummary,
|
|
804
842
|
securitySummaryPath: waveSecurityPath(lanePaths, wave.wave),
|
|
805
|
-
corridorSummary
|
|
843
|
+
corridorSummary,
|
|
806
844
|
corridorSummaryPath: waveCorridorContextPath(lanePaths, wave.wave),
|
|
807
845
|
integrationSummary,
|
|
808
846
|
integrationSummaryPath: waveIntegrationPath(lanePaths, wave.wave),
|
|
809
847
|
integrationMarkdownPath: waveIntegrationMarkdownPath(lanePaths, wave.wave),
|
|
810
848
|
securityMarkdownPath: waveSecurityMarkdownPath(lanePaths, wave.wave),
|
|
849
|
+
clarificationBarrier,
|
|
850
|
+
helperAssignmentBarrier,
|
|
851
|
+
dependencyBarrier,
|
|
852
|
+
closureMode,
|
|
853
|
+
closureComplexity,
|
|
811
854
|
ledger,
|
|
812
855
|
ledgerPath: waveLedgerPath(lanePaths, wave.wave),
|
|
813
856
|
responseMetrics,
|
|
@@ -53,6 +53,10 @@ import {
|
|
|
53
53
|
openClarificationLinkedRequests,
|
|
54
54
|
} from "./coordination-store.mjs";
|
|
55
55
|
import { contradictionsBlockingGate } from "./contradiction-entity.mjs";
|
|
56
|
+
import {
|
|
57
|
+
evaluateDocumentationAutoClosure,
|
|
58
|
+
evaluateInferredIntegrationClosure,
|
|
59
|
+
} from "./closure-policy.mjs";
|
|
56
60
|
|
|
57
61
|
function contradictionList(value) {
|
|
58
62
|
if (value instanceof Map) {
|
|
@@ -860,7 +864,21 @@ export function readWaveComponentMatrixGate(wave, agentRuns, options = {}) {
|
|
|
860
864
|
|
|
861
865
|
export function readWaveDocumentationGate(wave, agentRuns, options = {}) {
|
|
862
866
|
const mode = normalizeReadMode(options.mode || "live");
|
|
863
|
-
const documentationAgentId =
|
|
867
|
+
const documentationAgentId =
|
|
868
|
+
options.documentationAgentId || wave.documentationAgentId || "A9";
|
|
869
|
+
const autoClosure = evaluateDocumentationAutoClosure(options.derivedState, options, {
|
|
870
|
+
componentMatrixGate: options.componentMatrixGate,
|
|
871
|
+
});
|
|
872
|
+
if (autoClosure?.ok) {
|
|
873
|
+
return {
|
|
874
|
+
ok: true,
|
|
875
|
+
agentId: null,
|
|
876
|
+
statusCode: autoClosure.statusCode,
|
|
877
|
+
detail: autoClosure.detail,
|
|
878
|
+
logPath: null,
|
|
879
|
+
docClosureState: autoClosure.state,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
864
882
|
const docRun =
|
|
865
883
|
agentRuns.find((run) => run.agent.agentId === documentationAgentId) ?? null;
|
|
866
884
|
if (!docRun) {
|
|
@@ -1003,6 +1021,17 @@ export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
|
|
|
1003
1021
|
(options.requireIntegrationStewardFromWave !== null &&
|
|
1004
1022
|
options.requireIntegrationStewardFromWave !== undefined &&
|
|
1005
1023
|
wave.wave >= options.requireIntegrationStewardFromWave);
|
|
1024
|
+
const autoClosure = evaluateInferredIntegrationClosure(options.derivedState, options);
|
|
1025
|
+
if (autoClosure?.ok) {
|
|
1026
|
+
return {
|
|
1027
|
+
ok: true,
|
|
1028
|
+
agentId: null,
|
|
1029
|
+
statusCode: autoClosure.statusCode,
|
|
1030
|
+
detail: autoClosure.detail,
|
|
1031
|
+
logPath: null,
|
|
1032
|
+
integrationState: autoClosure.state,
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1006
1035
|
const integrationRun =
|
|
1007
1036
|
agentRuns.find((run) => run.agent.agentId === integrationAgentId) ?? null;
|
|
1008
1037
|
if (!integrationRun) {
|
|
@@ -1059,10 +1088,16 @@ export function readWaveIntegrationGate(wave, agentRuns, options = {}) {
|
|
|
1059
1088
|
}
|
|
1060
1089
|
|
|
1061
1090
|
export function readWaveIntegrationBarrier(wave, agentRuns, derivedState, options = {}) {
|
|
1062
|
-
const markerGate = readWaveIntegrationGate(wave, agentRuns,
|
|
1091
|
+
const markerGate = readWaveIntegrationGate(wave, agentRuns, {
|
|
1092
|
+
...options,
|
|
1093
|
+
derivedState,
|
|
1094
|
+
});
|
|
1063
1095
|
if (!markerGate.ok) {
|
|
1064
1096
|
return markerGate;
|
|
1065
1097
|
}
|
|
1098
|
+
if (!markerGate.agentId) {
|
|
1099
|
+
return markerGate;
|
|
1100
|
+
}
|
|
1066
1101
|
const integrationSummary = derivedState?.integrationSummary || null;
|
|
1067
1102
|
if (!integrationSummary) {
|
|
1068
1103
|
return {
|
|
@@ -1240,6 +1275,7 @@ export function buildGateSnapshot({
|
|
|
1240
1275
|
securityRolePromptPath: lanePaths?.securityRolePromptPath,
|
|
1241
1276
|
requireIntegrationStewardFromWave: lanePaths?.requireIntegrationStewardFromWave,
|
|
1242
1277
|
laneProfile: lanePaths?.laneProfile,
|
|
1278
|
+
autoClosure: lanePaths?.autoClosure,
|
|
1243
1279
|
benchmarkCatalogPath: lanePaths?.laneProfile?.paths?.benchmarkCatalogPath,
|
|
1244
1280
|
componentMatrixPayload,
|
|
1245
1281
|
componentMatrixJsonPath,
|
|
@@ -1446,6 +1482,19 @@ export function readWaveComponentMatrixGatePure(wave, agentResults, options = {}
|
|
|
1446
1482
|
|
|
1447
1483
|
export function readWaveDocumentationGatePure(wave, agentResults, options = {}) {
|
|
1448
1484
|
const documentationAgentId = options.documentationAgentId || wave.documentationAgentId || "A9";
|
|
1485
|
+
const autoClosure = evaluateDocumentationAutoClosure(options.derivedState, options, {
|
|
1486
|
+
componentMatrixGate: options.componentMatrixGate,
|
|
1487
|
+
});
|
|
1488
|
+
if (autoClosure?.ok) {
|
|
1489
|
+
return {
|
|
1490
|
+
ok: true,
|
|
1491
|
+
agentId: null,
|
|
1492
|
+
statusCode: autoClosure.statusCode,
|
|
1493
|
+
detail: autoClosure.detail,
|
|
1494
|
+
logPath: null,
|
|
1495
|
+
docClosureState: autoClosure.state,
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1449
1498
|
if (!waveDeclaresAgent(wave, documentationAgentId)) {
|
|
1450
1499
|
return { ok: true, agentId: null, statusCode: "pass",
|
|
1451
1500
|
detail: "No documentation steward declared for this wave.", logPath: null };
|
|
@@ -1507,6 +1556,17 @@ export function readWaveIntegrationGatePure(wave, agentResults, options = {}) {
|
|
|
1507
1556
|
const integrationAgentId = options.integrationAgentId || wave.integrationAgentId || "A8";
|
|
1508
1557
|
const requireIntegration = options.requireIntegrationSteward === true ||
|
|
1509
1558
|
(options.requireIntegrationStewardFromWave != null && wave.wave >= options.requireIntegrationStewardFromWave);
|
|
1559
|
+
const autoClosure = evaluateInferredIntegrationClosure(options.derivedState, options);
|
|
1560
|
+
if (autoClosure?.ok) {
|
|
1561
|
+
return {
|
|
1562
|
+
ok: true,
|
|
1563
|
+
agentId: null,
|
|
1564
|
+
statusCode: autoClosure.statusCode,
|
|
1565
|
+
detail: autoClosure.detail,
|
|
1566
|
+
logPath: null,
|
|
1567
|
+
integrationState: autoClosure.state,
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1510
1570
|
if (!waveDeclaresAgent(wave, integrationAgentId)) {
|
|
1511
1571
|
return {
|
|
1512
1572
|
ok: !requireIntegration,
|
|
@@ -1557,6 +1617,9 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
|
|
|
1557
1617
|
const integrationMarkerGate = readWaveIntegrationGatePure(wave, agentResults, {
|
|
1558
1618
|
integrationAgentId: laneConfig.integrationAgentId,
|
|
1559
1619
|
requireIntegrationStewardFromWave: laneConfig.requireIntegrationStewardFromWave,
|
|
1620
|
+
derivedState,
|
|
1621
|
+
laneProfile: laneConfig.laneProfile,
|
|
1622
|
+
autoClosure: laneConfig.autoClosure,
|
|
1560
1623
|
});
|
|
1561
1624
|
const integrationBarrier = (() => {
|
|
1562
1625
|
if (!integrationMarkerGate.ok) { return integrationMarkerGate; }
|
|
@@ -1585,12 +1648,17 @@ export function buildGateSnapshotPure({ wave, agentResults, derivedState, valida
|
|
|
1585
1648
|
}
|
|
1586
1649
|
return integrationMarkerGate;
|
|
1587
1650
|
})();
|
|
1588
|
-
const documentationGate = readWaveDocumentationGatePure(wave, agentResults, {
|
|
1589
|
-
documentationAgentId: laneConfig.documentationAgentId });
|
|
1590
1651
|
const componentMatrixGate = readWaveComponentMatrixGatePure(wave, agentResults, {
|
|
1591
1652
|
laneProfile: laneConfig.laneProfile, documentationAgentId: laneConfig.documentationAgentId,
|
|
1592
1653
|
componentMatrixPayload: laneConfig.componentMatrixPayload,
|
|
1593
1654
|
componentMatrixJsonPath: laneConfig.componentMatrixJsonPath });
|
|
1655
|
+
const documentationGate = readWaveDocumentationGatePure(wave, agentResults, {
|
|
1656
|
+
documentationAgentId: laneConfig.documentationAgentId,
|
|
1657
|
+
derivedState,
|
|
1658
|
+
laneProfile: laneConfig.laneProfile,
|
|
1659
|
+
autoClosure: laneConfig.autoClosure,
|
|
1660
|
+
componentMatrixGate,
|
|
1661
|
+
});
|
|
1594
1662
|
const contEvalGate = readWaveContEvalGatePure(wave, agentResults, {
|
|
1595
1663
|
contEvalAgentId: laneConfig.contEvalAgentId, mode: validationMode,
|
|
1596
1664
|
evalTargets: wave.evalTargets, benchmarkCatalogPath: laneConfig.benchmarkCatalogPath });
|
|
@@ -69,7 +69,7 @@ export const STARTER_TEMPLATE_PATHS = [
|
|
|
69
69
|
"docs/guides/author-and-run-waves.md",
|
|
70
70
|
"docs/guides/monorepo-projects.md",
|
|
71
71
|
"docs/guides/planner.md",
|
|
72
|
-
"docs/guides/recommendations-0.9.
|
|
72
|
+
"docs/guides/recommendations-0.9.12.md",
|
|
73
73
|
"docs/guides/sandboxed-environments.md",
|
|
74
74
|
"docs/guides/signal-wrappers.md",
|
|
75
75
|
"docs/guides/terminal-surfaces.md",
|
|
@@ -265,9 +265,9 @@ Options:
|
|
|
265
265
|
--dry-run Parse waves and update manifest only
|
|
266
266
|
--terminal-surface <mode>
|
|
267
267
|
Terminal surface: ${TERMINAL_SURFACES.join(" | ")} (default: ${terminalSurface})
|
|
268
|
-
--no-dashboard Disable per-wave
|
|
269
|
-
--cleanup-sessions
|
|
270
|
-
--keep-sessions Keep lane tmux sessions after each wave
|
|
268
|
+
--no-dashboard Disable the per-wave dashboard projection session
|
|
269
|
+
--cleanup-sessions Clean up lane tmux dashboard/projection sessions after each wave (default: on)
|
|
270
|
+
--keep-sessions Keep lane tmux dashboard/projection sessions after each wave
|
|
271
271
|
--keep-terminals Do not remove temporary terminal entries after each wave
|
|
272
272
|
--orchestrator-id <id> Stable orchestrator identity for cross-lane coordination
|
|
273
273
|
--orchestrator-board <path>
|
|
@@ -477,6 +477,15 @@ function parseArgs(argv) {
|
|
|
477
477
|
return { help: false, lanePaths, options, config };
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
function maybePrintOptionalTmuxNote(options) {
|
|
481
|
+
if (options.dryRun || options.terminalSurface !== "tmux" || options.dashboard) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
console.log(
|
|
485
|
+
"[terminal-surface] tmux is optional here: live agents still run as detached processes, and tmux only affects dashboard/projection attach when dashboards are enabled.",
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
480
489
|
// --- Local wrappers that bind engine calls to launcher scope ---
|
|
481
490
|
|
|
482
491
|
async function runClosureSweepPhase({
|
|
@@ -1062,11 +1071,12 @@ export async function runLauncherCli(argv) {
|
|
|
1062
1071
|
console.log(
|
|
1063
1072
|
`[dry-run] prompts and executor overlays written: ${path.relative(REPO_ROOT, lanePaths.executorOverlaysDir)}`,
|
|
1064
1073
|
);
|
|
1065
|
-
console.log("Dry run enabled, skipping
|
|
1074
|
+
console.log("Dry run enabled, skipping live execution and optional dashboard/projection launch.");
|
|
1066
1075
|
return;
|
|
1067
1076
|
}
|
|
1068
1077
|
|
|
1069
1078
|
preflightWavesForExecutorAvailability(filteredWaves, lanePaths);
|
|
1079
|
+
maybePrintOptionalTmuxNote(options);
|
|
1070
1080
|
const terminalRegistryEnabled = terminalSurfaceUsesTerminalRegistry(
|
|
1071
1081
|
options.terminalSurface,
|
|
1072
1082
|
);
|
|
@@ -2944,9 +2944,10 @@ async function runProjectSetupFlow(options = {}) {
|
|
|
2944
2944
|
),
|
|
2945
2945
|
);
|
|
2946
2946
|
|
|
2947
|
-
prompt.describe("\nHow do you want to
|
|
2948
|
-
prompt.describe("
|
|
2949
|
-
prompt.describe("
|
|
2947
|
+
prompt.describe("\nHow do you want to follow live runs?");
|
|
2948
|
+
prompt.describe("Live agent execution stays process-backed either way; this only changes the operator surface.");
|
|
2949
|
+
prompt.describe(" vscode — VS Code gets temporary terminal entries for agent logs and dashboards");
|
|
2950
|
+
prompt.describe(" tmux — terminal-native dashboard and projection surface with no VS Code integration");
|
|
2950
2951
|
const defaultTerminalSurface = normalizeTerminalSurface(
|
|
2951
2952
|
await prompt.askChoice(
|
|
2952
2953
|
"Default terminal surface",
|
|
@@ -277,6 +277,8 @@ export function buildLanePaths(laneInput = DEFAULT_WAVE_LANE, options = {}) {
|
|
|
277
277
|
laneProfile.validation.requireComponentPromotionsFromWave,
|
|
278
278
|
requireAgentComponentsFromWave: laneProfile.validation.requireAgentComponentsFromWave,
|
|
279
279
|
gateModeThresholds: laneProfile.validation.gateModeThresholds,
|
|
280
|
+
closureModeThresholds: laneProfile.validation.closureModeThresholds,
|
|
281
|
+
autoClosure: laneProfile.validation.autoClosure,
|
|
280
282
|
executors: laneProfile.executors,
|
|
281
283
|
skills: laneProfile.skills,
|
|
282
284
|
capabilityRouting: laneProfile.capabilityRouting,
|
|
@@ -428,9 +430,6 @@ export function normalizeWaveVerdict(verdict) {
|
|
|
428
430
|
const normalized = String(verdict || "")
|
|
429
431
|
.trim()
|
|
430
432
|
.toLowerCase();
|
|
431
|
-
if (normalized === "hold") {
|
|
432
|
-
return "concerns";
|
|
433
|
-
}
|
|
434
433
|
if (normalized === "fail") {
|
|
435
434
|
return "blocked";
|
|
436
435
|
}
|
|
@@ -796,7 +796,7 @@ function buildFullWaveSolve(row, taskWorkspace, options) {
|
|
|
796
796
|
});
|
|
797
797
|
assertSuccess(doctor, "wave doctor");
|
|
798
798
|
const launch = runShellCommand(
|
|
799
|
-
`node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard
|
|
799
|
+
`node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard`,
|
|
800
800
|
{
|
|
801
801
|
cwd: taskWorkspace.repoDir,
|
|
802
802
|
timeoutMs: options.maxWallClockMinutes * 60 * 1000,
|