@staff0rd/assist 0.175.0 → 0.176.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/README.md +5 -0
- package/allowed.cli-writes +3 -0
- package/claude/commands/refine.md +74 -0
- package/dist/allowed.cli-writes +3 -0
- package/dist/index.js +687 -450
- package/package.json +1 -1
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.
|
|
9
|
+
version: "0.176.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1500,6 +1500,41 @@ async function launchMode(slashCommand) {
|
|
|
1500
1500
|
}
|
|
1501
1501
|
}
|
|
1502
1502
|
|
|
1503
|
+
// src/commands/backlog/refine.ts
|
|
1504
|
+
import chalk17 from "chalk";
|
|
1505
|
+
import enquirer3 from "enquirer";
|
|
1506
|
+
async function pickItemForRefine() {
|
|
1507
|
+
const items = loadBacklog();
|
|
1508
|
+
const active = items.filter(
|
|
1509
|
+
(i) => i.status === "todo" || i.status === "in-progress"
|
|
1510
|
+
);
|
|
1511
|
+
if (active.length === 0) {
|
|
1512
|
+
console.log(chalk17.yellow("No active backlog items to refine."));
|
|
1513
|
+
return void 0;
|
|
1514
|
+
}
|
|
1515
|
+
if (active.length === 1) {
|
|
1516
|
+
const item = active[0];
|
|
1517
|
+
console.log(chalk17.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1518
|
+
return String(item.id);
|
|
1519
|
+
}
|
|
1520
|
+
const { selected } = await exitOnCancel(
|
|
1521
|
+
enquirer3.prompt({
|
|
1522
|
+
type: "select",
|
|
1523
|
+
name: "selected",
|
|
1524
|
+
message: "Choose a backlog item to refine:",
|
|
1525
|
+
choices: active.map((item) => ({
|
|
1526
|
+
name: `${typeLabel(item.type)} #${item.id}: ${item.name}`
|
|
1527
|
+
}))
|
|
1528
|
+
})
|
|
1529
|
+
);
|
|
1530
|
+
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
1531
|
+
}
|
|
1532
|
+
async function refine(id) {
|
|
1533
|
+
const itemId = id ?? await pickItemForRefine();
|
|
1534
|
+
if (!itemId) return;
|
|
1535
|
+
await launchMode(`refine ${itemId}`);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1503
1538
|
// src/commands/commit.ts
|
|
1504
1539
|
import { execSync } from "child_process";
|
|
1505
1540
|
|
|
@@ -1507,7 +1542,7 @@ import { execSync } from "child_process";
|
|
|
1507
1542
|
import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
1508
1543
|
import { homedir } from "os";
|
|
1509
1544
|
import { basename, dirname as dirname2, join as join8 } from "path";
|
|
1510
|
-
import
|
|
1545
|
+
import chalk18 from "chalk";
|
|
1511
1546
|
import { stringify as stringifyYaml } from "yaml";
|
|
1512
1547
|
|
|
1513
1548
|
// src/shared/loadRawYaml.ts
|
|
@@ -1703,7 +1738,7 @@ function getTranscriptConfig() {
|
|
|
1703
1738
|
const config = loadConfig();
|
|
1704
1739
|
if (!config.transcript) {
|
|
1705
1740
|
console.error(
|
|
1706
|
-
|
|
1741
|
+
chalk18.red(
|
|
1707
1742
|
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
1708
1743
|
)
|
|
1709
1744
|
);
|
|
@@ -1792,7 +1827,7 @@ function commit(args) {
|
|
|
1792
1827
|
}
|
|
1793
1828
|
|
|
1794
1829
|
// src/commands/config/index.ts
|
|
1795
|
-
import
|
|
1830
|
+
import chalk19 from "chalk";
|
|
1796
1831
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
1797
1832
|
|
|
1798
1833
|
// src/commands/config/setNestedValue.ts
|
|
@@ -1855,7 +1890,7 @@ function formatIssuePath(issue, key) {
|
|
|
1855
1890
|
function printValidationErrors(issues, key) {
|
|
1856
1891
|
for (const issue of issues) {
|
|
1857
1892
|
console.error(
|
|
1858
|
-
|
|
1893
|
+
chalk19.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
1859
1894
|
);
|
|
1860
1895
|
}
|
|
1861
1896
|
}
|
|
@@ -1872,7 +1907,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
1872
1907
|
function assertNotGlobalOnly(key, global) {
|
|
1873
1908
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
1874
1909
|
console.error(
|
|
1875
|
-
|
|
1910
|
+
chalk19.red(
|
|
1876
1911
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
1877
1912
|
)
|
|
1878
1913
|
);
|
|
@@ -1895,7 +1930,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
1895
1930
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
1896
1931
|
const target = options2.global ? "global" : "project";
|
|
1897
1932
|
console.log(
|
|
1898
|
-
|
|
1933
|
+
chalk19.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
1899
1934
|
);
|
|
1900
1935
|
}
|
|
1901
1936
|
function configList() {
|
|
@@ -1904,7 +1939,7 @@ function configList() {
|
|
|
1904
1939
|
}
|
|
1905
1940
|
|
|
1906
1941
|
// src/commands/config/configGet.ts
|
|
1907
|
-
import
|
|
1942
|
+
import chalk20 from "chalk";
|
|
1908
1943
|
|
|
1909
1944
|
// src/commands/config/getNestedValue.ts
|
|
1910
1945
|
function isTraversable(value) {
|
|
@@ -1936,7 +1971,7 @@ function requireNestedValue(config, key) {
|
|
|
1936
1971
|
return value;
|
|
1937
1972
|
}
|
|
1938
1973
|
function exitKeyNotSet(key) {
|
|
1939
|
-
console.error(
|
|
1974
|
+
console.error(chalk20.red(`Key "${key}" is not set`));
|
|
1940
1975
|
process.exit(1);
|
|
1941
1976
|
}
|
|
1942
1977
|
|
|
@@ -1956,20 +1991,20 @@ function coverage() {
|
|
|
1956
1991
|
}
|
|
1957
1992
|
|
|
1958
1993
|
// src/commands/verify/init/index.ts
|
|
1959
|
-
import
|
|
1994
|
+
import chalk35 from "chalk";
|
|
1960
1995
|
|
|
1961
1996
|
// src/shared/promptMultiselect.ts
|
|
1962
|
-
import
|
|
1963
|
-
import
|
|
1997
|
+
import chalk21 from "chalk";
|
|
1998
|
+
import enquirer4 from "enquirer";
|
|
1964
1999
|
async function promptMultiselect(message, options2) {
|
|
1965
2000
|
const { selected } = await exitOnCancel(
|
|
1966
|
-
|
|
2001
|
+
enquirer4.prompt({
|
|
1967
2002
|
type: "multiselect",
|
|
1968
2003
|
name: "selected",
|
|
1969
2004
|
message,
|
|
1970
2005
|
choices: options2.map((opt) => ({
|
|
1971
2006
|
name: opt.value,
|
|
1972
|
-
message: `${opt.name} - ${
|
|
2007
|
+
message: `${opt.name} - ${chalk21.dim(opt.description)}`
|
|
1973
2008
|
})),
|
|
1974
2009
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
1975
2010
|
symbols: {
|
|
@@ -1986,7 +2021,7 @@ async function promptMultiselect(message, options2) {
|
|
|
1986
2021
|
// src/shared/readPackageJson.ts
|
|
1987
2022
|
import * as fs from "fs";
|
|
1988
2023
|
import * as path from "path";
|
|
1989
|
-
import
|
|
2024
|
+
import chalk22 from "chalk";
|
|
1990
2025
|
function findPackageJson() {
|
|
1991
2026
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1992
2027
|
if (fs.existsSync(packageJsonPath)) {
|
|
@@ -2000,7 +2035,7 @@ function readPackageJson(filePath) {
|
|
|
2000
2035
|
function requirePackageJson() {
|
|
2001
2036
|
const packageJsonPath = findPackageJson();
|
|
2002
2037
|
if (!packageJsonPath) {
|
|
2003
|
-
console.error(
|
|
2038
|
+
console.error(chalk22.red("No package.json found in current directory"));
|
|
2004
2039
|
process.exit(1);
|
|
2005
2040
|
}
|
|
2006
2041
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -2031,7 +2066,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2031
2066
|
// src/commands/verify/installPackage.ts
|
|
2032
2067
|
import { execSync as execSync3 } from "child_process";
|
|
2033
2068
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
2034
|
-
import
|
|
2069
|
+
import chalk23 from "chalk";
|
|
2035
2070
|
function writePackageJson(filePath, pkg) {
|
|
2036
2071
|
writeFileSync6(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
2037
2072
|
`);
|
|
@@ -2046,12 +2081,12 @@ function addScript(pkg, name, command) {
|
|
|
2046
2081
|
};
|
|
2047
2082
|
}
|
|
2048
2083
|
function installPackage(name, cwd) {
|
|
2049
|
-
console.log(
|
|
2084
|
+
console.log(chalk23.dim(`Installing ${name}...`));
|
|
2050
2085
|
try {
|
|
2051
2086
|
execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2052
2087
|
return true;
|
|
2053
2088
|
} catch {
|
|
2054
|
-
console.error(
|
|
2089
|
+
console.error(chalk23.red(`Failed to install ${name}`));
|
|
2055
2090
|
return false;
|
|
2056
2091
|
}
|
|
2057
2092
|
}
|
|
@@ -2098,9 +2133,9 @@ var expectedScripts = {
|
|
|
2098
2133
|
};
|
|
2099
2134
|
|
|
2100
2135
|
// src/commands/verify/setup/setupBuild.ts
|
|
2101
|
-
import
|
|
2136
|
+
import chalk24 from "chalk";
|
|
2102
2137
|
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
2103
|
-
console.log(
|
|
2138
|
+
console.log(chalk24.blue("\nSetting up build verification..."));
|
|
2104
2139
|
let command;
|
|
2105
2140
|
if (hasVite && hasTypescript) {
|
|
2106
2141
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -2109,21 +2144,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
|
2109
2144
|
} else {
|
|
2110
2145
|
command = "npm run build";
|
|
2111
2146
|
}
|
|
2112
|
-
console.log(
|
|
2147
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2113
2148
|
writer("verify:build", command);
|
|
2114
2149
|
}
|
|
2115
2150
|
async function setupTypecheck(_packageJsonPath, writer) {
|
|
2116
|
-
console.log(
|
|
2151
|
+
console.log(chalk24.blue("\nSetting up typecheck verification..."));
|
|
2117
2152
|
const command = "tsc --noEmit";
|
|
2118
|
-
console.log(
|
|
2153
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2119
2154
|
writer("verify:typecheck", command);
|
|
2120
2155
|
}
|
|
2121
2156
|
|
|
2122
2157
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
2123
2158
|
import * as path2 from "path";
|
|
2124
|
-
import
|
|
2159
|
+
import chalk25 from "chalk";
|
|
2125
2160
|
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
2126
|
-
console.log(
|
|
2161
|
+
console.log(chalk25.blue("\nSetting up jscpd..."));
|
|
2127
2162
|
const cwd = path2.dirname(packageJsonPath);
|
|
2128
2163
|
const pkg = readPackageJson(packageJsonPath);
|
|
2129
2164
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -2135,12 +2170,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
|
|
|
2135
2170
|
|
|
2136
2171
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2137
2172
|
import * as path3 from "path";
|
|
2138
|
-
import
|
|
2173
|
+
import chalk27 from "chalk";
|
|
2139
2174
|
|
|
2140
2175
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
2141
2176
|
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
2142
2177
|
import { join as join10 } from "path";
|
|
2143
|
-
import
|
|
2178
|
+
import chalk26 from "chalk";
|
|
2144
2179
|
function loadKnipConfig(knipJsonPath) {
|
|
2145
2180
|
if (existsSync11(knipJsonPath)) {
|
|
2146
2181
|
return JSON.parse(readFileSync10(knipJsonPath, "utf-8"));
|
|
@@ -2159,16 +2194,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
2159
2194
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
2160
2195
|
`
|
|
2161
2196
|
);
|
|
2162
|
-
console.log(
|
|
2197
|
+
console.log(chalk26.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
2163
2198
|
}
|
|
2164
2199
|
} catch {
|
|
2165
|
-
console.log(
|
|
2200
|
+
console.log(chalk26.yellow("Warning: Could not update knip.json"));
|
|
2166
2201
|
}
|
|
2167
2202
|
}
|
|
2168
2203
|
|
|
2169
2204
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2170
2205
|
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
2171
|
-
console.log(
|
|
2206
|
+
console.log(chalk27.blue("\nSetting up hardcoded colors check..."));
|
|
2172
2207
|
const cwd = path3.dirname(packageJsonPath);
|
|
2173
2208
|
if (!hasOpenColor) {
|
|
2174
2209
|
installPackage("open-color", cwd);
|
|
@@ -2179,9 +2214,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
|
2179
2214
|
|
|
2180
2215
|
// src/commands/verify/setup/setupKnip.ts
|
|
2181
2216
|
import * as path4 from "path";
|
|
2182
|
-
import
|
|
2217
|
+
import chalk28 from "chalk";
|
|
2183
2218
|
async function setupKnip(packageJsonPath, writer) {
|
|
2184
|
-
console.log(
|
|
2219
|
+
console.log(chalk28.blue("\nSetting up knip..."));
|
|
2185
2220
|
const cwd = path4.dirname(packageJsonPath);
|
|
2186
2221
|
const pkg = readPackageJson(packageJsonPath);
|
|
2187
2222
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -2192,20 +2227,20 @@ async function setupKnip(packageJsonPath, writer) {
|
|
|
2192
2227
|
|
|
2193
2228
|
// src/commands/verify/setup/setupLint.ts
|
|
2194
2229
|
import * as path5 from "path";
|
|
2195
|
-
import
|
|
2230
|
+
import chalk31 from "chalk";
|
|
2196
2231
|
|
|
2197
2232
|
// src/commands/lint/init.ts
|
|
2198
2233
|
import { execSync as execSync5 } from "child_process";
|
|
2199
2234
|
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
2200
2235
|
import { dirname as dirname7, join as join11 } from "path";
|
|
2201
2236
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2202
|
-
import
|
|
2237
|
+
import chalk30 from "chalk";
|
|
2203
2238
|
|
|
2204
2239
|
// src/shared/promptConfirm.ts
|
|
2205
|
-
import
|
|
2240
|
+
import enquirer5 from "enquirer";
|
|
2206
2241
|
async function promptConfirm(message, initial = true) {
|
|
2207
2242
|
const { confirmed } = await exitOnCancel(
|
|
2208
|
-
|
|
2243
|
+
enquirer5.prompt({
|
|
2209
2244
|
type: "confirm",
|
|
2210
2245
|
name: "confirmed",
|
|
2211
2246
|
message,
|
|
@@ -2303,7 +2338,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
2303
2338
|
}
|
|
2304
2339
|
|
|
2305
2340
|
// src/utils/printDiff.ts
|
|
2306
|
-
import
|
|
2341
|
+
import chalk29 from "chalk";
|
|
2307
2342
|
import * as diff from "diff";
|
|
2308
2343
|
function normalizeJson(content) {
|
|
2309
2344
|
try {
|
|
@@ -2321,11 +2356,11 @@ function printDiff(oldContent, newContent) {
|
|
|
2321
2356
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
2322
2357
|
for (const line of lines) {
|
|
2323
2358
|
if (change.added) {
|
|
2324
|
-
console.log(
|
|
2359
|
+
console.log(chalk29.green(`+ ${line}`));
|
|
2325
2360
|
} else if (change.removed) {
|
|
2326
|
-
console.log(
|
|
2361
|
+
console.log(chalk29.red(`- ${line}`));
|
|
2327
2362
|
} else {
|
|
2328
|
-
console.log(
|
|
2363
|
+
console.log(chalk29.dim(` ${line}`));
|
|
2329
2364
|
}
|
|
2330
2365
|
}
|
|
2331
2366
|
}
|
|
@@ -2359,10 +2394,10 @@ async function init() {
|
|
|
2359
2394
|
console.log("biome.json already has the correct linter config");
|
|
2360
2395
|
return;
|
|
2361
2396
|
}
|
|
2362
|
-
console.log(
|
|
2397
|
+
console.log(chalk30.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
2363
2398
|
console.log();
|
|
2364
2399
|
printDiff(oldContent, newContent);
|
|
2365
|
-
const confirm = await promptConfirm(
|
|
2400
|
+
const confirm = await promptConfirm(chalk30.red("Update biome.json?"));
|
|
2366
2401
|
if (!confirm) {
|
|
2367
2402
|
console.log("Skipped biome.json update");
|
|
2368
2403
|
return;
|
|
@@ -2373,7 +2408,7 @@ async function init() {
|
|
|
2373
2408
|
|
|
2374
2409
|
// src/commands/verify/setup/setupLint.ts
|
|
2375
2410
|
async function setupLint(packageJsonPath, writer) {
|
|
2376
|
-
console.log(
|
|
2411
|
+
console.log(chalk31.blue("\nSetting up biome..."));
|
|
2377
2412
|
const cwd = path5.dirname(packageJsonPath);
|
|
2378
2413
|
const pkg = readPackageJson(packageJsonPath);
|
|
2379
2414
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -2387,9 +2422,9 @@ async function setupLint(packageJsonPath, writer) {
|
|
|
2387
2422
|
|
|
2388
2423
|
// src/commands/verify/setup/setupMadge.ts
|
|
2389
2424
|
import * as path6 from "path";
|
|
2390
|
-
import
|
|
2425
|
+
import chalk32 from "chalk";
|
|
2391
2426
|
async function setupMadge(packageJsonPath, writer) {
|
|
2392
|
-
console.log(
|
|
2427
|
+
console.log(chalk32.blue("\nSetting up madge..."));
|
|
2393
2428
|
const cwd = path6.dirname(packageJsonPath);
|
|
2394
2429
|
const pkg = readPackageJson(packageJsonPath);
|
|
2395
2430
|
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
@@ -2401,18 +2436,18 @@ async function setupMadge(packageJsonPath, writer) {
|
|
|
2401
2436
|
|
|
2402
2437
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
2403
2438
|
import * as path7 from "path";
|
|
2404
|
-
import
|
|
2439
|
+
import chalk33 from "chalk";
|
|
2405
2440
|
async function setupMaintainability(packageJsonPath, writer) {
|
|
2406
|
-
console.log(
|
|
2441
|
+
console.log(chalk33.blue("\nSetting up maintainability check..."));
|
|
2407
2442
|
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
2408
2443
|
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
2409
2444
|
}
|
|
2410
2445
|
|
|
2411
2446
|
// src/commands/verify/setup/setupTest.ts
|
|
2412
2447
|
import * as path8 from "path";
|
|
2413
|
-
import
|
|
2448
|
+
import chalk34 from "chalk";
|
|
2414
2449
|
async function setupTest(packageJsonPath, writer) {
|
|
2415
|
-
console.log(
|
|
2450
|
+
console.log(chalk34.blue("\nSetting up vitest..."));
|
|
2416
2451
|
const cwd = path8.dirname(packageJsonPath);
|
|
2417
2452
|
const pkg = readPackageJson(packageJsonPath);
|
|
2418
2453
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -2581,25 +2616,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
|
|
|
2581
2616
|
for (const choice of selected) {
|
|
2582
2617
|
await handlers[choice]?.(packageJsonPath, writer);
|
|
2583
2618
|
}
|
|
2584
|
-
console.log(
|
|
2619
|
+
console.log(chalk35.green(`
|
|
2585
2620
|
Added ${selected.length} verify script(s):`));
|
|
2586
2621
|
for (const choice of selected) {
|
|
2587
|
-
console.log(
|
|
2622
|
+
console.log(chalk35.green(` - verify:${choice}`));
|
|
2588
2623
|
}
|
|
2589
|
-
console.log(
|
|
2624
|
+
console.log(chalk35.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
2590
2625
|
}
|
|
2591
2626
|
async function promptForScripts(availableOptions) {
|
|
2592
2627
|
if (availableOptions.length === 0) {
|
|
2593
|
-
console.log(
|
|
2628
|
+
console.log(chalk35.green("All verify scripts are already configured!"));
|
|
2594
2629
|
return null;
|
|
2595
2630
|
}
|
|
2596
|
-
console.log(
|
|
2631
|
+
console.log(chalk35.bold("Available verify scripts to add:\n"));
|
|
2597
2632
|
const selected = await promptMultiselect(
|
|
2598
2633
|
"Select verify scripts to add:",
|
|
2599
2634
|
availableOptions
|
|
2600
2635
|
);
|
|
2601
2636
|
if (selected.length === 0) {
|
|
2602
|
-
console.log(
|
|
2637
|
+
console.log(chalk35.yellow("No scripts selected"));
|
|
2603
2638
|
return null;
|
|
2604
2639
|
}
|
|
2605
2640
|
return selected;
|
|
@@ -2619,17 +2654,17 @@ async function init2() {
|
|
|
2619
2654
|
}
|
|
2620
2655
|
|
|
2621
2656
|
// src/commands/vscode/init/index.ts
|
|
2622
|
-
import
|
|
2657
|
+
import chalk37 from "chalk";
|
|
2623
2658
|
|
|
2624
2659
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
2625
2660
|
import * as fs2 from "fs";
|
|
2626
2661
|
import * as path9 from "path";
|
|
2627
|
-
import
|
|
2662
|
+
import chalk36 from "chalk";
|
|
2628
2663
|
function ensureVscodeFolder() {
|
|
2629
2664
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
2630
2665
|
if (!fs2.existsSync(vscodeDir)) {
|
|
2631
2666
|
fs2.mkdirSync(vscodeDir);
|
|
2632
|
-
console.log(
|
|
2667
|
+
console.log(chalk36.dim("Created .vscode folder"));
|
|
2633
2668
|
}
|
|
2634
2669
|
}
|
|
2635
2670
|
function removeVscodeFromGitignore() {
|
|
@@ -2644,7 +2679,7 @@ function removeVscodeFromGitignore() {
|
|
|
2644
2679
|
);
|
|
2645
2680
|
if (filteredLines.length !== lines.length) {
|
|
2646
2681
|
fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2647
|
-
console.log(
|
|
2682
|
+
console.log(chalk36.dim("Removed .vscode references from .gitignore"));
|
|
2648
2683
|
}
|
|
2649
2684
|
}
|
|
2650
2685
|
function createLaunchJson(type) {
|
|
@@ -2663,7 +2698,7 @@ function createLaunchJson(type) {
|
|
|
2663
2698
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
2664
2699
|
fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
2665
2700
|
`);
|
|
2666
|
-
console.log(
|
|
2701
|
+
console.log(chalk36.green("Created .vscode/launch.json"));
|
|
2667
2702
|
}
|
|
2668
2703
|
function createSettingsJson() {
|
|
2669
2704
|
const settings = {
|
|
@@ -2676,7 +2711,7 @@ function createSettingsJson() {
|
|
|
2676
2711
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
2677
2712
|
fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
2678
2713
|
`);
|
|
2679
|
-
console.log(
|
|
2714
|
+
console.log(chalk36.green("Created .vscode/settings.json"));
|
|
2680
2715
|
}
|
|
2681
2716
|
function createExtensionsJson() {
|
|
2682
2717
|
const extensions = {
|
|
@@ -2688,7 +2723,7 @@ function createExtensionsJson() {
|
|
|
2688
2723
|
`${JSON.stringify(extensions, null, " ")}
|
|
2689
2724
|
`
|
|
2690
2725
|
);
|
|
2691
|
-
console.log(
|
|
2726
|
+
console.log(chalk36.green("Created .vscode/extensions.json"));
|
|
2692
2727
|
}
|
|
2693
2728
|
|
|
2694
2729
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
@@ -2745,7 +2780,7 @@ function applySelections(selected, setup2) {
|
|
|
2745
2780
|
for (const choice of selected) handlers[choice]?.();
|
|
2746
2781
|
}
|
|
2747
2782
|
async function promptForOptions(options2) {
|
|
2748
|
-
console.log(
|
|
2783
|
+
console.log(chalk37.bold("Available VS Code configurations to add:\n"));
|
|
2749
2784
|
return promptMultiselect("Select configurations to add:", options2);
|
|
2750
2785
|
}
|
|
2751
2786
|
async function init3({ all = false } = {}) {
|
|
@@ -2753,17 +2788,17 @@ async function init3({ all = false } = {}) {
|
|
|
2753
2788
|
const setup2 = detectVscodeSetup(pkg);
|
|
2754
2789
|
const options2 = getAvailableOptions2(setup2);
|
|
2755
2790
|
if (options2.length === 0) {
|
|
2756
|
-
console.log(
|
|
2791
|
+
console.log(chalk37.green("VS Code configuration already exists!"));
|
|
2757
2792
|
return;
|
|
2758
2793
|
}
|
|
2759
2794
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
2760
2795
|
if (selected.length === 0) {
|
|
2761
|
-
console.log(
|
|
2796
|
+
console.log(chalk37.yellow("No configurations selected"));
|
|
2762
2797
|
return;
|
|
2763
2798
|
}
|
|
2764
2799
|
applySelections(selected, setup2);
|
|
2765
2800
|
console.log(
|
|
2766
|
-
|
|
2801
|
+
chalk37.green(`
|
|
2767
2802
|
Added ${selected.length} VS Code configuration(s)`)
|
|
2768
2803
|
);
|
|
2769
2804
|
}
|
|
@@ -2776,7 +2811,7 @@ async function init4() {
|
|
|
2776
2811
|
|
|
2777
2812
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2778
2813
|
import path16 from "path";
|
|
2779
|
-
import
|
|
2814
|
+
import chalk39 from "chalk";
|
|
2780
2815
|
|
|
2781
2816
|
// src/commands/lint/lint/checkFileNames.ts
|
|
2782
2817
|
import fs5 from "fs";
|
|
@@ -2856,7 +2891,7 @@ function checkFileNames() {
|
|
|
2856
2891
|
}
|
|
2857
2892
|
|
|
2858
2893
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
2859
|
-
import
|
|
2894
|
+
import chalk38 from "chalk";
|
|
2860
2895
|
|
|
2861
2896
|
// src/commands/lint/lint/applyMoves.ts
|
|
2862
2897
|
import fs6 from "fs";
|
|
@@ -2941,25 +2976,25 @@ function fixFileNameViolations(moves) {
|
|
|
2941
2976
|
const start3 = performance.now();
|
|
2942
2977
|
const project = createLintProject();
|
|
2943
2978
|
const cwd = process.cwd();
|
|
2944
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
2979
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk38.green(line)));
|
|
2945
2980
|
const ms = (performance.now() - start3).toFixed(0);
|
|
2946
|
-
console.log(
|
|
2981
|
+
console.log(chalk38.dim(` Done in ${ms}ms`));
|
|
2947
2982
|
}
|
|
2948
2983
|
|
|
2949
2984
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2950
2985
|
function reportViolations(violations) {
|
|
2951
|
-
console.error(
|
|
2986
|
+
console.error(chalk39.red("\nFile name check failed:\n"));
|
|
2952
2987
|
console.error(
|
|
2953
|
-
|
|
2988
|
+
chalk39.red(
|
|
2954
2989
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
2955
2990
|
)
|
|
2956
2991
|
);
|
|
2957
2992
|
for (const violation of violations) {
|
|
2958
|
-
console.error(
|
|
2959
|
-
console.error(
|
|
2993
|
+
console.error(chalk39.red(` ${violation.filePath}`));
|
|
2994
|
+
console.error(chalk39.gray(` Rename to: ${violation.suggestedName}
|
|
2960
2995
|
`));
|
|
2961
2996
|
}
|
|
2962
|
-
console.error(
|
|
2997
|
+
console.error(chalk39.dim(" Run with -f to auto-fix.\n"));
|
|
2963
2998
|
}
|
|
2964
2999
|
function runFileNameCheck(fix = false) {
|
|
2965
3000
|
const violations = checkFileNames();
|
|
@@ -2988,17 +3023,17 @@ function runFileNameCheck(fix = false) {
|
|
|
2988
3023
|
import fs8 from "fs";
|
|
2989
3024
|
|
|
2990
3025
|
// src/commands/lint/shared.ts
|
|
2991
|
-
import
|
|
3026
|
+
import chalk40 from "chalk";
|
|
2992
3027
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
2993
3028
|
if (violations.length > 0) {
|
|
2994
|
-
console.error(
|
|
3029
|
+
console.error(chalk40.red(`
|
|
2995
3030
|
${checkName} failed:
|
|
2996
3031
|
`));
|
|
2997
|
-
console.error(
|
|
3032
|
+
console.error(chalk40.red(` ${errorMessage}
|
|
2998
3033
|
`));
|
|
2999
3034
|
for (const violation of violations) {
|
|
3000
|
-
console.error(
|
|
3001
|
-
console.error(
|
|
3035
|
+
console.error(chalk40.red(` ${violation.filePath}:${violation.line}`));
|
|
3036
|
+
console.error(chalk40.gray(` ${violation.content}
|
|
3002
3037
|
`));
|
|
3003
3038
|
}
|
|
3004
3039
|
return false;
|
|
@@ -3478,14 +3513,14 @@ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSy
|
|
|
3478
3513
|
|
|
3479
3514
|
// src/commands/deploy/init/index.ts
|
|
3480
3515
|
import { execSync as execSync12 } from "child_process";
|
|
3481
|
-
import
|
|
3482
|
-
import
|
|
3516
|
+
import chalk42 from "chalk";
|
|
3517
|
+
import enquirer6 from "enquirer";
|
|
3483
3518
|
|
|
3484
3519
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
3485
3520
|
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
|
|
3486
3521
|
import { dirname as dirname13, join as join14 } from "path";
|
|
3487
3522
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3488
|
-
import
|
|
3523
|
+
import chalk41 from "chalk";
|
|
3489
3524
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
3490
3525
|
var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
|
|
3491
3526
|
function getExistingSiteId() {
|
|
@@ -3510,20 +3545,20 @@ async function updateWorkflow(siteId) {
|
|
|
3510
3545
|
if (existsSync17(WORKFLOW_PATH)) {
|
|
3511
3546
|
const oldContent = readFileSync14(WORKFLOW_PATH, "utf-8");
|
|
3512
3547
|
if (oldContent === newContent) {
|
|
3513
|
-
console.log(
|
|
3548
|
+
console.log(chalk41.green("build.yml is already up to date"));
|
|
3514
3549
|
return;
|
|
3515
3550
|
}
|
|
3516
|
-
console.log(
|
|
3551
|
+
console.log(chalk41.yellow("\nbuild.yml will be updated:"));
|
|
3517
3552
|
console.log();
|
|
3518
3553
|
printDiff(oldContent, newContent);
|
|
3519
|
-
const confirm = await promptConfirm(
|
|
3554
|
+
const confirm = await promptConfirm(chalk41.red("Update build.yml?"));
|
|
3520
3555
|
if (!confirm) {
|
|
3521
3556
|
console.log("Skipped build.yml update");
|
|
3522
3557
|
return;
|
|
3523
3558
|
}
|
|
3524
3559
|
}
|
|
3525
3560
|
writeFileSync13(WORKFLOW_PATH, newContent);
|
|
3526
|
-
console.log(
|
|
3561
|
+
console.log(chalk41.green(`
|
|
3527
3562
|
Created ${WORKFLOW_PATH}`));
|
|
3528
3563
|
}
|
|
3529
3564
|
|
|
@@ -3534,50 +3569,50 @@ async function ensureNetlifyCli() {
|
|
|
3534
3569
|
} catch (error) {
|
|
3535
3570
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
3536
3571
|
throw error;
|
|
3537
|
-
console.error(
|
|
3572
|
+
console.error(chalk42.red("\nNetlify CLI is not installed.\n"));
|
|
3538
3573
|
const install = await promptConfirm("Would you like to install it now?");
|
|
3539
3574
|
if (!install) {
|
|
3540
3575
|
console.log(
|
|
3541
|
-
|
|
3576
|
+
chalk42.yellow(
|
|
3542
3577
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
3543
3578
|
)
|
|
3544
3579
|
);
|
|
3545
3580
|
process.exit(1);
|
|
3546
3581
|
}
|
|
3547
|
-
console.log(
|
|
3582
|
+
console.log(chalk42.dim("\nInstalling netlify-cli...\n"));
|
|
3548
3583
|
execSync12("npm install -g netlify-cli", { stdio: "inherit" });
|
|
3549
3584
|
console.log();
|
|
3550
3585
|
execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
3551
3586
|
}
|
|
3552
3587
|
}
|
|
3553
3588
|
function printSetupInstructions() {
|
|
3554
|
-
console.log(
|
|
3589
|
+
console.log(chalk42.bold("\nDeployment initialized successfully!"));
|
|
3555
3590
|
console.log(
|
|
3556
|
-
|
|
3591
|
+
chalk42.yellow("\nTo complete setup, create a personal access token at:")
|
|
3557
3592
|
);
|
|
3558
3593
|
console.log(
|
|
3559
|
-
|
|
3594
|
+
chalk42.cyan(
|
|
3560
3595
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
3561
3596
|
)
|
|
3562
3597
|
);
|
|
3563
3598
|
console.log(
|
|
3564
|
-
|
|
3599
|
+
chalk42.yellow(
|
|
3565
3600
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
3566
3601
|
)
|
|
3567
3602
|
);
|
|
3568
3603
|
}
|
|
3569
3604
|
async function init5() {
|
|
3570
|
-
console.log(
|
|
3605
|
+
console.log(chalk42.bold("Initializing Netlify deployment...\n"));
|
|
3571
3606
|
const existingSiteId = getExistingSiteId();
|
|
3572
3607
|
if (existingSiteId) {
|
|
3573
|
-
console.log(
|
|
3608
|
+
console.log(chalk42.dim(`Using existing site ID: ${existingSiteId}
|
|
3574
3609
|
`));
|
|
3575
3610
|
await updateWorkflow(existingSiteId);
|
|
3576
3611
|
return;
|
|
3577
3612
|
}
|
|
3578
3613
|
console.log("Creating Netlify site...\n");
|
|
3579
3614
|
await ensureNetlifyCli();
|
|
3580
|
-
const { siteId } = await
|
|
3615
|
+
const { siteId } = await enquirer6.prompt({
|
|
3581
3616
|
type: "input",
|
|
3582
3617
|
name: "siteId",
|
|
3583
3618
|
message: "Enter the Site ID from above:",
|
|
@@ -3749,27 +3784,27 @@ async function notify() {
|
|
|
3749
3784
|
}
|
|
3750
3785
|
|
|
3751
3786
|
// src/commands/backlog/comment/index.ts
|
|
3752
|
-
import
|
|
3787
|
+
import chalk43 from "chalk";
|
|
3753
3788
|
function comment(id, text) {
|
|
3754
3789
|
const result = loadAndFindItem(id);
|
|
3755
3790
|
if (!result) process.exit(1);
|
|
3756
3791
|
addComment(result.item, text);
|
|
3757
3792
|
saveBacklog(result.items);
|
|
3758
|
-
console.log(
|
|
3793
|
+
console.log(chalk43.green(`Comment added to item #${id}.`));
|
|
3759
3794
|
}
|
|
3760
3795
|
|
|
3761
3796
|
// src/commands/backlog/comments/index.ts
|
|
3762
|
-
import
|
|
3797
|
+
import chalk44 from "chalk";
|
|
3763
3798
|
function comments(id) {
|
|
3764
3799
|
const result = loadAndFindItem(id);
|
|
3765
3800
|
if (!result) process.exit(1);
|
|
3766
3801
|
const { item } = result;
|
|
3767
3802
|
const entries = item.comments ?? [];
|
|
3768
3803
|
if (entries.length === 0) {
|
|
3769
|
-
console.log(
|
|
3804
|
+
console.log(chalk44.dim(`No comments on item #${id}.`));
|
|
3770
3805
|
return;
|
|
3771
3806
|
}
|
|
3772
|
-
console.log(
|
|
3807
|
+
console.log(chalk44.bold(`Comments for #${id}: ${item.name}
|
|
3773
3808
|
`));
|
|
3774
3809
|
for (const entry of entries) {
|
|
3775
3810
|
console.log(`${formatComment(entry)}
|
|
@@ -3784,12 +3819,12 @@ function registerCommentCommands(cmd) {
|
|
|
3784
3819
|
}
|
|
3785
3820
|
|
|
3786
3821
|
// src/commands/backlog/add/index.ts
|
|
3787
|
-
import
|
|
3822
|
+
import chalk46 from "chalk";
|
|
3788
3823
|
|
|
3789
3824
|
// src/commands/backlog/commitBacklog.ts
|
|
3790
3825
|
import { execSync as execSync14 } from "child_process";
|
|
3791
3826
|
import { join as join15 } from "path";
|
|
3792
|
-
import
|
|
3827
|
+
import chalk45 from "chalk";
|
|
3793
3828
|
function commitBacklog(id, name) {
|
|
3794
3829
|
try {
|
|
3795
3830
|
const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
|
|
@@ -3797,7 +3832,7 @@ function commitBacklog(id, name) {
|
|
|
3797
3832
|
execSync14(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
|
|
3798
3833
|
execSync14(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
|
|
3799
3834
|
} catch {
|
|
3800
|
-
console.log(
|
|
3835
|
+
console.log(chalk45.yellow("Warning: could not auto-commit backlog file."));
|
|
3801
3836
|
}
|
|
3802
3837
|
}
|
|
3803
3838
|
|
|
@@ -3806,9 +3841,9 @@ import { spawnSync } from "child_process";
|
|
|
3806
3841
|
import { mkdtempSync, readFileSync as readFileSync16, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
|
|
3807
3842
|
import { tmpdir } from "os";
|
|
3808
3843
|
import { join as join16 } from "path";
|
|
3809
|
-
import
|
|
3844
|
+
import enquirer7 from "enquirer";
|
|
3810
3845
|
async function promptType() {
|
|
3811
|
-
const { type } = await
|
|
3846
|
+
const { type } = await enquirer7.prompt({
|
|
3812
3847
|
type: "select",
|
|
3813
3848
|
name: "type",
|
|
3814
3849
|
message: "Type:",
|
|
@@ -3818,7 +3853,7 @@ async function promptType() {
|
|
|
3818
3853
|
return type;
|
|
3819
3854
|
}
|
|
3820
3855
|
async function promptName() {
|
|
3821
|
-
const { name } = await
|
|
3856
|
+
const { name } = await enquirer7.prompt({
|
|
3822
3857
|
type: "input",
|
|
3823
3858
|
name: "name",
|
|
3824
3859
|
message: "Name:",
|
|
@@ -3827,14 +3862,14 @@ async function promptName() {
|
|
|
3827
3862
|
return name.trim();
|
|
3828
3863
|
}
|
|
3829
3864
|
async function promptDescription() {
|
|
3830
|
-
const { useEditor } = await
|
|
3865
|
+
const { useEditor } = await enquirer7.prompt({
|
|
3831
3866
|
type: "confirm",
|
|
3832
3867
|
name: "useEditor",
|
|
3833
3868
|
message: "Open editor for description?",
|
|
3834
3869
|
initial: false
|
|
3835
3870
|
});
|
|
3836
3871
|
if (!useEditor) {
|
|
3837
|
-
const { description } = await
|
|
3872
|
+
const { description } = await enquirer7.prompt({
|
|
3838
3873
|
type: "input",
|
|
3839
3874
|
name: "description",
|
|
3840
3875
|
message: "Description (optional):"
|
|
@@ -3860,7 +3895,7 @@ function openEditor() {
|
|
|
3860
3895
|
async function promptAcceptanceCriteria() {
|
|
3861
3896
|
const criteria = [];
|
|
3862
3897
|
for (; ; ) {
|
|
3863
|
-
const { criterion } = await
|
|
3898
|
+
const { criterion } = await enquirer7.prompt({
|
|
3864
3899
|
type: "input",
|
|
3865
3900
|
name: "criterion",
|
|
3866
3901
|
message: "Acceptance criterion (empty to finish):"
|
|
@@ -3889,12 +3924,12 @@ async function addFromOptions(options2) {
|
|
|
3889
3924
|
});
|
|
3890
3925
|
saveBacklog(items);
|
|
3891
3926
|
commitBacklog(id, name);
|
|
3892
|
-
console.log(
|
|
3927
|
+
console.log(chalk46.green(`Added item #${id}: ${name}`));
|
|
3893
3928
|
}
|
|
3894
3929
|
async function add(options2) {
|
|
3895
3930
|
if (!backlogExists()) {
|
|
3896
3931
|
console.log(
|
|
3897
|
-
|
|
3932
|
+
chalk46.yellow(
|
|
3898
3933
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3899
3934
|
)
|
|
3900
3935
|
);
|
|
@@ -3904,13 +3939,13 @@ async function add(options2) {
|
|
|
3904
3939
|
}
|
|
3905
3940
|
|
|
3906
3941
|
// src/commands/backlog/addPhase.ts
|
|
3907
|
-
import
|
|
3942
|
+
import chalk47 from "chalk";
|
|
3908
3943
|
function addPhase(id, name, options2) {
|
|
3909
3944
|
const result = loadAndFindItem(id);
|
|
3910
3945
|
if (!result) return;
|
|
3911
3946
|
const tasks = options2.task ?? [];
|
|
3912
3947
|
if (tasks.length === 0) {
|
|
3913
|
-
console.log(
|
|
3948
|
+
console.log(chalk47.red("At least one --task is required."));
|
|
3914
3949
|
process.exitCode = 1;
|
|
3915
3950
|
return;
|
|
3916
3951
|
}
|
|
@@ -3932,25 +3967,25 @@ function addPhase(id, name, options2) {
|
|
|
3932
3967
|
exportToJsonl(db, dir);
|
|
3933
3968
|
commitBacklog(itemId, result.item.name);
|
|
3934
3969
|
console.log(
|
|
3935
|
-
|
|
3970
|
+
chalk47.green(
|
|
3936
3971
|
`Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
3937
3972
|
)
|
|
3938
3973
|
);
|
|
3939
3974
|
}
|
|
3940
3975
|
|
|
3941
3976
|
// src/commands/backlog/init/index.ts
|
|
3942
|
-
import
|
|
3977
|
+
import chalk48 from "chalk";
|
|
3943
3978
|
async function init6() {
|
|
3944
3979
|
if (backlogExists()) {
|
|
3945
|
-
console.log(
|
|
3980
|
+
console.log(chalk48.yellow("Backlog already exists."));
|
|
3946
3981
|
return;
|
|
3947
3982
|
}
|
|
3948
3983
|
saveBacklog([]);
|
|
3949
|
-
console.log(
|
|
3984
|
+
console.log(chalk48.green("Created backlog."));
|
|
3950
3985
|
}
|
|
3951
3986
|
|
|
3952
3987
|
// src/commands/backlog/list/index.ts
|
|
3953
|
-
import
|
|
3988
|
+
import chalk49 from "chalk";
|
|
3954
3989
|
function filterItems(items, options2) {
|
|
3955
3990
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
3956
3991
|
if (!options2.all)
|
|
@@ -3960,7 +3995,7 @@ function filterItems(items, options2) {
|
|
|
3960
3995
|
async function list2(options2) {
|
|
3961
3996
|
if (!backlogExists()) {
|
|
3962
3997
|
console.log(
|
|
3963
|
-
|
|
3998
|
+
chalk49.yellow(
|
|
3964
3999
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3965
4000
|
)
|
|
3966
4001
|
);
|
|
@@ -3969,12 +4004,12 @@ async function list2(options2) {
|
|
|
3969
4004
|
const allItems = loadBacklog();
|
|
3970
4005
|
const items = filterItems(allItems, options2);
|
|
3971
4006
|
if (items.length === 0) {
|
|
3972
|
-
console.log(
|
|
4007
|
+
console.log(chalk49.dim("Backlog is empty."));
|
|
3973
4008
|
return;
|
|
3974
4009
|
}
|
|
3975
4010
|
for (const item of items) {
|
|
3976
4011
|
console.log(
|
|
3977
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4012
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk49.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
3978
4013
|
);
|
|
3979
4014
|
if (options2.verbose) {
|
|
3980
4015
|
printVerboseDetails(item);
|
|
@@ -3997,7 +4032,7 @@ function registerItemCommands(cmd) {
|
|
|
3997
4032
|
}
|
|
3998
4033
|
|
|
3999
4034
|
// src/commands/backlog/link.ts
|
|
4000
|
-
import
|
|
4035
|
+
import chalk51 from "chalk";
|
|
4001
4036
|
|
|
4002
4037
|
// src/commands/backlog/hasCycle.ts
|
|
4003
4038
|
function hasCycle(items, fromId, toId) {
|
|
@@ -4020,11 +4055,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
4020
4055
|
}
|
|
4021
4056
|
|
|
4022
4057
|
// src/commands/backlog/validateLinkTarget.ts
|
|
4023
|
-
import
|
|
4058
|
+
import chalk50 from "chalk";
|
|
4024
4059
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
4025
4060
|
const toItem = items.find((i) => i.id === toNum);
|
|
4026
4061
|
if (!toItem) {
|
|
4027
|
-
console.log(
|
|
4062
|
+
console.log(chalk50.red(`Item #${toId} not found.`));
|
|
4028
4063
|
return void 0;
|
|
4029
4064
|
}
|
|
4030
4065
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -4033,7 +4068,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4033
4068
|
);
|
|
4034
4069
|
if (duplicate) {
|
|
4035
4070
|
console.log(
|
|
4036
|
-
|
|
4071
|
+
chalk50.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
4037
4072
|
);
|
|
4038
4073
|
return void 0;
|
|
4039
4074
|
}
|
|
@@ -4044,13 +4079,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4044
4079
|
function link(fromId, toId, opts) {
|
|
4045
4080
|
const linkType = opts.type ?? "relates-to";
|
|
4046
4081
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
4047
|
-
console.log(
|
|
4082
|
+
console.log(chalk51.red(`Invalid link type: ${linkType}`));
|
|
4048
4083
|
return;
|
|
4049
4084
|
}
|
|
4050
4085
|
const fromNum = Number.parseInt(fromId, 10);
|
|
4051
4086
|
const toNum = Number.parseInt(toId, 10);
|
|
4052
4087
|
if (fromNum === toNum) {
|
|
4053
|
-
console.log(
|
|
4088
|
+
console.log(chalk51.red("Cannot link an item to itself."));
|
|
4054
4089
|
return;
|
|
4055
4090
|
}
|
|
4056
4091
|
const result = loadAndFindItem(fromId);
|
|
@@ -4067,7 +4102,7 @@ function link(fromId, toId, opts) {
|
|
|
4067
4102
|
if (!toItem) return;
|
|
4068
4103
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
4069
4104
|
console.log(
|
|
4070
|
-
|
|
4105
|
+
chalk51.red(
|
|
4071
4106
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
4072
4107
|
)
|
|
4073
4108
|
);
|
|
@@ -4077,32 +4112,32 @@ function link(fromId, toId, opts) {
|
|
|
4077
4112
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
4078
4113
|
saveBacklog(items);
|
|
4079
4114
|
console.log(
|
|
4080
|
-
|
|
4115
|
+
chalk51.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
4081
4116
|
);
|
|
4082
4117
|
}
|
|
4083
4118
|
|
|
4084
4119
|
// src/commands/backlog/unlink.ts
|
|
4085
|
-
import
|
|
4120
|
+
import chalk52 from "chalk";
|
|
4086
4121
|
function unlink(fromId, toId) {
|
|
4087
4122
|
const toNum = Number.parseInt(toId, 10);
|
|
4088
4123
|
const result = loadAndFindItem(fromId);
|
|
4089
4124
|
if (!result) return;
|
|
4090
4125
|
const { items, item: fromItem } = result;
|
|
4091
4126
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
4092
|
-
console.log(
|
|
4127
|
+
console.log(chalk52.yellow(`No links found on item #${fromId}.`));
|
|
4093
4128
|
return;
|
|
4094
4129
|
}
|
|
4095
4130
|
const before = fromItem.links.length;
|
|
4096
4131
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
4097
4132
|
if (fromItem.links.length === before) {
|
|
4098
|
-
console.log(
|
|
4133
|
+
console.log(chalk52.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
4099
4134
|
return;
|
|
4100
4135
|
}
|
|
4101
4136
|
if (fromItem.links.length === 0) {
|
|
4102
4137
|
fromItem.links = void 0;
|
|
4103
4138
|
}
|
|
4104
4139
|
saveBacklog(items);
|
|
4105
|
-
console.log(
|
|
4140
|
+
console.log(chalk52.green(`Removed link from #${fromId} to #${toId}.`));
|
|
4106
4141
|
}
|
|
4107
4142
|
|
|
4108
4143
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -4115,12 +4150,19 @@ function registerLinkCommands(cmd) {
|
|
|
4115
4150
|
cmd.command("unlink <from> <to>").description("Remove a link between two backlog items").action(unlink);
|
|
4116
4151
|
}
|
|
4117
4152
|
|
|
4153
|
+
// src/commands/backlog/registerRunCommand.ts
|
|
4154
|
+
function registerRunCommand(cmd) {
|
|
4155
|
+
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with acceptEdits permission mode").action(async (id, opts) => {
|
|
4156
|
+
await run(id, { allowEdits: opts.write });
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4118
4160
|
// src/commands/backlog/search/index.ts
|
|
4119
|
-
import
|
|
4161
|
+
import chalk53 from "chalk";
|
|
4120
4162
|
async function search(query) {
|
|
4121
4163
|
if (!backlogExists()) {
|
|
4122
4164
|
console.log(
|
|
4123
|
-
|
|
4165
|
+
chalk53.yellow(
|
|
4124
4166
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4125
4167
|
)
|
|
4126
4168
|
);
|
|
@@ -4128,18 +4170,18 @@ async function search(query) {
|
|
|
4128
4170
|
}
|
|
4129
4171
|
const items = searchBacklog(query);
|
|
4130
4172
|
if (items.length === 0) {
|
|
4131
|
-
console.log(
|
|
4173
|
+
console.log(chalk53.dim(`No items matching "${query}".`));
|
|
4132
4174
|
return;
|
|
4133
4175
|
}
|
|
4134
4176
|
console.log(
|
|
4135
|
-
|
|
4177
|
+
chalk53.dim(
|
|
4136
4178
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
4137
4179
|
`
|
|
4138
4180
|
)
|
|
4139
4181
|
);
|
|
4140
4182
|
for (const item of items) {
|
|
4141
4183
|
console.log(
|
|
4142
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4184
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk53.dim(`#${item.id}`)} ${item.name}`
|
|
4143
4185
|
);
|
|
4144
4186
|
}
|
|
4145
4187
|
}
|
|
@@ -4150,16 +4192,16 @@ function registerSearchCommand(cmd) {
|
|
|
4150
4192
|
}
|
|
4151
4193
|
|
|
4152
4194
|
// src/commands/backlog/delete/index.ts
|
|
4153
|
-
import
|
|
4195
|
+
import chalk54 from "chalk";
|
|
4154
4196
|
async function del(id) {
|
|
4155
4197
|
const name = removeItem(id);
|
|
4156
4198
|
if (name) {
|
|
4157
|
-
console.log(
|
|
4199
|
+
console.log(chalk54.green(`Deleted item #${id}: ${name}`));
|
|
4158
4200
|
}
|
|
4159
4201
|
}
|
|
4160
4202
|
|
|
4161
4203
|
// src/commands/backlog/done/index.ts
|
|
4162
|
-
import
|
|
4204
|
+
import chalk55 from "chalk";
|
|
4163
4205
|
async function done(id, summary) {
|
|
4164
4206
|
const result = loadAndFindItem(id);
|
|
4165
4207
|
if (!result) return;
|
|
@@ -4169,20 +4211,20 @@ async function done(id, summary) {
|
|
|
4169
4211
|
addPhaseSummary(result.item, summary, phase);
|
|
4170
4212
|
}
|
|
4171
4213
|
saveBacklog(result.items);
|
|
4172
|
-
console.log(
|
|
4214
|
+
console.log(chalk55.green(`Completed item #${id}: ${result.item.name}`));
|
|
4173
4215
|
}
|
|
4174
4216
|
|
|
4175
4217
|
// src/commands/backlog/start/index.ts
|
|
4176
|
-
import
|
|
4218
|
+
import chalk56 from "chalk";
|
|
4177
4219
|
async function start(id) {
|
|
4178
4220
|
const name = setStatus(id, "in-progress");
|
|
4179
4221
|
if (name) {
|
|
4180
|
-
console.log(
|
|
4222
|
+
console.log(chalk56.green(`Started item #${id}: ${name}`));
|
|
4181
4223
|
}
|
|
4182
4224
|
}
|
|
4183
4225
|
|
|
4184
4226
|
// src/commands/backlog/wontdo/index.ts
|
|
4185
|
-
import
|
|
4227
|
+
import chalk57 from "chalk";
|
|
4186
4228
|
async function wontdo(id, reason) {
|
|
4187
4229
|
const result = loadAndFindItem(id);
|
|
4188
4230
|
if (!result) return;
|
|
@@ -4192,7 +4234,7 @@ async function wontdo(id, reason) {
|
|
|
4192
4234
|
addPhaseSummary(result.item, reason, phase);
|
|
4193
4235
|
}
|
|
4194
4236
|
saveBacklog(result.items);
|
|
4195
|
-
console.log(
|
|
4237
|
+
console.log(chalk57.red(`Won't do item #${id}: ${result.item.name}`));
|
|
4196
4238
|
}
|
|
4197
4239
|
|
|
4198
4240
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -4203,6 +4245,204 @@ function registerStatusCommands(cmd) {
|
|
|
4203
4245
|
cmd.command("delete <id>").alias("remove").description("Delete a backlog item").action(del);
|
|
4204
4246
|
}
|
|
4205
4247
|
|
|
4248
|
+
// src/commands/backlog/removePhase.ts
|
|
4249
|
+
import chalk59 from "chalk";
|
|
4250
|
+
|
|
4251
|
+
// src/commands/backlog/findPhase.ts
|
|
4252
|
+
import chalk58 from "chalk";
|
|
4253
|
+
function findPhase(id, phase) {
|
|
4254
|
+
const result = loadAndFindItem(id);
|
|
4255
|
+
if (!result) return void 0;
|
|
4256
|
+
const dir = getBacklogDir();
|
|
4257
|
+
const db = openDb(dir);
|
|
4258
|
+
const itemId = result.item.id;
|
|
4259
|
+
const phaseIdx = Number.parseInt(phase, 10);
|
|
4260
|
+
const existing = db.prepare(
|
|
4261
|
+
"SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
|
|
4262
|
+
).get(itemId, phaseIdx);
|
|
4263
|
+
if (existing.cnt === 0) {
|
|
4264
|
+
console.log(chalk58.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
|
|
4265
|
+
process.exitCode = 1;
|
|
4266
|
+
return void 0;
|
|
4267
|
+
}
|
|
4268
|
+
return { result, dir, db, itemId, phaseIdx };
|
|
4269
|
+
}
|
|
4270
|
+
function reindexPhases(db, itemId) {
|
|
4271
|
+
const remaining = db.prepare("SELECT idx FROM plan_phases WHERE item_id = ? ORDER BY idx").all(itemId);
|
|
4272
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
4273
|
+
const oldIdx = remaining[i].idx;
|
|
4274
|
+
if (oldIdx !== i) {
|
|
4275
|
+
db.prepare(
|
|
4276
|
+
"UPDATE plan_tasks SET phase_idx = ? WHERE item_id = ? AND phase_idx = ?"
|
|
4277
|
+
).run(i, itemId, oldIdx);
|
|
4278
|
+
db.prepare(
|
|
4279
|
+
"UPDATE plan_phases SET idx = ? WHERE item_id = ? AND idx = ?"
|
|
4280
|
+
).run(i, itemId, oldIdx);
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
function adjustCurrentPhase(db, item, removedIdx) {
|
|
4285
|
+
if (item.currentPhase === void 0) return;
|
|
4286
|
+
if (removedIdx < item.currentPhase) {
|
|
4287
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4288
|
+
item.currentPhase - 1,
|
|
4289
|
+
item.id
|
|
4290
|
+
);
|
|
4291
|
+
} else if (removedIdx === item.currentPhase) {
|
|
4292
|
+
const { cnt } = db.prepare("SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ?").get(item.id);
|
|
4293
|
+
const newPhase = cnt === 0 ? null : Math.min(item.currentPhase, cnt - 1);
|
|
4294
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4295
|
+
newPhase,
|
|
4296
|
+
item.id
|
|
4297
|
+
);
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
// src/commands/backlog/removePhase.ts
|
|
4302
|
+
function removePhase(id, phase) {
|
|
4303
|
+
const found = findPhase(id, phase);
|
|
4304
|
+
if (!found) return;
|
|
4305
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4306
|
+
const run4 = db.transaction(() => {
|
|
4307
|
+
db.prepare(
|
|
4308
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4309
|
+
).run(itemId, phaseIdx);
|
|
4310
|
+
db.prepare("DELETE FROM plan_phases WHERE item_id = ? AND idx = ?").run(
|
|
4311
|
+
itemId,
|
|
4312
|
+
phaseIdx
|
|
4313
|
+
);
|
|
4314
|
+
reindexPhases(db, itemId);
|
|
4315
|
+
adjustCurrentPhase(db, result.item, phaseIdx);
|
|
4316
|
+
});
|
|
4317
|
+
run4();
|
|
4318
|
+
exportToJsonl(db, dir);
|
|
4319
|
+
commitBacklog(itemId, result.item.name);
|
|
4320
|
+
console.log(chalk59.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4323
|
+
// src/commands/backlog/update/index.ts
|
|
4324
|
+
import chalk61 from "chalk";
|
|
4325
|
+
|
|
4326
|
+
// src/commands/backlog/update/buildUpdateSql.ts
|
|
4327
|
+
import chalk60 from "chalk";
|
|
4328
|
+
function buildUpdateSql(options2) {
|
|
4329
|
+
const { name, desc, type, ac } = options2;
|
|
4330
|
+
if (!name && !desc && !type && !ac) {
|
|
4331
|
+
console.log(chalk60.red("Nothing to update. Provide at least one flag."));
|
|
4332
|
+
process.exitCode = 1;
|
|
4333
|
+
return void 0;
|
|
4334
|
+
}
|
|
4335
|
+
if (type && type !== "story" && type !== "bug") {
|
|
4336
|
+
console.log(chalk60.red('Invalid type. Must be "story" or "bug".'));
|
|
4337
|
+
process.exitCode = 1;
|
|
4338
|
+
return void 0;
|
|
4339
|
+
}
|
|
4340
|
+
const sets = [];
|
|
4341
|
+
const params = [];
|
|
4342
|
+
const fieldNames = [];
|
|
4343
|
+
if (name) {
|
|
4344
|
+
sets.push("name = ?");
|
|
4345
|
+
params.push(name);
|
|
4346
|
+
fieldNames.push("name");
|
|
4347
|
+
}
|
|
4348
|
+
if (desc) {
|
|
4349
|
+
sets.push("description = ?");
|
|
4350
|
+
params.push(desc);
|
|
4351
|
+
fieldNames.push("description");
|
|
4352
|
+
}
|
|
4353
|
+
if (type) {
|
|
4354
|
+
sets.push("type = ?");
|
|
4355
|
+
params.push(type);
|
|
4356
|
+
fieldNames.push("type");
|
|
4357
|
+
}
|
|
4358
|
+
if (ac) {
|
|
4359
|
+
sets.push("acceptance_criteria = ?");
|
|
4360
|
+
params.push(JSON.stringify(ac));
|
|
4361
|
+
fieldNames.push("acceptance criteria");
|
|
4362
|
+
}
|
|
4363
|
+
return { sets, params, fields: fieldNames.join(", ") };
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
// src/commands/backlog/update/index.ts
|
|
4367
|
+
function update(id, options2) {
|
|
4368
|
+
const result = loadAndFindItem(id);
|
|
4369
|
+
if (!result) return;
|
|
4370
|
+
const built = buildUpdateSql(options2);
|
|
4371
|
+
if (!built) return;
|
|
4372
|
+
const dir = getBacklogDir();
|
|
4373
|
+
const db = openDb(dir);
|
|
4374
|
+
const itemId = result.item.id;
|
|
4375
|
+
db.prepare(`UPDATE items SET ${built.sets.join(", ")} WHERE id = ?`).run(
|
|
4376
|
+
...built.params,
|
|
4377
|
+
itemId
|
|
4378
|
+
);
|
|
4379
|
+
exportToJsonl(db, dir);
|
|
4380
|
+
commitBacklog(itemId, options2.name ?? result.item.name);
|
|
4381
|
+
console.log(chalk61.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
// src/commands/backlog/updatePhase.ts
|
|
4385
|
+
import chalk62 from "chalk";
|
|
4386
|
+
|
|
4387
|
+
// src/commands/backlog/applyPhaseUpdate.ts
|
|
4388
|
+
function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
4389
|
+
const run4 = db.transaction(() => {
|
|
4390
|
+
if (fields.name) {
|
|
4391
|
+
db.prepare(
|
|
4392
|
+
"UPDATE plan_phases SET name = ? WHERE item_id = ? AND idx = ?"
|
|
4393
|
+
).run(fields.name, itemId, phaseIdx);
|
|
4394
|
+
}
|
|
4395
|
+
if (fields.manualCheck) {
|
|
4396
|
+
db.prepare(
|
|
4397
|
+
"UPDATE plan_phases SET manual_checks = ? WHERE item_id = ? AND idx = ?"
|
|
4398
|
+
).run(JSON.stringify(fields.manualCheck), itemId, phaseIdx);
|
|
4399
|
+
}
|
|
4400
|
+
if (fields.task) {
|
|
4401
|
+
db.prepare(
|
|
4402
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4403
|
+
).run(itemId, phaseIdx);
|
|
4404
|
+
const stmt = db.prepare(
|
|
4405
|
+
"INSERT INTO plan_tasks (item_id, phase_idx, idx, task) VALUES (?, ?, ?, ?)"
|
|
4406
|
+
);
|
|
4407
|
+
for (let i = 0; i < fields.task.length; i++) {
|
|
4408
|
+
stmt.run(itemId, phaseIdx, i, fields.task[i]);
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
});
|
|
4412
|
+
run4();
|
|
4413
|
+
}
|
|
4414
|
+
|
|
4415
|
+
// src/commands/backlog/updatePhase.ts
|
|
4416
|
+
function updatePhase(id, phase, options2) {
|
|
4417
|
+
const { name, task, manualCheck } = options2;
|
|
4418
|
+
if (!name && !task && !manualCheck) {
|
|
4419
|
+
console.log(chalk62.red("Nothing to update. Provide at least one flag."));
|
|
4420
|
+
process.exitCode = 1;
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
const found = findPhase(id, phase);
|
|
4424
|
+
if (!found) return;
|
|
4425
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4426
|
+
applyPhaseUpdate(db, itemId, phaseIdx, { name, task, manualCheck });
|
|
4427
|
+
exportToJsonl(db, dir);
|
|
4428
|
+
commitBacklog(itemId, result.item.name);
|
|
4429
|
+
const fields = [
|
|
4430
|
+
name && "name",
|
|
4431
|
+
task && "tasks",
|
|
4432
|
+
manualCheck && "manual checks"
|
|
4433
|
+
].filter(Boolean).join(", ");
|
|
4434
|
+
console.log(
|
|
4435
|
+
chalk62.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
|
|
4436
|
+
);
|
|
4437
|
+
}
|
|
4438
|
+
|
|
4439
|
+
// src/commands/backlog/registerUpdateCommands.ts
|
|
4440
|
+
function registerUpdateCommands(cmd) {
|
|
4441
|
+
cmd.command("update <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option("--desc <description>", "New description").option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").action(update);
|
|
4442
|
+
cmd.command("update-phase <id> <phase>").description("Modify a plan phase on a backlog item").option("--name <name>", "New phase name").option("--task <task...>", "Replace tasks (repeatable)").option("--manual-check <check...>", "Replace manual checks (repeatable)").action(updatePhase);
|
|
4443
|
+
cmd.command("remove-phase <id> <phase>").description("Remove a plan phase from a backlog item").action(removePhase);
|
|
4444
|
+
}
|
|
4445
|
+
|
|
4206
4446
|
// src/commands/registerBacklog.ts
|
|
4207
4447
|
function registerShowCommands(cmd) {
|
|
4208
4448
|
cmd.command("show <id>").alias("view").description("Show full detail for a backlog item").action(show);
|
|
@@ -4219,11 +4459,6 @@ function registerNextCommand(cmd) {
|
|
|
4219
4459
|
(opts) => next({ allowEdits: opts.write })
|
|
4220
4460
|
);
|
|
4221
4461
|
}
|
|
4222
|
-
function registerRunCommand(cmd) {
|
|
4223
|
-
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with acceptEdits permission mode").action(async (id, opts) => {
|
|
4224
|
-
await run(id, { allowEdits: opts.write });
|
|
4225
|
-
});
|
|
4226
|
-
}
|
|
4227
4462
|
function registerBacklog(program2) {
|
|
4228
4463
|
const cmd = program2.command("backlog").description("Manage a backlog of work items").option("--dir <path>", "Override directory for backlog file discovery").hook("preAction", (thisCommand) => {
|
|
4229
4464
|
setBacklogDir(thisCommand.opts().dir);
|
|
@@ -4238,6 +4473,7 @@ function registerBacklog(program2) {
|
|
|
4238
4473
|
registerNextCommand(cmd);
|
|
4239
4474
|
registerRunCommand(cmd);
|
|
4240
4475
|
registerSearchCommand(cmd);
|
|
4476
|
+
registerUpdateCommands(cmd);
|
|
4241
4477
|
}
|
|
4242
4478
|
|
|
4243
4479
|
// src/shared/isApprovedRead.ts
|
|
@@ -4647,48 +4883,48 @@ ${reasons.join("\n")}`);
|
|
|
4647
4883
|
}
|
|
4648
4884
|
|
|
4649
4885
|
// src/commands/deny/denyAdd.ts
|
|
4650
|
-
import
|
|
4886
|
+
import chalk63 from "chalk";
|
|
4651
4887
|
function denyAdd(pattern2, message) {
|
|
4652
4888
|
const config = loadProjectConfig();
|
|
4653
4889
|
const deny = config.deny ?? [];
|
|
4654
4890
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
4655
|
-
console.log(
|
|
4891
|
+
console.log(chalk63.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
4656
4892
|
return;
|
|
4657
4893
|
}
|
|
4658
4894
|
deny.push({ pattern: pattern2, message });
|
|
4659
4895
|
config.deny = deny;
|
|
4660
4896
|
saveConfig(config);
|
|
4661
|
-
console.log(
|
|
4897
|
+
console.log(chalk63.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
4662
4898
|
}
|
|
4663
4899
|
|
|
4664
4900
|
// src/commands/deny/denyList.ts
|
|
4665
|
-
import
|
|
4901
|
+
import chalk64 from "chalk";
|
|
4666
4902
|
function denyList() {
|
|
4667
4903
|
const config = loadConfig();
|
|
4668
4904
|
const deny = config.deny;
|
|
4669
4905
|
if (!deny || deny.length === 0) {
|
|
4670
|
-
console.log(
|
|
4906
|
+
console.log(chalk64.dim("No deny rules configured."));
|
|
4671
4907
|
return;
|
|
4672
4908
|
}
|
|
4673
4909
|
for (const rule of deny) {
|
|
4674
|
-
console.log(`${
|
|
4910
|
+
console.log(`${chalk64.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
4675
4911
|
}
|
|
4676
4912
|
}
|
|
4677
4913
|
|
|
4678
4914
|
// src/commands/deny/denyRemove.ts
|
|
4679
|
-
import
|
|
4915
|
+
import chalk65 from "chalk";
|
|
4680
4916
|
function denyRemove(pattern2) {
|
|
4681
4917
|
const config = loadProjectConfig();
|
|
4682
4918
|
const deny = config.deny ?? [];
|
|
4683
4919
|
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
4684
4920
|
if (index === -1) {
|
|
4685
|
-
console.log(
|
|
4921
|
+
console.log(chalk65.yellow(`No deny rule found for: ${pattern2}`));
|
|
4686
4922
|
return;
|
|
4687
4923
|
}
|
|
4688
4924
|
deny.splice(index, 1);
|
|
4689
4925
|
config.deny = deny.length > 0 ? deny : void 0;
|
|
4690
4926
|
saveConfig(config);
|
|
4691
|
-
console.log(
|
|
4927
|
+
console.log(chalk65.green(`Removed deny rule: ${pattern2}`));
|
|
4692
4928
|
}
|
|
4693
4929
|
|
|
4694
4930
|
// src/commands/permitCliReads/index.ts
|
|
@@ -4738,11 +4974,11 @@ function assertCliExists(cli) {
|
|
|
4738
4974
|
}
|
|
4739
4975
|
|
|
4740
4976
|
// src/commands/permitCliReads/colorize.ts
|
|
4741
|
-
import
|
|
4977
|
+
import chalk66 from "chalk";
|
|
4742
4978
|
function colorize(plainOutput) {
|
|
4743
4979
|
return plainOutput.split("\n").map((line) => {
|
|
4744
|
-
if (line.startsWith(" R ")) return
|
|
4745
|
-
if (line.startsWith(" W ")) return
|
|
4980
|
+
if (line.startsWith(" R ")) return chalk66.green(line);
|
|
4981
|
+
if (line.startsWith(" W ")) return chalk66.red(line);
|
|
4746
4982
|
return line;
|
|
4747
4983
|
}).join("\n");
|
|
4748
4984
|
}
|
|
@@ -5060,15 +5296,15 @@ function registerCliHook(program2) {
|
|
|
5060
5296
|
}
|
|
5061
5297
|
|
|
5062
5298
|
// src/commands/complexity/analyze.ts
|
|
5063
|
-
import
|
|
5299
|
+
import chalk72 from "chalk";
|
|
5064
5300
|
|
|
5065
5301
|
// src/commands/complexity/cyclomatic.ts
|
|
5066
|
-
import
|
|
5302
|
+
import chalk68 from "chalk";
|
|
5067
5303
|
|
|
5068
5304
|
// src/commands/complexity/shared/index.ts
|
|
5069
5305
|
import fs12 from "fs";
|
|
5070
5306
|
import path20 from "path";
|
|
5071
|
-
import
|
|
5307
|
+
import chalk67 from "chalk";
|
|
5072
5308
|
import ts5 from "typescript";
|
|
5073
5309
|
|
|
5074
5310
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -5314,7 +5550,7 @@ function createSourceFromFile(filePath) {
|
|
|
5314
5550
|
function withSourceFiles(pattern2, callback) {
|
|
5315
5551
|
const files = findSourceFiles2(pattern2);
|
|
5316
5552
|
if (files.length === 0) {
|
|
5317
|
-
console.log(
|
|
5553
|
+
console.log(chalk67.yellow("No files found matching pattern"));
|
|
5318
5554
|
return void 0;
|
|
5319
5555
|
}
|
|
5320
5556
|
return callback(files);
|
|
@@ -5347,11 +5583,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5347
5583
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
5348
5584
|
for (const { file, name, complexity } of results) {
|
|
5349
5585
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
5350
|
-
const color = exceedsThreshold ?
|
|
5351
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
5586
|
+
const color = exceedsThreshold ? chalk68.red : chalk68.white;
|
|
5587
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk68.cyan(complexity)}`);
|
|
5352
5588
|
}
|
|
5353
5589
|
console.log(
|
|
5354
|
-
|
|
5590
|
+
chalk68.dim(
|
|
5355
5591
|
`
|
|
5356
5592
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5357
5593
|
)
|
|
@@ -5363,7 +5599,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5363
5599
|
}
|
|
5364
5600
|
|
|
5365
5601
|
// src/commands/complexity/halstead.ts
|
|
5366
|
-
import
|
|
5602
|
+
import chalk69 from "chalk";
|
|
5367
5603
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
5368
5604
|
withSourceFiles(pattern2, (files) => {
|
|
5369
5605
|
const results = [];
|
|
@@ -5378,13 +5614,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5378
5614
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
5379
5615
|
for (const { file, name, metrics } of results) {
|
|
5380
5616
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
5381
|
-
const color = exceedsThreshold ?
|
|
5617
|
+
const color = exceedsThreshold ? chalk69.red : chalk69.white;
|
|
5382
5618
|
console.log(
|
|
5383
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
5619
|
+
`${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))}`
|
|
5384
5620
|
);
|
|
5385
5621
|
}
|
|
5386
5622
|
console.log(
|
|
5387
|
-
|
|
5623
|
+
chalk69.dim(
|
|
5388
5624
|
`
|
|
5389
5625
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5390
5626
|
)
|
|
@@ -5399,28 +5635,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5399
5635
|
import fs13 from "fs";
|
|
5400
5636
|
|
|
5401
5637
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
5402
|
-
import
|
|
5638
|
+
import chalk70 from "chalk";
|
|
5403
5639
|
function displayMaintainabilityResults(results, threshold) {
|
|
5404
5640
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
5405
5641
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
5406
|
-
console.log(
|
|
5642
|
+
console.log(chalk70.green("All files pass maintainability threshold"));
|
|
5407
5643
|
} else {
|
|
5408
5644
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
5409
|
-
const color = threshold !== void 0 ?
|
|
5645
|
+
const color = threshold !== void 0 ? chalk70.red : chalk70.white;
|
|
5410
5646
|
console.log(
|
|
5411
|
-
`${color(file)} \u2192 avg: ${
|
|
5647
|
+
`${color(file)} \u2192 avg: ${chalk70.cyan(avgMaintainability.toFixed(1))}, min: ${chalk70.yellow(minMaintainability.toFixed(1))}`
|
|
5412
5648
|
);
|
|
5413
5649
|
}
|
|
5414
5650
|
}
|
|
5415
|
-
console.log(
|
|
5651
|
+
console.log(chalk70.dim(`
|
|
5416
5652
|
Analyzed ${results.length} files`));
|
|
5417
5653
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
5418
5654
|
console.error(
|
|
5419
|
-
|
|
5655
|
+
chalk70.red(
|
|
5420
5656
|
`
|
|
5421
5657
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
5422
5658
|
|
|
5423
|
-
\u26A0\uFE0F ${
|
|
5659
|
+
\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.`
|
|
5424
5660
|
)
|
|
5425
5661
|
);
|
|
5426
5662
|
process.exit(1);
|
|
@@ -5477,7 +5713,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5477
5713
|
|
|
5478
5714
|
// src/commands/complexity/sloc.ts
|
|
5479
5715
|
import fs14 from "fs";
|
|
5480
|
-
import
|
|
5716
|
+
import chalk71 from "chalk";
|
|
5481
5717
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
5482
5718
|
withSourceFiles(pattern2, (files) => {
|
|
5483
5719
|
const results = [];
|
|
@@ -5493,12 +5729,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5493
5729
|
results.sort((a, b) => b.lines - a.lines);
|
|
5494
5730
|
for (const { file, lines } of results) {
|
|
5495
5731
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
5496
|
-
const color = exceedsThreshold ?
|
|
5497
|
-
console.log(`${color(file)} \u2192 ${
|
|
5732
|
+
const color = exceedsThreshold ? chalk71.red : chalk71.white;
|
|
5733
|
+
console.log(`${color(file)} \u2192 ${chalk71.cyan(lines)} lines`);
|
|
5498
5734
|
}
|
|
5499
5735
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
5500
5736
|
console.log(
|
|
5501
|
-
|
|
5737
|
+
chalk71.dim(`
|
|
5502
5738
|
Total: ${total} lines across ${files.length} files`)
|
|
5503
5739
|
);
|
|
5504
5740
|
if (hasViolation) {
|
|
@@ -5512,21 +5748,21 @@ async function analyze(pattern2) {
|
|
|
5512
5748
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
5513
5749
|
const files = findSourceFiles2(searchPattern);
|
|
5514
5750
|
if (files.length === 0) {
|
|
5515
|
-
console.log(
|
|
5751
|
+
console.log(chalk72.yellow("No files found matching pattern"));
|
|
5516
5752
|
return;
|
|
5517
5753
|
}
|
|
5518
5754
|
if (files.length === 1) {
|
|
5519
5755
|
const file = files[0];
|
|
5520
|
-
console.log(
|
|
5756
|
+
console.log(chalk72.bold.underline("SLOC"));
|
|
5521
5757
|
await sloc(file);
|
|
5522
5758
|
console.log();
|
|
5523
|
-
console.log(
|
|
5759
|
+
console.log(chalk72.bold.underline("Cyclomatic Complexity"));
|
|
5524
5760
|
await cyclomatic(file);
|
|
5525
5761
|
console.log();
|
|
5526
|
-
console.log(
|
|
5762
|
+
console.log(chalk72.bold.underline("Halstead Metrics"));
|
|
5527
5763
|
await halstead(file);
|
|
5528
5764
|
console.log();
|
|
5529
|
-
console.log(
|
|
5765
|
+
console.log(chalk72.bold.underline("Maintainability Index"));
|
|
5530
5766
|
await maintainability(file);
|
|
5531
5767
|
return;
|
|
5532
5768
|
}
|
|
@@ -5554,7 +5790,7 @@ function registerComplexity(program2) {
|
|
|
5554
5790
|
|
|
5555
5791
|
// src/commands/deploy/redirect.ts
|
|
5556
5792
|
import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
|
|
5557
|
-
import
|
|
5793
|
+
import chalk73 from "chalk";
|
|
5558
5794
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
5559
5795
|
if (!window.location.pathname.endsWith('/')) {
|
|
5560
5796
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -5563,22 +5799,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
5563
5799
|
function redirect() {
|
|
5564
5800
|
const indexPath = "index.html";
|
|
5565
5801
|
if (!existsSync22(indexPath)) {
|
|
5566
|
-
console.log(
|
|
5802
|
+
console.log(chalk73.yellow("No index.html found"));
|
|
5567
5803
|
return;
|
|
5568
5804
|
}
|
|
5569
5805
|
const content = readFileSync20(indexPath, "utf-8");
|
|
5570
5806
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
5571
|
-
console.log(
|
|
5807
|
+
console.log(chalk73.dim("Trailing slash script already present"));
|
|
5572
5808
|
return;
|
|
5573
5809
|
}
|
|
5574
5810
|
const headCloseIndex = content.indexOf("</head>");
|
|
5575
5811
|
if (headCloseIndex === -1) {
|
|
5576
|
-
console.log(
|
|
5812
|
+
console.log(chalk73.red("Could not find </head> tag in index.html"));
|
|
5577
5813
|
return;
|
|
5578
5814
|
}
|
|
5579
5815
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
5580
5816
|
writeFileSync18(indexPath, newContent);
|
|
5581
|
-
console.log(
|
|
5817
|
+
console.log(chalk73.green("Added trailing slash redirect to index.html"));
|
|
5582
5818
|
}
|
|
5583
5819
|
|
|
5584
5820
|
// src/commands/registerDeploy.ts
|
|
@@ -5605,7 +5841,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
5605
5841
|
|
|
5606
5842
|
// src/commands/devlog/shared.ts
|
|
5607
5843
|
import { execSync as execSync17 } from "child_process";
|
|
5608
|
-
import
|
|
5844
|
+
import chalk74 from "chalk";
|
|
5609
5845
|
|
|
5610
5846
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
5611
5847
|
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
@@ -5692,13 +5928,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
5692
5928
|
}
|
|
5693
5929
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
5694
5930
|
for (const commit2 of commits) {
|
|
5695
|
-
console.log(` ${
|
|
5931
|
+
console.log(` ${chalk74.yellow(commit2.hash)} ${commit2.message}`);
|
|
5696
5932
|
if (verbose) {
|
|
5697
5933
|
const visibleFiles = commit2.files.filter(
|
|
5698
5934
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
5699
5935
|
);
|
|
5700
5936
|
for (const file of visibleFiles) {
|
|
5701
|
-
console.log(` ${
|
|
5937
|
+
console.log(` ${chalk74.dim(file)}`);
|
|
5702
5938
|
}
|
|
5703
5939
|
}
|
|
5704
5940
|
}
|
|
@@ -5723,15 +5959,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
5723
5959
|
}
|
|
5724
5960
|
|
|
5725
5961
|
// src/commands/devlog/list/printDateHeader.ts
|
|
5726
|
-
import
|
|
5962
|
+
import chalk75 from "chalk";
|
|
5727
5963
|
function printDateHeader(date, isSkipped, entries) {
|
|
5728
5964
|
if (isSkipped) {
|
|
5729
|
-
console.log(`${
|
|
5965
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.dim("skipped")}`);
|
|
5730
5966
|
} else if (entries && entries.length > 0) {
|
|
5731
|
-
const entryInfo = entries.map((e) => `${
|
|
5732
|
-
console.log(`${
|
|
5967
|
+
const entryInfo = entries.map((e) => `${chalk75.green(e.version)} ${e.title}`).join(" | ");
|
|
5968
|
+
console.log(`${chalk75.bold.blue(date)} ${entryInfo}`);
|
|
5733
5969
|
} else {
|
|
5734
|
-
console.log(`${
|
|
5970
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.red("\u26A0 devlog missing")}`);
|
|
5735
5971
|
}
|
|
5736
5972
|
}
|
|
5737
5973
|
|
|
@@ -5835,24 +6071,24 @@ function bumpVersion(version2, type) {
|
|
|
5835
6071
|
|
|
5836
6072
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
5837
6073
|
import { execSync as execSync20 } from "child_process";
|
|
5838
|
-
import
|
|
6074
|
+
import chalk77 from "chalk";
|
|
5839
6075
|
|
|
5840
6076
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
5841
|
-
import
|
|
6077
|
+
import chalk76 from "chalk";
|
|
5842
6078
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
5843
6079
|
if (conventional && firstHash) {
|
|
5844
6080
|
const version2 = getVersionAtCommit(firstHash);
|
|
5845
6081
|
if (version2) {
|
|
5846
|
-
console.log(`${
|
|
6082
|
+
console.log(`${chalk76.bold("version:")} ${stripToMinor(version2)}`);
|
|
5847
6083
|
} else {
|
|
5848
|
-
console.log(`${
|
|
6084
|
+
console.log(`${chalk76.bold("version:")} ${chalk76.red("unknown")}`);
|
|
5849
6085
|
}
|
|
5850
6086
|
} else if (patchVersion && minorVersion) {
|
|
5851
6087
|
console.log(
|
|
5852
|
-
`${
|
|
6088
|
+
`${chalk76.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
5853
6089
|
);
|
|
5854
6090
|
} else {
|
|
5855
|
-
console.log(`${
|
|
6091
|
+
console.log(`${chalk76.bold("version:")} v0.1 (initial)`);
|
|
5856
6092
|
}
|
|
5857
6093
|
}
|
|
5858
6094
|
|
|
@@ -5899,16 +6135,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
5899
6135
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
5900
6136
|
}
|
|
5901
6137
|
function logName(repoName) {
|
|
5902
|
-
console.log(`${
|
|
6138
|
+
console.log(`${chalk77.bold("name:")} ${repoName}`);
|
|
5903
6139
|
}
|
|
5904
6140
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
5905
6141
|
logName(ctx.repoName);
|
|
5906
6142
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
5907
|
-
console.log(
|
|
6143
|
+
console.log(chalk77.bold.blue(targetDate));
|
|
5908
6144
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
5909
6145
|
}
|
|
5910
6146
|
function logNoCommits(lastInfo) {
|
|
5911
|
-
console.log(
|
|
6147
|
+
console.log(chalk77.dim(noCommitsMessage(!!lastInfo)));
|
|
5912
6148
|
}
|
|
5913
6149
|
|
|
5914
6150
|
// src/commands/devlog/next/index.ts
|
|
@@ -5949,11 +6185,11 @@ function next2(options2) {
|
|
|
5949
6185
|
import { execSync as execSync21 } from "child_process";
|
|
5950
6186
|
|
|
5951
6187
|
// src/commands/devlog/repos/printReposTable.ts
|
|
5952
|
-
import
|
|
6188
|
+
import chalk78 from "chalk";
|
|
5953
6189
|
function colorStatus(status2) {
|
|
5954
|
-
if (status2 === "missing") return
|
|
5955
|
-
if (status2 === "outdated") return
|
|
5956
|
-
return
|
|
6190
|
+
if (status2 === "missing") return chalk78.red(status2);
|
|
6191
|
+
if (status2 === "outdated") return chalk78.yellow(status2);
|
|
6192
|
+
return chalk78.green(status2);
|
|
5957
6193
|
}
|
|
5958
6194
|
function formatRow(row, nameWidth) {
|
|
5959
6195
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -5967,8 +6203,8 @@ function printReposTable(rows) {
|
|
|
5967
6203
|
"Last Devlog".padEnd(11),
|
|
5968
6204
|
"Status"
|
|
5969
6205
|
].join(" ");
|
|
5970
|
-
console.log(
|
|
5971
|
-
console.log(
|
|
6206
|
+
console.log(chalk78.dim(header));
|
|
6207
|
+
console.log(chalk78.dim("-".repeat(header.length)));
|
|
5972
6208
|
for (const row of rows) {
|
|
5973
6209
|
console.log(formatRow(row, nameWidth));
|
|
5974
6210
|
}
|
|
@@ -6026,14 +6262,14 @@ function repos(options2) {
|
|
|
6026
6262
|
// src/commands/devlog/skip.ts
|
|
6027
6263
|
import { writeFileSync as writeFileSync19 } from "fs";
|
|
6028
6264
|
import { join as join21 } from "path";
|
|
6029
|
-
import
|
|
6265
|
+
import chalk79 from "chalk";
|
|
6030
6266
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
6031
6267
|
function getBlogConfigPath() {
|
|
6032
6268
|
return join21(BLOG_REPO_ROOT, "assist.yml");
|
|
6033
6269
|
}
|
|
6034
6270
|
function skip(date) {
|
|
6035
6271
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
6036
|
-
console.log(
|
|
6272
|
+
console.log(chalk79.red("Invalid date format. Use YYYY-MM-DD"));
|
|
6037
6273
|
process.exit(1);
|
|
6038
6274
|
}
|
|
6039
6275
|
const repoName = getRepoName();
|
|
@@ -6044,7 +6280,7 @@ function skip(date) {
|
|
|
6044
6280
|
const skipDays = skip2[repoName] ?? [];
|
|
6045
6281
|
if (skipDays.includes(date)) {
|
|
6046
6282
|
console.log(
|
|
6047
|
-
|
|
6283
|
+
chalk79.yellow(`${date} is already in skip list for ${repoName}`)
|
|
6048
6284
|
);
|
|
6049
6285
|
return;
|
|
6050
6286
|
}
|
|
@@ -6054,20 +6290,20 @@ function skip(date) {
|
|
|
6054
6290
|
devlog.skip = skip2;
|
|
6055
6291
|
config.devlog = devlog;
|
|
6056
6292
|
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
6057
|
-
console.log(
|
|
6293
|
+
console.log(chalk79.green(`Added ${date} to skip list for ${repoName}`));
|
|
6058
6294
|
}
|
|
6059
6295
|
|
|
6060
6296
|
// src/commands/devlog/version.ts
|
|
6061
|
-
import
|
|
6297
|
+
import chalk80 from "chalk";
|
|
6062
6298
|
function version() {
|
|
6063
6299
|
const config = loadConfig();
|
|
6064
6300
|
const name = getRepoName();
|
|
6065
6301
|
const lastInfo = getLastVersionInfo(name, config);
|
|
6066
6302
|
const lastVersion = lastInfo?.version ?? null;
|
|
6067
6303
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
6068
|
-
console.log(`${
|
|
6069
|
-
console.log(`${
|
|
6070
|
-
console.log(`${
|
|
6304
|
+
console.log(`${chalk80.bold("name:")} ${name}`);
|
|
6305
|
+
console.log(`${chalk80.bold("last:")} ${lastVersion ?? chalk80.dim("none")}`);
|
|
6306
|
+
console.log(`${chalk80.bold("next:")} ${nextVersion ?? chalk80.dim("none")}`);
|
|
6071
6307
|
}
|
|
6072
6308
|
|
|
6073
6309
|
// src/commands/registerDevlog.ts
|
|
@@ -6091,7 +6327,7 @@ function registerDevlog(program2) {
|
|
|
6091
6327
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
6092
6328
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
6093
6329
|
import { join as join22 } from "path";
|
|
6094
|
-
import
|
|
6330
|
+
import chalk81 from "chalk";
|
|
6095
6331
|
|
|
6096
6332
|
// src/shared/findRepoRoot.ts
|
|
6097
6333
|
import { existsSync as existsSync23 } from "fs";
|
|
@@ -6154,14 +6390,14 @@ function checkBuildLocks(startDir) {
|
|
|
6154
6390
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
6155
6391
|
if (locked) {
|
|
6156
6392
|
console.error(
|
|
6157
|
-
|
|
6393
|
+
chalk81.red("Build output locked (is VS debugging?): ") + locked
|
|
6158
6394
|
);
|
|
6159
6395
|
process.exit(1);
|
|
6160
6396
|
}
|
|
6161
6397
|
}
|
|
6162
6398
|
async function checkBuildLocksCommand() {
|
|
6163
6399
|
checkBuildLocks();
|
|
6164
|
-
console.log(
|
|
6400
|
+
console.log(chalk81.green("No build locks detected"));
|
|
6165
6401
|
}
|
|
6166
6402
|
|
|
6167
6403
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -6260,30 +6496,30 @@ function escapeRegex(s) {
|
|
|
6260
6496
|
}
|
|
6261
6497
|
|
|
6262
6498
|
// src/commands/dotnet/printTree.ts
|
|
6263
|
-
import
|
|
6499
|
+
import chalk82 from "chalk";
|
|
6264
6500
|
function printNodes(nodes, prefix2) {
|
|
6265
6501
|
for (let i = 0; i < nodes.length; i++) {
|
|
6266
6502
|
const isLast = i === nodes.length - 1;
|
|
6267
6503
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
6268
6504
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
6269
6505
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
6270
|
-
const label2 = isMissing ?
|
|
6506
|
+
const label2 = isMissing ? chalk82.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
6271
6507
|
console.log(`${prefix2}${connector}${label2}`);
|
|
6272
6508
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
6273
6509
|
}
|
|
6274
6510
|
}
|
|
6275
6511
|
function printTree(tree, totalCount, solutions) {
|
|
6276
|
-
console.log(
|
|
6277
|
-
console.log(
|
|
6512
|
+
console.log(chalk82.bold("\nProject Dependency Tree"));
|
|
6513
|
+
console.log(chalk82.cyan(tree.relativePath));
|
|
6278
6514
|
printNodes(tree.children, "");
|
|
6279
|
-
console.log(
|
|
6515
|
+
console.log(chalk82.dim(`
|
|
6280
6516
|
${totalCount} projects total (including root)`));
|
|
6281
|
-
console.log(
|
|
6517
|
+
console.log(chalk82.bold("\nSolution Membership"));
|
|
6282
6518
|
if (solutions.length === 0) {
|
|
6283
|
-
console.log(
|
|
6519
|
+
console.log(chalk82.yellow(" Not found in any .sln"));
|
|
6284
6520
|
} else {
|
|
6285
6521
|
for (const sln of solutions) {
|
|
6286
|
-
console.log(` ${
|
|
6522
|
+
console.log(` ${chalk82.green(sln)}`);
|
|
6287
6523
|
}
|
|
6288
6524
|
}
|
|
6289
6525
|
console.log();
|
|
@@ -6312,16 +6548,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
6312
6548
|
// src/commands/dotnet/resolveCsproj.ts
|
|
6313
6549
|
import { existsSync as existsSync24 } from "fs";
|
|
6314
6550
|
import path24 from "path";
|
|
6315
|
-
import
|
|
6551
|
+
import chalk83 from "chalk";
|
|
6316
6552
|
function resolveCsproj(csprojPath) {
|
|
6317
6553
|
const resolved = path24.resolve(csprojPath);
|
|
6318
6554
|
if (!existsSync24(resolved)) {
|
|
6319
|
-
console.error(
|
|
6555
|
+
console.error(chalk83.red(`File not found: ${resolved}`));
|
|
6320
6556
|
process.exit(1);
|
|
6321
6557
|
}
|
|
6322
6558
|
const repoRoot = findRepoRoot(path24.dirname(resolved));
|
|
6323
6559
|
if (!repoRoot) {
|
|
6324
|
-
console.error(
|
|
6560
|
+
console.error(chalk83.red("Could not find git repository root"));
|
|
6325
6561
|
process.exit(1);
|
|
6326
6562
|
}
|
|
6327
6563
|
return { resolved, repoRoot };
|
|
@@ -6371,12 +6607,12 @@ function getChangedCsFiles(scope) {
|
|
|
6371
6607
|
}
|
|
6372
6608
|
|
|
6373
6609
|
// src/commands/dotnet/inSln.ts
|
|
6374
|
-
import
|
|
6610
|
+
import chalk84 from "chalk";
|
|
6375
6611
|
async function inSln(csprojPath) {
|
|
6376
6612
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
6377
6613
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
6378
6614
|
if (solutions.length === 0) {
|
|
6379
|
-
console.log(
|
|
6615
|
+
console.log(chalk84.yellow("Not found in any .sln file"));
|
|
6380
6616
|
process.exit(1);
|
|
6381
6617
|
}
|
|
6382
6618
|
for (const sln of solutions) {
|
|
@@ -6385,7 +6621,7 @@ async function inSln(csprojPath) {
|
|
|
6385
6621
|
}
|
|
6386
6622
|
|
|
6387
6623
|
// src/commands/dotnet/inspect.ts
|
|
6388
|
-
import
|
|
6624
|
+
import chalk90 from "chalk";
|
|
6389
6625
|
|
|
6390
6626
|
// src/shared/formatElapsed.ts
|
|
6391
6627
|
function formatElapsed(ms) {
|
|
@@ -6397,12 +6633,12 @@ function formatElapsed(ms) {
|
|
|
6397
6633
|
}
|
|
6398
6634
|
|
|
6399
6635
|
// src/commands/dotnet/displayIssues.ts
|
|
6400
|
-
import
|
|
6636
|
+
import chalk85 from "chalk";
|
|
6401
6637
|
var SEVERITY_COLOR = {
|
|
6402
|
-
ERROR:
|
|
6403
|
-
WARNING:
|
|
6404
|
-
SUGGESTION:
|
|
6405
|
-
HINT:
|
|
6638
|
+
ERROR: chalk85.red,
|
|
6639
|
+
WARNING: chalk85.yellow,
|
|
6640
|
+
SUGGESTION: chalk85.cyan,
|
|
6641
|
+
HINT: chalk85.dim
|
|
6406
6642
|
};
|
|
6407
6643
|
function groupByFile(issues) {
|
|
6408
6644
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -6418,15 +6654,15 @@ function groupByFile(issues) {
|
|
|
6418
6654
|
}
|
|
6419
6655
|
function displayIssues(issues) {
|
|
6420
6656
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
6421
|
-
console.log(
|
|
6657
|
+
console.log(chalk85.bold(file));
|
|
6422
6658
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
6423
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
6659
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk85.white;
|
|
6424
6660
|
console.log(
|
|
6425
|
-
` ${
|
|
6661
|
+
` ${chalk85.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
6426
6662
|
);
|
|
6427
6663
|
}
|
|
6428
6664
|
}
|
|
6429
|
-
console.log(
|
|
6665
|
+
console.log(chalk85.dim(`
|
|
6430
6666
|
${issues.length} issue(s) found`));
|
|
6431
6667
|
}
|
|
6432
6668
|
|
|
@@ -6485,12 +6721,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
6485
6721
|
// src/commands/dotnet/resolveSolution.ts
|
|
6486
6722
|
import { existsSync as existsSync25 } from "fs";
|
|
6487
6723
|
import path25 from "path";
|
|
6488
|
-
import
|
|
6724
|
+
import chalk87 from "chalk";
|
|
6489
6725
|
|
|
6490
6726
|
// src/commands/dotnet/findSolution.ts
|
|
6491
6727
|
import { readdirSync as readdirSync4 } from "fs";
|
|
6492
6728
|
import { dirname as dirname16, join as join23 } from "path";
|
|
6493
|
-
import
|
|
6729
|
+
import chalk86 from "chalk";
|
|
6494
6730
|
function findSlnInDir(dir) {
|
|
6495
6731
|
try {
|
|
6496
6732
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join23(dir, f));
|
|
@@ -6506,17 +6742,17 @@ function findSolution() {
|
|
|
6506
6742
|
const slnFiles = findSlnInDir(current);
|
|
6507
6743
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
6508
6744
|
if (slnFiles.length > 1) {
|
|
6509
|
-
console.error(
|
|
6745
|
+
console.error(chalk86.red(`Multiple .sln files found in ${current}:`));
|
|
6510
6746
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
6511
6747
|
console.error(
|
|
6512
|
-
|
|
6748
|
+
chalk86.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
6513
6749
|
);
|
|
6514
6750
|
process.exit(1);
|
|
6515
6751
|
}
|
|
6516
6752
|
if (current === ceiling) break;
|
|
6517
6753
|
current = dirname16(current);
|
|
6518
6754
|
}
|
|
6519
|
-
console.error(
|
|
6755
|
+
console.error(chalk86.red("No .sln file found between cwd and repo root"));
|
|
6520
6756
|
process.exit(1);
|
|
6521
6757
|
}
|
|
6522
6758
|
|
|
@@ -6525,7 +6761,7 @@ function resolveSolution(sln) {
|
|
|
6525
6761
|
if (sln) {
|
|
6526
6762
|
const resolved = path25.resolve(sln);
|
|
6527
6763
|
if (!existsSync25(resolved)) {
|
|
6528
|
-
console.error(
|
|
6764
|
+
console.error(chalk87.red(`Solution file not found: ${resolved}`));
|
|
6529
6765
|
process.exit(1);
|
|
6530
6766
|
}
|
|
6531
6767
|
return resolved;
|
|
@@ -6567,14 +6803,14 @@ import { execSync as execSync23 } from "child_process";
|
|
|
6567
6803
|
import { existsSync as existsSync26, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
|
|
6568
6804
|
import { tmpdir as tmpdir2 } from "os";
|
|
6569
6805
|
import path26 from "path";
|
|
6570
|
-
import
|
|
6806
|
+
import chalk88 from "chalk";
|
|
6571
6807
|
function assertJbInstalled() {
|
|
6572
6808
|
try {
|
|
6573
6809
|
execSync23("jb inspectcode --version", { stdio: "pipe" });
|
|
6574
6810
|
} catch {
|
|
6575
|
-
console.error(
|
|
6811
|
+
console.error(chalk88.red("jb is not installed. Install with:"));
|
|
6576
6812
|
console.error(
|
|
6577
|
-
|
|
6813
|
+
chalk88.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
6578
6814
|
);
|
|
6579
6815
|
process.exit(1);
|
|
6580
6816
|
}
|
|
@@ -6592,11 +6828,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6592
6828
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
6593
6829
|
process.stderr.write(err.stderr);
|
|
6594
6830
|
}
|
|
6595
|
-
console.error(
|
|
6831
|
+
console.error(chalk88.red("jb inspectcode failed"));
|
|
6596
6832
|
process.exit(1);
|
|
6597
6833
|
}
|
|
6598
6834
|
if (!existsSync26(reportPath)) {
|
|
6599
|
-
console.error(
|
|
6835
|
+
console.error(chalk88.red("Report file not generated"));
|
|
6600
6836
|
process.exit(1);
|
|
6601
6837
|
}
|
|
6602
6838
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
@@ -6606,7 +6842,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6606
6842
|
|
|
6607
6843
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
6608
6844
|
import { execSync as execSync24 } from "child_process";
|
|
6609
|
-
import
|
|
6845
|
+
import chalk89 from "chalk";
|
|
6610
6846
|
function resolveMsbuildPath() {
|
|
6611
6847
|
const config = loadConfig();
|
|
6612
6848
|
const buildConfig = config.run?.find((r) => r.name === "build");
|
|
@@ -6617,9 +6853,9 @@ function assertMsbuildInstalled() {
|
|
|
6617
6853
|
try {
|
|
6618
6854
|
execSync24(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
6619
6855
|
} catch {
|
|
6620
|
-
console.error(
|
|
6856
|
+
console.error(chalk89.red(`msbuild not found at: ${msbuild}`));
|
|
6621
6857
|
console.error(
|
|
6622
|
-
|
|
6858
|
+
chalk89.yellow(
|
|
6623
6859
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
6624
6860
|
)
|
|
6625
6861
|
);
|
|
@@ -6666,17 +6902,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
6666
6902
|
// src/commands/dotnet/inspect.ts
|
|
6667
6903
|
function logScope(changedFiles) {
|
|
6668
6904
|
if (changedFiles === null) {
|
|
6669
|
-
console.log(
|
|
6905
|
+
console.log(chalk90.dim("Inspecting full solution..."));
|
|
6670
6906
|
} else {
|
|
6671
6907
|
console.log(
|
|
6672
|
-
|
|
6908
|
+
chalk90.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
6673
6909
|
);
|
|
6674
6910
|
}
|
|
6675
6911
|
}
|
|
6676
6912
|
function reportResults(issues, elapsed) {
|
|
6677
6913
|
if (issues.length > 0) displayIssues(issues);
|
|
6678
|
-
else console.log(
|
|
6679
|
-
console.log(
|
|
6914
|
+
else console.log(chalk90.green("No issues found"));
|
|
6915
|
+
console.log(chalk90.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
6680
6916
|
if (issues.length > 0) process.exit(1);
|
|
6681
6917
|
}
|
|
6682
6918
|
async function inspect(sln, options2) {
|
|
@@ -6687,7 +6923,7 @@ async function inspect(sln, options2) {
|
|
|
6687
6923
|
const scope = parseScope(options2.scope);
|
|
6688
6924
|
const changedFiles = getChangedCsFiles(scope);
|
|
6689
6925
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
6690
|
-
console.log(
|
|
6926
|
+
console.log(chalk90.green("No changed .cs files found"));
|
|
6691
6927
|
return;
|
|
6692
6928
|
}
|
|
6693
6929
|
logScope(changedFiles);
|
|
@@ -6713,7 +6949,7 @@ function registerDotnet(program2) {
|
|
|
6713
6949
|
}
|
|
6714
6950
|
|
|
6715
6951
|
// src/commands/jira/acceptanceCriteria.ts
|
|
6716
|
-
import
|
|
6952
|
+
import chalk92 from "chalk";
|
|
6717
6953
|
|
|
6718
6954
|
// src/commands/jira/adfToText.ts
|
|
6719
6955
|
function renderInline(node) {
|
|
@@ -6774,7 +7010,7 @@ function adfToText(doc) {
|
|
|
6774
7010
|
|
|
6775
7011
|
// src/commands/jira/fetchIssue.ts
|
|
6776
7012
|
import { execSync as execSync25 } from "child_process";
|
|
6777
|
-
import
|
|
7013
|
+
import chalk91 from "chalk";
|
|
6778
7014
|
function fetchIssue(issueKey, fields) {
|
|
6779
7015
|
let result;
|
|
6780
7016
|
try {
|
|
@@ -6787,15 +7023,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
6787
7023
|
const stderr = error.stderr;
|
|
6788
7024
|
if (stderr.includes("unauthorized")) {
|
|
6789
7025
|
console.error(
|
|
6790
|
-
|
|
7026
|
+
chalk91.red("Jira authentication expired."),
|
|
6791
7027
|
"Run",
|
|
6792
|
-
|
|
7028
|
+
chalk91.cyan("assist jira auth"),
|
|
6793
7029
|
"to re-authenticate."
|
|
6794
7030
|
);
|
|
6795
7031
|
process.exit(1);
|
|
6796
7032
|
}
|
|
6797
7033
|
}
|
|
6798
|
-
console.error(
|
|
7034
|
+
console.error(chalk91.red(`Failed to fetch ${issueKey}.`));
|
|
6799
7035
|
process.exit(1);
|
|
6800
7036
|
}
|
|
6801
7037
|
return JSON.parse(result);
|
|
@@ -6809,7 +7045,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
6809
7045
|
const parsed = fetchIssue(issueKey, field);
|
|
6810
7046
|
const acValue = parsed?.fields?.[field];
|
|
6811
7047
|
if (!acValue) {
|
|
6812
|
-
console.log(
|
|
7048
|
+
console.log(chalk92.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
6813
7049
|
return;
|
|
6814
7050
|
}
|
|
6815
7051
|
if (typeof acValue === "string") {
|
|
@@ -6904,14 +7140,14 @@ async function jiraAuth() {
|
|
|
6904
7140
|
}
|
|
6905
7141
|
|
|
6906
7142
|
// src/commands/jira/viewIssue.ts
|
|
6907
|
-
import
|
|
7143
|
+
import chalk93 from "chalk";
|
|
6908
7144
|
function viewIssue(issueKey) {
|
|
6909
7145
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
6910
7146
|
const fields = parsed?.fields;
|
|
6911
7147
|
const summary = fields?.summary;
|
|
6912
7148
|
const description = fields?.description;
|
|
6913
7149
|
if (summary) {
|
|
6914
|
-
console.log(
|
|
7150
|
+
console.log(chalk93.bold(summary));
|
|
6915
7151
|
}
|
|
6916
7152
|
if (description) {
|
|
6917
7153
|
if (summary) console.log();
|
|
@@ -6925,7 +7161,7 @@ function viewIssue(issueKey) {
|
|
|
6925
7161
|
}
|
|
6926
7162
|
if (!summary && !description) {
|
|
6927
7163
|
console.log(
|
|
6928
|
-
|
|
7164
|
+
chalk93.yellow(`No summary or description found on ${issueKey}.`)
|
|
6929
7165
|
);
|
|
6930
7166
|
}
|
|
6931
7167
|
}
|
|
@@ -6939,11 +7175,11 @@ function registerJira(program2) {
|
|
|
6939
7175
|
}
|
|
6940
7176
|
|
|
6941
7177
|
// src/commands/news/add/index.ts
|
|
6942
|
-
import
|
|
6943
|
-
import
|
|
7178
|
+
import chalk94 from "chalk";
|
|
7179
|
+
import enquirer8 from "enquirer";
|
|
6944
7180
|
async function add2(url) {
|
|
6945
7181
|
if (!url) {
|
|
6946
|
-
const response = await
|
|
7182
|
+
const response = await enquirer8.prompt({
|
|
6947
7183
|
type: "input",
|
|
6948
7184
|
name: "url",
|
|
6949
7185
|
message: "RSS feed URL:",
|
|
@@ -6962,17 +7198,17 @@ async function add2(url) {
|
|
|
6962
7198
|
const news = config.news ?? {};
|
|
6963
7199
|
const feeds = news.feeds ?? [];
|
|
6964
7200
|
if (feeds.includes(url)) {
|
|
6965
|
-
console.log(
|
|
7201
|
+
console.log(chalk94.yellow("Feed already exists in config"));
|
|
6966
7202
|
return;
|
|
6967
7203
|
}
|
|
6968
7204
|
feeds.push(url);
|
|
6969
7205
|
config.news = { ...news, feeds };
|
|
6970
7206
|
saveGlobalConfig(config);
|
|
6971
|
-
console.log(
|
|
7207
|
+
console.log(chalk94.green(`Added feed: ${url}`));
|
|
6972
7208
|
}
|
|
6973
7209
|
|
|
6974
7210
|
// src/commands/news/web/handleRequest.ts
|
|
6975
|
-
import
|
|
7211
|
+
import chalk95 from "chalk";
|
|
6976
7212
|
|
|
6977
7213
|
// src/commands/news/web/shared.ts
|
|
6978
7214
|
import { decodeHTML } from "entities";
|
|
@@ -7108,17 +7344,17 @@ function prefetch() {
|
|
|
7108
7344
|
const config = loadConfig();
|
|
7109
7345
|
const total = config.news.feeds.length;
|
|
7110
7346
|
if (total === 0) return;
|
|
7111
|
-
process.stdout.write(
|
|
7347
|
+
process.stdout.write(chalk95.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
7112
7348
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
7113
7349
|
const width = 20;
|
|
7114
7350
|
const filled = Math.round(done2 / t * width);
|
|
7115
7351
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
7116
7352
|
process.stdout.write(
|
|
7117
|
-
`\r${
|
|
7353
|
+
`\r${chalk95.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
7118
7354
|
);
|
|
7119
7355
|
}).then((items) => {
|
|
7120
7356
|
process.stdout.write(
|
|
7121
|
-
`\r${
|
|
7357
|
+
`\r${chalk95.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
7122
7358
|
`
|
|
7123
7359
|
);
|
|
7124
7360
|
cachedItems = items;
|
|
@@ -7479,20 +7715,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
7479
7715
|
}
|
|
7480
7716
|
|
|
7481
7717
|
// src/commands/prs/listComments/printComments.ts
|
|
7482
|
-
import
|
|
7718
|
+
import chalk96 from "chalk";
|
|
7483
7719
|
function formatForHuman(comment3) {
|
|
7484
7720
|
if (comment3.type === "review") {
|
|
7485
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
7721
|
+
const stateColor = comment3.state === "APPROVED" ? chalk96.green : comment3.state === "CHANGES_REQUESTED" ? chalk96.red : chalk96.yellow;
|
|
7486
7722
|
return [
|
|
7487
|
-
`${
|
|
7723
|
+
`${chalk96.cyan("Review")} by ${chalk96.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
7488
7724
|
comment3.body,
|
|
7489
7725
|
""
|
|
7490
7726
|
].join("\n");
|
|
7491
7727
|
}
|
|
7492
7728
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
7493
7729
|
return [
|
|
7494
|
-
`${
|
|
7495
|
-
|
|
7730
|
+
`${chalk96.cyan("Line comment")} by ${chalk96.bold(comment3.user)} on ${chalk96.dim(`${comment3.path}${location}`)}`,
|
|
7731
|
+
chalk96.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
7496
7732
|
comment3.body,
|
|
7497
7733
|
""
|
|
7498
7734
|
].join("\n");
|
|
@@ -7579,16 +7815,16 @@ async function listComments() {
|
|
|
7579
7815
|
import { execSync as execSync32 } from "child_process";
|
|
7580
7816
|
|
|
7581
7817
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
7582
|
-
import
|
|
7818
|
+
import enquirer9 from "enquirer";
|
|
7583
7819
|
|
|
7584
7820
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
7585
|
-
import
|
|
7821
|
+
import chalk97 from "chalk";
|
|
7586
7822
|
var STATUS_MAP = {
|
|
7587
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
7588
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
7823
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk97.magenta("merged"), date: pr.mergedAt } : null,
|
|
7824
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk97.red("closed"), date: pr.closedAt } : null
|
|
7589
7825
|
};
|
|
7590
7826
|
function defaultStatus(pr) {
|
|
7591
|
-
return { label:
|
|
7827
|
+
return { label: chalk97.green("opened"), date: pr.createdAt };
|
|
7592
7828
|
}
|
|
7593
7829
|
function getStatus2(pr) {
|
|
7594
7830
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -7597,11 +7833,11 @@ function formatDate(dateStr) {
|
|
|
7597
7833
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
7598
7834
|
}
|
|
7599
7835
|
function formatPrHeader(pr, status2) {
|
|
7600
|
-
return `${
|
|
7836
|
+
return `${chalk97.cyan(`#${pr.number}`)} ${pr.title} ${chalk97.dim(`(${pr.author.login},`)} ${status2.label} ${chalk97.dim(`${formatDate(status2.date)})`)}`;
|
|
7601
7837
|
}
|
|
7602
7838
|
function logPrDetails(pr) {
|
|
7603
7839
|
console.log(
|
|
7604
|
-
|
|
7840
|
+
chalk97.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
7605
7841
|
);
|
|
7606
7842
|
console.log();
|
|
7607
7843
|
}
|
|
@@ -7649,7 +7885,7 @@ function parseAction(action) {
|
|
|
7649
7885
|
}
|
|
7650
7886
|
async function promptNavigation(currentPage, totalPages) {
|
|
7651
7887
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
7652
|
-
const { action } = await
|
|
7888
|
+
const { action } = await enquirer9.prompt({
|
|
7653
7889
|
type: "select",
|
|
7654
7890
|
name: "action",
|
|
7655
7891
|
message: "Navigate",
|
|
@@ -7767,10 +8003,10 @@ function registerPrs(program2) {
|
|
|
7767
8003
|
}
|
|
7768
8004
|
|
|
7769
8005
|
// src/commands/ravendb/ravendbAuth.ts
|
|
7770
|
-
import
|
|
8006
|
+
import chalk103 from "chalk";
|
|
7771
8007
|
|
|
7772
8008
|
// src/shared/createConnectionAuth.ts
|
|
7773
|
-
import
|
|
8009
|
+
import chalk98 from "chalk";
|
|
7774
8010
|
function listConnections(connections, format2) {
|
|
7775
8011
|
if (connections.length === 0) {
|
|
7776
8012
|
console.log("No connections configured.");
|
|
@@ -7783,7 +8019,7 @@ function listConnections(connections, format2) {
|
|
|
7783
8019
|
function removeConnection(connections, name, save) {
|
|
7784
8020
|
const filtered = connections.filter((c) => c.name !== name);
|
|
7785
8021
|
if (filtered.length === connections.length) {
|
|
7786
|
-
console.error(
|
|
8022
|
+
console.error(chalk98.red(`Connection "${name}" not found.`));
|
|
7787
8023
|
process.exit(1);
|
|
7788
8024
|
}
|
|
7789
8025
|
save(filtered);
|
|
@@ -7829,15 +8065,15 @@ function saveConnections(connections) {
|
|
|
7829
8065
|
}
|
|
7830
8066
|
|
|
7831
8067
|
// src/commands/ravendb/promptConnection.ts
|
|
7832
|
-
import
|
|
8068
|
+
import chalk101 from "chalk";
|
|
7833
8069
|
|
|
7834
8070
|
// src/commands/ravendb/selectOpSecret.ts
|
|
7835
|
-
import
|
|
8071
|
+
import chalk100 from "chalk";
|
|
7836
8072
|
import Enquirer2 from "enquirer";
|
|
7837
8073
|
|
|
7838
8074
|
// src/commands/ravendb/searchItems.ts
|
|
7839
8075
|
import { execSync as execSync34 } from "child_process";
|
|
7840
|
-
import
|
|
8076
|
+
import chalk99 from "chalk";
|
|
7841
8077
|
function opExec(args) {
|
|
7842
8078
|
return execSync34(`op ${args}`, {
|
|
7843
8079
|
encoding: "utf-8",
|
|
@@ -7850,7 +8086,7 @@ function searchItems(search2) {
|
|
|
7850
8086
|
items = JSON.parse(opExec("item list --format=json"));
|
|
7851
8087
|
} catch {
|
|
7852
8088
|
console.error(
|
|
7853
|
-
|
|
8089
|
+
chalk99.red(
|
|
7854
8090
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
7855
8091
|
)
|
|
7856
8092
|
);
|
|
@@ -7864,7 +8100,7 @@ function getItemFields(itemId) {
|
|
|
7864
8100
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
7865
8101
|
return item.fields.filter((f) => f.reference && f.label);
|
|
7866
8102
|
} catch {
|
|
7867
|
-
console.error(
|
|
8103
|
+
console.error(chalk99.red("Failed to get item details from 1Password."));
|
|
7868
8104
|
process.exit(1);
|
|
7869
8105
|
}
|
|
7870
8106
|
}
|
|
@@ -7883,7 +8119,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7883
8119
|
}).run();
|
|
7884
8120
|
const items = searchItems(search2);
|
|
7885
8121
|
if (items.length === 0) {
|
|
7886
|
-
console.error(
|
|
8122
|
+
console.error(chalk100.red(`No items found matching "${search2}".`));
|
|
7887
8123
|
process.exit(1);
|
|
7888
8124
|
}
|
|
7889
8125
|
const itemId = await selectOne(
|
|
@@ -7892,7 +8128,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7892
8128
|
);
|
|
7893
8129
|
const fields = getItemFields(itemId);
|
|
7894
8130
|
if (fields.length === 0) {
|
|
7895
|
-
console.error(
|
|
8131
|
+
console.error(chalk100.red("No fields with references found on this item."));
|
|
7896
8132
|
process.exit(1);
|
|
7897
8133
|
}
|
|
7898
8134
|
const ref = await selectOne(
|
|
@@ -7906,7 +8142,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7906
8142
|
async function promptConnection(existingNames) {
|
|
7907
8143
|
const name = await promptInput("name", "Connection name:");
|
|
7908
8144
|
if (existingNames.includes(name)) {
|
|
7909
|
-
console.error(
|
|
8145
|
+
console.error(chalk101.red(`Connection "${name}" already exists.`));
|
|
7910
8146
|
process.exit(1);
|
|
7911
8147
|
}
|
|
7912
8148
|
const url = await promptInput(
|
|
@@ -7915,22 +8151,22 @@ async function promptConnection(existingNames) {
|
|
|
7915
8151
|
);
|
|
7916
8152
|
const database = await promptInput("database", "Database name:");
|
|
7917
8153
|
if (!name || !url || !database) {
|
|
7918
|
-
console.error(
|
|
8154
|
+
console.error(chalk101.red("All fields are required."));
|
|
7919
8155
|
process.exit(1);
|
|
7920
8156
|
}
|
|
7921
8157
|
const apiKeyRef = await selectOpSecret();
|
|
7922
|
-
console.log(
|
|
8158
|
+
console.log(chalk101.dim(`Using: ${apiKeyRef}`));
|
|
7923
8159
|
return { name, url, database, apiKeyRef };
|
|
7924
8160
|
}
|
|
7925
8161
|
|
|
7926
8162
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
7927
|
-
import
|
|
8163
|
+
import chalk102 from "chalk";
|
|
7928
8164
|
function ravendbSetConnection(name) {
|
|
7929
8165
|
const raw = loadGlobalConfigRaw();
|
|
7930
8166
|
const ravendb = raw.ravendb ?? {};
|
|
7931
8167
|
const connections = ravendb.connections ?? [];
|
|
7932
8168
|
if (!connections.some((c) => c.name === name)) {
|
|
7933
|
-
console.error(
|
|
8169
|
+
console.error(chalk102.red(`Connection "${name}" not found.`));
|
|
7934
8170
|
console.error(
|
|
7935
8171
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
7936
8172
|
);
|
|
@@ -7946,16 +8182,16 @@ function ravendbSetConnection(name) {
|
|
|
7946
8182
|
var ravendbAuth = createConnectionAuth({
|
|
7947
8183
|
load: loadConnections,
|
|
7948
8184
|
save: saveConnections,
|
|
7949
|
-
format: (c) => `${
|
|
8185
|
+
format: (c) => `${chalk103.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
7950
8186
|
promptNew: promptConnection,
|
|
7951
8187
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
7952
8188
|
});
|
|
7953
8189
|
|
|
7954
8190
|
// src/commands/ravendb/ravendbCollections.ts
|
|
7955
|
-
import
|
|
8191
|
+
import chalk107 from "chalk";
|
|
7956
8192
|
|
|
7957
8193
|
// src/commands/ravendb/ravenFetch.ts
|
|
7958
|
-
import
|
|
8194
|
+
import chalk105 from "chalk";
|
|
7959
8195
|
|
|
7960
8196
|
// src/commands/ravendb/getAccessToken.ts
|
|
7961
8197
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -7992,10 +8228,10 @@ ${errorText}`
|
|
|
7992
8228
|
|
|
7993
8229
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
7994
8230
|
import { execSync as execSync35 } from "child_process";
|
|
7995
|
-
import
|
|
8231
|
+
import chalk104 from "chalk";
|
|
7996
8232
|
function resolveOpSecret(reference) {
|
|
7997
8233
|
if (!reference.startsWith("op://")) {
|
|
7998
|
-
console.error(
|
|
8234
|
+
console.error(chalk104.red(`Invalid secret reference: must start with op://`));
|
|
7999
8235
|
process.exit(1);
|
|
8000
8236
|
}
|
|
8001
8237
|
try {
|
|
@@ -8005,7 +8241,7 @@ function resolveOpSecret(reference) {
|
|
|
8005
8241
|
}).trim();
|
|
8006
8242
|
} catch {
|
|
8007
8243
|
console.error(
|
|
8008
|
-
|
|
8244
|
+
chalk104.red(
|
|
8009
8245
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
8010
8246
|
)
|
|
8011
8247
|
);
|
|
@@ -8032,7 +8268,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8032
8268
|
if (!response.ok) {
|
|
8033
8269
|
const body = await response.text();
|
|
8034
8270
|
console.error(
|
|
8035
|
-
|
|
8271
|
+
chalk105.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
8036
8272
|
);
|
|
8037
8273
|
console.error(body.substring(0, 500));
|
|
8038
8274
|
process.exit(1);
|
|
@@ -8041,7 +8277,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8041
8277
|
}
|
|
8042
8278
|
|
|
8043
8279
|
// src/commands/ravendb/resolveConnection.ts
|
|
8044
|
-
import
|
|
8280
|
+
import chalk106 from "chalk";
|
|
8045
8281
|
function loadRavendb() {
|
|
8046
8282
|
const raw = loadGlobalConfigRaw();
|
|
8047
8283
|
const ravendb = raw.ravendb;
|
|
@@ -8055,7 +8291,7 @@ function resolveConnection(name) {
|
|
|
8055
8291
|
const connectionName = name ?? defaultConnection;
|
|
8056
8292
|
if (!connectionName) {
|
|
8057
8293
|
console.error(
|
|
8058
|
-
|
|
8294
|
+
chalk106.red(
|
|
8059
8295
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
8060
8296
|
)
|
|
8061
8297
|
);
|
|
@@ -8063,7 +8299,7 @@ function resolveConnection(name) {
|
|
|
8063
8299
|
}
|
|
8064
8300
|
const connection = connections.find((c) => c.name === connectionName);
|
|
8065
8301
|
if (!connection) {
|
|
8066
|
-
console.error(
|
|
8302
|
+
console.error(chalk106.red(`Connection "${connectionName}" not found.`));
|
|
8067
8303
|
console.error(
|
|
8068
8304
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
8069
8305
|
);
|
|
@@ -8094,15 +8330,15 @@ async function ravendbCollections(connectionName) {
|
|
|
8094
8330
|
return;
|
|
8095
8331
|
}
|
|
8096
8332
|
for (const c of collections) {
|
|
8097
|
-
console.log(`${
|
|
8333
|
+
console.log(`${chalk107.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
8098
8334
|
}
|
|
8099
8335
|
}
|
|
8100
8336
|
|
|
8101
8337
|
// src/commands/ravendb/ravendbQuery.ts
|
|
8102
|
-
import
|
|
8338
|
+
import chalk109 from "chalk";
|
|
8103
8339
|
|
|
8104
8340
|
// src/commands/ravendb/fetchAllPages.ts
|
|
8105
|
-
import
|
|
8341
|
+
import chalk108 from "chalk";
|
|
8106
8342
|
|
|
8107
8343
|
// src/commands/ravendb/buildQueryPath.ts
|
|
8108
8344
|
function buildQueryPath(opts) {
|
|
@@ -8140,7 +8376,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8140
8376
|
allResults.push(...results);
|
|
8141
8377
|
start3 += results.length;
|
|
8142
8378
|
process.stderr.write(
|
|
8143
|
-
`\r${
|
|
8379
|
+
`\r${chalk108.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
8144
8380
|
);
|
|
8145
8381
|
if (start3 >= totalResults) break;
|
|
8146
8382
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -8155,7 +8391,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8155
8391
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
8156
8392
|
const resolved = resolveArgs(connectionName, collection);
|
|
8157
8393
|
if (!resolved.collection && !options2.query) {
|
|
8158
|
-
console.error(
|
|
8394
|
+
console.error(chalk109.red("Provide a collection name or --query filter."));
|
|
8159
8395
|
process.exit(1);
|
|
8160
8396
|
}
|
|
8161
8397
|
const { collection: col } = resolved;
|
|
@@ -8193,7 +8429,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
8193
8429
|
import * as path27 from "path";
|
|
8194
8430
|
|
|
8195
8431
|
// src/commands/refactor/logViolations.ts
|
|
8196
|
-
import
|
|
8432
|
+
import chalk110 from "chalk";
|
|
8197
8433
|
var DEFAULT_MAX_LINES = 100;
|
|
8198
8434
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
8199
8435
|
if (violations.length === 0) {
|
|
@@ -8202,43 +8438,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
8202
8438
|
}
|
|
8203
8439
|
return;
|
|
8204
8440
|
}
|
|
8205
|
-
console.error(
|
|
8441
|
+
console.error(chalk110.red(`
|
|
8206
8442
|
Refactor check failed:
|
|
8207
8443
|
`));
|
|
8208
|
-
console.error(
|
|
8444
|
+
console.error(chalk110.red(` The following files exceed ${maxLines} lines:
|
|
8209
8445
|
`));
|
|
8210
8446
|
for (const violation of violations) {
|
|
8211
|
-
console.error(
|
|
8447
|
+
console.error(chalk110.red(` ${violation.file} (${violation.lines} lines)`));
|
|
8212
8448
|
}
|
|
8213
8449
|
console.error(
|
|
8214
|
-
|
|
8450
|
+
chalk110.yellow(
|
|
8215
8451
|
`
|
|
8216
8452
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
8217
8453
|
way to refactor it, ignore it with:
|
|
8218
8454
|
`
|
|
8219
8455
|
)
|
|
8220
8456
|
);
|
|
8221
|
-
console.error(
|
|
8457
|
+
console.error(chalk110.gray(` assist refactor ignore <file>
|
|
8222
8458
|
`));
|
|
8223
8459
|
if (process.env.CLAUDECODE) {
|
|
8224
|
-
console.error(
|
|
8460
|
+
console.error(chalk110.cyan(`
|
|
8225
8461
|
## Extracting Code to New Files
|
|
8226
8462
|
`));
|
|
8227
8463
|
console.error(
|
|
8228
|
-
|
|
8464
|
+
chalk110.cyan(
|
|
8229
8465
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
8230
8466
|
`
|
|
8231
8467
|
)
|
|
8232
8468
|
);
|
|
8233
8469
|
console.error(
|
|
8234
|
-
|
|
8470
|
+
chalk110.cyan(
|
|
8235
8471
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
8236
8472
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
8237
8473
|
`
|
|
8238
8474
|
)
|
|
8239
8475
|
);
|
|
8240
8476
|
console.error(
|
|
8241
|
-
|
|
8477
|
+
chalk110.cyan(
|
|
8242
8478
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
8243
8479
|
domains, move it to a common/shared folder.
|
|
8244
8480
|
`
|
|
@@ -8394,7 +8630,7 @@ async function check(pattern2, options2) {
|
|
|
8394
8630
|
|
|
8395
8631
|
// src/commands/refactor/extract/index.ts
|
|
8396
8632
|
import path33 from "path";
|
|
8397
|
-
import
|
|
8633
|
+
import chalk113 from "chalk";
|
|
8398
8634
|
|
|
8399
8635
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
8400
8636
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -8941,23 +9177,23 @@ function buildPlan(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
8941
9177
|
|
|
8942
9178
|
// src/commands/refactor/extract/displayPlan.ts
|
|
8943
9179
|
import path31 from "path";
|
|
8944
|
-
import
|
|
9180
|
+
import chalk111 from "chalk";
|
|
8945
9181
|
function section(title) {
|
|
8946
9182
|
return `
|
|
8947
|
-
${
|
|
9183
|
+
${chalk111.cyan(title)}`;
|
|
8948
9184
|
}
|
|
8949
9185
|
function displayImporters(plan2, cwd) {
|
|
8950
9186
|
if (plan2.importersToUpdate.length === 0) return;
|
|
8951
9187
|
console.log(section("Update importers:"));
|
|
8952
9188
|
for (const imp of plan2.importersToUpdate) {
|
|
8953
9189
|
const rel = path31.relative(cwd, imp.file.getFilePath());
|
|
8954
|
-
console.log(` ${
|
|
9190
|
+
console.log(` ${chalk111.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
8955
9191
|
}
|
|
8956
9192
|
}
|
|
8957
9193
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
8958
|
-
console.log(
|
|
9194
|
+
console.log(chalk111.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
8959
9195
|
`));
|
|
8960
|
-
console.log(` ${
|
|
9196
|
+
console.log(` ${chalk111.cyan("Functions to move:")}`);
|
|
8961
9197
|
for (const name of plan2.extractedNames) {
|
|
8962
9198
|
console.log(` ${name}`);
|
|
8963
9199
|
}
|
|
@@ -8992,7 +9228,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
8992
9228
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
8993
9229
|
import fs17 from "fs";
|
|
8994
9230
|
import path32 from "path";
|
|
8995
|
-
import
|
|
9231
|
+
import chalk112 from "chalk";
|
|
8996
9232
|
import { Project as Project2 } from "ts-morph";
|
|
8997
9233
|
function findTsConfig(sourcePath) {
|
|
8998
9234
|
const rootConfig = path32.resolve("tsconfig.json");
|
|
@@ -9023,7 +9259,7 @@ function loadProjectFile(file) {
|
|
|
9023
9259
|
});
|
|
9024
9260
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
9025
9261
|
if (!sourceFile) {
|
|
9026
|
-
console.log(
|
|
9262
|
+
console.log(chalk112.red(`File not found in project: ${file}`));
|
|
9027
9263
|
process.exit(1);
|
|
9028
9264
|
}
|
|
9029
9265
|
return { project, sourceFile };
|
|
@@ -9046,19 +9282,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
9046
9282
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
9047
9283
|
if (options2.apply) {
|
|
9048
9284
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
9049
|
-
console.log(
|
|
9285
|
+
console.log(chalk113.green("\nExtraction complete"));
|
|
9050
9286
|
} else {
|
|
9051
|
-
console.log(
|
|
9287
|
+
console.log(chalk113.dim("\nDry run. Use --apply to execute."));
|
|
9052
9288
|
}
|
|
9053
9289
|
}
|
|
9054
9290
|
|
|
9055
9291
|
// src/commands/refactor/ignore.ts
|
|
9056
9292
|
import fs18 from "fs";
|
|
9057
|
-
import
|
|
9293
|
+
import chalk114 from "chalk";
|
|
9058
9294
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
9059
9295
|
function ignore(file) {
|
|
9060
9296
|
if (!fs18.existsSync(file)) {
|
|
9061
|
-
console.error(
|
|
9297
|
+
console.error(chalk114.red(`Error: File does not exist: ${file}`));
|
|
9062
9298
|
process.exit(1);
|
|
9063
9299
|
}
|
|
9064
9300
|
const content = fs18.readFileSync(file, "utf-8");
|
|
@@ -9074,7 +9310,7 @@ function ignore(file) {
|
|
|
9074
9310
|
fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
9075
9311
|
}
|
|
9076
9312
|
console.log(
|
|
9077
|
-
|
|
9313
|
+
chalk114.green(
|
|
9078
9314
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
9079
9315
|
)
|
|
9080
9316
|
);
|
|
@@ -9082,26 +9318,26 @@ function ignore(file) {
|
|
|
9082
9318
|
|
|
9083
9319
|
// src/commands/refactor/rename/index.ts
|
|
9084
9320
|
import path34 from "path";
|
|
9085
|
-
import
|
|
9321
|
+
import chalk115 from "chalk";
|
|
9086
9322
|
async function rename(source, destination, options2 = {}) {
|
|
9087
9323
|
const destPath = path34.resolve(destination);
|
|
9088
9324
|
const cwd = process.cwd();
|
|
9089
9325
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
9090
9326
|
const relDest = path34.relative(cwd, destPath);
|
|
9091
9327
|
const { project, sourceFile } = loadProjectFile(source);
|
|
9092
|
-
console.log(
|
|
9328
|
+
console.log(chalk115.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
9093
9329
|
if (options2.apply) {
|
|
9094
9330
|
sourceFile.move(destPath);
|
|
9095
9331
|
await project.save();
|
|
9096
|
-
console.log(
|
|
9332
|
+
console.log(chalk115.green("Done"));
|
|
9097
9333
|
} else {
|
|
9098
|
-
console.log(
|
|
9334
|
+
console.log(chalk115.dim("Dry run. Use --apply to execute."));
|
|
9099
9335
|
}
|
|
9100
9336
|
}
|
|
9101
9337
|
|
|
9102
9338
|
// src/commands/refactor/renameSymbol/index.ts
|
|
9103
9339
|
import path36 from "path";
|
|
9104
|
-
import
|
|
9340
|
+
import chalk116 from "chalk";
|
|
9105
9341
|
import { Project as Project3 } from "ts-morph";
|
|
9106
9342
|
|
|
9107
9343
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -9150,38 +9386,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
9150
9386
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
9151
9387
|
const sourceFile = project.getSourceFile(filePath);
|
|
9152
9388
|
if (!sourceFile) {
|
|
9153
|
-
console.log(
|
|
9389
|
+
console.log(chalk116.red(`File not found in project: ${file}`));
|
|
9154
9390
|
process.exit(1);
|
|
9155
9391
|
}
|
|
9156
9392
|
const symbol = findSymbol(sourceFile, oldName);
|
|
9157
9393
|
if (!symbol) {
|
|
9158
|
-
console.log(
|
|
9394
|
+
console.log(chalk116.red(`Symbol "${oldName}" not found in ${file}`));
|
|
9159
9395
|
process.exit(1);
|
|
9160
9396
|
}
|
|
9161
9397
|
const grouped = groupReferences(symbol, cwd);
|
|
9162
9398
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
9163
9399
|
console.log(
|
|
9164
|
-
|
|
9400
|
+
chalk116.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
9165
9401
|
`)
|
|
9166
9402
|
);
|
|
9167
9403
|
for (const [refFile, lines] of grouped) {
|
|
9168
9404
|
console.log(
|
|
9169
|
-
` ${
|
|
9405
|
+
` ${chalk116.dim(refFile)}: lines ${chalk116.cyan(lines.join(", "))}`
|
|
9170
9406
|
);
|
|
9171
9407
|
}
|
|
9172
9408
|
if (options2.apply) {
|
|
9173
9409
|
symbol.rename(newName);
|
|
9174
9410
|
await project.save();
|
|
9175
|
-
console.log(
|
|
9411
|
+
console.log(chalk116.green(`
|
|
9176
9412
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
9177
9413
|
} else {
|
|
9178
|
-
console.log(
|
|
9414
|
+
console.log(chalk116.dim("\nDry run. Use --apply to execute."));
|
|
9179
9415
|
}
|
|
9180
9416
|
}
|
|
9181
9417
|
|
|
9182
9418
|
// src/commands/refactor/restructure/index.ts
|
|
9183
9419
|
import path45 from "path";
|
|
9184
|
-
import
|
|
9420
|
+
import chalk119 from "chalk";
|
|
9185
9421
|
|
|
9186
9422
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
9187
9423
|
import path37 from "path";
|
|
@@ -9424,50 +9660,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
9424
9660
|
|
|
9425
9661
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
9426
9662
|
import path41 from "path";
|
|
9427
|
-
import
|
|
9663
|
+
import chalk117 from "chalk";
|
|
9428
9664
|
function relPath(filePath) {
|
|
9429
9665
|
return path41.relative(process.cwd(), filePath);
|
|
9430
9666
|
}
|
|
9431
9667
|
function displayMoves(plan2) {
|
|
9432
9668
|
if (plan2.moves.length === 0) return;
|
|
9433
|
-
console.log(
|
|
9669
|
+
console.log(chalk117.bold("\nFile moves:"));
|
|
9434
9670
|
for (const move of plan2.moves) {
|
|
9435
9671
|
console.log(
|
|
9436
|
-
` ${
|
|
9672
|
+
` ${chalk117.red(relPath(move.from))} \u2192 ${chalk117.green(relPath(move.to))}`
|
|
9437
9673
|
);
|
|
9438
|
-
console.log(
|
|
9674
|
+
console.log(chalk117.dim(` ${move.reason}`));
|
|
9439
9675
|
}
|
|
9440
9676
|
}
|
|
9441
9677
|
function displayRewrites(rewrites) {
|
|
9442
9678
|
if (rewrites.length === 0) return;
|
|
9443
9679
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
9444
|
-
console.log(
|
|
9680
|
+
console.log(chalk117.bold(`
|
|
9445
9681
|
Import rewrites (${affectedFiles.size} files):`));
|
|
9446
9682
|
for (const file of affectedFiles) {
|
|
9447
|
-
console.log(` ${
|
|
9683
|
+
console.log(` ${chalk117.cyan(relPath(file))}:`);
|
|
9448
9684
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
9449
9685
|
(r) => r.file === file
|
|
9450
9686
|
)) {
|
|
9451
9687
|
console.log(
|
|
9452
|
-
` ${
|
|
9688
|
+
` ${chalk117.red(`"${oldSpecifier}"`)} \u2192 ${chalk117.green(`"${newSpecifier}"`)}`
|
|
9453
9689
|
);
|
|
9454
9690
|
}
|
|
9455
9691
|
}
|
|
9456
9692
|
}
|
|
9457
9693
|
function displayPlan2(plan2) {
|
|
9458
9694
|
if (plan2.warnings.length > 0) {
|
|
9459
|
-
console.log(
|
|
9460
|
-
for (const w of plan2.warnings) console.log(
|
|
9695
|
+
console.log(chalk117.yellow("\nWarnings:"));
|
|
9696
|
+
for (const w of plan2.warnings) console.log(chalk117.yellow(` ${w}`));
|
|
9461
9697
|
}
|
|
9462
9698
|
if (plan2.newDirectories.length > 0) {
|
|
9463
|
-
console.log(
|
|
9699
|
+
console.log(chalk117.bold("\nNew directories:"));
|
|
9464
9700
|
for (const dir of plan2.newDirectories)
|
|
9465
|
-
console.log(
|
|
9701
|
+
console.log(chalk117.green(` ${dir}/`));
|
|
9466
9702
|
}
|
|
9467
9703
|
displayMoves(plan2);
|
|
9468
9704
|
displayRewrites(plan2.rewrites);
|
|
9469
9705
|
console.log(
|
|
9470
|
-
|
|
9706
|
+
chalk117.dim(
|
|
9471
9707
|
`
|
|
9472
9708
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
9473
9709
|
)
|
|
@@ -9477,18 +9713,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
9477
9713
|
// src/commands/refactor/restructure/executePlan.ts
|
|
9478
9714
|
import fs20 from "fs";
|
|
9479
9715
|
import path42 from "path";
|
|
9480
|
-
import
|
|
9716
|
+
import chalk118 from "chalk";
|
|
9481
9717
|
function executePlan(plan2) {
|
|
9482
9718
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
9483
9719
|
for (const [file, content] of updatedContents) {
|
|
9484
9720
|
fs20.writeFileSync(file, content, "utf-8");
|
|
9485
9721
|
console.log(
|
|
9486
|
-
|
|
9722
|
+
chalk118.cyan(` Rewrote imports in ${path42.relative(process.cwd(), file)}`)
|
|
9487
9723
|
);
|
|
9488
9724
|
}
|
|
9489
9725
|
for (const dir of plan2.newDirectories) {
|
|
9490
9726
|
fs20.mkdirSync(dir, { recursive: true });
|
|
9491
|
-
console.log(
|
|
9727
|
+
console.log(chalk118.green(` Created ${path42.relative(process.cwd(), dir)}/`));
|
|
9492
9728
|
}
|
|
9493
9729
|
for (const move of plan2.moves) {
|
|
9494
9730
|
const targetDir = path42.dirname(move.to);
|
|
@@ -9497,7 +9733,7 @@ function executePlan(plan2) {
|
|
|
9497
9733
|
}
|
|
9498
9734
|
fs20.renameSync(move.from, move.to);
|
|
9499
9735
|
console.log(
|
|
9500
|
-
|
|
9736
|
+
chalk118.white(
|
|
9501
9737
|
` Moved ${path42.relative(process.cwd(), move.from)} \u2192 ${path42.relative(process.cwd(), move.to)}`
|
|
9502
9738
|
)
|
|
9503
9739
|
);
|
|
@@ -9512,7 +9748,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
9512
9748
|
if (entries.length === 0) {
|
|
9513
9749
|
fs20.rmdirSync(dir);
|
|
9514
9750
|
console.log(
|
|
9515
|
-
|
|
9751
|
+
chalk118.dim(
|
|
9516
9752
|
` Removed empty directory ${path42.relative(process.cwd(), dir)}`
|
|
9517
9753
|
)
|
|
9518
9754
|
);
|
|
@@ -9645,22 +9881,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
9645
9881
|
const targetPattern = pattern2 ?? "src";
|
|
9646
9882
|
const files = findSourceFiles2(targetPattern);
|
|
9647
9883
|
if (files.length === 0) {
|
|
9648
|
-
console.log(
|
|
9884
|
+
console.log(chalk119.yellow("No files found matching pattern"));
|
|
9649
9885
|
return;
|
|
9650
9886
|
}
|
|
9651
9887
|
const tsConfigPath = path45.resolve("tsconfig.json");
|
|
9652
9888
|
const plan2 = buildPlan2(files, tsConfigPath);
|
|
9653
9889
|
if (plan2.moves.length === 0) {
|
|
9654
|
-
console.log(
|
|
9890
|
+
console.log(chalk119.green("No restructuring needed"));
|
|
9655
9891
|
return;
|
|
9656
9892
|
}
|
|
9657
9893
|
displayPlan2(plan2);
|
|
9658
9894
|
if (options2.apply) {
|
|
9659
|
-
console.log(
|
|
9895
|
+
console.log(chalk119.bold("\nApplying changes..."));
|
|
9660
9896
|
executePlan(plan2);
|
|
9661
|
-
console.log(
|
|
9897
|
+
console.log(chalk119.green("\nRestructuring complete"));
|
|
9662
9898
|
} else {
|
|
9663
|
-
console.log(
|
|
9899
|
+
console.log(chalk119.dim("\nDry run. Use --apply to execute."));
|
|
9664
9900
|
}
|
|
9665
9901
|
}
|
|
9666
9902
|
|
|
@@ -9700,7 +9936,7 @@ function registerRefactor(program2) {
|
|
|
9700
9936
|
}
|
|
9701
9937
|
|
|
9702
9938
|
// src/commands/seq/seqAuth.ts
|
|
9703
|
-
import
|
|
9939
|
+
import chalk121 from "chalk";
|
|
9704
9940
|
|
|
9705
9941
|
// src/commands/seq/loadConnections.ts
|
|
9706
9942
|
function loadConnections2() {
|
|
@@ -9729,11 +9965,11 @@ function setDefaultConnection(name) {
|
|
|
9729
9965
|
}
|
|
9730
9966
|
|
|
9731
9967
|
// src/commands/seq/promptConnection.ts
|
|
9732
|
-
import
|
|
9968
|
+
import chalk120 from "chalk";
|
|
9733
9969
|
async function promptConnection2(existingNames) {
|
|
9734
9970
|
const name = await promptInput("name", "Connection name:", "default");
|
|
9735
9971
|
if (existingNames.includes(name)) {
|
|
9736
|
-
console.error(
|
|
9972
|
+
console.error(chalk120.red(`Connection "${name}" already exists.`));
|
|
9737
9973
|
process.exit(1);
|
|
9738
9974
|
}
|
|
9739
9975
|
const url = await promptInput("url", "Seq URL:", "http://localhost:5341");
|
|
@@ -9745,16 +9981,16 @@ async function promptConnection2(existingNames) {
|
|
|
9745
9981
|
var seqAuth = createConnectionAuth({
|
|
9746
9982
|
load: loadConnections2,
|
|
9747
9983
|
save: saveConnections2,
|
|
9748
|
-
format: (c) => `${
|
|
9984
|
+
format: (c) => `${chalk121.bold(c.name)} ${c.url}`,
|
|
9749
9985
|
promptNew: promptConnection2,
|
|
9750
9986
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
9751
9987
|
});
|
|
9752
9988
|
|
|
9753
9989
|
// src/commands/seq/seqQuery.ts
|
|
9754
|
-
import
|
|
9990
|
+
import chalk125 from "chalk";
|
|
9755
9991
|
|
|
9756
9992
|
// src/commands/seq/fetchSeq.ts
|
|
9757
|
-
import
|
|
9993
|
+
import chalk122 from "chalk";
|
|
9758
9994
|
async function fetchSeq(conn, path50, params) {
|
|
9759
9995
|
const url = `${conn.url}${path50}?${params}`;
|
|
9760
9996
|
const response = await fetch(url, {
|
|
@@ -9765,7 +10001,7 @@ async function fetchSeq(conn, path50, params) {
|
|
|
9765
10001
|
});
|
|
9766
10002
|
if (!response.ok) {
|
|
9767
10003
|
const body = await response.text();
|
|
9768
|
-
console.error(
|
|
10004
|
+
console.error(chalk122.red(`Seq returned ${response.status}: ${body}`));
|
|
9769
10005
|
process.exit(1);
|
|
9770
10006
|
}
|
|
9771
10007
|
return response;
|
|
@@ -9818,23 +10054,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
9818
10054
|
}
|
|
9819
10055
|
|
|
9820
10056
|
// src/commands/seq/formatEvent.ts
|
|
9821
|
-
import
|
|
10057
|
+
import chalk123 from "chalk";
|
|
9822
10058
|
function levelColor(level) {
|
|
9823
10059
|
switch (level) {
|
|
9824
10060
|
case "Fatal":
|
|
9825
|
-
return
|
|
10061
|
+
return chalk123.bgRed.white;
|
|
9826
10062
|
case "Error":
|
|
9827
|
-
return
|
|
10063
|
+
return chalk123.red;
|
|
9828
10064
|
case "Warning":
|
|
9829
|
-
return
|
|
10065
|
+
return chalk123.yellow;
|
|
9830
10066
|
case "Information":
|
|
9831
|
-
return
|
|
10067
|
+
return chalk123.cyan;
|
|
9832
10068
|
case "Debug":
|
|
9833
|
-
return
|
|
10069
|
+
return chalk123.gray;
|
|
9834
10070
|
case "Verbose":
|
|
9835
|
-
return
|
|
10071
|
+
return chalk123.dim;
|
|
9836
10072
|
default:
|
|
9837
|
-
return
|
|
10073
|
+
return chalk123.white;
|
|
9838
10074
|
}
|
|
9839
10075
|
}
|
|
9840
10076
|
function levelAbbrev(level) {
|
|
@@ -9875,31 +10111,31 @@ function formatTimestamp(iso) {
|
|
|
9875
10111
|
function formatEvent(event) {
|
|
9876
10112
|
const color = levelColor(event.Level);
|
|
9877
10113
|
const abbrev = levelAbbrev(event.Level);
|
|
9878
|
-
const ts8 =
|
|
10114
|
+
const ts8 = chalk123.dim(formatTimestamp(event.Timestamp));
|
|
9879
10115
|
const msg = renderMessage(event);
|
|
9880
10116
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
9881
10117
|
if (event.Exception) {
|
|
9882
10118
|
for (const line of event.Exception.split("\n")) {
|
|
9883
|
-
lines.push(
|
|
10119
|
+
lines.push(chalk123.red(` ${line}`));
|
|
9884
10120
|
}
|
|
9885
10121
|
}
|
|
9886
10122
|
return lines.join("\n");
|
|
9887
10123
|
}
|
|
9888
10124
|
|
|
9889
10125
|
// src/commands/seq/resolveConnection.ts
|
|
9890
|
-
import
|
|
10126
|
+
import chalk124 from "chalk";
|
|
9891
10127
|
function resolveConnection2(name) {
|
|
9892
10128
|
const connections = loadConnections2();
|
|
9893
10129
|
if (connections.length === 0) {
|
|
9894
10130
|
console.error(
|
|
9895
|
-
|
|
10131
|
+
chalk124.red("No Seq connections configured. Run 'assist seq auth' first.")
|
|
9896
10132
|
);
|
|
9897
10133
|
process.exit(1);
|
|
9898
10134
|
}
|
|
9899
10135
|
const target = name ?? getDefaultConnection() ?? connections[0].name;
|
|
9900
10136
|
const connection = connections.find((c) => c.name === target);
|
|
9901
10137
|
if (!connection) {
|
|
9902
|
-
console.error(
|
|
10138
|
+
console.error(chalk124.red(`Seq connection "${target}" not found.`));
|
|
9903
10139
|
process.exit(1);
|
|
9904
10140
|
}
|
|
9905
10141
|
return connection;
|
|
@@ -9914,7 +10150,7 @@ async function seqQuery(filter, options2) {
|
|
|
9914
10150
|
new URLSearchParams({ filter, count: String(count) })
|
|
9915
10151
|
);
|
|
9916
10152
|
if (events.length === 0) {
|
|
9917
|
-
console.log(
|
|
10153
|
+
console.log(chalk125.yellow("No events found."));
|
|
9918
10154
|
return;
|
|
9919
10155
|
}
|
|
9920
10156
|
if (options2.json) {
|
|
@@ -9925,11 +10161,11 @@ async function seqQuery(filter, options2) {
|
|
|
9925
10161
|
for (const event of chronological) {
|
|
9926
10162
|
console.log(formatEvent(event));
|
|
9927
10163
|
}
|
|
9928
|
-
console.log(
|
|
10164
|
+
console.log(chalk125.dim(`
|
|
9929
10165
|
${events.length} events`));
|
|
9930
10166
|
if (events.length >= count) {
|
|
9931
10167
|
console.log(
|
|
9932
|
-
|
|
10168
|
+
chalk125.yellow(
|
|
9933
10169
|
`Results limited to ${count}. Use --count to retrieve more.`
|
|
9934
10170
|
)
|
|
9935
10171
|
);
|
|
@@ -9937,11 +10173,11 @@ ${events.length} events`));
|
|
|
9937
10173
|
}
|
|
9938
10174
|
|
|
9939
10175
|
// src/commands/seq/seqSetConnection.ts
|
|
9940
|
-
import
|
|
10176
|
+
import chalk126 from "chalk";
|
|
9941
10177
|
function seqSetConnection(name) {
|
|
9942
10178
|
const connections = loadConnections2();
|
|
9943
10179
|
if (!connections.find((c) => c.name === name)) {
|
|
9944
|
-
console.error(
|
|
10180
|
+
console.error(chalk126.red(`Connection "${name}" not found.`));
|
|
9945
10181
|
process.exit(1);
|
|
9946
10182
|
}
|
|
9947
10183
|
setDefaultConnection(name);
|
|
@@ -10480,14 +10716,14 @@ import {
|
|
|
10480
10716
|
import { dirname as dirname20, join as join34 } from "path";
|
|
10481
10717
|
|
|
10482
10718
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
10483
|
-
import
|
|
10719
|
+
import chalk127 from "chalk";
|
|
10484
10720
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
10485
10721
|
function validateStagedContent(filename, content) {
|
|
10486
10722
|
const firstLine = content.split("\n")[0];
|
|
10487
10723
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
10488
10724
|
if (!match) {
|
|
10489
10725
|
console.error(
|
|
10490
|
-
|
|
10726
|
+
chalk127.red(
|
|
10491
10727
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
10492
10728
|
)
|
|
10493
10729
|
);
|
|
@@ -10496,7 +10732,7 @@ function validateStagedContent(filename, content) {
|
|
|
10496
10732
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
10497
10733
|
if (!contentAfterLink) {
|
|
10498
10734
|
console.error(
|
|
10499
|
-
|
|
10735
|
+
chalk127.red(
|
|
10500
10736
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
10501
10737
|
)
|
|
10502
10738
|
);
|
|
@@ -10889,7 +11125,7 @@ function registerVoice(program2) {
|
|
|
10889
11125
|
|
|
10890
11126
|
// src/commands/roam/auth.ts
|
|
10891
11127
|
import { randomBytes } from "crypto";
|
|
10892
|
-
import
|
|
11128
|
+
import chalk128 from "chalk";
|
|
10893
11129
|
|
|
10894
11130
|
// src/lib/openBrowser.ts
|
|
10895
11131
|
import { execSync as execSync38 } from "child_process";
|
|
@@ -11024,7 +11260,7 @@ async function exchangeToken(params) {
|
|
|
11024
11260
|
}
|
|
11025
11261
|
|
|
11026
11262
|
// src/commands/roam/promptCredentials.ts
|
|
11027
|
-
import
|
|
11263
|
+
import enquirer10 from "enquirer";
|
|
11028
11264
|
function censor(value) {
|
|
11029
11265
|
const visible = value.slice(-4);
|
|
11030
11266
|
return `${"*".repeat(value.length - 4)}${visible}`;
|
|
@@ -11033,7 +11269,7 @@ function label(name, existing) {
|
|
|
11033
11269
|
return existing ? `${name} (${censor(existing)})` : name;
|
|
11034
11270
|
}
|
|
11035
11271
|
async function promptField(name, existing) {
|
|
11036
|
-
const { value } = await
|
|
11272
|
+
const { value } = await enquirer10.prompt({
|
|
11037
11273
|
type: "input",
|
|
11038
11274
|
name: "value",
|
|
11039
11275
|
message: `${label(name, existing)}:`,
|
|
@@ -11064,13 +11300,13 @@ async function auth() {
|
|
|
11064
11300
|
saveGlobalConfig(config);
|
|
11065
11301
|
const state = randomBytes(16).toString("hex");
|
|
11066
11302
|
console.log(
|
|
11067
|
-
|
|
11303
|
+
chalk128.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
11068
11304
|
);
|
|
11069
|
-
console.log(
|
|
11070
|
-
console.log(
|
|
11071
|
-
console.log(
|
|
11305
|
+
console.log(chalk128.white("http://localhost:14523/callback\n"));
|
|
11306
|
+
console.log(chalk128.blue("Opening browser for authorization..."));
|
|
11307
|
+
console.log(chalk128.dim("Waiting for authorization callback..."));
|
|
11072
11308
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
11073
|
-
console.log(
|
|
11309
|
+
console.log(chalk128.dim("Exchanging code for tokens..."));
|
|
11074
11310
|
const tokens = await exchangeToken({
|
|
11075
11311
|
code,
|
|
11076
11312
|
clientId,
|
|
@@ -11086,7 +11322,7 @@ async function auth() {
|
|
|
11086
11322
|
};
|
|
11087
11323
|
saveGlobalConfig(config);
|
|
11088
11324
|
console.log(
|
|
11089
|
-
|
|
11325
|
+
chalk128.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
11090
11326
|
);
|
|
11091
11327
|
}
|
|
11092
11328
|
|
|
@@ -11299,7 +11535,7 @@ import { execSync as execSync40 } from "child_process";
|
|
|
11299
11535
|
import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
|
|
11300
11536
|
import { tmpdir as tmpdir6 } from "os";
|
|
11301
11537
|
import { join as join43, resolve as resolve5 } from "path";
|
|
11302
|
-
import
|
|
11538
|
+
import chalk129 from "chalk";
|
|
11303
11539
|
|
|
11304
11540
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
11305
11541
|
var captureWindowPs1 = `
|
|
@@ -11450,22 +11686,22 @@ function screenshot(processName) {
|
|
|
11450
11686
|
const config = loadConfig();
|
|
11451
11687
|
const outputDir = resolve5(config.screenshot.outputDir);
|
|
11452
11688
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
11453
|
-
console.log(
|
|
11689
|
+
console.log(chalk129.gray(`Capturing window for process "${processName}" ...`));
|
|
11454
11690
|
try {
|
|
11455
11691
|
runPowerShellScript(processName, outputPath);
|
|
11456
|
-
console.log(
|
|
11692
|
+
console.log(chalk129.green(`Screenshot saved: ${outputPath}`));
|
|
11457
11693
|
} catch (error) {
|
|
11458
11694
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11459
|
-
console.error(
|
|
11695
|
+
console.error(chalk129.red(`Failed to capture screenshot: ${msg}`));
|
|
11460
11696
|
process.exit(1);
|
|
11461
11697
|
}
|
|
11462
11698
|
}
|
|
11463
11699
|
|
|
11464
11700
|
// src/commands/statusLine.ts
|
|
11465
|
-
import
|
|
11701
|
+
import chalk131 from "chalk";
|
|
11466
11702
|
|
|
11467
11703
|
// src/commands/buildLimitsSegment.ts
|
|
11468
|
-
import
|
|
11704
|
+
import chalk130 from "chalk";
|
|
11469
11705
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
11470
11706
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
11471
11707
|
function formatTimeLeft(resetsAt) {
|
|
@@ -11488,10 +11724,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
11488
11724
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
11489
11725
|
const label2 = `${Math.round(pct)}%`;
|
|
11490
11726
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
11491
|
-
if (projected == null) return
|
|
11492
|
-
if (projected > 100) return
|
|
11493
|
-
if (projected > 75) return
|
|
11494
|
-
return
|
|
11727
|
+
if (projected == null) return chalk130.green(label2);
|
|
11728
|
+
if (projected > 100) return chalk130.red(label2);
|
|
11729
|
+
if (projected > 75) return chalk130.yellow(label2);
|
|
11730
|
+
return chalk130.green(label2);
|
|
11495
11731
|
}
|
|
11496
11732
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
11497
11733
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -11517,14 +11753,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
11517
11753
|
}
|
|
11518
11754
|
|
|
11519
11755
|
// src/commands/statusLine.ts
|
|
11520
|
-
|
|
11756
|
+
chalk131.level = 3;
|
|
11521
11757
|
function formatNumber(num) {
|
|
11522
11758
|
return num.toLocaleString("en-US");
|
|
11523
11759
|
}
|
|
11524
11760
|
function colorizePercent(pct) {
|
|
11525
11761
|
const label2 = `${Math.round(pct)}%`;
|
|
11526
|
-
if (pct > 80) return
|
|
11527
|
-
if (pct > 40) return
|
|
11762
|
+
if (pct > 80) return chalk131.red(label2);
|
|
11763
|
+
if (pct > 40) return chalk131.yellow(label2);
|
|
11528
11764
|
return label2;
|
|
11529
11765
|
}
|
|
11530
11766
|
async function statusLine() {
|
|
@@ -11547,7 +11783,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
11547
11783
|
// src/commands/sync/syncClaudeMd.ts
|
|
11548
11784
|
import * as fs23 from "fs";
|
|
11549
11785
|
import * as path46 from "path";
|
|
11550
|
-
import
|
|
11786
|
+
import chalk132 from "chalk";
|
|
11551
11787
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
11552
11788
|
const source = path46.join(claudeDir, "CLAUDE.md");
|
|
11553
11789
|
const target = path46.join(targetBase, "CLAUDE.md");
|
|
@@ -11556,12 +11792,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11556
11792
|
const targetContent = fs23.readFileSync(target, "utf-8");
|
|
11557
11793
|
if (sourceContent !== targetContent) {
|
|
11558
11794
|
console.log(
|
|
11559
|
-
|
|
11795
|
+
chalk132.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
11560
11796
|
);
|
|
11561
11797
|
console.log();
|
|
11562
11798
|
printDiff(targetContent, sourceContent);
|
|
11563
11799
|
const confirm = options2?.yes || await promptConfirm(
|
|
11564
|
-
|
|
11800
|
+
chalk132.red("Overwrite existing CLAUDE.md?"),
|
|
11565
11801
|
false
|
|
11566
11802
|
);
|
|
11567
11803
|
if (!confirm) {
|
|
@@ -11577,7 +11813,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11577
11813
|
// src/commands/sync/syncSettings.ts
|
|
11578
11814
|
import * as fs24 from "fs";
|
|
11579
11815
|
import * as path47 from "path";
|
|
11580
|
-
import
|
|
11816
|
+
import chalk133 from "chalk";
|
|
11581
11817
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
11582
11818
|
const source = path47.join(claudeDir, "settings.json");
|
|
11583
11819
|
const target = path47.join(targetBase, "settings.json");
|
|
@@ -11593,14 +11829,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
11593
11829
|
if (mergedContent !== normalizedTarget) {
|
|
11594
11830
|
if (!options2?.yes) {
|
|
11595
11831
|
console.log(
|
|
11596
|
-
|
|
11832
|
+
chalk133.yellow(
|
|
11597
11833
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
11598
11834
|
)
|
|
11599
11835
|
);
|
|
11600
11836
|
console.log();
|
|
11601
11837
|
printDiff(targetContent, mergedContent);
|
|
11602
11838
|
const confirm = await promptConfirm(
|
|
11603
|
-
|
|
11839
|
+
chalk133.red("Overwrite existing settings.json?"),
|
|
11604
11840
|
false
|
|
11605
11841
|
);
|
|
11606
11842
|
if (!confirm) {
|
|
@@ -11653,7 +11889,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
11653
11889
|
return false;
|
|
11654
11890
|
}
|
|
11655
11891
|
}
|
|
11656
|
-
async function
|
|
11892
|
+
async function update2() {
|
|
11657
11893
|
const installDir = getInstallDir();
|
|
11658
11894
|
console.log(`Assist is installed at: ${installDir}`);
|
|
11659
11895
|
if (isGitRepo(installDir)) {
|
|
@@ -11705,7 +11941,7 @@ program.command("status-line").description("Format Claude Code status line from
|
|
|
11705
11941
|
program.command("notify").description(
|
|
11706
11942
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
11707
11943
|
).action(notify);
|
|
11708
|
-
program.command("update").description("Update assist to the latest version and sync commands").action(
|
|
11944
|
+
program.command("update").description("Update assist to the latest version and sync commands").action(update2);
|
|
11709
11945
|
program.command("coverage").description("Print global statement coverage percentage").action(coverage);
|
|
11710
11946
|
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);
|
|
11711
11947
|
registerCliHook(program);
|
|
@@ -11727,6 +11963,7 @@ registerVoice(program);
|
|
|
11727
11963
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
11728
11964
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|
|
11729
11965
|
program.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").action(() => launchMode("bug"));
|
|
11966
|
+
program.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").action((id) => refine(id));
|
|
11730
11967
|
var signalCommand = program.command("signal").description("Write an assist signal file");
|
|
11731
11968
|
signalCommand.command("next").description("Write a next signal to chain into assist next").action(() => {
|
|
11732
11969
|
writeSignal("next");
|