@gh-symphony/cli 0.3.0 → 0.4.1

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.
@@ -52,6 +52,10 @@ var DEFAULT_WORKFLOW_TRACKER = {
52
52
  endpoint: null,
53
53
  apiKey: null,
54
54
  projectSlug: null,
55
+ pickupLabels: {
56
+ include: [],
57
+ exclude: []
58
+ },
55
59
  activeStates: DEFAULT_WORKFLOW_LIFECYCLE.activeStates,
56
60
  terminalStates: DEFAULT_WORKFLOW_LIFECYCLE.terminalStates,
57
61
  projectId: null,
@@ -171,6 +175,7 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
171
175
  endpoint: readOptionalString(tracker, "endpoint", env) ?? (trackerKind === "linear" ? DEFAULT_LINEAR_GRAPHQL_URL : null),
172
176
  apiKey: readOptionalString(tracker, "api_key", env),
173
177
  projectSlug: readOptionalString(tracker, "project_slug", env),
178
+ pickupLabels: readPickupLabelsConfig(tracker),
174
179
  activeStates,
175
180
  terminalStates,
176
181
  projectId: readOptionalString(tracker, "project_id", env),
@@ -244,6 +249,22 @@ function validateTrackerConfig(tracker, trackerKind, env) {
244
249
  }
245
250
  }
246
251
  }
252
+ function readPickupLabelsConfig(tracker) {
253
+ const value = tracker.pickup_labels ?? tracker.pickupLabels;
254
+ if (value === void 0 || value === null) {
255
+ return DEFAULT_WORKFLOW_TRACKER.pickupLabels;
256
+ }
257
+ if (Array.isArray(value) || typeof value !== "object") {
258
+ throw new Error(
259
+ 'Workflow front matter field "tracker.pickup_labels" must be an object when provided.'
260
+ );
261
+ }
262
+ const input = value;
263
+ return {
264
+ include: readStringList(input, "include") ?? [],
265
+ exclude: readStringList(input, "exclude") ?? []
266
+ };
267
+ }
247
268
  function readPriorityConfig(tracker, env) {
248
269
  if (tracker.priority === void 0 || tracker.priority === null) {
249
270
  return null;
@@ -889,7 +910,8 @@ var SESSION_EXIT_CLASSIFICATIONS = [
889
910
  "max-turns-reached",
890
911
  "user-input-required",
891
912
  "timeout",
892
- "error"
913
+ "error",
914
+ "incomplete-turn-dirty-workspace"
893
915
  ];
894
916
  function isSessionExitClassification(value) {
895
917
  return typeof value === "string" && SESSION_EXIT_CLASSIFICATIONS.includes(value);
@@ -1471,11 +1493,30 @@ function buildProjectSnapshot(input) {
1471
1493
  retryKind: run.retryKind ?? "failure",
1472
1494
  nextRetryAt: run.nextRetryAt
1473
1495
  })),
1496
+ recovery: findLatestRecovery([...allRuns ?? [], ...activeRuns]),
1474
1497
  lastError,
1475
1498
  codexTotals: aggregateTokenUsage(allRuns ?? activeRuns, lastTickAt),
1476
1499
  rateLimits: rateLimits ?? null
1477
1500
  };
1478
1501
  }
