@gh-symphony/cli 0.1.4 → 0.2.2
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/README.md +87 -0
- package/dist/{chunk-HT3FAJAO.js → chunk-27UZ6KX2.js} +273 -10
- package/dist/{chunk-EWTMSDCE.js → chunk-3SKN5L3I.js} +260 -18
- package/dist/{chunk-WOVNN5NW.js → chunk-4ICDSQCJ.js} +1 -0
- package/dist/{chunk-DW63WPRE.js → chunk-6PFFGP7S.js} +18 -3
- package/dist/{chunk-Z3NZOPLZ.js → chunk-BOM2BYZQ.js} +43 -0
- package/dist/{chunk-E7OCBNB2.js → chunk-FAU72YC2.js} +1 -1
- package/dist/{chunk-RHLUIMBN.js → chunk-PLBG7TZA.js} +306 -30
- package/dist/{chunk-6I753NYO.js → chunk-RZ3WO7OV.js} +1 -1
- package/dist/{repo-IH6UWE4H.js → chunk-X4QSP3AX.js} +5443 -6207
- package/dist/{config-cmd-2ADPUYWA.js → config-cmd-AOZVS6GU.js} +1 -1
- package/dist/{doctor-I32MANQ4.js → doctor-GDZSGJIT.js} +602 -26
- package/dist/index.js +12 -8
- package/dist/repo-SWEUWY4H.js +2693 -0
- package/dist/{setup-UJC2WYHQ.js → setup-XNOSJ3RX.js} +35 -32
- package/dist/{upgrade-XYHCUGHT.js → upgrade-ZWUAJLHK.js} +2 -2
- package/dist/{version-B2AYYGLM.js → version-PLQK6X2P.js} +1 -1
- package/dist/worker-entry.js +77 -9
- package/dist/{workflow-WSXHMO5B.js → workflow-2ERPNGRB.js} +7 -6
- package/package.json +3 -3
- package/dist/chunk-YIARPBOR.js +0 -1648
|
@@ -7,15 +7,16 @@ import {
|
|
|
7
7
|
discoverUserProjects,
|
|
8
8
|
getGhTokenWithSource,
|
|
9
9
|
getProjectDetail,
|
|
10
|
+
listRepositoryLabels,
|
|
10
11
|
listUserProjects,
|
|
11
12
|
resolveGitHubAuth,
|
|
12
13
|
validateToken
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BOM2BYZQ.js";
|
|
14
15
|
import {
|
|
15
16
|
formatClaudePreflightText,
|
|
16
17
|
resolveClaudeCommandBinary,
|
|
17
18
|
runClaudePreflight
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-3SKN5L3I.js";
|
|
19
20
|
|
|
20
21
|
// src/mapping/smart-defaults.ts
|
|
21
22
|
var ROLE_PATTERNS = [
|
|
@@ -347,9 +348,7 @@ function buildFrontMatter(input) {
|
|
|
347
348
|
lines.push(" kind: github-project");
|
|
348
349
|
lines.push(` project_id: ${input.projectId}`);
|
|
349
350
|
lines.push(` state_field: ${input.stateFieldName}`);
|
|
350
|
-
|
|
351
|
-
lines.push(` priority_field: ${input.priorityFieldName}`);
|
|
352
|
-
}
|
|
351
|
+
lines.push(...buildPriorityFrontMatter(input));
|
|
353
352
|
if (input.lifecycle.activeStates.length > 0) {
|
|
354
353
|
lines.push(" active_states:");
|
|
355
354
|
for (const state of input.lifecycle.activeStates) {
|
|
@@ -381,6 +380,67 @@ function buildFrontMatter(input) {
|
|
|
381
380
|
lines.push(...buildRuntimeFrontMatter(input.runtime));
|
|
382
381
|
return lines.join("\n") + "\n";
|
|
383
382
|
}
|
|
383
|
+
function buildPriorityFrontMatter(input) {
|
|
384
|
+
const lines = [];
|
|
385
|
+
if (!input.priority) {
|
|
386
|
+
return lines;
|
|
387
|
+
}
|
|
388
|
+
if (input.priority.source === "disabled") {
|
|
389
|
+
lines.push(
|
|
390
|
+
" # Priority dispatch is disabled until an operator chooses one explicit source."
|
|
391
|
+
);
|
|
392
|
+
} else {
|
|
393
|
+
lines.push(
|
|
394
|
+
" # Priority is explicit. Numbers below are editable policy (lower = higher priority)."
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
lines.push(
|
|
398
|
+
" # See docs/adr/2026-05-18_explicit-dispatch-priority-mappings.md"
|
|
399
|
+
);
|
|
400
|
+
lines.push(" priority:");
|
|
401
|
+
if (input.priority.source === "project-field") {
|
|
402
|
+
lines.push(" source: project-field");
|
|
403
|
+
lines.push(` field: ${formatYamlScalar(input.priority.field)}`);
|
|
404
|
+
lines.push(" values:");
|
|
405
|
+
for (const [name, value] of Object.entries(input.priority.values)) {
|
|
406
|
+
lines.push(` ${formatYamlKey(name)}: ${value}`);
|
|
407
|
+
}
|
|
408
|
+
return lines;
|
|
409
|
+
}
|
|
410
|
+
if (input.priority.source === "labels") {
|
|
411
|
+
lines.push(" source: labels");
|
|
412
|
+
lines.push(" labels:");
|
|
413
|
+
for (const [name, value] of Object.entries(input.priority.labels)) {
|
|
414
|
+
lines.push(` ${formatYamlKey(name)}: ${value}`);
|
|
415
|
+
}
|
|
416
|
+
return lines;
|
|
417
|
+
}
|
|
418
|
+
lines.push(" source: disabled");
|
|
419
|
+
if (input.includePriorityTemplates) {
|
|
420
|
+
lines.push("");
|
|
421
|
+
lines.push(" # Optional template: project-field priority source.");
|
|
422
|
+
lines.push(" # priority:");
|
|
423
|
+
lines.push(" # source: project-field");
|
|
424
|
+
lines.push(" # field: Priority");
|
|
425
|
+
lines.push(" # values:");
|
|
426
|
+
lines.push(" # Urgent: 0");
|
|
427
|
+
lines.push(" # High: 1");
|
|
428
|
+
lines.push("");
|
|
429
|
+
lines.push(" # Optional template: labels priority source.");
|
|
430
|
+
lines.push(" # priority:");
|
|
431
|
+
lines.push(" # source: labels");
|
|
432
|
+
lines.push(" # labels:");
|
|
433
|
+
lines.push(" # P0: 0");
|
|
434
|
+
lines.push(" # P1: 1");
|
|
435
|
+
}
|
|
436
|
+
return lines;
|
|
437
|
+
}
|
|
438
|
+
function formatYamlScalar(value) {
|
|
439
|
+
return JSON.stringify(value);
|
|
440
|
+
}
|
|
441
|
+
function formatYamlKey(value) {
|
|
442
|
+
return JSON.stringify(value);
|
|
443
|
+
}
|
|
384
444
|
function buildPromptBody(input) {
|
|
385
445
|
const statusMap = generateStatusMapWithDescriptions(input.mappings);
|
|
386
446
|
const validationGuidance = buildRepositoryValidationGuidance(
|
|
@@ -917,11 +977,7 @@ function generateReferenceWorkflow(input) {
|
|
|
917
977
|
lines.push(" kind: github-project");
|
|
918
978
|
lines.push(` project_id: ${input.projectId}`);
|
|
919
979
|
lines.push(" state_field: Status");
|
|
920
|
-
|
|
921
|
-
lines.push(` priority_field: ${input.priorityFieldName}`);
|
|
922
|
-
} else {
|
|
923
|
-
lines.push(" # priority_field: Priority");
|
|
924
|
-
}
|
|
980
|
+
lines.push(...buildReferencePriorityLines(input.priority));
|
|
925
981
|
lines.push("");
|
|
926
982
|
const activeColumns = input.statusColumns.filter((c) => c.role === "active");
|
|
927
983
|
const waitColumns = input.statusColumns.filter((c) => c.role === "wait");
|
|
@@ -952,6 +1008,22 @@ function generateReferenceWorkflow(input) {
|
|
|
952
1008
|
lines.push(" blocker_check_states: [{first active state}]");
|
|
953
1009
|
}
|
|
954
1010
|
lines.push("");
|
|
1011
|
+
lines.push("# Linear tracker example:");
|
|
1012
|
+
lines.push("# tracker:");
|
|
1013
|
+
lines.push("# kind: linear");
|
|
1014
|
+
lines.push("# endpoint: https://api.linear.app/graphql");
|
|
1015
|
+
lines.push("# api_key: $LINEAR_API_KEY");
|
|
1016
|
+
lines.push("# project_slug: symphony-0c79b11b75ea");
|
|
1017
|
+
lines.push("# active_states:");
|
|
1018
|
+
lines.push("# - Todo");
|
|
1019
|
+
lines.push("# - In Progress");
|
|
1020
|
+
lines.push("# terminal_states:");
|
|
1021
|
+
lines.push("# - Done");
|
|
1022
|
+
lines.push("# - Canceled");
|
|
1023
|
+
lines.push("# - Duplicate");
|
|
1024
|
+
lines.push("# Linear uses repository-local polling; gh-symphony does not provide");
|
|
1025
|
+
lines.push("# a Linear webhook setup command.");
|
|
1026
|
+
lines.push("");
|
|
955
1027
|
lines.push("polling:");
|
|
956
1028
|
lines.push(" interval_ms: 30000");
|
|
957
1029
|
lines.push("");
|
|
@@ -1210,6 +1282,58 @@ function generateReferenceWorkflow(input) {
|
|
|
1210
1282
|
lines.push("");
|
|
1211
1283
|
return lines.join("\n");
|
|
1212
1284
|
}
|
|
1285
|
+
function buildReferencePriorityLines(priority) {
|
|
1286
|
+
const lines = [];
|
|
1287
|
+
if (priority?.source === "project-field" || priority?.source === "labels") {
|
|
1288
|
+
lines.push(
|
|
1289
|
+
" # Priority is explicit. Numbers below are editable policy (lower = higher priority)."
|
|
1290
|
+
);
|
|
1291
|
+
} else {
|
|
1292
|
+
lines.push(
|
|
1293
|
+
" # Priority dispatch is disabled until an operator chooses one explicit source."
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
lines.push(
|
|
1297
|
+
" # See docs/adr/2026-05-18_explicit-dispatch-priority-mappings.md"
|
|
1298
|
+
);
|
|
1299
|
+
if (priority?.source === "project-field") {
|
|
1300
|
+
lines.push(" priority:");
|
|
1301
|
+
lines.push(" source: project-field");
|
|
1302
|
+
lines.push(` field: ${JSON.stringify(priority.field)}`);
|
|
1303
|
+
lines.push(" values:");
|
|
1304
|
+
for (const [name, value] of Object.entries(priority.values)) {
|
|
1305
|
+
lines.push(` ${JSON.stringify(name)}: ${value}`);
|
|
1306
|
+
}
|
|
1307
|
+
return lines;
|
|
1308
|
+
}
|
|
1309
|
+
if (priority?.source === "labels") {
|
|
1310
|
+
lines.push(" priority:");
|
|
1311
|
+
lines.push(" source: labels");
|
|
1312
|
+
lines.push(" labels:");
|
|
1313
|
+
for (const [name, value] of Object.entries(priority.labels)) {
|
|
1314
|
+
lines.push(` ${JSON.stringify(name)}: ${value}`);
|
|
1315
|
+
}
|
|
1316
|
+
return lines;
|
|
1317
|
+
}
|
|
1318
|
+
lines.push(" priority:");
|
|
1319
|
+
lines.push(" source: disabled");
|
|
1320
|
+
lines.push("");
|
|
1321
|
+
lines.push(" # Optional template: project-field priority source.");
|
|
1322
|
+
lines.push(" # priority:");
|
|
1323
|
+
lines.push(" # source: project-field");
|
|
1324
|
+
lines.push(" # field: Priority");
|
|
1325
|
+
lines.push(" # values:");
|
|
1326
|
+
lines.push(" # Urgent: 0");
|
|
1327
|
+
lines.push(" # High: 1");
|
|
1328
|
+
lines.push("");
|
|
1329
|
+
lines.push(" # Optional template: labels priority source.");
|
|
1330
|
+
lines.push(" # priority:");
|
|
1331
|
+
lines.push(" # source: labels");
|
|
1332
|
+
lines.push(" # labels:");
|
|
1333
|
+
lines.push(" # P0: 0");
|
|
1334
|
+
lines.push(" # P1: 1");
|
|
1335
|
+
return lines;
|
|
1336
|
+
}
|
|
1213
1337
|
function resolveRoleAction(role) {
|
|
1214
1338
|
switch (role) {
|
|
1215
1339
|
case "active":
|
|
@@ -2021,6 +2145,35 @@ function resolvePriorityField(projectDetail, statusField) {
|
|
|
2021
2145
|
}
|
|
2022
2146
|
return { field: null, ambiguous: [] };
|
|
2023
2147
|
}
|
|
2148
|
+
function buildProjectFieldPriority(field) {
|
|
2149
|
+
return {
|
|
2150
|
+
source: "project-field",
|
|
2151
|
+
field: field.name,
|
|
2152
|
+
values: Object.fromEntries(
|
|
2153
|
+
field.options.map((option, index) => [option.name, index])
|
|
2154
|
+
)
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
function buildDisabledPriority() {
|
|
2158
|
+
return { source: "disabled" };
|
|
2159
|
+
}
|
|
2160
|
+
async function collectPriorityLabelNames(client, repositories) {
|
|
2161
|
+
const labels = /* @__PURE__ */ new Set();
|
|
2162
|
+
for (const repository of repositories) {
|
|
2163
|
+
try {
|
|
2164
|
+
const repoLabels = await listRepositoryLabels(
|
|
2165
|
+
client,
|
|
2166
|
+
repository.owner,
|
|
2167
|
+
repository.name
|
|
2168
|
+
);
|
|
2169
|
+
for (const label of repoLabels) {
|
|
2170
|
+
labels.add(label.name);
|
|
2171
|
+
}
|
|
2172
|
+
} catch {
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
return [...labels].sort((a, b) => a.localeCompare(b));
|
|
2176
|
+
}
|
|
2024
2177
|
async function promptPriorityField(priorityCandidates, options) {
|
|
2025
2178
|
if (priorityCandidates.length === 0) {
|
|
2026
2179
|
return null;
|
|
@@ -2037,7 +2190,7 @@ async function promptPriorityField(priorityCandidates, options) {
|
|
|
2037
2190
|
{
|
|
2038
2191
|
value: "__skip_priority_field__",
|
|
2039
2192
|
label: "Skip priority-aware dispatch",
|
|
2040
|
-
hint: "
|
|
2193
|
+
hint: "Write source: disabled"
|
|
2041
2194
|
}
|
|
2042
2195
|
]
|
|
2043
2196
|
})
|
|
@@ -2047,6 +2200,97 @@ async function promptPriorityField(priorityCandidates, options) {
|
|
|
2047
2200
|
}
|
|
2048
2201
|
return priorityCandidates.find((field) => field.id === selectedFieldId) ?? null;
|
|
2049
2202
|
}
|
|
2203
|
+
async function promptProjectFieldPriorityValues(field) {
|
|
2204
|
+
const values = {};
|
|
2205
|
+
for (const [index, option] of field.options.entries()) {
|
|
2206
|
+
const rawValue = await abortIfCancelled(
|
|
2207
|
+
p.text({
|
|
2208
|
+
message: `Priority value for option "${option.name}"`,
|
|
2209
|
+
placeholder: String(index),
|
|
2210
|
+
initialValue: String(index),
|
|
2211
|
+
validate: validatePriorityInteger
|
|
2212
|
+
})
|
|
2213
|
+
);
|
|
2214
|
+
values[option.name] = Number(rawValue);
|
|
2215
|
+
}
|
|
2216
|
+
return values;
|
|
2217
|
+
}
|
|
2218
|
+
async function promptPriorityConfig(input) {
|
|
2219
|
+
const hasProjectField = Boolean(input.priorityResolution.field) || input.priorityResolution.ambiguous.length > 0;
|
|
2220
|
+
const hasLabels = input.labelNames.length > 0;
|
|
2221
|
+
const selectedSource = await abortIfCancelled(
|
|
2222
|
+
p.select({
|
|
2223
|
+
message: `${input.stepLabel ?? "Priority"} \u2014 Choose one priority source:`,
|
|
2224
|
+
options: [
|
|
2225
|
+
...hasProjectField ? [
|
|
2226
|
+
{
|
|
2227
|
+
value: "project-field",
|
|
2228
|
+
label: "GitHub Project field",
|
|
2229
|
+
hint: "Map single-select options to explicit numbers"
|
|
2230
|
+
}
|
|
2231
|
+
] : [],
|
|
2232
|
+
...hasLabels ? [
|
|
2233
|
+
{
|
|
2234
|
+
value: "labels",
|
|
2235
|
+
label: "GitHub labels",
|
|
2236
|
+
hint: "Map existing repository labels to explicit numbers"
|
|
2237
|
+
}
|
|
2238
|
+
] : [],
|
|
2239
|
+
{
|
|
2240
|
+
value: "disabled",
|
|
2241
|
+
label: "Disabled",
|
|
2242
|
+
hint: "Write source: disabled"
|
|
2243
|
+
}
|
|
2244
|
+
]
|
|
2245
|
+
})
|
|
2246
|
+
);
|
|
2247
|
+
if (selectedSource === "disabled") {
|
|
2248
|
+
return { priority: buildDisabledPriority(), priorityField: null };
|
|
2249
|
+
}
|
|
2250
|
+
if (selectedSource === "labels") {
|
|
2251
|
+
const selectedLabels = await abortIfCancelled(
|
|
2252
|
+
p.multiselect({
|
|
2253
|
+
message: "Select priority labels to map:",
|
|
2254
|
+
options: input.labelNames.map((label) => ({
|
|
2255
|
+
value: label,
|
|
2256
|
+
label
|
|
2257
|
+
})),
|
|
2258
|
+
required: true
|
|
2259
|
+
})
|
|
2260
|
+
);
|
|
2261
|
+
const labels = {};
|
|
2262
|
+
for (const [index, label] of selectedLabels.entries()) {
|
|
2263
|
+
const rawValue = await abortIfCancelled(
|
|
2264
|
+
p.text({
|
|
2265
|
+
message: `Priority value for label "${label}"`,
|
|
2266
|
+
placeholder: String(index),
|
|
2267
|
+
initialValue: String(index),
|
|
2268
|
+
validate: validatePriorityInteger
|
|
2269
|
+
})
|
|
2270
|
+
);
|
|
2271
|
+
labels[label] = Number(rawValue);
|
|
2272
|
+
}
|
|
2273
|
+
return { priority: { source: "labels", labels }, priorityField: null };
|
|
2274
|
+
}
|
|
2275
|
+
const priorityField = input.priorityResolution.ambiguous.length > 0 ? await promptPriorityField(input.priorityResolution.ambiguous, {
|
|
2276
|
+
stepLabel: "Priority field"
|
|
2277
|
+
}) : input.priorityResolution.field;
|
|
2278
|
+
if (!priorityField) {
|
|
2279
|
+
return { priority: buildDisabledPriority(), priorityField: null };
|
|
2280
|
+
}
|
|
2281
|
+
return {
|
|
2282
|
+
priority: {
|
|
2283
|
+
source: "project-field",
|
|
2284
|
+
field: priorityField.name,
|
|
2285
|
+
values: await promptProjectFieldPriorityValues(priorityField)
|
|
2286
|
+
},
|
|
2287
|
+
priorityField
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
function validatePriorityInteger(value) {
|
|
2291
|
+
const trimmed = value.trim();
|
|
2292
|
+
return trimmed !== "" && Number.isInteger(Number(trimmed)) ? void 0 : "Enter an integer.";
|
|
2293
|
+
}
|
|
2050
2294
|
async function promptStateMappings(statusField, options) {
|
|
2051
2295
|
const mappings = {};
|
|
2052
2296
|
const inferred = inferAllStateRoles(statusField.options.map((o) => o.name));
|
|
@@ -2076,10 +2320,12 @@ async function promptStateMappings(statusField, options) {
|
|
|
2076
2320
|
}
|
|
2077
2321
|
async function planWorkflowArtifacts(opts) {
|
|
2078
2322
|
const environment = opts.environment ?? await detectEnvironment(opts.cwd);
|
|
2323
|
+
const priority = opts.priority ?? (opts.priorityField ? buildProjectFieldPriority(opts.priorityField) : buildDisabledPriority());
|
|
2079
2324
|
const workflowMd = generateWorkflowMarkdown({
|
|
2080
2325
|
projectId: opts.projectDetail.id,
|
|
2081
2326
|
stateFieldName: opts.statusField.name,
|
|
2082
|
-
|
|
2327
|
+
priority,
|
|
2328
|
+
includePriorityTemplates: opts.includePriorityTemplates ?? priority.source === "disabled",
|
|
2083
2329
|
mappings: opts.mappings,
|
|
2084
2330
|
lifecycle: toWorkflowLifecycleConfig(opts.statusField.name, opts.mappings),
|
|
2085
2331
|
runtime: opts.runtime,
|
|
@@ -2096,6 +2342,8 @@ async function planWorkflowArtifacts(opts) {
|
|
|
2096
2342
|
projectDetail: opts.projectDetail,
|
|
2097
2343
|
statusField: opts.statusField,
|
|
2098
2344
|
priorityField: opts.priorityField,
|
|
2345
|
+
priority,
|
|
2346
|
+
includePriorityTemplates: opts.includePriorityTemplates ?? priority.source === "disabled",
|
|
2099
2347
|
runtime: opts.runtime,
|
|
2100
2348
|
skipSkills: opts.skipSkills,
|
|
2101
2349
|
skipContext: opts.skipContext,
|
|
@@ -2130,6 +2378,7 @@ async function planEcosystem(opts) {
|
|
|
2130
2378
|
skipSkills,
|
|
2131
2379
|
skipContext
|
|
2132
2380
|
} = opts;
|
|
2381
|
+
const priority = opts.priority ?? (priorityField ? buildProjectFieldPriority(priorityField) : buildDisabledPriority());
|
|
2133
2382
|
const ghSymphonyDir = join3(cwd, ".gh-symphony");
|
|
2134
2383
|
const environment = opts.environment ?? await detectEnvironment(cwd);
|
|
2135
2384
|
const files = [];
|
|
@@ -2168,7 +2417,7 @@ async function planEcosystem(opts) {
|
|
|
2168
2417
|
role: null
|
|
2169
2418
|
})),
|
|
2170
2419
|
projectId: projectDetail.id,
|
|
2171
|
-
|
|
2420
|
+
priority,
|
|
2172
2421
|
detectedEnvironment: environment
|
|
2173
2422
|
});
|
|
2174
2423
|
files.push(
|
|
@@ -2219,7 +2468,7 @@ async function planEcosystem(opts) {
|
|
|
2219
2468
|
projectId: projectDetail.id,
|
|
2220
2469
|
githubProjectTitle: projectDetail.title,
|
|
2221
2470
|
runtime,
|
|
2222
|
-
|
|
2471
|
+
priority,
|
|
2223
2472
|
skillsDir,
|
|
2224
2473
|
skipSkills,
|
|
2225
2474
|
environment,
|
|
@@ -2268,7 +2517,7 @@ async function writeEcosystem(opts) {
|
|
|
2268
2517
|
projectId: plan.projectId,
|
|
2269
2518
|
githubProjectTitle: plan.githubProjectTitle,
|
|
2270
2519
|
runtime: plan.runtime,
|
|
2271
|
-
|
|
2520
|
+
priority: plan.priority,
|
|
2272
2521
|
skillsDir: plan.skillsDir,
|
|
2273
2522
|
skipSkills: plan.skipSkills,
|
|
2274
2523
|
afterCreateHookWritten,
|
|
@@ -2278,6 +2527,23 @@ async function writeEcosystem(opts) {
|
|
|
2278
2527
|
skillsSkipped: skillsSkipped.sort()
|
|
2279
2528
|
};
|
|
2280
2529
|
}
|
|
2530
|
+
function formatPrioritySummaryLines(priority) {
|
|
2531
|
+
if (priority.source === "disabled") {
|
|
2532
|
+
return ["Priority source disabled"];
|
|
2533
|
+
}
|
|
2534
|
+
if (priority.source === "project-field") {
|
|
2535
|
+
const mapping2 = Object.entries(priority.values).map(([name, value]) => `${name}=${value}`).join(", ");
|
|
2536
|
+
return [
|
|
2537
|
+
"Priority source project-field",
|
|
2538
|
+
`Priority mapping ${priority.field}: ${mapping2 || "none"}`
|
|
2539
|
+
];
|
|
2540
|
+
}
|
|
2541
|
+
const mapping = Object.entries(priority.labels).map(([name, value]) => `${name}=${value}`).join(", ");
|
|
2542
|
+
return [
|
|
2543
|
+
"Priority source labels",
|
|
2544
|
+
`Priority mapping ${mapping || "none"}`
|
|
2545
|
+
];
|
|
2546
|
+
}
|
|
2281
2547
|
function printEcosystemSummary(result, workflowPath, opts) {
|
|
2282
2548
|
const cwd = process.cwd();
|
|
2283
2549
|
const relWorkflow = relative(cwd, workflowPath) || "WORKFLOW.md";
|
|
@@ -2286,9 +2552,7 @@ function printEcosystemSummary(result, workflowPath, opts) {
|
|
|
2286
2552
|
`GitHub Project ${result.githubProjectTitle} (${result.projectId})`
|
|
2287
2553
|
);
|
|
2288
2554
|
lines.push(`Runtime ${result.runtime}`);
|
|
2289
|
-
|
|
2290
|
-
lines.push(`Priority field ${result.priorityFieldName}`);
|
|
2291
|
-
}
|
|
2555
|
+
lines.push(...formatPrioritySummaryLines(result.priority));
|
|
2292
2556
|
lines.push("");
|
|
2293
2557
|
lines.push("Generated files");
|
|
2294
2558
|
lines.push(` \u2713 WORKFLOW.md ${relWorkflow}`);
|
|
@@ -2342,9 +2606,7 @@ function renderDryRunPreview(workflowPath, workflowPlan, ecosystemPlan) {
|
|
|
2342
2606
|
`GitHub Project ${ecosystemPlan.githubProjectTitle} (${ecosystemPlan.projectId})`
|
|
2343
2607
|
);
|
|
2344
2608
|
lines.push(`Runtime ${ecosystemPlan.runtime}`);
|
|
2345
|
-
|
|
2346
|
-
lines.push(`Priority field ${ecosystemPlan.priorityFieldName}`);
|
|
2347
|
-
}
|
|
2609
|
+
lines.push(...formatPrioritySummaryLines(ecosystemPlan.priority));
|
|
2348
2610
|
lines.push("");
|
|
2349
2611
|
lines.push("Planned file changes");
|
|
2350
2612
|
lines.push(
|
|
@@ -2372,7 +2634,7 @@ function buildDryRunJsonResult(workflowPath, workflowPlan, ecosystemPlan) {
|
|
|
2372
2634
|
projectId: ecosystemPlan.projectId,
|
|
2373
2635
|
githubProjectTitle: ecosystemPlan.githubProjectTitle,
|
|
2374
2636
|
runtime: ecosystemPlan.runtime,
|
|
2375
|
-
|
|
2637
|
+
priority: ecosystemPlan.priority,
|
|
2376
2638
|
files: [workflowPlan, ...ecosystemPlan.files].map((file) => ({
|
|
2377
2639
|
path: file.path,
|
|
2378
2640
|
label: file.label,
|
|
@@ -2460,10 +2722,11 @@ async function runNonInteractive(flags, options) {
|
|
|
2460
2722
|
const { field: autoPriorityField, ambiguous: ambiguousPriorityFields } = resolvePriorityField(githubProject, statusField);
|
|
2461
2723
|
if (ambiguousPriorityFields.length > 0) {
|
|
2462
2724
|
process.stderr.write(
|
|
2463
|
-
`Warning: Multiple priority-like single-select fields found (${ambiguousPriorityFields.map((field) => `"${field.name}"`).join(", ")}).
|
|
2725
|
+
`Warning: Multiple priority-like single-select fields found (${ambiguousPriorityFields.map((field) => `"${field.name}"`).join(", ")}). Writing disabled priority scaffold in non-interactive mode.
|
|
2464
2726
|
`
|
|
2465
2727
|
);
|
|
2466
2728
|
}
|
|
2729
|
+
const priority = autoPriorityField ? buildProjectFieldPriority(autoPriorityField) : buildDisabledPriority();
|
|
2467
2730
|
const validation = validateStateMapping(mappings);
|
|
2468
2731
|
if (!validation.valid) {
|
|
2469
2732
|
process.stderr.write(
|
|
@@ -2481,6 +2744,8 @@ Run without --non-interactive for manual mapping.
|
|
|
2481
2744
|
projectDetail: githubProject,
|
|
2482
2745
|
statusField,
|
|
2483
2746
|
priorityField: autoPriorityField,
|
|
2747
|
+
priority,
|
|
2748
|
+
includePriorityTemplates: !autoPriorityField,
|
|
2484
2749
|
mappings,
|
|
2485
2750
|
runtime,
|
|
2486
2751
|
skipSkills: flags.skipSkills,
|
|
@@ -2504,6 +2769,8 @@ Run without --non-interactive for manual mapping.
|
|
|
2504
2769
|
projectDetail: githubProject,
|
|
2505
2770
|
statusField,
|
|
2506
2771
|
priorityField: autoPriorityField,
|
|
2772
|
+
priority,
|
|
2773
|
+
includePriorityTemplates: !autoPriorityField,
|
|
2507
2774
|
runtime,
|
|
2508
2775
|
skipSkills: flags.skipSkills,
|
|
2509
2776
|
skipContext: flags.skipContext
|
|
@@ -2610,15 +2877,18 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2610
2877
|
return;
|
|
2611
2878
|
}
|
|
2612
2879
|
const priorityResolution = resolvePriorityField(projectDetail, statusField);
|
|
2880
|
+
const priorityLabelNames = await collectPriorityLabelNames(
|
|
2881
|
+
client,
|
|
2882
|
+
projectDetail.linkedRepositories
|
|
2883
|
+
);
|
|
2613
2884
|
const mappings = await promptStateMappings(statusField, {
|
|
2614
|
-
stepLabel:
|
|
2885
|
+
stepLabel: "Step 3/4"
|
|
2886
|
+
});
|
|
2887
|
+
const { priority, priorityField } = await promptPriorityConfig({
|
|
2888
|
+
priorityResolution,
|
|
2889
|
+
labelNames: priorityLabelNames,
|
|
2890
|
+
stepLabel: "Step 4/4"
|
|
2615
2891
|
});
|
|
2616
|
-
let priorityField = priorityResolution.field;
|
|
2617
|
-
if (priorityResolution.ambiguous.length > 0) {
|
|
2618
|
-
priorityField = await promptPriorityField(priorityResolution.ambiguous, {
|
|
2619
|
-
stepLabel: "Step 4/4"
|
|
2620
|
-
});
|
|
2621
|
-
}
|
|
2622
2892
|
const validation = validateStateMapping(mappings);
|
|
2623
2893
|
if (!validation.valid) {
|
|
2624
2894
|
p.log.error("Mapping validation failed:");
|
|
@@ -2638,6 +2908,8 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2638
2908
|
projectDetail,
|
|
2639
2909
|
statusField,
|
|
2640
2910
|
priorityField,
|
|
2911
|
+
priority,
|
|
2912
|
+
includePriorityTemplates: priority.source === "disabled",
|
|
2641
2913
|
mappings,
|
|
2642
2914
|
runtime,
|
|
2643
2915
|
skipSkills: flags.skipSkills,
|
|
@@ -2653,6 +2925,8 @@ async function runInteractiveStandalone(flags, _options) {
|
|
|
2653
2925
|
projectDetail,
|
|
2654
2926
|
statusField,
|
|
2655
2927
|
priorityField,
|
|
2928
|
+
priority,
|
|
2929
|
+
includePriorityTemplates: priority.source === "disabled",
|
|
2656
2930
|
runtime,
|
|
2657
2931
|
skipSkills: flags.skipSkills,
|
|
2658
2932
|
skipContext: flags.skipContext
|
|
@@ -2670,6 +2944,8 @@ export {
|
|
|
2670
2944
|
resolveStatusField,
|
|
2671
2945
|
buildAutomaticStateMappings,
|
|
2672
2946
|
resolvePriorityField,
|
|
2947
|
+
collectPriorityLabelNames,
|
|
2948
|
+
promptPriorityConfig,
|
|
2673
2949
|
promptStateMappings,
|
|
2674
2950
|
planWorkflowArtifacts,
|
|
2675
2951
|
writeWorkflowPlan,
|