@gh-symphony/cli 0.2.4 → 0.3.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/dist/{chunk-DLZ2XHWY.js → chunk-2ZIPQ7ZS.js} +1 -1
- package/dist/{chunk-3SKN5L3I.js → chunk-5HQLPZR5.js} +15 -6
- package/dist/{chunk-FAU72YC2.js → chunk-A7EFL6EJ.js} +1 -1
- package/dist/{chunk-PLBG7TZA.js → chunk-GL55AKBI.js} +169 -33
- package/dist/{chunk-7Z7WYGDL.js → chunk-GTNWFVFU.js} +9 -5
- package/dist/{chunk-BOM2BYZQ.js → chunk-SMNIGNS3.js} +106 -11
- package/dist/{chunk-NRABQNAX.js → chunk-VHEGRYK7.js} +3 -2
- package/dist/{doctor-MD4MD6SZ.js → doctor-3IIM4UYS.js} +6 -6
- package/dist/index.js +7 -7
- package/dist/{repo-CK2IDMZF.js → repo-SLK4DDXH.js} +198 -13
- package/dist/{setup-KZ3U53PY.js → setup-G5VYN6FV.js} +33 -13
- package/dist/{upgrade-2WPPOUZL.js → upgrade-BXIHAENU.js} +2 -2
- package/dist/{version-Z2T42H5M.js → version-MC2KSPJB.js} +1 -1
- package/dist/worker-entry.js +5 -5
- package/dist/{workflow-7Y6GTV2C.js → workflow-4OFPSVZ3.js} +6 -6
- package/package.json +3 -3
|
@@ -5,7 +5,8 @@ var DEFAULT_WORKFLOW_LIFECYCLE = {
|
|
|
5
5
|
stateFieldName: "Status",
|
|
6
6
|
activeStates: ["Todo", "In Progress"],
|
|
7
7
|
terminalStates: ["Done"],
|
|
8
|
-
blockerCheckStates: [
|
|
8
|
+
blockerCheckStates: [],
|
|
9
|
+
planningStates: []
|
|
9
10
|
};
|
|
10
11
|
function isStateActive(state, lifecycle) {
|
|
11
12
|
return matchesWorkflowState(state, lifecycle.activeStates);
|
|
@@ -15,7 +16,9 @@ function isStateTerminal(state, lifecycle) {
|
|
|
15
16
|
}
|
|
16
17
|
function matchesWorkflowState(state, candidates) {
|
|
17
18
|
const normalizedState = normalizeWorkflowState(state);
|
|
18
|
-
return candidates.some(
|
|
19
|
+
return candidates.some(
|
|
20
|
+
(candidate) => normalizeWorkflowState(candidate) === normalizedState
|
|
21
|
+
);
|
|
19
22
|
}
|
|
20
23
|
function normalizeWorkflowState(state) {
|
|
21
24
|
return state.trim().toLowerCase();
|
|
@@ -55,7 +58,8 @@ var DEFAULT_WORKFLOW_TRACKER = {
|
|
|
55
58
|
stateFieldName: DEFAULT_WORKFLOW_LIFECYCLE.stateFieldName,
|
|
56
59
|
priority: null,
|
|
57
60
|
priorityFieldName: null,
|
|
58
|
-
blockerCheckStates: DEFAULT_WORKFLOW_LIFECYCLE.blockerCheckStates
|
|
61
|
+
blockerCheckStates: DEFAULT_WORKFLOW_LIFECYCLE.blockerCheckStates,
|
|
62
|
+
planningStates: DEFAULT_WORKFLOW_LIFECYCLE.planningStates
|
|
59
63
|
};
|
|
60
64
|
var DEFAULT_WORKFLOW_WORKSPACE = {
|
|
61
65
|
root: null
|
|
@@ -135,6 +139,7 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
135
139
|
const activeStates = readStringList(tracker, "active_states") ?? DEFAULT_WORKFLOW_TRACKER.activeStates;
|
|
136
140
|
const terminalStates = readStringList(tracker, "terminal_states") ?? DEFAULT_WORKFLOW_TRACKER.terminalStates;
|
|
137
141
|
const blockerCheckStates = readStringList(tracker, "blocker_check_states") ?? DEFAULT_WORKFLOW_TRACKER.blockerCheckStates;
|
|
142
|
+
const planningStates = readStringList(tracker, "planning_states") ?? blockerCheckStates;
|
|
138
143
|
const maxConcurrentAgentsByState = readNumberMap(
|
|
139
144
|
agent,
|
|
140
145
|
"max_concurrent_agents_by_state"
|
|
@@ -172,7 +177,8 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
172
177
|
stateFieldName: readOptionalString(tracker, "state_field", env) ?? DEFAULT_WORKFLOW_TRACKER.stateFieldName,
|
|
173
178
|
priority: readPriorityConfig(tracker, env),
|
|
174
179
|
priorityFieldName: readOptionalString(tracker, "priority_field", env),
|
|
175
|
-
blockerCheckStates
|
|
180
|
+
blockerCheckStates,
|
|
181
|
+
planningStates
|
|
176
182
|
},
|
|
177
183
|
polling: {
|
|
178
184
|
intervalMs: readOptionalIntegerLike(polling, "interval_ms") ?? DEFAULT_POLL_INTERVAL_MS
|
|
@@ -201,7 +207,8 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
201
207
|
stateFieldName: readOptionalString(tracker, "state_field", env) ?? DEFAULT_WORKFLOW_TRACKER.stateFieldName,
|
|
202
208
|
activeStates,
|
|
203
209
|
terminalStates,
|
|
204
|
-
blockerCheckStates
|
|
210
|
+
blockerCheckStates,
|
|
211
|
+
planningStates
|
|
205
212
|
},
|
|
206
213
|
format: "front-matter",
|
|
207
214
|
githubProjectId: readOptionalString(tracker, "project_id", env),
|
|
@@ -451,7 +458,9 @@ function parseScalar(value) {
|
|
|
451
458
|
return parsed;
|
|
452
459
|
}
|
|
453
460
|
} catch {
|
|
454
|
-
throw new Error(
|
|
461
|
+
throw new Error(
|
|
462
|
+
`Invalid quoted workflow front matter scalar "${value}".`
|
|
463
|
+
);
|
|
455
464
|
}
|
|
456
465
|
}
|
|
457
466
|
if (value.startsWith("'") && value.endsWith("'")) {
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
listUserProjects,
|
|
12
12
|
resolveGitHubAuth,
|
|
13
13
|
validateToken
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SMNIGNS3.js";
|
|
15
15
|
import {
|
|
16
16
|
formatClaudePreflightText,
|
|
17
17
|
resolveClaudeCommandBinary,
|
|
18
18
|
runClaudePreflight
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5HQLPZR5.js";
|
|
20
20
|
|
|
21
21
|
// src/mapping/smart-defaults.ts
|
|
22
22
|
var ROLE_PATTERNS = [
|
|
@@ -45,10 +45,9 @@ function inferStateRole(columnName) {
|
|
|
45
45
|
function inferAllStateRoles(columnNames) {
|
|
46
46
|
return columnNames.map(inferStateRole);
|
|
47
47
|
}
|
|
48
|
-
function toWorkflowLifecycleConfig(stateFieldName, mappings) {
|
|
48
|
+
function toWorkflowLifecycleConfig(stateFieldName, mappings, options = {}) {
|
|
49
49
|
const activeStates = [];
|
|
50
50
|
const terminalStates = [];
|
|
51
|
-
const blockerCheckStates = [];
|
|
52
51
|
for (const [columnName, mapping] of Object.entries(mappings)) {
|
|
53
52
|
switch (mapping.role) {
|
|
54
53
|
case "active":
|
|
@@ -61,14 +60,13 @@ function toWorkflowLifecycleConfig(stateFieldName, mappings) {
|
|
|
61
60
|
break;
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
blockerCheckStates.push(activeStates[0]);
|
|
66
|
-
}
|
|
63
|
+
const blockerCheckStates = options.blockerCheckStates ?? [];
|
|
67
64
|
return {
|
|
68
65
|
stateFieldName,
|
|
69
66
|
activeStates,
|
|
70
67
|
terminalStates,
|
|
71
|
-
blockerCheckStates
|
|
68
|
+
blockerCheckStates,
|
|
69
|
+
planningStates: options.planningStates ?? blockerCheckStates
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
72
|
function validateStateMapping(mappings) {
|
|
@@ -361,12 +359,18 @@ function buildFrontMatter(input) {
|
|
|
361
359
|
lines.push(` - ${state}`);
|
|
362
360
|
}
|
|
363
361
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
362
|
+
lines.push(
|
|
363
|
+
...buildStringListFrontMatter(
|
|
364
|
+
"blocker_check_states",
|
|
365
|
+
input.lifecycle.blockerCheckStates
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
lines.push(
|
|
369
|
+
...buildStringListFrontMatter(
|
|
370
|
+
"planning_states",
|
|
371
|
+
input.lifecycle.planningStates
|
|
372
|
+
)
|
|
373
|
+
);
|
|
370
374
|
lines.push("polling:");
|
|
371
375
|
lines.push(` interval_ms: ${input.pollIntervalMs ?? 3e4}`);
|
|
372
376
|
lines.push("workspace:");
|
|
@@ -380,6 +384,12 @@ function buildFrontMatter(input) {
|
|
|
380
384
|
lines.push(...buildRuntimeFrontMatter(input.runtime));
|
|
381
385
|
return lines.join("\n") + "\n";
|
|
382
386
|
}
|
|
387
|
+
function buildStringListFrontMatter(key, values) {
|
|
388
|
+
if (values.length === 0) {
|
|
389
|
+
return [` ${key}: []`];
|
|
390
|
+
}
|
|
391
|
+
return [` ${key}:`, ...values.map((value) => ` - ${value}`)];
|
|
392
|
+
}
|
|
383
393
|
function buildPriorityFrontMatter(input) {
|
|
384
394
|
const lines = [];
|
|
385
395
|
if (!input.priority) {
|
|
@@ -984,7 +994,8 @@ function generateReferenceWorkflow(input) {
|
|
|
984
994
|
const terminalColumns = input.statusColumns.filter(
|
|
985
995
|
(c) => c.role === "terminal"
|
|
986
996
|
);
|
|
987
|
-
const
|
|
997
|
+
const blockerCheckStates = input.lifecycle?.blockerCheckStates ?? [];
|
|
998
|
+
const planningStates = input.lifecycle?.planningStates ?? blockerCheckStates;
|
|
988
999
|
if (activeColumns.length > 0) {
|
|
989
1000
|
lines.push(" active_states:");
|
|
990
1001
|
for (const col of activeColumns) {
|
|
@@ -1001,12 +1012,10 @@ function generateReferenceWorkflow(input) {
|
|
|
1001
1012
|
} else {
|
|
1002
1013
|
lines.push(" terminal_states: [{terminal column names}]");
|
|
1003
1014
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
lines.push(" blocker_check_states: [{first active state}]");
|
|
1009
|
-
}
|
|
1015
|
+
lines.push(
|
|
1016
|
+
...buildReferenceStringList("blocker_check_states", blockerCheckStates)
|
|
1017
|
+
);
|
|
1018
|
+
lines.push(...buildReferenceStringList("planning_states", planningStates));
|
|
1010
1019
|
lines.push("");
|
|
1011
1020
|
lines.push("# Linear tracker example:");
|
|
1012
1021
|
lines.push("# tracker:");
|
|
@@ -1021,7 +1030,9 @@ function generateReferenceWorkflow(input) {
|
|
|
1021
1030
|
lines.push("# - Done");
|
|
1022
1031
|
lines.push("# - Canceled");
|
|
1023
1032
|
lines.push("# - Duplicate");
|
|
1024
|
-
lines.push(
|
|
1033
|
+
lines.push(
|
|
1034
|
+
"# Linear uses repository-local polling; gh-symphony does not provide"
|
|
1035
|
+
);
|
|
1025
1036
|
lines.push("# a Linear webhook setup command.");
|
|
1026
1037
|
lines.push("");
|
|
1027
1038
|
lines.push("polling:");
|
|
@@ -1282,6 +1293,12 @@ function generateReferenceWorkflow(input) {
|
|
|
1282
1293
|
lines.push("");
|
|
1283
1294
|
return lines.join("\n");
|
|
1284
1295
|
}
|
|
1296
|
+
function buildReferenceStringList(key, values) {
|
|
1297
|
+
if (values.length === 0) {
|
|
1298
|
+
return [` ${key}: []`];
|
|
1299
|
+
}
|
|
1300
|
+
return [` ${key}:`, ...values.map((value) => ` - ${value}`)];
|
|
1301
|
+
}
|
|
1285
1302
|
function buildReferencePriorityLines(priority) {
|
|
1286
1303
|
const lines = [];
|
|
1287
1304
|
if (priority?.source === "project-field" || priority?.source === "labels") {
|
|
@@ -2017,7 +2034,7 @@ function validateInitRuntime(runtime) {
|
|
|
2017
2034
|
async function promptRuntimeSelection() {
|
|
2018
2035
|
return abortIfCancelled(
|
|
2019
2036
|
p.select({
|
|
2020
|
-
message: "Step 1/
|
|
2037
|
+
message: "Step 1/5 \u2014 Select the agent runtime:",
|
|
2021
2038
|
options: [
|
|
2022
2039
|
{
|
|
2023
2040
|
value: "codex-app-server",
|
|
@@ -2318,16 +2335,68 @@ async function promptStateMappings(statusField, options) {
|
|
|
2318
2335
|
}
|
|
2319
2336
|
return mappings;
|
|
2320
2337
|
}
|
|
2338
|
+
function getDefaultBlockerCheckStates(lifecycle) {
|
|
2339
|
+
const firstActive = lifecycle.activeStates[0];
|
|
2340
|
+
return firstActive ? [firstActive] : [];
|
|
2341
|
+
}
|
|
2342
|
+
async function promptBlockerCheck(lifecycle, options) {
|
|
2343
|
+
const stepLabel = options?.stepLabel ?? "Step 3/5";
|
|
2344
|
+
const activeStates = lifecycle.activeStates;
|
|
2345
|
+
const defaultStates = getDefaultBlockerCheckStates(lifecycle);
|
|
2346
|
+
if (activeStates.length === 0) {
|
|
2347
|
+
p.log.warn("No active states; blocker check cannot be enabled.");
|
|
2348
|
+
p.log.info("Blocker check: disabled");
|
|
2349
|
+
return [];
|
|
2350
|
+
}
|
|
2351
|
+
const activeStateSummary = activeStates.length === 1 ? `"${activeStates[0]}"` : "selected active states";
|
|
2352
|
+
const enabled = await abortIfCancelled(
|
|
2353
|
+
p.confirm({
|
|
2354
|
+
message: `${stepLabel} \u2014 Enable blocker check? Issues with unresolved "blocked by" dependencies will be held back from dispatch on ${activeStateSummary}.`,
|
|
2355
|
+
initialValue: true
|
|
2356
|
+
})
|
|
2357
|
+
);
|
|
2358
|
+
if (!enabled) {
|
|
2359
|
+
p.log.info("Blocker check: disabled");
|
|
2360
|
+
return [];
|
|
2361
|
+
}
|
|
2362
|
+
if (activeStates.length === 1) {
|
|
2363
|
+
p.log.info(`Blocker check applies to: ${activeStates[0]}`);
|
|
2364
|
+
return [activeStates[0]];
|
|
2365
|
+
}
|
|
2366
|
+
const selectedStates = await abortIfCancelled(
|
|
2367
|
+
p.multiselect({
|
|
2368
|
+
message: `${stepLabel} \u2014 Which active states should be blocker-checked?`,
|
|
2369
|
+
options: activeStates.map((state) => ({
|
|
2370
|
+
value: state,
|
|
2371
|
+
label: state,
|
|
2372
|
+
hint: defaultStates.includes(state) ? "default" : void 0
|
|
2373
|
+
})),
|
|
2374
|
+
initialValues: defaultStates,
|
|
2375
|
+
required: true
|
|
2376
|
+
})
|
|
2377
|
+
);
|
|
2378
|
+
p.log.info(`Blocker check applies to: ${selectedStates.join(", ")}`);
|
|
2379
|
+
return [...selectedStates];
|
|
2380
|
+
}
|
|
2321
2381
|
async function planWorkflowArtifacts(opts) {
|
|
2322
2382
|
const environment = opts.environment ?? await detectEnvironment(opts.cwd);
|
|
2323
2383
|
const priority = opts.priority ?? (opts.priorityField ? buildProjectFieldPriority(opts.priorityField) : buildDisabledPriority());
|
|
2384
|
+
const defaultLifecycle = toWorkflowLifecycleConfig(
|
|
2385
|
+
opts.statusField.name,
|
|
2386
|
+
opts.mappings
|
|
2387
|
+
);
|
|
2388
|
+
const defaultBlockerCheckStates = getDefaultBlockerCheckStates(defaultLifecycle);
|
|
2389
|
+
const lifecycle = opts.lifecycle ?? toWorkflowLifecycleConfig(opts.statusField.name, opts.mappings, {
|
|
2390
|
+
blockerCheckStates: defaultBlockerCheckStates,
|
|
2391
|
+
planningStates: defaultBlockerCheckStates
|
|
2392
|
+
});
|
|
2324
2393
|
const workflowMd = generateWorkflowMarkdown({
|
|
2325
2394
|
projectId: opts.projectDetail.id,
|
|
2326
2395
|
stateFieldName: opts.statusField.name,
|
|
2327
2396
|
priority,
|
|
2328
2397
|
includePriorityTemplates: opts.includePriorityTemplates ?? priority.source === "disabled",
|
|
2329
2398
|
mappings: opts.mappings,
|
|
2330
|
-
lifecycle
|
|
2399
|
+
lifecycle,
|
|
2331
2400
|
runtime: opts.runtime,
|
|
2332
2401
|
detectedEnvironment: environment
|
|
2333
2402
|
});
|
|
@@ -2343,6 +2412,7 @@ async function planWorkflowArtifacts(opts) {
|
|
|
2343
2412
|
statusField: opts.statusField,
|
|
2344
2413
|
priorityField: opts.priorityField,
|
|
2345
2414
|
priority,
|
|
2415
|
+
lifecycle,
|
|
2346
2416
|
includePriorityTemplates: opts.includePriorityTemplates ?? priority.source === "disabled",
|
|
2347
2417
|
runtime: opts.runtime,
|
|
2348
2418
|
skipSkills: opts.skipSkills,
|
|
@@ -2368,6 +2438,11 @@ function summarizeEnvironment(env) {
|
|
|
2368
2438
|
`Existing skills ${env.existingSkills.length === 0 ? "none" : env.existingSkills.join(", ")}`
|
|
2369
2439
|
];
|
|
2370
2440
|
}
|
|
2441
|
+
function deriveWaitStates(statusField, lifecycle) {
|
|
2442
|
+
const active = new Set(lifecycle.activeStates);
|
|
2443
|
+
const terminal = new Set(lifecycle.terminalStates);
|
|
2444
|
+
return statusField.options.map((option) => option.name).filter((state) => !active.has(state) && !terminal.has(state));
|
|
2445
|
+
}
|
|
2371
2446
|
async function planEcosystem(opts) {
|
|
2372
2447
|
const {
|
|
2373
2448
|
cwd,
|
|
@@ -2379,6 +2454,19 @@ async function planEcosystem(opts) {
|
|
|
2379
2454
|
skipContext
|
|
2380
2455
|
} = opts;
|
|
2381
2456
|
const priority = opts.priority ?? (priorityField ? buildProjectFieldPriority(priorityField) : buildDisabledPriority());
|
|
2457
|
+
const automaticLifecycle = toWorkflowLifecycleConfig(
|
|
2458
|
+
statusField.name,
|
|
2459
|
+
buildAutomaticStateMappings(statusField)
|
|
2460
|
+
);
|
|
2461
|
+
const defaultBlockerCheckStates = getDefaultBlockerCheckStates(automaticLifecycle);
|
|
2462
|
+
const lifecycle = opts.lifecycle ?? toWorkflowLifecycleConfig(
|
|
2463
|
+
statusField.name,
|
|
2464
|
+
buildAutomaticStateMappings(statusField),
|
|
2465
|
+
{
|
|
2466
|
+
blockerCheckStates: defaultBlockerCheckStates,
|
|
2467
|
+
planningStates: defaultBlockerCheckStates
|
|
2468
|
+
}
|
|
2469
|
+
);
|
|
2382
2470
|
const ghSymphonyDir = join3(cwd, ".gh-symphony");
|
|
2383
2471
|
const environment = opts.environment ?? await detectEnvironment(cwd);
|
|
2384
2472
|
const files = [];
|
|
@@ -2418,6 +2506,7 @@ async function planEcosystem(opts) {
|
|
|
2418
2506
|
})),
|
|
2419
2507
|
projectId: projectDetail.id,
|
|
2420
2508
|
priority,
|
|
2509
|
+
lifecycle,
|
|
2421
2510
|
detectedEnvironment: environment
|
|
2422
2511
|
});
|
|
2423
2512
|
files.push(
|
|
@@ -2469,6 +2558,8 @@ async function planEcosystem(opts) {
|
|
|
2469
2558
|
githubProjectTitle: projectDetail.title,
|
|
2470
2559
|
runtime,
|
|
2471
2560
|
priority,
|
|
2561
|
+
lifecycle,
|
|
2562
|
+
waitStates: deriveWaitStates(statusField, lifecycle),
|
|
2472
2563
|
skillsDir,
|
|
2473
2564
|
skipSkills,
|
|
2474
2565
|
environment,
|
|
@@ -2518,6 +2609,8 @@ async function writeEcosystem(opts) {
|
|
|
2518
2609
|
githubProjectTitle: plan.githubProjectTitle,
|
|
2519
2610
|
runtime: plan.runtime,
|
|
2520
2611
|
priority: plan.priority,
|
|
2612
|
+
lifecycle: plan.lifecycle,
|
|
2613
|
+
waitStates: plan.waitStates,
|
|
2521
2614
|
skillsDir: plan.skillsDir,
|
|
2522
2615
|
skipSkills: plan.skipSkills,
|
|
2523
2616
|
afterCreateHookWritten,
|
|
@@ -2539,9 +2632,20 @@ function formatPrioritySummaryLines(priority) {
|
|
|
2539
2632
|
];
|
|
2540
2633
|
}
|
|
2541
2634
|
const mapping = Object.entries(priority.labels).map(([name, value]) => `${name}=${value}`).join(", ");
|
|
2635
|
+
return ["Priority source labels", `Priority mapping ${mapping || "none"}`];
|
|
2636
|
+
}
|
|
2637
|
+
function formatLifecycleValue(states) {
|
|
2638
|
+
return states.length > 0 ? states.join(", ") : "disabled";
|
|
2639
|
+
}
|
|
2640
|
+
function formatLifecycleSummaryLines(lifecycle, waitStates) {
|
|
2542
2641
|
return [
|
|
2543
|
-
"
|
|
2544
|
-
`
|
|
2642
|
+
"Lifecycle",
|
|
2643
|
+
` Status field ${lifecycle.stateFieldName}`,
|
|
2644
|
+
` Active ${lifecycle.activeStates.join(", ") || "(none)"}`,
|
|
2645
|
+
` Wait ${waitStates.join(", ") || "(none)"}`,
|
|
2646
|
+
` Terminal ${lifecycle.terminalStates.join(", ") || "(none)"}`,
|
|
2647
|
+
` Blocker check ${formatLifecycleValue(lifecycle.blockerCheckStates)}`,
|
|
2648
|
+
` Planning ${formatLifecycleValue(lifecycle.planningStates)}`
|
|
2545
2649
|
];
|
|
2546
2650
|
}
|
|
2547
2651
|
function printEcosystemSummary(result, workflowPath, opts) {
|
|
@@ -2554,6 +2658,10 @@ function printEcosystemSummary(result, workflowPath, opts) {
|
|
|
2554
2658
|
lines.push(`Runtime ${result.runtime}`);
|
|
2555
2659
|
lines.push(...formatPrioritySummaryLines(result.priority));
|
|
2556
2660
|
lines.push("");
|
|
2661
|
+
lines.push(
|
|
2662
|
+
...formatLifecycleSummaryLines(result.lifecycle, result.waitStates)
|
|
2663
|
+
);
|
|
2664
|
+
lines.push("");
|
|
2557
2665
|
lines.push("Generated files");
|
|
2558
2666
|
lines.push(` \u2713 WORKFLOW.md ${relWorkflow}`);
|
|
2559
2667
|
if (result.afterCreateHookWritten) {
|
|
@@ -2608,6 +2716,13 @@ function renderDryRunPreview(workflowPath, workflowPlan, ecosystemPlan) {
|
|
|
2608
2716
|
lines.push(`Runtime ${ecosystemPlan.runtime}`);
|
|
2609
2717
|
lines.push(...formatPrioritySummaryLines(ecosystemPlan.priority));
|
|
2610
2718
|
lines.push("");
|
|
2719
|
+
lines.push(
|
|
2720
|
+
...formatLifecycleSummaryLines(
|
|
2721
|
+
ecosystemPlan.lifecycle,
|
|
2722
|
+
ecosystemPlan.waitStates
|
|
2723
|
+
)
|
|
2724
|
+
);
|
|
2725
|
+
lines.push("");
|
|
2611
2726
|
lines.push("Planned file changes");
|
|
2612
2727
|
lines.push(
|
|
2613
2728
|
` ${statusIcon[workflowPlan.status]} ${workflowPlan.status.padEnd(9)} WORKFLOW.md ${relWorkflow}`
|
|
@@ -2737,6 +2852,13 @@ Run without --non-interactive for manual mapping.
|
|
|
2737
2852
|
process.exitCode = 1;
|
|
2738
2853
|
return;
|
|
2739
2854
|
}
|
|
2855
|
+
const defaultBlockerCheckStates = getDefaultBlockerCheckStates(
|
|
2856
|
+
toWorkflowLifecycleConfig(statusField.name, mappings)
|
|
2857
|
+
);
|
|
2858
|
+
const lifecycle = toWorkflowLifecycleConfig(statusField.name, mappings, {
|
|
2859
|
+
blockerCheckStates: defaultBlockerCheckStates,
|
|
2860
|
+
planningStates: defaultBlockerCheckStates
|
|
2861
|
+
});
|
|
2740
2862
|
const outputPath = resolve(flags.output ?? "WORKFLOW.md");
|
|
2741
2863
|
const { workflowPlan, ecosystemPlan } = await planWorkflowArtifacts({
|
|
2742
2864
|
cwd: process.cwd(),
|
|
@@ -2747,6 +2869,7 @@ Run without --non-interactive for manual mapping.
|
|
|
2747
2869
|
priority,
|
|
2748
2870
|
includePriorityTemplates: !autoPriorityField,
|
|
2749
2871
|
mappings,
|
|
2872
|
+
lifecycle,
|
|
2750
2873
|
runtime,
|
|
2751
2874
|
skipSkills: flags.skipSkills,
|
|
2752
2875
|
skipContext: flags.skipContext
|
|
@@ -2771,6 +2894,7 @@ Run without --non-interactive for manual mapping.
|
|
|
2771
2894
|
priorityField: autoPriorityField,
|
|
2772
2895
|
priority,
|
|
2773
2896
|
includePriorityTemplates: !autoPriorityField,
|
|
2897
|
+
lifecycle,
|
|
2774
2898
|
runtime,
|
|
2775
2899
|
skipSkills: flags.skipSkills,
|
|
2776
2900
|
skipContext: flags.skipContext
|
|
@@ -2847,7 +2971,7 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2847
2971
|
}
|
|
2848
2972
|
const selectedGithubProjectId = await abortIfCancelled(
|
|
2849
2973
|
p.select({
|
|
2850
|
-
message: "Step 2/
|
|
2974
|
+
message: "Step 2/5 \u2014 Select a GitHub Project board:",
|
|
2851
2975
|
options: projects.map((proj) => ({
|
|
2852
2976
|
value: proj.id,
|
|
2853
2977
|
label: `${proj.owner.login}/${proj.title}`,
|
|
@@ -2882,12 +3006,7 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2882
3006
|
projectDetail.linkedRepositories
|
|
2883
3007
|
);
|
|
2884
3008
|
const mappings = await promptStateMappings(statusField, {
|
|
2885
|
-
stepLabel: "Step 3/
|
|
2886
|
-
});
|
|
2887
|
-
const { priority, priorityField } = await promptPriorityConfig({
|
|
2888
|
-
priorityResolution,
|
|
2889
|
-
labelNames: priorityLabelNames,
|
|
2890
|
-
stepLabel: "Step 4/4"
|
|
3009
|
+
stepLabel: "Step 3/5"
|
|
2891
3010
|
});
|
|
2892
3011
|
const validation = validateStateMapping(mappings);
|
|
2893
3012
|
if (!validation.valid) {
|
|
@@ -2901,6 +3020,19 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2901
3020
|
for (const warn of validation.warnings) {
|
|
2902
3021
|
p.log.warn(` \u26A0 ${warn}`);
|
|
2903
3022
|
}
|
|
3023
|
+
const lifecycleBase = toWorkflowLifecycleConfig(statusField.name, mappings);
|
|
3024
|
+
const blockerCheckStates = await promptBlockerCheck(lifecycleBase, {
|
|
3025
|
+
stepLabel: "Step 4/5"
|
|
3026
|
+
});
|
|
3027
|
+
const lifecycle = toWorkflowLifecycleConfig(statusField.name, mappings, {
|
|
3028
|
+
blockerCheckStates,
|
|
3029
|
+
planningStates: blockerCheckStates
|
|
3030
|
+
});
|
|
3031
|
+
const { priority, priorityField } = await promptPriorityConfig({
|
|
3032
|
+
priorityResolution,
|
|
3033
|
+
labelNames: priorityLabelNames,
|
|
3034
|
+
stepLabel: "Step 5/5"
|
|
3035
|
+
});
|
|
2904
3036
|
const outputPath = resolve(flags.output ?? "WORKFLOW.md");
|
|
2905
3037
|
const { workflowPlan, ecosystemPlan } = await planWorkflowArtifacts({
|
|
2906
3038
|
cwd: process.cwd(),
|
|
@@ -2911,6 +3043,7 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2911
3043
|
priority,
|
|
2912
3044
|
includePriorityTemplates: priority.source === "disabled",
|
|
2913
3045
|
mappings,
|
|
3046
|
+
lifecycle,
|
|
2914
3047
|
runtime,
|
|
2915
3048
|
skipSkills: flags.skipSkills,
|
|
2916
3049
|
skipContext: flags.skipContext
|
|
@@ -2927,6 +3060,7 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2927
3060
|
priorityField,
|
|
2928
3061
|
priority,
|
|
2929
3062
|
includePriorityTemplates: priority.source === "disabled",
|
|
3063
|
+
lifecycle,
|
|
2930
3064
|
runtime,
|
|
2931
3065
|
skipSkills: flags.skipSkills,
|
|
2932
3066
|
skipContext: flags.skipContext
|
|
@@ -2938,6 +3072,7 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2938
3072
|
}
|
|
2939
3073
|
|
|
2940
3074
|
export {
|
|
3075
|
+
toWorkflowLifecycleConfig,
|
|
2941
3076
|
validateStateMapping,
|
|
2942
3077
|
abortIfCancelled,
|
|
2943
3078
|
workflow_init_default,
|
|
@@ -2947,6 +3082,7 @@ export {
|
|
|
2947
3082
|
collectPriorityLabelNames,
|
|
2948
3083
|
promptPriorityConfig,
|
|
2949
3084
|
promptStateMappings,
|
|
3085
|
+
promptBlockerCheck,
|
|
2950
3086
|
planWorkflowArtifacts,
|
|
2951
3087
|
writeWorkflowPlan,
|
|
2952
3088
|
writeEcosystem,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
workflow_init_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GL55AKBI.js";
|
|
5
5
|
import {
|
|
6
6
|
fetchGithubProjectIssueByRepositoryAndNumber,
|
|
7
7
|
inspectManagedProjectSelection,
|
|
8
8
|
resolveTrackerAdapter
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VHEGRYK7.js";
|
|
10
10
|
import {
|
|
11
11
|
GitHubApiError,
|
|
12
12
|
createClient,
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
getGhTokenWithSource,
|
|
15
15
|
getProjectDetail,
|
|
16
16
|
validateGitHubToken
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-SMNIGNS3.js";
|
|
18
18
|
import {
|
|
19
19
|
buildPromptVariables,
|
|
20
20
|
parseWorkflowMarkdown,
|
|
21
21
|
renderPrompt
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5HQLPZR5.js";
|
|
23
23
|
import {
|
|
24
24
|
loadActiveProjectConfig
|
|
25
25
|
} from "./chunk-4ICDSQCJ.js";
|
|
@@ -705,7 +705,9 @@ async function loadLinearIssue(issueIdentifier, workflow, options) {
|
|
|
705
705
|
repository: projectConfig.repository,
|
|
706
706
|
tracker: projectConfig.tracker
|
|
707
707
|
};
|
|
708
|
-
const trackerAdapter = workflowCommandDependencies.resolveTrackerAdapter(
|
|
708
|
+
const trackerAdapter = workflowCommandDependencies.resolveTrackerAdapter(
|
|
709
|
+
projectConfig.tracker
|
|
710
|
+
);
|
|
709
711
|
const [issue] = await trackerAdapter.fetchIssueStatesByIds(
|
|
710
712
|
orchestratorProject,
|
|
711
713
|
[issueIdentifier.trim().toUpperCase()],
|
|
@@ -752,6 +754,7 @@ function validateWorkflow(workflowPath, markdown) {
|
|
|
752
754
|
activeStates: workflow.lifecycle.activeStates,
|
|
753
755
|
terminalStates: workflow.lifecycle.terminalStates,
|
|
754
756
|
blockerCheckStates: workflow.lifecycle.blockerCheckStates,
|
|
757
|
+
planningStates: workflow.lifecycle.planningStates,
|
|
755
758
|
pollingIntervalMs: workflow.polling.intervalMs,
|
|
756
759
|
workspaceRoot: workflow.workspace.root,
|
|
757
760
|
agentCommand: workflow.agentCommand,
|
|
@@ -791,6 +794,7 @@ Lifecycle
|
|
|
791
794
|
active_states=${report.summary.activeStates.join(", ") || "(none)"}
|
|
792
795
|
terminal_states=${report.summary.terminalStates.join(", ") || "(none)"}
|
|
793
796
|
blocker_check_states=${report.summary.blockerCheckStates.join(", ") || "(none)"}
|
|
797
|
+
planning_states=${report.summary.planningStates.join(", ") || "(none)"}
|
|
794
798
|
|
|
795
799
|
Runtime
|
|
796
800
|
polling.interval_ms=${report.summary.pollingIntervalMs}
|