1502
+ function findLatestRecovery(runs) {
1503
+ return [...runs].filter((run) => isUnresolvedRecoveryRun(run, runs)).sort((left, right) => {
1504
+ const leftTime = new Date(left.updatedAt).getTime();
1505
+ const rightTime = new Date(right.updatedAt).getTime();
1506
+ return rightTime - leftTime;
1507
+ }).find((run) => run.recovery)?.recovery ?? null;
1508
+ }
1509
+ function isUnresolvedRecoveryRun(run, runs) {
1510
+ if (!run.recovery) {
1511
+ return false;
1512
+ }
1513
+ if (run.status === "suppressed" && runs.some(
1514
+ (candidate) => candidate.runId !== run.runId && candidate.retryKind === "recovery" && candidate.recovery?.runId === run.recovery?.runId && new Date(candidate.updatedAt).getTime() > new Date(run.updatedAt).getTime() && candidate.status !== "running" && candidate.status !== "retrying"
1515
+ )) {
1516
+ return false;
1517
+ }
1518
+ return run.status === "suppressed" || run.retryKind === "recovery" && (run.status === "running" || run.status === "retrying");
1519
+ }
1479
1520
  function aggregateTokenUsageByIssue(runs) {
1480
1521
  const totals = /* @__PURE__ */ new Map();
1481
1522
  for (const run of runs) {
@@ -66,7 +66,9 @@ async function saveGlobalConfig(configDir, config) {
66
66
  await writeJsonFile(configFilePath(configDir), config);
67
67
  }
68
68
  async function loadProjectConfig(configDir, projectId) {
69
- return readJsonFile(projectConfigPath(configDir, projectId));
69
+ return readJsonFile(
70
+ projectConfigPath(configDir, projectId)
71
+ );
70
72
  }
71
73
  async function saveProjectConfig(configDir, projectId, config) {
72
74
  await writeJsonFile(projectConfigPath(configDir, projectId), config);
@@ -3,7 +3,7 @@ import {
3
3
  configFilePath,
4
4
  loadGlobalConfig,
5
5
  saveGlobalConfig
6
- } from "./chunk-4ICDSQCJ.js";
6
+ } from "./chunk-YZP5N5XP.js";
7
7
 
8
8
  // src/commands/config-cmd.ts
9
9
  import { spawn } from "child_process";
@@ -5,17 +5,17 @@ import {
5
5
  parseIssueReference,
6
6
  readGitHubProjectBinding,
7
7
  renderIssueWorkflowPreview
8
- } from "./chunk-GTNWFVFU.js";
9
- import "./chunk-GL55AKBI.js";
8
+ } from "./chunk-3EFLX75C.js";
9
+ import "./chunk-RU5GQG6A.js";
10
10
  import {
11
11
  fetchGithubProjectIssueByRepositoryAndNumber,
12
12
  fetchGithubProjectIssues,
13
13
  inspectManagedProjectSelection
14
- } from "./chunk-VHEGRYK7.js";
15
- import "./chunk-A7EFL6EJ.js";
14
+ } from "./chunk-BBUCDKSL.js";
15
+ import "./chunk-GOR4JGJT.js";
16
16
  import {
17
17
  resolveRuntimeRoot
18
- } from "./chunk-RZ3WO7OV.js";
18
+ } from "./chunk-3IRPSPAF.js";
19
19
  import {
20
20
  GitHubApiError,
21
21
  REQUIRED_GH_SCOPES,
@@ -40,12 +40,12 @@ import {
40
40
  resolveClaudeCommandBinary,
41
41
  resolveRuntimeCommandBinary,
42
42
  runClaudePreflight
43
- } from "./chunk-5HQLPZR5.js";
43
+ } from "./chunk-YKC6CGD6.js";
44
44
  import {
45
45
  configFilePath,
46
46
  orchestratorLogPath,
47
47
  projectConfigPath
48
- } from "./chunk-4ICDSQCJ.js";
48
+ } from "./chunk-YZP5N5XP.js";
49
49
 
50
50
  // src/commands/doctor.ts
51
51
  import { constants as constants2 } from "fs";
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-MVRF7BES.js";
8
8
  import {
9
9
  resolveConfigDir
10
- } from "./chunk-4ICDSQCJ.js";
10
+ } from "./chunk-YZP5N5XP.js";
11
11
 
12
12
  // src/index.ts
13
13
  import { realpathSync } from "fs";
