@gh-symphony/cli 0.0.21 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +100 -69
  2. package/dist/chunk-6I753NYO.js +18 -0
  3. package/dist/{workflow-BLJH2HC3.js → chunk-B4ZJMAZL.js} +27 -19
  4. package/dist/{chunk-SXGT7LOF.js → chunk-DLZAJXZL.js} +600 -12
  5. package/dist/chunk-GHVDABFO.js +235 -0
  6. package/dist/{chunk-QEONJ5DZ.js → chunk-GPRCOJDJ.js} +1314 -35
  7. package/dist/{chunk-A67CMOYE.js → chunk-VFHMHHZW.js} +1 -1
  8. package/dist/{chunk-JN3TQVFV.js → chunk-WM2B6BJ7.js} +16 -62
  9. package/dist/{chunk-ROGRTUFI.js → chunk-WOVNN5NW.js} +16 -6
  10. package/dist/{chunk-C67H3OUL.js → chunk-Z3NZOPLZ.js} +0 -81
  11. package/dist/{config-cmd-DNXNL26Z.js → config-cmd-2ADPUYWA.js} +1 -1
  12. package/dist/{doctor-4HBRICHP.js → doctor-EEPNFCGF.js} +464 -40
  13. package/dist/index.js +357 -244
  14. package/dist/repo-RX4OK7XH.js +6783 -0
  15. package/dist/{setup-B2SVLW2R.js → setup-XNHHRBGU.js} +57 -91
  16. package/dist/{upgrade-OJXPZRYE.js → upgrade-NS53EO2B.js} +2 -2
  17. package/dist/{version-TBDCTKDO.js → version-2RHFZ5CI.js} +1 -1
  18. package/dist/worker-entry.js +376 -15
  19. package/dist/workflow-26QNZZWH.js +22 -0
  20. package/package.json +5 -5
  21. package/dist/chunk-5NV3LSAJ.js +0 -11
  22. package/dist/chunk-C7G7RJ4G.js +0 -146
  23. package/dist/chunk-KY6WKH66.js +0 -1300
  24. package/dist/chunk-MYVJ6HK4.js +0 -3510
  25. package/dist/chunk-S6VIK4FF.js +0 -723
  26. package/dist/chunk-XN5ABWZ6.js +0 -486
  27. package/dist/chunk-Y6TYJMNT.js +0 -109
  28. package/dist/init-HZ3JEDGQ.js +0 -38
  29. package/dist/logs-6JKKYDGJ.js +0 -188
  30. package/dist/project-25NQ4J4Y.js +0 -24
  31. package/dist/recover-L3MJHHDA.js +0 -133
  32. package/dist/repo-TDCWQR6P.js +0 -379
  33. package/dist/run-XJQ6BF7U.js +0 -110
  34. package/dist/start-I2CC7BLW.js +0 -18
  35. package/dist/status-QSCFVGRQ.js +0 -11
  36. package/dist/stop-7MFCBQVW.js +0 -9
package/dist/index.js CHANGED
@@ -1,7 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ bold,
4
+ cyan,
5
+ setNoColor,
6
+ yellow
7
+ } from "./chunk-MVRF7BES.js";
2
8
  import {
3
9
  resolveConfigDir
4
- } from "./chunk-ROGRTUFI.js";
10
+ } from "./chunk-WOVNN5NW.js";
5
11
 
6
12
  // src/index.ts
7
13
  import { realpathSync } from "fs";
