@staff0rd/assist 0.660.2 → 0.662.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 CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.660.2",
9
+ version: "0.662.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -651,8 +651,7 @@ var DEFAULT_BACKUP_DIR = "~/.assist/backups";
651
651
  var DEFAULT_CLONE_DIR = "~/git";
652
652
  var assistConfigShape = {
653
653
  advice: z3.strictObject({
654
- include: z3.array(z3.enum(adviceFragmentNames)).default([]),
655
- exclude: z3.array(z3.enum(adviceFragmentNames)).default([]),
654
+ fragments: z3.partialRecord(z3.enum(adviceFragmentNames), z3.boolean()).default({}),
656
655
  extra: z3.string().optional(),
657
656
  verify: z3.string().optional()
658
657
  }).optional(),
@@ -717,7 +716,12 @@ var assistConfigShape = {
717
716
  readingWordsPerMinute: z3.number().int().positive().optional()
718
717
  }).optional(),
719
718
  review: z3.strictObject({
720
- codexModel: z3.string().optional()
719
+ codexModel: z3.string().optional(),
720
+ highLevel: z3.strictObject({
721
+ criticalPaths: z3.array(z3.string()).default([]),
722
+ uiPaths: z3.array(z3.string()).default([]),
723
+ descriptionWordCap: z3.number().int().positive().default(300)
724
+ }).optional()
721
725
  }).optional(),
