@staff0rd/assist 0.402.0 → 0.404.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 +4 -4
- package/claude/settings.json +4 -4
- package/dist/commands/sessions/web/bundle.js +2 -2
- package/dist/index.js +278 -240
- package/package.json +1 -1
- /package/claude/commands/{review-comments.md → review-pr-comments.md} +0 -0
- /package/claude/commands/{strip-comments.md → strip-code-comments.md} +0 -0
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.404.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -242,7 +242,7 @@ var assistConfigSchema = z2.strictObject({
|
|
|
242
242
|
hardcodedColors: z2.strictObject({
|
|
243
243
|
ignore: z2.array(z2.string()).default([])
|
|
244
244
|
}).optional(),
|
|
245
|
-
|
|
245
|
+
blockCodeComments: z2.strictObject({
|
|
246
246
|
ignore: z2.array(z2.string()).default([])
|
|
247
247
|
}).optional(),
|
|
248
248
|
restructure: z2.strictObject({
|
|
@@ -1577,6 +1577,95 @@ function stageAndCommit(files, message) {
|
|
|
1577
1577
|
return commitStaged(message);
|
|
1578
1578
|
}
|
|
1579
1579
|
|
|
1580
|
+
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
1581
|
+
import * as fs from "fs";
|
|
1582
|
+
|
|
1583
|
+
// src/commands/sessions/summarise/parseUserLine.ts
|
|
1584
|
+
function parseUserLine(line) {
|
|
1585
|
+
let entry;
|
|
1586
|
+
try {
|
|
1587
|
+
entry = JSON.parse(line);
|
|
1588
|
+
} catch {
|
|
1589
|
+
return void 0;
|
|
1590
|
+
}
|
|
1591
|
+
if (entry.type !== "user") return void 0;
|
|
1592
|
+
const msg = entry.message;
|
|
1593
|
+
const c = msg?.content;
|
|
1594
|
+
let text17;
|
|
1595
|
+
if (typeof c === "string") {
|
|
1596
|
+
text17 = c;
|
|
1597
|
+
} else if (Array.isArray(c)) {
|
|
1598
|
+
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
1599
|
+
text17 = collected || void 0;
|
|
1600
|
+
}
|
|
1601
|
+
if (!text17) return void 0;
|
|
1602
|
+
return {
|
|
1603
|
+
text: text17,
|
|
1604
|
+
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
1609
|
+
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
1610
|
+
let content;
|
|
1611
|
+
try {
|
|
1612
|
+
const fd = fs.openSync(filePath, "r");
|
|
1613
|
+
try {
|
|
1614
|
+
const buf = Buffer.alloc(maxBytes);
|
|
1615
|
+
const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
|
|
1616
|
+
content = buf.toString("utf8", 0, bytesRead);
|
|
1617
|
+
} finally {
|
|
1618
|
+
fs.closeSync(fd);
|
|
1619
|
+
}
|
|
1620
|
+
} catch {
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
for (const line of content.split("\n")) {
|
|
1624
|
+
if (!line) continue;
|
|
1625
|
+
const entry = parseUserLine(line);
|
|
1626
|
+
if (entry) yield entry.text;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
1631
|
+
function scanSessionBacklogRefs(filePath) {
|
|
1632
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1633
|
+
for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
1634
|
+
for (const id of extractBacklogIds(text17)) {
|
|
1635
|
+
ids.add(id);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
return [...ids].sort((a, b) => a - b);
|
|
1639
|
+
}
|
|
1640
|
+
function extractBacklogIds(text17) {
|
|
1641
|
+
const ids = [];
|
|
1642
|
+
for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
|
|
1643
|
+
ids.push(Number.parseInt(m[1], 10));
|
|
1644
|
+
}
|
|
1645
|
+
for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
|
|
1646
|
+
ids.push(Number.parseInt(m[1], 10));
|
|
1647
|
+
}
|
|
1648
|
+
for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
|
|
1649
|
+
ids.push(Number.parseInt(m[1], 10));
|
|
1650
|
+
}
|
|
1651
|
+
for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
|
|
1652
|
+
ids.push(Number.parseInt(m[1], 10));
|
|
1653
|
+
}
|
|
1654
|
+
for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
1655
|
+
ids.push(Number.parseInt(m[1], 10));
|
|
1656
|
+
}
|
|
1657
|
+
return ids;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
// src/shared/findBacklogRefs.ts
|
|
1661
|
+
function findBacklogRefs(text17) {
|
|
1662
|
+
return [...new Set(extractBacklogIds(text17))];
|
|
1663
|
+
}
|
|
1664
|
+
function backlogRefError(subject, context, ids) {
|
|
1665
|
+
const refs = ids.map((id) => `a${id}`).join(", ");
|
|
1666
|
+
return `Error: ${subject} must not reference assist backlog items (found ${refs}). Do not include assist references or backlog numbers in ${context} \u2014 the backlog item links to your work, not the other way around.`;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1580
1669
|
// src/commands/commit/validateMessage.ts
|
|
1581
1670
|
var MAX_MESSAGE_LENGTH = 50;
|
|
1582
1671
|
var CONVENTIONAL_COMMIT_REGEX = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(!)?(\(.+\))?!?: .+$/;
|
|
@@ -1585,6 +1674,13 @@ function validateMessage(message, config) {
|
|
|
1585
1674
|
console.error("Error: Commit message must not reference Claude");
|
|
1586
1675
|
process.exit(1);
|
|
1587
1676
|
}
|
|
1677
|
+
const backlogIds = findBacklogRefs(message);
|
|
1678
|
+
if (backlogIds.length > 0) {
|
|
1679
|
+
console.error(
|
|
1680
|
+
backlogRefError("Commit message", "commit messages", backlogIds)
|
|
1681
|
+
);
|
|
1682
|
+
process.exit(1);
|
|
1683
|
+
}
|
|
1588
1684
|
if (config.commit?.conventional && !CONVENTIONAL_COMMIT_REGEX.test(message)) {
|
|
1589
1685
|
console.error(
|
|
1590
1686
|
"Error: Commit message must follow conventional commit format (e.g., 'feat: add feature', 'fix(scope): fix bug')"
|
|
@@ -1700,18 +1796,18 @@ async function promptMultiselect(message, options2) {
|
|
|
1700
1796
|
}
|
|
1701
1797
|
|
|
1702
1798
|
// src/shared/readPackageJson.ts
|
|
1703
|
-
import * as
|
|
1799
|
+
import * as fs2 from "fs";
|
|
1704
1800
|
import * as path from "path";
|
|
1705
1801
|
import chalk5 from "chalk";
|
|
1706
1802
|
function findPackageJson() {
|
|
1707
1803
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1708
|
-
if (
|
|
1804
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
1709
1805
|
return packageJsonPath;
|
|
1710
1806
|
}
|
|
1711
1807
|
return null;
|
|
1712
1808
|
}
|
|
1713
1809
|
function readPackageJson(filePath) {
|
|
1714
|
-
return JSON.parse(
|
|
1810
|
+
return JSON.parse(fs2.readFileSync(filePath, "utf8"));
|
|
1715
1811
|
}
|
|
1716
1812
|
function requirePackageJson() {
|
|
1717
1813
|
const packageJsonPath = findPackageJson();
|
|
@@ -1726,8 +1822,8 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
1726
1822
|
let currentDir = startDir;
|
|
1727
1823
|
while (true) {
|
|
1728
1824
|
const packageJsonPath = path.join(currentDir, "package.json");
|
|
1729
|
-
if (
|
|
1730
|
-
const packageJson = JSON.parse(
|
|
1825
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
1826
|
+
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
|
|
1731
1827
|
const scripts = packageJson.scripts || {};
|
|
1732
1828
|
const verifyScripts = Object.keys(scripts).filter(
|
|
1733
1829
|
(name) => name.startsWith("verify:")
|
|
@@ -2389,28 +2485,28 @@ async function init3(options2 = {}) {
|
|
|
2389
2485
|
import chalk23 from "chalk";
|
|
2390
2486
|
|
|
2391
2487
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
2392
|
-
import * as
|
|
2488
|
+
import * as fs3 from "fs";
|
|
2393
2489
|
import * as path8 from "path";
|
|
2394
2490
|
import chalk20 from "chalk";
|
|
2395
2491
|
function ensureVscodeFolder() {
|
|
2396
2492
|
const vscodeDir = path8.join(process.cwd(), ".vscode");
|
|
2397
|
-
if (!
|
|
2398
|
-
|
|
2493
|
+
if (!fs3.existsSync(vscodeDir)) {
|
|
2494
|
+
fs3.mkdirSync(vscodeDir);
|
|
2399
2495
|
console.log(chalk20.dim("Created .vscode folder"));
|
|
2400
2496
|
}
|
|
2401
2497
|
}
|
|
2402
2498
|
function removeVscodeFromGitignore() {
|
|
2403
2499
|
const gitignorePath = path8.join(process.cwd(), ".gitignore");
|
|
2404
|
-
if (!
|
|
2500
|
+
if (!fs3.existsSync(gitignorePath)) {
|
|
2405
2501
|
return;
|
|
2406
2502
|
}
|
|
2407
|
-
const content =
|
|
2503
|
+
const content = fs3.readFileSync(gitignorePath, "utf8");
|
|
2408
2504
|
const lines = content.split("\n");
|
|
2409
2505
|
const filteredLines = lines.filter(
|
|
2410
2506
|
(line) => !line.trim().toLowerCase().includes(".vscode")
|
|
2411
2507
|
);
|
|
2412
2508
|
if (filteredLines.length !== lines.length) {
|
|
2413
|
-
|
|
2509
|
+
fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2414
2510
|
console.log(chalk20.dim("Removed .vscode references from .gitignore"));
|
|
2415
2511
|
}
|
|
2416
2512
|
}
|
|
@@ -2428,20 +2524,20 @@ function createLaunchJson(type) {
|
|
|
2428
2524
|
]
|
|
2429
2525
|
};
|
|
2430
2526
|
const launchPath = path8.join(process.cwd(), ".vscode", "launch.json");
|
|
2431
|
-
|
|
2527
|
+
fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
2432
2528
|
`);
|
|
2433
2529
|
console.log(chalk20.green("Created .vscode/launch.json"));
|
|
2434
2530
|
}
|
|
2435
2531
|
|
|
2436
2532
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
2437
|
-
import * as
|
|
2533
|
+
import * as fs4 from "fs";
|
|
2438
2534
|
import * as path9 from "path";
|
|
2439
2535
|
function detectVscodeSetup(pkg) {
|
|
2440
2536
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
2441
2537
|
return {
|
|
2442
|
-
hasVscodeFolder:
|
|
2443
|
-
hasLaunchJson:
|
|
2444
|
-
hasSettingsJson:
|
|
2538
|
+
hasVscodeFolder: fs4.existsSync(vscodeDir),
|
|
2539
|
+
hasLaunchJson: fs4.existsSync(path9.join(vscodeDir, "launch.json")),
|
|
2540
|
+
hasSettingsJson: fs4.existsSync(path9.join(vscodeDir, "settings.json")),
|
|
2445
2541
|
hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
|
|
2446
2542
|
hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
|
|
2447
2543
|
};
|
|
@@ -2473,16 +2569,16 @@ function getAvailableOptions2(setup2) {
|
|
|
2473
2569
|
}
|
|
2474
2570
|
|
|
2475
2571
|
// src/commands/vscode/init/createSettingsJson.ts
|
|
2476
|
-
import * as
|
|
2572
|
+
import * as fs6 from "fs";
|
|
2477
2573
|
import * as path10 from "path";
|
|
2478
2574
|
import chalk21 from "chalk";
|
|
2479
2575
|
|
|
2480
2576
|
// src/commands/vscode/init/readVscodeJson.ts
|
|
2481
|
-
import * as
|
|
2577
|
+
import * as fs5 from "fs";
|
|
2482
2578
|
function readVscodeJson(filePath) {
|
|
2483
|
-
if (!
|
|
2579
|
+
if (!fs5.existsSync(filePath)) return {};
|
|
2484
2580
|
try {
|
|
2485
|
-
return JSON.parse(
|
|
2581
|
+
return JSON.parse(fs5.readFileSync(filePath, "utf8"));
|
|
2486
2582
|
} catch {
|
|
2487
2583
|
return {};
|
|
2488
2584
|
}
|
|
@@ -2501,7 +2597,7 @@ function createSettingsJson() {
|
|
|
2501
2597
|
"source.fixAll.oxc": "explicit"
|
|
2502
2598
|
}
|
|
2503
2599
|
};
|
|
2504
|
-
|
|
2600
|
+
fs6.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
2505
2601
|
`);
|
|
2506
2602
|
console.log(chalk21.green("Created .vscode/settings.json"));
|
|
2507
2603
|
}
|
|
@@ -2512,7 +2608,7 @@ function existingCodeActions(actions) {
|
|
|
2512
2608
|
}
|
|
2513
2609
|
|
|
2514
2610
|
// src/commands/vscode/init/createExtensionsJson.ts
|
|
2515
|
-
import * as
|
|
2611
|
+
import * as fs7 from "fs";
|
|
2516
2612
|
import * as path11 from "path";
|
|
2517
2613
|
import chalk22 from "chalk";
|
|
2518
2614
|
function createExtensionsJson() {
|
|
@@ -2521,7 +2617,7 @@ function createExtensionsJson() {
|
|
|
2521
2617
|
const previous = Array.isArray(existing.recommendations) ? existing.recommendations : [];
|
|
2522
2618
|
const recommendations = previous.includes("oxc.oxc-vscode") ? previous : [...previous, "oxc.oxc-vscode"];
|
|
2523
2619
|
const extensions = { ...existing, recommendations };
|
|
2524
|
-
|
|
2620
|
+
fs7.writeFileSync(
|
|
2525
2621
|
extensionsPath,
|
|
2526
2622
|
`${JSON.stringify(extensions, null, " ")}
|
|
2527
2623
|
`
|
|
@@ -2578,20 +2674,20 @@ import path17 from "path";
|
|
|
2578
2674
|
import chalk25 from "chalk";
|
|
2579
2675
|
|
|
2580
2676
|
// src/commands/lint/lint/checkFileNames.ts
|
|
2581
|
-
import
|
|
2677
|
+
import fs9 from "fs";
|
|
2582
2678
|
import path13 from "path";
|
|
2583
2679
|
|
|
2584
2680
|
// src/shared/findSourceFiles.ts
|
|
2585
|
-
import
|
|
2681
|
+
import fs8 from "fs";
|
|
2586
2682
|
import path12 from "path";
|
|
2587
2683
|
var EXTENSIONS = [".ts", ".tsx"];
|
|
2588
2684
|
function findSourceFiles(dir, options2 = {}) {
|
|
2589
2685
|
const { includeTests = true } = options2;
|
|
2590
2686
|
const results = [];
|
|
2591
|
-
if (!
|
|
2687
|
+
if (!fs8.existsSync(dir)) {
|
|
2592
2688
|
return results;
|
|
2593
2689
|
}
|
|
2594
|
-
const entries =
|
|
2690
|
+
const entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
2595
2691
|
for (const entry of entries) {
|
|
2596
2692
|
const fullPath = path12.join(dir, entry.name);
|
|
2597
2693
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
@@ -2641,7 +2737,7 @@ function checkFileNames() {
|
|
|
2641
2737
|
const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
|
|
2642
2738
|
if (/\.(stories|test)\.(ts|tsx)$/.test(fileName)) continue;
|
|
2643
2739
|
if (/^[A-Z]/.test(nameWithoutExt)) {
|
|
2644
|
-
const content =
|
|
2740
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
2645
2741
|
if (!hasClassOrComponent(content) && !hasMatchingTypeExport(content, nameWithoutExt)) {
|
|
2646
2742
|
violations.push({
|
|
2647
2743
|
filePath,
|
|
@@ -2658,7 +2754,7 @@ function checkFileNames() {
|
|
|
2658
2754
|
import chalk24 from "chalk";
|
|
2659
2755
|
|
|
2660
2756
|
// src/commands/lint/lint/applyMoves.ts
|
|
2661
|
-
import
|
|
2757
|
+
import fs10 from "fs";
|
|
2662
2758
|
import path15 from "path";
|
|
2663
2759
|
|
|
2664
2760
|
// src/commands/lint/lint/renameExports.ts
|
|
@@ -2694,8 +2790,8 @@ function isCaseOnly(a, b) {
|
|
|
2694
2790
|
}
|
|
2695
2791
|
function moveCaseInsensitive(absSource, absDest) {
|
|
2696
2792
|
const tmp = `${absSource}.tmp`;
|
|
2697
|
-
|
|
2698
|
-
|
|
2793
|
+
fs10.renameSync(absSource, tmp);
|
|
2794
|
+
fs10.renameSync(tmp, absDest);
|
|
2699
2795
|
}
|
|
2700
2796
|
function applyMoves(project, moves, cwd, emit4) {
|
|
2701
2797
|
for (const { sourcePath, destPath } of moves) {
|
|
@@ -2715,19 +2811,19 @@ function applyMoves(project, moves, cwd, emit4) {
|
|
|
2715
2811
|
for (const { sourcePath, destPath } of moves) {
|
|
2716
2812
|
const absSource = path15.resolve(sourcePath);
|
|
2717
2813
|
const absDest = path15.resolve(destPath);
|
|
2718
|
-
if (isCaseOnly(absSource, absDest) &&
|
|
2814
|
+
if (isCaseOnly(absSource, absDest) && fs10.existsSync(absSource)) {
|
|
2719
2815
|
moveCaseInsensitive(absSource, absDest);
|
|
2720
2816
|
}
|
|
2721
2817
|
}
|
|
2722
2818
|
}
|
|
2723
2819
|
|
|
2724
2820
|
// src/commands/lint/lint/createLintProject.ts
|
|
2725
|
-
import
|
|
2821
|
+
import fs11 from "fs";
|
|
2726
2822
|
import path16 from "path";
|
|
2727
2823
|
import { Project } from "ts-morph";
|
|
2728
2824
|
function createLintProject() {
|
|
2729
2825
|
const tsConfigPath = path16.resolve("tsconfig.json");
|
|
2730
|
-
const project =
|
|
2826
|
+
const project = fs11.existsSync(tsConfigPath) ? new Project({
|
|
2731
2827
|
tsConfigFilePath: tsConfigPath,
|
|
2732
2828
|
skipAddingFilesFromTsConfig: true
|
|
2733
2829
|
}) : new Project();
|
|
@@ -2784,7 +2880,7 @@ function runFileNameCheck(fix = false) {
|
|
|
2784
2880
|
}
|
|
2785
2881
|
|
|
2786
2882
|
// src/commands/lint/lint/runImportExtensionCheck.ts
|
|
2787
|
-
import
|
|
2883
|
+
import fs12 from "fs";
|
|
2788
2884
|
|
|
2789
2885
|
// src/commands/lint/shared.ts
|
|
2790
2886
|
import chalk26 from "chalk";
|
|
@@ -2810,7 +2906,7 @@ ${checkName} failed:
|
|
|
2810
2906
|
|
|
2811
2907
|
// src/commands/lint/lint/runImportExtensionCheck.ts
|
|
2812
2908
|
function checkForImportExtensions(filePath) {
|
|
2813
|
-
const content =
|
|
2909
|
+
const content = fs12.readFileSync(filePath, "utf8");
|
|
2814
2910
|
const lines = content.split("\n");
|
|
2815
2911
|
const violations = [];
|
|
2816
2912
|
const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
|
|
@@ -2844,9 +2940,9 @@ function runImportExtensionCheck() {
|
|
|
2844
2940
|
}
|
|
2845
2941
|
|
|
2846
2942
|
// src/commands/lint/lint/runStaticImportCheck.ts
|
|
2847
|
-
import
|
|
2943
|
+
import fs13 from "fs";
|
|
2848
2944
|
function checkForDynamicImports(filePath) {
|
|
2849
|
-
const content =
|
|
2945
|
+
const content = fs13.readFileSync(filePath, "utf8");
|
|
2850
2946
|
const lines = content.split("\n");
|
|
2851
2947
|
const violations = [];
|
|
2852
2948
|
const requirePattern = /\brequire\s*\(/;
|
|
@@ -2894,9 +2990,9 @@ function lint(options2 = {}) {
|
|
|
2894
2990
|
import { execSync as execSync18 } from "child_process";
|
|
2895
2991
|
import { basename as basename2, resolve as resolve5 } from "path";
|
|
2896
2992
|
|
|
2897
|
-
// src/commands/verify/
|
|
2993
|
+
// src/commands/verify/blockCodeComments/findComments.ts
|
|
2898
2994
|
import { execSync as execSync10 } from "child_process";
|
|
2899
|
-
import
|
|
2995
|
+
import fs15 from "fs";
|
|
2900
2996
|
import { minimatch } from "minimatch";
|
|
2901
2997
|
import { Project as Project2 } from "ts-morph";
|
|
2902
2998
|
|
|
@@ -2929,8 +3025,8 @@ function isHashCommentFile(filePath) {
|
|
|
2929
3025
|
return isYamlFile(filePath) || isDockerfile(filePath) || isEnvFile(filePath) || isShellFile(filePath);
|
|
2930
3026
|
}
|
|
2931
3027
|
|
|
2932
|
-
// src/commands/verify/
|
|
2933
|
-
import
|
|
3028
|
+
// src/commands/verify/blockCodeComments/collectFileComments.ts
|
|
3029
|
+
import fs14 from "fs";
|
|
2934
3030
|
|
|
2935
3031
|
// src/shared/isBicepFile.ts
|
|
2936
3032
|
var BICEP_EXTENSIONS = [".bicep", ".bicepparam"];
|
|
@@ -2939,7 +3035,7 @@ function isBicepFile(filePath) {
|
|
|
2939
3035
|
return BICEP_EXTENSIONS.some((ext) => filePath.endsWith(ext));
|
|
2940
3036
|
}
|
|
2941
3037
|
|
|
2942
|
-
// src/commands/verify/
|
|
3038
|
+
// src/commands/verify/blockCodeComments/collectBicepComments.ts
|
|
2943
3039
|
function blankNonNewline(text17) {
|
|
2944
3040
|
return text17.replace(/[^\n]/g, " ");
|
|
2945
3041
|
}
|
|
@@ -2962,7 +3058,7 @@ function collectBicepComments(content) {
|
|
|
2962
3058
|
return comments3;
|
|
2963
3059
|
}
|
|
2964
3060
|
|
|
2965
|
-
// src/commands/verify/
|
|
3061
|
+
// src/commands/verify/blockCodeComments/collectHashComments.ts
|
|
2966
3062
|
function blankNonNewline2(text17) {
|
|
2967
3063
|
return text17.replace(/[^\n]/g, " ");
|
|
2968
3064
|
}
|
|
@@ -2988,7 +3084,7 @@ function collectHashComments(content, options2) {
|
|
|
2988
3084
|
return comments3;
|
|
2989
3085
|
}
|
|
2990
3086
|
|
|
2991
|
-
// src/commands/verify/
|
|
3087
|
+
// src/commands/verify/blockCodeComments/collectComments.ts
|
|
2992
3088
|
function collectComments(sourceFile) {
|
|
2993
3089
|
const seen = /* @__PURE__ */ new Set();
|
|
2994
3090
|
const comments3 = [];
|
|
@@ -3025,7 +3121,7 @@ function parseMaintainabilityOverride(content) {
|
|
|
3025
3121
|
return void 0;
|
|
3026
3122
|
}
|
|
3027
3123
|
|
|
3028
|
-
// src/commands/verify/
|
|
3124
|
+
// src/commands/verify/blockCodeComments/isCommentExempt.ts
|
|
3029
3125
|
var MACHINE_DIRECTIVES = [
|
|
3030
3126
|
"oxlint-disable",
|
|
3031
3127
|
"oxlint-enable",
|
|
@@ -3046,7 +3142,7 @@ function isCommentExempt(text17) {
|
|
|
3046
3142
|
return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
|
|
3047
3143
|
}
|
|
3048
3144
|
|
|
3049
|
-
// src/commands/verify/
|
|
3145
|
+
// src/commands/verify/blockCodeComments/collectSourceFindings.ts
|
|
3050
3146
|
function toSingleLine(text17) {
|
|
3051
3147
|
return text17.replace(/\s+/g, " ").trim();
|
|
3052
3148
|
}
|
|
@@ -3062,7 +3158,7 @@ function collectSourceFindings(file, lines, project) {
|
|
|
3062
3158
|
return findings;
|
|
3063
3159
|
}
|
|
3064
3160
|
|
|
3065
|
-
// src/commands/verify/
|
|
3161
|
+
// src/commands/verify/blockCodeComments/collectYamlComments.ts
|
|
3066
3162
|
import { Lexer } from "yaml";
|
|
3067
3163
|
function collectYamlComments(content) {
|
|
3068
3164
|
const comments3 = [];
|
|
@@ -3074,7 +3170,7 @@ function collectYamlComments(content) {
|
|
|
3074
3170
|
return comments3;
|
|
3075
3171
|
}
|
|
3076
3172
|
|
|
3077
|
-
// src/commands/verify/
|
|
3173
|
+
// src/commands/verify/blockCodeComments/collectFileComments.ts
|
|
3078
3174
|
function toFindings(file, lines, raw, exempt) {
|
|
3079
3175
|
const findings = [];
|
|
3080
3176
|
for (const { line, text: text17 } of raw) {
|
|
@@ -3085,7 +3181,7 @@ function toFindings(file, lines, raw, exempt) {
|
|
|
3085
3181
|
return findings;
|
|
3086
3182
|
}
|
|
3087
3183
|
function collectFileComments(file, lines, project) {
|
|
3088
|
-
const read = () =>
|
|
3184
|
+
const read = () => fs14.readFileSync(file, "utf8");
|
|
3089
3185
|
if (isYamlFile(file))
|
|
3090
3186
|
return toFindings(file, lines, collectYamlComments(read()), false);
|
|
3091
3187
|
if (isDockerfile(file) || isEnvFile(file) || isShellFile(file))
|
|
@@ -3100,7 +3196,7 @@ function collectFileComments(file, lines, project) {
|
|
|
3100
3196
|
return collectSourceFindings(file, lines, project);
|
|
3101
3197
|
}
|
|
3102
3198
|
|
|
3103
|
-
// src/commands/verify/
|
|
3199
|
+
// src/commands/verify/blockCodeComments/parseDiffAddedLines.ts
|
|
3104
3200
|
var FILE_HEADER = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
3105
3201
|
var HUNK_HEADER = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
3106
3202
|
function parseDiffAddedLines(diff2) {
|
|
@@ -3135,7 +3231,7 @@ function parseDiffAddedLines(diff2) {
|
|
|
3135
3231
|
return added;
|
|
3136
3232
|
}
|
|
3137
3233
|
|
|
3138
|
-
// src/commands/verify/
|
|
3234
|
+
// src/commands/verify/blockCodeComments/findComments.ts
|
|
3139
3235
|
var SCANNED_EXTENSIONS = [
|
|
3140
3236
|
".ts",
|
|
3141
3237
|
".tsx",
|
|
@@ -3152,7 +3248,7 @@ function shouldScan(file, ignoreGlobs) {
|
|
|
3152
3248
|
if (!SCANNED_EXTENSIONS.some((ext) => file.endsWith(ext)) && !isHashCommentFile(file))
|
|
3153
3249
|
return false;
|
|
3154
3250
|
if (ignoreGlobs.some((glob) => minimatch(file, glob))) return false;
|
|
3155
|
-
return
|
|
3251
|
+
return fs15.existsSync(file);
|
|
3156
3252
|
}
|
|
3157
3253
|
function findComments(options2) {
|
|
3158
3254
|
const diff2 = execSync10("git diff HEAD", {
|
|
@@ -3173,9 +3269,9 @@ function findComments(options2) {
|
|
|
3173
3269
|
return findings;
|
|
3174
3270
|
}
|
|
3175
3271
|
|
|
3176
|
-
// src/commands/verify/
|
|
3177
|
-
function
|
|
3178
|
-
const ignoreGlobs = loadConfig().
|
|
3272
|
+
// src/commands/verify/blockCodeComments/index.ts
|
|
3273
|
+
function blockCodeComments() {
|
|
3274
|
+
const ignoreGlobs = loadConfig().blockCodeComments?.ignore ?? [];
|
|
3179
3275
|
const findings = findComments({ ignoreGlobs });
|
|
3180
3276
|
if (findings.length === 0) {
|
|
3181
3277
|
console.log("No comments on changed lines.");
|
|
@@ -4230,7 +4326,7 @@ function detectPlatform() {
|
|
|
4230
4326
|
|
|
4231
4327
|
// src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
|
|
4232
4328
|
import { spawn as spawn2 } from "child_process";
|
|
4233
|
-
import
|
|
4329
|
+
import fs16 from "fs";
|
|
4234
4330
|
import { createRequire } from "module";
|
|
4235
4331
|
import path21 from "path";
|
|
4236
4332
|
var require2 = createRequire(import.meta.url);
|
|
@@ -4242,7 +4338,7 @@ function showWindowsNotificationFromWsl(options2) {
|
|
|
4242
4338
|
const { title, message, sound } = options2;
|
|
4243
4339
|
const snoreToastPath = getSnoreToastPath();
|
|
4244
4340
|
try {
|
|
4245
|
-
|
|
4341
|
+
fs16.chmodSync(snoreToastPath, 493);
|
|
4246
4342
|
} catch {
|
|
4247
4343
|
}
|
|
4248
4344
|
const args = ["-t", title, "-m", message];
|
|
@@ -6684,12 +6780,12 @@ import chalk42 from "chalk";
|
|
|
6684
6780
|
import * as path24 from "path";
|
|
6685
6781
|
|
|
6686
6782
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
6687
|
-
import * as
|
|
6783
|
+
import * as fs18 from "fs";
|
|
6688
6784
|
import * as os2 from "os";
|
|
6689
6785
|
import * as path23 from "path";
|
|
6690
6786
|
|
|
6691
6787
|
// src/commands/sessions/shared/parseSessionFile.ts
|
|
6692
|
-
import * as
|
|
6788
|
+
import * as fs17 from "fs";
|
|
6693
6789
|
import * as path22 from "path";
|
|
6694
6790
|
|
|
6695
6791
|
// src/commands/sessions/shared/deriveHistoryFields.ts
|
|
@@ -6712,7 +6808,7 @@ function deriveHistoryFields(commandName, commandArgs, name) {
|
|
|
6712
6808
|
return fields;
|
|
6713
6809
|
}
|
|
6714
6810
|
function deriveSessionType(commandName, name) {
|
|
6715
|
-
if (commandName === "review-comments") return "review";
|
|
6811
|
+
if (commandName === "review-pr-comments") return "review";
|
|
6716
6812
|
if (KNOWN.includes(commandName))
|
|
6717
6813
|
return commandName;
|
|
6718
6814
|
if (commandName || name) return "prompt";
|
|
@@ -6787,10 +6883,10 @@ function matchMarker(text17, tag) {
|
|
|
6787
6883
|
async function parseSessionFile(filePath, origin = "wsl") {
|
|
6788
6884
|
let handle;
|
|
6789
6885
|
try {
|
|
6790
|
-
handle = await
|
|
6886
|
+
handle = await fs17.promises.open(filePath, "r");
|
|
6791
6887
|
const meta = extractSessionMeta(await readHeadLines(handle));
|
|
6792
6888
|
if (!meta.sessionId) return null;
|
|
6793
|
-
const timestamp6 = meta.timestamp || (await
|
|
6889
|
+
const timestamp6 = meta.timestamp || (await fs17.promises.stat(filePath)).mtime.toISOString();
|
|
6794
6890
|
return {
|
|
6795
6891
|
sessionId: meta.sessionId,
|
|
6796
6892
|
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
@@ -6836,7 +6932,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
6836
6932
|
sessionRoots().map(async ({ dir, origin }) => {
|
|
6837
6933
|
let projectDirs;
|
|
6838
6934
|
try {
|
|
6839
|
-
projectDirs = await
|
|
6935
|
+
projectDirs = await fs18.promises.readdir(dir);
|
|
6840
6936
|
} catch {
|
|
6841
6937
|
return;
|
|
6842
6938
|
}
|
|
@@ -6845,7 +6941,7 @@ async function discoverSessionJsonlPaths() {
|
|
|
6845
6941
|
const dirPath = path23.join(dir, dirName);
|
|
6846
6942
|
let entries;
|
|
6847
6943
|
try {
|
|
6848
|
-
entries = await
|
|
6944
|
+
entries = await fs18.promises.readdir(dirPath);
|
|
6849
6945
|
} catch {
|
|
6850
6946
|
return;
|
|
6851
6947
|
}
|
|
@@ -7618,9 +7714,9 @@ function startWebServer(label2, port, handler, initialPath, open = true) {
|
|
|
7618
7714
|
// src/commands/sessions/daemon/ensureDaemonRunning.ts
|
|
7619
7715
|
import { spawn as spawn4 } from "child_process";
|
|
7620
7716
|
import {
|
|
7621
|
-
closeSync,
|
|
7717
|
+
closeSync as closeSync2,
|
|
7622
7718
|
mkdirSync as mkdirSync10,
|
|
7623
|
-
openSync,
|
|
7719
|
+
openSync as openSync2,
|
|
7624
7720
|
statSync,
|
|
7625
7721
|
unlinkSync as unlinkSync5,
|
|
7626
7722
|
writeSync
|
|
@@ -7660,9 +7756,9 @@ function acquireSpawnLock() {
|
|
|
7660
7756
|
}
|
|
7661
7757
|
function tryCreateLock() {
|
|
7662
7758
|
try {
|
|
7663
|
-
const fd =
|
|
7759
|
+
const fd = openSync2(daemonPaths.spawnLock, "wx");
|
|
7664
7760
|
writeSync(fd, String(process.pid));
|
|
7665
|
-
|
|
7761
|
+
closeSync2(fd);
|
|
7666
7762
|
return true;
|
|
7667
7763
|
} catch {
|
|
7668
7764
|
return false;
|
|
@@ -7682,7 +7778,7 @@ function releaseSpawnLock() {
|
|
|
7682
7778
|
}
|
|
7683
7779
|
}
|
|
7684
7780
|
function spawnDaemon(reason) {
|
|
7685
|
-
const log =
|
|
7781
|
+
const log = openSync2(daemonPaths.log, "a");
|
|
7686
7782
|
const child = spawn4(process.execPath, [process.argv[1], "daemon", "run"], {
|
|
7687
7783
|
detached: true,
|
|
7688
7784
|
stdio: ["ignore", log, log],
|
|
@@ -12773,13 +12869,13 @@ import chalk119 from "chalk";
|
|
|
12773
12869
|
import chalk112 from "chalk";
|
|
12774
12870
|
|
|
12775
12871
|
// src/commands/complexity/shared/index.ts
|
|
12776
|
-
import
|
|
12872
|
+
import fs20 from "fs";
|
|
12777
12873
|
import path27 from "path";
|
|
12778
12874
|
import chalk111 from "chalk";
|
|
12779
12875
|
import ts5 from "typescript";
|
|
12780
12876
|
|
|
12781
12877
|
// src/commands/complexity/findSourceFiles.ts
|
|
12782
|
-
import
|
|
12878
|
+
import fs19 from "fs";
|
|
12783
12879
|
import path26 from "path";
|
|
12784
12880
|
import { minimatch as minimatch5 } from "minimatch";
|
|
12785
12881
|
function applyIgnoreGlobs(files, extraIgnore = []) {
|
|
@@ -12788,11 +12884,11 @@ function applyIgnoreGlobs(files, extraIgnore = []) {
|
|
|
12788
12884
|
return files.filter((f) => !ignore3.some((glob) => minimatch5(f, glob)));
|
|
12789
12885
|
}
|
|
12790
12886
|
function walk(dir, results) {
|
|
12791
|
-
if (!
|
|
12887
|
+
if (!fs19.existsSync(dir)) {
|
|
12792
12888
|
return;
|
|
12793
12889
|
}
|
|
12794
12890
|
const extensions = [".ts", ".tsx"];
|
|
12795
|
-
const entries =
|
|
12891
|
+
const entries = fs19.readdirSync(dir, { withFileTypes: true });
|
|
12796
12892
|
for (const entry of entries) {
|
|
12797
12893
|
const fullPath = path26.join(dir, entry.name);
|
|
12798
12894
|
if (entry.isDirectory()) {
|
|
@@ -12813,10 +12909,10 @@ function findSourceFiles2(pattern2, baseDir = ".", extraIgnore = []) {
|
|
|
12813
12909
|
extraIgnore
|
|
12814
12910
|
);
|
|
12815
12911
|
}
|
|
12816
|
-
if (
|
|
12912
|
+
if (fs19.existsSync(pattern2) && fs19.statSync(pattern2).isFile()) {
|
|
12817
12913
|
return [pattern2];
|
|
12818
12914
|
}
|
|
12819
|
-
if (
|
|
12915
|
+
if (fs19.existsSync(pattern2) && fs19.statSync(pattern2).isDirectory()) {
|
|
12820
12916
|
walk(pattern2, results);
|
|
12821
12917
|
return applyIgnoreGlobs(results, extraIgnore);
|
|
12822
12918
|
}
|
|
@@ -13014,7 +13110,7 @@ function countSloc(content) {
|
|
|
13014
13110
|
|
|
13015
13111
|
// src/commands/complexity/shared/index.ts
|
|
13016
13112
|
function createSourceFromFile(filePath) {
|
|
13017
|
-
const content =
|
|
13113
|
+
const content = fs20.readFileSync(filePath, "utf8");
|
|
13018
13114
|
return ts5.createSourceFile(
|
|
13019
13115
|
path27.basename(filePath),
|
|
13020
13116
|
content,
|
|
@@ -13174,7 +13270,7 @@ function printMaintainabilityFormula() {
|
|
|
13174
13270
|
}
|
|
13175
13271
|
|
|
13176
13272
|
// src/commands/complexity/maintainability/collectFileMetrics.ts
|
|
13177
|
-
import
|
|
13273
|
+
import fs21 from "fs";
|
|
13178
13274
|
|
|
13179
13275
|
// src/commands/complexity/maintainability/calculateMaintainabilityIndex.ts
|
|
13180
13276
|
function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, sloc2) {
|
|
@@ -13189,7 +13285,7 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
|
|
|
13189
13285
|
function collectFileMetrics(files) {
|
|
13190
13286
|
const fileMetrics = /* @__PURE__ */ new Map();
|
|
13191
13287
|
for (const file of files) {
|
|
13192
|
-
const content =
|
|
13288
|
+
const content = fs21.readFileSync(file, "utf8");
|
|
13193
13289
|
fileMetrics.set(file, {
|
|
13194
13290
|
sloc: countSloc(content),
|
|
13195
13291
|
functions: [],
|
|
@@ -13245,14 +13341,14 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
13245
13341
|
}
|
|
13246
13342
|
|
|
13247
13343
|
// src/commands/complexity/sloc.ts
|
|
13248
|
-
import
|
|
13344
|
+
import fs22 from "fs";
|
|
13249
13345
|
import chalk118 from "chalk";
|
|
13250
13346
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
13251
13347
|
withSourceFiles(pattern2, (files) => {
|
|
13252
13348
|
const results = [];
|
|
13253
13349
|
let hasViolation = false;
|
|
13254
13350
|
for (const file of files) {
|
|
13255
|
-
const content =
|
|
13351
|
+
const content = fs22.readFileSync(file, "utf8");
|
|
13256
13352
|
const lines = countSloc(content);
|
|
13257
13353
|
results.push({ file, lines });
|
|
13258
13354
|
if (options2.threshold !== void 0 && lines > options2.threshold) {
|
|
@@ -14147,7 +14243,7 @@ function registerDevlog(program2) {
|
|
|
14147
14243
|
}
|
|
14148
14244
|
|
|
14149
14245
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
14150
|
-
import { closeSync as
|
|
14246
|
+
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
|
|
14151
14247
|
import { join as join37 } from "path";
|
|
14152
14248
|
import chalk131 from "chalk";
|
|
14153
14249
|
|
|
@@ -14178,8 +14274,8 @@ function isLockedDll(debugDir) {
|
|
|
14178
14274
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
14179
14275
|
const dllPath = join37(debugDir, file);
|
|
14180
14276
|
try {
|
|
14181
|
-
const fd =
|
|
14182
|
-
|
|
14277
|
+
const fd = openSync3(dllPath, "r+");
|
|
14278
|
+
closeSync3(fd);
|
|
14183
14279
|
} catch {
|
|
14184
14280
|
return dllPath;
|
|
14185
14281
|
}
|
|
@@ -14779,7 +14875,7 @@ function registerDotnet(program2) {
|
|
|
14779
14875
|
}
|
|
14780
14876
|
|
|
14781
14877
|
// src/commands/editHook/index.ts
|
|
14782
|
-
import
|
|
14878
|
+
import fs23 from "fs";
|
|
14783
14879
|
|
|
14784
14880
|
// src/commands/editHook/extractComments.ts
|
|
14785
14881
|
var SOURCE_EXTENSIONS = [
|
|
@@ -14959,7 +15055,7 @@ function tryParseInput2(raw) {
|
|
|
14959
15055
|
function readExisting(filePath) {
|
|
14960
15056
|
if (!filePath) return void 0;
|
|
14961
15057
|
try {
|
|
14962
|
-
return
|
|
15058
|
+
return fs23.readFileSync(filePath, "utf8");
|
|
14963
15059
|
} catch {
|
|
14964
15060
|
return void 0;
|
|
14965
15061
|
}
|
|
@@ -15637,11 +15733,11 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
15637
15733
|
configHelp(command, HARNESS_CONFIG_HELP);
|
|
15638
15734
|
}
|
|
15639
15735
|
|
|
15640
|
-
// src/commands/
|
|
15736
|
+
// src/commands/reviewPrComments.ts
|
|
15641
15737
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
15642
15738
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
15643
15739
|
import chalk145 from "chalk";
|
|
15644
|
-
async function
|
|
15740
|
+
async function reviewPrComments(number) {
|
|
15645
15741
|
if (number) {
|
|
15646
15742
|
try {
|
|
15647
15743
|
execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
@@ -15651,8 +15747,12 @@ async function reviewComments(number) {
|
|
|
15651
15747
|
}
|
|
15652
15748
|
}
|
|
15653
15749
|
const claudeSessionId = randomUUID3();
|
|
15654
|
-
emitActivity({
|
|
15655
|
-
|
|
15750
|
+
emitActivity({
|
|
15751
|
+
kind: "command",
|
|
15752
|
+
name: "review-pr-comments",
|
|
15753
|
+
claudeSessionId
|
|
15754
|
+
});
|
|
15755
|
+
const { done: done2 } = spawnClaude("/review-pr-comments", {
|
|
15656
15756
|
permissionMode: "acceptEdits",
|
|
15657
15757
|
sessionId: claudeSessionId
|
|
15658
15758
|
});
|
|
@@ -15679,8 +15779,8 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
|
|
|
15679
15779
|
);
|
|
15680
15780
|
if (alias) command.alias(alias);
|
|
15681
15781
|
}
|
|
15682
|
-
function
|
|
15683
|
-
program2.command("review-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-comments mode (single session)").action((number) =>
|
|
15782
|
+
function registerReviewPrComments(program2) {
|
|
15783
|
+
program2.command("review-pr-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-pr-comments mode (single session)").action((number) => reviewPrComments(number));
|
|
15684
15784
|
}
|
|
15685
15785
|
function registerLaunch(program2) {
|
|
15686
15786
|
registerNext(program2);
|
|
@@ -15697,7 +15797,7 @@ function registerLaunch(program2) {
|
|
|
15697
15797
|
"bug",
|
|
15698
15798
|
"Launch Claude in /bug mode, chain into next on /next signal"
|
|
15699
15799
|
);
|
|
15700
|
-
|
|
15800
|
+
registerReviewPrComments(program2);
|
|
15701
15801
|
registerRefineLaunch(program2, RESUME_SESSION_FLAG);
|
|
15702
15802
|
}
|
|
15703
15803
|
|
|
@@ -16860,14 +16960,15 @@ ${resolves}` : baseWhy);
|
|
|
16860
16960
|
return serializePrBody(parsed);
|
|
16861
16961
|
}
|
|
16862
16962
|
|
|
16863
|
-
// src/commands/prs/
|
|
16963
|
+
// src/commands/prs/findWallOfText.ts
|
|
16864
16964
|
var MAX_PARAGRAPH_CHARS = 600;
|
|
16865
16965
|
var MAX_PARAGRAPH_SENTENCES = 4;
|
|
16866
|
-
function
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16966
|
+
function findWallOfText(body) {
|
|
16967
|
+
const wall = splitParagraphs(body).find((p) => isWallOfText(p.lines));
|
|
16968
|
+
if (!wall) {
|
|
16969
|
+
return void 0;
|
|
16970
|
+
}
|
|
16971
|
+
return { section: wall.section, chars: wall.lines.join(" ").trim().length };
|
|
16871
16972
|
}
|
|
16872
16973
|
function splitParagraphs(body) {
|
|
16873
16974
|
const paragraphs = [];
|
|
@@ -16900,6 +17001,14 @@ function isWallOfText(lines) {
|
|
|
16900
17001
|
const text17 = lines.join(" ").trim();
|
|
16901
17002
|
return text17.length > MAX_PARAGRAPH_CHARS || countSentences(text17) > MAX_PARAGRAPH_SENTENCES;
|
|
16902
17003
|
}
|
|
17004
|
+
function countSentences(paragraph) {
|
|
17005
|
+
return paragraph.match(/[.!?]+(\s|$)/g)?.length ?? 0;
|
|
17006
|
+
}
|
|
17007
|
+
function isListLine(line) {
|
|
17008
|
+
return /^\s*([-*+]|\d+[.)])\s/.test(line);
|
|
17009
|
+
}
|
|
17010
|
+
|
|
17011
|
+
// src/commands/prs/validatePrContent.ts
|
|
16903
17012
|
function validatePrContent(title, body) {
|
|
16904
17013
|
if (title.toLowerCase().includes("claude")) {
|
|
16905
17014
|
console.error("Error: PR title must not reference Claude");
|
|
@@ -16909,11 +17018,20 @@ function validatePrContent(title, body) {
|
|
|
16909
17018
|
console.error("Error: PR body must not reference Claude");
|
|
16910
17019
|
process.exit(1);
|
|
16911
17020
|
}
|
|
16912
|
-
const
|
|
17021
|
+
const titleBacklogIds = findBacklogRefs(title);
|
|
17022
|
+
if (titleBacklogIds.length > 0) {
|
|
17023
|
+
console.error(backlogRefError("PR title", "PRs", titleBacklogIds));
|
|
17024
|
+
process.exit(1);
|
|
17025
|
+
}
|
|
17026
|
+
const bodyBacklogIds = findBacklogRefs(body);
|
|
17027
|
+
if (bodyBacklogIds.length > 0) {
|
|
17028
|
+
console.error(backlogRefError("PR body", "PRs", bodyBacklogIds));
|
|
17029
|
+
process.exit(1);
|
|
17030
|
+
}
|
|
17031
|
+
const wall = findWallOfText(body);
|
|
16913
17032
|
if (wall) {
|
|
16914
|
-
const chars = wall.lines.join(" ").trim().length;
|
|
16915
17033
|
console.error(
|
|
16916
|
-
`Error: the "${wall.section}" section contains a wall-of-text paragraph (${chars} chars). Be concise \u2014 split it into bullet points or trim it.`
|
|
17034
|
+
`Error: the "${wall.section}" section contains a wall-of-text paragraph (${wall.chars} chars). Be concise \u2014 split it into bullet points or trim it.`
|
|
16917
17035
|
);
|
|
16918
17036
|
process.exit(1);
|
|
16919
17037
|
}
|
|
@@ -18116,17 +18234,17 @@ Refactor check failed:
|
|
|
18116
18234
|
|
|
18117
18235
|
// src/commands/refactor/check/getViolations/index.ts
|
|
18118
18236
|
import { execSync as execSync49 } from "child_process";
|
|
18119
|
-
import
|
|
18237
|
+
import fs25 from "fs";
|
|
18120
18238
|
import { minimatch as minimatch6 } from "minimatch";
|
|
18121
18239
|
|
|
18122
18240
|
// src/commands/refactor/check/getViolations/getIgnoredFiles.ts
|
|
18123
|
-
import
|
|
18241
|
+
import fs24 from "fs";
|
|
18124
18242
|
var REFACTOR_YML_PATH = "refactor.yml";
|
|
18125
18243
|
function parseRefactorYml() {
|
|
18126
|
-
if (!
|
|
18244
|
+
if (!fs24.existsSync(REFACTOR_YML_PATH)) {
|
|
18127
18245
|
return [];
|
|
18128
18246
|
}
|
|
18129
|
-
const content =
|
|
18247
|
+
const content = fs24.readFileSync(REFACTOR_YML_PATH, "utf8");
|
|
18130
18248
|
const entries = [];
|
|
18131
18249
|
const lines = content.split("\n");
|
|
18132
18250
|
let currentEntry = {};
|
|
@@ -18156,7 +18274,7 @@ function getIgnoredFiles() {
|
|
|
18156
18274
|
|
|
18157
18275
|
// src/commands/refactor/check/getViolations/index.ts
|
|
18158
18276
|
function countLines(filePath) {
|
|
18159
|
-
const content =
|
|
18277
|
+
const content = fs25.readFileSync(filePath, "utf8");
|
|
18160
18278
|
return content.split("\n").length;
|
|
18161
18279
|
}
|
|
18162
18280
|
function getGitFiles(options2) {
|
|
@@ -18914,12 +19032,12 @@ import chalk170 from "chalk";
|
|
|
18914
19032
|
import { Project as Project4 } from "ts-morph";
|
|
18915
19033
|
|
|
18916
19034
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
18917
|
-
import
|
|
19035
|
+
import fs26 from "fs";
|
|
18918
19036
|
import path39 from "path";
|
|
18919
19037
|
import { Project as Project3 } from "ts-morph";
|
|
18920
19038
|
function findTsConfig(sourcePath) {
|
|
18921
19039
|
const rootConfig = path39.resolve("tsconfig.json");
|
|
18922
|
-
if (!
|
|
19040
|
+
if (!fs26.existsSync(rootConfig)) return rootConfig;
|
|
18923
19041
|
const tried = /* @__PURE__ */ new Set();
|
|
18924
19042
|
const candidates = [rootConfig, ...readReferences(rootConfig)];
|
|
18925
19043
|
for (const candidate of candidates) {
|
|
@@ -18927,7 +19045,7 @@ function findTsConfig(sourcePath) {
|
|
|
18927
19045
|
tried.add(candidate);
|
|
18928
19046
|
if (projectIncludes(candidate, sourcePath)) return candidate;
|
|
18929
19047
|
}
|
|
18930
|
-
const siblings =
|
|
19048
|
+
const siblings = fs26.readdirSync(path39.dirname(rootConfig)).filter((f) => /^tsconfig.*\.json$/.test(f)).map((f) => path39.resolve(path39.dirname(rootConfig), f));
|
|
18931
19049
|
for (const sibling of siblings) {
|
|
18932
19050
|
if (tried.has(sibling)) continue;
|
|
18933
19051
|
tried.add(sibling);
|
|
@@ -18936,8 +19054,8 @@ function findTsConfig(sourcePath) {
|
|
|
18936
19054
|
return rootConfig;
|
|
18937
19055
|
}
|
|
18938
19056
|
function readReferences(configPath) {
|
|
18939
|
-
if (!
|
|
18940
|
-
const raw =
|
|
19057
|
+
if (!fs26.existsSync(configPath)) return [];
|
|
19058
|
+
const raw = fs26.readFileSync(configPath, "utf8");
|
|
18941
19059
|
const stripped = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
18942
19060
|
let parsed;
|
|
18943
19061
|
try {
|
|
@@ -18949,8 +19067,8 @@ function readReferences(configPath) {
|
|
|
18949
19067
|
const cwd = path39.dirname(configPath);
|
|
18950
19068
|
return parsed.references.map((ref) => {
|
|
18951
19069
|
const refPath = path39.resolve(cwd, ref.path);
|
|
18952
|
-
return
|
|
18953
|
-
}).filter((p) =>
|
|
19070
|
+
return fs26.statSync(refPath, { throwIfNoEntry: false })?.isDirectory() ? path39.join(refPath, "tsconfig.json") : refPath;
|
|
19071
|
+
}).filter((p) => fs26.existsSync(p));
|
|
18954
19072
|
}
|
|
18955
19073
|
function projectIncludes(configPath, sourcePath) {
|
|
18956
19074
|
try {
|
|
@@ -19000,25 +19118,25 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
19000
19118
|
}
|
|
19001
19119
|
|
|
19002
19120
|
// src/commands/refactor/ignore.ts
|
|
19003
|
-
import
|
|
19121
|
+
import fs27 from "fs";
|
|
19004
19122
|
import chalk172 from "chalk";
|
|
19005
19123
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
19006
19124
|
function ignore2(file) {
|
|
19007
|
-
if (!
|
|
19125
|
+
if (!fs27.existsSync(file)) {
|
|
19008
19126
|
console.error(chalk172.red(`Error: File does not exist: ${file}`));
|
|
19009
19127
|
process.exit(1);
|
|
19010
19128
|
}
|
|
19011
|
-
const content =
|
|
19129
|
+
const content = fs27.readFileSync(file, "utf8");
|
|
19012
19130
|
const lineCount = content.split("\n").length;
|
|
19013
19131
|
const maxLines = lineCount + 10;
|
|
19014
19132
|
const entry = `- file: ${file}
|
|
19015
19133
|
maxLines: ${maxLines}
|
|
19016
19134
|
`;
|
|
19017
|
-
if (
|
|
19018
|
-
const existing =
|
|
19019
|
-
|
|
19135
|
+
if (fs27.existsSync(REFACTOR_YML_PATH2)) {
|
|
19136
|
+
const existing = fs27.readFileSync(REFACTOR_YML_PATH2, "utf8");
|
|
19137
|
+
fs27.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
|
|
19020
19138
|
} else {
|
|
19021
|
-
|
|
19139
|
+
fs27.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
19022
19140
|
}
|
|
19023
19141
|
console.log(
|
|
19024
19142
|
chalk172.green(
|
|
@@ -19028,12 +19146,12 @@ function ignore2(file) {
|
|
|
19028
19146
|
}
|
|
19029
19147
|
|
|
19030
19148
|
// src/commands/refactor/rename/index.ts
|
|
19031
|
-
import
|
|
19149
|
+
import fs30 from "fs";
|
|
19032
19150
|
import path46 from "path";
|
|
19033
19151
|
import chalk175 from "chalk";
|
|
19034
19152
|
|
|
19035
19153
|
// src/commands/refactor/rename/applyRename.ts
|
|
19036
|
-
import
|
|
19154
|
+
import fs29 from "fs";
|
|
19037
19155
|
import path43 from "path";
|
|
19038
19156
|
import chalk173 from "chalk";
|
|
19039
19157
|
|
|
@@ -19041,7 +19159,7 @@ import chalk173 from "chalk";
|
|
|
19041
19159
|
import path42 from "path";
|
|
19042
19160
|
|
|
19043
19161
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
19044
|
-
import
|
|
19162
|
+
import fs28 from "fs";
|
|
19045
19163
|
function getOrCreateList(map, key) {
|
|
19046
19164
|
const list5 = map.get(key) ?? [];
|
|
19047
19165
|
if (!map.has(key)) map.set(key, list5);
|
|
@@ -19060,7 +19178,7 @@ function rewriteSpecifier(content, oldSpecifier, newSpecifier) {
|
|
|
19060
19178
|
return content.replace(pattern2, `$1${newSpecifier}$2`);
|
|
19061
19179
|
}
|
|
19062
19180
|
function applyFileRewrites(file, fileRewrites) {
|
|
19063
|
-
let content =
|
|
19181
|
+
let content = fs28.readFileSync(file, "utf8");
|
|
19064
19182
|
for (const { oldSpecifier, newSpecifier } of fileRewrites) {
|
|
19065
19183
|
content = rewriteSpecifier(content, oldSpecifier, newSpecifier);
|
|
19066
19184
|
}
|
|
@@ -19139,12 +19257,12 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
19139
19257
|
function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
19140
19258
|
const updatedContents = applyRewrites(rewrites);
|
|
19141
19259
|
for (const [file, content] of updatedContents) {
|
|
19142
|
-
|
|
19260
|
+
fs29.writeFileSync(file, content, "utf8");
|
|
19143
19261
|
console.log(chalk173.cyan(` Updated imports in ${path43.relative(cwd, file)}`));
|
|
19144
19262
|
}
|
|
19145
19263
|
const destDir = path43.dirname(destPath);
|
|
19146
|
-
if (!
|
|
19147
|
-
|
|
19264
|
+
if (!fs29.existsSync(destDir)) fs29.mkdirSync(destDir, { recursive: true });
|
|
19265
|
+
fs29.renameSync(sourcePath, destPath);
|
|
19148
19266
|
console.log(
|
|
19149
19267
|
chalk173.white(
|
|
19150
19268
|
` Moved ${path43.relative(cwd, sourcePath)} \u2192 ${path43.relative(cwd, destPath)}`
|
|
@@ -19252,11 +19370,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
19252
19370
|
const cwd = process.cwd();
|
|
19253
19371
|
const relSource = path46.relative(cwd, sourcePath);
|
|
19254
19372
|
const relDest = path46.relative(cwd, destPath);
|
|
19255
|
-
if (!
|
|
19373
|
+
if (!fs30.existsSync(sourcePath)) {
|
|
19256
19374
|
console.log(chalk175.red(`File not found: ${source}`));
|
|
19257
19375
|
process.exit(1);
|
|
19258
19376
|
}
|
|
19259
|
-
if (destPath !== sourcePath &&
|
|
19377
|
+
if (destPath !== sourcePath && fs30.existsSync(destPath)) {
|
|
19260
19378
|
console.log(chalk175.red(`Destination already exists: ${destination}`));
|
|
19261
19379
|
process.exit(1);
|
|
19262
19380
|
}
|
|
@@ -19481,27 +19599,27 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
19481
19599
|
}
|
|
19482
19600
|
|
|
19483
19601
|
// src/commands/refactor/restructure/executePlan.ts
|
|
19484
|
-
import
|
|
19602
|
+
import fs31 from "fs";
|
|
19485
19603
|
import path51 from "path";
|
|
19486
19604
|
import chalk178 from "chalk";
|
|
19487
19605
|
function executePlan(plan2) {
|
|
19488
19606
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
19489
19607
|
for (const [file, content] of updatedContents) {
|
|
19490
|
-
|
|
19608
|
+
fs31.writeFileSync(file, content, "utf8");
|
|
19491
19609
|
console.log(
|
|
19492
19610
|
chalk178.cyan(` Rewrote imports in ${path51.relative(process.cwd(), file)}`)
|
|
19493
19611
|
);
|
|
19494
19612
|
}
|
|
19495
19613
|
for (const dir of plan2.newDirectories) {
|
|
19496
|
-
|
|
19614
|
+
fs31.mkdirSync(dir, { recursive: true });
|
|
19497
19615
|
console.log(chalk178.green(` Created ${path51.relative(process.cwd(), dir)}/`));
|
|
19498
19616
|
}
|
|
19499
19617
|
for (const move2 of plan2.moves) {
|
|
19500
19618
|
const targetDir = path51.dirname(move2.to);
|
|
19501
|
-
if (!
|
|
19502
|
-
|
|
19619
|
+
if (!fs31.existsSync(targetDir)) {
|
|
19620
|
+
fs31.mkdirSync(targetDir, { recursive: true });
|
|
19503
19621
|
}
|
|
19504
|
-
|
|
19622
|
+
fs31.renameSync(move2.from, move2.to);
|
|
19505
19623
|
console.log(
|
|
19506
19624
|
chalk178.white(
|
|
19507
19625
|
` Moved ${path51.relative(process.cwd(), move2.from)} \u2192 ${path51.relative(process.cwd(), move2.to)}`
|
|
@@ -19513,10 +19631,10 @@ function executePlan(plan2) {
|
|
|
19513
19631
|
function removeEmptyDirectories(dirs) {
|
|
19514
19632
|
const unique = [...new Set(dirs)];
|
|
19515
19633
|
for (const dir of unique) {
|
|
19516
|
-
if (!
|
|
19517
|
-
const entries =
|
|
19634
|
+
if (!fs31.existsSync(dir)) continue;
|
|
19635
|
+
const entries = fs31.readdirSync(dir);
|
|
19518
19636
|
if (entries.length === 0) {
|
|
19519
|
-
|
|
19637
|
+
fs31.rmdirSync(dir);
|
|
19520
19638
|
console.log(
|
|
19521
19639
|
chalk178.dim(
|
|
19522
19640
|
` Removed empty directory ${path51.relative(process.cwd(), dir)}`
|
|
@@ -19530,18 +19648,18 @@ function removeEmptyDirectories(dirs) {
|
|
|
19530
19648
|
import path53 from "path";
|
|
19531
19649
|
|
|
19532
19650
|
// src/commands/refactor/restructure/planFileMoves/shared.ts
|
|
19533
|
-
import
|
|
19651
|
+
import fs32 from "fs";
|
|
19534
19652
|
function emptyResult() {
|
|
19535
19653
|
return { moves: [], directories: [], warnings: [] };
|
|
19536
19654
|
}
|
|
19537
19655
|
function checkDirConflict(result, label2, dir) {
|
|
19538
|
-
if (!
|
|
19656
|
+
if (!fs32.existsSync(dir)) return false;
|
|
19539
19657
|
result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
|
|
19540
19658
|
return true;
|
|
19541
19659
|
}
|
|
19542
19660
|
|
|
19543
19661
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
19544
|
-
import
|
|
19662
|
+
import fs33 from "fs";
|
|
19545
19663
|
import path52 from "path";
|
|
19546
19664
|
function collectEntry(results, dir, entry) {
|
|
19547
19665
|
const full = path52.join(dir, entry.name);
|
|
@@ -19549,9 +19667,9 @@ function collectEntry(results, dir, entry) {
|
|
|
19549
19667
|
results.push(...items2);
|
|
19550
19668
|
}
|
|
19551
19669
|
function listFilesRecursive(dir) {
|
|
19552
|
-
if (!
|
|
19670
|
+
if (!fs33.existsSync(dir)) return [];
|
|
19553
19671
|
const results = [];
|
|
19554
|
-
for (const entry of
|
|
19672
|
+
for (const entry of fs33.readdirSync(dir, { withFileTypes: true })) {
|
|
19555
19673
|
collectEntry(results, dir, entry);
|
|
19556
19674
|
}
|
|
19557
19675
|
return results;
|
|
@@ -22471,9 +22589,9 @@ var checks = [
|
|
|
22471
22589
|
action: hardcodedColors
|
|
22472
22590
|
},
|
|
22473
22591
|
{
|
|
22474
|
-
name: "block-comments",
|
|
22592
|
+
name: "block-code-comments",
|
|
22475
22593
|
description: "Fail on any comment on a changed line, whether added or edited",
|
|
22476
|
-
action:
|
|
22594
|
+
action: blockCodeComments
|
|
22477
22595
|
},
|
|
22478
22596
|
{
|
|
22479
22597
|
name: "no-venv",
|
|
@@ -22505,9 +22623,9 @@ function registerVerifyChecks(verifyCommand) {
|
|
|
22505
22623
|
// src/commands/verify/verifyConfigHelp.ts
|
|
22506
22624
|
var verifyConfigHelp = [
|
|
22507
22625
|
{
|
|
22508
|
-
key: "
|
|
22509
|
-
setter: 'assist config set
|
|
22510
|
-
note: "globs exempt from the block-comments check"
|
|
22626
|
+
key: "blockCodeComments.ignore",
|
|
22627
|
+
setter: 'assist config set blockCodeComments.ignore "**/*.test.ts"',
|
|
22628
|
+
note: "globs exempt from the block-code-comments check"
|
|
22511
22629
|
},
|
|
22512
22630
|
{
|
|
22513
22631
|
key: "hardcodedColors.ignore",
|
|
@@ -24231,14 +24349,14 @@ function createAssistSession(id, assistArgs, cwd, meta) {
|
|
|
24231
24349
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
24232
24350
|
|
|
24233
24351
|
// src/commands/sessions/daemon/readDesignSystemPrompt.ts
|
|
24234
|
-
import * as
|
|
24352
|
+
import * as fs34 from "fs";
|
|
24235
24353
|
import * as path56 from "path";
|
|
24236
24354
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
24237
24355
|
var __filename4 = fileURLToPath8(import.meta.url);
|
|
24238
24356
|
var __dirname6 = path56.dirname(__filename4);
|
|
24239
24357
|
function readDesignSystemPrompt() {
|
|
24240
24358
|
const promptPath = path56.join(__dirname6, "..", "claude", "system-prompt.md");
|
|
24241
|
-
return
|
|
24359
|
+
return fs34.readFileSync(promptPath, "utf8");
|
|
24242
24360
|
}
|
|
24243
24361
|
|
|
24244
24362
|
// src/commands/sessions/daemon/spawnClaude.ts
|
|
@@ -24617,7 +24735,7 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
|
24617
24735
|
}
|
|
24618
24736
|
|
|
24619
24737
|
// src/commands/sessions/shared/transcriptUsage.ts
|
|
24620
|
-
import * as
|
|
24738
|
+
import * as fs35 from "fs";
|
|
24621
24739
|
function transcriptUsage(lines) {
|
|
24622
24740
|
const byId = /* @__PURE__ */ new Map();
|
|
24623
24741
|
for (const line of lines) {
|
|
@@ -24641,7 +24759,7 @@ function transcriptUsage(lines) {
|
|
|
24641
24759
|
return [...byId.values()];
|
|
24642
24760
|
}
|
|
24643
24761
|
async function readTranscriptUsage(transcriptPath) {
|
|
24644
|
-
const content = await
|
|
24762
|
+
const content = await fs35.promises.readFile(transcriptPath, "utf8");
|
|
24645
24763
|
return transcriptUsage(content.split("\n"));
|
|
24646
24764
|
}
|
|
24647
24765
|
|
|
@@ -26099,7 +26217,7 @@ import * as net3 from "net";
|
|
|
26099
26217
|
import { createInterface as createInterface9 } from "readline";
|
|
26100
26218
|
|
|
26101
26219
|
// src/commands/sessions/shared/parseTranscript.ts
|
|
26102
|
-
import * as
|
|
26220
|
+
import * as fs36 from "fs";
|
|
26103
26221
|
|
|
26104
26222
|
// src/commands/sessions/shared/toolTarget.ts
|
|
26105
26223
|
function toolTarget(input) {
|
|
@@ -26151,7 +26269,7 @@ async function parseTranscript(sessionId) {
|
|
|
26151
26269
|
const filePath = await findSessionJsonlPath(sessionId);
|
|
26152
26270
|
if (!filePath) return [];
|
|
26153
26271
|
try {
|
|
26154
|
-
const raw = await
|
|
26272
|
+
const raw = await fs36.promises.readFile(filePath, "utf8");
|
|
26155
26273
|
return parseTranscriptLines(raw.split("\n"));
|
|
26156
26274
|
} catch {
|
|
26157
26275
|
return [];
|
|
@@ -26484,13 +26602,13 @@ import * as fs38 from "fs";
|
|
|
26484
26602
|
import chalk196 from "chalk";
|
|
26485
26603
|
|
|
26486
26604
|
// src/commands/sessions/summarise/shared.ts
|
|
26487
|
-
import * as
|
|
26605
|
+
import * as fs37 from "fs";
|
|
26488
26606
|
function writeSummary(jsonlPath2, summary) {
|
|
26489
|
-
|
|
26607
|
+
fs37.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
26490
26608
|
`, "utf8");
|
|
26491
26609
|
}
|
|
26492
26610
|
function hasSummary(jsonlPath2) {
|
|
26493
|
-
return
|
|
26611
|
+
return fs37.existsSync(summaryPathFor(jsonlPath2));
|
|
26494
26612
|
}
|
|
26495
26613
|
function summaryPathFor(jsonlPath2) {
|
|
26496
26614
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -26499,56 +26617,6 @@ function summaryPathFor(jsonlPath2) {
|
|
|
26499
26617
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
26500
26618
|
import { execFileSync as execFileSync12 } from "child_process";
|
|
26501
26619
|
|
|
26502
|
-
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
26503
|
-
import * as fs37 from "fs";
|
|
26504
|
-
|
|
26505
|
-
// src/commands/sessions/summarise/parseUserLine.ts
|
|
26506
|
-
function parseUserLine(line) {
|
|
26507
|
-
let entry;
|
|
26508
|
-
try {
|
|
26509
|
-
entry = JSON.parse(line);
|
|
26510
|
-
} catch {
|
|
26511
|
-
return void 0;
|
|
26512
|
-
}
|
|
26513
|
-
if (entry.type !== "user") return void 0;
|
|
26514
|
-
const msg = entry.message;
|
|
26515
|
-
const c = msg?.content;
|
|
26516
|
-
let text17;
|
|
26517
|
-
if (typeof c === "string") {
|
|
26518
|
-
text17 = c;
|
|
26519
|
-
} else if (Array.isArray(c)) {
|
|
26520
|
-
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
26521
|
-
text17 = collected || void 0;
|
|
26522
|
-
}
|
|
26523
|
-
if (!text17) return void 0;
|
|
26524
|
-
return {
|
|
26525
|
-
text: text17,
|
|
26526
|
-
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
26527
|
-
};
|
|
26528
|
-
}
|
|
26529
|
-
|
|
26530
|
-
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
26531
|
-
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
26532
|
-
let content;
|
|
26533
|
-
try {
|
|
26534
|
-
const fd = fs37.openSync(filePath, "r");
|
|
26535
|
-
try {
|
|
26536
|
-
const buf = Buffer.alloc(maxBytes);
|
|
26537
|
-
const bytesRead = fs37.readSync(fd, buf, 0, buf.length, 0);
|
|
26538
|
-
content = buf.toString("utf8", 0, bytesRead);
|
|
26539
|
-
} finally {
|
|
26540
|
-
fs37.closeSync(fd);
|
|
26541
|
-
}
|
|
26542
|
-
} catch {
|
|
26543
|
-
return;
|
|
26544
|
-
}
|
|
26545
|
-
for (const line of content.split("\n")) {
|
|
26546
|
-
if (!line) continue;
|
|
26547
|
-
const entry = parseUserLine(line);
|
|
26548
|
-
if (entry) yield entry.text;
|
|
26549
|
-
}
|
|
26550
|
-
}
|
|
26551
|
-
|
|
26552
26620
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
26553
26621
|
function extractFirstUserMessage(filePath) {
|
|
26554
26622
|
for (const text17 of iterateUserMessages(filePath)) {
|
|
@@ -26562,36 +26630,6 @@ function truncate3(text17, maxChars = 500) {
|
|
|
26562
26630
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
26563
26631
|
}
|
|
26564
26632
|
|
|
26565
|
-
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
26566
|
-
function scanSessionBacklogRefs(filePath) {
|
|
26567
|
-
const ids = /* @__PURE__ */ new Set();
|
|
26568
|
-
for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
26569
|
-
for (const id of extractBacklogIds(text17)) {
|
|
26570
|
-
ids.add(id);
|
|
26571
|
-
}
|
|
26572
|
-
}
|
|
26573
|
-
return [...ids].sort((a, b) => a - b);
|
|
26574
|
-
}
|
|
26575
|
-
function extractBacklogIds(text17) {
|
|
26576
|
-
const ids = [];
|
|
26577
|
-
for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
|
|
26578
|
-
ids.push(Number.parseInt(m[1], 10));
|
|
26579
|
-
}
|
|
26580
|
-
for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
|
|
26581
|
-
ids.push(Number.parseInt(m[1], 10));
|
|
26582
|
-
}
|
|
26583
|
-
for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
|
|
26584
|
-
ids.push(Number.parseInt(m[1], 10));
|
|
26585
|
-
}
|
|
26586
|
-
for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
|
|
26587
|
-
ids.push(Number.parseInt(m[1], 10));
|
|
26588
|
-
}
|
|
26589
|
-
for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
26590
|
-
ids.push(Number.parseInt(m[1], 10));
|
|
26591
|
-
}
|
|
26592
|
-
return ids;
|
|
26593
|
-
}
|
|
26594
|
-
|
|
26595
26633
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
26596
26634
|
function summariseSession(jsonlPath2) {
|
|
26597
26635
|
const firstMessage = extractFirstUserMessage(jsonlPath2);
|