@@ -19,13 +25,6 @@ var TOP_LEVEL_COMMANDS = [
19
25
  "setup",
20
26
  "doctor",
21
27
  "upgrade",
22
- "start",
23
- "stop",
24
- "status",
25
- "run",
26
- "recover",
27
- "logs",
28
- "project",
29
28
  "repo",
30
29
  "config",
31
30
  "completion",
@@ -58,70 +57,33 @@ var COMMAND_OPTIONS = {
58
57
  ...GLOBAL_OPTIONS
59
58
  ],
60
59
  "workflow:validate": ["--file", ...GLOBAL_OPTIONS],
61
- "workflow:preview": [
62
- "--file",
63
- "--sample",
64
- "--attempt",
65
- ...GLOBAL_OPTIONS
66
- ],
60
+ "workflow:preview": ["--file", "--sample", "--attempt", ...GLOBAL_OPTIONS],
67
61
  setup: [
68
62
  "--non-interactive",
69
- "--project",
70
- "--workspace-dir",
71
63
  "--assigned-only",
72
64
  "--output",
73
65
  "--skip-skills",
74
66
  "--skip-context",
75
67
  ...GLOBAL_OPTIONS
76
68
  ],
77
- doctor: ["--project-id", "--project", ...GLOBAL_OPTIONS],
78
- upgrade: [...GLOBAL_OPTIONS],
79
- start: ["--project-id", "--project", "--daemon", "-d", ...GLOBAL_OPTIONS],
80
- stop: ["--project-id", "--project", "--force", ...GLOBAL_OPTIONS],
81
- status: ["--project-id", "--project", "--watch", "-w", ...GLOBAL_OPTIONS],
82
- run: ["--project-id", "--project", "--watch", "-w", ...GLOBAL_OPTIONS],
83
- recover: ["--project-id", "--project", "--dry-run", ...GLOBAL_OPTIONS],
84
- logs: [
69
+ doctor: [
85
70
  "--project-id",
86
71
  "--project",
87
- "--follow",
88
- "-f",
72
+ "--fix",
73
+ "--smoke",
89
74
  "--issue",
90
- "--run",
91
- "--level",
92
- ...GLOBAL_OPTIONS
93
- ],
94
- project: ["add", "list", "remove", "start", "stop", "switch", "status"],
95
- "project:add": [
96
- "--non-interactive",
97
- "--project",
98
- "--workspace-dir",
99
- "--assigned-only",
100
- ...GLOBAL_OPTIONS
101
- ],
102
- "project:list": [...GLOBAL_OPTIONS],
103
- "project:remove": [...GLOBAL_OPTIONS],
104
- "project:start": [
105
- "--project-id",
106
- "--project",
107
- "--daemon",
108
- "-d",
109
- ...GLOBAL_OPTIONS
110
- ],
111
- "project:stop": ["--project-id", "--project", "--force", ...GLOBAL_OPTIONS],
112
- "project:switch": [...GLOBAL_OPTIONS],
113
- "project:status": [
114
- "--project-id",
115
- "--project",
116
- "--watch",
117
- "-w",
118
75
  ...GLOBAL_OPTIONS
119
76
  ],
120
- repo: ["list", "add", "remove", "sync"],
121
- "repo:list": [...GLOBAL_OPTIONS],
122
- "repo:add": [...GLOBAL_OPTIONS],
123
- "repo:remove": [...GLOBAL_OPTIONS],
124
- "repo:sync": ["--dry-run", "--prune", ...GLOBAL_OPTIONS],
77
+ upgrade: [...GLOBAL_OPTIONS],
78
+ repo: ["init", "start", "status", "stop", "run", "recover", "logs", "explain"],
79
+ "repo:init": ["--repo-dir", "--workflow-file", ...GLOBAL_OPTIONS],
80
+ "repo:start": ["--daemon", "-d", "--once", "--http", "--web", "--log-level", ...GLOBAL_OPTIONS],
81
+ "repo:status": ["--watch", "-w", ...GLOBAL_OPTIONS],
82
+ "repo:stop": ["--force", ...GLOBAL_OPTIONS],
83
+ "repo:run": ["--watch", ...GLOBAL_OPTIONS],
84
+ "repo:recover": ["--dry-run", ...GLOBAL_OPTIONS],
85
+ "repo:logs": ["--follow", "-f", "--issue", "--run", "--level", ...GLOBAL_OPTIONS],
86
+ "repo:explain": ["--json", "--workflow", ...GLOBAL_OPTIONS],
125
87
  config: ["show", "set", "edit"],
126
88
  "config:show": [...GLOBAL_OPTIONS],
127
89
  "config:set": [...GLOBAL_OPTIONS],
@@ -140,7 +102,7 @@ function renderBashCasePatterns() {
140
102
  return
141
103
  ;;`;
142
104
  }
143
- if (command === "workflow" || command === "project" || command === "repo" || command === "config") {
105
+ if (command === "workflow" || command === "repo" || command === "config") {
144
106
  return ` ${command})
145
107
  COMPREPLY=( $(compgen -W "${quoteWords(values)}" -- "$cur") )
146
108
  return
@@ -166,11 +128,6 @@ function renderFishLines() {
166
128
  `complete -c gh-symphony -f -n '__fish_use_subcommand' -a '${command}'`
167
129
  );
168
130
  }
169
- for (const subcommand of COMMAND_OPTIONS.project ?? []) {
170
- lines.push(
171
- `complete -c gh-symphony -f -n '__fish_seen_subcommand_from project' -a '${subcommand}'`
172
- );
173
- }
174
131
  for (const subcommand of COMMAND_OPTIONS.repo ?? []) {
175
132
  lines.push(
176
133
  `complete -c gh-symphony -f -n '__fish_seen_subcommand_from repo' -a '${subcommand}'`
@@ -255,7 +212,7 @@ _gh_symphony_completion() {
255
212
  return
256
213
  fi
257
214
 
258
- if [[ "\${path}" == "workflow" || "\${path}" == "project" || "\${path}" == "repo" || "\${path}" == "config" || "\${path}" == "completion" ]]; then
215
+ if [[ "\${path}" == "workflow" || "\${path}" == "repo" || "\${path}" == "config" || "\${path}" == "completion" ]]; then
259
216
  if [[ -n "\${GH_SYMPHONY_SUBCOMMAND}" ]]; then
260
217
  path="\${path}:\${GH_SYMPHONY_SUBCOMMAND}"
261
218
  fi
@@ -276,23 +233,194 @@ ${bashFunction}complete -F _gh_symphony_completion gh-symphony
276
233
  `;
277
234
  }
278
235
 
236
+ // src/commands/help.ts
237
+ var DESCRIPTION_COLUMN = 23;
238
+ var COMMAND_COLUMN_WIDTH = DESCRIPTION_COLUMN - 2;
239
+ var HELP_SECTIONS = [
240
+ {
241
+ title: "Setup",
242
+ entries: [
243
+ {
244
+ name: "setup",
245
+ description: "Run the one-command first-run setup flow"
246
+ },
247
+ {
248
+ name: "workflow init",
249
+ description: "Generate WORKFLOW.md and workflow support files"
250
+ },
251
+ {
252
+ name: "workflow validate",
253
+ description: "Strictly validate WORKFLOW.md"
254
+ },
255
+ {
256
+ name: "workflow preview",
257
+ description: "Render the worker prompt from a sample or live issue"
258
+ },
259
+ {
260
+ name: "doctor",
261
+ description: "Run diagnostics and optional remediation"
262
+ },
263
+ {
264
+ name: "config show",
265
+ description: "Show current configuration"
266
+ },
267
+ {
268
+ name: "config set",
269
+ description: "Set a configuration value"
270
+ },
271
+ {
272
+ name: "config edit",
273
+ description: "Open config in $EDITOR"
274
+ }
275
+ ]
276
+ },
277
+ {
278
+ title: "Orchestration (current repository)",
279
+ entries: [
280
+ {
281
+ name: "repo init",
282
+ description: "Initialize gh-symphony for the current repository"
283
+ },
284
+ {
285
+ name: "repo start",
286
+ description: "Start the orchestrator (foreground)"
287
+ },
288
+ {
289
+ name: "repo start --daemon",
290
+ description: "Start the orchestrator in the background"
291
+ },
292
+ {
293
+ name: "repo stop",
294
+ description: "Stop the background orchestrator"
295
+ },
296
+ {
297
+ name: "repo status",
298
+ description: "Show orchestrator status"
299
+ },
300
+ {
301
+ name: "repo run <issue>",
302
+ description: "Dispatch a single issue"
303
+ },
304
+ {
305
+ name: "repo recover",
306
+ description: "Recover stalled runs"
307
+ },
308
+ {
309
+ name: "repo logs",
310
+ description: "View orchestrator logs"
311
+ },
312
+ {
313
+ name: "repo explain <issue>",
314
+ description: "Explain why an issue is not dispatching"
315
+ }
316
+ ]
317
+ },
318
+ {
319
+ title: "Maintenance",
320
+ entries: [
321
+ {
322
+ name: "upgrade",
323
+ description: "Upgrade the CLI to the latest published version"
324
+ },
325
+ {
326
+ name: "completion <shell>",
327
+ description: "Print shell completion (bash/zsh/fish)"
328
+ },
329
+ {
330
+ name: "version",
331
+ description: "Show version"
332
+ },
333
+ {
334
+ name: "help [command]",
335
+ description: "Show help for a command"
336
+ }
337
+ ]
338
+ },
339
+ {
340
+ title: "Global Options",
341
+ entries: [
342
+ {
343
+ name: "--config <dir>",
344
+ description: [
345
+ "Config directory override (advanced; default uses initialized",
346
+ "cwd runtime, then ~/.gh-symphony)"
347
+ ]
348
+ },
349
+ {
350
+ name: "--verbose, -v",
351
+ description: "Verbose output"
352
+ },
353
+ {
354
+ name: "--json",
355
+ description: "JSON output"
356
+ },
357
+ {
358
+ name: "--no-color",
359
+ description: "Disable color output"
360
+ },
361
+ {
362
+ name: "--help, -h",
363
+ description: "Show help"
364
+ },
365
+ {
366
+ name: "--version, -V",
367
+ description: "Show version"
368
+ }
369
+ ]
370
+ }
371
+ ];
372
+ function sectionTitle(title, color) {
373
+ const label = `${title}:`;
374
+ return color ? yellow(bold(label)) : label;
375
+ }
376
+ function entryName(name, color) {
377
+ return color ? cyan(name) : name;
378
+ }
379
+ function renderEntry(entry, color) {
380
+ const descriptions = Array.isArray(entry.description) ? entry.description : [entry.description];
381
+ const lines = [
382
+ ` ${entryName(entry.name, color)}${" ".repeat(
383
+ Math.max(COMMAND_COLUMN_WIDTH - entry.name.length, 1)
384
+ )}${descriptions[0]}`
385
+ ];
386
+ for (const line of descriptions.slice(1)) {
387
+ lines.push(`${" ".repeat(DESCRIPTION_COLUMN)}${line}`);
388
+ }
389
+ return lines;
390
+ }
391
+ function renderHelp(options) {
392
+ const lines = ["gh-symphony \u2014 AI Coding Agent Orchestrator", ""];
393
+ for (const [index, section] of HELP_SECTIONS.entries()) {
394
+ if (index > 0) {
395
+ lines.push("");
396
+ }
397
+ lines.push(sectionTitle(section.title, options.color));
398
+ for (const entry of section.entries) {
399
+ lines.push(...renderEntry(entry, options.color));
400
+ }
401
+ }
402
+ return `${lines.join("\n")}
403
+ `;
404
+ }
405
+
406
+ // src/commands/removed-command.ts
407
+ function createRemovedCommandHandler(message) {
408
+ return async () => {
409
+ process.stderr.write(`${message}
410
+ `);
411
+ process.exitCode = 2;
412
+ };
413
+ }
414
+
279
415
  // src/index.ts
280
416
  var COMMANDS = {
281
- workflow: () => import("./workflow-BLJH2HC3.js"),
282
- init: () => import("./init-HZ3JEDGQ.js"),
283
- setup: () => import("./setup-B2SVLW2R.js"),
284
- doctor: () => import("./doctor-4HBRICHP.js"),
285
- upgrade: () => import("./upgrade-OJXPZRYE.js"),
286
- start: () => import("./start-I2CC7BLW.js"),
287
- stop: () => import("./stop-7MFCBQVW.js"),
288
- status: () => import("./status-QSCFVGRQ.js"),
289
- run: () => import("./run-XJQ6BF7U.js"),
290
- recover: () => import("./recover-L3MJHHDA.js"),
291
- logs: () => import("./logs-6JKKYDGJ.js"),
292
- project: () => import("./project-25NQ4J4Y.js"),
293
- repo: () => import("./repo-TDCWQR6P.js"),
294
- config: () => import("./config-cmd-DNXNL26Z.js"),
295
- version: () => import("./version-TBDCTKDO.js")
417
+ workflow: () => import("./workflow-26QNZZWH.js"),
418
+ setup: () => import("./setup-XNHHRBGU.js"),
419
+ doctor: () => import("./doctor-EEPNFCGF.js"),
420
+ upgrade: () => import("./upgrade-NS53EO2B.js"),
421
+ repo: () => import("./repo-RX4OK7XH.js"),
422
+ config: () => import("./config-cmd-2ADPUYWA.js"),
423
+ version: () => import("./version-2RHFZ5CI.js")
296
424
  };
297
425
  function addGlobalOptions(command) {
298
426
  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");
@@ -308,6 +436,7 @@ function resolveGlobalOptions(values) {
308
436
  if (options.noColor) {
309
437
  process.env.NO_COLOR = "1";
310
438
  }
439
+ setNoColor(options.noColor);
311
440
  return options;
312
441
  }
313
442
  function resolveProjectId(values) {
@@ -326,6 +455,9 @@ async function invokeHandler(key, args, values) {
326
455
  const module = await COMMANDS[key]();
327
456
  await module.default(args, resolveGlobalOptions(values));
328
457
  }
458
+ async function invokeRemovedCommand(message, values) {
459
+ await createRemovedCommandHandler(message)([], resolveGlobalOptions(values));
460
+ }
329
461
  function shellArgument(value) {
330
462
  if (value === "bash" || value === "zsh" || value === "fish") {
331
463
  return value;
@@ -345,8 +477,24 @@ function resolveVersionOptions(argv) {
345
477
  if (options.noColor) {
346
478
  process.env.NO_COLOR = "1";
347
479
  }
480
+ setNoColor(options.noColor);
348
481
  return options;
349
482
  }
483
+ function renderRootHelp(command) {
484
+ const values = command.optsWithGlobals();
485
+ const noColor = Boolean(values.noColor);
486
+ return renderHelp({ color: !noColor });
487
+ }
488
+ function registerRemovedCommand(program, commandSpec, message, markInvoked) {
489
+ const handler = createRemovedCommandHandler(message);
490
+ addGlobalOptions(
491
+ program.command(commandSpec, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true)
492
+ ).action(async function() {
493
+ markInvoked();
494
+ const values = this.optsWithGlobals();
495
+ await handler([], resolveGlobalOptions(values));
496
+ });
497
+ }
350
498
  function createProgram() {
351
499
  let actionInvoked = false;
352
500
  const markInvoked = () => {
@@ -355,21 +503,13 @@ function createProgram() {
355
503
  const program = addGlobalOptions(
356
504
  new Command().name("gh-symphony").description("AI Coding Agent Orchestrator").exitOverride().helpOption("-h, --help", "Show help").addHelpCommand("help [command]", "Show help for command").showHelpAfterError("(run with --help for usage)").option("-V, --version", "Show version")
357
505
  );
358
- addGlobalOptions(
359
- program.command("init", { hidden: true }).description("Alias for 'gh-symphony workflow init'").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("--runtime <kind>", "Runtime preset: codex-app-server or claude-print").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)
360
- ).action(async function() {
361
- markInvoked();
362
- const values = this.optsWithGlobals();
363
- const args = ["init"];
364
- pushOption(args, "--non-interactive", values.nonInteractive);
365
- pushOption(args, "--project", values.project);
366
- pushOption(args, "--output", values.output);
367
- pushOption(args, "--runtime", values.runtime);
368
- pushOption(args, "--skip-skills", values.skipSkills);
369
- pushOption(args, "--skip-context", values.skipContext);
370
- pushOption(args, "--dry-run", values.dryRun);
371
- await invokeHandler("workflow", args, values);
372
- });
506
+ program.helpInformation = () => renderRootHelp(program);
507
+ registerRemovedCommand(
508
+ program,
509
+ "init",
510
+ "Use 'gh-symphony workflow init'.",
511
+ markInvoked
512
+ );
373
513
  const workflow = addGlobalOptions(
374
514
  program.command("workflow").description("Manage WORKFLOW.md authoring")
375
515
  );
@@ -382,7 +522,10 @@ function createProgram() {
382
522
  );
383
523
  });
384
524
  addGlobalOptions(
385
- 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("--runtime <kind>", "Runtime preset: codex-app-server or claude-print").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)
525
+ 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(
526
+ "--runtime <kind>",
527
+ "Runtime preset: codex-app-server or claude-print"
528
+ ).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)
386
529
  ).action(async function() {
387
530
  markInvoked();
388
531
  const values = this.optsWithGlobals();
@@ -419,14 +562,12 @@ function createProgram() {
419
562
  await invokeHandler("workflow", args, values);
420
563
  });
421
564
  addGlobalOptions(
422
- program.command("setup").description("Run the one-command first-run setup flow").option("--non-interactive", "Run without prompts").option("--project <id>", "GitHub Project ID or URL").option("--workspace-dir <path>", "Workspace directory").option("--assigned-only", "Limit processing to assigned issues").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)
565
+ program.command("setup").description("Run the one-command first-run setup flow").option("--non-interactive", "Run without prompts").option("--assigned-only", "Limit processing to assigned issues").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)
423
566
  ).action(async function() {
424
567
  markInvoked();
425
568
  const values = this.optsWithGlobals();
426
569
  const args = [];
427
570
  pushOption(args, "--non-interactive", values.nonInteractive);
428
- pushOption(args, "--project", values.project);
429
- pushOption(args, "--workspace-dir", values.workspaceDir);
430
571
  pushOption(args, "--assigned-only", values.assignedOnly);
431
572
  pushOption(args, "--output", values.output);
432
573
  pushOption(args, "--skip-skills", values.skipSkills);
@@ -437,13 +578,18 @@ function createProgram() {
437
578
  program.command("doctor").description("Run diagnostics and optional first-run remediation").option("--project-id <projectId>", "Project identifier").option(
438
579
  "--fix",
439
580
  "Apply safe remediation steps and print manual follow-ups"
440
- ).addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
581
+ ).option(
582
+ "--smoke",
583
+ "Run a safe live issue readiness check without dispatching work"
584
+ ).option("--issue <owner/repo#number>", "Live issue to validate").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
441
585
  ).action(async function() {
442
586
  markInvoked();
443
587
  const values = this.optsWithGlobals();
444
588
  const args = [];
445
589
  pushOption(args, "--project-id", resolveProjectId(values));
446
590
  pushOption(args, "--fix", values.fix);
591
+ pushOption(args, "--smoke", values.smoke);
592
+ pushOption(args, "--issue", values.issue);
447
593
  await invokeHandler("doctor", args, values);
448
594
  });
449
595
  addGlobalOptions(
@@ -452,211 +598,178 @@ function createProgram() {
452
598
  markInvoked();
453
599
  await invokeHandler("upgrade", [], this.optsWithGlobals());
454
600
  });
601
+ registerRemovedCommand(
602
+ program,
603
+ "start",
604
+ "Use 'gh-symphony repo start' from the target repository.",
605
+ markInvoked
606
+ );
607
+ registerRemovedCommand(
608
+ program,
609
+ "stop",
610
+ "Use 'gh-symphony repo stop'.",
611
+ markInvoked
612
+ );
613
+ registerRemovedCommand(
614
+ program,
615
+ "status",
616
+ "Use 'gh-symphony repo status'.",
617
+ markInvoked
618
+ );
619
+ registerRemovedCommand(
620
+ program,
621
+ "run",
622
+ "Use 'gh-symphony repo run <issue>'.",
623
+ markInvoked
624
+ );
625
+ registerRemovedCommand(
626
+ program,
627
+ "recover",
628
+ "Use 'gh-symphony repo recover'.",
629
+ markInvoked
630
+ );
631
+ registerRemovedCommand(
632
+ program,
633
+ "logs",
634
+ "Use 'gh-symphony repo logs'.",
635
+ markInvoked
636
+ );
455
637
  addGlobalOptions(
456
- program.command("start").description("Start the orchestrator").option("-d, --daemon", "Start in daemon mode").option("--once", "Run a single orchestration tick and exit").option(
457
- "--http [port]",
458
- "Expose dashboard and refresh endpoints over HTTP"
459
- ).option(
460
- "--web [port]",
461
- "Expose the control plane web dashboard and API over HTTP"
462
- ).option("--log-level <level>", "Orchestrator lifecycle log level").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
463
- ).action(async function() {
464
- markInvoked();
465
- const values = this.optsWithGlobals();
466
- const args = [];
467
- pushOption(args, "--project-id", resolveProjectId(values));
468
- pushOption(args, "--daemon", values.daemon);
469
- pushOption(args, "--once", values.once);
470
- pushOption(args, "--http", values.http);
471
- pushOption(args, "--web", values.web);
472
- pushOption(args, "--log-level", values.logLevel);
473
- await invokeHandler("start", args, values);
474
- });
475
- addGlobalOptions(
476
- program.command("stop").description("Stop the background orchestrator").option("--force", "Force stop with SIGKILL").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
477
- ).action(async function() {
478
- markInvoked();
479
- const values = this.optsWithGlobals();
480
- const args = [];
481
- pushOption(args, "--project-id", resolveProjectId(values));
482
- pushOption(args, "--force", values.force);
483
- await invokeHandler("stop", args, values);
484
- });
485
- addGlobalOptions(
486
- program.command("status").description("Show orchestrator status").option("-w, --watch", "Watch status continuously").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
638
+ program.command("project").description("Removed project namespace").argument("[args...]", "Removed project command arguments").allowUnknownOption(true).allowExcessArguments(true)
487
639
  ).action(async function() {
488
640
  markInvoked();
489
- const values = this.optsWithGlobals();
490
- const args = [];
491
- pushOption(args, "--project-id", resolveProjectId(values));
492
- pushOption(args, "--watch", values.watch);
493
- await invokeHandler("status", args, values);
641
+ await createRemovedCommandHandler(
642
+ "The 'project' command was removed. The orchestrator is now per-repository. Run 'gh-symphony repo init' in the target repository."
643
+ )([], resolveGlobalOptions(this.optsWithGlobals()));
494
644
  });
495
- addGlobalOptions(
496
- program.command("run").description("Dispatch a single issue").argument("<issue>", "Issue identifier").option("--log-level <level>", "Orchestrator lifecycle log level").option("-w, --watch", "Watch status after dispatch").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
497
- ).action(async function(issue) {
645
+ const repo = addGlobalOptions(
646
+ program.command("repo").description("Manage the current repository runtime")
647
+ );
648
+ repo.action(async function() {
498
649
  markInvoked();
499
- const values = this.optsWithGlobals();
500
- const args = [issue];
501
- pushOption(args, "--project-id", resolveProjectId(values));
502
- pushOption(args, "--log-level", values.logLevel);
503
- pushOption(args, "--watch", values.watch);
504
- await invokeHandler("run", args, values);
650
+ await invokeHandler("repo", [], this.optsWithGlobals());
505
651
  });
652
+ addGlobalOptions(repo.command("list").description("Removed")).action(
653
+ async function() {
654
+ markInvoked();
655
+ await invokeRemovedCommand(
656
+ "Removed. Repository identity is shown by 'repo status'.",
657
+ this.optsWithGlobals()
658
+ );
659
+ }
660
+ );
506
661
  addGlobalOptions(
507
- program.command("recover").description("Recover stalled runs").option("--dry-run", "Show recoverable runs without recovering").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
662
+ repo.command("add").description("Removed").argument("[owner/name]", "Repository spec").allowExcessArguments(false)
508
663
  ).action(async function() {
509
664
  markInvoked();
510
- const values = this.optsWithGlobals();
511
- const args = [];
512
- pushOption(args, "--project-id", resolveProjectId(values));
513
- pushOption(args, "--dry-run", values.dryRun);
514
- await invokeHandler("recover", args, values);
665
+ await invokeRemovedCommand(
666
+ "Removed. The orchestrator binds to the cwd repository via 'repo init'.",
667
+ this.optsWithGlobals()
668
+ );
515
669
  });
516
670
  addGlobalOptions(
517
- program.command("logs").description("View orchestrator logs").option("-f, --follow", "Follow new log lines").option("--issue <issue>", "Filter by issue identifier").option("--run <runId>", "Read events for a specific run").option("--level <level>", "Filter by log level").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
671
+ repo.command("remove").description("Removed").argument("[owner/name]", "Repository spec").allowExcessArguments(false)
518
672
  ).action(async function() {
519
673
  markInvoked();
520
- const values = this.optsWithGlobals();
521
- const args = [];
522
- pushOption(args, "--project-id", resolveProjectId(values));
523
- pushOption(args, "--follow", values.follow);
524
- pushOption(args, "--issue", values.issue);
525
- pushOption(args, "--run", values.run);
526
- pushOption(args, "--level", values.level);
527
- await invokeHandler("logs", args, values);
528
- });
529
- const project = addGlobalOptions(
530
- program.command("project").description("Manage configured projects")
531
- );
532
- project.action(async function() {
533
- markInvoked();
534
- await invokeHandler("project", [], this.optsWithGlobals());
674
+ await invokeRemovedCommand(
675
+ "Removed. The orchestrator binds to the cwd repository via 'repo init'.",
676
+ this.optsWithGlobals()
677
+ );
535
678
  });
536
679
  addGlobalOptions(
537
- project.command("add").description("Add a new project").option("--non-interactive", "Run without prompts").option("--project <id>", "GitHub Project ID").option("--workspace-dir <path>", "Workspace directory").option("--assigned-only", "Limit processing to assigned issues").allowExcessArguments(false)
680
+ repo.command("sync").description("Removed").allowExcessArguments(false)
538
681
  ).action(async function() {
539
682
  markInvoked();
540
- const values = this.optsWithGlobals();
541
- const args = [];
542
- pushOption(args, "--non-interactive", values.nonInteractive);
543
- pushOption(args, "--project", values.project);
544
- pushOption(args, "--workspace-dir", values.workspaceDir);
545
- pushOption(args, "--assigned-only", values.assignedOnly);
546
- await invokeHandler("project", ["add", ...args], values);
683
+ await invokeRemovedCommand(
684
+ "Removed. Single-repo model has no linked-repo set to sync.",
685
+ this.optsWithGlobals()
686
+ );
547
687
  });
548
688
  addGlobalOptions(
549
- project.command("list").description("List configured projects")
689
+ repo.command("init").description("Initialize gh-symphony for the current repository").option("--repo-dir <path>", "Repository directory").option("--workflow-file <path>", "Use a custom WORKFLOW.md path").allowExcessArguments(false)
550
690
  ).action(async function() {
551
691
  markInvoked();
552
692
  const values = this.optsWithGlobals();
553
- await invokeHandler("project", ["list"], values);
554
- });
555
- addGlobalOptions(
556
- project.command("remove").description("Remove a project").argument("<projectId>", "Project identifier").allowExcessArguments(false)
557
- ).action(async function(projectId) {
558
- markInvoked();
559
- await invokeHandler(
560
- "project",
561
- ["remove", projectId],
562
- this.optsWithGlobals()
563
- );
693
+ const args = ["init"];
694
+ pushOption(args, "--repo-dir", values.repoDir);
695
+ pushOption(args, "--workflow-file", values.workflowFile);
696
+ await invokeHandler("repo", args, values);
564
697
  });
565
698
  addGlobalOptions(
566
- project.command("start").description("Start a specific project").option("-d, --daemon", "Start in daemon mode").option("--once", "Run a single orchestration tick and exit").option(
699
+ repo.command("start").description("Start the orchestrator for the current repository").option("-d, --daemon", "Start in daemon mode").option("--once", "Run a single orchestration tick and exit").option(
567
700
  "--http [port]",
568
701
  "Expose dashboard and refresh endpoints over HTTP"
569
702
  ).option(
570
703
  "--web [port]",
571
704
  "Expose the control plane web dashboard and API over HTTP"
572
- ).option("--log-level <level>", "Orchestrator lifecycle log level").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
705
+ ).option("--log-level <level>", "Orchestrator lifecycle log level").allowUnknownOption(true).allowExcessArguments(true)
573
706
  ).action(async function() {
574
707
  markInvoked();
575
708
  const values = this.optsWithGlobals();
576
- const args = ["start"];
577
- pushOption(args, "--project-id", resolveProjectId(values));
709
+ const args = ["start", ...this.args];
578
710
  pushOption(args, "--daemon", values.daemon);
579
711
  pushOption(args, "--once", values.once);
580
712
  pushOption(args, "--http", values.http);
581
713
  pushOption(args, "--web", values.web);
582
714
  pushOption(args, "--log-level", values.logLevel);
583
- await invokeHandler("project", args, values);
715
+ await invokeHandler("repo", args, values);
584
716
  });
585
717
  addGlobalOptions(
586
- project.command("stop").description("Stop a specific project").option("--force", "Force stop with SIGKILL").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
718
+ repo.command("status").description("Show current repository orchestrator status").option("-w, --watch", "Watch status continuously").allowUnknownOption(true).allowExcessArguments(true)
587
719
  ).action(async function() {
588
720
  markInvoked();
589
721
  const values = this.optsWithGlobals();
590
- const args = ["stop"];
591
- pushOption(args, "--project-id", resolveProjectId(values));
592
- pushOption(args, "--force", values.force);
593
- await invokeHandler("project", args, values);
722
+ const args = ["status", ...this.args];
723
+ pushOption(args, "--watch", values.watch);
724
+ await invokeHandler("repo", args, values);
594
725
  });
595
726
  addGlobalOptions(
596
- project.command("switch").description("Switch the active project")
727
+ repo.command("stop").description("Stop the current repository background orchestrator").option("--force", "Force stop with SIGKILL").allowUnknownOption(true).allowExcessArguments(true)
597
728
  ).action(async function() {
598
729
  markInvoked();
599
- await invokeHandler(
600
- "project",
601
- ["switch"],
602
- this.optsWithGlobals()
603
- );
730
+ const values = this.optsWithGlobals();
731
+ const args = ["stop", ...this.args];
732
+ pushOption(args, "--force", values.force);
733
+ await invokeHandler("repo", args, values);
604
734
  });
605
735
  addGlobalOptions(
606
- project.command("status").description("Show status for a specific project").option("-w, --watch", "Watch status continuously").option("--project-id <projectId>", "Project identifier").addOption(new Option("--project <projectId>").hideHelp()).allowExcessArguments(false)
607
- ).action(async function() {
736
+ repo.command("run").description("Dispatch a single issue from the current repository").argument("[args...]", "Issue identifier and passthrough options").option("--log-level <level>", "Orchestrator lifecycle log level").option("-w, --watch", "Watch status after dispatch").allowUnknownOption(true).allowExcessArguments(true)
737
+ ).action(async function(passthrough) {
608
738
  markInvoked();
609
739
  const values = this.optsWithGlobals();
610
- const args = ["status"];
611
- pushOption(args, "--project-id", resolveProjectId(values));
740
+ const args = ["run", ...passthrough];
741
+ pushOption(args, "--log-level", values.logLevel);
612
742
  pushOption(args, "--watch", values.watch);
613
- await invokeHandler("project", args, values);
614
- });
615
- const repo = addGlobalOptions(
616
- program.command("repo").description("Manage repositories in the active project")
617
- );
618
- repo.action(async function() {
619
- markInvoked();
620
- await invokeHandler("repo", [], this.optsWithGlobals());
743
+ await invokeHandler("repo", args, values);
621
744
  });
622
745
  addGlobalOptions(
623
- repo.command("list").description("List repositories")
746
+ repo.command("recover").description("Recover stalled runs for the current repository").option("--dry-run", "Show recoverable runs without recovering").allowUnknownOption(true).allowExcessArguments(true)
624
747
  ).action(async function() {
625
748
  markInvoked();
626
- await invokeHandler(
627
- "repo",
628
- ["list"],
629
- this.optsWithGlobals()
630
- );
631
- });
632
- addGlobalOptions(
633
- repo.command("add").description("Add a repository").argument("<owner/name>", "Repository spec").allowExcessArguments(false)
634
- ).action(async function(repoSpec) {
635
- markInvoked();
636
- await invokeHandler(
637
- "repo",
638
- ["add", repoSpec],
639
- this.optsWithGlobals()
640
- );
749
+ const values = this.optsWithGlobals();
750
+ const args = ["recover", ...this.args];
751
+ pushOption(args, "--dry-run", values.dryRun);
752
+ await invokeHandler("repo", args, values);
641
753
  });
642
754
  addGlobalOptions(
643
- repo.command("remove").description("Remove a repository").argument("<owner/name>", "Repository spec").allowExcessArguments(false)
644
- ).action(async function(repoSpec) {
755
+ repo.command("logs").description("View current repository orchestrator logs").option("-f, --follow", "Follow new log lines").option("--issue <issue>", "Filter by issue identifier").option("--run <runId>", "Read events for a specific run").option("--level <level>", "Filter by log level").allowUnknownOption(true).allowExcessArguments(true)
756
+ ).action(async function() {
645
757
  markInvoked();
646
- await invokeHandler(
647
- "repo",
648
- ["remove", repoSpec],
649
- this.optsWithGlobals()
650
- );
758
+ const values = this.optsWithGlobals();
759
+ const args = ["logs", ...this.args];
760
+ pushOption(args, "--follow", values.follow);
761
+ pushOption(args, "--issue", values.issue);
762
+ pushOption(args, "--run", values.run);
763
+ pushOption(args, "--level", values.level);
764
+ await invokeHandler("repo", args, values);
651
765
  });
652
766
  addGlobalOptions(
653
- repo.command("sync").description("Sync repositories from the active GitHub Project").option("--dry-run", "Preview repository changes without writing config").option("--prune", "Remove local repositories that are no longer linked").allowExcessArguments(false)
654
- ).action(async function() {
767
+ repo.command("explain").description("Explain why a repository issue is not dispatching").argument("[args...]", "Issue identifier and passthrough options").option("--workflow <path>", "Path to the WORKFLOW.md file to evaluate").allowUnknownOption(true).allowExcessArguments(true)
768
+ ).action(async function(passthrough) {
655
769
  markInvoked();
656
770
  const values = this.optsWithGlobals();
657
- const args = ["sync"];
658
- pushOption(args, "--dry-run", values.dryRun);
659
- pushOption(args, "--prune", values.prune);
771
+ const args = ["explain", ...passthrough];
772
+ pushOption(args, "--workflow", values.workflow);
660
773
  await invokeHandler("repo", args, values);
661
774
  });
662
775
  const config = addGlobalOptions(