@staff0rd/assist 0.658.0 → 0.659.1
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 +3 -2
- package/dist/commands/sessions/web/bundle.js +391 -391
- package/dist/index.js +229 -157
- 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.659.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -561,6 +561,23 @@ function stripLegacyConfigKeys(config) {
|
|
|
561
561
|
// src/shared/types.ts
|
|
562
562
|
import { z as z3 } from "zod";
|
|
563
563
|
|
|
564
|
+
// src/shared/adviceFragmentNames.ts
|
|
565
|
+
var adviceFragmentNames = [
|
|
566
|
+
"assist-global",
|
|
567
|
+
"backlog-ids",
|
|
568
|
+
"backlog-prs",
|
|
569
|
+
"code-comments",
|
|
570
|
+
"drafting-messages",
|
|
571
|
+
"editing-files",
|
|
572
|
+
"filename-convention",
|
|
573
|
+
"jira-context",
|
|
574
|
+
"jira-smart-links",
|
|
575
|
+
"markdown",
|
|
576
|
+
"refactor",
|
|
577
|
+
"settings-json",
|
|
578
|
+
"verify"
|
|
579
|
+
];
|
|
580
|
+
|
|
564
581
|
// src/shared/runConfigSchema.ts
|
|
565
582
|
import { z } from "zod";
|
|
566
583
|
var runParamSchema = z.strictObject({
|
|
@@ -619,8 +636,8 @@ var DEFAULT_BACKUP_DIR = "~/.assist/backups";
|
|
|
619
636
|
var DEFAULT_CLONE_DIR = "~/git";
|
|
620
637
|
var assistConfigShape = {
|
|
621
638
|
advice: z3.strictObject({
|
|
622
|
-
include: z3.array(z3.
|
|
623
|
-
exclude: z3.array(z3.
|
|
639
|
+
include: z3.array(z3.enum(adviceFragmentNames)).default([]),
|
|
640
|
+
exclude: z3.array(z3.enum(adviceFragmentNames)).default([]),
|
|
624
641
|
extra: z3.string().optional(),
|
|
625
642
|
verify: z3.string().optional()
|
|
626
643
|
}).optional(),
|
|
@@ -2013,7 +2030,96 @@ function lint(options2 = {}) {
|
|
|
2013
2030
|
|
|
2014
2031
|
// src/commands/new/registerNew/newCli/index.ts
|
|
2015
2032
|
import { execSync as execSync12 } from "child_process";
|
|
2016
|
-
import { basename as
|
|
2033
|
+
import { basename as basename4, resolve as resolve6 } from "path";
|
|
2034
|
+
|
|
2035
|
+
// src/commands/advise/loadAdviceFragments.ts
|
|
2036
|
+
import { readdirSync, readFileSync as readFileSync10 } from "fs";
|
|
2037
|
+
import { basename as basename2, join as join10 } from "path";
|
|
2038
|
+
|
|
2039
|
+
// src/commands/advise/adviceDir.ts
|
|
2040
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2041
|
+
import { dirname as dirname10, join as join9 } from "path";
|
|
2042
|
+
import { fileURLToPath } from "url";
|
|
2043
|
+
function adviceDir() {
|
|
2044
|
+
let current = dirname10(fileURLToPath(import.meta.url));
|
|
2045
|
+
while (current !== dirname10(current)) {
|
|
2046
|
+
const candidate = join9(current, "claude", "advice");
|
|
2047
|
+
if (existsSync13(candidate)) return candidate;
|
|
2048
|
+
current = dirname10(current);
|
|
2049
|
+
}
|
|
2050
|
+
throw new Error("Could not locate the shipped claude/advice directory");
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
// src/commands/advise/parseAdviceFragment.ts
|
|
2054
|
+
import { parse as parseYaml2 } from "yaml";
|
|
2055
|
+
var frontmatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
2056
|
+
function parseAdviceFragment(name, content) {
|
|
2057
|
+
const match = frontmatter.exec(content);
|
|
2058
|
+
if (!match) throw new Error(`Advice fragment ${name} has no frontmatter`);
|
|
2059
|
+
const meta = parseYaml2(match[1]) ?? {};
|
|
2060
|
+
const title = meta.title;
|
|
2061
|
+
const when = meta.when;
|
|
2062
|
+
if (typeof title !== "string" || typeof when !== "string")
|
|
2063
|
+
throw new Error(
|
|
2064
|
+
`Advice fragment ${name} needs a title and a when condition`
|
|
2065
|
+
);
|
|
2066
|
+
return {
|
|
2067
|
+
name,
|
|
2068
|
+
title,
|
|
2069
|
+
when,
|
|
2070
|
+
body: content.slice(match[0].length).trim()
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
// src/commands/advise/loadAdviceFragments.ts
|
|
2075
|
+
function loadAdviceFragments(dir = adviceDir()) {
|
|
2076
|
+
return readdirSync(dir).filter((file) => file.endsWith(".md")).sort().map(
|
|
2077
|
+
(file) => parseAdviceFragment(
|
|
2078
|
+
basename2(file, ".md"),
|
|
2079
|
+
readFileSync10(join10(dir, file), "utf8")
|
|
2080
|
+
)
|
|
2081
|
+
);
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
// src/commands/verify/reportVerifyProblems.ts
|
|
2085
|
+
function verifySection(label2, entries) {
|
|
2086
|
+
if (entries.length === 0) return void 0;
|
|
2087
|
+
const list5 = entries.sort().map((entry) => ` ${entry}`).join("\n");
|
|
2088
|
+
return `${label2}:
|
|
2089
|
+
${list5}`;
|
|
2090
|
+
}
|
|
2091
|
+
function reportVerifyProblems(problems, success) {
|
|
2092
|
+
const found = problems.filter(
|
|
2093
|
+
(problem) => problem !== void 0
|
|
2094
|
+
);
|
|
2095
|
+
if (found.length > 0) {
|
|
2096
|
+
console.log(found.join("\n\n"));
|
|
2097
|
+
process.exit(1);
|
|
2098
|
+
}
|
|
2099
|
+
console.log(success);
|
|
2100
|
+
process.exit(0);
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
// src/commands/verify/adviceFragments.ts
|
|
2104
|
+
function adviceFragments() {
|
|
2105
|
+
const shipped = new Set(
|
|
2106
|
+
loadAdviceFragments().map((fragment) => fragment.name)
|
|
2107
|
+
);
|
|
2108
|
+
const declared = new Set(adviceFragmentNames);
|
|
2109
|
+
reportVerifyProblems(
|
|
2110
|
+
[
|
|
2111
|
+
verifySection(
|
|
2112
|
+
"Shipped in claude/advice but missing from adviceFragmentNames (add them, or advice.include/exclude cannot name them)",
|
|
2113
|
+
[...shipped].filter((name) => !declared.has(name))
|
|
2114
|
+
),
|
|
2115
|
+
verifySection(
|
|
2116
|
+
"Listed in adviceFragmentNames but no longer shipped in claude/advice (remove them)",
|
|
2117
|
+
[...declared].filter((name) => !shipped.has(name))
|
|
2118
|
+
)
|
|
2119
|
+
],
|
|
2120
|
+
`All ${shipped.size} advice fragments are named in adviceFragmentNames.`
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2017
2123
|
|
|
2018
2124
|
// src/commands/verify/blockCodeComments/findComments.ts
|
|
2019
2125
|
import { execSync as execSync4 } from "child_process";
|
|
@@ -2960,12 +3066,12 @@ var adviceConfigHelp = [
|
|
|
2960
3066
|
{
|
|
2961
3067
|
key: "advice.include",
|
|
2962
3068
|
setter: 'assist config set advice.include "refactor"',
|
|
2963
|
-
note: "fragment names included whatever their condition says"
|
|
3069
|
+
note: "fragment names included whatever their condition says; 'assist advise --explain' lists every name"
|
|
2964
3070
|
},
|
|
2965
3071
|
{
|
|
2966
3072
|
key: "advice.exclude",
|
|
2967
3073
|
setter: 'assist config set advice.exclude "jira-context"',
|
|
2968
|
-
note: "fragment names dropped even when their condition matches"
|
|
3074
|
+
note: "fragment names dropped even when their condition matches; 'assist advise --explain' lists every name"
|
|
2969
3075
|
},
|
|
2970
3076
|
{
|
|
2971
3077
|
key: "advice.extra",
|
|
@@ -3573,57 +3679,46 @@ var pendingConfigDocumentation = /* @__PURE__ */ new Set([
|
|
|
3573
3679
|
]);
|
|
3574
3680
|
|
|
3575
3681
|
// src/commands/verify/configKeys.ts
|
|
3576
|
-
function section(label2, keys) {
|
|
3577
|
-
if (keys.length === 0) return void 0;
|
|
3578
|
-
const list5 = keys.sort().map((key) => ` ${key}`).join("\n");
|
|
3579
|
-
return `${label2}:
|
|
3580
|
-
${list5}`;
|
|
3581
|
-
}
|
|
3582
3682
|
function configKeys() {
|
|
3583
3683
|
const schemaKeys = new Set(enumerateConfigLeafKeys(assistConfigSchema));
|
|
3584
3684
|
const documented = getDocumentedConfigKeys();
|
|
3585
3685
|
const pending = pendingConfigDocumentation;
|
|
3586
3686
|
const aggregated = new Set(configHelpEntries.map((entry) => entry.key));
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3687
|
+
reportVerifyProblems(
|
|
3688
|
+
[
|
|
3689
|
+
verifySection(
|
|
3690
|
+
"Config keys documented by no command (surface them with configHelp)",
|
|
3691
|
+
[...schemaKeys].filter(
|
|
3692
|
+
(key) => !documented.has(key) && !pending.has(key)
|
|
3693
|
+
)
|
|
3694
|
+
),
|
|
3695
|
+
verifySection(
|
|
3696
|
+
"Documented config keys not present in assistConfigSchema",
|
|
3697
|
+
[...documented].filter((key) => !schemaKeys.has(key))
|
|
3698
|
+
),
|
|
3699
|
+
verifySection(
|
|
3700
|
+
"Keys now documented but still in pendingConfigDocumentation (remove them)",
|
|
3701
|
+
[...pending].filter((key) => documented.has(key))
|
|
3702
|
+
),
|
|
3703
|
+
verifySection(
|
|
3704
|
+
"pendingConfigDocumentation lists keys not in assistConfigSchema (remove them)",
|
|
3705
|
+
[...pending].filter((key) => !schemaKeys.has(key))
|
|
3706
|
+
),
|
|
3707
|
+
verifySection(
|
|
3708
|
+
"Keys documented by a command but missing from configHelpEntries (add their module to src/commands/configHelpEntries.ts)",
|
|
3709
|
+
[...documented].filter((key) => !aggregated.has(key))
|
|
3710
|
+
),
|
|
3711
|
+
verifySection(
|
|
3712
|
+
"configHelpEntries lists keys no command documents (remove them)",
|
|
3713
|
+
[...aggregated].filter((key) => !documented.has(key))
|
|
3592
3714
|
)
|
|
3593
|
-
|
|
3594
|
-
section(
|
|
3595
|
-
"Documented config keys not present in assistConfigSchema",
|
|
3596
|
-
[...documented].filter((key) => !schemaKeys.has(key))
|
|
3597
|
-
),
|
|
3598
|
-
section(
|
|
3599
|
-
"Keys now documented but still in pendingConfigDocumentation (remove them)",
|
|
3600
|
-
[...pending].filter((key) => documented.has(key))
|
|
3601
|
-
),
|
|
3602
|
-
section(
|
|
3603
|
-
"pendingConfigDocumentation lists keys not in assistConfigSchema (remove them)",
|
|
3604
|
-
[...pending].filter((key) => !schemaKeys.has(key))
|
|
3605
|
-
),
|
|
3606
|
-
section(
|
|
3607
|
-
"Keys documented by a command but missing from configHelpEntries (add their module to src/commands/configHelpEntries.ts)",
|
|
3608
|
-
[...documented].filter((key) => !aggregated.has(key))
|
|
3609
|
-
),
|
|
3610
|
-
section(
|
|
3611
|
-
"configHelpEntries lists keys no command documents (remove them)",
|
|
3612
|
-
[...aggregated].filter((key) => !documented.has(key))
|
|
3613
|
-
)
|
|
3614
|
-
].filter((problem) => problem !== void 0);
|
|
3615
|
-
if (problems.length > 0) {
|
|
3616
|
-
console.log(problems.join("\n\n"));
|
|
3617
|
-
process.exit(1);
|
|
3618
|
-
}
|
|
3619
|
-
console.log(
|
|
3715
|
+
],
|
|
3620
3716
|
`All ${schemaKeys.size} config keys are surfaced in --help or pending documentation.`
|
|
3621
3717
|
);
|
|
3622
|
-
process.exit(0);
|
|
3623
3718
|
}
|
|
3624
3719
|
|
|
3625
3720
|
// src/commands/verify/forbiddenStrings/index.ts
|
|
3626
|
-
import { existsSync as
|
|
3721
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
|
|
3627
3722
|
|
|
3628
3723
|
// src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
|
|
3629
3724
|
import { minimatch as minimatch2 } from "minimatch";
|
|
@@ -3664,13 +3759,13 @@ function forbiddenStrings() {
|
|
|
3664
3759
|
const cache5 = /* @__PURE__ */ new Map();
|
|
3665
3760
|
const readJson = (file) => {
|
|
3666
3761
|
if (cache5.has(file)) return cache5.get(file);
|
|
3667
|
-
if (!
|
|
3762
|
+
if (!existsSync14(file)) {
|
|
3668
3763
|
console.log(`Forbidden-strings file not found: ${file}`);
|
|
3669
3764
|
process.exit(1);
|
|
3670
3765
|
}
|
|
3671
3766
|
let parsed;
|
|
3672
3767
|
try {
|
|
3673
|
-
parsed = JSON.parse(
|
|
3768
|
+
parsed = JSON.parse(readFileSync11(file, "utf8"));
|
|
3674
3769
|
} catch (error) {
|
|
3675
3770
|
console.log(`Could not parse ${file}: ${error.message}`);
|
|
3676
3771
|
process.exit(1);
|
|
@@ -3743,7 +3838,7 @@ Total: ${lines2.length} hardcoded color(s)`);
|
|
|
3743
3838
|
import * as path20 from "path";
|
|
3744
3839
|
|
|
3745
3840
|
// src/shared/resolveRunConfigs.ts
|
|
3746
|
-
import { dirname as
|
|
3841
|
+
import { dirname as dirname11, relative, resolve as resolve4 } from "path";
|
|
3747
3842
|
|
|
3748
3843
|
// src/shared/assertNoDuplicateRunNames.ts
|
|
3749
3844
|
function findDuplicateNames(configs) {
|
|
@@ -3765,14 +3860,14 @@ function assertNoDuplicateRunNames(configs) {
|
|
|
3765
3860
|
}
|
|
3766
3861
|
|
|
3767
3862
|
// src/shared/findLinkedConfigPath.ts
|
|
3768
|
-
import { existsSync as
|
|
3769
|
-
import { join as
|
|
3863
|
+
import { existsSync as existsSync15 } from "fs";
|
|
3864
|
+
import { join as join11, resolve as resolve2 } from "path";
|
|
3770
3865
|
function findLinkedConfigPath(linkPath, fromDir) {
|
|
3771
3866
|
const resolved = resolve2(fromDir, linkPath);
|
|
3772
|
-
const claudePath =
|
|
3773
|
-
if (
|
|
3774
|
-
const rootPath =
|
|
3775
|
-
if (
|
|
3867
|
+
const claudePath = join11(resolved, ".claude", "assist.yml");
|
|
3868
|
+
if (existsSync15(claudePath)) return claudePath;
|
|
3869
|
+
const rootPath = join11(resolved, "assist.yml");
|
|
3870
|
+
if (existsSync15(rootPath)) return rootPath;
|
|
3776
3871
|
throw new Error(`No assist.yml found in linked project: ${resolved}`);
|
|
3777
3872
|
}
|
|
3778
3873
|
|
|
@@ -3814,7 +3909,7 @@ function loadAndResolveLink(linkPath, configDir, ctx) {
|
|
|
3814
3909
|
const entries = loadLinkedEntries(configPath, ctx.visited);
|
|
3815
3910
|
const defaultCwd = relativeToRoot(ctx, resolve4(configDir, linkPath));
|
|
3816
3911
|
return setDefaultCwd(
|
|
3817
|
-
resolveRecursive(entries,
|
|
3912
|
+
resolveRecursive(entries, dirname11(configPath), ctx),
|
|
3818
3913
|
defaultCwd
|
|
3819
3914
|
);
|
|
3820
3915
|
}
|
|
@@ -3841,12 +3936,12 @@ function resolveLocalCwd(config, configDir, ctx) {
|
|
|
3841
3936
|
}
|
|
3842
3937
|
|
|
3843
3938
|
// src/shared/findRepoRoot.ts
|
|
3844
|
-
import { existsSync as
|
|
3939
|
+
import { existsSync as existsSync16 } from "fs";
|
|
3845
3940
|
import path19 from "path";
|
|
3846
3941
|
function findRepoRoot(dir) {
|
|
3847
3942
|
let current = dir;
|
|
3848
3943
|
while (current !== path19.dirname(current)) {
|
|
3849
|
-
if (
|
|
3944
|
+
if (existsSync16(path19.join(current, ".git"))) {
|
|
3850
3945
|
return current;
|
|
3851
3946
|
}
|
|
3852
3947
|
current = path19.dirname(current);
|
|
@@ -3917,9 +4012,9 @@ function list() {
|
|
|
3917
4012
|
}
|
|
3918
4013
|
|
|
3919
4014
|
// src/commands/verify/migrations/index.ts
|
|
3920
|
-
import { readFileSync as
|
|
4015
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
3921
4016
|
import path21 from "path";
|
|
3922
|
-
import { fileURLToPath } from "url";
|
|
4017
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3923
4018
|
|
|
3924
4019
|
// src/shared/db/migrations/migration0001Baseline.ts
|
|
3925
4020
|
var sql = `
|
|
@@ -4267,15 +4362,15 @@ function checkSequential(migrations3, files) {
|
|
|
4267
4362
|
}
|
|
4268
4363
|
|
|
4269
4364
|
// src/commands/verify/migrations/listMigrationFiles.ts
|
|
4270
|
-
import { readdirSync } from "fs";
|
|
4365
|
+
import { readdirSync as readdirSync2 } from "fs";
|
|
4271
4366
|
var MIGRATION_FILE2 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
4272
4367
|
function listMigrationFiles(dir) {
|
|
4273
|
-
return
|
|
4368
|
+
return readdirSync2(dir).filter((file) => MIGRATION_FILE2.test(file));
|
|
4274
4369
|
}
|
|
4275
4370
|
|
|
4276
4371
|
// src/commands/verify/migrations/readBaselineMigrations.ts
|
|
4277
4372
|
import { execSync as execSync6 } from "child_process";
|
|
4278
|
-
import { basename as
|
|
4373
|
+
import { basename as basename3 } from "path";
|
|
4279
4374
|
var MIGRATION_FILE3 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
4280
4375
|
function readBaselineMigrations(repoRelativeDir, ref) {
|
|
4281
4376
|
const baseline = /* @__PURE__ */ new Map();
|
|
@@ -4288,7 +4383,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4288
4383
|
} catch {
|
|
4289
4384
|
return baseline;
|
|
4290
4385
|
}
|
|
4291
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path91) => MIGRATION_FILE3.test(
|
|
4386
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path91) => MIGRATION_FILE3.test(basename3(path91)));
|
|
4292
4387
|
for (const path91 of paths) {
|
|
4293
4388
|
try {
|
|
4294
4389
|
const content = execSync6(`git show "${ref}:${path91}"`, {
|
|
@@ -4296,7 +4391,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4296
4391
|
maxBuffer: 16 * 1024 * 1024,
|
|
4297
4392
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4298
4393
|
});
|
|
4299
|
-
baseline.set(
|
|
4394
|
+
baseline.set(basename3(path91), content);
|
|
4300
4395
|
} catch {
|
|
4301
4396
|
}
|
|
4302
4397
|
}
|
|
@@ -4338,7 +4433,7 @@ function resolveBaselineRef() {
|
|
|
4338
4433
|
var REPO_RELATIVE_DIR = "src/shared/db/migrations";
|
|
4339
4434
|
function migrationsDir() {
|
|
4340
4435
|
return path21.resolve(
|
|
4341
|
-
path21.dirname(
|
|
4436
|
+
path21.dirname(fileURLToPath2(import.meta.url)),
|
|
4342
4437
|
"../../../shared/db/migrations"
|
|
4343
4438
|
);
|
|
4344
4439
|
}
|
|
@@ -4356,7 +4451,7 @@ function migrations2() {
|
|
|
4356
4451
|
if (ref) {
|
|
4357
4452
|
const baseline = readBaselineMigrations(REPO_RELATIVE_DIR, ref);
|
|
4358
4453
|
const current = new Map(
|
|
4359
|
-
files.map((file) => [file,
|
|
4454
|
+
files.map((file) => [file, readFileSync12(path21.join(dir, file), "utf8")])
|
|
4360
4455
|
);
|
|
4361
4456
|
for (const finding of checkAppendOnly(baseline, current)) {
|
|
4362
4457
|
problems.push(
|
|
@@ -4415,15 +4510,15 @@ import * as net from "net";
|
|
|
4415
4510
|
|
|
4416
4511
|
// src/commands/sessions/daemon/daemonPaths.ts
|
|
4417
4512
|
import { homedir as homedir2 } from "os";
|
|
4418
|
-
import { join as
|
|
4419
|
-
var DAEMON_DIR =
|
|
4513
|
+
import { join as join12 } from "path";
|
|
4514
|
+
var DAEMON_DIR = join12(homedir2(), ".assist", "daemon");
|
|
4420
4515
|
var daemonPaths = {
|
|
4421
4516
|
dir: DAEMON_DIR,
|
|
4422
|
-
socket: process.platform === "win32" ? String.raw`\\.\pipe\assist-sessions-daemon` :
|
|
4423
|
-
log:
|
|
4424
|
-
pid:
|
|
4425
|
-
spawnLock:
|
|
4426
|
-
hooksSettings:
|
|
4517
|
+
socket: process.platform === "win32" ? String.raw`\\.\pipe\assist-sessions-daemon` : join12(DAEMON_DIR, "daemon.sock"),
|
|
4518
|
+
log: join12(DAEMON_DIR, "daemon.log"),
|
|
4519
|
+
pid: join12(DAEMON_DIR, "daemon.pid"),
|
|
4520
|
+
spawnLock: join12(DAEMON_DIR, "spawn.lock"),
|
|
4521
|
+
hooksSettings: join12(DAEMON_DIR, "hooks-settings.json")
|
|
4427
4522
|
};
|
|
4428
4523
|
|
|
4429
4524
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
@@ -4731,7 +4826,7 @@ program.parse();
|
|
|
4731
4826
|
|
|
4732
4827
|
// src/commands/new/registerNew/newCli/index.ts
|
|
4733
4828
|
async function newCli() {
|
|
4734
|
-
const name =
|
|
4829
|
+
const name = basename4(resolve6("."));
|
|
4735
4830
|
initGit();
|
|
4736
4831
|
initPackageJson(name);
|
|
4737
4832
|
console.log("Installing dependencies...");
|
|
@@ -4746,7 +4841,7 @@ async function newCli() {
|
|
|
4746
4841
|
|
|
4747
4842
|
// src/commands/new/registerNew/newProject.ts
|
|
4748
4843
|
import { execSync as execSync14 } from "child_process";
|
|
4749
|
-
import { existsSync as
|
|
4844
|
+
import { existsSync as existsSync18, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
|
|
4750
4845
|
|
|
4751
4846
|
// src/commands/deploy/init/index.ts
|
|
4752
4847
|
import { execSync as execSync13 } from "child_process";
|
|
@@ -4754,33 +4849,33 @@ import chalk27 from "chalk";
|
|
|
4754
4849
|
import enquirer3 from "enquirer";
|
|
4755
4850
|
|
|
4756
4851
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
4757
|
-
import { existsSync as
|
|
4758
|
-
import { dirname as
|
|
4759
|
-
import { fileURLToPath as
|
|
4852
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync3, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
4853
|
+
import { dirname as dirname13, join as join13 } from "path";
|
|
4854
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4760
4855
|
import chalk26 from "chalk";
|
|
4761
4856
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
4762
|
-
var __dirname2 =
|
|
4857
|
+
var __dirname2 = dirname13(fileURLToPath3(import.meta.url));
|
|
4763
4858
|
function getExistingSiteId() {
|
|
4764
|
-
if (!
|
|
4859
|
+
if (!existsSync17(WORKFLOW_PATH)) {
|
|
4765
4860
|
return null;
|
|
4766
4861
|
}
|
|
4767
|
-
const content =
|
|
4862
|
+
const content = readFileSync13(WORKFLOW_PATH, "utf8");
|
|
4768
4863
|
const match = content.match(/-s\s+([a-f0-9-]{36})/);
|
|
4769
4864
|
return match ? match[1] : null;
|
|
4770
4865
|
}
|
|
4771
4866
|
function getTemplateContent(siteId) {
|
|
4772
|
-
const templatePath =
|
|
4773
|
-
const template =
|
|
4867
|
+
const templatePath = join13(__dirname2, "commands/deploy/build.yml");
|
|
4868
|
+
const template = readFileSync13(templatePath, "utf8");
|
|
4774
4869
|
return template.replace("{{NETLIFY_SITE_ID}}", siteId);
|
|
4775
4870
|
}
|
|
4776
4871
|
async function updateWorkflow(siteId) {
|
|
4777
4872
|
const newContent = getTemplateContent(siteId);
|
|
4778
4873
|
const workflowDir = ".github/workflows";
|
|
4779
|
-
if (!
|
|
4874
|
+
if (!existsSync17(workflowDir)) {
|
|
4780
4875
|
mkdirSync3(workflowDir, { recursive: true });
|
|
4781
4876
|
}
|
|
4782
|
-
if (
|
|
4783
|
-
const oldContent =
|
|
4877
|
+
if (existsSync17(WORKFLOW_PATH)) {
|
|
4878
|
+
const oldContent = readFileSync13(WORKFLOW_PATH, "utf8");
|
|
4784
4879
|
if (oldContent === newContent) {
|
|
4785
4880
|
console.log(chalk26.green("build.yml is already up to date"));
|
|
4786
4881
|
return;
|
|
@@ -4874,11 +4969,11 @@ async function newProject() {
|
|
|
4874
4969
|
}
|
|
4875
4970
|
function addViteBaseConfig() {
|
|
4876
4971
|
const viteConfigPath = "vite.config.ts";
|
|
4877
|
-
if (!
|
|
4972
|
+
if (!existsSync18(viteConfigPath)) {
|
|
4878
4973
|
console.log("No vite.config.ts found, skipping base config");
|
|
4879
4974
|
return;
|
|
4880
4975
|
}
|
|
4881
|
-
const content =
|
|
4976
|
+
const content = readFileSync14(viteConfigPath, "utf8");
|
|
4882
4977
|
if (content.includes("base:")) {
|
|
4883
4978
|
console.log("vite.config.ts already has base config");
|
|
4884
4979
|
return;
|
|
@@ -5038,7 +5133,9 @@ function renderLineChart({
|
|
|
5038
5133
|
seriesTitle,
|
|
5039
5134
|
labels,
|
|
5040
5135
|
values,
|
|
5041
|
-
wholeNumbersOnly = false
|
|
5136
|
+
wholeNumbersOnly = false,
|
|
5137
|
+
minY,
|
|
5138
|
+
maxY
|
|
5042
5139
|
}) {
|
|
5043
5140
|
const input = keyboardInput();
|
|
5044
5141
|
const screen = blessed.screen({
|
|
@@ -5053,7 +5150,9 @@ function renderLineChart({
|
|
|
5053
5150
|
legend: { width: Math.max(12, seriesTitle.length + 2) },
|
|
5054
5151
|
xLabelPadding: 3,
|
|
5055
5152
|
xPadding: 5,
|
|
5056
|
-
wholeNumbersOnly
|
|
5153
|
+
wholeNumbersOnly,
|
|
5154
|
+
minY,
|
|
5155
|
+
maxY
|
|
5057
5156
|
});
|
|
5058
5157
|
line.setData([
|
|
5059
5158
|
{
|
|
@@ -5151,55 +5250,6 @@ function adviceContextFor(cwd) {
|
|
|
5151
5250
|
};
|
|
5152
5251
|
}
|
|
5153
5252
|
|
|
5154
|
-
// src/commands/advise/loadAdviceFragments.ts
|
|
5155
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync14 } from "fs";
|
|
5156
|
-
import { basename as basename4, join as join13 } from "path";
|
|
5157
|
-
|
|
5158
|
-
// src/commands/advise/adviceDir.ts
|
|
5159
|
-
import { existsSync as existsSync18 } from "fs";
|
|
5160
|
-
import { dirname as dirname13, join as join12 } from "path";
|
|
5161
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5162
|
-
function adviceDir() {
|
|
5163
|
-
let current = dirname13(fileURLToPath3(import.meta.url));
|
|
5164
|
-
while (current !== dirname13(current)) {
|
|
5165
|
-
const candidate = join12(current, "claude", "advice");
|
|
5166
|
-
if (existsSync18(candidate)) return candidate;
|
|
5167
|
-
current = dirname13(current);
|
|
5168
|
-
}
|
|
5169
|
-
throw new Error("Could not locate the shipped claude/advice directory");
|
|
5170
|
-
}
|
|
5171
|
-
|
|
5172
|
-
// src/commands/advise/parseAdviceFragment.ts
|
|
5173
|
-
import { parse as parseYaml2 } from "yaml";
|
|
5174
|
-
var frontmatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
5175
|
-
function parseAdviceFragment(name, content) {
|
|
5176
|
-
const match = frontmatter.exec(content);
|
|
5177
|
-
if (!match) throw new Error(`Advice fragment ${name} has no frontmatter`);
|
|
5178
|
-
const meta = parseYaml2(match[1]) ?? {};
|
|
5179
|
-
const title = meta.title;
|
|
5180
|
-
const when = meta.when;
|
|
5181
|
-
if (typeof title !== "string" || typeof when !== "string")
|
|
5182
|
-
throw new Error(
|
|
5183
|
-
`Advice fragment ${name} needs a title and a when condition`
|
|
5184
|
-
);
|
|
5185
|
-
return {
|
|
5186
|
-
name,
|
|
5187
|
-
title,
|
|
5188
|
-
when,
|
|
5189
|
-
body: content.slice(match[0].length).trim()
|
|
5190
|
-
};
|
|
5191
|
-
}
|
|
5192
|
-
|
|
5193
|
-
// src/commands/advise/loadAdviceFragments.ts
|
|
5194
|
-
function loadAdviceFragments(dir = adviceDir()) {
|
|
5195
|
-
return readdirSync2(dir).filter((file) => file.endsWith(".md")).sort().map(
|
|
5196
|
-
(file) => parseAdviceFragment(
|
|
5197
|
-
basename4(file, ".md"),
|
|
5198
|
-
readFileSync14(join13(dir, file), "utf8")
|
|
5199
|
-
)
|
|
5200
|
-
);
|
|
5201
|
-
}
|
|
5202
|
-
|
|
5203
5253
|
// src/commands/advise/verifyRunCommandNames.ts
|
|
5204
5254
|
function verifyRunCommandNames({
|
|
5205
5255
|
config,
|
|
@@ -5268,9 +5318,11 @@ var adviceConditions = {
|
|
|
5268
5318
|
// src/commands/advise/selectAdvice.ts
|
|
5269
5319
|
function decide(fragment, context) {
|
|
5270
5320
|
const advice = context.config.advice;
|
|
5271
|
-
|
|
5321
|
+
const exclude = advice?.exclude ?? [];
|
|
5322
|
+
const include = advice?.include ?? [];
|
|
5323
|
+
if (exclude.includes(fragment.name))
|
|
5272
5324
|
return { fragment, included: false, reason: "excluded by advice.exclude" };
|
|
5273
|
-
if (
|
|
5325
|
+
if (include.includes(fragment.name))
|
|
5274
5326
|
return { fragment, included: true, reason: "included by advice.include" };
|
|
5275
5327
|
const condition = adviceConditions[fragment.when];
|
|
5276
5328
|
if (!condition)
|
|
@@ -6362,6 +6414,19 @@ function registerBackup(program2) {
|
|
|
6362
6414
|
configHelp(backupCommand, backupConfigHelp);
|
|
6363
6415
|
}
|
|
6364
6416
|
|
|
6417
|
+
// src/commands/chart/chartYRange.ts
|
|
6418
|
+
var toCentsWithoutFloatError = (value) => Number((value * 100).toFixed(6));
|
|
6419
|
+
function chartYRange(values) {
|
|
6420
|
+
const min = Math.min(...values);
|
|
6421
|
+
const max = Math.max(...values);
|
|
6422
|
+
const span = max - min;
|
|
6423
|
+
const pad2 = span === 0 ? Math.max(Math.abs(max) * 0.1, 1) : span * 0.2;
|
|
6424
|
+
return {
|
|
6425
|
+
minY: Math.floor(toCentsWithoutFloatError(min - pad2)) / 100,
|
|
6426
|
+
maxY: Math.ceil(toCentsWithoutFloatError(max + pad2)) / 100
|
|
6427
|
+
};
|
|
6428
|
+
}
|
|
6429
|
+
|
|
6365
6430
|
// src/commands/chart/parseChartSeries.ts
|
|
6366
6431
|
function parseChartSeries(lines2) {
|
|
6367
6432
|
const points = [];
|
|
@@ -6412,12 +6477,14 @@ async function chart(options2) {
|
|
|
6412
6477
|
return;
|
|
6413
6478
|
}
|
|
6414
6479
|
const title = options2.title ?? "Chart";
|
|
6480
|
+
const values = points.map((p) => p.value);
|
|
6415
6481
|
renderLineChart({
|
|
6416
6482
|
title,
|
|
6417
6483
|
label: title,
|
|
6418
6484
|
seriesTitle: title,
|
|
6419
6485
|
labels: points.map((p) => p.label),
|
|
6420
|
-
values
|
|
6486
|
+
values,
|
|
6487
|
+
...chartYRange(values)
|
|
6421
6488
|
});
|
|
6422
6489
|
}
|
|
6423
6490
|
|
|
@@ -16800,13 +16867,13 @@ function phaseNotes(entry, position) {
|
|
|
16800
16867
|
}
|
|
16801
16868
|
function renderDiffPhase(entry, idx) {
|
|
16802
16869
|
const notes = phaseNotes(entry, idx + 1);
|
|
16803
|
-
const
|
|
16870
|
+
const section2 = renderPhaseSection(
|
|
16804
16871
|
{ ...entry.phase, name: `${entry.phase.name} (${notes.join(", ")})` },
|
|
16805
16872
|
idx
|
|
16806
16873
|
);
|
|
16807
|
-
if (!entry.previousTasks) return
|
|
16874
|
+
if (!entry.previousTasks) return section2;
|
|
16808
16875
|
return [
|
|
16809
|
-
|
|
16876
|
+
section2,
|
|
16810
16877
|
"**Previously:**",
|
|
16811
16878
|
entry.previousTasks.map((task) => `- ${task}`).join("\n")
|
|
16812
16879
|
].join("\n\n");
|
|
@@ -26319,9 +26386,9 @@ function parsePrBody(body) {
|
|
|
26319
26386
|
return sections;
|
|
26320
26387
|
}
|
|
26321
26388
|
function serializePrBody(sections) {
|
|
26322
|
-
return sections.map((
|
|
26389
|
+
return sections.map((section2) => `## ${section2.heading}
|
|
26323
26390
|
|
|
26324
|
-
${
|
|
26391
|
+
${section2.content}`).join("\n\n");
|
|
26325
26392
|
}
|
|
26326
26393
|
|
|
26327
26394
|
// src/commands/prs/editPrBody.ts
|
|
@@ -26370,11 +26437,11 @@ function findWallOfText(body) {
|
|
|
26370
26437
|
}
|
|
26371
26438
|
function splitParagraphs(body) {
|
|
26372
26439
|
const paragraphs = [];
|
|
26373
|
-
let
|
|
26440
|
+
let section2 = "(intro)";
|
|
26374
26441
|
let lines2 = [];
|
|
26375
26442
|
const flush = () => {
|
|
26376
26443
|
if (lines2.length > 0) {
|
|
26377
|
-
paragraphs.push({ section:
|
|
26444
|
+
paragraphs.push({ section: section2, lines: lines2 });
|
|
26378
26445
|
lines2 = [];
|
|
26379
26446
|
}
|
|
26380
26447
|
};
|
|
@@ -26382,7 +26449,7 @@ function splitParagraphs(body) {
|
|
|
26382
26449
|
const heading2 = line.match(/^#{1,6}\s+(.*)$/);
|
|
26383
26450
|
if (heading2) {
|
|
26384
26451
|
flush();
|
|
26385
|
-
|
|
26452
|
+
section2 = heading2[1].trim();
|
|
26386
26453
|
} else if (line.trim() === "") {
|
|
26387
26454
|
flush();
|
|
26388
26455
|
} else {
|
|
@@ -29103,13 +29170,13 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
29103
29170
|
// src/commands/refactor/extract/displayPlan.ts
|
|
29104
29171
|
import path50 from "path";
|
|
29105
29172
|
import chalk199 from "chalk";
|
|
29106
|
-
function
|
|
29173
|
+
function section(title) {
|
|
29107
29174
|
return `
|
|
29108
29175
|
${chalk199.cyan(title)}`;
|
|
29109
29176
|
}
|
|
29110
29177
|
function displayImporters(plan2, cwd) {
|
|
29111
29178
|
if (plan2.importersToUpdate.length === 0) return;
|
|
29112
|
-
console.log(
|
|
29179
|
+
console.log(section("Update importers:"));
|
|
29113
29180
|
for (const imp of plan2.importersToUpdate) {
|
|
29114
29181
|
const rel = path50.relative(cwd, imp.file.getFilePath());
|
|
29115
29182
|
console.log(` ${chalk199.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
@@ -29123,18 +29190,18 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
29123
29190
|
console.log(` ${name}`);
|
|
29124
29191
|
}
|
|
29125
29192
|
if (plan2.imports.length > 0) {
|
|
29126
|
-
console.log(
|
|
29193
|
+
console.log(section("Imports to copy:"));
|
|
29127
29194
|
for (const imp of plan2.imports) {
|
|
29128
29195
|
console.log(` ${formatImportLine(imp)}`);
|
|
29129
29196
|
}
|
|
29130
29197
|
}
|
|
29131
29198
|
if (plan2.exportedDeps.length > 0) {
|
|
29132
|
-
console.log(
|
|
29199
|
+
console.log(section("New imports from source:"));
|
|
29133
29200
|
console.log(
|
|
29134
29201
|
` import { ${plan2.exportedDeps.join(", ")} } from "${plan2.sourceRelPath}";`
|
|
29135
29202
|
);
|
|
29136
29203
|
}
|
|
29137
|
-
console.log(
|
|
29204
|
+
console.log(section("Source file changes:"));
|
|
29138
29205
|
console.log(` Remove: ${plan2.extractedNames.join(", ")}`);
|
|
29139
29206
|
if (plan2.sourceNeedsReimport) {
|
|
29140
29207
|
console.log(
|
|
@@ -29143,7 +29210,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
29143
29210
|
}
|
|
29144
29211
|
displayImporters(plan2, cwd);
|
|
29145
29212
|
if (plan2.barrel) {
|
|
29146
|
-
console.log(
|
|
29213
|
+
console.log(section("Barrel export:"));
|
|
29147
29214
|
console.log(
|
|
29148
29215
|
` Add: export { ${functionName} } from "${plan2.barrelRelPath}";`
|
|
29149
29216
|
);
|
|
@@ -34080,6 +34147,11 @@ var checks = [
|
|
|
34080
34147
|
description: "Check every assistConfigSchema key is surfaced in some command's --help via configHelp",
|
|
34081
34148
|
action: configKeys
|
|
34082
34149
|
},
|
|
34150
|
+
{
|
|
34151
|
+
name: "advice-fragments",
|
|
34152
|
+
description: "Check ADVICE_FRAGMENT_NAMES matches the fragments shipped in claude/advice, so advice.include/exclude can name every one",
|
|
34153
|
+
action: adviceFragments
|
|
34154
|
+
},
|
|
34083
34155
|
{
|
|
34084
34156
|
name: "migrations",
|
|
34085
34157
|
description: "Check DB migrations are sequentially numbered, append-only, and gate destructive DDL behind an acknowledgement marker",
|