@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.
- package/README.md +72 -77
- package/dist/{chunk-IWFX2FMA.js → chunk-6I753NYO.js} +4 -1
- package/dist/{workflow-L3KT6HB7.js → chunk-B4ZJMAZL.js} +27 -19
- package/dist/{chunk-2TSM3INR.js → chunk-DLZAJXZL.js} +575 -12
- package/dist/chunk-GHVDABFO.js +235 -0
- package/dist/{chunk-EEQQWTXS.js → chunk-GPRCOJDJ.js} +158 -75
- package/dist/{chunk-36KYEDEO.js → chunk-MVRF7BES.js} +1 -10
- package/dist/{chunk-2UW7NQLX.js → chunk-VFHMHHZW.js} +1 -1
- package/dist/{chunk-HMLBBZNY.js → chunk-WM2B6BJ7.js} +16 -71
- package/dist/{chunk-QIRE2VXS.js → chunk-WOVNN5NW.js} +16 -17
- package/dist/{chunk-C67H3OUL.js → chunk-Z3NZOPLZ.js} +0 -81
- package/dist/{config-cmd-Z3A7V6NC.js → config-cmd-2ADPUYWA.js} +1 -1
- package/dist/{doctor-EJUMPBMW.js → doctor-EEPNFCGF.js} +464 -40
- package/dist/index.js +340 -294
- package/dist/{chunk-PUDXVBSN.js → repo-RX4OK7XH.js} +5944 -3001
- package/dist/{setup-TZJSM3QV.js → setup-XNHHRBGU.js} +57 -92
- package/dist/{upgrade-O33S2SJK.js → upgrade-NS53EO2B.js} +2 -2
- package/dist/{version-CW54Q7BK.js → version-2RHFZ5CI.js} +1 -1
- package/dist/worker-entry.js +10 -5
- package/dist/workflow-26QNZZWH.js +22 -0
- package/package.json +4 -4
- package/dist/chunk-DDL4BWSL.js +0 -146
- package/dist/chunk-DFLXHNYQ.js +0 -482
- package/dist/chunk-E7HYEEZD.js +0 -1318
- package/dist/chunk-GDE6FYN4.js +0 -26
- package/dist/chunk-GSX2FV3M.js +0 -103
- package/dist/chunk-ZHOKYUO3.js +0 -1047
- package/dist/init-54HMKNYI.js +0 -38
- package/dist/logs-GTZ4U5JE.js +0 -188
- package/dist/project-RMYMZSFV.js +0 -25
- package/dist/recover-LTLKMTRX.js +0 -133
- package/dist/repo-WI7GF6XQ.js +0 -749
- package/dist/run-IHN3ZL35.js +0 -122
- package/dist/start-RTAHQMR2.js +0 -19
- package/dist/status-F4D52OVK.js +0 -12
- package/dist/stop-MDKMJPVR.js +0 -10
|
@@ -10,24 +10,12 @@ import {
|
|
|
10
10
|
listUserProjects,
|
|
11
11
|
resolveGitHubAuth,
|
|
12
12
|
validateToken
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Z3NZOPLZ.js";
|
|
14
14
|
import {
|
|
15
15
|
formatClaudePreflightText,
|
|
16
16
|
resolveClaudeCommandBinary,
|
|
17
17
|
runClaudePreflight
|
|
18
|
-
} from "./chunk-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|