@chllming/wave-orchestration 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -1
- package/README.md +60 -11
- package/docs/README.md +8 -2
- package/docs/agents/wave-design-role.md +47 -0
- package/docs/concepts/what-is-a-wave.md +11 -7
- package/docs/guides/author-and-run-waves.md +24 -0
- package/docs/guides/planner.md +44 -0
- package/docs/plans/architecture-hardening-migration.md +8 -1
- package/docs/plans/current-state.md +19 -7
- package/docs/plans/end-state-architecture.md +88 -70
- package/docs/plans/examples/wave-example-design-handoff.md +262 -0
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +370 -64
- package/docs/plans/wave-orchestrator.md +49 -13
- package/docs/reference/cli-reference.md +46 -14
- package/docs/reference/coordination-and-closure.md +19 -6
- package/docs/reference/npmjs-trusted-publishing.md +5 -4
- package/docs/reference/sample-waves.md +14 -7
- package/docs/reference/skills.md +10 -0
- package/package.json +1 -1
- package/releases/manifest.json +39 -0
- package/scripts/wave-orchestrator/agent-state.mjs +64 -491
- package/scripts/wave-orchestrator/autonomous.mjs +10 -6
- package/scripts/wave-orchestrator/{launcher-closure.mjs → closure-engine.mjs} +190 -74
- package/scripts/wave-orchestrator/config.mjs +5 -0
- package/scripts/wave-orchestrator/coordination.mjs +42 -1
- package/scripts/wave-orchestrator/{launcher-derived-state.mjs → derived-state-engine.mjs} +34 -146
- package/scripts/wave-orchestrator/{launcher-gates.mjs → gate-engine.mjs} +501 -141
- package/scripts/wave-orchestrator/human-input-resolution.mjs +14 -10
- package/scripts/wave-orchestrator/human-input-workflow.mjs +104 -0
- package/scripts/wave-orchestrator/implementation-engine.mjs +120 -0
- package/scripts/wave-orchestrator/install.mjs +3 -0
- package/scripts/wave-orchestrator/launcher-runtime.mjs +11 -6
- package/scripts/wave-orchestrator/launcher.mjs +324 -723
- package/scripts/wave-orchestrator/ledger.mjs +56 -27
- package/scripts/wave-orchestrator/local-executor.mjs +37 -0
- package/scripts/wave-orchestrator/planner.mjs +24 -4
- package/scripts/wave-orchestrator/projection-writer.mjs +256 -0
- package/scripts/wave-orchestrator/reconcile-format.mjs +32 -0
- package/scripts/wave-orchestrator/reducer-snapshot.mjs +297 -0
- package/scripts/wave-orchestrator/replay.mjs +3 -1
- package/scripts/wave-orchestrator/result-envelope.mjs +620 -0
- package/scripts/wave-orchestrator/retry-control.mjs +22 -2
- package/scripts/wave-orchestrator/{launcher-retry.mjs → retry-engine.mjs} +352 -18
- package/scripts/wave-orchestrator/role-helpers.mjs +124 -1
- package/scripts/wave-orchestrator/{launcher-supervisor.mjs → session-supervisor.mjs} +178 -103
- package/scripts/wave-orchestrator/shared.mjs +2 -0
- package/scripts/wave-orchestrator/skills.mjs +1 -0
- package/scripts/wave-orchestrator/task-entity.mjs +65 -45
- package/scripts/wave-orchestrator/traces.mjs +10 -1
- package/scripts/wave-orchestrator/wave-files.mjs +96 -10
- package/scripts/wave-orchestrator/wave-state-reducer.mjs +76 -12
- package/skills/README.md +7 -0
- package/skills/role-design/SKILL.md +50 -0
- package/skills/role-design/skill.json +36 -0
- package/skills/tui-design/SKILL.md +77 -0
- package/skills/tui-design/references/tui-design.md +259 -0
- package/skills/tui-design/skill.json +36 -0
- package/wave.config.json +15 -1
|
@@ -5,8 +5,17 @@ import {
|
|
|
5
5
|
setWaveDashboardAgent,
|
|
6
6
|
updateWaveDashboardMessageBoard,
|
|
7
7
|
} from "./dashboard-state.mjs";
|
|
8
|
+
import {
|
|
9
|
+
materializeAgentExecutionSummaryForRun as materializeAgentExecutionSummaryForRunDefault,
|
|
10
|
+
readWaveComponentMatrixGate as readWaveComponentMatrixGateDefault,
|
|
11
|
+
readWaveContEvalGate as readWaveContEvalGateDefault,
|
|
12
|
+
readWaveContQaGate as readWaveContQaGateDefault,
|
|
13
|
+
readWaveDocumentationGate as readWaveDocumentationGateDefault,
|
|
14
|
+
readWaveIntegrationBarrier as readWaveIntegrationBarrierDefault,
|
|
15
|
+
readWaveSecurityGate as readWaveSecurityGateDefault,
|
|
16
|
+
} from "./gate-engine.mjs";
|
|
8
17
|
import { REPO_ROOT, toIsoTimestamp } from "./shared.mjs";
|
|
9
|
-
import { isSecurityReviewAgent } from "./role-helpers.mjs";
|
|
18
|
+
import { isSecurityReviewAgent, resolveWaveRoleBindings } from "./role-helpers.mjs";
|
|
10
19
|
import { summarizeResolvedSkills } from "./skills.mjs";
|
|
11
20
|
|
|
12
21
|
function failureResultFromGate(gate, fallbackLogPath) {
|
|
@@ -71,76 +80,41 @@ export async function runClosureSweepPhase({
|
|
|
71
80
|
materializeAgentExecutionSummaryForRunFn,
|
|
72
81
|
monitorWaveHumanFeedbackFn,
|
|
73
82
|
}) {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
refreshDerivedState?.(dashboardState?.attempt || 0),
|
|
110
|
-
{
|
|
111
|
-
integrationAgentId,
|
|
112
|
-
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
113
|
-
},
|
|
114
|
-
),
|
|
115
|
-
actionRequested:
|
|
116
|
-
`Lane ${lanePaths.lane} owners should resolve integration contradictions or blockers before documentation and cont-QA closure.`,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
agentId: documentationAgentId,
|
|
120
|
-
label: "Documentation closure",
|
|
121
|
-
runs: closureRuns.filter((run) => run.agent.agentId === documentationAgentId),
|
|
122
|
-
validate: () => {
|
|
123
|
-
const documentationGate = readWaveDocumentationGateFn(wave, closureRuns);
|
|
124
|
-
if (!documentationGate.ok) {
|
|
125
|
-
return documentationGate;
|
|
126
|
-
}
|
|
127
|
-
return readWaveComponentMatrixGateFn(wave, closureRuns, {
|
|
128
|
-
laneProfile: lanePaths.laneProfile,
|
|
129
|
-
documentationAgentId,
|
|
130
|
-
});
|
|
131
|
-
},
|
|
132
|
-
actionRequested:
|
|
133
|
-
`Lane ${lanePaths.lane} owners should resolve the shared-plan or component-matrix closure state before cont-QA progression.`,
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
agentId: contQaAgentId,
|
|
137
|
-
label: "cont-QA gate",
|
|
138
|
-
runs: closureRuns.filter((run) => run.agent.agentId === contQaAgentId),
|
|
139
|
-
validate: () => readWaveContQaGateFn(wave, closureRuns, { contQaAgentId, mode: "live" }),
|
|
140
|
-
actionRequested:
|
|
141
|
-
`Lane ${lanePaths.lane} owners should resolve the cont-QA gate before wave progression.`,
|
|
142
|
-
},
|
|
143
|
-
];
|
|
83
|
+
const materializeSummary =
|
|
84
|
+
typeof materializeAgentExecutionSummaryForRunFn === "function"
|
|
85
|
+
? materializeAgentExecutionSummaryForRunFn
|
|
86
|
+
: materializeAgentExecutionSummaryForRunDefault;
|
|
87
|
+
const monitorHumanFeedback =
|
|
88
|
+
typeof monitorWaveHumanFeedbackFn === "function"
|
|
89
|
+
? monitorWaveHumanFeedbackFn
|
|
90
|
+
: () => false;
|
|
91
|
+
const readContEvalGate =
|
|
92
|
+
typeof readWaveContEvalGateFn === "function"
|
|
93
|
+
? readWaveContEvalGateFn
|
|
94
|
+
: readWaveContEvalGateDefault;
|
|
95
|
+
const readSecurityGate =
|
|
96
|
+
typeof readWaveSecurityGateFn === "function"
|
|
97
|
+
? readWaveSecurityGateFn
|
|
98
|
+
: readWaveSecurityGateDefault;
|
|
99
|
+
const readIntegrationBarrier =
|
|
100
|
+
typeof readWaveIntegrationBarrierFn === "function"
|
|
101
|
+
? readWaveIntegrationBarrierFn
|
|
102
|
+
: readWaveIntegrationBarrierDefault;
|
|
103
|
+
const readDocumentationGate =
|
|
104
|
+
typeof readWaveDocumentationGateFn === "function"
|
|
105
|
+
? readWaveDocumentationGateFn
|
|
106
|
+
: readWaveDocumentationGateDefault;
|
|
107
|
+
const readComponentMatrixGate =
|
|
108
|
+
typeof readWaveComponentMatrixGateFn === "function"
|
|
109
|
+
? readWaveComponentMatrixGateFn
|
|
110
|
+
: readWaveComponentMatrixGateDefault;
|
|
111
|
+
const readContQaGate =
|
|
112
|
+
typeof readWaveContQaGateFn === "function"
|
|
113
|
+
? readWaveContQaGateFn
|
|
114
|
+
: readWaveContQaGateDefault;
|
|
115
|
+
const stagedRuns = planClosureStages({ lanePaths, wave, closureRuns });
|
|
116
|
+
const { contQaAgentId, contEvalAgentId, integrationAgentId, documentationAgentId } =
|
|
117
|
+
resolveWaveRoleBindings(wave, lanePaths);
|
|
144
118
|
for (const stage of stagedRuns) {
|
|
145
119
|
if (stage.runs.length === 0) {
|
|
146
120
|
continue;
|
|
@@ -177,6 +151,11 @@ export async function runClosureSweepPhase({
|
|
|
177
151
|
agentRateLimitBaseDelaySeconds: options.agentRateLimitBaseDelaySeconds,
|
|
178
152
|
agentRateLimitMaxDelaySeconds: options.agentRateLimitMaxDelaySeconds,
|
|
179
153
|
context7Enabled: options.context7Enabled,
|
|
154
|
+
attempt: dashboardState?.attempt || 1,
|
|
155
|
+
controlPlane: {
|
|
156
|
+
waveNumber: wave.wave,
|
|
157
|
+
attempt: dashboardState?.attempt || 1,
|
|
158
|
+
},
|
|
180
159
|
});
|
|
181
160
|
runInfo.lastLaunchAttempt = dashboardState?.attempt || null;
|
|
182
161
|
runInfo.lastPromptHash = launchResult?.promptHash || null;
|
|
@@ -201,7 +180,7 @@ export async function runClosureSweepPhase({
|
|
|
201
180
|
refreshWaveDashboardAgentStates(dashboardState, [runInfo], pendingAgentIds, (event) =>
|
|
202
181
|
recordCombinedEvent(event),
|
|
203
182
|
);
|
|
204
|
-
const feedbackChanged =
|
|
183
|
+
const feedbackChanged = monitorHumanFeedback({
|
|
205
184
|
lanePaths,
|
|
206
185
|
waveNumber: wave.wave,
|
|
207
186
|
agentRuns: [runInfo],
|
|
@@ -217,14 +196,37 @@ export async function runClosureSweepPhase({
|
|
|
217
196
|
updateWaveDashboardMessageBoard(dashboardState, runInfo.messageBoardPath);
|
|
218
197
|
flushDashboards();
|
|
219
198
|
},
|
|
199
|
+
{
|
|
200
|
+
controlPlane: {
|
|
201
|
+
waveNumber: wave.wave,
|
|
202
|
+
attempt: dashboardState?.attempt || 1,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
220
205
|
);
|
|
221
|
-
|
|
206
|
+
materializeSummary(wave, runInfo);
|
|
222
207
|
refreshDerivedState?.(dashboardState?.attempt || 0);
|
|
223
208
|
if (result.failures.length > 0) {
|
|
224
209
|
return result;
|
|
225
210
|
}
|
|
226
211
|
}
|
|
227
|
-
const gate =
|
|
212
|
+
const gate = evaluateClosureStage({
|
|
213
|
+
stage,
|
|
214
|
+
wave,
|
|
215
|
+
closureRuns,
|
|
216
|
+
lanePaths,
|
|
217
|
+
dashboardState,
|
|
218
|
+
refreshDerivedState,
|
|
219
|
+
readWaveContEvalGateFn: readContEvalGate,
|
|
220
|
+
readWaveSecurityGateFn: readSecurityGate,
|
|
221
|
+
readWaveIntegrationBarrierFn: readIntegrationBarrier,
|
|
222
|
+
readWaveDocumentationGateFn: readDocumentationGate,
|
|
223
|
+
readWaveComponentMatrixGateFn: readComponentMatrixGate,
|
|
224
|
+
readWaveContQaGateFn: readContQaGate,
|
|
225
|
+
contEvalAgentId,
|
|
226
|
+
integrationAgentId,
|
|
227
|
+
documentationAgentId,
|
|
228
|
+
contQaAgentId,
|
|
229
|
+
});
|
|
228
230
|
if (!gate.ok) {
|
|
229
231
|
recordClosureGateFailure({
|
|
230
232
|
wave,
|
|
@@ -244,6 +246,120 @@ export async function runClosureSweepPhase({
|
|
|
244
246
|
return { failures: [], timedOut: false };
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
export function planClosureStages({ lanePaths, wave, closureRuns }) {
|
|
250
|
+
const { contQaAgentId, contEvalAgentId, integrationAgentId, documentationAgentId } =
|
|
251
|
+
resolveWaveRoleBindings(wave, lanePaths);
|
|
252
|
+
return [
|
|
253
|
+
{
|
|
254
|
+
key: "cont-eval",
|
|
255
|
+
agentId: contEvalAgentId,
|
|
256
|
+
label: "cont-EVAL gate",
|
|
257
|
+
runs: closureRuns.filter((run) => run.agent.agentId === contEvalAgentId),
|
|
258
|
+
actionRequested:
|
|
259
|
+
`Lane ${lanePaths.lane} owners should resolve cont-EVAL tuning gaps before integration closure.`,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "security-review",
|
|
263
|
+
agentId: "security",
|
|
264
|
+
label: "Security review",
|
|
265
|
+
runs: closureRuns.filter((run) => isSecurityReviewAgent(run.agent)),
|
|
266
|
+
actionRequested:
|
|
267
|
+
`Lane ${lanePaths.lane} owners should resolve blocked security findings or missing approvals before integration closure.`,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
key: "integration",
|
|
271
|
+
agentId: integrationAgentId,
|
|
272
|
+
label: "Integration gate",
|
|
273
|
+
runs: closureRuns.filter((run) => run.agent.agentId === integrationAgentId),
|
|
274
|
+
actionRequested:
|
|
275
|
+
`Lane ${lanePaths.lane} owners should resolve integration contradictions or blockers before documentation and cont-QA closure.`,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
key: "documentation",
|
|
279
|
+
agentId: documentationAgentId,
|
|
280
|
+
label: "Documentation closure",
|
|
281
|
+
runs: closureRuns.filter((run) => run.agent.agentId === documentationAgentId),
|
|
282
|
+
actionRequested:
|
|
283
|
+
`Lane ${lanePaths.lane} owners should resolve the shared-plan or component-matrix closure state before cont-QA progression.`,
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
key: "cont-qa",
|
|
287
|
+
agentId: contQaAgentId,
|
|
288
|
+
label: "cont-QA gate",
|
|
289
|
+
runs: closureRuns.filter((run) => run.agent.agentId === contQaAgentId),
|
|
290
|
+
actionRequested:
|
|
291
|
+
`Lane ${lanePaths.lane} owners should resolve the cont-QA gate before wave progression.`,
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function evaluateClosureStage({
|
|
297
|
+
stage,
|
|
298
|
+
wave,
|
|
299
|
+
closureRuns,
|
|
300
|
+
lanePaths,
|
|
301
|
+
dashboardState,
|
|
302
|
+
refreshDerivedState,
|
|
303
|
+
readWaveContEvalGateFn,
|
|
304
|
+
readWaveSecurityGateFn,
|
|
305
|
+
readWaveIntegrationBarrierFn,
|
|
306
|
+
readWaveDocumentationGateFn,
|
|
307
|
+
readWaveComponentMatrixGateFn,
|
|
308
|
+
readWaveContQaGateFn,
|
|
309
|
+
contEvalAgentId,
|
|
310
|
+
integrationAgentId,
|
|
311
|
+
documentationAgentId,
|
|
312
|
+
contQaAgentId,
|
|
313
|
+
}) {
|
|
314
|
+
switch (stage.key) {
|
|
315
|
+
case "cont-eval":
|
|
316
|
+
return readWaveContEvalGateFn(wave, closureRuns, {
|
|
317
|
+
contEvalAgentId,
|
|
318
|
+
mode: "live",
|
|
319
|
+
evalTargets: wave.evalTargets,
|
|
320
|
+
benchmarkCatalogPath: lanePaths.laneProfile?.paths?.benchmarkCatalogPath,
|
|
321
|
+
});
|
|
322
|
+
case "security-review":
|
|
323
|
+
return readWaveSecurityGateFn(wave, closureRuns, { mode: "live" });
|
|
324
|
+
case "integration":
|
|
325
|
+
return readWaveIntegrationBarrierFn(
|
|
326
|
+
wave,
|
|
327
|
+
closureRuns,
|
|
328
|
+
refreshDerivedState?.(dashboardState?.attempt || 0),
|
|
329
|
+
{
|
|
330
|
+
integrationAgentId,
|
|
331
|
+
mode: "live",
|
|
332
|
+
requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave,
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
case "documentation": {
|
|
336
|
+
const documentationGate = readWaveDocumentationGateFn(wave, closureRuns, {
|
|
337
|
+
mode: "live",
|
|
338
|
+
});
|
|
339
|
+
if (!documentationGate.ok) {
|
|
340
|
+
return documentationGate;
|
|
341
|
+
}
|
|
342
|
+
return readWaveComponentMatrixGateFn(wave, closureRuns, {
|
|
343
|
+
laneProfile: lanePaths.laneProfile,
|
|
344
|
+
documentationAgentId,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
case "cont-qa":
|
|
348
|
+
return readWaveContQaGateFn(wave, closureRuns, {
|
|
349
|
+
contQaAgentId,
|
|
350
|
+
mode: "live",
|
|
351
|
+
});
|
|
352
|
+
default:
|
|
353
|
+
return {
|
|
354
|
+
ok: true,
|
|
355
|
+
agentId: null,
|
|
356
|
+
statusCode: "pass",
|
|
357
|
+
detail: "No closure stage configured.",
|
|
358
|
+
logPath: null,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
247
363
|
const NON_BLOCKING_INFRA_SIGNAL_STATES = new Set([
|
|
248
364
|
"conformant",
|
|
249
365
|
"setup-required",
|
|
@@ -28,6 +28,7 @@ export const DEFAULT_INTEGRATION_ROLE_PROMPT_PATH = "docs/agents/wave-integratio
|
|
|
28
28
|
export const DEFAULT_DOCUMENTATION_ROLE_PROMPT_PATH =
|
|
29
29
|
"docs/agents/wave-documentation-role.md";
|
|
30
30
|
export const DEFAULT_SECURITY_ROLE_PROMPT_PATH = "docs/agents/wave-security-role.md";
|
|
31
|
+
export const DEFAULT_DESIGN_ROLE_PROMPT_PATH = "docs/agents/wave-design-role.md";
|
|
31
32
|
export const DEFAULT_TERMINALS_PATH = ".vscode/terminals.json";
|
|
32
33
|
export const DEFAULT_DOCS_DIR = "docs";
|
|
33
34
|
export const DEFAULT_STATE_ROOT = ".tmp";
|
|
@@ -348,6 +349,10 @@ function normalizeRoles(rawRoles = {}) {
|
|
|
348
349
|
rawRoles.securityRolePromptPath || DEFAULT_SECURITY_ROLE_PROMPT_PATH,
|
|
349
350
|
"roles.securityRolePromptPath",
|
|
350
351
|
),
|
|
352
|
+
designRolePromptPath: normalizeRepoRelativePath(
|
|
353
|
+
rawRoles.designRolePromptPath || DEFAULT_DESIGN_ROLE_PROMPT_PATH,
|
|
354
|
+
"roles.designRolePromptPath",
|
|
355
|
+
),
|
|
351
356
|
};
|
|
352
357
|
}
|
|
353
358
|
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
import { resolveEvalTargetsAgainstCatalog } from "./evals.mjs";
|
|
18
18
|
import {
|
|
19
19
|
isContEvalImplementationOwningAgent,
|
|
20
|
+
isDesignAgent,
|
|
21
|
+
isImplementationOwningDesignAgent,
|
|
20
22
|
isSecurityReviewAgent,
|
|
21
23
|
} from "./role-helpers.mjs";
|
|
22
24
|
|
|
@@ -199,6 +201,8 @@ export function buildExecutionPrompt({
|
|
|
199
201
|
evalTargets = null,
|
|
200
202
|
benchmarkCatalogPath = null,
|
|
201
203
|
sharedPlanDocs = null,
|
|
204
|
+
designPacketPaths = null,
|
|
205
|
+
designExecutionMode = null,
|
|
202
206
|
contQaAgentId = "A0",
|
|
203
207
|
contEvalAgentId = "E0",
|
|
204
208
|
integrationAgentId = "A8",
|
|
@@ -222,6 +226,10 @@ export function buildExecutionPrompt({
|
|
|
222
226
|
const contEvalImplementationOwning = isContEvalImplementationOwningAgent(agent, {
|
|
223
227
|
contEvalAgentId,
|
|
224
228
|
});
|
|
229
|
+
const hybridDesignAgent = isImplementationOwningDesignAgent(agent);
|
|
230
|
+
const designAgent = isDesignAgent(agent);
|
|
231
|
+
const designImplementationPass = designAgent && hybridDesignAgent && designExecutionMode === "implementation-pass";
|
|
232
|
+
const designPacketPass = designAgent && !designImplementationPass;
|
|
225
233
|
const resolvedEvalTargets = (() => {
|
|
226
234
|
try {
|
|
227
235
|
return resolveEvalTargetsAgainstCatalog(evalTargets, { benchmarkCatalogPath }).targets;
|
|
@@ -269,6 +277,22 @@ export function buildExecutionPrompt({
|
|
|
269
277
|
"- Use `clear` only when no unresolved findings or approvals remain. Use `blocked` only when the wave must stop before integration.",
|
|
270
278
|
]
|
|
271
279
|
: [];
|
|
280
|
+
const designRequirements = designAgent
|
|
281
|
+
? [
|
|
282
|
+
designImplementationPass
|
|
283
|
+
? "- You are in the hybrid design steward's implementation follow-through pass. Keep the design packet current, implement only your explicit owned paths, and finish with both `[wave-design]` and the normal implementation proof markers."
|
|
284
|
+
: "- You are the wave's design steward. Stay packet-first and docs/spec-owned unless the wave explicitly assigns more.",
|
|
285
|
+
"- Leave one design packet with these sections in order: `Problem`, `Constraints`, `Decisions`, `Assumptions`, `Open Questions`, `Interface Impacts`, `Validation Plan`, `Implementation Handoff`.",
|
|
286
|
+
"- Emit one final structured design marker: `[wave-design] state=<ready-for-implementation|needs-clarification|blocked> decisions=<n> assumptions=<n> open_questions=<n> detail=<short-note>`.",
|
|
287
|
+
"- Use `ready-for-implementation` only when downstream implementation owners can start without unresolved design ambiguity.",
|
|
288
|
+
"- Use `needs-clarification` when the wave should stop for a specific question or decision before coding starts.",
|
|
289
|
+
...(hybridDesignAgent && !designImplementationPass
|
|
290
|
+
? [
|
|
291
|
+
"- This wave also assigns you explicit implementation-owned files, but this first pass is still design-only. Do not claim implementation proof yet; the code-owning pass starts only after the design packet is ready.",
|
|
292
|
+
]
|
|
293
|
+
: []),
|
|
294
|
+
]
|
|
295
|
+
: [];
|
|
272
296
|
const coordinationCommand = [
|
|
273
297
|
"pnpm exec wave coord post",
|
|
274
298
|
`--lane ${lane}`,
|
|
@@ -280,6 +304,7 @@ export function buildExecutionPrompt({
|
|
|
280
304
|
].join(" ");
|
|
281
305
|
const implementationRequirements =
|
|
282
306
|
![contQaAgentId, documentationAgentId].includes(agent.agentId) &&
|
|
307
|
+
(!designAgent || designImplementationPass) &&
|
|
283
308
|
!isSecurityReviewAgent(agent) &&
|
|
284
309
|
(agent.agentId !== contEvalAgentId || contEvalImplementationOwning)
|
|
285
310
|
? [
|
|
@@ -294,7 +319,8 @@ export function buildExecutionPrompt({
|
|
|
294
319
|
`- Route unresolved architecture, integration, durability, ops, or docs issues through \`${coordinationCommand}\`. Do not append \`[wave-gap]\` lines after the final implementation markers.`,
|
|
295
320
|
]
|
|
296
321
|
: [];
|
|
297
|
-
const exitContractLines =
|
|
322
|
+
const exitContractLines =
|
|
323
|
+
implementationRequirements.length > 0 && agent.exitContract
|
|
298
324
|
? [
|
|
299
325
|
"Exit contract for this run:",
|
|
300
326
|
`- completion: ${agent.exitContract.completion}`,
|
|
@@ -385,6 +411,7 @@ export function buildExecutionPrompt({
|
|
|
385
411
|
: [];
|
|
386
412
|
const ownedComponentLines =
|
|
387
413
|
![contQaAgentId, documentationAgentId].includes(agent.agentId) &&
|
|
414
|
+
(!designAgent || designImplementationPass) &&
|
|
388
415
|
(agent.agentId !== contEvalAgentId || contEvalImplementationOwning) &&
|
|
389
416
|
Array.isArray(agent.components) &&
|
|
390
417
|
agent.components.length > 0
|
|
@@ -398,6 +425,7 @@ export function buildExecutionPrompt({
|
|
|
398
425
|
]
|
|
399
426
|
: [];
|
|
400
427
|
const deliverableLines =
|
|
428
|
+
(!designAgent || designImplementationPass) &&
|
|
401
429
|
Array.isArray(agent.deliverables) && agent.deliverables.length > 0
|
|
402
430
|
? [
|
|
403
431
|
"Deliverables required for this agent:",
|
|
@@ -405,7 +433,18 @@ export function buildExecutionPrompt({
|
|
|
405
433
|
"",
|
|
406
434
|
]
|
|
407
435
|
: [];
|
|
436
|
+
const designPacketLines =
|
|
437
|
+
!designAgent &&
|
|
438
|
+
Array.isArray(designPacketPaths) &&
|
|
439
|
+
designPacketPaths.length > 0
|
|
440
|
+
? [
|
|
441
|
+
"Same-wave design packets to read before coding:",
|
|
442
|
+
...designPacketPaths.map((designPacketPath) => `- ${designPacketPath}`),
|
|
443
|
+
"",
|
|
444
|
+
]
|
|
445
|
+
: [];
|
|
408
446
|
const proofArtifactLines =
|
|
447
|
+
implementationRequirements.length > 0 &&
|
|
409
448
|
Array.isArray(agent.proofArtifacts) && agent.proofArtifacts.length > 0
|
|
410
449
|
? [
|
|
411
450
|
"Proof artifacts required for this agent:",
|
|
@@ -473,6 +512,7 @@ export function buildExecutionPrompt({
|
|
|
473
512
|
...contEvalRequirements,
|
|
474
513
|
...docStewardRequirements,
|
|
475
514
|
...securityRequirements,
|
|
515
|
+
...designRequirements,
|
|
476
516
|
...implementationRequirements,
|
|
477
517
|
`- Update docs impacted by your implementation. If your work changes status, sequencing, ownership, or explicit proof expectations, update the relevant docs. If shared plan docs need changes outside your owned files, post the exact doc paths and exact delta needed for ${sharedPlanDocList} as a coordination record instead of leaving documentation drift for later cleanup.`,
|
|
478
518
|
"- If the wave defines a documentation steward or other explicit owner for shared plan docs, coordinate those updates through that owner, notify them as soon as the delta is known, and stay engaged until they confirm `closed` or `no-change`. Do not treat the ownership boundary as the definition of done.",
|
|
@@ -503,6 +543,7 @@ export function buildExecutionPrompt({
|
|
|
503
543
|
...evalTargetLines,
|
|
504
544
|
...ownedComponentLines,
|
|
505
545
|
...deliverableLines,
|
|
546
|
+
...designPacketLines,
|
|
506
547
|
...proofArtifactLines,
|
|
507
548
|
...skillLines,
|
|
508
549
|
...context7PromptLines,
|