@brainervirus/workit-claude-code 8.1.0 → 8.1.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.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/workit-hook.js +37 -37
- package/dist/workit.js +358 -156
- package/package.json +3 -3
package/dist/workit.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "8.1.
|
|
68
|
+
version: "8.1.1",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,9 +103,9 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-core": "^8.1.
|
|
107
|
-
"@brainervirus/workit-cursor": "^8.1.
|
|
108
|
-
"@brainervirus/workit-opencode": "^8.1.
|
|
106
|
+
"@brainervirus/workit-core": "^8.1.1",
|
|
107
|
+
"@brainervirus/workit-cursor": "^8.1.1",
|
|
108
|
+
"@brainervirus/workit-opencode": "^8.1.1",
|
|
109
109
|
"@inkjs/ui": "2.0.0",
|
|
110
110
|
ink: "7.1.1",
|
|
111
111
|
react: "19.2.8"
|
|
@@ -12831,12 +12831,13 @@ function pushForge(cwd, options = {}) {
|
|
|
12831
12831
|
};
|
|
12832
12832
|
const forge = deriveForge(url, options);
|
|
12833
12833
|
if (!forge) {
|
|
12834
|
-
const
|
|
12834
|
+
const parsed = parseRemoteUrl(url);
|
|
12835
|
+
const host = parsed?.host || null;
|
|
12835
12836
|
return {
|
|
12836
12837
|
ok: false,
|
|
12837
12838
|
code: "unavailable",
|
|
12838
|
-
error: host ? `cannot tell whether push host "${host}" is GitHub or GitLab` : `push URL ${redactRemote(url)} of remote "${remote}" is not a GitHub/GitLab URL`,
|
|
12839
|
-
unblock: host ? `
|
|
12839
|
+
error: host ? parsed?.protocol === "ssh" && !host.includes(".") ? `unsupported_forge: could not resolve ssh alias "${host}" to GitHub or GitLab; PR and CI verbs need one (workit git push still pushes with git)` : parsed?.protocol === "ssh" ? `unsupported_forge: ssh host "${host}" is not a GitHub/GitLab host or an alias workit can resolve; PR and CI verbs need one (workit git push still pushes with git)` : `unsupported_forge: cannot tell whether push host "${host}" is GitHub or GitLab; PR and CI verbs need one (workit git push still pushes with git)` : `push URL ${redactRemote(url)} of remote "${remote}" is not a GitHub/GitLab URL`,
|
|
12840
|
+
unblock: host ? `if ${host} is an ssh alias of GitHub/GitLab, add "Host ${host}" with "HostName github.com" (or gitlab.com) to ~/.ssh/config; if it is a self-hosted GitHub/GitLab, set github.host or gitlab.host in ~/.config/workit/vcs.json; other forges (Bitbucket, Gitea…) have no PR/CI verbs` : `git remote set-url --push ${remote} <ssh-or-https-url>`
|
|
12840
12841
|
};
|
|
12841
12842
|
}
|
|
12842
12843
|
return { ok: true, remote, url: redactRemote(url), forge };
|
|
@@ -12847,8 +12848,8 @@ function forgeConflict(derived, configuredProvider) {
|
|
|
12847
12848
|
return null;
|
|
12848
12849
|
return {
|
|
12849
12850
|
code: "blocked",
|
|
12850
|
-
error: `forge_mismatch: push remote ${derived.host} is ${derived.kind} but the workspace vcs.provider is ${configured}`,
|
|
12851
|
-
unblock: `
|
|
12851
|
+
error: `forge_mismatch: push remote ${derived.host} is ${derived.kind} but the workspace vcs.provider is ${configured}, so its account and grants do not apply; PR and CI verbs stop here (workit git push still pushes with git)`,
|
|
12852
|
+
unblock: `add a workspace whose glob matches only this repo, with "vcs": {"provider": "${derived.kind}"} (and its account), to ~/.config/workit/workspaces.json; the most specific glob wins`
|
|
12852
12853
|
};
|
|
12853
12854
|
}
|
|
12854
12855
|
var MAX_BUFFER, GIT_TIMEOUTS, git2 = (cwd, args, options = {}) => {
|
|
@@ -15235,6 +15236,7 @@ var init_commit_flavors = __esm(() => {
|
|
|
15235
15236
|
var init_git = () => {};
|
|
15236
15237
|
|
|
15237
15238
|
// packages/workit-core/src/core/workspaces.ts
|
|
15239
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
15238
15240
|
import { createHash as createHash8 } from "node:crypto";
|
|
15239
15241
|
import { readFileSync as readFileSync4, realpathSync as realpathSync3 } from "node:fs";
|
|
15240
15242
|
import path14 from "node:path";
|
|
@@ -15362,6 +15364,46 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15362
15364
|
};
|
|
15363
15365
|
}
|
|
15364
15366
|
return { ok: true };
|
|
15367
|
+
}, WorkspaceConfigError, mainCheckouts, mainCheckoutOf = (cwd) => {
|
|
15368
|
+
const cached = mainCheckouts.get(cwd);
|
|
15369
|
+
if (cached !== undefined)
|
|
15370
|
+
return cached;
|
|
15371
|
+
const env = { ...process.env };
|
|
15372
|
+
for (const name of ["GIT_DIR", "GIT_WORK_TREE", "GIT_COMMON_DIR", "GIT_INDEX_FILE"])
|
|
15373
|
+
delete env[name];
|
|
15374
|
+
const git = (args) => {
|
|
15375
|
+
const run = spawnSync8("git", args, {
|
|
15376
|
+
cwd,
|
|
15377
|
+
env,
|
|
15378
|
+
encoding: "utf8",
|
|
15379
|
+
timeout: 5000,
|
|
15380
|
+
windowsHide: true
|
|
15381
|
+
});
|
|
15382
|
+
return run.status === 0 ? run.stdout : null;
|
|
15383
|
+
};
|
|
15384
|
+
let main = null;
|
|
15385
|
+
const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
|
|
15386
|
+
const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
|
|
15387
|
+
if (gitDir && common && path14.resolve(gitDir) !== path14.resolve(common)) {
|
|
15388
|
+
const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
|
|
15389
|
+
main = listed?.trim() || (path14.basename(common) === ".git" ? path14.dirname(common) : common);
|
|
15390
|
+
}
|
|
15391
|
+
mainCheckouts.set(cwd, main);
|
|
15392
|
+
return main;
|
|
15393
|
+
}, matchingEntries = (cwd, entries) => {
|
|
15394
|
+
const match = (where) => {
|
|
15395
|
+
const targets = [where, realpathOf(where)].map((value) => value.replaceAll("\\", "/"));
|
|
15396
|
+
return entries.filter((entry) => {
|
|
15397
|
+
const glob = entry.glob.replaceAll("\\", "/");
|
|
15398
|
+
const canonical = canonicalGlob(glob);
|
|
15399
|
+
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
15400
|
+
});
|
|
15401
|
+
};
|
|
15402
|
+
const direct = match(cwd);
|
|
15403
|
+
if (direct.length)
|
|
15404
|
+
return direct;
|
|
15405
|
+
const main = mainCheckoutOf(cwd);
|
|
15406
|
+
return main ? match(main) : direct;
|
|
15365
15407
|
}, realpathOf = (p) => {
|
|
15366
15408
|
const real = realpathSync3.native ?? realpathSync3;
|
|
15367
15409
|
try {
|
|
@@ -15383,41 +15425,27 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15383
15425
|
if (named.length === 1)
|
|
15384
15426
|
return named[0];
|
|
15385
15427
|
if (named.length > 1)
|
|
15386
|
-
throw new
|
|
15428
|
+
throw new WorkspaceConfigError(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
15387
15429
|
if (matches.length > 0) {
|
|
15388
|
-
throw new
|
|
15430
|
+
throw new WorkspaceConfigError(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
15389
15431
|
}
|
|
15390
|
-
throw new
|
|
15432
|
+
throw new WorkspaceConfigError(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
15391
15433
|
}
|
|
15392
15434
|
if (matches.length < 2)
|
|
15393
15435
|
return matches[0];
|
|
15394
15436
|
const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
|
|
15395
15437
|
const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
|
|
15396
15438
|
if (mostSpecific.length > 1) {
|
|
15397
|
-
throw new
|
|
15439
|
+
throw new WorkspaceConfigError(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
|
|
15398
15440
|
}
|
|
15399
15441
|
return mostSpecific[0];
|
|
15400
15442
|
}, resolveWorkspaceFromEntries = (cwd, entries, workspaceName) => {
|
|
15401
|
-
const
|
|
15402
|
-
const matches = [];
|
|
15403
|
-
for (const ws of entries) {
|
|
15404
|
-
const glob = ws.glob.replaceAll("\\", "/");
|
|
15405
|
-
const canonical = canonicalGlob(glob);
|
|
15406
|
-
let matched = false;
|
|
15407
|
-
for (const target of targets) {
|
|
15408
|
-
if (matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target)) {
|
|
15409
|
-
matched = true;
|
|
15410
|
-
break;
|
|
15411
|
-
}
|
|
15412
|
-
}
|
|
15413
|
-
if (matched)
|
|
15414
|
-
matches.push(ws);
|
|
15415
|
-
}
|
|
15443
|
+
const matches = matchingEntries(cwd, entries);
|
|
15416
15444
|
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
15417
15445
|
}, resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
15418
15446
|
const result = readWorkspacesResult(dir);
|
|
15419
15447
|
if (result.status === "malformed" || result.status === "invalid")
|
|
15420
|
-
throw new
|
|
15448
|
+
throw new WorkspaceConfigError(result.error);
|
|
15421
15449
|
return resolveWorkspaceFromEntries(cwd, result.entries, workspaceName);
|
|
15422
15450
|
}, runtimeWorkspacePolicySchema = (kind) => {
|
|
15423
15451
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
@@ -15443,31 +15471,26 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15443
15471
|
} catch (error) {
|
|
15444
15472
|
if (error.code === "ENOENT")
|
|
15445
15473
|
return null;
|
|
15446
|
-
throw new
|
|
15474
|
+
throw new WorkspaceConfigError(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
15447
15475
|
}
|
|
15448
15476
|
let parsed;
|
|
15449
15477
|
try {
|
|
15450
15478
|
parsed = JSON.parse(raw);
|
|
15451
15479
|
} catch {
|
|
15452
|
-
throw new
|
|
15480
|
+
throw new WorkspaceConfigError(`${file} is not valid JSON`);
|
|
15453
15481
|
}
|
|
15454
15482
|
const validated = runtimeWorkspaceIndexSchema.safeParse(parsed);
|
|
15455
15483
|
if (!validated.success) {
|
|
15456
15484
|
const detail = validated.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspaces"}: ${issue.message}`).join("; ");
|
|
15457
|
-
throw new
|
|
15485
|
+
throw new WorkspaceConfigError(`${file} has invalid workspace matching data: ${detail}`);
|
|
15458
15486
|
}
|
|
15459
15487
|
const entries = validated.data.workspaces;
|
|
15460
15488
|
for (const entry of entries ?? []) {
|
|
15461
15489
|
const glob = validateWorkspaceGlob(entry.glob);
|
|
15462
15490
|
if (!glob.ok)
|
|
15463
|
-
throw new
|
|
15491
|
+
throw new WorkspaceConfigError(`${file} workspace ${entry.name}: ${glob.error}`);
|
|
15464
15492
|
}
|
|
15465
|
-
const
|
|
15466
|
-
const matches = (entries ?? []).filter((entry) => {
|
|
15467
|
-
const glob = entry.glob.replaceAll("\\", "/");
|
|
15468
|
-
const canonical = canonicalGlob(glob);
|
|
15469
|
-
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
15470
|
-
});
|
|
15493
|
+
const matches = matchingEntries(cwd, entries ?? []);
|
|
15471
15494
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
15472
15495
|
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
15473
15496
|
return selected ? { file, selected } : null;
|
|
@@ -15482,7 +15505,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15482
15505
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
15483
15506
|
if (!policy.success) {
|
|
15484
15507
|
const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
|
|
15485
|
-
throw new
|
|
15508
|
+
throw new WorkspaceConfigError(`${file} has invalid ${kind} policy configuration: ${detail}`);
|
|
15486
15509
|
}
|
|
15487
15510
|
return policy.data;
|
|
15488
15511
|
}, resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
|
|
@@ -15492,10 +15515,10 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15492
15515
|
const key = kind === "branch" ? "branchPolicy" : "commitPolicy";
|
|
15493
15516
|
const profileName = requestedProfile?.trim() || candidate.defaultProfile;
|
|
15494
15517
|
if (candidate.defaultProfile && !Object.hasOwn(candidate.profiles ?? {}, candidate.defaultProfile))
|
|
15495
|
-
throw new
|
|
15518
|
+
throw new WorkspaceConfigError(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(candidate.defaultProfile)}`);
|
|
15496
15519
|
const profile = profileName ? candidate.profiles?.[profileName] : undefined;
|
|
15497
15520
|
if (profileName && !profile)
|
|
15498
|
-
throw new
|
|
15521
|
+
throw new WorkspaceConfigError(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(profileName)}`);
|
|
15499
15522
|
const profilePolicy = profile?.[key];
|
|
15500
15523
|
const workspacePolicy = candidate[key];
|
|
15501
15524
|
return {
|
|
@@ -15666,6 +15689,10 @@ var init_workspaces = __esm(() => {
|
|
|
15666
15689
|
});
|
|
15667
15690
|
UNSUPPORTED_GLOB = /[?[\]{}]/;
|
|
15668
15691
|
UNSUPPORTED_EXTGLOB = /[@+*]\(|!/;
|
|
15692
|
+
WorkspaceConfigError = class WorkspaceConfigError extends Error {
|
|
15693
|
+
name = "WorkspaceConfigError";
|
|
15694
|
+
};
|
|
15695
|
+
mainCheckouts = new Map;
|
|
15669
15696
|
runtimeWorkspaceIndexSchema = object({
|
|
15670
15697
|
workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
|
|
15671
15698
|
}).passthrough();
|
|
@@ -15673,7 +15700,7 @@ var init_workspaces = __esm(() => {
|
|
|
15673
15700
|
|
|
15674
15701
|
// packages/workit-core/src/core/release-tracks.ts
|
|
15675
15702
|
import { createHash as createHash9 } from "node:crypto";
|
|
15676
|
-
import { spawnSync as
|
|
15703
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
15677
15704
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
15678
15705
|
function readReleaseTracks(raw) {
|
|
15679
15706
|
const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
|
|
@@ -16075,7 +16102,7 @@ var ReleaseTrackError, KNOWN_FIELDS, BRANCH_FIELDS, PLACEHOLDER, HAS_PLACEHOLDER
|
|
|
16075
16102
|
const remote = remotes.find((name) => bare.startsWith(`${name}/`));
|
|
16076
16103
|
return remote ? bare.slice(remote.length + 1) : bare;
|
|
16077
16104
|
}, MAX_RECORDED_HOPS = 10, git4 = (cwd, args) => {
|
|
16078
|
-
const run =
|
|
16105
|
+
const run = spawnSync9("git", args, {
|
|
16079
16106
|
cwd,
|
|
16080
16107
|
encoding: "utf8",
|
|
16081
16108
|
timeout: 20000,
|
|
@@ -16136,7 +16163,7 @@ var init_release_tracks = __esm(() => {
|
|
|
16136
16163
|
// packages/workit-core/src/core/vcs-config.ts
|
|
16137
16164
|
import fs12 from "node:fs";
|
|
16138
16165
|
import path15 from "node:path";
|
|
16139
|
-
import { spawnSync as
|
|
16166
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
16140
16167
|
function vcsConfig(mode, cwd, options = {}) {
|
|
16141
16168
|
const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
|
|
16142
16169
|
const wsVcs = ws?.vcs ?? {};
|
|
@@ -16219,7 +16246,7 @@ function vcsConfig(mode, cwd, options = {}) {
|
|
|
16219
16246
|
return out;
|
|
16220
16247
|
}
|
|
16221
16248
|
var workspacesPath = () => path15.join(configDir(), "workspaces.json"), vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd(), remoteProvider = (cwd) => {
|
|
16222
|
-
const r =
|
|
16249
|
+
const r = spawnSync10("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
16223
16250
|
if (r.status !== 0)
|
|
16224
16251
|
return null;
|
|
16225
16252
|
const url = (r.stdout ?? "").trim();
|
|
@@ -18535,7 +18562,7 @@ var init_pr_body = __esm(() => {
|
|
|
18535
18562
|
|
|
18536
18563
|
// packages/workit-core/src/core/pr-create.ts
|
|
18537
18564
|
import path19 from "node:path";
|
|
18538
|
-
import { spawnSync as
|
|
18565
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
18539
18566
|
import { pathToFileURL } from "node:url";
|
|
18540
18567
|
var safePushUrl = (remote) => {
|
|
18541
18568
|
const raw = remote.trim();
|
|
@@ -18563,7 +18590,7 @@ var safePushUrl = (remote) => {
|
|
|
18563
18590
|
const target = safePushUrl(remote);
|
|
18564
18591
|
if (!target)
|
|
18565
18592
|
return false;
|
|
18566
|
-
const result =
|
|
18593
|
+
const result = spawnSync11("git", ["config", "--get-regexp", "^url\\..*\\.(insteadof|pushinsteadof)$"], { cwd, encoding: "utf8" });
|
|
18567
18594
|
if (result.status !== 0 && result.status !== 1)
|
|
18568
18595
|
return false;
|
|
18569
18596
|
const prefixes = (result.stdout ?? "").split(/\r?\n/u).map((line) => line.trim().slice(line.trim().indexOf(" ") + 1)).filter(Boolean);
|
|
@@ -62851,7 +62878,7 @@ var init_support_matrix = __esm(() => {
|
|
|
62851
62878
|
});
|
|
62852
62879
|
|
|
62853
62880
|
// packages/workit-cli/src/admin/host-install.ts
|
|
62854
|
-
import { spawnSync as
|
|
62881
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
62855
62882
|
import {
|
|
62856
62883
|
accessSync,
|
|
62857
62884
|
constants as constants2,
|
|
@@ -63122,7 +63149,7 @@ function runHostCommand(step, context = {}) {
|
|
|
63122
63149
|
stderr: `Cannot safely execute batch shim ${step.command}; resolve its Node.js CLI entrypoint and retry`
|
|
63123
63150
|
};
|
|
63124
63151
|
}
|
|
63125
|
-
const result =
|
|
63152
|
+
const result = spawnSync12(step.command, step.args, {
|
|
63126
63153
|
cwd: step.cwd,
|
|
63127
63154
|
env: (() => {
|
|
63128
63155
|
const home = context.home ?? context.env?.HOME ?? os6.homedir();
|
|
@@ -63327,7 +63354,7 @@ var init_skill_manifests = __esm(() => {
|
|
|
63327
63354
|
});
|
|
63328
63355
|
|
|
63329
63356
|
// packages/workit-cli/src/admin/doctor.ts
|
|
63330
|
-
import { spawnSync as
|
|
63357
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
63331
63358
|
import {
|
|
63332
63359
|
existsSync as existsSync13,
|
|
63333
63360
|
lstatSync as lstatSync4,
|
|
@@ -63411,7 +63438,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63411
63438
|
}
|
|
63412
63439
|
return false;
|
|
63413
63440
|
}, versionOf = (bin, env, timeout) => {
|
|
63414
|
-
const r =
|
|
63441
|
+
const r = spawnSync13(bin, ["--version"], { encoding: "utf8", env, timeout });
|
|
63415
63442
|
if (r.error)
|
|
63416
63443
|
return null;
|
|
63417
63444
|
return (r.stdout ?? "").trim();
|
|
@@ -63660,7 +63687,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63660
63687
|
`)) {
|
|
63661
63688
|
return false;
|
|
63662
63689
|
}
|
|
63663
|
-
return
|
|
63690
|
+
return spawnSync13(runtime, ["--check", entry], { encoding: "utf8", env }).status === 0;
|
|
63664
63691
|
} catch {
|
|
63665
63692
|
return false;
|
|
63666
63693
|
}
|
|
@@ -63874,7 +63901,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63874
63901
|
if (!cmd)
|
|
63875
63902
|
return null;
|
|
63876
63903
|
try {
|
|
63877
|
-
const r =
|
|
63904
|
+
const r = spawnSync13(cmd, ["view", pkgName, "version"], {
|
|
63878
63905
|
encoding: "utf8",
|
|
63879
63906
|
timeout: 20000,
|
|
63880
63907
|
env: res.env
|
|
@@ -64313,7 +64340,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64313
64340
|
}, defaultIdentityProbes = (env) => ({
|
|
64314
64341
|
origin: (cwd) => {
|
|
64315
64342
|
try {
|
|
64316
|
-
const out =
|
|
64343
|
+
const out = spawnSync13("git", ["remote", "get-url", "origin"], {
|
|
64317
64344
|
cwd,
|
|
64318
64345
|
encoding: "utf8",
|
|
64319
64346
|
env
|
|
@@ -64325,7 +64352,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64325
64352
|
},
|
|
64326
64353
|
ghLogin: (e) => {
|
|
64327
64354
|
try {
|
|
64328
|
-
const out =
|
|
64355
|
+
const out = spawnSync13("gh", ["api", "user", "--jq", ".login"], { encoding: "utf8", env: e });
|
|
64329
64356
|
const login = (out.stdout ?? "").trim();
|
|
64330
64357
|
return out.status === 0 && login ? login : null;
|
|
64331
64358
|
} catch {
|
|
@@ -64334,7 +64361,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64334
64361
|
},
|
|
64335
64362
|
glabLogin: (e) => {
|
|
64336
64363
|
try {
|
|
64337
|
-
const out =
|
|
64364
|
+
const out = spawnSync13("glab", ["api", "user", "--jq", ".username"], {
|
|
64338
64365
|
encoding: "utf8",
|
|
64339
64366
|
env: e
|
|
64340
64367
|
});
|
|
@@ -64346,7 +64373,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64346
64373
|
},
|
|
64347
64374
|
sshLogin: (host) => {
|
|
64348
64375
|
try {
|
|
64349
|
-
const out =
|
|
64376
|
+
const out = spawnSync13("ssh", ["-o", "BatchMode=yes", "-o", "ConnectTimeout=5", "-T", `git@${host}`], {
|
|
64350
64377
|
encoding: "utf8",
|
|
64351
64378
|
env
|
|
64352
64379
|
});
|
|
@@ -69504,7 +69531,7 @@ var init_init = __esm(() => {
|
|
|
69504
69531
|
});
|
|
69505
69532
|
|
|
69506
69533
|
// packages/workit-cli/src/upgrade.ts
|
|
69507
|
-
import { spawnSync as
|
|
69534
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
69508
69535
|
import {
|
|
69509
69536
|
existsSync as existsSync17,
|
|
69510
69537
|
mkdtempSync as mkdtempSync3,
|
|
@@ -69860,7 +69887,7 @@ async function runLaunchCommand(argv, deps = {}) {
|
|
|
69860
69887
|
}
|
|
69861
69888
|
if (deps.run)
|
|
69862
69889
|
return deps.run(host, hostArgs).status ?? 1;
|
|
69863
|
-
return
|
|
69890
|
+
return spawnSync14(launch.command, launch.args, {
|
|
69864
69891
|
stdio: "inherit",
|
|
69865
69892
|
env
|
|
69866
69893
|
}).status ?? 1;
|
|
@@ -70042,7 +70069,7 @@ var init_launch = __esm(() => {
|
|
|
70042
70069
|
});
|
|
70043
70070
|
|
|
70044
70071
|
// packages/workit-core/src/knowledge.ts
|
|
70045
|
-
import { spawnSync as
|
|
70072
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
70046
70073
|
import fs17 from "node:fs";
|
|
70047
70074
|
import path36 from "node:path";
|
|
70048
70075
|
function lintKnowledge(root) {
|
|
@@ -70163,7 +70190,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
70163
70190
|
return "unreadable";
|
|
70164
70191
|
}
|
|
70165
70192
|
}, trackedTopLevel = (root) => {
|
|
70166
|
-
const run =
|
|
70193
|
+
const run = spawnSync15("git", ["ls-files", "-z", "--cached"], {
|
|
70167
70194
|
cwd: root,
|
|
70168
70195
|
encoding: "utf8",
|
|
70169
70196
|
maxBuffer: 256 * 1024 * 1024,
|
|
@@ -70542,7 +70569,7 @@ var init_redact = __esm(() => {
|
|
|
70542
70569
|
});
|
|
70543
70570
|
|
|
70544
70571
|
// packages/workit-core/src/checks.ts
|
|
70545
|
-
import { spawn, spawnSync as
|
|
70572
|
+
import { spawn, spawnSync as spawnSync16 } from "node:child_process";
|
|
70546
70573
|
import { createHash as createHash14 } from "node:crypto";
|
|
70547
70574
|
import fs18 from "node:fs";
|
|
70548
70575
|
import os13 from "node:os";
|
|
@@ -70721,7 +70748,7 @@ function runCheckCommand(argv, options) {
|
|
|
70721
70748
|
if (!child?.pid)
|
|
70722
70749
|
return;
|
|
70723
70750
|
if (windows)
|
|
70724
|
-
|
|
70751
|
+
spawnSync16("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
|
|
70725
70752
|
stdio: "ignore",
|
|
70726
70753
|
windowsHide: true
|
|
70727
70754
|
});
|
|
@@ -71443,7 +71470,7 @@ var init_check = __esm(() => {
|
|
|
71443
71470
|
var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock) => ({ ok: false, code, error, ...unblock ? { unblock } : {} });
|
|
71444
71471
|
|
|
71445
71472
|
// packages/workit-core/src/git/ops.ts
|
|
71446
|
-
import { spawnSync as
|
|
71473
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
71447
71474
|
import { existsSync as existsSync18, readFileSync as readFileSync18 } from "node:fs";
|
|
71448
71475
|
import path39 from "node:path";
|
|
71449
71476
|
function operationInProgress(cwd) {
|
|
@@ -71931,7 +71958,8 @@ ${gitOutput(run)}`);
|
|
|
71931
71958
|
url: plan.url,
|
|
71932
71959
|
previous: before.sha,
|
|
71933
71960
|
pushed,
|
|
71934
|
-
forced
|
|
71961
|
+
forced,
|
|
71962
|
+
...input.identity ? { identity: input.identity } : {}
|
|
71935
71963
|
});
|
|
71936
71964
|
return success2({
|
|
71937
71965
|
remote: plan.remote,
|
|
@@ -71975,7 +72003,7 @@ ${run.stdout}`;
|
|
|
71975
72003
|
} : { ok: false, lease: false, error: gitError(run) };
|
|
71976
72004
|
}
|
|
71977
72005
|
var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}) => {
|
|
71978
|
-
const result =
|
|
72006
|
+
const result = spawnSync17("git", args, {
|
|
71979
72007
|
cwd,
|
|
71980
72008
|
encoding: "utf8",
|
|
71981
72009
|
env: { ...options.env ?? process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
@@ -72355,16 +72383,16 @@ function waitVerdict(doc, options) {
|
|
|
72355
72383
|
const checks = doc.checks.state;
|
|
72356
72384
|
if (checks === "failing")
|
|
72357
72385
|
return { state: "failed", reason: "checks_failing" };
|
|
72358
|
-
if (checks
|
|
72359
|
-
return { state: "waiting", reason: "checks_pending" };
|
|
72360
|
-
if (checks === "passing")
|
|
72361
|
-
return { state: "ready", reason: "checks_passing" };
|
|
72362
|
-
if (doc.conflicts)
|
|
72386
|
+
if (doc.conflicts && checks !== "passing")
|
|
72363
72387
|
return {
|
|
72364
72388
|
state: "blocked",
|
|
72365
72389
|
reason: "conflicts",
|
|
72366
72390
|
unblock: `rebase onto ${doc.base} and push; CI does not run on a conflicting PR`
|
|
72367
72391
|
};
|
|
72392
|
+
if (checks === "pending")
|
|
72393
|
+
return { state: "waiting", reason: "checks_pending" };
|
|
72394
|
+
if (checks === "passing")
|
|
72395
|
+
return { state: "ready", reason: "checks_passing" };
|
|
72368
72396
|
const ciRequired = doc.checks.missingRequired === null || doc.mergeState === "ci_must_pass" || doc.mergeState === "ci_still_running";
|
|
72369
72397
|
if (ciRequired)
|
|
72370
72398
|
return { state: "waiting", reason: "no_checks_yet" };
|
|
@@ -72472,7 +72500,7 @@ var init_report = __esm(() => {
|
|
|
72472
72500
|
});
|
|
72473
72501
|
|
|
72474
72502
|
// packages/workit-core/src/forge/pr-ops.ts
|
|
72475
|
-
import { spawnSync as
|
|
72503
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
72476
72504
|
function fillFromCommits(cwd, resolved, base) {
|
|
72477
72505
|
const tracking = `refs/remotes/${resolved.baseRemote}/${base}`;
|
|
72478
72506
|
if (!base.startsWith("-"))
|
|
@@ -72480,7 +72508,7 @@ function fillFromCommits(cwd, resolved, base) {
|
|
|
72480
72508
|
const from = resolveRef(cwd, tracking) ?? resolveRef(cwd, `refs/heads/${base}`);
|
|
72481
72509
|
if (!from)
|
|
72482
72510
|
return failure3("not_found", `base ${base} is not available locally`, `git fetch ${resolved.baseRemote} ${base}`);
|
|
72483
|
-
const log =
|
|
72511
|
+
const log = spawnSync18("git", ["log", "--reverse", "--no-merges", "--format=%s%x1f%b%x1e", `${from}..HEAD`], {
|
|
72484
72512
|
cwd,
|
|
72485
72513
|
encoding: "utf8",
|
|
72486
72514
|
timeout: GIT_TIMEOUTS.local,
|
|
@@ -72785,7 +72813,7 @@ var init_pr_ops = __esm(() => {
|
|
|
72785
72813
|
});
|
|
72786
72814
|
|
|
72787
72815
|
// packages/workit-core/src/forge/exec.ts
|
|
72788
|
-
import { spawnSync as
|
|
72816
|
+
import { spawnSync as spawnSync19 } from "node:child_process";
|
|
72789
72817
|
import fs20 from "node:fs";
|
|
72790
72818
|
import path41 from "node:path";
|
|
72791
72819
|
function findExecutable(bin, env) {
|
|
@@ -72820,7 +72848,7 @@ function systemRunner(kind, apiHost, env = process.env) {
|
|
|
72820
72848
|
if (!exe)
|
|
72821
72849
|
return { status: null, stdout: "", stderr: "", timedOut: false, missing: true };
|
|
72822
72850
|
const token = options.token ? kind === "github" ? { GH_TOKEN: options.token, GH_ENTERPRISE_TOKEN: options.token } : { GITLAB_TOKEN: options.token } : {};
|
|
72823
|
-
const result =
|
|
72851
|
+
const result = spawnSync19(exe, [...args], {
|
|
72824
72852
|
encoding: "utf8",
|
|
72825
72853
|
env: { ...childEnv, ...token },
|
|
72826
72854
|
maxBuffer: MAX_BUFFER2,
|
|
@@ -72839,17 +72867,45 @@ function systemRunner(kind, apiHost, env = process.env) {
|
|
|
72839
72867
|
};
|
|
72840
72868
|
};
|
|
72841
72869
|
}
|
|
72870
|
+
function forgeReason(run) {
|
|
72871
|
+
const parts = [];
|
|
72872
|
+
try {
|
|
72873
|
+
const body = JSON.parse(run.stdout);
|
|
72874
|
+
const add = (value) => {
|
|
72875
|
+
if (typeof value === "string" && value.trim())
|
|
72876
|
+
parts.push(value.trim());
|
|
72877
|
+
else if (Array.isArray(value))
|
|
72878
|
+
value.forEach(add);
|
|
72879
|
+
else if (value && typeof value === "object") {
|
|
72880
|
+
const record = value;
|
|
72881
|
+
if (typeof record.message === "string")
|
|
72882
|
+
add(record.message);
|
|
72883
|
+
else if (!("code" in record))
|
|
72884
|
+
Object.values(record).forEach(add);
|
|
72885
|
+
}
|
|
72886
|
+
};
|
|
72887
|
+
add(body.message);
|
|
72888
|
+
add(body.error);
|
|
72889
|
+
add(body.errors);
|
|
72890
|
+
} catch {}
|
|
72891
|
+
const stderr = (run.stderr.split(/\r?\n/u).find((value) => value.trim()) ?? "").trim();
|
|
72892
|
+
const unique = [...new Set(parts)];
|
|
72893
|
+
const text = unique.length ? `${unique.join("; ")}${stderr ? ` (${stderr.replace(/^gh: |^glab: /u, "")})` : ""}` : stderr || (run.stdout.split(/\r?\n/u).find((value) => value.trim()) ?? "");
|
|
72894
|
+
return redactText(text).slice(0, 300);
|
|
72895
|
+
}
|
|
72842
72896
|
function cliFailure(bin, apiHost, run, what, timeoutMs) {
|
|
72843
72897
|
if (run.missing)
|
|
72844
72898
|
return failure3("unavailable", `${bin} is not installed`, installHint(bin));
|
|
72845
72899
|
if (run.timedOut)
|
|
72846
|
-
return failure3("unavailable", `${bin} api ${what} timed out after ${timeoutMs} ms`);
|
|
72900
|
+
return failure3("unavailable", run.timeoutMs === 0 ? `${bin} api ${what} not attempted: the command's time budget ran out` : `${bin} api ${what} timed out after ${run.timeoutMs ?? timeoutMs} ms`, `check the network to ${apiHost}, then retry`);
|
|
72847
72901
|
const stderr = redactText(run.stderr).trim();
|
|
72848
72902
|
if (/auth login|not logged in|no token|authentication required|bad credentials|\b401\b|unauthorized/iu.test(stderr))
|
|
72849
72903
|
return failure3("unavailable", `${bin} is not authenticated for ${apiHost}`, loginHint(bin, apiHost));
|
|
72850
72904
|
if (/\b404\b|not found/iu.test(stderr))
|
|
72851
72905
|
return failure3("not_found", `${what} was not found`);
|
|
72852
72906
|
const first = stderr.split(/\r?\n/u).find((value) => value.trim()) ?? `exit ${run.status}`;
|
|
72907
|
+
if (isNetworkError(stderr))
|
|
72908
|
+
return failure3("unavailable", `${bin} api ${what} failed (network): ${first.slice(0, 200)}`, `check the network to ${apiHost}, then retry`);
|
|
72853
72909
|
return failure3("failed", `${bin} api ${what} failed: ${first.slice(0, 200)}`);
|
|
72854
72910
|
}
|
|
72855
72911
|
function apiJson(runner, bin, apiHost, args, what, timeoutMs = FORGE_TIMEOUTS.api, options = {}) {
|
|
@@ -72880,12 +72936,15 @@ function apiWrite(runner, bin, apiHost, args, what, timeoutMs = FORGE_TIMEOUTS.a
|
|
|
72880
72936
|
if (run.status !== 0) {
|
|
72881
72937
|
const text = redactText(`${run.stderr}
|
|
72882
72938
|
${run.stdout}`).trim();
|
|
72883
|
-
const reason = (
|
|
72939
|
+
const reason = forgeReason(run);
|
|
72884
72940
|
if (!run.missing && !run.timedOut && /\b409\b|head branch was modified|sha does not match|sha.*mismatch/iu.test(text))
|
|
72885
72941
|
return failure3("blocked", `head_moved: ${what} refused because the head changed (${reason})`, "workit pr status # re-check the new head, then verify it again");
|
|
72886
72942
|
if (!run.missing && !run.timedOut && /\b(405|406|422)\b/u.test(text))
|
|
72887
72943
|
return failure3("blocked", `${what} refused by the forge: ${reason}`);
|
|
72888
|
-
|
|
72944
|
+
const failed = cliFailure(bin, apiHost, run, what, timeoutMs);
|
|
72945
|
+
if (!failed.ok && failed.code === "unavailable" && !run.missing && !/ is not authenticated for /u.test(failed.error))
|
|
72946
|
+
return failure3("unavailable", failed.error, "workit pr status # the write may have gone through; check it first, then retry");
|
|
72947
|
+
return failed;
|
|
72889
72948
|
}
|
|
72890
72949
|
if (!run.stdout.trim())
|
|
72891
72950
|
return { ok: true, data: {} };
|
|
@@ -72895,11 +72954,12 @@ ${run.stdout}`).trim();
|
|
|
72895
72954
|
return failure3("failed", `${bin} api ${what} returned invalid JSON`);
|
|
72896
72955
|
}
|
|
72897
72956
|
}
|
|
72898
|
-
var FORGE_TIMEOUTS, MAX_BUFFER2, installHint = (bin) => bin === "gh" ? "install the GitHub CLI (https://cli.github.com) and run: gh auth login" : "install glab (https://gitlab.com/gitlab-org/cli) and run: glab auth login", loginHint = (bin, apiHost) => `${bin} auth login --hostname ${apiHost}
|
|
72957
|
+
var FORGE_TIMEOUTS, MAX_BUFFER2, installHint = (bin) => bin === "gh" ? "install the GitHub CLI (https://cli.github.com) and run: gh auth login" : "install glab (https://gitlab.com/gitlab-org/cli) and run: glab auth login", loginHint = (bin, apiHost) => `${bin} auth login --hostname ${apiHost}`, NETWORK, isNetworkError = (text) => NETWORK.test(text);
|
|
72899
72958
|
var init_exec = __esm(() => {
|
|
72900
72959
|
init_redact();
|
|
72901
72960
|
FORGE_TIMEOUTS = { api: 20000, log: 30000 };
|
|
72902
72961
|
MAX_BUFFER2 = 64 * 1024 * 1024;
|
|
72962
|
+
NETWORK = /error connecting|could not resolve|no such host|connection (refused|reset|timed out)|network is unreachable|i\/o timeout|tls handshake|unexpected eof|\bHTTP 5\d\d\b|bad gateway|service unavailable|gateway time-?out/iu;
|
|
72903
72963
|
});
|
|
72904
72964
|
|
|
72905
72965
|
// packages/workit-core/src/forge/github.ts
|
|
@@ -73491,6 +73551,82 @@ var init_gitlab = __esm(() => {
|
|
|
73491
73551
|
|
|
73492
73552
|
// packages/workit-core/src/forge/resolve.ts
|
|
73493
73553
|
import fs21 from "node:fs";
|
|
73554
|
+
function memo4(scope, key, compute, now = Date.now) {
|
|
73555
|
+
let entries = memoScopes.get(scope.owner);
|
|
73556
|
+
if (!entries)
|
|
73557
|
+
memoScopes.set(scope.owner, entries = new Map);
|
|
73558
|
+
const full = `${scope.key} ${key}`;
|
|
73559
|
+
const hit = entries.get(full);
|
|
73560
|
+
if (hit && now() - hit.at < MEMO_TTL_MS)
|
|
73561
|
+
return hit.value;
|
|
73562
|
+
const { keep, value } = compute();
|
|
73563
|
+
if (keep)
|
|
73564
|
+
entries.set(full, { at: now(), value });
|
|
73565
|
+
return value;
|
|
73566
|
+
}
|
|
73567
|
+
function clampedRunner(base, limits, now, token) {
|
|
73568
|
+
return (bin, args, callOptions) => {
|
|
73569
|
+
let timeoutMs = callOptions.timeoutMs;
|
|
73570
|
+
if (limits.deadline !== null) {
|
|
73571
|
+
const remaining = limits.deadline - now();
|
|
73572
|
+
if (remaining <= 0)
|
|
73573
|
+
return {
|
|
73574
|
+
status: null,
|
|
73575
|
+
stdout: "",
|
|
73576
|
+
stderr: "",
|
|
73577
|
+
timedOut: true,
|
|
73578
|
+
missing: false,
|
|
73579
|
+
timeoutMs: 0
|
|
73580
|
+
};
|
|
73581
|
+
timeoutMs = Math.min(timeoutMs, remaining);
|
|
73582
|
+
}
|
|
73583
|
+
const run = base(bin, args, { ...callOptions, timeoutMs, ...token ? { token } : {} });
|
|
73584
|
+
return run.timedOut && run.timeoutMs === undefined ? { ...run, timeoutMs } : run;
|
|
73585
|
+
};
|
|
73586
|
+
}
|
|
73587
|
+
function resolveCredential(workspace, derived, run, scope) {
|
|
73588
|
+
const { kind, apiHost } = derived;
|
|
73589
|
+
const expectedAccount = workspace?.vcs?.account ?? null;
|
|
73590
|
+
const tokenFile = workspace?.vcs?.tokenFile;
|
|
73591
|
+
if (typeof tokenFile === "string" && tokenFile.trim()) {
|
|
73592
|
+
const workspaceHost = workspace?.vcs?.host;
|
|
73593
|
+
const explicit = typeof workspaceHost === "string" && workspaceHost.trim().toLowerCase().replace(/^https?:\/\//u, "").replace(/\/.*$/u, "") === apiHost;
|
|
73594
|
+
if (derived.via === "host_name" && !explicit)
|
|
73595
|
+
return failure3("blocked", `token_host_unverified: push host ${derived.host} only looks like ${kind}; workspace ${workspace?.name ?? "?"} vcs.tokenFile is not sent to it`, `if ${apiHost} is your ${kind} server, set ${kind}.host in ~/.config/workit/vcs.json (or vcs.host for the workspace); otherwise fix the push remote`);
|
|
73596
|
+
let token = "";
|
|
73597
|
+
try {
|
|
73598
|
+
token = fs21.readFileSync(tokenFile.trim(), "utf8").trim();
|
|
73599
|
+
} catch {
|
|
73600
|
+
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile cannot be read`, "fix vcs.tokenFile in ~/.config/workit/workspaces.json");
|
|
73601
|
+
}
|
|
73602
|
+
if (!token)
|
|
73603
|
+
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile is empty`, "fix vcs.tokenFile in ~/.config/workit/workspaces.json");
|
|
73604
|
+
return success2({ token, credential: "workspace_token_file" });
|
|
73605
|
+
}
|
|
73606
|
+
if (!expectedAccount || kind !== "github")
|
|
73607
|
+
return success2({ token: undefined, credential: "cli_login" });
|
|
73608
|
+
return memo4(scope, `token ${apiHost} ${expectedAccount}`, () => {
|
|
73609
|
+
const issued = run("gh", ["auth", "token", "--hostname", apiHost, "--user", expectedAccount], {
|
|
73610
|
+
timeoutMs: FORGE_TIMEOUTS.api
|
|
73611
|
+
});
|
|
73612
|
+
const value = authTokenResult(issued, apiHost, expectedAccount, workspace?.name ?? "?");
|
|
73613
|
+
return { keep: value.ok, value };
|
|
73614
|
+
});
|
|
73615
|
+
}
|
|
73616
|
+
function authTokenResult(issued, apiHost, account, workspace) {
|
|
73617
|
+
if (issued.missing)
|
|
73618
|
+
return failure3("unavailable", "gh is not installed", "install the GitHub CLI (https://cli.github.com) and run: gh auth login");
|
|
73619
|
+
if (issued.timedOut)
|
|
73620
|
+
return failure3("unavailable", `gh auth token ${issued.timeoutMs === 0 ? "not attempted: the time budget ran out" : `timed out after ${issued.timeoutMs ?? FORGE_TIMEOUTS.api} ms`} (looking up the ${account} login on ${apiHost})`, "gh auth status # check gh and the network, then retry");
|
|
73621
|
+
const token = issued.status === 0 ? issued.stdout.trim() : "";
|
|
73622
|
+
if (token)
|
|
73623
|
+
return success2({ token, credential: "gh_account_token" });
|
|
73624
|
+
const stderr = redactText(issued.stderr).trim();
|
|
73625
|
+
const first = stderr.split(/\r?\n/u).find((line) => line.trim()) ?? "";
|
|
73626
|
+
if (issued.status !== 0 && first && !/no oauth token|not logged in|no account/iu.test(stderr))
|
|
73627
|
+
return failure3("unavailable", `gh auth token failed${isNetworkError(stderr) ? " (network)" : ""}: ${first.slice(0, 200)}`, "gh auth status # check gh and the network, then retry");
|
|
73628
|
+
return failure3("blocked", `identity_unavailable: gh has no login for ${account} on ${apiHost} (workspace ${workspace})`, `gh auth login --hostname ${apiHost} # sign in as ${account}; workit passes that account's token per call and never switches the active account`);
|
|
73629
|
+
}
|
|
73494
73630
|
function resolveForge(cwd, options = {}) {
|
|
73495
73631
|
let workspace;
|
|
73496
73632
|
try {
|
|
@@ -73508,48 +73644,16 @@ function resolveForge(cwd, options = {}) {
|
|
|
73508
73644
|
const derived = pushed.forge;
|
|
73509
73645
|
const { kind, apiHost } = derived;
|
|
73510
73646
|
const base = options.runner ?? systemRunner(kind, apiHost, options.env ?? process.env);
|
|
73647
|
+
const scope = memoScope(options.runner, options.env ?? process.env);
|
|
73511
73648
|
const now = options.now ?? Date.now;
|
|
73512
73649
|
const expectedAccount = workspace?.vcs?.account ?? null;
|
|
73513
|
-
|
|
73514
|
-
|
|
73515
|
-
|
|
73516
|
-
|
|
73517
|
-
|
|
73518
|
-
const explicit = typeof workspaceHost === "string" && workspaceHost.trim().toLowerCase().replace(/^https?:\/\//u, "").replace(/\/.*$/u, "") === apiHost;
|
|
73519
|
-
if (derived.via === "host_name" && !explicit)
|
|
73520
|
-
return failure3("blocked", `token_host_unverified: push host ${derived.host} only looks like ${kind}; workspace ${workspace?.name ?? "?"} vcs.tokenFile is not sent to it`, `if ${apiHost} is your ${kind} server, set ${kind}.host in ~/.config/workit/vcs.json (or vcs.host for the workspace); otherwise fix the push remote`);
|
|
73521
|
-
try {
|
|
73522
|
-
token = fs21.readFileSync(tokenFile.trim(), "utf8").trim();
|
|
73523
|
-
} catch {
|
|
73524
|
-
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile cannot be read`, "fix vcs.tokenFile in ~/.config/workit/workspaces.json");
|
|
73525
|
-
}
|
|
73526
|
-
if (!token)
|
|
73527
|
-
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile is empty`, "fix vcs.tokenFile in ~/.config/workit/workspaces.json");
|
|
73528
|
-
credential = "workspace_token_file";
|
|
73529
|
-
} else if (expectedAccount && kind === "github") {
|
|
73530
|
-
const issued = base("gh", ["auth", "token", "--hostname", apiHost, "--user", expectedAccount], {
|
|
73531
|
-
timeoutMs: FORGE_TIMEOUTS.api
|
|
73532
|
-
});
|
|
73533
|
-
if (issued.missing)
|
|
73534
|
-
return failure3("unavailable", "gh is not installed", "install the GitHub CLI (https://cli.github.com) and run: gh auth login");
|
|
73535
|
-
token = issued.status === 0 ? issued.stdout.trim() : "";
|
|
73536
|
-
if (!token)
|
|
73537
|
-
return failure3("blocked", `identity_unavailable: gh has no login for ${expectedAccount} on ${apiHost} (workspace ${workspace?.name ?? "?"})`, `gh auth login --hostname ${apiHost} # sign in as ${expectedAccount}; workit passes that account's token per call and never switches the active account`);
|
|
73538
|
-
credential = "gh_account_token";
|
|
73539
|
-
}
|
|
73540
|
-
const limits = { deadline: null };
|
|
73541
|
-
const runner = (bin, args, callOptions) => {
|
|
73542
|
-
let timeoutMs = callOptions.timeoutMs;
|
|
73543
|
-
if (limits.deadline !== null) {
|
|
73544
|
-
const remaining = limits.deadline - now();
|
|
73545
|
-
if (remaining <= 0)
|
|
73546
|
-
return { status: null, stdout: "", stderr: "", timedOut: true, missing: false };
|
|
73547
|
-
timeoutMs = Math.min(timeoutMs, remaining);
|
|
73548
|
-
}
|
|
73549
|
-
return base(bin, args, { ...callOptions, timeoutMs, ...token ? { token } : {} });
|
|
73550
|
-
};
|
|
73650
|
+
const limits = { deadline: options.deadline ?? null };
|
|
73651
|
+
const credential = resolveCredential(workspace, derived, clampedRunner(base, limits, now), scope);
|
|
73652
|
+
if (!credential.ok)
|
|
73653
|
+
return credential;
|
|
73654
|
+
const runner = clampedRunner(base, limits, now, credential.data.token);
|
|
73551
73655
|
const headRepo = derived.repo;
|
|
73552
|
-
const probe = createForge(derived, headRepo, runner);
|
|
73656
|
+
const probe = memoizedIdentity(createForge(derived, headRepo, runner), scope, credential.data);
|
|
73553
73657
|
const info = probe.repoInfo(headRepo);
|
|
73554
73658
|
if (!info.ok && info.code !== "not_found")
|
|
73555
73659
|
return info;
|
|
@@ -73564,13 +73668,13 @@ function resolveForge(cwd, options = {}) {
|
|
|
73564
73668
|
const baseRepo = upstream && upstream !== headRepo ? upstream : info.ok && info.data.parent ? info.data.parent : headRepo;
|
|
73565
73669
|
const baseRemote = baseRepo === headRepo ? pushed.remote : remotes.find((name) => repoOfRemote(name) === baseRepo) ?? pushed.remote;
|
|
73566
73670
|
return success2({
|
|
73567
|
-
forge: baseRepo === headRepo ? probe : createForge(derived, baseRepo, runner),
|
|
73671
|
+
forge: baseRepo === headRepo ? probe : memoizedIdentity(createForge(derived, baseRepo, runner), scope, credential.data),
|
|
73568
73672
|
remote: pushed.remote,
|
|
73569
73673
|
url: pushed.url,
|
|
73570
73674
|
derived,
|
|
73571
73675
|
workspace: workspace?.name ?? null,
|
|
73572
73676
|
expectedAccount,
|
|
73573
|
-
credential,
|
|
73677
|
+
credential: credential.data.credential,
|
|
73574
73678
|
headRepo,
|
|
73575
73679
|
headProjectId,
|
|
73576
73680
|
fork: baseRepo !== headRepo,
|
|
@@ -73583,14 +73687,74 @@ function checkIdentity(resolved) {
|
|
|
73583
73687
|
const identity = forge.identity(expectedAccount);
|
|
73584
73688
|
if (!identity.ok)
|
|
73585
73689
|
return identity;
|
|
73586
|
-
if (identity.data.matches === false)
|
|
73587
|
-
|
|
73588
|
-
const where = `workspace ${resolved.workspace ?? "?"}`;
|
|
73589
|
-
return failure3("blocked", `identity_mismatch: the ${resolved.credential === "workspace_token_file" ? "vcs.tokenFile token" : `${bin} login`} is ${identity.data.login} but ${where} expects ${expectedAccount}`, resolved.credential === "workspace_token_file" ? `put a token for ${expectedAccount} in the ${where} vcs.tokenFile` : `${bin} auth login --hostname ${forge.apiHost} # sign in as ${expectedAccount}`);
|
|
73590
|
-
}
|
|
73690
|
+
if (identity.data.matches === false)
|
|
73691
|
+
return mismatch(resolved, identity.data.login ?? "?", resolved.workspace);
|
|
73591
73692
|
return identity;
|
|
73592
73693
|
}
|
|
73593
|
-
|
|
73694
|
+
function checkPushIdentity(cwd, options = {}) {
|
|
73695
|
+
let workspace;
|
|
73696
|
+
try {
|
|
73697
|
+
workspace = resolveRuntimeWorkspaceVcs(cwd);
|
|
73698
|
+
} catch (error) {
|
|
73699
|
+
return failure3("blocked", error instanceof Error ? error.message : String(error), "fix ~/.config/workit/workspaces.json (workit init → Workspaces)");
|
|
73700
|
+
}
|
|
73701
|
+
const account = workspace?.vcs?.account ?? null;
|
|
73702
|
+
const skipped = (forge, reason, unblock) => success2({
|
|
73703
|
+
status: "skipped",
|
|
73704
|
+
forge,
|
|
73705
|
+
account,
|
|
73706
|
+
login: null,
|
|
73707
|
+
reason,
|
|
73708
|
+
...unblock ? { unblock } : {}
|
|
73709
|
+
});
|
|
73710
|
+
const pushed = pushForge(cwd, {
|
|
73711
|
+
branch: options.branch,
|
|
73712
|
+
hosts: configuredHosts(),
|
|
73713
|
+
sshConfig: options.sshConfig
|
|
73714
|
+
});
|
|
73715
|
+
if (!pushed.ok) {
|
|
73716
|
+
const host = /^unsupported_forge: .*?"([^"]+)"/u.exec(pushed.error)?.[1];
|
|
73717
|
+
const what = /could not resolve ssh alias/u.test(pushed.error) ? `could not resolve ssh alias ${host} to GitHub or GitLab` : pushed.error.startsWith("unsupported_forge: ssh host") ? `ssh host ${host} is not a GitHub/GitLab host or an alias workit can resolve` : `${host} is not a GitHub or GitLab host workit knows`;
|
|
73718
|
+
return skipped(null, host ? `unsupported_forge: ${what}; account checks skipped, pushed with git only (no PR or CI verbs)` : pushed.error, pushed.unblock);
|
|
73719
|
+
}
|
|
73720
|
+
const derived = pushed.forge;
|
|
73721
|
+
const conflict = forgeConflict(derived, workspace?.vcs?.provider);
|
|
73722
|
+
if (conflict)
|
|
73723
|
+
return skipped(derived.kind, conflict.error, conflict.unblock);
|
|
73724
|
+
if (!account)
|
|
73725
|
+
return success2({ status: "no_account", forge: derived.kind, account, login: null });
|
|
73726
|
+
const base = options.runner ?? systemRunner(derived.kind, derived.apiHost, options.env ?? process.env);
|
|
73727
|
+
const scope = memoScope(options.runner, options.env ?? process.env);
|
|
73728
|
+
const now = options.now ?? Date.now;
|
|
73729
|
+
const limits = { deadline: now() + (options.budgetMs ?? PUSH_IDENTITY_BUDGET_MS) };
|
|
73730
|
+
const credential = resolveCredential(workspace, derived, clampedRunner(base, limits, now), scope);
|
|
73731
|
+
if (!credential.ok)
|
|
73732
|
+
return unreachable(credential) ? skipped(derived.kind, credential.error, credential.unblock) : credential;
|
|
73733
|
+
const forge = memoizedIdentity(createForge(derived, derived.repo, clampedRunner(base, limits, now, credential.data.token)), scope, credential.data);
|
|
73734
|
+
const identity = forge.identity(account);
|
|
73735
|
+
if (!identity.ok)
|
|
73736
|
+
return unreachable(identity) ? skipped(derived.kind, identity.error, identity.unblock) : identity;
|
|
73737
|
+
if (identity.data.matches === false)
|
|
73738
|
+
return mismatch({ forge, credential: credential.data.credential, expectedAccount: account }, identity.data.login ?? "?", workspace?.name ?? null);
|
|
73739
|
+
if (identity.data.matches === null)
|
|
73740
|
+
return skipped(derived.kind, identity.data.note ?? "the credential cannot read /user");
|
|
73741
|
+
return success2({ status: "verified", forge: derived.kind, account, login: identity.data.login });
|
|
73742
|
+
}
|
|
73743
|
+
var MEMO_TTL_MS, SYSTEM_SCOPE, memoScopes, memoScope = (runner, env) => ({
|
|
73744
|
+
owner: runner ?? SYSTEM_SCOPE,
|
|
73745
|
+
key: [env.GH_CONFIG_DIR, env.GLAB_CONFIG_DIR, env.XDG_CONFIG_HOME, env.HOME].map((value) => value ?? "").join("|")
|
|
73746
|
+
}), memoizedIdentity = (forge, scope, credential) => {
|
|
73747
|
+
if (credential.credential === "cli_login")
|
|
73748
|
+
return forge;
|
|
73749
|
+
const identity = (expected) => forge.identity(expected);
|
|
73750
|
+
return {
|
|
73751
|
+
...forge,
|
|
73752
|
+
identity: (expected) => memo4(scope, `identity ${forge.kind} ${forge.apiHost} ${credential.credential} ${credential.token ?? ""} ${expected ?? ""}`, () => {
|
|
73753
|
+
const value = identity(expected);
|
|
73754
|
+
return { keep: value.ok, value };
|
|
73755
|
+
})
|
|
73756
|
+
};
|
|
73757
|
+
}, configuredHosts = () => {
|
|
73594
73758
|
const vcs = readVcsConfig();
|
|
73595
73759
|
if (vcs.status !== "valid")
|
|
73596
73760
|
return {};
|
|
@@ -73599,7 +73763,13 @@ var configuredHosts = () => {
|
|
|
73599
73763
|
return typeof value === "string" && value.trim() ? [value.trim()] : [];
|
|
73600
73764
|
};
|
|
73601
73765
|
return { github: host("github"), gitlab: host("gitlab") };
|
|
73602
|
-
}, createForge = (derived, repo, runner) => derived.kind === "github" ? createGitHubForge({ apiHost: derived.apiHost, repo, runner }) : createGitLabForge({ apiHost: derived.apiHost, repo, runner })
|
|
73766
|
+
}, createForge = (derived, repo, runner) => derived.kind === "github" ? createGitHubForge({ apiHost: derived.apiHost, repo, runner }) : createGitLabForge({ apiHost: derived.apiHost, repo, runner }), mismatch = (resolved, login, workspace) => {
|
|
73767
|
+
const { forge, expectedAccount } = resolved;
|
|
73768
|
+
const bin = forge.kind === "github" ? "gh" : "glab";
|
|
73769
|
+
const where = `workspace ${workspace ?? "?"}`;
|
|
73770
|
+
const fileFix = `put a token for ${expectedAccount} in the ${where} vcs.tokenFile`;
|
|
73771
|
+
return failure3("blocked", `identity_mismatch: the ${resolved.credential === "workspace_token_file" ? "vcs.tokenFile token" : `${bin} login`} is ${login} but ${where} expects ${expectedAccount}`, resolved.credential === "workspace_token_file" ? fileFix : forge.kind === "github" ? `gh auth login --hostname ${forge.apiHost} # sign in as ${expectedAccount}` : `${fileFix} (glab keeps one login per host, so workit never switches it)`);
|
|
73772
|
+
}, unreachable = (result) => result.code === "unavailable" && !/ is not authenticated for /u.test(result.error), PUSH_IDENTITY_BUDGET_MS = 5000;
|
|
73603
73773
|
var init_resolve = __esm(() => {
|
|
73604
73774
|
init_vcs_config();
|
|
73605
73775
|
init_workspaces();
|
|
@@ -73607,6 +73777,10 @@ var init_resolve = __esm(() => {
|
|
|
73607
73777
|
init_exec();
|
|
73608
73778
|
init_github();
|
|
73609
73779
|
init_gitlab();
|
|
73780
|
+
init_redact();
|
|
73781
|
+
MEMO_TTL_MS = 5 * 60000;
|
|
73782
|
+
SYSTEM_SCOPE = {};
|
|
73783
|
+
memoScopes = new WeakMap;
|
|
73610
73784
|
});
|
|
73611
73785
|
|
|
73612
73786
|
// packages/workit-core/src/duration.ts
|
|
@@ -73699,16 +73873,19 @@ function releaseTrunk(io, track, branch) {
|
|
|
73699
73873
|
tracked: Boolean(resolved.releaseTrack)
|
|
73700
73874
|
};
|
|
73701
73875
|
}
|
|
73702
|
-
function connect(io, branch) {
|
|
73876
|
+
function connect(io, branch, options = {}) {
|
|
73877
|
+
const verbDeadline = options.deadline ?? null;
|
|
73703
73878
|
const resolved = resolveForge(io.cwd, {
|
|
73704
73879
|
branch,
|
|
73705
73880
|
env: io.env,
|
|
73706
73881
|
runner: forgeDeps.runner,
|
|
73707
|
-
now: forgeDeps.now
|
|
73882
|
+
now: forgeDeps.now,
|
|
73883
|
+
deadline: verbDeadline ?? forgeDeps.now() + CONNECT_BUDGET_MS
|
|
73708
73884
|
});
|
|
73709
73885
|
if (!resolved.ok)
|
|
73710
73886
|
return resolved;
|
|
73711
73887
|
const identity = checkIdentity(resolved.data);
|
|
73888
|
+
resolved.data.limits.deadline = verbDeadline;
|
|
73712
73889
|
if (!identity.ok)
|
|
73713
73890
|
return identity;
|
|
73714
73891
|
return {
|
|
@@ -73763,7 +73940,12 @@ function renderStatus(doc) {
|
|
|
73763
73940
|
lines.push(`next: ${doc.next}`);
|
|
73764
73941
|
return lines;
|
|
73765
73942
|
}
|
|
73766
|
-
var forgeDeps, MAX_REASON = 500, usage3 = (io, message, line) => emit(io, fail("invalid_input", message, { unblock: line })), forgeFail = (io, result, data) => emit(io, fail(result.code, result.error, { data, unblock: result.unblock })),
|
|
73943
|
+
var forgeDeps, MAX_REASON = 500, usage3 = (io, message, line) => emit(io, fail("invalid_input", message, { unblock: line })), forgeFail = (io, result, data) => emit(io, fail(result.code, result.error, { data, unblock: result.unblock })), CONNECT_BUDGET_MS = 15000, pushIdentity = (io, branch) => checkPushIdentity(io.cwd, {
|
|
73944
|
+
branch,
|
|
73945
|
+
env: io.env,
|
|
73946
|
+
runner: forgeDeps.runner,
|
|
73947
|
+
now: forgeDeps.now
|
|
73948
|
+
}), short = (sha) => sha ? sha.slice(0, 7) : "?";
|
|
73767
73949
|
var init_forge_common = __esm(() => {
|
|
73768
73950
|
init_resolve();
|
|
73769
73951
|
init_vcs_config();
|
|
@@ -74013,16 +74195,17 @@ async function wait(argv, io) {
|
|
|
74013
74195
|
const head = flags.values.head ?? null;
|
|
74014
74196
|
if (head !== null && !/^[0-9a-f]{7,64}$/u.test(head))
|
|
74015
74197
|
return usage3(io, "--head must be a commit sha (7-64 hex chars)", WAIT_USAGE);
|
|
74016
|
-
const
|
|
74198
|
+
const started = forgeDeps.now();
|
|
74199
|
+
const deadline = started + timeoutMs;
|
|
74200
|
+
const connected = connect(io, flags.values.branch, {
|
|
74201
|
+
deadline: started + Math.max(timeoutMs, ONE_POLL_MS)
|
|
74202
|
+
});
|
|
74017
74203
|
if (!connected.ok)
|
|
74018
74204
|
return forgeFail(io, connected);
|
|
74019
74205
|
const resolved = connected.data;
|
|
74020
74206
|
const number = selectPr(io.cwd, resolved, { pr, branch: flags.values.branch ?? null });
|
|
74021
74207
|
if (!number.ok)
|
|
74022
74208
|
return forgeFail(io, number);
|
|
74023
|
-
const started = forgeDeps.now();
|
|
74024
|
-
const deadline = started + timeoutMs;
|
|
74025
|
-
resolved.limits.deadline = started + Math.max(timeoutMs, ONE_POLL_MS);
|
|
74026
74209
|
let polls = 0;
|
|
74027
74210
|
let errors = 0;
|
|
74028
74211
|
let status = null;
|
|
@@ -74359,12 +74542,11 @@ async function push(argv, io) {
|
|
|
74359
74542
|
const plan = pushPreflight(io.cwd);
|
|
74360
74543
|
if (!plan.ok)
|
|
74361
74544
|
return forgeFail(io, plan);
|
|
74362
|
-
|
|
74363
|
-
|
|
74364
|
-
|
|
74365
|
-
|
|
74366
|
-
}
|
|
74367
|
-
const grant = requireGrant(io.cwd, "push", { forge: !plan.data.local });
|
|
74545
|
+
const identity = plan.data.local ? null : pushIdentity(io, plan.data.branch);
|
|
74546
|
+
if (identity && !identity.ok)
|
|
74547
|
+
return forgeFail(io, identity);
|
|
74548
|
+
const checked = identity?.data ?? null;
|
|
74549
|
+
const grant = requireGrant(io.cwd, "push", { forge: checked?.forge != null });
|
|
74368
74550
|
if (!grant.allowed)
|
|
74369
74551
|
return emit(io, fail("blocked", grant.error, {
|
|
74370
74552
|
unblock: grant.unblock,
|
|
@@ -74375,14 +74557,22 @@ async function push(argv, io) {
|
|
|
74375
74557
|
overwriteUnintegrated: flags.booleans.has("overwrite-unintegrated"),
|
|
74376
74558
|
expect,
|
|
74377
74559
|
setUpstream: flags.booleans.has("set-upstream"),
|
|
74378
|
-
actor: actorFromEnv(io.env)
|
|
74560
|
+
actor: actorFromEnv(io.env),
|
|
74561
|
+
...checked ? { identity: { ...checked } } : {}
|
|
74379
74562
|
});
|
|
74380
74563
|
if (!result.ok)
|
|
74381
74564
|
return forgeFail(io, result, {
|
|
74382
74565
|
branch: plan.data.branch,
|
|
74383
74566
|
sha: plan.data.sha
|
|
74384
74567
|
});
|
|
74385
|
-
|
|
74568
|
+
const warnings = checked?.status === "skipped" ? [
|
|
74569
|
+
`identity check skipped: ${checked.reason}${checked.unblock ? ` (to restore it: ${checked.unblock})` : ""}`
|
|
74570
|
+
] : [];
|
|
74571
|
+
for (const warning of warnings)
|
|
74572
|
+
io.stderr(`warning: ${warning}
|
|
74573
|
+
`);
|
|
74574
|
+
const envelope = ok({ ...result.data, identity: checked });
|
|
74575
|
+
return emit(io, warnings.length ? { ...envelope, warnings } : envelope, (data) => [
|
|
74386
74576
|
data.pushed ? `pushed ${data.branch} ${short2(data.previous)} -> ${short2(data.sha)} to ${data.remote}${data.forced ? " (force-with-lease)" : ""}; remote tip verified` : `${data.remote}/${data.branch} is already at ${short2(data.sha)}; remote tip verified`,
|
|
74387
74577
|
...data.upstream ? [`upstream: ${data.remote}/${data.branch}`] : []
|
|
74388
74578
|
]);
|
|
@@ -74415,7 +74605,7 @@ var init_git2 = __esm(() => {
|
|
|
74415
74605
|
});
|
|
74416
74606
|
|
|
74417
74607
|
// packages/workit-core/src/forge/verify.ts
|
|
74418
|
-
import { spawnSync as
|
|
74608
|
+
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
74419
74609
|
function finish(cwd, report, actor) {
|
|
74420
74610
|
const delivered = report.observations.length > 0 && report.observations.every((entry) => entry.ok);
|
|
74421
74611
|
const out = { ...report, delivered };
|
|
@@ -74628,7 +74818,7 @@ var NPM_NAME, SEMVER, SAFE_ARG, systemNpm = (args) => {
|
|
|
74628
74818
|
};
|
|
74629
74819
|
const found = process.platform === "win32" ? findExecutable("npm.cmd", process.env) : null;
|
|
74630
74820
|
const npmCmd = found && !/["%!^]/u.test(found) ? `"${found}"` : "npm.cmd";
|
|
74631
|
-
const result = process.platform === "win32" ?
|
|
74821
|
+
const result = process.platform === "win32" ? spawnSync20(`${npmCmd} ${args.join(" ")}`, { ...options, shell: true }) : spawnSync20("npm", [...args], options);
|
|
74632
74822
|
return { status: result.status, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
|
|
74633
74823
|
}, short3 = (sha) => sha ? sha.slice(0, 12) : "(absent)", npmView = (stdout) => {
|
|
74634
74824
|
try {
|
|
@@ -74735,7 +74925,7 @@ var init_verify_delivery = __esm(() => {
|
|
|
74735
74925
|
});
|
|
74736
74926
|
|
|
74737
74927
|
// packages/workit-core/src/stack.ts
|
|
74738
|
-
import { spawnSync as
|
|
74928
|
+
import { spawnSync as spawnSync21 } from "node:child_process";
|
|
74739
74929
|
import { createHash as createHash15, randomBytes as randomBytes3 } from "node:crypto";
|
|
74740
74930
|
import fs22 from "node:fs";
|
|
74741
74931
|
import path44 from "node:path";
|
|
@@ -75248,7 +75438,7 @@ function commitKeys(cwd, range) {
|
|
|
75248
75438
|
const patches = new Map;
|
|
75249
75439
|
const diff = gitRun3(cwd, ["log", "--no-merges", "-p", "--format=commit %H", range]);
|
|
75250
75440
|
if (diff.ok && diff.stdout.trim()) {
|
|
75251
|
-
const ids =
|
|
75441
|
+
const ids = spawnSync21("git", ["patch-id", "--stable"], {
|
|
75252
75442
|
cwd,
|
|
75253
75443
|
input: diff.stdout,
|
|
75254
75444
|
encoding: "utf8",
|
|
@@ -75872,7 +76062,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
75872
76062
|
...unblock ? { unblock } : {},
|
|
75873
76063
|
...data ? { data } : {}
|
|
75874
76064
|
}), fromForge = (result) => stackFail(result.code, result.error, result.unblock), stackDeps, gitRun3 = (cwd, args, timeoutMs = GIT_TIMEOUTS.local) => {
|
|
75875
|
-
const run =
|
|
76065
|
+
const run = spawnSync21("git", args, {
|
|
75876
76066
|
cwd,
|
|
75877
76067
|
encoding: "utf8",
|
|
75878
76068
|
timeout: timeoutMs,
|
|
@@ -76167,7 +76357,7 @@ var init_stack2 = __esm(() => {
|
|
|
76167
76357
|
});
|
|
76168
76358
|
|
|
76169
76359
|
// packages/workit-core/src/fanout.ts
|
|
76170
|
-
import { spawnSync as
|
|
76360
|
+
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
76171
76361
|
import { createHash as createHash16 } from "node:crypto";
|
|
76172
76362
|
import fs23 from "node:fs";
|
|
76173
76363
|
import path45 from "node:path";
|
|
@@ -76940,7 +77130,7 @@ var FANOUT_VERSION = 1, TIERS, FAN_IN_MODES, fanoutFail = (code, error, unblock,
|
|
|
76940
77130
|
text: edges.map((edge) => `add "${edge.dependsOn}" to "dependsOn" of slice ${edge.slice}`).join("; ")
|
|
76941
77131
|
};
|
|
76942
77132
|
}, gitRun4 = (cwd, args, timeoutMs = GIT_TIMEOUTS.local) => {
|
|
76943
|
-
const run =
|
|
77133
|
+
const run = spawnSync22("git", args, {
|
|
76944
77134
|
cwd,
|
|
76945
77135
|
encoding: "utf8",
|
|
76946
77136
|
timeout: timeoutMs,
|
|
@@ -77460,7 +77650,7 @@ var init_fanout_brief = __esm(() => {
|
|
|
77460
77650
|
});
|
|
77461
77651
|
|
|
77462
77652
|
// packages/workit-core/src/fanout-landed.ts
|
|
77463
|
-
import { spawnSync as
|
|
77653
|
+
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
77464
77654
|
function forgeBreaker(resolved) {
|
|
77465
77655
|
if (!resolved)
|
|
77466
77656
|
return { forge: null, down: () => null };
|
|
@@ -77551,7 +77741,7 @@ function trunkPatchIds(ctx, fork) {
|
|
|
77551
77741
|
"--"
|
|
77552
77742
|
]);
|
|
77553
77743
|
if (log.ok && log.stdout.trim()) {
|
|
77554
|
-
const run =
|
|
77744
|
+
const run = spawnSync23("git", ["patch-id", "--stable"], {
|
|
77555
77745
|
cwd: ctx.cwd,
|
|
77556
77746
|
input: log.stdout,
|
|
77557
77747
|
encoding: "utf8",
|
|
@@ -94494,11 +94684,11 @@ var init_rules = __esm(() => {
|
|
|
94494
94684
|
});
|
|
94495
94685
|
|
|
94496
94686
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
94497
|
-
import { spawnSync as
|
|
94687
|
+
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
94498
94688
|
import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync21, statSync as statSync7 } from "node:fs";
|
|
94499
94689
|
import path49 from "node:path";
|
|
94500
94690
|
function git6(cwd, args) {
|
|
94501
|
-
const run =
|
|
94691
|
+
const run = spawnSync24("git", ["-c", "core.quotepath=off", ...args], {
|
|
94502
94692
|
cwd,
|
|
94503
94693
|
encoding: "utf8",
|
|
94504
94694
|
maxBuffer: 64 * 1024 * 1024
|
|
@@ -96391,9 +96581,21 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
96391
96581
|
globalThis[Symbol.for("workit.migrationReporter")] = (report) => io.stderr(`workit: migrated ${report.tasks} task${report.tasks === 1 ? "" : "s"} from ${report.from} to ${report.to} (backup: ${report.backup})
|
|
96392
96582
|
`);
|
|
96393
96583
|
const verb = await entry.load();
|
|
96584
|
+
const runVerb = (target) => guarded(target, () => verb.run(ended, target));
|
|
96394
96585
|
if (!io.json)
|
|
96395
|
-
return
|
|
96396
|
-
return runJsonPure(io, command,
|
|
96586
|
+
return runVerb(io);
|
|
96587
|
+
return runJsonPure(io, command, runVerb);
|
|
96588
|
+
}
|
|
96589
|
+
async function guarded(io, run) {
|
|
96590
|
+
try {
|
|
96591
|
+
return await run();
|
|
96592
|
+
} catch (error) {
|
|
96593
|
+
if (!(error instanceof Error) || error.name !== "WorkspaceConfigError")
|
|
96594
|
+
throw error;
|
|
96595
|
+
return emit(io, fail("blocked", error.message, {
|
|
96596
|
+
unblock: "fix ~/.config/workit/workspaces.json (workit init → Workspaces)"
|
|
96597
|
+
}));
|
|
96598
|
+
}
|
|
96397
96599
|
}
|
|
96398
96600
|
var CODE_FOR_EXIT = {
|
|
96399
96601
|
1: "failed",
|