@chllming/wave-orchestration 0.8.9 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +23 -7
- package/docs/README.md +5 -3
- package/docs/concepts/context7-vs-skills.md +1 -1
- package/docs/concepts/operating-modes.md +1 -1
- package/docs/concepts/what-is-a-wave.md +1 -1
- package/docs/guides/author-and-run-waves.md +14 -1
- package/docs/guides/monorepo-projects.md +226 -0
- package/docs/guides/planner.md +9 -2
- package/docs/guides/{recommendations-0.8.9.md → recommendations-0.9.0.md} +7 -7
- package/docs/plans/current-state.md +8 -6
- package/docs/plans/end-state-architecture.md +1 -1
- package/docs/plans/examples/wave-example-design-handoff.md +3 -1
- package/docs/plans/examples/wave-example-live-proof.md +6 -1
- package/docs/plans/examples/wave-example-rollout-fidelity.md +2 -0
- package/docs/plans/migration.md +21 -18
- package/docs/plans/wave-orchestrator.md +4 -4
- package/docs/reference/cli-reference.md +55 -51
- package/docs/reference/coordination-and-closure.md +1 -1
- package/docs/reference/npmjs-trusted-publishing.md +2 -2
- package/docs/reference/runtime-config/README.md +140 -12
- package/docs/reference/sample-waves.md +100 -5
- package/docs/reference/skills.md +1 -1
- package/docs/reference/wave-control.md +23 -5
- package/docs/roadmap.md +2 -2
- package/package.json +1 -1
- package/releases/manifest.json +19 -0
- package/scripts/wave-orchestrator/adhoc.mjs +49 -17
- package/scripts/wave-orchestrator/autonomous.mjs +49 -15
- package/scripts/wave-orchestrator/benchmark-external.mjs +23 -7
- package/scripts/wave-orchestrator/benchmark.mjs +33 -10
- package/scripts/wave-orchestrator/config.mjs +239 -24
- package/scripts/wave-orchestrator/control-cli.mjs +29 -23
- package/scripts/wave-orchestrator/coord-cli.mjs +22 -14
- package/scripts/wave-orchestrator/coordination-store.mjs +8 -0
- package/scripts/wave-orchestrator/dashboard-renderer.mjs +10 -3
- package/scripts/wave-orchestrator/dep-cli.mjs +47 -21
- package/scripts/wave-orchestrator/feedback.mjs +28 -11
- package/scripts/wave-orchestrator/human-input-resolution.mjs +5 -1
- package/scripts/wave-orchestrator/launcher.mjs +24 -3
- package/scripts/wave-orchestrator/planner.mjs +48 -27
- package/scripts/wave-orchestrator/project-profile.mjs +31 -8
- package/scripts/wave-orchestrator/proof-cli.mjs +18 -12
- package/scripts/wave-orchestrator/retry-cli.mjs +19 -13
- package/scripts/wave-orchestrator/shared.mjs +77 -14
- package/scripts/wave-orchestrator/wave-control-client.mjs +84 -16
- package/scripts/wave-orchestrator/wave-files.mjs +5 -1
|
@@ -15,10 +15,10 @@ import { parseWaveFiles } from "./wave-files.mjs";
|
|
|
15
15
|
|
|
16
16
|
function printUsage() {
|
|
17
17
|
console.log(`Usage:
|
|
18
|
-
wave dep post --owner-lane <lane> --requester-lane <lane> --owner-wave <n> --requester-wave <n> --agent <id> --summary <text> [options]
|
|
19
|
-
wave dep show --lane <lane> [--wave <n>] [--json]
|
|
20
|
-
wave dep resolve --lane <lane> --id <id> --agent <id> [--detail <text>] [--status resolved|closed]
|
|
21
|
-
wave dep render --lane <lane> [--wave <n>] [--json]
|
|
18
|
+
wave dep post --owner-project <id> --owner-lane <lane> --requester-project <id> --requester-lane <lane> --owner-wave <n> --requester-wave <n> --agent <id> --summary <text> [options]
|
|
19
|
+
wave dep show --project <id> --lane <lane> [--wave <n>] [--json]
|
|
20
|
+
wave dep resolve --project <id> --lane <lane> --id <id> --agent <id> [--detail <text>] [--status resolved|closed]
|
|
21
|
+
wave dep render --project <id> --lane <lane> [--wave <n>] [--json]
|
|
22
22
|
`);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -26,6 +26,9 @@ function parseArgs(argv) {
|
|
|
26
26
|
const args = argv[0] === "--" ? argv.slice(1) : argv;
|
|
27
27
|
const subcommand = String(args[0] || "").trim().toLowerCase();
|
|
28
28
|
const options = {
|
|
29
|
+
project: "",
|
|
30
|
+
ownerProject: "",
|
|
31
|
+
requesterProject: "",
|
|
29
32
|
lane: "",
|
|
30
33
|
ownerLane: "",
|
|
31
34
|
requesterLane: "",
|
|
@@ -46,7 +49,13 @@ function parseArgs(argv) {
|
|
|
46
49
|
};
|
|
47
50
|
for (let index = 1; index < args.length; index += 1) {
|
|
48
51
|
const arg = args[index];
|
|
49
|
-
if (arg === "--
|
|
52
|
+
if (arg === "--project") {
|
|
53
|
+
options.project = String(args[++index] || "").trim();
|
|
54
|
+
} else if (arg === "--owner-project") {
|
|
55
|
+
options.ownerProject = String(args[++index] || "").trim();
|
|
56
|
+
} else if (arg === "--requester-project") {
|
|
57
|
+
options.requesterProject = String(args[++index] || "").trim();
|
|
58
|
+
} else if (arg === "--lane") {
|
|
50
59
|
options.lane = String(args[++index] || "").trim();
|
|
51
60
|
} else if (arg === "--owner-lane") {
|
|
52
61
|
options.ownerLane = String(args[++index] || "").trim();
|
|
@@ -112,11 +121,15 @@ export async function runDependencyCli(argv) {
|
|
|
112
121
|
return;
|
|
113
122
|
}
|
|
114
123
|
const { subcommand, options } = parseArgs(argv);
|
|
124
|
+
const baseProject =
|
|
125
|
+
options.project || options.ownerProject || options.requesterProject || undefined;
|
|
115
126
|
const baseLane = options.lane || options.ownerLane || options.requesterLane || "main";
|
|
116
|
-
const lanePaths = buildLanePaths(baseLane);
|
|
127
|
+
const lanePaths = buildLanePaths(baseLane, { project: baseProject });
|
|
117
128
|
ensureDirectory(lanePaths.crossLaneDependenciesDir);
|
|
118
129
|
|
|
119
130
|
if (subcommand === "post") {
|
|
131
|
+
const ownerProject = options.ownerProject || options.project || lanePaths.project;
|
|
132
|
+
const requesterProject = options.requesterProject || options.project || lanePaths.project;
|
|
120
133
|
const ownerLane = options.ownerLane || options.lane;
|
|
121
134
|
const requesterLane = options.requesterLane || lanePaths.lane;
|
|
122
135
|
if (!ownerLane || !requesterLane || options.ownerWave === null || options.requesterWave === null) {
|
|
@@ -125,13 +138,17 @@ export async function runDependencyCli(argv) {
|
|
|
125
138
|
if (!options.agent || !options.summary) {
|
|
126
139
|
throw new Error("--agent and --summary are required");
|
|
127
140
|
}
|
|
128
|
-
const
|
|
141
|
+
const ownerLanePaths = buildLanePaths(ownerLane, { project: ownerProject });
|
|
142
|
+
ensureDirectory(ownerLanePaths.crossLaneDependenciesDir);
|
|
143
|
+
const record = appendDependencyTicket(ownerLanePaths.crossLaneDependenciesDir, ownerLane, {
|
|
129
144
|
id: options.id || `dep-${Date.now().toString(36)}`,
|
|
130
145
|
kind: "request",
|
|
131
146
|
lane: ownerLane,
|
|
132
147
|
wave: options.ownerWave,
|
|
148
|
+
ownerProject,
|
|
133
149
|
ownerLane,
|
|
134
150
|
ownerWave: options.ownerWave,
|
|
151
|
+
requesterProject,
|
|
135
152
|
requesterLane,
|
|
136
153
|
requesterWave: options.requesterWave,
|
|
137
154
|
agentId: options.agent,
|
|
@@ -155,14 +172,15 @@ export async function runDependencyCli(argv) {
|
|
|
155
172
|
if (!lane || !options.id || !options.agent) {
|
|
156
173
|
throw new Error("--lane, --id, and --agent are required for resolve");
|
|
157
174
|
}
|
|
158
|
-
const
|
|
159
|
-
const
|
|
175
|
+
const targetProject = options.project || options.ownerProject || lanePaths.project;
|
|
176
|
+
const targetLanePaths = buildLanePaths(lane, { project: targetProject });
|
|
177
|
+
const latest = materializeCoordinationState(readDependencyTickets(targetLanePaths.crossLaneDependenciesDir, lane)).byId.get(
|
|
160
178
|
options.id,
|
|
161
179
|
);
|
|
162
180
|
if (!latest) {
|
|
163
181
|
throw new Error(`Dependency ${options.id} not found for lane ${lane}`);
|
|
164
182
|
}
|
|
165
|
-
const record = appendDependencyTicket(
|
|
183
|
+
const record = appendDependencyTicket(targetLanePaths.crossLaneDependenciesDir, lane, {
|
|
166
184
|
...latest,
|
|
167
185
|
agentId: options.agent,
|
|
168
186
|
status: options.status || "resolved",
|
|
@@ -175,17 +193,23 @@ export async function runDependencyCli(argv) {
|
|
|
175
193
|
|
|
176
194
|
if (subcommand === "show") {
|
|
177
195
|
const lane = options.lane || options.ownerLane || lanePaths.lane;
|
|
196
|
+
const targetProject = options.project || options.ownerProject || lanePaths.project;
|
|
197
|
+
const targetLanePaths = buildLanePaths(lane, { project: targetProject });
|
|
178
198
|
const records =
|
|
179
199
|
options.wave === null
|
|
180
|
-
? readAllDependencyTickets(
|
|
181
|
-
(record) =>
|
|
200
|
+
? readAllDependencyTickets(targetLanePaths.crossLaneDependenciesDir).filter(
|
|
201
|
+
(record) =>
|
|
202
|
+
(record.ownerLane === lane || record.requesterLane === lane || record.lane === lane) &&
|
|
203
|
+
(!options.project ||
|
|
204
|
+
record.ownerProject === targetProject ||
|
|
205
|
+
record.requesterProject === targetProject),
|
|
182
206
|
)
|
|
183
207
|
: buildDependencySnapshot({
|
|
184
|
-
dirPath:
|
|
208
|
+
dirPath: targetLanePaths.crossLaneDependenciesDir,
|
|
185
209
|
lane,
|
|
186
210
|
waveNumber: options.wave,
|
|
187
|
-
agents: loadWaveAgents(
|
|
188
|
-
capabilityRouting:
|
|
211
|
+
agents: loadWaveAgents(targetLanePaths, options.wave),
|
|
212
|
+
capabilityRouting: targetLanePaths.capabilityRouting,
|
|
189
213
|
});
|
|
190
214
|
if (options.json || options.wave !== null) {
|
|
191
215
|
console.log(JSON.stringify(records, null, 2));
|
|
@@ -201,20 +225,22 @@ export async function runDependencyCli(argv) {
|
|
|
201
225
|
|
|
202
226
|
if (subcommand === "render") {
|
|
203
227
|
const lane = options.lane || options.ownerLane || lanePaths.lane;
|
|
228
|
+
const targetProject = options.project || options.ownerProject || lanePaths.project;
|
|
229
|
+
const targetLanePaths = buildLanePaths(lane, { project: targetProject });
|
|
204
230
|
const snapshot = buildDependencySnapshot({
|
|
205
|
-
dirPath:
|
|
231
|
+
dirPath: targetLanePaths.crossLaneDependenciesDir,
|
|
206
232
|
lane,
|
|
207
233
|
waveNumber: options.wave ?? 0,
|
|
208
|
-
agents: loadWaveAgents(
|
|
209
|
-
capabilityRouting:
|
|
234
|
+
agents: loadWaveAgents(targetLanePaths, options.wave ?? 0),
|
|
235
|
+
capabilityRouting: targetLanePaths.capabilityRouting,
|
|
210
236
|
});
|
|
211
|
-
const markdownPath = dependencyMarkdownPath(
|
|
212
|
-
writeDependencySnapshot(path.join(
|
|
237
|
+
const markdownPath = dependencyMarkdownPath(targetLanePaths, lane);
|
|
238
|
+
writeDependencySnapshot(path.join(targetLanePaths.crossLaneDependenciesDir, `${lane}.json`), snapshot, {
|
|
213
239
|
lane,
|
|
214
240
|
wave: options.wave ?? 0,
|
|
215
241
|
});
|
|
216
242
|
writeTextAtomic(markdownPath, `${renderDependencySnapshotMarkdown(snapshot)}\n`);
|
|
217
|
-
console.log(JSON.stringify({ markdownPath, jsonPath: path.join(
|
|
243
|
+
console.log(JSON.stringify({ markdownPath, jsonPath: path.join(targetLanePaths.crossLaneDependenciesDir, `${lane}.json`) }, null, 2));
|
|
218
244
|
return;
|
|
219
245
|
}
|
|
220
246
|
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
DEFAULT_WAIT_TIMEOUT_SECONDS,
|
|
7
7
|
DEFAULT_WATCH_REFRESH_MS,
|
|
8
8
|
DEFAULT_WAVE_LANE,
|
|
9
|
-
REPO_ROOT,
|
|
10
9
|
buildLanePaths,
|
|
11
10
|
compactSingleLine,
|
|
12
11
|
ensureDirectory,
|
|
12
|
+
findAdhocRunRecord,
|
|
13
13
|
formatAgeFromTimestamp,
|
|
14
14
|
parseNonNegativeInt,
|
|
15
15
|
parsePositiveInt,
|
|
@@ -41,9 +41,12 @@ function requestFilePath(feedbackRequestsDir, requestId) {
|
|
|
41
41
|
return path.join(feedbackRequestsDir, `${requestId}.json`);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
return
|
|
44
|
+
function resolveRunContext(runId, fallbackProject, fallbackLane) {
|
|
45
|
+
const record = findAdhocRunRecord(runId);
|
|
46
|
+
return {
|
|
47
|
+
project: record?.project || fallbackProject,
|
|
48
|
+
lane: record?.result?.lane || fallbackLane,
|
|
49
|
+
};
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
function buildRequestId({ lane, wave, agentId }) {
|
|
@@ -55,6 +58,7 @@ function buildRequestId({ lane, wave, agentId }) {
|
|
|
55
58
|
export function createFeedbackRequest({
|
|
56
59
|
feedbackStateDir,
|
|
57
60
|
feedbackRequestsDir,
|
|
61
|
+
project = null,
|
|
58
62
|
lane,
|
|
59
63
|
wave,
|
|
60
64
|
agentId,
|
|
@@ -69,6 +73,7 @@ export function createFeedbackRequest({
|
|
|
69
73
|
const now = toIsoTimestamp();
|
|
70
74
|
const payload = {
|
|
71
75
|
id: requestId,
|
|
76
|
+
project: project || null,
|
|
72
77
|
createdAt: now,
|
|
73
78
|
updatedAt: now,
|
|
74
79
|
lane,
|
|
@@ -88,7 +93,9 @@ export function createFeedbackRequest({
|
|
|
88
93
|
});
|
|
89
94
|
if (recordTelemetry) {
|
|
90
95
|
try {
|
|
91
|
-
const lanePaths = buildLanePaths(lane
|
|
96
|
+
const lanePaths = buildLanePaths(lane, {
|
|
97
|
+
project: project || undefined,
|
|
98
|
+
});
|
|
92
99
|
safeQueueWaveControlEvent(lanePaths, {
|
|
93
100
|
category: "feedback",
|
|
94
101
|
entityType: "human_input",
|
|
@@ -148,7 +155,9 @@ export function answerFeedbackRequest({
|
|
|
148
155
|
});
|
|
149
156
|
if (recordTelemetry) {
|
|
150
157
|
try {
|
|
151
|
-
const lanePaths = buildLanePaths(answeredPayload?.lane || DEFAULT_WAVE_LANE
|
|
158
|
+
const lanePaths = buildLanePaths(answeredPayload?.lane || DEFAULT_WAVE_LANE, {
|
|
159
|
+
project: answeredPayload?.project || undefined,
|
|
160
|
+
});
|
|
152
161
|
safeQueueWaveControlEvent(lanePaths, {
|
|
153
162
|
category: "feedback",
|
|
154
163
|
entityType: "human_input",
|
|
@@ -245,6 +254,7 @@ function parseFeedbackArgs(argv) {
|
|
|
245
254
|
id: "",
|
|
246
255
|
response: "",
|
|
247
256
|
operator: "human-operator",
|
|
257
|
+
project: "",
|
|
248
258
|
force: false,
|
|
249
259
|
pending: false,
|
|
250
260
|
json: false,
|
|
@@ -255,7 +265,9 @@ function parseFeedbackArgs(argv) {
|
|
|
255
265
|
if (arg === "--") {
|
|
256
266
|
continue;
|
|
257
267
|
}
|
|
258
|
-
if (arg === "--
|
|
268
|
+
if (arg === "--project") {
|
|
269
|
+
out.project = String(args[++i] || "").trim();
|
|
270
|
+
} else if (arg === "--lane") {
|
|
259
271
|
out.lane = sanitizeLaneName(args[++i]);
|
|
260
272
|
} else if (arg === "--run") {
|
|
261
273
|
out.runId = sanitizeAdhocRunId(args[++i]);
|
|
@@ -310,10 +322,10 @@ async function waitForAnswer(filePath, timeoutSeconds) {
|
|
|
310
322
|
|
|
311
323
|
function printHelp() {
|
|
312
324
|
console.log(`Usage:
|
|
313
|
-
pnpm exec wave-feedback ask --lane <lane> --wave <n> --agent <id> --question "<text>" [options]
|
|
325
|
+
pnpm exec wave-feedback ask --project <id> --lane <lane> --wave <n> --agent <id> --question "<text>" [options]
|
|
314
326
|
pnpm exec wave-feedback respond --id <request-id> --response "<text>" [options]
|
|
315
|
-
pnpm exec wave-feedback list [--pending] [--lane <lane>] [--wave <n>] [--agent <id>] [--json]
|
|
316
|
-
pnpm exec wave-feedback watch [--pending] [--lane <lane>] [--wave <n>] [--agent <id>] [--refresh-ms <n>]
|
|
327
|
+
pnpm exec wave-feedback list [--pending] [--project <id>] [--lane <lane>] [--wave <n>] [--agent <id>] [--json]
|
|
328
|
+
pnpm exec wave-feedback watch [--pending] [--project <id>] [--lane <lane>] [--wave <n>] [--agent <id>] [--refresh-ms <n>]
|
|
317
329
|
pnpm exec wave-feedback show --id <request-id>
|
|
318
330
|
`);
|
|
319
331
|
}
|
|
@@ -325,9 +337,12 @@ export async function runFeedbackCli(argv) {
|
|
|
325
337
|
return;
|
|
326
338
|
}
|
|
327
339
|
if (options.runId) {
|
|
328
|
-
|
|
340
|
+
const context = resolveRunContext(options.runId, options.project, options.lane);
|
|
341
|
+
options.project = context.project;
|
|
342
|
+
options.lane = context.lane;
|
|
329
343
|
}
|
|
330
344
|
const lanePaths = buildLanePaths(options.lane, {
|
|
345
|
+
project: options.project || undefined,
|
|
331
346
|
adhocRunId: options.runId || null,
|
|
332
347
|
});
|
|
333
348
|
const requestsDir = lanePaths.feedbackRequestsDir;
|
|
@@ -340,6 +355,7 @@ export async function runFeedbackCli(argv) {
|
|
|
340
355
|
const result = createFeedbackRequest({
|
|
341
356
|
feedbackStateDir: stateDir,
|
|
342
357
|
feedbackRequestsDir: requestsDir,
|
|
358
|
+
project: lanePaths.project,
|
|
343
359
|
lane: options.lane,
|
|
344
360
|
wave: options.wave,
|
|
345
361
|
agentId: options.agent,
|
|
@@ -375,6 +391,7 @@ export async function runFeedbackCli(argv) {
|
|
|
375
391
|
});
|
|
376
392
|
if (answered?.lane && Number.isFinite(Number(answered.wave))) {
|
|
377
393
|
answerHumanInputByRequest({
|
|
394
|
+
project: answered.project || options.project || null,
|
|
378
395
|
lane: answered.lane,
|
|
379
396
|
waveNumber: Number(answered.wave),
|
|
380
397
|
requestId: options.id,
|
|
@@ -331,13 +331,17 @@ export function answerHumanInputAndReconcile({
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
export function answerHumanInputByRequest({
|
|
334
|
+
project = null,
|
|
334
335
|
lane,
|
|
335
336
|
waveNumber,
|
|
336
337
|
requestId,
|
|
337
338
|
operator = "human-operator",
|
|
338
339
|
runId = null,
|
|
339
340
|
}) {
|
|
340
|
-
const lanePaths = buildLanePaths(lane, {
|
|
341
|
+
const lanePaths = buildLanePaths(lane, {
|
|
342
|
+
project: project || undefined,
|
|
343
|
+
adhocRunId: runId || null,
|
|
344
|
+
});
|
|
341
345
|
const wave = loadWave(lanePaths, waveNumber);
|
|
342
346
|
return answerHumanInputAndReconcile({
|
|
343
347
|
lanePaths,
|
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import {
|
|
6
6
|
CODEX_SANDBOX_MODES,
|
|
7
7
|
DEFAULT_CODEX_SANDBOX_MODE,
|
|
8
|
+
loadWaveConfig,
|
|
8
9
|
normalizeCodexSandboxMode,
|
|
9
10
|
normalizeExecutorMode,
|
|
10
11
|
SUPPORTED_EXECUTOR_MODES,
|
|
@@ -234,6 +235,7 @@ function printUsage(lanePaths, terminalSurface) {
|
|
|
234
235
|
console.log(`Usage: pnpm exec wave launch [options]
|
|
235
236
|
|
|
236
237
|
Options:
|
|
238
|
+
--project <id> Project id (default: ${lanePaths.project})
|
|
237
239
|
--lane <name> Wave lane name (default: ${DEFAULT_WAVE_LANE})
|
|
238
240
|
--start-wave <n> Start from wave number (default: 0)
|
|
239
241
|
--end-wave <n> End at wave number (default: last available)
|
|
@@ -278,9 +280,10 @@ Options:
|
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
function parseArgs(argv) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
const config = loadWaveConfig();
|
|
284
|
+
let lanePaths = buildLanePaths(DEFAULT_WAVE_LANE, { config, project: config.defaultProject });
|
|
283
285
|
const options = {
|
|
286
|
+
project: config.defaultProject,
|
|
284
287
|
lane: DEFAULT_WAVE_LANE,
|
|
285
288
|
startWave: 0,
|
|
286
289
|
endWave: null,
|
|
@@ -298,7 +301,9 @@ function parseArgs(argv) {
|
|
|
298
301
|
codexSandboxMode: DEFAULT_CODEX_SANDBOX_MODE,
|
|
299
302
|
manifestOut: lanePaths.defaultManifestPath,
|
|
300
303
|
dryRun: false,
|
|
301
|
-
terminalSurface: resolveDefaultTerminalSurface(
|
|
304
|
+
terminalSurface: resolveDefaultTerminalSurface(
|
|
305
|
+
readProjectProfile({ config, project: config.defaultProject }),
|
|
306
|
+
),
|
|
302
307
|
dashboard: true,
|
|
303
308
|
cleanupSessions: true,
|
|
304
309
|
keepTerminals: false,
|
|
@@ -348,14 +353,28 @@ function parseArgs(argv) {
|
|
|
348
353
|
} else if (arg === "--no-orchestrator-board") {
|
|
349
354
|
options.orchestratorBoardPath = null;
|
|
350
355
|
orchestratorBoardProvided = true;
|
|
356
|
+
} else if (arg === "--project") {
|
|
357
|
+
options.project = String(argv[++i] || "").trim();
|
|
358
|
+
lanePaths = buildLanePaths(options.lane, {
|
|
359
|
+
config,
|
|
360
|
+
project: options.project,
|
|
361
|
+
adhocRunId: options.adhocRunId,
|
|
362
|
+
});
|
|
363
|
+
options.terminalSurface = resolveDefaultTerminalSurface(
|
|
364
|
+
readProjectProfile({ config, project: options.project }),
|
|
365
|
+
);
|
|
351
366
|
} else if (arg === "--lane") {
|
|
352
367
|
options.lane = String(argv[++i] || "").trim();
|
|
353
368
|
lanePaths = buildLanePaths(options.lane, {
|
|
369
|
+
config,
|
|
370
|
+
project: options.project,
|
|
354
371
|
adhocRunId: options.adhocRunId,
|
|
355
372
|
});
|
|
356
373
|
} else if (arg === "--adhoc-run") {
|
|
357
374
|
options.adhocRunId = sanitizeAdhocRunId(argv[++i]);
|
|
358
375
|
lanePaths = buildLanePaths(options.lane, {
|
|
376
|
+
config,
|
|
377
|
+
project: options.project,
|
|
359
378
|
adhocRunId: options.adhocRunId,
|
|
360
379
|
});
|
|
361
380
|
} else if (arg === "--orchestrator-id") {
|
|
@@ -406,6 +425,8 @@ function parseArgs(argv) {
|
|
|
406
425
|
}
|
|
407
426
|
|
|
408
427
|
lanePaths = buildLanePaths(options.lane, {
|
|
428
|
+
config,
|
|
429
|
+
project: options.project,
|
|
409
430
|
runVariant: options.dryRun ? "dry-run" : undefined,
|
|
410
431
|
adhocRunId: options.adhocRunId,
|
|
411
432
|
});
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
buildDefaultProjectProfile,
|
|
37
37
|
normalizeDraftTemplate,
|
|
38
38
|
normalizeOversightMode,
|
|
39
|
+
projectProfilePath,
|
|
39
40
|
PROJECT_OVERSIGHT_MODES,
|
|
40
|
-
PROJECT_PROFILE_PATH,
|
|
41
41
|
PROJECT_PROFILE_TERMINAL_SURFACES,
|
|
42
42
|
readProjectProfile,
|
|
43
43
|
updateProjectProfile,
|
|
@@ -1336,8 +1336,9 @@ function collectPlannerSources({ config, lanePaths, task, fromWave }) {
|
|
|
1336
1336
|
)) {
|
|
1337
1337
|
sources.add(sourcePath, "core-context", "planner core context");
|
|
1338
1338
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1339
|
+
const plannerProfilePath = projectProfilePath(lanePaths.project || config.defaultProject);
|
|
1340
|
+
if (fileExists(plannerProfilePath)) {
|
|
1341
|
+
sources.add(repoRelativePath(plannerProfilePath), "project-profile", "saved project profile");
|
|
1341
1342
|
}
|
|
1342
1343
|
for (const sourcePath of ensureRepoRelativePathList(
|
|
1343
1344
|
plannerConfig.lessonsPaths || DEFAULT_PLANNER_AGENTIC_LESSONS_PATHS,
|
|
@@ -2587,9 +2588,10 @@ function parsePlannerWaveSelection(rawValue, waveOrder) {
|
|
|
2587
2588
|
|
|
2588
2589
|
async function runAgenticDraftFlow(options = {}) {
|
|
2589
2590
|
const config = options.config || loadWaveConfig();
|
|
2590
|
-
const
|
|
2591
|
+
const projectId = options.project || config.defaultProject;
|
|
2592
|
+
const profile = await ensureProjectProfile({ config, project: projectId });
|
|
2591
2593
|
const lane = options.lane || profile.plannerDefaults.lane || config.defaultLane;
|
|
2592
|
-
const lanePaths = buildLanePaths(lane, { config });
|
|
2594
|
+
const lanePaths = buildLanePaths(lane, { config, project: projectId });
|
|
2593
2595
|
const matrix = loadComponentCutoverMatrix({ laneProfile: lanePaths.laneProfile });
|
|
2594
2596
|
const bundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
|
|
2595
2597
|
const plannerExecutorProfile =
|
|
@@ -2794,7 +2796,7 @@ async function runAgenticDraftFlow(options = {}) {
|
|
|
2794
2796
|
lane: lanePaths.lane,
|
|
2795
2797
|
},
|
|
2796
2798
|
}),
|
|
2797
|
-
{ config },
|
|
2799
|
+
{ config, project: projectId },
|
|
2798
2800
|
);
|
|
2799
2801
|
return resultPayload;
|
|
2800
2802
|
}
|
|
@@ -2810,7 +2812,12 @@ async function runApplyPlannerRun(options = {}) {
|
|
|
2810
2812
|
);
|
|
2811
2813
|
}
|
|
2812
2814
|
const config = options.config || loadWaveConfig();
|
|
2813
|
-
const
|
|
2815
|
+
const projectId =
|
|
2816
|
+
cleanText(options.project) ||
|
|
2817
|
+
cleanText(bundle.request.project) ||
|
|
2818
|
+
cleanText(bundle.result?.project) ||
|
|
2819
|
+
config.defaultProject;
|
|
2820
|
+
const lanePaths = buildLanePaths(bundle.request.lane, { config, project: projectId });
|
|
2814
2821
|
const selectedWaves = parsePlannerWaveSelection(options.waves, bundle.plan?.waveOrder || []);
|
|
2815
2822
|
if (selectedWaves.length === 0) {
|
|
2816
2823
|
throw new Error("No waves selected for apply");
|
|
@@ -2894,12 +2901,13 @@ function showPlannerRun(options = {}) {
|
|
|
2894
2901
|
|
|
2895
2902
|
async function ensureProjectProfile(options = {}) {
|
|
2896
2903
|
const config = options.config || loadWaveConfig();
|
|
2897
|
-
const existing = readProjectProfile({ config });
|
|
2904
|
+
const existing = readProjectProfile({ config, project: options.project });
|
|
2898
2905
|
if (existing) {
|
|
2899
2906
|
return existing;
|
|
2900
2907
|
}
|
|
2901
2908
|
return runProjectSetupFlow({
|
|
2902
2909
|
config,
|
|
2910
|
+
project: options.project,
|
|
2903
2911
|
json: false,
|
|
2904
2912
|
fromDraft: true,
|
|
2905
2913
|
});
|
|
@@ -2907,12 +2915,14 @@ async function ensureProjectProfile(options = {}) {
|
|
|
2907
2915
|
|
|
2908
2916
|
async function runProjectSetupFlow(options = {}) {
|
|
2909
2917
|
const config = options.config || loadWaveConfig();
|
|
2910
|
-
const
|
|
2918
|
+
const projectId = cleanText(options.project || config.defaultProject);
|
|
2919
|
+
const existing = readProjectProfile({ config, project: projectId });
|
|
2911
2920
|
const base = existing || buildDefaultProjectProfile(config);
|
|
2912
2921
|
const prompt = new PromptSession();
|
|
2913
2922
|
try {
|
|
2923
|
+
const projectLanes = Object.keys(config.projects?.[projectId]?.lanes || {});
|
|
2914
2924
|
const laneChoices = Array.from(
|
|
2915
|
-
new Set([config.defaultLane, ...Object.keys(config.lanes || {})].filter(Boolean)),
|
|
2925
|
+
new Set([config.defaultLane, ...projectLanes, ...Object.keys(config.lanes || {})].filter(Boolean)),
|
|
2916
2926
|
);
|
|
2917
2927
|
const newProject = await prompt.askBoolean("Treat this repository as a new project?", base.newProject);
|
|
2918
2928
|
const defaultOversightMode = normalizeOversightMode(
|
|
@@ -2994,7 +3004,7 @@ async function runProjectSetupFlow(options = {}) {
|
|
|
2994
3004
|
lane,
|
|
2995
3005
|
},
|
|
2996
3006
|
},
|
|
2997
|
-
{ config },
|
|
3007
|
+
{ config, project: projectId },
|
|
2998
3008
|
);
|
|
2999
3009
|
return profile;
|
|
3000
3010
|
} finally {
|
|
@@ -3284,10 +3294,11 @@ async function collectEvalTargets({ prompt }) {
|
|
|
3284
3294
|
|
|
3285
3295
|
async function runDraftFlow(options = {}) {
|
|
3286
3296
|
const config = options.config || loadWaveConfig();
|
|
3287
|
-
const
|
|
3297
|
+
const projectId = options.project || config.defaultProject;
|
|
3298
|
+
const profile = await ensureProjectProfile({ config, project: projectId });
|
|
3288
3299
|
const waveNumber = options.wave;
|
|
3289
3300
|
const lane = options.lane || profile.plannerDefaults.lane || config.defaultLane;
|
|
3290
|
-
const lanePaths = buildLanePaths(lane, { config });
|
|
3301
|
+
const lanePaths = buildLanePaths(lane, { config, project: projectId });
|
|
3291
3302
|
const matrix = loadComponentCutoverMatrix({ laneProfile: lanePaths.laneProfile });
|
|
3292
3303
|
const bundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
|
|
3293
3304
|
const context7BundleChoices = Object.keys(bundleIndex.bundles || {}).sort((left, right) =>
|
|
@@ -3409,9 +3420,10 @@ async function runDraftFlow(options = {}) {
|
|
|
3409
3420
|
lane: lanePaths.lane,
|
|
3410
3421
|
},
|
|
3411
3422
|
}),
|
|
3412
|
-
{ config },
|
|
3423
|
+
{ config, project: projectId },
|
|
3413
3424
|
);
|
|
3414
3425
|
return {
|
|
3426
|
+
project: projectId,
|
|
3415
3427
|
wave: waveNumber,
|
|
3416
3428
|
lane: lanePaths.lane,
|
|
3417
3429
|
template,
|
|
@@ -3419,7 +3431,7 @@ async function runDraftFlow(options = {}) {
|
|
|
3419
3431
|
specPath: path.relative(REPO_ROOT, specPath),
|
|
3420
3432
|
matrixJsonPath: path.relative(REPO_ROOT, path.resolve(REPO_ROOT, lanePaths.componentCutoverMatrixJsonPath)),
|
|
3421
3433
|
matrixDocPath: path.relative(REPO_ROOT, path.resolve(REPO_ROOT, lanePaths.componentCutoverMatrixDocPath)),
|
|
3422
|
-
profilePath: path.relative(REPO_ROOT,
|
|
3434
|
+
profilePath: path.relative(REPO_ROOT, projectProfilePath(projectId)),
|
|
3423
3435
|
};
|
|
3424
3436
|
} finally {
|
|
3425
3437
|
await prompt.close();
|
|
@@ -3428,12 +3440,12 @@ async function runDraftFlow(options = {}) {
|
|
|
3428
3440
|
|
|
3429
3441
|
function printPlannerHelp() {
|
|
3430
3442
|
console.log(`Usage:
|
|
3431
|
-
wave project setup [--json]
|
|
3432
|
-
wave project show [--json]
|
|
3433
|
-
wave draft --wave <n> [--lane <lane>] [--template implementation|qa|infra|release] [--force] [--json]
|
|
3434
|
-
wave draft --agentic --task "<text>" --from-wave <n> [--lane <lane>] [--max-waves <n>] [--planner-executor <profile>] [--json]
|
|
3443
|
+
wave project setup [--project <id>] [--json]
|
|
3444
|
+
wave project show [--project <id>] [--json]
|
|
3445
|
+
wave draft --wave <n> [--project <id>] [--lane <lane>] [--template implementation|qa|infra|release] [--force] [--json]
|
|
3446
|
+
wave draft --agentic --task "<text>" --from-wave <n> [--project <id>] [--lane <lane>] [--max-waves <n>] [--planner-executor <profile>] [--json]
|
|
3435
3447
|
wave draft --show-run <run-id> [--json]
|
|
3436
|
-
wave draft --apply-run <run-id> [--waves <list>|all] [--force] [--json]
|
|
3448
|
+
wave draft --apply-run <run-id> [--project <id>] [--waves <list>|all] [--force] [--json]
|
|
3437
3449
|
`);
|
|
3438
3450
|
}
|
|
3439
3451
|
|
|
@@ -3444,6 +3456,7 @@ export async function runPlannerCli(argv) {
|
|
|
3444
3456
|
json: false,
|
|
3445
3457
|
force: false,
|
|
3446
3458
|
wave: null,
|
|
3459
|
+
project: null,
|
|
3447
3460
|
lane: null,
|
|
3448
3461
|
template: null,
|
|
3449
3462
|
agentic: false,
|
|
@@ -3464,6 +3477,8 @@ export async function runPlannerCli(argv) {
|
|
|
3464
3477
|
for (const arg of args) {
|
|
3465
3478
|
if (arg === "--json") {
|
|
3466
3479
|
options.json = true;
|
|
3480
|
+
} else if (arg === "--project") {
|
|
3481
|
+
options.project = cleanText(args.shift());
|
|
3467
3482
|
} else if (arg === "--help" || arg === "-h") {
|
|
3468
3483
|
printPlannerHelp();
|
|
3469
3484
|
return;
|
|
@@ -3472,15 +3487,17 @@ export async function runPlannerCli(argv) {
|
|
|
3472
3487
|
}
|
|
3473
3488
|
}
|
|
3474
3489
|
if (action === "setup") {
|
|
3475
|
-
const
|
|
3490
|
+
const projectId = options.project || loadWaveConfig().defaultProject;
|
|
3491
|
+
const profile = await runProjectSetupFlow({ json: options.json, project: projectId });
|
|
3476
3492
|
if (options.json) {
|
|
3477
3493
|
printJson({
|
|
3478
|
-
profilePath: path.relative(REPO_ROOT,
|
|
3494
|
+
profilePath: path.relative(REPO_ROOT, projectProfilePath(projectId)),
|
|
3479
3495
|
profile,
|
|
3480
3496
|
});
|
|
3481
3497
|
return;
|
|
3482
3498
|
}
|
|
3483
|
-
console.log(`[wave:project] profile: ${path.relative(REPO_ROOT,
|
|
3499
|
+
console.log(`[wave:project] profile: ${path.relative(REPO_ROOT, projectProfilePath(projectId))}`);
|
|
3500
|
+
console.log(`[wave:project] project_id=${projectId}`);
|
|
3484
3501
|
console.log(`[wave:project] lane=${profile.plannerDefaults.lane}`);
|
|
3485
3502
|
console.log(`[wave:project] template=${profile.plannerDefaults.template}`);
|
|
3486
3503
|
console.log(`[wave:project] oversight=${profile.defaultOversightMode}`);
|
|
@@ -3488,19 +3505,21 @@ export async function runPlannerCli(argv) {
|
|
|
3488
3505
|
return;
|
|
3489
3506
|
}
|
|
3490
3507
|
if (action === "show") {
|
|
3491
|
-
const
|
|
3508
|
+
const projectId = options.project || loadWaveConfig().defaultProject;
|
|
3509
|
+
const profile = readProjectProfile({ project: projectId });
|
|
3492
3510
|
if (options.json) {
|
|
3493
3511
|
printJson({
|
|
3494
|
-
profilePath: path.relative(REPO_ROOT,
|
|
3512
|
+
profilePath: path.relative(REPO_ROOT, projectProfilePath(projectId)),
|
|
3495
3513
|
profile,
|
|
3496
3514
|
});
|
|
3497
3515
|
return;
|
|
3498
3516
|
}
|
|
3499
3517
|
if (!profile) {
|
|
3500
|
-
console.log(`[wave:project] no saved profile at ${path.relative(REPO_ROOT,
|
|
3518
|
+
console.log(`[wave:project] no saved profile at ${path.relative(REPO_ROOT, projectProfilePath(projectId))}`);
|
|
3501
3519
|
return;
|
|
3502
3520
|
}
|
|
3503
|
-
console.log(`[wave:project] profile: ${path.relative(REPO_ROOT,
|
|
3521
|
+
console.log(`[wave:project] profile: ${path.relative(REPO_ROOT, projectProfilePath(projectId))}`);
|
|
3522
|
+
console.log(`[wave:project] project_id=${projectId}`);
|
|
3504
3523
|
console.log(`[wave:project] project=${profile.source.projectName}`);
|
|
3505
3524
|
console.log(`[wave:project] lane=${profile.plannerDefaults.lane}`);
|
|
3506
3525
|
console.log(`[wave:project] template=${profile.plannerDefaults.template}`);
|
|
@@ -3537,6 +3556,8 @@ export async function runPlannerCli(argv) {
|
|
|
3537
3556
|
options.waves = cleanText(args[++index]);
|
|
3538
3557
|
} else if (arg === "--wave") {
|
|
3539
3558
|
options.wave = Number.parseInt(String(args[++index] || ""), 10);
|
|
3559
|
+
} else if (arg === "--project") {
|
|
3560
|
+
options.project = cleanText(args[++index]);
|
|
3540
3561
|
} else if (arg === "--lane") {
|
|
3541
3562
|
options.lane = cleanText(args[++index]);
|
|
3542
3563
|
} else if (arg === "--template") {
|