@@ -417,13 +417,13 @@ function createRemovedCommandHandler(message) {
417
417
 
418
418
  // src/index.ts
419
419
  var COMMANDS = {
420
- workflow: () => import("./workflow-4OFPSVZ3.js"),
421
- setup: () => import("./setup-G5VYN6FV.js"),
422
- doctor: () => import("./doctor-3IIM4UYS.js"),
423
- upgrade: () => import("./upgrade-BXIHAENU.js"),
424
- repo: () => import("./repo-SLK4DDXH.js"),
425
- config: () => import("./config-cmd-AOZVS6GU.js"),
426
- version: () => import("./version-MC2KSPJB.js")
420
+ workflow: () => import("./workflow-URPIYFYQ.js"),
421
+ setup: () => import("./setup-AADOLSW5.js"),
422
+ doctor: () => import("./doctor-3WDODAKW.js"),
423
+ upgrade: () => import("./upgrade-KTTYQQFB.js"),
424
+ repo: () => import("./repo-3JLOCGRJ.js"),
425
+ config: () => import("./config-cmd-OIVIUKG7.js"),
426
+ version: () => import("./version-HXAMSXVG.js")
427
427
  };
428
428
  function addGlobalOptions(command) {
429
429
  return command.option("--config <dir>", "Config directory").addOption(new Option("--config-dir <dir>").hideHelp()).option("-v, --verbose", "Enable verbose output").option("--json", "Output in JSON format").option("--no-color", "Disable color output");
@@ -528,7 +528,7 @@ function createProgram() {
528
528
  workflow.command("init").description("Generate WORKFLOW.md and workflow support files").option("--non-interactive", "Run without prompts").option("--project <id>", "GitHub Project ID or URL").option("--output <path>", "Write WORKFLOW.md to a custom path").option(
529
529
  "--runtime <kind>",
530
530
  "Runtime preset: codex-app-server or claude-print"
531
- ).option("--skip-skills", "Skip runtime skill generation").option("--skip-context", "Skip .gh-symphony/context.yaml generation").option("--dry-run", "Preview generated files without writing them").allowExcessArguments(false)
531
+ ).option("--skip-skills", "Skip runtime skill generation").option("--skip-context", "Deprecated no-op").option("--dry-run", "Preview generated files without writing them").allowExcessArguments(false)
532
532
  ).action(async function() {
533
533
  markInvoked();
534
534
  const values = this.optsWithGlobals();
@@ -565,7 +565,7 @@ function createProgram() {
565
565
  await invokeHandler("workflow", args, values);
566
566
  });
567
567
  addGlobalOptions(
568
- program.command("setup").description("Run the one-command first-run setup flow").option("--non-interactive", "Run without prompts").option("--output <path>", "Write WORKFLOW.md to a custom path").option("--skip-skills", "Skip runtime skill generation").option("--skip-context", "Skip .gh-symphony/context.yaml generation").allowExcessArguments(false)
568
+ program.command("setup").description("Run the one-command first-run setup flow").option("--non-interactive", "Run without prompts").option("--output <path>", "Write WORKFLOW.md to a custom path").option("--skip-skills", "Skip runtime skill generation").option("--skip-context", "Deprecated no-op").allowExcessArguments(false)
569
569
  ).action(async function() {
570
570
  markInvoked();
571
571
  const values = this.optsWithGlobals();
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  initRepoRuntime,
19
19
  parseRepoRuntimeFlags
20
- } from "./chunk-2ZIPQ7ZS.js";
20
+ } from "./chunk-MUN7QSFF.js";
21
21
  import {
22
22
  OrchestratorService,
23
23
  acquireProjectLock,
@@ -33,12 +33,12 @@ import {
33
33
  resolveOrchestratorLogLevel,
34
34
  resolveTrackerAdapter,
35
35
  runCli
36
- } from "./chunk-VHEGRYK7.js";
37
- import "./chunk-A7EFL6EJ.js";
36
+ } from "./chunk-BBUCDKSL.js";
37
+ import "./chunk-GOR4JGJT.js";
38
38
  import {
39
39
  resolveRepoRuntimeRoot,
40
40
  resolveRuntimeRoot
41
- } from "./chunk-RZ3WO7OV.js";
41
+ } from "./chunk-3IRPSPAF.js";
42
42
  import {
43
43
  GhAuthError,
44
44
  GitHubApiError,
@@ -58,14 +58,14 @@ import {
58
58
  parseRecentEvents,
59
59
  readJsonFile,
60
60
  safeReadDir
61
- } from "./chunk-5HQLPZR5.js";
61
+ } from "./chunk-YKC6CGD6.js";
62
62
  import {
63
63
  daemonPidPath,
64
64
  httpStatusPath,
65
65
  loadActiveProjectConfig,
66
66
  orchestratorLogPath,
67
67
  writeJsonFile
68
- } from "./chunk-4ICDSQCJ.js";
68
+ } from "./chunk-YZP5N5XP.js";
69
69
 
70
70
  // src/commands/logs.ts
71
71
  import { readFile, readdir, stat } from "fs/promises";
