@chllming/wave-orchestration 0.9.11 → 0.9.13

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +7 -8
  3. package/docs/README.md +4 -10
  4. package/docs/architecture/README.md +12 -4
  5. package/docs/concepts/operating-modes.md +1 -1
  6. package/docs/guides/author-and-run-waves.md +3 -2
  7. package/docs/guides/planner.md +3 -3
  8. package/docs/guides/recommendations-0.9.13.md +49 -0
  9. package/docs/guides/sandboxed-environments.md +2 -2
  10. package/docs/guides/terminal-surfaces.md +1 -1
  11. package/docs/plans/current-state.md +3 -3
  12. package/docs/plans/end-state-architecture.md +1 -1
  13. package/docs/plans/examples/wave-example-design-handoff.md +1 -1
  14. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  15. package/docs/plans/migration.md +31 -28
  16. package/docs/plans/wave-orchestrator.md +1 -1
  17. package/docs/reference/cli-reference.md +2 -2
  18. package/docs/reference/coordination-and-closure.md +1 -1
  19. package/docs/reference/npmjs-token-publishing.md +3 -3
  20. package/docs/reference/package-publishing-flow.md +12 -12
  21. package/docs/reference/runtime-config/README.md +2 -2
  22. package/docs/reference/sample-waves.md +5 -5
  23. package/docs/reference/skills.md +1 -1
  24. package/docs/reference/wave-control.md +3 -1
  25. package/docs/roadmap.md +3 -3
  26. package/package.json +8 -9
  27. package/releases/manifest.json +50 -0
  28. package/scripts/context7-api-check.sh +0 -0
  29. package/scripts/context7-export-env.sh +0 -0
  30. package/scripts/wave-autonomous.mjs +0 -0
  31. package/scripts/wave-dashboard.mjs +0 -0
  32. package/scripts/wave-human-feedback.mjs +0 -0
  33. package/scripts/wave-launcher.mjs +0 -0
  34. package/scripts/wave-local-executor.mjs +0 -0
  35. package/scripts/wave-orchestrator/agent-process-runner.mjs +24 -0
  36. package/scripts/wave-orchestrator/agent-state.mjs +4 -4
  37. package/scripts/wave-orchestrator/autonomous.mjs +2 -2
  38. package/scripts/wave-orchestrator/closure-engine.mjs +103 -6
  39. package/scripts/wave-orchestrator/closure-policy.mjs +319 -0
  40. package/scripts/wave-orchestrator/config.mjs +15 -0
  41. package/scripts/wave-orchestrator/coordination.mjs +2 -2
  42. package/scripts/wave-orchestrator/derived-state-engine.mjs +45 -2
  43. package/scripts/wave-orchestrator/executors.mjs +2 -1
  44. package/scripts/wave-orchestrator/gate-engine.mjs +72 -4
  45. package/scripts/wave-orchestrator/install.mjs +1 -1
  46. package/scripts/wave-orchestrator/launcher.mjs +44 -7
  47. package/scripts/wave-orchestrator/planner.mjs +4 -3
  48. package/scripts/wave-orchestrator/shared.mjs +2 -3
  49. package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1 -1
  50. package/scripts/wave-orchestrator/traces.mjs +22 -1
  51. package/scripts/wave-orchestrator/wave-files.mjs +14 -3
  52. package/scripts/wave-status.sh +0 -0
  53. package/scripts/wave-watch.sh +0 -0
  54. package/scripts/wave.mjs +0 -0
  55. 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,
@@ -319,11 +319,11 @@ export function buildExecutionPrompt({
319
319
  !isSecurityReviewAgent(agent) &&
320
320
  (agent.agentId !== contEvalAgentId || contEvalImplementationOwning)
321
321
  ? [
322
- "- Emit one final structured proof marker: `[wave-proof] completion=<contract|integrated|authoritative|live> durability=<none|ephemeral|durable> proof=<unit|integration|live> state=<met|gap> detail=<short-note>`.",
322
+ "- Emit one final structured proof marker: `[wave-proof] completion=<contract|integrated|authoritative|live> durability=<none|ephemeral|durable> proof=<unit|integration|live> state=<met|complete|gap> detail=<short-note>`. Use `met` or `complete` when proof is satisfied; use `gap` only when proof cannot be produced.",
323
323
  "- Emit one final structured documentation marker: `[wave-doc-delta] state=<none|owned|shared-plan> paths=<comma-separated-paths> detail=<short-note>`.",
324
324
  ...(Array.isArray(agent.components) && agent.components.length > 0
325
325
  ? [
326
- "- Emit one final structured component marker per owned component: `[wave-component] component=<id> level=<level> state=<met|gap> detail=<short-note>`.",
326
+ "- Emit one final structured component marker per owned component: `[wave-component] component=<id> level=<level> state=<met|complete|gap> detail=<short-note>`. Use `met` or `complete` when proof is satisfied; use `gap` only when proof cannot be produced.",
327
327
  ]
328
328
  : []),
329
329
  "- If the work is incomplete, keep the required proof/doc/component markers and set `state=gap` on the relevant final marker instead of narrating completion.",
@@ -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: readWaveCorridorContext(lanePaths, wave.wave),
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: readWaveCorridorContext(lanePaths, wave.wave),
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,
@@ -185,8 +185,9 @@ export function buildCodexExecInvocation(
185
185
  ) {
186
186
  const tokens = [
187
187
  command,
188
- "--ask-for-approval never",
188
+
189
189
  "exec",
190
+ "--dangerously-bypass-approvals-and-sandbox",
190
191
  "--skip-git-repo-check",
191
192
  `--sandbox ${shellQuote(codexSandboxMode || DEFAULT_CODEX_SANDBOX_MODE)}`,
192
193
  ];
@@ -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 = wave.documentationAgentId || "A9";
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, options);
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.7.md",
72
+ "docs/guides/recommendations-0.9.13.md",
73
73
  "docs/guides/sandboxed-environments.md",
74
74
  "docs/guides/signal-wrappers.md",
75
75
  "docs/guides/terminal-surfaces.md",