@brainervirus/workit-cli 8.39.3 → 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.
Files changed (2) hide show
  1. package/dist/index.js +285 -25
  2. 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.3",
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.3",
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.3"
9364
+ "@brainervirus/workit-core": "^8.39.4"
9365
9365
  },
9366
9366
  engines: {
9367
9367
  node: ">=24"
@@ -21305,7 +21305,10 @@ async function payloadValue(raw, deps) {
21305
21305
  }
21306
21306
  try {
21307
21307
  const value = JSON.parse(source);
21308
- return isObject7(value) ? { ok: true, value } : { ok: false, result: failure2("invalid_input", "payload must be a JSON object") };
21308
+ return isObject7(value) ? { ok: true, value } : {
21309
+ ok: false,
21310
+ result: failure2("invalid_input", "payload must be a JSON object")
21311
+ };
21309
21312
  } catch (error) {
21310
21313
  return {
21311
21314
  ok: false,
@@ -21500,7 +21503,11 @@ function laneOf(root) {
21500
21503
  } catch {
21501
21504
  verification = DEFAULT_VERIFICATION;
21502
21505
  }
21503
- const lane = branchLane(root, { head: null, workingTree: true, judgment: currentJudgment(root) });
21506
+ const lane = branchLane(root, {
21507
+ head: null,
21508
+ workingTree: true,
21509
+ judgment: currentJudgment(root)
21510
+ });
21504
21511
  return {
21505
21512
  lane: lane.lane,
21506
21513
  reasons: lane.reasons,
@@ -21574,7 +21581,69 @@ function printHuman(result, deps, handoff = false) {
21574
21581
  write(stream, `policy gap: ${gap.reason}`);
21575
21582
  }
21576
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
+ }
21577
21644
  async function runTaskCommand(argv, deps = {}) {
21645
+ if (argv[0] === "finding" && argv[1] === "list")
21646
+ return runFindingList(argv.slice(2), deps);
21578
21647
  const parsed = await parseTaskArgs(argv, deps);
21579
21648
  if (!parsed.ok) {
21580
21649
  if (parsed.json)
@@ -21587,7 +21656,9 @@ async function runTaskCommand(argv, deps = {}) {
21587
21656
  const store = new TaskStore(root);
21588
21657
  try {
21589
21658
  const now = new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
21590
- closeDeliveredTasks(store, now, { cached: parsed.parsed.action !== "list" });
21659
+ closeDeliveredTasks(store, now, {
21660
+ cached: parsed.parsed.action !== "list"
21661
+ });
21591
21662
  } catch {}
21592
21663
  const core = new WorkitCore(store, contextFor(root, parsed.parsed.actor !== undefined ? { ...deps, actor: parsed.parsed.actor } : deps));
21593
21664
  let result;
@@ -21678,7 +21749,7 @@ var TASK_FAMILIES, workspaceRootFor = (deps = {}) => {
21678
21749
  capabilities: deps.capabilities ?? [],
21679
21750
  constraints: deps.constraints ?? [],
21680
21751
  now: deps.now ?? (() => new Date().toISOString())
21681
- });
21752
+ }), FINDING_LIST_USAGE = "workit finding list [--branch <b>] [--status open|resolved] [--json]";
21682
21753
  var init_task = __esm(() => {
21683
21754
  init_check_config();
21684
21755
  init_autonomy();
@@ -21695,7 +21766,7 @@ var init_task = __esm(() => {
21695
21766
  task: ["start", "list", "inspect", "revise", "progress", "pause", "resume", "close"],
21696
21767
  policy: ["assess", "preview", "explain"],
21697
21768
  evidence: ["record"],
21698
- finding: ["record", "resolve"],
21769
+ finding: ["record", "resolve", "list"],
21699
21770
  decision: ["record", "revoke"],
21700
21771
  worker: ["assign", "report", "cancel"],
21701
21772
  state: ["export", "import"]
@@ -86747,10 +86818,124 @@ var init_forge_common = __esm(() => {
86747
86818
  // packages/workit-cli/src/verbs/pr.ts
86748
86819
  var exports_pr = {};
86749
86820
  __export(exports_pr, {
86821
+ checkPrTitle: () => checkPrTitle,
86750
86822
  run: () => run15
86751
86823
  });
86752
- import { readFileSync as readFileSync27 } from "node:fs";
86824
+ import { existsSync as existsSync26, readFileSync as readFileSync27 } from "node:fs";
86753
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
+ }
86754
86939
  function readBodyFile(io, file) {
86755
86940
  try {
86756
86941
  return {
@@ -86920,6 +87105,9 @@ async function create4(argv, io) {
86920
87105
  }
86921
87106
  if (!base)
86922
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;
86923
87111
  const connected = connect(io, branch);
86924
87112
  if (!connected.ok)
86925
87113
  return forgeFail(io, connected);
@@ -86931,6 +87119,11 @@ async function create4(argv, io) {
86931
87119
  title ||= filled.data.title;
86932
87120
  body ??= filled.data.body;
86933
87121
  }
87122
+ if (!flags.values.title) {
87123
+ const filled = refuseTitle(io, title, CREATE_USAGE);
87124
+ if (filled !== null)
87125
+ return filled;
87126
+ }
86934
87127
  const forge = connected.data.forge;
86935
87128
  const planned = planIssueLinks(io.cwd, {
86936
87129
  issues: flags.lists.issue ?? [],
@@ -87149,6 +87342,11 @@ async function edit(argv, io) {
87149
87342
  return usage4(io, read, EDIT_USAGE);
87150
87343
  body = read.body;
87151
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
+ }
87152
87350
  const connected = connect(io);
87153
87351
  if (!connected.ok)
87154
87352
  return forgeFail(io, connected);
@@ -87251,7 +87449,19 @@ async function run15(argv, io) {
87251
87449
  return reply(rest, io);
87252
87450
  return usage4(io, sub && !sub.startsWith("-") ? `unknown pr subcommand "${sub}"` : "missing pr subcommand", USAGE9);
87253
87451
  }
87254
- 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]", 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) => {
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) => {
87255
87465
  if (verdict.review === "self-reviewed")
87256
87466
  return `self-reviewed (lane ${verdict.lane}): the author's verdict ${verdict.verdictId ?? "?"}; no independent verdict accepted for that head`;
87257
87467
  if (!verdict.verdictId)
@@ -87275,8 +87485,48 @@ var init_pr = __esm(() => {
87275
87485
  init_lane();
87276
87486
  init_pr_lane();
87277
87487
  init_vcs_config();
87488
+ init_check_config();
87278
87489
  init_output();
87279
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
+ ];
87280
87530
  NEED_TEXT = {
87281
87531
  none: "no verdict",
87282
87532
  self: "the author's own --self verdict (or an independent one)",
@@ -87733,10 +87983,10 @@ async function push(argv, io) {
87733
87983
  });
87734
87984
  if (typeof flags === "string")
87735
87985
  return usage4(io, flags, PUSH_USAGE);
87736
- const release = flags.lists.release;
87986
+ const release = flags.lists.release?.flatMap((value) => value.split(",").map((name) => name.trim()).filter(Boolean));
87737
87987
  if (release) {
87738
87988
  if (flags.booleans.size || flags.values.expect !== undefined || flags.positionals.length)
87739
- return usage4(io, "--release takes only ref names (repeat it: --release main --release v1.2.0)", PUSH_USAGE);
87989
+ return usage4(io, "--release takes only ref names (a comma list or a repeated flag: --release main,v1.2.0)", PUSH_USAGE);
87740
87990
  return releasePush(release, io);
87741
87991
  }
87742
87992
  if (flags.positionals.length)
@@ -87838,7 +88088,7 @@ async function run17(argv, io) {
87838
88088
  return trailers(rest, io);
87839
88089
  return usage4(io, sub && !sub.startsWith("-") ? `unknown git subcommand "${sub}"` : "missing git subcommand", USAGE10);
87840
88090
  }
87841
- 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;
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;
87842
88092
  var init_git2 = __esm(() => {
87843
88093
  init_autonomy();
87844
88094
  init_branch();
@@ -90128,7 +90378,13 @@ async function run22(argv, io) {
90128
90378
  type: values.type,
90129
90379
  last: last ?? 50
90130
90380
  });
90131
- return emit(io, ok2({ path: ledger.value.path, skipped: ledger.value.skipped, rows: listed }), (data) => data.rows.length ? data.rows.map((row) => {
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) => {
90132
90388
  const line = summarizeRow(row);
90133
90389
  return `#${line.seq} ${line.at} ${line.type}${line.branch ? ` [${line.branch}]` : ""}${line.labels.length ? ` (${line.labels.join(", ")})` : ""} ${line.summary}`;
90134
90390
  }) : "ledger is empty");
@@ -106273,7 +106529,7 @@ var init_rules = __esm(() => {
106273
106529
 
106274
106530
  // packages/workit-cli/src/test-audit/audit.ts
106275
106531
  import { spawnSync as spawnSync29 } from "node:child_process";
106276
- import { existsSync as existsSync26, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
106532
+ import { existsSync as existsSync27, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
106277
106533
  import path71 from "node:path";
106278
106534
  function git7(cwd, args) {
106279
106535
  const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
@@ -106300,7 +106556,7 @@ function expandPaths(cwd, inputs) {
106300
106556
  const missing = [];
106301
106557
  for (const input of inputs.length > 0 ? inputs : ["."]) {
106302
106558
  const full = path71.resolve(cwd, input);
106303
- if (!existsSync26(full))
106559
+ if (!existsSync27(full))
106304
106560
  missing.push(input);
106305
106561
  else if (statSync10(full).isDirectory())
106306
106562
  walkTests(full, files);
@@ -106416,7 +106672,7 @@ var init_audit = __esm(() => {
106416
106672
  // packages/workit-cli/src/test-audit/mutate.ts
106417
106673
  import { spawn as spawn2 } from "node:child_process";
106418
106674
  import {
106419
- existsSync as existsSync27,
106675
+ existsSync as existsSync28,
106420
106676
  lstatSync as lstatSync8,
106421
106677
  mkdirSync as mkdirSync12,
106422
106678
  mkdtempSync as mkdtempSync4,
@@ -106645,7 +106901,7 @@ function copyWorkingTree(repo) {
106645
106901
  }
106646
106902
  for (const parent of dirs) {
106647
106903
  const modules = path72.join(repo, parent, "node_modules");
106648
- if (existsSync27(modules) && !existsSync27(path72.join(tree, parent, "node_modules")))
106904
+ if (existsSync28(modules) && !existsSync28(path72.join(tree, parent, "node_modules")))
106649
106905
  linkNodeModules(modules, path72.join(tree, parent, "node_modules"), repo, tree);
106650
106906
  }
106651
106907
  return { dir, tree };
@@ -106695,7 +106951,7 @@ async function runMutation(options) {
106695
106951
  const relative = toPosix(path72.relative(repo, absolute));
106696
106952
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
106697
106953
  continue;
106698
- if (NOT_SOURCE.test(relative) || !existsSync27(absolute))
106954
+ if (NOT_SOURCE.test(relative) || !existsSync28(absolute))
106699
106955
  continue;
106700
106956
  try {
106701
106957
  candidates.push(...mutantsFor(readFileSync30(absolute, "utf8"), relative, lines));
@@ -106885,7 +107141,7 @@ var exports_test_audit = {};
106885
107141
  __export(exports_test_audit, {
106886
107142
  run: () => run23
106887
107143
  });
106888
- import { existsSync as existsSync28 } from "node:fs";
107144
+ import { existsSync as existsSync29 } from "node:fs";
106889
107145
  import path73 from "node:path";
106890
107146
  function parse8(argv) {
106891
107147
  const options = {
@@ -107009,7 +107265,7 @@ usage: ${USAGE16}`));
107009
107265
  }
107010
107266
  let files;
107011
107267
  if (options.diff && changed)
107012
- files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync28(file)).toSorted();
107268
+ files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync29(file)).toSorted();
107013
107269
  else {
107014
107270
  const expanded = expandPaths(io.cwd, options.paths);
107015
107271
  if (expanded.missing.length > 0)
@@ -107457,7 +107713,11 @@ var FAMILY_ACTIONS = {
107457
107713
  explain: "Explain the policy in force"
107458
107714
  },
107459
107715
  evidence: { record: "Record evidence against a task's requirements" },
107460
- finding: { record: "Record a finding", resolve: "Resolve a 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
+ },
107461
107721
  decision: {
107462
107722
  record: "Record a task decision",
107463
107723
  revoke: "Revoke a task decision"
@@ -107504,7 +107764,7 @@ var familySubcommands = (name) => {
107504
107764
  const implicit = name === "task" ? TASK_IMPLICIT : [];
107505
107765
  const grammar = Object.entries(FAMILY_ACTIONS[name]).filter(([action]) => !implicit.some((entry) => entry.name === action)).map(([action, summary]) => ({
107506
107766
  name: action,
107507
- 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}`,
107508
107768
  summary
107509
107769
  }));
107510
107770
  return [...implicit, ...grammar];
@@ -107819,7 +108079,7 @@ var VERBS = [
107819
108079
  {
107820
108080
  name: "push",
107821
108081
  deferredFlags: ["force"],
107822
- 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>[,…]]",
107823
108083
  summary: "Push the current branch and verify the remote tip (never a blind --force); --release finishes a git-flow release"
107824
108084
  },
107825
108085
  {
@@ -107989,7 +108249,7 @@ var VERBS = [
107989
108249
  name: "list",
107990
108250
  aliases: ["show"],
107991
108251
  usage: "workit ledger list|show [--branch <b>] [--pr <n>] [--type <t>] [--last <n>]",
107992
- summary: "List ledger rows, newest last"
108252
+ summary: "List ledger rows, newest last (findings live in the task: workit finding list)"
107993
108253
  },
107994
108254
  {
107995
108255
  name: "check",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.39.3",
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.3",
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.3"
47
+ "@brainervirus/workit-core": "^8.39.4"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"