@staff0rd/assist 0.660.2 → 0.661.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.661.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -717,7 +717,12 @@ var assistConfigShape = {
717
717
  readingWordsPerMinute: z3.number().int().positive().optional()
718
718
  }).optional(),
719
719
  review: z3.strictObject({
720
- codexModel: z3.string().optional()
720
+ codexModel: z3.string().optional(),
721
+ highLevel: z3.strictObject({
722
+ criticalPaths: z3.array(z3.string()).default([]),
723
+ uiPaths: z3.array(z3.string()).default([]),
724
+ descriptionWordCap: z3.number().int().positive().default(300)
725
+ }).optional()
721
726
  }).optional(),
722
727
  readTime: z3.strictObject({
723
728
  wordsPerMinute: z3.number().int().positive().default(200)
@@ -1941,10 +1946,10 @@ import fs11 from "fs";
1941
1946
 
1942
1947
  // src/commands/lint/shared.ts
1943
1948
  import chalk24 from "chalk";
1944
- function reportViolations2(violations, checkName, errorMessage, successMessage) {
1949
+ function reportViolations2(violations, checkName2, errorMessage, successMessage) {
1945
1950
  if (violations.length > 0) {
1946
1951
  console.error(chalk24.red(`
1947
- ${checkName} failed:
1952
+ ${checkName2} failed:
1948
1953
  `));
1949
1954
  console.error(chalk24.red(` ${errorMessage}
1950
1955
  `));
@@ -3363,6 +3368,21 @@ var reviewConfigHelp = [
3363
3368
  key: "review.codexModel",
3364
3369
  setter: "assist config set review.codexModel gpt-5-codex",
3365
3370
  note: "optional; runs the codex reviewer on this model via the LiteLLM proxy (needs litellm.baseUrl and litellm.apiKey)"
3371
+ },
3372
+ {
3373
+ key: "review.highLevel.criticalPaths",
3374
+ setter: 'assist config set review.highLevel.criticalPaths "**/*.graphql,en-AU/translation.json"',
3375
+ note: "comma-separated globs whose full diffs the high-level review shows; unset shows none"
3376
+ },
3377
+ {
3378
+ key: "review.highLevel.uiPaths",
3379
+ setter: 'assist config set review.highLevel.uiPaths "src/ui/**"',
3380
+ note: "comma-separated globs that make a change a UI change, so --high-level requires a screenshot or video; unset requires none"
3381
+ },
3382
+ {
3383
+ key: "review.highLevel.descriptionWordCap",
3384
+ setter: "assist config set review.highLevel.descriptionWordCap 300",
3385
+ note: "word cap --high-level holds the PR description to (default 300)"
3366
3386
  }
3367
3387
  ];
3368
3388
 
@@ -5010,12 +5030,12 @@ function addViteBaseConfig() {
5010
5030
  console.log("vite.config.ts already has base config");
5011
5031
  return;
5012
5032
  }
5013
- const updated = content.replace(
5033
+ const updated2 = content.replace(
5014
5034
  /defineConfig\(\{/,
5015
5035
  'defineConfig({\n base: "./",'
5016
5036
  );
5017
- if (updated !== content) {
5018
- writeFileSync13(viteConfigPath, updated);
5037
+ if (updated2 !== content) {
5038
+ writeFileSync13(viteConfigPath, updated2);
5019
5039
  console.log('Added base: "./" to vite.config.ts');
5020
5040
  }
5021
5041
  }
@@ -10716,16 +10736,16 @@ async function patchItemStatus(req, res, id) {
10716
10736
  const result = await findItemOr404(res, id);
10717
10737
  if (!result) return;
10718
10738
  await updateStatus(result.orm, id, status3);
10719
- const updated = { ...result.item, status: status3 };
10720
- respondJson(res, 200, updated);
10739
+ const updated2 = { ...result.item, status: status3 };
10740
+ respondJson(res, 200, updated2);
10721
10741
  }
10722
10742
  async function patchItemStar(req, res, id) {
10723
10743
  const { starred } = await parseStarBody(req);
10724
10744
  const result = await findItemOr404(res, id);
10725
10745
  if (!result) return;
10726
10746
  await updateStarred(result.orm, id, starred);
10727
- const updated = { ...result.item, starred };
10728
- respondJson(res, 200, updated);
10747
+ const updated2 = { ...result.item, starred };
10748
+ respondJson(res, 200, updated2);
10729
10749
  }
10730
10750
 
10731
10751
  // src/commands/backlog/web/deleteItemComment.ts
@@ -13045,15 +13065,15 @@ function setNestedValue(obj, path91, value) {
13045
13065
  }
13046
13066
 
13047
13067
  // src/commands/config/validateConfig.ts
13048
- function validateConfig(updated, key, schema2 = assistConfigSchema) {
13049
- const result = schema2.safeParse(stripLegacyConfigKeys(updated));
13068
+ function validateConfig(updated2, key, schema2 = assistConfigSchema) {
13069
+ const result = schema2.safeParse(stripLegacyConfigKeys(updated2));
13050
13070
  if (result.success) return { ok: true };
13051
13071
  const errors = result.error.issues.flatMap(
13052
13072
  (issue) => formatIssue2(issue, key)
13053
13073
  );
13054
13074
  return {
13055
13075
  ok: false,
13056
- errors: scrubConfigSecrets(errors, updated, describeConfigNode(schema2))
13076
+ errors: scrubConfigSecrets(errors, updated2, describeConfigNode(schema2))
13057
13077
  };
13058
13078
  }
13059
13079
  function formatIssue2(issue, key) {
@@ -13076,14 +13096,14 @@ function applyConfigSet(key, coerced, global, cwd = process.cwd(), globalConfigP
13076
13096
  };
13077
13097
  }
13078
13098
  const raw = global ? loadGlobalConfigRaw(globalConfigPath) : loadProjectConfig(cwd);
13079
- const updated = setNestedValue(raw, key, coerced);
13080
- const validation = validateConfig(updated, key);
13099
+ const updated2 = setNestedValue(raw, key, coerced);
13100
+ const validation = validateConfig(updated2, key);
13081
13101
  if (!validation.ok) return validation;
13082
13102
  if (global) {
13083
- saveGlobalConfig(updated, globalConfigPath);
13103
+ saveGlobalConfig(updated2, globalConfigPath);
13084
13104
  return { ok: true, target: "global" };
13085
13105
  }
13086
- saveConfig(updated, cwd);
13106
+ saveConfig(updated2, cwd);
13087
13107
  return { ok: true, target: "project" };
13088
13108
  }
13089
13109
 
@@ -16467,20 +16487,20 @@ function hasListMutations(options2) {
16467
16487
  options2.add && options2.add.length > 0 || options2.edit || options2.remove
16468
16488
  );
16469
16489
  }
16470
- function applyListMutations(current, options2, flags) {
16490
+ function applyListMutations(current, options2, flags2) {
16471
16491
  let items2 = [...current];
16472
16492
  if (options2.edit) {
16473
16493
  const [rawIndex, ...textParts] = options2.edit;
16474
16494
  if (rawIndex === void 0 || textParts.length === 0) {
16475
16495
  return {
16476
16496
  ok: false,
16477
- error: `${flags.edit} requires an index and replacement text.`
16497
+ error: `${flags2.edit} requires an index and replacement text.`
16478
16498
  };
16479
16499
  }
16480
16500
  const parsed = parseListIndex(
16481
16501
  rawIndex,
16482
16502
  items2.length,
16483
- `${flags.edit} index`
16503
+ `${flags2.edit} index`
16484
16504
  );
16485
16505
  if (!parsed.ok) return parsed;
16486
16506
  items2[parsed.index - 1] = textParts.join(" ");
@@ -16489,7 +16509,7 @@ function applyListMutations(current, options2, flags) {
16489
16509
  const parsed = parseListIndex(
16490
16510
  options2.remove,
16491
16511
  items2.length,
16492
- `${flags.remove} index`
16512
+ `${flags2.remove} index`
16493
16513
  );
16494
16514
  if (!parsed.ok) return parsed;
16495
16515
  items2 = items2.filter((_, i) => i !== parsed.index - 1);
@@ -16501,15 +16521,15 @@ function applyListMutations(current, options2, flags) {
16501
16521
  }
16502
16522
 
16503
16523
  // src/commands/backlog/update/resolveListUpdate.ts
16504
- function resolveListUpdate(whole, current, mutations, wholeFlag, flags) {
16524
+ function resolveListUpdate(whole, current, mutations, wholeFlag, flags2) {
16505
16525
  if (!hasListMutations(mutations)) return { ok: true, items: whole };
16506
16526
  if (whole) {
16507
16527
  return {
16508
16528
  ok: false,
16509
- error: `Cannot combine ${wholeFlag} with ${flags.add}/${flags.edit}/${flags.remove}.`
16529
+ error: `Cannot combine ${wholeFlag} with ${flags2.add}/${flags2.edit}/${flags2.remove}.`
16510
16530
  };
16511
16531
  }
16512
- return applyListMutations(current, mutations, flags);
16532
+ return applyListMutations(current, mutations, flags2);
16513
16533
  }
16514
16534
 
16515
16535
  // src/commands/backlog/resolvePhaseFields.ts
@@ -18428,8 +18448,8 @@ function loadDenyConfig(global) {
18428
18448
  const deny = config.deny ?? [];
18429
18449
  return {
18430
18450
  deny,
18431
- saveDeny: (updated) => {
18432
- config.deny = updated;
18451
+ saveDeny: (updated2) => {
18452
+ config.deny = updated2;
18433
18453
  save(config);
18434
18454
  }
18435
18455
  };
@@ -27471,8 +27491,218 @@ async function reply(commentId, body) {
27471
27491
  }
27472
27492
  }
27473
27493
 
27474
- // src/commands/prs/wontfix.ts
27494
+ // src/commands/prs/status/describeFetchError.ts
27495
+ function firstLine2(text18) {
27496
+ const line = text18.split("\n").map((candidate) => candidate.trim()).find((candidate) => candidate.length > 0);
27497
+ return line ?? null;
27498
+ }
27499
+ function stderrText(error) {
27500
+ const stderr = error?.stderr;
27501
+ if (typeof stderr === "string") return firstLine2(stderr);
27502
+ if (stderr instanceof Uint8Array) {
27503
+ return firstLine2(Buffer.from(stderr).toString("utf8"));
27504
+ }
27505
+ return null;
27506
+ }
27507
+ function describeFetchError(error) {
27508
+ if (isGhNotInstalled(error)) {
27509
+ return "GitHub CLI (gh) is not installed \u2014 see https://cli.github.com/";
27510
+ }
27511
+ const stderr = stderrText(error);
27512
+ if (stderr) return stderr;
27513
+ if (error instanceof Error) return firstLine2(error.message) ?? error.message;
27514
+ return String(error);
27515
+ }
27516
+
27517
+ // src/commands/prs/status/fetchRepoPullRequests.ts
27475
27518
  import { execSync as execSync51 } from "child_process";
27519
+ var FIELDS = "number,title,url,author,isDraft,createdAt,updatedAt,reviewDecision,latestReviews,statusCheckRollup,mergeable";
27520
+ function fetchRepoPullRequests(org, repo) {
27521
+ const output = execSync51(
27522
+ `gh pr list --state open --json ${FIELDS} --limit 100 -R ${org}/${repo}`,
27523
+ { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
27524
+ );
27525
+ const parsed = JSON.parse(output);
27526
+ if (!Array.isArray(parsed)) {
27527
+ throw new Error("unexpected response from gh pr list");
27528
+ }
27529
+ return parsed;
27530
+ }
27531
+
27532
+ // src/commands/prs/status/parseRepoArgument.ts
27533
+ var REPO_ARGUMENT = /^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)$/;
27534
+ function parseRepoArgument(value) {
27535
+ const match = REPO_ARGUMENT.exec(value.trim());
27536
+ if (!match) return null;
27537
+ return { org: match[1], repo: match[2] };
27538
+ }
27539
+
27540
+ // src/commands/prs/status/describeAge.ts
27541
+ function describeAge(timestamp6, now = Date.now()) {
27542
+ const parsed = new Date(timestamp6).getTime();
27543
+ if (Number.isNaN(parsed)) return { hours: null, label: "unknown" };
27544
+ const hours = Math.max(0, Math.floor((now - parsed) / 36e5));
27545
+ if (hours < 1) return { hours, label: "<1h" };
27546
+ if (hours < 24) return { hours, label: `${hours}h` };
27547
+ return { hours, label: `${Math.floor(hours / 24)}d` };
27548
+ }
27549
+
27550
+ // src/commands/prs/status/summariseChecks.ts
27551
+ var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["SUCCESS", "NEUTRAL", "SKIPPED"]);
27552
+ var PENDING_STATES = /* @__PURE__ */ new Set(["PENDING", "EXPECTED"]);
27553
+ function checkName(check2) {
27554
+ return check2.name?.trim() || check2.context?.trim() || "unnamed check";
27555
+ }
27556
+ function isPending(check2) {
27557
+ if (check2.status) return check2.status !== "COMPLETED";
27558
+ return PENDING_STATES.has(check2.state ?? "");
27559
+ }
27560
+ function isFailing(check2) {
27561
+ if (check2.status) return !PASSING_CONCLUSIONS.has(check2.conclusion ?? "");
27562
+ return !PASSING_CONCLUSIONS.has(check2.state ?? "");
27563
+ }
27564
+ function summariseChecks(rollup) {
27565
+ const summary = { failing: [], pending: [] };
27566
+ for (const check2 of rollup ?? []) {
27567
+ if (isPending(check2)) summary.pending.push(checkName(check2));
27568
+ else if (isFailing(check2)) summary.failing.push(checkName(check2));
27569
+ }
27570
+ return summary;
27571
+ }
27572
+
27573
+ // src/commands/prs/status/toPrStatus.ts
27574
+ function toReviews(pr) {
27575
+ return (pr.latestReviews ?? []).map((review2) => ({
27576
+ reviewer: review2.author?.login ?? "unknown",
27577
+ state: review2.state ?? "UNKNOWN"
27578
+ }));
27579
+ }
27580
+ function toPrStatus(pr, now = Date.now()) {
27581
+ const age = describeAge(pr.updatedAt, now);
27582
+ return {
27583
+ number: pr.number,
27584
+ title: pr.title,
27585
+ url: pr.url,
27586
+ author: pr.author?.login ?? "unknown",
27587
+ isBot: pr.author?.is_bot === true,
27588
+ isDraft: pr.isDraft === true,
27589
+ createdAt: pr.createdAt,
27590
+ updatedAt: pr.updatedAt,
27591
+ age: age.label,
27592
+ ageHours: age.hours,
27593
+ reviewDecision: pr.reviewDecision || null,
27594
+ reviews: toReviews(pr),
27595
+ checks: summariseChecks(pr.statusCheckRollup),
27596
+ mergeable: pr.mergeable || "UNKNOWN"
27597
+ };
27598
+ }
27599
+
27600
+ // src/commands/prs/status/buildPrsStatusReport.ts
27601
+ function buildPrsStatusReport(repoArguments, now = Date.now()) {
27602
+ const report2 = { repos: [], errors: [] };
27603
+ for (const argument of repoArguments) {
27604
+ const parsed = parseRepoArgument(argument);
27605
+ if (!parsed) {
27606
+ report2.errors.push({
27607
+ repo: argument,
27608
+ error: "not an owner/repo argument"
27609
+ });
27610
+ continue;
27611
+ }
27612
+ const repo = `${parsed.org}/${parsed.repo}`;
27613
+ try {
27614
+ const pullRequests = fetchRepoPullRequests(parsed.org, parsed.repo).map(
27615
+ (pr) => toPrStatus(pr, now)
27616
+ );
27617
+ report2.repos.push({ repo, pullRequests });
27618
+ } catch (error) {
27619
+ report2.errors.push({ repo, error: describeFetchError(error) });
27620
+ }
27621
+ }
27622
+ return report2;
27623
+ }
27624
+
27625
+ // src/commands/prs/status/printPrsStatus.ts
27626
+ import chalk187 from "chalk";
27627
+
27628
+ // src/commands/prs/status/printPrStatus.ts
27629
+ import chalk186 from "chalk";
27630
+ function flags(pr) {
27631
+ const markers = [];
27632
+ if (pr.isDraft) markers.push("draft");
27633
+ if (pr.isBot) markers.push("bot");
27634
+ return markers.length ? ` ${chalk186.yellow(`[${markers.join(", ")}]`)}` : "";
27635
+ }
27636
+ function updated(pr) {
27637
+ return pr.ageHours === null ? "updated unknown" : `updated ${pr.age} ago`;
27638
+ }
27639
+ function reviewLine(pr) {
27640
+ if (!pr.reviewDecision && pr.reviews.length === 0) return null;
27641
+ const reviewers = pr.reviews.map((review2) => `${review2.reviewer}: ${review2.state}`).join(", ");
27642
+ const decision = pr.reviewDecision ?? "no decision";
27643
+ return reviewers ? `review: ${decision} | ${reviewers}` : `review: ${decision}`;
27644
+ }
27645
+ function checkLines(pr) {
27646
+ const lines2 = [];
27647
+ if (pr.checks.failing.length) {
27648
+ lines2.push(chalk186.red(`failing: ${pr.checks.failing.join(", ")}`));
27649
+ }
27650
+ if (pr.checks.pending.length) {
27651
+ lines2.push(chalk186.yellow(`pending: ${pr.checks.pending.join(", ")}`));
27652
+ }
27653
+ return lines2;
27654
+ }
27655
+ function mergeableLine(pr) {
27656
+ if (pr.mergeable === "CONFLICTING") return chalk186.red("conflicting");
27657
+ if (pr.mergeable === "MERGEABLE") return null;
27658
+ return chalk186.dim(`mergeable: ${pr.mergeable.toLowerCase()}`);
27659
+ }
27660
+ function printPrStatus(pr) {
27661
+ console.log(
27662
+ ` ${chalk186.cyan(`#${pr.number}`)} ${pr.title} ${chalk186.dim(`(${pr.author}, ${updated(pr)})`)}${flags(pr)}`
27663
+ );
27664
+ const details = [
27665
+ reviewLine(pr),
27666
+ ...checkLines(pr),
27667
+ mergeableLine(pr),
27668
+ chalk186.dim(pr.url)
27669
+ ];
27670
+ for (const detail of details) {
27671
+ if (detail) console.log(` ${detail}`);
27672
+ }
27673
+ }
27674
+
27675
+ // src/commands/prs/status/printPrsStatus.ts
27676
+ function printPrsStatus(report2) {
27677
+ for (const repo of report2.repos) {
27678
+ const count8 = repo.pullRequests.length;
27679
+ console.log(`${chalk187.bold(repo.repo)} ${chalk187.dim(`(${count8} open)`)}`);
27680
+ for (const pr of repo.pullRequests) {
27681
+ printPrStatus(pr);
27682
+ }
27683
+ if (count8 === 0) console.log(chalk187.dim(" no open pull requests"));
27684
+ console.log();
27685
+ }
27686
+ if (report2.errors.length === 0) return;
27687
+ console.log(chalk187.bold("Errors"));
27688
+ for (const failure of report2.errors) {
27689
+ console.log(` ${chalk187.red(failure.repo)}: ${failure.error}`);
27690
+ }
27691
+ console.log();
27692
+ }
27693
+
27694
+ // src/commands/prs/status/index.ts
27695
+ function prsStatus(repos2, options2) {
27696
+ const report2 = buildPrsStatusReport(repos2);
27697
+ if (options2.json) {
27698
+ console.log(JSON.stringify(report2, null, 2));
27699
+ return;
27700
+ }
27701
+ printPrsStatus(report2);
27702
+ }
27703
+
27704
+ // src/commands/prs/wontfix.ts
27705
+ import { execSync as execSync52 } from "child_process";
27476
27706
  function validateReason(reason4) {
27477
27707
  const lowerReason = reason4.toLowerCase();
27478
27708
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -27489,7 +27719,7 @@ function validateShaReferences(reason4) {
27489
27719
  const invalidShas = [];
27490
27720
  for (const sha of shas) {
27491
27721
  try {
27492
- execSync51(`git cat-file -t ${sha}`, { stdio: "pipe" });
27722
+ execSync52(`git cat-file -t ${sha}`, { stdio: "pipe" });
27493
27723
  } catch {
27494
27724
  invalidShas.push(sha);
27495
27725
  }
@@ -27782,6 +28012,13 @@ function registerPrsRaise(prsCommand) {
27782
28012
  configHelp(raiseCommand, prsRaiseConfigHelp);
27783
28013
  }
27784
28014
 
28015
+ // src/commands/registerPrsStatus.ts
28016
+ function registerPrsStatus(prsCommand) {
28017
+ prsCommand.command("status <repo...>").description(
28018
+ "Report every open pull request in each owner/repo, grouped by repo"
28019
+ ).option("--json", "Output as JSON").action(prsStatus);
28020
+ }
28021
+
27785
28022
  // src/commands/readTime/readTime.ts
27786
28023
  import { readFileSync as readFileSync46 } from "fs";
27787
28024
 
@@ -27871,7 +28108,7 @@ function resolveReadTimeTarget(target) {
27871
28108
  }
27872
28109
 
27873
28110
  // src/commands/prs/fetchPrBody.ts
27874
- import { execSync as execSync52 } from "child_process";
28111
+ import { execSync as execSync53 } from "child_process";
27875
28112
  function exitGhNotInstalled() {
27876
28113
  console.error("Error: GitHub CLI (gh) is not installed.");
27877
28114
  console.error("Install it from https://cli.github.com/");
@@ -27892,7 +28129,7 @@ function currentRepo() {
27892
28129
  function fetchPrBody(number, repo) {
27893
28130
  const { org, repo: name } = repo ?? currentRepo();
27894
28131
  try {
27895
- const raw = execSync52(`gh pr view ${number} --json body -R ${org}/${name}`, {
28132
+ const raw = execSync53(`gh pr view ${number} --json body -R ${org}/${name}`, {
27896
28133
  encoding: "utf8",
27897
28134
  stdio: ["pipe", "pipe", "pipe"]
27898
28135
  });
@@ -27971,6 +28208,7 @@ function registerReadTime(parent) {
27971
28208
  function registerPrs(program2) {
27972
28209
  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
28210
  registerPrsRaise(prsCommand);
28211
+ registerPrsStatus(prsCommand);
27974
28212
  registerPrsEdit(prsCommand);
27975
28213
  registerPrsComments(prsCommand);
27976
28214
  registerReadTime(prsCommand);
@@ -27978,10 +28216,10 @@ function registerPrs(program2) {
27978
28216
  }
27979
28217
 
27980
28218
  // src/commands/ravendb/ravendbAuth.ts
27981
- import chalk191 from "chalk";
28219
+ import chalk193 from "chalk";
27982
28220
 
27983
28221
  // src/shared/createConnectionAuth.ts
27984
- import chalk186 from "chalk";
28222
+ import chalk188 from "chalk";
27985
28223
  function listConnections(connections, format2) {
27986
28224
  if (connections.length === 0) {
27987
28225
  console.log("No connections configured.");
@@ -27994,7 +28232,7 @@ function listConnections(connections, format2) {
27994
28232
  function removeConnection(connections, name, save) {
27995
28233
  const filtered = connections.filter((c) => c.name !== name);
27996
28234
  if (filtered.length === connections.length) {
27997
- console.error(chalk186.red(`Connection "${name}" not found.`));
28235
+ console.error(chalk188.red(`Connection "${name}" not found.`));
27998
28236
  process.exit(1);
27999
28237
  }
28000
28238
  save(filtered);
@@ -28040,17 +28278,17 @@ function saveConnections(connections) {
28040
28278
  }
28041
28279
 
28042
28280
  // src/commands/ravendb/promptConnection.ts
28043
- import chalk189 from "chalk";
28281
+ import chalk191 from "chalk";
28044
28282
 
28045
28283
  // src/commands/ravendb/selectOpSecret.ts
28046
- import chalk188 from "chalk";
28284
+ import chalk190 from "chalk";
28047
28285
  import Enquirer2 from "enquirer";
28048
28286
 
28049
28287
  // src/commands/ravendb/searchItems.ts
28050
- import { execSync as execSync53 } from "child_process";
28051
- import chalk187 from "chalk";
28288
+ import { execSync as execSync54 } from "child_process";
28289
+ import chalk189 from "chalk";
28052
28290
  function opExec(args) {
28053
- return execSync53(`op ${args}`, {
28291
+ return execSync54(`op ${args}`, {
28054
28292
  encoding: "utf8",
28055
28293
  stdio: ["pipe", "pipe", "pipe"]
28056
28294
  }).trim();
@@ -28061,7 +28299,7 @@ function searchItems(search2) {
28061
28299
  items2 = JSON.parse(opExec("item list --format=json"));
28062
28300
  } catch {
28063
28301
  console.error(
28064
- chalk187.red(
28302
+ chalk189.red(
28065
28303
  "Failed to search 1Password. Ensure the CLI is installed and you are signed in."
28066
28304
  )
28067
28305
  );
@@ -28075,7 +28313,7 @@ function getItemFields(itemId2) {
28075
28313
  const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
28076
28314
  return item.fields.filter((f) => f.reference && f.label);
28077
28315
  } catch {
28078
- console.error(chalk187.red("Failed to get item details from 1Password."));
28316
+ console.error(chalk189.red("Failed to get item details from 1Password."));
28079
28317
  process.exit(1);
28080
28318
  }
28081
28319
  }
@@ -28094,7 +28332,7 @@ async function selectOpSecret(searchTerm) {
28094
28332
  }).run();
28095
28333
  const items2 = searchItems(search2);
28096
28334
  if (items2.length === 0) {
28097
- console.error(chalk188.red(`No items found matching "${search2}".`));
28335
+ console.error(chalk190.red(`No items found matching "${search2}".`));
28098
28336
  process.exit(1);
28099
28337
  }
28100
28338
  const itemId2 = await selectOne(
@@ -28103,7 +28341,7 @@ async function selectOpSecret(searchTerm) {
28103
28341
  );
28104
28342
  const fields = getItemFields(itemId2);
28105
28343
  if (fields.length === 0) {
28106
- console.error(chalk188.red("No fields with references found on this item."));
28344
+ console.error(chalk190.red("No fields with references found on this item."));
28107
28345
  process.exit(1);
28108
28346
  }
28109
28347
  const ref = await selectOne(
@@ -28117,7 +28355,7 @@ async function selectOpSecret(searchTerm) {
28117
28355
  async function promptConnection(existingNames) {
28118
28356
  const name = await promptInput("name", "Connection name:");
28119
28357
  if (existingNames.includes(name)) {
28120
- console.error(chalk189.red(`Connection "${name}" already exists.`));
28358
+ console.error(chalk191.red(`Connection "${name}" already exists.`));
28121
28359
  process.exit(1);
28122
28360
  }
28123
28361
  const url = await promptInput(
@@ -28126,22 +28364,22 @@ async function promptConnection(existingNames) {
28126
28364
  );
28127
28365
  const database = await promptInput("database", "Database name:");
28128
28366
  if (!name || !url || !database) {
28129
- console.error(chalk189.red("All fields are required."));
28367
+ console.error(chalk191.red("All fields are required."));
28130
28368
  process.exit(1);
28131
28369
  }
28132
28370
  const apiKeyRef = await selectOpSecret();
28133
- console.log(chalk189.dim(`Using: ${apiKeyRef}`));
28371
+ console.log(chalk191.dim(`Using: ${apiKeyRef}`));
28134
28372
  return { name, url, database, apiKeyRef };
28135
28373
  }
28136
28374
 
28137
28375
  // src/commands/ravendb/ravendbSetConnection.ts
28138
- import chalk190 from "chalk";
28376
+ import chalk192 from "chalk";
28139
28377
  function ravendbSetConnection(name) {
28140
28378
  const raw = loadGlobalConfigRaw();
28141
28379
  const ravendb = raw.ravendb ?? {};
28142
28380
  const connections = ravendb.connections ?? [];
28143
28381
  if (!connections.some((c) => c.name === name)) {
28144
- console.error(chalk190.red(`Connection "${name}" not found.`));
28382
+ console.error(chalk192.red(`Connection "${name}" not found.`));
28145
28383
  console.error(
28146
28384
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
28147
28385
  );
@@ -28157,16 +28395,16 @@ function ravendbSetConnection(name) {
28157
28395
  var ravendbAuth = createConnectionAuth({
28158
28396
  load: loadConnections,
28159
28397
  save: saveConnections,
28160
- format: (c) => `${chalk191.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
28398
+ format: (c) => `${chalk193.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
28161
28399
  promptNew: promptConnection,
28162
28400
  onFirst: (c) => ravendbSetConnection(c.name)
28163
28401
  });
28164
28402
 
28165
28403
  // src/commands/ravendb/ravendbCollections.ts
28166
- import chalk195 from "chalk";
28404
+ import chalk197 from "chalk";
28167
28405
 
28168
28406
  // src/commands/ravendb/ravenFetch.ts
28169
- import chalk193 from "chalk";
28407
+ import chalk195 from "chalk";
28170
28408
 
28171
28409
  // src/commands/ravendb/getAccessToken.ts
28172
28410
  var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
@@ -28202,21 +28440,21 @@ ${errorText}`
28202
28440
  }
28203
28441
 
28204
28442
  // src/commands/ravendb/resolveOpSecret.ts
28205
- import { execSync as execSync54 } from "child_process";
28206
- import chalk192 from "chalk";
28443
+ import { execSync as execSync55 } from "child_process";
28444
+ import chalk194 from "chalk";
28207
28445
  function resolveOpSecret(reference) {
28208
28446
  if (!reference.startsWith("op://")) {
28209
- console.error(chalk192.red(`Invalid secret reference: must start with op://`));
28447
+ console.error(chalk194.red(`Invalid secret reference: must start with op://`));
28210
28448
  process.exit(1);
28211
28449
  }
28212
28450
  try {
28213
- return execSync54(`op read "${reference}"`, {
28451
+ return execSync55(`op read "${reference}"`, {
28214
28452
  encoding: "utf8",
28215
28453
  stdio: ["pipe", "pipe", "pipe"]
28216
28454
  }).trim();
28217
28455
  } catch {
28218
28456
  console.error(
28219
- chalk192.red(
28457
+ chalk194.red(
28220
28458
  "Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
28221
28459
  )
28222
28460
  );
@@ -28243,7 +28481,7 @@ async function ravenFetch(connection, path91) {
28243
28481
  if (!response.ok) {
28244
28482
  const body = await response.text();
28245
28483
  console.error(
28246
- chalk193.red(`RavenDB error: ${response.status} ${response.statusText}`)
28484
+ chalk195.red(`RavenDB error: ${response.status} ${response.statusText}`)
28247
28485
  );
28248
28486
  console.error(body.substring(0, 500));
28249
28487
  process.exit(1);
@@ -28252,7 +28490,7 @@ async function ravenFetch(connection, path91) {
28252
28490
  }
28253
28491
 
28254
28492
  // src/commands/ravendb/resolveConnection.ts
28255
- import chalk194 from "chalk";
28493
+ import chalk196 from "chalk";
28256
28494
  function loadRavendb() {
28257
28495
  const raw = loadGlobalConfigRaw();
28258
28496
  const ravendb = raw.ravendb;
@@ -28266,7 +28504,7 @@ function resolveConnection(name) {
28266
28504
  const connectionName = name ?? defaultConnection;
28267
28505
  if (!connectionName) {
28268
28506
  console.error(
28269
- chalk194.red(
28507
+ chalk196.red(
28270
28508
  "No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
28271
28509
  )
28272
28510
  );
@@ -28274,7 +28512,7 @@ function resolveConnection(name) {
28274
28512
  }
28275
28513
  const connection = connections.find((c) => c.name === connectionName);
28276
28514
  if (!connection) {
28277
- console.error(chalk194.red(`Connection "${connectionName}" not found.`));
28515
+ console.error(chalk196.red(`Connection "${connectionName}" not found.`));
28278
28516
  console.error(
28279
28517
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
28280
28518
  );
@@ -28305,15 +28543,15 @@ async function ravendbCollections(connectionName) {
28305
28543
  return;
28306
28544
  }
28307
28545
  for (const c of collections) {
28308
- console.log(`${chalk195.bold(c.Name)} ${c.CountOfDocuments} docs`);
28546
+ console.log(`${chalk197.bold(c.Name)} ${c.CountOfDocuments} docs`);
28309
28547
  }
28310
28548
  }
28311
28549
 
28312
28550
  // src/commands/ravendb/ravendbQuery.ts
28313
- import chalk197 from "chalk";
28551
+ import chalk199 from "chalk";
28314
28552
 
28315
28553
  // src/commands/ravendb/fetchAllPages.ts
28316
- import chalk196 from "chalk";
28554
+ import chalk198 from "chalk";
28317
28555
 
28318
28556
  // src/commands/ravendb/buildQueryPath.ts
28319
28557
  function buildQueryPath(opts) {
@@ -28351,7 +28589,7 @@ async function fetchAllPages(connection, opts) {
28351
28589
  allResults.push(...results);
28352
28590
  start3 += results.length;
28353
28591
  process.stderr.write(
28354
- `\r${chalk196.dim(`Fetched ${allResults.length}/${totalResults}`)}`
28592
+ `\r${chalk198.dim(`Fetched ${allResults.length}/${totalResults}`)}`
28355
28593
  );
28356
28594
  if (start3 >= totalResults) break;
28357
28595
  if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
@@ -28366,7 +28604,7 @@ async function fetchAllPages(connection, opts) {
28366
28604
  async function ravendbQuery(connectionName, collection, options2) {
28367
28605
  const resolved = resolveArgs(connectionName, collection);
28368
28606
  if (!resolved.collection && !options2.query) {
28369
- console.error(chalk197.red("Provide a collection name or --query filter."));
28607
+ console.error(chalk199.red("Provide a collection name or --query filter."));
28370
28608
  process.exit(1);
28371
28609
  }
28372
28610
  const { collection: col } = resolved;
@@ -28405,7 +28643,7 @@ import { spawn as spawn6 } from "child_process";
28405
28643
  import * as path46 from "path";
28406
28644
 
28407
28645
  // src/commands/refactor/logViolations.ts
28408
- import chalk198 from "chalk";
28646
+ import chalk200 from "chalk";
28409
28647
  var DEFAULT_MAX_LINES2 = 100;
28410
28648
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
28411
28649
  if (violations.length === 0) {
@@ -28414,43 +28652,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
28414
28652
  }
28415
28653
  return;
28416
28654
  }
28417
- console.error(chalk198.red(`
28655
+ console.error(chalk200.red(`
28418
28656
  Refactor check failed:
28419
28657
  `));
28420
- console.error(chalk198.red(` The following files exceed ${maxLines} lines:
28658
+ console.error(chalk200.red(` The following files exceed ${maxLines} lines:
28421
28659
  `));
28422
28660
  for (const violation of violations) {
28423
- console.error(chalk198.red(` ${violation.file} (${violation.lines} lines)`));
28661
+ console.error(chalk200.red(` ${violation.file} (${violation.lines} lines)`));
28424
28662
  }
28425
28663
  console.error(
28426
- chalk198.yellow(
28664
+ chalk200.yellow(
28427
28665
  `
28428
28666
  Each file needs to be sensibly refactored, or if there is no sensible
28429
28667
  way to refactor it, ignore it with:
28430
28668
  `
28431
28669
  )
28432
28670
  );
28433
- console.error(chalk198.gray(` assist refactor ignore <file>
28671
+ console.error(chalk200.gray(` assist refactor ignore <file>
28434
28672
  `));
28435
28673
  if (process.env.CLAUDECODE) {
28436
- console.error(chalk198.cyan(`
28674
+ console.error(chalk200.cyan(`
28437
28675
  ## Extracting Code to New Files
28438
28676
  `));
28439
28677
  console.error(
28440
- chalk198.cyan(
28678
+ chalk200.cyan(
28441
28679
  ` When extracting logic from one file to another, consider where the extracted code belongs:
28442
28680
  `
28443
28681
  )
28444
28682
  );
28445
28683
  console.error(
28446
- chalk198.cyan(
28684
+ chalk200.cyan(
28447
28685
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
28448
28686
  original file's domain, create a new folder containing both the original and extracted files.
28449
28687
  `
28450
28688
  )
28451
28689
  );
28452
28690
  console.error(
28453
- chalk198.cyan(
28691
+ chalk200.cyan(
28454
28692
  ` 2. Share common utilities: If the extracted code can be reused across multiple
28455
28693
  domains, move it to a common/shared folder.
28456
28694
  `
@@ -28460,7 +28698,7 @@ Refactor check failed:
28460
28698
  }
28461
28699
 
28462
28700
  // src/commands/refactor/check/getViolations/index.ts
28463
- import { execSync as execSync55 } from "child_process";
28701
+ import { execSync as execSync56 } from "child_process";
28464
28702
  import fs31 from "fs";
28465
28703
  import { minimatch as minimatch6 } from "minimatch";
28466
28704
 
@@ -28510,7 +28748,7 @@ function getGitFiles(options2) {
28510
28748
  }
28511
28749
  const files = /* @__PURE__ */ new Set();
28512
28750
  if (options2.staged || options2.modified) {
28513
- const staged = execSync55("git diff --cached --name-only", {
28751
+ const staged = execSync56("git diff --cached --name-only", {
28514
28752
  encoding: "utf8"
28515
28753
  });
28516
28754
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -28518,7 +28756,7 @@ function getGitFiles(options2) {
28518
28756
  }
28519
28757
  }
28520
28758
  if (options2.unstaged || options2.modified) {
28521
- const unstaged = execSync55("git diff --name-only", { encoding: "utf8" });
28759
+ const unstaged = execSync56("git diff --name-only", { encoding: "utf8" });
28522
28760
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
28523
28761
  files.add(file);
28524
28762
  }
@@ -28606,7 +28844,7 @@ async function check(pattern2, options2) {
28606
28844
 
28607
28845
  // src/commands/refactor/extract/index.ts
28608
28846
  import path54 from "path";
28609
- import chalk201 from "chalk";
28847
+ import chalk203 from "chalk";
28610
28848
 
28611
28849
  // src/commands/refactor/extract/applyExtraction.ts
28612
28850
  import { SyntaxKind as SyntaxKind4 } from "ts-morph";
@@ -29205,23 +29443,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
29205
29443
 
29206
29444
  // src/commands/refactor/extract/displayPlan.ts
29207
29445
  import path50 from "path";
29208
- import chalk199 from "chalk";
29446
+ import chalk201 from "chalk";
29209
29447
  function section(title) {
29210
29448
  return `
29211
- ${chalk199.cyan(title)}`;
29449
+ ${chalk201.cyan(title)}`;
29212
29450
  }
29213
29451
  function displayImporters(plan2, cwd) {
29214
29452
  if (plan2.importersToUpdate.length === 0) return;
29215
29453
  console.log(section("Update importers:"));
29216
29454
  for (const imp of plan2.importersToUpdate) {
29217
29455
  const rel = path50.relative(cwd, imp.file.getFilePath());
29218
- console.log(` ${chalk199.dim(rel)}: \u2192 import from "${imp.relPath}"`);
29456
+ console.log(` ${chalk201.dim(rel)}: \u2192 import from "${imp.relPath}"`);
29219
29457
  }
29220
29458
  }
29221
29459
  function displayPlan(functionName, relDest, plan2, cwd) {
29222
- console.log(chalk199.bold(`Extract: ${functionName} \u2192 ${relDest}
29460
+ console.log(chalk201.bold(`Extract: ${functionName} \u2192 ${relDest}
29223
29461
  `));
29224
- console.log(` ${chalk199.cyan("Functions to move:")}`);
29462
+ console.log(` ${chalk201.cyan("Functions to move:")}`);
29225
29463
  for (const name of plan2.extractedNames) {
29226
29464
  console.log(` ${name}`);
29227
29465
  }
@@ -29255,7 +29493,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
29255
29493
 
29256
29494
  // src/commands/refactor/extract/loadProjectFile.ts
29257
29495
  import path53 from "path";
29258
- import chalk200 from "chalk";
29496
+ import chalk202 from "chalk";
29259
29497
  import { Project as Project4 } from "ts-morph";
29260
29498
 
29261
29499
  // src/commands/refactor/extract/findTsConfig.ts
@@ -29347,7 +29585,7 @@ function loadProjectFile(file) {
29347
29585
  });
29348
29586
  const sourceFile = project.getSourceFile(sourcePath);
29349
29587
  if (!sourceFile) {
29350
- console.log(chalk200.red(`File not found in project: ${file}`));
29588
+ console.log(chalk202.red(`File not found in project: ${file}`));
29351
29589
  process.exit(1);
29352
29590
  }
29353
29591
  return { project, sourceFile };
@@ -29370,19 +29608,19 @@ async function extract(file, functionName, destination, options2 = {}) {
29370
29608
  displayPlan(functionName, relDest, plan2, cwd);
29371
29609
  if (options2.apply) {
29372
29610
  await applyExtraction(functionName, sourceFile, destPath, plan2, project);
29373
- console.log(chalk201.green("\nExtraction complete"));
29611
+ console.log(chalk203.green("\nExtraction complete"));
29374
29612
  } else {
29375
- console.log(chalk201.dim("\nDry run. Use --apply to execute."));
29613
+ console.log(chalk203.dim("\nDry run. Use --apply to execute."));
29376
29614
  }
29377
29615
  }
29378
29616
 
29379
29617
  // src/commands/refactor/ignore.ts
29380
29618
  import fs34 from "fs";
29381
- import chalk202 from "chalk";
29619
+ import chalk204 from "chalk";
29382
29620
  var REFACTOR_YML_PATH2 = "refactor.yml";
29383
29621
  function ignore2(file) {
29384
29622
  if (!fs34.existsSync(file)) {
29385
- console.error(chalk202.red(`Error: File does not exist: ${file}`));
29623
+ console.error(chalk204.red(`Error: File does not exist: ${file}`));
29386
29624
  process.exit(1);
29387
29625
  }
29388
29626
  const content = fs34.readFileSync(file, "utf8");
@@ -29398,7 +29636,7 @@ function ignore2(file) {
29398
29636
  fs34.writeFileSync(REFACTOR_YML_PATH2, entry);
29399
29637
  }
29400
29638
  console.log(
29401
- chalk202.green(
29639
+ chalk204.green(
29402
29640
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
29403
29641
  )
29404
29642
  );
@@ -29407,12 +29645,12 @@ function ignore2(file) {
29407
29645
  // src/commands/refactor/rename/index.ts
29408
29646
  import fs37 from "fs";
29409
29647
  import path59 from "path";
29410
- import chalk205 from "chalk";
29648
+ import chalk207 from "chalk";
29411
29649
 
29412
29650
  // src/commands/refactor/rename/applyRename.ts
29413
29651
  import fs36 from "fs";
29414
29652
  import path56 from "path";
29415
- import chalk203 from "chalk";
29653
+ import chalk205 from "chalk";
29416
29654
 
29417
29655
  // src/commands/refactor/restructure/computeRewrites/index.ts
29418
29656
  import path55 from "path";
@@ -29517,13 +29755,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
29517
29755
  const updatedContents = applyRewrites(rewrites);
29518
29756
  for (const [file, content] of updatedContents) {
29519
29757
  fs36.writeFileSync(file, content, "utf8");
29520
- console.log(chalk203.cyan(` Updated imports in ${path56.relative(cwd, file)}`));
29758
+ console.log(chalk205.cyan(` Updated imports in ${path56.relative(cwd, file)}`));
29521
29759
  }
29522
29760
  const destDir = path56.dirname(destPath);
29523
29761
  if (!fs36.existsSync(destDir)) fs36.mkdirSync(destDir, { recursive: true });
29524
29762
  fs36.renameSync(sourcePath, destPath);
29525
29763
  console.log(
29526
- chalk203.white(
29764
+ chalk205.white(
29527
29765
  ` Moved ${path56.relative(cwd, sourcePath)} \u2192 ${path56.relative(cwd, destPath)}`
29528
29766
  )
29529
29767
  );
@@ -29610,16 +29848,16 @@ function computeRenameRewrites(sourcePath, destPath) {
29610
29848
 
29611
29849
  // src/commands/refactor/rename/printRenamePreview.ts
29612
29850
  import path58 from "path";
29613
- import chalk204 from "chalk";
29851
+ import chalk206 from "chalk";
29614
29852
  function printRenamePreview(rewrites, cwd) {
29615
29853
  for (const rewrite of rewrites) {
29616
29854
  console.log(
29617
- chalk204.dim(
29855
+ chalk206.dim(
29618
29856
  ` ${path58.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
29619
29857
  )
29620
29858
  );
29621
29859
  }
29622
- console.log(chalk204.dim("Dry run. Use --apply to execute."));
29860
+ console.log(chalk206.dim("Dry run. Use --apply to execute."));
29623
29861
  }
29624
29862
 
29625
29863
  // src/commands/refactor/rename/index.ts
@@ -29630,20 +29868,20 @@ async function rename(source, destination, options2 = {}) {
29630
29868
  const relSource = path59.relative(cwd, sourcePath);
29631
29869
  const relDest = path59.relative(cwd, destPath);
29632
29870
  if (!fs37.existsSync(sourcePath)) {
29633
- console.log(chalk205.red(`File not found: ${source}`));
29871
+ console.log(chalk207.red(`File not found: ${source}`));
29634
29872
  process.exit(1);
29635
29873
  }
29636
29874
  if (destPath !== sourcePath && fs37.existsSync(destPath)) {
29637
- console.log(chalk205.red(`Destination already exists: ${destination}`));
29875
+ console.log(chalk207.red(`Destination already exists: ${destination}`));
29638
29876
  process.exit(1);
29639
29877
  }
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..."));
29878
+ console.log(chalk207.bold(`Rename: ${relSource} \u2192 ${relDest}`));
29879
+ console.log(chalk207.dim("Loading project..."));
29880
+ console.log(chalk207.dim("Scanning imports across the project..."));
29643
29881
  const rewrites = computeRenameRewrites(sourcePath, destPath);
29644
29882
  const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
29645
29883
  console.log(
29646
- chalk205.dim(
29884
+ chalk207.dim(
29647
29885
  `${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
29648
29886
  )
29649
29887
  );
@@ -29652,11 +29890,11 @@ async function rename(source, destination, options2 = {}) {
29652
29890
  return;
29653
29891
  }
29654
29892
  applyRename(rewrites, sourcePath, destPath, cwd);
29655
- console.log(chalk205.green("Done"));
29893
+ console.log(chalk207.green("Done"));
29656
29894
  }
29657
29895
 
29658
29896
  // src/commands/refactor/renameSymbol/index.ts
29659
- import chalk206 from "chalk";
29897
+ import chalk208 from "chalk";
29660
29898
 
29661
29899
  // src/commands/refactor/renameSymbol/findSymbol.ts
29662
29900
  import { SyntaxKind as SyntaxKind15 } from "ts-morph";
@@ -29702,33 +29940,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
29702
29940
  const { project, sourceFile } = loadProjectFile(file);
29703
29941
  const symbol = findSymbol(sourceFile, oldName);
29704
29942
  if (!symbol) {
29705
- console.log(chalk206.red(`Symbol "${oldName}" not found in ${file}`));
29943
+ console.log(chalk208.red(`Symbol "${oldName}" not found in ${file}`));
29706
29944
  process.exit(1);
29707
29945
  }
29708
29946
  const grouped = groupReferences(symbol, cwd);
29709
29947
  const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
29710
29948
  console.log(
29711
- chalk206.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
29949
+ chalk208.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
29712
29950
  `)
29713
29951
  );
29714
29952
  for (const [refFile, lines2] of grouped) {
29715
29953
  console.log(
29716
- ` ${chalk206.dim(refFile)}: lines ${chalk206.cyan(lines2.join(", "))}`
29954
+ ` ${chalk208.dim(refFile)}: lines ${chalk208.cyan(lines2.join(", "))}`
29717
29955
  );
29718
29956
  }
29719
29957
  if (options2.apply) {
29720
29958
  symbol.rename(newName);
29721
29959
  await project.save();
29722
- console.log(chalk206.green(`
29960
+ console.log(chalk208.green(`
29723
29961
  Renamed ${oldName} \u2192 ${newName}`));
29724
29962
  } else {
29725
- console.log(chalk206.dim("\nDry run. Use --apply to execute."));
29963
+ console.log(chalk208.dim("\nDry run. Use --apply to execute."));
29726
29964
  }
29727
29965
  }
29728
29966
 
29729
29967
  // src/commands/refactor/restructure/index.ts
29730
29968
  import path67 from "path";
29731
- import chalk209 from "chalk";
29969
+ import chalk211 from "chalk";
29732
29970
 
29733
29971
  // src/commands/refactor/restructure/clusterDirectories.ts
29734
29972
  import path61 from "path";
@@ -29807,50 +30045,50 @@ function clusterFiles(graph) {
29807
30045
 
29808
30046
  // src/commands/refactor/restructure/displayPlan.ts
29809
30047
  import path63 from "path";
29810
- import chalk207 from "chalk";
30048
+ import chalk209 from "chalk";
29811
30049
  function relPath(filePath) {
29812
30050
  return path63.relative(process.cwd(), filePath);
29813
30051
  }
29814
30052
  function displayMoves(plan2) {
29815
30053
  if (plan2.moves.length === 0) return;
29816
- console.log(chalk207.bold("\nFile moves:"));
30054
+ console.log(chalk209.bold("\nFile moves:"));
29817
30055
  for (const move2 of plan2.moves) {
29818
30056
  console.log(
29819
- ` ${chalk207.red(relPath(move2.from))} \u2192 ${chalk207.green(relPath(move2.to))}`
30057
+ ` ${chalk209.red(relPath(move2.from))} \u2192 ${chalk209.green(relPath(move2.to))}`
29820
30058
  );
29821
- console.log(chalk207.dim(` ${move2.reason}`));
30059
+ console.log(chalk209.dim(` ${move2.reason}`));
29822
30060
  }
29823
30061
  }
29824
30062
  function displayRewrites(rewrites) {
29825
30063
  if (rewrites.length === 0) return;
29826
30064
  const affectedFiles = new Set(rewrites.map((r) => r.file));
29827
- console.log(chalk207.bold(`
30065
+ console.log(chalk209.bold(`
29828
30066
  Import rewrites (${affectedFiles.size} files):`));
29829
30067
  for (const file of affectedFiles) {
29830
- console.log(` ${chalk207.cyan(relPath(file))}:`);
30068
+ console.log(` ${chalk209.cyan(relPath(file))}:`);
29831
30069
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
29832
30070
  (r) => r.file === file
29833
30071
  )) {
29834
30072
  console.log(
29835
- ` ${chalk207.red(`"${oldSpecifier}"`)} \u2192 ${chalk207.green(`"${newSpecifier}"`)}`
30073
+ ` ${chalk209.red(`"${oldSpecifier}"`)} \u2192 ${chalk209.green(`"${newSpecifier}"`)}`
29836
30074
  );
29837
30075
  }
29838
30076
  }
29839
30077
  }
29840
30078
  function displayPlan2(plan2) {
29841
30079
  if (plan2.warnings.length > 0) {
29842
- console.log(chalk207.yellow("\nWarnings:"));
29843
- for (const w of plan2.warnings) console.log(chalk207.yellow(` ${w}`));
30080
+ console.log(chalk209.yellow("\nWarnings:"));
30081
+ for (const w of plan2.warnings) console.log(chalk209.yellow(` ${w}`));
29844
30082
  }
29845
30083
  if (plan2.newDirectories.length > 0) {
29846
- console.log(chalk207.bold("\nNew directories:"));
30084
+ console.log(chalk209.bold("\nNew directories:"));
29847
30085
  for (const dir of plan2.newDirectories)
29848
- console.log(chalk207.green(` ${dir}/`));
30086
+ console.log(chalk209.green(` ${dir}/`));
29849
30087
  }
29850
30088
  displayMoves(plan2);
29851
30089
  displayRewrites(plan2.rewrites);
29852
30090
  console.log(
29853
- chalk207.dim(
30091
+ chalk209.dim(
29854
30092
  `
29855
30093
  Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
29856
30094
  )
@@ -29860,18 +30098,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
29860
30098
  // src/commands/refactor/restructure/executePlan.ts
29861
30099
  import fs38 from "fs";
29862
30100
  import path64 from "path";
29863
- import chalk208 from "chalk";
30101
+ import chalk210 from "chalk";
29864
30102
  function executePlan(plan2) {
29865
30103
  const updatedContents = applyRewrites(plan2.rewrites);
29866
30104
  for (const [file, content] of updatedContents) {
29867
30105
  fs38.writeFileSync(file, content, "utf8");
29868
30106
  console.log(
29869
- chalk208.cyan(` Rewrote imports in ${path64.relative(process.cwd(), file)}`)
30107
+ chalk210.cyan(` Rewrote imports in ${path64.relative(process.cwd(), file)}`)
29870
30108
  );
29871
30109
  }
29872
30110
  for (const dir of plan2.newDirectories) {
29873
30111
  fs38.mkdirSync(dir, { recursive: true });
29874
- console.log(chalk208.green(` Created ${path64.relative(process.cwd(), dir)}/`));
30112
+ console.log(chalk210.green(` Created ${path64.relative(process.cwd(), dir)}/`));
29875
30113
  }
29876
30114
  for (const move2 of plan2.moves) {
29877
30115
  const targetDir = path64.dirname(move2.to);
@@ -29880,7 +30118,7 @@ function executePlan(plan2) {
29880
30118
  }
29881
30119
  fs38.renameSync(move2.from, move2.to);
29882
30120
  console.log(
29883
- chalk208.white(
30121
+ chalk210.white(
29884
30122
  ` Moved ${path64.relative(process.cwd(), move2.from)} \u2192 ${path64.relative(process.cwd(), move2.to)}`
29885
30123
  )
29886
30124
  );
@@ -29895,7 +30133,7 @@ function removeEmptyDirectories(dirs) {
29895
30133
  if (entries.length === 0) {
29896
30134
  fs38.rmdirSync(dir);
29897
30135
  console.log(
29898
- chalk208.dim(
30136
+ chalk210.dim(
29899
30137
  ` Removed empty directory ${path64.relative(process.cwd(), dir)}`
29900
30138
  )
29901
30139
  );
@@ -30028,22 +30266,22 @@ async function restructure(pattern2, options2 = {}) {
30028
30266
  const targetPattern = pattern2 ?? "src";
30029
30267
  const files = findSourceFiles2(targetPattern);
30030
30268
  if (files.length === 0) {
30031
- console.log(chalk209.yellow("No files found matching pattern"));
30269
+ console.log(chalk211.yellow("No files found matching pattern"));
30032
30270
  return;
30033
30271
  }
30034
30272
  const tsConfigPath = findTsConfig(path67.resolve(files[0]));
30035
30273
  const plan2 = buildPlan3(files, tsConfigPath);
30036
30274
  if (plan2.moves.length === 0) {
30037
- console.log(chalk209.green("No restructuring needed"));
30275
+ console.log(chalk211.green("No restructuring needed"));
30038
30276
  return;
30039
30277
  }
30040
30278
  displayPlan2(plan2);
30041
30279
  if (options2.apply) {
30042
- console.log(chalk209.bold("\nApplying changes..."));
30280
+ console.log(chalk211.bold("\nApplying changes..."));
30043
30281
  executePlan(plan2);
30044
- console.log(chalk209.green("\nRestructuring complete"));
30282
+ console.log(chalk211.green("\nRestructuring complete"));
30045
30283
  } else {
30046
- console.log(chalk209.dim("\nDry run. Use --apply to execute."));
30284
+ console.log(chalk211.dim("\nDry run. Use --apply to execute."));
30047
30285
  }
30048
30286
  }
30049
30287
 
@@ -30096,6 +30334,293 @@ async function checkoutOnlySession(number) {
30096
30334
  await done2;
30097
30335
  }
30098
30336
 
30337
+ // src/commands/review/highLevel/runHighLevelReview.ts
30338
+ import chalk213 from "chalk";
30339
+
30340
+ // src/commands/review/fetchPrDiffInfo.ts
30341
+ import { execSync as execSync57 } from "child_process";
30342
+ function getCurrentBranch3() {
30343
+ return execSync57("git rev-parse --abbrev-ref HEAD", {
30344
+ encoding: "utf8"
30345
+ }).trim();
30346
+ }
30347
+ function fetchPrDiffInfo() {
30348
+ const { org, repo } = getRepoInfo();
30349
+ const branch2 = getCurrentBranch3();
30350
+ const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
30351
+ const raw = execSync57(
30352
+ `gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
30353
+ {
30354
+ encoding: "utf8",
30355
+ stdio: ["ignore", "pipe", "pipe"]
30356
+ }
30357
+ );
30358
+ const parsed = JSON.parse(raw);
30359
+ const pr = parsed[0];
30360
+ if (!pr) {
30361
+ console.error(
30362
+ `Error: No open pull request found for branch \`${branch2}\`. Open a PR for this branch before running \`assist review\`.`
30363
+ );
30364
+ process.exit(1);
30365
+ }
30366
+ return {
30367
+ prNumber: pr.number,
30368
+ baseRef: pr.baseRefName,
30369
+ baseSha: pr.baseRefOid,
30370
+ headRef: pr.headRefName,
30371
+ headSha: pr.headRefOid
30372
+ };
30373
+ }
30374
+ function fetchPrChangedFiles(prNumber) {
30375
+ const { org, repo } = getRepoInfo();
30376
+ const out = execSync57(
30377
+ `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
30378
+ {
30379
+ encoding: "utf8",
30380
+ maxBuffer: 64 * 1024 * 1024
30381
+ }
30382
+ );
30383
+ return out.trim().split("\n").filter(Boolean);
30384
+ }
30385
+
30386
+ // src/commands/review/highLevel/checkDescriptionLinksIssue.ts
30387
+ var ISSUE_URL_PATTERN = /https?:\/\/github\.com\/[\w.-]+\/[\w.-]+\/issues\/\d+/g;
30388
+ var CROSS_REPO_PATTERN = /\b[\w.-]+\/[\w.-]+#\d+/g;
30389
+ var SAME_REPO_PATTERN2 = /(?<![\w/#-])#\d+\b/g;
30390
+ function firstMatch(body, pattern2) {
30391
+ return body.match(pattern2)?.[0] ?? null;
30392
+ }
30393
+ function checkDescriptionLinksIssue(body) {
30394
+ const reference = firstMatch(body, ISSUE_URL_PATTERN) ?? firstMatch(body, CROSS_REPO_PATTERN) ?? firstMatch(body, SAME_REPO_PATTERN2);
30395
+ if (!reference)
30396
+ return {
30397
+ status: "fail",
30398
+ reason: "no GitHub issue reference (`#123`, `owner/repo#123`, or an issue URL) in the description"
30399
+ };
30400
+ return { status: "pass", reason: `links ${reference}` };
30401
+ }
30402
+
30403
+ // src/commands/review/highLevel/checkDescriptionSections.ts
30404
+ function sectionContent(body, heading2) {
30405
+ const section2 = parsePrBody(body).find(
30406
+ (candidate) => candidate.heading.trim().toLowerCase() === heading2
30407
+ );
30408
+ return section2 ? section2.content.trim() : null;
30409
+ }
30410
+ function describe5(heading2, content) {
30411
+ if (content === null) return `no \`## ${heading2}\` section`;
30412
+ if (content === "") return `\`## ${heading2}\` is empty`;
30413
+ return null;
30414
+ }
30415
+ function checkDescriptionSections(body) {
30416
+ const problems = [
30417
+ describe5("What", sectionContent(body, "what")),
30418
+ describe5("Why", sectionContent(body, "why"))
30419
+ ].filter((problem) => problem !== null);
30420
+ if (problems.length > 0)
30421
+ return { status: "fail", reason: problems.join("; ") };
30422
+ const how = sectionContent(body, "how");
30423
+ const optional = how ? ", plus an optional `## How`" : "";
30424
+ return {
30425
+ status: "pass",
30426
+ reason: `\`## What\` and \`## Why\` are both present${optional}`
30427
+ };
30428
+ }
30429
+
30430
+ // src/commands/review/highLevel/checkDescriptionWordCap.ts
30431
+ function checkDescriptionWordCap(body, cap2) {
30432
+ const { prose, code } = countReadingWords(body);
30433
+ const words = prose + code;
30434
+ if (words > cap2)
30435
+ return {
30436
+ status: "fail",
30437
+ reason: `${words} words, ${words - cap2} over the ${cap2}-word cap`
30438
+ };
30439
+ return { status: "pass", reason: `${words} of ${cap2} words` };
30440
+ }
30441
+
30442
+ // src/commands/review/highLevel/checkUiEvidence.ts
30443
+ import { minimatch as minimatch7 } from "minimatch";
30444
+ var EVIDENCE_PATTERNS = [
30445
+ /!\[[^\]]*\]\([^)]+\)/g,
30446
+ /<(?:img|video)\b[^>]*>/gi,
30447
+ /https?:\/\/github\.com\/user-attachments\/assets\/\S+/g,
30448
+ /https?:\/\/\S+\.(?:png|jpe?g|gif|webp|avif|svg|mp4|mov|webm)\b/gi
30449
+ ];
30450
+ function countEvidence(body) {
30451
+ return EVIDENCE_PATTERNS.reduce(
30452
+ (total, pattern2) => total + (body.match(pattern2)?.length ?? 0),
30453
+ 0
30454
+ );
30455
+ }
30456
+ function plural(count8, noun) {
30457
+ return `${count8} ${noun}${count8 === 1 ? "" : "s"}`;
30458
+ }
30459
+ function checkUiEvidence(body, changedFiles2, uiPaths) {
30460
+ if (uiPaths.length === 0)
30461
+ return {
30462
+ status: "pass",
30463
+ reason: "review.highLevel.uiPaths is unset, so no UI evidence is required"
30464
+ };
30465
+ const touched = changedFiles2.filter(
30466
+ (file) => uiPaths.some((glob) => minimatch7(file, glob))
30467
+ );
30468
+ if (touched.length === 0)
30469
+ return {
30470
+ status: "pass",
30471
+ reason: "no changed file matches review.highLevel.uiPaths"
30472
+ };
30473
+ const evidence = countEvidence(body);
30474
+ if (evidence === 0)
30475
+ return {
30476
+ status: "fail",
30477
+ reason: `${plural(touched.length, "UI file")} changed (${touched[0]}) but no screenshot or video in the description`
30478
+ };
30479
+ const shown = evidence === 1 ? "1 screenshot or video" : `${evidence} screenshots or videos`;
30480
+ return {
30481
+ status: "pass",
30482
+ reason: `${shown} for ${plural(touched.length, "changed UI file")}`
30483
+ };
30484
+ }
30485
+
30486
+ // src/commands/review/highLevel/highLevelChecklist.ts
30487
+ var highLevelChecklist = [
30488
+ {
30489
+ id: "description-what-why",
30490
+ kind: "deterministic",
30491
+ title: "Description has a What and a Why",
30492
+ backing: "The PR body's `## What` and `## Why` sections"
30493
+ },
30494
+ {
30495
+ id: "description-word-cap",
30496
+ kind: "deterministic",
30497
+ title: "Description is under the word cap",
30498
+ backing: "The PR body's word count against review.highLevel.descriptionWordCap"
30499
+ },
30500
+ {
30501
+ id: "description-links-issue",
30502
+ kind: "deterministic",
30503
+ title: "Description links the GitHub issue the PR resolves",
30504
+ backing: "GitHub issue references in the PR body"
30505
+ },
30506
+ {
30507
+ id: "ui-evidence",
30508
+ kind: "deterministic",
30509
+ title: "UI changes are evidenced by a screenshot or video",
30510
+ backing: "Images and videos in the PR body, when a changed file matches review.highLevel.uiPaths"
30511
+ },
30512
+ {
30513
+ id: "structure-sensible",
30514
+ kind: "manual",
30515
+ title: "The structure of the change is sensible",
30516
+ backing: "The changed-file tree with add/delete/modify counts and per-file GitHub diff links"
30517
+ },
30518
+ {
30519
+ id: "critical-diffs-correct",
30520
+ kind: "manual",
30521
+ title: "The critical-file diffs are correct",
30522
+ backing: "Full diffs of files matching review.highLevel.criticalPaths"
30523
+ },
30524
+ {
30525
+ id: "backend-pr-linked",
30526
+ kind: "manual",
30527
+ title: "The backend PR is linked, if the change needs backend work",
30528
+ backing: "The PR body"
30529
+ }
30530
+ ];
30531
+
30532
+ // src/commands/review/highLevel/evaluateHighLevelChecks.ts
30533
+ var evaluators = {
30534
+ "description-what-why": (subject) => checkDescriptionSections(subject.body),
30535
+ "description-word-cap": (subject) => checkDescriptionWordCap(subject.body, subject.config.descriptionWordCap),
30536
+ "description-links-issue": (subject) => checkDescriptionLinksIssue(subject.body),
30537
+ "ui-evidence": (subject) => checkUiEvidence(subject.body, subject.changedFiles, subject.config.uiPaths)
30538
+ };
30539
+ function evaluateHighLevelChecks(subject) {
30540
+ return highLevelChecklist.map((check2) => {
30541
+ if (check2.kind === "manual")
30542
+ return { ...check2, status: "manual", reason: check2.backing };
30543
+ return { ...check2, ...evaluators[check2.id](subject) };
30544
+ });
30545
+ }
30546
+
30547
+ // src/commands/review/highLevel/formatHighLevelChecklist.ts
30548
+ import chalk212 from "chalk";
30549
+ var MARKERS = {
30550
+ pass: () => chalk212.green("\u2714"),
30551
+ fail: () => chalk212.red("\u2718"),
30552
+ manual: () => chalk212.yellow("\u25A1")
30553
+ };
30554
+ function formatCheck(check2) {
30555
+ const title = check2.status === "fail" ? chalk212.red(check2.title) : chalk212.bold(check2.title);
30556
+ return ` ${MARKERS[check2.status]()} ${title}
30557
+ ${chalk212.dim(check2.reason)}`;
30558
+ }
30559
+ function formatGroup(heading2, checks2) {
30560
+ if (checks2.length === 0) return [];
30561
+ return ["", chalk212.bold.underline(heading2), ...checks2.map(formatCheck)];
30562
+ }
30563
+ function formatHighLevelChecklist(checks2) {
30564
+ const deterministic = checks2.filter(
30565
+ (check2) => check2.kind === "deterministic"
30566
+ );
30567
+ const failed2 = deterministic.filter(
30568
+ (check2) => check2.status === "fail"
30569
+ ).length;
30570
+ const summary = failed2 === 0 ? chalk212.green(`All ${deterministic.length} deterministic checks pass`) : chalk212.red(
30571
+ `${failed2} of ${deterministic.length} deterministic checks fail`
30572
+ );
30573
+ return [
30574
+ ...formatGroup("Deterministic", deterministic),
30575
+ ...formatGroup(
30576
+ "Manual",
30577
+ checks2.filter((check2) => check2.kind === "manual")
30578
+ ),
30579
+ "",
30580
+ summary
30581
+ ].join("\n");
30582
+ }
30583
+
30584
+ // src/commands/review/highLevel/resolveHighLevelConfig.ts
30585
+ var DEFAULT_DESCRIPTION_WORD_CAP = 300;
30586
+ function resolveHighLevelConfig(config) {
30587
+ const highLevel = config.review?.highLevel;
30588
+ return {
30589
+ criticalPaths: highLevel?.criticalPaths ?? [],
30590
+ uiPaths: highLevel?.uiPaths ?? [],
30591
+ descriptionWordCap: highLevel?.descriptionWordCap ?? DEFAULT_DESCRIPTION_WORD_CAP
30592
+ };
30593
+ }
30594
+
30595
+ // src/commands/review/highLevel/runHighLevelReview.ts
30596
+ function resolvePrNumber2(number) {
30597
+ if (number === void 0) return getCurrentPrNumber();
30598
+ const parsed = Number(number);
30599
+ if (!Number.isInteger(parsed) || parsed <= 0) {
30600
+ console.error(`Error: \`${number}\` is not a pull request number.`);
30601
+ process.exit(1);
30602
+ }
30603
+ return parsed;
30604
+ }
30605
+ function runHighLevelReview(number) {
30606
+ const prNumber = resolvePrNumber2(number);
30607
+ const { org, repo } = getRepoInfo();
30608
+ const config = resolveHighLevelConfig(loadConfig());
30609
+ const body = fetchPrBody(prNumber, { org, repo });
30610
+ const changedFiles2 = fetchPrChangedFiles(prNumber);
30611
+ const checks2 = evaluateHighLevelChecks({ body, changedFiles: changedFiles2, config });
30612
+ console.log(
30613
+ chalk213.bold(`High-level review of ${org}/${repo}#${prNumber}`),
30614
+ chalk213.dim(`\xB7 ${changedFiles2.length} changed files`)
30615
+ );
30616
+ console.log(formatHighLevelChecklist(checks2));
30617
+ console.log(
30618
+ chalk213.dim(
30619
+ "\nManual items are for the reviewer to judge; see docs/high-level-review.md."
30620
+ )
30621
+ );
30622
+ }
30623
+
30099
30624
  // src/commands/review/annotateDiffWithLineNumbers.ts
30100
30625
  var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
30101
30626
  var HUNK_HEADER2 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
@@ -30229,9 +30754,9 @@ function buildReviewPaths(repoRoot2, key) {
30229
30754
  }
30230
30755
 
30231
30756
  // src/commands/review/fetchExistingComments.ts
30232
- import { execSync as execSync56 } from "child_process";
30757
+ import { execSync as execSync58 } from "child_process";
30233
30758
  function fetchRawComments(org, repo, prNumber) {
30234
- const out = execSync56(
30759
+ const out = execSync58(
30235
30760
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
30236
30761
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
30237
30762
  );
@@ -30262,14 +30787,14 @@ function fetchExistingComments() {
30262
30787
  }
30263
30788
 
30264
30789
  // src/commands/review/gatherContext.ts
30265
- import { execSync as execSync59 } from "child_process";
30790
+ import { execSync as execSync60 } from "child_process";
30266
30791
 
30267
30792
  // src/commands/review/fetchPrDiff.ts
30268
- import { execSync as execSync57 } from "child_process";
30793
+ import { execSync as execSync59 } from "child_process";
30269
30794
  function fetchPrDiff(prNumber, baseSha, headSha) {
30270
30795
  const { org, repo } = getRepoInfo();
30271
30796
  try {
30272
- return execSync57(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
30797
+ return execSync59(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
30273
30798
  encoding: "utf8",
30274
30799
  maxBuffer: 256 * 1024 * 1024,
30275
30800
  stdio: ["ignore", "pipe", "pipe"]
@@ -30284,68 +30809,22 @@ function isDiffTooLarge(error) {
30284
30809
  }
30285
30810
  function fetchDiffViaGit(baseSha, headSha) {
30286
30811
  try {
30287
- execSync57(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
30812
+ execSync59(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
30288
30813
  } catch {
30289
30814
  }
30290
- return execSync57(`git diff ${baseSha}...${headSha}`, {
30815
+ return execSync59(`git diff ${baseSha}...${headSha}`, {
30291
30816
  encoding: "utf8",
30292
30817
  maxBuffer: 256 * 1024 * 1024
30293
30818
  });
30294
30819
  }
30295
30820
 
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
30821
  // src/commands/review/gatherContext.ts
30343
30822
  function gatherContext() {
30344
- const branch2 = execSync59("git rev-parse --abbrev-ref HEAD", {
30823
+ const branch2 = execSync60("git rev-parse --abbrev-ref HEAD", {
30345
30824
  encoding: "utf8"
30346
30825
  }).trim();
30347
- const sha = execSync59("git rev-parse HEAD", { encoding: "utf8" }).trim();
30348
- const shortSha = execSync59("git rev-parse --short=7 HEAD", {
30826
+ const sha = execSync60("git rev-parse HEAD", { encoding: "utf8" }).trim();
30827
+ const shortSha = execSync60("git rev-parse --short=7 HEAD", {
30349
30828
  encoding: "utf8"
30350
30829
  }).trim();
30351
30830
  const prInfo = fetchPrDiffInfo();
@@ -30704,18 +31183,18 @@ function partitionFindingsByDiff(findings, index3) {
30704
31183
  }
30705
31184
 
30706
31185
  // src/commands/review/warnOutOfDiff.ts
30707
- import chalk210 from "chalk";
31186
+ import chalk214 from "chalk";
30708
31187
  function warnOutOfDiff(outOfDiff) {
30709
31188
  if (outOfDiff.length === 0) return;
30710
31189
  console.warn(
30711
- chalk210.yellow(
31190
+ chalk214.yellow(
30712
31191
  `Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
30713
31192
  )
30714
31193
  );
30715
31194
  for (const finding of outOfDiff) {
30716
31195
  const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
30717
31196
  console.warn(
30718
- ` ${chalk210.yellow("\xB7")} ${finding.title} ${chalk210.dim(
31197
+ ` ${chalk214.yellow("\xB7")} ${finding.title} ${chalk214.dim(
30719
31198
  `(${finding.file}:${range})`
30720
31199
  )}`
30721
31200
  );
@@ -30739,18 +31218,18 @@ function selectInDiffFindings(lineBound, prDiff) {
30739
31218
  }
30740
31219
 
30741
31220
  // src/commands/review/warnUnlocated.ts
30742
- import chalk211 from "chalk";
31221
+ import chalk215 from "chalk";
30743
31222
  function warnUnlocated(unlocated) {
30744
31223
  if (unlocated.length === 0) return;
30745
31224
  console.warn(
30746
- chalk211.yellow(
31225
+ chalk215.yellow(
30747
31226
  `Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
30748
31227
  )
30749
31228
  );
30750
31229
  for (const finding of unlocated) {
30751
- const where = finding.location || chalk211.dim("missing");
31230
+ const where = finding.location || chalk215.dim("missing");
30752
31231
  console.warn(
30753
- ` ${chalk211.yellow("\xB7")} ${finding.title} ${chalk211.dim(`(${where})`)}`
31232
+ ` ${chalk215.yellow("\xB7")} ${finding.title} ${chalk215.dim(`(${where})`)}`
30754
31233
  );
30755
31234
  }
30756
31235
  }
@@ -31340,9 +31819,9 @@ import { writeFileSync as writeFileSync39 } from "fs";
31340
31819
  // src/commands/review/finaliseReviewerSpinner.ts
31341
31820
  var SUMMARY_MAX_LEN = 80;
31342
31821
  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();
31822
+ const firstLine3 = stderr.split(/\r?\n/).find((l) => l.trim().length > 0);
31823
+ if (!firstLine3) return "";
31824
+ const trimmed = firstLine3.trim();
31346
31825
  return trimmed.length > SUMMARY_MAX_LEN ? `${trimmed.slice(0, SUMMARY_MAX_LEN - 1)}\u2026` : trimmed;
31347
31826
  }
31348
31827
  function finaliseReviewerSpinner(spinner, outcome) {
@@ -32050,14 +32529,8 @@ async function reviewPr(repoRoot2, options2) {
32050
32529
  console.log(`Done. Review folder: ${paths.reviewDir}`);
32051
32530
  }
32052
32531
 
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) {
32532
+ // src/commands/review/validateReviewOptions.ts
32533
+ function validateReviewOptions(options2) {
32061
32534
  if (options2.apply && options2.refine) {
32062
32535
  console.error("Error: --apply cannot be combined with --refine.");
32063
32536
  process.exit(1);
@@ -32069,6 +32542,7 @@ function validateOptions(options2) {
32069
32542
  process.exit(1);
32070
32543
  }
32071
32544
  validateCheckoutOnly(options2);
32545
+ validateHighLevel(options2);
32072
32546
  }
32073
32547
  function validateCheckoutOnly(options2) {
32074
32548
  if (!options2.checkoutOnly) return;
@@ -32083,13 +32557,31 @@ function validateCheckoutOnly(options2) {
32083
32557
  process.exit(1);
32084
32558
  }
32085
32559
  }
32560
+ function validateHighLevel(options2) {
32561
+ if (!options2.highLevel) return;
32562
+ if (options2.refine || options2.apply || options2.backlog || options2.submit || options2.checkoutOnly) {
32563
+ console.error(
32564
+ "Error: --high-level cannot be combined with --refine, --apply, --backlog, --submit or --checkout-only."
32565
+ );
32566
+ process.exit(1);
32567
+ }
32568
+ }
32569
+
32570
+ // src/commands/review/review.ts
32571
+ function resolveRepoRoot() {
32572
+ const repoRoot2 = findRepoRoot(process.cwd());
32573
+ if (repoRoot2) return repoRoot2;
32574
+ console.error("Error: not inside a git repository.");
32575
+ process.exit(1);
32576
+ }
32086
32577
  async function review(options2 = {}) {
32087
- validateOptions(options2);
32578
+ validateReviewOptions(options2);
32088
32579
  startReviewLog();
32089
32580
  const invokedIn = resolveRepoRoot();
32090
32581
  if (options2.checkoutOnly && options2.number)
32091
32582
  return checkoutOnlySession(options2.number);
32092
32583
  emitActivity({ kind: "command", name: "review" });
32584
+ if (options2.highLevel) return runHighLevelReview(options2.number);
32093
32585
  if (!options2.number) return reviewPr(invokedIn, options2);
32094
32586
  await checkoutPr(options2.number);
32095
32587
  return reviewPr(resolveRepoRoot(), options2);
@@ -32123,6 +32615,9 @@ function registerReview(program2) {
32123
32615
  ).option(
32124
32616
  "--checkout-only",
32125
32617
  "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"
32618
+ ).option(
32619
+ "--high-level",
32620
+ "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
32621
  ).option(
32127
32622
  "--address-comments",
32128
32623
  "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 +32640,7 @@ function registerReview(program2) {
32145
32640
  // src/commands/rules/addRule.ts
32146
32641
  import { existsSync as existsSync68, readFileSync as readFileSync52, writeFileSync as writeFileSync41 } from "fs";
32147
32642
  import path72 from "path";
32148
- import chalk212 from "chalk";
32643
+ import chalk216 from "chalk";
32149
32644
 
32150
32645
  // src/commands/rules/insertRuleBullet.ts
32151
32646
  function ruleBullet({ code, title, text: text18 }) {
@@ -32281,7 +32776,7 @@ function read2(file) {
32281
32776
  function addRule(text18, options2) {
32282
32777
  const rule = text18.trim();
32283
32778
  if (rule === "") {
32284
- console.error(chalk212.red("Rule text is required"));
32779
+ console.error(chalk216.red("Rule text is required"));
32285
32780
  process.exitCode = 1;
32286
32781
  return;
32287
32782
  }
@@ -32299,13 +32794,13 @@ function addRule(text18, options2) {
32299
32794
  );
32300
32795
  updateScopedRulesIndex(root);
32301
32796
  console.log(
32302
- `Added ${chalk212.cyan(code)} to ${path72.relative(process.cwd(), target) || target}`
32797
+ `Added ${chalk216.cyan(code)} to ${path72.relative(process.cwd(), target) || target}`
32303
32798
  );
32304
32799
  }
32305
32800
 
32306
32801
  // src/commands/rules/indexRules.ts
32307
32802
  import path73 from "path";
32308
- import chalk213 from "chalk";
32803
+ import chalk217 from "chalk";
32309
32804
  function indexRules() {
32310
32805
  const startDir = scopeDirectory(process.cwd());
32311
32806
  const root = findRepoRoot(startDir) ?? startDir;
@@ -32313,24 +32808,24 @@ function indexRules() {
32313
32808
  const rootFile = path73.relative(process.cwd(), path73.join(root, "CLAUDE.md"));
32314
32809
  if (directories.length === 0) {
32315
32810
  console.log(
32316
- chalk213.gray(`No directories carry their own \`## Rules\` under ${root}`)
32811
+ chalk217.gray(`No directories carry their own \`## Rules\` under ${root}`)
32317
32812
  );
32318
32813
  return;
32319
32814
  }
32320
32815
  console.log(`Recorded in ${rootFile || "CLAUDE.md"}`);
32321
32816
  for (const directory of directories)
32322
- console.log(` ${chalk213.cyan(directory)}`);
32817
+ console.log(` ${chalk217.cyan(directory)}`);
32323
32818
  }
32324
32819
 
32325
32820
  // src/commands/rules/listRules.ts
32326
32821
  import path74 from "path";
32327
- import chalk214 from "chalk";
32822
+ import chalk218 from "chalk";
32328
32823
  function listRules(target, options2 = {}) {
32329
32824
  const resolved = path74.resolve(target ?? process.cwd());
32330
32825
  const rules3 = readScopedRules(resolved);
32331
32826
  if (rules3.length === 0) {
32332
32827
  const label2 = path74.relative(process.cwd(), resolved) || ".";
32333
- console.log(chalk214.gray(`No rules in scope for ${label2}`));
32828
+ console.log(chalk218.gray(`No rules in scope for ${label2}`));
32334
32829
  return;
32335
32830
  }
32336
32831
  const base = findRepoRoot(scopeDirectory(resolved));
@@ -32340,14 +32835,14 @@ function listRules(target, options2 = {}) {
32340
32835
  if (rule.source !== shown) {
32341
32836
  shown = rule.source;
32342
32837
  console.log(
32343
- chalk214.dim(base ? path74.relative(base, rule.source) : rule.source)
32838
+ chalk218.dim(base ? path74.relative(base, rule.source) : rule.source)
32344
32839
  );
32345
32840
  }
32346
32841
  console.log(
32347
- ` ${chalk214.cyan(rule.code.padEnd(width))} ${rule.title ?? rule.text}`
32842
+ ` ${chalk218.cyan(rule.code.padEnd(width))} ${rule.title ?? rule.text}`
32348
32843
  );
32349
32844
  if (options2.full && rule.title)
32350
- console.log(` ${" ".repeat(width)} ${chalk214.dim(rule.text)}`);
32845
+ console.log(` ${" ".repeat(width)} ${chalk218.dim(rule.text)}`);
32351
32846
  }
32352
32847
  }
32353
32848
 
@@ -32376,7 +32871,7 @@ function registerRules(program2) {
32376
32871
  }
32377
32872
 
32378
32873
  // src/commands/seq/seqAuth.ts
32379
- import chalk216 from "chalk";
32874
+ import chalk220 from "chalk";
32380
32875
 
32381
32876
  // src/commands/seq/loadConnections.ts
32382
32877
  function loadConnections2() {
@@ -32405,10 +32900,10 @@ function setDefaultConnection(name) {
32405
32900
  }
32406
32901
 
32407
32902
  // src/shared/assertUniqueName.ts
32408
- import chalk215 from "chalk";
32903
+ import chalk219 from "chalk";
32409
32904
  function assertUniqueName(existingNames, name) {
32410
32905
  if (existingNames.includes(name)) {
32411
- console.error(chalk215.red(`Connection "${name}" already exists.`));
32906
+ console.error(chalk219.red(`Connection "${name}" already exists.`));
32412
32907
  process.exit(1);
32413
32908
  }
32414
32909
  }
@@ -32426,16 +32921,16 @@ async function promptConnection2(existingNames) {
32426
32921
  var seqAuth = createConnectionAuth({
32427
32922
  load: loadConnections2,
32428
32923
  save: saveConnections2,
32429
- format: (c) => `${chalk216.bold(c.name)} ${c.url}`,
32924
+ format: (c) => `${chalk220.bold(c.name)} ${c.url}`,
32430
32925
  promptNew: promptConnection2,
32431
32926
  onFirst: (c) => setDefaultConnection(c.name)
32432
32927
  });
32433
32928
 
32434
32929
  // src/commands/seq/seqQuery.ts
32435
- import chalk220 from "chalk";
32930
+ import chalk224 from "chalk";
32436
32931
 
32437
32932
  // src/commands/seq/fetchSeq.ts
32438
- import chalk217 from "chalk";
32933
+ import chalk221 from "chalk";
32439
32934
  async function fetchSeq(conn, path91, params) {
32440
32935
  const url = `${conn.url}${path91}?${params}`;
32441
32936
  const response = await fetch(url, {
@@ -32446,7 +32941,7 @@ async function fetchSeq(conn, path91, params) {
32446
32941
  });
32447
32942
  if (!response.ok) {
32448
32943
  const body = await response.text();
32449
- console.error(chalk217.red(`Seq returned ${response.status}: ${body}`));
32944
+ console.error(chalk221.red(`Seq returned ${response.status}: ${body}`));
32450
32945
  process.exit(1);
32451
32946
  }
32452
32947
  return response;
@@ -32505,23 +33000,23 @@ async function fetchSeqEvents(conn, params) {
32505
33000
  }
32506
33001
 
32507
33002
  // src/commands/seq/formatEvent.ts
32508
- import chalk218 from "chalk";
33003
+ import chalk222 from "chalk";
32509
33004
  function levelColor(level) {
32510
33005
  switch (level) {
32511
33006
  case "Fatal":
32512
- return chalk218.bgRed.white;
33007
+ return chalk222.bgRed.white;
32513
33008
  case "Error":
32514
- return chalk218.red;
33009
+ return chalk222.red;
32515
33010
  case "Warning":
32516
- return chalk218.yellow;
33011
+ return chalk222.yellow;
32517
33012
  case "Information":
32518
- return chalk218.cyan;
33013
+ return chalk222.cyan;
32519
33014
  case "Debug":
32520
- return chalk218.gray;
33015
+ return chalk222.gray;
32521
33016
  case "Verbose":
32522
- return chalk218.dim;
33017
+ return chalk222.dim;
32523
33018
  default:
32524
- return chalk218.white;
33019
+ return chalk222.white;
32525
33020
  }
32526
33021
  }
32527
33022
  function levelAbbrev(level) {
@@ -32562,12 +33057,12 @@ function formatTimestamp(iso) {
32562
33057
  function formatEvent(event) {
32563
33058
  const color = levelColor(event.Level);
32564
33059
  const abbrev = levelAbbrev(event.Level);
32565
- const ts8 = chalk218.dim(formatTimestamp(event.Timestamp));
33060
+ const ts8 = chalk222.dim(formatTimestamp(event.Timestamp));
32566
33061
  const msg = renderMessage(event);
32567
33062
  const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
32568
33063
  if (event.Exception) {
32569
33064
  for (const line of event.Exception.split("\n")) {
32570
- lines2.push(chalk218.red(` ${line}`));
33065
+ lines2.push(chalk222.red(` ${line}`));
32571
33066
  }
32572
33067
  }
32573
33068
  return lines2.join("\n");
@@ -32600,11 +33095,11 @@ function rejectTimestampFilter(filter) {
32600
33095
  }
32601
33096
 
32602
33097
  // src/shared/resolveNamedConnection.ts
32603
- import chalk219 from "chalk";
33098
+ import chalk223 from "chalk";
32604
33099
  function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
32605
33100
  if (connections.length === 0) {
32606
33101
  console.error(
32607
- chalk219.red(
33102
+ chalk223.red(
32608
33103
  `No ${kind} connections configured. Run '${authCommand}' first.`
32609
33104
  )
32610
33105
  );
@@ -32613,7 +33108,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
32613
33108
  const target = requested ?? defaultName ?? connections[0].name;
32614
33109
  const connection = connections.find((c) => c.name === target);
32615
33110
  if (!connection) {
32616
- console.error(chalk219.red(`${kind} connection "${target}" not found.`));
33111
+ console.error(chalk223.red(`${kind} connection "${target}" not found.`));
32617
33112
  process.exit(1);
32618
33113
  }
32619
33114
  return connection;
@@ -32642,7 +33137,7 @@ async function seqQuery(filter, options2) {
32642
33137
  new URLSearchParams({ filter, count: String(count8) })
32643
33138
  );
32644
33139
  if (events.length === 0) {
32645
- console.log(chalk220.yellow("No events found."));
33140
+ console.log(chalk224.yellow("No events found."));
32646
33141
  return;
32647
33142
  }
32648
33143
  if (options2.json) {
@@ -32653,11 +33148,11 @@ async function seqQuery(filter, options2) {
32653
33148
  for (const event of chronological) {
32654
33149
  console.log(formatEvent(event));
32655
33150
  }
32656
- console.log(chalk220.dim(`
33151
+ console.log(chalk224.dim(`
32657
33152
  ${events.length} events`));
32658
33153
  if (events.length >= count8) {
32659
33154
  console.log(
32660
- chalk220.yellow(
33155
+ chalk224.yellow(
32661
33156
  `Results limited to ${count8}. Use --count to retrieve more.`
32662
33157
  )
32663
33158
  );
@@ -32665,10 +33160,10 @@ ${events.length} events`));
32665
33160
  }
32666
33161
 
32667
33162
  // src/shared/setNamedDefaultConnection.ts
32668
- import chalk221 from "chalk";
33163
+ import chalk225 from "chalk";
32669
33164
  function setNamedDefaultConnection(connections, name, setDefault, kind) {
32670
33165
  if (!connections.find((c) => c.name === name)) {
32671
- console.error(chalk221.red(`Connection "${name}" not found.`));
33166
+ console.error(chalk225.red(`Connection "${name}" not found.`));
32672
33167
  process.exit(1);
32673
33168
  }
32674
33169
  setDefault(name);
@@ -32817,7 +33312,7 @@ function registerSlack(program2) {
32817
33312
  }
32818
33313
 
32819
33314
  // src/commands/sql/sqlAuth.ts
32820
- import chalk223 from "chalk";
33315
+ import chalk227 from "chalk";
32821
33316
 
32822
33317
  // src/commands/sql/loadConnections.ts
32823
33318
  function loadConnections3() {
@@ -32846,7 +33341,7 @@ function setDefaultConnection2(name) {
32846
33341
  }
32847
33342
 
32848
33343
  // src/commands/sql/promptConnection.ts
32849
- import chalk222 from "chalk";
33344
+ import chalk226 from "chalk";
32850
33345
  async function promptConnection3(existingNames) {
32851
33346
  const name = await promptInput("name", "Connection name:", "default");
32852
33347
  assertUniqueName(existingNames, name);
@@ -32854,7 +33349,7 @@ async function promptConnection3(existingNames) {
32854
33349
  const portStr = await promptInput("port", "Port:", "1433");
32855
33350
  const port = Number.parseInt(portStr, 10);
32856
33351
  if (!Number.isFinite(port)) {
32857
- console.error(chalk222.red(`Invalid port "${portStr}".`));
33352
+ console.error(chalk226.red(`Invalid port "${portStr}".`));
32858
33353
  process.exit(1);
32859
33354
  }
32860
33355
  const user = await promptInput("user", "User:");
@@ -32867,13 +33362,13 @@ async function promptConnection3(existingNames) {
32867
33362
  var sqlAuth = createConnectionAuth({
32868
33363
  load: loadConnections3,
32869
33364
  save: saveConnections3,
32870
- format: (c) => `${chalk223.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
33365
+ format: (c) => `${chalk227.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
32871
33366
  promptNew: promptConnection3,
32872
33367
  onFirst: (c) => setDefaultConnection2(c.name)
32873
33368
  });
32874
33369
 
32875
33370
  // src/commands/sql/printTable.ts
32876
- import chalk224 from "chalk";
33371
+ import chalk228 from "chalk";
32877
33372
  function formatCell(value) {
32878
33373
  if (value === null || value === void 0) return "";
32879
33374
  if (value instanceof Date) return value.toISOString();
@@ -32882,7 +33377,7 @@ function formatCell(value) {
32882
33377
  }
32883
33378
  function printTable(rows) {
32884
33379
  if (rows.length === 0) {
32885
- console.log(chalk224.yellow("(no rows)"));
33380
+ console.log(chalk228.yellow("(no rows)"));
32886
33381
  return;
32887
33382
  }
32888
33383
  const columns = Object.keys(rows[0]);
@@ -32890,13 +33385,13 @@ function printTable(rows) {
32890
33385
  (col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
32891
33386
  );
32892
33387
  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)));
33388
+ console.log(chalk228.dim(header));
33389
+ console.log(chalk228.dim("-".repeat(header.length)));
32895
33390
  for (const row of rows) {
32896
33391
  const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
32897
33392
  console.log(line);
32898
33393
  }
32899
- console.log(chalk224.dim(`
33394
+ console.log(chalk228.dim(`
32900
33395
  ${rows.length} row${rows.length === 1 ? "" : "s"}`));
32901
33396
  }
32902
33397
 
@@ -32956,7 +33451,7 @@ async function sqlColumns(table, connectionName) {
32956
33451
  }
32957
33452
 
32958
33453
  // src/commands/sql/sqlMutate.ts
32959
- import chalk225 from "chalk";
33454
+ import chalk229 from "chalk";
32960
33455
 
32961
33456
  // src/commands/sql/isMutation.ts
32962
33457
  var MUTATION_KEYWORDS = [
@@ -32990,7 +33485,7 @@ function isMutation(sql29) {
32990
33485
  async function sqlMutate(query, connectionName) {
32991
33486
  if (!isMutation(query)) {
32992
33487
  console.error(
32993
- chalk225.red(
33488
+ chalk229.red(
32994
33489
  "assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
32995
33490
  )
32996
33491
  );
@@ -33000,18 +33495,18 @@ async function sqlMutate(query, connectionName) {
33000
33495
  const pool = await sqlConnect(conn);
33001
33496
  try {
33002
33497
  const result = await pool.request().query(query);
33003
- console.log(chalk225.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
33498
+ console.log(chalk229.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
33004
33499
  } finally {
33005
33500
  await pool.close();
33006
33501
  }
33007
33502
  }
33008
33503
 
33009
33504
  // src/commands/sql/sqlQuery.ts
33010
- import chalk226 from "chalk";
33505
+ import chalk230 from "chalk";
33011
33506
  async function sqlQuery(query, connectionName) {
33012
33507
  if (isMutation(query)) {
33013
33508
  console.error(
33014
- chalk226.red(
33509
+ chalk230.red(
33015
33510
  "assist sql query refuses mutating statements. Use `assist sql mutate` instead."
33016
33511
  )
33017
33512
  );
@@ -33026,7 +33521,7 @@ async function sqlQuery(query, connectionName) {
33026
33521
  printTable(rows);
33027
33522
  } else {
33028
33523
  console.log(
33029
- chalk226.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
33524
+ chalk230.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
33030
33525
  );
33031
33526
  }
33032
33527
  } finally {
@@ -33400,7 +33895,7 @@ function syncPi(claudeDir, options2) {
33400
33895
  // src/commands/sync/syncSettings.ts
33401
33896
  import * as fs48 from "fs";
33402
33897
  import * as path84 from "path";
33403
- import chalk227 from "chalk";
33898
+ import chalk231 from "chalk";
33404
33899
  async function syncSettings(claudeDir, targetBase, options2) {
33405
33900
  const source = path84.join(claudeDir, "settings.json");
33406
33901
  const target = path84.join(targetBase, "settings.json");
@@ -33419,7 +33914,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
33419
33914
  if (mergedContent !== normalizedTarget) {
33420
33915
  if (!options2?.yes) {
33421
33916
  console.log(
33422
- chalk227.yellow(
33917
+ chalk231.yellow(
33423
33918
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
33424
33919
  )
33425
33920
  );
@@ -33427,7 +33922,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
33427
33922
  printDiff(targetContent, mergedContent);
33428
33923
  printAutoConfirmHint();
33429
33924
  const confirm = await promptConfirm(
33430
- chalk227.red("Overwrite existing settings.json?"),
33925
+ chalk231.red("Overwrite existing settings.json?"),
33431
33926
  false
33432
33927
  );
33433
33928
  if (!confirm) {
@@ -34296,7 +34791,7 @@ import { mkdirSync as mkdirSync31 } from "fs";
34296
34791
  import { join as join93 } from "path";
34297
34792
 
34298
34793
  // src/commands/voice/checkLockFile.ts
34299
- import { execSync as execSync60 } from "child_process";
34794
+ import { execSync as execSync61 } from "child_process";
34300
34795
  import { existsSync as existsSync78, mkdirSync as mkdirSync30, readFileSync as readFileSync58, writeFileSync as writeFileSync48 } from "fs";
34301
34796
  import { join as join92 } from "path";
34302
34797
  function isProcessAlive2(pid) {
@@ -34325,7 +34820,7 @@ function bootstrapVenv() {
34325
34820
  if (existsSync78(getVenvPython())) return;
34326
34821
  console.log("Setting up Python environment...");
34327
34822
  const pythonDir = getPythonDir();
34328
- execSync60(
34823
+ execSync61(
34329
34824
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
34330
34825
  {
34331
34826
  stdio: "inherit",
@@ -34946,11 +35441,11 @@ function runCommandToCompletion(command, args, env, cwd, quiet) {
34946
35441
  }
34947
35442
 
34948
35443
  // src/commands/run/runPreCommands.ts
34949
- import { execSync as execSync61 } from "child_process";
35444
+ import { execSync as execSync62 } from "child_process";
34950
35445
  function runPreCommands(pre, cwd) {
34951
35446
  for (const cmd of pre) {
34952
35447
  try {
34953
- execSync61(cmd, { stdio: "inherit", cwd });
35448
+ execSync62(cmd, { stdio: "inherit", cwd });
34954
35449
  } catch (error) {
34955
35450
  const code = error && typeof error === "object" && "status" in error ? error.status : 1;
34956
35451
  process.exit(code);
@@ -35169,7 +35664,7 @@ function registerWatch(program2) {
35169
35664
 
35170
35665
  // src/commands/roam/auth.ts
35171
35666
  import { randomBytes } from "crypto";
35172
- import chalk228 from "chalk";
35667
+ import chalk232 from "chalk";
35173
35668
 
35174
35669
  // src/commands/roam/waitForCallback.ts
35175
35670
  import { createServer as createServer3 } from "http";
@@ -35300,13 +35795,13 @@ async function auth() {
35300
35795
  saveGlobalConfig(config);
35301
35796
  const state = randomBytes(16).toString("hex");
35302
35797
  console.log(
35303
- chalk228.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
35798
+ chalk232.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
35304
35799
  );
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..."));
35800
+ console.log(chalk232.white("http://localhost:14523/callback\n"));
35801
+ console.log(chalk232.blue("Opening browser for authorization..."));
35802
+ console.log(chalk232.dim("Waiting for authorization callback..."));
35308
35803
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
35309
- console.log(chalk228.dim("Exchanging code for tokens..."));
35804
+ console.log(chalk232.dim("Exchanging code for tokens..."));
35310
35805
  const tokens = await exchangeToken({
35311
35806
  code,
35312
35807
  clientId,
@@ -35322,7 +35817,7 @@ async function auth() {
35322
35817
  };
35323
35818
  saveGlobalConfig(config);
35324
35819
  console.log(
35325
- chalk228.green("Roam credentials and tokens saved to ~/.assist.yml")
35820
+ chalk232.green("Roam credentials and tokens saved to ~/.assist.yml")
35326
35821
  );
35327
35822
  }
35328
35823
 
@@ -35677,11 +36172,11 @@ function registerRun(program2) {
35677
36172
  }
35678
36173
 
35679
36174
  // src/commands/screenshot/index.ts
35680
- import { execSync as execSync62 } from "child_process";
36175
+ import { execSync as execSync63 } from "child_process";
35681
36176
  import { existsSync as existsSync85, mkdirSync as mkdirSync34, unlinkSync as unlinkSync22, writeFileSync as writeFileSync51 } from "fs";
35682
36177
  import { tmpdir as tmpdir9 } from "os";
35683
36178
  import { join as join100, resolve as resolve21 } from "path";
35684
- import chalk229 from "chalk";
36179
+ import chalk233 from "chalk";
35685
36180
 
35686
36181
  // src/commands/screenshot/captureWindowPs1.ts
35687
36182
  var captureWindowPs1 = `
@@ -35820,7 +36315,7 @@ function runPowerShellScript(processName, outputPath) {
35820
36315
  const scriptPath = join100(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
35821
36316
  writeFileSync51(scriptPath, captureWindowPs1, "utf8");
35822
36317
  try {
35823
- execSync62(
36318
+ execSync63(
35824
36319
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
35825
36320
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
35826
36321
  );
@@ -35832,13 +36327,13 @@ function screenshot(processName) {
35832
36327
  const config = loadConfig();
35833
36328
  const outputDir = resolve21(config.screenshot.outputDir);
35834
36329
  const outputPath = buildOutputPath(outputDir, processName);
35835
- console.log(chalk229.gray(`Capturing window for process "${processName}" ...`));
36330
+ console.log(chalk233.gray(`Capturing window for process "${processName}" ...`));
35836
36331
  try {
35837
36332
  runPowerShellScript(processName, outputPath);
35838
- console.log(chalk229.green(`Screenshot saved: ${outputPath}`));
36333
+ console.log(chalk233.green(`Screenshot saved: ${outputPath}`));
35839
36334
  } catch (error) {
35840
36335
  const msg = error instanceof Error ? error.message : String(error);
35841
- console.error(chalk229.red(`Failed to capture screenshot: ${msg}`));
36336
+ console.error(chalk233.red(`Failed to capture screenshot: ${msg}`));
35842
36337
  process.exit(1);
35843
36338
  }
35844
36339
  }
@@ -41800,7 +42295,7 @@ async function renameSession(title) {
41800
42295
 
41801
42296
  // src/commands/sessions/summarise/index.ts
41802
42297
  import * as fs57 from "fs";
41803
- import chalk230 from "chalk";
42298
+ import chalk234 from "chalk";
41804
42299
 
41805
42300
  // src/commands/sessions/summarise/shared.ts
41806
42301
  import * as fs56 from "fs";
@@ -41859,22 +42354,22 @@ ${firstMessage}`);
41859
42354
  async function summarise2(options2) {
41860
42355
  const files = await discoverSessionFiles();
41861
42356
  if (files.length === 0) {
41862
- console.log(chalk230.yellow("No sessions found."));
42357
+ console.log(chalk234.yellow("No sessions found."));
41863
42358
  return;
41864
42359
  }
41865
42360
  const toProcess = selectCandidates(files, options2);
41866
42361
  if (toProcess.length === 0) {
41867
- console.log(chalk230.green("All sessions already summarised."));
42362
+ console.log(chalk234.green("All sessions already summarised."));
41868
42363
  return;
41869
42364
  }
41870
42365
  console.log(
41871
- chalk230.cyan(
42366
+ chalk234.cyan(
41872
42367
  `Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
41873
42368
  )
41874
42369
  );
41875
42370
  const { succeeded, failed: failed2 } = processSessions(toProcess);
41876
42371
  console.log(
41877
- chalk230.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk230.yellow(`, ${failed2} skipped`) : "")
42372
+ chalk234.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk234.yellow(`, ${failed2} skipped`) : "")
41878
42373
  );
41879
42374
  }
41880
42375
  function selectCandidates(files, options2) {
@@ -41894,16 +42389,16 @@ function processSessions(files) {
41894
42389
  let failed2 = 0;
41895
42390
  for (let i = 0; i < files.length; i++) {
41896
42391
  const file = files[i];
41897
- process.stdout.write(chalk230.dim(` [${i + 1}/${files.length}] `));
42392
+ process.stdout.write(chalk234.dim(` [${i + 1}/${files.length}] `));
41898
42393
  const summary = summariseSession(file);
41899
42394
  if (summary) {
41900
42395
  writeSummary(file, summary);
41901
42396
  succeeded++;
41902
- process.stdout.write(`${chalk230.green("\u2713")} ${summary}
42397
+ process.stdout.write(`${chalk234.green("\u2713")} ${summary}
41903
42398
  `);
41904
42399
  } else {
41905
42400
  failed2++;
41906
- process.stdout.write(` ${chalk230.yellow("skip")}
42401
+ process.stdout.write(` ${chalk234.yellow("skip")}
41907
42402
  `);
41908
42403
  }
41909
42404
  }
@@ -41930,7 +42425,7 @@ function registerSessions(program2) {
41930
42425
  }
41931
42426
 
41932
42427
  // src/commands/statusLine.ts
41933
- import chalk232 from "chalk";
42428
+ import chalk236 from "chalk";
41934
42429
 
41935
42430
  // src/shared/contextLevel.ts
41936
42431
  function contextLevel(pct) {
@@ -41940,7 +42435,7 @@ function contextLevel(pct) {
41940
42435
  }
41941
42436
 
41942
42437
  // src/commands/buildLimitsSegment.ts
41943
- import chalk231 from "chalk";
42438
+ import chalk235 from "chalk";
41944
42439
 
41945
42440
  // src/shared/rateLimitLevel.ts
41946
42441
  var FIVE_HOUR_SECONDS = 5 * 3600;
@@ -41978,9 +42473,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
41978
42473
 
41979
42474
  // src/commands/buildLimitsSegment.ts
41980
42475
  var LEVEL_COLOR = {
41981
- ok: chalk231.green,
41982
- warn: chalk231.yellow,
41983
- over: chalk231.red
42476
+ ok: chalk235.green,
42477
+ warn: chalk235.yellow,
42478
+ over: chalk235.red
41984
42479
  };
41985
42480
  function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
41986
42481
  const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
@@ -42076,7 +42571,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
42076
42571
  }
42077
42572
 
42078
42573
  // src/commands/statusLine.ts
42079
- chalk232.level = 3;
42574
+ chalk236.level = 3;
42080
42575
  function formatNumber(num) {
42081
42576
  return num.toLocaleString("en-US");
42082
42577
  }
@@ -42084,9 +42579,9 @@ function colorizePercent(pct) {
42084
42579
  const label2 = `${Math.round(pct)}%`;
42085
42580
  switch (contextLevel(pct)) {
42086
42581
  case "red":
42087
- return chalk232.red(label2);
42582
+ return chalk236.red(label2);
42088
42583
  case "yellow":
42089
- return chalk232.yellow(label2);
42584
+ return chalk236.yellow(label2);
42090
42585
  default:
42091
42586
  return label2;
42092
42587
  }
@@ -42099,7 +42594,7 @@ async function statusLine() {
42099
42594
  const usedPct = data.context_window.used_percentage ?? 0;
42100
42595
  const dir = data.workspace?.current_dir ?? data.cwd;
42101
42596
  const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
42102
- const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk232.cyan(branch2)} | ` : "";
42597
+ const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk236.cyan(branch2)} | ` : "";
42103
42598
  console.log(
42104
42599
  `${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
42105
42600
  );
@@ -42112,7 +42607,7 @@ async function statusLine() {
42112
42607
  }
42113
42608
 
42114
42609
  // src/commands/update.ts
42115
- import { execSync as execSync63 } from "child_process";
42610
+ import { execSync as execSync64 } from "child_process";
42116
42611
  import * as path90 from "path";
42117
42612
 
42118
42613
  // src/commands/restartDaemonAfterUpdate.ts
@@ -42136,7 +42631,7 @@ function isGlobalNpmInstall(dir) {
42136
42631
  if (resolved.split(path90.sep).includes("node_modules")) {
42137
42632
  return true;
42138
42633
  }
42139
- const globalPrefix = execSync63("npm prefix -g", { stdio: "pipe" }).toString().trim();
42634
+ const globalPrefix = execSync64("npm prefix -g", { stdio: "pipe" }).toString().trim();
42140
42635
  return resolved.toLowerCase().startsWith(path90.resolve(globalPrefix).toLowerCase());
42141
42636
  } catch {
42142
42637
  return false;
@@ -42147,18 +42642,18 @@ async function update2() {
42147
42642
  console.log(`Assist is installed at: ${installDir}`);
42148
42643
  if (isGitRepo(installDir)) {
42149
42644
  console.log("Detected git repo installation, pulling latest...");
42150
- execSync63("git pull", { cwd: installDir, stdio: "inherit" });
42645
+ execSync64("git pull", { cwd: installDir, stdio: "inherit" });
42151
42646
  console.log("Installing dependencies...");
42152
- execSync63("npm i", { cwd: installDir, stdio: "inherit" });
42647
+ execSync64("npm i", { cwd: installDir, stdio: "inherit" });
42153
42648
  console.log("Building...");
42154
- execSync63("npm run build", { cwd: installDir, stdio: "inherit" });
42649
+ execSync64("npm run build", { cwd: installDir, stdio: "inherit" });
42155
42650
  console.log("Syncing commands...");
42156
- execSync63("assist sync", { stdio: "inherit" });
42651
+ execSync64("assist sync", { stdio: "inherit" });
42157
42652
  } else if (isGlobalNpmInstall(installDir)) {
42158
42653
  console.log("Detected global npm installation, updating...");
42159
- execSync63("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
42654
+ execSync64("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
42160
42655
  console.log("Syncing commands...");
42161
- execSync63("assist sync", { stdio: "inherit" });
42656
+ execSync64("assist sync", { stdio: "inherit" });
42162
42657
  } else {
42163
42658
  console.error(
42164
42659
  "Could not determine installation method. Expected a git repo or global npm install."
@@ -42169,10 +42664,10 @@ async function update2() {
42169
42664
  }
42170
42665
 
42171
42666
  // src/reportCliError.ts
42172
- import chalk233 from "chalk";
42667
+ import chalk237 from "chalk";
42173
42668
  function reportCliError(error) {
42174
42669
  if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
42175
- console.error(chalk233.red(error.message));
42670
+ console.error(chalk237.red(error.message));
42176
42671
  } else {
42177
42672
  console.error(error);
42178
42673
  }