@brainervirus/workit-cli 8.39.2 → 8.39.4
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 +413 -33
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -9317,7 +9317,7 @@ var package_default;
|
|
|
9317
9317
|
var init_package = __esm(() => {
|
|
9318
9318
|
package_default = {
|
|
9319
9319
|
name: "@brainervirus/workit-cli",
|
|
9320
|
-
version: "8.39.
|
|
9320
|
+
version: "8.39.4",
|
|
9321
9321
|
private: false,
|
|
9322
9322
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9323
9323
|
keywords: [
|
|
@@ -9355,13 +9355,13 @@ var init_package = __esm(() => {
|
|
|
9355
9355
|
},
|
|
9356
9356
|
dependencies: {
|
|
9357
9357
|
"@babel/parser": "7.29.9",
|
|
9358
|
-
"@brainervirus/workit-cursor": "^8.39.
|
|
9358
|
+
"@brainervirus/workit-cursor": "^8.39.4",
|
|
9359
9359
|
"@inkjs/ui": "2.0.0",
|
|
9360
9360
|
ink: "7.1.1",
|
|
9361
9361
|
react: "19.2.8"
|
|
9362
9362
|
},
|
|
9363
9363
|
devDependencies: {
|
|
9364
|
-
"@brainervirus/workit-core": "^8.39.
|
|
9364
|
+
"@brainervirus/workit-core": "^8.39.4"
|
|
9365
9365
|
},
|
|
9366
9366
|
engines: {
|
|
9367
9367
|
node: ">=24"
|
|
@@ -9462,6 +9462,11 @@ function detectedChecks(root) {
|
|
|
9462
9462
|
if (typeof script === "string" && script.trim() !== "")
|
|
9463
9463
|
add(scriptCheck(pm, name));
|
|
9464
9464
|
}
|
|
9465
|
+
for (const [name, script] of Object.entries(SCRIPT_CHECK_ALIASES)) {
|
|
9466
|
+
const body = scripts[script];
|
|
9467
|
+
if (typeof body === "string" && body.trim() !== "")
|
|
9468
|
+
add({ ...scriptCheck(pm, script), name });
|
|
9469
|
+
}
|
|
9465
9470
|
}
|
|
9466
9471
|
const plain = (name, argv) => ({ name, argv, accepts: [argv] });
|
|
9467
9472
|
if (read("go.mod") !== null)
|
|
@@ -9580,7 +9585,7 @@ function workitAvailable(env = process.env) {
|
|
|
9580
9585
|
function checkCommand(args, version, onPath = workitAvailable()) {
|
|
9581
9586
|
return onPath ? `workit check ${args}` : `npx -y @brainervirus/workit-cli@${version} check ${args}`;
|
|
9582
9587
|
}
|
|
9583
|
-
var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "workit.checks.json", WORKIT_GITIGNORE = `*
|
|
9588
|
+
var SCRIPT_CHECKS, SCRIPT_CHECK_ALIASES, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "workit.checks.json", WORKIT_GITIGNORE = `*
|
|
9584
9589
|
!risk-paths
|
|
9585
9590
|
`, isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SHELL_META, git3 = (cwd, args) => {
|
|
9586
9591
|
const run = spawnSync7("git", args, {
|
|
@@ -9610,6 +9615,7 @@ var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "wo
|
|
|
9610
9615
|
}, CHECK_NAME, GATES, sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]), workitOnPath;
|
|
9611
9616
|
var init_check_config = __esm(() => {
|
|
9612
9617
|
SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
|
|
9618
|
+
SCRIPT_CHECK_ALIASES = { packaging: "test:packaging" };
|
|
9613
9619
|
SHELL_META = /[|&;<>()$`\\*?[\]{}~!#]/u;
|
|
9614
9620
|
CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
|
|
9615
9621
|
GATES = ["testing", "verification"];
|
|
@@ -15571,6 +15577,7 @@ function recordVerdict(context, input) {
|
|
|
15571
15577
|
sessionSource: context.sessionSource ?? "env",
|
|
15572
15578
|
...context.sessionBound === true ? { sessionBound: true } : {},
|
|
15573
15579
|
evidenceRefs: input.evidenceRefs ?? [],
|
|
15580
|
+
...input.checkEvidence?.length ? { checkEvidence: input.checkEvidence } : {},
|
|
15574
15581
|
...untrackedField(context.cwd)
|
|
15575
15582
|
}, { now: context.now });
|
|
15576
15583
|
}
|
|
@@ -21298,7 +21305,10 @@ async function payloadValue(raw, deps) {
|
|
|
21298
21305
|
}
|
|
21299
21306
|
try {
|
|
21300
21307
|
const value = JSON.parse(source);
|
|
21301
|
-
return isObject7(value) ? { ok: true, value } : {
|
|
21308
|
+
return isObject7(value) ? { ok: true, value } : {
|
|
21309
|
+
ok: false,
|
|
21310
|
+
result: failure2("invalid_input", "payload must be a JSON object")
|
|
21311
|
+
};
|
|
21302
21312
|
} catch (error) {
|
|
21303
21313
|
return {
|
|
21304
21314
|
ok: false,
|
|
@@ -21493,7 +21503,11 @@ function laneOf(root) {
|
|
|
21493
21503
|
} catch {
|
|
21494
21504
|
verification = DEFAULT_VERIFICATION;
|
|
21495
21505
|
}
|
|
21496
|
-
const lane = branchLane(root, {
|
|
21506
|
+
const lane = branchLane(root, {
|
|
21507
|
+
head: null,
|
|
21508
|
+
workingTree: true,
|
|
21509
|
+
judgment: currentJudgment(root)
|
|
21510
|
+
});
|
|
21497
21511
|
return {
|
|
21498
21512
|
lane: lane.lane,
|
|
21499
21513
|
reasons: lane.reasons,
|
|
@@ -21567,7 +21581,69 @@ function printHuman(result, deps, handoff = false) {
|
|
|
21567
21581
|
write(stream, `policy gap: ${gap.reason}`);
|
|
21568
21582
|
}
|
|
21569
21583
|
}
|
|
21584
|
+
function runFindingList(argv, deps) {
|
|
21585
|
+
let json = false;
|
|
21586
|
+
let branch;
|
|
21587
|
+
let status;
|
|
21588
|
+
const fail = (message) => {
|
|
21589
|
+
if (json)
|
|
21590
|
+
jsonResult(outOf(deps), usage(message));
|
|
21591
|
+
else
|
|
21592
|
+
write(errOf(deps), `${message}
|
|
21593
|
+
usage: ${FINDING_LIST_USAGE}`);
|
|
21594
|
+
return 2;
|
|
21595
|
+
};
|
|
21596
|
+
for (let i = 0;i < argv.length; i += 1) {
|
|
21597
|
+
const eq = argv[i].startsWith("--") ? argv[i].indexOf("=") : -1;
|
|
21598
|
+
const token = eq > 0 ? argv[i].slice(0, eq) : argv[i];
|
|
21599
|
+
if (token === "--json")
|
|
21600
|
+
json = true;
|
|
21601
|
+
else if (token === "--branch" || token === "--status") {
|
|
21602
|
+
const value = eq > 0 ? argv[i].slice(eq + 1) : argv[++i];
|
|
21603
|
+
if (value === undefined || !value.trim())
|
|
21604
|
+
return fail(`${token} requires a value`);
|
|
21605
|
+
if (token === "--branch")
|
|
21606
|
+
branch = value;
|
|
21607
|
+
else
|
|
21608
|
+
status = value;
|
|
21609
|
+
} else
|
|
21610
|
+
return fail(`unknown argument: ${argv[i]}`);
|
|
21611
|
+
}
|
|
21612
|
+
if (status !== undefined && status !== "open" && status !== "resolved")
|
|
21613
|
+
return fail(`--status is open or resolved (got ${status})`);
|
|
21614
|
+
const store = new TaskStore(workspaceRootFor(deps));
|
|
21615
|
+
const index = store.listTaskIndex();
|
|
21616
|
+
const tasks = store.listTasks();
|
|
21617
|
+
const result = !index.ok ? index : !tasks.ok ? tasks : success(null, null, null);
|
|
21618
|
+
if (!result.ok || !index.ok || !tasks.ok) {
|
|
21619
|
+
if (json)
|
|
21620
|
+
jsonResult(outOf(deps), result);
|
|
21621
|
+
else
|
|
21622
|
+
printHuman(result, deps);
|
|
21623
|
+
return 1;
|
|
21624
|
+
}
|
|
21625
|
+
const keys = new Map(index.data.map((entry) => [entry.id, entry.key]));
|
|
21626
|
+
const rows = tasks.data.filter((task) => branch === undefined || keys.get(task.id) === branch).flatMap((task) => task.findings.filter((item) => status === undefined || item.data.disposition === "open" === (status === "open")).map((item) => ({
|
|
21627
|
+
id: item.id,
|
|
21628
|
+
taskId: task.id,
|
|
21629
|
+
branch: keys.get(task.id) ?? null,
|
|
21630
|
+
disposition: item.data.disposition,
|
|
21631
|
+
recordedAt: item.recordedAt,
|
|
21632
|
+
claim: item.data.claim
|
|
21633
|
+
})));
|
|
21634
|
+
const total = tasks.data.reduce((sum, task) => sum + task.findings.length, 0);
|
|
21635
|
+
if (json)
|
|
21636
|
+
jsonResult(outOf(deps), success(null, null, { findings: rows, total }));
|
|
21637
|
+
else if (!rows.length)
|
|
21638
|
+
write(outOf(deps), total ? `no findings match the filters (${total} finding${total === 1 ? "" : "s"} in all; drop --branch/--status to list them)` : "no findings recorded (record one: workit finding record --payload '{…}'); ledger rows hold verdicts and rulings, not findings");
|
|
21639
|
+
else
|
|
21640
|
+
for (const row of rows)
|
|
21641
|
+
write(outOf(deps), `${row.id} ${row.disposition}${row.branch ? ` [${row.branch}]` : ""} (task ${row.taskId}) ${row.claim}`);
|
|
21642
|
+
return 0;
|
|
21643
|
+
}
|
|
21570
21644
|
async function runTaskCommand(argv, deps = {}) {
|
|
21645
|
+
if (argv[0] === "finding" && argv[1] === "list")
|
|
21646
|
+
return runFindingList(argv.slice(2), deps);
|
|
21571
21647
|
const parsed = await parseTaskArgs(argv, deps);
|
|
21572
21648
|
if (!parsed.ok) {
|
|
21573
21649
|
if (parsed.json)
|
|
@@ -21580,7 +21656,9 @@ async function runTaskCommand(argv, deps = {}) {
|
|
|
21580
21656
|
const store = new TaskStore(root);
|
|
21581
21657
|
try {
|
|
21582
21658
|
const now = new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
21583
|
-
closeDeliveredTasks(store, now, {
|
|
21659
|
+
closeDeliveredTasks(store, now, {
|
|
21660
|
+
cached: parsed.parsed.action !== "list"
|
|
21661
|
+
});
|
|
21584
21662
|
} catch {}
|
|
21585
21663
|
const core = new WorkitCore(store, contextFor(root, parsed.parsed.actor !== undefined ? { ...deps, actor: parsed.parsed.actor } : deps));
|
|
21586
21664
|
let result;
|
|
@@ -21671,7 +21749,7 @@ var TASK_FAMILIES, workspaceRootFor = (deps = {}) => {
|
|
|
21671
21749
|
capabilities: deps.capabilities ?? [],
|
|
21672
21750
|
constraints: deps.constraints ?? [],
|
|
21673
21751
|
now: deps.now ?? (() => new Date().toISOString())
|
|
21674
|
-
});
|
|
21752
|
+
}), FINDING_LIST_USAGE = "workit finding list [--branch <b>] [--status open|resolved] [--json]";
|
|
21675
21753
|
var init_task = __esm(() => {
|
|
21676
21754
|
init_check_config();
|
|
21677
21755
|
init_autonomy();
|
|
@@ -21688,7 +21766,7 @@ var init_task = __esm(() => {
|
|
|
21688
21766
|
task: ["start", "list", "inspect", "revise", "progress", "pause", "resume", "close"],
|
|
21689
21767
|
policy: ["assess", "preview", "explain"],
|
|
21690
21768
|
evidence: ["record"],
|
|
21691
|
-
finding: ["record", "resolve"],
|
|
21769
|
+
finding: ["record", "resolve", "list"],
|
|
21692
21770
|
decision: ["record", "revoke"],
|
|
21693
21771
|
worker: ["assign", "report", "cancel"],
|
|
21694
21772
|
state: ["export", "import"]
|
|
@@ -78399,7 +78477,7 @@ var init_resources = __esm(() => {
|
|
|
78399
78477
|
init_checks3();
|
|
78400
78478
|
init_heavy();
|
|
78401
78479
|
init_heavy_scope();
|
|
78402
|
-
DEFAULT_HEAVY_CHECKS = ["test", "build"];
|
|
78480
|
+
DEFAULT_HEAVY_CHECKS = ["test", "build", "packaging"];
|
|
78403
78481
|
DEFAULT_LIGHT_CHECKS = ["lint", "typecheck", "format"];
|
|
78404
78482
|
SIZE = /^(\d+(?:\.\d+)?)([KMGT]?)$/iu;
|
|
78405
78483
|
PERCENT = /^(\d+(?:\.\d+)?)%$/u;
|
|
@@ -78617,28 +78695,39 @@ function countWarnings(log) {
|
|
|
78617
78695
|
return redactLog(log).replace(ANSI_COLOR, "").split(`
|
|
78618
78696
|
`).filter((line) => WARNING_LINE.test(line) && !NO_WARNINGS.test(line)).length;
|
|
78619
78697
|
}
|
|
78620
|
-
function boundedOutput(log, lines, stderr = "") {
|
|
78698
|
+
function boundedOutput(log, lines, stderr = "", failed = false) {
|
|
78621
78699
|
const all = tailLines(log, Number.MAX_SAFE_INTEGER);
|
|
78622
78700
|
if (all.length === 0)
|
|
78623
78701
|
return "";
|
|
78624
|
-
|
|
78702
|
+
const markers = failed ? [...new Set(all.filter((line) => FAILURE_LINE.test(line)))] : [];
|
|
78703
|
+
const listed = markers.slice(0, MAX_FAILURE_LINES);
|
|
78704
|
+
const more = markers.length - listed.length;
|
|
78705
|
+
const failureRoom = listed.length ? listed.length + 2 + (more > 0 ? 1 : 0) : 0;
|
|
78706
|
+
let shown = all.slice(-Math.max(1, lines - failureRoom));
|
|
78625
78707
|
const errors = tailLines(redactLog(stderr), STDERR_TAIL_LINES);
|
|
78626
78708
|
let missing = [];
|
|
78627
78709
|
if (errors.length) {
|
|
78628
78710
|
const tail = new Set(shown);
|
|
78629
78711
|
if (errors.some((line) => !tail.has(line))) {
|
|
78630
|
-
shown = all.slice(-Math.max(1, lines - errors.length - 2));
|
|
78712
|
+
shown = all.slice(-Math.max(1, lines - failureRoom - errors.length - 2));
|
|
78631
78713
|
const kept = new Set(shown);
|
|
78632
78714
|
missing = errors.filter((line) => !kept.has(line));
|
|
78633
78715
|
}
|
|
78634
78716
|
}
|
|
78635
78717
|
const omitted = all.length - shown.length;
|
|
78718
|
+
const inTail = new Set([...shown, ...missing]);
|
|
78719
|
+
const failures = listed.filter((line) => !inTail.has(line));
|
|
78720
|
+
const failureFooter = failures.length ? `… failures from the omitted lines:
|
|
78721
|
+
${failures.join(`
|
|
78722
|
+
`)}
|
|
78723
|
+
${more > 0 ? `+${more} more failures in the log
|
|
78724
|
+
` : ""}` : "";
|
|
78636
78725
|
const footer = missing.length ? `… the last stderr lines, which the merged log holds earlier:
|
|
78637
78726
|
${missing.join(`
|
|
78638
78727
|
`)}
|
|
78639
78728
|
` : "";
|
|
78640
78729
|
return `${omitted ? `… ${omitted} earlier line${omitted === 1 ? "" : "s"} omitted (the full log is named below; --full streams it)
|
|
78641
|
-
` : ""}${shown.join(`
|
|
78730
|
+
` : ""}${failureFooter}${shown.join(`
|
|
78642
78731
|
`)}
|
|
78643
78732
|
${footer}`;
|
|
78644
78733
|
}
|
|
@@ -78938,7 +79027,7 @@ async function run12(argv, io) {
|
|
|
78938
79027
|
`);
|
|
78939
79028
|
else {
|
|
78940
79029
|
if (!options.full)
|
|
78941
|
-
io.stdout(boundedOutput(result.log, OUTPUT_LINES, stderrTail));
|
|
79030
|
+
io.stdout(boundedOutput(result.log, OUTPUT_LINES, stderrTail, !passed));
|
|
78942
79031
|
io.stderr(`${summary}
|
|
78943
79032
|
`);
|
|
78944
79033
|
if (recordError && passed)
|
|
@@ -78955,7 +79044,7 @@ async function run12(argv, io) {
|
|
|
78955
79044
|
return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
|
|
78956
79045
|
return 0;
|
|
78957
79046
|
}
|
|
78958
|
-
var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--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(path53.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536;
|
|
79047
|
+
var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--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(path53.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536, FAILURE_LINE, MAX_FAILURE_LINES = 15;
|
|
78959
79048
|
var init_check = __esm(() => {
|
|
78960
79049
|
init_check_config();
|
|
78961
79050
|
init_checks3();
|
|
@@ -78976,6 +79065,7 @@ var init_check = __esm(() => {
|
|
|
78976
79065
|
ANSI_COLOR = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
78977
79066
|
WARNING_LINE = /^\s*(?:⚠|\[(?:WARN|WARNING|warn|warning)\]|(?:npm\s+)?(?:WARN\s|warn\s)|warn(?:ing)?(?:\[[^\]]*\])?:|\d+:\d+\s+warning\s|\S+\(\d+,\d+\):\s*warning\s|\S+:\d+:\d+:\s*warning\b)/;
|
|
78978
79067
|
NO_WARNINGS = /\b(?:no|0|zero|none)\s+warnings?\b/i;
|
|
79068
|
+
FAILURE_LINE = /^\s*(?:\(fail\)|FAIL\b|✗|error:)/u;
|
|
78979
79069
|
});
|
|
78980
79070
|
|
|
78981
79071
|
// packages/workit-cli/src/verbs/lock.ts
|
|
@@ -80398,6 +80488,67 @@ var init_pr_lane = __esm(() => {
|
|
|
80398
80488
|
init_lane();
|
|
80399
80489
|
});
|
|
80400
80490
|
|
|
80491
|
+
// packages/workit-core/src/core/policy/check-evidence.ts
|
|
80492
|
+
function neededChecks(lane, configured) {
|
|
80493
|
+
if (lane !== "focused" && lane !== "full")
|
|
80494
|
+
return [];
|
|
80495
|
+
const names = configured.filter((name) => name !== AGGREGATE);
|
|
80496
|
+
return names.length ? names : [...configured];
|
|
80497
|
+
}
|
|
80498
|
+
function localCheckRows(rows) {
|
|
80499
|
+
return rows.filter((row) => row.type === "check" && row.observer === "workit_cli").map((row) => ({
|
|
80500
|
+
name: String(row.name ?? ""),
|
|
80501
|
+
head: String(row.head ?? ""),
|
|
80502
|
+
dirty: row.dirty === true,
|
|
80503
|
+
passed: row.result === "passed"
|
|
80504
|
+
}));
|
|
80505
|
+
}
|
|
80506
|
+
function verdictEvidence(cwd, input) {
|
|
80507
|
+
const lane = branchLane(cwd, { base: input.base ?? null, head: input.head });
|
|
80508
|
+
return checkEvidence({
|
|
80509
|
+
lane: lane.lane,
|
|
80510
|
+
head: input.head,
|
|
80511
|
+
configured: gateCheckNames(loadCheckConfig(cwd), "verification"),
|
|
80512
|
+
local: localCheckRows(input.rows),
|
|
80513
|
+
ci: []
|
|
80514
|
+
});
|
|
80515
|
+
}
|
|
80516
|
+
function checkEvidence(input) {
|
|
80517
|
+
const ciCovers = input.lane === "focused";
|
|
80518
|
+
const needed = neededChecks(input.lane, input.configured).map((name) => {
|
|
80519
|
+
const last = input.local.findLast((row) => row.name === name && row.head === input.head && !row.dirty);
|
|
80520
|
+
if (last?.passed)
|
|
80521
|
+
return { name, status: "fresh", via: "local", ciCovers };
|
|
80522
|
+
const ci = input.ci.filter((check) => ciMatch(check, name));
|
|
80523
|
+
if (ci.some((check) => check.state === "failing"))
|
|
80524
|
+
return { name, status: "failing", via: "ci", ciCovers };
|
|
80525
|
+
if (last)
|
|
80526
|
+
return { name, status: "failing", via: "local", ciCovers };
|
|
80527
|
+
if (ciCovers && ci.some((check) => check.state === "passing"))
|
|
80528
|
+
return { name, status: "fresh", via: "ci", ciCovers };
|
|
80529
|
+
return { name, status: "missing", via: null, ciCovers };
|
|
80530
|
+
});
|
|
80531
|
+
return {
|
|
80532
|
+
lane: input.lane,
|
|
80533
|
+
head: input.head,
|
|
80534
|
+
needed,
|
|
80535
|
+
satisfied: needed.every((item) => item.status === "fresh")
|
|
80536
|
+
};
|
|
80537
|
+
}
|
|
80538
|
+
function evidenceLines(doc) {
|
|
80539
|
+
if (!doc.needed.length)
|
|
80540
|
+
return [`evidence: lane ${doc.lane} needs no check run`];
|
|
80541
|
+
return [
|
|
80542
|
+
`evidence for lane ${doc.lane} on ${doc.head.slice(0, 7)}: ${doc.satisfied ? "complete" : "incomplete"}`,
|
|
80543
|
+
...doc.needed.map((item) => ` ${item.status === "fresh" ? "ok" : "x"} ${item.name}: ${item.status}${item.via ? ` (${item.via})` : item.ciCovers ? " (run it, or green CI covers it)" : " (run workit check " + item.name + " on this head)"}`)
|
|
80544
|
+
];
|
|
80545
|
+
}
|
|
80546
|
+
var AGGREGATE = "check", ciMatch = (ci, name) => new RegExp(`(^|[^a-z0-9])${name.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}([^a-z0-9]|$)`, "iu").test(ci.name);
|
|
80547
|
+
var init_check_evidence = __esm(() => {
|
|
80548
|
+
init_check_config();
|
|
80549
|
+
init_lane();
|
|
80550
|
+
});
|
|
80551
|
+
|
|
80401
80552
|
// packages/workit-core/src/forge/reruns.ts
|
|
80402
80553
|
import fs27 from "node:fs";
|
|
80403
80554
|
import path58 from "node:path";
|
|
@@ -80614,6 +80765,14 @@ function selectPr(cwd, resolved, options) {
|
|
|
80614
80765
|
}
|
|
80615
80766
|
return success2(found.data.number);
|
|
80616
80767
|
}
|
|
80768
|
+
function evidenceFor(cwd, status, ci = status.checks) {
|
|
80769
|
+
const lane = branchLane(cwd, { base: status.base, head: status.head.sha });
|
|
80770
|
+
const configured = gateCheckNames(loadCheckConfig(cwd), "verification");
|
|
80771
|
+
const read = readLedger(cwd);
|
|
80772
|
+
const local = read.ok ? localCheckRows(read.value.rows) : [];
|
|
80773
|
+
const ciChecks = ci.flatMap((check) => check.state === "skipped" ? [] : [{ name: check.name, state: check.state }]);
|
|
80774
|
+
return checkEvidence({ lane: lane.lane, head: status.head.sha, configured, local, ci: ciChecks });
|
|
80775
|
+
}
|
|
80617
80776
|
function buildStatusDoc(cwd, resolved, status, options) {
|
|
80618
80777
|
const { forge } = resolved;
|
|
80619
80778
|
const reruns = rerunCounts(cwd, { repo: forge.repo, pr: status.number, head: status.head.sha });
|
|
@@ -80691,6 +80850,7 @@ function buildStatusDoc(cwd, resolved, status, options) {
|
|
|
80691
80850
|
passing: status.checks.filter((check) => check.state === "passing").length,
|
|
80692
80851
|
missingRequired: missing
|
|
80693
80852
|
},
|
|
80853
|
+
evidence: evidenceFor(cwd, status),
|
|
80694
80854
|
reviews: { decision: status.reviewDecision, unresolvedThreads: status.threads },
|
|
80695
80855
|
blockers: status.state === "open" ? blockers.map((blocker) => blocker.reason) : [],
|
|
80696
80856
|
identity: options.identity ?? null,
|
|
@@ -80874,6 +81034,9 @@ var MAX_LOG_TAILS = 5, GITLAB_MERGEABLE, GITHUB_MERGEABLE, NO_CHECKS_GRACE_MS =
|
|
|
80874
81034
|
var init_report2 = __esm(() => {
|
|
80875
81035
|
init_rev();
|
|
80876
81036
|
init_ledger();
|
|
81037
|
+
init_check_config();
|
|
81038
|
+
init_lane();
|
|
81039
|
+
init_check_evidence();
|
|
80877
81040
|
init_reruns();
|
|
80878
81041
|
GITLAB_MERGEABLE = new Set(["mergeable"]);
|
|
80879
81042
|
GITHUB_MERGEABLE = new Set(["clean", "unstable", "has_hooks"]);
|
|
@@ -86620,6 +86783,8 @@ function renderStatus(doc) {
|
|
|
86620
86783
|
lines.push(` - ${thread.path ? `${thread.path}${thread.line ? `:${thread.line}` : ""} ` : ""}@${thread.author ?? "?"}${thread.isBot ? " (bot)" : ""}: ${thread.body}`);
|
|
86621
86784
|
if (doc.truncated)
|
|
86622
86785
|
lines.push("(lists truncated at the page cap)");
|
|
86786
|
+
if (doc.evidence)
|
|
86787
|
+
lines.push(...evidenceLines(doc.evidence));
|
|
86623
86788
|
if (doc.blockers.length)
|
|
86624
86789
|
lines.push(`blockers: ${doc.blockers.join(", ")}`);
|
|
86625
86790
|
if (doc.identity?.note)
|
|
@@ -86636,6 +86801,7 @@ var forgeDeps, MAX_REASON = 500, usage4 = (io, message, line) => emit(io, fail2(
|
|
|
86636
86801
|
now: forgeDeps.now
|
|
86637
86802
|
}), short = (sha) => sha ? sha.slice(0, 7) : "?";
|
|
86638
86803
|
var init_forge_common = __esm(() => {
|
|
86804
|
+
init_check_evidence();
|
|
86639
86805
|
init_resolve();
|
|
86640
86806
|
init_vcs_config();
|
|
86641
86807
|
init_duration();
|
|
@@ -86652,10 +86818,124 @@ var init_forge_common = __esm(() => {
|
|
|
86652
86818
|
// packages/workit-cli/src/verbs/pr.ts
|
|
86653
86819
|
var exports_pr = {};
|
|
86654
86820
|
__export(exports_pr, {
|
|
86821
|
+
checkPrTitle: () => checkPrTitle,
|
|
86655
86822
|
run: () => run15
|
|
86656
86823
|
});
|
|
86657
|
-
import { readFileSync as readFileSync27 } from "node:fs";
|
|
86824
|
+
import { existsSync as existsSync26, readFileSync as readFileSync27 } from "node:fs";
|
|
86658
86825
|
import path66 from "node:path";
|
|
86826
|
+
function titleRules(cwd) {
|
|
86827
|
+
let root;
|
|
86828
|
+
try {
|
|
86829
|
+
root = checkRoot(cwd);
|
|
86830
|
+
} catch {
|
|
86831
|
+
return { rules: null, note: null };
|
|
86832
|
+
}
|
|
86833
|
+
let text = null;
|
|
86834
|
+
let name = "";
|
|
86835
|
+
for (const candidate of COMMITLINT_FILES) {
|
|
86836
|
+
const full = path66.join(root, candidate);
|
|
86837
|
+
if (!existsSync26(full))
|
|
86838
|
+
continue;
|
|
86839
|
+
text = readFileSync27(full, "utf8");
|
|
86840
|
+
name = candidate;
|
|
86841
|
+
break;
|
|
86842
|
+
}
|
|
86843
|
+
if (text === null) {
|
|
86844
|
+
try {
|
|
86845
|
+
const pkg = JSON.parse(readFileSync27(path66.join(root, "package.json"), "utf8"));
|
|
86846
|
+
if (pkg.commitlint === undefined)
|
|
86847
|
+
return { rules: null, note: null };
|
|
86848
|
+
text = JSON.stringify(pkg.commitlint);
|
|
86849
|
+
} catch {
|
|
86850
|
+
return { rules: null, note: null };
|
|
86851
|
+
}
|
|
86852
|
+
}
|
|
86853
|
+
if (/\.[cm]?[jt]s$/u.test(name))
|
|
86854
|
+
return UNCHECKED("JS/TS");
|
|
86855
|
+
let config;
|
|
86856
|
+
try {
|
|
86857
|
+
const parsed = JSON.parse(text);
|
|
86858
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
86859
|
+
return UNCHECKED("not a plain JSON object");
|
|
86860
|
+
config = parsed;
|
|
86861
|
+
} catch {
|
|
86862
|
+
return UNCHECKED(/\.ya?ml$|^\.commitlintrc$/u.test(name) ? "YAML" : "unreadable");
|
|
86863
|
+
}
|
|
86864
|
+
if (config.ignores !== undefined)
|
|
86865
|
+
return UNCHECKED("using custom ignores");
|
|
86866
|
+
const extend = config.extends === undefined ? [] : [config.extends].flat();
|
|
86867
|
+
const known = (entry) => typeof entry === "string" && /^(@commitlint\/)?config-conventional$/u.test(entry);
|
|
86868
|
+
if (!extend.every(known))
|
|
86869
|
+
return UNCHECKED("extending a shareable config");
|
|
86870
|
+
const rules = {
|
|
86871
|
+
types: null,
|
|
86872
|
+
maxHeader: null,
|
|
86873
|
+
format: 0,
|
|
86874
|
+
defaultIgnores: config.defaultIgnores !== false
|
|
86875
|
+
};
|
|
86876
|
+
if (extend.length) {
|
|
86877
|
+
rules.types = { level: 2, values: CONVENTIONAL_TYPES };
|
|
86878
|
+
rules.maxHeader = { level: 2, value: 100 };
|
|
86879
|
+
rules.format = 2;
|
|
86880
|
+
}
|
|
86881
|
+
const own = config.rules ?? {};
|
|
86882
|
+
const types = readRule(own, "type-enum");
|
|
86883
|
+
if (types === "off")
|
|
86884
|
+
rules.types = null;
|
|
86885
|
+
else if (types && Array.isArray(types.value))
|
|
86886
|
+
rules.types = { level: types.level, values: types.value.map(String) };
|
|
86887
|
+
const max = readRule(own, "header-max-length");
|
|
86888
|
+
if (max === "off")
|
|
86889
|
+
rules.maxHeader = null;
|
|
86890
|
+
else if (max && typeof max.value === "number")
|
|
86891
|
+
rules.maxHeader = { level: max.level, value: max.value };
|
|
86892
|
+
for (const rule of ["type-empty", "subject-empty"]) {
|
|
86893
|
+
const read = readRule(own, rule);
|
|
86894
|
+
if (read === "off")
|
|
86895
|
+
rules.format = 0;
|
|
86896
|
+
else if (read)
|
|
86897
|
+
rules.format = Math.max(rules.format, read.level);
|
|
86898
|
+
}
|
|
86899
|
+
return { rules, note: null };
|
|
86900
|
+
}
|
|
86901
|
+
function checkPrTitle(cwd, title) {
|
|
86902
|
+
const { rules, note } = titleRules(cwd);
|
|
86903
|
+
if (!rules)
|
|
86904
|
+
return { error: null, notes: note ? [note] : [] };
|
|
86905
|
+
const header = title.split(`
|
|
86906
|
+
`, 1)[0] ?? "";
|
|
86907
|
+
if (rules.defaultIgnores && DEFAULT_IGNORES.some((pattern) => pattern.test(title)))
|
|
86908
|
+
return { error: null, notes: [] };
|
|
86909
|
+
const problems = [];
|
|
86910
|
+
const parsed = /^(\w*)(?:\((.*)\))?!?: (.*)$/u.exec(header);
|
|
86911
|
+
if (rules.format && (!parsed || !parsed[1] || !parsed[3]?.trim()))
|
|
86912
|
+
problems.push({
|
|
86913
|
+
level: rules.format,
|
|
86914
|
+
message: `PR title ${JSON.stringify(header)} is not a Conventional Commit "<type>(<scope>): <subject>" (commitlint type-empty/subject-empty); the squash-merge title is the commit and CI lints it`
|
|
86915
|
+
});
|
|
86916
|
+
else if (parsed && rules.types && !rules.types.values.includes(parsed[1]))
|
|
86917
|
+
problems.push({
|
|
86918
|
+
level: rules.types.level,
|
|
86919
|
+
message: `PR title type "${parsed[1]}" is not allowed (commitlint type-enum: ${rules.types.values.join(", ")})`
|
|
86920
|
+
});
|
|
86921
|
+
if (rules.maxHeader && header.length > rules.maxHeader.value)
|
|
86922
|
+
problems.push({
|
|
86923
|
+
level: rules.maxHeader.level,
|
|
86924
|
+
message: `PR title is ${header.length} characters, over the ${rules.maxHeader.value} allowed (commitlint header-max-length); shorten it by ${header.length - rules.maxHeader.value}`
|
|
86925
|
+
});
|
|
86926
|
+
const refused = problems.filter((problem) => problem.level >= 2);
|
|
86927
|
+
return {
|
|
86928
|
+
error: refused.length ? refused.map((problem) => problem.message).join("; ") : null,
|
|
86929
|
+
notes: problems.filter((problem) => problem.level < 2).map((p) => `warning: ${p.message}`)
|
|
86930
|
+
};
|
|
86931
|
+
}
|
|
86932
|
+
function refuseTitle(io, title, line) {
|
|
86933
|
+
const checked = checkPrTitle(io.cwd, title);
|
|
86934
|
+
for (const note of checked.notes)
|
|
86935
|
+
io.stderr(`${note}
|
|
86936
|
+
`);
|
|
86937
|
+
return checked.error ? usage4(io, checked.error, line) : null;
|
|
86938
|
+
}
|
|
86659
86939
|
function readBodyFile(io, file) {
|
|
86660
86940
|
try {
|
|
86661
86941
|
return {
|
|
@@ -86825,6 +87105,9 @@ async function create4(argv, io) {
|
|
|
86825
87105
|
}
|
|
86826
87106
|
if (!base)
|
|
86827
87107
|
return usage4(io, "no default target branch is configured; pass --base <b>", CREATE_USAGE);
|
|
87108
|
+
const given = flags.values.title ? refuseTitle(io, flags.values.title, CREATE_USAGE) : null;
|
|
87109
|
+
if (given !== null)
|
|
87110
|
+
return given;
|
|
86828
87111
|
const connected = connect(io, branch);
|
|
86829
87112
|
if (!connected.ok)
|
|
86830
87113
|
return forgeFail(io, connected);
|
|
@@ -86836,6 +87119,11 @@ async function create4(argv, io) {
|
|
|
86836
87119
|
title ||= filled.data.title;
|
|
86837
87120
|
body ??= filled.data.body;
|
|
86838
87121
|
}
|
|
87122
|
+
if (!flags.values.title) {
|
|
87123
|
+
const filled = refuseTitle(io, title, CREATE_USAGE);
|
|
87124
|
+
if (filled !== null)
|
|
87125
|
+
return filled;
|
|
87126
|
+
}
|
|
86839
87127
|
const forge = connected.data.forge;
|
|
86840
87128
|
const planned = planIssueLinks(io.cwd, {
|
|
86841
87129
|
issues: flags.lists.issue ?? [],
|
|
@@ -87054,6 +87342,11 @@ async function edit(argv, io) {
|
|
|
87054
87342
|
return usage4(io, read, EDIT_USAGE);
|
|
87055
87343
|
body = read.body;
|
|
87056
87344
|
}
|
|
87345
|
+
if (flags.values.title !== undefined) {
|
|
87346
|
+
const edited = refuseTitle(io, flags.values.title, EDIT_USAGE);
|
|
87347
|
+
if (edited !== null)
|
|
87348
|
+
return edited;
|
|
87349
|
+
}
|
|
87057
87350
|
const connected = connect(io);
|
|
87058
87351
|
if (!connected.ok)
|
|
87059
87352
|
return forgeFail(io, connected);
|
|
@@ -87156,7 +87449,19 @@ async function run15(argv, io) {
|
|
|
87156
87449
|
return reply(rest, io);
|
|
87157
87450
|
return usage4(io, sub && !sub.startsWith("-") ? `unknown pr subcommand "${sub}"` : "missing pr subcommand", USAGE9);
|
|
87158
87451
|
}
|
|
87159
|
-
var
|
|
87452
|
+
var CONVENTIONAL_TYPES, COMMITLINT_FILES, DEFAULT_IGNORES, UNCHECKED = (what) => ({
|
|
87453
|
+
rules: null,
|
|
87454
|
+
note: `commitlint config is ${what}; title not pre-checked, CI checks it`
|
|
87455
|
+
}), readRule = (rules, name) => {
|
|
87456
|
+
const rule = rules[name];
|
|
87457
|
+
if (rule === undefined)
|
|
87458
|
+
return null;
|
|
87459
|
+
if (!Array.isArray(rule) || typeof rule[0] !== "number")
|
|
87460
|
+
return "off";
|
|
87461
|
+
if (rule[0] === 0 || rule[1] === "never")
|
|
87462
|
+
return "off";
|
|
87463
|
+
return { level: rule[0], value: rule[2] };
|
|
87464
|
+
}, 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]", USAGE9 = "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)" : ""}`, mergedOnLine = (verdict) => {
|
|
87160
87465
|
if (verdict.review === "self-reviewed")
|
|
87161
87466
|
return `self-reviewed (lane ${verdict.lane}): the author's verdict ${verdict.verdictId ?? "?"}; no independent verdict accepted for that head`;
|
|
87162
87467
|
if (!verdict.verdictId)
|
|
@@ -87180,8 +87485,48 @@ var init_pr = __esm(() => {
|
|
|
87180
87485
|
init_lane();
|
|
87181
87486
|
init_pr_lane();
|
|
87182
87487
|
init_vcs_config();
|
|
87488
|
+
init_check_config();
|
|
87183
87489
|
init_output();
|
|
87184
87490
|
init_forge_common();
|
|
87491
|
+
CONVENTIONAL_TYPES = [
|
|
87492
|
+
"build",
|
|
87493
|
+
"chore",
|
|
87494
|
+
"ci",
|
|
87495
|
+
"docs",
|
|
87496
|
+
"feat",
|
|
87497
|
+
"fix",
|
|
87498
|
+
"perf",
|
|
87499
|
+
"refactor",
|
|
87500
|
+
"revert",
|
|
87501
|
+
"style",
|
|
87502
|
+
"test"
|
|
87503
|
+
];
|
|
87504
|
+
COMMITLINT_FILES = [
|
|
87505
|
+
".commitlintrc.json",
|
|
87506
|
+
".commitlintrc",
|
|
87507
|
+
".commitlintrc.yaml",
|
|
87508
|
+
".commitlintrc.yml",
|
|
87509
|
+
".commitlintrc.js",
|
|
87510
|
+
".commitlintrc.cjs",
|
|
87511
|
+
".commitlintrc.mjs",
|
|
87512
|
+
".commitlintrc.ts",
|
|
87513
|
+
"commitlint.config.js",
|
|
87514
|
+
"commitlint.config.cjs",
|
|
87515
|
+
"commitlint.config.mjs",
|
|
87516
|
+
"commitlint.config.ts"
|
|
87517
|
+
];
|
|
87518
|
+
DEFAULT_IGNORES = [
|
|
87519
|
+
/^((Merge pull request)|(Merge (.*?) into (.*?)|(Merge branch (.*?)))(?:\r?\n)*$)/m,
|
|
87520
|
+
/^(Merge tag (.*?))(?:\r?\n)*$/m,
|
|
87521
|
+
/^(R|r)evert (.*)/,
|
|
87522
|
+
/^(R|r)eapply (.*)/,
|
|
87523
|
+
/^(amend|fixup|squash)!/,
|
|
87524
|
+
/^(Merged (.*?)(in|into) (.*)|Merged PR (.*): (.*))/,
|
|
87525
|
+
/^Merge remote-tracking branch(\s*)(.*)/,
|
|
87526
|
+
/^Automatic merge(.*)/,
|
|
87527
|
+
/^Auto-merged (.*?) into (.*)/,
|
|
87528
|
+
/^(chore(\([^)]+\))?:\s*)?v?\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?\s*$/
|
|
87529
|
+
];
|
|
87185
87530
|
NEED_TEXT = {
|
|
87186
87531
|
none: "no verdict",
|
|
87187
87532
|
self: "the author's own --self verdict (or an independent one)",
|
|
@@ -87638,10 +87983,10 @@ async function push(argv, io) {
|
|
|
87638
87983
|
});
|
|
87639
87984
|
if (typeof flags === "string")
|
|
87640
87985
|
return usage4(io, flags, PUSH_USAGE);
|
|
87641
|
-
const release = flags.lists.release;
|
|
87986
|
+
const release = flags.lists.release?.flatMap((value) => value.split(",").map((name) => name.trim()).filter(Boolean));
|
|
87642
87987
|
if (release) {
|
|
87643
87988
|
if (flags.booleans.size || flags.values.expect !== undefined || flags.positionals.length)
|
|
87644
|
-
return usage4(io, "--release takes only ref names (
|
|
87989
|
+
return usage4(io, "--release takes only ref names (a comma list or a repeated flag: --release main,v1.2.0)", PUSH_USAGE);
|
|
87645
87990
|
return releasePush(release, io);
|
|
87646
87991
|
}
|
|
87647
87992
|
if (flags.positionals.length)
|
|
@@ -87743,7 +88088,7 @@ async function run17(argv, io) {
|
|
|
87743
88088
|
return trailers(rest, io);
|
|
87744
88089
|
return usage4(io, sub && !sub.startsWith("-") ? `unknown git subcommand "${sub}"` : "missing git subcommand", USAGE10);
|
|
87745
88090
|
}
|
|
87746
|
-
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
|
|
88091
|
+
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]", USAGE10 = "workit git branch|commit|push|trailers ... (workit help git)", short2 = (sha) => sha ? sha.slice(0, 12) : "(none)", COMMIT_SWITCHES, READ_ONLY;
|
|
87747
88092
|
var init_git2 = __esm(() => {
|
|
87748
88093
|
init_autonomy();
|
|
87749
88094
|
init_branch();
|
|
@@ -90033,7 +90378,13 @@ async function run22(argv, io) {
|
|
|
90033
90378
|
type: values.type,
|
|
90034
90379
|
last: last ?? 50
|
|
90035
90380
|
});
|
|
90036
|
-
|
|
90381
|
+
const note = values.type === "finding" && listed.length === 0 ? "findings are not ledger rows; they live in the task: workit finding list [--branch <b>] [--status open|resolved]" : undefined;
|
|
90382
|
+
return emit(io, ok2({
|
|
90383
|
+
path: ledger.value.path,
|
|
90384
|
+
skipped: ledger.value.skipped,
|
|
90385
|
+
rows: listed,
|
|
90386
|
+
...note ? { note } : {}
|
|
90387
|
+
}), (data) => note ? note : data.rows.length ? data.rows.map((row) => {
|
|
90037
90388
|
const line = summarizeRow(row);
|
|
90038
90389
|
return `#${line.seq} ${line.at} ${line.type}${line.branch ? ` [${line.branch}]` : ""}${line.labels.length ? ` (${line.labels.join(", ")})` : ""} ${line.summary}`;
|
|
90039
90390
|
}) : "ledger is empty");
|
|
@@ -90105,6 +90456,16 @@ async function run22(argv, io) {
|
|
|
90105
90456
|
const refusal = claimed === null ? null : sessionClaimRefusal(io.env, claimed, io.cwd, { token, flag: acting.source === "flag" });
|
|
90106
90457
|
if (refusal)
|
|
90107
90458
|
return emit(io, fail2("blocked", refusal.error, { unblock: refusal.unblock }));
|
|
90459
|
+
const evidence = values.self !== true && (rest[0] === "verified" || rest[0] === "tests-verified") ? verdictCheckEvidence(io.cwd, target.value, values.base ?? null) : null;
|
|
90460
|
+
const redCheck = evidence?.needed.find((item) => item.status === "failing");
|
|
90461
|
+
if (redCheck)
|
|
90462
|
+
return emit(io, fail2("blocked", `check_failing: the configured check "${redCheck.name}" is failing on ${evidence?.head.slice(0, 12)} (${redCheck.via ?? "local"} run); a ${rest[0]} verdict cannot be recorded`, {
|
|
90463
|
+
unblock: `fix it, then workit check ${redCheck.name} on this head, or record failed/blocked`
|
|
90464
|
+
}));
|
|
90465
|
+
const missingChecks = evidence?.needed.filter((item) => item.status === "missing") ?? [];
|
|
90466
|
+
if (missingChecks.length)
|
|
90467
|
+
io.stderr(`warning: no fresh run on ${evidence?.head.slice(0, 12)} of the configured check${missingChecks.length === 1 ? "" : "s"} ${missingChecks.map((item) => item.name).join(", ")}; the verdict records it as missing
|
|
90468
|
+
`);
|
|
90108
90469
|
const bound = claimed !== null && issuedTokenMatches(io.cwd, claimed, token);
|
|
90109
90470
|
const verdict = await recorded(recordVerdict({ ...context, ...bound ? { sessionBound: true } : {} }, {
|
|
90110
90471
|
result: rest[0],
|
|
@@ -90113,6 +90474,13 @@ async function run22(argv, io) {
|
|
|
90113
90474
|
surface: values.surface ?? null,
|
|
90114
90475
|
self: values.self === true,
|
|
90115
90476
|
evidenceRefs: values.evidence,
|
|
90477
|
+
...evidence?.needed.length ? {
|
|
90478
|
+
checkEvidence: evidence.needed.map(({ name, status, via }) => ({
|
|
90479
|
+
name,
|
|
90480
|
+
status,
|
|
90481
|
+
via
|
|
90482
|
+
}))
|
|
90483
|
+
} : {},
|
|
90116
90484
|
..."derivedFrom" in acting ? { derivedFrom: acting.derivedFrom } : {}
|
|
90117
90485
|
}));
|
|
90118
90486
|
if (verdict.ok && verdict.value.selfReason === "flag" && !passedTestOn(io.cwd, verdict.value))
|
|
@@ -90129,6 +90497,13 @@ async function run22(argv, io) {
|
|
|
90129
90497
|
].join(`
|
|
90130
90498
|
`));
|
|
90131
90499
|
}
|
|
90500
|
+
function verdictCheckEvidence(cwd, branch, base) {
|
|
90501
|
+
const head = branch === null ? headSha(cwd) : resolveRef(cwd, branch);
|
|
90502
|
+
const ledger = readLedger(cwd);
|
|
90503
|
+
if (!head || !ledger.ok)
|
|
90504
|
+
return null;
|
|
90505
|
+
return verdictEvidence(cwd, { head, base, rows: ledger.value.rows });
|
|
90506
|
+
}
|
|
90132
90507
|
function standingFanout(io, values) {
|
|
90133
90508
|
if (values.fanout !== undefined) {
|
|
90134
90509
|
const name = values.fanout.trim();
|
|
@@ -90273,6 +90648,7 @@ var init_ledger2 = __esm(() => {
|
|
|
90273
90648
|
init_fanout();
|
|
90274
90649
|
init_rev();
|
|
90275
90650
|
init_host_session();
|
|
90651
|
+
init_check_evidence();
|
|
90276
90652
|
init_implicit_task();
|
|
90277
90653
|
init_output();
|
|
90278
90654
|
OPTIONS = {
|
|
@@ -106153,7 +106529,7 @@ var init_rules = __esm(() => {
|
|
|
106153
106529
|
|
|
106154
106530
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
106155
106531
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
106156
|
-
import { existsSync as
|
|
106532
|
+
import { existsSync as existsSync27, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
|
|
106157
106533
|
import path71 from "node:path";
|
|
106158
106534
|
function git7(cwd, args) {
|
|
106159
106535
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
@@ -106180,7 +106556,7 @@ function expandPaths(cwd, inputs) {
|
|
|
106180
106556
|
const missing = [];
|
|
106181
106557
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
106182
106558
|
const full = path71.resolve(cwd, input);
|
|
106183
|
-
if (!
|
|
106559
|
+
if (!existsSync27(full))
|
|
106184
106560
|
missing.push(input);
|
|
106185
106561
|
else if (statSync10(full).isDirectory())
|
|
106186
106562
|
walkTests(full, files);
|
|
@@ -106296,7 +106672,7 @@ var init_audit = __esm(() => {
|
|
|
106296
106672
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
106297
106673
|
import { spawn as spawn2 } from "node:child_process";
|
|
106298
106674
|
import {
|
|
106299
|
-
existsSync as
|
|
106675
|
+
existsSync as existsSync28,
|
|
106300
106676
|
lstatSync as lstatSync8,
|
|
106301
106677
|
mkdirSync as mkdirSync12,
|
|
106302
106678
|
mkdtempSync as mkdtempSync4,
|
|
@@ -106525,7 +106901,7 @@ function copyWorkingTree(repo) {
|
|
|
106525
106901
|
}
|
|
106526
106902
|
for (const parent of dirs) {
|
|
106527
106903
|
const modules = path72.join(repo, parent, "node_modules");
|
|
106528
|
-
if (
|
|
106904
|
+
if (existsSync28(modules) && !existsSync28(path72.join(tree, parent, "node_modules")))
|
|
106529
106905
|
linkNodeModules(modules, path72.join(tree, parent, "node_modules"), repo, tree);
|
|
106530
106906
|
}
|
|
106531
106907
|
return { dir, tree };
|
|
@@ -106575,7 +106951,7 @@ async function runMutation(options) {
|
|
|
106575
106951
|
const relative = toPosix(path72.relative(repo, absolute));
|
|
106576
106952
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
106577
106953
|
continue;
|
|
106578
|
-
if (NOT_SOURCE.test(relative) || !
|
|
106954
|
+
if (NOT_SOURCE.test(relative) || !existsSync28(absolute))
|
|
106579
106955
|
continue;
|
|
106580
106956
|
try {
|
|
106581
106957
|
candidates.push(...mutantsFor(readFileSync30(absolute, "utf8"), relative, lines));
|
|
@@ -106765,7 +107141,7 @@ var exports_test_audit = {};
|
|
|
106765
107141
|
__export(exports_test_audit, {
|
|
106766
107142
|
run: () => run23
|
|
106767
107143
|
});
|
|
106768
|
-
import { existsSync as
|
|
107144
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
106769
107145
|
import path73 from "node:path";
|
|
106770
107146
|
function parse8(argv) {
|
|
106771
107147
|
const options = {
|
|
@@ -106889,7 +107265,7 @@ usage: ${USAGE16}`));
|
|
|
106889
107265
|
}
|
|
106890
107266
|
let files;
|
|
106891
107267
|
if (options.diff && changed)
|
|
106892
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
107268
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync29(file)).toSorted();
|
|
106893
107269
|
else {
|
|
106894
107270
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
106895
107271
|
if (expanded.missing.length > 0)
|
|
@@ -107337,7 +107713,11 @@ var FAMILY_ACTIONS = {
|
|
|
107337
107713
|
explain: "Explain the policy in force"
|
|
107338
107714
|
},
|
|
107339
107715
|
evidence: { record: "Record evidence against a task's requirements" },
|
|
107340
|
-
finding: {
|
|
107716
|
+
finding: {
|
|
107717
|
+
record: "Record a finding",
|
|
107718
|
+
resolve: "Resolve a finding",
|
|
107719
|
+
list: "List findings with their ids [--branch <b>] [--status open|resolved]"
|
|
107720
|
+
},
|
|
107341
107721
|
decision: {
|
|
107342
107722
|
record: "Record a task decision",
|
|
107343
107723
|
revoke: "Revoke a task decision"
|
|
@@ -107384,7 +107764,7 @@ var familySubcommands = (name) => {
|
|
|
107384
107764
|
const implicit = name === "task" ? TASK_IMPLICIT : [];
|
|
107385
107765
|
const grammar = Object.entries(FAMILY_ACTIONS[name]).filter(([action]) => !implicit.some((entry) => entry.name === action)).map(([action, summary]) => ({
|
|
107386
107766
|
name: action,
|
|
107387
|
-
usage: name === "task" && action === "list" ? `workit task list [--status all] ${FAMILY_OPTIONS}` : name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : name === "worker" && action !== "assign" ? `workit worker ${action} [<workerId>] ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
|
|
107767
|
+
usage: name === "task" && action === "list" ? `workit task list [--status all] ${FAMILY_OPTIONS}` : name === "finding" && action === "list" ? "workit finding list [--branch <b>] [--status open|resolved] [--json]" : name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : name === "worker" && action !== "assign" ? `workit worker ${action} [<workerId>] ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
|
|
107388
107768
|
summary
|
|
107389
107769
|
}));
|
|
107390
107770
|
return [...implicit, ...grammar];
|
|
@@ -107699,7 +108079,7 @@ var VERBS = [
|
|
|
107699
108079
|
{
|
|
107700
108080
|
name: "push",
|
|
107701
108081
|
deferredFlags: ["force"],
|
|
107702
|
-
usage: "workit git push [-u|--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--release <main|develop|v-tag
|
|
108082
|
+
usage: "workit git push [-u|--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--release <main|develop|v-tag>[,…]]",
|
|
107703
108083
|
summary: "Push the current branch and verify the remote tip (never a blind --force); --release finishes a git-flow release"
|
|
107704
108084
|
},
|
|
107705
108085
|
{
|
|
@@ -107869,7 +108249,7 @@ var VERBS = [
|
|
|
107869
108249
|
name: "list",
|
|
107870
108250
|
aliases: ["show"],
|
|
107871
108251
|
usage: "workit ledger list|show [--branch <b>] [--pr <n>] [--type <t>] [--last <n>]",
|
|
107872
|
-
summary: "List ledger rows, newest last"
|
|
108252
|
+
summary: "List ledger rows, newest last (findings live in the task: workit finding list)"
|
|
107873
108253
|
},
|
|
107874
108254
|
{
|
|
107875
108255
|
name: "check",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "8.39.
|
|
3
|
+
"version": "8.39.4",
|
|
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.39.
|
|
41
|
+
"@brainervirus/workit-cursor": "^8.39.4",
|
|
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.39.
|
|
47
|
+
"@brainervirus/workit-core": "^8.39.4"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|