@brainervirus/workit-cli 8.17.0 → 8.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +172 -37
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "8.
|
|
68
|
+
version: "8.18.0",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,13 +103,13 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-cursor": "^8.
|
|
106
|
+
"@brainervirus/workit-cursor": "^8.18.0",
|
|
107
107
|
"@inkjs/ui": "2.0.0",
|
|
108
108
|
ink: "7.1.1",
|
|
109
109
|
react: "19.2.8"
|
|
110
110
|
},
|
|
111
111
|
devDependencies: {
|
|
112
|
-
"@brainervirus/workit-core": "^8.
|
|
112
|
+
"@brainervirus/workit-core": "^8.18.0"
|
|
113
113
|
},
|
|
114
114
|
engines: {
|
|
115
115
|
node: ">=24"
|
|
@@ -170,6 +170,20 @@ var init_output = __esm(() => {
|
|
|
170
170
|
import { spawnSync } from "node:child_process";
|
|
171
171
|
import fs from "node:fs";
|
|
172
172
|
import path from "node:path";
|
|
173
|
+
function checksConfigFile(root) {
|
|
174
|
+
const current = path.join(root, CHECKS_FILE);
|
|
175
|
+
const legacy = path.join(root, LEGACY_CHECKS_FILE);
|
|
176
|
+
return !fs.existsSync(current) && fs.existsSync(legacy) ? legacy : current;
|
|
177
|
+
}
|
|
178
|
+
function ensureWorkitDir(root) {
|
|
179
|
+
const dir = path.join(root, ".workit");
|
|
180
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
181
|
+
const ignore = path.join(dir, ".gitignore");
|
|
182
|
+
if (!fs.existsSync(ignore))
|
|
183
|
+
fs.writeFileSync(ignore, `*
|
|
184
|
+
`);
|
|
185
|
+
return dir;
|
|
186
|
+
}
|
|
173
187
|
function repoHeavyCommands(root) {
|
|
174
188
|
try {
|
|
175
189
|
const value = JSON.parse(fs.readFileSync(checksConfigFile(root), "utf8"));
|
|
@@ -261,19 +275,25 @@ function detectedChecks(root) {
|
|
|
261
275
|
function loadCheckConfig(cwd) {
|
|
262
276
|
const root = checkRoot(cwd);
|
|
263
277
|
const file = checksConfigFile(root);
|
|
278
|
+
const legacy = path.basename(file) === LEGACY_CHECKS_FILE;
|
|
279
|
+
const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
|
|
280
|
+
const note = legacy ? {
|
|
281
|
+
note: `${LEGACY_CHECKS_FILE} is deprecated; move it to ${CHECKS_FILE} (workit doctor --fix)`
|
|
282
|
+
} : {};
|
|
264
283
|
const none = (error = null) => ({
|
|
265
|
-
source: error ?
|
|
284
|
+
source: error ? label : "none",
|
|
266
285
|
root,
|
|
267
286
|
checks: [],
|
|
268
287
|
gates: {},
|
|
269
|
-
error
|
|
288
|
+
error,
|
|
289
|
+
...note
|
|
270
290
|
});
|
|
271
291
|
let text = null;
|
|
272
292
|
try {
|
|
273
293
|
text = fs.readFileSync(file, "utf8");
|
|
274
294
|
} catch (error) {
|
|
275
295
|
if (error.code !== "ENOENT")
|
|
276
|
-
return none(`cannot read ${
|
|
296
|
+
return none(`cannot read ${label}: ${error.message}`);
|
|
277
297
|
}
|
|
278
298
|
if (text === null) {
|
|
279
299
|
const checks = detectedChecks(root);
|
|
@@ -283,33 +303,33 @@ function loadCheckConfig(cwd) {
|
|
|
283
303
|
try {
|
|
284
304
|
parsed = JSON.parse(text);
|
|
285
305
|
} catch {
|
|
286
|
-
return none(`${
|
|
306
|
+
return none(`${label} is not valid JSON`);
|
|
287
307
|
}
|
|
288
308
|
if (!isRecord(parsed) || !isRecord(parsed.checks))
|
|
289
|
-
return none(`${
|
|
309
|
+
return none(`${label} must be {"checks":{"<name>":"<command>"|["argv",…]}}`);
|
|
290
310
|
const checks = [];
|
|
291
311
|
for (const [name, value] of Object.entries(parsed.checks)) {
|
|
292
312
|
if (!CHECK_NAME.test(name))
|
|
293
|
-
return none(`${
|
|
313
|
+
return none(`${label}: check name "${name}" must match ${CHECK_NAME.source}`);
|
|
294
314
|
const argv = typeof value === "string" ? splitCommand(value) : Array.isArray(value) && value.length > 0 && value.every((item) => typeof item === "string" && item.length > 0) ? value : new Error("expected a command string or a non-empty argv array");
|
|
295
315
|
if (argv instanceof Error)
|
|
296
|
-
return none(`${
|
|
316
|
+
return none(`${label}: check "${name}": ${argv.message}`);
|
|
297
317
|
checks.push({ name, argv, accepts: [argv] });
|
|
298
318
|
}
|
|
299
319
|
const gates = {};
|
|
300
320
|
if (parsed.gates !== undefined) {
|
|
301
321
|
if (!isRecord(parsed.gates))
|
|
302
|
-
return none(`${
|
|
322
|
+
return none(`${label}: gates must be {"testing":"<name>"|["<name>",…]}`);
|
|
303
323
|
for (const [gate, value] of Object.entries(parsed.gates)) {
|
|
304
324
|
if (!GATES.includes(gate))
|
|
305
|
-
return none(`${
|
|
325
|
+
return none(`${label}: unknown gate "${gate}" (use ${GATES.join(" or ")})`);
|
|
306
326
|
const names = typeof value === "string" ? [value] : value;
|
|
307
327
|
if (!Array.isArray(names) || names.length === 0 || !names.every((name) => typeof name === "string" && checks.some((c) => c.name === name)))
|
|
308
|
-
return none(`${
|
|
328
|
+
return none(`${label}: gates.${gate} must name configured checks`);
|
|
309
329
|
gates[gate] = names;
|
|
310
330
|
}
|
|
311
331
|
}
|
|
312
|
-
return { source:
|
|
332
|
+
return { source: label, root, checks, gates, error: null, ...note, resources: parsed.resources };
|
|
313
333
|
}
|
|
314
334
|
function matchesNamedCheck(config, name, argv, cwd) {
|
|
315
335
|
if (config.error || name === null || cwd !== ".")
|
|
@@ -344,7 +364,7 @@ function workitAvailable(env = process.env) {
|
|
|
344
364
|
function checkCommand(args, version, onPath = workitAvailable()) {
|
|
345
365
|
return onPath ? `workit check ${args}` : `npx -y @brainervirus/workit-cli@${version} check ${args}`;
|
|
346
366
|
}
|
|
347
|
-
var SCRIPT_CHECKS, CHECKS_FILE = "workit
|
|
367
|
+
var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "workit.checks.json", isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SHELL_META, git = (cwd, args) => {
|
|
348
368
|
const run = spawnSync("git", args, {
|
|
349
369
|
cwd,
|
|
350
370
|
encoding: "utf8",
|
|
@@ -15647,6 +15667,10 @@ function checkSupersede(context, type, row = {}) {
|
|
|
15647
15667
|
return problem ? err("invalid_input", `--supersedes: ${problem}`) : { ok: true, value: undefined };
|
|
15648
15668
|
}
|
|
15649
15669
|
function recordDecision(context, input) {
|
|
15670
|
+
if (input.by !== undefined && input.by !== "decider")
|
|
15671
|
+
return err("invalid_input", `--by takes "decider", got "${input.by}"`);
|
|
15672
|
+
if (input.by === undefined && input.views?.length)
|
|
15673
|
+
return err("invalid_input", "--view needs --by decider");
|
|
15650
15674
|
const what = required2(input.what, "<what>");
|
|
15651
15675
|
if (!what.ok)
|
|
15652
15676
|
return what;
|
|
@@ -15661,7 +15685,9 @@ function recordDecision(context, input) {
|
|
|
15661
15685
|
type: "decision",
|
|
15662
15686
|
what: what.value,
|
|
15663
15687
|
why: why.value,
|
|
15664
|
-
refs: input.refs ?? []
|
|
15688
|
+
refs: input.refs ?? [],
|
|
15689
|
+
...input.by === "decider" ? { by: "decider" } : {},
|
|
15690
|
+
...input.views?.length ? { views: input.views } : {}
|
|
15665
15691
|
}, { now: context.now });
|
|
15666
15692
|
}
|
|
15667
15693
|
function recordRuling(context, input) {
|
|
@@ -15828,15 +15854,19 @@ function rowLabels(row) {
|
|
|
15828
15854
|
labels.push("ignored");
|
|
15829
15855
|
if (row.type === "verdict" && row.self === true)
|
|
15830
15856
|
labels.push("self");
|
|
15857
|
+
if (row.type === "decision" && row.by === "decider")
|
|
15858
|
+
labels.push("decider");
|
|
15831
15859
|
return labels;
|
|
15832
15860
|
}
|
|
15833
15861
|
function summarizeRow(row) {
|
|
15834
15862
|
const text = (key) => str2(row[key]) ?? "";
|
|
15835
15863
|
let summary;
|
|
15836
15864
|
switch (row.type) {
|
|
15837
|
-
case "decision":
|
|
15838
|
-
|
|
15865
|
+
case "decision": {
|
|
15866
|
+
const views = Array.isArray(row.views) ? row.views.map(String) : [];
|
|
15867
|
+
summary = `${row.by === "decider" ? "[decider] " : ""}${text("what")} (why: ${text("why")}${views.length ? `; views: ${views.join(" | ")}` : ""})`;
|
|
15839
15868
|
break;
|
|
15869
|
+
}
|
|
15840
15870
|
case "ruling":
|
|
15841
15871
|
summary = `${text("what")} (why: ${text("why")}; cost if wrong: ${text("costIfWrong")})`;
|
|
15842
15872
|
break;
|
|
@@ -16445,7 +16475,7 @@ var RULES, derived2 = (spec) => ({
|
|
|
16445
16475
|
};
|
|
16446
16476
|
const since = Date.parse(task.createdAt);
|
|
16447
16477
|
const branch = ledger.branch();
|
|
16448
|
-
const row = ledger.rows().findLast((item) => item.type === "decision" && !item.superseded && (item.branch ?? null) === branch && Date.parse(item.at) >= since);
|
|
16478
|
+
const row = ledger.rows().findLast((item) => item.type === "decision" && item.by !== "decider" && !item.superseded && (item.branch ?? null) === branch && Date.parse(item.at) >= since);
|
|
16449
16479
|
return row ? { met: true, reason: `ledger decision ${row.id} records the choice`, decisionIds: [] } : {
|
|
16450
16480
|
met: false,
|
|
16451
16481
|
reason: 'open product choice: ask the user, then `workit ledger decision "<choice>" --why "<reason>"` (or, if it is not open, `workit policy assess --judge product-choice=no --why "<reason>"`)',
|
|
@@ -16680,7 +16710,7 @@ function evaluateObservedGate(task, requirement, statuses, config) {
|
|
|
16680
16710
|
return {
|
|
16681
16711
|
satisfied: [],
|
|
16682
16712
|
considered,
|
|
16683
|
-
reason: requirement.dimension === "testing" && config.checks.length ? `no \`test\` check is configured; add one (or gates.testing) to ${CHECKS_FILE}, then run ${checkCommand("test", runtimeVersion())}` : `no checks are configured or detected; add ${CHECKS_FILE}
|
|
16713
|
+
reason: requirement.dimension === "testing" && config.checks.length ? `no \`test\` check is configured; add one (or gates.testing) to ${CHECKS_FILE}, then run ${checkCommand("test", runtimeVersion())}` : `no checks are configured or detected; add ${CHECKS_FILE}, e.g. {"checks":{"test":"<your test command>"}}, then run ${checkCommand("test", runtimeVersion())}`
|
|
16684
16714
|
};
|
|
16685
16715
|
const satisfied = fresh.filter(named);
|
|
16686
16716
|
if (satisfied.length)
|
|
@@ -66219,6 +66249,7 @@ import {
|
|
|
66219
66249
|
readdirSync as readdirSync8,
|
|
66220
66250
|
readFileSync as readFileSync14,
|
|
66221
66251
|
readlinkSync as readlinkSync2,
|
|
66252
|
+
renameSync as renameSync4,
|
|
66222
66253
|
rmSync as rmSync3,
|
|
66223
66254
|
statSync as statSync5,
|
|
66224
66255
|
unlinkSync as unlinkSync3,
|
|
@@ -66257,6 +66288,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66257
66288
|
cursorMcp: options.cursorMcp ?? path34.join(home, ".cursor", "mcp.json"),
|
|
66258
66289
|
cursorPluginDir: options.cursorPluginDir ?? path34.join(home, ".cursor", "plugins", "local", "workit"),
|
|
66259
66290
|
cursorHeartbeatDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
|
|
66291
|
+
hookStateDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
|
|
66260
66292
|
codexHome: options.codexHome,
|
|
66261
66293
|
piAgentDir: options.piAgentDir,
|
|
66262
66294
|
env,
|
|
@@ -67951,6 +67983,79 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67951
67983
|
detail: `heavy-check scopes do not apply their limits: ${probe.reason}${delegate}`,
|
|
67952
67984
|
fix: SCOPE_DELEGATE_FIX
|
|
67953
67985
|
};
|
|
67986
|
+
}, DAY_MS, HOOK_SKIPS_FILE = "hook-skips.jsonl", countHookSkips = (stateDir, since) => {
|
|
67987
|
+
const counts = { skip: 0, late: 0 };
|
|
67988
|
+
let text = "";
|
|
67989
|
+
try {
|
|
67990
|
+
text = readFileSync14(path34.join(stateDir, HOOK_SKIPS_FILE), "utf8");
|
|
67991
|
+
} catch {
|
|
67992
|
+
return counts;
|
|
67993
|
+
}
|
|
67994
|
+
for (const line of text.split(`
|
|
67995
|
+
`)) {
|
|
67996
|
+
try {
|
|
67997
|
+
const row = JSON.parse(line);
|
|
67998
|
+
if (!(Date.parse(String(row.at)) >= since))
|
|
67999
|
+
continue;
|
|
68000
|
+
if (row.outcome === "skip")
|
|
68001
|
+
counts.skip += 1;
|
|
68002
|
+
else if (row.outcome === "late")
|
|
68003
|
+
counts.late += 1;
|
|
68004
|
+
} catch {}
|
|
68005
|
+
}
|
|
68006
|
+
return counts;
|
|
68007
|
+
}, checkHookDeadline = (res) => {
|
|
68008
|
+
const file = path34.join(res.hookStateDir, HOOK_SKIPS_FILE);
|
|
68009
|
+
const { skip, late } = countHookSkips(res.hookStateDir, Date.now() - DAY_MS);
|
|
68010
|
+
const lateText = late > 0 ? `; ${late} answered past it in full` : "";
|
|
68011
|
+
if (skip > 0)
|
|
68012
|
+
return {
|
|
68013
|
+
id: "hook_deadline",
|
|
68014
|
+
status: "warn",
|
|
68015
|
+
detail: `${skip} hook${skip === 1 ? "" : "s"} skipped past the hook deadline in the last day (host under load: Workit context, gates and nudges were not applied)${lateText} (${file})`,
|
|
68016
|
+
fix: "Lower the machine load: run heavy commands through `workit check` (the lease serializes them) and fewer parallel agents; WORKIT_HOOK_DEADLINE_MS raises the deadline"
|
|
68017
|
+
};
|
|
68018
|
+
if (late > 0)
|
|
68019
|
+
return {
|
|
68020
|
+
id: "hook_deadline",
|
|
68021
|
+
status: "info",
|
|
68022
|
+
detail: `no hook skipped in the last day${lateText} (${file})`
|
|
68023
|
+
};
|
|
68024
|
+
return {
|
|
68025
|
+
id: "hook_deadline",
|
|
68026
|
+
status: "pass",
|
|
68027
|
+
detail: "no hook passed its deadline in the last day"
|
|
68028
|
+
};
|
|
68029
|
+
}, checkChecksConfig = (res) => {
|
|
68030
|
+
const root = checkRoot(res.cwd);
|
|
68031
|
+
const current = existsSync14(path34.join(root, CHECKS_FILE));
|
|
68032
|
+
const legacy = existsSync14(path34.join(root, LEGACY_CHECKS_FILE));
|
|
68033
|
+
if (!legacy)
|
|
68034
|
+
return {
|
|
68035
|
+
id: "checks_config",
|
|
68036
|
+
status: "pass",
|
|
68037
|
+
detail: current ? `${CHECKS_FILE} is the checks config` : "no per-repo checks config at the root"
|
|
68038
|
+
};
|
|
68039
|
+
return {
|
|
68040
|
+
id: "checks_config",
|
|
68041
|
+
status: "warn",
|
|
68042
|
+
detail: current ? `${LEGACY_CHECKS_FILE} at the repo root is ignored: ${CHECKS_FILE} wins` : `${LEGACY_CHECKS_FILE} at the repo root is a legacy location, still read`,
|
|
68043
|
+
fix: current ? `delete ${LEGACY_CHECKS_FILE} once ${CHECKS_FILE} has what you need` : "workit doctor --fix (moves it to .workit/checks.json)"
|
|
68044
|
+
};
|
|
68045
|
+
}, fixChecksConfig = (options = {}) => {
|
|
68046
|
+
const root = checkRoot(resolve(options).cwd);
|
|
68047
|
+
const from = path34.join(root, LEGACY_CHECKS_FILE);
|
|
68048
|
+
const to = path34.join(root, CHECKS_FILE);
|
|
68049
|
+
if (!existsSync14(from))
|
|
68050
|
+
return { action: "none", detail: `no ${LEGACY_CHECKS_FILE} at ${root}` };
|
|
68051
|
+
if (existsSync14(to))
|
|
68052
|
+
return {
|
|
68053
|
+
action: "skipped",
|
|
68054
|
+
detail: `${CHECKS_FILE} already exists; ${LEGACY_CHECKS_FILE} left in place`
|
|
68055
|
+
};
|
|
68056
|
+
ensureWorkitDir(root);
|
|
68057
|
+
renameSync4(from, to);
|
|
68058
|
+
return { action: "moved", detail: `${LEGACY_CHECKS_FILE} -> ${CHECKS_FILE}` };
|
|
67954
68059
|
}, CLAUDE_PLUGIN_PACKAGE = "@brainervirus/workit-claude-code", versionBehind = (version, latest) => version !== latest && semverAtLeast(latest, version), checkClaudePlugin = (res) => {
|
|
67955
68060
|
const installs = claudeWorkitInstalls(res.home, res.env, res.cwd);
|
|
67956
68061
|
if (installs.length === 0)
|
|
@@ -68137,6 +68242,7 @@ var init_doctor = __esm(() => {
|
|
|
68137
68242
|
init_branch_policy();
|
|
68138
68243
|
init_config();
|
|
68139
68244
|
init_logger();
|
|
68245
|
+
init_check_config();
|
|
68140
68246
|
init_heavy_scope();
|
|
68141
68247
|
init_package_root();
|
|
68142
68248
|
init_registration();
|
|
@@ -68148,6 +68254,7 @@ var init_doctor = __esm(() => {
|
|
|
68148
68254
|
AGENT_MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
|
|
68149
68255
|
canonicalCursorHook = cursorHooksEntry().command;
|
|
68150
68256
|
SILENT_HOOK_GRACE_MS = 2 * 60000;
|
|
68257
|
+
DAY_MS = 24 * 60 * 60 * 1000;
|
|
68151
68258
|
SEMVER = /\d+\.\d+\.\d+/;
|
|
68152
68259
|
workitVersions = new Map;
|
|
68153
68260
|
RUN_CHECKS = [
|
|
@@ -68176,7 +68283,9 @@ var init_doctor = __esm(() => {
|
|
|
68176
68283
|
checkGithubIdentity,
|
|
68177
68284
|
checkGitLabIdentity,
|
|
68178
68285
|
checkLogWritable,
|
|
68179
|
-
checkHeavyScope
|
|
68286
|
+
checkHeavyScope,
|
|
68287
|
+
checkHookDeadline,
|
|
68288
|
+
checkChecksConfig
|
|
68180
68289
|
];
|
|
68181
68290
|
INSTALLER_REQUIRED = new Set([
|
|
68182
68291
|
"runtime",
|
|
@@ -68201,7 +68310,7 @@ import {
|
|
|
68201
68310
|
readFileSync as readFileSync15,
|
|
68202
68311
|
readdirSync as readdirSync9,
|
|
68203
68312
|
realpathSync as realpathSync7,
|
|
68204
|
-
renameSync as
|
|
68313
|
+
renameSync as renameSync5,
|
|
68205
68314
|
rmSync as rmSync4,
|
|
68206
68315
|
statSync as statSync6,
|
|
68207
68316
|
writeFileSync as writeFileSync8
|
|
@@ -68490,7 +68599,7 @@ function applyMutation(m) {
|
|
|
68490
68599
|
detail: "workspace config changed while applying the preview; rebuild and review it"
|
|
68491
68600
|
};
|
|
68492
68601
|
}
|
|
68493
|
-
|
|
68602
|
+
renameSync5(tmp, m.path);
|
|
68494
68603
|
} catch (error) {
|
|
68495
68604
|
rmSync4(tmp, { force: true });
|
|
68496
68605
|
return {
|
|
@@ -68683,12 +68792,12 @@ function copyPluginDir(src, dest) {
|
|
|
68683
68792
|
throw new Error("staged adapter resolved to a symlink — refusing fragile cache install");
|
|
68684
68793
|
}
|
|
68685
68794
|
if (hadDir)
|
|
68686
|
-
|
|
68795
|
+
renameSync5(dest, backup);
|
|
68687
68796
|
try {
|
|
68688
|
-
|
|
68797
|
+
renameSync5(stage, dest);
|
|
68689
68798
|
} catch (error) {
|
|
68690
68799
|
if (hadDir && !existsSync15(dest))
|
|
68691
|
-
|
|
68800
|
+
renameSync5(backup, dest);
|
|
68692
68801
|
throw error;
|
|
68693
68802
|
}
|
|
68694
68803
|
rmSync4(backup, { recursive: true, force: true });
|
|
@@ -69211,7 +69320,7 @@ var init_setup = __esm(() => {
|
|
|
69211
69320
|
});
|
|
69212
69321
|
|
|
69213
69322
|
// packages/workit-core/src/core/workspace-branch-policy.ts
|
|
69214
|
-
import { mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as
|
|
69323
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
69215
69324
|
import path36 from "node:path";
|
|
69216
69325
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
69217
69326
|
function applyWorkspaceBranchPolicy(opts) {
|
|
@@ -69289,7 +69398,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
69289
69398
|
error: `workspaces.json changed while applying the branch policy: ${wsPath}`
|
|
69290
69399
|
};
|
|
69291
69400
|
}
|
|
69292
|
-
|
|
69401
|
+
renameSync6(tmp, wsPath);
|
|
69293
69402
|
} catch (error) {
|
|
69294
69403
|
try {
|
|
69295
69404
|
rmSync5(tmp, { force: true });
|
|
@@ -73890,6 +73999,17 @@ async function run6(argv, io) {
|
|
|
73890
73999
|
};
|
|
73891
74000
|
}
|
|
73892
74001
|
}
|
|
74002
|
+
let checksConfig = null;
|
|
74003
|
+
if (argv.includes("--fix")) {
|
|
74004
|
+
try {
|
|
74005
|
+
checksConfig = fixChecksConfig({ host: "cli", cwd: io.cwd });
|
|
74006
|
+
} catch (error) {
|
|
74007
|
+
checksConfig = {
|
|
74008
|
+
action: "failed",
|
|
74009
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
74010
|
+
};
|
|
74011
|
+
}
|
|
74012
|
+
}
|
|
73893
74013
|
const report = runDoctor({
|
|
73894
74014
|
host: "cli",
|
|
73895
74015
|
cwd: io.cwd,
|
|
@@ -73912,7 +74032,7 @@ async function run6(argv, io) {
|
|
|
73912
74032
|
budget: knowledge.budget,
|
|
73913
74033
|
findings: knowledge.findings.length
|
|
73914
74034
|
} : { unavailable: true };
|
|
73915
|
-
io.stdout(`${JSON.stringify({ ...report, ...fixLock ? { fixLock } : {}, ...sessionHook ? { sessionHook } : {}, knowledge: summary }, null, 2)}
|
|
74035
|
+
io.stdout(`${JSON.stringify({ ...report, ...fixLock ? { fixLock } : {}, ...sessionHook ? { sessionHook } : {}, ...checksConfig ? { checksConfig } : {}, knowledge: summary }, null, 2)}
|
|
73916
74036
|
`);
|
|
73917
74037
|
return report.exitCode;
|
|
73918
74038
|
}
|
|
@@ -73923,6 +74043,9 @@ async function run6(argv, io) {
|
|
|
73923
74043
|
}
|
|
73924
74044
|
if (sessionHook)
|
|
73925
74045
|
io.stdout(`fix: session hook ${sessionHook.action}: ${sessionHook.detail}
|
|
74046
|
+
`);
|
|
74047
|
+
if (checksConfig && checksConfig.action !== "none")
|
|
74048
|
+
io.stdout(`fix: checks config ${checksConfig.action}: ${checksConfig.detail}
|
|
73926
74049
|
`);
|
|
73927
74050
|
io.stdout(`workit doctor — ${report.ok ? "healthy" : "problems found"} (${report.offline ? "offline" : "online"})
|
|
73928
74051
|
`);
|
|
@@ -75778,6 +75901,9 @@ async function run10(argv, io) {
|
|
|
75778
75901
|
if (options instanceof Error)
|
|
75779
75902
|
return emit(io, fail("invalid_input", options.message, { unblock: USAGE3 }));
|
|
75780
75903
|
const config = loadCheckConfig(io.cwd);
|
|
75904
|
+
if (config.note)
|
|
75905
|
+
io.stderr(`note: ${config.note}
|
|
75906
|
+
`);
|
|
75781
75907
|
const top = checkRoot(io.cwd);
|
|
75782
75908
|
let command;
|
|
75783
75909
|
let runCwd = io.cwd;
|
|
@@ -75792,7 +75918,7 @@ async function run10(argv, io) {
|
|
|
75792
75918
|
if (!check)
|
|
75793
75919
|
return emit(io, fail("not_found", `no configured check named "${name}"`, {
|
|
75794
75920
|
data: { configured: config.checks.map((item) => item.name), source: config.source },
|
|
75795
|
-
unblock: config.checks.length ? `workit check ${config.checks.map((item) => item.name).join("|")}` : `add {"checks":{"${name}":"<command>"}} to workit
|
|
75921
|
+
unblock: config.checks.length ? `workit check ${config.checks.map((item) => item.name).join("|")}` : `add {"checks":{"${name}":"<command>"}} to .workit/checks.json, or run workit check --name ${name} -- <cmd…>`
|
|
75796
75922
|
}));
|
|
75797
75923
|
command = check.argv;
|
|
75798
75924
|
runCwd = config.root;
|
|
@@ -84749,7 +84875,8 @@ var DEFAULT_TIMEBOX = "30 minutes", REPORT, identityOf = (host) => {
|
|
|
84749
84875
|
' 2. Decide ambiguities yourself: `workit ledger ruling "<what>" --why "<why>" --cost-if-wrong "<cost>"`; stop only for an irreversible, security-sensitive or out-of-worktree action.',
|
|
84750
84876
|
plain ? ' 3. Commit with plain `git commit -m <msg> --trailer "Workit-Session: <the WORKIT_SESSION_ID in your env>" --trailer "<your host attribution trailer>" -- <paths in SCOPE>`; push only if this brief says so.' : " 3. Commit with `workit git commit -m <msg> -- <paths in SCOPE>`; push only if this brief says so.",
|
|
84751
84877
|
" 4. Never record a verdict on your own work.",
|
|
84752
|
-
" 5. Run tests, lint, typecheck and builds only through `workit check` (a named check, or `workit check --heavy -- <cmd>`): one machine-wide lease queues every agent, so never a hand-made flock; `workit lock status` shows who holds it."
|
|
84878
|
+
" 5. Run tests, lint, typecheck and builds only through `workit check` (a named check, or `workit check --heavy -- <cmd>`): one machine-wide lease queues every agent, so never a hand-made flock; `workit lock status` shows who holds it.",
|
|
84879
|
+
" 6. A failed review gets one fix round and one recheck. Still failing: stop and report the open finding, never a third round (the lead spawns a decider). A product choice is the user's: report it, do not decide it."
|
|
84753
84880
|
];
|
|
84754
84881
|
}, sessionSafe = (text) => text.replace(/[^A-Za-z0-9_.:@/+-]/gu, "-"), SESSION_MAX = 128;
|
|
84755
84882
|
var init_fanout_brief = __esm(() => {
|
|
@@ -85843,7 +85970,13 @@ async function run19(argv, io) {
|
|
|
85843
85970
|
return result;
|
|
85844
85971
|
};
|
|
85845
85972
|
if (sub === "decision")
|
|
85846
|
-
return fromResult(io, await recorded(recordDecision(context, {
|
|
85973
|
+
return fromResult(io, await recorded(recordDecision(context, {
|
|
85974
|
+
what: text,
|
|
85975
|
+
why: values.why,
|
|
85976
|
+
refs: values.ref,
|
|
85977
|
+
by: values.by,
|
|
85978
|
+
views: values.view
|
|
85979
|
+
})), (row) => `recorded decision ${row.id}`);
|
|
85847
85980
|
if (sub === "ruling")
|
|
85848
85981
|
return fromResult(io, await recorded(recordRuling(context, {
|
|
85849
85982
|
what: text,
|
|
@@ -86016,6 +86149,8 @@ var init_ledger2 = __esm(() => {
|
|
|
86016
86149
|
why: { type: "string" },
|
|
86017
86150
|
"cost-if-wrong": { type: "string" },
|
|
86018
86151
|
ref: { type: "string", multiple: true },
|
|
86152
|
+
by: { type: "string" },
|
|
86153
|
+
view: { type: "string", multiple: true },
|
|
86019
86154
|
how: { type: "string" },
|
|
86020
86155
|
kind: { type: "string" },
|
|
86021
86156
|
surface: { type: "string" },
|
|
@@ -102036,7 +102171,7 @@ import {
|
|
|
102036
102171
|
readFileSync as readFileSync24,
|
|
102037
102172
|
readlinkSync as readlinkSync3,
|
|
102038
102173
|
realpathSync as realpathSync9,
|
|
102039
|
-
renameSync as
|
|
102174
|
+
renameSync as renameSync7,
|
|
102040
102175
|
rmSync as rmSync8,
|
|
102041
102176
|
statSync as statSync9,
|
|
102042
102177
|
symlinkSync,
|
|
@@ -102213,7 +102348,7 @@ function writeInside(copy, file, content) {
|
|
|
102213
102348
|
}
|
|
102214
102349
|
const temp = `${target}.workit-mutant-${process.pid}`;
|
|
102215
102350
|
writeFileSync11(temp, content);
|
|
102216
|
-
|
|
102351
|
+
renameSync7(temp, target);
|
|
102217
102352
|
return true;
|
|
102218
102353
|
}
|
|
102219
102354
|
function copyWorkingTree(repo) {
|
|
@@ -102642,7 +102777,7 @@ usage: ${USAGE12}`));
|
|
|
102642
102777
|
const runner = testCommand(repo, io.cwd, options.testCmd);
|
|
102643
102778
|
if (!runner)
|
|
102644
102779
|
return emit(io, fail("unavailable", "no test command for --mutate", {
|
|
102645
|
-
unblock: 'workit test-audit --mutate --test-cmd "<runner> {files}" (or configure a `test` check in workit
|
|
102780
|
+
unblock: 'workit test-audit --mutate --test-cmd "<runner> {files}" (or configure a `test` check in .workit/checks.json)'
|
|
102646
102781
|
}));
|
|
102647
102782
|
try {
|
|
102648
102783
|
mutation = await runMutation({
|
|
@@ -103540,8 +103675,8 @@ var VERBS = [
|
|
|
103540
103675
|
subcommands: [
|
|
103541
103676
|
{
|
|
103542
103677
|
name: "decision",
|
|
103543
|
-
usage: `workit ledger decision "<what>" --why "<why>" [--ref <path|url>]… ${LEDGER_ACTOR}`,
|
|
103544
|
-
summary: "Record a decision and why"
|
|
103678
|
+
usage: `workit ledger decision "<what>" --why "<why>" [--by decider [--view "<view>"]…] [--ref <path|url>]… ${LEDGER_ACTOR}`,
|
|
103679
|
+
summary: "Record a decision and why; --by decider marks a tie-breaker agent's call (not the user's answer, not a verdict)"
|
|
103545
103680
|
},
|
|
103546
103681
|
{
|
|
103547
103682
|
name: "ruling",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.18.0",
|
|
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.18.0",
|
|
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.18.0"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|