@brainervirus/workit-cli 8.29.1 → 8.30.0
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/dist/index.js +864 -345
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -6428,11 +6428,12 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6428
6428
|
};
|
|
6429
6429
|
}
|
|
6430
6430
|
}
|
|
6431
|
+
const document2 = parsed;
|
|
6431
6432
|
return {
|
|
6432
6433
|
status: "valid",
|
|
6433
6434
|
path: file,
|
|
6434
|
-
entries:
|
|
6435
|
-
document:
|
|
6435
|
+
entries: document2.workspaces ?? [],
|
|
6436
|
+
document: document2
|
|
6436
6437
|
};
|
|
6437
6438
|
}, readWorkspacesResult = (dir = configDir()) => {
|
|
6438
6439
|
const file = path2.join(dir, "workspaces.json");
|
|
@@ -6570,7 +6571,40 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6570
6571
|
return glob;
|
|
6571
6572
|
const real = realpathOf(prefix.replace(/\/+$/, "") || "/");
|
|
6572
6573
|
return real + (prefix.endsWith("/") ? "/" : "") + rest;
|
|
6573
|
-
}, globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length,
|
|
6574
|
+
}, globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length, globRoot = (glob) => {
|
|
6575
|
+
const normalized = glob.replaceAll("\\", "/");
|
|
6576
|
+
const wild = /[*?[\]{]/.exec(normalized);
|
|
6577
|
+
const prefix = wild ? normalized.slice(0, wild.index) : normalized;
|
|
6578
|
+
return prefix.replace(/\/+$/u, "") || "/";
|
|
6579
|
+
}, literalPrefixes = (glob) => {
|
|
6580
|
+
const normalized = glob.replaceAll("\\", "/");
|
|
6581
|
+
const prefixOf = (value) => {
|
|
6582
|
+
const wild = /[*?[\]{]/.exec(value);
|
|
6583
|
+
return wild ? value.slice(0, wild.index) : value;
|
|
6584
|
+
};
|
|
6585
|
+
return [
|
|
6586
|
+
...new Set([prefixOf(normalized), prefixOf(canonicalGlob(normalized).replaceAll("\\", "/"))])
|
|
6587
|
+
];
|
|
6588
|
+
}, globsMayOverlap = (a, b) => literalPrefixes(a).some((pa) => literalPrefixes(b).some((pb) => pa.startsWith(pb) || pb.startsWith(pa))), overlappingEntries = (glob, entries) => entries.filter((entry) => globsMayOverlap(entry.glob, glob)), workspaceOverlaps = (entries) => {
|
|
6589
|
+
const out = [];
|
|
6590
|
+
for (const [i, a] of entries.entries())
|
|
6591
|
+
for (const b of entries.slice(i + 1)) {
|
|
6592
|
+
const aInB = matchWorkspace(b.glob, globRoot(a.glob));
|
|
6593
|
+
const bInA = matchWorkspace(a.glob, globRoot(b.glob));
|
|
6594
|
+
if (!aInB && !bInA)
|
|
6595
|
+
continue;
|
|
6596
|
+
const [inner, outer] = aInB && !bInA ? [a, b] : bInA && !aInB ? [b, a] : globSpecificity(a.glob) >= globSpecificity(b.glob) ? [a, b] : [b, a];
|
|
6597
|
+
const si = globSpecificity(inner.glob);
|
|
6598
|
+
const so = globSpecificity(outer.glob);
|
|
6599
|
+
out.push({
|
|
6600
|
+
inner: inner.name,
|
|
6601
|
+
outer: outer.name,
|
|
6602
|
+
at: globRoot(inner.glob),
|
|
6603
|
+
winner: si === so ? null : si > so ? inner.name : outer.name
|
|
6604
|
+
});
|
|
6605
|
+
}
|
|
6606
|
+
return out;
|
|
6607
|
+
}, workspaceMatches = (cwd, entries) => matchingEntries(cwd, entries), selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
6574
6608
|
if (workspaceName !== undefined) {
|
|
6575
6609
|
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
6576
6610
|
if (named.length === 1)
|
|
@@ -9251,7 +9285,7 @@ var package_default;
|
|
|
9251
9285
|
var init_package = __esm(() => {
|
|
9252
9286
|
package_default = {
|
|
9253
9287
|
name: "@brainervirus/workit-cli",
|
|
9254
|
-
version: "8.
|
|
9288
|
+
version: "8.30.0",
|
|
9255
9289
|
private: false,
|
|
9256
9290
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9257
9291
|
keywords: [
|
|
@@ -9289,13 +9323,13 @@ var init_package = __esm(() => {
|
|
|
9289
9323
|
},
|
|
9290
9324
|
dependencies: {
|
|
9291
9325
|
"@babel/parser": "7.29.9",
|
|
9292
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9326
|
+
"@brainervirus/workit-cursor": "^8.30.0",
|
|
9293
9327
|
"@inkjs/ui": "2.0.0",
|
|
9294
9328
|
ink: "7.1.1",
|
|
9295
9329
|
react: "19.2.8"
|
|
9296
9330
|
},
|
|
9297
9331
|
devDependencies: {
|
|
9298
|
-
"@brainervirus/workit-core": "^8.
|
|
9332
|
+
"@brainervirus/workit-core": "^8.30.0"
|
|
9299
9333
|
},
|
|
9300
9334
|
engines: {
|
|
9301
9335
|
node: ">=24"
|
|
@@ -9660,6 +9694,27 @@ function effectiveEndpoint(endpoint, context) {
|
|
|
9660
9694
|
return { endpoint: "green", reason: missing("merge") };
|
|
9661
9695
|
return { endpoint };
|
|
9662
9696
|
}
|
|
9697
|
+
function endpointMismatch(view) {
|
|
9698
|
+
const { defaultEndpoint: endpoint } = view;
|
|
9699
|
+
const ws = view.workspace ?? "<workspace>";
|
|
9700
|
+
const explicit = (kind) => view.configured.includes(kind) && view.grants[kind] !== false;
|
|
9701
|
+
if (explicit("merge") && endpoint !== "merged")
|
|
9702
|
+
return `merge granted, but endpoint ${endpoint} stops at ${STOPS[endpoint]}; to land on green: workit grant set ${ws} defaultEndpoint=merged (your terminal)`;
|
|
9703
|
+
if (explicit("pr") && endpoint === "commit")
|
|
9704
|
+
return `pr granted, but endpoint commit stops at the local commit; to open PRs: workit grant set ${ws} defaultEndpoint=pr (your terminal)`;
|
|
9705
|
+
return null;
|
|
9706
|
+
}
|
|
9707
|
+
function entryMismatch(entry) {
|
|
9708
|
+
if (!entry)
|
|
9709
|
+
return null;
|
|
9710
|
+
const { grants } = configuredGrants(entry);
|
|
9711
|
+
return endpointMismatch({
|
|
9712
|
+
workspace: entry.name ?? null,
|
|
9713
|
+
grants: { ...DEFAULT_GRANTS, ...grants },
|
|
9714
|
+
configured: GRANT_KINDS.filter((kind) => grants[kind] !== undefined),
|
|
9715
|
+
defaultEndpoint: endpointOf(entry).endpoint
|
|
9716
|
+
});
|
|
9717
|
+
}
|
|
9663
9718
|
function endpointView(entry, context) {
|
|
9664
9719
|
const { raw, endpoint, issue } = endpointOf(entry);
|
|
9665
9720
|
const effective = effectiveEndpoint(endpoint, context);
|
|
@@ -9876,7 +9931,7 @@ var accountHome = () => {
|
|
|
9876
9931
|
}, grantsHome, grantsDir = () => path11.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
|
|
9877
9932
|
const configured = path11.resolve(resolveConfigDir());
|
|
9878
9933
|
return configured === path11.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path11.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
9879
|
-
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), raisesEndpoint = (current, next) => DEFAULT_ENDPOINTS.indexOf(next) > DEFAULT_ENDPOINTS.indexOf(current), VERIFICATION_MODES, DEFAULT_VERIFICATION = "proportional", verificationOf = (entry) => {
|
|
9934
|
+
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), raisesEndpoint = (current, next) => DEFAULT_ENDPOINTS.indexOf(next) > DEFAULT_ENDPOINTS.indexOf(current), STOPS, VERIFICATION_MODES, DEFAULT_VERIFICATION = "proportional", verificationOf = (entry) => {
|
|
9880
9935
|
const value = entry?.verification;
|
|
9881
9936
|
return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
|
|
9882
9937
|
}, isGrantKind = (value) => typeof value === "string" && GRANT_KINDS.includes(value), isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
|
|
@@ -9909,6 +9964,12 @@ var init_autonomy = __esm(() => {
|
|
|
9909
9964
|
rerun: true
|
|
9910
9965
|
});
|
|
9911
9966
|
DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
|
|
9967
|
+
STOPS = {
|
|
9968
|
+
commit: "the local commit",
|
|
9969
|
+
pr: "the PR",
|
|
9970
|
+
green: "a green PR",
|
|
9971
|
+
merged: "the merge"
|
|
9972
|
+
};
|
|
9912
9973
|
VERIFICATION_MODES = [
|
|
9913
9974
|
"proportional",
|
|
9914
9975
|
"self",
|
|
@@ -15376,9 +15437,18 @@ function liftStop(context, input) {
|
|
|
15376
15437
|
}
|
|
15377
15438
|
return { ok: true, value: cleared };
|
|
15378
15439
|
}
|
|
15440
|
+
function trackedDirty(cwd) {
|
|
15441
|
+
const status = gitRun2(cwd, ["status", "--porcelain", "--untracked-files=no"]);
|
|
15442
|
+
return status.ok ? status.stdout.trim().length > 0 : null;
|
|
15443
|
+
}
|
|
15444
|
+
function untrackedFiles2(cwd) {
|
|
15445
|
+
const listed = gitRun2(cwd, ["ls-files", "--others", "--exclude-standard"]);
|
|
15446
|
+
return listed.ok ? listed.stdout.split(`
|
|
15447
|
+
`).filter(Boolean) : [];
|
|
15448
|
+
}
|
|
15379
15449
|
function dirtyElsewhere(cwd, branch, head) {
|
|
15380
15450
|
if (headSha(cwd) === head)
|
|
15381
|
-
return
|
|
15451
|
+
return trackedDirty(cwd) !== false;
|
|
15382
15452
|
const list = git4(cwd, ["worktree", "list", "--porcelain"]);
|
|
15383
15453
|
let worktree = null;
|
|
15384
15454
|
for (const line of (list ?? "").split(`
|
|
@@ -15386,7 +15456,7 @@ function dirtyElsewhere(cwd, branch, head) {
|
|
|
15386
15456
|
if (line.startsWith("worktree "))
|
|
15387
15457
|
worktree = line.slice("worktree ".length);
|
|
15388
15458
|
else if (line === `branch refs/heads/${branch}` && worktree) {
|
|
15389
|
-
const status = gitRun2(worktree, ["status", "--porcelain", "--untracked-files=
|
|
15459
|
+
const status = gitRun2(worktree, ["status", "--porcelain", "--untracked-files=no"]);
|
|
15390
15460
|
return status.ok && status.stdout.trim().length > 0;
|
|
15391
15461
|
}
|
|
15392
15462
|
}
|
|
@@ -15413,8 +15483,9 @@ function recordVerdict(context, input) {
|
|
|
15413
15483
|
const key = codeKey(context.cwd, { branch, base: context.base });
|
|
15414
15484
|
if (!key.head)
|
|
15415
15485
|
return err("not_found", `branch "${branch}" has no commit to judge`);
|
|
15416
|
-
|
|
15417
|
-
|
|
15486
|
+
const dirty = key.dirty === null ? dirtyElsewhere(context.cwd, branch, key.head) : trackedDirty(context.cwd) !== false;
|
|
15487
|
+
if (dirty)
|
|
15488
|
+
return err("blocked", `dirty_worktree: ${branch} has uncommitted changes to tracked files, so its head is not what was judged`, "commit or stash the changes, re-check, then record the verdict");
|
|
15418
15489
|
const session = context.actor.session;
|
|
15419
15490
|
const selfReason = input.self === true ? "flag" : session && input.derivedFrom !== null ? null : "no_session";
|
|
15420
15491
|
const self2 = selfReason !== null;
|
|
@@ -15440,9 +15511,14 @@ function recordVerdict(context, input) {
|
|
|
15440
15511
|
selfReason,
|
|
15441
15512
|
sessionSource: context.sessionSource ?? "env",
|
|
15442
15513
|
...context.sessionBound === true ? { sessionBound: true } : {},
|
|
15443
|
-
evidenceRefs: input.evidenceRefs ?? []
|
|
15514
|
+
evidenceRefs: input.evidenceRefs ?? [],
|
|
15515
|
+
...untrackedField(context.cwd)
|
|
15444
15516
|
}, { now: context.now });
|
|
15445
15517
|
}
|
|
15518
|
+
function untrackedField(cwd) {
|
|
15519
|
+
const files = untrackedFiles2(cwd);
|
|
15520
|
+
return files.length ? { untracked: files.slice(0, MAX_UNTRACKED_LISTED), untrackedCount: files.length } : {};
|
|
15521
|
+
}
|
|
15446
15522
|
function recordHandoff(context, input) {
|
|
15447
15523
|
return appendRow(context.cwd, { ...common(context, noteKey(context)), type: "handoff", note: input.note, next: input.next }, { now: context.now });
|
|
15448
15524
|
}
|
|
@@ -15783,7 +15859,7 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
15783
15859
|
}, required2 = (value, flag) => {
|
|
15784
15860
|
const text = value?.trim();
|
|
15785
15861
|
return text ? { ok: true, value: text } : err("invalid_input", `${flag} is required`);
|
|
15786
|
-
}, fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session), isDelegateSession = (session) => session !== null && (/-w-[a-z0-9._-]+(?:\+try\d)?$/u.test(session) || /-v\d+$/u.test(session) || session.includes(":")), stopOrderText = (note) => `STOP: start nothing new, stop every process you started (dev servers, browsers, watchers), commit only finished work, and report to the lead now${note ? ` (${note})` : ""}`, OBSERVED_ONLY, MAX_DIRTY_PATHS = 10, dirtyState = (cwd) => {
|
|
15862
|
+
}, fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session), isDelegateSession = (session) => session !== null && (/-w-[a-z0-9._-]+(?:\+try\d)?$/u.test(session) || /-v\d+$/u.test(session) || session.includes(":")), stopOrderText = (note) => `STOP: start nothing new, stop every process you started (dev servers, browsers, watchers), commit only finished work, and report to the lead now${note ? ` (${note})` : ""}`, MAX_UNTRACKED_LISTED = 20, OBSERVED_ONLY, MAX_DIRTY_PATHS = 10, dirtyState = (cwd) => {
|
|
15787
15863
|
const run = gitRun2(cwd, ["status", "--porcelain=v1", "-z", "--untracked-files=normal"], GIT_TIMEOUTS.worktree);
|
|
15788
15864
|
if (!run.ok)
|
|
15789
15865
|
return { dirty: false, files: 0, paths: [] };
|
|
@@ -68429,6 +68505,24 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68429
68505
|
return [];
|
|
68430
68506
|
}
|
|
68431
68507
|
}, checkWorkspaceMismatch = (res) => {
|
|
68508
|
+
const check = checkWorkspaceMatch(res);
|
|
68509
|
+
const result = readWorkspacesResult(res.configDir);
|
|
68510
|
+
if (result.status !== "valid")
|
|
68511
|
+
return check;
|
|
68512
|
+
const overlaps = workspaceOverlaps(result.entries);
|
|
68513
|
+
if (overlaps.length === 0)
|
|
68514
|
+
return check;
|
|
68515
|
+
const lines = overlaps.map((overlap) => overlap.winner ? `overlap: ${overlap.inner} inside ${overlap.outer}, ${overlap.winner} wins at ${overlap.at}` : `overlap: ${overlap.inner} and ${overlap.outer} tie at ${overlap.at} (ambiguous)`);
|
|
68516
|
+
const ties = overlaps.filter((overlap) => !overlap.winner);
|
|
68517
|
+
return {
|
|
68518
|
+
...check,
|
|
68519
|
+
detail: [check.detail, ...lines].join("; "),
|
|
68520
|
+
...ties.length && check.status === "pass" ? {
|
|
68521
|
+
status: "warn",
|
|
68522
|
+
fix: `Make one glob more specific than the other in ${result.path} (workit workspace list shows the effective entry)`
|
|
68523
|
+
} : {}
|
|
68524
|
+
};
|
|
68525
|
+
}, checkWorkspaceMatch = (res) => {
|
|
68432
68526
|
const result = readWorkspacesResult(res.configDir);
|
|
68433
68527
|
const file = result.path;
|
|
68434
68528
|
if (result.status === "missing" || result.status === "valid" && result.entries.length === 0)
|
|
@@ -68902,6 +68996,17 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68902
68996
|
status: "pass",
|
|
68903
68997
|
detail: "no hook passed its deadline in the last day"
|
|
68904
68998
|
};
|
|
68999
|
+
}, checkGrantEndpoint = (res) => {
|
|
69000
|
+
let line = null;
|
|
69001
|
+
try {
|
|
69002
|
+
line = entryMismatch(resolveWorkspaceFrom(res.cwd, res.configDir));
|
|
69003
|
+
} catch {}
|
|
69004
|
+
return line ? {
|
|
69005
|
+
id: "grant_endpoint",
|
|
69006
|
+
status: "warn",
|
|
69007
|
+
detail: line.split("; ")[0],
|
|
69008
|
+
fix: line.split("; ")[1]
|
|
69009
|
+
} : { id: "grant_endpoint", status: "pass", detail: "grants and default endpoint agree" };
|
|
68905
69010
|
}, checkChecksConfig = (res) => {
|
|
68906
69011
|
const root = checkRoot(res.cwd);
|
|
68907
69012
|
const current = existsSync16(path38.join(root, CHECKS_FILE));
|
|
@@ -69195,6 +69300,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
69195
69300
|
return report;
|
|
69196
69301
|
};
|
|
69197
69302
|
var init_doctor = __esm(() => {
|
|
69303
|
+
init_autonomy();
|
|
69198
69304
|
init_support_matrix();
|
|
69199
69305
|
init_store_lock();
|
|
69200
69306
|
init_runtime_identity();
|
|
@@ -69250,6 +69356,7 @@ var init_doctor = __esm(() => {
|
|
|
69250
69356
|
checkLogWritable,
|
|
69251
69357
|
checkHeavyScope,
|
|
69252
69358
|
checkHookDeadline,
|
|
69359
|
+
checkGrantEndpoint,
|
|
69253
69360
|
checkChecksConfig,
|
|
69254
69361
|
checkHostPermissions("claude-code", "claude_permissions"),
|
|
69255
69362
|
checkHostPermissions("codex", "codex_permissions"),
|
|
@@ -75853,7 +75960,8 @@ function show(argv, io) {
|
|
|
75853
75960
|
return emit(io, fail2("not_found", `no workspace named "${named[0]}" in ${listed.path}`));
|
|
75854
75961
|
return emit(io, ok2({ path: listed.path, defaults: DEFAULT_GRANTS, workspaces: rows }), () => rows.flatMap((entry) => [
|
|
75855
75962
|
`${entry.name} (${entry.glob})`,
|
|
75856
|
-
...describe2(entry.grants, entry.configured, entry, entry.verification)
|
|
75963
|
+
...describe2(entry.grants, entry.configured, entry, entry.verification),
|
|
75964
|
+
...endpointMismatch({ ...entry, workspace: entry.name }) ? [`note: ${endpointMismatch({ ...entry, workspace: entry.name })}`] : []
|
|
75857
75965
|
]));
|
|
75858
75966
|
}
|
|
75859
75967
|
let autonomy;
|
|
@@ -75874,6 +75982,7 @@ function show(argv, io) {
|
|
|
75874
75982
|
...tierModelIssues.map((issue) => `note: ${issue}`),
|
|
75875
75983
|
data.workspace ? `workspace ${data.workspace} (${data.source === "default" ? "D4 defaults" : `from ${data.source}`})` : "no workspace matches this checkout: D4 defaults apply",
|
|
75876
75984
|
...describe2(data.grants, data.configured, data, data.verification),
|
|
75985
|
+
...endpointMismatch(data) ? [`note: ${endpointMismatch(data)}`] : [],
|
|
75877
75986
|
...describeReleaseTracks(tracks).map((line) => ` ${line}`),
|
|
75878
75987
|
"raising a grant needs the user: workit grant set <workspace> <kind>=<value>"
|
|
75879
75988
|
]);
|
|
@@ -75933,7 +76042,9 @@ async function change(verb, argv, io, deps) {
|
|
|
75933
76042
|
const command = `workit grant ${verb} ${workspace} ${specs.join(" ")}`;
|
|
75934
76043
|
const agent = agentMarker(io.env);
|
|
75935
76044
|
if (!deps.interactive() || agent)
|
|
75936
|
-
return emit(io, fail2("blocked", `grant_raise_refused: raising ${raised.map(({ kind }) => kind).join(", ")} needs the user at an interactive terminal${agent ? ` (this shell belongs to an agent: ${agent} is set)` : ""}; grants are never raised headless`, {
|
|
76045
|
+
return emit(io, fail2("blocked", `grant_raise_refused: raising ${raised.map(({ kind }) => kind).join(", ")} needs the user at an interactive terminal${agent ? ` (this shell belongs to an agent: ${agent} is set)` : ""}; grants are never raised headless`, {
|
|
76046
|
+
unblock: `ask the user to run, in a terminal outside the agent host (not Claude Code's \`!\` prefix or an agent shell): ${command}`
|
|
76047
|
+
}));
|
|
75937
76048
|
const answer = await askOrCancel(io, () => deps.ask(`Raise ${raised.map(({ kind, value }) => `${kind}=${value}`).join(", ")} for workspace "${workspace}"? An agent there may then do this without asking. Type the workspace name to confirm: `));
|
|
75938
76049
|
if (answer === null)
|
|
75939
76050
|
return cancelled(io);
|
|
@@ -76003,6 +76114,288 @@ var init_grant = __esm(() => {
|
|
|
76003
76114
|
};
|
|
76004
76115
|
});
|
|
76005
76116
|
|
|
76117
|
+
// packages/workit-cli/src/verbs/workspace.ts
|
|
76118
|
+
var exports_workspace = {};
|
|
76119
|
+
__export(exports_workspace, {
|
|
76120
|
+
INHERITED_KEYS: () => INHERITED_KEYS,
|
|
76121
|
+
run: () => run11,
|
|
76122
|
+
runWorkspace: () => runWorkspace
|
|
76123
|
+
});
|
|
76124
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync21 } from "node:fs";
|
|
76125
|
+
function list2(argv, io) {
|
|
76126
|
+
if (argv.length)
|
|
76127
|
+
return usage3(io, `unexpected argument ${argv[0]}`);
|
|
76128
|
+
const current = load(io);
|
|
76129
|
+
if (typeof current === "number")
|
|
76130
|
+
return current;
|
|
76131
|
+
const entries = entriesOf(current);
|
|
76132
|
+
const matches = workspaceMatches(io.cwd, entries);
|
|
76133
|
+
let effective = null;
|
|
76134
|
+
let reason;
|
|
76135
|
+
try {
|
|
76136
|
+
effective = resolveWorkspaceFromEntries(io.cwd, entries)?.name ?? null;
|
|
76137
|
+
reason = matches.length === 0 ? "no glob matches this directory: the defaults apply" : matches.length === 1 ? "the only glob that matches" : `the most specific of ${matches.length} matching globs (${matches.map((entry) => `${entry.name}: ${globSpecificity(entry.glob)} literal segments`).join(", ")})`;
|
|
76138
|
+
} catch (error) {
|
|
76139
|
+
reason = error instanceof WorkspaceConfigError ? error.message : String(error);
|
|
76140
|
+
}
|
|
76141
|
+
const rows = entries.map((entry) => ({
|
|
76142
|
+
name: entry.name,
|
|
76143
|
+
glob: entry.glob,
|
|
76144
|
+
keys: Object.keys(entry).filter((key) => key !== "name" && key !== "glob")
|
|
76145
|
+
}));
|
|
76146
|
+
return emit(io, ok2({
|
|
76147
|
+
path: current.path,
|
|
76148
|
+
workspaces: rows,
|
|
76149
|
+
cwd: io.cwd,
|
|
76150
|
+
effective,
|
|
76151
|
+
matches: matches.map((entry) => entry.name),
|
|
76152
|
+
reason
|
|
76153
|
+
}), (data) => [
|
|
76154
|
+
...data.workspaces.length ? [] : [`no workspaces in ${data.path}`],
|
|
76155
|
+
...data.workspaces.map((row) => `${row.name === data.effective ? "*" : " "} ${row.name} (${row.glob})${row.keys.length ? `: ${row.keys.join(", ")}` : ""}`),
|
|
76156
|
+
`${data.cwd}: ${data.effective ? `workspace ${data.effective}` : "no workspace"} (${data.reason})`
|
|
76157
|
+
]);
|
|
76158
|
+
}
|
|
76159
|
+
function add2(argv, io) {
|
|
76160
|
+
const positional = argv.filter((arg, index) => !arg.startsWith("--") && !["--glob", "--from"].includes(argv[index - 1] ?? ""));
|
|
76161
|
+
const [name, extra] = positional;
|
|
76162
|
+
if (!name)
|
|
76163
|
+
return usage3(io, "add needs <name>");
|
|
76164
|
+
if (extra)
|
|
76165
|
+
return usage3(io, `unexpected argument ${extra}`);
|
|
76166
|
+
const glob = flagValue(argv, "--glob");
|
|
76167
|
+
if (!glob)
|
|
76168
|
+
return usage3(io, "add needs --glob <glob>");
|
|
76169
|
+
const checked = validateWorkspaceGlob(glob);
|
|
76170
|
+
if (!checked.ok)
|
|
76171
|
+
return emit(io, fail2("invalid_input", checked.error));
|
|
76172
|
+
const from = flagValue(argv, "--from");
|
|
76173
|
+
if (from === null)
|
|
76174
|
+
return usage3(io, "--from needs <parent>");
|
|
76175
|
+
const current = load(io);
|
|
76176
|
+
if (typeof current === "number")
|
|
76177
|
+
return current;
|
|
76178
|
+
const entries = entriesOf(current);
|
|
76179
|
+
if (entries.some((entry) => entry.name === name))
|
|
76180
|
+
return emit(io, fail2("invalid_input", `a workspace named "${name}" already exists in ${current.path}`, {
|
|
76181
|
+
unblock: `workit workspace set ${name} <key>=<value>`
|
|
76182
|
+
}));
|
|
76183
|
+
const parent = from === undefined ? undefined : entries.find((entry) => entry.name === from);
|
|
76184
|
+
if (from !== undefined && !parent)
|
|
76185
|
+
return emit(io, fail2("not_found", `no workspace named "${from}" in ${current.path}`));
|
|
76186
|
+
const inherited = parent ? Object.fromEntries(INHERITED_KEYS.filter((key) => parent[key] !== undefined).map((key) => [
|
|
76187
|
+
key,
|
|
76188
|
+
structuredClone(parent[key])
|
|
76189
|
+
])) : {};
|
|
76190
|
+
const shadowed = overlappingEntries(glob, entries);
|
|
76191
|
+
const entry = {
|
|
76192
|
+
name,
|
|
76193
|
+
glob,
|
|
76194
|
+
...inherited,
|
|
76195
|
+
...clampToShadowed(shadowedCeiling(entries))
|
|
76196
|
+
};
|
|
76197
|
+
const result = save(current, [...entries, entry]);
|
|
76198
|
+
if (!result.ok)
|
|
76199
|
+
return emit(io, fail2("invalid_input", result.error));
|
|
76200
|
+
const ceiling = ceilingOf(entry);
|
|
76201
|
+
return emit(io, ok2({
|
|
76202
|
+
path: result.path,
|
|
76203
|
+
backup: result.backup,
|
|
76204
|
+
workspace: entry,
|
|
76205
|
+
inherited: Object.keys(inherited),
|
|
76206
|
+
shadows: shadowed.map((item) => item.name),
|
|
76207
|
+
grants: ceiling.grants,
|
|
76208
|
+
defaultEndpoint: ceiling.endpoint,
|
|
76209
|
+
verification: ceiling.verification
|
|
76210
|
+
}), (data) => [
|
|
76211
|
+
`${name} (${glob}) added to ${written(data.path, data.backup)}`,
|
|
76212
|
+
...data.inherited.length ? [` from ${from}: ${data.inherited.join(", ")}`] : [],
|
|
76213
|
+
...data.shadows.length ? [` overlaps: ${data.shadows.join(", ")}`] : [],
|
|
76214
|
+
` grants start at the strictest level of every workspace and the defaults:`,
|
|
76215
|
+
` grants: ${GRANT_KINDS.map((kind) => `${kind}=${String(data.grants[kind])}`).join(" ")}; default endpoint ${data.defaultEndpoint}; verification ${data.verification}`,
|
|
76216
|
+
` raising a grant needs the user, in their own terminal: workit grant set ${name} <kind>=<value>`
|
|
76217
|
+
]);
|
|
76218
|
+
}
|
|
76219
|
+
function set2(argv, io) {
|
|
76220
|
+
const [name, ...specs] = argv;
|
|
76221
|
+
if (!name || specs.length === 0)
|
|
76222
|
+
return usage3(io, "set needs <name> and <key>=<value>");
|
|
76223
|
+
const grantSpecs = [];
|
|
76224
|
+
const changes = [];
|
|
76225
|
+
for (const spec of specs) {
|
|
76226
|
+
const eq = spec.indexOf("=");
|
|
76227
|
+
if (eq <= 0)
|
|
76228
|
+
return usage3(io, `${spec}: expected <key>=<value>`);
|
|
76229
|
+
const key = spec.slice(0, eq);
|
|
76230
|
+
const keyPath = key.split(".");
|
|
76231
|
+
if (keyPath.some((part) => !SEGMENT.test(part) || UNSAFE_SEGMENTS.has(part)))
|
|
76232
|
+
return usage3(io, `${spec}: each key segment is letters, digits, _ or -`);
|
|
76233
|
+
if (GRANT_KEYS.has(keyPath[0])) {
|
|
76234
|
+
grantSpecs.push(spec);
|
|
76235
|
+
continue;
|
|
76236
|
+
}
|
|
76237
|
+
if (SCOPE_KEYS.has(keyPath[0]))
|
|
76238
|
+
return emit(io, fail2("blocked", `${keyPath[0]} decides where the entry's grants apply; workspace set does not change it`, {
|
|
76239
|
+
unblock: `ask the user to edit ${keyPath[0]} of "${name}" in their own editor, or add a new entry: workit workspace add <name> --glob <g> --from ${name}`
|
|
76240
|
+
}));
|
|
76241
|
+
if (!SETTABLE_KEYS.has(keyPath[0]))
|
|
76242
|
+
return usage3(io, `${spec}: unknown key ${keyPath[0]} (settable: ${[...SETTABLE_KEYS].join(", ")})`);
|
|
76243
|
+
changes.push({ path: keyPath, value: parseSetValue(spec.slice(eq + 1)) });
|
|
76244
|
+
}
|
|
76245
|
+
if (grantSpecs.length)
|
|
76246
|
+
return emit(io, fail2("blocked", `workspace set does not change grants, defaultEndpoint or verification (${grantSpecs.join(", ")})`, {
|
|
76247
|
+
unblock: `ask the user to run, in their own terminal outside the agent host: workit grant set ${name} ${grantSpecs.join(" ")}`
|
|
76248
|
+
}));
|
|
76249
|
+
const current = load(io);
|
|
76250
|
+
if (typeof current === "number")
|
|
76251
|
+
return current;
|
|
76252
|
+
const entries = structuredClone(entriesOf(current));
|
|
76253
|
+
const entry = entries.find((item) => item.name === name);
|
|
76254
|
+
if (!entry)
|
|
76255
|
+
return emit(io, fail2("not_found", `no workspace named "${name}" in ${current.path}`));
|
|
76256
|
+
const credential = changes.find((change) => change.path[0] === "vcs");
|
|
76257
|
+
if (credential && (configuredGrants(entry).source !== "default" || entry.defaultEndpoint !== undefined))
|
|
76258
|
+
return emit(io, fail2("blocked", `${name} has grants of its own; its vcs decides the account they act through, so workspace set does not change it`, {
|
|
76259
|
+
unblock: `ask the user to change ${credential.path.join(".")} of "${name}" in their own editor, or to unset the grants first (workit grant unset ${name} …)`
|
|
76260
|
+
}));
|
|
76261
|
+
for (const change of changes) {
|
|
76262
|
+
let target = entry;
|
|
76263
|
+
for (const part of change.path.slice(0, -1)) {
|
|
76264
|
+
const next = target[part];
|
|
76265
|
+
if (next === undefined || next === null)
|
|
76266
|
+
target[part] = {};
|
|
76267
|
+
else if (typeof next !== "object" || Array.isArray(next))
|
|
76268
|
+
return usage3(io, `${change.path.join(".")}: ${part} is not an object`);
|
|
76269
|
+
target = target[part];
|
|
76270
|
+
}
|
|
76271
|
+
const last = change.path[change.path.length - 1];
|
|
76272
|
+
if (change.value === null)
|
|
76273
|
+
delete target[last];
|
|
76274
|
+
else
|
|
76275
|
+
target[last] = change.value;
|
|
76276
|
+
}
|
|
76277
|
+
const result = save(current, entries);
|
|
76278
|
+
if (!result.ok)
|
|
76279
|
+
return emit(io, fail2("invalid_input", result.error));
|
|
76280
|
+
return emit(io, ok2({ path: result.path, backup: result.backup, workspace: entry }), (data) => [
|
|
76281
|
+
`${name}: ${changes.map((change) => change.path.join(".")).join(", ")} updated in ${written(data.path, data.backup)}`
|
|
76282
|
+
]);
|
|
76283
|
+
}
|
|
76284
|
+
async function runWorkspace(argv, io) {
|
|
76285
|
+
const [sub, ...rest] = argv.filter((arg) => arg !== "--json" && arg !== "--");
|
|
76286
|
+
if (sub === undefined || sub === "list")
|
|
76287
|
+
return list2(rest, io);
|
|
76288
|
+
if (sub === "add")
|
|
76289
|
+
return add2(rest, io);
|
|
76290
|
+
if (sub === "set")
|
|
76291
|
+
return set2(rest, io);
|
|
76292
|
+
return usage3(io, `unknown subcommand "${sub}"`);
|
|
76293
|
+
}
|
|
76294
|
+
var USAGE4 = "workit workspace list | workspace add <name> --glob <g> [--from <parent>] | workspace set <name> <key>=<value>…", INHERITED_KEYS, GRANT_KEYS, SCOPE_KEYS, SETTABLE_KEYS, SEGMENT, UNSAFE_SEGMENTS, ceilingOf = (entry) => ({
|
|
76295
|
+
grants: { ...DEFAULT_GRANTS, ...configuredGrants(entry).grants },
|
|
76296
|
+
endpoint: isDefaultEndpoint(entry?.defaultEndpoint) ? entry.defaultEndpoint : DEFAULT_ENDPOINT,
|
|
76297
|
+
verification: verificationOf(entry)
|
|
76298
|
+
}), STRICTNESS, looser = (current, next) => STRICTNESS.indexOf(next) > STRICTNESS.indexOf(current), shadowedCeiling = (shadowed) => {
|
|
76299
|
+
if (shadowed.length === 0)
|
|
76300
|
+
return null;
|
|
76301
|
+
const ceilings = shadowed.map(ceilingOf);
|
|
76302
|
+
const grants = { ...DEFAULT_GRANTS };
|
|
76303
|
+
for (const kind of GRANT_KINDS)
|
|
76304
|
+
grants[kind] = ceilings.map((ceiling) => ceiling.grants[kind]).reduce((low, value) => raises(kind, value, low) ? value : low);
|
|
76305
|
+
return {
|
|
76306
|
+
grants,
|
|
76307
|
+
endpoint: ceilings.map((ceiling) => ceiling.endpoint).reduce((low, value) => raisesEndpoint(value, low) ? value : low),
|
|
76308
|
+
verification: ceilings.map((ceiling) => ceiling.verification).reduce((strict, value) => looser(value, strict) ? value : strict)
|
|
76309
|
+
};
|
|
76310
|
+
}, clampToShadowed = (shadowed) => {
|
|
76311
|
+
if (!shadowed)
|
|
76312
|
+
return {};
|
|
76313
|
+
const autonomy = Object.fromEntries(GRANT_KINDS.filter((kind) => raises(kind, shadowed.grants[kind], DEFAULT_GRANTS[kind])).map((kind) => [kind, shadowed.grants[kind]]));
|
|
76314
|
+
return {
|
|
76315
|
+
...Object.keys(autonomy).length ? { autonomy } : {},
|
|
76316
|
+
...looser(shadowed.verification, DEFAULT_VERIFICATION) ? { verification: shadowed.verification } : {}
|
|
76317
|
+
};
|
|
76318
|
+
}, usage3 = (io, message) => emit(io, fail2("invalid_input", `${message}
|
|
76319
|
+
usage: ${USAGE4}`)), load = (io) => {
|
|
76320
|
+
const current = readWorkspacesResult();
|
|
76321
|
+
if (current.status === "malformed" || current.status === "invalid")
|
|
76322
|
+
return emit(io, fail2("invalid_input", current.error ?? `${current.path} is invalid`));
|
|
76323
|
+
return current;
|
|
76324
|
+
}, entriesOf = (current) => current.entries, save = (current, entries) => {
|
|
76325
|
+
const document2 = { ...current.document, workspaces: entries };
|
|
76326
|
+
const validated = validateWorkspacesDocument(document2, current.path);
|
|
76327
|
+
if (validated.status !== "valid")
|
|
76328
|
+
return { ok: false, error: validated.error ?? "invalid workspaces.json" };
|
|
76329
|
+
const latest = readWorkspacesResult();
|
|
76330
|
+
if (latest.revision !== current.revision)
|
|
76331
|
+
return { ok: false, error: `${current.path} changed; retry` };
|
|
76332
|
+
let backup = null;
|
|
76333
|
+
try {
|
|
76334
|
+
if (existsSync21(current.path)) {
|
|
76335
|
+
backup = `${current.path}.bak`;
|
|
76336
|
+
copyFileSync7(current.path, backup);
|
|
76337
|
+
}
|
|
76338
|
+
writeFileAtomic(current.path, `${JSON.stringify(document2, null, 2)}
|
|
76339
|
+
`);
|
|
76340
|
+
} catch (error) {
|
|
76341
|
+
return {
|
|
76342
|
+
ok: false,
|
|
76343
|
+
error: `failed to write ${current.path}: ${error instanceof Error ? error.message : String(error)}`
|
|
76344
|
+
};
|
|
76345
|
+
}
|
|
76346
|
+
return { ok: true, path: current.path, backup };
|
|
76347
|
+
}, written = (path, backup) => `${path}${backup ? ` (previous copy: ${backup})` : ""}`, flagValue = (argv, flag) => {
|
|
76348
|
+
const index = argv.findIndex((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
76349
|
+
if (index < 0)
|
|
76350
|
+
return;
|
|
76351
|
+
const arg = argv[index];
|
|
76352
|
+
if (arg.includes("="))
|
|
76353
|
+
return arg.slice(flag.length + 1);
|
|
76354
|
+
return argv[index + 1] ?? null;
|
|
76355
|
+
}, parseSetValue = (raw) => {
|
|
76356
|
+
try {
|
|
76357
|
+
return JSON.parse(raw);
|
|
76358
|
+
} catch {
|
|
76359
|
+
return raw;
|
|
76360
|
+
}
|
|
76361
|
+
}, run11 = (argv, io) => runWorkspace(argv, io);
|
|
76362
|
+
var init_workspace = __esm(() => {
|
|
76363
|
+
init_autonomy();
|
|
76364
|
+
init_safe_write();
|
|
76365
|
+
init_workspaces();
|
|
76366
|
+
init_output();
|
|
76367
|
+
INHERITED_KEYS = [
|
|
76368
|
+
"vcs",
|
|
76369
|
+
"issues",
|
|
76370
|
+
"branchPolicy",
|
|
76371
|
+
"commitPolicy",
|
|
76372
|
+
"trailers",
|
|
76373
|
+
"youtrack",
|
|
76374
|
+
"models"
|
|
76375
|
+
];
|
|
76376
|
+
GRANT_KEYS = new Set(["autonomy", "autoApprove", "defaultEndpoint", "verification"]);
|
|
76377
|
+
SCOPE_KEYS = new Set(["name", "glob"]);
|
|
76378
|
+
SETTABLE_KEYS = new Set([
|
|
76379
|
+
"vcs",
|
|
76380
|
+
"issues",
|
|
76381
|
+
"branchPolicy",
|
|
76382
|
+
"commitPolicy",
|
|
76383
|
+
"trailers",
|
|
76384
|
+
"liveSessionGuard",
|
|
76385
|
+
"youtrack",
|
|
76386
|
+
"models",
|
|
76387
|
+
"fanout",
|
|
76388
|
+
"delegation",
|
|
76389
|
+
"defaultProfile",
|
|
76390
|
+
"profiles",
|
|
76391
|
+
"releaseTracks",
|
|
76392
|
+
"resources"
|
|
76393
|
+
]);
|
|
76394
|
+
SEGMENT = /^[A-Za-z0-9_-]+$/u;
|
|
76395
|
+
UNSAFE_SEGMENTS = new Set(["__proto__", "constructor", "prototype"]);
|
|
76396
|
+
STRICTNESS = ["independent", "self", "proportional"];
|
|
76397
|
+
});
|
|
76398
|
+
|
|
76006
76399
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
76007
76400
|
import fs22 from "node:fs";
|
|
76008
76401
|
import path46 from "node:path";
|
|
@@ -76876,7 +77269,7 @@ __export(exports_check, {
|
|
|
76876
77269
|
OUTPUT_LINES: () => OUTPUT_LINES,
|
|
76877
77270
|
boundedOutput: () => boundedOutput,
|
|
76878
77271
|
hostToolWaitCapMs: () => hostToolWaitCapMs,
|
|
76879
|
-
run: () =>
|
|
77272
|
+
run: () => run12,
|
|
76880
77273
|
workspaceResources: () => workspaceResources
|
|
76881
77274
|
});
|
|
76882
77275
|
import os20 from "node:os";
|
|
@@ -77160,10 +77553,10 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
77160
77553
|
env
|
|
77161
77554
|
};
|
|
77162
77555
|
}
|
|
77163
|
-
async function
|
|
77556
|
+
async function run12(argv, io) {
|
|
77164
77557
|
const options = parse6(argv);
|
|
77165
77558
|
if (options instanceof Error)
|
|
77166
|
-
return emit(io, fail2("invalid_input", options.message, { unblock:
|
|
77559
|
+
return emit(io, fail2("invalid_input", options.message, { unblock: USAGE5 }));
|
|
77167
77560
|
const config = loadCheckConfig(io.cwd);
|
|
77168
77561
|
if (config.note)
|
|
77169
77562
|
io.stderr(`note: ${config.note}
|
|
@@ -77174,7 +77567,7 @@ async function run11(argv, io) {
|
|
|
77174
77567
|
let name = options.name;
|
|
77175
77568
|
if (options.command === null) {
|
|
77176
77569
|
if (options.positionals.length !== 1 || options.name || options.shell)
|
|
77177
|
-
return emit(io, fail2("invalid_input", "pass a check name, or a command after --", { unblock:
|
|
77570
|
+
return emit(io, fail2("invalid_input", "pass a check name, or a command after --", { unblock: USAGE5 }));
|
|
77178
77571
|
name = options.positionals[0];
|
|
77179
77572
|
if (config.error)
|
|
77180
77573
|
return emit(io, fail2("invalid_input", `check config is invalid: ${config.error}`));
|
|
@@ -77189,11 +77582,11 @@ async function run11(argv, io) {
|
|
|
77189
77582
|
} else {
|
|
77190
77583
|
if (options.positionals.length)
|
|
77191
77584
|
return emit(io, fail2("invalid_input", `unexpected argument ${options.positionals[0]} before --`, {
|
|
77192
|
-
unblock:
|
|
77585
|
+
unblock: USAGE5
|
|
77193
77586
|
}));
|
|
77194
77587
|
command = options.command;
|
|
77195
77588
|
if (!command.length)
|
|
77196
|
-
return emit(io, fail2("invalid_input", "no command after --", { unblock:
|
|
77589
|
+
return emit(io, fail2("invalid_input", "no command after --", { unblock: USAGE5 }));
|
|
77197
77590
|
if (options.shell && command.length !== 1)
|
|
77198
77591
|
return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
|
|
77199
77592
|
}
|
|
@@ -77372,7 +77765,7 @@ async function run11(argv, io) {
|
|
|
77372
77765
|
return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
|
|
77373
77766
|
return 0;
|
|
77374
77767
|
}
|
|
77375
|
-
var
|
|
77768
|
+
var USAGE5 = 'workit check <name> [--full] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <s>] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path49.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, HOST_TOOL_WAIT_CAP_MS = 1e5;
|
|
77376
77769
|
var init_check = __esm(() => {
|
|
77377
77770
|
init_check_config();
|
|
77378
77771
|
init_checks3();
|
|
@@ -77395,7 +77788,7 @@ var init_check = __esm(() => {
|
|
|
77395
77788
|
// packages/workit-cli/src/verbs/lock.ts
|
|
77396
77789
|
var exports_lock = {};
|
|
77397
77790
|
__export(exports_lock, {
|
|
77398
|
-
run: () =>
|
|
77791
|
+
run: () => run13
|
|
77399
77792
|
});
|
|
77400
77793
|
import fs25 from "node:fs";
|
|
77401
77794
|
import path50 from "node:path";
|
|
@@ -77466,7 +77859,7 @@ async function runHeavy(args, io) {
|
|
|
77466
77859
|
unblock: "workit lock run [--shell] [--wait <s>] [--timeout <s>] -- <cmd…>"
|
|
77467
77860
|
}));
|
|
77468
77861
|
const check = await Promise.resolve().then(() => (init_check(), {}));
|
|
77469
|
-
return
|
|
77862
|
+
return run12([`--heavy`, ...head, ...args.slice(split)], io);
|
|
77470
77863
|
}
|
|
77471
77864
|
function readPatterns(file) {
|
|
77472
77865
|
try {
|
|
@@ -77537,7 +77930,7 @@ async function heavy(args, io) {
|
|
|
77537
77930
|
unblock: "workit lock heavy list|add <pattern>|remove <pattern>|test -- <cmd…>"
|
|
77538
77931
|
}));
|
|
77539
77932
|
}
|
|
77540
|
-
async function
|
|
77933
|
+
async function run13(argv, io) {
|
|
77541
77934
|
const [sub, ...rest] = argv;
|
|
77542
77935
|
if (sub === "status")
|
|
77543
77936
|
return status(io);
|
|
@@ -77547,9 +77940,9 @@ async function run12(argv, io) {
|
|
|
77547
77940
|
return runHeavy(rest, io);
|
|
77548
77941
|
if (sub === "heavy")
|
|
77549
77942
|
return heavy(rest, io);
|
|
77550
|
-
return emit(io, fail2("invalid_input", `unknown lock subcommand ${sub ?? "(none)"}`, { unblock:
|
|
77943
|
+
return emit(io, fail2("invalid_input", `unknown lock subcommand ${sub ?? "(none)"}`, { unblock: USAGE6 }));
|
|
77551
77944
|
}
|
|
77552
|
-
var
|
|
77945
|
+
var USAGE6 = "workit lock status | wait [--timeout <s>] | run [--shell] [--wait <s>] [--timeout <s>] -- <cmd…> | heavy list|add|remove|test", held = (slots) => slots.filter((slot) => slot.holder && !slot.stale), sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), commandText = (args) => {
|
|
77553
77946
|
const split = args.indexOf("--");
|
|
77554
77947
|
return (split < 0 ? args : args.slice(split + 1)).join(" ").trim();
|
|
77555
77948
|
};
|
|
@@ -77564,15 +77957,15 @@ var init_lock = __esm(() => {
|
|
|
77564
77957
|
// packages/workit-cli/src/verbs/models.ts
|
|
77565
77958
|
var exports_models = {};
|
|
77566
77959
|
__export(exports_models, {
|
|
77567
|
-
run: () =>
|
|
77960
|
+
run: () => run14
|
|
77568
77961
|
});
|
|
77569
|
-
import { existsSync as
|
|
77962
|
+
import { existsSync as existsSync22, readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync9 } from "node:fs";
|
|
77570
77963
|
import os21 from "node:os";
|
|
77571
77964
|
import path51 from "node:path";
|
|
77572
|
-
async function
|
|
77965
|
+
async function run14(argv, io) {
|
|
77573
77966
|
const [sub, ...args] = argv.filter((arg) => arg !== "--json");
|
|
77574
77967
|
if (sub !== "show")
|
|
77575
|
-
return emit(io, fail2("invalid_input", `usage: ${
|
|
77968
|
+
return emit(io, fail2("invalid_input", `usage: ${USAGE7}`, { unblock: "workit help models" }));
|
|
77576
77969
|
const role = flag3(args, "--role");
|
|
77577
77970
|
const tier = flag3(args, "--tier");
|
|
77578
77971
|
const hostFlag = flag3(args, "--host");
|
|
@@ -77619,7 +78012,7 @@ async function run13(argv, io) {
|
|
|
77619
78012
|
...(data.issues ?? []).map((issue) => `note: ${issue}`)
|
|
77620
78013
|
]);
|
|
77621
78014
|
}
|
|
77622
|
-
var
|
|
78015
|
+
var USAGE7 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--report [--days <n>]] [--json]", flag3 = (argv, name) => {
|
|
77623
78016
|
const at = argv.findIndex((arg) => arg === name || arg.startsWith(`${name}=`));
|
|
77624
78017
|
if (at < 0)
|
|
77625
78018
|
return null;
|
|
@@ -77662,7 +78055,7 @@ var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
|
|
|
77662
78055
|
continue;
|
|
77663
78056
|
const agentType = JSON.parse(readFileSync21(meta, "utf8")).agentType;
|
|
77664
78057
|
const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
|
|
77665
|
-
if (typeof agentType !== "string" || !
|
|
78058
|
+
if (typeof agentType !== "string" || !existsSync22(transcript))
|
|
77666
78059
|
continue;
|
|
77667
78060
|
const ran = modelsOf(transcript);
|
|
77668
78061
|
if (!ran.size)
|
|
@@ -77801,7 +78194,7 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
77801
78194
|
|
|
77802
78195
|
// packages/workit-core/src/git/ops.ts
|
|
77803
78196
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
77804
|
-
import { existsSync as
|
|
78197
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22 } from "node:fs";
|
|
77805
78198
|
import path52 from "node:path";
|
|
77806
78199
|
function operationInProgress(cwd) {
|
|
77807
78200
|
const markers = [
|
|
@@ -77819,11 +78212,11 @@ function operationInProgress(cwd) {
|
|
|
77819
78212
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
77820
78213
|
for (const [index, [, operation]] of markers.entries()) {
|
|
77821
78214
|
const marker = found[index];
|
|
77822
|
-
if (!marker || !
|
|
78215
|
+
if (!marker || !existsSync23(marker))
|
|
77823
78216
|
continue;
|
|
77824
|
-
if (index === 1 &&
|
|
78217
|
+
if (index === 1 && existsSync23(path52.join(marker, "applying")))
|
|
77825
78218
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
77826
|
-
if (index === 0 &&
|
|
78219
|
+
if (index === 0 && existsSync23(path52.join(marker, "amend")) && !conflicted()) {
|
|
77827
78220
|
let headName = "";
|
|
77828
78221
|
try {
|
|
77829
78222
|
headName = readFileSync22(path52.join(marker, "head-name"), "utf8").trim();
|
|
@@ -78154,7 +78547,7 @@ function gitCommit(cwd, input) {
|
|
|
78154
78547
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
78155
78548
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
78156
78549
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
78157
|
-
const addable = paths.filter((value) =>
|
|
78550
|
+
const addable = paths.filter((value) => existsSync23(path52.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
78158
78551
|
if (addable.length) {
|
|
78159
78552
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
78160
78553
|
if (!added.ok)
|
|
@@ -78182,9 +78575,13 @@ function gitCommit(cwd, input) {
|
|
|
78182
78575
|
timeoutMs: COMMIT_TIMEOUT_MS,
|
|
78183
78576
|
env: { ...input.env ?? process.env, WORKIT_TRAILERS: trailersOn ? "on" : "off" }
|
|
78184
78577
|
});
|
|
78185
|
-
if (!committed.ok)
|
|
78578
|
+
if (!committed.ok) {
|
|
78579
|
+
const output = gitOutput(committed);
|
|
78580
|
+
const refusal = hookRefusal(output);
|
|
78186
78581
|
return failure3("failed", `git commit failed (a hook or git refused it):
|
|
78187
|
-
${
|
|
78582
|
+
${output}${refusal ? `
|
|
78583
|
+
${refusal}` : ""}`);
|
|
78584
|
+
}
|
|
78188
78585
|
const sha = headSha(cwd);
|
|
78189
78586
|
if (!sha)
|
|
78190
78587
|
return failure3("failed", "the commit did not resolve");
|
|
@@ -78641,6 +79038,14 @@ var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}
|
|
|
78641
79038
|
const lines = redactText(`${run.stderr}
|
|
78642
79039
|
${run.stdout ?? ""}`).split(/\r?\n/u).map((value) => value.trim()).filter((value) => value && !value.startsWith("hint:"));
|
|
78643
79040
|
return lines.slice(-max).join(" / ").slice(0, 400) || "git failed";
|
|
79041
|
+
}, hookRefusal = (output) => {
|
|
79042
|
+
const match = /✖\s+(.*?)\s*\[([\w-]+)\]/u.exec(output);
|
|
79043
|
+
if (!match)
|
|
79044
|
+
return null;
|
|
79045
|
+
const [, text, rule] = match;
|
|
79046
|
+
const limit = /(?:longer|shorter|exceed\w*|more|less|than)\D*?(\d+)/iu.exec(text)?.[1];
|
|
79047
|
+
const got = /(?:current length is|got|is)\s+(\d+)/iu.exec(text)?.[1];
|
|
79048
|
+
return `commit refused by commit-msg hook: ${rule}${limit ? ` ${limit}` : ""}${got ? ` (got ${got})` : ""}${limit || got ? "" : ` (${text})`}`;
|
|
78644
79049
|
}, OUTPUT_LINES2 = 200, OUTPUT_LINE_CHARS = 1000, gitOutput = (run) => {
|
|
78645
79050
|
const lines = redactText(`${run.stderr}
|
|
78646
79051
|
${run.stdout ?? ""}`).split(/\r?\n/u).map((value) => value.trimEnd()).filter((value) => value.trim() && !value.trimStart().startsWith("hint:")).map((value) => value.length > OUTPUT_LINE_CHARS ? `${value.slice(0, OUTPUT_LINE_CHARS)}…` : value);
|
|
@@ -79157,6 +79562,8 @@ function waitVerdict(doc, options) {
|
|
|
79157
79562
|
};
|
|
79158
79563
|
if (checks === "pending")
|
|
79159
79564
|
return { state: "waiting", reason: "checks_pending" };
|
|
79565
|
+
if (doc.checks.pending.length > 0)
|
|
79566
|
+
return { state: "waiting", reason: "checks_pending" };
|
|
79160
79567
|
if (checks === "passing")
|
|
79161
79568
|
return { state: "ready", reason: "checks_passing" };
|
|
79162
79569
|
const ciRequired = doc.checks.missingRequired === null || doc.mergeState === "ci_must_pass" || doc.mergeState === "ci_still_running";
|
|
@@ -81365,7 +81772,35 @@ function ancestors(slices) {
|
|
|
81365
81772
|
}
|
|
81366
81773
|
return out;
|
|
81367
81774
|
}
|
|
81368
|
-
function
|
|
81775
|
+
function regeneratedFiles(root, tracked) {
|
|
81776
|
+
const found = new Map;
|
|
81777
|
+
let scripts;
|
|
81778
|
+
try {
|
|
81779
|
+
const manifest = JSON.parse(fs29.readFileSync(path56.join(root, "package.json"), "utf8"));
|
|
81780
|
+
scripts = manifest.scripts ?? {};
|
|
81781
|
+
} catch {
|
|
81782
|
+
return found;
|
|
81783
|
+
}
|
|
81784
|
+
const runner = fs29.existsSync(path56.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path56.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path56.join(root, "yarn.lock")) ? "yarn run" : "npm run";
|
|
81785
|
+
const outputs = tracked.filter((file) => !CODE.test(file));
|
|
81786
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
81787
|
+
if (!name.startsWith("write:") || typeof command !== "string")
|
|
81788
|
+
continue;
|
|
81789
|
+
for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
|
|
81790
|
+
let source;
|
|
81791
|
+
try {
|
|
81792
|
+
source = fs29.readFileSync(path56.join(root, file), "utf8");
|
|
81793
|
+
} catch {
|
|
81794
|
+
continue;
|
|
81795
|
+
}
|
|
81796
|
+
for (const output of outputs)
|
|
81797
|
+
if (!found.has(output) && source.includes(output))
|
|
81798
|
+
found.set(output, `${runner} ${name}`);
|
|
81799
|
+
}
|
|
81800
|
+
}
|
|
81801
|
+
return found;
|
|
81802
|
+
}
|
|
81803
|
+
function analyzeOverlap(plan, candidates, regenerated = new Map) {
|
|
81369
81804
|
const shared = [...DEFAULT_SHARED, ...plan.shared];
|
|
81370
81805
|
const before = ancestors(plan.slices);
|
|
81371
81806
|
const related = (a, b) => Boolean(before.get(a)?.has(b) || before.get(b)?.has(a));
|
|
@@ -81386,6 +81821,11 @@ function analyzeOverlap(plan, candidates) {
|
|
|
81386
81821
|
overlaps.push({ path: file, slices: ids, resolution: "owner", owner: owners[0].id });
|
|
81387
81822
|
continue;
|
|
81388
81823
|
}
|
|
81824
|
+
const writer = spellings.map((spelling) => regenerated.get(spelling)).find(Boolean);
|
|
81825
|
+
if (writer) {
|
|
81826
|
+
overlaps.push({ path: file, slices: ids, resolution: "regenerated", writer });
|
|
81827
|
+
continue;
|
|
81828
|
+
}
|
|
81389
81829
|
if (owners.length === 0 && matching.every((a, i) => matching.slice(i + 1).every((b) => related(a.id, b.id)))) {
|
|
81390
81830
|
overlaps.push({ path: file, slices: ids, resolution: "serialized" });
|
|
81391
81831
|
continue;
|
|
@@ -81668,7 +82108,7 @@ function planFanout(cwd, input, now = new Date) {
|
|
|
81668
82108
|
const ref = trunkRef(cwd, plan.trunk);
|
|
81669
82109
|
const tracked = ref ? nulList2(gitRun4(cwd, ["ls-tree", "-r", "-z", "--name-only", ref]).stdout) : [];
|
|
81670
82110
|
const samples = plan.slices.flatMap((slice) => [...slice.scope, ...slice.owns].flatMap(scopeSamples));
|
|
81671
|
-
const { overlaps, conflicts } = analyzeOverlap(plan, [...tracked, ...samples]);
|
|
82111
|
+
const { overlaps, conflicts } = analyzeOverlap(plan, [...tracked, ...samples], regeneratedFiles(mainCheckout(cwd), tracked));
|
|
81672
82112
|
if (conflicts.length)
|
|
81673
82113
|
return fanoutFail("blocked", `${conflicts.length} file-scope overlap${conflicts.length === 1 ? "" : "s"} between slices: ${conflicts[0].slices.join(" and ")} on ${conflicts[0].paths[0]}${conflicts[0].paths.length > 1 ? ` (+${conflicts[0].paths.length - 1})` : ""}`, conflicts[0].suggestion.text, { name: plan.name, conflicts, overlaps });
|
|
81674
82114
|
const trunkCase = caseIndex(tracked);
|
|
@@ -81738,6 +82178,9 @@ function planFanout(cwd, input, now = new Date) {
|
|
|
81738
82178
|
if (wave.length > IN_FLIGHT_CAP)
|
|
81739
82179
|
notes.push(`wave ${index + 1} has ${wave.length} slices; keep 4-${IN_FLIGHT_CAP} in flight and queue the rest`);
|
|
81740
82180
|
});
|
|
82181
|
+
for (const overlap of overlaps)
|
|
82182
|
+
if (overlap.writer)
|
|
82183
|
+
notes.push(`${overlap.path} is regenerated at fan-in: slices leave it uncommitted, and the lead runs \`${overlap.writer}\` after each rebase`);
|
|
81741
82184
|
for (const slice of plan.slices)
|
|
81742
82185
|
if (slice.dependsOn.length > 1 && slice.base === plan.trunk)
|
|
81743
82186
|
notes.push(`slice ${slice.id} depends on ${slice.dependsOn.join(", ")}: start it from ${plan.trunk} after they land`);
|
|
@@ -81779,7 +82222,7 @@ var FANOUT_VERSION = 1, TIERS, REASONS, FAN_IN_MODES, fanoutFail = (code, error,
|
|
|
81779
82222
|
if (Array.isArray(value) && value.every((item) => typeof item === "string"))
|
|
81780
82223
|
return value;
|
|
81781
82224
|
return null;
|
|
81782
|
-
}, ID, quoteList = (items) => items.map((item) => `"${item}"`).join(", "), ownerSuggestion = (slice, paths) => ({
|
|
82225
|
+
}, ID, CODE, quoteList = (items) => items.map((item) => `"${item}"`).join(", "), ownerSuggestion = (slice, paths) => ({
|
|
81783
82226
|
kind: "owner",
|
|
81784
82227
|
slice,
|
|
81785
82228
|
paths,
|
|
@@ -81829,6 +82272,7 @@ var init_fanout = __esm(() => {
|
|
|
81829
82272
|
compiled = new Map;
|
|
81830
82273
|
PLACEHOLDER3 = /^(?:<[^>]*>|tbd|todo|fixme|\?+|\.\.\.|…)$/iu;
|
|
81831
82274
|
ID = /^[a-z0-9][a-z0-9._-]{0,63}$/u;
|
|
82275
|
+
CODE = /\.(?:[cm]?[jt]sx?)$/u;
|
|
81832
82276
|
});
|
|
81833
82277
|
|
|
81834
82278
|
// packages/workit-core/src/forge/exec.ts
|
|
@@ -83628,6 +84072,17 @@ function unverifiedFlag(flags) {
|
|
|
83628
84072
|
return "--unverified needs --reason <why the user asked for it>";
|
|
83629
84073
|
return reason.length > MAX_REASON ? `--reason is capped at ${MAX_REASON} characters` : { reason };
|
|
83630
84074
|
}
|
|
84075
|
+
function selector(flags) {
|
|
84076
|
+
const pr = positiveInt(flags.values.pr, "--pr");
|
|
84077
|
+
if (typeof pr === "string")
|
|
84078
|
+
return pr;
|
|
84079
|
+
const branch = flags.values.branch ?? flags.values.head ?? null;
|
|
84080
|
+
if (flags.values.branch !== undefined && flags.values.head !== undefined)
|
|
84081
|
+
return "pass --branch or --head, not both";
|
|
84082
|
+
if (pr && branch)
|
|
84083
|
+
return "pass --pr or --branch, not both";
|
|
84084
|
+
return { pr, branch };
|
|
84085
|
+
}
|
|
83631
84086
|
function positiveInt(value, flag) {
|
|
83632
84087
|
if (value === undefined)
|
|
83633
84088
|
return null;
|
|
@@ -83714,7 +84169,7 @@ function renderStatus(doc) {
|
|
|
83714
84169
|
lines.push(`next: ${doc.next}`);
|
|
83715
84170
|
return lines;
|
|
83716
84171
|
}
|
|
83717
|
-
var forgeDeps, MAX_REASON = 500,
|
|
84172
|
+
var forgeDeps, MAX_REASON = 500, usage4 = (io, message, line) => emit(io, fail2("invalid_input", message, { unblock: line })), forgeFail = (io, result, data) => emit(io, fail2(result.code, result.error, { data, unblock: result.unblock })), CONNECT_BUDGET_MS = 15000, pushIdentity = (io, branch) => checkPushIdentity(io.cwd, {
|
|
83718
84173
|
branch,
|
|
83719
84174
|
env: io.env,
|
|
83720
84175
|
runner: forgeDeps.runner,
|
|
@@ -83737,7 +84192,7 @@ var init_forge_common = __esm(() => {
|
|
|
83737
84192
|
// packages/workit-cli/src/verbs/pr.ts
|
|
83738
84193
|
var exports_pr = {};
|
|
83739
84194
|
__export(exports_pr, {
|
|
83740
|
-
run: () =>
|
|
84195
|
+
run: () => run15
|
|
83741
84196
|
});
|
|
83742
84197
|
import { readFileSync as readFileSync24 } from "node:fs";
|
|
83743
84198
|
import path58 from "node:path";
|
|
@@ -83753,25 +84208,24 @@ function readBodyFile(io, file) {
|
|
|
83753
84208
|
async function status2(argv, io) {
|
|
83754
84209
|
const flags = parseFlags(argv, { pr: "value", branch: "value", "log-lines": "value" });
|
|
83755
84210
|
if (typeof flags === "string")
|
|
83756
|
-
return
|
|
84211
|
+
return usage4(io, flags, STATUS_USAGE);
|
|
83757
84212
|
if (flags.positionals.length)
|
|
83758
|
-
return
|
|
83759
|
-
const
|
|
83760
|
-
if (typeof
|
|
83761
|
-
return
|
|
83762
|
-
|
|
83763
|
-
return usage3(io, "pass --pr or --branch, not both", STATUS_USAGE);
|
|
84213
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, STATUS_USAGE);
|
|
84214
|
+
const picked = selector(flags);
|
|
84215
|
+
if (typeof picked === "string")
|
|
84216
|
+
return usage4(io, picked, STATUS_USAGE);
|
|
84217
|
+
const { pr, branch: pickedBranch } = picked;
|
|
83764
84218
|
const logLines = flags.values["log-lines"] === "0" ? 0 : positiveInt(flags.values["log-lines"], "--log-lines");
|
|
83765
84219
|
if (typeof logLines === "string")
|
|
83766
|
-
return
|
|
84220
|
+
return usage4(io, logLines, STATUS_USAGE);
|
|
83767
84221
|
if (logLines !== null && logLines > 500)
|
|
83768
|
-
return
|
|
83769
|
-
const connected = connect(io,
|
|
84222
|
+
return usage4(io, "--log-lines is capped at 500", STATUS_USAGE);
|
|
84223
|
+
const connected = connect(io, pickedBranch);
|
|
83770
84224
|
if (!connected.ok)
|
|
83771
84225
|
return forgeFail(io, connected);
|
|
83772
84226
|
const report = prStatusReport(io.cwd, connected.data, {
|
|
83773
84227
|
pr,
|
|
83774
|
-
branch:
|
|
84228
|
+
branch: pickedBranch,
|
|
83775
84229
|
logLines: logLines ?? 60,
|
|
83776
84230
|
identity: connected.data.identity,
|
|
83777
84231
|
actor: actorFromEnv(io.env)
|
|
@@ -83863,23 +84317,23 @@ async function create4(argv, io) {
|
|
|
83863
84317
|
refs: "boolean"
|
|
83864
84318
|
});
|
|
83865
84319
|
if (typeof flags === "string")
|
|
83866
|
-
return
|
|
84320
|
+
return usage4(io, flags, CREATE_USAGE);
|
|
83867
84321
|
if (flags.positionals.length)
|
|
83868
|
-
return
|
|
84322
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, CREATE_USAGE);
|
|
83869
84323
|
const fill = flags.booleans.has("fill");
|
|
83870
84324
|
if (!fill && !flags.values.title)
|
|
83871
|
-
return
|
|
84325
|
+
return usage4(io, "pass --title <t> or --fill", CREATE_USAGE);
|
|
83872
84326
|
if (flags.values.body !== undefined && flags.values["body-file"] !== undefined)
|
|
83873
|
-
return
|
|
84327
|
+
return usage4(io, "pass --body or --body-file, not both", CREATE_USAGE);
|
|
83874
84328
|
let body = flags.values.body ?? null;
|
|
83875
84329
|
if (flags.values["body-file"] !== undefined) {
|
|
83876
84330
|
const read = readBodyFile(io, flags.values["body-file"]);
|
|
83877
84331
|
if (typeof read === "string")
|
|
83878
|
-
return
|
|
84332
|
+
return usage4(io, read, CREATE_USAGE);
|
|
83879
84333
|
body = read.body;
|
|
83880
84334
|
}
|
|
83881
84335
|
if (flags.values.base !== undefined && flags.values.track !== undefined)
|
|
83882
|
-
return
|
|
84336
|
+
return usage4(io, "pass --base or --track, not both (--track picks the base for you)", CREATE_USAGE);
|
|
83883
84337
|
let base = flags.values.base ?? null;
|
|
83884
84338
|
const branch = currentBranch(io.cwd);
|
|
83885
84339
|
const kind = branchKindOf(branch);
|
|
@@ -83910,7 +84364,7 @@ async function create4(argv, io) {
|
|
|
83910
84364
|
base = route.target;
|
|
83911
84365
|
}
|
|
83912
84366
|
if (!base)
|
|
83913
|
-
return
|
|
84367
|
+
return usage4(io, "no default target branch is configured; pass --base <b>", CREATE_USAGE);
|
|
83914
84368
|
const connected = connect(io, branch);
|
|
83915
84369
|
if (!connected.ok)
|
|
83916
84370
|
return forgeFail(io, connected);
|
|
@@ -83930,7 +84384,7 @@ async function create4(argv, io) {
|
|
|
83930
84384
|
forge: { kind: forge.kind, repo: forge.repo, host: forge.apiHost }
|
|
83931
84385
|
});
|
|
83932
84386
|
if (!planned.ok)
|
|
83933
|
-
return
|
|
84387
|
+
return usage4(io, planned.error, CREATE_USAGE);
|
|
83934
84388
|
const links = planned.data.links;
|
|
83935
84389
|
const actor = actorFromEnv(io.env);
|
|
83936
84390
|
const result = await createPullRequest(io.cwd, connected.data, {
|
|
@@ -83973,9 +84427,17 @@ async function create4(argv, io) {
|
|
|
83973
84427
|
...issueLines(links, opened, linked, backlinks, data.number),
|
|
83974
84428
|
...planned.data.warnings.map((warning) => `note: ${warning}`),
|
|
83975
84429
|
..."error" in data.recorded ? [`ledger: not recorded (${data.recorded.error})`] : [],
|
|
83976
|
-
`next: ${data.next}`
|
|
84430
|
+
`next: ${data.next}${endpointNote(io.cwd)}`
|
|
83977
84431
|
]);
|
|
83978
84432
|
}
|
|
84433
|
+
function endpointNote(cwd) {
|
|
84434
|
+
try {
|
|
84435
|
+
const line = endpointMismatch(resolveAutonomy(cwd));
|
|
84436
|
+
return line ? `; ${line}` : "";
|
|
84437
|
+
} catch {
|
|
84438
|
+
return "";
|
|
84439
|
+
}
|
|
84440
|
+
}
|
|
83979
84441
|
function issueLines(links, opened, linked, backlinks, number) {
|
|
83980
84442
|
if (links.length === 0)
|
|
83981
84443
|
return [];
|
|
@@ -83994,6 +84456,9 @@ async function merge3(argv, io) {
|
|
|
83994
84456
|
const flags = parseFlags(argv, {
|
|
83995
84457
|
pr: "value",
|
|
83996
84458
|
method: "value",
|
|
84459
|
+
squash: "boolean",
|
|
84460
|
+
merge: "boolean",
|
|
84461
|
+
rebase: "boolean",
|
|
83997
84462
|
"delete-branch": "boolean",
|
|
83998
84463
|
unverified: "boolean",
|
|
83999
84464
|
reason: "value",
|
|
@@ -84002,33 +84467,37 @@ async function merge3(argv, io) {
|
|
|
84002
84467
|
"body-file": "value"
|
|
84003
84468
|
});
|
|
84004
84469
|
if (typeof flags === "string")
|
|
84005
|
-
return
|
|
84470
|
+
return usage4(io, flags, MERGE_USAGE);
|
|
84006
84471
|
const unverified = unverifiedFlag(flags);
|
|
84007
84472
|
if (typeof unverified === "string")
|
|
84008
|
-
return
|
|
84473
|
+
return usage4(io, unverified, MERGE_USAGE);
|
|
84009
84474
|
if (flags.positionals.length)
|
|
84010
|
-
return
|
|
84011
|
-
const
|
|
84012
|
-
if (typeof
|
|
84013
|
-
return
|
|
84014
|
-
const
|
|
84475
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, MERGE_USAGE);
|
|
84476
|
+
const picked = selector(flags);
|
|
84477
|
+
if (typeof picked === "string")
|
|
84478
|
+
return usage4(io, picked, MERGE_USAGE);
|
|
84479
|
+
const { pr } = picked;
|
|
84480
|
+
const aliases = ["squash", "merge", "rebase"].filter((name) => flags.booleans.has(name));
|
|
84481
|
+
if (aliases.length > 1 || aliases.length === 1 && flags.values.method !== undefined)
|
|
84482
|
+
return usage4(io, "pass one of --squash, --merge, --rebase or --method", MERGE_USAGE);
|
|
84483
|
+
const method = aliases[0] ?? flags.values.method ?? "squash";
|
|
84015
84484
|
if (!METHODS2.has(method))
|
|
84016
|
-
return
|
|
84485
|
+
return usage4(io, "--method must be squash, merge or rebase", MERGE_USAGE);
|
|
84017
84486
|
const { subject } = flags.values;
|
|
84018
84487
|
if (flags.values.body !== undefined && flags.values["body-file"] !== undefined)
|
|
84019
|
-
return
|
|
84488
|
+
return usage4(io, "pass --body or --body-file, not both", MERGE_USAGE);
|
|
84020
84489
|
let body = flags.values.body;
|
|
84021
84490
|
if (flags.values["body-file"] !== undefined) {
|
|
84022
84491
|
const read = readBodyFile(io, flags.values["body-file"]);
|
|
84023
84492
|
if (typeof read === "string")
|
|
84024
|
-
return
|
|
84493
|
+
return usage4(io, read, MERGE_USAGE);
|
|
84025
84494
|
body = read.body;
|
|
84026
84495
|
}
|
|
84027
84496
|
if ((subject !== undefined || body !== undefined) && method !== "squash")
|
|
84028
|
-
return
|
|
84497
|
+
return usage4(io, "--subject and --body set a squash message; use --method squash", MERGE_USAGE);
|
|
84029
84498
|
if (subject !== undefined && (!subject.trim() || subject.includes(`
|
|
84030
84499
|
`)))
|
|
84031
|
-
return
|
|
84500
|
+
return usage4(io, "--subject must be one non-empty line", MERGE_USAGE);
|
|
84032
84501
|
const connected = connect(io);
|
|
84033
84502
|
if (!connected.ok)
|
|
84034
84503
|
return forgeFail(io, connected);
|
|
@@ -84060,12 +84529,13 @@ async function merge3(argv, io) {
|
|
|
84060
84529
|
async function ready(argv, io) {
|
|
84061
84530
|
const flags = parseFlags(argv, { pr: "value", undo: "boolean" });
|
|
84062
84531
|
if (typeof flags === "string")
|
|
84063
|
-
return
|
|
84532
|
+
return usage4(io, flags, READY_USAGE);
|
|
84064
84533
|
if (flags.positionals.length)
|
|
84065
|
-
return
|
|
84066
|
-
const
|
|
84067
|
-
if (typeof
|
|
84068
|
-
return
|
|
84534
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, READY_USAGE);
|
|
84535
|
+
const picked = selector(flags);
|
|
84536
|
+
if (typeof picked === "string")
|
|
84537
|
+
return usage4(io, picked, READY_USAGE);
|
|
84538
|
+
const { pr } = picked;
|
|
84069
84539
|
const connected = connect(io);
|
|
84070
84540
|
if (!connected.ok)
|
|
84071
84541
|
return forgeFail(io, connected);
|
|
@@ -84091,17 +84561,18 @@ async function edit(argv, io) {
|
|
|
84091
84561
|
"add-reviewer": "list"
|
|
84092
84562
|
});
|
|
84093
84563
|
if (typeof flags === "string")
|
|
84094
|
-
return
|
|
84564
|
+
return usage4(io, flags, EDIT_USAGE);
|
|
84095
84565
|
if (flags.positionals.length)
|
|
84096
|
-
return
|
|
84097
|
-
const
|
|
84098
|
-
if (typeof
|
|
84099
|
-
return
|
|
84566
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, EDIT_USAGE);
|
|
84567
|
+
const picked = selector(flags);
|
|
84568
|
+
if (typeof picked === "string")
|
|
84569
|
+
return usage4(io, picked, EDIT_USAGE);
|
|
84570
|
+
const { pr } = picked;
|
|
84100
84571
|
let body;
|
|
84101
84572
|
if (flags.values["body-file"] !== undefined) {
|
|
84102
84573
|
const read = readBodyFile(io, flags.values["body-file"]);
|
|
84103
84574
|
if (typeof read === "string")
|
|
84104
|
-
return
|
|
84575
|
+
return usage4(io, read, EDIT_USAGE);
|
|
84105
84576
|
body = read.body;
|
|
84106
84577
|
}
|
|
84107
84578
|
const connected = connect(io);
|
|
@@ -84119,7 +84590,7 @@ async function edit(argv, io) {
|
|
|
84119
84590
|
}
|
|
84120
84591
|
});
|
|
84121
84592
|
if (!result.ok)
|
|
84122
|
-
return result.code === "invalid_input" ?
|
|
84593
|
+
return result.code === "invalid_input" ? usage4(io, result.error, EDIT_USAGE) : forgeFail(io, result);
|
|
84123
84594
|
const kind = connected.data.forge.kind;
|
|
84124
84595
|
return emit(io, ok2(result.data), (data) => [
|
|
84125
84596
|
`edited ${prLabel(kind, data.number)} (${data.changed.join(", ")}): ${data.title} -> ${data.base} ${data.url}`
|
|
@@ -84128,12 +84599,13 @@ async function edit(argv, io) {
|
|
|
84128
84599
|
async function threads(argv, io) {
|
|
84129
84600
|
const flags = parseFlags(argv, { pr: "value" });
|
|
84130
84601
|
if (typeof flags === "string")
|
|
84131
|
-
return
|
|
84602
|
+
return usage4(io, flags, THREADS_USAGE);
|
|
84132
84603
|
if (flags.positionals.length)
|
|
84133
|
-
return
|
|
84134
|
-
const
|
|
84135
|
-
if (typeof
|
|
84136
|
-
return
|
|
84604
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, THREADS_USAGE);
|
|
84605
|
+
const picked = selector(flags);
|
|
84606
|
+
if (typeof picked === "string")
|
|
84607
|
+
return usage4(io, picked, THREADS_USAGE);
|
|
84608
|
+
const { pr } = picked;
|
|
84137
84609
|
const connected = connect(io);
|
|
84138
84610
|
if (!connected.ok)
|
|
84139
84611
|
return forgeFail(io, connected);
|
|
@@ -84154,20 +84626,21 @@ async function reply(argv, io) {
|
|
|
84154
84626
|
resolve: "boolean"
|
|
84155
84627
|
});
|
|
84156
84628
|
if (typeof flags === "string")
|
|
84157
|
-
return
|
|
84629
|
+
return usage4(io, flags, REPLY_USAGE);
|
|
84158
84630
|
if (flags.positionals.length)
|
|
84159
|
-
return
|
|
84160
|
-
const
|
|
84161
|
-
if (typeof
|
|
84162
|
-
return
|
|
84631
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, REPLY_USAGE);
|
|
84632
|
+
const picked = selector(flags);
|
|
84633
|
+
if (typeof picked === "string")
|
|
84634
|
+
return usage4(io, picked, REPLY_USAGE);
|
|
84635
|
+
const { pr } = picked;
|
|
84163
84636
|
const thread = flags.values.thread;
|
|
84164
84637
|
if (!thread)
|
|
84165
|
-
return
|
|
84638
|
+
return usage4(io, "--thread <id> is required (workit pr threads)", REPLY_USAGE);
|
|
84166
84639
|
let body = null;
|
|
84167
84640
|
if (flags.values["body-file"] !== undefined) {
|
|
84168
84641
|
const read = readBodyFile(io, flags.values["body-file"]);
|
|
84169
84642
|
if (typeof read === "string")
|
|
84170
|
-
return
|
|
84643
|
+
return usage4(io, read, REPLY_USAGE);
|
|
84171
84644
|
body = read.body;
|
|
84172
84645
|
}
|
|
84173
84646
|
const connected = connect(io);
|
|
@@ -84180,13 +84653,13 @@ async function reply(argv, io) {
|
|
|
84180
84653
|
resolve: flags.booleans.has("resolve")
|
|
84181
84654
|
});
|
|
84182
84655
|
if (!result.ok)
|
|
84183
|
-
return result.code === "invalid_input" ?
|
|
84656
|
+
return result.code === "invalid_input" ? usage4(io, result.error, REPLY_USAGE) : forgeFail(io, result);
|
|
84184
84657
|
const kind = connected.data.forge.kind;
|
|
84185
84658
|
return emit(io, ok2(result.data), (data) => [
|
|
84186
84659
|
`${[data.replied ? "replied to" : null, data.resolved ? "resolved" : null].filter(Boolean).join(" and ")} thread ${data.thread} on ${prLabel(kind, data.number)}${data.replyUrl ? ` ${data.replyUrl}` : ""}`
|
|
84187
84660
|
]);
|
|
84188
84661
|
}
|
|
84189
|
-
async function
|
|
84662
|
+
async function run15(argv, io) {
|
|
84190
84663
|
const [sub, ...rest] = argv;
|
|
84191
84664
|
if (sub === "status")
|
|
84192
84665
|
return status2(rest, io);
|
|
@@ -84202,10 +84675,11 @@ async function run14(argv, io) {
|
|
|
84202
84675
|
return threads(rest, io);
|
|
84203
84676
|
if (sub === "reply")
|
|
84204
84677
|
return reply(rest, io);
|
|
84205
|
-
return
|
|
84678
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown pr subcommand "${sub}"` : "missing pr subcommand", USAGE8);
|
|
84206
84679
|
}
|
|
84207
|
-
var STATUS_USAGE = "workit pr status [--pr <n> | --branch <b>] [--log-lines 60] [--json]", CREATE_USAGE = "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f|->] | --fill) [--issue <#n|ID|url>]… [--refs] [--label <l>]… [--reviewer <login>]… [--draft] [--json]", MERGE_USAGE = "workit pr merge [--pr <n>] [--method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch] [--unverified --reason <why>] [--json]", READY_USAGE = "workit pr ready [--pr <n>] [--undo] [--json]", EDIT_USAGE = "workit pr edit [--pr <n>] [--title <t>] [--body-file <f|->] [--add-label <l>]… [--remove-label <l>]… [--add-reviewer <login>]… [--base <b>] [--json]", THREADS_USAGE = "workit pr threads [--pr <n>] [--json]", REPLY_USAGE = "workit pr reply [--pr <n>] --thread <id> [--body-file <f|->] [--resolve] [--json]",
|
|
84680
|
+
var STATUS_USAGE = "workit pr status [--pr <n> | --branch <b>] [--log-lines 60] [--json]", CREATE_USAGE = "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f|->] | --fill) [--issue <#n|ID|url>]… [--refs] [--label <l>]… [--reviewer <login>]… [--draft] [--json]", MERGE_USAGE = "workit pr merge [--pr <n>] [--squash|--merge|--rebase | --method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch] [--unverified --reason <why>] [--json]", READY_USAGE = "workit pr ready [--pr <n>] [--undo] [--json]", EDIT_USAGE = "workit pr edit [--pr <n>] [--title <t>] [--body-file <f|->] [--add-label <l>]… [--remove-label <l>]… [--add-reviewer <login>]… [--base <b>] [--json]", THREADS_USAGE = "workit pr threads [--pr <n>] [--json]", REPLY_USAGE = "workit pr reply [--pr <n>] --thread <id> [--body-file <f|->] [--resolve] [--json]", USAGE8 = "workit pr status|create|merge|ready|edit|threads|reply ... (workit help pr)", prLabel = (kind, number) => `${kind === "github" ? "PR #" : "MR !"}${number}`, NEED_TEXT, mergedVerdictLine = (landed) => landed === "untracked" ? "merged outside workit (no merge record)" : landed.unverified ? `merged unverified at ${(landed.head ?? "?").slice(0, 12)} (recorded bypass)` : landed.lane === "none" && !landed.verdictId ? `merged at ${(landed.head ?? "?").slice(0, 12)} with no verdict (lane none)` : landed.review === "self-reviewed" ? `merged self-reviewed (lane self) with the author's verdict ${landed.verdictId ?? "?"} at ${(landed.head ?? "?").slice(0, 12)}` : `merged with accepted verdict ${landed.verdictId ?? "?"} at ${(landed.head ?? "?").slice(0, 12)}${landed.intentOnly ? " (merge intent recorded; the merge call itself failed)" : ""}`, acceptedHow = (verdict) => verdict.cover ? `stack verdict ${verdict.cover.verdictId} on ${verdict.cover.branch} @ ${verdict.cover.head.slice(0, 12)}` : verdict.carry ? carryLabel(verdict.carry) : verdict.basis, METHODS2;
|
|
84208
84681
|
var init_pr = __esm(() => {
|
|
84682
|
+
init_autonomy();
|
|
84209
84683
|
init_issue_link();
|
|
84210
84684
|
init_pr_edit();
|
|
84211
84685
|
init_pr_ops();
|
|
@@ -84230,7 +84704,7 @@ var init_pr = __esm(() => {
|
|
|
84230
84704
|
// packages/workit-cli/src/verbs/ci.ts
|
|
84231
84705
|
var exports_ci = {};
|
|
84232
84706
|
__export(exports_ci, {
|
|
84233
|
-
run: () =>
|
|
84707
|
+
run: () => run16
|
|
84234
84708
|
});
|
|
84235
84709
|
async function wait2(argv, io) {
|
|
84236
84710
|
const flags = parseFlags(argv, {
|
|
@@ -84241,23 +84715,23 @@ async function wait2(argv, io) {
|
|
|
84241
84715
|
interval: "value"
|
|
84242
84716
|
});
|
|
84243
84717
|
if (typeof flags === "string")
|
|
84244
|
-
return
|
|
84718
|
+
return usage4(io, flags, WAIT_USAGE);
|
|
84245
84719
|
if (flags.positionals.length)
|
|
84246
|
-
return
|
|
84720
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, WAIT_USAGE);
|
|
84247
84721
|
const pr = positiveInt(flags.values.pr, "--pr");
|
|
84248
84722
|
if (typeof pr === "string")
|
|
84249
|
-
return
|
|
84723
|
+
return usage4(io, pr, WAIT_USAGE);
|
|
84250
84724
|
const timeoutMs = parseDuration2(flags.values.timeout ?? "20m");
|
|
84251
84725
|
const intervalMs = parseDuration2(flags.values.interval ?? "30s");
|
|
84252
84726
|
if (timeoutMs === null || timeoutMs > 6 * 3600000)
|
|
84253
|
-
return
|
|
84727
|
+
return usage4(io, "--timeout must be a duration up to 6h (20m, 90s)", WAIT_USAGE);
|
|
84254
84728
|
if (intervalMs === null || intervalMs < 1000 || intervalMs > 600000)
|
|
84255
|
-
return
|
|
84729
|
+
return usage4(io, "--interval must be between 1s and 10m", WAIT_USAGE);
|
|
84256
84730
|
if (pr && flags.values.branch)
|
|
84257
|
-
return
|
|
84731
|
+
return usage4(io, "pass --pr or --branch, not both", WAIT_USAGE);
|
|
84258
84732
|
const head = flags.values.head ?? null;
|
|
84259
84733
|
if (head !== null && !/^[0-9a-f]{7,64}$/u.test(head))
|
|
84260
|
-
return
|
|
84734
|
+
return usage4(io, "--head must be a commit sha (7-64 hex chars)", WAIT_USAGE);
|
|
84261
84735
|
const started = forgeDeps.now();
|
|
84262
84736
|
const deadline = started + timeoutMs;
|
|
84263
84737
|
const connected = connect(io, flags.values.branch, {
|
|
@@ -84314,7 +84788,8 @@ async function wait2(argv, io) {
|
|
|
84314
84788
|
return forgeFail(io, built);
|
|
84315
84789
|
const doc = built.data;
|
|
84316
84790
|
const data = {
|
|
84317
|
-
state: verdict.state,
|
|
84791
|
+
state: verdict.state === "waiting" ? "in_progress" : verdict.state,
|
|
84792
|
+
...verdict.state === "failed" && doc.checks.pending.length > 0 ? { failFast: true, stillRunning: doc.checks.pending } : {},
|
|
84318
84793
|
reason: verdict.reason,
|
|
84319
84794
|
polls,
|
|
84320
84795
|
elapsedMs,
|
|
@@ -84352,20 +84827,20 @@ async function rerun(argv, io) {
|
|
|
84352
84827
|
force: "boolean"
|
|
84353
84828
|
});
|
|
84354
84829
|
if (typeof flags === "string")
|
|
84355
|
-
return
|
|
84830
|
+
return usage4(io, flags, RERUN_USAGE);
|
|
84356
84831
|
if (flags.positionals.length)
|
|
84357
|
-
return
|
|
84832
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, RERUN_USAGE);
|
|
84358
84833
|
const pr = positiveInt(flags.values.pr, "--pr");
|
|
84359
84834
|
if (typeof pr === "string")
|
|
84360
|
-
return
|
|
84835
|
+
return usage4(io, pr, RERUN_USAGE);
|
|
84361
84836
|
const names = flags.lists.check ?? [];
|
|
84362
84837
|
if (pr && flags.values.branch)
|
|
84363
|
-
return
|
|
84838
|
+
return usage4(io, "pass --pr or --branch, not both", RERUN_USAGE);
|
|
84364
84839
|
if (names.length && flags.booleans.has("failed"))
|
|
84365
|
-
return
|
|
84840
|
+
return usage4(io, "pass --check or --failed, not both", RERUN_USAGE);
|
|
84366
84841
|
const reason = flags.values.reason;
|
|
84367
84842
|
if (reason !== "flake" && reason !== "infra")
|
|
84368
|
-
return
|
|
84843
|
+
return usage4(io, "--reason flake|infra is required: rerun only what you judged a flake or an infrastructure failure", RERUN_USAGE);
|
|
84369
84844
|
const connected = connect(io, flags.values.branch);
|
|
84370
84845
|
if (!connected.ok)
|
|
84371
84846
|
return forgeFail(io, connected);
|
|
@@ -84402,16 +84877,16 @@ async function rerun(argv, io) {
|
|
|
84402
84877
|
async function logs(argv, io) {
|
|
84403
84878
|
const flags = parseFlags(argv, { pr: "value", branch: "value", failed: "boolean" });
|
|
84404
84879
|
if (typeof flags === "string")
|
|
84405
|
-
return
|
|
84880
|
+
return usage4(io, flags, LOGS_USAGE);
|
|
84406
84881
|
if (flags.positionals.length)
|
|
84407
|
-
return
|
|
84882
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, LOGS_USAGE);
|
|
84408
84883
|
if (!flags.booleans.has("failed"))
|
|
84409
|
-
return
|
|
84884
|
+
return usage4(io, "pass --failed: only the failing steps' tails are printed", LOGS_USAGE);
|
|
84410
84885
|
const pr = positiveInt(flags.values.pr, "--pr");
|
|
84411
84886
|
if (typeof pr === "string")
|
|
84412
|
-
return
|
|
84887
|
+
return usage4(io, pr, LOGS_USAGE);
|
|
84413
84888
|
if (pr && flags.values.branch)
|
|
84414
|
-
return
|
|
84889
|
+
return usage4(io, "pass --pr or --branch, not both", LOGS_USAGE);
|
|
84415
84890
|
const connected = connect(io, flags.values.branch);
|
|
84416
84891
|
if (!connected.ok)
|
|
84417
84892
|
return forgeFail(io, connected);
|
|
@@ -84446,7 +84921,7 @@ async function logs(argv, io) {
|
|
|
84446
84921
|
])
|
|
84447
84922
|
] : [`PR #${data.pr} head ${data.head.slice(0, 7)}: no failing checks`]);
|
|
84448
84923
|
}
|
|
84449
|
-
async function
|
|
84924
|
+
async function run16(argv, io) {
|
|
84450
84925
|
const [sub, ...rest] = argv;
|
|
84451
84926
|
if (sub === "wait")
|
|
84452
84927
|
return wait2(rest, io);
|
|
@@ -84454,7 +84929,7 @@ async function run15(argv, io) {
|
|
|
84454
84929
|
return rerun(rest, io);
|
|
84455
84930
|
if (sub === "logs")
|
|
84456
84931
|
return logs(rest, io);
|
|
84457
|
-
return
|
|
84932
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown ci subcommand "${sub}"` : "missing ci subcommand", `${WAIT_USAGE}
|
|
84458
84933
|
${RERUN_USAGE}
|
|
84459
84934
|
${LOGS_USAGE}`);
|
|
84460
84935
|
}
|
|
@@ -84497,7 +84972,7 @@ var init_implicit_task = __esm(() => {
|
|
|
84497
84972
|
// packages/workit-cli/src/verbs/git.ts
|
|
84498
84973
|
var exports_git = {};
|
|
84499
84974
|
__export(exports_git, {
|
|
84500
|
-
run: () =>
|
|
84975
|
+
run: () => run17
|
|
84501
84976
|
});
|
|
84502
84977
|
import { readFileSync as readFileSync25 } from "node:fs";
|
|
84503
84978
|
import path59 from "node:path";
|
|
@@ -84521,18 +84996,18 @@ async function branch(argv, io) {
|
|
|
84521
84996
|
carry: "boolean"
|
|
84522
84997
|
});
|
|
84523
84998
|
if (typeof flags === "string")
|
|
84524
|
-
return
|
|
84999
|
+
return usage4(io, flags, BRANCH_USAGE);
|
|
84525
85000
|
const { kind, slug } = flags.values;
|
|
84526
85001
|
if (flags.positionals.length > 1)
|
|
84527
|
-
return
|
|
85002
|
+
return usage4(io, `unexpected argument ${flags.positionals[1]}`, BRANCH_USAGE);
|
|
84528
85003
|
if (kind === undefined !== (slug === undefined))
|
|
84529
|
-
return
|
|
85004
|
+
return usage4(io, "--kind and --slug go together", BRANCH_USAGE);
|
|
84530
85005
|
if (kind !== undefined && !BRANCH_KINDS.includes(kind))
|
|
84531
|
-
return
|
|
85006
|
+
return usage4(io, `--kind must be ${BRANCH_KINDS.join(", ")}; ${kindHint(io.cwd, kind)}`, BRANCH_USAGE);
|
|
84532
85007
|
if (kind !== undefined && flags.positionals.length)
|
|
84533
|
-
return
|
|
85008
|
+
return usage4(io, "pass a name or --kind/--slug, not both", BRANCH_USAGE);
|
|
84534
85009
|
if (kind === undefined && !flags.positionals[0])
|
|
84535
|
-
return
|
|
85010
|
+
return usage4(io, "missing branch name", BRANCH_USAGE);
|
|
84536
85011
|
const result = gitBranch(io.cwd, {
|
|
84537
85012
|
...kind !== undefined ? { kind, slug } : { name: flags.positionals[0] },
|
|
84538
85013
|
base: flags.values.base ?? null,
|
|
@@ -84614,21 +85089,21 @@ function commitMessage(parsed, io) {
|
|
|
84614
85089
|
async function commit(argv, io) {
|
|
84615
85090
|
const parsed = parseCommit(argv);
|
|
84616
85091
|
if (typeof parsed === "string")
|
|
84617
|
-
return
|
|
85092
|
+
return usage4(io, parsed, COMMIT_USAGE);
|
|
84618
85093
|
if (parsed.all && parsed.paths.length)
|
|
84619
|
-
return
|
|
85094
|
+
return usage4(io, "pass --all or paths, not both", COMMIT_USAGE);
|
|
84620
85095
|
if (parsed.noEdit && !parsed.amend)
|
|
84621
|
-
return
|
|
85096
|
+
return usage4(io, "--no-edit only applies with --amend", COMMIT_USAGE);
|
|
84622
85097
|
const given = parsed.messages.length + parsed.files.length > 0;
|
|
84623
85098
|
if (parsed.noEdit && given)
|
|
84624
|
-
return
|
|
85099
|
+
return usage4(io, "--no-edit keeps the message; drop -m/-F or --no-edit", COMMIT_USAGE);
|
|
84625
85100
|
if (!given && !parsed.noEdit)
|
|
84626
|
-
return
|
|
85101
|
+
return usage4(io, parsed.amend ? "--amend needs -m/-F or --no-edit" : "missing -m <msg> or -F <file>", COMMIT_USAGE);
|
|
84627
85102
|
const message = given ? commitMessage(parsed, io) : null;
|
|
84628
85103
|
if (message !== null && typeof message !== "string")
|
|
84629
|
-
return
|
|
85104
|
+
return usage4(io, message.error, COMMIT_USAGE);
|
|
84630
85105
|
if (message !== null && !message.trim())
|
|
84631
|
-
return
|
|
85106
|
+
return usage4(io, "the commit message is empty", COMMIT_USAGE);
|
|
84632
85107
|
const result = gitCommit(io.cwd, {
|
|
84633
85108
|
message,
|
|
84634
85109
|
all: parsed.all,
|
|
@@ -84653,7 +85128,7 @@ async function commit(argv, io) {
|
|
|
84653
85128
|
}
|
|
84654
85129
|
async function push(argv, io) {
|
|
84655
85130
|
if (argv.includes("--force") || argv.includes("-f"))
|
|
84656
|
-
return
|
|
85131
|
+
return usage4(io, "workit never force-pushes blindly; use --force-with-lease (the lease is the tip workit last recorded)", PUSH_USAGE);
|
|
84657
85132
|
const normalized = argv.map((arg) => arg === "-u" ? "--set-upstream" : arg);
|
|
84658
85133
|
const flags = parseFlags(normalized, {
|
|
84659
85134
|
"set-upstream": "boolean",
|
|
@@ -84663,20 +85138,20 @@ async function push(argv, io) {
|
|
|
84663
85138
|
release: "list"
|
|
84664
85139
|
});
|
|
84665
85140
|
if (typeof flags === "string")
|
|
84666
|
-
return
|
|
85141
|
+
return usage4(io, flags, PUSH_USAGE);
|
|
84667
85142
|
const release = flags.lists.release;
|
|
84668
85143
|
if (release) {
|
|
84669
85144
|
if (flags.booleans.size || flags.values.expect !== undefined || flags.positionals.length)
|
|
84670
|
-
return
|
|
85145
|
+
return usage4(io, "--release takes only ref names (repeat it: --release main --release v1.2.0)", PUSH_USAGE);
|
|
84671
85146
|
return releasePush(release, io);
|
|
84672
85147
|
}
|
|
84673
85148
|
if (flags.positionals.length)
|
|
84674
|
-
return
|
|
85149
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]} (workit pushes the current branch)`, PUSH_USAGE);
|
|
84675
85150
|
const expect = flags.values.expect ?? null;
|
|
84676
85151
|
if ((expect !== null || flags.booleans.has("overwrite-unintegrated")) && !flags.booleans.has("force-with-lease"))
|
|
84677
|
-
return
|
|
85152
|
+
return usage4(io, "--expect and --overwrite-unintegrated only apply with --force-with-lease", PUSH_USAGE);
|
|
84678
85153
|
if (expect !== null && !/^[0-9a-f]{7,64}$/u.test(expect))
|
|
84679
|
-
return
|
|
85154
|
+
return usage4(io, "--expect must be a commit sha (at least 7 hex digits)", PUSH_USAGE);
|
|
84680
85155
|
const plan = pushPreflight(io.cwd);
|
|
84681
85156
|
if (!plan.ok)
|
|
84682
85157
|
return forgeFail(io, plan);
|
|
@@ -84711,7 +85186,7 @@ async function push(argv, io) {
|
|
|
84711
85186
|
`);
|
|
84712
85187
|
const envelope = ok2({ ...result.data, identity: checked });
|
|
84713
85188
|
return emit(io, warnings.length ? { ...envelope, warnings } : envelope, (data) => [
|
|
84714
|
-
data.pushed ? `pushed ${data.branch} ${short2(data.previous)} -> ${short2(data.sha)} to ${data.remote}${data.forced ? " (force-with-lease)" : ""}; remote tip verified` :
|
|
85189
|
+
data.pushed ? `pushed ${data.branch} ${short2(data.previous)} -> ${short2(data.sha)} to ${data.remote}${data.forced ? " (force-with-lease)" : ""}; remote tip verified` : `nothing to push: ${data.remote}/${data.branch} is already at ${short2(data.sha)}`,
|
|
84715
85190
|
...data.upstream ? [`upstream: ${data.remote}/${data.branch}`] : []
|
|
84716
85191
|
]);
|
|
84717
85192
|
}
|
|
@@ -84744,19 +85219,21 @@ async function releasePush(names, io) {
|
|
|
84744
85219
|
if (!result.ok)
|
|
84745
85220
|
return forgeFail(io, result);
|
|
84746
85221
|
return emit(io, ok2({ ...result.data, identity: checked }), (data) => [
|
|
84747
|
-
...data.refs.map((ref) => ref.pushed ? `pushed ${ref.name} ${short2(ref.previous)} -> ${short2(ref.sha)} to ${data.remote}; remote tip verified` :
|
|
85222
|
+
...data.refs.map((ref) => ref.pushed ? `pushed ${ref.name} ${short2(ref.previous)} -> ${short2(ref.sha)} to ${data.remote}; remote tip verified` : `nothing to push: ${data.remote} ${ref.name} is already at ${short2(ref.sha)}`),
|
|
84748
85223
|
..."error" in data.recorded ? [`ledger: not recorded (${data.recorded.error})`] : []
|
|
84749
85224
|
]);
|
|
84750
85225
|
}
|
|
84751
85226
|
function trailers(argv, io) {
|
|
84752
85227
|
const extra = argv.find((arg) => arg !== "--json");
|
|
84753
85228
|
if (extra !== undefined)
|
|
84754
|
-
return
|
|
85229
|
+
return usage4(io, `unexpected argument ${extra}`, "workit git trailers");
|
|
84755
85230
|
const state = workspaceTrailers(io.cwd);
|
|
84756
85231
|
return emit(io, ok2(state), (data) => data.enabled ? "on" : "off");
|
|
84757
85232
|
}
|
|
84758
|
-
async function
|
|
85233
|
+
async function run17(argv, io) {
|
|
84759
85234
|
const [sub, ...rest] = argv;
|
|
85235
|
+
if (sub !== undefined && READ_ONLY.has(sub))
|
|
85236
|
+
return usage4(io, `workit git has no ${sub}`, `read-only git is fine raw: \`git -C ${io.cwd} ${sub}\``);
|
|
84760
85237
|
if (sub === "branch")
|
|
84761
85238
|
return branch(rest, io);
|
|
84762
85239
|
if (sub === "commit")
|
|
@@ -84765,9 +85242,9 @@ async function run16(argv, io) {
|
|
|
84765
85242
|
return push(rest, io);
|
|
84766
85243
|
if (sub === "trailers")
|
|
84767
85244
|
return trailers(rest, io);
|
|
84768
|
-
return
|
|
85245
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown git subcommand "${sub}"` : "missing git subcommand", USAGE9);
|
|
84769
85246
|
}
|
|
84770
|
-
var BRANCH_USAGE = "workit git branch <name> | --kind feature|bugfix|release|hotfix --slug <s> [--base <b>] [--track <t>] [--carry] [--json]", COMMIT_USAGE = "workit git commit -m|--message <msg>… | -F|--file <file|-> [--trailer <key: value>]… [--amend [--no-edit]] [--allow-empty] [-a|--all | [--] <paths…>] [--json]", PUSH_USAGE = "workit git push [--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--release <main|develop|v-tag>…] [--json]",
|
|
85247
|
+
var BRANCH_USAGE = "workit git branch <name> | --kind feature|bugfix|release|hotfix --slug <s> [--base <b>] [--track <t>] [--carry] [--json]", COMMIT_USAGE = "workit git commit -m|--message <msg>… | -F|--file <file|-> [--trailer <key: value>]… [--amend [--no-edit]] [--allow-empty] [-a|--all | [--] <paths…>] [--json]", PUSH_USAGE = "workit git push [--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--release <main|develop|v-tag>…] [--json]", USAGE9 = "workit git branch|commit|push|trailers ... (workit help git)", short2 = (sha) => sha ? sha.slice(0, 12) : "(none)", COMMIT_SWITCHES, READ_ONLY;
|
|
84771
85248
|
var init_git2 = __esm(() => {
|
|
84772
85249
|
init_autonomy();
|
|
84773
85250
|
init_branch();
|
|
@@ -84784,6 +85261,7 @@ var init_git2 = __esm(() => {
|
|
|
84784
85261
|
"--no-edit": "noEdit",
|
|
84785
85262
|
"--allow-empty": "allowEmpty"
|
|
84786
85263
|
};
|
|
85264
|
+
READ_ONLY = new Set(["status", "diff", "log", "fetch", "show", "blame"]);
|
|
84787
85265
|
});
|
|
84788
85266
|
|
|
84789
85267
|
// packages/workit-core/src/forge/verify.ts
|
|
@@ -85448,7 +85926,7 @@ var init_release = __esm(() => {
|
|
|
85448
85926
|
// packages/workit-cli/src/verbs/release.ts
|
|
85449
85927
|
var exports_release = {};
|
|
85450
85928
|
__export(exports_release, {
|
|
85451
|
-
run: () =>
|
|
85929
|
+
run: () => run18
|
|
85452
85930
|
});
|
|
85453
85931
|
async function subVerb(load, argv, io) {
|
|
85454
85932
|
let out = "";
|
|
@@ -85469,9 +85947,9 @@ async function subVerb(load, argv, io) {
|
|
|
85469
85947
|
async function start(argv, io) {
|
|
85470
85948
|
const flags = parseFlags(argv, { hotfix: "boolean", track: "value" });
|
|
85471
85949
|
if (typeof flags === "string")
|
|
85472
|
-
return
|
|
85950
|
+
return usage4(io, flags, START_USAGE);
|
|
85473
85951
|
if (flags.positionals.length !== 1)
|
|
85474
|
-
return
|
|
85952
|
+
return usage4(io, flags.positionals.length ? "pass one version" : "missing <version>", START_USAGE);
|
|
85475
85953
|
const result = releaseStart(io.cwd, {
|
|
85476
85954
|
version: flags.positionals[0],
|
|
85477
85955
|
hotfix: flags.booleans.has("hotfix"),
|
|
@@ -85524,9 +86002,9 @@ async function releasePr(io, plan, dryRun) {
|
|
|
85524
86002
|
async function finish2(argv, io) {
|
|
85525
86003
|
const flags = parseFlags(argv, { track: "value", "dry-run": "boolean" });
|
|
85526
86004
|
if (typeof flags === "string")
|
|
85527
|
-
return
|
|
86005
|
+
return usage4(io, flags, FINISH_USAGE);
|
|
85528
86006
|
if (flags.positionals.length > 1)
|
|
85529
|
-
return
|
|
86007
|
+
return usage4(io, `unexpected argument ${flags.positionals[1]}`, FINISH_USAGE);
|
|
85530
86008
|
const dryRun = flags.booleans.has("dry-run");
|
|
85531
86009
|
const planned = planReleaseFinish(io.cwd, {
|
|
85532
86010
|
version: flags.positionals[0] ?? null,
|
|
@@ -85636,9 +86114,9 @@ async function finish2(argv, io) {
|
|
|
85636
86114
|
async function publish(argv, io) {
|
|
85637
86115
|
const flags = parseFlags(argv, {});
|
|
85638
86116
|
if (typeof flags === "string")
|
|
85639
|
-
return
|
|
86117
|
+
return usage4(io, flags, PUBLISH_USAGE);
|
|
85640
86118
|
if (flags.positionals.length > 1)
|
|
85641
|
-
return
|
|
86119
|
+
return usage4(io, `unexpected argument ${flags.positionals[1]}`, PUBLISH_USAGE);
|
|
85642
86120
|
const located = releaseToPublish(io.cwd, flags.positionals[0] ?? null);
|
|
85643
86121
|
if (!located.ok)
|
|
85644
86122
|
return forgeFail(io, located);
|
|
@@ -85671,7 +86149,7 @@ async function publish(argv, io) {
|
|
|
85671
86149
|
`published ${data.branch} (${short4(data.sha)}) to ${data.remote}; remote tip verified`
|
|
85672
86150
|
]);
|
|
85673
86151
|
}
|
|
85674
|
-
async function
|
|
86152
|
+
async function run18(argv, io) {
|
|
85675
86153
|
const [sub, ...rest] = argv;
|
|
85676
86154
|
if (sub === "start")
|
|
85677
86155
|
return start(rest, io);
|
|
@@ -85679,9 +86157,9 @@ async function run17(argv, io) {
|
|
|
85679
86157
|
return finish2(rest, io);
|
|
85680
86158
|
if (sub === "publish")
|
|
85681
86159
|
return publish(rest, io);
|
|
85682
|
-
return
|
|
86160
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown release subcommand "${sub}"` : "missing release subcommand", USAGE10);
|
|
85683
86161
|
}
|
|
85684
|
-
var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--json]", FINISH_USAGE = "workit release finish [<version>] [--track <t>] [--dry-run] [--json]", PUBLISH_USAGE = "workit release publish [<version>] [--json]",
|
|
86162
|
+
var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--json]", FINISH_USAGE = "workit release finish [<version>] [--track <t>] [--dry-run] [--json]", PUBLISH_USAGE = "workit release publish [<version>] [--json]", USAGE10 = "workit release start|finish|publish ... (workit help release)", short4 = (sha) => sha ? sha.slice(0, 12) : "(none)", blocked = (io, grant) => emit(io, fail2("blocked", grant.error, { unblock: grant.unblock, data: { reason: grant.reason } })), isLocalRemote = (cwd, remote) => {
|
|
85685
86163
|
const url = remote ? pushUrl(cwd, remote) : null;
|
|
85686
86164
|
return !url || parseRemoteUrl(url)?.protocol === "file";
|
|
85687
86165
|
}, stepsOf = (plan) => [
|
|
@@ -85713,9 +86191,9 @@ var init_release2 = __esm(() => {
|
|
|
85713
86191
|
// packages/workit-cli/src/verbs/verify-delivery.ts
|
|
85714
86192
|
var exports_verify_delivery = {};
|
|
85715
86193
|
__export(exports_verify_delivery, {
|
|
85716
|
-
run: () =>
|
|
86194
|
+
run: () => run19
|
|
85717
86195
|
});
|
|
85718
|
-
async function
|
|
86196
|
+
async function run19(argv, io) {
|
|
85719
86197
|
const flags = parseFlags(argv, {
|
|
85720
86198
|
expect: "value",
|
|
85721
86199
|
branch: "value",
|
|
@@ -85725,31 +86203,31 @@ async function run18(argv, io) {
|
|
|
85725
86203
|
package: "value"
|
|
85726
86204
|
});
|
|
85727
86205
|
if (typeof flags === "string")
|
|
85728
|
-
return
|
|
86206
|
+
return usage4(io, flags, USAGE11);
|
|
85729
86207
|
if (flags.positionals.length > 1)
|
|
85730
|
-
return
|
|
86208
|
+
return usage4(io, `unexpected argument ${flags.positionals[1]}`, USAGE11);
|
|
85731
86209
|
const named = flags.positionals[0];
|
|
85732
86210
|
if (named !== undefined && !ENDPOINTS[named])
|
|
85733
|
-
return
|
|
86211
|
+
return usage4(io, `unknown endpoint "${named}"`, USAGE11);
|
|
85734
86212
|
if (flags.values.expect !== undefined && !ENDPOINTS[flags.values.expect])
|
|
85735
|
-
return
|
|
86213
|
+
return usage4(io, "--expect must be pushed, pr, merged or released", USAGE11);
|
|
85736
86214
|
if (named && flags.values.expect && ENDPOINTS[named] !== ENDPOINTS[flags.values.expect])
|
|
85737
|
-
return
|
|
86215
|
+
return usage4(io, `${named} and --expect ${flags.values.expect} disagree`, USAGE11);
|
|
85738
86216
|
const expect = ENDPOINTS[named ?? ""] ?? ENDPOINTS[flags.values.expect ?? ""] ?? (flags.values.tag || flags.values.package ? "released" : flags.values.pr ? "pr" : "pushed");
|
|
85739
86217
|
const pr = positiveInt(flags.values.pr, "--pr");
|
|
85740
86218
|
if (typeof pr === "string")
|
|
85741
|
-
return
|
|
86219
|
+
return usage4(io, pr, USAGE11);
|
|
85742
86220
|
if (pr && flags.values.branch)
|
|
85743
|
-
return
|
|
86221
|
+
return usage4(io, "pass --pr or --branch, not both", USAGE11);
|
|
85744
86222
|
const sha = flags.values.sha ?? null;
|
|
85745
86223
|
if (sha !== null && !/^[0-9a-f]{7,64}$/u.test(sha))
|
|
85746
|
-
return
|
|
86224
|
+
return usage4(io, "--sha must be a commit sha (7-64 hex chars)", USAGE11);
|
|
85747
86225
|
const actor = actorFromEnv(io.env);
|
|
85748
86226
|
const branch = flags.values.branch ?? null;
|
|
85749
86227
|
let result;
|
|
85750
86228
|
if (expect === "pushed") {
|
|
85751
86229
|
if (pr)
|
|
85752
|
-
return
|
|
86230
|
+
return usage4(io, "push is checked by --branch, not --pr", USAGE11);
|
|
85753
86231
|
result = verifyPushed(io.cwd, { branch, sha, actor });
|
|
85754
86232
|
} else if (expect === "released") {
|
|
85755
86233
|
result = verifyReleased(io.cwd, { tag: flags.values.tag ?? null, pkg: flags.values.package ?? null, sha, actor }, forgeDeps.npm);
|
|
@@ -85774,7 +86252,7 @@ async function run18(argv, io) {
|
|
|
85774
86252
|
unblock: expect === "pushed" ? "workit git push" : expect === "pr" ? "workit git push && workit pr create --fill" : expect === "merged" ? "workit pr status # then workit pr merge when READY and granted" : "check the release workflow; the tag/package is not published"
|
|
85775
86253
|
}));
|
|
85776
86254
|
}
|
|
85777
|
-
var
|
|
86255
|
+
var USAGE11 = "workit verify-delivery [push|pr|merge|release] [--expect pushed|pr|merged|released] [--branch <b>] [--pr <n>] [--sha <sha>] [--tag <t>] [--package <name[@version]>] [--json]", ENDPOINTS, render2 = (report) => [
|
|
85778
86256
|
`${report.expect}: ${report.delivered ? "delivered" : "NOT delivered"}${report.branch ? ` (${report.branch}${report.sha ? ` @ ${report.sha.slice(0, 12)}` : ""})` : ""}${report.pr ? ` #${report.pr}` : ""}`,
|
|
85779
86257
|
...report.observations.map((entry) => ` ${entry.ok ? "ok" : "x "} ${entry.kind}: expected ${entry.expected ?? "-"}, observed ${entry.observed ?? "(none)"}${entry.note ? ` — ${entry.note}` : ""}`)
|
|
85780
86258
|
];
|
|
@@ -85797,12 +86275,12 @@ var init_verify_delivery = __esm(() => {
|
|
|
85797
86275
|
// packages/workit-cli/src/verbs/stack.ts
|
|
85798
86276
|
var exports_stack = {};
|
|
85799
86277
|
__export(exports_stack, {
|
|
85800
|
-
run: () =>
|
|
86278
|
+
run: () => run20
|
|
85801
86279
|
});
|
|
85802
86280
|
async function plan(argv, io) {
|
|
85803
86281
|
const flags = parseFlags(argv, { name: "value", trunk: "value", track: "value" });
|
|
85804
86282
|
if (typeof flags === "string")
|
|
85805
|
-
return
|
|
86283
|
+
return usage4(io, flags, PLAN_USAGE);
|
|
85806
86284
|
const name = flags.values.name ?? null;
|
|
85807
86285
|
const existingByName = name ? readStack(io.cwd, name) : null;
|
|
85808
86286
|
if (existingByName && !existingByName.ok)
|
|
@@ -85815,7 +86293,7 @@ async function plan(argv, io) {
|
|
|
85815
86293
|
}
|
|
85816
86294
|
const track = flags.values.track ?? null;
|
|
85817
86295
|
if (track !== null && flags.values.trunk !== undefined)
|
|
85818
|
-
return
|
|
86296
|
+
return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE);
|
|
85819
86297
|
let trunk = flags.values.trunk ?? existing?.trunk ?? null;
|
|
85820
86298
|
if (trunk === null || track !== null) {
|
|
85821
86299
|
const derived = releaseTrunk(io, track, flags.positionals[0] ?? null);
|
|
@@ -85852,9 +86330,9 @@ async function plan(argv, io) {
|
|
|
85852
86330
|
async function status3(argv, io) {
|
|
85853
86331
|
const flags = parseFlags(argv, { name: "value" });
|
|
85854
86332
|
if (typeof flags === "string")
|
|
85855
|
-
return
|
|
86333
|
+
return usage4(io, flags, STATUS_USAGE2);
|
|
85856
86334
|
if (flags.positionals.length)
|
|
85857
|
-
return
|
|
86335
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, STATUS_USAGE2);
|
|
85858
86336
|
const selected = selectStack(io.cwd, flags.values.name ?? null);
|
|
85859
86337
|
if (!selected.ok)
|
|
85860
86338
|
return stackFailed(io, selected);
|
|
@@ -85878,16 +86356,16 @@ async function sync(argv, io) {
|
|
|
85878
86356
|
force: "list"
|
|
85879
86357
|
});
|
|
85880
86358
|
if (typeof flags === "string")
|
|
85881
|
-
return
|
|
86359
|
+
return usage4(io, flags, SYNC_USAGE);
|
|
85882
86360
|
if (flags.positionals.length)
|
|
85883
|
-
return
|
|
86361
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, SYNC_USAGE);
|
|
85884
86362
|
const selected = selectStack(io.cwd, flags.values.name ?? null);
|
|
85885
86363
|
if (!selected.ok)
|
|
85886
86364
|
return stackFailed(io, selected);
|
|
85887
86365
|
const force = new Set(flags.lists.force ?? []);
|
|
85888
86366
|
const unknown = [...force].filter((branch) => !selected.data.branches.some((entry) => entry.branch === branch));
|
|
85889
86367
|
if (unknown.length)
|
|
85890
|
-
return
|
|
86368
|
+
return usage4(io, `--force ${unknown[0]}: not a branch of stack ${selected.data.name}`, SYNC_USAGE);
|
|
85891
86369
|
const local = flags.booleans.has("local");
|
|
85892
86370
|
let ctx = null;
|
|
85893
86371
|
if (!local) {
|
|
@@ -85928,24 +86406,24 @@ async function land(argv, io) {
|
|
|
85928
86406
|
reason: "value"
|
|
85929
86407
|
});
|
|
85930
86408
|
if (typeof flags === "string")
|
|
85931
|
-
return
|
|
86409
|
+
return usage4(io, flags, LAND_USAGE);
|
|
85932
86410
|
const unverified = unverifiedFlag(flags);
|
|
85933
86411
|
if (typeof unverified === "string")
|
|
85934
|
-
return
|
|
86412
|
+
return usage4(io, unverified, LAND_USAGE);
|
|
85935
86413
|
if (flags.positionals.length)
|
|
85936
|
-
return
|
|
86414
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, LAND_USAGE);
|
|
85937
86415
|
const max = positiveInt(flags.values.max, "--max");
|
|
85938
86416
|
if (typeof max === "string")
|
|
85939
|
-
return
|
|
86417
|
+
return usage4(io, max, LAND_USAGE);
|
|
85940
86418
|
const method = flags.values.method ?? "squash";
|
|
85941
86419
|
if (!METHODS3.has(method))
|
|
85942
|
-
return
|
|
86420
|
+
return usage4(io, "--method must be squash, merge or rebase", LAND_USAGE);
|
|
85943
86421
|
const timeoutMs = parseDuration2(flags.values.timeout ?? "20m");
|
|
85944
86422
|
const intervalMs = parseDuration2(flags.values.interval ?? "30s");
|
|
85945
86423
|
if (timeoutMs === null || timeoutMs > 6 * 3600000)
|
|
85946
|
-
return
|
|
86424
|
+
return usage4(io, "--timeout must be a duration up to 6h (20m, 90s)", LAND_USAGE);
|
|
85947
86425
|
if (intervalMs === null || intervalMs < 1000 || intervalMs > 600000)
|
|
85948
|
-
return
|
|
86426
|
+
return usage4(io, "--interval must be between 1s and 10m", LAND_USAGE);
|
|
85949
86427
|
const selected = selectStack(io.cwd, flags.values.name ?? null);
|
|
85950
86428
|
if (!selected.ok)
|
|
85951
86429
|
return stackFailed(io, selected);
|
|
@@ -85979,7 +86457,7 @@ async function land(argv, io) {
|
|
|
85979
86457
|
unblock: ${data.stoppedAt.unblock}` : data.complete ? "stack complete" : ""
|
|
85980
86458
|
].filter(Boolean));
|
|
85981
86459
|
}
|
|
85982
|
-
async function
|
|
86460
|
+
async function run20(argv, io) {
|
|
85983
86461
|
const [sub, ...rest] = argv.filter((arg) => arg !== "--json");
|
|
85984
86462
|
if (sub === "plan")
|
|
85985
86463
|
return plan(rest, io);
|
|
@@ -85989,9 +86467,9 @@ async function run19(argv, io) {
|
|
|
85989
86467
|
return sync(rest, io);
|
|
85990
86468
|
if (sub === "land")
|
|
85991
86469
|
return land(rest, io);
|
|
85992
|
-
return
|
|
86470
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown stack subcommand "${sub}"` : "missing stack subcommand", USAGE12);
|
|
85993
86471
|
}
|
|
85994
|
-
var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<bottom> … <top>] [--json]", STATUS_USAGE2 = "workit stack status [--name <n>] [--json]", SYNC_USAGE = "workit stack sync [--name <n>] [--local] [--dry-run] [--force <branch>]… [--json]", LAND_USAGE = "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s] [--json]",
|
|
86472
|
+
var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<bottom> … <top>] [--json]", STATUS_USAGE2 = "workit stack status [--name <n>] [--json]", SYNC_USAGE = "workit stack sync [--name <n>] [--local] [--dry-run] [--force <branch>]… [--json]", LAND_USAGE = "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s] [--json]", USAGE12 = "workit stack plan|status|sync|land ... (workit help stack)", short5 = (sha) => sha ? sha.slice(0, 12) : "?", stackFailed = (io, result) => emit(io, fail2(result.code, result.error, { unblock: result.unblock, data: result.data ?? {} })), label3 = (forge, pr) => pr === null ? "no PR" : `${forge === "gitlab" ? "MR !" : "PR #"}${pr}`, renderSync = (data) => [
|
|
85995
86473
|
`${data.dryRun ? "would sync" : "synced"} stack ${data.name}${data.merged.length ? `; merged: ${data.merged.map((item) => item.branch).join(", ")}` : ""}`,
|
|
85996
86474
|
...data.steps.map((step) => [
|
|
85997
86475
|
` ${step.branch} on ${step.parent}:`,
|
|
@@ -86425,7 +86903,8 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
86425
86903
|
planCreatedAt: plan.createdAt,
|
|
86426
86904
|
sliceHash: slice.hash,
|
|
86427
86905
|
...admin ? { adminId: admin.id, adminIno: admin.ino, adminToken: admin.token } : {},
|
|
86428
|
-
...baseSha ? { baseSha } : {}
|
|
86906
|
+
...baseSha ? { baseSha } : {},
|
|
86907
|
+
...deps.install ? { install: deps.install } : {}
|
|
86429
86908
|
});
|
|
86430
86909
|
return {
|
|
86431
86910
|
ok: true,
|
|
@@ -86608,6 +87087,8 @@ var init_fanout_worktree = __esm(() => {
|
|
|
86608
87087
|
|
|
86609
87088
|
// packages/workit-core/src/fanout-brief.ts
|
|
86610
87089
|
import { createHash as createHash19 } from "node:crypto";
|
|
87090
|
+
import fs34 from "node:fs";
|
|
87091
|
+
import path63 from "node:path";
|
|
86611
87092
|
function workerSession(lead, slice, attempt) {
|
|
86612
87093
|
const tail = attempt === null ? "" : `+try${attempt}`;
|
|
86613
87094
|
const full = `${lead}-w-${slice}${tail}`;
|
|
@@ -86631,10 +87112,12 @@ function renderBrief(cwd, plan, input) {
|
|
|
86631
87112
|
if (taken)
|
|
86632
87113
|
return fanoutFail("invalid_input", `attempt branch ${branch} is slice ${taken.id}'s branch`, "pick another --attempt number, or rename one of the branches in the plan");
|
|
86633
87114
|
const head = branchRef(cwd, branch);
|
|
86634
|
-
const
|
|
87115
|
+
const planned = `${slicePath(cwd, slice)}${input.attempt === null ? "" : `+try${input.attempt}`}`;
|
|
87116
|
+
const made = ledger.value.rows.findLast((row) => row.type === "fanout.worktree.created" && row.fanout === plan.name && row.slice === slice.id && typeof row.path === "string" && samePath(row.path, planned));
|
|
87117
|
+
const fresh = Boolean(head) && made?.baseSha === head;
|
|
87118
|
+
const mode = input.mode ?? (head && !fresh ? "resume" : "new");
|
|
86635
87119
|
if (mode === "resume" && !head)
|
|
86636
87120
|
return fanoutFail("not_found", `MODE resume needs the branch ${branch}, which does not exist here`, `workit fanout brief ${slice.id} --mode new`);
|
|
86637
|
-
const planned = `${slicePath(cwd, slice)}${input.attempt === null ? "" : `+try${input.attempt}`}`;
|
|
86638
87121
|
const exists = listWorktrees(cwd).some((entry) => samePath(entry.path, planned));
|
|
86639
87122
|
excludeScratch(cwd);
|
|
86640
87123
|
const scratch = exists ? `${planned}/${SCRATCH_DIR}` : SCRATCH_DIR;
|
|
@@ -86687,6 +87170,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
86687
87170
|
"STANDING:",
|
|
86688
87171
|
...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
|
|
86689
87172
|
exists ? `WORKTREE: ${planned} (made by \`workit fanout worktree create ${slice.id}\`; yours alone)` : `WORKTREE: ${planned} (not made yet: the lead runs \`workit fanout worktree create ${slice.id}\` before spawning, then renders this brief again)`,
|
|
87173
|
+
...exists && typeof made?.install === "string" && !fs34.existsSync(path63.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
|
|
86690
87174
|
...identityLines(identity, minted),
|
|
86691
87175
|
...rules(mode, branch, slice.base, exists ? planned : null)
|
|
86692
87176
|
];
|
|
@@ -86755,7 +87239,8 @@ var init_fanout_brief = __esm(() => {
|
|
|
86755
87239
|
REPORT = [
|
|
86756
87240
|
"REPORT: branch, head SHA, files changed, each VERIFY command with its exit code,",
|
|
86757
87241
|
" each ACCEPTANCE line met / not met, rulings you made (`workit ledger ruling`),",
|
|
86758
|
-
" anything out of scope as a follow-up, not a diff."
|
|
87242
|
+
" anything out of scope as a follow-up, not a diff. Report heads when pushed; CI is waited on once, at the end.",
|
|
87243
|
+
" A PR body goes through `--body-file -` (stdin), never a shared scratch path."
|
|
86759
87244
|
];
|
|
86760
87245
|
});
|
|
86761
87246
|
|
|
@@ -87423,10 +87908,10 @@ var init_fanout_status = __esm(() => {
|
|
|
87423
87908
|
// packages/workit-cli/src/verbs/fanout.ts
|
|
87424
87909
|
var exports_fanout = {};
|
|
87425
87910
|
__export(exports_fanout, {
|
|
87426
|
-
run: () =>
|
|
87911
|
+
run: () => run21
|
|
87427
87912
|
});
|
|
87428
|
-
import
|
|
87429
|
-
import
|
|
87913
|
+
import fs35 from "node:fs";
|
|
87914
|
+
import path64 from "node:path";
|
|
87430
87915
|
function forgeFor(io, offline) {
|
|
87431
87916
|
if (offline)
|
|
87432
87917
|
return { forge: null, error: "--offline" };
|
|
@@ -87469,7 +87954,7 @@ function resolveTrunk(io, raw, flag, track) {
|
|
|
87469
87954
|
};
|
|
87470
87955
|
if (named !== null && derived.trunk !== named)
|
|
87471
87956
|
return {
|
|
87472
|
-
code:
|
|
87957
|
+
code: usage4(io, `the plan names trunk ${named}; --track ${track} targets ${derived.trunk ?? "(none)"}`, PLAN_USAGE2)
|
|
87473
87958
|
};
|
|
87474
87959
|
return { trunk: derived.tracked || track !== null ? derived.trunk : null };
|
|
87475
87960
|
}
|
|
@@ -87481,18 +87966,18 @@ function plan2(argv, io) {
|
|
|
87481
87966
|
"take-lead": "boolean"
|
|
87482
87967
|
});
|
|
87483
87968
|
if (typeof flags === "string")
|
|
87484
|
-
return
|
|
87969
|
+
return usage4(io, flags, PLAN_USAGE2);
|
|
87485
87970
|
const track = flags.values.track ?? null;
|
|
87486
87971
|
if (track !== null && flags.values.trunk !== undefined)
|
|
87487
|
-
return
|
|
87972
|
+
return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
87488
87973
|
if (flags.positionals.length !== 1)
|
|
87489
|
-
return
|
|
87490
|
-
const file =
|
|
87974
|
+
return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
87975
|
+
const file = path64.resolve(io.cwd, flags.positionals[0]);
|
|
87491
87976
|
let raw;
|
|
87492
87977
|
try {
|
|
87493
|
-
raw = JSON.parse(
|
|
87978
|
+
raw = JSON.parse(fs35.readFileSync(file, "utf8"));
|
|
87494
87979
|
} catch (error) {
|
|
87495
|
-
return
|
|
87980
|
+
return usage4(io, `cannot read ${file} as JSON: ${error.message}`, PLAN_USAGE2);
|
|
87496
87981
|
}
|
|
87497
87982
|
const trunk = resolveTrunk(io, raw, flags.values.trunk ?? null, track);
|
|
87498
87983
|
if ("code" in trunk)
|
|
@@ -87513,7 +87998,7 @@ function plan2(argv, io) {
|
|
|
87513
87998
|
`${data.created ? "planned" : "re-planned"} fanout ${data.name} on ${data.trunk}${data.fanIn === "integration" ? " (integration branch: one PR)" : ""}: ${data.slices.length} slice${data.slices.length === 1 ? "" : "s"}`,
|
|
87514
87999
|
...data.slices.map((slice) => ` ${slice.id} [${slice.tier}] ${slice.branch} <- ${slice.base}${slice.dependsOn.length ? ` after ${slice.dependsOn.join(", ")}` : ""}
|
|
87515
88000
|
worktree ${slice.worktree}`),
|
|
87516
|
-
...data.overlaps.map((overlap) => ` shared ${overlap.path}: ${overlap.resolution === "owner" ? `owned by ${overlap.owner}` : `serialized (${overlap.slices.join(" -> ")})`}`),
|
|
88001
|
+
...data.overlaps.map((overlap) => ` shared ${overlap.path}: ${overlap.resolution === "owner" ? `owned by ${overlap.owner}` : overlap.resolution === "regenerated" ? `regenerated at fan-in (${overlap.writer})` : `serialized (${overlap.slices.join(" -> ")})`}`),
|
|
87517
88002
|
`waves: ${data.waves.map((wave) => wave.join(", ")).join(" | ")}`,
|
|
87518
88003
|
`landing order: ${data.landingOrder.join(", ")}`,
|
|
87519
88004
|
...data.notes.map((note) => `note: ${note}`),
|
|
@@ -87523,16 +88008,16 @@ function plan2(argv, io) {
|
|
|
87523
88008
|
function brief(argv, io) {
|
|
87524
88009
|
const flags = parseFlags(argv, { name: "value", mode: "value", attempt: "value" });
|
|
87525
88010
|
if (typeof flags === "string")
|
|
87526
|
-
return
|
|
88011
|
+
return usage4(io, flags, BRIEF_USAGE);
|
|
87527
88012
|
if (flags.positionals.length !== 1)
|
|
87528
|
-
return
|
|
88013
|
+
return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <slice>", BRIEF_USAGE);
|
|
87529
88014
|
const mode = flags.values.mode ?? null;
|
|
87530
88015
|
if (mode !== null && mode !== "new" && mode !== "resume")
|
|
87531
|
-
return
|
|
88016
|
+
return usage4(io, "--mode takes new or resume", BRIEF_USAGE);
|
|
87532
88017
|
const rawAttempt = flags.values.attempt;
|
|
87533
88018
|
const attempt = rawAttempt === undefined ? null : Number(rawAttempt);
|
|
87534
88019
|
if (attempt !== null && !(Number.isInteger(attempt) && attempt >= 1 && attempt <= 9))
|
|
87535
|
-
return
|
|
88020
|
+
return usage4(io, "--attempt takes a number from 1 to 9", BRIEF_USAGE);
|
|
87536
88021
|
const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
|
|
87537
88022
|
if (!selected.ok)
|
|
87538
88023
|
return failed(io, selected);
|
|
@@ -87549,7 +88034,7 @@ function brief(argv, io) {
|
|
|
87549
88034
|
function check2(argv, io) {
|
|
87550
88035
|
const flags = parseFlags(argv, { name: "value", base: "value", offline: "boolean" });
|
|
87551
88036
|
if (typeof flags === "string")
|
|
87552
|
-
return
|
|
88037
|
+
return usage4(io, flags, CHECK_USAGE);
|
|
87553
88038
|
const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
|
|
87554
88039
|
if (!selected.ok)
|
|
87555
88040
|
return failed(io, selected);
|
|
@@ -87575,13 +88060,13 @@ function check2(argv, io) {
|
|
|
87575
88060
|
function status4(argv, io) {
|
|
87576
88061
|
const flags = parseFlags(argv, { name: "value", "stuck-after": "value", offline: "boolean" });
|
|
87577
88062
|
if (typeof flags === "string")
|
|
87578
|
-
return
|
|
88063
|
+
return usage4(io, flags, STATUS_USAGE3);
|
|
87579
88064
|
if (flags.positionals.length)
|
|
87580
|
-
return
|
|
88065
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, STATUS_USAGE3);
|
|
87581
88066
|
const raw = flags.values["stuck-after"];
|
|
87582
88067
|
const stuckAfterMs = raw === undefined ? null : parseDuration2(raw);
|
|
87583
88068
|
if (stuckAfterMs === 0 || raw !== undefined && stuckAfterMs === null)
|
|
87584
|
-
return
|
|
88069
|
+
return usage4(io, "--stuck-after takes a duration such as 30m, 45m or 2h", STATUS_USAGE3);
|
|
87585
88070
|
const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
|
|
87586
88071
|
if (!selected.ok)
|
|
87587
88072
|
return failed(io, selected);
|
|
@@ -87599,13 +88084,13 @@ function worktree(argv, io) {
|
|
|
87599
88084
|
const [action, ...rest] = argv;
|
|
87600
88085
|
const flags = parseFlags(rest, { name: "value", force: "boolean" });
|
|
87601
88086
|
if (typeof flags === "string")
|
|
87602
|
-
return
|
|
88087
|
+
return usage4(io, flags, WORKTREE_USAGE);
|
|
87603
88088
|
if (action !== "create" && action !== "release")
|
|
87604
|
-
return
|
|
88089
|
+
return usage4(io, action ? `unknown worktree action "${action}"` : "missing create or release", WORKTREE_USAGE);
|
|
87605
88090
|
if (flags.positionals.length !== 1)
|
|
87606
|
-
return
|
|
88091
|
+
return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <slice>", WORKTREE_USAGE);
|
|
87607
88092
|
if (action === "create" && flags.booleans.has("force"))
|
|
87608
|
-
return
|
|
88093
|
+
return usage4(io, "--force applies to release only", WORKTREE_USAGE);
|
|
87609
88094
|
const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
|
|
87610
88095
|
if (!selected.ok)
|
|
87611
88096
|
return failed(io, selected);
|
|
@@ -87643,7 +88128,7 @@ function worktree(argv, io) {
|
|
|
87643
88128
|
...data.notes.map((note) => `note: ${note}`)
|
|
87644
88129
|
]);
|
|
87645
88130
|
}
|
|
87646
|
-
async function
|
|
88131
|
+
async function run21(argv, io) {
|
|
87647
88132
|
const [sub, ...rest] = argv.filter((arg) => arg !== "--json");
|
|
87648
88133
|
if (sub === "plan")
|
|
87649
88134
|
return plan2(rest, io);
|
|
@@ -87655,9 +88140,9 @@ async function run20(argv, io) {
|
|
|
87655
88140
|
return status4(rest, io);
|
|
87656
88141
|
if (sub === "worktree")
|
|
87657
88142
|
return worktree(rest, io);
|
|
87658
|
-
return
|
|
88143
|
+
return usage4(io, sub && !sub.startsWith("-") ? `unknown fanout subcommand "${sub}"` : "missing fanout subcommand", USAGE13);
|
|
87659
88144
|
}
|
|
87660
|
-
var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead] [--json]", BRIEF_USAGE = "workit fanout brief <slice> [--name <n>] [--mode new|resume] [--attempt <n>] [--json]", CHECK_USAGE = "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline] [--json]", STATUS_USAGE3 = "workit fanout status [--name <n>] [--stuck-after 30m] [--offline] [--json]", WORKTREE_USAGE = "workit fanout worktree create <slice> [--name <n>] | worktree release <slice> [--name <n>] [--force] [--json]",
|
|
88145
|
+
var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead] [--json]", BRIEF_USAGE = "workit fanout brief <slice> [--name <n>] [--mode new|resume] [--attempt <n>] [--json]", CHECK_USAGE = "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline] [--json]", STATUS_USAGE3 = "workit fanout status [--name <n>] [--stuck-after 30m] [--offline] [--json]", WORKTREE_USAGE = "workit fanout worktree create <slice> [--name <n>] | worktree release <slice> [--name <n>] [--force] [--json]", USAGE13 = "workit fanout plan|brief|check|status|worktree ... (workit help fanout)", failed = (io, result) => emit(io, fail2(result.code, result.error, { unblock: result.unblock, data: result.data ?? {} })), renderCheck = (data) => [
|
|
87661
88146
|
`fanout ${data.name} against ${data.trunkRef}: ${data.ready ? "ready to land" : "blocked"}`,
|
|
87662
88147
|
...data.slices.map((slice) => slice.status === "landed" ? ` -- ${slice.id} (${slice.branch}) landed (${slice.landed?.how}${slice.landed?.pr ? ` #${slice.landed.pr}` : ""})` : ` ${slice.status === "ready" ? "ok " : "x "}${slice.id} (${slice.branch}) ${slice.changed} file${slice.changed === 1 ? "" : "s"} · verdict ${slice.verdict.accepted ? "accepted" : slice.verdict.basis}${slice.reasons.length ? `
|
|
87663
88148
|
${slice.reasons.join(`
|
|
@@ -87709,7 +88194,7 @@ var init_fanout2 = __esm(() => {
|
|
|
87709
88194
|
// packages/workit-cli/src/verbs/ledger.ts
|
|
87710
88195
|
var exports_ledger = {};
|
|
87711
88196
|
__export(exports_ledger, {
|
|
87712
|
-
run: () =>
|
|
88197
|
+
run: () => run22
|
|
87713
88198
|
});
|
|
87714
88199
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
87715
88200
|
import { parseArgs } from "node:util";
|
|
@@ -87733,30 +88218,30 @@ function targetBranch(io, rows, branch, pr) {
|
|
|
87733
88218
|
}
|
|
87734
88219
|
return { ok: true, value: branch ?? null };
|
|
87735
88220
|
}
|
|
87736
|
-
async function
|
|
88221
|
+
async function run22(argv, io) {
|
|
87737
88222
|
let parsed;
|
|
87738
88223
|
try {
|
|
87739
88224
|
parsed = parseArgs({ args: argv, options: OPTIONS, allowPositionals: true, strict: true });
|
|
87740
88225
|
} catch (error) {
|
|
87741
|
-
return
|
|
88226
|
+
return usage5(io, error.message);
|
|
87742
88227
|
}
|
|
87743
88228
|
const { values } = parsed;
|
|
87744
88229
|
let positionals = parsed.positionals;
|
|
87745
88230
|
if (positionals[0] === "add") {
|
|
87746
88231
|
positionals = positionals.slice(1);
|
|
87747
88232
|
if (!["decision", "ruling", "verdict"].includes(positionals[0] ?? ""))
|
|
87748
|
-
return
|
|
88233
|
+
return usage5(io, "ledger add takes decision|ruling|verdict");
|
|
87749
88234
|
}
|
|
87750
88235
|
const [sub, ...rest] = positionals;
|
|
87751
88236
|
const pr = positiveInt2(values.pr, "--pr");
|
|
87752
88237
|
if (pr instanceof Error)
|
|
87753
|
-
return
|
|
88238
|
+
return usage5(io, pr.message);
|
|
87754
88239
|
const last = positiveInt2(values.last, "--last");
|
|
87755
88240
|
if (last instanceof Error)
|
|
87756
|
-
return
|
|
88241
|
+
return usage5(io, last.message);
|
|
87757
88242
|
const text = rest.join(" ");
|
|
87758
88243
|
if (sub === undefined)
|
|
87759
|
-
return
|
|
88244
|
+
return usage5(io, "missing subcommand");
|
|
87760
88245
|
if (![
|
|
87761
88246
|
"decision",
|
|
87762
88247
|
"ruling",
|
|
@@ -87767,7 +88252,7 @@ async function run21(argv, io) {
|
|
|
87767
88252
|
"check",
|
|
87768
88253
|
"verify-integrity"
|
|
87769
88254
|
].includes(sub))
|
|
87770
|
-
return
|
|
88255
|
+
return usage5(io, `unknown ledger subcommand "${sub}"`);
|
|
87771
88256
|
if (sub === "standing")
|
|
87772
88257
|
return standing(io, values, rest);
|
|
87773
88258
|
const ledger = readLedger(io.cwd, {
|
|
@@ -87778,7 +88263,7 @@ async function run21(argv, io) {
|
|
|
87778
88263
|
const { rows } = ledger.value;
|
|
87779
88264
|
if (sub === "verify-integrity") {
|
|
87780
88265
|
if (rest.length)
|
|
87781
|
-
return
|
|
88266
|
+
return usage5(io, `unexpected argument: ${rest[0]}`);
|
|
87782
88267
|
const integrity = ledger.value.integrity ?? { chained: 0, legacy: 0, unverified: [] };
|
|
87783
88268
|
return emit(io, ok2({
|
|
87784
88269
|
path: ledger.value.path,
|
|
@@ -87790,7 +88275,7 @@ async function run21(argv, io) {
|
|
|
87790
88275
|
}
|
|
87791
88276
|
if (sub === "list" || sub === "show") {
|
|
87792
88277
|
if (rest.length)
|
|
87793
|
-
return
|
|
88278
|
+
return usage5(io, `unexpected argument: ${rest[0]}`);
|
|
87794
88279
|
const listed = filterRows(rows, {
|
|
87795
88280
|
branch: values.branch,
|
|
87796
88281
|
pr,
|
|
@@ -87805,7 +88290,7 @@ async function run21(argv, io) {
|
|
|
87805
88290
|
const isRead = sub === "check" || sub === "verdict" && values.how === undefined && !VERDICT_RESULTS.includes(rest[0] ?? "");
|
|
87806
88291
|
if (isRead) {
|
|
87807
88292
|
if (rest.length > (sub === "verdict" ? 1 : 0))
|
|
87808
|
-
return
|
|
88293
|
+
return usage5(io, `unexpected argument: ${rest.at(-1)}`);
|
|
87809
88294
|
const target = targetBranch(io, rows, rest[0] ?? values.branch, pr);
|
|
87810
88295
|
if (!target.ok)
|
|
87811
88296
|
return failed2(io, target);
|
|
@@ -87829,7 +88314,7 @@ async function run21(argv, io) {
|
|
|
87829
88314
|
}
|
|
87830
88315
|
const acting = actorFor(io, values);
|
|
87831
88316
|
if (acting instanceof Error)
|
|
87832
|
-
return
|
|
88317
|
+
return usage5(io, acting.message);
|
|
87833
88318
|
const { actor } = acting;
|
|
87834
88319
|
const context = {
|
|
87835
88320
|
cwd: io.cwd,
|
|
@@ -87861,7 +88346,7 @@ async function run21(argv, io) {
|
|
|
87861
88346
|
refs: values.ref
|
|
87862
88347
|
})), (row) => `recorded ruling ${row.id}`);
|
|
87863
88348
|
if (rest.length !== 1)
|
|
87864
|
-
return
|
|
88349
|
+
return usage5(io, `ledger verdict takes one result: ${VERDICT_RESULTS.join("|")}`);
|
|
87865
88350
|
const claimed = values.self === true ? null : claimedSession(acting);
|
|
87866
88351
|
const token = values.token ?? io.env.WORKIT_SESSION_TOKEN ?? null;
|
|
87867
88352
|
const refusal = claimed === null ? null : sessionClaimRefusal(io.env, claimed, io.cwd, { token, flag: acting.source === "flag" });
|
|
@@ -87907,9 +88392,9 @@ async function standing(io, values, args) {
|
|
|
87907
88392
|
if (action !== "add" && action !== "list" && action !== "clear")
|
|
87908
88393
|
return emit(io, fail2("invalid_input", action ? `unknown standing action "${action}"` : "missing add, list or clear", { unblock: STANDING_USAGE }));
|
|
87909
88394
|
if ((values.stop || values.clear) && action !== "add")
|
|
87910
|
-
return
|
|
88395
|
+
return usage5(io, `--stop and --clear go with standing add, not standing ${action}`);
|
|
87911
88396
|
if (values.stop && values.clear)
|
|
87912
|
-
return
|
|
88397
|
+
return usage5(io, "pass --stop or --clear, not both");
|
|
87913
88398
|
const target = standingFanout(io, values);
|
|
87914
88399
|
if (target instanceof Error)
|
|
87915
88400
|
return emit(io, fail2("invalid_input", target.message, { unblock: STANDING_USAGE }));
|
|
@@ -87918,7 +88403,7 @@ async function standing(io, values, args) {
|
|
|
87918
88403
|
const leads = target.plan ? planLeads(target.plan) : null;
|
|
87919
88404
|
if (action === "list") {
|
|
87920
88405
|
if (rest.length)
|
|
87921
|
-
return
|
|
88406
|
+
return usage5(io, `unexpected argument: ${rest[0]}`);
|
|
87922
88407
|
const ledger = readLedger(io.cwd);
|
|
87923
88408
|
if (!ledger.ok)
|
|
87924
88409
|
return failed2(io, ledger);
|
|
@@ -87934,7 +88419,7 @@ async function standing(io, values, args) {
|
|
|
87934
88419
|
}
|
|
87935
88420
|
const acting = actorFor(io, values);
|
|
87936
88421
|
if (acting instanceof Error)
|
|
87937
|
-
return
|
|
88422
|
+
return usage5(io, acting.message);
|
|
87938
88423
|
const context = {
|
|
87939
88424
|
cwd: io.cwd,
|
|
87940
88425
|
actor: acting.actor,
|
|
@@ -87946,16 +88431,16 @@ async function standing(io, values, args) {
|
|
|
87946
88431
|
}));
|
|
87947
88432
|
if (action === "add" && values.clear) {
|
|
87948
88433
|
if (rest.length)
|
|
87949
|
-
return
|
|
88434
|
+
return usage5(io, `unexpected argument: ${rest[0]}`);
|
|
87950
88435
|
return fromResult(io, liftStop(context, { fanout, lead, leads }), (rows) => `lifted the stop line for fanout ${fanout} (cleared ${rows.map((row) => row.target).join(", ")}); running workers are told on their next tool call`);
|
|
87951
88436
|
}
|
|
87952
88437
|
if (action === "add")
|
|
87953
88438
|
return fromResult(io, recordStanding(context, { fanout, lead, what: rest.join(" "), stop: values.stop === true }), (row) => row.stop ? `recorded stop line ${row.id} for fanout ${fanout}; running workers stop and report on their next tool call` : `recorded standing order ${row.id} for fanout ${fanout}; running workers get it on their next tool call`);
|
|
87954
88439
|
if (rest.length > 1)
|
|
87955
|
-
return
|
|
88440
|
+
return usage5(io, `unexpected argument: ${rest[1]}`);
|
|
87956
88441
|
return fromResult(io, clearStanding(context, { fanout, lead, leads, target: rest[0] ?? null }), (row) => row.target ? `cleared standing order ${row.target} for fanout ${fanout}` : `cleared every standing order for fanout ${fanout}`);
|
|
87957
88442
|
}
|
|
87958
|
-
var
|
|
88443
|
+
var USAGE14 = "workit ledger decision|ruling|verdict|standing|list|check ... (workit help ledger for the grammar)", STANDING_USAGE = 'workit ledger standing add "<order>" | add --stop ["<note>"] | add --clear | list | clear [<id>] [--fanout <name>] [--json]', OPTIONS, SESSION_SAFE2, ROLE_SAFE, actorFor = (io, values) => {
|
|
87959
88444
|
const actor = actorFromEnv(io.env);
|
|
87960
88445
|
if (values.session !== undefined && values.as !== undefined)
|
|
87961
88446
|
return new Error("pass --session or --as, not both");
|
|
@@ -87982,7 +88467,7 @@ var USAGE13 = "workit ledger decision|ruling|verdict|standing|list|check ... (wo
|
|
|
87982
88467
|
return;
|
|
87983
88468
|
const parsed = Number(value);
|
|
87984
88469
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : new Error(`${flag} must be a positive integer`);
|
|
87985
|
-
}, failed2 = (io, result) => emit(io, fail2(result.code, result.error, result.unblock ? { unblock: result.unblock } : {})), fromResult = (io, result, human) => result.ok ? emit(io, ok2(result.value), human) : failed2(io, result),
|
|
88470
|
+
}, failed2 = (io, result) => emit(io, fail2(result.code, result.error, result.unblock ? { unblock: result.unblock } : {})), fromResult = (io, result, human) => result.ok ? emit(io, ok2(result.value), human) : failed2(io, result), usage5 = (io, error) => emit(io, fail2("invalid_input", error, { unblock: USAGE14 })), passedTestOn = (cwd, verdict) => {
|
|
87986
88471
|
const ledger = readLedger(cwd);
|
|
87987
88472
|
return ledger.ok && ledger.value.rows.some((row) => row.type === "check" && row.observer === "workit_cli" && row.name === "test" && row.result === "passed" && row.dirty !== true && row.branch === verdict.branch && row.head === verdict.head);
|
|
87988
88473
|
}, verdictLines = (check) => {
|
|
@@ -103028,7 +103513,7 @@ var init_ast = __esm(() => {
|
|
|
103028
103513
|
|
|
103029
103514
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
103030
103515
|
import { builtinModules } from "node:module";
|
|
103031
|
-
import
|
|
103516
|
+
import path65 from "node:path";
|
|
103032
103517
|
function testCallee(call) {
|
|
103033
103518
|
let callee = call.callee;
|
|
103034
103519
|
if (callee.type === "CallExpression")
|
|
@@ -103521,12 +104006,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
103521
104006
|
}
|
|
103522
104007
|
function checkOverMocking(ctx, emit) {
|
|
103523
104008
|
const { program } = ctx.parsed;
|
|
103524
|
-
const unit =
|
|
104009
|
+
const unit = path65.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
103525
104010
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
103526
104011
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
103527
104012
|
for (const call of mocked) {
|
|
103528
104013
|
const spec = call.arguments[0].value;
|
|
103529
|
-
const base =
|
|
104014
|
+
const base = path65.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
103530
104015
|
if (base === unit)
|
|
103531
104016
|
emit({
|
|
103532
104017
|
rule: "over-mocking",
|
|
@@ -103915,8 +104400,8 @@ var init_rules = __esm(() => {
|
|
|
103915
104400
|
|
|
103916
104401
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
103917
104402
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
103918
|
-
import { existsSync as
|
|
103919
|
-
import
|
|
104403
|
+
import { existsSync as existsSync24, readdirSync as readdirSync11, readFileSync as readFileSync26, statSync as statSync10 } from "node:fs";
|
|
104404
|
+
import path66 from "node:path";
|
|
103920
104405
|
function git7(cwd, args) {
|
|
103921
104406
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
103922
104407
|
cwd,
|
|
@@ -103929,7 +104414,7 @@ function walkTests(dir, out) {
|
|
|
103929
104414
|
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
103930
104415
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
103931
104416
|
continue;
|
|
103932
|
-
const full =
|
|
104417
|
+
const full = path66.join(dir, entry.name);
|
|
103933
104418
|
if (entry.isDirectory()) {
|
|
103934
104419
|
if (!SKIP_DIRS.has(entry.name))
|
|
103935
104420
|
walkTests(full, out);
|
|
@@ -103941,8 +104426,8 @@ function expandPaths(cwd, inputs) {
|
|
|
103941
104426
|
const files = [];
|
|
103942
104427
|
const missing = [];
|
|
103943
104428
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
103944
|
-
const full =
|
|
103945
|
-
if (!
|
|
104429
|
+
const full = path66.resolve(cwd, input);
|
|
104430
|
+
if (!existsSync24(full))
|
|
103946
104431
|
missing.push(input);
|
|
103947
104432
|
else if (statSync10(full).isDirectory())
|
|
103948
104433
|
walkTests(full, files);
|
|
@@ -103978,11 +104463,11 @@ function changedLines(cwd, base) {
|
|
|
103978
104463
|
for (let offset = 0;offset < count; offset += 1)
|
|
103979
104464
|
lines.add(start + offset);
|
|
103980
104465
|
}
|
|
103981
|
-
changed.set(
|
|
104466
|
+
changed.set(path66.join(root, file), lines);
|
|
103982
104467
|
}
|
|
103983
104468
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
103984
104469
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
103985
|
-
changed.set(
|
|
104470
|
+
changed.set(path66.join(root, file), "all");
|
|
103986
104471
|
return changed;
|
|
103987
104472
|
}
|
|
103988
104473
|
function auditFiles(files, display) {
|
|
@@ -104044,7 +104529,7 @@ function auditFiles(files, display) {
|
|
|
104044
104529
|
durationMs: Math.round(performance.now() - started)
|
|
104045
104530
|
};
|
|
104046
104531
|
}
|
|
104047
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
104532
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path66.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
104048
104533
|
var init_audit = __esm(() => {
|
|
104049
104534
|
init_ast();
|
|
104050
104535
|
init_rules();
|
|
@@ -104058,7 +104543,7 @@ var init_audit = __esm(() => {
|
|
|
104058
104543
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
104059
104544
|
import { spawn as spawn2 } from "node:child_process";
|
|
104060
104545
|
import {
|
|
104061
|
-
existsSync as
|
|
104546
|
+
existsSync as existsSync25,
|
|
104062
104547
|
lstatSync as lstatSync8,
|
|
104063
104548
|
mkdirSync as mkdirSync11,
|
|
104064
104549
|
mkdtempSync as mkdtempSync4,
|
|
@@ -104071,10 +104556,10 @@ import {
|
|
|
104071
104556
|
statSync as statSync11,
|
|
104072
104557
|
symlinkSync,
|
|
104073
104558
|
writeFileSync as writeFileSync11,
|
|
104074
|
-
copyFileSync as
|
|
104559
|
+
copyFileSync as copyFileSync8
|
|
104075
104560
|
} from "node:fs";
|
|
104076
104561
|
import os22 from "node:os";
|
|
104077
|
-
import
|
|
104562
|
+
import path67 from "node:path";
|
|
104078
104563
|
function mutantsFor(source, file, lines) {
|
|
104079
104564
|
const parsed = parseSource(source, file);
|
|
104080
104565
|
const out = [];
|
|
@@ -104147,7 +104632,7 @@ function relatedTests(source, testFiles) {
|
|
|
104147
104632
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
104148
104633
|
const spec = match[1];
|
|
104149
104634
|
if (spec.startsWith(".")) {
|
|
104150
|
-
if (stripExt(
|
|
104635
|
+
if (stripExt(path67.posix.join(path67.posix.dirname(file), spec)) === target)
|
|
104151
104636
|
return true;
|
|
104152
104637
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
104153
104638
|
return true;
|
|
@@ -104167,12 +104652,12 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
|
104167
104652
|
for (const name of names) {
|
|
104168
104653
|
if (!name.startsWith(TEMP_PREFIX))
|
|
104169
104654
|
continue;
|
|
104170
|
-
const dir =
|
|
104655
|
+
const dir = path67.join(tmp, name);
|
|
104171
104656
|
try {
|
|
104172
104657
|
const stat = lstatSync8(dir);
|
|
104173
104658
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
104174
104659
|
continue;
|
|
104175
|
-
const pid = Number(readFileSync27(
|
|
104660
|
+
const pid = Number(readFileSync27(path67.join(dir, PID_FILE), "utf8"));
|
|
104176
104661
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
104177
104662
|
continue;
|
|
104178
104663
|
} catch (error) {
|
|
@@ -104189,8 +104674,8 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
|
104189
104674
|
function linkNodeModules(origin, target, repo, copy) {
|
|
104190
104675
|
mkdirSync11(target, { recursive: true });
|
|
104191
104676
|
for (const entry of readdirSync12(origin, { withFileTypes: true })) {
|
|
104192
|
-
const from =
|
|
104193
|
-
const to =
|
|
104677
|
+
const from = path67.join(origin, entry.name);
|
|
104678
|
+
const to = path67.join(target, entry.name);
|
|
104194
104679
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
104195
104680
|
linkNodeModules(from, to, repo, copy);
|
|
104196
104681
|
continue;
|
|
@@ -104206,9 +104691,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
104206
104691
|
} catch {
|
|
104207
104692
|
continue;
|
|
104208
104693
|
}
|
|
104209
|
-
const relative =
|
|
104210
|
-
if (!relative.startsWith("..") && !
|
|
104211
|
-
symlinkSync(
|
|
104694
|
+
const relative = path67.relative(repo, real);
|
|
104695
|
+
if (!relative.startsWith("..") && !path67.isAbsolute(relative) && !relative.split(path67.sep).includes("node_modules")) {
|
|
104696
|
+
symlinkSync(path67.join(copy, relative), to, "junction");
|
|
104212
104697
|
continue;
|
|
104213
104698
|
}
|
|
104214
104699
|
}
|
|
@@ -104224,19 +104709,19 @@ function copySymlink(repo, tree, from, to) {
|
|
|
104224
104709
|
}
|
|
104225
104710
|
const realRepo = realpathSync10(repo);
|
|
104226
104711
|
if (real && inside4(realRepo, real)) {
|
|
104227
|
-
symlinkSync(
|
|
104712
|
+
symlinkSync(path67.relative(path67.dirname(to), path67.join(tree, path67.relative(realRepo, real))), to);
|
|
104228
104713
|
return;
|
|
104229
104714
|
}
|
|
104230
104715
|
if (real && statSync11(real).isFile())
|
|
104231
|
-
|
|
104716
|
+
copyFileSync8(real, to);
|
|
104232
104717
|
else
|
|
104233
104718
|
symlinkSync(readlinkSync3(from), to);
|
|
104234
104719
|
}
|
|
104235
104720
|
function writeInside(copy, file, content) {
|
|
104236
|
-
const target =
|
|
104721
|
+
const target = path67.join(copy, file);
|
|
104237
104722
|
try {
|
|
104238
104723
|
const stat = lstatSync8(target);
|
|
104239
|
-
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(
|
|
104724
|
+
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(path67.dirname(target))))
|
|
104240
104725
|
return false;
|
|
104241
104726
|
} catch {
|
|
104242
104727
|
return false;
|
|
@@ -104247,9 +104732,9 @@ function writeInside(copy, file, content) {
|
|
|
104247
104732
|
return true;
|
|
104248
104733
|
}
|
|
104249
104734
|
function copyWorkingTree(repo) {
|
|
104250
|
-
const dir = mkdtempSync4(
|
|
104251
|
-
writeFileSync11(
|
|
104252
|
-
const tree =
|
|
104735
|
+
const dir = mkdtempSync4(path67.join(os22.tmpdir(), TEMP_PREFIX));
|
|
104736
|
+
writeFileSync11(path67.join(dir, PID_FILE), String(process.pid));
|
|
104737
|
+
const tree = path67.join(dir, "tree");
|
|
104253
104738
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
104254
104739
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
104255
104740
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -104266,29 +104751,29 @@ function copyWorkingTree(repo) {
|
|
|
104266
104751
|
for (const relative of listed) {
|
|
104267
104752
|
if (!relative)
|
|
104268
104753
|
continue;
|
|
104269
|
-
const from =
|
|
104754
|
+
const from = path67.join(repo, relative);
|
|
104270
104755
|
let stat;
|
|
104271
104756
|
try {
|
|
104272
104757
|
stat = lstatSync8(from);
|
|
104273
104758
|
} catch {
|
|
104274
104759
|
continue;
|
|
104275
104760
|
}
|
|
104276
|
-
const to =
|
|
104277
|
-
mkdirSync11(
|
|
104761
|
+
const to = path67.join(tree, relative);
|
|
104762
|
+
mkdirSync11(path67.dirname(to), { recursive: true });
|
|
104278
104763
|
if (stat.isSymbolicLink())
|
|
104279
104764
|
copySymlink(repo, tree, from, to);
|
|
104280
104765
|
else if (stat.isFile())
|
|
104281
|
-
|
|
104282
|
-
let parent =
|
|
104766
|
+
copyFileSync8(from, to);
|
|
104767
|
+
let parent = path67.dirname(relative);
|
|
104283
104768
|
while (parent !== "." && !dirs.has(parent)) {
|
|
104284
104769
|
dirs.add(parent);
|
|
104285
|
-
parent =
|
|
104770
|
+
parent = path67.dirname(parent);
|
|
104286
104771
|
}
|
|
104287
104772
|
}
|
|
104288
104773
|
for (const parent of dirs) {
|
|
104289
|
-
const modules =
|
|
104290
|
-
if (
|
|
104291
|
-
linkNodeModules(modules,
|
|
104774
|
+
const modules = path67.join(repo, parent, "node_modules");
|
|
104775
|
+
if (existsSync25(modules) && !existsSync25(path67.join(tree, parent, "node_modules")))
|
|
104776
|
+
linkNodeModules(modules, path67.join(tree, parent, "node_modules"), repo, tree);
|
|
104292
104777
|
}
|
|
104293
104778
|
return { dir, tree };
|
|
104294
104779
|
}
|
|
@@ -104327,17 +104812,17 @@ async function runMutation(options) {
|
|
|
104327
104812
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
104328
104813
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
104329
104814
|
try {
|
|
104330
|
-
return { file, text: readFileSync27(
|
|
104815
|
+
return { file, text: readFileSync27(path67.join(repo, file), "utf8") };
|
|
104331
104816
|
} catch {
|
|
104332
104817
|
return { file, text: "" };
|
|
104333
104818
|
}
|
|
104334
104819
|
});
|
|
104335
104820
|
const candidates = [];
|
|
104336
104821
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
104337
|
-
const relative = toPosix(
|
|
104822
|
+
const relative = toPosix(path67.relative(repo, absolute));
|
|
104338
104823
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
104339
104824
|
continue;
|
|
104340
|
-
if (NOT_SOURCE.test(relative) || !
|
|
104825
|
+
if (NOT_SOURCE.test(relative) || !existsSync25(absolute))
|
|
104341
104826
|
continue;
|
|
104342
104827
|
try {
|
|
104343
104828
|
candidates.push(...mutantsFor(readFileSync27(absolute, "utf8"), relative, lines));
|
|
@@ -104348,9 +104833,9 @@ async function runMutation(options) {
|
|
|
104348
104833
|
for (const mutant of mutants)
|
|
104349
104834
|
if (!related.has(mutant.file))
|
|
104350
104835
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
104351
|
-
const cwdRelative =
|
|
104836
|
+
const cwdRelative = path67.relative(repo, options.cwd);
|
|
104352
104837
|
const asArg = (file) => {
|
|
104353
|
-
const relative = toPosix(
|
|
104838
|
+
const relative = toPosix(path67.relative(cwdRelative, file));
|
|
104354
104839
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
104355
104840
|
};
|
|
104356
104841
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -104386,7 +104871,7 @@ async function runMutation(options) {
|
|
|
104386
104871
|
return finish3(options, 0, results, counts, started);
|
|
104387
104872
|
removeStaleCopies();
|
|
104388
104873
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
104389
|
-
const copyCwd =
|
|
104874
|
+
const copyCwd = path67.join(copy, cwdRelative);
|
|
104390
104875
|
let current = null;
|
|
104391
104876
|
const restore = () => {
|
|
104392
104877
|
if (current)
|
|
@@ -104421,7 +104906,7 @@ async function runMutation(options) {
|
|
|
104421
104906
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
104422
104907
|
continue;
|
|
104423
104908
|
}
|
|
104424
|
-
const original = readFileSync27(
|
|
104909
|
+
const original = readFileSync27(path67.join(copy, mutant.file), "utf8");
|
|
104425
104910
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
104426
104911
|
current = { file: mutant.file, original };
|
|
104427
104912
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -104478,8 +104963,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
104478
104963
|
return error.code === "EPERM";
|
|
104479
104964
|
}
|
|
104480
104965
|
}, inside4 = (root, file) => {
|
|
104481
|
-
const relative =
|
|
104482
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
104966
|
+
const relative = path67.relative(root, file);
|
|
104967
|
+
return relative === "" || !relative.startsWith("..") && !path67.isAbsolute(relative);
|
|
104483
104968
|
}, active, killTree = (child) => {
|
|
104484
104969
|
try {
|
|
104485
104970
|
if (child.pid && process.platform !== "win32")
|
|
@@ -104525,10 +105010,10 @@ var init_mutate = __esm(() => {
|
|
|
104525
105010
|
// packages/workit-cli/src/verbs/test-audit.ts
|
|
104526
105011
|
var exports_test_audit = {};
|
|
104527
105012
|
__export(exports_test_audit, {
|
|
104528
|
-
run: () =>
|
|
105013
|
+
run: () => run23
|
|
104529
105014
|
});
|
|
104530
|
-
import { existsSync as
|
|
104531
|
-
import
|
|
105015
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
105016
|
+
import path68 from "node:path";
|
|
104532
105017
|
function parse8(argv) {
|
|
104533
105018
|
const options = {
|
|
104534
105019
|
paths: [],
|
|
@@ -104627,14 +105112,14 @@ function human(data) {
|
|
|
104627
105112
|
}
|
|
104628
105113
|
return lines;
|
|
104629
105114
|
}
|
|
104630
|
-
async function
|
|
105115
|
+
async function run23(argv, io) {
|
|
104631
105116
|
const options = parse8(argv);
|
|
104632
105117
|
if (typeof options === "string")
|
|
104633
105118
|
return emit(io, fail2("invalid_input", `${options}
|
|
104634
|
-
usage: ${
|
|
105119
|
+
usage: ${USAGE15}`));
|
|
104635
105120
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
104636
|
-
const repo = top.ok ?
|
|
104637
|
-
const display = (file) => toPosix(
|
|
105121
|
+
const repo = top.ok ? path68.resolve(top.stdout.trim()) : null;
|
|
105122
|
+
const display = (file) => toPosix(path68.relative(io.cwd, file) || file);
|
|
104638
105123
|
let base = null;
|
|
104639
105124
|
let changed = null;
|
|
104640
105125
|
if (options.diff || options.mutate) {
|
|
@@ -104651,7 +105136,7 @@ usage: ${USAGE14}`));
|
|
|
104651
105136
|
}
|
|
104652
105137
|
let files;
|
|
104653
105138
|
if (options.diff && changed)
|
|
104654
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
105139
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync26(file)).toSorted();
|
|
104655
105140
|
else {
|
|
104656
105141
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
104657
105142
|
if (expanded.missing.length > 0)
|
|
@@ -104717,7 +105202,7 @@ usage: ${USAGE14}`));
|
|
|
104717
105202
|
}
|
|
104718
105203
|
return emit(io, ok2(data), human);
|
|
104719
105204
|
}
|
|
104720
|
-
var
|
|
105205
|
+
var USAGE15 = "workit test-audit [paths…] [--diff [base]] [--rule <ids>] [--min-severity <level>] [--fail-on <level>] [--mutate [--test-cmd <cmd>] [--max-mutants <n>] [--budget <s>] [--timeout <s>]] [--json]", LEVELS, VALUE_FLAGS2, quote = (arg) => /^[\w./@:=+-]+$/.test(arg) ? arg : `'${arg.replace(/'/g, "'\\''")}'`;
|
|
104721
105206
|
var init_test_audit = __esm(() => {
|
|
104722
105207
|
init_audit();
|
|
104723
105208
|
init_mutate();
|
|
@@ -104738,12 +105223,12 @@ var init_test_audit = __esm(() => {
|
|
|
104738
105223
|
// packages/workit-cli/src/verbs/knowledge.ts
|
|
104739
105224
|
var exports_knowledge = {};
|
|
104740
105225
|
__export(exports_knowledge, {
|
|
104741
|
-
run: () =>
|
|
105226
|
+
run: () => run24
|
|
104742
105227
|
});
|
|
104743
|
-
async function
|
|
105228
|
+
async function run24(argv, io) {
|
|
104744
105229
|
const [sub, ...rest] = argv.filter((arg) => arg !== "--json");
|
|
104745
105230
|
if (sub !== "lint" || rest.length > 0)
|
|
104746
|
-
return emit(io, fail2("invalid_input", `usage: ${
|
|
105231
|
+
return emit(io, fail2("invalid_input", `usage: ${USAGE16}`));
|
|
104747
105232
|
const report = lintKnowledge(checkRoot(io.cwd));
|
|
104748
105233
|
if (report.unreadable.length > 0)
|
|
104749
105234
|
return emit(io, fail2("unavailable", `knowledge lint: cannot read ${report.unreadable.join(", ")}`, {
|
|
@@ -104760,7 +105245,7 @@ async function run23(argv, io) {
|
|
|
104760
105245
|
`);
|
|
104761
105246
|
return report.findings.length === 0 ? 0 : 1;
|
|
104762
105247
|
}
|
|
104763
|
-
var
|
|
105248
|
+
var USAGE16 = "workit knowledge lint [--json]";
|
|
104764
105249
|
var init_knowledge2 = __esm(() => {
|
|
104765
105250
|
init_check_config();
|
|
104766
105251
|
init_knowledge();
|
|
@@ -104770,14 +105255,14 @@ var init_knowledge2 = __esm(() => {
|
|
|
104770
105255
|
// packages/workit-cli/src/verbs/youtrack.ts
|
|
104771
105256
|
var exports_youtrack = {};
|
|
104772
105257
|
__export(exports_youtrack, {
|
|
104773
|
-
run: () =>
|
|
105258
|
+
run: () => run25
|
|
104774
105259
|
});
|
|
104775
105260
|
import { readFileSync as readFileSync28 } from "node:fs";
|
|
104776
|
-
import
|
|
104777
|
-
async function
|
|
105261
|
+
import path69 from "node:path";
|
|
105262
|
+
async function run25(argv, io) {
|
|
104778
105263
|
const [sub, ...rest] = argv;
|
|
104779
105264
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
104780
|
-
return
|
|
105265
|
+
return usage4(io, `unknown subcommand "${sub ?? ""}"`, USAGE17);
|
|
104781
105266
|
const flags = parseFlags(rest, {
|
|
104782
105267
|
markdown: "value",
|
|
104783
105268
|
file: "value",
|
|
@@ -104786,18 +105271,18 @@ async function run24(argv, io) {
|
|
|
104786
105271
|
date: "value"
|
|
104787
105272
|
});
|
|
104788
105273
|
if (typeof flags === "string")
|
|
104789
|
-
return
|
|
105274
|
+
return usage4(io, flags, USAGE17);
|
|
104790
105275
|
const [issueId, extra] = flags.positionals;
|
|
104791
105276
|
if (!issueId || !ISSUE_RE2.test(issueId))
|
|
104792
|
-
return
|
|
105277
|
+
return usage4(io, "an issue id like ABC-123 is required", USAGE17);
|
|
104793
105278
|
if (extra !== undefined)
|
|
104794
|
-
return
|
|
105279
|
+
return usage4(io, `unexpected argument ${extra}`, USAGE17);
|
|
104795
105280
|
const minutes = positiveInt(flags.values.minutes, "--minutes");
|
|
104796
105281
|
if (typeof minutes === "string")
|
|
104797
|
-
return
|
|
105282
|
+
return usage4(io, minutes, USAGE17);
|
|
104798
105283
|
const date = youTrackWorkDateMs(flags.values.date ?? "auto");
|
|
104799
105284
|
if ("error" in date)
|
|
104800
|
-
return
|
|
105285
|
+
return usage4(io, date.error, USAGE17);
|
|
104801
105286
|
const dateMs = date.data.dateMs;
|
|
104802
105287
|
const markedDay = flags.values.date !== undefined && flags.values.date !== "auto" ? { dateMs } : {};
|
|
104803
105288
|
const root = io.cwd;
|
|
@@ -104815,24 +105300,24 @@ async function run24(argv, io) {
|
|
|
104815
105300
|
};
|
|
104816
105301
|
if (sub === "note") {
|
|
104817
105302
|
if (Boolean(flags.values.markdown) === Boolean(flags.values.file))
|
|
104818
|
-
return
|
|
105303
|
+
return usage4(io, "pass exactly one of --markdown or --file", USAGE17);
|
|
104819
105304
|
let markdown = flags.values.markdown ?? "";
|
|
104820
105305
|
if (flags.values.file)
|
|
104821
105306
|
try {
|
|
104822
|
-
markdown = readFileSync28(
|
|
105307
|
+
markdown = readFileSync28(path69.resolve(io.cwd, flags.values.file), "utf8");
|
|
104823
105308
|
} catch (error) {
|
|
104824
|
-
return
|
|
105309
|
+
return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE17);
|
|
104825
105310
|
}
|
|
104826
105311
|
if (!markdown.trim())
|
|
104827
|
-
return
|
|
105312
|
+
return usage4(io, "the note is empty", USAGE17);
|
|
104828
105313
|
const missing = step("comment", "comments", { operation: "note", issueId, markdown }, markdown, async (text) => commentResult(await postComment(issueId, text, root))) ?? (minutes ? step("time", "workItems", { operation: "note.time", issueId, markdown, minutes, ...markedDay }, "workit update", (text) => logTimeUpdate({ issueId, minutes, text, dateMs, workspace_root: root })) : null);
|
|
104829
105314
|
if (missing)
|
|
104830
105315
|
return emit(io, fail2("unavailable", missing));
|
|
104831
105316
|
} else {
|
|
104832
105317
|
if (!minutes)
|
|
104833
|
-
return
|
|
105318
|
+
return usage4(io, `${sub} needs --minutes <n>`, USAGE17);
|
|
104834
105319
|
if (sub === "meeting" && !flags.values.text)
|
|
104835
|
-
return
|
|
105320
|
+
return usage4(io, "meeting needs --text <what the meeting was>", USAGE17);
|
|
104836
105321
|
const text = flags.values.text ?? "";
|
|
104837
105322
|
const missing = step(sub, "workItems", { operation: sub, issueId, minutes, text, ...markedDay }, text, (marked) => logTimeUpdate({ issueId, minutes, text: marked, dateMs, workspace_root: root }));
|
|
104838
105323
|
if (missing)
|
|
@@ -104861,7 +105346,7 @@ async function run24(argv, io) {
|
|
|
104861
105346
|
...data.steps.flatMap((entry) => entry.note ? [` note (${entry.step}): ${entry.note}`] : [])
|
|
104862
105347
|
]);
|
|
104863
105348
|
}
|
|
104864
|
-
var
|
|
105349
|
+
var USAGE17 = "workit youtrack note <ISSUE> (--markdown <t> | --file <p>) [--minutes <n>] [--date auto|YYYY-MM-DD] | youtrack time <ISSUE> --minutes <n> [--text <t>] [--date …] | youtrack meeting <ISSUE> --minutes <n> --text <t> [--date …]", commentResult = (value) => {
|
|
104865
105350
|
try {
|
|
104866
105351
|
return { ok: true, data: unwrap(value) };
|
|
104867
105352
|
} catch (error) {
|
|
@@ -104885,14 +105370,14 @@ var init_youtrack2 = __esm(() => {
|
|
|
104885
105370
|
// packages/workit-cli/src/verbs/changelog.ts
|
|
104886
105371
|
var exports_changelog = {};
|
|
104887
105372
|
__export(exports_changelog, {
|
|
104888
|
-
run: () =>
|
|
105373
|
+
run: () => run26
|
|
104889
105374
|
});
|
|
104890
105375
|
import { readFileSync as readFileSync29 } from "node:fs";
|
|
104891
|
-
import
|
|
104892
|
-
async function
|
|
105376
|
+
import path70 from "node:path";
|
|
105377
|
+
async function run26(argv, io) {
|
|
104893
105378
|
const [sub, ...rest] = argv;
|
|
104894
105379
|
if (sub !== "apply")
|
|
104895
|
-
return
|
|
105380
|
+
return usage4(io, `unknown subcommand "${sub ?? ""}"`, USAGE18);
|
|
104896
105381
|
const flags = parseFlags(rest, {
|
|
104897
105382
|
entries: "value",
|
|
104898
105383
|
path: "value",
|
|
@@ -104900,18 +105385,18 @@ async function run25(argv, io) {
|
|
|
104900
105385
|
preview: "boolean"
|
|
104901
105386
|
});
|
|
104902
105387
|
if (typeof flags === "string")
|
|
104903
|
-
return
|
|
105388
|
+
return usage4(io, flags, USAGE18);
|
|
104904
105389
|
if (flags.positionals.length)
|
|
104905
|
-
return
|
|
105390
|
+
return usage4(io, `unexpected argument ${flags.positionals[0]}`, USAGE18);
|
|
104906
105391
|
const normalizeOnly = flags.booleans.has("normalize-only");
|
|
104907
105392
|
if (!normalizeOnly && !flags.values.entries)
|
|
104908
|
-
return
|
|
105393
|
+
return usage4(io, "pass --entries <JSON> or --normalize-only", USAGE18);
|
|
104909
105394
|
let entries;
|
|
104910
105395
|
if (flags.values.entries)
|
|
104911
105396
|
try {
|
|
104912
105397
|
entries = readEntries(flags.values.entries, io.cwd);
|
|
104913
105398
|
} catch (error) {
|
|
104914
|
-
return
|
|
105399
|
+
return usage4(io, `--entries is not valid JSON: ${String(error)}`, USAGE18);
|
|
104915
105400
|
}
|
|
104916
105401
|
const input = {
|
|
104917
105402
|
entries,
|
|
@@ -104933,8 +105418,8 @@ async function run25(argv, io) {
|
|
|
104933
105418
|
`changelog updated: ${String(applied.path ?? "CHANGELOG.md")}`
|
|
104934
105419
|
]);
|
|
104935
105420
|
}
|
|
104936
|
-
var
|
|
104937
|
-
const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(
|
|
105421
|
+
var USAGE18 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
105422
|
+
const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(path70.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
104938
105423
|
return JSON.parse(text);
|
|
104939
105424
|
};
|
|
104940
105425
|
var init_changelog2 = __esm(() => {
|
|
@@ -104947,10 +105432,10 @@ var init_changelog2 = __esm(() => {
|
|
|
104947
105432
|
var exports_handoff = {};
|
|
104948
105433
|
__export(exports_handoff, {
|
|
104949
105434
|
MAX_BRIEF_BYTES: () => MAX_BRIEF_BYTES,
|
|
104950
|
-
run: () =>
|
|
105435
|
+
run: () => run27
|
|
104951
105436
|
});
|
|
104952
|
-
import
|
|
104953
|
-
import
|
|
105437
|
+
import fs36 from "node:fs";
|
|
105438
|
+
import path71 from "node:path";
|
|
104954
105439
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
104955
105440
|
function render3(brief) {
|
|
104956
105441
|
const lines = [
|
|
@@ -104990,10 +105475,10 @@ function bounded(brief, cwd) {
|
|
|
104990
105475
|
let file = null;
|
|
104991
105476
|
if (store.ok)
|
|
104992
105477
|
try {
|
|
104993
|
-
const dir =
|
|
104994
|
-
|
|
104995
|
-
file =
|
|
104996
|
-
|
|
105478
|
+
const dir = path71.join(store.value.root, "handoff");
|
|
105479
|
+
fs36.mkdirSync(dir, { recursive: true });
|
|
105480
|
+
file = path71.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
|
|
105481
|
+
fs36.writeFileSync(file, `${[...body, ...tail].join(`
|
|
104997
105482
|
`)}
|
|
104998
105483
|
`, { mode: 384 });
|
|
104999
105484
|
} catch {
|
|
@@ -105025,11 +105510,11 @@ async function resumeBrief(argv, io) {
|
|
|
105025
105510
|
strict: true
|
|
105026
105511
|
}));
|
|
105027
105512
|
} catch (error) {
|
|
105028
|
-
return emit(io, fail2("invalid_input", error.message, { unblock:
|
|
105513
|
+
return emit(io, fail2("invalid_input", error.message, { unblock: USAGE19 }));
|
|
105029
105514
|
}
|
|
105030
105515
|
const last = values.last === undefined ? 10 : Number(values.last);
|
|
105031
105516
|
if (!Number.isInteger(last) || last < 1)
|
|
105032
|
-
return emit(io, fail2("invalid_input", "--last must be a positive integer", { unblock:
|
|
105517
|
+
return emit(io, fail2("invalid_input", "--last must be a positive integer", { unblock: USAGE19 }));
|
|
105033
105518
|
const built = buildHandoff(io.cwd, {
|
|
105034
105519
|
last,
|
|
105035
105520
|
note: values.note ?? null,
|
|
@@ -105047,13 +105532,13 @@ async function resumeBrief(argv, io) {
|
|
|
105047
105532
|
}
|
|
105048
105533
|
return emit(io, ok2({ ...data, recorded }), (brief) => bounded(brief, io.cwd));
|
|
105049
105534
|
}
|
|
105050
|
-
async function
|
|
105535
|
+
async function run27(argv, io) {
|
|
105051
105536
|
if (!argv.some((arg) => arg === "--task" || arg.startsWith("--task=")))
|
|
105052
105537
|
return resumeBrief(argv, io);
|
|
105053
105538
|
await Promise.resolve().then(() => init_task());
|
|
105054
105539
|
return runTaskCommand(["handoff", ...argv]);
|
|
105055
105540
|
}
|
|
105056
|
-
var
|
|
105541
|
+
var USAGE19 = "workit handoff [--note <text>] [--next <text>] [--record] [--last <n>] [--json]", MAX_BRIEF_BYTES = 4096, short7 = (sha) => sha ? sha.slice(0, 12) : "no commit", bytes = (lines) => Buffer.byteLength(`${lines.join(`
|
|
105057
105542
|
`)}
|
|
105058
105543
|
`);
|
|
105059
105544
|
var init_handoff = __esm(() => {
|
|
@@ -105064,7 +105549,7 @@ var init_handoff = __esm(() => {
|
|
|
105064
105549
|
// packages/workit-cli/src/main.ts
|
|
105065
105550
|
init_host_session();
|
|
105066
105551
|
init_package();
|
|
105067
|
-
import
|
|
105552
|
+
import path72 from "node:path";
|
|
105068
105553
|
|
|
105069
105554
|
// packages/workit-cli/src/verbs/registry.ts
|
|
105070
105555
|
var TASK_FAMILY_NAMES = [
|
|
@@ -105249,6 +105734,38 @@ var VERBS = [
|
|
|
105249
105734
|
examples: ["workit grant show", "workit grant set my-repo push=true pr=true"],
|
|
105250
105735
|
load: () => Promise.resolve().then(() => (init_grant(), exports_grant))
|
|
105251
105736
|
}, { optional: true }),
|
|
105737
|
+
withSubcommands({
|
|
105738
|
+
name: "workspace",
|
|
105739
|
+
group: "setup",
|
|
105740
|
+
summary: "Edit workspace entries without the wizard; never raises a grant",
|
|
105741
|
+
subcommands: [
|
|
105742
|
+
{
|
|
105743
|
+
name: "list",
|
|
105744
|
+
usage: "workit workspace list",
|
|
105745
|
+
summary: "Show every entry and the one that applies to --cwd, and why"
|
|
105746
|
+
},
|
|
105747
|
+
{
|
|
105748
|
+
name: "add",
|
|
105749
|
+
usage: "workit workspace add <name> --glob <glob> [--from <parent>]",
|
|
105750
|
+
summary: "Add an entry; --from copies vcs, issues, branchPolicy, commitPolicy, trailers, youtrack and models, never grants"
|
|
105751
|
+
},
|
|
105752
|
+
{
|
|
105753
|
+
name: "set",
|
|
105754
|
+
usage: "workit workspace set <name> <key>=<value>…",
|
|
105755
|
+
summary: "Change non-grant keys (dotted paths, JSON values, null removes); grants stay with workit grant set"
|
|
105756
|
+
}
|
|
105757
|
+
],
|
|
105758
|
+
examples: [
|
|
105759
|
+
"workit workspace list",
|
|
105760
|
+
"workit workspace add kit --glob '/home/me/work/libs/kit/**' --from work",
|
|
105761
|
+
"workit workspace set kit branchPolicy.integration=merge"
|
|
105762
|
+
],
|
|
105763
|
+
notes: [
|
|
105764
|
+
"A new entry starts with no grants of its own. It starts at the strictest level of every entry and the defaults, so its folders never get more than they had. Remove an entry in your own editor. Raising a grant, defaultEndpoint or verification needs the user: workit grant set <name> <kind>=<value> in their own terminal.",
|
|
105765
|
+
"Every write keeps the previous file as workspaces.json.bak. `workit doctor` lists overlapping globs and which entry wins."
|
|
105766
|
+
],
|
|
105767
|
+
load: () => Promise.resolve().then(() => (init_workspace(), exports_workspace))
|
|
105768
|
+
}, { optional: true }),
|
|
105252
105769
|
...TASK_FAMILY_NAMES.map(family2),
|
|
105253
105770
|
{
|
|
105254
105771
|
name: "check",
|
|
@@ -105360,7 +105877,7 @@ var VERBS = [
|
|
|
105360
105877
|
},
|
|
105361
105878
|
{
|
|
105362
105879
|
name: "merge",
|
|
105363
|
-
usage: "workit pr merge [--pr <n>] [--method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch] [--unverified --reason <why>]",
|
|
105880
|
+
usage: "workit pr merge [--pr <n>] [--squash|--merge|--rebase | --method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch] [--unverified --reason <why>]",
|
|
105364
105881
|
summary: "Merge when READY, verified by a non-author and granted; --subject/--body set the squash message"
|
|
105365
105882
|
}
|
|
105366
105883
|
],
|
|
@@ -105794,7 +106311,9 @@ function closest(word, candidates) {
|
|
|
105794
106311
|
}
|
|
105795
106312
|
var COMMAND_HINTS = {
|
|
105796
106313
|
status: "workit task status (this branch's task) or workit pr status (its PR); workit handoff prints the whole picture",
|
|
105797
|
-
context: "workit handoff prints the branch, HEAD, dirty state, verdict and next command"
|
|
106314
|
+
context: "workit handoff prints the branch, HEAD, dirty state, verdict and next command",
|
|
106315
|
+
config: "workit grant show prints the workspace settings; workit doctor checks the install",
|
|
106316
|
+
issue: "workit youtrack <action> handles tracker issues; gh api repos/<owner>/<repo>/issues/<n> reads a GitHub one"
|
|
105798
106317
|
};
|
|
105799
106318
|
function commandUnblock(command) {
|
|
105800
106319
|
const near = closest(command, VERBS.filter((entry) => !entry.planned).map((entry) => entry.name));
|
|
@@ -105936,7 +106455,7 @@ var defaultIo = (json) => ({
|
|
|
105936
106455
|
});
|
|
105937
106456
|
async function main(argv, overrides = {}, options = {}) {
|
|
105938
106457
|
const parsed = parseGlobals(argv);
|
|
105939
|
-
const cwd =
|
|
106458
|
+
const cwd = path72.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
105940
106459
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
105941
106460
|
if (parsed.error)
|
|
105942
106461
|
return emit(io, fail2("invalid_input", parsed.error));
|