@staff0rd/assist 0.175.0 → 0.177.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 +699 -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.177.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
|
|
@@ -1615,6 +1650,9 @@ var assistConfigSchema = z2.strictObject({
|
|
|
1615
1650
|
screenshot: z2.strictObject({
|
|
1616
1651
|
outputDir: z2.string().default("./screenshots")
|
|
1617
1652
|
}).default({ outputDir: "./screenshots" }),
|
|
1653
|
+
backlog: z2.strictObject({
|
|
1654
|
+
autoCommit: z2.boolean().default(false)
|
|
1655
|
+
}).default({ autoCommit: false }),
|
|
1618
1656
|
deny: z2.array(
|
|
1619
1657
|
z2.strictObject({
|
|
1620
1658
|
pattern: z2.string(),
|
|
@@ -1703,7 +1741,7 @@ function getTranscriptConfig() {
|
|
|
1703
1741
|
const config = loadConfig();
|
|
1704
1742
|
if (!config.transcript) {
|
|
1705
1743
|
console.error(
|
|
1706
|
-
|
|
1744
|
+
chalk18.red(
|
|
1707
1745
|
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
1708
1746
|
)
|
|
1709
1747
|
);
|
|
@@ -1792,7 +1830,7 @@ function commit(args) {
|
|
|
1792
1830
|
}
|
|
1793
1831
|
|
|
1794
1832
|
// src/commands/config/index.ts
|
|
1795
|
-
import
|
|
1833
|
+
import chalk19 from "chalk";
|
|
1796
1834
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
1797
1835
|
|
|
1798
1836
|
// src/commands/config/setNestedValue.ts
|
|
@@ -1855,7 +1893,7 @@ function formatIssuePath(issue, key) {
|
|
|
1855
1893
|
function printValidationErrors(issues, key) {
|
|
1856
1894
|
for (const issue of issues) {
|
|
1857
1895
|
console.error(
|
|
1858
|
-
|
|
1896
|
+
chalk19.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
1859
1897
|
);
|
|
1860
1898
|
}
|
|
1861
1899
|
}
|
|
@@ -1872,7 +1910,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
1872
1910
|
function assertNotGlobalOnly(key, global) {
|
|
1873
1911
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
1874
1912
|
console.error(
|
|
1875
|
-
|
|
1913
|
+
chalk19.red(
|
|
1876
1914
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
1877
1915
|
)
|
|
1878
1916
|
);
|
|
@@ -1895,7 +1933,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
1895
1933
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
1896
1934
|
const target = options2.global ? "global" : "project";
|
|
1897
1935
|
console.log(
|
|
1898
|
-
|
|
1936
|
+
chalk19.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
1899
1937
|
);
|
|
1900
1938
|
}
|
|
1901
1939
|
function configList() {
|
|
@@ -1904,7 +1942,7 @@ function configList() {
|
|
|
1904
1942
|
}
|
|
1905
1943
|
|
|
1906
1944
|
// src/commands/config/configGet.ts
|
|
1907
|
-
import
|
|
1945
|
+
import chalk20 from "chalk";
|
|
1908
1946
|
|
|
1909
1947
|
// src/commands/config/getNestedValue.ts
|
|
1910
1948
|
function isTraversable(value) {
|
|
@@ -1936,7 +1974,7 @@ function requireNestedValue(config, key) {
|
|
|
1936
1974
|
return value;
|
|
1937
1975
|
}
|
|
1938
1976
|
function exitKeyNotSet(key) {
|
|
1939
|
-
console.error(
|
|
1977
|
+
console.error(chalk20.red(`Key "${key}" is not set`));
|
|
1940
1978
|
process.exit(1);
|
|
1941
1979
|
}
|
|
1942
1980
|
|
|
@@ -1956,20 +1994,20 @@ function coverage() {
|
|
|
1956
1994
|
}
|
|
1957
1995
|
|
|
1958
1996
|
// src/commands/verify/init/index.ts
|
|
1959
|
-
import
|
|
1997
|
+
import chalk35 from "chalk";
|
|
1960
1998
|
|
|
1961
1999
|
// src/shared/promptMultiselect.ts
|
|
1962
|
-
import
|
|
1963
|
-
import
|
|
2000
|
+
import chalk21 from "chalk";
|
|
2001
|
+
import enquirer4 from "enquirer";
|
|
1964
2002
|
async function promptMultiselect(message, options2) {
|
|
1965
2003
|
const { selected } = await exitOnCancel(
|
|
1966
|
-
|
|
2004
|
+
enquirer4.prompt({
|
|
1967
2005
|
type: "multiselect",
|
|
1968
2006
|
name: "selected",
|
|
1969
2007
|
message,
|
|
1970
2008
|
choices: options2.map((opt) => ({
|
|
1971
2009
|
name: opt.value,
|
|
1972
|
-
message: `${opt.name} - ${
|
|
2010
|
+
message: `${opt.name} - ${chalk21.dim(opt.description)}`
|
|
1973
2011
|
})),
|
|
1974
2012
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
1975
2013
|
symbols: {
|
|
@@ -1986,7 +2024,7 @@ async function promptMultiselect(message, options2) {
|
|
|
1986
2024
|
// src/shared/readPackageJson.ts
|
|
1987
2025
|
import * as fs from "fs";
|
|
1988
2026
|
import * as path from "path";
|
|
1989
|
-
import
|
|
2027
|
+
import chalk22 from "chalk";
|
|
1990
2028
|
function findPackageJson() {
|
|
1991
2029
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1992
2030
|
if (fs.existsSync(packageJsonPath)) {
|
|
@@ -2000,7 +2038,7 @@ function readPackageJson(filePath) {
|
|
|
2000
2038
|
function requirePackageJson() {
|
|
2001
2039
|
const packageJsonPath = findPackageJson();
|
|
2002
2040
|
if (!packageJsonPath) {
|
|
2003
|
-
console.error(
|
|
2041
|
+
console.error(chalk22.red("No package.json found in current directory"));
|
|
2004
2042
|
process.exit(1);
|
|
2005
2043
|
}
|
|
2006
2044
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -2031,7 +2069,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2031
2069
|
// src/commands/verify/installPackage.ts
|
|
2032
2070
|
import { execSync as execSync3 } from "child_process";
|
|
2033
2071
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
2034
|
-
import
|
|
2072
|
+
import chalk23 from "chalk";
|
|
2035
2073
|
function writePackageJson(filePath, pkg) {
|
|
2036
2074
|
writeFileSync6(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
2037
2075
|
`);
|
|
@@ -2046,12 +2084,12 @@ function addScript(pkg, name, command) {
|
|
|
2046
2084
|
};
|
|
2047
2085
|
}
|
|
2048
2086
|
function installPackage(name, cwd) {
|
|
2049
|
-
console.log(
|
|
2087
|
+
console.log(chalk23.dim(`Installing ${name}...`));
|
|
2050
2088
|
try {
|
|
2051
2089
|
execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2052
2090
|
return true;
|
|
2053
2091
|
} catch {
|
|
2054
|
-
console.error(
|
|
2092
|
+
console.error(chalk23.red(`Failed to install ${name}`));
|
|
2055
2093
|
return false;
|
|
2056
2094
|
}
|
|
2057
2095
|
}
|
|
@@ -2098,9 +2136,9 @@ var expectedScripts = {
|
|
|
2098
2136
|
};
|
|
2099
2137
|
|
|
2100
2138
|
// src/commands/verify/setup/setupBuild.ts
|
|
2101
|
-
import
|
|
2139
|
+
import chalk24 from "chalk";
|
|
2102
2140
|
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
2103
|
-
console.log(
|
|
2141
|
+
console.log(chalk24.blue("\nSetting up build verification..."));
|
|
2104
2142
|
let command;
|
|
2105
2143
|
if (hasVite && hasTypescript) {
|
|
2106
2144
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -2109,21 +2147,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
|
2109
2147
|
} else {
|
|
2110
2148
|
command = "npm run build";
|
|
2111
2149
|
}
|
|
2112
|
-
console.log(
|
|
2150
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2113
2151
|
writer("verify:build", command);
|
|
2114
2152
|
}
|
|
2115
2153
|
async function setupTypecheck(_packageJsonPath, writer) {
|
|
2116
|
-
console.log(
|
|
2154
|
+
console.log(chalk24.blue("\nSetting up typecheck verification..."));
|
|
2117
2155
|
const command = "tsc --noEmit";
|
|
2118
|
-
console.log(
|
|
2156
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2119
2157
|
writer("verify:typecheck", command);
|
|
2120
2158
|
}
|
|
2121
2159
|
|
|
2122
2160
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
2123
2161
|
import * as path2 from "path";
|
|
2124
|
-
import
|
|
2162
|
+
import chalk25 from "chalk";
|
|
2125
2163
|
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
2126
|
-
console.log(
|
|
2164
|
+
console.log(chalk25.blue("\nSetting up jscpd..."));
|
|
2127
2165
|
const cwd = path2.dirname(packageJsonPath);
|
|
2128
2166
|
const pkg = readPackageJson(packageJsonPath);
|
|
2129
2167
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -2135,12 +2173,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
|
|
|
2135
2173
|
|
|
2136
2174
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2137
2175
|
import * as path3 from "path";
|
|
2138
|
-
import
|
|
2176
|
+
import chalk27 from "chalk";
|
|
2139
2177
|
|
|
2140
2178
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
2141
2179
|
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
2142
2180
|
import { join as join10 } from "path";
|
|
2143
|
-
import
|
|
2181
|
+
import chalk26 from "chalk";
|
|
2144
2182
|
function loadKnipConfig(knipJsonPath) {
|
|
2145
2183
|
if (existsSync11(knipJsonPath)) {
|
|
2146
2184
|
return JSON.parse(readFileSync10(knipJsonPath, "utf-8"));
|
|
@@ -2159,16 +2197,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
2159
2197
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
2160
2198
|
`
|
|
2161
2199
|
);
|
|
2162
|
-
console.log(
|
|
2200
|
+
console.log(chalk26.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
2163
2201
|
}
|
|
2164
2202
|
} catch {
|
|
2165
|
-
console.log(
|
|
2203
|
+
console.log(chalk26.yellow("Warning: Could not update knip.json"));
|
|
2166
2204
|
}
|
|
2167
2205
|
}
|
|
2168
2206
|
|
|
2169
2207
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2170
2208
|
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
2171
|
-
console.log(
|
|
2209
|
+
console.log(chalk27.blue("\nSetting up hardcoded colors check..."));
|
|
2172
2210
|
const cwd = path3.dirname(packageJsonPath);
|
|
2173
2211
|
if (!hasOpenColor) {
|
|
2174
2212
|
installPackage("open-color", cwd);
|
|
@@ -2179,9 +2217,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
|
2179
2217
|
|
|
2180
2218
|
// src/commands/verify/setup/setupKnip.ts
|
|
2181
2219
|
import * as path4 from "path";
|
|
2182
|
-
import
|
|
2220
|
+
import chalk28 from "chalk";
|
|
2183
2221
|
async function setupKnip(packageJsonPath, writer) {
|
|
2184
|
-
console.log(
|
|
2222
|
+
console.log(chalk28.blue("\nSetting up knip..."));
|
|
2185
2223
|
const cwd = path4.dirname(packageJsonPath);
|
|
2186
2224
|
const pkg = readPackageJson(packageJsonPath);
|
|
2187
2225
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -2192,20 +2230,20 @@ async function setupKnip(packageJsonPath, writer) {
|
|
|
2192
2230
|
|
|
2193
2231
|
// src/commands/verify/setup/setupLint.ts
|
|
2194
2232
|
import * as path5 from "path";
|
|
2195
|
-
import
|
|
2233
|
+
import chalk31 from "chalk";
|
|
2196
2234
|
|
|
2197
2235
|
// src/commands/lint/init.ts
|
|
2198
2236
|
import { execSync as execSync5 } from "child_process";
|
|
2199
2237
|
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
2200
2238
|
import { dirname as dirname7, join as join11 } from "path";
|
|
2201
2239
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2202
|
-
import
|
|
2240
|
+
import chalk30 from "chalk";
|
|
2203
2241
|
|
|
2204
2242
|
// src/shared/promptConfirm.ts
|
|
2205
|
-
import
|
|
2243
|
+
import enquirer5 from "enquirer";
|
|
2206
2244
|
async function promptConfirm(message, initial = true) {
|
|
2207
2245
|
const { confirmed } = await exitOnCancel(
|
|
2208
|
-
|
|
2246
|
+
enquirer5.prompt({
|
|
2209
2247
|
type: "confirm",
|
|
2210
2248
|
name: "confirmed",
|
|
2211
2249
|
message,
|
|
@@ -2303,7 +2341,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
2303
2341
|
}
|
|
2304
2342
|
|
|
2305
2343
|
// src/utils/printDiff.ts
|
|
2306
|
-
import
|
|
2344
|
+
import chalk29 from "chalk";
|
|
2307
2345
|
import * as diff from "diff";
|
|
2308
2346
|
function normalizeJson(content) {
|
|
2309
2347
|
try {
|
|
@@ -2321,11 +2359,11 @@ function printDiff(oldContent, newContent) {
|
|
|
2321
2359
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
2322
2360
|
for (const line of lines) {
|
|
2323
2361
|
if (change.added) {
|
|
2324
|
-
console.log(
|
|
2362
|
+
console.log(chalk29.green(`+ ${line}`));
|
|
2325
2363
|
} else if (change.removed) {
|
|
2326
|
-
console.log(
|
|
2364
|
+
console.log(chalk29.red(`- ${line}`));
|
|
2327
2365
|
} else {
|
|
2328
|
-
console.log(
|
|
2366
|
+
console.log(chalk29.dim(` ${line}`));
|
|
2329
2367
|
}
|
|
2330
2368
|
}
|
|
2331
2369
|
}
|
|
@@ -2359,10 +2397,10 @@ async function init() {
|
|
|
2359
2397
|
console.log("biome.json already has the correct linter config");
|
|
2360
2398
|
return;
|
|
2361
2399
|
}
|
|
2362
|
-
console.log(
|
|
2400
|
+
console.log(chalk30.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
2363
2401
|
console.log();
|
|
2364
2402
|
printDiff(oldContent, newContent);
|
|
2365
|
-
const confirm = await promptConfirm(
|
|
2403
|
+
const confirm = await promptConfirm(chalk30.red("Update biome.json?"));
|
|
2366
2404
|
if (!confirm) {
|
|
2367
2405
|
console.log("Skipped biome.json update");
|
|
2368
2406
|
return;
|
|
@@ -2373,7 +2411,7 @@ async function init() {
|
|
|
2373
2411
|
|
|
2374
2412
|
// src/commands/verify/setup/setupLint.ts
|
|
2375
2413
|
async function setupLint(packageJsonPath, writer) {
|
|
2376
|
-
console.log(
|
|
2414
|
+
console.log(chalk31.blue("\nSetting up biome..."));
|
|
2377
2415
|
const cwd = path5.dirname(packageJsonPath);
|
|
2378
2416
|
const pkg = readPackageJson(packageJsonPath);
|
|
2379
2417
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -2387,9 +2425,9 @@ async function setupLint(packageJsonPath, writer) {
|
|
|
2387
2425
|
|
|
2388
2426
|
// src/commands/verify/setup/setupMadge.ts
|
|
2389
2427
|
import * as path6 from "path";
|
|
2390
|
-
import
|
|
2428
|
+
import chalk32 from "chalk";
|
|
2391
2429
|
async function setupMadge(packageJsonPath, writer) {
|
|
2392
|
-
console.log(
|
|
2430
|
+
console.log(chalk32.blue("\nSetting up madge..."));
|
|
2393
2431
|
const cwd = path6.dirname(packageJsonPath);
|
|
2394
2432
|
const pkg = readPackageJson(packageJsonPath);
|
|
2395
2433
|
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
@@ -2401,18 +2439,18 @@ async function setupMadge(packageJsonPath, writer) {
|
|
|
2401
2439
|
|
|
2402
2440
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
2403
2441
|
import * as path7 from "path";
|
|
2404
|
-
import
|
|
2442
|
+
import chalk33 from "chalk";
|
|
2405
2443
|
async function setupMaintainability(packageJsonPath, writer) {
|
|
2406
|
-
console.log(
|
|
2444
|
+
console.log(chalk33.blue("\nSetting up maintainability check..."));
|
|
2407
2445
|
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
2408
2446
|
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
2409
2447
|
}
|
|
2410
2448
|
|
|
2411
2449
|
// src/commands/verify/setup/setupTest.ts
|
|
2412
2450
|
import * as path8 from "path";
|
|
2413
|
-
import
|
|
2451
|
+
import chalk34 from "chalk";
|
|
2414
2452
|
async function setupTest(packageJsonPath, writer) {
|
|
2415
|
-
console.log(
|
|
2453
|
+
console.log(chalk34.blue("\nSetting up vitest..."));
|
|
2416
2454
|
const cwd = path8.dirname(packageJsonPath);
|
|
2417
2455
|
const pkg = readPackageJson(packageJsonPath);
|
|
2418
2456
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -2581,25 +2619,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
|
|
|
2581
2619
|
for (const choice of selected) {
|
|
2582
2620
|
await handlers[choice]?.(packageJsonPath, writer);
|
|
2583
2621
|
}
|
|
2584
|
-
console.log(
|
|
2622
|
+
console.log(chalk35.green(`
|
|
2585
2623
|
Added ${selected.length} verify script(s):`));
|
|
2586
2624
|
for (const choice of selected) {
|
|
2587
|
-
console.log(
|
|
2625
|
+
console.log(chalk35.green(` - verify:${choice}`));
|
|
2588
2626
|
}
|
|
2589
|
-
console.log(
|
|
2627
|
+
console.log(chalk35.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
2590
2628
|
}
|
|
2591
2629
|
async function promptForScripts(availableOptions) {
|
|
2592
2630
|
if (availableOptions.length === 0) {
|
|
2593
|
-
console.log(
|
|
2631
|
+
console.log(chalk35.green("All verify scripts are already configured!"));
|
|
2594
2632
|
return null;
|
|
2595
2633
|
}
|
|
2596
|
-
console.log(
|
|
2634
|
+
console.log(chalk35.bold("Available verify scripts to add:\n"));
|
|
2597
2635
|
const selected = await promptMultiselect(
|
|
2598
2636
|
"Select verify scripts to add:",
|
|
2599
2637
|
availableOptions
|
|
2600
2638
|
);
|
|
2601
2639
|
if (selected.length === 0) {
|
|
2602
|
-
console.log(
|
|
2640
|
+
console.log(chalk35.yellow("No scripts selected"));
|
|
2603
2641
|
return null;
|
|
2604
2642
|
}
|
|
2605
2643
|
return selected;
|
|
@@ -2619,17 +2657,17 @@ async function init2() {
|
|
|
2619
2657
|
}
|
|
2620
2658
|
|
|
2621
2659
|
// src/commands/vscode/init/index.ts
|
|
2622
|
-
import
|
|
2660
|
+
import chalk37 from "chalk";
|
|
2623
2661
|
|
|
2624
2662
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
2625
2663
|
import * as fs2 from "fs";
|
|
2626
2664
|
import * as path9 from "path";
|
|
2627
|
-
import
|
|
2665
|
+
import chalk36 from "chalk";
|
|
2628
2666
|
function ensureVscodeFolder() {
|
|
2629
2667
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
2630
2668
|
if (!fs2.existsSync(vscodeDir)) {
|
|
2631
2669
|
fs2.mkdirSync(vscodeDir);
|
|
2632
|
-
console.log(
|
|
2670
|
+
console.log(chalk36.dim("Created .vscode folder"));
|
|
2633
2671
|
}
|
|
2634
2672
|
}
|
|
2635
2673
|
function removeVscodeFromGitignore() {
|
|
@@ -2644,7 +2682,7 @@ function removeVscodeFromGitignore() {
|
|
|
2644
2682
|
);
|
|
2645
2683
|
if (filteredLines.length !== lines.length) {
|
|
2646
2684
|
fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2647
|
-
console.log(
|
|
2685
|
+
console.log(chalk36.dim("Removed .vscode references from .gitignore"));
|
|
2648
2686
|
}
|
|
2649
2687
|
}
|
|
2650
2688
|
function createLaunchJson(type) {
|
|
@@ -2663,7 +2701,7 @@ function createLaunchJson(type) {
|
|
|
2663
2701
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
2664
2702
|
fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
2665
2703
|
`);
|
|
2666
|
-
console.log(
|
|
2704
|
+
console.log(chalk36.green("Created .vscode/launch.json"));
|
|
2667
2705
|
}
|
|
2668
2706
|
function createSettingsJson() {
|
|
2669
2707
|
const settings = {
|
|
@@ -2676,7 +2714,7 @@ function createSettingsJson() {
|
|
|
2676
2714
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
2677
2715
|
fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
2678
2716
|
`);
|
|
2679
|
-
console.log(
|
|
2717
|
+
console.log(chalk36.green("Created .vscode/settings.json"));
|
|
2680
2718
|
}
|
|
2681
2719
|
function createExtensionsJson() {
|
|
2682
2720
|
const extensions = {
|
|
@@ -2688,7 +2726,7 @@ function createExtensionsJson() {
|
|
|
2688
2726
|
`${JSON.stringify(extensions, null, " ")}
|
|
2689
2727
|
`
|
|
2690
2728
|
);
|
|
2691
|
-
console.log(
|
|
2729
|
+
console.log(chalk36.green("Created .vscode/extensions.json"));
|
|
2692
2730
|
}
|
|
2693
2731
|
|
|
2694
2732
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
@@ -2745,7 +2783,7 @@ function applySelections(selected, setup2) {
|
|
|
2745
2783
|
for (const choice of selected) handlers[choice]?.();
|
|
2746
2784
|
}
|
|
2747
2785
|
async function promptForOptions(options2) {
|
|
2748
|
-
console.log(
|
|
2786
|
+
console.log(chalk37.bold("Available VS Code configurations to add:\n"));
|
|
2749
2787
|
return promptMultiselect("Select configurations to add:", options2);
|
|
2750
2788
|
}
|
|
2751
2789
|
async function init3({ all = false } = {}) {
|
|
@@ -2753,17 +2791,17 @@ async function init3({ all = false } = {}) {
|
|
|
2753
2791
|
const setup2 = detectVscodeSetup(pkg);
|
|
2754
2792
|
const options2 = getAvailableOptions2(setup2);
|
|
2755
2793
|
if (options2.length === 0) {
|
|
2756
|
-
console.log(
|
|
2794
|
+
console.log(chalk37.green("VS Code configuration already exists!"));
|
|
2757
2795
|
return;
|
|
2758
2796
|
}
|
|
2759
2797
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
2760
2798
|
if (selected.length === 0) {
|
|
2761
|
-
console.log(
|
|
2799
|
+
console.log(chalk37.yellow("No configurations selected"));
|
|
2762
2800
|
return;
|
|
2763
2801
|
}
|
|
2764
2802
|
applySelections(selected, setup2);
|
|
2765
2803
|
console.log(
|
|
2766
|
-
|
|
2804
|
+
chalk37.green(`
|
|
2767
2805
|
Added ${selected.length} VS Code configuration(s)`)
|
|
2768
2806
|
);
|
|
2769
2807
|
}
|
|
@@ -2776,7 +2814,7 @@ async function init4() {
|
|
|
2776
2814
|
|
|
2777
2815
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2778
2816
|
import path16 from "path";
|
|
2779
|
-
import
|
|
2817
|
+
import chalk39 from "chalk";
|
|
2780
2818
|
|
|
2781
2819
|
// src/commands/lint/lint/checkFileNames.ts
|
|
2782
2820
|
import fs5 from "fs";
|
|
@@ -2856,7 +2894,7 @@ function checkFileNames() {
|
|
|
2856
2894
|
}
|
|
2857
2895
|
|
|
2858
2896
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
2859
|
-
import
|
|
2897
|
+
import chalk38 from "chalk";
|
|
2860
2898
|
|
|
2861
2899
|
// src/commands/lint/lint/applyMoves.ts
|
|
2862
2900
|
import fs6 from "fs";
|
|
@@ -2941,25 +2979,25 @@ function fixFileNameViolations(moves) {
|
|
|
2941
2979
|
const start3 = performance.now();
|
|
2942
2980
|
const project = createLintProject();
|
|
2943
2981
|
const cwd = process.cwd();
|
|
2944
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
2982
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk38.green(line)));
|
|
2945
2983
|
const ms = (performance.now() - start3).toFixed(0);
|
|
2946
|
-
console.log(
|
|
2984
|
+
console.log(chalk38.dim(` Done in ${ms}ms`));
|
|
2947
2985
|
}
|
|
2948
2986
|
|
|
2949
2987
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2950
2988
|
function reportViolations(violations) {
|
|
2951
|
-
console.error(
|
|
2989
|
+
console.error(chalk39.red("\nFile name check failed:\n"));
|
|
2952
2990
|
console.error(
|
|
2953
|
-
|
|
2991
|
+
chalk39.red(
|
|
2954
2992
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
2955
2993
|
)
|
|
2956
2994
|
);
|
|
2957
2995
|
for (const violation of violations) {
|
|
2958
|
-
console.error(
|
|
2959
|
-
console.error(
|
|
2996
|
+
console.error(chalk39.red(` ${violation.filePath}`));
|
|
2997
|
+
console.error(chalk39.gray(` Rename to: ${violation.suggestedName}
|
|
2960
2998
|
`));
|
|
2961
2999
|
}
|
|
2962
|
-
console.error(
|
|
3000
|
+
console.error(chalk39.dim(" Run with -f to auto-fix.\n"));
|
|
2963
3001
|
}
|
|
2964
3002
|
function runFileNameCheck(fix = false) {
|
|
2965
3003
|
const violations = checkFileNames();
|
|
@@ -2988,17 +3026,17 @@ function runFileNameCheck(fix = false) {
|
|
|
2988
3026
|
import fs8 from "fs";
|
|
2989
3027
|
|
|
2990
3028
|
// src/commands/lint/shared.ts
|
|
2991
|
-
import
|
|
3029
|
+
import chalk40 from "chalk";
|
|
2992
3030
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
2993
3031
|
if (violations.length > 0) {
|
|
2994
|
-
console.error(
|
|
3032
|
+
console.error(chalk40.red(`
|
|
2995
3033
|
${checkName} failed:
|
|
2996
3034
|
`));
|
|
2997
|
-
console.error(
|
|
3035
|
+
console.error(chalk40.red(` ${errorMessage}
|
|
2998
3036
|
`));
|
|
2999
3037
|
for (const violation of violations) {
|
|
3000
|
-
console.error(
|
|
3001
|
-
console.error(
|
|
3038
|
+
console.error(chalk40.red(` ${violation.filePath}:${violation.line}`));
|
|
3039
|
+
console.error(chalk40.gray(` ${violation.content}
|
|
3002
3040
|
`));
|
|
3003
3041
|
}
|
|
3004
3042
|
return false;
|
|
@@ -3478,14 +3516,14 @@ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSy
|
|
|
3478
3516
|
|
|
3479
3517
|
// src/commands/deploy/init/index.ts
|
|
3480
3518
|
import { execSync as execSync12 } from "child_process";
|
|
3481
|
-
import
|
|
3482
|
-
import
|
|
3519
|
+
import chalk42 from "chalk";
|
|
3520
|
+
import enquirer6 from "enquirer";
|
|
3483
3521
|
|
|
3484
3522
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
3485
3523
|
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
|
|
3486
3524
|
import { dirname as dirname13, join as join14 } from "path";
|
|
3487
3525
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3488
|
-
import
|
|
3526
|
+
import chalk41 from "chalk";
|
|
3489
3527
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
3490
3528
|
var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
|
|
3491
3529
|
function getExistingSiteId() {
|
|
@@ -3510,20 +3548,20 @@ async function updateWorkflow(siteId) {
|
|
|
3510
3548
|
if (existsSync17(WORKFLOW_PATH)) {
|
|
3511
3549
|
const oldContent = readFileSync14(WORKFLOW_PATH, "utf-8");
|
|
3512
3550
|
if (oldContent === newContent) {
|
|
3513
|
-
console.log(
|
|
3551
|
+
console.log(chalk41.green("build.yml is already up to date"));
|
|
3514
3552
|
return;
|
|
3515
3553
|
}
|
|
3516
|
-
console.log(
|
|
3554
|
+
console.log(chalk41.yellow("\nbuild.yml will be updated:"));
|
|
3517
3555
|
console.log();
|
|
3518
3556
|
printDiff(oldContent, newContent);
|
|
3519
|
-
const confirm = await promptConfirm(
|
|
3557
|
+
const confirm = await promptConfirm(chalk41.red("Update build.yml?"));
|
|
3520
3558
|
if (!confirm) {
|
|
3521
3559
|
console.log("Skipped build.yml update");
|
|
3522
3560
|
return;
|
|
3523
3561
|
}
|
|
3524
3562
|
}
|
|
3525
3563
|
writeFileSync13(WORKFLOW_PATH, newContent);
|
|
3526
|
-
console.log(
|
|
3564
|
+
console.log(chalk41.green(`
|
|
3527
3565
|
Created ${WORKFLOW_PATH}`));
|
|
3528
3566
|
}
|
|
3529
3567
|
|
|
@@ -3534,50 +3572,50 @@ async function ensureNetlifyCli() {
|
|
|
3534
3572
|
} catch (error) {
|
|
3535
3573
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
3536
3574
|
throw error;
|
|
3537
|
-
console.error(
|
|
3575
|
+
console.error(chalk42.red("\nNetlify CLI is not installed.\n"));
|
|
3538
3576
|
const install = await promptConfirm("Would you like to install it now?");
|
|
3539
3577
|
if (!install) {
|
|
3540
3578
|
console.log(
|
|
3541
|
-
|
|
3579
|
+
chalk42.yellow(
|
|
3542
3580
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
3543
3581
|
)
|
|
3544
3582
|
);
|
|
3545
3583
|
process.exit(1);
|
|
3546
3584
|
}
|
|
3547
|
-
console.log(
|
|
3585
|
+
console.log(chalk42.dim("\nInstalling netlify-cli...\n"));
|
|
3548
3586
|
execSync12("npm install -g netlify-cli", { stdio: "inherit" });
|
|
3549
3587
|
console.log();
|
|
3550
3588
|
execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
3551
3589
|
}
|
|
3552
3590
|
}
|
|
3553
3591
|
function printSetupInstructions() {
|
|
3554
|
-
console.log(
|
|
3592
|
+
console.log(chalk42.bold("\nDeployment initialized successfully!"));
|
|
3555
3593
|
console.log(
|
|
3556
|
-
|
|
3594
|
+
chalk42.yellow("\nTo complete setup, create a personal access token at:")
|
|
3557
3595
|
);
|
|
3558
3596
|
console.log(
|
|
3559
|
-
|
|
3597
|
+
chalk42.cyan(
|
|
3560
3598
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
3561
3599
|
)
|
|
3562
3600
|
);
|
|
3563
3601
|
console.log(
|
|
3564
|
-
|
|
3602
|
+
chalk42.yellow(
|
|
3565
3603
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
3566
3604
|
)
|
|
3567
3605
|
);
|
|
3568
3606
|
}
|
|
3569
3607
|
async function init5() {
|
|
3570
|
-
console.log(
|
|
3608
|
+
console.log(chalk42.bold("Initializing Netlify deployment...\n"));
|
|
3571
3609
|
const existingSiteId = getExistingSiteId();
|
|
3572
3610
|
if (existingSiteId) {
|
|
3573
|
-
console.log(
|
|
3611
|
+
console.log(chalk42.dim(`Using existing site ID: ${existingSiteId}
|
|
3574
3612
|
`));
|
|
3575
3613
|
await updateWorkflow(existingSiteId);
|
|
3576
3614
|
return;
|
|
3577
3615
|
}
|
|
3578
3616
|
console.log("Creating Netlify site...\n");
|
|
3579
3617
|
await ensureNetlifyCli();
|
|
3580
|
-
const { siteId } = await
|
|
3618
|
+
const { siteId } = await enquirer6.prompt({
|
|
3581
3619
|
type: "input",
|
|
3582
3620
|
name: "siteId",
|
|
3583
3621
|
message: "Enter the Site ID from above:",
|
|
@@ -3749,27 +3787,27 @@ async function notify() {
|
|
|
3749
3787
|
}
|
|
3750
3788
|
|
|
3751
3789
|
// src/commands/backlog/comment/index.ts
|
|
3752
|
-
import
|
|
3790
|
+
import chalk43 from "chalk";
|
|
3753
3791
|
function comment(id, text) {
|
|
3754
3792
|
const result = loadAndFindItem(id);
|
|
3755
3793
|
if (!result) process.exit(1);
|
|
3756
3794
|
addComment(result.item, text);
|
|
3757
3795
|
saveBacklog(result.items);
|
|
3758
|
-
console.log(
|
|
3796
|
+
console.log(chalk43.green(`Comment added to item #${id}.`));
|
|
3759
3797
|
}
|
|
3760
3798
|
|
|
3761
3799
|
// src/commands/backlog/comments/index.ts
|
|
3762
|
-
import
|
|
3800
|
+
import chalk44 from "chalk";
|
|
3763
3801
|
function comments(id) {
|
|
3764
3802
|
const result = loadAndFindItem(id);
|
|
3765
3803
|
if (!result) process.exit(1);
|
|
3766
3804
|
const { item } = result;
|
|
3767
3805
|
const entries = item.comments ?? [];
|
|
3768
3806
|
if (entries.length === 0) {
|
|
3769
|
-
console.log(
|
|
3807
|
+
console.log(chalk44.dim(`No comments on item #${id}.`));
|
|
3770
3808
|
return;
|
|
3771
3809
|
}
|
|
3772
|
-
console.log(
|
|
3810
|
+
console.log(chalk44.bold(`Comments for #${id}: ${item.name}
|
|
3773
3811
|
`));
|
|
3774
3812
|
for (const entry of entries) {
|
|
3775
3813
|
console.log(`${formatComment(entry)}
|
|
@@ -3784,20 +3822,29 @@ function registerCommentCommands(cmd) {
|
|
|
3784
3822
|
}
|
|
3785
3823
|
|
|
3786
3824
|
// src/commands/backlog/add/index.ts
|
|
3787
|
-
import
|
|
3825
|
+
import chalk46 from "chalk";
|
|
3788
3826
|
|
|
3789
3827
|
// src/commands/backlog/commitBacklog.ts
|
|
3790
3828
|
import { execSync as execSync14 } from "child_process";
|
|
3791
3829
|
import { join as join15 } from "path";
|
|
3792
|
-
import
|
|
3830
|
+
import chalk45 from "chalk";
|
|
3793
3831
|
function commitBacklog(id, name) {
|
|
3832
|
+
const config = loadConfig();
|
|
3833
|
+
if (!config.backlog.autoCommit) {
|
|
3834
|
+
console.log(
|
|
3835
|
+
chalk45.yellow(
|
|
3836
|
+
"Warning: auto-commit is disabled. Stage and commit the backlog file manually."
|
|
3837
|
+
)
|
|
3838
|
+
);
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3794
3841
|
try {
|
|
3795
3842
|
const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
|
|
3796
3843
|
const message = `chore: add backlog item #${id} \u2014 ${name}`;
|
|
3797
3844
|
execSync14(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
|
|
3798
3845
|
execSync14(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
|
|
3799
3846
|
} catch {
|
|
3800
|
-
console.log(
|
|
3847
|
+
console.log(chalk45.yellow("Warning: could not auto-commit backlog file."));
|
|
3801
3848
|
}
|
|
3802
3849
|
}
|
|
3803
3850
|
|
|
@@ -3806,9 +3853,9 @@ import { spawnSync } from "child_process";
|
|
|
3806
3853
|
import { mkdtempSync, readFileSync as readFileSync16, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
|
|
3807
3854
|
import { tmpdir } from "os";
|
|
3808
3855
|
import { join as join16 } from "path";
|
|
3809
|
-
import
|
|
3856
|
+
import enquirer7 from "enquirer";
|
|
3810
3857
|
async function promptType() {
|
|
3811
|
-
const { type } = await
|
|
3858
|
+
const { type } = await enquirer7.prompt({
|
|
3812
3859
|
type: "select",
|
|
3813
3860
|
name: "type",
|
|
3814
3861
|
message: "Type:",
|
|
@@ -3818,7 +3865,7 @@ async function promptType() {
|
|
|
3818
3865
|
return type;
|
|
3819
3866
|
}
|
|
3820
3867
|
async function promptName() {
|
|
3821
|
-
const { name } = await
|
|
3868
|
+
const { name } = await enquirer7.prompt({
|
|
3822
3869
|
type: "input",
|
|
3823
3870
|
name: "name",
|
|
3824
3871
|
message: "Name:",
|
|
@@ -3827,14 +3874,14 @@ async function promptName() {
|
|
|
3827
3874
|
return name.trim();
|
|
3828
3875
|
}
|
|
3829
3876
|
async function promptDescription() {
|
|
3830
|
-
const { useEditor } = await
|
|
3877
|
+
const { useEditor } = await enquirer7.prompt({
|
|
3831
3878
|
type: "confirm",
|
|
3832
3879
|
name: "useEditor",
|
|
3833
3880
|
message: "Open editor for description?",
|
|
3834
3881
|
initial: false
|
|
3835
3882
|
});
|
|
3836
3883
|
if (!useEditor) {
|
|
3837
|
-
const { description } = await
|
|
3884
|
+
const { description } = await enquirer7.prompt({
|
|
3838
3885
|
type: "input",
|
|
3839
3886
|
name: "description",
|
|
3840
3887
|
message: "Description (optional):"
|
|
@@ -3860,7 +3907,7 @@ function openEditor() {
|
|
|
3860
3907
|
async function promptAcceptanceCriteria() {
|
|
3861
3908
|
const criteria = [];
|
|
3862
3909
|
for (; ; ) {
|
|
3863
|
-
const { criterion } = await
|
|
3910
|
+
const { criterion } = await enquirer7.prompt({
|
|
3864
3911
|
type: "input",
|
|
3865
3912
|
name: "criterion",
|
|
3866
3913
|
message: "Acceptance criterion (empty to finish):"
|
|
@@ -3889,12 +3936,12 @@ async function addFromOptions(options2) {
|
|
|
3889
3936
|
});
|
|
3890
3937
|
saveBacklog(items);
|
|
3891
3938
|
commitBacklog(id, name);
|
|
3892
|
-
console.log(
|
|
3939
|
+
console.log(chalk46.green(`Added item #${id}: ${name}`));
|
|
3893
3940
|
}
|
|
3894
3941
|
async function add(options2) {
|
|
3895
3942
|
if (!backlogExists()) {
|
|
3896
3943
|
console.log(
|
|
3897
|
-
|
|
3944
|
+
chalk46.yellow(
|
|
3898
3945
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3899
3946
|
)
|
|
3900
3947
|
);
|
|
@@ -3904,13 +3951,13 @@ async function add(options2) {
|
|
|
3904
3951
|
}
|
|
3905
3952
|
|
|
3906
3953
|
// src/commands/backlog/addPhase.ts
|
|
3907
|
-
import
|
|
3954
|
+
import chalk47 from "chalk";
|
|
3908
3955
|
function addPhase(id, name, options2) {
|
|
3909
3956
|
const result = loadAndFindItem(id);
|
|
3910
3957
|
if (!result) return;
|
|
3911
3958
|
const tasks = options2.task ?? [];
|
|
3912
3959
|
if (tasks.length === 0) {
|
|
3913
|
-
console.log(
|
|
3960
|
+
console.log(chalk47.red("At least one --task is required."));
|
|
3914
3961
|
process.exitCode = 1;
|
|
3915
3962
|
return;
|
|
3916
3963
|
}
|
|
@@ -3932,25 +3979,25 @@ function addPhase(id, name, options2) {
|
|
|
3932
3979
|
exportToJsonl(db, dir);
|
|
3933
3980
|
commitBacklog(itemId, result.item.name);
|
|
3934
3981
|
console.log(
|
|
3935
|
-
|
|
3982
|
+
chalk47.green(
|
|
3936
3983
|
`Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
3937
3984
|
)
|
|
3938
3985
|
);
|
|
3939
3986
|
}
|
|
3940
3987
|
|
|
3941
3988
|
// src/commands/backlog/init/index.ts
|
|
3942
|
-
import
|
|
3989
|
+
import chalk48 from "chalk";
|
|
3943
3990
|
async function init6() {
|
|
3944
3991
|
if (backlogExists()) {
|
|
3945
|
-
console.log(
|
|
3992
|
+
console.log(chalk48.yellow("Backlog already exists."));
|
|
3946
3993
|
return;
|
|
3947
3994
|
}
|
|
3948
3995
|
saveBacklog([]);
|
|
3949
|
-
console.log(
|
|
3996
|
+
console.log(chalk48.green("Created backlog."));
|
|
3950
3997
|
}
|
|
3951
3998
|
|
|
3952
3999
|
// src/commands/backlog/list/index.ts
|
|
3953
|
-
import
|
|
4000
|
+
import chalk49 from "chalk";
|
|
3954
4001
|
function filterItems(items, options2) {
|
|
3955
4002
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
3956
4003
|
if (!options2.all)
|
|
@@ -3960,7 +4007,7 @@ function filterItems(items, options2) {
|
|
|
3960
4007
|
async function list2(options2) {
|
|
3961
4008
|
if (!backlogExists()) {
|
|
3962
4009
|
console.log(
|
|
3963
|
-
|
|
4010
|
+
chalk49.yellow(
|
|
3964
4011
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3965
4012
|
)
|
|
3966
4013
|
);
|
|
@@ -3969,12 +4016,12 @@ async function list2(options2) {
|
|
|
3969
4016
|
const allItems = loadBacklog();
|
|
3970
4017
|
const items = filterItems(allItems, options2);
|
|
3971
4018
|
if (items.length === 0) {
|
|
3972
|
-
console.log(
|
|
4019
|
+
console.log(chalk49.dim("Backlog is empty."));
|
|
3973
4020
|
return;
|
|
3974
4021
|
}
|
|
3975
4022
|
for (const item of items) {
|
|
3976
4023
|
console.log(
|
|
3977
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4024
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk49.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
3978
4025
|
);
|
|
3979
4026
|
if (options2.verbose) {
|
|
3980
4027
|
printVerboseDetails(item);
|
|
@@ -3997,7 +4044,7 @@ function registerItemCommands(cmd) {
|
|
|
3997
4044
|
}
|
|
3998
4045
|
|
|
3999
4046
|
// src/commands/backlog/link.ts
|
|
4000
|
-
import
|
|
4047
|
+
import chalk51 from "chalk";
|
|
4001
4048
|
|
|
4002
4049
|
// src/commands/backlog/hasCycle.ts
|
|
4003
4050
|
function hasCycle(items, fromId, toId) {
|
|
@@ -4020,11 +4067,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
4020
4067
|
}
|
|
4021
4068
|
|
|
4022
4069
|
// src/commands/backlog/validateLinkTarget.ts
|
|
4023
|
-
import
|
|
4070
|
+
import chalk50 from "chalk";
|
|
4024
4071
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
4025
4072
|
const toItem = items.find((i) => i.id === toNum);
|
|
4026
4073
|
if (!toItem) {
|
|
4027
|
-
console.log(
|
|
4074
|
+
console.log(chalk50.red(`Item #${toId} not found.`));
|
|
4028
4075
|
return void 0;
|
|
4029
4076
|
}
|
|
4030
4077
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -4033,7 +4080,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4033
4080
|
);
|
|
4034
4081
|
if (duplicate) {
|
|
4035
4082
|
console.log(
|
|
4036
|
-
|
|
4083
|
+
chalk50.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
4037
4084
|
);
|
|
4038
4085
|
return void 0;
|
|
4039
4086
|
}
|
|
@@ -4044,13 +4091,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4044
4091
|
function link(fromId, toId, opts) {
|
|
4045
4092
|
const linkType = opts.type ?? "relates-to";
|
|
4046
4093
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
4047
|
-
console.log(
|
|
4094
|
+
console.log(chalk51.red(`Invalid link type: ${linkType}`));
|
|
4048
4095
|
return;
|
|
4049
4096
|
}
|
|
4050
4097
|
const fromNum = Number.parseInt(fromId, 10);
|
|
4051
4098
|
const toNum = Number.parseInt(toId, 10);
|
|
4052
4099
|
if (fromNum === toNum) {
|
|
4053
|
-
console.log(
|
|
4100
|
+
console.log(chalk51.red("Cannot link an item to itself."));
|
|
4054
4101
|
return;
|
|
4055
4102
|
}
|
|
4056
4103
|
const result = loadAndFindItem(fromId);
|
|
@@ -4067,7 +4114,7 @@ function link(fromId, toId, opts) {
|
|
|
4067
4114
|
if (!toItem) return;
|
|
4068
4115
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
4069
4116
|
console.log(
|
|
4070
|
-
|
|
4117
|
+
chalk51.red(
|
|
4071
4118
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
4072
4119
|
)
|
|
4073
4120
|
);
|
|
@@ -4077,32 +4124,32 @@ function link(fromId, toId, opts) {
|
|
|
4077
4124
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
4078
4125
|
saveBacklog(items);
|
|
4079
4126
|
console.log(
|
|
4080
|
-
|
|
4127
|
+
chalk51.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
4081
4128
|
);
|
|
4082
4129
|
}
|
|
4083
4130
|
|
|
4084
4131
|
// src/commands/backlog/unlink.ts
|
|
4085
|
-
import
|
|
4132
|
+
import chalk52 from "chalk";
|
|
4086
4133
|
function unlink(fromId, toId) {
|
|
4087
4134
|
const toNum = Number.parseInt(toId, 10);
|
|
4088
4135
|
const result = loadAndFindItem(fromId);
|
|
4089
4136
|
if (!result) return;
|
|
4090
4137
|
const { items, item: fromItem } = result;
|
|
4091
4138
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
4092
|
-
console.log(
|
|
4139
|
+
console.log(chalk52.yellow(`No links found on item #${fromId}.`));
|
|
4093
4140
|
return;
|
|
4094
4141
|
}
|
|
4095
4142
|
const before = fromItem.links.length;
|
|
4096
4143
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
4097
4144
|
if (fromItem.links.length === before) {
|
|
4098
|
-
console.log(
|
|
4145
|
+
console.log(chalk52.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
4099
4146
|
return;
|
|
4100
4147
|
}
|
|
4101
4148
|
if (fromItem.links.length === 0) {
|
|
4102
4149
|
fromItem.links = void 0;
|
|
4103
4150
|
}
|
|
4104
4151
|
saveBacklog(items);
|
|
4105
|
-
console.log(
|
|
4152
|
+
console.log(chalk52.green(`Removed link from #${fromId} to #${toId}.`));
|
|
4106
4153
|
}
|
|
4107
4154
|
|
|
4108
4155
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -4115,12 +4162,19 @@ function registerLinkCommands(cmd) {
|
|
|
4115
4162
|
cmd.command("unlink <from> <to>").description("Remove a link between two backlog items").action(unlink);
|
|
4116
4163
|
}
|
|
4117
4164
|
|
|
4165
|
+
// src/commands/backlog/registerRunCommand.ts
|
|
4166
|
+
function registerRunCommand(cmd) {
|
|
4167
|
+
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) => {
|
|
4168
|
+
await run(id, { allowEdits: opts.write });
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
|
|
4118
4172
|
// src/commands/backlog/search/index.ts
|
|
4119
|
-
import
|
|
4173
|
+
import chalk53 from "chalk";
|
|
4120
4174
|
async function search(query) {
|
|
4121
4175
|
if (!backlogExists()) {
|
|
4122
4176
|
console.log(
|
|
4123
|
-
|
|
4177
|
+
chalk53.yellow(
|
|
4124
4178
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4125
4179
|
)
|
|
4126
4180
|
);
|
|
@@ -4128,18 +4182,18 @@ async function search(query) {
|
|
|
4128
4182
|
}
|
|
4129
4183
|
const items = searchBacklog(query);
|
|
4130
4184
|
if (items.length === 0) {
|
|
4131
|
-
console.log(
|
|
4185
|
+
console.log(chalk53.dim(`No items matching "${query}".`));
|
|
4132
4186
|
return;
|
|
4133
4187
|
}
|
|
4134
4188
|
console.log(
|
|
4135
|
-
|
|
4189
|
+
chalk53.dim(
|
|
4136
4190
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
4137
4191
|
`
|
|
4138
4192
|
)
|
|
4139
4193
|
);
|
|
4140
4194
|
for (const item of items) {
|
|
4141
4195
|
console.log(
|
|
4142
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4196
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk53.dim(`#${item.id}`)} ${item.name}`
|
|
4143
4197
|
);
|
|
4144
4198
|
}
|
|
4145
4199
|
}
|
|
@@ -4150,16 +4204,16 @@ function registerSearchCommand(cmd) {
|
|
|
4150
4204
|
}
|
|
4151
4205
|
|
|
4152
4206
|
// src/commands/backlog/delete/index.ts
|
|
4153
|
-
import
|
|
4207
|
+
import chalk54 from "chalk";
|
|
4154
4208
|
async function del(id) {
|
|
4155
4209
|
const name = removeItem(id);
|
|
4156
4210
|
if (name) {
|
|
4157
|
-
console.log(
|
|
4211
|
+
console.log(chalk54.green(`Deleted item #${id}: ${name}`));
|
|
4158
4212
|
}
|
|
4159
4213
|
}
|
|
4160
4214
|
|
|
4161
4215
|
// src/commands/backlog/done/index.ts
|
|
4162
|
-
import
|
|
4216
|
+
import chalk55 from "chalk";
|
|
4163
4217
|
async function done(id, summary) {
|
|
4164
4218
|
const result = loadAndFindItem(id);
|
|
4165
4219
|
if (!result) return;
|
|
@@ -4169,20 +4223,20 @@ async function done(id, summary) {
|
|
|
4169
4223
|
addPhaseSummary(result.item, summary, phase);
|
|
4170
4224
|
}
|
|
4171
4225
|
saveBacklog(result.items);
|
|
4172
|
-
console.log(
|
|
4226
|
+
console.log(chalk55.green(`Completed item #${id}: ${result.item.name}`));
|
|
4173
4227
|
}
|
|
4174
4228
|
|
|
4175
4229
|
// src/commands/backlog/start/index.ts
|
|
4176
|
-
import
|
|
4230
|
+
import chalk56 from "chalk";
|
|
4177
4231
|
async function start(id) {
|
|
4178
4232
|
const name = setStatus(id, "in-progress");
|
|
4179
4233
|
if (name) {
|
|
4180
|
-
console.log(
|
|
4234
|
+
console.log(chalk56.green(`Started item #${id}: ${name}`));
|
|
4181
4235
|
}
|
|
4182
4236
|
}
|
|
4183
4237
|
|
|
4184
4238
|
// src/commands/backlog/wontdo/index.ts
|
|
4185
|
-
import
|
|
4239
|
+
import chalk57 from "chalk";
|
|
4186
4240
|
async function wontdo(id, reason) {
|
|
4187
4241
|
const result = loadAndFindItem(id);
|
|
4188
4242
|
if (!result) return;
|
|
@@ -4192,7 +4246,7 @@ async function wontdo(id, reason) {
|
|
|
4192
4246
|
addPhaseSummary(result.item, reason, phase);
|
|
4193
4247
|
}
|
|
4194
4248
|
saveBacklog(result.items);
|
|
4195
|
-
console.log(
|
|
4249
|
+
console.log(chalk57.red(`Won't do item #${id}: ${result.item.name}`));
|
|
4196
4250
|
}
|
|
4197
4251
|
|
|
4198
4252
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -4203,6 +4257,204 @@ function registerStatusCommands(cmd) {
|
|
|
4203
4257
|
cmd.command("delete <id>").alias("remove").description("Delete a backlog item").action(del);
|
|
4204
4258
|
}
|
|
4205
4259
|
|
|
4260
|
+
// src/commands/backlog/removePhase.ts
|
|
4261
|
+
import chalk59 from "chalk";
|
|
4262
|
+
|
|
4263
|
+
// src/commands/backlog/findPhase.ts
|
|
4264
|
+
import chalk58 from "chalk";
|
|
4265
|
+
function findPhase(id, phase) {
|
|
4266
|
+
const result = loadAndFindItem(id);
|
|
4267
|
+
if (!result) return void 0;
|
|
4268
|
+
const dir = getBacklogDir();
|
|
4269
|
+
const db = openDb(dir);
|
|
4270
|
+
const itemId = result.item.id;
|
|
4271
|
+
const phaseIdx = Number.parseInt(phase, 10);
|
|
4272
|
+
const existing = db.prepare(
|
|
4273
|
+
"SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
|
|
4274
|
+
).get(itemId, phaseIdx);
|
|
4275
|
+
if (existing.cnt === 0) {
|
|
4276
|
+
console.log(chalk58.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
|
|
4277
|
+
process.exitCode = 1;
|
|
4278
|
+
return void 0;
|
|
4279
|
+
}
|
|
4280
|
+
return { result, dir, db, itemId, phaseIdx };
|
|
4281
|
+
}
|
|
4282
|
+
function reindexPhases(db, itemId) {
|
|
4283
|
+
const remaining = db.prepare("SELECT idx FROM plan_phases WHERE item_id = ? ORDER BY idx").all(itemId);
|
|
4284
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
4285
|
+
const oldIdx = remaining[i].idx;
|
|
4286
|
+
if (oldIdx !== i) {
|
|
4287
|
+
db.prepare(
|
|
4288
|
+
"UPDATE plan_tasks SET phase_idx = ? WHERE item_id = ? AND phase_idx = ?"
|
|
4289
|
+
).run(i, itemId, oldIdx);
|
|
4290
|
+
db.prepare(
|
|
4291
|
+
"UPDATE plan_phases SET idx = ? WHERE item_id = ? AND idx = ?"
|
|
4292
|
+
).run(i, itemId, oldIdx);
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
function adjustCurrentPhase(db, item, removedIdx) {
|
|
4297
|
+
if (item.currentPhase === void 0) return;
|
|
4298
|
+
if (removedIdx < item.currentPhase) {
|
|
4299
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4300
|
+
item.currentPhase - 1,
|
|
4301
|
+
item.id
|
|
4302
|
+
);
|
|
4303
|
+
} else if (removedIdx === item.currentPhase) {
|
|
4304
|
+
const { cnt } = db.prepare("SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ?").get(item.id);
|
|
4305
|
+
const newPhase = cnt === 0 ? null : Math.min(item.currentPhase, cnt - 1);
|
|
4306
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4307
|
+
newPhase,
|
|
4308
|
+
item.id
|
|
4309
|
+
);
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
|
|
4313
|
+
// src/commands/backlog/removePhase.ts
|
|
4314
|
+
function removePhase(id, phase) {
|
|
4315
|
+
const found = findPhase(id, phase);
|
|
4316
|
+
if (!found) return;
|
|
4317
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4318
|
+
const run4 = db.transaction(() => {
|
|
4319
|
+
db.prepare(
|
|
4320
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4321
|
+
).run(itemId, phaseIdx);
|
|
4322
|
+
db.prepare("DELETE FROM plan_phases WHERE item_id = ? AND idx = ?").run(
|
|
4323
|
+
itemId,
|
|
4324
|
+
phaseIdx
|
|
4325
|
+
);
|
|
4326
|
+
reindexPhases(db, itemId);
|
|
4327
|
+
adjustCurrentPhase(db, result.item, phaseIdx);
|
|
4328
|
+
});
|
|
4329
|
+
run4();
|
|
4330
|
+
exportToJsonl(db, dir);
|
|
4331
|
+
commitBacklog(itemId, result.item.name);
|
|
4332
|
+
console.log(chalk59.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4335
|
+
// src/commands/backlog/update/index.ts
|
|
4336
|
+
import chalk61 from "chalk";
|
|
4337
|
+
|
|
4338
|
+
// src/commands/backlog/update/buildUpdateSql.ts
|
|
4339
|
+
import chalk60 from "chalk";
|
|
4340
|
+
function buildUpdateSql(options2) {
|
|
4341
|
+
const { name, desc, type, ac } = options2;
|
|
4342
|
+
if (!name && !desc && !type && !ac) {
|
|
4343
|
+
console.log(chalk60.red("Nothing to update. Provide at least one flag."));
|
|
4344
|
+
process.exitCode = 1;
|
|
4345
|
+
return void 0;
|
|
4346
|
+
}
|
|
4347
|
+
if (type && type !== "story" && type !== "bug") {
|
|
4348
|
+
console.log(chalk60.red('Invalid type. Must be "story" or "bug".'));
|
|
4349
|
+
process.exitCode = 1;
|
|
4350
|
+
return void 0;
|
|
4351
|
+
}
|
|
4352
|
+
const sets = [];
|
|
4353
|
+
const params = [];
|
|
4354
|
+
const fieldNames = [];
|
|
4355
|
+
if (name) {
|
|
4356
|
+
sets.push("name = ?");
|
|
4357
|
+
params.push(name);
|
|
4358
|
+
fieldNames.push("name");
|
|
4359
|
+
}
|
|
4360
|
+
if (desc) {
|
|
4361
|
+
sets.push("description = ?");
|
|
4362
|
+
params.push(desc);
|
|
4363
|
+
fieldNames.push("description");
|
|
4364
|
+
}
|
|
4365
|
+
if (type) {
|
|
4366
|
+
sets.push("type = ?");
|
|
4367
|
+
params.push(type);
|
|
4368
|
+
fieldNames.push("type");
|
|
4369
|
+
}
|
|
4370
|
+
if (ac) {
|
|
4371
|
+
sets.push("acceptance_criteria = ?");
|
|
4372
|
+
params.push(JSON.stringify(ac));
|
|
4373
|
+
fieldNames.push("acceptance criteria");
|
|
4374
|
+
}
|
|
4375
|
+
return { sets, params, fields: fieldNames.join(", ") };
|
|
4376
|
+
}
|
|
4377
|
+
|
|
4378
|
+
// src/commands/backlog/update/index.ts
|
|
4379
|
+
function update(id, options2) {
|
|
4380
|
+
const result = loadAndFindItem(id);
|
|
4381
|
+
if (!result) return;
|
|
4382
|
+
const built = buildUpdateSql(options2);
|
|
4383
|
+
if (!built) return;
|
|
4384
|
+
const dir = getBacklogDir();
|
|
4385
|
+
const db = openDb(dir);
|
|
4386
|
+
const itemId = result.item.id;
|
|
4387
|
+
db.prepare(`UPDATE items SET ${built.sets.join(", ")} WHERE id = ?`).run(
|
|
4388
|
+
...built.params,
|
|
4389
|
+
itemId
|
|
4390
|
+
);
|
|
4391
|
+
exportToJsonl(db, dir);
|
|
4392
|
+
commitBacklog(itemId, options2.name ?? result.item.name);
|
|
4393
|
+
console.log(chalk61.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
4394
|
+
}
|
|
4395
|
+
|
|
4396
|
+
// src/commands/backlog/updatePhase.ts
|
|
4397
|
+
import chalk62 from "chalk";
|
|
4398
|
+
|
|
4399
|
+
// src/commands/backlog/applyPhaseUpdate.ts
|
|
4400
|
+
function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
4401
|
+
const run4 = db.transaction(() => {
|
|
4402
|
+
if (fields.name) {
|
|
4403
|
+
db.prepare(
|
|
4404
|
+
"UPDATE plan_phases SET name = ? WHERE item_id = ? AND idx = ?"
|
|
4405
|
+
).run(fields.name, itemId, phaseIdx);
|
|
4406
|
+
}
|
|
4407
|
+
if (fields.manualCheck) {
|
|
4408
|
+
db.prepare(
|
|
4409
|
+
"UPDATE plan_phases SET manual_checks = ? WHERE item_id = ? AND idx = ?"
|
|
4410
|
+
).run(JSON.stringify(fields.manualCheck), itemId, phaseIdx);
|
|
4411
|
+
}
|
|
4412
|
+
if (fields.task) {
|
|
4413
|
+
db.prepare(
|
|
4414
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4415
|
+
).run(itemId, phaseIdx);
|
|
4416
|
+
const stmt = db.prepare(
|
|
4417
|
+
"INSERT INTO plan_tasks (item_id, phase_idx, idx, task) VALUES (?, ?, ?, ?)"
|
|
4418
|
+
);
|
|
4419
|
+
for (let i = 0; i < fields.task.length; i++) {
|
|
4420
|
+
stmt.run(itemId, phaseIdx, i, fields.task[i]);
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
});
|
|
4424
|
+
run4();
|
|
4425
|
+
}
|
|
4426
|
+
|
|
4427
|
+
// src/commands/backlog/updatePhase.ts
|
|
4428
|
+
function updatePhase(id, phase, options2) {
|
|
4429
|
+
const { name, task, manualCheck } = options2;
|
|
4430
|
+
if (!name && !task && !manualCheck) {
|
|
4431
|
+
console.log(chalk62.red("Nothing to update. Provide at least one flag."));
|
|
4432
|
+
process.exitCode = 1;
|
|
4433
|
+
return;
|
|
4434
|
+
}
|
|
4435
|
+
const found = findPhase(id, phase);
|
|
4436
|
+
if (!found) return;
|
|
4437
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4438
|
+
applyPhaseUpdate(db, itemId, phaseIdx, { name, task, manualCheck });
|
|
4439
|
+
exportToJsonl(db, dir);
|
|
4440
|
+
commitBacklog(itemId, result.item.name);
|
|
4441
|
+
const fields = [
|
|
4442
|
+
name && "name",
|
|
4443
|
+
task && "tasks",
|
|
4444
|
+
manualCheck && "manual checks"
|
|
4445
|
+
].filter(Boolean).join(", ");
|
|
4446
|
+
console.log(
|
|
4447
|
+
chalk62.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
|
|
4448
|
+
);
|
|
4449
|
+
}
|
|
4450
|
+
|
|
4451
|
+
// src/commands/backlog/registerUpdateCommands.ts
|
|
4452
|
+
function registerUpdateCommands(cmd) {
|
|
4453
|
+
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);
|
|
4454
|
+
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);
|
|
4455
|
+
cmd.command("remove-phase <id> <phase>").description("Remove a plan phase from a backlog item").action(removePhase);
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4206
4458
|
// src/commands/registerBacklog.ts
|
|
4207
4459
|
function registerShowCommands(cmd) {
|
|
4208
4460
|
cmd.command("show <id>").alias("view").description("Show full detail for a backlog item").action(show);
|
|
@@ -4219,11 +4471,6 @@ function registerNextCommand(cmd) {
|
|
|
4219
4471
|
(opts) => next({ allowEdits: opts.write })
|
|
4220
4472
|
);
|
|
4221
4473
|
}
|
|
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
4474
|
function registerBacklog(program2) {
|
|
4228
4475
|
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
4476
|
setBacklogDir(thisCommand.opts().dir);
|
|
@@ -4238,6 +4485,7 @@ function registerBacklog(program2) {
|
|
|
4238
4485
|
registerNextCommand(cmd);
|
|
4239
4486
|
registerRunCommand(cmd);
|
|
4240
4487
|
registerSearchCommand(cmd);
|
|
4488
|
+
registerUpdateCommands(cmd);
|
|
4241
4489
|
}
|
|
4242
4490
|
|
|
4243
4491
|
// src/shared/isApprovedRead.ts
|
|
@@ -4647,48 +4895,48 @@ ${reasons.join("\n")}`);
|
|
|
4647
4895
|
}
|
|
4648
4896
|
|
|
4649
4897
|
// src/commands/deny/denyAdd.ts
|
|
4650
|
-
import
|
|
4898
|
+
import chalk63 from "chalk";
|
|
4651
4899
|
function denyAdd(pattern2, message) {
|
|
4652
4900
|
const config = loadProjectConfig();
|
|
4653
4901
|
const deny = config.deny ?? [];
|
|
4654
4902
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
4655
|
-
console.log(
|
|
4903
|
+
console.log(chalk63.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
4656
4904
|
return;
|
|
4657
4905
|
}
|
|
4658
4906
|
deny.push({ pattern: pattern2, message });
|
|
4659
4907
|
config.deny = deny;
|
|
4660
4908
|
saveConfig(config);
|
|
4661
|
-
console.log(
|
|
4909
|
+
console.log(chalk63.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
4662
4910
|
}
|
|
4663
4911
|
|
|
4664
4912
|
// src/commands/deny/denyList.ts
|
|
4665
|
-
import
|
|
4913
|
+
import chalk64 from "chalk";
|
|
4666
4914
|
function denyList() {
|
|
4667
4915
|
const config = loadConfig();
|
|
4668
4916
|
const deny = config.deny;
|
|
4669
4917
|
if (!deny || deny.length === 0) {
|
|
4670
|
-
console.log(
|
|
4918
|
+
console.log(chalk64.dim("No deny rules configured."));
|
|
4671
4919
|
return;
|
|
4672
4920
|
}
|
|
4673
4921
|
for (const rule of deny) {
|
|
4674
|
-
console.log(`${
|
|
4922
|
+
console.log(`${chalk64.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
4675
4923
|
}
|
|
4676
4924
|
}
|
|
4677
4925
|
|
|
4678
4926
|
// src/commands/deny/denyRemove.ts
|
|
4679
|
-
import
|
|
4927
|
+
import chalk65 from "chalk";
|
|
4680
4928
|
function denyRemove(pattern2) {
|
|
4681
4929
|
const config = loadProjectConfig();
|
|
4682
4930
|
const deny = config.deny ?? [];
|
|
4683
4931
|
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
4684
4932
|
if (index === -1) {
|
|
4685
|
-
console.log(
|
|
4933
|
+
console.log(chalk65.yellow(`No deny rule found for: ${pattern2}`));
|
|
4686
4934
|
return;
|
|
4687
4935
|
}
|
|
4688
4936
|
deny.splice(index, 1);
|
|
4689
4937
|
config.deny = deny.length > 0 ? deny : void 0;
|
|
4690
4938
|
saveConfig(config);
|
|
4691
|
-
console.log(
|
|
4939
|
+
console.log(chalk65.green(`Removed deny rule: ${pattern2}`));
|
|
4692
4940
|
}
|
|
4693
4941
|
|
|
4694
4942
|
// src/commands/permitCliReads/index.ts
|
|
@@ -4738,11 +4986,11 @@ function assertCliExists(cli) {
|
|
|
4738
4986
|
}
|
|
4739
4987
|
|
|
4740
4988
|
// src/commands/permitCliReads/colorize.ts
|
|
4741
|
-
import
|
|
4989
|
+
import chalk66 from "chalk";
|
|
4742
4990
|
function colorize(plainOutput) {
|
|
4743
4991
|
return plainOutput.split("\n").map((line) => {
|
|
4744
|
-
if (line.startsWith(" R ")) return
|
|
4745
|
-
if (line.startsWith(" W ")) return
|
|
4992
|
+
if (line.startsWith(" R ")) return chalk66.green(line);
|
|
4993
|
+
if (line.startsWith(" W ")) return chalk66.red(line);
|
|
4746
4994
|
return line;
|
|
4747
4995
|
}).join("\n");
|
|
4748
4996
|
}
|
|
@@ -5060,15 +5308,15 @@ function registerCliHook(program2) {
|
|
|
5060
5308
|
}
|
|
5061
5309
|
|
|
5062
5310
|
// src/commands/complexity/analyze.ts
|
|
5063
|
-
import
|
|
5311
|
+
import chalk72 from "chalk";
|
|
5064
5312
|
|
|
5065
5313
|
// src/commands/complexity/cyclomatic.ts
|
|
5066
|
-
import
|
|
5314
|
+
import chalk68 from "chalk";
|
|
5067
5315
|
|
|
5068
5316
|
// src/commands/complexity/shared/index.ts
|
|
5069
5317
|
import fs12 from "fs";
|
|
5070
5318
|
import path20 from "path";
|
|
5071
|
-
import
|
|
5319
|
+
import chalk67 from "chalk";
|
|
5072
5320
|
import ts5 from "typescript";
|
|
5073
5321
|
|
|
5074
5322
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -5314,7 +5562,7 @@ function createSourceFromFile(filePath) {
|
|
|
5314
5562
|
function withSourceFiles(pattern2, callback) {
|
|
5315
5563
|
const files = findSourceFiles2(pattern2);
|
|
5316
5564
|
if (files.length === 0) {
|
|
5317
|
-
console.log(
|
|
5565
|
+
console.log(chalk67.yellow("No files found matching pattern"));
|
|
5318
5566
|
return void 0;
|
|
5319
5567
|
}
|
|
5320
5568
|
return callback(files);
|
|
@@ -5347,11 +5595,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5347
5595
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
5348
5596
|
for (const { file, name, complexity } of results) {
|
|
5349
5597
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
5350
|
-
const color = exceedsThreshold ?
|
|
5351
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
5598
|
+
const color = exceedsThreshold ? chalk68.red : chalk68.white;
|
|
5599
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk68.cyan(complexity)}`);
|
|
5352
5600
|
}
|
|
5353
5601
|
console.log(
|
|
5354
|
-
|
|
5602
|
+
chalk68.dim(
|
|
5355
5603
|
`
|
|
5356
5604
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5357
5605
|
)
|
|
@@ -5363,7 +5611,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5363
5611
|
}
|
|
5364
5612
|
|
|
5365
5613
|
// src/commands/complexity/halstead.ts
|
|
5366
|
-
import
|
|
5614
|
+
import chalk69 from "chalk";
|
|
5367
5615
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
5368
5616
|
withSourceFiles(pattern2, (files) => {
|
|
5369
5617
|
const results = [];
|
|
@@ -5378,13 +5626,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5378
5626
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
5379
5627
|
for (const { file, name, metrics } of results) {
|
|
5380
5628
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
5381
|
-
const color = exceedsThreshold ?
|
|
5629
|
+
const color = exceedsThreshold ? chalk69.red : chalk69.white;
|
|
5382
5630
|
console.log(
|
|
5383
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
5631
|
+
`${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
5632
|
);
|
|
5385
5633
|
}
|
|
5386
5634
|
console.log(
|
|
5387
|
-
|
|
5635
|
+
chalk69.dim(
|
|
5388
5636
|
`
|
|
5389
5637
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5390
5638
|
)
|
|
@@ -5399,28 +5647,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5399
5647
|
import fs13 from "fs";
|
|
5400
5648
|
|
|
5401
5649
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
5402
|
-
import
|
|
5650
|
+
import chalk70 from "chalk";
|
|
5403
5651
|
function displayMaintainabilityResults(results, threshold) {
|
|
5404
5652
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
5405
5653
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
5406
|
-
console.log(
|
|
5654
|
+
console.log(chalk70.green("All files pass maintainability threshold"));
|
|
5407
5655
|
} else {
|
|
5408
5656
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
5409
|
-
const color = threshold !== void 0 ?
|
|
5657
|
+
const color = threshold !== void 0 ? chalk70.red : chalk70.white;
|
|
5410
5658
|
console.log(
|
|
5411
|
-
`${color(file)} \u2192 avg: ${
|
|
5659
|
+
`${color(file)} \u2192 avg: ${chalk70.cyan(avgMaintainability.toFixed(1))}, min: ${chalk70.yellow(minMaintainability.toFixed(1))}`
|
|
5412
5660
|
);
|
|
5413
5661
|
}
|
|
5414
5662
|
}
|
|
5415
|
-
console.log(
|
|
5663
|
+
console.log(chalk70.dim(`
|
|
5416
5664
|
Analyzed ${results.length} files`));
|
|
5417
5665
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
5418
5666
|
console.error(
|
|
5419
|
-
|
|
5667
|
+
chalk70.red(
|
|
5420
5668
|
`
|
|
5421
5669
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
5422
5670
|
|
|
5423
|
-
\u26A0\uFE0F ${
|
|
5671
|
+
\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
5672
|
)
|
|
5425
5673
|
);
|
|
5426
5674
|
process.exit(1);
|
|
@@ -5477,7 +5725,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5477
5725
|
|
|
5478
5726
|
// src/commands/complexity/sloc.ts
|
|
5479
5727
|
import fs14 from "fs";
|
|
5480
|
-
import
|
|
5728
|
+
import chalk71 from "chalk";
|
|
5481
5729
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
5482
5730
|
withSourceFiles(pattern2, (files) => {
|
|
5483
5731
|
const results = [];
|
|
@@ -5493,12 +5741,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5493
5741
|
results.sort((a, b) => b.lines - a.lines);
|
|
5494
5742
|
for (const { file, lines } of results) {
|
|
5495
5743
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
5496
|
-
const color = exceedsThreshold ?
|
|
5497
|
-
console.log(`${color(file)} \u2192 ${
|
|
5744
|
+
const color = exceedsThreshold ? chalk71.red : chalk71.white;
|
|
5745
|
+
console.log(`${color(file)} \u2192 ${chalk71.cyan(lines)} lines`);
|
|
5498
5746
|
}
|
|
5499
5747
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
5500
5748
|
console.log(
|
|
5501
|
-
|
|
5749
|
+
chalk71.dim(`
|
|
5502
5750
|
Total: ${total} lines across ${files.length} files`)
|
|
5503
5751
|
);
|
|
5504
5752
|
if (hasViolation) {
|
|
@@ -5512,21 +5760,21 @@ async function analyze(pattern2) {
|
|
|
5512
5760
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
5513
5761
|
const files = findSourceFiles2(searchPattern);
|
|
5514
5762
|
if (files.length === 0) {
|
|
5515
|
-
console.log(
|
|
5763
|
+
console.log(chalk72.yellow("No files found matching pattern"));
|
|
5516
5764
|
return;
|
|
5517
5765
|
}
|
|
5518
5766
|
if (files.length === 1) {
|
|
5519
5767
|
const file = files[0];
|
|
5520
|
-
console.log(
|
|
5768
|
+
console.log(chalk72.bold.underline("SLOC"));
|
|
5521
5769
|
await sloc(file);
|
|
5522
5770
|
console.log();
|
|
5523
|
-
console.log(
|
|
5771
|
+
console.log(chalk72.bold.underline("Cyclomatic Complexity"));
|
|
5524
5772
|
await cyclomatic(file);
|
|
5525
5773
|
console.log();
|
|
5526
|
-
console.log(
|
|
5774
|
+
console.log(chalk72.bold.underline("Halstead Metrics"));
|
|
5527
5775
|
await halstead(file);
|
|
5528
5776
|
console.log();
|
|
5529
|
-
console.log(
|
|
5777
|
+
console.log(chalk72.bold.underline("Maintainability Index"));
|
|
5530
5778
|
await maintainability(file);
|
|
5531
5779
|
return;
|
|
5532
5780
|
}
|
|
@@ -5554,7 +5802,7 @@ function registerComplexity(program2) {
|
|
|
5554
5802
|
|
|
5555
5803
|
// src/commands/deploy/redirect.ts
|
|
5556
5804
|
import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
|
|
5557
|
-
import
|
|
5805
|
+
import chalk73 from "chalk";
|
|
5558
5806
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
5559
5807
|
if (!window.location.pathname.endsWith('/')) {
|
|
5560
5808
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -5563,22 +5811,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
5563
5811
|
function redirect() {
|
|
5564
5812
|
const indexPath = "index.html";
|
|
5565
5813
|
if (!existsSync22(indexPath)) {
|
|
5566
|
-
console.log(
|
|
5814
|
+
console.log(chalk73.yellow("No index.html found"));
|
|
5567
5815
|
return;
|
|
5568
5816
|
}
|
|
5569
5817
|
const content = readFileSync20(indexPath, "utf-8");
|
|
5570
5818
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
5571
|
-
console.log(
|
|
5819
|
+
console.log(chalk73.dim("Trailing slash script already present"));
|
|
5572
5820
|
return;
|
|
5573
5821
|
}
|
|
5574
5822
|
const headCloseIndex = content.indexOf("</head>");
|
|
5575
5823
|
if (headCloseIndex === -1) {
|
|
5576
|
-
console.log(
|
|
5824
|
+
console.log(chalk73.red("Could not find </head> tag in index.html"));
|
|
5577
5825
|
return;
|
|
5578
5826
|
}
|
|
5579
5827
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
5580
5828
|
writeFileSync18(indexPath, newContent);
|
|
5581
|
-
console.log(
|
|
5829
|
+
console.log(chalk73.green("Added trailing slash redirect to index.html"));
|
|
5582
5830
|
}
|
|
5583
5831
|
|
|
5584
5832
|
// src/commands/registerDeploy.ts
|
|
@@ -5605,7 +5853,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
5605
5853
|
|
|
5606
5854
|
// src/commands/devlog/shared.ts
|
|
5607
5855
|
import { execSync as execSync17 } from "child_process";
|
|
5608
|
-
import
|
|
5856
|
+
import chalk74 from "chalk";
|
|
5609
5857
|
|
|
5610
5858
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
5611
5859
|
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
@@ -5692,13 +5940,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
5692
5940
|
}
|
|
5693
5941
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
5694
5942
|
for (const commit2 of commits) {
|
|
5695
|
-
console.log(` ${
|
|
5943
|
+
console.log(` ${chalk74.yellow(commit2.hash)} ${commit2.message}`);
|
|
5696
5944
|
if (verbose) {
|
|
5697
5945
|
const visibleFiles = commit2.files.filter(
|
|
5698
5946
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
5699
5947
|
);
|
|
5700
5948
|
for (const file of visibleFiles) {
|
|
5701
|
-
console.log(` ${
|
|
5949
|
+
console.log(` ${chalk74.dim(file)}`);
|
|
5702
5950
|
}
|
|
5703
5951
|
}
|
|
5704
5952
|
}
|
|
@@ -5723,15 +5971,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
5723
5971
|
}
|
|
5724
5972
|
|
|
5725
5973
|
// src/commands/devlog/list/printDateHeader.ts
|
|
5726
|
-
import
|
|
5974
|
+
import chalk75 from "chalk";
|
|
5727
5975
|
function printDateHeader(date, isSkipped, entries) {
|
|
5728
5976
|
if (isSkipped) {
|
|
5729
|
-
console.log(`${
|
|
5977
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.dim("skipped")}`);
|
|
5730
5978
|
} else if (entries && entries.length > 0) {
|
|
5731
|
-
const entryInfo = entries.map((e) => `${
|
|
5732
|
-
console.log(`${
|
|
5979
|
+
const entryInfo = entries.map((e) => `${chalk75.green(e.version)} ${e.title}`).join(" | ");
|
|
5980
|
+
console.log(`${chalk75.bold.blue(date)} ${entryInfo}`);
|
|
5733
5981
|
} else {
|
|
5734
|
-
console.log(`${
|
|
5982
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.red("\u26A0 devlog missing")}`);
|
|
5735
5983
|
}
|
|
5736
5984
|
}
|
|
5737
5985
|
|
|
@@ -5835,24 +6083,24 @@ function bumpVersion(version2, type) {
|
|
|
5835
6083
|
|
|
5836
6084
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
5837
6085
|
import { execSync as execSync20 } from "child_process";
|
|
5838
|
-
import
|
|
6086
|
+
import chalk77 from "chalk";
|
|
5839
6087
|
|
|
5840
6088
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
5841
|
-
import
|
|
6089
|
+
import chalk76 from "chalk";
|
|
5842
6090
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
5843
6091
|
if (conventional && firstHash) {
|
|
5844
6092
|
const version2 = getVersionAtCommit(firstHash);
|
|
5845
6093
|
if (version2) {
|
|
5846
|
-
console.log(`${
|
|
6094
|
+
console.log(`${chalk76.bold("version:")} ${stripToMinor(version2)}`);
|
|
5847
6095
|
} else {
|
|
5848
|
-
console.log(`${
|
|
6096
|
+
console.log(`${chalk76.bold("version:")} ${chalk76.red("unknown")}`);
|
|
5849
6097
|
}
|
|
5850
6098
|
} else if (patchVersion && minorVersion) {
|
|
5851
6099
|
console.log(
|
|
5852
|
-
`${
|
|
6100
|
+
`${chalk76.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
5853
6101
|
);
|
|
5854
6102
|
} else {
|
|
5855
|
-
console.log(`${
|
|
6103
|
+
console.log(`${chalk76.bold("version:")} v0.1 (initial)`);
|
|
5856
6104
|
}
|
|
5857
6105
|
}
|
|
5858
6106
|
|
|
@@ -5899,16 +6147,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
5899
6147
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
5900
6148
|
}
|
|
5901
6149
|
function logName(repoName) {
|
|
5902
|
-
console.log(`${
|
|
6150
|
+
console.log(`${chalk77.bold("name:")} ${repoName}`);
|
|
5903
6151
|
}
|
|
5904
6152
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
5905
6153
|
logName(ctx.repoName);
|
|
5906
6154
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
5907
|
-
console.log(
|
|
6155
|
+
console.log(chalk77.bold.blue(targetDate));
|
|
5908
6156
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
5909
6157
|
}
|
|
5910
6158
|
function logNoCommits(lastInfo) {
|
|
5911
|
-
console.log(
|
|
6159
|
+
console.log(chalk77.dim(noCommitsMessage(!!lastInfo)));
|
|
5912
6160
|
}
|
|
5913
6161
|
|
|
5914
6162
|
// src/commands/devlog/next/index.ts
|
|
@@ -5949,11 +6197,11 @@ function next2(options2) {
|
|
|
5949
6197
|
import { execSync as execSync21 } from "child_process";
|
|
5950
6198
|
|
|
5951
6199
|
// src/commands/devlog/repos/printReposTable.ts
|
|
5952
|
-
import
|
|
6200
|
+
import chalk78 from "chalk";
|
|
5953
6201
|
function colorStatus(status2) {
|
|
5954
|
-
if (status2 === "missing") return
|
|
5955
|
-
if (status2 === "outdated") return
|
|
5956
|
-
return
|
|
6202
|
+
if (status2 === "missing") return chalk78.red(status2);
|
|
6203
|
+
if (status2 === "outdated") return chalk78.yellow(status2);
|
|
6204
|
+
return chalk78.green(status2);
|
|
5957
6205
|
}
|
|
5958
6206
|
function formatRow(row, nameWidth) {
|
|
5959
6207
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -5967,8 +6215,8 @@ function printReposTable(rows) {
|
|
|
5967
6215
|
"Last Devlog".padEnd(11),
|
|
5968
6216
|
"Status"
|
|
5969
6217
|
].join(" ");
|
|
5970
|
-
console.log(
|
|
5971
|
-
console.log(
|
|
6218
|
+
console.log(chalk78.dim(header));
|
|
6219
|
+
console.log(chalk78.dim("-".repeat(header.length)));
|
|
5972
6220
|
for (const row of rows) {
|
|
5973
6221
|
console.log(formatRow(row, nameWidth));
|
|
5974
6222
|
}
|
|
@@ -6026,14 +6274,14 @@ function repos(options2) {
|
|
|
6026
6274
|
// src/commands/devlog/skip.ts
|
|
6027
6275
|
import { writeFileSync as writeFileSync19 } from "fs";
|
|
6028
6276
|
import { join as join21 } from "path";
|
|
6029
|
-
import
|
|
6277
|
+
import chalk79 from "chalk";
|
|
6030
6278
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
6031
6279
|
function getBlogConfigPath() {
|
|
6032
6280
|
return join21(BLOG_REPO_ROOT, "assist.yml");
|
|
6033
6281
|
}
|
|
6034
6282
|
function skip(date) {
|
|
6035
6283
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
6036
|
-
console.log(
|
|
6284
|
+
console.log(chalk79.red("Invalid date format. Use YYYY-MM-DD"));
|
|
6037
6285
|
process.exit(1);
|
|
6038
6286
|
}
|
|
6039
6287
|
const repoName = getRepoName();
|
|
@@ -6044,7 +6292,7 @@ function skip(date) {
|
|
|
6044
6292
|
const skipDays = skip2[repoName] ?? [];
|
|
6045
6293
|
if (skipDays.includes(date)) {
|
|
6046
6294
|
console.log(
|
|
6047
|
-
|
|
6295
|
+
chalk79.yellow(`${date} is already in skip list for ${repoName}`)
|
|
6048
6296
|
);
|
|
6049
6297
|
return;
|
|
6050
6298
|
}
|
|
@@ -6054,20 +6302,20 @@ function skip(date) {
|
|
|
6054
6302
|
devlog.skip = skip2;
|
|
6055
6303
|
config.devlog = devlog;
|
|
6056
6304
|
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
6057
|
-
console.log(
|
|
6305
|
+
console.log(chalk79.green(`Added ${date} to skip list for ${repoName}`));
|
|
6058
6306
|
}
|
|
6059
6307
|
|
|
6060
6308
|
// src/commands/devlog/version.ts
|
|
6061
|
-
import
|
|
6309
|
+
import chalk80 from "chalk";
|
|
6062
6310
|
function version() {
|
|
6063
6311
|
const config = loadConfig();
|
|
6064
6312
|
const name = getRepoName();
|
|
6065
6313
|
const lastInfo = getLastVersionInfo(name, config);
|
|
6066
6314
|
const lastVersion = lastInfo?.version ?? null;
|
|
6067
6315
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
6068
|
-
console.log(`${
|
|
6069
|
-
console.log(`${
|
|
6070
|
-
console.log(`${
|
|
6316
|
+
console.log(`${chalk80.bold("name:")} ${name}`);
|
|
6317
|
+
console.log(`${chalk80.bold("last:")} ${lastVersion ?? chalk80.dim("none")}`);
|
|
6318
|
+
console.log(`${chalk80.bold("next:")} ${nextVersion ?? chalk80.dim("none")}`);
|
|
6071
6319
|
}
|
|
6072
6320
|
|
|
6073
6321
|
// src/commands/registerDevlog.ts
|
|
@@ -6091,7 +6339,7 @@ function registerDevlog(program2) {
|
|
|
6091
6339
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
6092
6340
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
6093
6341
|
import { join as join22 } from "path";
|
|
6094
|
-
import
|
|
6342
|
+
import chalk81 from "chalk";
|
|
6095
6343
|
|
|
6096
6344
|
// src/shared/findRepoRoot.ts
|
|
6097
6345
|
import { existsSync as existsSync23 } from "fs";
|
|
@@ -6154,14 +6402,14 @@ function checkBuildLocks(startDir) {
|
|
|
6154
6402
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
6155
6403
|
if (locked) {
|
|
6156
6404
|
console.error(
|
|
6157
|
-
|
|
6405
|
+
chalk81.red("Build output locked (is VS debugging?): ") + locked
|
|
6158
6406
|
);
|
|
6159
6407
|
process.exit(1);
|
|
6160
6408
|
}
|
|
6161
6409
|
}
|
|
6162
6410
|
async function checkBuildLocksCommand() {
|
|
6163
6411
|
checkBuildLocks();
|
|
6164
|
-
console.log(
|
|
6412
|
+
console.log(chalk81.green("No build locks detected"));
|
|
6165
6413
|
}
|
|
6166
6414
|
|
|
6167
6415
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -6260,30 +6508,30 @@ function escapeRegex(s) {
|
|
|
6260
6508
|
}
|
|
6261
6509
|
|
|
6262
6510
|
// src/commands/dotnet/printTree.ts
|
|
6263
|
-
import
|
|
6511
|
+
import chalk82 from "chalk";
|
|
6264
6512
|
function printNodes(nodes, prefix2) {
|
|
6265
6513
|
for (let i = 0; i < nodes.length; i++) {
|
|
6266
6514
|
const isLast = i === nodes.length - 1;
|
|
6267
6515
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
6268
6516
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
6269
6517
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
6270
|
-
const label2 = isMissing ?
|
|
6518
|
+
const label2 = isMissing ? chalk82.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
6271
6519
|
console.log(`${prefix2}${connector}${label2}`);
|
|
6272
6520
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
6273
6521
|
}
|
|
6274
6522
|
}
|
|
6275
6523
|
function printTree(tree, totalCount, solutions) {
|
|
6276
|
-
console.log(
|
|
6277
|
-
console.log(
|
|
6524
|
+
console.log(chalk82.bold("\nProject Dependency Tree"));
|
|
6525
|
+
console.log(chalk82.cyan(tree.relativePath));
|
|
6278
6526
|
printNodes(tree.children, "");
|
|
6279
|
-
console.log(
|
|
6527
|
+
console.log(chalk82.dim(`
|
|
6280
6528
|
${totalCount} projects total (including root)`));
|
|
6281
|
-
console.log(
|
|
6529
|
+
console.log(chalk82.bold("\nSolution Membership"));
|
|
6282
6530
|
if (solutions.length === 0) {
|
|
6283
|
-
console.log(
|
|
6531
|
+
console.log(chalk82.yellow(" Not found in any .sln"));
|
|
6284
6532
|
} else {
|
|
6285
6533
|
for (const sln of solutions) {
|
|
6286
|
-
console.log(` ${
|
|
6534
|
+
console.log(` ${chalk82.green(sln)}`);
|
|
6287
6535
|
}
|
|
6288
6536
|
}
|
|
6289
6537
|
console.log();
|
|
@@ -6312,16 +6560,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
6312
6560
|
// src/commands/dotnet/resolveCsproj.ts
|
|
6313
6561
|
import { existsSync as existsSync24 } from "fs";
|
|
6314
6562
|
import path24 from "path";
|
|
6315
|
-
import
|
|
6563
|
+
import chalk83 from "chalk";
|
|
6316
6564
|
function resolveCsproj(csprojPath) {
|
|
6317
6565
|
const resolved = path24.resolve(csprojPath);
|
|
6318
6566
|
if (!existsSync24(resolved)) {
|
|
6319
|
-
console.error(
|
|
6567
|
+
console.error(chalk83.red(`File not found: ${resolved}`));
|
|
6320
6568
|
process.exit(1);
|
|
6321
6569
|
}
|
|
6322
6570
|
const repoRoot = findRepoRoot(path24.dirname(resolved));
|
|
6323
6571
|
if (!repoRoot) {
|
|
6324
|
-
console.error(
|
|
6572
|
+
console.error(chalk83.red("Could not find git repository root"));
|
|
6325
6573
|
process.exit(1);
|
|
6326
6574
|
}
|
|
6327
6575
|
return { resolved, repoRoot };
|
|
@@ -6371,12 +6619,12 @@ function getChangedCsFiles(scope) {
|
|
|
6371
6619
|
}
|
|
6372
6620
|
|
|
6373
6621
|
// src/commands/dotnet/inSln.ts
|
|
6374
|
-
import
|
|
6622
|
+
import chalk84 from "chalk";
|
|
6375
6623
|
async function inSln(csprojPath) {
|
|
6376
6624
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
6377
6625
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
6378
6626
|
if (solutions.length === 0) {
|
|
6379
|
-
console.log(
|
|
6627
|
+
console.log(chalk84.yellow("Not found in any .sln file"));
|
|
6380
6628
|
process.exit(1);
|
|
6381
6629
|
}
|
|
6382
6630
|
for (const sln of solutions) {
|
|
@@ -6385,7 +6633,7 @@ async function inSln(csprojPath) {
|
|
|
6385
6633
|
}
|
|
6386
6634
|
|
|
6387
6635
|
// src/commands/dotnet/inspect.ts
|
|
6388
|
-
import
|
|
6636
|
+
import chalk90 from "chalk";
|
|
6389
6637
|
|
|
6390
6638
|
// src/shared/formatElapsed.ts
|
|
6391
6639
|
function formatElapsed(ms) {
|
|
@@ -6397,12 +6645,12 @@ function formatElapsed(ms) {
|
|
|
6397
6645
|
}
|
|
6398
6646
|
|
|
6399
6647
|
// src/commands/dotnet/displayIssues.ts
|
|
6400
|
-
import
|
|
6648
|
+
import chalk85 from "chalk";
|
|
6401
6649
|
var SEVERITY_COLOR = {
|
|
6402
|
-
ERROR:
|
|
6403
|
-
WARNING:
|
|
6404
|
-
SUGGESTION:
|
|
6405
|
-
HINT:
|
|
6650
|
+
ERROR: chalk85.red,
|
|
6651
|
+
WARNING: chalk85.yellow,
|
|
6652
|
+
SUGGESTION: chalk85.cyan,
|
|
6653
|
+
HINT: chalk85.dim
|
|
6406
6654
|
};
|
|
6407
6655
|
function groupByFile(issues) {
|
|
6408
6656
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -6418,15 +6666,15 @@ function groupByFile(issues) {
|
|
|
6418
6666
|
}
|
|
6419
6667
|
function displayIssues(issues) {
|
|
6420
6668
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
6421
|
-
console.log(
|
|
6669
|
+
console.log(chalk85.bold(file));
|
|
6422
6670
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
6423
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
6671
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk85.white;
|
|
6424
6672
|
console.log(
|
|
6425
|
-
` ${
|
|
6673
|
+
` ${chalk85.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
6426
6674
|
);
|
|
6427
6675
|
}
|
|
6428
6676
|
}
|
|
6429
|
-
console.log(
|
|
6677
|
+
console.log(chalk85.dim(`
|
|
6430
6678
|
${issues.length} issue(s) found`));
|
|
6431
6679
|
}
|
|
6432
6680
|
|
|
@@ -6485,12 +6733,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
6485
6733
|
// src/commands/dotnet/resolveSolution.ts
|
|
6486
6734
|
import { existsSync as existsSync25 } from "fs";
|
|
6487
6735
|
import path25 from "path";
|
|
6488
|
-
import
|
|
6736
|
+
import chalk87 from "chalk";
|
|
6489
6737
|
|
|
6490
6738
|
// src/commands/dotnet/findSolution.ts
|
|
6491
6739
|
import { readdirSync as readdirSync4 } from "fs";
|
|
6492
6740
|
import { dirname as dirname16, join as join23 } from "path";
|
|
6493
|
-
import
|
|
6741
|
+
import chalk86 from "chalk";
|
|
6494
6742
|
function findSlnInDir(dir) {
|
|
6495
6743
|
try {
|
|
6496
6744
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join23(dir, f));
|
|
@@ -6506,17 +6754,17 @@ function findSolution() {
|
|
|
6506
6754
|
const slnFiles = findSlnInDir(current);
|
|
6507
6755
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
6508
6756
|
if (slnFiles.length > 1) {
|
|
6509
|
-
console.error(
|
|
6757
|
+
console.error(chalk86.red(`Multiple .sln files found in ${current}:`));
|
|
6510
6758
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
6511
6759
|
console.error(
|
|
6512
|
-
|
|
6760
|
+
chalk86.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
6513
6761
|
);
|
|
6514
6762
|
process.exit(1);
|
|
6515
6763
|
}
|
|
6516
6764
|
if (current === ceiling) break;
|
|
6517
6765
|
current = dirname16(current);
|
|
6518
6766
|
}
|
|
6519
|
-
console.error(
|
|
6767
|
+
console.error(chalk86.red("No .sln file found between cwd and repo root"));
|
|
6520
6768
|
process.exit(1);
|
|
6521
6769
|
}
|
|
6522
6770
|
|
|
@@ -6525,7 +6773,7 @@ function resolveSolution(sln) {
|
|
|
6525
6773
|
if (sln) {
|
|
6526
6774
|
const resolved = path25.resolve(sln);
|
|
6527
6775
|
if (!existsSync25(resolved)) {
|
|
6528
|
-
console.error(
|
|
6776
|
+
console.error(chalk87.red(`Solution file not found: ${resolved}`));
|
|
6529
6777
|
process.exit(1);
|
|
6530
6778
|
}
|
|
6531
6779
|
return resolved;
|
|
@@ -6567,14 +6815,14 @@ import { execSync as execSync23 } from "child_process";
|
|
|
6567
6815
|
import { existsSync as existsSync26, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
|
|
6568
6816
|
import { tmpdir as tmpdir2 } from "os";
|
|
6569
6817
|
import path26 from "path";
|
|
6570
|
-
import
|
|
6818
|
+
import chalk88 from "chalk";
|
|
6571
6819
|
function assertJbInstalled() {
|
|
6572
6820
|
try {
|
|
6573
6821
|
execSync23("jb inspectcode --version", { stdio: "pipe" });
|
|
6574
6822
|
} catch {
|
|
6575
|
-
console.error(
|
|
6823
|
+
console.error(chalk88.red("jb is not installed. Install with:"));
|
|
6576
6824
|
console.error(
|
|
6577
|
-
|
|
6825
|
+
chalk88.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
6578
6826
|
);
|
|
6579
6827
|
process.exit(1);
|
|
6580
6828
|
}
|
|
@@ -6592,11 +6840,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6592
6840
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
6593
6841
|
process.stderr.write(err.stderr);
|
|
6594
6842
|
}
|
|
6595
|
-
console.error(
|
|
6843
|
+
console.error(chalk88.red("jb inspectcode failed"));
|
|
6596
6844
|
process.exit(1);
|
|
6597
6845
|
}
|
|
6598
6846
|
if (!existsSync26(reportPath)) {
|
|
6599
|
-
console.error(
|
|
6847
|
+
console.error(chalk88.red("Report file not generated"));
|
|
6600
6848
|
process.exit(1);
|
|
6601
6849
|
}
|
|
6602
6850
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
@@ -6606,7 +6854,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6606
6854
|
|
|
6607
6855
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
6608
6856
|
import { execSync as execSync24 } from "child_process";
|
|
6609
|
-
import
|
|
6857
|
+
import chalk89 from "chalk";
|
|
6610
6858
|
function resolveMsbuildPath() {
|
|
6611
6859
|
const config = loadConfig();
|
|
6612
6860
|
const buildConfig = config.run?.find((r) => r.name === "build");
|
|
@@ -6617,9 +6865,9 @@ function assertMsbuildInstalled() {
|
|
|
6617
6865
|
try {
|
|
6618
6866
|
execSync24(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
6619
6867
|
} catch {
|
|
6620
|
-
console.error(
|
|
6868
|
+
console.error(chalk89.red(`msbuild not found at: ${msbuild}`));
|
|
6621
6869
|
console.error(
|
|
6622
|
-
|
|
6870
|
+
chalk89.yellow(
|
|
6623
6871
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
6624
6872
|
)
|
|
6625
6873
|
);
|
|
@@ -6666,17 +6914,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
6666
6914
|
// src/commands/dotnet/inspect.ts
|
|
6667
6915
|
function logScope(changedFiles) {
|
|
6668
6916
|
if (changedFiles === null) {
|
|
6669
|
-
console.log(
|
|
6917
|
+
console.log(chalk90.dim("Inspecting full solution..."));
|
|
6670
6918
|
} else {
|
|
6671
6919
|
console.log(
|
|
6672
|
-
|
|
6920
|
+
chalk90.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
6673
6921
|
);
|
|
6674
6922
|
}
|
|
6675
6923
|
}
|
|
6676
6924
|
function reportResults(issues, elapsed) {
|
|
6677
6925
|
if (issues.length > 0) displayIssues(issues);
|
|
6678
|
-
else console.log(
|
|
6679
|
-
console.log(
|
|
6926
|
+
else console.log(chalk90.green("No issues found"));
|
|
6927
|
+
console.log(chalk90.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
6680
6928
|
if (issues.length > 0) process.exit(1);
|
|
6681
6929
|
}
|
|
6682
6930
|
async function inspect(sln, options2) {
|
|
@@ -6687,7 +6935,7 @@ async function inspect(sln, options2) {
|
|
|
6687
6935
|
const scope = parseScope(options2.scope);
|
|
6688
6936
|
const changedFiles = getChangedCsFiles(scope);
|
|
6689
6937
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
6690
|
-
console.log(
|
|
6938
|
+
console.log(chalk90.green("No changed .cs files found"));
|
|
6691
6939
|
return;
|
|
6692
6940
|
}
|
|
6693
6941
|
logScope(changedFiles);
|
|
@@ -6713,7 +6961,7 @@ function registerDotnet(program2) {
|
|
|
6713
6961
|
}
|
|
6714
6962
|
|
|
6715
6963
|
// src/commands/jira/acceptanceCriteria.ts
|
|
6716
|
-
import
|
|
6964
|
+
import chalk92 from "chalk";
|
|
6717
6965
|
|
|
6718
6966
|
// src/commands/jira/adfToText.ts
|
|
6719
6967
|
function renderInline(node) {
|
|
@@ -6774,7 +7022,7 @@ function adfToText(doc) {
|
|
|
6774
7022
|
|
|
6775
7023
|
// src/commands/jira/fetchIssue.ts
|
|
6776
7024
|
import { execSync as execSync25 } from "child_process";
|
|
6777
|
-
import
|
|
7025
|
+
import chalk91 from "chalk";
|
|
6778
7026
|
function fetchIssue(issueKey, fields) {
|
|
6779
7027
|
let result;
|
|
6780
7028
|
try {
|
|
@@ -6787,15 +7035,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
6787
7035
|
const stderr = error.stderr;
|
|
6788
7036
|
if (stderr.includes("unauthorized")) {
|
|
6789
7037
|
console.error(
|
|
6790
|
-
|
|
7038
|
+
chalk91.red("Jira authentication expired."),
|
|
6791
7039
|
"Run",
|
|
6792
|
-
|
|
7040
|
+
chalk91.cyan("assist jira auth"),
|
|
6793
7041
|
"to re-authenticate."
|
|
6794
7042
|
);
|
|
6795
7043
|
process.exit(1);
|
|
6796
7044
|
}
|
|
6797
7045
|
}
|
|
6798
|
-
console.error(
|
|
7046
|
+
console.error(chalk91.red(`Failed to fetch ${issueKey}.`));
|
|
6799
7047
|
process.exit(1);
|
|
6800
7048
|
}
|
|
6801
7049
|
return JSON.parse(result);
|
|
@@ -6809,7 +7057,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
6809
7057
|
const parsed = fetchIssue(issueKey, field);
|
|
6810
7058
|
const acValue = parsed?.fields?.[field];
|
|
6811
7059
|
if (!acValue) {
|
|
6812
|
-
console.log(
|
|
7060
|
+
console.log(chalk92.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
6813
7061
|
return;
|
|
6814
7062
|
}
|
|
6815
7063
|
if (typeof acValue === "string") {
|
|
@@ -6904,14 +7152,14 @@ async function jiraAuth() {
|
|
|
6904
7152
|
}
|
|
6905
7153
|
|
|
6906
7154
|
// src/commands/jira/viewIssue.ts
|
|
6907
|
-
import
|
|
7155
|
+
import chalk93 from "chalk";
|
|
6908
7156
|
function viewIssue(issueKey) {
|
|
6909
7157
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
6910
7158
|
const fields = parsed?.fields;
|
|
6911
7159
|
const summary = fields?.summary;
|
|
6912
7160
|
const description = fields?.description;
|
|
6913
7161
|
if (summary) {
|
|
6914
|
-
console.log(
|
|
7162
|
+
console.log(chalk93.bold(summary));
|
|
6915
7163
|
}
|
|
6916
7164
|
if (description) {
|
|
6917
7165
|
if (summary) console.log();
|
|
@@ -6925,7 +7173,7 @@ function viewIssue(issueKey) {
|
|
|
6925
7173
|
}
|
|
6926
7174
|
if (!summary && !description) {
|
|
6927
7175
|
console.log(
|
|
6928
|
-
|
|
7176
|
+
chalk93.yellow(`No summary or description found on ${issueKey}.`)
|
|
6929
7177
|
);
|
|
6930
7178
|
}
|
|
6931
7179
|
}
|
|
@@ -6939,11 +7187,11 @@ function registerJira(program2) {
|
|
|
6939
7187
|
}
|
|
6940
7188
|
|
|
6941
7189
|
// src/commands/news/add/index.ts
|
|
6942
|
-
import
|
|
6943
|
-
import
|
|
7190
|
+
import chalk94 from "chalk";
|
|
7191
|
+
import enquirer8 from "enquirer";
|
|
6944
7192
|
async function add2(url) {
|
|
6945
7193
|
if (!url) {
|
|
6946
|
-
const response = await
|
|
7194
|
+
const response = await enquirer8.prompt({
|
|
6947
7195
|
type: "input",
|
|
6948
7196
|
name: "url",
|
|
6949
7197
|
message: "RSS feed URL:",
|
|
@@ -6962,17 +7210,17 @@ async function add2(url) {
|
|
|
6962
7210
|
const news = config.news ?? {};
|
|
6963
7211
|
const feeds = news.feeds ?? [];
|
|
6964
7212
|
if (feeds.includes(url)) {
|
|
6965
|
-
console.log(
|
|
7213
|
+
console.log(chalk94.yellow("Feed already exists in config"));
|
|
6966
7214
|
return;
|
|
6967
7215
|
}
|
|
6968
7216
|
feeds.push(url);
|
|
6969
7217
|
config.news = { ...news, feeds };
|
|
6970
7218
|
saveGlobalConfig(config);
|
|
6971
|
-
console.log(
|
|
7219
|
+
console.log(chalk94.green(`Added feed: ${url}`));
|
|
6972
7220
|
}
|
|
6973
7221
|
|
|
6974
7222
|
// src/commands/news/web/handleRequest.ts
|
|
6975
|
-
import
|
|
7223
|
+
import chalk95 from "chalk";
|
|
6976
7224
|
|
|
6977
7225
|
// src/commands/news/web/shared.ts
|
|
6978
7226
|
import { decodeHTML } from "entities";
|
|
@@ -7108,17 +7356,17 @@ function prefetch() {
|
|
|
7108
7356
|
const config = loadConfig();
|
|
7109
7357
|
const total = config.news.feeds.length;
|
|
7110
7358
|
if (total === 0) return;
|
|
7111
|
-
process.stdout.write(
|
|
7359
|
+
process.stdout.write(chalk95.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
7112
7360
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
7113
7361
|
const width = 20;
|
|
7114
7362
|
const filled = Math.round(done2 / t * width);
|
|
7115
7363
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
7116
7364
|
process.stdout.write(
|
|
7117
|
-
`\r${
|
|
7365
|
+
`\r${chalk95.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
7118
7366
|
);
|
|
7119
7367
|
}).then((items) => {
|
|
7120
7368
|
process.stdout.write(
|
|
7121
|
-
`\r${
|
|
7369
|
+
`\r${chalk95.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
7122
7370
|
`
|
|
7123
7371
|
);
|
|
7124
7372
|
cachedItems = items;
|
|
@@ -7479,20 +7727,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
7479
7727
|
}
|
|
7480
7728
|
|
|
7481
7729
|
// src/commands/prs/listComments/printComments.ts
|
|
7482
|
-
import
|
|
7730
|
+
import chalk96 from "chalk";
|
|
7483
7731
|
function formatForHuman(comment3) {
|
|
7484
7732
|
if (comment3.type === "review") {
|
|
7485
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
7733
|
+
const stateColor = comment3.state === "APPROVED" ? chalk96.green : comment3.state === "CHANGES_REQUESTED" ? chalk96.red : chalk96.yellow;
|
|
7486
7734
|
return [
|
|
7487
|
-
`${
|
|
7735
|
+
`${chalk96.cyan("Review")} by ${chalk96.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
7488
7736
|
comment3.body,
|
|
7489
7737
|
""
|
|
7490
7738
|
].join("\n");
|
|
7491
7739
|
}
|
|
7492
7740
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
7493
7741
|
return [
|
|
7494
|
-
`${
|
|
7495
|
-
|
|
7742
|
+
`${chalk96.cyan("Line comment")} by ${chalk96.bold(comment3.user)} on ${chalk96.dim(`${comment3.path}${location}`)}`,
|
|
7743
|
+
chalk96.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
7496
7744
|
comment3.body,
|
|
7497
7745
|
""
|
|
7498
7746
|
].join("\n");
|
|
@@ -7579,16 +7827,16 @@ async function listComments() {
|
|
|
7579
7827
|
import { execSync as execSync32 } from "child_process";
|
|
7580
7828
|
|
|
7581
7829
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
7582
|
-
import
|
|
7830
|
+
import enquirer9 from "enquirer";
|
|
7583
7831
|
|
|
7584
7832
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
7585
|
-
import
|
|
7833
|
+
import chalk97 from "chalk";
|
|
7586
7834
|
var STATUS_MAP = {
|
|
7587
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
7588
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
7835
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk97.magenta("merged"), date: pr.mergedAt } : null,
|
|
7836
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk97.red("closed"), date: pr.closedAt } : null
|
|
7589
7837
|
};
|
|
7590
7838
|
function defaultStatus(pr) {
|
|
7591
|
-
return { label:
|
|
7839
|
+
return { label: chalk97.green("opened"), date: pr.createdAt };
|
|
7592
7840
|
}
|
|
7593
7841
|
function getStatus2(pr) {
|
|
7594
7842
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -7597,11 +7845,11 @@ function formatDate(dateStr) {
|
|
|
7597
7845
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
7598
7846
|
}
|
|
7599
7847
|
function formatPrHeader(pr, status2) {
|
|
7600
|
-
return `${
|
|
7848
|
+
return `${chalk97.cyan(`#${pr.number}`)} ${pr.title} ${chalk97.dim(`(${pr.author.login},`)} ${status2.label} ${chalk97.dim(`${formatDate(status2.date)})`)}`;
|
|
7601
7849
|
}
|
|
7602
7850
|
function logPrDetails(pr) {
|
|
7603
7851
|
console.log(
|
|
7604
|
-
|
|
7852
|
+
chalk97.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
7605
7853
|
);
|
|
7606
7854
|
console.log();
|
|
7607
7855
|
}
|
|
@@ -7649,7 +7897,7 @@ function parseAction(action) {
|
|
|
7649
7897
|
}
|
|
7650
7898
|
async function promptNavigation(currentPage, totalPages) {
|
|
7651
7899
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
7652
|
-
const { action } = await
|
|
7900
|
+
const { action } = await enquirer9.prompt({
|
|
7653
7901
|
type: "select",
|
|
7654
7902
|
name: "action",
|
|
7655
7903
|
message: "Navigate",
|
|
@@ -7767,10 +8015,10 @@ function registerPrs(program2) {
|
|
|
7767
8015
|
}
|
|
7768
8016
|
|
|
7769
8017
|
// src/commands/ravendb/ravendbAuth.ts
|
|
7770
|
-
import
|
|
8018
|
+
import chalk103 from "chalk";
|
|
7771
8019
|
|
|
7772
8020
|
// src/shared/createConnectionAuth.ts
|
|
7773
|
-
import
|
|
8021
|
+
import chalk98 from "chalk";
|
|
7774
8022
|
function listConnections(connections, format2) {
|
|
7775
8023
|
if (connections.length === 0) {
|
|
7776
8024
|
console.log("No connections configured.");
|
|
@@ -7783,7 +8031,7 @@ function listConnections(connections, format2) {
|
|
|
7783
8031
|
function removeConnection(connections, name, save) {
|
|
7784
8032
|
const filtered = connections.filter((c) => c.name !== name);
|
|
7785
8033
|
if (filtered.length === connections.length) {
|
|
7786
|
-
console.error(
|
|
8034
|
+
console.error(chalk98.red(`Connection "${name}" not found.`));
|
|
7787
8035
|
process.exit(1);
|
|
7788
8036
|
}
|
|
7789
8037
|
save(filtered);
|
|
@@ -7829,15 +8077,15 @@ function saveConnections(connections) {
|
|
|
7829
8077
|
}
|
|
7830
8078
|
|
|
7831
8079
|
// src/commands/ravendb/promptConnection.ts
|
|
7832
|
-
import
|
|
8080
|
+
import chalk101 from "chalk";
|
|
7833
8081
|
|
|
7834
8082
|
// src/commands/ravendb/selectOpSecret.ts
|
|
7835
|
-
import
|
|
8083
|
+
import chalk100 from "chalk";
|
|
7836
8084
|
import Enquirer2 from "enquirer";
|
|
7837
8085
|
|
|
7838
8086
|
// src/commands/ravendb/searchItems.ts
|
|
7839
8087
|
import { execSync as execSync34 } from "child_process";
|
|
7840
|
-
import
|
|
8088
|
+
import chalk99 from "chalk";
|
|
7841
8089
|
function opExec(args) {
|
|
7842
8090
|
return execSync34(`op ${args}`, {
|
|
7843
8091
|
encoding: "utf-8",
|
|
@@ -7850,7 +8098,7 @@ function searchItems(search2) {
|
|
|
7850
8098
|
items = JSON.parse(opExec("item list --format=json"));
|
|
7851
8099
|
} catch {
|
|
7852
8100
|
console.error(
|
|
7853
|
-
|
|
8101
|
+
chalk99.red(
|
|
7854
8102
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
7855
8103
|
)
|
|
7856
8104
|
);
|
|
@@ -7864,7 +8112,7 @@ function getItemFields(itemId) {
|
|
|
7864
8112
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
7865
8113
|
return item.fields.filter((f) => f.reference && f.label);
|
|
7866
8114
|
} catch {
|
|
7867
|
-
console.error(
|
|
8115
|
+
console.error(chalk99.red("Failed to get item details from 1Password."));
|
|
7868
8116
|
process.exit(1);
|
|
7869
8117
|
}
|
|
7870
8118
|
}
|
|
@@ -7883,7 +8131,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7883
8131
|
}).run();
|
|
7884
8132
|
const items = searchItems(search2);
|
|
7885
8133
|
if (items.length === 0) {
|
|
7886
|
-
console.error(
|
|
8134
|
+
console.error(chalk100.red(`No items found matching "${search2}".`));
|
|
7887
8135
|
process.exit(1);
|
|
7888
8136
|
}
|
|
7889
8137
|
const itemId = await selectOne(
|
|
@@ -7892,7 +8140,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7892
8140
|
);
|
|
7893
8141
|
const fields = getItemFields(itemId);
|
|
7894
8142
|
if (fields.length === 0) {
|
|
7895
|
-
console.error(
|
|
8143
|
+
console.error(chalk100.red("No fields with references found on this item."));
|
|
7896
8144
|
process.exit(1);
|
|
7897
8145
|
}
|
|
7898
8146
|
const ref = await selectOne(
|
|
@@ -7906,7 +8154,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7906
8154
|
async function promptConnection(existingNames) {
|
|
7907
8155
|
const name = await promptInput("name", "Connection name:");
|
|
7908
8156
|
if (existingNames.includes(name)) {
|
|
7909
|
-
console.error(
|
|
8157
|
+
console.error(chalk101.red(`Connection "${name}" already exists.`));
|
|
7910
8158
|
process.exit(1);
|
|
7911
8159
|
}
|
|
7912
8160
|
const url = await promptInput(
|
|
@@ -7915,22 +8163,22 @@ async function promptConnection(existingNames) {
|
|
|
7915
8163
|
);
|
|
7916
8164
|
const database = await promptInput("database", "Database name:");
|
|
7917
8165
|
if (!name || !url || !database) {
|
|
7918
|
-
console.error(
|
|
8166
|
+
console.error(chalk101.red("All fields are required."));
|
|
7919
8167
|
process.exit(1);
|
|
7920
8168
|
}
|
|
7921
8169
|
const apiKeyRef = await selectOpSecret();
|
|
7922
|
-
console.log(
|
|
8170
|
+
console.log(chalk101.dim(`Using: ${apiKeyRef}`));
|
|
7923
8171
|
return { name, url, database, apiKeyRef };
|
|
7924
8172
|
}
|
|
7925
8173
|
|
|
7926
8174
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
7927
|
-
import
|
|
8175
|
+
import chalk102 from "chalk";
|
|
7928
8176
|
function ravendbSetConnection(name) {
|
|
7929
8177
|
const raw = loadGlobalConfigRaw();
|
|
7930
8178
|
const ravendb = raw.ravendb ?? {};
|
|
7931
8179
|
const connections = ravendb.connections ?? [];
|
|
7932
8180
|
if (!connections.some((c) => c.name === name)) {
|
|
7933
|
-
console.error(
|
|
8181
|
+
console.error(chalk102.red(`Connection "${name}" not found.`));
|
|
7934
8182
|
console.error(
|
|
7935
8183
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
7936
8184
|
);
|
|
@@ -7946,16 +8194,16 @@ function ravendbSetConnection(name) {
|
|
|
7946
8194
|
var ravendbAuth = createConnectionAuth({
|
|
7947
8195
|
load: loadConnections,
|
|
7948
8196
|
save: saveConnections,
|
|
7949
|
-
format: (c) => `${
|
|
8197
|
+
format: (c) => `${chalk103.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
7950
8198
|
promptNew: promptConnection,
|
|
7951
8199
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
7952
8200
|
});
|
|
7953
8201
|
|
|
7954
8202
|
// src/commands/ravendb/ravendbCollections.ts
|
|
7955
|
-
import
|
|
8203
|
+
import chalk107 from "chalk";
|
|
7956
8204
|
|
|
7957
8205
|
// src/commands/ravendb/ravenFetch.ts
|
|
7958
|
-
import
|
|
8206
|
+
import chalk105 from "chalk";
|
|
7959
8207
|
|
|
7960
8208
|
// src/commands/ravendb/getAccessToken.ts
|
|
7961
8209
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -7992,10 +8240,10 @@ ${errorText}`
|
|
|
7992
8240
|
|
|
7993
8241
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
7994
8242
|
import { execSync as execSync35 } from "child_process";
|
|
7995
|
-
import
|
|
8243
|
+
import chalk104 from "chalk";
|
|
7996
8244
|
function resolveOpSecret(reference) {
|
|
7997
8245
|
if (!reference.startsWith("op://")) {
|
|
7998
|
-
console.error(
|
|
8246
|
+
console.error(chalk104.red(`Invalid secret reference: must start with op://`));
|
|
7999
8247
|
process.exit(1);
|
|
8000
8248
|
}
|
|
8001
8249
|
try {
|
|
@@ -8005,7 +8253,7 @@ function resolveOpSecret(reference) {
|
|
|
8005
8253
|
}).trim();
|
|
8006
8254
|
} catch {
|
|
8007
8255
|
console.error(
|
|
8008
|
-
|
|
8256
|
+
chalk104.red(
|
|
8009
8257
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
8010
8258
|
)
|
|
8011
8259
|
);
|
|
@@ -8032,7 +8280,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8032
8280
|
if (!response.ok) {
|
|
8033
8281
|
const body = await response.text();
|
|
8034
8282
|
console.error(
|
|
8035
|
-
|
|
8283
|
+
chalk105.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
8036
8284
|
);
|
|
8037
8285
|
console.error(body.substring(0, 500));
|
|
8038
8286
|
process.exit(1);
|
|
@@ -8041,7 +8289,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8041
8289
|
}
|
|
8042
8290
|
|
|
8043
8291
|
// src/commands/ravendb/resolveConnection.ts
|
|
8044
|
-
import
|
|
8292
|
+
import chalk106 from "chalk";
|
|
8045
8293
|
function loadRavendb() {
|
|
8046
8294
|
const raw = loadGlobalConfigRaw();
|
|
8047
8295
|
const ravendb = raw.ravendb;
|
|
@@ -8055,7 +8303,7 @@ function resolveConnection(name) {
|
|
|
8055
8303
|
const connectionName = name ?? defaultConnection;
|
|
8056
8304
|
if (!connectionName) {
|
|
8057
8305
|
console.error(
|
|
8058
|
-
|
|
8306
|
+
chalk106.red(
|
|
8059
8307
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
8060
8308
|
)
|
|
8061
8309
|
);
|
|
@@ -8063,7 +8311,7 @@ function resolveConnection(name) {
|
|
|
8063
8311
|
}
|
|
8064
8312
|
const connection = connections.find((c) => c.name === connectionName);
|
|
8065
8313
|
if (!connection) {
|
|
8066
|
-
console.error(
|
|
8314
|
+
console.error(chalk106.red(`Connection "${connectionName}" not found.`));
|
|
8067
8315
|
console.error(
|
|
8068
8316
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
8069
8317
|
);
|
|
@@ -8094,15 +8342,15 @@ async function ravendbCollections(connectionName) {
|
|
|
8094
8342
|
return;
|
|
8095
8343
|
}
|
|
8096
8344
|
for (const c of collections) {
|
|
8097
|
-
console.log(`${
|
|
8345
|
+
console.log(`${chalk107.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
8098
8346
|
}
|
|
8099
8347
|
}
|
|
8100
8348
|
|
|
8101
8349
|
// src/commands/ravendb/ravendbQuery.ts
|
|
8102
|
-
import
|
|
8350
|
+
import chalk109 from "chalk";
|
|
8103
8351
|
|
|
8104
8352
|
// src/commands/ravendb/fetchAllPages.ts
|
|
8105
|
-
import
|
|
8353
|
+
import chalk108 from "chalk";
|
|
8106
8354
|
|
|
8107
8355
|
// src/commands/ravendb/buildQueryPath.ts
|
|
8108
8356
|
function buildQueryPath(opts) {
|
|
@@ -8140,7 +8388,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8140
8388
|
allResults.push(...results);
|
|
8141
8389
|
start3 += results.length;
|
|
8142
8390
|
process.stderr.write(
|
|
8143
|
-
`\r${
|
|
8391
|
+
`\r${chalk108.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
8144
8392
|
);
|
|
8145
8393
|
if (start3 >= totalResults) break;
|
|
8146
8394
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -8155,7 +8403,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8155
8403
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
8156
8404
|
const resolved = resolveArgs(connectionName, collection);
|
|
8157
8405
|
if (!resolved.collection && !options2.query) {
|
|
8158
|
-
console.error(
|
|
8406
|
+
console.error(chalk109.red("Provide a collection name or --query filter."));
|
|
8159
8407
|
process.exit(1);
|
|
8160
8408
|
}
|
|
8161
8409
|
const { collection: col } = resolved;
|
|
@@ -8193,7 +8441,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
8193
8441
|
import * as path27 from "path";
|
|
8194
8442
|
|
|
8195
8443
|
// src/commands/refactor/logViolations.ts
|
|
8196
|
-
import
|
|
8444
|
+
import chalk110 from "chalk";
|
|
8197
8445
|
var DEFAULT_MAX_LINES = 100;
|
|
8198
8446
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
8199
8447
|
if (violations.length === 0) {
|
|
@@ -8202,43 +8450,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
8202
8450
|
}
|
|
8203
8451
|
return;
|
|
8204
8452
|
}
|
|
8205
|
-
console.error(
|
|
8453
|
+
console.error(chalk110.red(`
|
|
8206
8454
|
Refactor check failed:
|
|
8207
8455
|
`));
|
|
8208
|
-
console.error(
|
|
8456
|
+
console.error(chalk110.red(` The following files exceed ${maxLines} lines:
|
|
8209
8457
|
`));
|
|
8210
8458
|
for (const violation of violations) {
|
|
8211
|
-
console.error(
|
|
8459
|
+
console.error(chalk110.red(` ${violation.file} (${violation.lines} lines)`));
|
|
8212
8460
|
}
|
|
8213
8461
|
console.error(
|
|
8214
|
-
|
|
8462
|
+
chalk110.yellow(
|
|
8215
8463
|
`
|
|
8216
8464
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
8217
8465
|
way to refactor it, ignore it with:
|
|
8218
8466
|
`
|
|
8219
8467
|
)
|
|
8220
8468
|
);
|
|
8221
|
-
console.error(
|
|
8469
|
+
console.error(chalk110.gray(` assist refactor ignore <file>
|
|
8222
8470
|
`));
|
|
8223
8471
|
if (process.env.CLAUDECODE) {
|
|
8224
|
-
console.error(
|
|
8472
|
+
console.error(chalk110.cyan(`
|
|
8225
8473
|
## Extracting Code to New Files
|
|
8226
8474
|
`));
|
|
8227
8475
|
console.error(
|
|
8228
|
-
|
|
8476
|
+
chalk110.cyan(
|
|
8229
8477
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
8230
8478
|
`
|
|
8231
8479
|
)
|
|
8232
8480
|
);
|
|
8233
8481
|
console.error(
|
|
8234
|
-
|
|
8482
|
+
chalk110.cyan(
|
|
8235
8483
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
8236
8484
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
8237
8485
|
`
|
|
8238
8486
|
)
|
|
8239
8487
|
);
|
|
8240
8488
|
console.error(
|
|
8241
|
-
|
|
8489
|
+
chalk110.cyan(
|
|
8242
8490
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
8243
8491
|
domains, move it to a common/shared folder.
|
|
8244
8492
|
`
|
|
@@ -8394,7 +8642,7 @@ async function check(pattern2, options2) {
|
|
|
8394
8642
|
|
|
8395
8643
|
// src/commands/refactor/extract/index.ts
|
|
8396
8644
|
import path33 from "path";
|
|
8397
|
-
import
|
|
8645
|
+
import chalk113 from "chalk";
|
|
8398
8646
|
|
|
8399
8647
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
8400
8648
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -8941,23 +9189,23 @@ function buildPlan(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
8941
9189
|
|
|
8942
9190
|
// src/commands/refactor/extract/displayPlan.ts
|
|
8943
9191
|
import path31 from "path";
|
|
8944
|
-
import
|
|
9192
|
+
import chalk111 from "chalk";
|
|
8945
9193
|
function section(title) {
|
|
8946
9194
|
return `
|
|
8947
|
-
${
|
|
9195
|
+
${chalk111.cyan(title)}`;
|
|
8948
9196
|
}
|
|
8949
9197
|
function displayImporters(plan2, cwd) {
|
|
8950
9198
|
if (plan2.importersToUpdate.length === 0) return;
|
|
8951
9199
|
console.log(section("Update importers:"));
|
|
8952
9200
|
for (const imp of plan2.importersToUpdate) {
|
|
8953
9201
|
const rel = path31.relative(cwd, imp.file.getFilePath());
|
|
8954
|
-
console.log(` ${
|
|
9202
|
+
console.log(` ${chalk111.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
8955
9203
|
}
|
|
8956
9204
|
}
|
|
8957
9205
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
8958
|
-
console.log(
|
|
9206
|
+
console.log(chalk111.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
8959
9207
|
`));
|
|
8960
|
-
console.log(` ${
|
|
9208
|
+
console.log(` ${chalk111.cyan("Functions to move:")}`);
|
|
8961
9209
|
for (const name of plan2.extractedNames) {
|
|
8962
9210
|
console.log(` ${name}`);
|
|
8963
9211
|
}
|
|
@@ -8992,7 +9240,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
8992
9240
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
8993
9241
|
import fs17 from "fs";
|
|
8994
9242
|
import path32 from "path";
|
|
8995
|
-
import
|
|
9243
|
+
import chalk112 from "chalk";
|
|
8996
9244
|
import { Project as Project2 } from "ts-morph";
|
|
8997
9245
|
function findTsConfig(sourcePath) {
|
|
8998
9246
|
const rootConfig = path32.resolve("tsconfig.json");
|
|
@@ -9023,7 +9271,7 @@ function loadProjectFile(file) {
|
|
|
9023
9271
|
});
|
|
9024
9272
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
9025
9273
|
if (!sourceFile) {
|
|
9026
|
-
console.log(
|
|
9274
|
+
console.log(chalk112.red(`File not found in project: ${file}`));
|
|
9027
9275
|
process.exit(1);
|
|
9028
9276
|
}
|
|
9029
9277
|
return { project, sourceFile };
|
|
@@ -9046,19 +9294,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
9046
9294
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
9047
9295
|
if (options2.apply) {
|
|
9048
9296
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
9049
|
-
console.log(
|
|
9297
|
+
console.log(chalk113.green("\nExtraction complete"));
|
|
9050
9298
|
} else {
|
|
9051
|
-
console.log(
|
|
9299
|
+
console.log(chalk113.dim("\nDry run. Use --apply to execute."));
|
|
9052
9300
|
}
|
|
9053
9301
|
}
|
|
9054
9302
|
|
|
9055
9303
|
// src/commands/refactor/ignore.ts
|
|
9056
9304
|
import fs18 from "fs";
|
|
9057
|
-
import
|
|
9305
|
+
import chalk114 from "chalk";
|
|
9058
9306
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
9059
9307
|
function ignore(file) {
|
|
9060
9308
|
if (!fs18.existsSync(file)) {
|
|
9061
|
-
console.error(
|
|
9309
|
+
console.error(chalk114.red(`Error: File does not exist: ${file}`));
|
|
9062
9310
|
process.exit(1);
|
|
9063
9311
|
}
|
|
9064
9312
|
const content = fs18.readFileSync(file, "utf-8");
|
|
@@ -9074,7 +9322,7 @@ function ignore(file) {
|
|
|
9074
9322
|
fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
9075
9323
|
}
|
|
9076
9324
|
console.log(
|
|
9077
|
-
|
|
9325
|
+
chalk114.green(
|
|
9078
9326
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
9079
9327
|
)
|
|
9080
9328
|
);
|
|
@@ -9082,26 +9330,26 @@ function ignore(file) {
|
|
|
9082
9330
|
|
|
9083
9331
|
// src/commands/refactor/rename/index.ts
|
|
9084
9332
|
import path34 from "path";
|
|
9085
|
-
import
|
|
9333
|
+
import chalk115 from "chalk";
|
|
9086
9334
|
async function rename(source, destination, options2 = {}) {
|
|
9087
9335
|
const destPath = path34.resolve(destination);
|
|
9088
9336
|
const cwd = process.cwd();
|
|
9089
9337
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
9090
9338
|
const relDest = path34.relative(cwd, destPath);
|
|
9091
9339
|
const { project, sourceFile } = loadProjectFile(source);
|
|
9092
|
-
console.log(
|
|
9340
|
+
console.log(chalk115.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
9093
9341
|
if (options2.apply) {
|
|
9094
9342
|
sourceFile.move(destPath);
|
|
9095
9343
|
await project.save();
|
|
9096
|
-
console.log(
|
|
9344
|
+
console.log(chalk115.green("Done"));
|
|
9097
9345
|
} else {
|
|
9098
|
-
console.log(
|
|
9346
|
+
console.log(chalk115.dim("Dry run. Use --apply to execute."));
|
|
9099
9347
|
}
|
|
9100
9348
|
}
|
|
9101
9349
|
|
|
9102
9350
|
// src/commands/refactor/renameSymbol/index.ts
|
|
9103
9351
|
import path36 from "path";
|
|
9104
|
-
import
|
|
9352
|
+
import chalk116 from "chalk";
|
|
9105
9353
|
import { Project as Project3 } from "ts-morph";
|
|
9106
9354
|
|
|
9107
9355
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -9150,38 +9398,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
9150
9398
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
9151
9399
|
const sourceFile = project.getSourceFile(filePath);
|
|
9152
9400
|
if (!sourceFile) {
|
|
9153
|
-
console.log(
|
|
9401
|
+
console.log(chalk116.red(`File not found in project: ${file}`));
|
|
9154
9402
|
process.exit(1);
|
|
9155
9403
|
}
|
|
9156
9404
|
const symbol = findSymbol(sourceFile, oldName);
|
|
9157
9405
|
if (!symbol) {
|
|
9158
|
-
console.log(
|
|
9406
|
+
console.log(chalk116.red(`Symbol "${oldName}" not found in ${file}`));
|
|
9159
9407
|
process.exit(1);
|
|
9160
9408
|
}
|
|
9161
9409
|
const grouped = groupReferences(symbol, cwd);
|
|
9162
9410
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
9163
9411
|
console.log(
|
|
9164
|
-
|
|
9412
|
+
chalk116.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
9165
9413
|
`)
|
|
9166
9414
|
);
|
|
9167
9415
|
for (const [refFile, lines] of grouped) {
|
|
9168
9416
|
console.log(
|
|
9169
|
-
` ${
|
|
9417
|
+
` ${chalk116.dim(refFile)}: lines ${chalk116.cyan(lines.join(", "))}`
|
|
9170
9418
|
);
|
|
9171
9419
|
}
|
|
9172
9420
|
if (options2.apply) {
|
|
9173
9421
|
symbol.rename(newName);
|
|
9174
9422
|
await project.save();
|
|
9175
|
-
console.log(
|
|
9423
|
+
console.log(chalk116.green(`
|
|
9176
9424
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
9177
9425
|
} else {
|
|
9178
|
-
console.log(
|
|
9426
|
+
console.log(chalk116.dim("\nDry run. Use --apply to execute."));
|
|
9179
9427
|
}
|
|
9180
9428
|
}
|
|
9181
9429
|
|
|
9182
9430
|
// src/commands/refactor/restructure/index.ts
|
|
9183
9431
|
import path45 from "path";
|
|
9184
|
-
import
|
|
9432
|
+
import chalk119 from "chalk";
|
|
9185
9433
|
|
|
9186
9434
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
9187
9435
|
import path37 from "path";
|
|
@@ -9424,50 +9672,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
9424
9672
|
|
|
9425
9673
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
9426
9674
|
import path41 from "path";
|
|
9427
|
-
import
|
|
9675
|
+
import chalk117 from "chalk";
|
|
9428
9676
|
function relPath(filePath) {
|
|
9429
9677
|
return path41.relative(process.cwd(), filePath);
|
|
9430
9678
|
}
|
|
9431
9679
|
function displayMoves(plan2) {
|
|
9432
9680
|
if (plan2.moves.length === 0) return;
|
|
9433
|
-
console.log(
|
|
9681
|
+
console.log(chalk117.bold("\nFile moves:"));
|
|
9434
9682
|
for (const move of plan2.moves) {
|
|
9435
9683
|
console.log(
|
|
9436
|
-
` ${
|
|
9684
|
+
` ${chalk117.red(relPath(move.from))} \u2192 ${chalk117.green(relPath(move.to))}`
|
|
9437
9685
|
);
|
|
9438
|
-
console.log(
|
|
9686
|
+
console.log(chalk117.dim(` ${move.reason}`));
|
|
9439
9687
|
}
|
|
9440
9688
|
}
|
|
9441
9689
|
function displayRewrites(rewrites) {
|
|
9442
9690
|
if (rewrites.length === 0) return;
|
|
9443
9691
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
9444
|
-
console.log(
|
|
9692
|
+
console.log(chalk117.bold(`
|
|
9445
9693
|
Import rewrites (${affectedFiles.size} files):`));
|
|
9446
9694
|
for (const file of affectedFiles) {
|
|
9447
|
-
console.log(` ${
|
|
9695
|
+
console.log(` ${chalk117.cyan(relPath(file))}:`);
|
|
9448
9696
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
9449
9697
|
(r) => r.file === file
|
|
9450
9698
|
)) {
|
|
9451
9699
|
console.log(
|
|
9452
|
-
` ${
|
|
9700
|
+
` ${chalk117.red(`"${oldSpecifier}"`)} \u2192 ${chalk117.green(`"${newSpecifier}"`)}`
|
|
9453
9701
|
);
|
|
9454
9702
|
}
|
|
9455
9703
|
}
|
|
9456
9704
|
}
|
|
9457
9705
|
function displayPlan2(plan2) {
|
|
9458
9706
|
if (plan2.warnings.length > 0) {
|
|
9459
|
-
console.log(
|
|
9460
|
-
for (const w of plan2.warnings) console.log(
|
|
9707
|
+
console.log(chalk117.yellow("\nWarnings:"));
|
|
9708
|
+
for (const w of plan2.warnings) console.log(chalk117.yellow(` ${w}`));
|
|
9461
9709
|
}
|
|
9462
9710
|
if (plan2.newDirectories.length > 0) {
|
|
9463
|
-
console.log(
|
|
9711
|
+
console.log(chalk117.bold("\nNew directories:"));
|
|
9464
9712
|
for (const dir of plan2.newDirectories)
|
|
9465
|
-
console.log(
|
|
9713
|
+
console.log(chalk117.green(` ${dir}/`));
|
|
9466
9714
|
}
|
|
9467
9715
|
displayMoves(plan2);
|
|
9468
9716
|
displayRewrites(plan2.rewrites);
|
|
9469
9717
|
console.log(
|
|
9470
|
-
|
|
9718
|
+
chalk117.dim(
|
|
9471
9719
|
`
|
|
9472
9720
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
9473
9721
|
)
|
|
@@ -9477,18 +9725,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
9477
9725
|
// src/commands/refactor/restructure/executePlan.ts
|
|
9478
9726
|
import fs20 from "fs";
|
|
9479
9727
|
import path42 from "path";
|
|
9480
|
-
import
|
|
9728
|
+
import chalk118 from "chalk";
|
|
9481
9729
|
function executePlan(plan2) {
|
|
9482
9730
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
9483
9731
|
for (const [file, content] of updatedContents) {
|
|
9484
9732
|
fs20.writeFileSync(file, content, "utf-8");
|
|
9485
9733
|
console.log(
|
|
9486
|
-
|
|
9734
|
+
chalk118.cyan(` Rewrote imports in ${path42.relative(process.cwd(), file)}`)
|
|
9487
9735
|
);
|
|
9488
9736
|
}
|
|
9489
9737
|
for (const dir of plan2.newDirectories) {
|
|
9490
9738
|
fs20.mkdirSync(dir, { recursive: true });
|
|
9491
|
-
console.log(
|
|
9739
|
+
console.log(chalk118.green(` Created ${path42.relative(process.cwd(), dir)}/`));
|
|
9492
9740
|
}
|
|
9493
9741
|
for (const move of plan2.moves) {
|
|
9494
9742
|
const targetDir = path42.dirname(move.to);
|
|
@@ -9497,7 +9745,7 @@ function executePlan(plan2) {
|
|
|
9497
9745
|
}
|
|
9498
9746
|
fs20.renameSync(move.from, move.to);
|
|
9499
9747
|
console.log(
|
|
9500
|
-
|
|
9748
|
+
chalk118.white(
|
|
9501
9749
|
` Moved ${path42.relative(process.cwd(), move.from)} \u2192 ${path42.relative(process.cwd(), move.to)}`
|
|
9502
9750
|
)
|
|
9503
9751
|
);
|
|
@@ -9512,7 +9760,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
9512
9760
|
if (entries.length === 0) {
|
|
9513
9761
|
fs20.rmdirSync(dir);
|
|
9514
9762
|
console.log(
|
|
9515
|
-
|
|
9763
|
+
chalk118.dim(
|
|
9516
9764
|
` Removed empty directory ${path42.relative(process.cwd(), dir)}`
|
|
9517
9765
|
)
|
|
9518
9766
|
);
|
|
@@ -9645,22 +9893,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
9645
9893
|
const targetPattern = pattern2 ?? "src";
|
|
9646
9894
|
const files = findSourceFiles2(targetPattern);
|
|
9647
9895
|
if (files.length === 0) {
|
|
9648
|
-
console.log(
|
|
9896
|
+
console.log(chalk119.yellow("No files found matching pattern"));
|
|
9649
9897
|
return;
|
|
9650
9898
|
}
|
|
9651
9899
|
const tsConfigPath = path45.resolve("tsconfig.json");
|
|
9652
9900
|
const plan2 = buildPlan2(files, tsConfigPath);
|
|
9653
9901
|
if (plan2.moves.length === 0) {
|
|
9654
|
-
console.log(
|
|
9902
|
+
console.log(chalk119.green("No restructuring needed"));
|
|
9655
9903
|
return;
|
|
9656
9904
|
}
|
|
9657
9905
|
displayPlan2(plan2);
|
|
9658
9906
|
if (options2.apply) {
|
|
9659
|
-
console.log(
|
|
9907
|
+
console.log(chalk119.bold("\nApplying changes..."));
|
|
9660
9908
|
executePlan(plan2);
|
|
9661
|
-
console.log(
|
|
9909
|
+
console.log(chalk119.green("\nRestructuring complete"));
|
|
9662
9910
|
} else {
|
|
9663
|
-
console.log(
|
|
9911
|
+
console.log(chalk119.dim("\nDry run. Use --apply to execute."));
|
|
9664
9912
|
}
|
|
9665
9913
|
}
|
|
9666
9914
|
|
|
@@ -9700,7 +9948,7 @@ function registerRefactor(program2) {
|
|
|
9700
9948
|
}
|
|
9701
9949
|
|
|
9702
9950
|
// src/commands/seq/seqAuth.ts
|
|
9703
|
-
import
|
|
9951
|
+
import chalk121 from "chalk";
|
|
9704
9952
|
|
|
9705
9953
|
// src/commands/seq/loadConnections.ts
|
|
9706
9954
|
function loadConnections2() {
|
|
@@ -9729,11 +9977,11 @@ function setDefaultConnection(name) {
|
|
|
9729
9977
|
}
|
|
9730
9978
|
|
|
9731
9979
|
// src/commands/seq/promptConnection.ts
|
|
9732
|
-
import
|
|
9980
|
+
import chalk120 from "chalk";
|
|
9733
9981
|
async function promptConnection2(existingNames) {
|
|
9734
9982
|
const name = await promptInput("name", "Connection name:", "default");
|
|
9735
9983
|
if (existingNames.includes(name)) {
|
|
9736
|
-
console.error(
|
|
9984
|
+
console.error(chalk120.red(`Connection "${name}" already exists.`));
|
|
9737
9985
|
process.exit(1);
|
|
9738
9986
|
}
|
|
9739
9987
|
const url = await promptInput("url", "Seq URL:", "http://localhost:5341");
|
|
@@ -9745,16 +9993,16 @@ async function promptConnection2(existingNames) {
|
|
|
9745
9993
|
var seqAuth = createConnectionAuth({
|
|
9746
9994
|
load: loadConnections2,
|
|
9747
9995
|
save: saveConnections2,
|
|
9748
|
-
format: (c) => `${
|
|
9996
|
+
format: (c) => `${chalk121.bold(c.name)} ${c.url}`,
|
|
9749
9997
|
promptNew: promptConnection2,
|
|
9750
9998
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
9751
9999
|
});
|
|
9752
10000
|
|
|
9753
10001
|
// src/commands/seq/seqQuery.ts
|
|
9754
|
-
import
|
|
10002
|
+
import chalk125 from "chalk";
|
|
9755
10003
|
|
|
9756
10004
|
// src/commands/seq/fetchSeq.ts
|
|
9757
|
-
import
|
|
10005
|
+
import chalk122 from "chalk";
|
|
9758
10006
|
async function fetchSeq(conn, path50, params) {
|
|
9759
10007
|
const url = `${conn.url}${path50}?${params}`;
|
|
9760
10008
|
const response = await fetch(url, {
|
|
@@ -9765,7 +10013,7 @@ async function fetchSeq(conn, path50, params) {
|
|
|
9765
10013
|
});
|
|
9766
10014
|
if (!response.ok) {
|
|
9767
10015
|
const body = await response.text();
|
|
9768
|
-
console.error(
|
|
10016
|
+
console.error(chalk122.red(`Seq returned ${response.status}: ${body}`));
|
|
9769
10017
|
process.exit(1);
|
|
9770
10018
|
}
|
|
9771
10019
|
return response;
|
|
@@ -9818,23 +10066,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
9818
10066
|
}
|
|
9819
10067
|
|
|
9820
10068
|
// src/commands/seq/formatEvent.ts
|
|
9821
|
-
import
|
|
10069
|
+
import chalk123 from "chalk";
|
|
9822
10070
|
function levelColor(level) {
|
|
9823
10071
|
switch (level) {
|
|
9824
10072
|
case "Fatal":
|
|
9825
|
-
return
|
|
10073
|
+
return chalk123.bgRed.white;
|
|
9826
10074
|
case "Error":
|
|
9827
|
-
return
|
|
10075
|
+
return chalk123.red;
|
|
9828
10076
|
case "Warning":
|
|
9829
|
-
return
|
|
10077
|
+
return chalk123.yellow;
|
|
9830
10078
|
case "Information":
|
|
9831
|
-
return
|
|
10079
|
+
return chalk123.cyan;
|
|
9832
10080
|
case "Debug":
|
|
9833
|
-
return
|
|
10081
|
+
return chalk123.gray;
|
|
9834
10082
|
case "Verbose":
|
|
9835
|
-
return
|
|
10083
|
+
return chalk123.dim;
|
|
9836
10084
|
default:
|
|
9837
|
-
return
|
|
10085
|
+
return chalk123.white;
|
|
9838
10086
|
}
|
|
9839
10087
|
}
|
|
9840
10088
|
function levelAbbrev(level) {
|
|
@@ -9875,31 +10123,31 @@ function formatTimestamp(iso) {
|
|
|
9875
10123
|
function formatEvent(event) {
|
|
9876
10124
|
const color = levelColor(event.Level);
|
|
9877
10125
|
const abbrev = levelAbbrev(event.Level);
|
|
9878
|
-
const ts8 =
|
|
10126
|
+
const ts8 = chalk123.dim(formatTimestamp(event.Timestamp));
|
|
9879
10127
|
const msg = renderMessage(event);
|
|
9880
10128
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
9881
10129
|
if (event.Exception) {
|
|
9882
10130
|
for (const line of event.Exception.split("\n")) {
|
|
9883
|
-
lines.push(
|
|
10131
|
+
lines.push(chalk123.red(` ${line}`));
|
|
9884
10132
|
}
|
|
9885
10133
|
}
|
|
9886
10134
|
return lines.join("\n");
|
|
9887
10135
|
}
|
|
9888
10136
|
|
|
9889
10137
|
// src/commands/seq/resolveConnection.ts
|
|
9890
|
-
import
|
|
10138
|
+
import chalk124 from "chalk";
|
|
9891
10139
|
function resolveConnection2(name) {
|
|
9892
10140
|
const connections = loadConnections2();
|
|
9893
10141
|
if (connections.length === 0) {
|
|
9894
10142
|
console.error(
|
|
9895
|
-
|
|
10143
|
+
chalk124.red("No Seq connections configured. Run 'assist seq auth' first.")
|
|
9896
10144
|
);
|
|
9897
10145
|
process.exit(1);
|
|
9898
10146
|
}
|
|
9899
10147
|
const target = name ?? getDefaultConnection() ?? connections[0].name;
|
|
9900
10148
|
const connection = connections.find((c) => c.name === target);
|
|
9901
10149
|
if (!connection) {
|
|
9902
|
-
console.error(
|
|
10150
|
+
console.error(chalk124.red(`Seq connection "${target}" not found.`));
|
|
9903
10151
|
process.exit(1);
|
|
9904
10152
|
}
|
|
9905
10153
|
return connection;
|
|
@@ -9914,7 +10162,7 @@ async function seqQuery(filter, options2) {
|
|
|
9914
10162
|
new URLSearchParams({ filter, count: String(count) })
|
|
9915
10163
|
);
|
|
9916
10164
|
if (events.length === 0) {
|
|
9917
|
-
console.log(
|
|
10165
|
+
console.log(chalk125.yellow("No events found."));
|
|
9918
10166
|
return;
|
|
9919
10167
|
}
|
|
9920
10168
|
if (options2.json) {
|
|
@@ -9925,11 +10173,11 @@ async function seqQuery(filter, options2) {
|
|
|
9925
10173
|
for (const event of chronological) {
|
|
9926
10174
|
console.log(formatEvent(event));
|
|
9927
10175
|
}
|
|
9928
|
-
console.log(
|
|
10176
|
+
console.log(chalk125.dim(`
|
|
9929
10177
|
${events.length} events`));
|
|
9930
10178
|
if (events.length >= count) {
|
|
9931
10179
|
console.log(
|
|
9932
|
-
|
|
10180
|
+
chalk125.yellow(
|
|
9933
10181
|
`Results limited to ${count}. Use --count to retrieve more.`
|
|
9934
10182
|
)
|
|
9935
10183
|
);
|
|
@@ -9937,11 +10185,11 @@ ${events.length} events`));
|
|
|
9937
10185
|
}
|
|
9938
10186
|
|
|
9939
10187
|
// src/commands/seq/seqSetConnection.ts
|
|
9940
|
-
import
|
|
10188
|
+
import chalk126 from "chalk";
|
|
9941
10189
|
function seqSetConnection(name) {
|
|
9942
10190
|
const connections = loadConnections2();
|
|
9943
10191
|
if (!connections.find((c) => c.name === name)) {
|
|
9944
|
-
console.error(
|
|
10192
|
+
console.error(chalk126.red(`Connection "${name}" not found.`));
|
|
9945
10193
|
process.exit(1);
|
|
9946
10194
|
}
|
|
9947
10195
|
setDefaultConnection(name);
|
|
@@ -10480,14 +10728,14 @@ import {
|
|
|
10480
10728
|
import { dirname as dirname20, join as join34 } from "path";
|
|
10481
10729
|
|
|
10482
10730
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
10483
|
-
import
|
|
10731
|
+
import chalk127 from "chalk";
|
|
10484
10732
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
10485
10733
|
function validateStagedContent(filename, content) {
|
|
10486
10734
|
const firstLine = content.split("\n")[0];
|
|
10487
10735
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
10488
10736
|
if (!match) {
|
|
10489
10737
|
console.error(
|
|
10490
|
-
|
|
10738
|
+
chalk127.red(
|
|
10491
10739
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
10492
10740
|
)
|
|
10493
10741
|
);
|
|
@@ -10496,7 +10744,7 @@ function validateStagedContent(filename, content) {
|
|
|
10496
10744
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
10497
10745
|
if (!contentAfterLink) {
|
|
10498
10746
|
console.error(
|
|
10499
|
-
|
|
10747
|
+
chalk127.red(
|
|
10500
10748
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
10501
10749
|
)
|
|
10502
10750
|
);
|
|
@@ -10889,7 +11137,7 @@ function registerVoice(program2) {
|
|
|
10889
11137
|
|
|
10890
11138
|
// src/commands/roam/auth.ts
|
|
10891
11139
|
import { randomBytes } from "crypto";
|
|
10892
|
-
import
|
|
11140
|
+
import chalk128 from "chalk";
|
|
10893
11141
|
|
|
10894
11142
|
// src/lib/openBrowser.ts
|
|
10895
11143
|
import { execSync as execSync38 } from "child_process";
|
|
@@ -11024,7 +11272,7 @@ async function exchangeToken(params) {
|
|
|
11024
11272
|
}
|
|
11025
11273
|
|
|
11026
11274
|
// src/commands/roam/promptCredentials.ts
|
|
11027
|
-
import
|
|
11275
|
+
import enquirer10 from "enquirer";
|
|
11028
11276
|
function censor(value) {
|
|
11029
11277
|
const visible = value.slice(-4);
|
|
11030
11278
|
return `${"*".repeat(value.length - 4)}${visible}`;
|
|
@@ -11033,7 +11281,7 @@ function label(name, existing) {
|
|
|
11033
11281
|
return existing ? `${name} (${censor(existing)})` : name;
|
|
11034
11282
|
}
|
|
11035
11283
|
async function promptField(name, existing) {
|
|
11036
|
-
const { value } = await
|
|
11284
|
+
const { value } = await enquirer10.prompt({
|
|
11037
11285
|
type: "input",
|
|
11038
11286
|
name: "value",
|
|
11039
11287
|
message: `${label(name, existing)}:`,
|
|
@@ -11064,13 +11312,13 @@ async function auth() {
|
|
|
11064
11312
|
saveGlobalConfig(config);
|
|
11065
11313
|
const state = randomBytes(16).toString("hex");
|
|
11066
11314
|
console.log(
|
|
11067
|
-
|
|
11315
|
+
chalk128.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
11068
11316
|
);
|
|
11069
|
-
console.log(
|
|
11070
|
-
console.log(
|
|
11071
|
-
console.log(
|
|
11317
|
+
console.log(chalk128.white("http://localhost:14523/callback\n"));
|
|
11318
|
+
console.log(chalk128.blue("Opening browser for authorization..."));
|
|
11319
|
+
console.log(chalk128.dim("Waiting for authorization callback..."));
|
|
11072
11320
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
11073
|
-
console.log(
|
|
11321
|
+
console.log(chalk128.dim("Exchanging code for tokens..."));
|
|
11074
11322
|
const tokens = await exchangeToken({
|
|
11075
11323
|
code,
|
|
11076
11324
|
clientId,
|
|
@@ -11086,7 +11334,7 @@ async function auth() {
|
|
|
11086
11334
|
};
|
|
11087
11335
|
saveGlobalConfig(config);
|
|
11088
11336
|
console.log(
|
|
11089
|
-
|
|
11337
|
+
chalk128.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
11090
11338
|
);
|
|
11091
11339
|
}
|
|
11092
11340
|
|
|
@@ -11299,7 +11547,7 @@ import { execSync as execSync40 } from "child_process";
|
|
|
11299
11547
|
import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
|
|
11300
11548
|
import { tmpdir as tmpdir6 } from "os";
|
|
11301
11549
|
import { join as join43, resolve as resolve5 } from "path";
|
|
11302
|
-
import
|
|
11550
|
+
import chalk129 from "chalk";
|
|
11303
11551
|
|
|
11304
11552
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
11305
11553
|
var captureWindowPs1 = `
|
|
@@ -11450,22 +11698,22 @@ function screenshot(processName) {
|
|
|
11450
11698
|
const config = loadConfig();
|
|
11451
11699
|
const outputDir = resolve5(config.screenshot.outputDir);
|
|
11452
11700
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
11453
|
-
console.log(
|
|
11701
|
+
console.log(chalk129.gray(`Capturing window for process "${processName}" ...`));
|
|
11454
11702
|
try {
|
|
11455
11703
|
runPowerShellScript(processName, outputPath);
|
|
11456
|
-
console.log(
|
|
11704
|
+
console.log(chalk129.green(`Screenshot saved: ${outputPath}`));
|
|
11457
11705
|
} catch (error) {
|
|
11458
11706
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11459
|
-
console.error(
|
|
11707
|
+
console.error(chalk129.red(`Failed to capture screenshot: ${msg}`));
|
|
11460
11708
|
process.exit(1);
|
|
11461
11709
|
}
|
|
11462
11710
|
}
|
|
11463
11711
|
|
|
11464
11712
|
// src/commands/statusLine.ts
|
|
11465
|
-
import
|
|
11713
|
+
import chalk131 from "chalk";
|
|
11466
11714
|
|
|
11467
11715
|
// src/commands/buildLimitsSegment.ts
|
|
11468
|
-
import
|
|
11716
|
+
import chalk130 from "chalk";
|
|
11469
11717
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
11470
11718
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
11471
11719
|
function formatTimeLeft(resetsAt) {
|
|
@@ -11488,10 +11736,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
11488
11736
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
11489
11737
|
const label2 = `${Math.round(pct)}%`;
|
|
11490
11738
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
11491
|
-
if (projected == null) return
|
|
11492
|
-
if (projected > 100) return
|
|
11493
|
-
if (projected > 75) return
|
|
11494
|
-
return
|
|
11739
|
+
if (projected == null) return chalk130.green(label2);
|
|
11740
|
+
if (projected > 100) return chalk130.red(label2);
|
|
11741
|
+
if (projected > 75) return chalk130.yellow(label2);
|
|
11742
|
+
return chalk130.green(label2);
|
|
11495
11743
|
}
|
|
11496
11744
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
11497
11745
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -11517,14 +11765,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
11517
11765
|
}
|
|
11518
11766
|
|
|
11519
11767
|
// src/commands/statusLine.ts
|
|
11520
|
-
|
|
11768
|
+
chalk131.level = 3;
|
|
11521
11769
|
function formatNumber(num) {
|
|
11522
11770
|
return num.toLocaleString("en-US");
|
|
11523
11771
|
}
|
|
11524
11772
|
function colorizePercent(pct) {
|
|
11525
11773
|
const label2 = `${Math.round(pct)}%`;
|
|
11526
|
-
if (pct > 80) return
|
|
11527
|
-
if (pct > 40) return
|
|
11774
|
+
if (pct > 80) return chalk131.red(label2);
|
|
11775
|
+
if (pct > 40) return chalk131.yellow(label2);
|
|
11528
11776
|
return label2;
|
|
11529
11777
|
}
|
|
11530
11778
|
async function statusLine() {
|
|
@@ -11547,7 +11795,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
11547
11795
|
// src/commands/sync/syncClaudeMd.ts
|
|
11548
11796
|
import * as fs23 from "fs";
|
|
11549
11797
|
import * as path46 from "path";
|
|
11550
|
-
import
|
|
11798
|
+
import chalk132 from "chalk";
|
|
11551
11799
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
11552
11800
|
const source = path46.join(claudeDir, "CLAUDE.md");
|
|
11553
11801
|
const target = path46.join(targetBase, "CLAUDE.md");
|
|
@@ -11556,12 +11804,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11556
11804
|
const targetContent = fs23.readFileSync(target, "utf-8");
|
|
11557
11805
|
if (sourceContent !== targetContent) {
|
|
11558
11806
|
console.log(
|
|
11559
|
-
|
|
11807
|
+
chalk132.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
11560
11808
|
);
|
|
11561
11809
|
console.log();
|
|
11562
11810
|
printDiff(targetContent, sourceContent);
|
|
11563
11811
|
const confirm = options2?.yes || await promptConfirm(
|
|
11564
|
-
|
|
11812
|
+
chalk132.red("Overwrite existing CLAUDE.md?"),
|
|
11565
11813
|
false
|
|
11566
11814
|
);
|
|
11567
11815
|
if (!confirm) {
|
|
@@ -11577,7 +11825,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11577
11825
|
// src/commands/sync/syncSettings.ts
|
|
11578
11826
|
import * as fs24 from "fs";
|
|
11579
11827
|
import * as path47 from "path";
|
|
11580
|
-
import
|
|
11828
|
+
import chalk133 from "chalk";
|
|
11581
11829
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
11582
11830
|
const source = path47.join(claudeDir, "settings.json");
|
|
11583
11831
|
const target = path47.join(targetBase, "settings.json");
|
|
@@ -11593,14 +11841,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
11593
11841
|
if (mergedContent !== normalizedTarget) {
|
|
11594
11842
|
if (!options2?.yes) {
|
|
11595
11843
|
console.log(
|
|
11596
|
-
|
|
11844
|
+
chalk133.yellow(
|
|
11597
11845
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
11598
11846
|
)
|
|
11599
11847
|
);
|
|
11600
11848
|
console.log();
|
|
11601
11849
|
printDiff(targetContent, mergedContent);
|
|
11602
11850
|
const confirm = await promptConfirm(
|
|
11603
|
-
|
|
11851
|
+
chalk133.red("Overwrite existing settings.json?"),
|
|
11604
11852
|
false
|
|
11605
11853
|
);
|
|
11606
11854
|
if (!confirm) {
|
|
@@ -11653,7 +11901,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
11653
11901
|
return false;
|
|
11654
11902
|
}
|
|
11655
11903
|
}
|
|
11656
|
-
async function
|
|
11904
|
+
async function update2() {
|
|
11657
11905
|
const installDir = getInstallDir();
|
|
11658
11906
|
console.log(`Assist is installed at: ${installDir}`);
|
|
11659
11907
|
if (isGitRepo(installDir)) {
|
|
@@ -11705,7 +11953,7 @@ program.command("status-line").description("Format Claude Code status line from
|
|
|
11705
11953
|
program.command("notify").description(
|
|
11706
11954
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
11707
11955
|
).action(notify);
|
|
11708
|
-
program.command("update").description("Update assist to the latest version and sync commands").action(
|
|
11956
|
+
program.command("update").description("Update assist to the latest version and sync commands").action(update2);
|
|
11709
11957
|
program.command("coverage").description("Print global statement coverage percentage").action(coverage);
|
|
11710
11958
|
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
11959
|
registerCliHook(program);
|
|
@@ -11727,6 +11975,7 @@ registerVoice(program);
|
|
|
11727
11975
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
11728
11976
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|
|
11729
11977
|
program.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").action(() => launchMode("bug"));
|
|
11978
|
+
program.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").action((id) => refine(id));
|
|
11730
11979
|
var signalCommand = program.command("signal").description("Write an assist signal file");
|
|
11731
11980
|
signalCommand.command("next").description("Write a next signal to chain into assist next").action(() => {
|
|
11732
11981
|
writeSignal("next");
|