@brainervirus/workit-cli 8.34.0 → 8.35.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +339 -63
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -6401,9 +6401,16 @@ function workspaceDefaultTarget(cwd, globalDefault) {
|
|
|
6401
6401
|
}
|
|
6402
6402
|
var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspaceCommitPolicySchema, workspaceProfileSchema, versionSourceSchema, releaseTrackSchema, workspaceConfigSchema, workspacesFileSchema, workspacesRevision = (contents) => createHash("sha256").update(contents ?? "<missing>").digest("hex"), validateWorkspacesDocument = (parsed, file) => {
|
|
6403
6403
|
if (!isConfigObject(parsed)) {
|
|
6404
|
-
return {
|
|
6404
|
+
return {
|
|
6405
|
+
status: "malformed",
|
|
6406
|
+
path: file,
|
|
6407
|
+
entries: [],
|
|
6408
|
+
error: `${file} is not a JSON object`
|
|
6409
|
+
};
|
|
6405
6410
|
}
|
|
6406
|
-
const validated = workspacesFileSchema.safeParse(parsed, {
|
|
6411
|
+
const validated = workspacesFileSchema.safeParse(parsed, {
|
|
6412
|
+
reportInput: true
|
|
6413
|
+
});
|
|
6407
6414
|
if (!validated.success) {
|
|
6408
6415
|
const detail = validated.error.issues.map((issue) => {
|
|
6409
6416
|
const field = String(issue.path[issue.path.length - 1] ?? "");
|
|
@@ -6442,7 +6449,12 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6442
6449
|
raw = readFileSync2(file, "utf8");
|
|
6443
6450
|
} catch (error) {
|
|
6444
6451
|
if (error.code === "ENOENT")
|
|
6445
|
-
return {
|
|
6452
|
+
return {
|
|
6453
|
+
status: "missing",
|
|
6454
|
+
path: file,
|
|
6455
|
+
entries: [],
|
|
6456
|
+
revision: workspacesRevision(null)
|
|
6457
|
+
};
|
|
6446
6458
|
return {
|
|
6447
6459
|
status: "malformed",
|
|
6448
6460
|
path: file,
|
|
@@ -6462,7 +6474,10 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6462
6474
|
error: `${file} is not valid JSON`
|
|
6463
6475
|
};
|
|
6464
6476
|
}
|
|
6465
|
-
return {
|
|
6477
|
+
return {
|
|
6478
|
+
...validateWorkspacesDocument(parsed, file),
|
|
6479
|
+
revision: workspacesRevision(raw)
|
|
6480
|
+
};
|
|
6466
6481
|
}, loadWorkspacesFrom = (dir) => readWorkspacesResult(dir).entries, globToRegExp = (glob) => {
|
|
6467
6482
|
let out = "";
|
|
6468
6483
|
for (let i = 0;i < glob.length; i++) {
|
|
@@ -6591,7 +6606,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6591
6606
|
for (const b of entries.slice(i + 1)) {
|
|
6592
6607
|
const aInB = matchWorkspace(b.glob, globRoot(a.glob));
|
|
6593
6608
|
const bInA = matchWorkspace(a.glob, globRoot(b.glob));
|
|
6594
|
-
if (!aInB && !bInA)
|
|
6609
|
+
if (!aInB && !bInA && !globsMayOverlap(a.glob, b.glob))
|
|
6595
6610
|
continue;
|
|
6596
6611
|
const [inner, outer] = aInB && !bInA ? [a, b] : bInA && !aInB ? [b, a] : globSpecificity(a.glob) >= globSpecificity(b.glob) ? [a, b] : [b, a];
|
|
6597
6612
|
const si = globSpecificity(inner.glob);
|
|
@@ -6681,7 +6696,10 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6681
6696
|
return selected ? { file, selected, matches } : null;
|
|
6682
6697
|
}, resolveRuntimeReleaseTracks = (cwd) => {
|
|
6683
6698
|
const matched = matchRuntimeWorkspace(cwd);
|
|
6684
|
-
return matched ? {
|
|
6699
|
+
return matched ? {
|
|
6700
|
+
workspace: matched.selected.name,
|
|
6701
|
+
releaseTracks: matched.selected.releaseTracks
|
|
6702
|
+
} : null;
|
|
6685
6703
|
}, inheritedSetting = (cwd, dir, has) => {
|
|
6686
6704
|
let matched;
|
|
6687
6705
|
try {
|
|
@@ -6693,7 +6711,10 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6693
6711
|
return null;
|
|
6694
6712
|
const { selected, matches } = matched;
|
|
6695
6713
|
const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
|
|
6696
|
-
return {
|
|
6714
|
+
return {
|
|
6715
|
+
workspace: selected.name,
|
|
6716
|
+
source: [selected, ...enclosing].find(has) ?? null
|
|
6717
|
+
};
|
|
6697
6718
|
}, workspaceDeleteBranch = (cwd, dir) => inheritedSetting(cwd, dir, (entry) => typeof entry.deleteBranch === "boolean")?.source?.deleteBranch !== false, workspaceTrailers = (cwd, dir) => {
|
|
6698
6719
|
const found = inheritedSetting(cwd, dir, (entry) => typeof entry.trailers === "boolean");
|
|
6699
6720
|
return {
|
|
@@ -6821,7 +6842,10 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
6821
6842
|
status: "resolved",
|
|
6822
6843
|
profileName: null,
|
|
6823
6844
|
workspace: null,
|
|
6824
|
-
provenance: {
|
|
6845
|
+
provenance: {
|
|
6846
|
+
branchPolicy: "user-default",
|
|
6847
|
+
commitPolicy: "user-default"
|
|
6848
|
+
}
|
|
6825
6849
|
};
|
|
6826
6850
|
if (selected.status === "invalid")
|
|
6827
6851
|
return selected;
|
|
@@ -6892,7 +6916,11 @@ var init_workspaces = __esm(() => {
|
|
|
6892
6916
|
["requiredChecks", track.requiredChecks ?? []]
|
|
6893
6917
|
]) {
|
|
6894
6918
|
if (new Set(values).size !== values.length) {
|
|
6895
|
-
context.addIssue({
|
|
6919
|
+
context.addIssue({
|
|
6920
|
+
code: "custom",
|
|
6921
|
+
path: [field],
|
|
6922
|
+
message: "entries must be unique"
|
|
6923
|
+
});
|
|
6896
6924
|
}
|
|
6897
6925
|
}
|
|
6898
6926
|
if (track.versionSource?.kind === "package-json" && (path2.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
|
|
@@ -6925,7 +6953,10 @@ var init_workspaces = __esm(() => {
|
|
|
6925
6953
|
kind,
|
|
6926
6954
|
union([boolean2(), literal("verified")]).optional()
|
|
6927
6955
|
]))).passthrough().optional(),
|
|
6928
|
-
youtrack: object({
|
|
6956
|
+
youtrack: object({
|
|
6957
|
+
baseUrl: nonBlank.optional(),
|
|
6958
|
+
link_issues: boolean2().optional()
|
|
6959
|
+
}).passthrough().optional(),
|
|
6929
6960
|
issues: object({
|
|
6930
6961
|
provider: _enum(["github", "gitlab", "youtrack"]).optional(),
|
|
6931
6962
|
link: boolean2().optional(),
|
|
@@ -9286,7 +9317,7 @@ var package_default;
|
|
|
9286
9317
|
var init_package = __esm(() => {
|
|
9287
9318
|
package_default = {
|
|
9288
9319
|
name: "@brainervirus/workit-cli",
|
|
9289
|
-
version: "8.
|
|
9320
|
+
version: "8.35.2",
|
|
9290
9321
|
private: false,
|
|
9291
9322
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9292
9323
|
keywords: [
|
|
@@ -9324,13 +9355,13 @@ var init_package = __esm(() => {
|
|
|
9324
9355
|
},
|
|
9325
9356
|
dependencies: {
|
|
9326
9357
|
"@babel/parser": "7.29.9",
|
|
9327
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9358
|
+
"@brainervirus/workit-cursor": "^8.35.2",
|
|
9328
9359
|
"@inkjs/ui": "2.0.0",
|
|
9329
9360
|
ink: "7.1.1",
|
|
9330
9361
|
react: "19.2.8"
|
|
9331
9362
|
},
|
|
9332
9363
|
devDependencies: {
|
|
9333
|
-
"@brainervirus/workit-core": "^8.
|
|
9364
|
+
"@brainervirus/workit-core": "^8.35.2"
|
|
9334
9365
|
},
|
|
9335
9366
|
engines: {
|
|
9336
9367
|
node: ">=24"
|
|
@@ -14889,7 +14920,12 @@ function readLedger(cwd, options = {}) {
|
|
|
14889
14920
|
});
|
|
14890
14921
|
return {
|
|
14891
14922
|
ok: true,
|
|
14892
|
-
value: {
|
|
14923
|
+
value: {
|
|
14924
|
+
path: file.value,
|
|
14925
|
+
rows,
|
|
14926
|
+
skipped,
|
|
14927
|
+
integrity: options.integrity ? integrity : null
|
|
14928
|
+
}
|
|
14893
14929
|
};
|
|
14894
14930
|
}
|
|
14895
14931
|
function ledgerTampering(cwd) {
|
|
@@ -15014,7 +15050,10 @@ function branchScope(cwd, branch) {
|
|
|
15014
15050
|
return at >= since && at <= until;
|
|
15015
15051
|
};
|
|
15016
15052
|
}
|
|
15017
|
-
function authorSessions(cwd, rows, branch, range = {
|
|
15053
|
+
function authorSessions(cwd, rows, branch, range = {
|
|
15054
|
+
base: null,
|
|
15055
|
+
head: null
|
|
15056
|
+
}, scope = branchScope(cwd, branch)) {
|
|
15018
15057
|
const sessions = new Set;
|
|
15019
15058
|
for (const row of rows) {
|
|
15020
15059
|
if (!scope(row) || row.type !== "commit.recorded" && row.type !== "task.opened")
|
|
@@ -15089,12 +15128,13 @@ function restackCarries(exactIn, rows, branch, from, to) {
|
|
|
15089
15128
|
const cwd = exactIn;
|
|
15090
15129
|
let known = restackExact.get(row);
|
|
15091
15130
|
if (known === undefined) {
|
|
15092
|
-
|
|
15131
|
+
const range = typeof row.fromBase === "string" && typeof row.toBase === "string" ? {
|
|
15093
15132
|
from: fromHead,
|
|
15094
15133
|
to: head,
|
|
15095
15134
|
fromBase: row.fromBase,
|
|
15096
15135
|
toBase: row.toBase
|
|
15097
|
-
}
|
|
15136
|
+
} : null;
|
|
15137
|
+
known = range !== null && (sameOwnChange(cwd, range) || cleanRebase(cwd, range));
|
|
15098
15138
|
restackExact.set(row, known);
|
|
15099
15139
|
}
|
|
15100
15140
|
return known;
|
|
@@ -15129,7 +15169,10 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15129
15169
|
const cacheKey = `${base}\x00${at}`;
|
|
15130
15170
|
let key = keyCache.get(cacheKey);
|
|
15131
15171
|
if (!key) {
|
|
15132
|
-
key = {
|
|
15172
|
+
key = {
|
|
15173
|
+
patchId: patchId(cwd, base, at),
|
|
15174
|
+
diffHash: diffHash(cwd, base, at)
|
|
15175
|
+
};
|
|
15133
15176
|
keyCache.set(cacheKey, key);
|
|
15134
15177
|
}
|
|
15135
15178
|
return key;
|
|
@@ -15169,7 +15212,10 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15169
15212
|
};
|
|
15170
15213
|
const exactCarry = (row) => FAILING.has(String(row.result)) || exactMatch(row) !== null;
|
|
15171
15214
|
const keyBasis = (row) => {
|
|
15172
|
-
const basis = verdictBasis(row, {
|
|
15215
|
+
const basis = verdictBasis(row, {
|
|
15216
|
+
head,
|
|
15217
|
+
...keyFor(row.base ?? fallbackBase)
|
|
15218
|
+
});
|
|
15173
15219
|
return basis === "carried" && !exactCarry(row) ? "stale" : basis;
|
|
15174
15220
|
};
|
|
15175
15221
|
const rebaseNote = (row) => row.head && head && row.head !== head && !FAILING.has(String(row.result)) && keyBasis(row) === "carried" && exactMatch(row) === "rebase" ? { rule: "rebase", since: row.head, files: [] } : null;
|
|
@@ -15274,7 +15320,11 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15274
15320
|
const newestCurrent = verdicts.findLast((entry) => entry.current) ?? verdicts.at(-1) ?? null;
|
|
15275
15321
|
const failing = verdicts.find((entry) => entry.current && entry.independent && FAILING.has(String(entry.verdict.result)));
|
|
15276
15322
|
const newestAccepted = verdicts.findLast((entry) => entry.accepted && STRONG_RESULTS.has(String(entry.verdict.result))) ?? null;
|
|
15277
|
-
const accepted = tampered.length ? {
|
|
15323
|
+
const accepted = tampered.length ? {
|
|
15324
|
+
accepted: false,
|
|
15325
|
+
verdict: null,
|
|
15326
|
+
reasons: ["ledger_tampered"]
|
|
15327
|
+
} : newestAccepted && !failing ? { accepted: true, verdict: newestAccepted.verdict, reasons: [] } : {
|
|
15278
15328
|
accepted: false,
|
|
15279
15329
|
verdict: failing?.verdict ?? null,
|
|
15280
15330
|
reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
|
|
@@ -15292,7 +15342,10 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15292
15342
|
selfVerdict: accepted.accepted ? null : selfEntry?.verdict ?? null,
|
|
15293
15343
|
base: newestCurrent?.verdict.base ?? fallbackBase,
|
|
15294
15344
|
patchId: keyFor(newestCurrent?.verdict.base ?? fallbackBase).patchId,
|
|
15295
|
-
current: {
|
|
15345
|
+
current: {
|
|
15346
|
+
basis: newestCurrent?.basis ?? "none",
|
|
15347
|
+
verdict: newestCurrent?.verdict ?? null
|
|
15348
|
+
},
|
|
15296
15349
|
carry: carryEntry?.carry ?? null,
|
|
15297
15350
|
reverify,
|
|
15298
15351
|
accepted,
|
|
@@ -15531,10 +15584,18 @@ function recordVerdict(context, input) {
|
|
|
15531
15584
|
}
|
|
15532
15585
|
function untrackedField(cwd) {
|
|
15533
15586
|
const files = untrackedFiles2(cwd);
|
|
15534
|
-
return files.length ? {
|
|
15587
|
+
return files.length ? {
|
|
15588
|
+
untracked: files.slice(0, MAX_UNTRACKED_LISTED),
|
|
15589
|
+
untrackedCount: files.length
|
|
15590
|
+
} : {};
|
|
15535
15591
|
}
|
|
15536
15592
|
function recordHandoff(context, input) {
|
|
15537
|
-
return appendRow(context.cwd, {
|
|
15593
|
+
return appendRow(context.cwd, {
|
|
15594
|
+
...common(context, noteKey(context)),
|
|
15595
|
+
type: "handoff",
|
|
15596
|
+
note: input.note,
|
|
15597
|
+
next: input.next
|
|
15598
|
+
}, { now: context.now });
|
|
15538
15599
|
}
|
|
15539
15600
|
function rowLabels(row) {
|
|
15540
15601
|
const labels = [];
|
|
@@ -15689,7 +15750,11 @@ function buildHandoff(cwd, options = {}) {
|
|
|
15689
15750
|
}));
|
|
15690
15751
|
const lastHandoffRow = mine.findLast((row) => row.type === "handoff");
|
|
15691
15752
|
const partial = {
|
|
15692
|
-
store: {
|
|
15753
|
+
store: {
|
|
15754
|
+
root: store.value.root,
|
|
15755
|
+
shared: store.value.shared,
|
|
15756
|
+
ledger: ledger.path
|
|
15757
|
+
},
|
|
15693
15758
|
branch,
|
|
15694
15759
|
head,
|
|
15695
15760
|
subject: head ? git4(cwd, ["log", "-1", "--format=%s", head]) : null,
|
|
@@ -15722,7 +15787,11 @@ function buildHandoff(cwd, options = {}) {
|
|
|
15722
15787
|
const nextCommand = nextCommandFor(partial);
|
|
15723
15788
|
return {
|
|
15724
15789
|
ok: true,
|
|
15725
|
-
value: {
|
|
15790
|
+
value: {
|
|
15791
|
+
...partial,
|
|
15792
|
+
nextCommand,
|
|
15793
|
+
next: options.next?.trim() || nextCommand
|
|
15794
|
+
}
|
|
15726
15795
|
};
|
|
15727
15796
|
}
|
|
15728
15797
|
var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, VERDICT_RESULTS, PASSING, FAILING, STRONG_RESULTS, VERDICT_KINDS, VERDICT_SURFACES, PR_ROW_TYPES, err = (code, error, unblock) => ({
|
|
@@ -15887,7 +15956,11 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
15887
15956
|
if (entry[0] === "R" || entry[0] === "C")
|
|
15888
15957
|
index += 1;
|
|
15889
15958
|
}
|
|
15890
|
-
return {
|
|
15959
|
+
return {
|
|
15960
|
+
dirty: paths.length > 0,
|
|
15961
|
+
files: paths.length,
|
|
15962
|
+
paths: paths.slice(0, MAX_DIRTY_PATHS)
|
|
15963
|
+
};
|
|
15891
15964
|
}, nextCommandFor = (brief) => {
|
|
15892
15965
|
const branchFlag = brief.branch ? ` --branch ${brief.branch}` : "";
|
|
15893
15966
|
const verify = `workit ledger verdict verified${branchFlag} --how "<method and evidence>" (from a session that did not author the branch, with WORKIT_SESSION_ID set)`;
|
|
@@ -80235,6 +80308,22 @@ function implicitDeleteSkip(cwd, resolved, doc, branch) {
|
|
|
80235
80308
|
return `open PR ${children.data.map((n) => `#${n}`).join(", ")} targets ${branch} (a stack)`;
|
|
80236
80309
|
return null;
|
|
80237
80310
|
}
|
|
80311
|
+
function baseCiState(cwd, resolved, base) {
|
|
80312
|
+
if (!isProtectedTarget(cwd, base))
|
|
80313
|
+
return { ok: true, note: null };
|
|
80314
|
+
const read = resolved.forge.branchChecks(base);
|
|
80315
|
+
if (!read.ok)
|
|
80316
|
+
return { ok: true, note: `base ${base} CI not read (${read.error}); merging anyway` };
|
|
80317
|
+
const { requiredKnown } = read.data;
|
|
80318
|
+
const failing = read.data.checks.filter((check) => check.state === "failing" && (requiredKnown ? check.required === true : check.required !== false && check.conclusion === "failure"));
|
|
80319
|
+
if (failing.length)
|
|
80320
|
+
return { ok: false, failing, sha: read.data.sha, requiredKnown };
|
|
80321
|
+
const pending = read.data.checks.filter((check) => check.state === "pending");
|
|
80322
|
+
return {
|
|
80323
|
+
ok: true,
|
|
80324
|
+
note: pending.length ? `base ${base} CI is still running (${pending.map((check) => check.name).join(", ")}); merging without waiting` : null
|
|
80325
|
+
};
|
|
80326
|
+
}
|
|
80238
80327
|
async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
80239
80328
|
const grant = requireGrant(cwd, "merge");
|
|
80240
80329
|
if (!grant.allowed)
|
|
@@ -80244,6 +80333,9 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
80244
80333
|
return failure3("invalid_input", "--unverified needs --reason <why the user asked for it>");
|
|
80245
80334
|
if (bypass && !grant.allowUnverified)
|
|
80246
80335
|
return refuse(`unverified_refused: workspace ${grant.workspace ? `"${grant.workspace}"` : "(none)"} grants merge: "verified", which never merges without an accepted independent verdict`, "a non-author session verifies the head (workit-review), then merge without --unverified", { reason: "unverified_refused" });
|
|
80336
|
+
const baseRed = input.baseRedOk ?? null;
|
|
80337
|
+
if (baseRed && !baseRed.reason.trim())
|
|
80338
|
+
return failure3("invalid_input", "--base-red-ok needs --reason <why merging onto a red base is fine>");
|
|
80247
80339
|
const number = selectPr(cwd, resolved, { pr: input.pr });
|
|
80248
80340
|
if (!number.ok)
|
|
80249
80341
|
return number;
|
|
@@ -80328,6 +80420,15 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
80328
80420
|
const lane = gate.verification === "proportional" ? `, ${laneLabel(gate)}` : "";
|
|
80329
80421
|
return refuse(gate.need === "self" ? `NEEDS_VERDICT: ${label} has no verdict for ${head.slice(0, 12)}${lane}: the author's own --self verdict is enough (${check.accepted.reasons.join(", ")})` : `NEEDS_VERDICT: ${label} has no accepted independent verdict for ${head.slice(0, 12)}${lane} (${check.accepted.reasons.join(", ")})`, gate.need === "self" ? `after an observed passing \`workit check test\`, the author runs: workit ledger verdict tests-verified --self --how "<what you ran>" --branch ${branch} (or a verifier records one)${bypassHint}` : `an independent session verifies the head and runs: workit ledger verdict verified --how "<what was exercised>" --branch ${branch}${bypassHint}`, { reason: "needs_verdict", verdict: summary });
|
|
80330
80422
|
}
|
|
80423
|
+
const baseCi = baseCiState(cwd, resolved, doc.base);
|
|
80424
|
+
let baseRedOverride = null;
|
|
80425
|
+
if (!baseCi.ok) {
|
|
80426
|
+
const names = baseCi.failing.map((failed) => failed.name).join(", ");
|
|
80427
|
+
const url = baseCi.failing.find((failed) => failed.url)?.url ?? null;
|
|
80428
|
+
if (!baseRed)
|
|
80429
|
+
return refuse(`base_red: ${doc.base} at ${baseCi.sha?.slice(0, 12) ?? "its head"} has failing CI (${names}${baseCi.requiredKnown ? "" : "; the required checks could not be read, so every failed check counts"})${url ? `: ${url}` : ""}; merging ${label} onto it would land on a red base`, `fix ${doc.base} first, or, if the user accepts it: workit pr merge${input.pr ? ` --pr ${doc.number}` : ""} --base-red-ok --reason "<why>"`, { reason: "base_red", blockers: baseCi.failing.map((failed) => failed.name) });
|
|
80430
|
+
baseRedOverride = baseRed;
|
|
80431
|
+
}
|
|
80331
80432
|
const squashMessage = squashMessageFor(cwd, resolved, input, doc);
|
|
80332
80433
|
if (squashMessage && !squashMessage.ok)
|
|
80333
80434
|
return squashMessage;
|
|
@@ -80343,6 +80444,7 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
80343
80444
|
review: verdict.review,
|
|
80344
80445
|
lane: verdict.lane,
|
|
80345
80446
|
...unverified ? { unverified: unverified.recorded } : {},
|
|
80447
|
+
...baseRedOverride ? { baseRedOk: baseRedOverride.reason } : {},
|
|
80346
80448
|
grant: grant.source
|
|
80347
80449
|
});
|
|
80348
80450
|
if (!intent.ok)
|
|
@@ -80371,6 +80473,7 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
80371
80473
|
review: verdict.review,
|
|
80372
80474
|
lane: verdict.lane,
|
|
80373
80475
|
...unverified ? { unverified: unverified.recorded } : {},
|
|
80476
|
+
...baseRedOverride ? { baseRedOk: baseRedOverride.reason } : {},
|
|
80374
80477
|
grant: grant.source,
|
|
80375
80478
|
intent: intentId,
|
|
80376
80479
|
verified: false
|
|
@@ -80427,6 +80530,10 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
80427
80530
|
mergeSha: merged.data.mergeSha,
|
|
80428
80531
|
verdict,
|
|
80429
80532
|
unverified,
|
|
80533
|
+
baseCi: {
|
|
80534
|
+
note: baseRedOverride ? `base ${doc.base} CI is red; merged anyway (--base-red-ok: ${baseRedOverride.reason})` : baseCi.ok ? baseCi.note : null,
|
|
80535
|
+
override: baseRedOverride
|
|
80536
|
+
},
|
|
80430
80537
|
grant: { source: grant.source },
|
|
80431
80538
|
deletedBranch,
|
|
80432
80539
|
recorded,
|
|
@@ -80535,12 +80642,22 @@ function gitRestack(cwd, input) {
|
|
|
80535
80642
|
if (!dir) {
|
|
80536
80643
|
const scratch = scratchDir(cwd);
|
|
80537
80644
|
if (!scratch)
|
|
80538
|
-
return {
|
|
80645
|
+
return {
|
|
80646
|
+
ok: false,
|
|
80647
|
+
conflict: false,
|
|
80648
|
+
worktree: cwd,
|
|
80649
|
+
error: "no store root"
|
|
80650
|
+
};
|
|
80539
80651
|
fs28.mkdirSync(scratch, { recursive: true });
|
|
80540
80652
|
dir = path56.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
80541
80653
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
80542
80654
|
if (!added.ok)
|
|
80543
|
-
return {
|
|
80655
|
+
return {
|
|
80656
|
+
ok: false,
|
|
80657
|
+
conflict: false,
|
|
80658
|
+
worktree: cwd,
|
|
80659
|
+
error: firstLine(added)
|
|
80660
|
+
};
|
|
80544
80661
|
}
|
|
80545
80662
|
const run = gitRun3(dir, [
|
|
80546
80663
|
"-c",
|
|
@@ -80563,7 +80680,12 @@ function gitRestack(cwd, input) {
|
|
|
80563
80680
|
error: `git rebase did not finish within ${stackDeps.rebaseTimeoutMs} ms`
|
|
80564
80681
|
};
|
|
80565
80682
|
if (rebaseInProgress(dir))
|
|
80566
|
-
return {
|
|
80683
|
+
return {
|
|
80684
|
+
ok: false,
|
|
80685
|
+
conflict: true,
|
|
80686
|
+
worktree: dir,
|
|
80687
|
+
error: firstLine(run)
|
|
80688
|
+
};
|
|
80567
80689
|
if (!owner)
|
|
80568
80690
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
80569
80691
|
return { ok: false, conflict: false, worktree: dir, error: firstLine(run) };
|
|
@@ -80571,7 +80693,12 @@ function gitRestack(cwd, input) {
|
|
|
80571
80693
|
if (!owner)
|
|
80572
80694
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
80573
80695
|
const head = branchTip(cwd, input.branch);
|
|
80574
|
-
return head ? { ok: true, head } : {
|
|
80696
|
+
return head ? { ok: true, head } : {
|
|
80697
|
+
ok: false,
|
|
80698
|
+
conflict: false,
|
|
80699
|
+
worktree: dir,
|
|
80700
|
+
error: `${input.branch} vanished`
|
|
80701
|
+
};
|
|
80575
80702
|
}
|
|
80576
80703
|
function pruneScratch(cwd) {
|
|
80577
80704
|
const scratch = scratchDir(cwd);
|
|
@@ -80696,7 +80823,10 @@ function listStacks(cwd) {
|
|
|
80696
80823
|
if (parsed && fileFor(parsed.name) === name)
|
|
80697
80824
|
out.push(parsed);
|
|
80698
80825
|
}
|
|
80699
|
-
return {
|
|
80826
|
+
return {
|
|
80827
|
+
ok: true,
|
|
80828
|
+
data: out.toSorted((a, b) => a.name.localeCompare(b.name))
|
|
80829
|
+
};
|
|
80700
80830
|
}
|
|
80701
80831
|
function selectStack(cwd, name) {
|
|
80702
80832
|
if (name !== null && !validName(name))
|
|
@@ -81041,7 +81171,10 @@ function statusDoc(ctx, pr) {
|
|
|
81041
81171
|
const status = ctx.resolved.forge.prStatus(pr);
|
|
81042
81172
|
if (!status.ok)
|
|
81043
81173
|
return status;
|
|
81044
|
-
return buildStatusDoc(ctx.cwd, ctx.resolved, status.data, {
|
|
81174
|
+
return buildStatusDoc(ctx.cwd, ctx.resolved, status.data, {
|
|
81175
|
+
logLines: 0,
|
|
81176
|
+
behind: false
|
|
81177
|
+
});
|
|
81045
81178
|
}
|
|
81046
81179
|
function prBinding(ctx, entry, doc) {
|
|
81047
81180
|
const label = noun2(ctx.resolved, entry.pr);
|
|
@@ -81061,7 +81194,10 @@ function prBinding(ctx, entry, doc) {
|
|
|
81061
81194
|
function repoMismatch(ctx, stack) {
|
|
81062
81195
|
const { kind, repo } = ctx.resolved.forge;
|
|
81063
81196
|
if (stack.repo && stack.repo !== repo || stack.forge && stack.forge !== kind)
|
|
81064
|
-
return stackFail("blocked", `repo_mismatch: stack ${stack.name} was planned on ${stack.forge ?? "?"} ${stack.repo ?? "?"}, but this checkout resolves to ${kind} ${repo}`, `workit stack plan --name ${stack.name} <branch…> # re-plan it here, or run from the right checkout`, {
|
|
81197
|
+
return stackFail("blocked", `repo_mismatch: stack ${stack.name} was planned on ${stack.forge ?? "?"} ${stack.repo ?? "?"}, but this checkout resolves to ${kind} ${repo}`, `workit stack plan --name ${stack.name} <branch…> # re-plan it here, or run from the right checkout`, {
|
|
81198
|
+
planned: { forge: stack.forge, repo: stack.repo },
|
|
81199
|
+
resolved: { forge: kind, repo }
|
|
81200
|
+
});
|
|
81065
81201
|
return null;
|
|
81066
81202
|
}
|
|
81067
81203
|
function qualify(ctx, stack, entry, doc, verdict, grant, binding = null, bypass = false) {
|
|
@@ -81202,7 +81338,11 @@ function detectMerged(ctx, cwd, stack, trunkSha, state) {
|
|
|
81202
81338
|
merged = tip !== null && hasOwnCommits(cwd, tip, entry.lastParentHead) && isAncestor2(cwd, tip, trunkSha);
|
|
81203
81339
|
}
|
|
81204
81340
|
if (merged) {
|
|
81205
|
-
entry.merged = {
|
|
81341
|
+
entry.merged = {
|
|
81342
|
+
pr: entry.pr,
|
|
81343
|
+
mergeSha: null,
|
|
81344
|
+
at: new Date().toISOString()
|
|
81345
|
+
};
|
|
81206
81346
|
newly.push({ branch: entry.branch, pr: entry.pr });
|
|
81207
81347
|
}
|
|
81208
81348
|
}
|
|
@@ -81216,18 +81356,31 @@ function pushBranch(cwd, actor, branch, priorTip) {
|
|
|
81216
81356
|
if (!remote.ok)
|
|
81217
81357
|
return stackFail(remote.code, remote.error);
|
|
81218
81358
|
if (remote.sha === plan.data.sha)
|
|
81219
|
-
return {
|
|
81359
|
+
return {
|
|
81360
|
+
ok: true,
|
|
81361
|
+
data: { pushed: false, forced: false, sha: plan.data.sha }
|
|
81362
|
+
};
|
|
81220
81363
|
const grant = requireGrant(cwd, "push", { forge: !plan.data.local });
|
|
81221
81364
|
if (!grant.allowed)
|
|
81222
|
-
return stackFail("blocked", grant.error, grant.unblock, {
|
|
81365
|
+
return stackFail("blocked", grant.error, grant.unblock, {
|
|
81366
|
+
reason: grant.reason
|
|
81367
|
+
});
|
|
81223
81368
|
const force = remote.sha !== null && !isAncestor2(cwd, remote.sha, plan.data.sha);
|
|
81224
81369
|
const expect = !force ? null : remote.sha === priorTip ? priorTip : recordedRemoteTip(cwd, plan.data) ?? null;
|
|
81225
|
-
const pushed = executePush(cwd, plan.data, {
|
|
81370
|
+
const pushed = executePush(cwd, plan.data, {
|
|
81371
|
+
forceWithLease: force,
|
|
81372
|
+
expect,
|
|
81373
|
+
actor
|
|
81374
|
+
});
|
|
81226
81375
|
if (!pushed.ok)
|
|
81227
81376
|
return { ...fromForge(pushed), data: { branch } };
|
|
81228
81377
|
return {
|
|
81229
81378
|
ok: true,
|
|
81230
|
-
data: {
|
|
81379
|
+
data: {
|
|
81380
|
+
pushed: pushed.data.pushed,
|
|
81381
|
+
forced: pushed.data.forced,
|
|
81382
|
+
sha: plan.data.sha
|
|
81383
|
+
}
|
|
81231
81384
|
};
|
|
81232
81385
|
}
|
|
81233
81386
|
function syncStack(cwd, ctx, stack, options, actor) {
|
|
@@ -81337,7 +81490,11 @@ function syncStack(cwd, ctx, stack, options, actor) {
|
|
|
81337
81490
|
worktree: rebased.worktree,
|
|
81338
81491
|
progress: outcome
|
|
81339
81492
|
});
|
|
81340
|
-
return rebased.conflict ? stackFail("blocked", `conflict restacking ${entry.branch} onto ${parent.name}: ${rebased.error}`, `resolve the conflicts in ${rebased.worktree}, git rebase --continue, then workit stack sync # or git rebase --abort`, {
|
|
81493
|
+
return rebased.conflict ? stackFail("blocked", `conflict restacking ${entry.branch} onto ${parent.name}: ${rebased.error}`, `resolve the conflicts in ${rebased.worktree}, git rebase --continue, then workit stack sync # or git rebase --abort`, {
|
|
81494
|
+
conflict: entry.branch,
|
|
81495
|
+
worktree: rebased.worktree,
|
|
81496
|
+
progress: outcome
|
|
81497
|
+
}) : stackFail("failed", `restacking ${entry.branch} failed: ${rebased.error}`, undefined, {
|
|
81341
81498
|
branch: entry.branch,
|
|
81342
81499
|
progress: outcome
|
|
81343
81500
|
});
|
|
@@ -81397,8 +81554,16 @@ function syncStack(cwd, ctx, stack, options, actor) {
|
|
|
81397
81554
|
p: patchId(cwd, fromBase, fromHead),
|
|
81398
81555
|
d: diffHash(cwd, fromBase, fromHead)
|
|
81399
81556
|
};
|
|
81400
|
-
const after = {
|
|
81401
|
-
|
|
81557
|
+
const after = {
|
|
81558
|
+
p: patchId(cwd, parentTip, newTip),
|
|
81559
|
+
d: diffHash(cwd, parentTip, newTip)
|
|
81560
|
+
};
|
|
81561
|
+
const equal = before.d !== null && before.d === after.d && before.p !== null && before.p === after.p && sameOwnChange(cwd, {
|
|
81562
|
+
from: fromHead,
|
|
81563
|
+
to: newTip,
|
|
81564
|
+
fromBase,
|
|
81565
|
+
toBase: parentTip
|
|
81566
|
+
});
|
|
81402
81567
|
appendObserved(cwd, {
|
|
81403
81568
|
type: "stack.restacked",
|
|
81404
81569
|
actor,
|
|
@@ -81416,7 +81581,12 @@ function syncStack(cwd, ctx, stack, options, actor) {
|
|
|
81416
81581
|
if (step.restack)
|
|
81417
81582
|
step.restack.carried = equal;
|
|
81418
81583
|
else
|
|
81419
|
-
step.restack = {
|
|
81584
|
+
step.restack = {
|
|
81585
|
+
from: fromBase,
|
|
81586
|
+
onto: parentTip,
|
|
81587
|
+
head: newTip,
|
|
81588
|
+
carried: equal
|
|
81589
|
+
};
|
|
81420
81590
|
}
|
|
81421
81591
|
if (options.publish) {
|
|
81422
81592
|
touchStackLock();
|
|
@@ -81445,7 +81615,10 @@ function syncStack(cwd, ctx, stack, options, actor) {
|
|
|
81445
81615
|
});
|
|
81446
81616
|
const updated = ctx.resolved.forge.updateBase(entry.pr, parent.name);
|
|
81447
81617
|
if (!updated.ok)
|
|
81448
|
-
return {
|
|
81618
|
+
return {
|
|
81619
|
+
...fromForge(updated),
|
|
81620
|
+
data: { branch: entry.branch, progress: outcome }
|
|
81621
|
+
};
|
|
81449
81622
|
appendObserved(cwd, {
|
|
81450
81623
|
type: "pr.retargeted",
|
|
81451
81624
|
actor,
|
|
@@ -81520,7 +81693,9 @@ async function landStack(ctx, stack, options) {
|
|
|
81520
81693
|
if (bypass) {
|
|
81521
81694
|
const grant = requireGrant(ctx.cwd, "merge");
|
|
81522
81695
|
if (!grant.allowed)
|
|
81523
|
-
return failWith(stackFail("blocked", grant.error, grant.unblock, {
|
|
81696
|
+
return failWith(stackFail("blocked", grant.error, grant.unblock, {
|
|
81697
|
+
reason: "grant_required"
|
|
81698
|
+
}));
|
|
81524
81699
|
if (!grant.allowUnverified)
|
|
81525
81700
|
return failWith(stackFail("blocked", `unverified_refused: workspace ${grant.workspace ? `"${grant.workspace}"` : "(none)"} grants merge: "verified", which never lands without an accepted independent verdict`, "a non-author session verifies each head (workit-review), then land without --unverified", { reason: "unverified_refused" }));
|
|
81526
81701
|
}
|
|
@@ -81593,7 +81768,8 @@ async function landStack(ctx, stack, options) {
|
|
|
81593
81768
|
deleteBranch: false,
|
|
81594
81769
|
actor: ctx.actor,
|
|
81595
81770
|
expect: { base: stack.trunk, branch: entry.branch },
|
|
81596
|
-
...bypass && !verdict.satisfied ? { unverified: bypass } : {}
|
|
81771
|
+
...bypass && !verdict.satisfied ? { unverified: bypass } : {},
|
|
81772
|
+
...options.baseRedOk ? { baseRedOk: options.baseRedOk } : {}
|
|
81597
81773
|
}, ctx.sleep);
|
|
81598
81774
|
if (!merged.ok) {
|
|
81599
81775
|
if (merged.code === "blocked" && "refusal" in merged && merged.refusal) {
|
|
@@ -81615,7 +81791,11 @@ async function landStack(ctx, stack, options) {
|
|
|
81615
81791
|
mergeSha: merged.data.mergeSha,
|
|
81616
81792
|
unverified: merged.data.unverified?.recorded ?? null
|
|
81617
81793
|
});
|
|
81618
|
-
entry.merged = {
|
|
81794
|
+
entry.merged = {
|
|
81795
|
+
pr,
|
|
81796
|
+
mergeSha: merged.data.mergeSha,
|
|
81797
|
+
at: new Date().toISOString()
|
|
81798
|
+
};
|
|
81619
81799
|
const written = writeStack(ctx.cwd, stack);
|
|
81620
81800
|
if (!written.ok)
|
|
81621
81801
|
return failWith(written);
|
|
@@ -82982,6 +83162,30 @@ function createGitHubForge(options) {
|
|
|
82982
83162
|
};
|
|
82983
83163
|
return success2(status);
|
|
82984
83164
|
},
|
|
83165
|
+
branchChecks(branch) {
|
|
83166
|
+
const contexts = [];
|
|
83167
|
+
let sha = null;
|
|
83168
|
+
let cursor = null;
|
|
83169
|
+
for (let page = 1;page <= maxPages; page += 1) {
|
|
83170
|
+
const data = graphql(BRANCH_CHECKS_QUERY, { owner, name, ref: `refs/heads/${branch}`, contexts: cursor }, `checks on ${branch}`);
|
|
83171
|
+
if (!data.ok)
|
|
83172
|
+
return data;
|
|
83173
|
+
const commit = data.data.repository?.object ?? null;
|
|
83174
|
+
if (!commit)
|
|
83175
|
+
return failure3("not_found", `branch ${branch} was not found`);
|
|
83176
|
+
sha = commit.oid ?? sha;
|
|
83177
|
+
const rollup = commit.statusCheckRollup;
|
|
83178
|
+
if (!rollup)
|
|
83179
|
+
break;
|
|
83180
|
+
contexts.push(...rollup.contexts.nodes);
|
|
83181
|
+
if (!rollup.contexts.pageInfo.hasNextPage)
|
|
83182
|
+
break;
|
|
83183
|
+
cursor = rollup.contexts.pageInfo.endCursor;
|
|
83184
|
+
}
|
|
83185
|
+
const required = requiredContexts(branch);
|
|
83186
|
+
const checks = latestPerName(contexts.map(checkFromContext).filter((check) => check !== null)).map((check) => required ? { ...check, required: required.includes(check.context) } : check);
|
|
83187
|
+
return success2({ sha, checks, requiredKnown: required !== null });
|
|
83188
|
+
},
|
|
82985
83189
|
jobLogTail(job, lines) {
|
|
82986
83190
|
const text = apiText(runner, "gh", apiHost, ["api", `repos/${repo}/actions/jobs/${job.jobId}/logs`], `job ${job.jobId} log`, FORGE_TIMEOUTS.log);
|
|
82987
83191
|
return text.ok ? success2(logTail(text.data, lines)) : text;
|
|
@@ -83179,7 +83383,7 @@ function createGitHubForge(options) {
|
|
|
83179
83383
|
}
|
|
83180
83384
|
};
|
|
83181
83385
|
}
|
|
83182
|
-
var GITHUB_MAX_PAGES = 10, PR_FIELDS = `number url state isDraft isInMergeQueue mergeable mergeStateStatus baseRefName baseRefOid baseRef { target { oid } } headRefName headRefOid reviewDecision`, THREADS = `reviewThreads(first: 100, after: $threads) { pageInfo { hasNextPage endCursor } nodes { id isResolved isOutdated path line comments(first: 1) { nodes { author { login __typename } body url } } } }`, CONTEXTS = `contexts(first: 100, after: $contexts) { pageInfo { hasNextPage endCursor } nodes { __typename ... on CheckRun { name status conclusion detailsUrl databaseId isRequired(pullRequestNumber: $number) checkSuite { workflowRun { databaseId workflow { name } } } } ... on StatusContext { context state targetUrl isRequired(pullRequestNumber: $number) } } }`, PR_STATUS_QUERY, FIND_PR_QUERY = `query($owner: String!, $name: String!, $head: String!) { repository(owner: $owner, name: $name) { pullRequests(headRefName: $head, first: 20, orderBy: { field: CREATED_AT, direction: DESC }) { nodes { number url state baseRefName headRefName headRefOid headRepositoryOwner { login } } } } }`, READY_MUTATION = `mutation($id: ID!) { markPullRequestReadyForReview(input: { pullRequestId: $id }) { pullRequest { isDraft } } }`, DRAFT_MUTATION = `mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { isDraft } } }`, REPLY_MUTATION = `mutation($thread: ID!, $body: String!) { addPullRequestReviewThreadReply(input: { pullRequestReviewThreadId: $thread, body: $body }) { comment { url } } }`, RESOLVE_MUTATION = `mutation($thread: ID!) { resolveReviewThread(input: { threadId: $thread }) { thread { isResolved } } }`, THREAD_QUERY = `query($thread: ID!) { node(id: $thread) { ... on PullRequestReviewThread { isResolved pullRequest { number } } } }`, prState = (value) => value === "MERGED" ? "merged" : value === "CLOSED" ? "closed" : "open", FAILING2, safeUrl = (value) => value ? redactText(value) : null, encodeRef = (ref) => ref.split("/").map(encodeURIComponent).join("/");
|
|
83386
|
+
var GITHUB_MAX_PAGES = 10, PR_FIELDS = `number url state isDraft isInMergeQueue mergeable mergeStateStatus baseRefName baseRefOid baseRef { target { oid } } headRefName headRefOid reviewDecision`, THREADS = `reviewThreads(first: 100, after: $threads) { pageInfo { hasNextPage endCursor } nodes { id isResolved isOutdated path line comments(first: 1) { nodes { author { login __typename } body url } } } }`, CONTEXTS = `contexts(first: 100, after: $contexts) { pageInfo { hasNextPage endCursor } nodes { __typename ... on CheckRun { name status conclusion detailsUrl databaseId isRequired(pullRequestNumber: $number) checkSuite { workflowRun { databaseId workflow { name } } } } ... on StatusContext { context state targetUrl isRequired(pullRequestNumber: $number) } } }`, PR_STATUS_QUERY, FIND_PR_QUERY = `query($owner: String!, $name: String!, $head: String!) { repository(owner: $owner, name: $name) { pullRequests(headRefName: $head, first: 20, orderBy: { field: CREATED_AT, direction: DESC }) { nodes { number url state baseRefName headRefName headRefOid headRepositoryOwner { login } } } } }`, BRANCH_CHECKS_QUERY = `query($owner: String!, $name: String!, $ref: String!, $contexts: String) { repository(owner: $owner, name: $name) { object(expression: $ref) { ... on Commit { oid statusCheckRollup { contexts(first: 100, after: $contexts) { pageInfo { hasNextPage endCursor } nodes { __typename ... on CheckRun { name status conclusion detailsUrl databaseId checkSuite { workflowRun { databaseId workflow { name } } } } ... on StatusContext { context state targetUrl } } } } } } } }`, READY_MUTATION = `mutation($id: ID!) { markPullRequestReadyForReview(input: { pullRequestId: $id }) { pullRequest { isDraft } } }`, DRAFT_MUTATION = `mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { isDraft } } }`, REPLY_MUTATION = `mutation($thread: ID!, $body: String!) { addPullRequestReviewThreadReply(input: { pullRequestReviewThreadId: $thread, body: $body }) { comment { url } } }`, RESOLVE_MUTATION = `mutation($thread: ID!) { resolveReviewThread(input: { threadId: $thread }) { thread { isResolved } } }`, THREAD_QUERY = `query($thread: ID!) { node(id: $thread) { ... on PullRequestReviewThread { isResolved pullRequest { number } } } }`, prState = (value) => value === "MERGED" ? "merged" : value === "CLOSED" ? "closed" : "open", FAILING2, safeUrl = (value) => value ? redactText(value) : null, encodeRef = (ref) => ref.split("/").map(encodeURIComponent).join("/");
|
|
83183
83387
|
var init_github = __esm(() => {
|
|
83184
83388
|
init_exec();
|
|
83185
83389
|
init_redact();
|
|
@@ -83380,6 +83584,35 @@ function createGitLabForge(options) {
|
|
|
83380
83584
|
};
|
|
83381
83585
|
return success2(status);
|
|
83382
83586
|
},
|
|
83587
|
+
branchChecks(branch) {
|
|
83588
|
+
const tip = baseTip(branch);
|
|
83589
|
+
if (!tip)
|
|
83590
|
+
return failure3("not_found", `branch ${branch} was not found`);
|
|
83591
|
+
const latest = apiJson(runner, "glab", apiHost, api(`${project}/pipelines?ref=${encodeURIComponent(branch)}&sha=${tip}&order_by=id&sort=desc&per_page=1`), `pipelines on ${branch}`);
|
|
83592
|
+
if (!latest.ok)
|
|
83593
|
+
return latest;
|
|
83594
|
+
const pipeline = Array.isArray(latest.data) ? latest.data[0] : undefined;
|
|
83595
|
+
if (!pipeline)
|
|
83596
|
+
return success2({ sha: tip, checks: [], requiredKnown: true });
|
|
83597
|
+
const scope = String(pipeline.project_id ?? encodeURIComponent(repo));
|
|
83598
|
+
const jobs = pages(`projects/${scope}/pipelines/${pipeline.id}/jobs`, `pipeline ${pipeline.id} jobs`);
|
|
83599
|
+
if (!jobs.ok)
|
|
83600
|
+
return jobs;
|
|
83601
|
+
const bridges = pages(`projects/${scope}/pipelines/${pipeline.id}/bridges`, `pipeline ${pipeline.id} bridges`);
|
|
83602
|
+
if (!bridges.ok)
|
|
83603
|
+
return bridges;
|
|
83604
|
+
const checks = [
|
|
83605
|
+
...jobs.data.items.map((job) => checkFromJob(job, pipeline.id, scope)),
|
|
83606
|
+
...bridges.data.items.map((bridge) => checkFromBridge(bridge, pipeline.id, scope))
|
|
83607
|
+
];
|
|
83608
|
+
if (stateOf(pipeline.status, false) === "failing" && !checks.some((check) => check.state === "failing"))
|
|
83609
|
+
checks.push(pipelineCheck("failing", pipeline.status, {
|
|
83610
|
+
id: pipeline.id,
|
|
83611
|
+
project_id: pipeline.project_id ?? 0,
|
|
83612
|
+
web_url: pipeline.web_url
|
|
83613
|
+
}));
|
|
83614
|
+
return success2({ sha: tip, checks, requiredKnown: true });
|
|
83615
|
+
},
|
|
83383
83616
|
jobLogTail(job, lines) {
|
|
83384
83617
|
const scope = job.scope ?? encodeURIComponent(repo);
|
|
83385
83618
|
const text = apiText(runner, "glab", apiHost, ["api", `projects/${scope}/jobs/${job.jobId}/trace`], `job ${job.jobId} trace`, FORGE_TIMEOUTS.log);
|
|
@@ -85487,6 +85720,7 @@ async function merge3(argv, io) {
|
|
|
85487
85720
|
"delete-branch": "boolean",
|
|
85488
85721
|
"keep-branch": "boolean",
|
|
85489
85722
|
unverified: "boolean",
|
|
85723
|
+
"base-red-ok": "boolean",
|
|
85490
85724
|
reason: "value",
|
|
85491
85725
|
subject: "value",
|
|
85492
85726
|
body: "value",
|
|
@@ -85494,7 +85728,11 @@ async function merge3(argv, io) {
|
|
|
85494
85728
|
});
|
|
85495
85729
|
if (typeof flags === "string")
|
|
85496
85730
|
return usage4(io, flags, MERGE_USAGE);
|
|
85497
|
-
const
|
|
85731
|
+
const baseRedOk = flags.booleans.has("base-red-ok");
|
|
85732
|
+
const baseRedReason = flags.values.reason?.trim();
|
|
85733
|
+
if (baseRedOk && !baseRedReason)
|
|
85734
|
+
return usage4(io, "--base-red-ok needs --reason <why merging onto a red base is fine>", MERGE_USAGE);
|
|
85735
|
+
const unverified = baseRedOk && !flags.booleans.has("unverified") ? null : unverifiedFlag(flags);
|
|
85498
85736
|
if (typeof unverified === "string")
|
|
85499
85737
|
return usage4(io, unverified, MERGE_USAGE);
|
|
85500
85738
|
if (flags.positionals.length)
|
|
@@ -85536,6 +85774,7 @@ async function merge3(argv, io) {
|
|
|
85536
85774
|
implicitDelete: !flags.booleans.has("keep-branch") && workspaceDeleteBranch(io.cwd),
|
|
85537
85775
|
actor: actorFromEnv(io.env),
|
|
85538
85776
|
...unverified ? { unverified } : {},
|
|
85777
|
+
...baseRedOk && baseRedReason ? { baseRedOk: { reason: baseRedReason } } : {},
|
|
85539
85778
|
...subject !== undefined ? { subject } : {},
|
|
85540
85779
|
...body !== undefined ? { body } : {}
|
|
85541
85780
|
}, forgeDeps.sleep);
|
|
@@ -85548,6 +85787,7 @@ async function merge3(argv, io) {
|
|
|
85548
85787
|
return emit(io, ok2({ ...result.data, localCleanup: cleanup }), (data) => [
|
|
85549
85788
|
`merged ${connected.data.forge.kind === "github" ? "PR #" : "MR !"}${data.number} (${data.method}) at head ${data.head.slice(0, 12)}${data.mergeSha ? ` -> ${data.mergeSha.slice(0, 12)}` : ""}`,
|
|
85550
85789
|
data.unverified ? `UNVERIFIED: merged without a verdict (--unverified: ${data.unverified.reason}); ledger ${data.unverified.recorded}` : `verdict ${data.verdict.verdictId ?? "?"} accepted for that head${data.verdict.cover ? ` (stack verdict on ${data.verdict.cover.branch} @ ${data.verdict.cover.head.slice(0, 12)})` : data.verdict.carry ? ` (${carryLabel(data.verdict.carry)})` : ""}`,
|
|
85790
|
+
...data.baseCi.note ? [data.baseCi.note] : [],
|
|
85551
85791
|
...data.mergeBack.length ? [
|
|
85552
85792
|
`merge back: ${data.base} is the ${data.mergeBackTrack} production branch; bring it into ${data.mergeBack.join(", ")}`
|
|
85553
85793
|
] : [],
|
|
@@ -85714,7 +85954,7 @@ async function run15(argv, io) {
|
|
|
85714
85954
|
return reply(rest, io);
|
|
85715
85955
|
return usage4(io, sub && !sub.startsWith("-") ? `unknown pr subcommand "${sub}"` : "missing pr subcommand", USAGE8);
|
|
85716
85956
|
}
|
|
85717
|
-
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 | --keep-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;
|
|
85957
|
+
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 | --keep-branch] [--unverified --reason <why>] [--base-red-ok --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;
|
|
85718
85958
|
var init_pr = __esm(() => {
|
|
85719
85959
|
init_autonomy();
|
|
85720
85960
|
init_issue_link();
|
|
@@ -87317,7 +87557,11 @@ __export(exports_stack, {
|
|
|
87317
87557
|
run: () => run20
|
|
87318
87558
|
});
|
|
87319
87559
|
async function plan(argv, io) {
|
|
87320
|
-
const flags = parseFlags(argv, {
|
|
87560
|
+
const flags = parseFlags(argv, {
|
|
87561
|
+
name: "value",
|
|
87562
|
+
trunk: "value",
|
|
87563
|
+
track: "value"
|
|
87564
|
+
});
|
|
87321
87565
|
if (typeof flags === "string")
|
|
87322
87566
|
return usage4(io, flags, PLAN_USAGE);
|
|
87323
87567
|
const name = flags.values.name ?? null;
|
|
@@ -87378,7 +87622,12 @@ async function status3(argv, io) {
|
|
|
87378
87622
|
const connected = connect(io, selected.data.branches[0]?.branch ?? null);
|
|
87379
87623
|
if (!connected.ok)
|
|
87380
87624
|
return forgeFail(io, connected);
|
|
87381
|
-
const result = stackStatus({
|
|
87625
|
+
const result = stackStatus({
|
|
87626
|
+
cwd: io.cwd,
|
|
87627
|
+
resolved: connected.data,
|
|
87628
|
+
actor: actorFromEnv(io.env),
|
|
87629
|
+
sleep: forgeDeps.sleep
|
|
87630
|
+
}, selected.data);
|
|
87382
87631
|
if (!result.ok)
|
|
87383
87632
|
return stackFailed(io, result);
|
|
87384
87633
|
return emit(io, ok2(result.data), (data) => [
|
|
@@ -87442,11 +87691,16 @@ async function land(argv, io) {
|
|
|
87442
87691
|
timeout: "value",
|
|
87443
87692
|
interval: "value",
|
|
87444
87693
|
unverified: "boolean",
|
|
87694
|
+
"base-red-ok": "boolean",
|
|
87445
87695
|
reason: "value"
|
|
87446
87696
|
});
|
|
87447
87697
|
if (typeof flags === "string")
|
|
87448
87698
|
return usage4(io, flags, LAND_USAGE);
|
|
87449
|
-
const
|
|
87699
|
+
const baseRedOk = flags.booleans.has("base-red-ok");
|
|
87700
|
+
const baseRedReason = flags.values.reason?.trim();
|
|
87701
|
+
if (baseRedOk && !baseRedReason)
|
|
87702
|
+
return usage4(io, "--base-red-ok needs --reason <why merging onto a red base is fine>", LAND_USAGE);
|
|
87703
|
+
const unverified = baseRedOk && !flags.booleans.has("unverified") ? null : unverifiedFlag(flags);
|
|
87450
87704
|
if (typeof unverified === "string")
|
|
87451
87705
|
return usage4(io, unverified, LAND_USAGE);
|
|
87452
87706
|
if (flags.positionals.length)
|
|
@@ -87479,7 +87733,15 @@ async function land(argv, io) {
|
|
|
87479
87733
|
resolved: connected.data,
|
|
87480
87734
|
actor: actorFromEnv(io.env),
|
|
87481
87735
|
sleep: forgeDeps.sleep
|
|
87482
|
-
}, fresh.data ?? selected.data, {
|
|
87736
|
+
}, fresh.data ?? selected.data, {
|
|
87737
|
+
dryRun: flags.booleans.has("dry-run"),
|
|
87738
|
+
max,
|
|
87739
|
+
method,
|
|
87740
|
+
timeoutMs,
|
|
87741
|
+
intervalMs,
|
|
87742
|
+
unverified,
|
|
87743
|
+
baseRedOk: baseRedOk && baseRedReason ? { reason: baseRedReason } : null
|
|
87744
|
+
});
|
|
87483
87745
|
});
|
|
87484
87746
|
if (!result.ok)
|
|
87485
87747
|
return stackFailed(io, result);
|
|
@@ -87508,7 +87770,10 @@ async function run20(argv, io) {
|
|
|
87508
87770
|
return land(rest, io);
|
|
87509
87771
|
return usage4(io, sub && !sub.startsWith("-") ? `unknown stack subcommand "${sub}"` : "missing stack subcommand", USAGE12);
|
|
87510
87772
|
}
|
|
87511
|
-
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, {
|
|
87773
|
+
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>] [--base-red-ok --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, {
|
|
87774
|
+
unblock: result.unblock,
|
|
87775
|
+
data: result.data ?? {}
|
|
87776
|
+
})), label3 = (forge, pr) => pr === null ? "no PR" : `${forge === "gitlab" ? "MR !" : "PR #"}${pr}`, renderSync = (data) => [
|
|
87512
87777
|
`${data.dryRun ? "would sync" : "synced"} stack ${data.name}${data.merged.length ? `; merged: ${data.merged.map((item) => item.branch).join(", ")}` : ""}`,
|
|
87513
87778
|
...data.steps.map((step) => [
|
|
87514
87779
|
` ${step.branch} on ${step.parent}:`,
|
|
@@ -105920,19 +106185,22 @@ function bounded(brief, cwd) {
|
|
|
105920
106185
|
file = path73.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
|
|
105921
106186
|
fs37.writeFileSync(file, `${[...body, ...tail].join(`
|
|
105922
106187
|
`)}
|
|
105923
|
-
`, {
|
|
106188
|
+
`, {
|
|
106189
|
+
mode: 384
|
|
106190
|
+
});
|
|
105924
106191
|
} catch {
|
|
105925
106192
|
file = null;
|
|
105926
106193
|
}
|
|
105927
106194
|
const pointer = `… cut to ${MAX_BRIEF_BYTES} bytes; full brief: ${file ?? "not written (workit handoff --json has it all)"}`;
|
|
106195
|
+
const cappedTail = tail.map(capLine);
|
|
105928
106196
|
const kept = [];
|
|
105929
106197
|
for (const line of body) {
|
|
105930
106198
|
const cut = line.length > 400 ? `${line.slice(0, 400)}…` : line;
|
|
105931
|
-
if (bytes([...kept, cut, pointer, ...
|
|
106199
|
+
if (bytes([...kept, cut, pointer, ...cappedTail]) > MAX_BRIEF_BYTES)
|
|
105932
106200
|
break;
|
|
105933
106201
|
kept.push(cut);
|
|
105934
106202
|
}
|
|
105935
|
-
return [...kept, pointer, ...
|
|
106203
|
+
return [...kept, pointer, ...cappedTail];
|
|
105936
106204
|
}
|
|
105937
106205
|
async function resumeBrief(argv, io) {
|
|
105938
106206
|
let values;
|
|
@@ -105954,7 +106222,9 @@ async function resumeBrief(argv, io) {
|
|
|
105954
106222
|
}
|
|
105955
106223
|
const last = values.last === undefined ? 10 : Number(values.last);
|
|
105956
106224
|
if (!Number.isInteger(last) || last < 1)
|
|
105957
|
-
return emit(io, fail2("invalid_input", "--last must be a positive integer", {
|
|
106225
|
+
return emit(io, fail2("invalid_input", "--last must be a positive integer", {
|
|
106226
|
+
unblock: USAGE19
|
|
106227
|
+
}));
|
|
105958
106228
|
const built = buildHandoff(io.cwd, {
|
|
105959
106229
|
last,
|
|
105960
106230
|
note: values.note ?? null,
|
|
@@ -105980,7 +106250,7 @@ async function run27(argv, io) {
|
|
|
105980
106250
|
}
|
|
105981
106251
|
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(`
|
|
105982
106252
|
`)}
|
|
105983
|
-
`)
|
|
106253
|
+
`), TAIL_LINE_BYTES = 480, capLine = (line) => Buffer.byteLength(line) <= TAIL_LINE_BYTES ? line : `${Buffer.from(line).subarray(0, TAIL_LINE_BYTES).toString().replace(/\uFFFD$/u, "")}… (cut)`;
|
|
105984
106254
|
var init_handoff = __esm(() => {
|
|
105985
106255
|
init_ledger();
|
|
105986
106256
|
init_output();
|
|
@@ -106020,13 +106290,19 @@ var FAMILY_ACTIONS = {
|
|
|
106020
106290
|
},
|
|
106021
106291
|
evidence: { record: "Record evidence against a task's requirements" },
|
|
106022
106292
|
finding: { record: "Record a finding", resolve: "Resolve a finding" },
|
|
106023
|
-
decision: {
|
|
106293
|
+
decision: {
|
|
106294
|
+
record: "Record a task decision",
|
|
106295
|
+
revoke: "Revoke a task decision"
|
|
106296
|
+
},
|
|
106024
106297
|
worker: {
|
|
106025
106298
|
assign: "Assign a worker to a task",
|
|
106026
106299
|
report: "Report a worker's result",
|
|
106027
106300
|
cancel: "Cancel a worker assignment"
|
|
106028
106301
|
},
|
|
106029
|
-
state: {
|
|
106302
|
+
state: {
|
|
106303
|
+
export: "Export a task's state (v1)",
|
|
106304
|
+
import: "Import an exported task state"
|
|
106305
|
+
}
|
|
106030
106306
|
};
|
|
106031
106307
|
var POLICY_JUDGE = "--judge risk=trivial|normal|high behavior=yes|no product-choice=yes|no plan=yes|no [--ref <path>]… [--why <reason>]";
|
|
106032
106308
|
var TASK_IMPLICIT = [
|
|
@@ -106317,7 +106593,7 @@ var VERBS = [
|
|
|
106317
106593
|
},
|
|
106318
106594
|
{
|
|
106319
106595
|
name: "merge",
|
|
106320
|
-
usage: "workit pr merge [--pr <n>] [--squash|--merge|--rebase | --method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch | --keep-branch] [--unverified --reason <why>]",
|
|
106596
|
+
usage: "workit pr merge [--pr <n>] [--squash|--merge|--rebase | --method squash|merge|rebase] [--subject <s>] [--body <b> | --body-file <f|->] [--delete-branch | --keep-branch] [--unverified --reason <why>] [--base-red-ok --reason <why>]",
|
|
106321
106597
|
summary: "Merge when READY, verified by a non-author and granted; --subject/--body set the squash message"
|
|
106322
106598
|
}
|
|
106323
106599
|
],
|
|
@@ -106460,7 +106736,7 @@ var VERBS = [
|
|
|
106460
106736
|
},
|
|
106461
106737
|
{
|
|
106462
106738
|
name: "land",
|
|
106463
|
-
usage: "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s]",
|
|
106739
|
+
usage: "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--base-red-ok --reason <why>] [--timeout 20m] [--interval 30s]",
|
|
106464
106740
|
summary: "Merge the stack root first, restacking the rest as each lands"
|
|
106465
106741
|
}
|
|
106466
106742
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.35.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@babel/parser": "7.29.9",
|
|
41
|
-
"@brainervirus/workit-cursor": "^8.
|
|
41
|
+
"@brainervirus/workit-cursor": "^8.35.2",
|
|
42
42
|
"@inkjs/ui": "2.0.0",
|
|
43
43
|
"ink": "7.1.1",
|
|
44
44
|
"react": "19.2.8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@brainervirus/workit-core": "^8.
|
|
47
|
+
"@brainervirus/workit-core": "^8.35.2"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|