@@ -990,6 +990,7 @@ async function statusForIssue(reader, issueIdentifier) {
990
990
  kind: resolvedRun?.retryKind ?? null,
991
991
  error: resolvedRun?.lastError ?? issueRecord.retryEntry?.error ?? null
992
992
  } : null,
993
+ recovery: resolvedRun?.recovery ?? null,
993
994
  logs: {
994
995
  codex_session_logs: resolvedRun === null ? [] : [
995
996
  {
@@ -2568,6 +2569,22 @@ function renderLegacyStatus(snapshot, noColor) {
2568
2569
  }
2569
2570
  lines.push("");
2570
2571
  }
2572
+ if (snapshot.recovery) {
2573
+ const recovery = snapshot.recovery;
2574
+ lines.push(apply(yellow(" Recoverable incomplete turn:")));
2575
+ lines.push(` Run ${recovery.runId}`);
2576
+ lines.push(` Issue ${recovery.issueId}`);
2577
+ lines.push(` Workspace ${recovery.workspacePath}`);
2578
+ lines.push(
2579
+ ` Dirty ${recovery.dirtyFiles.length > 0 ? recovery.dirtyFiles.join(", ") : "none"}`
2580
+ );
2581
+ lines.push(` Last ${recovery.lastEvent ?? "unknown"}`);
2582
+ lines.push(` At ${recovery.lastEventAt ?? "unknown"}`);
2583
+ lines.push(` Session ${recovery.sessionId ?? "unknown"}`);
2584
+ lines.push(` Thread ${recovery.threadId ?? "unknown"}`);
2585
+ lines.push(` Command ${recovery.suggestedCommand}`);
2586
+ lines.push("");
2587
+ }
2571
2588
  if (snapshot.lastError) {
2572
2589
  lines.push(apply(red(` \u2717 ${snapshot.lastError}`)));
2573
2590
  lines.push("");
@@ -5,6 +5,7 @@ import {
5
5
  collectPriorityLabelNames,
6
6
  planWorkflowArtifacts,
7
7
  promptBlockerCheck,
8
+ promptLegacyGhSymphonyCleanup,
8
9
  promptPriorityConfig,
9
10
  promptStateMappings,
10
11
  renderDryRunPreview,
@@ -12,13 +13,14 @@ import {
12
13
  resolveStatusField,
13
14
  toWorkflowLifecycleConfig,
14
15
  validateStateMapping,
16
+ warnDeprecatedSkipContext,
15
17
  writeEcosystem,
16
18
  writeWorkflowPlan
17
- } from "./chunk-GL55AKBI.js";
19
+ } from "./chunk-RU5GQG6A.js";
18
20
  import {
19
21
  initRepoRuntime
20
- } from "./chunk-2ZIPQ7ZS.js";
21
- import "./chunk-RZ3WO7OV.js";
22
+ } from "./chunk-MUN7QSFF.js";
23
+ import "./chunk-3IRPSPAF.js";
22
24
  import {
23
25
  GhAuthError,
24
26
  GitHubScopeError,
@@ -31,8 +33,8 @@ import {
31
33
  listUserProjects,
32
34
  validateToken
33
35
  } from "./chunk-SMNIGNS3.js";
34
- import "./chunk-5HQLPZR5.js";
35
- import "./chunk-4ICDSQCJ.js";
36
+ import "./chunk-YKC6CGD6.js";
37
+ import "./chunk-YZP5N5XP.js";
36
38
 
37
39
  // src/commands/setup.ts
38
40
  import * as p from "@clack/prompts";
@@ -63,7 +65,7 @@ function parseSetupFlags(args) {
63
65
  default:
64
66
  if (arg?.startsWith("-")) {
65
67
  throw new Error(
66
- `Unknown option '${arg}'. Removed project/workspace flags are no longer supported; run 'gh-symphony setup' from inside the target repository. Supported flags: --non-interactive, --output, --skip-skills, --skip-context.`
68
+ `Unknown option '${arg}'. Removed project/workspace flags are no longer supported; run 'gh-symphony setup' from inside the target repository. Supported flags: --non-interactive, --output, --skip-skills. Deprecated no-op: --skip-context.`
67
69
  );
68
70
  }
69
71
  }
@@ -142,6 +144,9 @@ var handler = async (args, options) => {
142
144
  process.exitCode = 2;
143
145
  return;
144
146
  }
147
+ if (flags.skipContext) {
148
+ warnDeprecatedSkipContext();
149
+ }
145
150
  if (flags.nonInteractive) {
146
151
  await runNonInteractive(flags, options);
147
152
  return;
@@ -407,6 +412,7 @@ async function runInteractive(flags, _options) {
407
412
  process.exitCode = 130;
408
413
  return;
409
414
  }
415
+ await promptLegacyGhSymphonyCleanup(process.cwd());
410
416
  const writeSpinner = p.spinner();
411
417
  writeSpinner.start("Writing setup files...");
412
418
  try {
@@ -16,8 +16,8 @@ function execFileAsync(file, args, execFileImpl = execFileCallback) {
16
16
  });
17
17
  }
18
18
  function resolveCurrentCliVersion() {
19
- if ("0.3.0".length > 0) {
20
- return "0.3.0";
19
+ if ("0.4.1".length > 0) {
20
+ return "0.4.1";
21
21
  }
22
22
  const pkg = JSON.parse(
23
23
  readFileSync(new URL("../../package.json", import.meta.url), "utf8")
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/commands/version.ts
4
4
  var handler = async (_args, options) => {
5
- const version = "0.3.0";
5
+ const version = "0.4.1";
6
6
  if (options.json) {
7
7
  process.stdout.write(JSON.stringify({ version }) + "\n");
8
8
  } else {
@@ -6,7 +6,7 @@ import {
6
6
  normalizeCodexRuntimeEvents,
7
7
  prepareCodexRuntimePlan,
8
8
  resolveLocalRuntimeLaunchConfig
9
- } from "./chunk-A7EFL6EJ.js";
9
+ } from "./chunk-GOR4JGJT.js";
10
10
  import {
11
11
  DEFAULT_AGENT_INPUT_REQUIRED_REASON,
12
12
  classifySessionExit,
@@ -17,7 +17,7 @@ import {
17
17
  resolveClaudeCommandBinary,
18
18
  resolveWorkflowRuntimeCommand,
19
19
  runClaudePreflight
20
- } from "./chunk-5HQLPZR5.js";
20
+ } from "./chunk-YKC6CGD6.js";
21
21
 
22
22
  // ../worker/src/index.ts
23
23
  import { spawn as spawn2 } from "child_process";
@@ -6,13 +6,13 @@ import {
6
6
  resetWorkflowCommandDependenciesForTest,
7
7
  setWorkflowCommandDependenciesForTest,
8
8
  workflow_default
9
- } from "./chunk-GTNWFVFU.js";
10
- import "./chunk-GL55AKBI.js";
11
- import "./chunk-VHEGRYK7.js";
12
- import "./chunk-A7EFL6EJ.js";
9
+ } from "./chunk-3EFLX75C.js";
10
+ import "./chunk-RU5GQG6A.js";
11
+ import "./chunk-BBUCDKSL.js";
12
+ import "./chunk-GOR4JGJT.js";
13
13
  import "./chunk-SMNIGNS3.js";
14
- import "./chunk-5HQLPZR5.js";
15
- import "./chunk-4ICDSQCJ.js";
14
+ import "./chunk-YKC6CGD6.js";
15
+ import "./chunk-YZP5N5XP.js";
16
16
  export {
17
17
  workflow_default as default,
18
18
  parseIssueReference,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gh-symphony/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "license": "MIT",
5
5
  "author": "hojinzs",
6
6
  "description": "Interactive CLI for GitHub Symphony orchestration",
@@ -44,10 +44,10 @@
44
44
  "@gh-symphony/core": "0.0.14",
45
45
  "@gh-symphony/control-plane": "0.0.15",
46
46
  "@gh-symphony/dashboard": "0.0.14",
47
- "@gh-symphony/runtime-claude": "0.0.14",
48
47
  "@gh-symphony/orchestrator": "0.0.14",
49
- "@gh-symphony/worker": "0.0.14",
50
- "@gh-symphony/tracker-github": "0.0.14"
48
+ "@gh-symphony/runtime-claude": "0.0.14",
49
+ "@gh-symphony/tracker-github": "0.0.14",
50
+ "@gh-symphony/worker": "0.0.14"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsup",