@gh-symphony/cli 0.0.22 → 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 +72 -77
  2. package/dist/{chunk-IWFX2FMA.js → chunk-6I753NYO.js} +4 -1
  3. package/dist/{workflow-L3KT6HB7.js → chunk-B4ZJMAZL.js} +27 -19
  4. package/dist/{chunk-2TSM3INR.js → chunk-DLZAJXZL.js} +575 -12
  5. package/dist/chunk-GHVDABFO.js +235 -0
  6. package/dist/{chunk-EEQQWTXS.js → chunk-GPRCOJDJ.js} +158 -75
  7. package/dist/{chunk-36KYEDEO.js → chunk-MVRF7BES.js} +1 -10
  8. package/dist/{chunk-2UW7NQLX.js → chunk-VFHMHHZW.js} +1 -1
  9. package/dist/{chunk-HMLBBZNY.js → chunk-WM2B6BJ7.js} +16 -71
  10. package/dist/{chunk-QIRE2VXS.js → chunk-WOVNN5NW.js} +16 -17
  11. package/dist/{chunk-C67H3OUL.js → chunk-Z3NZOPLZ.js} +0 -81
  12. package/dist/{config-cmd-Z3A7V6NC.js → config-cmd-2ADPUYWA.js} +1 -1
  13. package/dist/{doctor-EJUMPBMW.js → doctor-EEPNFCGF.js} +464 -40
  14. package/dist/index.js +340 -294
  15. package/dist/{chunk-PUDXVBSN.js → repo-RX4OK7XH.js} +5944 -3001
  16. package/dist/{setup-TZJSM3QV.js → setup-XNHHRBGU.js} +57 -92
  17. package/dist/{upgrade-O33S2SJK.js → upgrade-NS53EO2B.js} +2 -2
  18. package/dist/{version-CW54Q7BK.js → version-2RHFZ5CI.js} +1 -1
  19. package/dist/worker-entry.js +10 -5
  20. package/dist/workflow-26QNZZWH.js +22 -0
  21. package/package.json +4 -4
  22. package/dist/chunk-DDL4BWSL.js +0 -146
  23. package/dist/chunk-DFLXHNYQ.js +0 -482
  24. package/dist/chunk-E7HYEEZD.js +0 -1318
  25. package/dist/chunk-GDE6FYN4.js +0 -26
  26. package/dist/chunk-GSX2FV3M.js +0 -103
  27. package/dist/chunk-ZHOKYUO3.js +0 -1047
  28. package/dist/init-54HMKNYI.js +0 -38
  29. package/dist/logs-GTZ4U5JE.js +0 -188
  30. package/dist/project-RMYMZSFV.js +0 -25
  31. package/dist/recover-LTLKMTRX.js +0 -133
  32. package/dist/repo-WI7GF6XQ.js +0 -749
  33. package/dist/run-IHN3ZL35.js +0 -122
  34. package/dist/start-RTAHQMR2.js +0 -19
  35. package/dist/status-F4D52OVK.js +0 -12
  36. package/dist/stop-MDKMJPVR.js +0 -10
@@ -10,24 +10,12 @@ import {
10
10
  listUserProjects,
11
11
  resolveGitHubAuth,
12
12
  validateToken
13
- } from "./chunk-C67H3OUL.js";
13
+ } from "./chunk-Z3NZOPLZ.js";
14
14
  import {
15
15
  formatClaudePreflightText,
16
16
  resolveClaudeCommandBinary,
17
17
  runClaudePreflight
18
- } from "./chunk-EEQQWTXS.js";
19
- import {
20
- loadGlobalConfig,
21
- saveGlobalConfig,
22
- saveProjectConfig
23
- } from "./chunk-QIRE2VXS.js";
24
-
25
- // src/commands/init.ts
26
- import * as p from "@clack/prompts";
27
- import { spawnSync } from "child_process";
28
- import { createHash } from "crypto";
29
- import { chmod, mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
30
- import { basename, dirname as dirname2, join as join3, relative, resolve } from "path";
18
+ } from "./chunk-GPRCOJDJ.js";
31
19
 
32
20
  // src/mapping/smart-defaults.ts
33
21
  var ROLE_PATTERNS = [
@@ -106,6 +94,13 @@ function validateStateMapping(mappings) {
106
94
  return { valid: errors.length === 0, errors, warnings };
107
95
  }
108
96
 
97
+ // src/commands/workflow-init.ts
98
+ import * as p from "@clack/prompts";
99
+ import { spawnSync } from "child_process";
100
+ import { createHash } from "crypto";
101
+ import { chmod, mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
102
+ import { basename, dirname as dirname2, join as join3, relative, resolve } from "path";
103
+
109
104
  // src/prompts/runtime-claude-constraints.ts
110
105
  var CLAUDE_RUNTIME_CONSTRAINTS_SECTION = `## Runtime Constraints
111
106
 
@@ -317,8 +312,6 @@ function buildRuntimeFrontMatter(runtime) {
317
312
  " isolation:",
318
313
  " bare: false",
319
314
  " strict_mcp_config: false",
320
- " auth:",
321
- " env: ANTHROPIC_API_KEY",
322
315
  " timeouts:",
323
316
  " read_timeout_ms: 5000",
324
317
  " turn_timeout_ms: 3600000",
@@ -1785,7 +1778,7 @@ var ALL_SKILL_TEMPLATES = [
1785
1778
  { name: "land", fileName: "SKILL.md", generate: generateLandSkill }
1786
1779
  ];
1787
1780
 
1788
- // src/commands/init.ts
1781
+ // src/commands/workflow-init.ts
1789
1782
  var KNOWN_REQUIRED_SCOPES = ["repo", "read:org", "project"];
1790
1783
  function displayScopeError(error, retryCommand) {
1791
1784
  const plural = error.requiredScopes.length === 1 ? "" : "s";
@@ -1868,6 +1861,7 @@ async function runInitRuntimePreflight(runtime) {
1868
1861
  cwd: process.cwd(),
1869
1862
  env: process.env,
1870
1863
  command: resolveClaudeCommandBinary(resolveRuntimeCommand(runtime)) ?? resolveRuntimeCommand(runtime),
1864
+ authMode: "local-or-api-key",
1871
1865
  includeGhAuth: !hasGitHubGraphqlToken
1872
1866
  });
1873
1867
  const message = formatClaudePreflightText(report);
@@ -1886,7 +1880,7 @@ var handler = async (args, options) => {
1886
1880
  }
1887
1881
  await runInteractive(flags, options);
1888
1882
  };
1889
- var init_default = handler;
1883
+ var workflow_init_default = handler;
1890
1884
  function resolveInitRuntime(runtime) {
1891
1885
  return normalizeInitRuntime(runtime ?? "codex-app-server");
1892
1886
  }
@@ -2521,7 +2515,7 @@ Run without --non-interactive for manual mapping.
2521
2515
  } else {
2522
2516
  printEcosystemSummary(ecosystemResult, outputPath, {
2523
2517
  interactive: false,
2524
- nextSteps: "Run 'gh-symphony project add' to register a project."
2518
+ nextSteps: "Run 'gh-symphony repo init' from the target repository."
2525
2519
  });
2526
2520
  }
2527
2521
  }
@@ -2665,69 +2659,20 @@ async function runInteractiveStandalone(flags, _options) {
2665
2659
  });
2666
2660
  printEcosystemSummary(ecosystemResult, outputPath, {
2667
2661
  interactive: true,
2668
- nextSteps: "Run 'gh-symphony project add' to register a project."
2669
- });
2670
- }
2671
- async function writeConfig(configDir, input) {
2672
- const repository = input.repos[0];
2673
- await saveProjectConfig(configDir, input.projectId, {
2674
- projectId: input.projectId,
2675
- slug: input.projectId,
2676
- displayName: input.project.title,
2677
- workspaceDir: input.workspaceDir,
2678
- ...repository ? {
2679
- repository: {
2680
- owner: repository.owner,
2681
- name: repository.name,
2682
- cloneUrl: repository.cloneUrl
2683
- }
2684
- } : {},
2685
- repositories: input.repos.map((r) => ({
2686
- owner: r.owner,
2687
- name: r.name,
2688
- cloneUrl: r.cloneUrl
2689
- })),
2690
- tracker: {
2691
- adapter: "github-project",
2692
- bindingId: input.project.id,
2693
- settings: {
2694
- projectId: input.project.id,
2695
- ...input.repos[0] ? { repository: `${repository.owner}/${repository.name}` } : {},
2696
- ...input.assignedOnly ? { assignedOnly: true } : {}
2697
- }
2698
- }
2662
+ nextSteps: "Run 'gh-symphony repo init' from the target repository."
2699
2663
  });
2700
- const existing = await loadGlobalConfig(configDir);
2701
- const globalConfig = {
2702
- activeProject: input.projectId,
2703
- projects: [
2704
- ...(existing?.projects ?? []).filter((t) => t !== input.projectId),
2705
- input.projectId
2706
- ]
2707
- };
2708
- await saveGlobalConfig(configDir, globalConfig);
2709
- }
2710
- function generateProjectId(githubProjectTitle, uniqueKey) {
2711
- const slug = githubProjectTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 32);
2712
- const suffix = createHash("sha1").update(uniqueKey).digest("hex").slice(0, 8);
2713
- return [slug || "project", suffix].join("-");
2714
2664
  }
2715
2665
 
2716
2666
  export {
2717
2667
  validateStateMapping,
2718
- warnIfProjectDiscoveryPartial,
2719
2668
  abortIfCancelled,
2720
- init_default,
2669
+ workflow_init_default,
2721
2670
  resolveStatusField,
2722
2671
  buildAutomaticStateMappings,
2723
2672
  resolvePriorityField,
2724
2673
  promptStateMappings,
2725
2674
  planWorkflowArtifacts,
2726
2675
  writeWorkflowPlan,
2727
- planEcosystem,
2728
2676
  writeEcosystem,
2729
- renderDryRunPreview,
2730
- buildDryRunJsonResult,
2731
- writeConfig,
2732
- generateProjectId
2677
+ renderDryRunPreview
2733
2678
  };
@@ -1,16 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/config.ts
4
+ import { existsSync } from "fs";
4
5
  import { readFile, writeFile, mkdir } from "fs/promises";
5
- import { dirname, join } from "path";
6
+ import { dirname, join, resolve } from "path";
6
7
  import { homedir } from "os";
7
8
  var DEFAULT_CONFIG_DIR = join(homedir(), ".gh-symphony");
8
9
  var CONFIG_FILE = "config.json";
9
10
  var DAEMON_PID_FILE = "daemon.pid";
10
11
  var ORCHESTRATOR_LOG_FILE = "orchestrator.log";
11
12
  var HTTP_STATUS_FILE = "http.json";
13
+ var REPO_RUNTIME_DIR = join(".runtime", "orchestrator");
12
14
  function resolveConfigDir(override) {
13
- return override ?? process.env.GH_SYMPHONY_CONFIG_DIR ?? DEFAULT_CONFIG_DIR;
15
+ if (override) {
16
+ return override;
17
+ }
18
+ if (process.env.GH_SYMPHONY_CONFIG_DIR) {
19
+ return process.env.GH_SYMPHONY_CONFIG_DIR;
20
+ }
21
+ const repoRuntimeDir = resolve(process.cwd(), REPO_RUNTIME_DIR);
22
+ if (existsSync(configFilePath(repoRuntimeDir))) {
23
+ return repoRuntimeDir;
24
+ }
25
+ return DEFAULT_CONFIG_DIR;
14
26
  }
15
27
  function configFilePath(configDir) {
16
28
  return join(configDir, CONFIG_FILE);
@@ -54,15 +66,7 @@ async function saveGlobalConfig(configDir, config) {
54
66
  await writeJsonFile(configFilePath(configDir), config);
55
67
  }
56
68
  async function loadProjectConfig(configDir, projectId) {
57
- const config = await readJsonFile(projectConfigPath(configDir, projectId));
58
- if (!config) {
59
- return null;
60
- }
61
- const repository = config.repository ?? firstConfiguredRepository(config);
62
- return {
63
- ...config,
64
- ...repository ? { repository } : {}
65
- };
69
+ return readJsonFile(projectConfigPath(configDir, projectId));
66
70
  }
67
71
  async function saveProjectConfig(configDir, projectId, config) {
68
72
  await writeJsonFile(projectConfigPath(configDir, projectId), config);
@@ -97,16 +101,11 @@ function isFileMissing(error) {
97
101
  error && typeof error === "object" && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")
98
102
  );
99
103
  }
100
- function firstConfiguredRepository(config) {
101
- return config.repositories?.find(
102
- (repository) => typeof repository.owner === "string" && repository.owner.length > 0 && typeof repository.name === "string" && repository.name.length > 0
103
- );
104
- }
105
104
 
106
105
  export {
106
+ REPO_RUNTIME_DIR,
107
107
  resolveConfigDir,
108
108
  configFilePath,
109
- projectConfigDir,
110
109
  daemonPidPath,
111
110
  orchestratorLogPath,
112
111
  httpStatusPath,
@@ -25,14 +25,6 @@ var GitHubScopeError = class extends GitHubApiError {
25
25
  this.name = "GitHubScopeError";
26
26
  }
27
27
  };
28
- var GitHubRepositoryLookupError = class extends GitHubApiError {
29
- constructor(reason, message, remediation, status) {
30
- super(message, status);
31
- this.reason = reason;
32
- this.remediation = remediation;
33
- this.name = "GitHubRepositoryLookupError";
34
- }
35
- };
36
28
  function createClient(token, options) {
37
29
  return {
38
30
  token,
@@ -40,77 +32,6 @@ function createClient(token, options) {
40
32
  fetchImpl: options?.fetchImpl ?? fetch
41
33
  };
42
34
  }
43
- async function getRepositoryMetadata(client, owner, name) {
44
- const restUrl = client.apiUrl.replace("/graphql", "");
45
- const baseUrl = restUrl === client.apiUrl ? REST_API_URL : restUrl;
46
- const repoPath = `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`;
47
- let response;
48
- try {
49
- response = await client.fetchImpl(`${baseUrl}${repoPath}`, {
50
- headers: {
51
- authorization: `Bearer ${client.token}`,
52
- accept: "application/vnd.github+json"
53
- }
54
- });
55
- } catch (error) {
56
- const detail = error instanceof Error && error.message.length > 0 ? ` ${error.message}` : "";
57
- throw new GitHubRepositoryLookupError(
58
- "offline",
59
- `GitHub repository validation could not reach the API.${detail}`.trim(),
60
- "Check your network connection and re-run the command to validate before saving."
61
- );
62
- }
63
- if (!response.ok) {
64
- const payload = await response.json().catch(() => null);
65
- const message = payload?.message?.trim() || response.statusText;
66
- if (response.status === 403 && (response.headers.get("x-ratelimit-remaining") === "0" || /rate limit/i.test(message))) {
67
- throw new GitHubRepositoryLookupError(
68
- "rate_limited",
69
- "GitHub API rate limit blocked repository validation.",
70
- "Wait for the rate limit window to reset, then re-run 'gh-symphony repo add owner/name'.",
71
- response.status
72
- );
73
- }
74
- if (response.status === 401) {
75
- throw new GitHubRepositoryLookupError(
76
- "invalid_token",
77
- "GitHub token is invalid or expired.",
78
- "Run 'gh auth login --scopes repo,read:org,project' or refresh GITHUB_GRAPHQL_TOKEN, then retry.",
79
- response.status
80
- );
81
- }
82
- if (response.status === 403 || /resource not accessible|saml|single sign-on|access denied/i.test(message)) {
83
- throw new GitHubRepositoryLookupError(
84
- "no_access",
85
- `GitHub denied access to ${owner}/${name}.`,
86
- "Confirm that the authenticated user can read this repository and that the token has the required access.",
87
- response.status
88
- );
89
- }
90
- if (response.status === 404) {
91
- throw new GitHubRepositoryLookupError(
92
- "not_found",
93
- `Repository ${owner}/${name} was not found.`,
94
- "Check the owner/name spelling. If the repository is private, confirm the current token can access it.",
95
- response.status
96
- );
97
- }
98
- throw new GitHubRepositoryLookupError(
99
- "unknown",
100
- `GitHub repository validation failed: ${response.status} ${message}`.trim(),
101
- "Retry the command. If the problem continues, verify GitHub API access separately.",
102
- response.status
103
- );
104
- }
105
- const repo = await response.json();
106
- return {
107
- owner: repo.owner.login,
108
- name: repo.name,
109
- url: repo.html_url,
110
- cloneUrl: repo.clone_url,
111
- visibility: repo.visibility ?? (repo.private === true ? "private" : "public")
112
- };
113
- }
114
35
  async function validateToken(client) {
115
36
  const restUrl = client.apiUrl.replace("/graphql", "");
116
37
  const baseUrl = restUrl === client.apiUrl ? REST_API_URL : restUrl;
@@ -817,9 +738,7 @@ export {
817
738
  findLinkedRepository,
818
739
  GitHubApiError,
819
740
  GitHubScopeError,
820
- GitHubRepositoryLookupError,
821
741
  createClient,
822
- getRepositoryMetadata,
823
742
  validateToken,
824
743
  checkRequiredScopes,
825
744
  discoverUserProjects,
@@ -3,7 +3,7 @@ import {
3
3
  configFilePath,
4
4
  loadGlobalConfig,
5
5
  saveGlobalConfig
6
- } from "./chunk-QIRE2VXS.js";
6
+ } from "./chunk-WOVNN5NW.js";
7
7
 
8
8
  // src/commands/config-cmd.ts
9
9
  import { spawn } from "child_process";