@staff0rd/assist 0.178.0 → 0.180.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.178.0",
9
+ version: "0.180.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -39,6 +39,8 @@ var package_default = {
39
39
  },
40
40
  dependencies: {
41
41
  "better-sqlite3": "^12.8.0",
42
+ blessed: "^0.1.81",
43
+ "blessed-contrib": "^4.11.0",
42
44
  chalk: "^5.6.2",
43
45
  commander: "^14.0.2",
44
46
  diff: "^8.0.2",
@@ -61,6 +63,7 @@ var package_default = {
61
63
  "@semantic-release/exec": "^7.1.0",
62
64
  "@semantic-release/git": "^10.0.1",
63
65
  "@types/better-sqlite3": "^7.6.13",
66
+ "@types/blessed": "^0.1.27",
64
67
  "@types/node": "^24.10.1",
65
68
  "@types/node-notifier": "^8.0.5",
66
69
  "@types/react": "^19.2.14",
@@ -1829,155 +1832,6 @@ function commit(args) {
1829
1832
  execCommit(files, message, config);
1830
1833
  }
1831
1834
 
1832
- // src/commands/config/index.ts
1833
- import chalk19 from "chalk";
1834
- import { stringify as stringifyYaml2 } from "yaml";
1835
-
1836
- // src/commands/config/setNestedValue.ts
1837
- function isPlainObject(val) {
1838
- return val !== null && typeof val === "object" && !Array.isArray(val);
1839
- }
1840
- function isNumericKey(key) {
1841
- return /^\d+$/.test(key);
1842
- }
1843
- function resolveKey(key) {
1844
- return isNumericKey(key) ? Number.parseInt(key, 10) : key;
1845
- }
1846
- function getItem(container, key) {
1847
- if (Array.isArray(container)) return container[key];
1848
- return container[key];
1849
- }
1850
- function setItem(container, key, value) {
1851
- if (Array.isArray(container)) container[key] = value;
1852
- else container[key] = value;
1853
- }
1854
- function ensureArray(container, key) {
1855
- const existing = getItem(container, key);
1856
- const arr = Array.isArray(existing) ? [...existing] : [];
1857
- setItem(container, key, arr);
1858
- return arr;
1859
- }
1860
- function ensureObject(container, key) {
1861
- const existing = getItem(container, key);
1862
- const obj = isPlainObject(existing) ? { ...existing } : {};
1863
- setItem(container, key, obj);
1864
- return obj;
1865
- }
1866
- function stepIntoNested(container, key, nextKey) {
1867
- const resolved = resolveKey(key);
1868
- if (nextKey !== void 0 && isNumericKey(nextKey)) {
1869
- return ensureArray(container, resolved);
1870
- }
1871
- return ensureObject(container, resolved);
1872
- }
1873
- function setNestedValue(obj, path50, value) {
1874
- const keys = path50.split(".");
1875
- const result = { ...obj };
1876
- let current = result;
1877
- for (let i = 0; i < keys.length - 1; i++) {
1878
- current = stepIntoNested(current, keys[i], keys[i + 1]);
1879
- }
1880
- setItem(current, resolveKey(keys[keys.length - 1]), value);
1881
- return result;
1882
- }
1883
-
1884
- // src/commands/config/index.ts
1885
- function coerceValue(value) {
1886
- if (value === "true") return true;
1887
- if (value === "false") return false;
1888
- return value;
1889
- }
1890
- function formatIssuePath(issue, key) {
1891
- return issue.path.length > 0 ? issue.path.join(".") : key;
1892
- }
1893
- function printValidationErrors(issues, key) {
1894
- for (const issue of issues) {
1895
- console.error(
1896
- chalk19.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
1897
- );
1898
- }
1899
- }
1900
- function exitValidationFailed(issues, key) {
1901
- printValidationErrors(issues, key);
1902
- process.exit(1);
1903
- }
1904
- function validateConfig(updated, key) {
1905
- const result = assistConfigSchema.safeParse(updated);
1906
- if (!result.success) return exitValidationFailed(result.error.issues, key);
1907
- return updated;
1908
- }
1909
- var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
1910
- function assertNotGlobalOnly(key, global) {
1911
- if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
1912
- console.error(
1913
- chalk19.red(
1914
- `"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
1915
- )
1916
- );
1917
- process.exit(1);
1918
- }
1919
- }
1920
- function applyConfigSet(key, coerced, global) {
1921
- assertNotGlobalOnly(key, global);
1922
- const raw = global ? loadGlobalConfigRaw() : loadProjectConfig();
1923
- const updated = setNestedValue(raw, key, coerced);
1924
- validateConfig(updated, key);
1925
- if (global) {
1926
- saveGlobalConfig(updated);
1927
- } else {
1928
- saveConfig(updated);
1929
- }
1930
- }
1931
- function configSet(key, value, options2 = {}) {
1932
- const coerced = coerceValue(value);
1933
- applyConfigSet(key, coerced, options2.global ?? false);
1934
- const target = options2.global ? "global" : "project";
1935
- console.log(
1936
- chalk19.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
1937
- );
1938
- }
1939
- function configList() {
1940
- const config = loadConfig();
1941
- console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
1942
- }
1943
-
1944
- // src/commands/config/configGet.ts
1945
- import chalk20 from "chalk";
1946
-
1947
- // src/commands/config/getNestedValue.ts
1948
- function isTraversable(value) {
1949
- return value !== null && value !== void 0 && typeof value === "object";
1950
- }
1951
- function stepInto(current, key) {
1952
- return isTraversable(current) ? current[key] : void 0;
1953
- }
1954
- function getNestedValue(obj, path50) {
1955
- let current = obj;
1956
- for (const key of path50.split(".")) current = stepInto(current, key);
1957
- return current;
1958
- }
1959
-
1960
- // src/commands/config/configGet.ts
1961
- function configGet(key) {
1962
- console.log(
1963
- formatOutput(
1964
- requireNestedValue(loadConfig(), key)
1965
- )
1966
- );
1967
- }
1968
- function formatOutput(value) {
1969
- return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
1970
- }
1971
- function requireNestedValue(config, key) {
1972
- const value = getNestedValue(config, key);
1973
- if (value === void 0) return exitKeyNotSet(key);
1974
- return value;
1975
- }
1976
- function exitKeyNotSet(key) {
1977
- console.error(chalk20.red(`Key "${key}" is not set`));
1978
- process.exit(1);
1979
- }
1980
-
1981
1835
  // src/commands/coverage.ts
1982
1836
  import { execSync as execSync2 } from "child_process";
1983
1837
  function coverage() {
@@ -1994,10 +1848,10 @@ function coverage() {
1994
1848
  }
1995
1849
 
1996
1850
  // src/commands/verify/init/index.ts
1997
- import chalk35 from "chalk";
1851
+ import chalk33 from "chalk";
1998
1852
 
1999
1853
  // src/shared/promptMultiselect.ts
2000
- import chalk21 from "chalk";
1854
+ import chalk19 from "chalk";
2001
1855
  import enquirer4 from "enquirer";
2002
1856
  async function promptMultiselect(message, options2) {
2003
1857
  const { selected } = await exitOnCancel(
@@ -2007,7 +1861,7 @@ async function promptMultiselect(message, options2) {
2007
1861
  message,
2008
1862
  choices: options2.map((opt) => ({
2009
1863
  name: opt.value,
2010
- message: `${opt.name} - ${chalk21.dim(opt.description)}`
1864
+ message: `${opt.name} - ${chalk19.dim(opt.description)}`
2011
1865
  })),
2012
1866
  // @ts-expect-error - enquirer types don't include symbols but it's supported
2013
1867
  symbols: {
@@ -2024,7 +1878,7 @@ async function promptMultiselect(message, options2) {
2024
1878
  // src/shared/readPackageJson.ts
2025
1879
  import * as fs from "fs";
2026
1880
  import * as path from "path";
2027
- import chalk22 from "chalk";
1881
+ import chalk20 from "chalk";
2028
1882
  function findPackageJson() {
2029
1883
  const packageJsonPath = path.join(process.cwd(), "package.json");
2030
1884
  if (fs.existsSync(packageJsonPath)) {
@@ -2038,7 +1892,7 @@ function readPackageJson(filePath) {
2038
1892
  function requirePackageJson() {
2039
1893
  const packageJsonPath = findPackageJson();
2040
1894
  if (!packageJsonPath) {
2041
- console.error(chalk22.red("No package.json found in current directory"));
1895
+ console.error(chalk20.red("No package.json found in current directory"));
2042
1896
  process.exit(1);
2043
1897
  }
2044
1898
  const pkg = readPackageJson(packageJsonPath);
@@ -2069,7 +1923,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
2069
1923
  // src/commands/verify/installPackage.ts
2070
1924
  import { execSync as execSync3 } from "child_process";
2071
1925
  import { writeFileSync as writeFileSync6 } from "fs";
2072
- import chalk23 from "chalk";
1926
+ import chalk21 from "chalk";
2073
1927
  function writePackageJson(filePath, pkg) {
2074
1928
  writeFileSync6(filePath, `${JSON.stringify(pkg, null, 2)}
2075
1929
  `);
@@ -2084,12 +1938,12 @@ function addScript(pkg, name, command) {
2084
1938
  };
2085
1939
  }
2086
1940
  function installPackage(name, cwd) {
2087
- console.log(chalk23.dim(`Installing ${name}...`));
1941
+ console.log(chalk21.dim(`Installing ${name}...`));
2088
1942
  try {
2089
1943
  execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
2090
1944
  return true;
2091
1945
  } catch {
2092
- console.error(chalk23.red(`Failed to install ${name}`));
1946
+ console.error(chalk21.red(`Failed to install ${name}`));
2093
1947
  return false;
2094
1948
  }
2095
1949
  }
@@ -2136,9 +1990,9 @@ var expectedScripts = {
2136
1990
  };
2137
1991
 
2138
1992
  // src/commands/verify/setup/setupBuild.ts
2139
- import chalk24 from "chalk";
1993
+ import chalk22 from "chalk";
2140
1994
  async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
2141
- console.log(chalk24.blue("\nSetting up build verification..."));
1995
+ console.log(chalk22.blue("\nSetting up build verification..."));
2142
1996
  let command;
2143
1997
  if (hasVite && hasTypescript) {
2144
1998
  command = "tsc -b && vite build --logLevel error";
@@ -2147,21 +2001,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
2147
2001
  } else {
2148
2002
  command = "npm run build";
2149
2003
  }
2150
- console.log(chalk24.dim(`Using: ${command}`));
2004
+ console.log(chalk22.dim(`Using: ${command}`));
2151
2005
  writer("verify:build", command);
2152
2006
  }
2153
2007
  async function setupTypecheck(_packageJsonPath, writer) {
2154
- console.log(chalk24.blue("\nSetting up typecheck verification..."));
2008
+ console.log(chalk22.blue("\nSetting up typecheck verification..."));
2155
2009
  const command = "tsc --noEmit";
2156
- console.log(chalk24.dim(`Using: ${command}`));
2010
+ console.log(chalk22.dim(`Using: ${command}`));
2157
2011
  writer("verify:typecheck", command);
2158
2012
  }
2159
2013
 
2160
2014
  // src/commands/verify/setup/setupDuplicateCode.ts
2161
2015
  import * as path2 from "path";
2162
- import chalk25 from "chalk";
2016
+ import chalk23 from "chalk";
2163
2017
  async function setupDuplicateCode(packageJsonPath, writer) {
2164
- console.log(chalk25.blue("\nSetting up jscpd..."));
2018
+ console.log(chalk23.blue("\nSetting up jscpd..."));
2165
2019
  const cwd = path2.dirname(packageJsonPath);
2166
2020
  const pkg = readPackageJson(packageJsonPath);
2167
2021
  const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
@@ -2173,12 +2027,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
2173
2027
 
2174
2028
  // src/commands/verify/setup/setupHardcodedColors.ts
2175
2029
  import * as path3 from "path";
2176
- import chalk27 from "chalk";
2030
+ import chalk25 from "chalk";
2177
2031
 
2178
2032
  // src/commands/verify/addToKnipIgnoreBinaries.ts
2179
2033
  import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
2180
2034
  import { join as join10 } from "path";
2181
- import chalk26 from "chalk";
2035
+ import chalk24 from "chalk";
2182
2036
  function loadKnipConfig(knipJsonPath) {
2183
2037
  if (existsSync11(knipJsonPath)) {
2184
2038
  return JSON.parse(readFileSync10(knipJsonPath, "utf-8"));
@@ -2197,16 +2051,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
2197
2051
  `${JSON.stringify(knipConfig, null, " ")}
2198
2052
  `
2199
2053
  );
2200
- console.log(chalk26.dim(`Added '${binary}' to knip.json ignoreBinaries`));
2054
+ console.log(chalk24.dim(`Added '${binary}' to knip.json ignoreBinaries`));
2201
2055
  }
2202
2056
  } catch {
2203
- console.log(chalk26.yellow("Warning: Could not update knip.json"));
2057
+ console.log(chalk24.yellow("Warning: Could not update knip.json"));
2204
2058
  }
2205
2059
  }
2206
2060
 
2207
2061
  // src/commands/verify/setup/setupHardcodedColors.ts
2208
2062
  async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
2209
- console.log(chalk27.blue("\nSetting up hardcoded colors check..."));
2063
+ console.log(chalk25.blue("\nSetting up hardcoded colors check..."));
2210
2064
  const cwd = path3.dirname(packageJsonPath);
2211
2065
  if (!hasOpenColor) {
2212
2066
  installPackage("open-color", cwd);
@@ -2217,9 +2071,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
2217
2071
 
2218
2072
  // src/commands/verify/setup/setupKnip.ts
2219
2073
  import * as path4 from "path";
2220
- import chalk28 from "chalk";
2074
+ import chalk26 from "chalk";
2221
2075
  async function setupKnip(packageJsonPath, writer) {
2222
- console.log(chalk28.blue("\nSetting up knip..."));
2076
+ console.log(chalk26.blue("\nSetting up knip..."));
2223
2077
  const cwd = path4.dirname(packageJsonPath);
2224
2078
  const pkg = readPackageJson(packageJsonPath);
2225
2079
  if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
@@ -2230,14 +2084,14 @@ async function setupKnip(packageJsonPath, writer) {
2230
2084
 
2231
2085
  // src/commands/verify/setup/setupLint.ts
2232
2086
  import * as path5 from "path";
2233
- import chalk31 from "chalk";
2087
+ import chalk29 from "chalk";
2234
2088
 
2235
2089
  // src/commands/lint/init.ts
2236
2090
  import { execSync as execSync5 } from "child_process";
2237
2091
  import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
2238
2092
  import { dirname as dirname7, join as join11 } from "path";
2239
2093
  import { fileURLToPath as fileURLToPath2 } from "url";
2240
- import chalk30 from "chalk";
2094
+ import chalk28 from "chalk";
2241
2095
 
2242
2096
  // src/shared/promptConfirm.ts
2243
2097
  import enquirer5 from "enquirer";
@@ -2341,7 +2195,7 @@ function removeEslintScripts(scripts, options2) {
2341
2195
  }
2342
2196
 
2343
2197
  // src/utils/printDiff.ts
2344
- import chalk29 from "chalk";
2198
+ import chalk27 from "chalk";
2345
2199
  import * as diff from "diff";
2346
2200
  function normalizeJson(content) {
2347
2201
  try {
@@ -2359,11 +2213,11 @@ function printDiff(oldContent, newContent) {
2359
2213
  const lines = change.value.replace(/\n$/, "").split("\n");
2360
2214
  for (const line of lines) {
2361
2215
  if (change.added) {
2362
- console.log(chalk29.green(`+ ${line}`));
2216
+ console.log(chalk27.green(`+ ${line}`));
2363
2217
  } else if (change.removed) {
2364
- console.log(chalk29.red(`- ${line}`));
2218
+ console.log(chalk27.red(`- ${line}`));
2365
2219
  } else {
2366
- console.log(chalk29.dim(` ${line}`));
2220
+ console.log(chalk27.dim(` ${line}`));
2367
2221
  }
2368
2222
  }
2369
2223
  }
@@ -2397,10 +2251,10 @@ async function init() {
2397
2251
  console.log("biome.json already has the correct linter config");
2398
2252
  return;
2399
2253
  }
2400
- console.log(chalk30.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
2254
+ console.log(chalk28.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
2401
2255
  console.log();
2402
2256
  printDiff(oldContent, newContent);
2403
- const confirm = await promptConfirm(chalk30.red("Update biome.json?"));
2257
+ const confirm = await promptConfirm(chalk28.red("Update biome.json?"));
2404
2258
  if (!confirm) {
2405
2259
  console.log("Skipped biome.json update");
2406
2260
  return;
@@ -2411,7 +2265,7 @@ async function init() {
2411
2265
 
2412
2266
  // src/commands/verify/setup/setupLint.ts
2413
2267
  async function setupLint(packageJsonPath, writer) {
2414
- console.log(chalk31.blue("\nSetting up biome..."));
2268
+ console.log(chalk29.blue("\nSetting up biome..."));
2415
2269
  const cwd = path5.dirname(packageJsonPath);
2416
2270
  const pkg = readPackageJson(packageJsonPath);
2417
2271
  if (!pkg.devDependencies?.["@biomejs/biome"]) {
@@ -2425,9 +2279,9 @@ async function setupLint(packageJsonPath, writer) {
2425
2279
 
2426
2280
  // src/commands/verify/setup/setupMadge.ts
2427
2281
  import * as path6 from "path";
2428
- import chalk32 from "chalk";
2282
+ import chalk30 from "chalk";
2429
2283
  async function setupMadge(packageJsonPath, writer) {
2430
- console.log(chalk32.blue("\nSetting up madge..."));
2284
+ console.log(chalk30.blue("\nSetting up madge..."));
2431
2285
  const cwd = path6.dirname(packageJsonPath);
2432
2286
  const pkg = readPackageJson(packageJsonPath);
2433
2287
  const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
@@ -2439,18 +2293,18 @@ async function setupMadge(packageJsonPath, writer) {
2439
2293
 
2440
2294
  // src/commands/verify/setup/setupMaintainability.ts
2441
2295
  import * as path7 from "path";
2442
- import chalk33 from "chalk";
2296
+ import chalk31 from "chalk";
2443
2297
  async function setupMaintainability(packageJsonPath, writer) {
2444
- console.log(chalk33.blue("\nSetting up maintainability check..."));
2298
+ console.log(chalk31.blue("\nSetting up maintainability check..."));
2445
2299
  addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
2446
2300
  writer("verify:maintainability", expectedScripts["verify:maintainability"]);
2447
2301
  }
2448
2302
 
2449
2303
  // src/commands/verify/setup/setupTest.ts
2450
2304
  import * as path8 from "path";
2451
- import chalk34 from "chalk";
2305
+ import chalk32 from "chalk";
2452
2306
  async function setupTest(packageJsonPath, writer) {
2453
- console.log(chalk34.blue("\nSetting up vitest..."));
2307
+ console.log(chalk32.blue("\nSetting up vitest..."));
2454
2308
  const cwd = path8.dirname(packageJsonPath);
2455
2309
  const pkg = readPackageJson(packageJsonPath);
2456
2310
  if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
@@ -2619,25 +2473,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
2619
2473
  for (const choice of selected) {
2620
2474
  await handlers[choice]?.(packageJsonPath, writer);
2621
2475
  }
2622
- console.log(chalk35.green(`
2476
+ console.log(chalk33.green(`
2623
2477
  Added ${selected.length} verify script(s):`));
2624
2478
  for (const choice of selected) {
2625
- console.log(chalk35.green(` - verify:${choice}`));
2479
+ console.log(chalk33.green(` - verify:${choice}`));
2626
2480
  }
2627
- console.log(chalk35.dim("\nRun 'assist verify' to run all verify scripts"));
2481
+ console.log(chalk33.dim("\nRun 'assist verify' to run all verify scripts"));
2628
2482
  }
2629
2483
  async function promptForScripts(availableOptions) {
2630
2484
  if (availableOptions.length === 0) {
2631
- console.log(chalk35.green("All verify scripts are already configured!"));
2485
+ console.log(chalk33.green("All verify scripts are already configured!"));
2632
2486
  return null;
2633
2487
  }
2634
- console.log(chalk35.bold("Available verify scripts to add:\n"));
2488
+ console.log(chalk33.bold("Available verify scripts to add:\n"));
2635
2489
  const selected = await promptMultiselect(
2636
2490
  "Select verify scripts to add:",
2637
2491
  availableOptions
2638
2492
  );
2639
2493
  if (selected.length === 0) {
2640
- console.log(chalk35.yellow("No scripts selected"));
2494
+ console.log(chalk33.yellow("No scripts selected"));
2641
2495
  return null;
2642
2496
  }
2643
2497
  return selected;
@@ -2657,17 +2511,17 @@ async function init2() {
2657
2511
  }
2658
2512
 
2659
2513
  // src/commands/vscode/init/index.ts
2660
- import chalk37 from "chalk";
2514
+ import chalk35 from "chalk";
2661
2515
 
2662
2516
  // src/commands/vscode/init/createLaunchJson.ts
2663
2517
  import * as fs2 from "fs";
2664
2518
  import * as path9 from "path";
2665
- import chalk36 from "chalk";
2519
+ import chalk34 from "chalk";
2666
2520
  function ensureVscodeFolder() {
2667
2521
  const vscodeDir = path9.join(process.cwd(), ".vscode");
2668
2522
  if (!fs2.existsSync(vscodeDir)) {
2669
2523
  fs2.mkdirSync(vscodeDir);
2670
- console.log(chalk36.dim("Created .vscode folder"));
2524
+ console.log(chalk34.dim("Created .vscode folder"));
2671
2525
  }
2672
2526
  }
2673
2527
  function removeVscodeFromGitignore() {
@@ -2682,7 +2536,7 @@ function removeVscodeFromGitignore() {
2682
2536
  );
2683
2537
  if (filteredLines.length !== lines.length) {
2684
2538
  fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
2685
- console.log(chalk36.dim("Removed .vscode references from .gitignore"));
2539
+ console.log(chalk34.dim("Removed .vscode references from .gitignore"));
2686
2540
  }
2687
2541
  }
2688
2542
  function createLaunchJson(type) {
@@ -2701,7 +2555,7 @@ function createLaunchJson(type) {
2701
2555
  const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
2702
2556
  fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
2703
2557
  `);
2704
- console.log(chalk36.green("Created .vscode/launch.json"));
2558
+ console.log(chalk34.green("Created .vscode/launch.json"));
2705
2559
  }
2706
2560
  function createSettingsJson() {
2707
2561
  const settings = {
@@ -2714,7 +2568,7 @@ function createSettingsJson() {
2714
2568
  const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
2715
2569
  fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
2716
2570
  `);
2717
- console.log(chalk36.green("Created .vscode/settings.json"));
2571
+ console.log(chalk34.green("Created .vscode/settings.json"));
2718
2572
  }
2719
2573
  function createExtensionsJson() {
2720
2574
  const extensions = {
@@ -2726,7 +2580,7 @@ function createExtensionsJson() {
2726
2580
  `${JSON.stringify(extensions, null, " ")}
2727
2581
  `
2728
2582
  );
2729
- console.log(chalk36.green("Created .vscode/extensions.json"));
2583
+ console.log(chalk34.green("Created .vscode/extensions.json"));
2730
2584
  }
2731
2585
 
2732
2586
  // src/commands/vscode/init/detectVscodeSetup.ts
@@ -2783,7 +2637,7 @@ function applySelections(selected, setup2) {
2783
2637
  for (const choice of selected) handlers[choice]?.();
2784
2638
  }
2785
2639
  async function promptForOptions(options2) {
2786
- console.log(chalk37.bold("Available VS Code configurations to add:\n"));
2640
+ console.log(chalk35.bold("Available VS Code configurations to add:\n"));
2787
2641
  return promptMultiselect("Select configurations to add:", options2);
2788
2642
  }
2789
2643
  async function init3({ all = false } = {}) {
@@ -2791,17 +2645,17 @@ async function init3({ all = false } = {}) {
2791
2645
  const setup2 = detectVscodeSetup(pkg);
2792
2646
  const options2 = getAvailableOptions2(setup2);
2793
2647
  if (options2.length === 0) {
2794
- console.log(chalk37.green("VS Code configuration already exists!"));
2648
+ console.log(chalk35.green("VS Code configuration already exists!"));
2795
2649
  return;
2796
2650
  }
2797
2651
  const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
2798
2652
  if (selected.length === 0) {
2799
- console.log(chalk37.yellow("No configurations selected"));
2653
+ console.log(chalk35.yellow("No configurations selected"));
2800
2654
  return;
2801
2655
  }
2802
2656
  applySelections(selected, setup2);
2803
2657
  console.log(
2804
- chalk37.green(`
2658
+ chalk35.green(`
2805
2659
  Added ${selected.length} VS Code configuration(s)`)
2806
2660
  );
2807
2661
  }
@@ -2814,7 +2668,7 @@ async function init4() {
2814
2668
 
2815
2669
  // src/commands/lint/lint/runFileNameCheck.ts
2816
2670
  import path16 from "path";
2817
- import chalk39 from "chalk";
2671
+ import chalk37 from "chalk";
2818
2672
 
2819
2673
  // src/commands/lint/lint/checkFileNames.ts
2820
2674
  import fs5 from "fs";
@@ -2894,7 +2748,7 @@ function checkFileNames() {
2894
2748
  }
2895
2749
 
2896
2750
  // src/commands/lint/lint/fixFileNameViolations.ts
2897
- import chalk38 from "chalk";
2751
+ import chalk36 from "chalk";
2898
2752
 
2899
2753
  // src/commands/lint/lint/applyMoves.ts
2900
2754
  import fs6 from "fs";
@@ -2979,25 +2833,25 @@ function fixFileNameViolations(moves) {
2979
2833
  const start3 = performance.now();
2980
2834
  const project = createLintProject();
2981
2835
  const cwd = process.cwd();
2982
- applyMoves(project, moves, cwd, (line) => console.log(chalk38.green(line)));
2836
+ applyMoves(project, moves, cwd, (line) => console.log(chalk36.green(line)));
2983
2837
  const ms = (performance.now() - start3).toFixed(0);
2984
- console.log(chalk38.dim(` Done in ${ms}ms`));
2838
+ console.log(chalk36.dim(` Done in ${ms}ms`));
2985
2839
  }
2986
2840
 
2987
2841
  // src/commands/lint/lint/runFileNameCheck.ts
2988
2842
  function reportViolations(violations) {
2989
- console.error(chalk39.red("\nFile name check failed:\n"));
2843
+ console.error(chalk37.red("\nFile name check failed:\n"));
2990
2844
  console.error(
2991
- chalk39.red(
2845
+ chalk37.red(
2992
2846
  " Files without classes or React components should not start with a capital letter.\n"
2993
2847
  )
2994
2848
  );
2995
2849
  for (const violation of violations) {
2996
- console.error(chalk39.red(` ${violation.filePath}`));
2997
- console.error(chalk39.gray(` Rename to: ${violation.suggestedName}
2850
+ console.error(chalk37.red(` ${violation.filePath}`));
2851
+ console.error(chalk37.gray(` Rename to: ${violation.suggestedName}
2998
2852
  `));
2999
2853
  }
3000
- console.error(chalk39.dim(" Run with -f to auto-fix.\n"));
2854
+ console.error(chalk37.dim(" Run with -f to auto-fix.\n"));
3001
2855
  }
3002
2856
  function runFileNameCheck(fix = false) {
3003
2857
  const violations = checkFileNames();
@@ -3026,17 +2880,17 @@ function runFileNameCheck(fix = false) {
3026
2880
  import fs8 from "fs";
3027
2881
 
3028
2882
  // src/commands/lint/shared.ts
3029
- import chalk40 from "chalk";
2883
+ import chalk38 from "chalk";
3030
2884
  function reportViolations2(violations, checkName, errorMessage, successMessage) {
3031
2885
  if (violations.length > 0) {
3032
- console.error(chalk40.red(`
2886
+ console.error(chalk38.red(`
3033
2887
  ${checkName} failed:
3034
2888
  `));
3035
- console.error(chalk40.red(` ${errorMessage}
2889
+ console.error(chalk38.red(` ${errorMessage}
3036
2890
  `));
3037
2891
  for (const violation of violations) {
3038
- console.error(chalk40.red(` ${violation.filePath}:${violation.line}`));
3039
- console.error(chalk40.gray(` ${violation.content}
2892
+ console.error(chalk38.red(` ${violation.filePath}:${violation.line}`));
2893
+ console.error(chalk38.gray(` ${violation.content}
3040
2894
  `));
3041
2895
  }
3042
2896
  return false;
@@ -3516,14 +3370,14 @@ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSy
3516
3370
 
3517
3371
  // src/commands/deploy/init/index.ts
3518
3372
  import { execSync as execSync12 } from "child_process";
3519
- import chalk42 from "chalk";
3373
+ import chalk40 from "chalk";
3520
3374
  import enquirer6 from "enquirer";
3521
3375
 
3522
3376
  // src/commands/deploy/init/updateWorkflow.ts
3523
3377
  import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
3524
3378
  import { dirname as dirname13, join as join14 } from "path";
3525
3379
  import { fileURLToPath as fileURLToPath3 } from "url";
3526
- import chalk41 from "chalk";
3380
+ import chalk39 from "chalk";
3527
3381
  var WORKFLOW_PATH = ".github/workflows/build.yml";
3528
3382
  var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
3529
3383
  function getExistingSiteId() {
@@ -3548,20 +3402,20 @@ async function updateWorkflow(siteId) {
3548
3402
  if (existsSync17(WORKFLOW_PATH)) {
3549
3403
  const oldContent = readFileSync14(WORKFLOW_PATH, "utf-8");
3550
3404
  if (oldContent === newContent) {
3551
- console.log(chalk41.green("build.yml is already up to date"));
3405
+ console.log(chalk39.green("build.yml is already up to date"));
3552
3406
  return;
3553
3407
  }
3554
- console.log(chalk41.yellow("\nbuild.yml will be updated:"));
3408
+ console.log(chalk39.yellow("\nbuild.yml will be updated:"));
3555
3409
  console.log();
3556
3410
  printDiff(oldContent, newContent);
3557
- const confirm = await promptConfirm(chalk41.red("Update build.yml?"));
3411
+ const confirm = await promptConfirm(chalk39.red("Update build.yml?"));
3558
3412
  if (!confirm) {
3559
3413
  console.log("Skipped build.yml update");
3560
3414
  return;
3561
3415
  }
3562
3416
  }
3563
3417
  writeFileSync13(WORKFLOW_PATH, newContent);
3564
- console.log(chalk41.green(`
3418
+ console.log(chalk39.green(`
3565
3419
  Created ${WORKFLOW_PATH}`));
3566
3420
  }
3567
3421
 
@@ -3572,43 +3426,43 @@ async function ensureNetlifyCli() {
3572
3426
  } catch (error) {
3573
3427
  if (!(error instanceof Error) || !error.message.includes("command not found"))
3574
3428
  throw error;
3575
- console.error(chalk42.red("\nNetlify CLI is not installed.\n"));
3429
+ console.error(chalk40.red("\nNetlify CLI is not installed.\n"));
3576
3430
  const install = await promptConfirm("Would you like to install it now?");
3577
3431
  if (!install) {
3578
3432
  console.log(
3579
- chalk42.yellow(
3433
+ chalk40.yellow(
3580
3434
  "\nInstall it manually with: npm install -g netlify-cli\n"
3581
3435
  )
3582
3436
  );
3583
3437
  process.exit(1);
3584
3438
  }
3585
- console.log(chalk42.dim("\nInstalling netlify-cli...\n"));
3439
+ console.log(chalk40.dim("\nInstalling netlify-cli...\n"));
3586
3440
  execSync12("npm install -g netlify-cli", { stdio: "inherit" });
3587
3441
  console.log();
3588
3442
  execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
3589
3443
  }
3590
3444
  }
3591
3445
  function printSetupInstructions() {
3592
- console.log(chalk42.bold("\nDeployment initialized successfully!"));
3446
+ console.log(chalk40.bold("\nDeployment initialized successfully!"));
3593
3447
  console.log(
3594
- chalk42.yellow("\nTo complete setup, create a personal access token at:")
3448
+ chalk40.yellow("\nTo complete setup, create a personal access token at:")
3595
3449
  );
3596
3450
  console.log(
3597
- chalk42.cyan(
3451
+ chalk40.cyan(
3598
3452
  "https://app.netlify.com/user/applications#personal-access-tokens"
3599
3453
  )
3600
3454
  );
3601
3455
  console.log(
3602
- chalk42.yellow(
3456
+ chalk40.yellow(
3603
3457
  "\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
3604
3458
  )
3605
3459
  );
3606
3460
  }
3607
3461
  async function init5() {
3608
- console.log(chalk42.bold("Initializing Netlify deployment...\n"));
3462
+ console.log(chalk40.bold("Initializing Netlify deployment...\n"));
3609
3463
  const existingSiteId = getExistingSiteId();
3610
3464
  if (existingSiteId) {
3611
- console.log(chalk42.dim(`Using existing site ID: ${existingSiteId}
3465
+ console.log(chalk40.dim(`Using existing site ID: ${existingSiteId}
3612
3466
  `));
3613
3467
  await updateWorkflow(existingSiteId);
3614
3468
  return;
@@ -3786,28 +3640,126 @@ async function notify() {
3786
3640
  console.log(`Notification sent: ${notification_type} for ${projectName}`);
3787
3641
  }
3788
3642
 
3643
+ // src/commands/activity/activityChart.ts
3644
+ import blessed from "blessed";
3645
+ import contrib from "blessed-contrib";
3646
+ function activityChart(data) {
3647
+ const screen = blessed.screen({
3648
+ smartCSR: true,
3649
+ title: "Commit Activity"
3650
+ });
3651
+ const grid = new contrib.grid({ rows: 1, cols: 1, screen });
3652
+ const labels = data.map((d) => d.date.slice(5));
3653
+ const values = data.map((d) => d.count);
3654
+ const line = grid.set(0, 0, 1, 1, contrib.line, {
3655
+ label: " Commits per day (press q to close) ",
3656
+ showLegend: true,
3657
+ legend: { width: 12 },
3658
+ xLabelPadding: 3,
3659
+ xPadding: 5,
3660
+ wholeNumbersOnly: true
3661
+ });
3662
+ line.setData([
3663
+ {
3664
+ title: "Commits",
3665
+ x: labels,
3666
+ y: values,
3667
+ style: { line: "green" }
3668
+ }
3669
+ ]);
3670
+ screen.key(["q", "C-c", "escape"], () => {
3671
+ screen.destroy();
3672
+ });
3673
+ screen.render();
3674
+ }
3675
+
3676
+ // src/commands/activity/fetchCommitsPerDay.ts
3677
+ import { execSync as execSync14 } from "child_process";
3678
+ function fetchContributions(from, to) {
3679
+ const query = `{ viewer { contributionsCollection(from: "${from}T00:00:00Z", to: "${to}T23:59:59Z") { contributionCalendar { weeks { contributionDays { date contributionCount } } } } } }`;
3680
+ const jq = ".data.viewer.contributionsCollection.contributionCalendar.weeks[].contributionDays[]";
3681
+ const raw = execSync14(`gh api graphql -f query='${query}' --jq '${jq}'`, {
3682
+ encoding: "utf-8"
3683
+ }).trim();
3684
+ if (!raw) return [];
3685
+ return raw.split("\n").map((line) => {
3686
+ const obj = JSON.parse(line);
3687
+ return { date: obj.date, count: obj.contributionCount };
3688
+ });
3689
+ }
3690
+ function fetchCommitsPerDay(since) {
3691
+ const start3 = new Date(since);
3692
+ const end = /* @__PURE__ */ new Date();
3693
+ const results = [];
3694
+ let cursor = new Date(start3);
3695
+ while (cursor <= end) {
3696
+ const yearEnd = new Date(cursor);
3697
+ yearEnd.setFullYear(yearEnd.getFullYear(), yearEnd.getMonth() + 12);
3698
+ yearEnd.setDate(yearEnd.getDate() - 1);
3699
+ const windowEnd = yearEnd > end ? end : yearEnd;
3700
+ const from = cursor.toISOString().slice(0, 10);
3701
+ const to = windowEnd.toISOString().slice(0, 10);
3702
+ results.push(...fetchContributions(from, to));
3703
+ cursor = new Date(windowEnd);
3704
+ cursor.setDate(cursor.getDate() + 1);
3705
+ }
3706
+ return results.filter(
3707
+ (d) => d.date >= since && d.date <= end.toISOString().slice(0, 10)
3708
+ );
3709
+ }
3710
+
3711
+ // src/commands/activity.ts
3712
+ async function activity(options2) {
3713
+ const since = options2.since ?? new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString().slice(0, 10);
3714
+ const data = fetchCommitsPerDay(since);
3715
+ if (data.length < 2) {
3716
+ console.log("Not enough data points to chart.");
3717
+ return;
3718
+ }
3719
+ const total = data.reduce((sum, d) => sum + d.count, 0);
3720
+ const activeDays = data.filter((d) => d.count > 0).length;
3721
+ console.log(`${total} commits across ${activeDays} active days.`);
3722
+ const weekly = /* @__PURE__ */ new Map();
3723
+ for (const { date, count } of data) {
3724
+ const d = new Date(date);
3725
+ d.setDate(d.getDate() - d.getDay());
3726
+ const weekStart = d.toISOString().slice(0, 10);
3727
+ weekly.set(weekStart, (weekly.get(weekStart) ?? 0) + count);
3728
+ }
3729
+ const weeklyData = [...weekly.entries()].map(([date, count]) => ({ date, count })).sort((a, b) => a.date.localeCompare(b.date));
3730
+ activityChart(weeklyData);
3731
+ }
3732
+
3733
+ // src/commands/registerActivity.ts
3734
+ function registerActivity(program2) {
3735
+ program2.command("activity").description("Chart GitHub commit activity per day").option(
3736
+ "--since <date>",
3737
+ "Start date (YYYY-MM-DD), defaults to 30 days ago"
3738
+ ).action(activity);
3739
+ }
3740
+
3789
3741
  // src/commands/backlog/comment/index.ts
3790
- import chalk43 from "chalk";
3742
+ import chalk41 from "chalk";
3791
3743
  function comment(id, text) {
3792
3744
  const result = loadAndFindItem(id);
3793
3745
  if (!result) process.exit(1);
3794
3746
  addComment(result.item, text);
3795
3747
  saveBacklog(result.items);
3796
- console.log(chalk43.green(`Comment added to item #${id}.`));
3748
+ console.log(chalk41.green(`Comment added to item #${id}.`));
3797
3749
  }
3798
3750
 
3799
3751
  // src/commands/backlog/comments/index.ts
3800
- import chalk44 from "chalk";
3752
+ import chalk42 from "chalk";
3801
3753
  function comments(id) {
3802
3754
  const result = loadAndFindItem(id);
3803
3755
  if (!result) process.exit(1);
3804
3756
  const { item } = result;
3805
3757
  const entries = item.comments ?? [];
3806
3758
  if (entries.length === 0) {
3807
- console.log(chalk44.dim(`No comments on item #${id}.`));
3759
+ console.log(chalk42.dim(`No comments on item #${id}.`));
3808
3760
  return;
3809
3761
  }
3810
- console.log(chalk44.bold(`Comments for #${id}: ${item.name}
3762
+ console.log(chalk42.bold(`Comments for #${id}: ${item.name}
3811
3763
  `));
3812
3764
  for (const entry of entries) {
3813
3765
  console.log(`${formatComment(entry)}
@@ -3822,17 +3774,17 @@ function registerCommentCommands(cmd) {
3822
3774
  }
3823
3775
 
3824
3776
  // src/commands/backlog/add/index.ts
3825
- import chalk46 from "chalk";
3777
+ import chalk44 from "chalk";
3826
3778
 
3827
3779
  // src/commands/backlog/commitBacklog.ts
3828
- import { execSync as execSync14 } from "child_process";
3780
+ import { execSync as execSync15 } from "child_process";
3829
3781
  import { join as join15 } from "path";
3830
- import chalk45 from "chalk";
3782
+ import chalk43 from "chalk";
3831
3783
  function commitBacklog(id, name) {
3832
3784
  const config = loadConfig();
3833
3785
  if (!config.backlog.autoCommit) {
3834
3786
  console.log(
3835
- chalk45.yellow(
3787
+ chalk43.yellow(
3836
3788
  "Warning: auto-commit is disabled. Stage and commit the backlog file manually."
3837
3789
  )
3838
3790
  );
@@ -3841,10 +3793,10 @@ function commitBacklog(id, name) {
3841
3793
  try {
3842
3794
  const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
3843
3795
  const message = `chore: add backlog item #${id} \u2014 ${name}`;
3844
- execSync14(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
3845
- execSync14(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
3796
+ execSync15(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
3797
+ execSync15(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
3846
3798
  } catch {
3847
- console.log(chalk45.yellow("Warning: could not auto-commit backlog file."));
3799
+ console.log(chalk43.yellow("Warning: could not auto-commit backlog file."));
3848
3800
  }
3849
3801
  }
3850
3802
 
@@ -3936,12 +3888,12 @@ async function addFromOptions(options2) {
3936
3888
  });
3937
3889
  saveBacklog(items);
3938
3890
  commitBacklog(id, name);
3939
- console.log(chalk46.green(`Added item #${id}: ${name}`));
3891
+ console.log(chalk44.green(`Added item #${id}: ${name}`));
3940
3892
  }
3941
3893
  async function add(options2) {
3942
3894
  if (!backlogExists()) {
3943
3895
  console.log(
3944
- chalk46.yellow(
3896
+ chalk44.yellow(
3945
3897
  "No backlog found. Run 'assist backlog init' to create one."
3946
3898
  )
3947
3899
  );
@@ -3951,13 +3903,13 @@ async function add(options2) {
3951
3903
  }
3952
3904
 
3953
3905
  // src/commands/backlog/addPhase.ts
3954
- import chalk47 from "chalk";
3906
+ import chalk45 from "chalk";
3955
3907
  function addPhase(id, name, options2) {
3956
3908
  const result = loadAndFindItem(id);
3957
3909
  if (!result) return;
3958
3910
  const tasks = options2.task ?? [];
3959
3911
  if (tasks.length === 0) {
3960
- console.log(chalk47.red("At least one --task is required."));
3912
+ console.log(chalk45.red("At least one --task is required."));
3961
3913
  process.exitCode = 1;
3962
3914
  return;
3963
3915
  }
@@ -3979,25 +3931,25 @@ function addPhase(id, name, options2) {
3979
3931
  exportToJsonl(db, dir);
3980
3932
  commitBacklog(itemId, result.item.name);
3981
3933
  console.log(
3982
- chalk47.green(
3934
+ chalk45.green(
3983
3935
  `Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
3984
3936
  )
3985
3937
  );
3986
3938
  }
3987
3939
 
3988
3940
  // src/commands/backlog/init/index.ts
3989
- import chalk48 from "chalk";
3941
+ import chalk46 from "chalk";
3990
3942
  async function init6() {
3991
3943
  if (backlogExists()) {
3992
- console.log(chalk48.yellow("Backlog already exists."));
3944
+ console.log(chalk46.yellow("Backlog already exists."));
3993
3945
  return;
3994
3946
  }
3995
3947
  saveBacklog([]);
3996
- console.log(chalk48.green("Created backlog."));
3948
+ console.log(chalk46.green("Created backlog."));
3997
3949
  }
3998
3950
 
3999
3951
  // src/commands/backlog/list/index.ts
4000
- import chalk49 from "chalk";
3952
+ import chalk47 from "chalk";
4001
3953
  function filterItems(items, options2) {
4002
3954
  if (options2.status) return items.filter((i) => i.status === options2.status);
4003
3955
  if (!options2.all)
@@ -4007,7 +3959,7 @@ function filterItems(items, options2) {
4007
3959
  async function list2(options2) {
4008
3960
  if (!backlogExists()) {
4009
3961
  console.log(
4010
- chalk49.yellow(
3962
+ chalk47.yellow(
4011
3963
  "No backlog found. Run 'assist backlog init' to create one."
4012
3964
  )
4013
3965
  );
@@ -4016,12 +3968,12 @@ async function list2(options2) {
4016
3968
  const allItems = loadBacklog();
4017
3969
  const items = filterItems(allItems, options2);
4018
3970
  if (items.length === 0) {
4019
- console.log(chalk49.dim("Backlog is empty."));
3971
+ console.log(chalk47.dim("Backlog is empty."));
4020
3972
  return;
4021
3973
  }
4022
3974
  for (const item of items) {
4023
3975
  console.log(
4024
- `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk49.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
3976
+ `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk47.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
4025
3977
  );
4026
3978
  if (options2.verbose) {
4027
3979
  printVerboseDetails(item);
@@ -4044,7 +3996,7 @@ function registerItemCommands(cmd) {
4044
3996
  }
4045
3997
 
4046
3998
  // src/commands/backlog/link.ts
4047
- import chalk51 from "chalk";
3999
+ import chalk49 from "chalk";
4048
4000
 
4049
4001
  // src/commands/backlog/hasCycle.ts
4050
4002
  function hasCycle(items, fromId, toId) {
@@ -4067,11 +4019,11 @@ function hasCycle(items, fromId, toId) {
4067
4019
  }
4068
4020
 
4069
4021
  // src/commands/backlog/validateLinkTarget.ts
4070
- import chalk50 from "chalk";
4022
+ import chalk48 from "chalk";
4071
4023
  function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
4072
4024
  const toItem = items.find((i) => i.id === toNum);
4073
4025
  if (!toItem) {
4074
- console.log(chalk50.red(`Item #${toId} not found.`));
4026
+ console.log(chalk48.red(`Item #${toId} not found.`));
4075
4027
  return void 0;
4076
4028
  }
4077
4029
  if (!fromItem.links) fromItem.links = [];
@@ -4080,7 +4032,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
4080
4032
  );
4081
4033
  if (duplicate) {
4082
4034
  console.log(
4083
- chalk50.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
4035
+ chalk48.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
4084
4036
  );
4085
4037
  return void 0;
4086
4038
  }
@@ -4091,13 +4043,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
4091
4043
  function link(fromId, toId, opts) {
4092
4044
  const linkType = opts.type ?? "relates-to";
4093
4045
  if (linkType !== "relates-to" && linkType !== "depends-on") {
4094
- console.log(chalk51.red(`Invalid link type: ${linkType}`));
4046
+ console.log(chalk49.red(`Invalid link type: ${linkType}`));
4095
4047
  return;
4096
4048
  }
4097
4049
  const fromNum = Number.parseInt(fromId, 10);
4098
4050
  const toNum = Number.parseInt(toId, 10);
4099
4051
  if (fromNum === toNum) {
4100
- console.log(chalk51.red("Cannot link an item to itself."));
4052
+ console.log(chalk49.red("Cannot link an item to itself."));
4101
4053
  return;
4102
4054
  }
4103
4055
  const result = loadAndFindItem(fromId);
@@ -4114,7 +4066,7 @@ function link(fromId, toId, opts) {
4114
4066
  if (!toItem) return;
4115
4067
  if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
4116
4068
  console.log(
4117
- chalk51.red(
4069
+ chalk49.red(
4118
4070
  `Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
4119
4071
  )
4120
4072
  );
@@ -4124,32 +4076,32 @@ function link(fromId, toId, opts) {
4124
4076
  fromItem.links.push({ type: linkType, targetId: toNum });
4125
4077
  saveBacklog(items);
4126
4078
  console.log(
4127
- chalk51.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
4079
+ chalk49.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
4128
4080
  );
4129
4081
  }
4130
4082
 
4131
4083
  // src/commands/backlog/unlink.ts
4132
- import chalk52 from "chalk";
4084
+ import chalk50 from "chalk";
4133
4085
  function unlink(fromId, toId) {
4134
4086
  const toNum = Number.parseInt(toId, 10);
4135
4087
  const result = loadAndFindItem(fromId);
4136
4088
  if (!result) return;
4137
4089
  const { items, item: fromItem } = result;
4138
4090
  if (!fromItem.links || fromItem.links.length === 0) {
4139
- console.log(chalk52.yellow(`No links found on item #${fromId}.`));
4091
+ console.log(chalk50.yellow(`No links found on item #${fromId}.`));
4140
4092
  return;
4141
4093
  }
4142
4094
  const before = fromItem.links.length;
4143
4095
  fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
4144
4096
  if (fromItem.links.length === before) {
4145
- console.log(chalk52.yellow(`No link from #${fromId} to #${toId} found.`));
4097
+ console.log(chalk50.yellow(`No link from #${fromId} to #${toId} found.`));
4146
4098
  return;
4147
4099
  }
4148
4100
  if (fromItem.links.length === 0) {
4149
4101
  fromItem.links = void 0;
4150
4102
  }
4151
4103
  saveBacklog(items);
4152
- console.log(chalk52.green(`Removed link from #${fromId} to #${toId}.`));
4104
+ console.log(chalk50.green(`Removed link from #${fromId} to #${toId}.`));
4153
4105
  }
4154
4106
 
4155
4107
  // src/commands/backlog/registerLinkCommands.ts
@@ -4170,11 +4122,11 @@ function registerRunCommand(cmd) {
4170
4122
  }
4171
4123
 
4172
4124
  // src/commands/backlog/search/index.ts
4173
- import chalk53 from "chalk";
4125
+ import chalk51 from "chalk";
4174
4126
  async function search(query) {
4175
4127
  if (!backlogExists()) {
4176
4128
  console.log(
4177
- chalk53.yellow(
4129
+ chalk51.yellow(
4178
4130
  "No backlog found. Run 'assist backlog init' to create one."
4179
4131
  )
4180
4132
  );
@@ -4182,18 +4134,18 @@ async function search(query) {
4182
4134
  }
4183
4135
  const items = searchBacklog(query);
4184
4136
  if (items.length === 0) {
4185
- console.log(chalk53.dim(`No items matching "${query}".`));
4137
+ console.log(chalk51.dim(`No items matching "${query}".`));
4186
4138
  return;
4187
4139
  }
4188
4140
  console.log(
4189
- chalk53.dim(
4141
+ chalk51.dim(
4190
4142
  `${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
4191
4143
  `
4192
4144
  )
4193
4145
  );
4194
4146
  for (const item of items) {
4195
4147
  console.log(
4196
- `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk53.dim(`#${item.id}`)} ${item.name}`
4148
+ `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk51.dim(`#${item.id}`)} ${item.name}`
4197
4149
  );
4198
4150
  }
4199
4151
  }
@@ -4204,16 +4156,16 @@ function registerSearchCommand(cmd) {
4204
4156
  }
4205
4157
 
4206
4158
  // src/commands/backlog/delete/index.ts
4207
- import chalk54 from "chalk";
4159
+ import chalk52 from "chalk";
4208
4160
  async function del(id) {
4209
4161
  const name = removeItem(id);
4210
4162
  if (name) {
4211
- console.log(chalk54.green(`Deleted item #${id}: ${name}`));
4163
+ console.log(chalk52.green(`Deleted item #${id}: ${name}`));
4212
4164
  }
4213
4165
  }
4214
4166
 
4215
4167
  // src/commands/backlog/done/index.ts
4216
- import chalk55 from "chalk";
4168
+ import chalk53 from "chalk";
4217
4169
  async function done(id, summary) {
4218
4170
  const result = loadAndFindItem(id);
4219
4171
  if (!result) return;
@@ -4223,12 +4175,12 @@ async function done(id, summary) {
4223
4175
  const pending = item.plan.slice(completed);
4224
4176
  if (pending.length > 0) {
4225
4177
  console.log(
4226
- chalk55.red(
4178
+ chalk53.red(
4227
4179
  `Cannot complete item #${id}: ${pending.length} pending phase(s):`
4228
4180
  )
4229
4181
  );
4230
4182
  for (const phase of pending) {
4231
- console.log(chalk55.yellow(` - ${phase.name}`));
4183
+ console.log(chalk53.yellow(` - ${phase.name}`));
4232
4184
  }
4233
4185
  process.exitCode = 1;
4234
4186
  return;
@@ -4240,20 +4192,20 @@ async function done(id, summary) {
4240
4192
  addPhaseSummary(item, summary, phase);
4241
4193
  }
4242
4194
  saveBacklog(result.items);
4243
- console.log(chalk55.green(`Completed item #${id}: ${item.name}`));
4195
+ console.log(chalk53.green(`Completed item #${id}: ${item.name}`));
4244
4196
  }
4245
4197
 
4246
4198
  // src/commands/backlog/start/index.ts
4247
- import chalk56 from "chalk";
4199
+ import chalk54 from "chalk";
4248
4200
  async function start(id) {
4249
4201
  const name = setStatus(id, "in-progress");
4250
4202
  if (name) {
4251
- console.log(chalk56.green(`Started item #${id}: ${name}`));
4203
+ console.log(chalk54.green(`Started item #${id}: ${name}`));
4252
4204
  }
4253
4205
  }
4254
4206
 
4255
4207
  // src/commands/backlog/wontdo/index.ts
4256
- import chalk57 from "chalk";
4208
+ import chalk55 from "chalk";
4257
4209
  async function wontdo(id, reason) {
4258
4210
  const result = loadAndFindItem(id);
4259
4211
  if (!result) return;
@@ -4263,7 +4215,7 @@ async function wontdo(id, reason) {
4263
4215
  addPhaseSummary(result.item, reason, phase);
4264
4216
  }
4265
4217
  saveBacklog(result.items);
4266
- console.log(chalk57.red(`Won't do item #${id}: ${result.item.name}`));
4218
+ console.log(chalk55.red(`Won't do item #${id}: ${result.item.name}`));
4267
4219
  }
4268
4220
 
4269
4221
  // src/commands/backlog/registerStatusCommands.ts
@@ -4275,10 +4227,10 @@ function registerStatusCommands(cmd) {
4275
4227
  }
4276
4228
 
4277
4229
  // src/commands/backlog/removePhase.ts
4278
- import chalk59 from "chalk";
4230
+ import chalk57 from "chalk";
4279
4231
 
4280
4232
  // src/commands/backlog/findPhase.ts
4281
- import chalk58 from "chalk";
4233
+ import chalk56 from "chalk";
4282
4234
  function findPhase(id, phase) {
4283
4235
  const result = loadAndFindItem(id);
4284
4236
  if (!result) return void 0;
@@ -4290,7 +4242,7 @@ function findPhase(id, phase) {
4290
4242
  "SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
4291
4243
  ).get(itemId, phaseIdx);
4292
4244
  if (existing.cnt === 0) {
4293
- console.log(chalk58.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
4245
+ console.log(chalk56.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
4294
4246
  process.exitCode = 1;
4295
4247
  return void 0;
4296
4248
  }
@@ -4346,23 +4298,23 @@ function removePhase(id, phase) {
4346
4298
  run4();
4347
4299
  exportToJsonl(db, dir);
4348
4300
  commitBacklog(itemId, result.item.name);
4349
- console.log(chalk59.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
4301
+ console.log(chalk57.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
4350
4302
  }
4351
4303
 
4352
4304
  // src/commands/backlog/update/index.ts
4353
- import chalk61 from "chalk";
4305
+ import chalk59 from "chalk";
4354
4306
 
4355
4307
  // src/commands/backlog/update/buildUpdateSql.ts
4356
- import chalk60 from "chalk";
4308
+ import chalk58 from "chalk";
4357
4309
  function buildUpdateSql(options2) {
4358
4310
  const { name, desc, type, ac } = options2;
4359
4311
  if (!name && !desc && !type && !ac) {
4360
- console.log(chalk60.red("Nothing to update. Provide at least one flag."));
4312
+ console.log(chalk58.red("Nothing to update. Provide at least one flag."));
4361
4313
  process.exitCode = 1;
4362
4314
  return void 0;
4363
4315
  }
4364
4316
  if (type && type !== "story" && type !== "bug") {
4365
- console.log(chalk60.red('Invalid type. Must be "story" or "bug".'));
4317
+ console.log(chalk58.red('Invalid type. Must be "story" or "bug".'));
4366
4318
  process.exitCode = 1;
4367
4319
  return void 0;
4368
4320
  }
@@ -4407,11 +4359,11 @@ function update(id, options2) {
4407
4359
  );
4408
4360
  exportToJsonl(db, dir);
4409
4361
  commitBacklog(itemId, options2.name ?? result.item.name);
4410
- console.log(chalk61.green(`Updated ${built.fields} on item #${itemId}.`));
4362
+ console.log(chalk59.green(`Updated ${built.fields} on item #${itemId}.`));
4411
4363
  }
4412
4364
 
4413
4365
  // src/commands/backlog/updatePhase.ts
4414
- import chalk62 from "chalk";
4366
+ import chalk60 from "chalk";
4415
4367
 
4416
4368
  // src/commands/backlog/applyPhaseUpdate.ts
4417
4369
  function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
@@ -4445,7 +4397,7 @@ function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
4445
4397
  function updatePhase(id, phase, options2) {
4446
4398
  const { name, task, manualCheck } = options2;
4447
4399
  if (!name && !task && !manualCheck) {
4448
- console.log(chalk62.red("Nothing to update. Provide at least one flag."));
4400
+ console.log(chalk60.red("Nothing to update. Provide at least one flag."));
4449
4401
  process.exitCode = 1;
4450
4402
  return;
4451
4403
  }
@@ -4461,7 +4413,7 @@ function updatePhase(id, phase, options2) {
4461
4413
  manualCheck && "manual checks"
4462
4414
  ].filter(Boolean).join(", ");
4463
4415
  console.log(
4464
- chalk62.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
4416
+ chalk60.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
4465
4417
  );
4466
4418
  }
4467
4419
 
@@ -4912,48 +4864,48 @@ ${reasons.join("\n")}`);
4912
4864
  }
4913
4865
 
4914
4866
  // src/commands/deny/denyAdd.ts
4915
- import chalk63 from "chalk";
4867
+ import chalk61 from "chalk";
4916
4868
  function denyAdd(pattern2, message) {
4917
4869
  const config = loadProjectConfig();
4918
4870
  const deny = config.deny ?? [];
4919
4871
  if (deny.some((r) => r.pattern === pattern2)) {
4920
- console.log(chalk63.yellow(`Deny rule already exists for: ${pattern2}`));
4872
+ console.log(chalk61.yellow(`Deny rule already exists for: ${pattern2}`));
4921
4873
  return;
4922
4874
  }
4923
4875
  deny.push({ pattern: pattern2, message });
4924
4876
  config.deny = deny;
4925
4877
  saveConfig(config);
4926
- console.log(chalk63.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
4878
+ console.log(chalk61.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
4927
4879
  }
4928
4880
 
4929
4881
  // src/commands/deny/denyList.ts
4930
- import chalk64 from "chalk";
4882
+ import chalk62 from "chalk";
4931
4883
  function denyList() {
4932
4884
  const config = loadConfig();
4933
4885
  const deny = config.deny;
4934
4886
  if (!deny || deny.length === 0) {
4935
- console.log(chalk64.dim("No deny rules configured."));
4887
+ console.log(chalk62.dim("No deny rules configured."));
4936
4888
  return;
4937
4889
  }
4938
4890
  for (const rule of deny) {
4939
- console.log(`${chalk64.red(rule.pattern)} \u2192 ${rule.message}`);
4891
+ console.log(`${chalk62.red(rule.pattern)} \u2192 ${rule.message}`);
4940
4892
  }
4941
4893
  }
4942
4894
 
4943
4895
  // src/commands/deny/denyRemove.ts
4944
- import chalk65 from "chalk";
4896
+ import chalk63 from "chalk";
4945
4897
  function denyRemove(pattern2) {
4946
4898
  const config = loadProjectConfig();
4947
4899
  const deny = config.deny ?? [];
4948
4900
  const index = deny.findIndex((r) => r.pattern === pattern2);
4949
4901
  if (index === -1) {
4950
- console.log(chalk65.yellow(`No deny rule found for: ${pattern2}`));
4902
+ console.log(chalk63.yellow(`No deny rule found for: ${pattern2}`));
4951
4903
  return;
4952
4904
  }
4953
4905
  deny.splice(index, 1);
4954
4906
  config.deny = deny.length > 0 ? deny : void 0;
4955
4907
  saveConfig(config);
4956
- console.log(chalk65.green(`Removed deny rule: ${pattern2}`));
4908
+ console.log(chalk63.green(`Removed deny rule: ${pattern2}`));
4957
4909
  }
4958
4910
 
4959
4911
  // src/commands/permitCliReads/index.ts
@@ -4962,7 +4914,7 @@ import { homedir as homedir4 } from "os";
4962
4914
  import { join as join18 } from "path";
4963
4915
 
4964
4916
  // src/shared/getInstallDir.ts
4965
- import { execSync as execSync15 } from "child_process";
4917
+ import { execSync as execSync16 } from "child_process";
4966
4918
  import { dirname as dirname15, resolve as resolve4 } from "path";
4967
4919
  import { fileURLToPath as fileURLToPath5 } from "url";
4968
4920
  var __filename3 = fileURLToPath5(import.meta.url);
@@ -4972,7 +4924,7 @@ function getInstallDir() {
4972
4924
  }
4973
4925
  function isGitRepo(dir) {
4974
4926
  try {
4975
- const result = execSync15("git rev-parse --show-toplevel", {
4927
+ const result = execSync16("git rev-parse --show-toplevel", {
4976
4928
  cwd: dir,
4977
4929
  stdio: "pipe"
4978
4930
  }).toString().trim();
@@ -4983,7 +4935,7 @@ function isGitRepo(dir) {
4983
4935
  }
4984
4936
 
4985
4937
  // src/commands/permitCliReads/assertCliExists.ts
4986
- import { execSync as execSync16 } from "child_process";
4938
+ import { execSync as execSync17 } from "child_process";
4987
4939
  function assertCliExists(cli) {
4988
4940
  const binary = cli.split(/\s+/)[0];
4989
4941
  const opts = {
@@ -4991,10 +4943,10 @@ function assertCliExists(cli) {
4991
4943
  stdio: ["ignore", "pipe", "pipe"]
4992
4944
  };
4993
4945
  try {
4994
- execSync16(`command -v ${binary}`, opts);
4946
+ execSync17(`command -v ${binary}`, opts);
4995
4947
  } catch {
4996
4948
  try {
4997
- execSync16(`where ${binary}`, opts);
4949
+ execSync17(`where ${binary}`, opts);
4998
4950
  } catch {
4999
4951
  console.error(`CLI "${cli}" not found in PATH`);
5000
4952
  process.exit(1);
@@ -5003,11 +4955,11 @@ function assertCliExists(cli) {
5003
4955
  }
5004
4956
 
5005
4957
  // src/commands/permitCliReads/colorize.ts
5006
- import chalk66 from "chalk";
4958
+ import chalk64 from "chalk";
5007
4959
  function colorize(plainOutput) {
5008
4960
  return plainOutput.split("\n").map((line) => {
5009
- if (line.startsWith(" R ")) return chalk66.green(line);
5010
- if (line.startsWith(" W ")) return chalk66.red(line);
4961
+ if (line.startsWith(" R ")) return chalk64.green(line);
4962
+ if (line.startsWith(" W ")) return chalk64.red(line);
5011
4963
  return line;
5012
4964
  }).join("\n");
5013
4965
  }
@@ -5325,15 +5277,15 @@ function registerCliHook(program2) {
5325
5277
  }
5326
5278
 
5327
5279
  // src/commands/complexity/analyze.ts
5328
- import chalk72 from "chalk";
5280
+ import chalk70 from "chalk";
5329
5281
 
5330
5282
  // src/commands/complexity/cyclomatic.ts
5331
- import chalk68 from "chalk";
5283
+ import chalk66 from "chalk";
5332
5284
 
5333
5285
  // src/commands/complexity/shared/index.ts
5334
5286
  import fs12 from "fs";
5335
5287
  import path20 from "path";
5336
- import chalk67 from "chalk";
5288
+ import chalk65 from "chalk";
5337
5289
  import ts5 from "typescript";
5338
5290
 
5339
5291
  // src/commands/complexity/findSourceFiles.ts
@@ -5579,7 +5531,7 @@ function createSourceFromFile(filePath) {
5579
5531
  function withSourceFiles(pattern2, callback) {
5580
5532
  const files = findSourceFiles2(pattern2);
5581
5533
  if (files.length === 0) {
5582
- console.log(chalk67.yellow("No files found matching pattern"));
5534
+ console.log(chalk65.yellow("No files found matching pattern"));
5583
5535
  return void 0;
5584
5536
  }
5585
5537
  return callback(files);
@@ -5612,11 +5564,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
5612
5564
  results.sort((a, b) => b.complexity - a.complexity);
5613
5565
  for (const { file, name, complexity } of results) {
5614
5566
  const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
5615
- const color = exceedsThreshold ? chalk68.red : chalk68.white;
5616
- console.log(`${color(`${file}:${name}`)} \u2192 ${chalk68.cyan(complexity)}`);
5567
+ const color = exceedsThreshold ? chalk66.red : chalk66.white;
5568
+ console.log(`${color(`${file}:${name}`)} \u2192 ${chalk66.cyan(complexity)}`);
5617
5569
  }
5618
5570
  console.log(
5619
- chalk68.dim(
5571
+ chalk66.dim(
5620
5572
  `
5621
5573
  Analyzed ${results.length} functions across ${files.length} files`
5622
5574
  )
@@ -5628,7 +5580,7 @@ Analyzed ${results.length} functions across ${files.length} files`
5628
5580
  }
5629
5581
 
5630
5582
  // src/commands/complexity/halstead.ts
5631
- import chalk69 from "chalk";
5583
+ import chalk67 from "chalk";
5632
5584
  async function halstead(pattern2 = "**/*.ts", options2 = {}) {
5633
5585
  withSourceFiles(pattern2, (files) => {
5634
5586
  const results = [];
@@ -5643,13 +5595,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
5643
5595
  results.sort((a, b) => b.metrics.effort - a.metrics.effort);
5644
5596
  for (const { file, name, metrics } of results) {
5645
5597
  const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
5646
- const color = exceedsThreshold ? chalk69.red : chalk69.white;
5598
+ const color = exceedsThreshold ? chalk67.red : chalk67.white;
5647
5599
  console.log(
5648
- `${color(`${file}:${name}`)} \u2192 volume: ${chalk69.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk69.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk69.magenta(metrics.effort.toFixed(1))}`
5600
+ `${color(`${file}:${name}`)} \u2192 volume: ${chalk67.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk67.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk67.magenta(metrics.effort.toFixed(1))}`
5649
5601
  );
5650
5602
  }
5651
5603
  console.log(
5652
- chalk69.dim(
5604
+ chalk67.dim(
5653
5605
  `
5654
5606
  Analyzed ${results.length} functions across ${files.length} files`
5655
5607
  )
@@ -5664,28 +5616,28 @@ Analyzed ${results.length} functions across ${files.length} files`
5664
5616
  import fs13 from "fs";
5665
5617
 
5666
5618
  // src/commands/complexity/maintainability/displayMaintainabilityResults.ts
5667
- import chalk70 from "chalk";
5619
+ import chalk68 from "chalk";
5668
5620
  function displayMaintainabilityResults(results, threshold) {
5669
5621
  const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
5670
5622
  if (threshold !== void 0 && filtered.length === 0) {
5671
- console.log(chalk70.green("All files pass maintainability threshold"));
5623
+ console.log(chalk68.green("All files pass maintainability threshold"));
5672
5624
  } else {
5673
5625
  for (const { file, avgMaintainability, minMaintainability } of filtered) {
5674
- const color = threshold !== void 0 ? chalk70.red : chalk70.white;
5626
+ const color = threshold !== void 0 ? chalk68.red : chalk68.white;
5675
5627
  console.log(
5676
- `${color(file)} \u2192 avg: ${chalk70.cyan(avgMaintainability.toFixed(1))}, min: ${chalk70.yellow(minMaintainability.toFixed(1))}`
5628
+ `${color(file)} \u2192 avg: ${chalk68.cyan(avgMaintainability.toFixed(1))}, min: ${chalk68.yellow(minMaintainability.toFixed(1))}`
5677
5629
  );
5678
5630
  }
5679
5631
  }
5680
- console.log(chalk70.dim(`
5632
+ console.log(chalk68.dim(`
5681
5633
  Analyzed ${results.length} files`));
5682
5634
  if (filtered.length > 0 && threshold !== void 0) {
5683
5635
  console.error(
5684
- chalk70.red(
5636
+ chalk68.red(
5685
5637
  `
5686
5638
  Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
5687
5639
 
5688
- \u26A0\uFE0F ${chalk70.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
5640
+ \u26A0\uFE0F ${chalk68.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
5689
5641
  )
5690
5642
  );
5691
5643
  process.exit(1);
@@ -5742,7 +5694,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
5742
5694
 
5743
5695
  // src/commands/complexity/sloc.ts
5744
5696
  import fs14 from "fs";
5745
- import chalk71 from "chalk";
5697
+ import chalk69 from "chalk";
5746
5698
  async function sloc(pattern2 = "**/*.ts", options2 = {}) {
5747
5699
  withSourceFiles(pattern2, (files) => {
5748
5700
  const results = [];
@@ -5758,12 +5710,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
5758
5710
  results.sort((a, b) => b.lines - a.lines);
5759
5711
  for (const { file, lines } of results) {
5760
5712
  const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
5761
- const color = exceedsThreshold ? chalk71.red : chalk71.white;
5762
- console.log(`${color(file)} \u2192 ${chalk71.cyan(lines)} lines`);
5713
+ const color = exceedsThreshold ? chalk69.red : chalk69.white;
5714
+ console.log(`${color(file)} \u2192 ${chalk69.cyan(lines)} lines`);
5763
5715
  }
5764
5716
  const total = results.reduce((sum, r) => sum + r.lines, 0);
5765
5717
  console.log(
5766
- chalk71.dim(`
5718
+ chalk69.dim(`
5767
5719
  Total: ${total} lines across ${files.length} files`)
5768
5720
  );
5769
5721
  if (hasViolation) {
@@ -5777,21 +5729,21 @@ async function analyze(pattern2) {
5777
5729
  const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
5778
5730
  const files = findSourceFiles2(searchPattern);
5779
5731
  if (files.length === 0) {
5780
- console.log(chalk72.yellow("No files found matching pattern"));
5732
+ console.log(chalk70.yellow("No files found matching pattern"));
5781
5733
  return;
5782
5734
  }
5783
5735
  if (files.length === 1) {
5784
5736
  const file = files[0];
5785
- console.log(chalk72.bold.underline("SLOC"));
5737
+ console.log(chalk70.bold.underline("SLOC"));
5786
5738
  await sloc(file);
5787
5739
  console.log();
5788
- console.log(chalk72.bold.underline("Cyclomatic Complexity"));
5740
+ console.log(chalk70.bold.underline("Cyclomatic Complexity"));
5789
5741
  await cyclomatic(file);
5790
5742
  console.log();
5791
- console.log(chalk72.bold.underline("Halstead Metrics"));
5743
+ console.log(chalk70.bold.underline("Halstead Metrics"));
5792
5744
  await halstead(file);
5793
5745
  console.log();
5794
- console.log(chalk72.bold.underline("Maintainability Index"));
5746
+ console.log(chalk70.bold.underline("Maintainability Index"));
5795
5747
  await maintainability(file);
5796
5748
  return;
5797
5749
  }
@@ -5817,6 +5769,163 @@ function registerComplexity(program2) {
5817
5769
  complexityCommand.command("sloc [pattern]").description("Count source lines of code per file").option("--threshold <number>", "Max lines threshold", Number.parseInt).action(sloc);
5818
5770
  }
5819
5771
 
5772
+ // src/commands/config/index.ts
5773
+ import chalk71 from "chalk";
5774
+ import { stringify as stringifyYaml2 } from "yaml";
5775
+
5776
+ // src/commands/config/setNestedValue.ts
5777
+ function isPlainObject(val) {
5778
+ return val !== null && typeof val === "object" && !Array.isArray(val);
5779
+ }
5780
+ function isNumericKey(key) {
5781
+ return /^\d+$/.test(key);
5782
+ }
5783
+ function resolveKey(key) {
5784
+ return isNumericKey(key) ? Number.parseInt(key, 10) : key;
5785
+ }
5786
+ function getItem(container, key) {
5787
+ if (Array.isArray(container)) return container[key];
5788
+ return container[key];
5789
+ }
5790
+ function setItem(container, key, value) {
5791
+ if (Array.isArray(container)) container[key] = value;
5792
+ else container[key] = value;
5793
+ }
5794
+ function ensureArray(container, key) {
5795
+ const existing = getItem(container, key);
5796
+ const arr = Array.isArray(existing) ? [...existing] : [];
5797
+ setItem(container, key, arr);
5798
+ return arr;
5799
+ }
5800
+ function ensureObject(container, key) {
5801
+ const existing = getItem(container, key);
5802
+ const obj = isPlainObject(existing) ? { ...existing } : {};
5803
+ setItem(container, key, obj);
5804
+ return obj;
5805
+ }
5806
+ function stepIntoNested(container, key, nextKey) {
5807
+ const resolved = resolveKey(key);
5808
+ if (nextKey !== void 0 && isNumericKey(nextKey)) {
5809
+ return ensureArray(container, resolved);
5810
+ }
5811
+ return ensureObject(container, resolved);
5812
+ }
5813
+ function setNestedValue(obj, path50, value) {
5814
+ const keys = path50.split(".");
5815
+ const result = { ...obj };
5816
+ let current = result;
5817
+ for (let i = 0; i < keys.length - 1; i++) {
5818
+ current = stepIntoNested(current, keys[i], keys[i + 1]);
5819
+ }
5820
+ setItem(current, resolveKey(keys[keys.length - 1]), value);
5821
+ return result;
5822
+ }
5823
+
5824
+ // src/commands/config/index.ts
5825
+ function coerceValue(value) {
5826
+ if (value === "true") return true;
5827
+ if (value === "false") return false;
5828
+ return value;
5829
+ }
5830
+ function formatIssuePath(issue, key) {
5831
+ return issue.path.length > 0 ? issue.path.join(".") : key;
5832
+ }
5833
+ function printValidationErrors(issues, key) {
5834
+ for (const issue of issues) {
5835
+ console.error(
5836
+ chalk71.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
5837
+ );
5838
+ }
5839
+ }
5840
+ function exitValidationFailed(issues, key) {
5841
+ printValidationErrors(issues, key);
5842
+ process.exit(1);
5843
+ }
5844
+ function validateConfig(updated, key) {
5845
+ const result = assistConfigSchema.safeParse(updated);
5846
+ if (!result.success) return exitValidationFailed(result.error.issues, key);
5847
+ return updated;
5848
+ }
5849
+ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
5850
+ function assertNotGlobalOnly(key, global) {
5851
+ if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
5852
+ console.error(
5853
+ chalk71.red(
5854
+ `"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
5855
+ )
5856
+ );
5857
+ process.exit(1);
5858
+ }
5859
+ }
5860
+ function applyConfigSet(key, coerced, global) {
5861
+ assertNotGlobalOnly(key, global);
5862
+ const raw = global ? loadGlobalConfigRaw() : loadProjectConfig();
5863
+ const updated = setNestedValue(raw, key, coerced);
5864
+ validateConfig(updated, key);
5865
+ if (global) {
5866
+ saveGlobalConfig(updated);
5867
+ } else {
5868
+ saveConfig(updated);
5869
+ }
5870
+ }
5871
+ function configSet(key, value, options2 = {}) {
5872
+ const coerced = coerceValue(value);
5873
+ applyConfigSet(key, coerced, options2.global ?? false);
5874
+ const target = options2.global ? "global" : "project";
5875
+ console.log(
5876
+ chalk71.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
5877
+ );
5878
+ }
5879
+ function configList() {
5880
+ const config = loadConfig();
5881
+ console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
5882
+ }
5883
+
5884
+ // src/commands/config/configGet.ts
5885
+ import chalk72 from "chalk";
5886
+
5887
+ // src/commands/config/getNestedValue.ts
5888
+ function isTraversable(value) {
5889
+ return value !== null && value !== void 0 && typeof value === "object";
5890
+ }
5891
+ function stepInto(current, key) {
5892
+ return isTraversable(current) ? current[key] : void 0;
5893
+ }
5894
+ function getNestedValue(obj, path50) {
5895
+ let current = obj;
5896
+ for (const key of path50.split(".")) current = stepInto(current, key);
5897
+ return current;
5898
+ }
5899
+
5900
+ // src/commands/config/configGet.ts
5901
+ function configGet(key) {
5902
+ console.log(
5903
+ formatOutput(
5904
+ requireNestedValue(loadConfig(), key)
5905
+ )
5906
+ );
5907
+ }
5908
+ function formatOutput(value) {
5909
+ return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
5910
+ }
5911
+ function requireNestedValue(config, key) {
5912
+ const value = getNestedValue(config, key);
5913
+ if (value === void 0) return exitKeyNotSet(key);
5914
+ return value;
5915
+ }
5916
+ function exitKeyNotSet(key) {
5917
+ console.error(chalk72.red(`Key "${key}" is not set`));
5918
+ process.exit(1);
5919
+ }
5920
+
5921
+ // src/commands/registerConfig.ts
5922
+ function registerConfig(program2) {
5923
+ const configCommand = program2.command("config").description("View and modify assist.yml configuration");
5924
+ configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").action((key, value, options2) => configSet(key, value, options2));
5925
+ configCommand.command("get <key>").description("Get a config value").action(configGet);
5926
+ configCommand.command("list").description("List all config values").action(configList);
5927
+ }
5928
+
5820
5929
  // src/commands/deploy/redirect.ts
5821
5930
  import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
5822
5931
  import chalk73 from "chalk";
@@ -5854,7 +5963,7 @@ function registerDeploy(program2) {
5854
5963
  }
5855
5964
 
5856
5965
  // src/commands/devlog/list/index.ts
5857
- import { execSync as execSync18 } from "child_process";
5966
+ import { execSync as execSync19 } from "child_process";
5858
5967
  import { basename as basename3 } from "path";
5859
5968
 
5860
5969
  // src/commands/devlog/loadBlogSkipDays.ts
@@ -5869,7 +5978,7 @@ function loadBlogSkipDays(repoName) {
5869
5978
  }
5870
5979
 
5871
5980
  // src/commands/devlog/shared.ts
5872
- import { execSync as execSync17 } from "child_process";
5981
+ import { execSync as execSync18 } from "child_process";
5873
5982
  import chalk74 from "chalk";
5874
5983
 
5875
5984
  // src/commands/devlog/loadDevlogEntries.ts
@@ -5939,7 +6048,7 @@ function loadAllDevlogLatestDates() {
5939
6048
  // src/commands/devlog/shared.ts
5940
6049
  function getCommitFiles(hash) {
5941
6050
  try {
5942
- const output = execSync17(`git show --name-only --format="" ${hash}`, {
6051
+ const output = execSync18(`git show --name-only --format="" ${hash}`, {
5943
6052
  encoding: "utf-8"
5944
6053
  });
5945
6054
  return output.trim().split("\n").filter(Boolean);
@@ -6010,7 +6119,7 @@ function list3(options2) {
6010
6119
  const devlogEntries = loadDevlogEntries(repoName);
6011
6120
  const reverseFlag = options2.reverse ? "--reverse " : "";
6012
6121
  const limitFlag = options2.reverse ? "" : "-n 500 ";
6013
- const output = execSync18(
6122
+ const output = execSync19(
6014
6123
  `git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
6015
6124
  { encoding: "utf-8" }
6016
6125
  );
@@ -6036,11 +6145,11 @@ function list3(options2) {
6036
6145
  }
6037
6146
 
6038
6147
  // src/commands/devlog/getLastVersionInfo.ts
6039
- import { execSync as execSync19 } from "child_process";
6148
+ import { execSync as execSync20 } from "child_process";
6040
6149
  import semver from "semver";
6041
6150
  function getVersionAtCommit(hash) {
6042
6151
  try {
6043
- const content = execSync19(`git show ${hash}:package.json`, {
6152
+ const content = execSync20(`git show ${hash}:package.json`, {
6044
6153
  encoding: "utf-8"
6045
6154
  });
6046
6155
  const pkg = JSON.parse(content);
@@ -6055,7 +6164,7 @@ function stripToMinor(version2) {
6055
6164
  }
6056
6165
  function getLastVersionInfoFromGit() {
6057
6166
  try {
6058
- const output = execSync19(
6167
+ const output = execSync20(
6059
6168
  "git log -1 --pretty=format:'%ad|%h' --date=short",
6060
6169
  {
6061
6170
  encoding: "utf-8"
@@ -6099,7 +6208,7 @@ function bumpVersion(version2, type) {
6099
6208
  }
6100
6209
 
6101
6210
  // src/commands/devlog/next/displayNextEntry/index.ts
6102
- import { execSync as execSync20 } from "child_process";
6211
+ import { execSync as execSync21 } from "child_process";
6103
6212
  import chalk77 from "chalk";
6104
6213
 
6105
6214
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
@@ -6133,7 +6242,7 @@ function findTargetDate(commitsByDate, skipDays) {
6133
6242
  return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
6134
6243
  }
6135
6244
  function fetchCommitsByDate(ignore2, lastDate) {
6136
- const output = execSync20(
6245
+ const output = execSync21(
6137
6246
  "git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
6138
6247
  { encoding: "utf-8" }
6139
6248
  );
@@ -6211,7 +6320,7 @@ function next2(options2) {
6211
6320
  }
6212
6321
 
6213
6322
  // src/commands/devlog/repos/index.ts
6214
- import { execSync as execSync21 } from "child_process";
6323
+ import { execSync as execSync22 } from "child_process";
6215
6324
 
6216
6325
  // src/commands/devlog/repos/printReposTable.ts
6217
6326
  import chalk78 from "chalk";
@@ -6246,7 +6355,7 @@ function getStatus(lastPush, lastDevlog) {
6246
6355
  return lastDevlog < lastPush ? "outdated" : "ok";
6247
6356
  }
6248
6357
  function fetchRepos(days, all) {
6249
- const json = execSync21(
6358
+ const json = execSync22(
6250
6359
  "gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
6251
6360
  { encoding: "utf-8" }
6252
6361
  );
@@ -6606,7 +6715,7 @@ async function deps(csprojPath, options2) {
6606
6715
  }
6607
6716
 
6608
6717
  // src/commands/dotnet/getChangedCsFiles.ts
6609
- import { execSync as execSync22 } from "child_process";
6718
+ import { execSync as execSync23 } from "child_process";
6610
6719
  var SCOPE_ALL = "all";
6611
6720
  var SCOPE_BASE = "base:";
6612
6721
  var SCOPE_COMMIT = "commit:";
@@ -6630,7 +6739,7 @@ function getChangedCsFiles(scope) {
6630
6739
  } else {
6631
6740
  cmd = "git diff --name-only HEAD";
6632
6741
  }
6633
- const output = execSync22(cmd, { encoding: "utf-8" }).trim();
6742
+ const output = execSync23(cmd, { encoding: "utf-8" }).trim();
6634
6743
  if (output === "") return [];
6635
6744
  return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
6636
6745
  }
@@ -6828,14 +6937,14 @@ function parseInspectReport(json) {
6828
6937
  }
6829
6938
 
6830
6939
  // src/commands/dotnet/runInspectCode.ts
6831
- import { execSync as execSync23 } from "child_process";
6940
+ import { execSync as execSync24 } from "child_process";
6832
6941
  import { existsSync as existsSync26, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
6833
6942
  import { tmpdir as tmpdir2 } from "os";
6834
6943
  import path26 from "path";
6835
6944
  import chalk88 from "chalk";
6836
6945
  function assertJbInstalled() {
6837
6946
  try {
6838
- execSync23("jb inspectcode --version", { stdio: "pipe" });
6947
+ execSync24("jb inspectcode --version", { stdio: "pipe" });
6839
6948
  } catch {
6840
6949
  console.error(chalk88.red("jb is not installed. Install with:"));
6841
6950
  console.error(
@@ -6849,7 +6958,7 @@ function runInspectCode(slnPath, include, swea) {
6849
6958
  const includeFlag = include ? ` --include="${include}"` : "";
6850
6959
  const sweaFlag = swea ? " --swea" : "";
6851
6960
  try {
6852
- execSync23(
6961
+ execSync24(
6853
6962
  `jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
6854
6963
  { stdio: "pipe" }
6855
6964
  );
@@ -6870,7 +6979,7 @@ function runInspectCode(slnPath, include, swea) {
6870
6979
  }
6871
6980
 
6872
6981
  // src/commands/dotnet/runRoslynInspect.ts
6873
- import { execSync as execSync24 } from "child_process";
6982
+ import { execSync as execSync25 } from "child_process";
6874
6983
  import chalk89 from "chalk";
6875
6984
  function resolveMsbuildPath() {
6876
6985
  const config = loadConfig();
@@ -6880,7 +6989,7 @@ function resolveMsbuildPath() {
6880
6989
  function assertMsbuildInstalled() {
6881
6990
  const msbuild = resolveMsbuildPath();
6882
6991
  try {
6883
- execSync24(`"${msbuild}" -version`, { stdio: "pipe" });
6992
+ execSync25(`"${msbuild}" -version`, { stdio: "pipe" });
6884
6993
  } catch {
6885
6994
  console.error(chalk89.red(`msbuild not found at: ${msbuild}`));
6886
6995
  console.error(
@@ -6906,7 +7015,7 @@ function runRoslynInspect(slnPath) {
6906
7015
  const msbuild = resolveMsbuildPath();
6907
7016
  let output;
6908
7017
  try {
6909
- output = execSync24(
7018
+ output = execSync25(
6910
7019
  `"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
6911
7020
  { encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
6912
7021
  );
@@ -7038,12 +7147,12 @@ function adfToText(doc) {
7038
7147
  }
7039
7148
 
7040
7149
  // src/commands/jira/fetchIssue.ts
7041
- import { execSync as execSync25 } from "child_process";
7150
+ import { execSync as execSync26 } from "child_process";
7042
7151
  import chalk91 from "chalk";
7043
7152
  function fetchIssue(issueKey, fields) {
7044
7153
  let result;
7045
7154
  try {
7046
- result = execSync25(
7155
+ result = execSync26(
7047
7156
  `acli jira workitem view ${issueKey} -f ${fields} --json`,
7048
7157
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
7049
7158
  );
@@ -7089,7 +7198,7 @@ function acceptanceCriteria(issueKey) {
7089
7198
  }
7090
7199
 
7091
7200
  // src/commands/jira/jiraAuth.ts
7092
- import { execSync as execSync26 } from "child_process";
7201
+ import { execSync as execSync27 } from "child_process";
7093
7202
 
7094
7203
  // src/shared/loadJson.ts
7095
7204
  import { existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
@@ -7153,7 +7262,7 @@ async function jiraAuth() {
7153
7262
  console.error("All fields are required.");
7154
7263
  process.exit(1);
7155
7264
  }
7156
- execSync26(`acli jira auth login --site ${site} --email "${email}" --token`, {
7265
+ execSync27(`acli jira auth login --site ${site} --email "${email}" --token`, {
7157
7266
  encoding: "utf-8",
7158
7267
  input: token,
7159
7268
  stdio: ["pipe", "inherit", "inherit"]
@@ -7434,7 +7543,7 @@ import { tmpdir as tmpdir3 } from "os";
7434
7543
  import { join as join25 } from "path";
7435
7544
 
7436
7545
  // src/commands/prs/shared.ts
7437
- import { execSync as execSync27 } from "child_process";
7546
+ import { execSync as execSync28 } from "child_process";
7438
7547
  function isGhNotInstalled(error) {
7439
7548
  if (error instanceof Error) {
7440
7549
  const msg = error.message.toLowerCase();
@@ -7450,14 +7559,14 @@ function isNotFound(error) {
7450
7559
  }
7451
7560
  function getRepoInfo() {
7452
7561
  const repoInfo = JSON.parse(
7453
- execSync27("gh repo view --json owner,name", { encoding: "utf-8" })
7562
+ execSync28("gh repo view --json owner,name", { encoding: "utf-8" })
7454
7563
  );
7455
7564
  return { org: repoInfo.owner.login, repo: repoInfo.name };
7456
7565
  }
7457
7566
  function getCurrentPrNumber() {
7458
7567
  try {
7459
7568
  const prInfo = JSON.parse(
7460
- execSync27("gh pr view --json number", { encoding: "utf-8" })
7569
+ execSync28("gh pr view --json number", { encoding: "utf-8" })
7461
7570
  );
7462
7571
  return prInfo.number;
7463
7572
  } catch (error) {
@@ -7471,7 +7580,7 @@ function getCurrentPrNumber() {
7471
7580
  function getCurrentPrNodeId() {
7472
7581
  try {
7473
7582
  const prInfo = JSON.parse(
7474
- execSync27("gh pr view --json id", { encoding: "utf-8" })
7583
+ execSync28("gh pr view --json id", { encoding: "utf-8" })
7475
7584
  );
7476
7585
  return prInfo.id;
7477
7586
  } catch (error) {
@@ -7542,10 +7651,10 @@ function comment2(path50, line, body) {
7542
7651
  }
7543
7652
 
7544
7653
  // src/commands/prs/fixed.ts
7545
- import { execSync as execSync29 } from "child_process";
7654
+ import { execSync as execSync30 } from "child_process";
7546
7655
 
7547
7656
  // src/commands/prs/resolveCommentWithReply.ts
7548
- import { execSync as execSync28 } from "child_process";
7657
+ import { execSync as execSync29 } from "child_process";
7549
7658
  import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
7550
7659
  import { tmpdir as tmpdir4 } from "os";
7551
7660
  import { join as join27 } from "path";
@@ -7575,7 +7684,7 @@ function deleteCommentsCache(prNumber) {
7575
7684
 
7576
7685
  // src/commands/prs/resolveCommentWithReply.ts
7577
7686
  function replyToComment(org, repo, prNumber, commentId, message) {
7578
- execSync28(
7687
+ execSync29(
7579
7688
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
7580
7689
  { stdio: ["inherit", "pipe", "inherit"] }
7581
7690
  );
@@ -7585,7 +7694,7 @@ function resolveThread(threadId) {
7585
7694
  const queryFile = join27(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
7586
7695
  writeFileSync22(queryFile, mutation);
7587
7696
  try {
7588
- execSync28(
7697
+ execSync29(
7589
7698
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
7590
7699
  { stdio: ["inherit", "pipe", "inherit"] }
7591
7700
  );
@@ -7637,7 +7746,7 @@ function resolveCommentWithReply(commentId, message) {
7637
7746
  // src/commands/prs/fixed.ts
7638
7747
  function verifySha(sha) {
7639
7748
  try {
7640
- return execSync29(`git rev-parse --verify ${sha}`, {
7749
+ return execSync30(`git rev-parse --verify ${sha}`, {
7641
7750
  encoding: "utf-8"
7642
7751
  }).trim();
7643
7752
  } catch {
@@ -7651,7 +7760,7 @@ function fixed(commentId, sha) {
7651
7760
  const { org, repo } = getRepoInfo();
7652
7761
  const repoUrl = `https://github.com/${org}/${repo}`;
7653
7762
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
7654
- execSync29("git push", { stdio: "inherit" });
7763
+ execSync30("git push", { stdio: "inherit" });
7655
7764
  resolveCommentWithReply(commentId, message);
7656
7765
  } catch (error) {
7657
7766
  if (isGhNotInstalled(error)) {
@@ -7669,7 +7778,7 @@ import { join as join29 } from "path";
7669
7778
  import { stringify } from "yaml";
7670
7779
 
7671
7780
  // src/commands/prs/fetchThreadIds.ts
7672
- import { execSync as execSync30 } from "child_process";
7781
+ import { execSync as execSync31 } from "child_process";
7673
7782
  import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync23 } from "fs";
7674
7783
  import { tmpdir as tmpdir5 } from "os";
7675
7784
  import { join as join28 } from "path";
@@ -7678,7 +7787,7 @@ function fetchThreadIds(org, repo, prNumber) {
7678
7787
  const queryFile = join28(tmpdir5(), `gh-query-${Date.now()}.graphql`);
7679
7788
  writeFileSync23(queryFile, THREAD_QUERY);
7680
7789
  try {
7681
- const result = execSync30(
7790
+ const result = execSync31(
7682
7791
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
7683
7792
  { encoding: "utf-8" }
7684
7793
  );
@@ -7700,9 +7809,9 @@ function fetchThreadIds(org, repo, prNumber) {
7700
7809
  }
7701
7810
 
7702
7811
  // src/commands/prs/listComments/fetchReviewComments.ts
7703
- import { execSync as execSync31 } from "child_process";
7812
+ import { execSync as execSync32 } from "child_process";
7704
7813
  function fetchJson(endpoint) {
7705
- const result = execSync31(`gh api --paginate ${endpoint}`, {
7814
+ const result = execSync32(`gh api --paginate ${endpoint}`, {
7706
7815
  encoding: "utf-8"
7707
7816
  });
7708
7817
  if (!result.trim()) return [];
@@ -7841,7 +7950,7 @@ async function listComments() {
7841
7950
  }
7842
7951
 
7843
7952
  // src/commands/prs/prs/index.ts
7844
- import { execSync as execSync32 } from "child_process";
7953
+ import { execSync as execSync33 } from "child_process";
7845
7954
 
7846
7955
  // src/commands/prs/prs/displayPaginated/index.ts
7847
7956
  import enquirer9 from "enquirer";
@@ -7947,7 +8056,7 @@ async function displayPaginated(pullRequests) {
7947
8056
  async function prs(options2) {
7948
8057
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
7949
8058
  try {
7950
- const result = execSync32(
8059
+ const result = execSync33(
7951
8060
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
7952
8061
  { encoding: "utf-8" }
7953
8062
  );
@@ -7970,7 +8079,7 @@ async function prs(options2) {
7970
8079
  }
7971
8080
 
7972
8081
  // src/commands/prs/wontfix.ts
7973
- import { execSync as execSync33 } from "child_process";
8082
+ import { execSync as execSync34 } from "child_process";
7974
8083
  function validateReason(reason) {
7975
8084
  const lowerReason = reason.toLowerCase();
7976
8085
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -7987,7 +8096,7 @@ function validateShaReferences(reason) {
7987
8096
  const invalidShas = [];
7988
8097
  for (const sha of shas) {
7989
8098
  try {
7990
- execSync33(`git cat-file -t ${sha}`, { stdio: "pipe" });
8099
+ execSync34(`git cat-file -t ${sha}`, { stdio: "pipe" });
7991
8100
  } catch {
7992
8101
  invalidShas.push(sha);
7993
8102
  }
@@ -8101,10 +8210,10 @@ import chalk100 from "chalk";
8101
8210
  import Enquirer2 from "enquirer";
8102
8211
 
8103
8212
  // src/commands/ravendb/searchItems.ts
8104
- import { execSync as execSync34 } from "child_process";
8213
+ import { execSync as execSync35 } from "child_process";
8105
8214
  import chalk99 from "chalk";
8106
8215
  function opExec(args) {
8107
- return execSync34(`op ${args}`, {
8216
+ return execSync35(`op ${args}`, {
8108
8217
  encoding: "utf-8",
8109
8218
  stdio: ["pipe", "pipe", "pipe"]
8110
8219
  }).trim();
@@ -8256,7 +8365,7 @@ ${errorText}`
8256
8365
  }
8257
8366
 
8258
8367
  // src/commands/ravendb/resolveOpSecret.ts
8259
- import { execSync as execSync35 } from "child_process";
8368
+ import { execSync as execSync36 } from "child_process";
8260
8369
  import chalk104 from "chalk";
8261
8370
  function resolveOpSecret(reference) {
8262
8371
  if (!reference.startsWith("op://")) {
@@ -8264,7 +8373,7 @@ function resolveOpSecret(reference) {
8264
8373
  process.exit(1);
8265
8374
  }
8266
8375
  try {
8267
- return execSync35(`op read "${reference}"`, {
8376
+ return execSync36(`op read "${reference}"`, {
8268
8377
  encoding: "utf-8",
8269
8378
  stdio: ["pipe", "pipe", "pipe"]
8270
8379
  }).trim();
@@ -8513,7 +8622,7 @@ Refactor check failed:
8513
8622
  }
8514
8623
 
8515
8624
  // src/commands/refactor/check/getViolations/index.ts
8516
- import { execSync as execSync36 } from "child_process";
8625
+ import { execSync as execSync37 } from "child_process";
8517
8626
  import fs16 from "fs";
8518
8627
  import { minimatch as minimatch4 } from "minimatch";
8519
8628
 
@@ -8563,7 +8672,7 @@ function getGitFiles(options2) {
8563
8672
  }
8564
8673
  const files = /* @__PURE__ */ new Set();
8565
8674
  if (options2.staged || options2.modified) {
8566
- const staged = execSync36("git diff --cached --name-only", {
8675
+ const staged = execSync37("git diff --cached --name-only", {
8567
8676
  encoding: "utf-8"
8568
8677
  });
8569
8678
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -8571,7 +8680,7 @@ function getGitFiles(options2) {
8571
8680
  }
8572
8681
  }
8573
8682
  if (options2.unstaged || options2.modified) {
8574
- const unstaged = execSync36("git diff --name-only", { encoding: "utf-8" });
8683
+ const unstaged = execSync37("git diff --name-only", { encoding: "utf-8" });
8575
8684
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
8576
8685
  files.add(file);
8577
8686
  }
@@ -10961,7 +11070,7 @@ import { mkdirSync as mkdirSync11 } from "fs";
10961
11070
  import { join as join39 } from "path";
10962
11071
 
10963
11072
  // src/commands/voice/checkLockFile.ts
10964
- import { execSync as execSync37 } from "child_process";
11073
+ import { execSync as execSync38 } from "child_process";
10965
11074
  import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
10966
11075
  import { join as join38 } from "path";
10967
11076
  function isProcessAlive2(pid) {
@@ -10990,7 +11099,7 @@ function bootstrapVenv() {
10990
11099
  if (existsSync36(getVenvPython())) return;
10991
11100
  console.log("Setting up Python environment...");
10992
11101
  const pythonDir = getPythonDir();
10993
- execSync37(
11102
+ execSync38(
10994
11103
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
10995
11104
  {
10996
11105
  stdio: "inherit",
@@ -11157,11 +11266,11 @@ import { randomBytes } from "crypto";
11157
11266
  import chalk128 from "chalk";
11158
11267
 
11159
11268
  // src/lib/openBrowser.ts
11160
- import { execSync as execSync38 } from "child_process";
11269
+ import { execSync as execSync39 } from "child_process";
11161
11270
  function tryExec(commands) {
11162
11271
  for (const cmd of commands) {
11163
11272
  try {
11164
- execSync38(cmd);
11273
+ execSync39(cmd);
11165
11274
  return true;
11166
11275
  } catch {
11167
11276
  }
@@ -11387,7 +11496,7 @@ function registerRoam(program2) {
11387
11496
  }
11388
11497
 
11389
11498
  // src/commands/run/index.ts
11390
- import { execSync as execSync39 } from "child_process";
11499
+ import { execSync as execSync40 } from "child_process";
11391
11500
 
11392
11501
  // src/commands/run/formatConfiguredCommands.ts
11393
11502
  function formatConfiguredCommands() {
@@ -11552,7 +11661,7 @@ function listRunConfigs() {
11552
11661
  function runPreCommands(pre) {
11553
11662
  for (const cmd of pre) {
11554
11663
  try {
11555
- execSync39(cmd, { stdio: "inherit" });
11664
+ execSync40(cmd, { stdio: "inherit" });
11556
11665
  } catch (err) {
11557
11666
  const code = err && typeof err === "object" && "status" in err ? err.status : 1;
11558
11667
  process.exit(code);
@@ -11575,7 +11684,7 @@ function run3(name, args) {
11575
11684
  }
11576
11685
 
11577
11686
  // src/commands/screenshot/index.ts
11578
- import { execSync as execSync40 } from "child_process";
11687
+ import { execSync as execSync41 } from "child_process";
11579
11688
  import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
11580
11689
  import { tmpdir as tmpdir6 } from "os";
11581
11690
  import { join as join43, resolve as resolve5 } from "path";
@@ -11718,7 +11827,7 @@ function runPowerShellScript(processName, outputPath) {
11718
11827
  const scriptPath = join43(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
11719
11828
  writeFileSync29(scriptPath, captureWindowPs1, "utf-8");
11720
11829
  try {
11721
- execSync40(
11830
+ execSync41(
11722
11831
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
11723
11832
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
11724
11833
  );
@@ -11919,7 +12028,7 @@ function syncCommands(claudeDir, targetBase) {
11919
12028
  }
11920
12029
 
11921
12030
  // src/commands/update.ts
11922
- import { execSync as execSync41 } from "child_process";
12031
+ import { execSync as execSync42 } from "child_process";
11923
12032
  import * as path49 from "path";
11924
12033
  function isGlobalNpmInstall(dir) {
11925
12034
  try {
@@ -11927,7 +12036,7 @@ function isGlobalNpmInstall(dir) {
11927
12036
  if (resolved.split(path49.sep).includes("node_modules")) {
11928
12037
  return true;
11929
12038
  }
11930
- const globalPrefix = execSync41("npm prefix -g", { stdio: "pipe" }).toString().trim();
12039
+ const globalPrefix = execSync42("npm prefix -g", { stdio: "pipe" }).toString().trim();
11931
12040
  return resolved.toLowerCase().startsWith(path49.resolve(globalPrefix).toLowerCase());
11932
12041
  } catch {
11933
12042
  return false;
@@ -11938,18 +12047,18 @@ async function update2() {
11938
12047
  console.log(`Assist is installed at: ${installDir}`);
11939
12048
  if (isGitRepo(installDir)) {
11940
12049
  console.log("Detected git repo installation, pulling latest...");
11941
- execSync41("git pull", { cwd: installDir, stdio: "inherit" });
12050
+ execSync42("git pull", { cwd: installDir, stdio: "inherit" });
11942
12051
  console.log("Installing dependencies...");
11943
- execSync41("npm i", { cwd: installDir, stdio: "inherit" });
12052
+ execSync42("npm i", { cwd: installDir, stdio: "inherit" });
11944
12053
  console.log("Building...");
11945
- execSync41("npm run build", { cwd: installDir, stdio: "inherit" });
12054
+ execSync42("npm run build", { cwd: installDir, stdio: "inherit" });
11946
12055
  console.log("Syncing commands...");
11947
- execSync41("assist sync", { stdio: "inherit" });
12056
+ execSync42("assist sync", { stdio: "inherit" });
11948
12057
  } else if (isGlobalNpmInstall(installDir)) {
11949
12058
  console.log("Detected global npm installation, updating...");
11950
- execSync41("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
12059
+ execSync42("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
11951
12060
  console.log("Syncing commands...");
11952
- execSync41("assist sync", { stdio: "inherit" });
12061
+ execSync42("assist sync", { stdio: "inherit" });
11953
12062
  } else {
11954
12063
  console.error(
11955
12064
  "Could not determine installation method. Expected a git repo or global npm install."
@@ -11964,10 +12073,7 @@ program.name("assist").description("CLI application").version(package_default.ve
11964
12073
  program.command("sync").description("Copy command files to ~/.claude/commands").option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
11965
12074
  program.command("init").description("Initialize VS Code and verify configurations").action(init4);
11966
12075
  program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
11967
- var configCommand = program.command("config").description("View and modify assist.yml configuration");
11968
- configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").action((key, value, options2) => configSet(key, value, options2));
11969
- configCommand.command("get <key>").description("Get a config value").action(configGet);
11970
- configCommand.command("list").description("List all config values").action(configList);
12076
+ registerConfig(program);
11971
12077
  var runCommand = program.command("run").description("Run a configured command from assist.yml").argument("[name]", "Name of the configured command").argument("[args...]", "Arguments to pass to the command").allowUnknownOption().addHelpText("after", () => formatConfiguredCommands()).action((name, args) => run3(name, args));
11972
12078
  runCommand.command("list").description("List configured run commands").action(listRunConfigs);
11973
12079
  runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").addHelpText(
@@ -11986,6 +12092,7 @@ program.command("notify").description(
11986
12092
  program.command("update").description("Update assist to the latest version and sync commands").action(update2);
11987
12093
  program.command("coverage").description("Print global statement coverage percentage").action(coverage);
11988
12094
  program.command("screenshot").description("Capture a screenshot of a running application window").argument("<process>", "Name of the running process (e.g. notepad, code)").action(screenshot);
12095
+ registerActivity(program);
11989
12096
  registerCliHook(program);
11990
12097
  registerJira(program);
11991
12098
  registerPrs(program);