722
726
  readTime: z3.strictObject({
723
727
  wordsPerMinute: z3.number().int().positive().default(200)
@@ -1941,10 +1945,10 @@ import fs11 from "fs";
1941
1945
 
1942
1946
  // src/commands/lint/shared.ts
1943
1947
  import chalk24 from "chalk";
1944
- function reportViolations2(violations, checkName, errorMessage, successMessage) {
1948
+ function reportViolations2(violations, checkName2, errorMessage, successMessage) {
1945
1949
  if (violations.length > 0) {
1946
1950
  console.error(chalk24.red(`
1947
- ${checkName} failed:
1951
+ ${checkName2} failed:
1948
1952
  `));
1949
1953
  console.error(chalk24.red(` ${errorMessage}
1950
1954
  `));
@@ -2865,8 +2869,7 @@ function configHelp(command, entries, preamble) {
2865
2869
 
2866
2870
  // src/shared/configEnumDescriptions.ts
2867
2871
  var byKey = {
2868
- "advice.include": adviceFragmentTitles,
2869
- "advice.exclude": adviceFragmentTitles
2872
+ "advice.fragments": adviceFragmentTitles
2870
2873
  };
2871
2874
  function configEnumDescriptions(key) {
2872
2875
  return byKey[key];
@@ -2997,11 +3000,24 @@ function unionOfObjectsConfigNode(inner, base, build2) {
2997
3000
  }
2998
3001
 
2999
3002
  // src/shared/recordConfigNode.ts
3003
+ function enumKeyValues(keyType, base, build2) {
3004
+ if (!keyType) return void 0;
3005
+ const key = build2(keyType, base.path);
3006
+ return key.kind === "scalar" ? key.enumValues : void 0;
3007
+ }
3000
3008
  function recordConfigNode(inner, base, build2) {
3001
3009
  const valueType = inner.def?.valueType;
3002
3010
  if (inner.def?.type !== "record" || !valueType) return void 0;
3003
3011
  const value = build2(valueType, [...base.path, { kind: "entry" }]);
3004
- return { ...base, kind: "record", value };
3012
+ const keyValues = enumKeyValues(inner.def?.keyType, base, build2);
3013
+ const keyDescriptions = keyValues ? configEnumDescriptions(formatConfigPath(base.path)) : void 0;
3014
+ return {
3015
+ ...base,
3016
+ kind: "record",
3017
+ value,
3018
+ ...keyValues ? { keyValues } : {},
3019
+ ...keyDescriptions ? { keyDescriptions } : {}
3020
+ };
3005
3021
  }
3006
3022
 
3007
3023
  // src/shared/scalarConfigNode.ts
@@ -3096,14 +3112,9 @@ function enumerateConfigLeafKeys(schema2) {
3096
3112
  // src/commands/advise/adviceConfigHelp.ts
3097
3113
  var adviceConfigHelp = [
3098
3114
  {
3099
- key: "advice.include",
3100
- setter: 'assist config set advice.include "refactor"',
3101
- note: "fragment names included whatever their condition says; 'assist advise --explain' lists every name"
3102
- },
3103
- {
3104
- key: "advice.exclude",
3105
- setter: 'assist config set advice.exclude "jira-context"',
3106
- note: "fragment names dropped even when their condition matches; 'assist advise --explain' lists every name"
3115
+ key: "advice.fragments",
3116
+ setter: "assist config set advice.fragments.verify false",
3117
+ note: "force a fragment on (true) or off (false) whatever its condition says; 'assist advise --explain' lists every name"
3107
3118
  },
3108
3119
  {
3109
3120
  key: "advice.extra",
@@ -3363,6 +3374,21 @@ var reviewConfigHelp = [
3363
3374
  key: "review.codexModel",
3364
3375
  setter: "assist config set review.codexModel gpt-5-codex",
3365
3376
  note: "optional; runs the codex reviewer on this model via the LiteLLM proxy (needs litellm.baseUrl and litellm.apiKey)"
3377
+ },
3378
+ {
3379
+ key: "review.highLevel.criticalPaths",
3380
+ setter: 'assist config set review.highLevel.criticalPaths "**/*.graphql,en-AU/translation.json"',
3381
+ note: "comma-separated globs whose full diffs the high-level review shows; unset shows none"
3382
+ },
3383
+ {
3384
+ key: "review.highLevel.uiPaths",
3385
+ setter: 'assist config set review.highLevel.uiPaths "src/ui/**"',
3386
+ note: "comma-separated globs that make a change a UI change, so --high-level requires a screenshot or video; unset requires none"
3387
+ },
3388
+ {
3389
+ key: "review.highLevel.descriptionWordCap",
3390
+ setter: "assist config set review.highLevel.descriptionWordCap 300",
3391
+ note: "word cap --high-level holds the PR description to (default 300)"
3366
3392
  }
3367
3393
  ];
3368
3394
 
@@ -5010,12 +5036,12 @@ function addViteBaseConfig() {
5010
5036
  console.log("vite.config.ts already has base config");
5011
5037
  return;
5012
5038
  }
5013
- const updated = content.replace(
5039
+ const updated2 = content.replace(
5014
5040
  /defineConfig\(\{/,
5015
5041
  'defineConfig({\n base: "./",'
5016
5042
  );
5017
- if (updated !== content) {
5018
- writeFileSync13(viteConfigPath, updated);
5043
+ if (updated2 !== content) {
5044
+ writeFileSync13(viteConfigPath, updated2);
5019
5045
  console.log('Added base: "./" to vite.config.ts');
5020
5046
  }
5021
5047
  }
@@ -5349,13 +5375,14 @@ var adviceConditions = {
5349
5375
 
5350
5376
  // src/commands/advise/selectAdvice.ts
5351
5377
  function decide(fragment, context) {
5352
- const advice = context.config.advice;
5353
- const exclude = advice?.exclude ?? [];
5354
- const include = advice?.include ?? [];
5355
- if (exclude.includes(fragment.name))
5356
- return { fragment, included: false, reason: "excluded by advice.exclude" };
5357
- if (include.includes(fragment.name))
5358
- return { fragment, included: true, reason: "included by advice.include" };
5378
+ const fragments = context.config.advice?.fragments ?? {};
5379
+ const override = fragments[fragment.name];
5380
+ if (override !== void 0)
5381
+ return {
5382
+ fragment,
5383
+ included: override,
5384
+ reason: `advice.fragments.${fragment.name} is ${override}`
5385
+ };
5359
5386
  const condition = adviceConditions[fragment.when];
5360
5387
  if (!condition)
5361
5388
  return {
@@ -10716,16 +10743,16 @@ async function patchItemStatus(req, res, id) {
10716
10743
  const result = await findItemOr404(res, id);
10717
10744
  if (!result) return;
10718
10745
  await updateStatus(result.orm, id, status3);
10719
- const updated = { ...result.item, status: status3 };
10720
- respondJson(res, 200, updated);
10746
+ const updated2 = { ...result.item, status: status3 };
10747
+ respondJson(res, 200, updated2);
10721
10748
  }
10722
10749
  async function patchItemStar(req, res, id) {
10723
10750
  const { starred } = await parseStarBody(req);
10724
10751
  const result = await findItemOr404(res, id);
10725
10752
  if (!result) return;
10726
10753
  await updateStarred(result.orm, id, starred);
10727
- const updated = { ...result.item, starred };
10728
- respondJson(res, 200, updated);
10754
+ const updated2 = { ...result.item, starred };
10755
+ respondJson(res, 200, updated2);
10729
10756
  }
10730
10757
 
10731
10758
  // src/commands/backlog/web/deleteItemComment.ts
@@ -13045,15 +13072,15 @@ function setNestedValue(obj, path91, value) {
13045
13072
  }
13046
13073
 
13047
13074
  // src/commands/config/validateConfig.ts
13048
- function validateConfig(updated, key, schema2 = assistConfigSchema) {
13049
- const result = schema2.safeParse(stripLegacyConfigKeys(updated));
13075
+ function validateConfig(updated2, key, schema2 = assistConfigSchema) {
13076
+ const result = schema2.safeParse(stripLegacyConfigKeys(updated2));
13050
13077
  if (result.success) return { ok: true };
13051
13078
  const errors = result.error.issues.flatMap(
13052
13079
  (issue) => formatIssue2(issue, key)
13053
13080
  );
13054
13081
  return {
13055
13082
  ok: false,
13056
- errors: scrubConfigSecrets(errors, updated, describeConfigNode(schema2))
13083
+ errors: scrubConfigSecrets(errors, updated2, describeConfigNode(schema2))
13057
13084
  };
13058
13085
  }
13059
13086
  function formatIssue2(issue, key) {
@@ -13076,14 +13103,14 @@ function applyConfigSet(key, coerced, global, cwd = process.cwd(), globalConfigP
13076
13103
  };
13077
13104
  }
13078
13105
  const raw = global ? loadGlobalConfigRaw(globalConfigPath) : loadProjectConfig(cwd);
13079
- const updated = setNestedValue(raw, key, coerced);
13080
- const validation = validateConfig(updated, key);
13106
+ const updated2 = setNestedValue(raw, key, coerced);
13107
+ const validation = validateConfig(updated2, key);
13081
13108
  if (!validation.ok) return validation;
13082
13109
  if (global) {
13083
- saveGlobalConfig(updated, globalConfigPath);
13110
+ saveGlobalConfig(updated2, globalConfigPath);
13084
13111
  return { ok: true, target: "global" };
13085
13112
  }
13086
- saveConfig(updated, cwd);
13113
+ saveConfig(updated2, cwd);
13087
13114
  return { ok: true, target: "project" };
13088
13115
  }
13089
13116
 
@@ -16467,20 +16494,20 @@ function hasListMutations(options2) {
16467
16494
  options2.add && options2.add.length > 0 || options2.edit || options2.remove
16468
16495
  );
16469
16496
  }
16470
- function applyListMutations(current, options2, flags) {
16497
+ function applyListMutations(current, options2, flags2) {
16471
16498
  let items2 = [...current];
16472
16499
  if (options2.edit) {
16473
16500
  const [rawIndex, ...textParts] = options2.edit;
16474
16501
  if (rawIndex === void 0 || textParts.length === 0) {
16475
16502
  return {
16476
16503
  ok: false,
16477
- error: `${flags.edit} requires an index and replacement text.`
16504
+ error: `${flags2.edit} requires an index and replacement text.`
16478
16505
  };
16479
16506
  }
16480
16507
  const parsed = parseListIndex(
16481
16508
  rawIndex,
16482
16509
  items2.length,
16483
- `${flags.edit} index`
16510
+ `${flags2.edit} index`
16484
16511
  );
16485
16512
  if (!parsed.ok) return parsed;
16486
16513
  items2[parsed.index - 1] = textParts.join(" ");
@@ -16489,7 +16516,7 @@ function applyListMutations(current, options2, flags) {
16489
16516
  const parsed = parseListIndex(
16490
16517
  options2.remove,
16491
16518
  items2.length,
16492
- `${flags.remove} index`
16519
+ `${flags2.remove} index`
16493
16520
  );
16494
16521
  if (!parsed.ok) return parsed;
16495
16522
  items2 = items2.filter((_, i) => i !== parsed.index - 1);
@@ -16501,15 +16528,15 @@ function applyListMutations(current, options2, flags) {
16501
16528
  }
16502
16529
 
16503
16530
  // src/commands/backlog/update/resolveListUpdate.ts
16504
- function resolveListUpdate(whole, current, mutations, wholeFlag, flags) {
16531
+ function resolveListUpdate(whole, current, mutations, wholeFlag, flags2) {
16505
16532
  if (!hasListMutations(mutations)) return { ok: true, items: whole };
16506
16533
  if (whole) {
16507
16534
  return {
16508
16535
  ok: false,
16509
- error: `Cannot combine ${wholeFlag} with ${flags.add}/${flags.edit}/${flags.remove}.`
16536
+ error: `Cannot combine ${wholeFlag} with ${flags2.add}/${flags2.edit}/${flags2.remove}.`
16510
16537
  };
16511
16538
  }
16512
- return applyListMutations(current, mutations, flags);
16539
+ return applyListMutations(current, mutations, flags2);
16513
16540
  }
16514
16541
 
16515
16542
  // src/commands/backlog/resolvePhaseFields.ts
@@ -18428,8 +18455,8 @@ function loadDenyConfig(global) {
18428
18455
  const deny = config.deny ?? [];
18429
18456
  return {
18430
18457
  deny,
18431
- saveDeny: (updated) => {
18432
- config.deny = updated;
18458
+ saveDeny: (updated2) => {
18459
+ config.deny = updated2;
18433
18460
  save(config);
18434
18461
  }
18435
18462
  };
@@ -27471,8 +27498,218 @@ async function reply(commentId, body) {
27471
27498
  }
27472
27499
  }
27473
27500
 
27474
- // src/commands/prs/wontfix.ts
27501
+ // src/commands/prs/status/describeFetchError.ts
27502
+ function firstLine2(text18) {
27503
+ const line = text18.split("\n").map((candidate) => candidate.trim()).find((candidate) => candidate.length > 0);
27504
+ return line ?? null;
27505
+ }
27506
+ function stderrText(error) {
27507
+ const stderr = error?.stderr;
27508
+ if (typeof stderr === "string") return firstLine2(stderr);
27509
+ if (stderr instanceof Uint8Array) {
27510
+ return firstLine2(Buffer.from(stderr).toString("utf8"));
27511
+ }
27512
+ return null;
27513
+ }
27514
+ function describeFetchError(error) {
27515
+ if (isGhNotInstalled(error)) {
27516
+ return "GitHub CLI (gh) is not installed \u2014 see https://cli.github.com/";
27517
+ }
27518
+ const stderr = stderrText(error);
27519
+ if (stderr) return stderr;
27520
+ if (error instanceof Error) return firstLine2(error.message) ?? error.message;
27521
+ return String(error);
27522
+ }
27523
+
27524
+ // src/commands/prs/status/fetchRepoPullRequests.ts
27475
27525
  import { execSync as execSync51 } from "child_process";
27526
+ var FIELDS = "number,title,url,author,isDraft,createdAt,updatedAt,reviewDecision,latestReviews,statusCheckRollup,mergeable";
27527
+ function fetchRepoPullRequests(org, repo) {
27528
+ const output = execSync51(
27529
+ `gh pr list --state open --json ${FIELDS} --limit 100 -R ${org}/${repo}`,
27530
+ { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
27531
+ );
27532
+ const parsed = JSON.parse(output);
27533
+ if (!Array.isArray(parsed)) {
27534
+ throw new Error("unexpected response from gh pr list");
27535
+ }
27536
+ return parsed;
27537
+ }
27538
+
27539
+ // src/commands/prs/status/parseRepoArgument.ts
27540
+ var REPO_ARGUMENT = /^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)$/;
27541
+ function parseRepoArgument(value) {
27542
+ const match = REPO_ARGUMENT.exec(value.trim());
27543
+ if (!match) return null;
27544
+ return { org: match[1], repo: match[2] };
27545
+ }
27546
+
27547
+ // src/commands/prs/status/describeAge.ts
27548
+ function describeAge(timestamp6, now = Date.now()) {
27549
+ const parsed = new Date(timestamp6).getTime();
27550
+ if (Number.isNaN(parsed)) return { hours: null, label: "unknown" };
27551
+ const hours = Math.max(0, Math.floor((now - parsed) / 36e5));
27552
+ if (hours < 1) return { hours, label: "<1h" };
27553
+ if (hours < 24) return { hours, label: `${hours}h` };
27554
+ return { hours, label: `${Math.floor(hours / 24)}d` };
27555
+ }
27556
+
27557
+ // src/commands/prs/status/summariseChecks.ts
27558
+ var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["SUCCESS", "NEUTRAL", "SKIPPED"]);
27559
+ var PENDING_STATES = /* @__PURE__ */ new Set(["PENDING", "EXPECTED"]);
27560
+ function checkName(check2) {
27561
+ return check2.name?.trim() || check2.context?.trim() || "unnamed check";
27562
+ }
27563
+ function isPending(check2) {
27564
+ if (check2.status) return check2.status !== "COMPLETED";
27565
+ return PENDING_STATES.has(check2.state ?? "");
27566
+ }
27567
+ function isFailing(check2) {
27568
+ if (check2.status) return !PASSING_CONCLUSIONS.has(check2.conclusion ?? "");
27569
+ return !PASSING_CONCLUSIONS.has(check2.state ?? "");
27570
+ }
27571
+ function summariseChecks(rollup) {
27572
+ const summary = { failing: [], pending: [] };
27573
+ for (const check2 of rollup ?? []) {
27574
+ if (isPending(check2)) summary.pending.push(checkName(check2));
27575
+ else if (isFailing(check2)) summary.failing.push(checkName(check2));
27576
+ }
27577
+ return summary;
27578
+ }
27579
+
27580
+ // src/commands/prs/status/toPrStatus.ts
27581
+ function toReviews(pr) {
27582
+ return (pr.latestReviews ?? []).map((review2) => ({
27583
+ reviewer: review2.author?.login ?? "unknown",
27584
+ state: review2.state ?? "UNKNOWN"
27585
+ }));
27586
+ }
27587
+ function toPrStatus(pr, now = Date.now()) {
27588
+ const age = describeAge(pr.updatedAt, now);
27589
+ return {
27590
+ number: pr.number,
27591
+ title: pr.title,
27592
+ url: pr.url,
27593
+ author: pr.author?.login ?? "unknown",
27594
+ isBot: pr.author?.is_bot === true,
27595
+ isDraft: pr.isDraft === true,
27596
+ createdAt: pr.createdAt,
27597
+ updatedAt: pr.updatedAt,
27598
+ age: age.label,
27599
+ ageHours: age.hours,
27600
+ reviewDecision: pr.reviewDecision || null,
27601
+ reviews: toReviews(pr),
27602
+ checks: summariseChecks(pr.statusCheckRollup),
27603
+ mergeable: pr.mergeable || "UNKNOWN"
27604
+ };
27605
+ }
27606
+
27607
+ // src/commands/prs/status/buildPrsStatusReport.ts
27608
+ function buildPrsStatusReport(repoArguments, now = Date.now()) {
27609
+ const report2 = { repos: [], errors: [] };
27610
+ for (const argument of repoArguments) {
27611
+ const parsed = parseRepoArgument(argument);
27612
+ if (!parsed) {
27613
+ report2.errors.push({
27614
+ repo: argument,
27615
+ error: "not an owner/repo argument"
27616
+ });
27617
+ continue;
27618
+ }
27619
+ const repo = `${parsed.org}/${parsed.repo}`;
27620
+ try {
27621
+ const pullRequests = fetchRepoPullRequests(parsed.org, parsed.repo).map(
27622
+ (pr) => toPrStatus(pr, now)
27623
+ );
27624
+ report2.repos.push({ repo, pullRequests });
27625
+ } catch (error) {
27626
+ report2.errors.push({ repo, error: describeFetchError(error) });
27627
+ }
27628
+ }
27629
+ return report2;
27630
+ }
27631
+
27632
+ // src/commands/prs/status/printPrsStatus.ts
27633
+ import chalk187 from "chalk";
27634
+
27635
+ // src/commands/prs/status/printPrStatus.ts
27636
+ import chalk186 from "chalk";
27637
+ function flags(pr) {
27638
+ const markers = [];
27639
+ if (pr.isDraft) markers.push("draft");
27640
+ if (pr.isBot) markers.push("bot");
27641
+ return markers.length ? ` ${chalk186.yellow(`[${markers.join(", ")}]`)}` : "";
27642
+ }
27643
+ function updated(pr) {
27644
+ return pr.ageHours === null ? "updated unknown" : `updated ${pr.age} ago`;
27645
+ }
27646
+ function reviewLine(pr) {
27647
+ if (!pr.reviewDecision && pr.reviews.length === 0) return null;
27648
+ const reviewers = pr.reviews.map((review2) => `${review2.reviewer}: ${review2.state}`).join(", ");
27649
+ const decision = pr.reviewDecision ?? "no decision";
27650
+ return reviewers ? `review: ${decision} | ${reviewers}` : `review: ${decision}`;
27651
+ }
27652
+ function checkLines(pr) {
27653
+ const lines2 = [];
27654
+ if (pr.checks.failing.length) {
27655
+ lines2.push(chalk186.red(`failing: ${pr.checks.failing.join(", ")}`));
27656
+ }
27657
+ if (pr.checks.pending.length) {
27658
+ lines2.push(chalk186.yellow(`pending: ${pr.checks.pending.join(", ")}`));
27659
+ }
27660
+ return lines2;
27661
+ }
27662
+ function mergeableLine(pr) {
27663
+ if (pr.mergeable === "CONFLICTING") return chalk186.red("conflicting");
27664
+ if (pr.mergeable === "MERGEABLE") return null;
27665
+ return chalk186.dim(`mergeable: ${pr.mergeable.toLowerCase()}`);
27666
+ }
27667
+ function printPrStatus(pr) {
27668
+ console.log(
27669
+ ` ${chalk186.cyan(`#${pr.number}`)} ${pr.title} ${chalk186.dim(`(${pr.author}, ${updated(pr)})`)}${flags(pr)}`
27670
+ );
27671
+ const details = [
27672
+ reviewLine(pr),
27673
+ ...checkLines(pr),
27674
+ mergeableLine(pr),
27675
+ chalk186.dim(pr.url)
27676
+ ];
27677
+ for (const detail of details) {
27678
+ if (detail) console.log(` ${detail}`);
27679
+ }
27680
+ }
27681
+
27682
+ // src/commands/prs/status/printPrsStatus.ts
27683
+ function printPrsStatus(report2) {
27684
+ for (const repo of report2.repos) {
27685
+ const count8 = repo.pullRequests.length;
27686
+ console.log(`${chalk187.bold(repo.repo)} ${chalk187.dim(`(${count8} open)`)}`);
27687
+ for (const pr of repo.pullRequests) {
27688
+ printPrStatus(pr);
27689
+ }
27690
+ if (count8 === 0) console.log(chalk187.dim(" no open pull requests"));
27691
+ console.log();
27692
+ }
27693
+ if (report2.errors.length === 0) return;
27694
+ console.log(chalk187.bold("Errors"));
27695
+ for (const failure of report2.errors) {
27696
+ console.log(` ${chalk187.red(failure.repo)}: ${failure.error}`);
27697
+ }
27698
+ console.log();
27699
+ }
27700
+
27701
+ // src/commands/prs/status/index.ts
27702
+ function prsStatus(repos2, options2) {
27703
+ const report2 = buildPrsStatusReport(repos2);
27704
+ if (options2.json) {
27705
+ console.log(JSON.stringify(report2, null, 2));
27706
+ return;
27707
+ }
27708
+ printPrsStatus(report2);
27709
+ }
27710
+
27711
+ // src/commands/prs/wontfix.ts
27712
+ import { execSync as execSync52 } from "child_process";
27476
27713
  function validateReason(reason4) {
27477
27714
  const lowerReason = reason4.toLowerCase();
27478
27715
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -27489,7 +27726,7 @@ function validateShaReferences(reason4) {
27489
27726
  const invalidShas = [];
27490
27727
  for (const sha of shas) {
27491
27728
  try {
27492
- execSync51(`git cat-file -t ${sha}`, { stdio: "pipe" });
27729
+ execSync52(`git cat-file -t ${sha}`, { stdio: "pipe" });
27493
27730
  } catch {
27494
27731
  invalidShas.push(sha);
27495
27732
  }
@@ -27782,6 +28019,13 @@ function registerPrsRaise(prsCommand) {
27782
28019
  configHelp(raiseCommand, prsRaiseConfigHelp);
27783
28020
  }
27784
28021
 
28022
+ // src/commands/registerPrsStatus.ts
28023
+ function registerPrsStatus(prsCommand) {
28024
+ prsCommand.command("status <repo...>").description(
28025
+ "Report every open pull request in each owner/repo, grouped by repo"
28026
+ ).option("--json", "Output as JSON").action(prsStatus);
28027
+ }
28028
+
27785
28029
  // src/commands/readTime/readTime.ts
27786
28030
  import { readFileSync as readFileSync46 } from "fs";
27787
28031
 
@@ -27871,7 +28115,7 @@ function resolveReadTimeTarget(target) {
27871
28115
  }
27872
28116
 
27873
28117
  // src/commands/prs/fetchPrBody.ts
27874
- import { execSync as execSync52 } from "child_process";
28118
+ import { execSync as execSync53 } from "child_process";
27875
28119
  function exitGhNotInstalled() {
27876
28120
  console.error("Error: GitHub CLI (gh) is not installed.");
27877
28121
  console.error("Install it from https://cli.github.com/");
@@ -27892,7 +28136,7 @@ function currentRepo() {
27892
28136
  function fetchPrBody(number, repo) {
27893
28137
  const { org, repo: name } = repo ?? currentRepo();
27894
28138
  try {
27895
- const raw = execSync52(`gh pr view ${number} --json body -R ${org}/${name}`, {
28139
+ const raw = execSync53(`gh pr view ${number} --json body -R ${org}/${name}`, {
27896
28140
  encoding: "utf8",
27897
28141
  stdio: ["pipe", "pipe", "pipe"]
27898
28142
  });
@@ -27971,6 +28215,7 @@ function registerReadTime(parent) {
27971
28215
  function registerPrs(program2) {
27972
28216
  const prsCommand = program2.command("prs").description("Pull request utilities").option("--open", "List only open pull requests").option("--closed", "List only closed pull requests").action(prs);
27973
28217
  registerPrsRaise(prsCommand);
28218
+ registerPrsStatus(prsCommand);
27974
28219
  registerPrsEdit(prsCommand);
27975
28220
  registerPrsComments(prsCommand);
27976
28221
  registerReadTime(prsCommand);
@@ -27978,10 +28223,10 @@ function registerPrs(program2) {
27978
28223
  }
27979
28224
 
27980
28225
  // src/commands/ravendb/ravendbAuth.ts
27981
- import chalk191 from "chalk";
28226
+ import chalk193 from "chalk";
27982
28227
 
27983
28228
  // src/shared/createConnectionAuth.ts
27984
- import chalk186 from "chalk";
28229
+ import chalk188 from "chalk";
27985
28230
  function listConnections(connections, format2) {
27986
28231
  if (connections.length === 0) {
27987
28232
  console.log("No connections configured.");
@@ -27994,7 +28239,7 @@ function listConnections(connections, format2) {
27994
28239
  function removeConnection(connections, name, save) {
27995
28240
  const filtered = connections.filter((c) => c.name !== name);
27996
28241
  if (filtered.length === connections.length) {
27997
- console.error(chalk186.red(`Connection "${name}" not found.`));
28242
+ console.error(chalk188.red(`Connection "${name}" not found.`));
27998
28243
  process.exit(1);
27999
28244
  }
28000
28245
  save(filtered);
@@ -28040,17 +28285,17 @@ function saveConnections(connections) {
28040
28285
  }
28041
28286
 
28042
28287
  // src/commands/ravendb/promptConnection.ts
28043
- import chalk189 from "chalk";
28288
+ import chalk191 from "chalk";
28044
28289
 
28045
28290
  // src/commands/ravendb/selectOpSecret.ts
28046
- import chalk188 from "chalk";
28291
+ import chalk190 from "chalk";
28047
28292
  import Enquirer2 from "enquirer";
28048
28293
 
28049
28294
  // src/commands/ravendb/searchItems.ts
28050
- import { execSync as execSync53 } from "child_process";
28051
- import chalk187 from "chalk";
28295
+ import { execSync as execSync54 } from "child_process";
28296
+ import chalk189 from "chalk";
28052
28297
  function opExec(args) {
28053
- return execSync53(`op ${args}`, {
28298
+ return execSync54(`op ${args}`, {
28054
28299
  encoding: "utf8",
28055
28300
  stdio: ["pipe", "pipe", "pipe"]
28056
28301
  }).trim();
@@ -28061,7 +28306,7 @@ function searchItems(search2) {
28061
28306
  items2 = JSON.parse(opExec("item list --format=json"));
28062
28307
  } catch {
28063
28308
  console.error(
28064
- chalk187.red(
28309
+ chalk189.red(
28065
28310
  "Failed to search 1Password. Ensure the CLI is installed and you are signed in."
28066
28311
  )
28067
28312
  );
@@ -28075,7 +28320,7 @@ function getItemFields(itemId2) {
28075
28320
  const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
28076
28321
  return item.fields.filter((f) => f.reference && f.label);
28077
28322
  } catch {
28078
- console.error(chalk187.red("Failed to get item details from 1Password."));
28323
+ console.error(chalk189.red("Failed to get item details from 1Password."));
28079
28324
  process.exit(1);
28080
28325
  }
28081
28326
  }
@@ -28094,7 +28339,7 @@ async function selectOpSecret(searchTerm) {
28094
28339
  }).run();
28095
28340
  const items2 = searchItems(search2);
28096
28341
  if (items2.length === 0) {
28097
- console.error(chalk188.red(`No items found matching "${search2}".`));
28342
+ console.error(chalk190.red(`No items found matching "${search2}".`));
28098
28343
  process.exit(1);
28099
28344
  }
28100
28345
  const itemId2 = await selectOne(
@@ -28103,7 +28348,7 @@ async function selectOpSecret(searchTerm) {
28103
28348
  );
28104
28349
  const fields = getItemFields(itemId2);
28105
28350
  if (fields.length === 0) {
28106
- console.error(chalk188.red("No fields with references found on this item."));
28351
+ console.error(chalk190.red("No fields with references found on this item."));
28107
28352
  process.exit(1);
28108
28353
  }
28109
28354
  const ref = await selectOne(
@@ -28117,7 +28362,7 @@ async function selectOpSecret(searchTerm) {
28117
28362
  async function promptConnection(existingNames) {
28118
28363
  const name = await promptInput("name", "Connection name:");
28119
28364
  if (existingNames.includes(name)) {
28120
- console.error(chalk189.red(`Connection "${name}" already exists.`));
28365
+ console.error(chalk191.red(`Connection "${name}" already exists.`));
28121
28366
  process.exit(1);
28122
28367
  }
28123
28368
  const url = await promptInput(
@@ -28126,22 +28371,22 @@ async function promptConnection(existingNames) {
28126
28371
  );
28127
28372
  const database = await promptInput("database", "Database name:");
28128
28373
  if (!name || !url || !database) {
28129
- console.error(chalk189.red("All fields are required."));
28374
+ console.error(chalk191.red("All fields are required."));
28130
28375
  process.exit(1);
28131
28376
  }
28132
28377
  const apiKeyRef = await selectOpSecret();
28133
- console.log(chalk189.dim(`Using: ${apiKeyRef}`));
28378
+ console.log(chalk191.dim(`Using: ${apiKeyRef}`));
28134
28379
  return { name, url, database, apiKeyRef };
28135
28380
  }
28136
28381
 
28137
28382
  // src/commands/ravendb/ravendbSetConnection.ts
28138
- import chalk190 from "chalk";
28383
+ import chalk192 from "chalk";
28139
28384
  function ravendbSetConnection(name) {
28140
28385
  const raw = loadGlobalConfigRaw();
28141
28386
  const ravendb = raw.ravendb ?? {};
28142
28387
  const connections = ravendb.connections ?? [];
28143
28388
  if (!connections.some((c) => c.name === name)) {
28144
- console.error(chalk190.red(`Connection "${name}" not found.`));
28389
+ console.error(chalk192.red(`Connection "${name}" not found.`));
28145
28390
  console.error(
28146
28391
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
28147
28392
  );
@@ -28157,16 +28402,16 @@ function ravendbSetConnection(name) {
28157
28402
  var ravendbAuth = createConnectionAuth({
28158
28403
  load: loadConnections,
28159
28404
  save: saveConnections,
28160
- format: (c) => `${chalk191.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
28405
+ format: (c) => `${chalk193.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
28161
28406
  promptNew: promptConnection,
28162
28407
  onFirst: (c) => ravendbSetConnection(c.name)
28163
28408
  });
28164
28409
 
28165
28410
  // src/commands/ravendb/ravendbCollections.ts
28166
- import chalk195 from "chalk";
28411
+ import chalk197 from "chalk";
28167
28412
 
28168
28413
  // src/commands/ravendb/ravenFetch.ts
28169
- import chalk193 from "chalk";
28414
+ import chalk195 from "chalk";
28170
28415
 
28171
28416
  // src/commands/ravendb/getAccessToken.ts
28172
28417
  var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
@@ -28202,21 +28447,21 @@ ${errorText}`
28202
28447
  }
28203
28448
 
28204
28449
  // src/commands/ravendb/resolveOpSecret.ts
28205
- import { execSync as execSync54 } from "child_process";
28206
- import chalk192 from "chalk";
28450
+ import { execSync as execSync55 } from "child_process";
28451
+ import chalk194 from "chalk";
28207
28452
  function resolveOpSecret(reference) {
28208
28453
  if (!reference.startsWith("op://")) {
28209
- console.error(chalk192.red(`Invalid secret reference: must start with op://`));
28454
+ console.error(chalk194.red(`Invalid secret reference: must start with op://`));
28210
28455
  process.exit(1);
28211
28456
  }
28212
28457
  try {
28213
- return execSync54(`op read "${reference}"`, {
28458
+ return execSync55(`op read "${reference}"`, {
28214
28459
  encoding: "utf8",
28215
28460
  stdio: ["pipe", "pipe", "pipe"]
28216
28461
  }).trim();
28217
28462
  } catch {
28218
28463
  console.error(
28219
- chalk192.red(
28464
+ chalk194.red(
28220
28465
  "Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
28221
28466
  )
28222
28467
  );
@@ -28243,7 +28488,7 @@ async function ravenFetch(connection, path91) {
28243
28488
  if (!response.ok) {
28244
28489
  const body = await response.text();
28245
28490
  console.error(
28246
- chalk193.red(`RavenDB error: ${response.status} ${response.statusText}`)
28491
+ chalk195.red(`RavenDB error: ${response.status} ${response.statusText}`)
28247
28492
  );
28248
28493
  console.error(body.substring(0, 500));
28249
28494
  process.exit(1);
@@ -28252,7 +28497,7 @@ async function ravenFetch(connection, path91) {
28252
28497
  }
28253
28498
 
28254
28499
  // src/commands/ravendb/resolveConnection.ts
28255
- import chalk194 from "chalk";
28500
+ import chalk196 from "chalk";
28256
28501
  function loadRavendb() {
28257
28502
  const raw = loadGlobalConfigRaw();
28258
28503
  const ravendb = raw.ravendb;
@@ -28266,7 +28511,7 @@ function resolveConnection(name) {
28266
28511
  const connectionName = name ?? defaultConnection;
28267
28512
  if (!connectionName) {
28268
28513
  console.error(
28269
- chalk194.red(
28514
+ chalk196.red(
28270
28515
  "No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
28271
28516
  )
28272
28517
  );
@@ -28274,7 +28519,7 @@ function resolveConnection(name) {
28274
28519
  }
28275
28520
  const connection = connections.find((c) => c.name === connectionName);
28276
28521
  if (!connection) {
28277
- console.error(chalk194.red(`Connection "${connectionName}" not found.`));
28522
+ console.error(chalk196.red(`Connection "${connectionName}" not found.`));
28278
28523
  console.error(
28279
28524
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
28280
28525
  );
@@ -28305,15 +28550,15 @@ async function ravendbCollections(connectionName) {
28305
28550
  return;
28306
28551
  }
28307
28552
  for (const c of collections) {
28308
- console.log(`${chalk195.bold(c.Name)} ${c.CountOfDocuments} docs`);
28553
+ console.log(`${chalk197.bold(c.Name)} ${c.CountOfDocuments} docs`);
28309
28554
  }
28310
28555
  }
28311
28556
 
28312
28557
  // src/commands/ravendb/ravendbQuery.ts
28313
- import chalk197 from "chalk";
28558
+ import chalk199 from "chalk";
28314
28559
 
28315
28560
  // src/commands/ravendb/fetchAllPages.ts
28316
- import chalk196 from "chalk";
28561
+ import chalk198 from "chalk";
28317
28562
 
28318
28563
  // src/commands/ravendb/buildQueryPath.ts
28319
28564
  function buildQueryPath(opts) {
@@ -28351,7 +28596,7 @@ async function fetchAllPages(connection, opts) {
28351
28596
  allResults.push(...results);
28352
28597
  start3 += results.length;
28353
28598
  process.stderr.write(
28354
- `\r${chalk196.dim(`Fetched ${allResults.length}/${totalResults}`)}`
28599
+ `\r${chalk198.dim(`Fetched ${allResults.length}/${totalResults}`)}`
28355
28600
  );
28356
28601
  if (start3 >= totalResults) break;
28357
28602
  if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
@@ -28366,7 +28611,7 @@ async function fetchAllPages(connection, opts) {
28366
28611
  async function ravendbQuery(connectionName, collection, options2) {
28367
28612
  const resolved = resolveArgs(connectionName, collection);
28368
28613
  if (!resolved.collection && !options2.query) {
28369
- console.error(chalk197.red("Provide a collection name or --query filter."));
28614
+ console.error(chalk199.red("Provide a collection name or --query filter."));
28370
28615
  process.exit(1);
28371
28616
  }
28372
28617
  const { collection: col } = resolved;
@@ -28405,7 +28650,7 @@ import { spawn as spawn6 } from "child_process";
28405
28650
  import * as path46 from "path";
28406
28651
 
28407
28652
  // src/commands/refactor/logViolations.ts
28408
- import chalk198 from "chalk";
28653
+ import chalk200 from "chalk";
28409
28654
  var DEFAULT_MAX_LINES2 = 100;
28410
28655
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
28411
28656
  if (violations.length === 0) {
@@ -28414,43 +28659,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
28414
28659
  }
28415
28660
  return;
28416
28661
  }
28417
- console.error(chalk198.red(`
28662
+ console.error(chalk200.red(`
28418
28663
  Refactor check failed:
28419
28664
  `));
28420
- console.error(chalk198.red(` The following files exceed ${maxLines} lines:
28665
+ console.error(chalk200.red(` The following files exceed ${maxLines} lines:
28421
28666
  `));
28422
28667
  for (const violation of violations) {
28423
- console.error(chalk198.red(` ${violation.file} (${violation.lines} lines)`));
28668
+ console.error(chalk200.red(` ${violation.file} (${violation.lines} lines)`));
28424
28669
  }
28425
28670
  console.error(
28426
- chalk198.yellow(
28671
+ chalk200.yellow(
28427
28672
  `
28428
28673
  Each file needs to be sensibly refactored, or if there is no sensible
28429
28674
  way to refactor it, ignore it with:
28430
28675
  `
28431
28676
  )
28432
28677
  );
28433
- console.error(chalk198.gray(` assist refactor ignore <file>
28678
+ console.error(chalk200.gray(` assist refactor ignore <file>
28434
28679
  `));
28435
28680
  if (process.env.CLAUDECODE) {
28436
- console.error(chalk198.cyan(`
28681
+ console.error(chalk200.cyan(`
28437
28682
  ## Extracting Code to New Files
28438
28683
  `));
28439
28684
  console.error(
28440
- chalk198.cyan(
28685
+ chalk200.cyan(
28441
28686
  ` When extracting logic from one file to another, consider where the extracted code belongs:
28442
28687
  `
28443
28688
  )
28444
28689
  );
28445
28690
  console.error(
28446
- chalk198.cyan(
28691
+ chalk200.cyan(
28447
28692
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
28448
28693
  original file's domain, create a new folder containing both the original and extracted files.
28449
28694
  `
28450
28695
  )
28451
28696
  );
28452
28697
  console.error(
28453
- chalk198.cyan(
28698
+ chalk200.cyan(
28454
28699
  ` 2. Share common utilities: If the extracted code can be reused across multiple
28455
28700
  domains, move it to a common/shared folder.
28456
28701
  `
@@ -28460,7 +28705,7 @@ Refactor check failed:
28460
28705
  }
28461
28706
 
28462
28707
  // src/commands/refactor/check/getViolations/index.ts
28463
- import { execSync as execSync55 } from "child_process";
28708
+ import { execSync as execSync56 } from "child_process";
28464
28709
  import fs31 from "fs";
28465
28710
  import { minimatch as minimatch6 } from "minimatch";
28466
28711
 
@@ -28510,7 +28755,7 @@ function getGitFiles(options2) {
28510
28755
  }
28511
28756
  const files = /* @__PURE__ */ new Set();
28512
28757
  if (options2.staged || options2.modified) {
28513
- const staged = execSync55("git diff --cached --name-only", {
28758
+ const staged = execSync56("git diff --cached --name-only", {
28514
28759
  encoding: "utf8"
28515
28760
  });
28516
28761
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -28518,7 +28763,7 @@ function getGitFiles(options2) {
28518
28763
  }
28519
28764
  }
28520
28765
  if (options2.unstaged || options2.modified) {
28521
- const unstaged = execSync55("git diff --name-only", { encoding: "utf8" });
28766
+ const unstaged = execSync56("git diff --name-only", { encoding: "utf8" });
28522
28767
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
28523
28768
  files.add(file);
28524
28769
  }
@@ -28606,7 +28851,7 @@ async function check(pattern2, options2) {
28606
28851
 
28607
28852
  // src/commands/refactor/extract/index.ts
28608
28853
  import path54 from "path";
28609
- import chalk201 from "chalk";
28854
+ import chalk203 from "chalk";
28610
28855
 
28611
28856
  // src/commands/refactor/extract/applyExtraction.ts
28612
28857
  import { SyntaxKind as SyntaxKind4 } from "ts-morph";
@@ -29205,23 +29450,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
29205
29450
 
29206
29451
  // src/commands/refactor/extract/displayPlan.ts
29207
29452
  import path50 from "path";
29208
- import chalk199 from "chalk";
29453
+ import chalk201 from "chalk";
29209
29454
  function section(title) {
29210
29455
  return `
29211
- ${chalk199.cyan(title)}`;
29456
+ ${chalk201.cyan(title)}`;
29212
29457
  }
29213
29458
  function displayImporters(plan2, cwd) {
29214
29459
  if (plan2.importersToUpdate.length === 0) return;
29215
29460
  console.log(section("Update importers:"));
29216
29461
  for (const imp of plan2.importersToUpdate) {
29217
29462
  const rel = path50.relative(cwd, imp.file.getFilePath());
29218
- console.log(` ${chalk199.dim(rel)}: \u2192 import from "${imp.relPath}"`);
29463
+ console.log(` ${chalk201.dim(rel)}: \u2192 import from "${imp.relPath}"`);
29219
29464
  }
29220
29465
  }
29221
29466
  function displayPlan(functionName, relDest, plan2, cwd) {
29222
- console.log(chalk199.bold(`Extract: ${functionName} \u2192 ${relDest}
29467
+ console.log(chalk201.bold(`Extract: ${functionName} \u2192 ${relDest}
29223
29468
  `));
29224
- console.log(` ${chalk199.cyan("Functions to move:")}`);
29469
+ console.log(` ${chalk201.cyan("Functions to move:")}`);
29225
29470
  for (const name of plan2.extractedNames) {
29226
29471
  console.log(` ${name}`);
29227
29472
  }
@@ -29255,7 +29500,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
29255
29500
 
29256
29501
  // src/commands/refactor/extract/loadProjectFile.ts
29257
29502
  import path53 from "path";
29258
- import chalk200 from "chalk";
29503
+ import chalk202 from "chalk";
29259
29504
  import { Project as Project4 } from "ts-morph";
29260
29505
 
29261
29506
  // src/commands/refactor/extract/findTsConfig.ts
@@ -29347,7 +29592,7 @@ function loadProjectFile(file) {
29347
29592
  });
29348
29593
  const sourceFile = project.getSourceFile(sourcePath);
29349
29594
  if (!sourceFile) {
29350
- console.log(chalk200.red(`File not found in project: ${file}`));
29595
+ console.log(chalk202.red(`File not found in project: ${file}`));
29351
29596
  process.exit(1);
29352
29597
  }
29353
29598
  return { project, sourceFile };
@@ -29370,19 +29615,19 @@ async function extract(file, functionName, destination, options2 = {}) {
29370
29615
  displayPlan(functionName, relDest, plan2, cwd);
29371
29616
  if (options2.apply) {
29372
29617
  await applyExtraction(functionName, sourceFile, destPath, plan2, project);
29373
- console.log(chalk201.green("\nExtraction complete"));
29618
+ console.log(chalk203.green("\nExtraction complete"));
29374
29619
  } else {
29375
- console.log(chalk201.dim("\nDry run. Use --apply to execute."));
29620
+ console.log(chalk203.dim("\nDry run. Use --apply to execute."));
29376
29621
  }
29377
29622
  }
29378
29623
 
29379
29624
  // src/commands/refactor/ignore.ts
29380
29625
  import fs34 from "fs";
29381
- import chalk202 from "chalk";
29626
+ import chalk204 from "chalk";
29382
29627
  var REFACTOR_YML_PATH2 = "refactor.yml";
29383
29628
  function ignore2(file) {
29384
29629
  if (!fs34.existsSync(file)) {
29385
- console.error(chalk202.red(`Error: File does not exist: ${file}`));
29630
+ console.error(chalk204.red(`Error: File does not exist: ${file}`));
29386
29631
  process.exit(1);
29387
29632
  }
29388
29633
  const content = fs34.readFileSync(file, "utf8");
@@ -29398,7 +29643,7 @@ function ignore2(file) {
29398
29643
  fs34.writeFileSync(REFACTOR_YML_PATH2, entry);
29399
29644
  }
29400
29645
  console.log(
29401
- chalk202.green(
29646
+ chalk204.green(
29402
29647
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
29403
29648
  )
29404
29649
  );
@@ -29407,12 +29652,12 @@ function ignore2(file) {
29407
29652
  // src/commands/refactor/rename/index.ts
29408
29653
  import fs37 from "fs";
29409
29654
  import path59 from "path";
29410
- import chalk205 from "chalk";
29655
+ import chalk207 from "chalk";
29411
29656
 
29412
29657
  // src/commands/refactor/rename/applyRename.ts
29413
29658
  import fs36 from "fs";
29414
29659
  import path56 from "path";
29415
- import chalk203 from "chalk";
29660
+ import chalk205 from "chalk";
29416
29661
 
29417
29662
  // src/commands/refactor/restructure/computeRewrites/index.ts
29418
29663
  import path55 from "path";
@@ -29517,13 +29762,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
29517
29762
  const updatedContents = applyRewrites(rewrites);
29518
29763
  for (const [file, content] of updatedContents) {
29519
29764
  fs36.writeFileSync(file, content, "utf8");
29520
- console.log(chalk203.cyan(` Updated imports in ${path56.relative(cwd, file)}`));
29765
+ console.log(chalk205.cyan(` Updated imports in ${path56.relative(cwd, file)}`));
29521
29766
  }
29522
29767
  const destDir = path56.dirname(destPath);
29523
29768
  if (!fs36.existsSync(destDir)) fs36.mkdirSync(destDir, { recursive: true });
29524
29769
  fs36.renameSync(sourcePath, destPath);
29525
29770
  console.log(
29526
- chalk203.white(
29771
+ chalk205.white(
29527
29772
  ` Moved ${path56.relative(cwd, sourcePath)} \u2192 ${path56.relative(cwd, destPath)}`
29528
29773
  )
29529
29774
  );
@@ -29610,16 +29855,16 @@ function computeRenameRewrites(sourcePath, destPath) {
29610
29855
 
29611
29856
  // src/commands/refactor/rename/printRenamePreview.ts
29612
29857
  import path58 from "path";
29613
- import chalk204 from "chalk";
29858
+ import chalk206 from "chalk";
29614
29859
  function printRenamePreview(rewrites, cwd) {
29615
29860
  for (const rewrite of rewrites) {
29616
29861
  console.log(
29617
- chalk204.dim(
29862
+ chalk206.dim(
29618
29863
  ` ${path58.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
29619
29864
  )
29620
29865
  );
29621
29866
  }
29622
- console.log(chalk204.dim("Dry run. Use --apply to execute."));
29867
+ console.log(chalk206.dim("Dry run. Use --apply to execute."));
29623
29868
  }
29624
29869
 
29625
29870
  // src/commands/refactor/rename/index.ts
@@ -29630,20 +29875,20 @@ async function rename(source, destination, options2 = {}) {
29630
29875
  const relSource = path59.relative(cwd, sourcePath);
29631
29876
  const relDest = path59.relative(cwd, destPath);
29632
29877
  if (!fs37.existsSync(sourcePath)) {
29633
- console.log(chalk205.red(`File not found: ${source}`));
29878
+ console.log(chalk207.red(`File not found: ${source}`));
29634
29879
  process.exit(1);
29635
29880
  }
29636
29881
  if (destPath !== sourcePath && fs37.existsSync(destPath)) {
29637
- console.log(chalk205.red(`Destination already exists: ${destination}`));
29882
+ console.log(chalk207.red(`Destination already exists: ${destination}`));
29638
29883
  process.exit(1);
29639
29884
  }
29640
- console.log(chalk205.bold(`Rename: ${relSource} \u2192 ${relDest}`));
29641
- console.log(chalk205.dim("Loading project..."));
29642
- console.log(chalk205.dim("Scanning imports across the project..."));
29885
+ console.log(chalk207.bold(`Rename: ${relSource} \u2192 ${relDest}`));
29886
+ console.log(chalk207.dim("Loading project..."));
29887
+ console.log(chalk207.dim("Scanning imports across the project..."));
29643
29888
  const rewrites = computeRenameRewrites(sourcePath, destPath);
29644
29889
  const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
29645
29890
  console.log(
29646
- chalk205.dim(
29891
+ chalk207.dim(
29647
29892
  `${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
29648
29893
  )
29649
29894
  );
@@ -29652,11 +29897,11 @@ async function rename(source, destination, options2 = {}) {
29652
29897
  return;
29653
29898
  }
29654
29899
  applyRename(rewrites, sourcePath, destPath, cwd);
29655
- console.log(chalk205.green("Done"));
29900
+ console.log(chalk207.green("Done"));
29656
29901
  }
29657
29902
 
29658
29903
  // src/commands/refactor/renameSymbol/index.ts
29659
- import chalk206 from "chalk";
29904
+ import chalk208 from "chalk";
29660
29905
 
29661
29906
  // src/commands/refactor/renameSymbol/findSymbol.ts
29662
29907
  import { SyntaxKind as SyntaxKind15 } from "ts-morph";
@@ -29702,33 +29947,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
29702
29947
  const { project, sourceFile } = loadProjectFile(file);
29703
29948
  const symbol = findSymbol(sourceFile, oldName);
29704
29949
  if (!symbol) {
29705
- console.log(chalk206.red(`Symbol "${oldName}" not found in ${file}`));
29950
+ console.log(chalk208.red(`Symbol "${oldName}" not found in ${file}`));
29706
29951
  process.exit(1);
29707
29952
  }
29708
29953
  const grouped = groupReferences(symbol, cwd);
29709
29954
  const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
29710
29955
  console.log(
29711
- chalk206.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
29956
+ chalk208.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
29712
29957
  `)
29713
29958
  );
29714
29959
  for (const [refFile, lines2] of grouped) {
29715
29960
  console.log(
29716
- ` ${chalk206.dim(refFile)}: lines ${chalk206.cyan(lines2.join(", "))}`
29961
+ ` ${chalk208.dim(refFile)}: lines ${chalk208.cyan(lines2.join(", "))}`
29717
29962
  );
29718
29963
  }
29719
29964
  if (options2.apply) {
29720
29965
  symbol.rename(newName);
29721
29966
  await project.save();
29722
- console.log(chalk206.green(`
29967
+ console.log(chalk208.green(`
29723
29968
  Renamed ${oldName} \u2192 ${newName}`));
29724
29969
  } else {
29725
- console.log(chalk206.dim("\nDry run. Use --apply to execute."));
29970
+ console.log(chalk208.dim("\nDry run. Use --apply to execute."));
29726
29971
  }
29727
29972
  }
29728
29973
 
29729
29974
  // src/commands/refactor/restructure/index.ts
29730
29975
  import path67 from "path";
29731
- import chalk209 from "chalk";
29976
+ import chalk211 from "chalk";
29732
29977
 
29733
29978
  // src/commands/refactor/restructure/clusterDirectories.ts
29734
29979
  import path61 from "path";
@@ -29807,50 +30052,50 @@ function clusterFiles(graph) {
29807
30052
 
29808
30053
  // src/commands/refactor/restructure/displayPlan.ts
29809
30054
  import path63 from "path";
29810
- import chalk207 from "chalk";
30055
+ import chalk209 from "chalk";
29811
30056
  function relPath(filePath) {
29812
30057
  return path63.relative(process.cwd(), filePath);
29813
30058
  }
29814
30059
  function displayMoves(plan2) {
29815
30060
  if (plan2.moves.length === 0) return;
29816
- console.log(chalk207.bold("\nFile moves:"));
30061
+ console.log(chalk209.bold("\nFile moves:"));
29817
30062
  for (const move2 of plan2.moves) {
29818
30063
  console.log(
29819
- ` ${chalk207.red(relPath(move2.from))} \u2192 ${chalk207.green(relPath(move2.to))}`
30064
+ ` ${chalk209.red(relPath(move2.from))} \u2192 ${chalk209.green(relPath(move2.to))}`
29820
30065
  );
29821
- console.log(chalk207.dim(` ${move2.reason}`));
30066
+ console.log(chalk209.dim(` ${move2.reason}`));
29822
30067
  }
29823
30068
  }
29824
30069
  function displayRewrites(rewrites) {
29825
30070
  if (rewrites.length === 0) return;
29826
30071
  const affectedFiles = new Set(rewrites.map((r) => r.file));
29827
- console.log(chalk207.bold(`
30072
+ console.log(chalk209.bold(`
29828
30073
  Import rewrites (${affectedFiles.size} files):`));
29829
30074
  for (const file of affectedFiles) {
29830
- console.log(` ${chalk207.cyan(relPath(file))}:`);
30075
+ console.log(` ${chalk209.cyan(relPath(file))}:`);
29831
30076
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
29832
30077
  (r) => r.file === file
29833
30078
  )) {
29834
30079
  console.log(
29835
- ` ${chalk207.red(`"${oldSpecifier}"`)} \u2192 ${chalk207.green(`"${newSpecifier}"`)}`
30080
+ ` ${chalk209.red(`"${oldSpecifier}"`)} \u2192 ${chalk209.green(`"${newSpecifier}"`)}`
29836
30081
  );
29837
30082
  }
29838
30083
  }
29839
30084
  }
29840
30085
  function displayPlan2(plan2) {
29841
30086
  if (plan2.warnings.length > 0) {
29842
- console.log(chalk207.yellow("\nWarnings:"));
29843
- for (const w of plan2.warnings) console.log(chalk207.yellow(` ${w}`));
30087
+ console.log(chalk209.yellow("\nWarnings:"));
30088
+ for (const w of plan2.warnings) console.log(chalk209.yellow(` ${w}`));
29844
30089
  }
29845
30090
  if (plan2.newDirectories.length > 0) {
29846
- console.log(chalk207.bold("\nNew directories:"));
30091
+ console.log(chalk209.bold("\nNew directories:"));
29847
30092
  for (const dir of plan2.newDirectories)
29848
- console.log(chalk207.green(` ${dir}/`));
30093
+ console.log(chalk209.green(` ${dir}/`));
29849
30094
  }
29850
30095
  displayMoves(plan2);
29851
30096
  displayRewrites(plan2.rewrites);
29852
30097
  console.log(
29853
- chalk207.dim(
30098
+ chalk209.dim(
29854
30099
  `
29855
30100
  Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
29856
30101
  )
@@ -29860,18 +30105,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
29860
30105
  // src/commands/refactor/restructure/executePlan.ts
29861
30106
  import fs38 from "fs";
29862
30107
  import path64 from "path";
29863
- import chalk208 from "chalk";
30108
+ import chalk210 from "chalk";
29864
30109
  function executePlan(plan2) {
29865
30110
  const updatedContents = applyRewrites(plan2.rewrites);
29866
30111
  for (const [file, content] of updatedContents) {
29867
30112
  fs38.writeFileSync(file, content, "utf8");
29868
30113
  console.log(
29869
- chalk208.cyan(` Rewrote imports in ${path64.relative(process.cwd(), file)}`)
30114
+ chalk210.cyan(` Rewrote imports in ${path64.relative(process.cwd(), file)}`)
29870
30115
  );
29871
30116
  }
29872
30117
  for (const dir of plan2.newDirectories) {
29873
30118
  fs38.mkdirSync(dir, { recursive: true });
29874
- console.log(chalk208.green(` Created ${path64.relative(process.cwd(), dir)}/`));
30119
+ console.log(chalk210.green(` Created ${path64.relative(process.cwd(), dir)}/`));
29875
30120
  }
29876
30121
  for (const move2 of plan2.moves) {
29877
30122
  const targetDir = path64.dirname(move2.to);
@@ -29880,7 +30125,7 @@ function executePlan(plan2) {
29880
30125
  }
29881
30126
  fs38.renameSync(move2.from, move2.to);
29882
30127
  console.log(
29883
- chalk208.white(
30128
+ chalk210.white(
29884
30129
  ` Moved ${path64.relative(process.cwd(), move2.from)} \u2192 ${path64.relative(process.cwd(), move2.to)}`
29885
30130
  )
29886
30131
  );
@@ -29895,7 +30140,7 @@ function removeEmptyDirectories(dirs) {
29895
30140
  if (entries.length === 0) {
29896
30141
  fs38.rmdirSync(dir);
29897
30142
  console.log(
29898
- chalk208.dim(
30143
+ chalk210.dim(
29899
30144
  ` Removed empty directory ${path64.relative(process.cwd(), dir)}`
29900
30145
  )
29901
30146
  );
@@ -30028,22 +30273,22 @@ async function restructure(pattern2, options2 = {}) {
30028
30273
  const targetPattern = pattern2 ?? "src";
30029
30274
  const files = findSourceFiles2(targetPattern);
30030
30275
  if (files.length === 0) {
30031
- console.log(chalk209.yellow("No files found matching pattern"));
30276
+ console.log(chalk211.yellow("No files found matching pattern"));
30032
30277
  return;
30033
30278
  }
30034
30279
  const tsConfigPath = findTsConfig(path67.resolve(files[0]));
30035
30280
  const plan2 = buildPlan3(files, tsConfigPath);
30036
30281
  if (plan2.moves.length === 0) {
30037
- console.log(chalk209.green("No restructuring needed"));
30282
+ console.log(chalk211.green("No restructuring needed"));
30038
30283
  return;
30039
30284
  }
30040
30285
  displayPlan2(plan2);
30041
30286
  if (options2.apply) {
30042
- console.log(chalk209.bold("\nApplying changes..."));
30287
+ console.log(chalk211.bold("\nApplying changes..."));
30043
30288
  executePlan(plan2);
30044
- console.log(chalk209.green("\nRestructuring complete"));
30289
+ console.log(chalk211.green("\nRestructuring complete"));
30045
30290
  } else {
30046
- console.log(chalk209.dim("\nDry run. Use --apply to execute."));
30291
+ console.log(chalk211.dim("\nDry run. Use --apply to execute."));
30047
30292
  }
30048
30293
  }
30049
30294
 
@@ -30096,6 +30341,293 @@ async function checkoutOnlySession(number) {
30096
30341
  await done2;
30097
30342
  }
30098
30343
 
30344
+ // src/commands/review/highLevel/runHighLevelReview.ts
30345
+ import chalk213 from "chalk";
30346
+
30347
+ // src/commands/review/fetchPrDiffInfo.ts
30348
+ import { execSync as execSync57 } from "child_process";
30349
+ function getCurrentBranch3() {
30350
+ return execSync57("git rev-parse --abbrev-ref HEAD", {
30351
+ encoding: "utf8"
30352
+ }).trim();
30353
+ }
30354
+ function fetchPrDiffInfo() {
30355
+ const { org, repo } = getRepoInfo();
30356
+ const branch2 = getCurrentBranch3();
30357
+ const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
30358
+ const raw = execSync57(
30359
+ `gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
30360
+ {
30361
+ encoding: "utf8",
30362
+ stdio: ["ignore", "pipe", "pipe"]
30363
+ }
30364
+ );
30365
+ const parsed = JSON.parse(raw);
30366
+ const pr = parsed[0];
30367
+ if (!pr) {
30368
+ console.error(
30369
+ `Error: No open pull request found for branch \`${branch2}\`. Open a PR for this branch before running \`assist review\`.`
30370
+ );
30371
+ process.exit(1);
30372
+ }
30373
+ return {
30374
+ prNumber: pr.number,
30375
+ baseRef: pr.baseRefName,
30376
+ baseSha: pr.baseRefOid,
30377
+ headRef: pr.headRefName,
30378
+ headSha: pr.headRefOid
30379
+ };
30380
+ }
30381
+ function fetchPrChangedFiles(prNumber) {
30382
+ const { org, repo } = getRepoInfo();
30383
+ const out = execSync57(
30384
+ `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
30385
+ {
30386
+ encoding: "utf8",
30387
+ maxBuffer: 64 * 1024 * 1024
30388
+ }
30389
+ );
30390
+ return out.trim().split("\n").filter(Boolean);
30391
+ }
30392
+
30393
+ // src/commands/review/highLevel/checkDescriptionLinksIssue.ts
30394
+ var ISSUE_URL_PATTERN = /https?:\/\/github\.com\/[\w.-]+\/[\w.-]+\/issues\/\d+/g;
30395
+ var CROSS_REPO_PATTERN = /\b[\w.-]+\/[\w.-]+#\d+/g;
30396
+ var SAME_REPO_PATTERN2 = /(?<![\w/#-])#\d+\b/g;
30397
+ function firstMatch(body, pattern2) {
30398
+ return body.match(pattern2)?.[0] ?? null;
30399
+ }
30400
+ function checkDescriptionLinksIssue(body) {
30401
+ const reference = firstMatch(body, ISSUE_URL_PATTERN) ?? firstMatch(body, CROSS_REPO_PATTERN) ?? firstMatch(body, SAME_REPO_PATTERN2);
30402
+ if (!reference)
30403
+ return {
30404
+ status: "fail",
30405
+ reason: "no GitHub issue reference (`#123`, `owner/repo#123`, or an issue URL) in the description"
30406
+ };
30407
+ return { status: "pass", reason: `links ${reference}` };
30408
+ }
30409
+
30410
+ // src/commands/review/highLevel/checkDescriptionSections.ts
30411
+ function sectionContent(body, heading2) {
30412
+ const section2 = parsePrBody(body).find(
30413
+ (candidate) => candidate.heading.trim().toLowerCase() === heading2
30414
+ );
30415
+ return section2 ? section2.content.trim() : null;
30416
+ }
30417
+ function describe5(heading2, content) {
30418
+ if (content === null) return `no \`## ${heading2}\` section`;
30419
+ if (content === "") return `\`## ${heading2}\` is empty`;
30420
+ return null;
30421
+ }
30422
+ function checkDescriptionSections(body) {
30423
+ const problems = [
30424
+ describe5("What", sectionContent(body, "what")),
30425
+ describe5("Why", sectionContent(body, "why"))
30426
+ ].filter((problem) => problem !== null);
30427
+ if (problems.length > 0)
30428
+ return { status: "fail", reason: problems.join("; ") };
30429
+ const how = sectionContent(body, "how");
30430
+ const optional = how ? ", plus an optional `## How`" : "";
30431
+ return {
30432
+ status: "pass",
30433
+ reason: `\`## What\` and \`## Why\` are both present${optional}`
30434
+ };
30435
+ }
30436
+
30437
+ // src/commands/review/highLevel/checkDescriptionWordCap.ts
30438
+ function checkDescriptionWordCap(body, cap2) {
30439
+ const { prose, code } = countReadingWords(body);
30440
+ const words = prose + code;
30441
+ if (words > cap2)
30442
+ return {
30443
+ status: "fail",
30444
+ reason: `${words} words, ${words - cap2} over the ${cap2}-word cap`
30445
+ };
30446
+ return { status: "pass", reason: `${words} of ${cap2} words` };
30447
+ }
30448
+
30449
+ // src/commands/review/highLevel/checkUiEvidence.ts
30450
+ import { minimatch as minimatch7 } from "minimatch";
30451
+ var EVIDENCE_PATTERNS = [
30452
+ /!\[[^\]]*\]\([^)]+\)/g,
30453
+ /<(?:img|video)\b[^>]*>/gi,
30454
+ /https?:\/\/github\.com\/user-attachments\/assets\/\S+/g,
30455
+ /https?:\/\/\S+\.(?:png|jpe?g|gif|webp|avif|svg|mp4|mov|webm)\b/gi
30456
+ ];
30457
+ function countEvidence(body) {
30458
+ return EVIDENCE_PATTERNS.reduce(
30459
+ (total, pattern2) => total + (body.match(pattern2)?.length ?? 0),
30460
+ 0
30461
+ );
30462
+ }
30463
+ function plural(count8, noun) {
30464
+ return `${count8} ${noun}${count8 === 1 ? "" : "s"}`;
30465
+ }
30466
+ function checkUiEvidence(body, changedFiles2, uiPaths) {
30467
+ if (uiPaths.length === 0)
30468
+ return {
30469
+ status: "pass",
30470
+ reason: "review.highLevel.uiPaths is unset, so no UI evidence is required"
30471
+ };
30472
+ const touched = changedFiles2.filter(
30473
+ (file) => uiPaths.some((glob) => minimatch7(file, glob))
30474
+ );
30475
+ if (touched.length === 0)
30476
+ return {
30477
+ status: "pass",
30478
+ reason: "no changed file matches review.highLevel.uiPaths"
30479
+ };
30480
+ const evidence = countEvidence(body);
30481
+ if (evidence === 0)
30482
+ return {
30483
+ status: "fail",
30484
+ reason: `${plural(touched.length, "UI file")} changed (${touched[0]}) but no screenshot or video in the description`
30485
+ };
30486
+ const shown = evidence === 1 ? "1 screenshot or video" : `${evidence} screenshots or videos`;
30487
+ return {
30488
+ status: "pass",
30489
+ reason: `${shown} for ${plural(touched.length, "changed UI file")}`
30490
+ };
30491
+ }
30492
+
30493
+ // src/commands/review/highLevel/highLevelChecklist.ts
30494
+ var highLevelChecklist = [
30495
+ {
30496
+ id: "description-what-why",
30497
+ kind: "deterministic",
30498
+ title: "Description has a What and a Why",
30499
+ backing: "The PR body's `## What` and `## Why` sections"
30500
+ },
30501
+ {
30502
+ id: "description-word-cap",
30503
+ kind: "deterministic",
30504
+ title: "Description is under the word cap",
30505
+ backing: "The PR body's word count against review.highLevel.descriptionWordCap"
30506
+ },
30507
+ {
30508
+ id: "description-links-issue",
30509
+ kind: "deterministic",
30510
+ title: "Description links the GitHub issue the PR resolves",
30511
+ backing: "GitHub issue references in the PR body"
30512
+ },
30513
+ {
30514
+ id: "ui-evidence",
30515
+ kind: "deterministic",
30516
+ title: "UI changes are evidenced by a screenshot or video",
30517
+ backing: "Images and videos in the PR body, when a changed file matches review.highLevel.uiPaths"
30518
+ },
30519
+ {
30520
+ id: "structure-sensible",
30521
+ kind: "manual",
30522
+ title: "The structure of the change is sensible",
30523
+ backing: "The changed-file tree with add/delete/modify counts and per-file GitHub diff links"
30524
+ },
30525
+ {
30526
+ id: "critical-diffs-correct",
30527
+ kind: "manual",
30528
+ title: "The critical-file diffs are correct",
30529
+ backing: "Full diffs of files matching review.highLevel.criticalPaths"
30530
+ },
30531
+ {
30532
+ id: "backend-pr-linked",
30533
+ kind: "manual",
30534
+ title: "The backend PR is linked, if the change needs backend work",
30535
+ backing: "The PR body"
30536
+ }
30537
+ ];
30538
+
30539
+ // src/commands/review/highLevel/evaluateHighLevelChecks.ts
30540
+ var evaluators = {
30541
+ "description-what-why": (subject) => checkDescriptionSections(subject.body),
30542
+ "description-word-cap": (subject) => checkDescriptionWordCap(subject.body, subject.config.descriptionWordCap),
30543
+ "description-links-issue": (subject) => checkDescriptionLinksIssue(subject.body),
30544
+ "ui-evidence": (subject) => checkUiEvidence(subject.body, subject.changedFiles, subject.config.uiPaths)
30545
+ };
30546
+ function evaluateHighLevelChecks(subject) {
30547
+ return highLevelChecklist.map((check2) => {
30548
+ if (check2.kind === "manual")
30549
+ return { ...check2, status: "manual", reason: check2.backing };
30550
+ return { ...check2, ...evaluators[check2.id](subject) };
30551
+ });
30552
+ }
30553
+
30554
+ // src/commands/review/highLevel/formatHighLevelChecklist.ts
30555
+ import chalk212 from "chalk";
30556
+ var MARKERS = {
30557
+ pass: () => chalk212.green("\u2714"),
30558
+ fail: () => chalk212.red("\u2718"),
30559
+ manual: () => chalk212.yellow("\u25A1")
30560
+ };
30561
+ function formatCheck(check2) {
30562
+ const title = check2.status === "fail" ? chalk212.red(check2.title) : chalk212.bold(check2.title);
30563
+ return ` ${MARKERS[check2.status]()} ${title}
30564
+ ${chalk212.dim(check2.reason)}`;
30565
+ }
30566
+ function formatGroup(heading2, checks2) {
30567
+ if (checks2.length === 0) return [];
30568
+ return ["", chalk212.bold.underline(heading2), ...checks2.map(formatCheck)];
30569
+ }
30570
+ function formatHighLevelChecklist(checks2) {
30571
+ const deterministic = checks2.filter(
30572
+ (check2) => check2.kind === "deterministic"
30573
+ );
30574
+ const failed2 = deterministic.filter(
30575
+ (check2) => check2.status === "fail"
30576
+ ).length;
30577
+ const summary = failed2 === 0 ? chalk212.green(`All ${deterministic.length} deterministic checks pass`) : chalk212.red(
30578
+ `${failed2} of ${deterministic.length} deterministic checks fail`
30579
+ );
30580
+ return [
30581
+ ...formatGroup("Deterministic", deterministic),
30582
+ ...formatGroup(
30583
+ "Manual",
30584
+ checks2.filter((check2) => check2.kind === "manual")
30585
+ ),
30586
+ "",
30587
+ summary
30588
+ ].join("\n");
30589
+ }
30590
+
30591
+ // src/commands/review/highLevel/resolveHighLevelConfig.ts
30592
+ var DEFAULT_DESCRIPTION_WORD_CAP = 300;
30593
+ function resolveHighLevelConfig(config) {
30594
+ const highLevel = config.review?.highLevel;
30595
+ return {
30596
+ criticalPaths: highLevel?.criticalPaths ?? [],
30597
+ uiPaths: highLevel?.uiPaths ?? [],
30598
+ descriptionWordCap: highLevel?.descriptionWordCap ?? DEFAULT_DESCRIPTION_WORD_CAP
30599
+ };
30600
+ }
30601
+
30602
+ // src/commands/review/highLevel/runHighLevelReview.ts
30603
+ function resolvePrNumber2(number) {
30604
+ if (number === void 0) return getCurrentPrNumber();
30605
+ const parsed = Number(number);
30606
+ if (!Number.isInteger(parsed) || parsed <= 0) {
30607
+ console.error(`Error: \`${number}\` is not a pull request number.`);
30608
+ process.exit(1);
30609
+ }
30610
+ return parsed;
30611
+ }
30612
+ function runHighLevelReview(number) {
30613
+ const prNumber = resolvePrNumber2(number);
30614
+ const { org, repo } = getRepoInfo();
30615
+ const config = resolveHighLevelConfig(loadConfig());
30616
+ const body = fetchPrBody(prNumber, { org, repo });
30617
+ const changedFiles2 = fetchPrChangedFiles(prNumber);
30618
+ const checks2 = evaluateHighLevelChecks({ body, changedFiles: changedFiles2, config });
30619
+ console.log(
30620
+ chalk213.bold(`High-level review of ${org}/${repo}#${prNumber}`),
30621
+ chalk213.dim(`\xB7 ${changedFiles2.length} changed files`)
30622
+ );
30623
+ console.log(formatHighLevelChecklist(checks2));
30624
+ console.log(
30625
+ chalk213.dim(
30626
+ "\nManual items are for the reviewer to judge; see docs/high-level-review.md."
30627
+ )
30628
+ );
30629
+ }
30630
+
30099
30631
  // src/commands/review/annotateDiffWithLineNumbers.ts
30100
30632
  var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
30101
30633
  var HUNK_HEADER2 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
@@ -30229,9 +30761,9 @@ function buildReviewPaths(repoRoot2, key) {
30229
30761
  }
30230
30762
 
30231
30763
  // src/commands/review/fetchExistingComments.ts
30232
- import { execSync as execSync56 } from "child_process";
30764
+ import { execSync as execSync58 } from "child_process";
30233
30765
  function fetchRawComments(org, repo, prNumber) {
30234
- const out = execSync56(
30766
+ const out = execSync58(
30235
30767
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
30236
30768
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
30237
30769
  );
@@ -30262,14 +30794,14 @@ function fetchExistingComments() {
30262
30794
  }
30263
30795
 
30264
30796
  // src/commands/review/gatherContext.ts
30265
- import { execSync as execSync59 } from "child_process";
30797
+ import { execSync as execSync60 } from "child_process";
30266
30798
 
30267
30799
  // src/commands/review/fetchPrDiff.ts
30268
- import { execSync as execSync57 } from "child_process";
30800
+ import { execSync as execSync59 } from "child_process";
30269
30801
  function fetchPrDiff(prNumber, baseSha, headSha) {
30270
30802
  const { org, repo } = getRepoInfo();
30271
30803
  try {
30272
- return execSync57(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
30804
+ return execSync59(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
30273
30805
  encoding: "utf8",
30274
30806
  maxBuffer: 256 * 1024 * 1024,
30275
30807
  stdio: ["ignore", "pipe", "pipe"]
@@ -30284,68 +30816,22 @@ function isDiffTooLarge(error) {
30284
30816
  }
30285
30817
  function fetchDiffViaGit(baseSha, headSha) {
30286
30818
  try {
30287
- execSync57(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
30819
+ execSync59(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
30288
30820
  } catch {
30289
30821
  }
30290
- return execSync57(`git diff ${baseSha}...${headSha}`, {
30822
+ return execSync59(`git diff ${baseSha}...${headSha}`, {
30291
30823
  encoding: "utf8",
30292
30824
  maxBuffer: 256 * 1024 * 1024
30293
30825
  });
30294
30826
  }
30295
30827
 
30296
- // src/commands/review/fetchPrDiffInfo.ts
30297
- import { execSync as execSync58 } from "child_process";
30298
- function getCurrentBranch3() {
30299
- return execSync58("git rev-parse --abbrev-ref HEAD", {
30300
- encoding: "utf8"
30301
- }).trim();
30302
- }
30303
- function fetchPrDiffInfo() {
30304
- const { org, repo } = getRepoInfo();
30305
- const branch2 = getCurrentBranch3();
30306
- const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
30307
- const raw = execSync58(
30308
- `gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
30309
- {
30310
- encoding: "utf8",
30311
- stdio: ["ignore", "pipe", "pipe"]
30312
- }
30313
- );
30314
- const parsed = JSON.parse(raw);
30315
- const pr = parsed[0];
30316
- if (!pr) {
30317
- console.error(
30318
- `Error: No open pull request found for branch \`${branch2}\`. Open a PR for this branch before running \`assist review\`.`
30319
- );
30320
- process.exit(1);
30321
- }
30322
- return {
30323
- prNumber: pr.number,
30324
- baseRef: pr.baseRefName,
30325
- baseSha: pr.baseRefOid,
30326
- headRef: pr.headRefName,
30327
- headSha: pr.headRefOid
30328
- };
30329
- }
30330
- function fetchPrChangedFiles(prNumber) {
30331
- const { org, repo } = getRepoInfo();
30332
- const out = execSync58(
30333
- `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
30334
- {
30335
- encoding: "utf8",
30336
- maxBuffer: 64 * 1024 * 1024
30337
- }
30338
- );
30339
- return out.trim().split("\n").filter(Boolean);
30340
- }
30341
-
30342
30828
  // src/commands/review/gatherContext.ts
30343
30829
  function gatherContext() {
30344
- const branch2 = execSync59("git rev-parse --abbrev-ref HEAD", {
30830
+ const branch2 = execSync60("git rev-parse --abbrev-ref HEAD", {
30345
30831
  encoding: "utf8"
30346
30832
  }).trim();
30347
- const sha = execSync59("git rev-parse HEAD", { encoding: "utf8" }).trim();
30348
- const shortSha = execSync59("git rev-parse --short=7 HEAD", {
30833
+ const sha = execSync60("git rev-parse HEAD", { encoding: "utf8" }).trim();
30834
+ const shortSha = execSync60("git rev-parse --short=7 HEAD", {
30349
30835
  encoding: "utf8"
30350
30836
  }).trim();
30351
30837
  const prInfo = fetchPrDiffInfo();
@@ -30704,18 +31190,18 @@ function partitionFindingsByDiff(findings, index3) {
30704
31190
  }
30705
31191
 
30706
31192
  // src/commands/review/warnOutOfDiff.ts
30707
- import chalk210 from "chalk";
31193
+ import chalk214 from "chalk";
30708
31194
  function warnOutOfDiff(outOfDiff) {
30709
31195
  if (outOfDiff.length === 0) return;
30710
31196
  console.warn(
30711
- chalk210.yellow(
31197
+ chalk214.yellow(
30712
31198
  `Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
30713
31199
  )
30714
31200
  );
30715
31201
  for (const finding of outOfDiff) {
30716
31202
  const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
30717
31203
  console.warn(
30718
- ` ${chalk210.yellow("\xB7")} ${finding.title} ${chalk210.dim(
31204
+ ` ${chalk214.yellow("\xB7")} ${finding.title} ${chalk214.dim(
30719
31205
  `(${finding.file}:${range})`
30720
31206
  )}`
30721
31207
  );
@@ -30739,18 +31225,18 @@ function selectInDiffFindings(lineBound, prDiff) {
30739
31225
  }
30740
31226
 
30741
31227
  // src/commands/review/warnUnlocated.ts
30742
- import chalk211 from "chalk";
31228
+ import chalk215 from "chalk";
30743
31229
  function warnUnlocated(unlocated) {
30744
31230
  if (unlocated.length === 0) return;
30745
31231
  console.warn(
30746
- chalk211.yellow(
31232
+ chalk215.yellow(
30747
31233
  `Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
30748
31234
  )
30749
31235
  );
30750
31236
  for (const finding of unlocated) {
30751
- const where = finding.location || chalk211.dim("missing");
31237
+ const where = finding.location || chalk215.dim("missing");
30752
31238
  console.warn(
30753
- ` ${chalk211.yellow("\xB7")} ${finding.title} ${chalk211.dim(`(${where})`)}`
31239
+ ` ${chalk215.yellow("\xB7")} ${finding.title} ${chalk215.dim(`(${where})`)}`
30754
31240
  );
30755
31241
  }
30756
31242
  }
@@ -31340,9 +31826,9 @@ import { writeFileSync as writeFileSync39 } from "fs";
31340
31826
  // src/commands/review/finaliseReviewerSpinner.ts
31341
31827
  var SUMMARY_MAX_LEN = 80;
31342
31828
  function summariseStderr(stderr) {
31343
- const firstLine2 = stderr.split(/\r?\n/).find((l) => l.trim().length > 0);
31344
- if (!firstLine2) return "";
31345
- const trimmed = firstLine2.trim();
31829
+ const firstLine3 = stderr.split(/\r?\n/).find((l) => l.trim().length > 0);
31830
+ if (!firstLine3) return "";
31831
+ const trimmed = firstLine3.trim();
31346
31832
  return trimmed.length > SUMMARY_MAX_LEN ? `${trimmed.slice(0, SUMMARY_MAX_LEN - 1)}\u2026` : trimmed;
31347
31833
  }
31348
31834
  function finaliseReviewerSpinner(spinner, outcome) {
@@ -32050,14 +32536,8 @@ async function reviewPr(repoRoot2, options2) {
32050
32536
  console.log(`Done. Review folder: ${paths.reviewDir}`);
32051
32537
  }
32052
32538
 
32053
- // src/commands/review/review.ts
32054
- function resolveRepoRoot() {
32055
- const repoRoot2 = findRepoRoot(process.cwd());
32056
- if (repoRoot2) return repoRoot2;
32057
- console.error("Error: not inside a git repository.");
32058
- process.exit(1);
32059
- }
32060
- function validateOptions(options2) {
32539
+ // src/commands/review/validateReviewOptions.ts
32540
+ function validateReviewOptions(options2) {
32061
32541
  if (options2.apply && options2.refine) {
32062
32542
  console.error("Error: --apply cannot be combined with --refine.");
32063
32543
  process.exit(1);
@@ -32069,6 +32549,7 @@ function validateOptions(options2) {
32069
32549
  process.exit(1);
32070
32550
  }
32071
32551
  validateCheckoutOnly(options2);
32552
+ validateHighLevel(options2);
32072
32553
  }
32073
32554
  function validateCheckoutOnly(options2) {
32074
32555
  if (!options2.checkoutOnly) return;
@@ -32083,13 +32564,31 @@ function validateCheckoutOnly(options2) {
32083
32564
  process.exit(1);
32084
32565
  }
32085
32566
  }
32567
+ function validateHighLevel(options2) {
32568
+ if (!options2.highLevel) return;
32569
+ if (options2.refine || options2.apply || options2.backlog || options2.submit || options2.checkoutOnly) {
32570
+ console.error(
32571
+ "Error: --high-level cannot be combined with --refine, --apply, --backlog, --submit or --checkout-only."
32572
+ );
32573
+ process.exit(1);
32574
+ }
32575
+ }
32576
+
32577
+ // src/commands/review/review.ts
32578
+ function resolveRepoRoot() {
32579
+ const repoRoot2 = findRepoRoot(process.cwd());
32580
+ if (repoRoot2) return repoRoot2;
32581
+ console.error("Error: not inside a git repository.");
32582
+ process.exit(1);
32583
+ }
32086
32584
  async function review(options2 = {}) {
32087
- validateOptions(options2);
32585
+ validateReviewOptions(options2);
32088
32586
  startReviewLog();
32089
32587
  const invokedIn = resolveRepoRoot();
32090
32588
  if (options2.checkoutOnly && options2.number)
32091
32589
  return checkoutOnlySession(options2.number);
32092
32590
  emitActivity({ kind: "command", name: "review" });
32591
+ if (options2.highLevel) return runHighLevelReview(options2.number);
32093
32592
  if (!options2.number) return reviewPr(invokedIn, options2);
32094
32593
  await checkoutPr(options2.number);
32095
32594
  return reviewPr(resolveRepoRoot(), options2);
@@ -32123,6 +32622,9 @@ function registerReview(program2) {
32123
32622
  ).option(
32124
32623
  "--checkout-only",
32125
32624
  "Check the PR out and start an idle interactive Claude session in the checkout tree instead of reviewing; requires a PR number and cannot be combined with --refine, --apply, --backlog or --submit"
32625
+ ).option(
32626
+ "--high-level",
32627
+ "Skip the LLM review; evaluate the high-level review checklist against the PR description and changed files and print each item as pass, fail or manual. Nothing is posted to GitHub; cannot be combined with --refine, --apply, --backlog, --submit or --checkout-only"
32126
32628
  ).option(
32127
32629
  "--address-comments",
32128
32630
  "After posting and submitting the review, start an Address Comments session (assist review-pr-comments <n>) for the PR; no-op when nothing was posted or the review was not submitted, and only inside an assist session"
@@ -32145,7 +32647,7 @@ function registerReview(program2) {
32145
32647
  // src/commands/rules/addRule.ts
32146
32648
  import { existsSync as existsSync68, readFileSync as readFileSync52, writeFileSync as writeFileSync41 } from "fs";
32147
32649
  import path72 from "path";
32148
- import chalk212 from "chalk";
32650
+ import chalk216 from "chalk";
32149
32651
 
32150
32652
  // src/commands/rules/insertRuleBullet.ts
32151
32653
  function ruleBullet({ code, title, text: text18 }) {
@@ -32281,7 +32783,7 @@ function read2(file) {
32281
32783
  function addRule(text18, options2) {
32282
32784
  const rule = text18.trim();
32283
32785
  if (rule === "") {
32284
- console.error(chalk212.red("Rule text is required"));
32786
+ console.error(chalk216.red("Rule text is required"));
32285
32787
  process.exitCode = 1;
32286
32788
  return;
32287
32789
  }
@@ -32299,13 +32801,13 @@ function addRule(text18, options2) {
32299
32801
  );
32300
32802
  updateScopedRulesIndex(root);
32301
32803
  console.log(
32302
- `Added ${chalk212.cyan(code)} to ${path72.relative(process.cwd(), target) || target}`
32804
+ `Added ${chalk216.cyan(code)} to ${path72.relative(process.cwd(), target) || target}`
32303
32805
  );
32304
32806
  }
32305
32807
 
32306
32808
  // src/commands/rules/indexRules.ts
32307
32809
  import path73 from "path";
32308
- import chalk213 from "chalk";
32810
+ import chalk217 from "chalk";
32309
32811
  function indexRules() {
32310
32812
  const startDir = scopeDirectory(process.cwd());
32311
32813
  const root = findRepoRoot(startDir) ?? startDir;
@@ -32313,24 +32815,24 @@ function indexRules() {
32313
32815
  const rootFile = path73.relative(process.cwd(), path73.join(root, "CLAUDE.md"));
32314
32816
  if (directories.length === 0) {
32315
32817
  console.log(
32316
- chalk213.gray(`No directories carry their own \`## Rules\` under ${root}`)
32818
+ chalk217.gray(`No directories carry their own \`## Rules\` under ${root}`)
32317
32819
  );
32318
32820
  return;
32319
32821
  }
32320
32822
  console.log(`Recorded in ${rootFile || "CLAUDE.md"}`);
32321
32823
  for (const directory of directories)
32322
- console.log(` ${chalk213.cyan(directory)}`);
32824
+ console.log(` ${chalk217.cyan(directory)}`);
32323
32825
  }
32324
32826
 
32325
32827
  // src/commands/rules/listRules.ts
32326
32828
  import path74 from "path";
32327
- import chalk214 from "chalk";
32829
+ import chalk218 from "chalk";
32328
32830
  function listRules(target, options2 = {}) {
32329
32831
  const resolved = path74.resolve(target ?? process.cwd());
32330
32832
  const rules3 = readScopedRules(resolved);
32331
32833
  if (rules3.length === 0) {
32332
32834
  const label2 = path74.relative(process.cwd(), resolved) || ".";
32333
- console.log(chalk214.gray(`No rules in scope for ${label2}`));
32835
+ console.log(chalk218.gray(`No rules in scope for ${label2}`));
32334
32836
  return;
32335
32837
  }
32336
32838
  const base = findRepoRoot(scopeDirectory(resolved));
@@ -32340,14 +32842,14 @@ function listRules(target, options2 = {}) {
32340
32842
  if (rule.source !== shown) {
32341
32843
  shown = rule.source;
32342
32844
  console.log(
32343
- chalk214.dim(base ? path74.relative(base, rule.source) : rule.source)
32845
+ chalk218.dim(base ? path74.relative(base, rule.source) : rule.source)
32344
32846
  );
32345
32847
  }
32346
32848
  console.log(
32347
- ` ${chalk214.cyan(rule.code.padEnd(width))} ${rule.title ?? rule.text}`
32849
+ ` ${chalk218.cyan(rule.code.padEnd(width))} ${rule.title ?? rule.text}`
32348
32850
  );
32349
32851
  if (options2.full && rule.title)
32350
- console.log(` ${" ".repeat(width)} ${chalk214.dim(rule.text)}`);
32852
+ console.log(` ${" ".repeat(width)} ${chalk218.dim(rule.text)}`);
32351
32853
  }
32352
32854
  }
32353
32855
 
@@ -32376,7 +32878,7 @@ function registerRules(program2) {
32376
32878
  }
32377
32879
 
32378
32880
  // src/commands/seq/seqAuth.ts
32379
- import chalk216 from "chalk";
32881
+ import chalk220 from "chalk";
32380
32882
 
32381
32883
  // src/commands/seq/loadConnections.ts
32382
32884
  function loadConnections2() {
@@ -32405,10 +32907,10 @@ function setDefaultConnection(name) {
32405
32907
  }
32406
32908
 
32407
32909
  // src/shared/assertUniqueName.ts
32408
- import chalk215 from "chalk";
32910
+ import chalk219 from "chalk";
32409
32911
  function assertUniqueName(existingNames, name) {
32410
32912
  if (existingNames.includes(name)) {
32411
- console.error(chalk215.red(`Connection "${name}" already exists.`));
32913
+ console.error(chalk219.red(`Connection "${name}" already exists.`));
32412
32914
  process.exit(1);
32413
32915
  }
32414
32916
  }
@@ -32426,16 +32928,16 @@ async function promptConnection2(existingNames) {
32426
32928
  var seqAuth = createConnectionAuth({
32427
32929
  load: loadConnections2,
32428
32930
  save: saveConnections2,
32429
- format: (c) => `${chalk216.bold(c.name)} ${c.url}`,
32931
+ format: (c) => `${chalk220.bold(c.name)} ${c.url}`,
32430
32932
  promptNew: promptConnection2,
32431
32933
  onFirst: (c) => setDefaultConnection(c.name)
32432
32934
  });
32433
32935
 
32434
32936
  // src/commands/seq/seqQuery.ts
32435
- import chalk220 from "chalk";
32937
+ import chalk224 from "chalk";
32436
32938
 
32437
32939
  // src/commands/seq/fetchSeq.ts
32438
- import chalk217 from "chalk";
32940
+ import chalk221 from "chalk";
32439
32941
  async function fetchSeq(conn, path91, params) {
32440
32942
  const url = `${conn.url}${path91}?${params}`;
32441
32943
  const response = await fetch(url, {
@@ -32446,7 +32948,7 @@ async function fetchSeq(conn, path91, params) {
32446
32948
  });
32447
32949
  if (!response.ok) {
32448
32950
  const body = await response.text();
32449
- console.error(chalk217.red(`Seq returned ${response.status}: ${body}`));
32951
+ console.error(chalk221.red(`Seq returned ${response.status}: ${body}`));
32450
32952
  process.exit(1);
32451
32953
  }
32452
32954
  return response;
@@ -32505,23 +33007,23 @@ async function fetchSeqEvents(conn, params) {
32505
33007
  }
32506
33008
 
32507
33009
  // src/commands/seq/formatEvent.ts
32508
- import chalk218 from "chalk";
33010
+ import chalk222 from "chalk";
32509
33011
  function levelColor(level) {
32510
33012
  switch (level) {
32511
33013
  case "Fatal":
32512
- return chalk218.bgRed.white;
33014
+ return chalk222.bgRed.white;
32513
33015
  case "Error":
32514
- return chalk218.red;
33016
+ return chalk222.red;
32515
33017
  case "Warning":
32516
- return chalk218.yellow;
33018
+ return chalk222.yellow;
32517
33019
  case "Information":
32518
- return chalk218.cyan;
33020
+ return chalk222.cyan;
32519
33021
  case "Debug":
32520
- return chalk218.gray;
33022
+ return chalk222.gray;
32521
33023
  case "Verbose":
32522
- return chalk218.dim;
33024
+ return chalk222.dim;
32523
33025
  default:
32524
- return chalk218.white;
33026
+ return chalk222.white;
32525
33027
  }
32526
33028
  }
32527
33029
  function levelAbbrev(level) {
@@ -32562,12 +33064,12 @@ function formatTimestamp(iso) {
32562
33064
  function formatEvent(event) {
32563
33065
  const color = levelColor(event.Level);
32564
33066
  const abbrev = levelAbbrev(event.Level);
32565
- const ts8 = chalk218.dim(formatTimestamp(event.Timestamp));
33067
+ const ts8 = chalk222.dim(formatTimestamp(event.Timestamp));
32566
33068
  const msg = renderMessage(event);
32567
33069
  const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
32568
33070
  if (event.Exception) {
32569
33071
  for (const line of event.Exception.split("\n")) {
32570
- lines2.push(chalk218.red(` ${line}`));
33072
+ lines2.push(chalk222.red(` ${line}`));
32571
33073
  }
32572
33074
  }
32573
33075
  return lines2.join("\n");
@@ -32600,11 +33102,11 @@ function rejectTimestampFilter(filter) {
32600
33102
  }
32601
33103
 
32602
33104
  // src/shared/resolveNamedConnection.ts
32603
- import chalk219 from "chalk";
33105
+ import chalk223 from "chalk";
32604
33106
  function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
32605
33107
  if (connections.length === 0) {
32606
33108
  console.error(
32607
- chalk219.red(
33109
+ chalk223.red(
32608
33110
  `No ${kind} connections configured. Run '${authCommand}' first.`
32609
33111
  )
32610
33112
  );
@@ -32613,7 +33115,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
32613
33115
  const target = requested ?? defaultName ?? connections[0].name;
32614
33116
  const connection = connections.find((c) => c.name === target);
32615
33117
  if (!connection) {
32616
- console.error(chalk219.red(`${kind} connection "${target}" not found.`));
33118
+ console.error(chalk223.red(`${kind} connection "${target}" not found.`));
32617
33119
  process.exit(1);
32618
33120
  }
32619
33121
  return connection;
@@ -32642,7 +33144,7 @@ async function seqQuery(filter, options2) {
32642
33144
  new URLSearchParams({ filter, count: String(count8) })
32643
33145
  );
32644
33146
  if (events.length === 0) {
32645
- console.log(chalk220.yellow("No events found."));
33147
+ console.log(chalk224.yellow("No events found."));
32646
33148
  return;
32647
33149
  }
32648
33150
  if (options2.json) {
@@ -32653,11 +33155,11 @@ async function seqQuery(filter, options2) {
32653
33155
  for (const event of chronological) {
32654
33156
  console.log(formatEvent(event));
32655
33157
  }
32656
- console.log(chalk220.dim(`
33158
+ console.log(chalk224.dim(`
32657
33159
  ${events.length} events`));
32658
33160
  if (events.length >= count8) {
32659
33161
  console.log(
32660
- chalk220.yellow(
33162
+ chalk224.yellow(
32661
33163
  `Results limited to ${count8}. Use --count to retrieve more.`
32662
33164
  )
32663
33165
  );
@@ -32665,10 +33167,10 @@ ${events.length} events`));
32665
33167
  }
32666
33168
 
32667
33169
  // src/shared/setNamedDefaultConnection.ts
32668
- import chalk221 from "chalk";
33170
+ import chalk225 from "chalk";
32669
33171
  function setNamedDefaultConnection(connections, name, setDefault, kind) {
32670
33172
  if (!connections.find((c) => c.name === name)) {
32671
- console.error(chalk221.red(`Connection "${name}" not found.`));
33173
+ console.error(chalk225.red(`Connection "${name}" not found.`));
32672
33174
  process.exit(1);
32673
33175
  }
32674
33176
  setDefault(name);
@@ -32817,7 +33319,7 @@ function registerSlack(program2) {
32817
33319
  }
32818
33320
 
32819
33321
  // src/commands/sql/sqlAuth.ts
32820
- import chalk223 from "chalk";
33322
+ import chalk227 from "chalk";
32821
33323
 
32822
33324
  // src/commands/sql/loadConnections.ts
32823
33325
  function loadConnections3() {
@@ -32846,7 +33348,7 @@ function setDefaultConnection2(name) {
32846
33348
  }
32847
33349
 
32848
33350
  // src/commands/sql/promptConnection.ts
32849
- import chalk222 from "chalk";
33351
+ import chalk226 from "chalk";
32850
33352
  async function promptConnection3(existingNames) {
32851
33353
  const name = await promptInput("name", "Connection name:", "default");
32852
33354
  assertUniqueName(existingNames, name);
@@ -32854,7 +33356,7 @@ async function promptConnection3(existingNames) {
32854
33356
  const portStr = await promptInput("port", "Port:", "1433");
32855
33357
  const port = Number.parseInt(portStr, 10);
32856
33358
  if (!Number.isFinite(port)) {
32857
- console.error(chalk222.red(`Invalid port "${portStr}".`));
33359
+ console.error(chalk226.red(`Invalid port "${portStr}".`));
32858
33360
  process.exit(1);
32859
33361
  }
32860
33362
  const user = await promptInput("user", "User:");
@@ -32867,13 +33369,13 @@ async function promptConnection3(existingNames) {
32867
33369
  var sqlAuth = createConnectionAuth({
32868
33370
  load: loadConnections3,
32869
33371
  save: saveConnections3,
32870
- format: (c) => `${chalk223.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
33372
+ format: (c) => `${chalk227.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
32871
33373
  promptNew: promptConnection3,
32872
33374
  onFirst: (c) => setDefaultConnection2(c.name)
32873
33375
  });
32874
33376
 
32875
33377
  // src/commands/sql/printTable.ts
32876
- import chalk224 from "chalk";
33378
+ import chalk228 from "chalk";
32877
33379
  function formatCell(value) {
32878
33380
  if (value === null || value === void 0) return "";
32879
33381
  if (value instanceof Date) return value.toISOString();
@@ -32882,7 +33384,7 @@ function formatCell(value) {
32882
33384
  }
32883
33385
  function printTable(rows) {
32884
33386
  if (rows.length === 0) {
32885
- console.log(chalk224.yellow("(no rows)"));
33387
+ console.log(chalk228.yellow("(no rows)"));
32886
33388
  return;
32887
33389
  }
32888
33390
  const columns = Object.keys(rows[0]);
@@ -32890,13 +33392,13 @@ function printTable(rows) {
32890
33392
  (col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
32891
33393
  );
32892
33394
  const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
32893
- console.log(chalk224.dim(header));
32894
- console.log(chalk224.dim("-".repeat(header.length)));
33395
+ console.log(chalk228.dim(header));
33396
+ console.log(chalk228.dim("-".repeat(header.length)));
32895
33397
  for (const row of rows) {
32896
33398
  const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
32897
33399
  console.log(line);
32898
33400
  }
32899
- console.log(chalk224.dim(`
33401
+ console.log(chalk228.dim(`
32900
33402
  ${rows.length} row${rows.length === 1 ? "" : "s"}`));
32901
33403
  }
32902
33404
 
@@ -32956,7 +33458,7 @@ async function sqlColumns(table, connectionName) {
32956
33458
  }
32957
33459
 
32958
33460
  // src/commands/sql/sqlMutate.ts
32959
- import chalk225 from "chalk";
33461
+ import chalk229 from "chalk";
32960
33462
 
32961
33463
  // src/commands/sql/isMutation.ts
32962
33464
  var MUTATION_KEYWORDS = [
@@ -32990,7 +33492,7 @@ function isMutation(sql29) {
32990
33492
  async function sqlMutate(query, connectionName) {
32991
33493
  if (!isMutation(query)) {
32992
33494
  console.error(
32993
- chalk225.red(
33495
+ chalk229.red(
32994
33496
  "assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
32995
33497
  )
32996
33498
  );
@@ -33000,18 +33502,18 @@ async function sqlMutate(query, connectionName) {
33000
33502
  const pool = await sqlConnect(conn);
33001
33503
  try {
33002
33504
  const result = await pool.request().query(query);
33003
- console.log(chalk225.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
33505
+ console.log(chalk229.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
33004
33506
  } finally {
33005
33507
  await pool.close();
33006
33508
  }
33007
33509
  }
33008
33510
 
33009
33511
  // src/commands/sql/sqlQuery.ts
33010
- import chalk226 from "chalk";
33512
+ import chalk230 from "chalk";
33011
33513
  async function sqlQuery(query, connectionName) {
33012
33514
  if (isMutation(query)) {
33013
33515
  console.error(
33014
- chalk226.red(
33516
+ chalk230.red(
33015
33517
  "assist sql query refuses mutating statements. Use `assist sql mutate` instead."
33016
33518
  )
33017
33519
  );
@@ -33026,7 +33528,7 @@ async function sqlQuery(query, connectionName) {
33026
33528
  printTable(rows);
33027
33529
  } else {
33028
33530
  console.log(
33029
- chalk226.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
33531
+ chalk230.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
33030
33532
  );
33031
33533
  }
33032
33534
  } finally {
@@ -33400,7 +33902,7 @@ function syncPi(claudeDir, options2) {
33400
33902
  // src/commands/sync/syncSettings.ts
33401
33903
  import * as fs48 from "fs";
33402
33904
  import * as path84 from "path";
33403
- import chalk227 from "chalk";
33905
+ import chalk231 from "chalk";
33404
33906
  async function syncSettings(claudeDir, targetBase, options2) {
33405
33907
  const source = path84.join(claudeDir, "settings.json");
33406
33908
  const target = path84.join(targetBase, "settings.json");
@@ -33419,7 +33921,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
33419
33921
  if (mergedContent !== normalizedTarget) {
33420
33922
  if (!options2?.yes) {
33421
33923
  console.log(
33422
- chalk227.yellow(
33924
+ chalk231.yellow(
33423
33925
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
33424
33926
  )
33425
33927
  );
@@ -33427,7 +33929,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
33427
33929
  printDiff(targetContent, mergedContent);
33428
33930
  printAutoConfirmHint();
33429
33931
  const confirm = await promptConfirm(
33430
- chalk227.red("Overwrite existing settings.json?"),
33932
+ chalk231.red("Overwrite existing settings.json?"),
33431
33933
  false
33432
33934
  );
33433
33935
  if (!confirm) {
@@ -34296,7 +34798,7 @@ import { mkdirSync as mkdirSync31 } from "fs";
34296
34798
  import { join as join93 } from "path";
34297
34799
 
34298
34800
  // src/commands/voice/checkLockFile.ts
34299
- import { execSync as execSync60 } from "child_process";
34801
+ import { execSync as execSync61 } from "child_process";
34300
34802
  import { existsSync as existsSync78, mkdirSync as mkdirSync30, readFileSync as readFileSync58, writeFileSync as writeFileSync48 } from "fs";
34301
34803
  import { join as join92 } from "path";
34302
34804
  function isProcessAlive2(pid) {
@@ -34325,7 +34827,7 @@ function bootstrapVenv() {
34325
34827
  if (existsSync78(getVenvPython())) return;
34326
34828
  console.log("Setting up Python environment...");
34327
34829
  const pythonDir = getPythonDir();
34328
- execSync60(
34830
+ execSync61(
34329
34831
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
34330
34832
  {
34331
34833
  stdio: "inherit",
@@ -34946,11 +35448,11 @@ function runCommandToCompletion(command, args, env, cwd, quiet) {
34946
35448
  }
34947
35449
 
34948
35450
  // src/commands/run/runPreCommands.ts
34949
- import { execSync as execSync61 } from "child_process";
35451
+ import { execSync as execSync62 } from "child_process";
34950
35452
  function runPreCommands(pre, cwd) {
34951
35453
  for (const cmd of pre) {
34952
35454
  try {
34953
- execSync61(cmd, { stdio: "inherit", cwd });
35455
+ execSync62(cmd, { stdio: "inherit", cwd });
34954
35456
  } catch (error) {
34955
35457
  const code = error && typeof error === "object" && "status" in error ? error.status : 1;
34956
35458
  process.exit(code);
@@ -35169,7 +35671,7 @@ function registerWatch(program2) {
35169
35671
 
35170
35672
  // src/commands/roam/auth.ts
35171
35673
  import { randomBytes } from "crypto";
35172
- import chalk228 from "chalk";
35674
+ import chalk232 from "chalk";
35173
35675
 
35174
35676
  // src/commands/roam/waitForCallback.ts
35175
35677
  import { createServer as createServer3 } from "http";
@@ -35300,13 +35802,13 @@ async function auth() {
35300
35802
  saveGlobalConfig(config);
35301
35803
  const state = randomBytes(16).toString("hex");
35302
35804
  console.log(
35303
- chalk228.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
35805
+ chalk232.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
35304
35806
  );
35305
- console.log(chalk228.white("http://localhost:14523/callback\n"));
35306
- console.log(chalk228.blue("Opening browser for authorization..."));
35307
- console.log(chalk228.dim("Waiting for authorization callback..."));
35807
+ console.log(chalk232.white("http://localhost:14523/callback\n"));
35808
+ console.log(chalk232.blue("Opening browser for authorization..."));
35809
+ console.log(chalk232.dim("Waiting for authorization callback..."));
35308
35810
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
35309
- console.log(chalk228.dim("Exchanging code for tokens..."));
35811
+ console.log(chalk232.dim("Exchanging code for tokens..."));
35310
35812
  const tokens = await exchangeToken({
35311
35813
  code,
35312
35814
  clientId,
@@ -35322,7 +35824,7 @@ async function auth() {
35322
35824
  };
35323
35825
  saveGlobalConfig(config);
35324
35826
  console.log(
35325
- chalk228.green("Roam credentials and tokens saved to ~/.assist.yml")
35827
+ chalk232.green("Roam credentials and tokens saved to ~/.assist.yml")
35326
35828
  );
35327
35829
  }
35328
35830
 
@@ -35677,11 +36179,11 @@ function registerRun(program2) {
35677
36179
  }
35678
36180
 
35679
36181
  // src/commands/screenshot/index.ts
35680
- import { execSync as execSync62 } from "child_process";
36182
+ import { execSync as execSync63 } from "child_process";
35681
36183
  import { existsSync as existsSync85, mkdirSync as mkdirSync34, unlinkSync as unlinkSync22, writeFileSync as writeFileSync51 } from "fs";
35682
36184
  import { tmpdir as tmpdir9 } from "os";
35683
36185
  import { join as join100, resolve as resolve21 } from "path";
35684
- import chalk229 from "chalk";
36186
+ import chalk233 from "chalk";
35685
36187
 
35686
36188
  // src/commands/screenshot/captureWindowPs1.ts
35687
36189
  var captureWindowPs1 = `
@@ -35820,7 +36322,7 @@ function runPowerShellScript(processName, outputPath) {
35820
36322
  const scriptPath = join100(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
35821
36323
  writeFileSync51(scriptPath, captureWindowPs1, "utf8");
35822
36324
  try {
35823
- execSync62(
36325
+ execSync63(
35824
36326
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
35825
36327
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
35826
36328
  );
@@ -35832,13 +36334,13 @@ function screenshot(processName) {
35832
36334
  const config = loadConfig();
35833
36335
  const outputDir = resolve21(config.screenshot.outputDir);
35834
36336
  const outputPath = buildOutputPath(outputDir, processName);
35835
- console.log(chalk229.gray(`Capturing window for process "${processName}" ...`));
36337
+ console.log(chalk233.gray(`Capturing window for process "${processName}" ...`));
35836
36338
  try {
35837
36339
  runPowerShellScript(processName, outputPath);
35838
- console.log(chalk229.green(`Screenshot saved: ${outputPath}`));
36340
+ console.log(chalk233.green(`Screenshot saved: ${outputPath}`));
35839
36341
  } catch (error) {
35840
36342
  const msg = error instanceof Error ? error.message : String(error);
35841
- console.error(chalk229.red(`Failed to capture screenshot: ${msg}`));
36343
+ console.error(chalk233.red(`Failed to capture screenshot: ${msg}`));
35842
36344
  process.exit(1);
35843
36345
  }
35844
36346
  }
@@ -41800,7 +42302,7 @@ async function renameSession(title) {
41800
42302
 
41801
42303
  // src/commands/sessions/summarise/index.ts
41802
42304
  import * as fs57 from "fs";
41803
- import chalk230 from "chalk";
42305
+ import chalk234 from "chalk";
41804
42306
 
41805
42307
  // src/commands/sessions/summarise/shared.ts
41806
42308
  import * as fs56 from "fs";
@@ -41859,22 +42361,22 @@ ${firstMessage}`);
41859
42361
  async function summarise2(options2) {
41860
42362
  const files = await discoverSessionFiles();
41861
42363
  if (files.length === 0) {
41862
- console.log(chalk230.yellow("No sessions found."));
42364
+ console.log(chalk234.yellow("No sessions found."));
41863
42365
  return;
41864
42366
  }
41865
42367
  const toProcess = selectCandidates(files, options2);
41866
42368
  if (toProcess.length === 0) {
41867
- console.log(chalk230.green("All sessions already summarised."));
42369
+ console.log(chalk234.green("All sessions already summarised."));
41868
42370
  return;
41869
42371
  }
41870
42372
  console.log(
41871
- chalk230.cyan(
42373
+ chalk234.cyan(
41872
42374
  `Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
41873
42375
  )
41874
42376
  );
41875
42377
  const { succeeded, failed: failed2 } = processSessions(toProcess);
41876
42378
  console.log(
41877
- chalk230.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk230.yellow(`, ${failed2} skipped`) : "")
42379
+ chalk234.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk234.yellow(`, ${failed2} skipped`) : "")
41878
42380
  );
41879
42381
  }
41880
42382
  function selectCandidates(files, options2) {
@@ -41894,16 +42396,16 @@ function processSessions(files) {
41894
42396
  let failed2 = 0;
41895
42397
  for (let i = 0; i < files.length; i++) {
41896
42398
  const file = files[i];
41897
- process.stdout.write(chalk230.dim(` [${i + 1}/${files.length}] `));
42399
+ process.stdout.write(chalk234.dim(` [${i + 1}/${files.length}] `));
41898
42400
  const summary = summariseSession(file);
41899
42401
  if (summary) {
41900
42402
  writeSummary(file, summary);
41901
42403
  succeeded++;
41902
- process.stdout.write(`${chalk230.green("\u2713")} ${summary}
42404
+ process.stdout.write(`${chalk234.green("\u2713")} ${summary}
41903
42405
  `);
41904
42406
  } else {
41905
42407
  failed2++;
41906
- process.stdout.write(` ${chalk230.yellow("skip")}
42408
+ process.stdout.write(` ${chalk234.yellow("skip")}
41907
42409
  `);
41908
42410
  }
41909
42411
  }
@@ -41930,7 +42432,7 @@ function registerSessions(program2) {
41930
42432
  }
41931
42433
 
41932
42434
  // src/commands/statusLine.ts
41933
- import chalk232 from "chalk";
42435
+ import chalk236 from "chalk";
41934
42436
 
41935
42437
  // src/shared/contextLevel.ts
41936
42438
  function contextLevel(pct) {
@@ -41940,7 +42442,7 @@ function contextLevel(pct) {
41940
42442
  }
41941
42443
 
41942
42444
  // src/commands/buildLimitsSegment.ts
41943
- import chalk231 from "chalk";
42445
+ import chalk235 from "chalk";
41944
42446
 
41945
42447
  // src/shared/rateLimitLevel.ts
41946
42448
  var FIVE_HOUR_SECONDS = 5 * 3600;
@@ -41978,9 +42480,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
41978
42480
 
41979
42481
  // src/commands/buildLimitsSegment.ts
41980
42482
  var LEVEL_COLOR = {
41981
- ok: chalk231.green,
41982
- warn: chalk231.yellow,
41983
- over: chalk231.red
42483
+ ok: chalk235.green,
42484
+ warn: chalk235.yellow,
42485
+ over: chalk235.red
41984
42486
  };
41985
42487
  function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
41986
42488
  const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
@@ -42076,7 +42578,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
42076
42578
  }
42077
42579
 
42078
42580
  // src/commands/statusLine.ts
42079
- chalk232.level = 3;
42581
+ chalk236.level = 3;
42080
42582
  function formatNumber(num) {
42081
42583
  return num.toLocaleString("en-US");
42082
42584
  }
@@ -42084,9 +42586,9 @@ function colorizePercent(pct) {
42084
42586
  const label2 = `${Math.round(pct)}%`;
42085
42587
  switch (contextLevel(pct)) {
42086
42588
  case "red":
42087
- return chalk232.red(label2);
42589
+ return chalk236.red(label2);
42088
42590
  case "yellow":
42089
- return chalk232.yellow(label2);
42591
+ return chalk236.yellow(label2);
42090
42592
  default:
42091
42593
  return label2;
42092
42594
  }
@@ -42099,7 +42601,7 @@ async function statusLine() {
42099
42601
  const usedPct = data.context_window.used_percentage ?? 0;
42100
42602
  const dir = data.workspace?.current_dir ?? data.cwd;
42101
42603
  const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
42102
- const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk232.cyan(branch2)} | ` : "";
42604
+ const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk236.cyan(branch2)} | ` : "";
42103
42605
  console.log(
42104
42606
  `${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
42105
42607
  );
@@ -42112,7 +42614,7 @@ async function statusLine() {
42112
42614
  }
42113
42615
 
42114
42616
  // src/commands/update.ts
42115
- import { execSync as execSync63 } from "child_process";
42617
+ import { execSync as execSync64 } from "child_process";
42116
42618
  import * as path90 from "path";
42117
42619
 
42118
42620
  // src/commands/restartDaemonAfterUpdate.ts
@@ -42136,7 +42638,7 @@ function isGlobalNpmInstall(dir) {
42136
42638
  if (resolved.split(path90.sep).includes("node_modules")) {
42137
42639
  return true;
42138
42640
  }
42139
- const globalPrefix = execSync63("npm prefix -g", { stdio: "pipe" }).toString().trim();
42641
+ const globalPrefix = execSync64("npm prefix -g", { stdio: "pipe" }).toString().trim();
42140
42642
  return resolved.toLowerCase().startsWith(path90.resolve(globalPrefix).toLowerCase());
42141
42643
  } catch {
42142
42644
  return false;
@@ -42147,18 +42649,18 @@ async function update2() {
42147
42649
  console.log(`Assist is installed at: ${installDir}`);
42148
42650
  if (isGitRepo(installDir)) {
42149
42651
  console.log("Detected git repo installation, pulling latest...");
42150
- execSync63("git pull", { cwd: installDir, stdio: "inherit" });
42652
+ execSync64("git pull", { cwd: installDir, stdio: "inherit" });
42151
42653
  console.log("Installing dependencies...");
42152
- execSync63("npm i", { cwd: installDir, stdio: "inherit" });
42654
+ execSync64("npm i", { cwd: installDir, stdio: "inherit" });
42153
42655
  console.log("Building...");
42154
- execSync63("npm run build", { cwd: installDir, stdio: "inherit" });
42656
+ execSync64("npm run build", { cwd: installDir, stdio: "inherit" });
42155
42657
  console.log("Syncing commands...");
42156
- execSync63("assist sync", { stdio: "inherit" });
42658
+ execSync64("assist sync", { stdio: "inherit" });
42157
42659
  } else if (isGlobalNpmInstall(installDir)) {
42158
42660
  console.log("Detected global npm installation, updating...");
42159
- execSync63("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
42661
+ execSync64("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
42160
42662
  console.log("Syncing commands...");
42161
- execSync63("assist sync", { stdio: "inherit" });
42663
+ execSync64("assist sync", { stdio: "inherit" });
42162
42664
  } else {
42163
42665
  console.error(
42164
42666
  "Could not determine installation method. Expected a git repo or global npm install."
@@ -42169,10 +42671,10 @@ async function update2() {
42169
42671
  }
42170
42672
 
42171
42673
  // src/reportCliError.ts
42172
- import chalk233 from "chalk";
42674
+ import chalk237 from "chalk";
42173
42675
  function reportCliError(error) {
42174
42676
  if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
42175
- console.error(chalk233.red(error.message));
42677
+ console.error(chalk237.red(error.message));
42176
42678
  } else {
42177
42679
  console.error(error);
42178
42680
  }