@thebassclef/lite 1.9.11 → 1.9.13
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 +1 -1
- package/dist/cli.cjs +126 -25
- package/dist/cli.js +127 -26
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ your browser.
|
|
|
67
67
|
|
|
68
68
|
## Current release
|
|
69
69
|
|
|
70
|
-
<!-- version-start -->1.9.
|
|
70
|
+
<!-- version-start -->1.9.13<!-- version-end -->
|
|
71
71
|
|
|
72
72
|
See [CHANGELOG.md](CHANGELOG.md) for the full changelog. Adopter-facing
|
|
73
73
|
release notes live at [docs.bassclef.dev/docs/whats-new/releases](https://docs.bassclef.dev/docs/whats-new/releases).
|
package/dist/cli.cjs
CHANGED
|
@@ -272,6 +272,47 @@ function hashContent(content) {
|
|
|
272
272
|
normalized = normalized.replace(/\r\n/g, "\n");
|
|
273
273
|
return node_crypto.createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
274
274
|
}
|
|
275
|
+
const SCHEMA_VERSION = "1.0.0";
|
|
276
|
+
const WRITER_SLUG = "bassclef-init-npm";
|
|
277
|
+
function registerInstallWrittenPaths(targetDir, paths, now = /* @__PURE__ */ new Date()) {
|
|
278
|
+
if (paths.length === 0) return;
|
|
279
|
+
const manifestPath = node_path.join(targetDir, "state", "install-written-paths.json");
|
|
280
|
+
let manifest = {
|
|
281
|
+
schema_version: SCHEMA_VERSION,
|
|
282
|
+
entries: []
|
|
283
|
+
};
|
|
284
|
+
if (node_fs.existsSync(manifestPath)) {
|
|
285
|
+
try {
|
|
286
|
+
const parsed = JSON.parse(node_fs.readFileSync(manifestPath, "utf8"));
|
|
287
|
+
if (parsed && typeof parsed === "object" && "entries" in parsed && Array.isArray(parsed.entries)) {
|
|
288
|
+
manifest = parsed;
|
|
289
|
+
manifest.schema_version = SCHEMA_VERSION;
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const writtenAt = now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
295
|
+
const uniqueInputs = /* @__PURE__ */ new Map();
|
|
296
|
+
for (const p of paths) {
|
|
297
|
+
uniqueInputs.set(p.relativePath, p);
|
|
298
|
+
}
|
|
299
|
+
const incomingPaths = new Set(uniqueInputs.keys());
|
|
300
|
+
manifest.entries = manifest.entries.filter((e) => !incomingPaths.has(e.path));
|
|
301
|
+
for (const p of uniqueInputs.values()) {
|
|
302
|
+
manifest.entries.push({
|
|
303
|
+
path: p.relativePath,
|
|
304
|
+
writer: WRITER_SLUG,
|
|
305
|
+
written_at: writtenAt,
|
|
306
|
+
content_hash: `sha256:${p.contentHashSha256}`
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
node_fs.mkdirSync(node_path.dirname(manifestPath), { recursive: true });
|
|
310
|
+
node_fs.writeFileSync(
|
|
311
|
+
manifestPath,
|
|
312
|
+
JSON.stringify(manifest, null, 2) + "\n",
|
|
313
|
+
"utf8"
|
|
314
|
+
);
|
|
315
|
+
}
|
|
275
316
|
const SUBSTRATE_CONFIG_TEMPLATE_VERSION = "0.0.1";
|
|
276
317
|
function substrateConfigMdTemplate(pkgVersion) {
|
|
277
318
|
return [
|
|
@@ -549,6 +590,7 @@ function copySubstrate(targetDir, options = {}) {
|
|
|
549
590
|
copied: [],
|
|
550
591
|
copiedEntries: [],
|
|
551
592
|
refused: [],
|
|
593
|
+
unchanged: [],
|
|
552
594
|
errored: [],
|
|
553
595
|
erroredMessages: [],
|
|
554
596
|
hookCount: 0,
|
|
@@ -736,6 +778,16 @@ function copyOne(relPath, bundleRoot, options, result, scopeDecision) {
|
|
|
736
778
|
} catch (e) {
|
|
737
779
|
if (e instanceof WriteError) {
|
|
738
780
|
if (e.kind === "AlreadyExists") {
|
|
781
|
+
if (scope === "user") {
|
|
782
|
+
try {
|
|
783
|
+
const existing = node_fs.readFileSync(targetPath, "utf8");
|
|
784
|
+
if (hashContent(existing) === hashContent(outputContent)) {
|
|
785
|
+
result.unchanged.push(adopterRelPath);
|
|
786
|
+
return "unchanged";
|
|
787
|
+
}
|
|
788
|
+
} catch {
|
|
789
|
+
}
|
|
790
|
+
}
|
|
739
791
|
result.refused.push(adopterRelPath);
|
|
740
792
|
return "refused";
|
|
741
793
|
}
|
|
@@ -1028,6 +1080,24 @@ function matchesDesired(current) {
|
|
|
1028
1080
|
const c = current;
|
|
1029
1081
|
return c.type === STATUSLINE_FIELD.type && c.command === STATUSLINE_FIELD.command;
|
|
1030
1082
|
}
|
|
1083
|
+
const VALUE_TEST_BLOCK = `Bassclef is ready.
|
|
1084
|
+
|
|
1085
|
+
It added engineering workflows and automatic checks to Claude Code.
|
|
1086
|
+
Nothing else needs configuring.
|
|
1087
|
+
|
|
1088
|
+
Try it on something small:
|
|
1089
|
+
|
|
1090
|
+
claude
|
|
1091
|
+
/riff
|
|
1092
|
+
|
|
1093
|
+
Describe a feature you're considering. You'll get three approaches before any code is written.
|
|
1094
|
+
|
|
1095
|
+
Then choose one:
|
|
1096
|
+
/launch
|
|
1097
|
+
|
|
1098
|
+
When the plan looks right:
|
|
1099
|
+
/build
|
|
1100
|
+
`;
|
|
1031
1101
|
const FAMILIES = [
|
|
1032
1102
|
"skills",
|
|
1033
1103
|
"rules",
|
|
@@ -1079,13 +1149,14 @@ function buildInitReport(input) {
|
|
|
1079
1149
|
else project += 1;
|
|
1080
1150
|
}
|
|
1081
1151
|
const refused = input.refused.length;
|
|
1152
|
+
const unchanged = input.unchanged?.length ?? 0;
|
|
1082
1153
|
const errored = input.errored.length;
|
|
1083
1154
|
const written = input.configs.length + input.entries.length;
|
|
1084
1155
|
return {
|
|
1085
1156
|
schema_version: 3,
|
|
1086
1157
|
tier: input.tier,
|
|
1087
1158
|
totals: {
|
|
1088
|
-
files: written + refused + errored,
|
|
1159
|
+
files: written + refused + unchanged + errored,
|
|
1089
1160
|
written,
|
|
1090
1161
|
project,
|
|
1091
1162
|
user,
|
|
@@ -1098,6 +1169,7 @@ function buildInitReport(input) {
|
|
|
1098
1169
|
files: catalog.hooks
|
|
1099
1170
|
},
|
|
1100
1171
|
refused,
|
|
1172
|
+
unchanged,
|
|
1101
1173
|
errored,
|
|
1102
1174
|
failed: refused + errored
|
|
1103
1175
|
};
|
|
@@ -1203,6 +1275,7 @@ function runInit(argv) {
|
|
|
1203
1275
|
entries: outcome.result?.wouldCopyEntries ?? [],
|
|
1204
1276
|
configs: plans.map((pl) => ({ path: pl.relativePath })),
|
|
1205
1277
|
refused: outcome.result?.refused ?? [],
|
|
1278
|
+
unchanged: outcome.result?.unchanged ?? [],
|
|
1206
1279
|
// A dry run still reads every source file, so it can still fail
|
|
1207
1280
|
// to read one. Hard-coding this empty hid those failures from
|
|
1208
1281
|
// the JSON (RFC-0005 A-3).
|
|
@@ -1301,6 +1374,7 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1301
1374
|
}
|
|
1302
1375
|
const parts = [];
|
|
1303
1376
|
if (result.copied.length > 0) parts.push(`${result.copied.length} substrate files copied`);
|
|
1377
|
+
if (result.unchanged.length > 0) parts.push(`${result.unchanged.length} already-present`);
|
|
1304
1378
|
if (result.refused.length > 0) parts.push(`${result.refused.length} refused`);
|
|
1305
1379
|
if (result.errored.length > 0) parts.push(`${result.errored.length} error(s)`);
|
|
1306
1380
|
say(`bassclef init: ${parts.join(", ")}.
|
|
@@ -1366,32 +1440,34 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1366
1440
|
catalogCounts["root-docs"] += 1;
|
|
1367
1441
|
}
|
|
1368
1442
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1443
|
+
if (verbose) {
|
|
1444
|
+
const claudeCounts = [
|
|
1445
|
+
catalogCounts.skills > 0 ? `${catalogCounts.skills} skills` : null,
|
|
1446
|
+
catalogCounts.rules > 0 ? `${catalogCounts.rules} rules` : null,
|
|
1447
|
+
catalogCounts.agents > 0 ? `${catalogCounts.agents} agents` : null,
|
|
1448
|
+
catalogCounts.luminaries > 0 ? `${catalogCounts.luminaries} luminaries` : null
|
|
1449
|
+
].filter((s) => s !== null);
|
|
1450
|
+
if (claudeCounts.length > 0) {
|
|
1451
|
+
say(
|
|
1452
|
+
`bassclef init: Installed ${claudeCounts.join(", ")} under <repo>/.claude/.
|
|
1378
1453
|
`
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
const otherCounts = [
|
|
1457
|
+
catalogCounts.libs > 0 ? `${catalogCounts.libs} libs` : null,
|
|
1458
|
+
catalogCounts.adrs > 0 ? `${catalogCounts.adrs} ADRs` : null,
|
|
1459
|
+
catalogCounts.templates > 0 ? `${catalogCounts.templates} templates` : null,
|
|
1460
|
+
catalogCounts["presence-templates"] > 0 ? `${catalogCounts["presence-templates"]} presence-templates` : null,
|
|
1461
|
+
catalogCounts.standards > 0 ? `${catalogCounts.standards} standards` : null,
|
|
1462
|
+
catalogCounts["root-docs"] > 0 ? `${catalogCounts["root-docs"]} root-docs` : null,
|
|
1463
|
+
catalogCounts.scripts > 0 ? `${catalogCounts.scripts} scripts` : null
|
|
1464
|
+
].filter((s) => s !== null);
|
|
1465
|
+
if (otherCounts.length > 0) {
|
|
1466
|
+
say(
|
|
1467
|
+
`bassclef init: Installed ${otherCounts.join(", ")} under <repo>/.
|
|
1393
1468
|
`
|
|
1394
|
-
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1395
1471
|
}
|
|
1396
1472
|
if (result.refused.length > 0) {
|
|
1397
1473
|
say(
|
|
@@ -1531,12 +1607,25 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1531
1607
|
entries: walker.result?.copiedEntries ?? [],
|
|
1532
1608
|
configs: results.map((r) => ({ path: r.plan.relativePath })),
|
|
1533
1609
|
refused: walker.result?.refused ?? [],
|
|
1610
|
+
unchanged: walker.result?.unchanged ?? [],
|
|
1534
1611
|
errored: walker.result?.errored ?? [],
|
|
1535
1612
|
hookCount: walker.result?.hookCount ?? 0,
|
|
1536
1613
|
declaredHooksCopied,
|
|
1537
1614
|
tier: RESOLVED_TIER
|
|
1538
1615
|
});
|
|
1539
1616
|
writeManifest(targetDir, results, walker.result);
|
|
1617
|
+
const createdConfigPaths = results.filter((r) => r.outcome === "created").map((r) => ({
|
|
1618
|
+
relativePath: r.plan.relativePath,
|
|
1619
|
+
contentHashSha256: hashContent(r.plan.content)
|
|
1620
|
+
}));
|
|
1621
|
+
const createdBundlePaths = (walker.result?.copiedEntries ?? []).filter((e) => typeof e.content_hash_sha256 === "string").map((e) => ({
|
|
1622
|
+
relativePath: e.path,
|
|
1623
|
+
contentHashSha256: e.content_hash_sha256
|
|
1624
|
+
}));
|
|
1625
|
+
registerInstallWrittenPaths(targetDir, [
|
|
1626
|
+
...createdConfigPaths,
|
|
1627
|
+
...createdBundlePaths
|
|
1628
|
+
]);
|
|
1540
1629
|
if (walker.code === 0) {
|
|
1541
1630
|
say(
|
|
1542
1631
|
`bassclef init: your substrate lives under .claude/. Add .claude/ to .gitignore if you have not.
|
|
@@ -1562,6 +1651,9 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1562
1651
|
process.stdout.write(t);
|
|
1563
1652
|
});
|
|
1564
1653
|
}
|
|
1654
|
+
if (!json && walker.code === 0) {
|
|
1655
|
+
say(VALUE_TEST_BLOCK);
|
|
1656
|
+
}
|
|
1565
1657
|
return walker.code;
|
|
1566
1658
|
}
|
|
1567
1659
|
function shouldRefuseRoot(currentUid, allowRoot) {
|
|
@@ -1606,6 +1698,15 @@ function writeManifest(targetDir, results, walkerResult) {
|
|
|
1606
1698
|
source: "bundle"
|
|
1607
1699
|
});
|
|
1608
1700
|
}
|
|
1701
|
+
for (const path of walkerResult.unchanged) {
|
|
1702
|
+
entries.push({
|
|
1703
|
+
path,
|
|
1704
|
+
template: `bundle:${path}`,
|
|
1705
|
+
template_version: index.version,
|
|
1706
|
+
outcome: "unchanged",
|
|
1707
|
+
source: "bundle"
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1609
1710
|
for (const path of walkerResult.errored) {
|
|
1610
1711
|
entries.push({
|
|
1611
1712
|
path,
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { version } from "./index.js";
|
|
3
|
-
import { realpathSync, statSync, constants, lstatSync, mkdirSync, accessSync, unlinkSync, openSync, writeSync, closeSync, readlinkSync,
|
|
3
|
+
import { realpathSync, statSync, constants, lstatSync, mkdirSync, accessSync, unlinkSync, openSync, writeSync, closeSync, readlinkSync, existsSync, readFileSync, writeFileSync, chmodSync, readdirSync, renameSync } from "node:fs";
|
|
4
4
|
import { isAbsolute, resolve, dirname, join, normalize, relative, basename as basename$1 } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
@@ -249,6 +249,47 @@ function hashContent(content) {
|
|
|
249
249
|
normalized = normalized.replace(/\r\n/g, "\n");
|
|
250
250
|
return createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
251
251
|
}
|
|
252
|
+
const SCHEMA_VERSION = "1.0.0";
|
|
253
|
+
const WRITER_SLUG = "bassclef-init-npm";
|
|
254
|
+
function registerInstallWrittenPaths(targetDir, paths, now = /* @__PURE__ */ new Date()) {
|
|
255
|
+
if (paths.length === 0) return;
|
|
256
|
+
const manifestPath = join(targetDir, "state", "install-written-paths.json");
|
|
257
|
+
let manifest = {
|
|
258
|
+
schema_version: SCHEMA_VERSION,
|
|
259
|
+
entries: []
|
|
260
|
+
};
|
|
261
|
+
if (existsSync(manifestPath)) {
|
|
262
|
+
try {
|
|
263
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
264
|
+
if (parsed && typeof parsed === "object" && "entries" in parsed && Array.isArray(parsed.entries)) {
|
|
265
|
+
manifest = parsed;
|
|
266
|
+
manifest.schema_version = SCHEMA_VERSION;
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const writtenAt = now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
272
|
+
const uniqueInputs = /* @__PURE__ */ new Map();
|
|
273
|
+
for (const p of paths) {
|
|
274
|
+
uniqueInputs.set(p.relativePath, p);
|
|
275
|
+
}
|
|
276
|
+
const incomingPaths = new Set(uniqueInputs.keys());
|
|
277
|
+
manifest.entries = manifest.entries.filter((e) => !incomingPaths.has(e.path));
|
|
278
|
+
for (const p of uniqueInputs.values()) {
|
|
279
|
+
manifest.entries.push({
|
|
280
|
+
path: p.relativePath,
|
|
281
|
+
writer: WRITER_SLUG,
|
|
282
|
+
written_at: writtenAt,
|
|
283
|
+
content_hash: `sha256:${p.contentHashSha256}`
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
mkdirSync(dirname(manifestPath), { recursive: true });
|
|
287
|
+
writeFileSync(
|
|
288
|
+
manifestPath,
|
|
289
|
+
JSON.stringify(manifest, null, 2) + "\n",
|
|
290
|
+
"utf8"
|
|
291
|
+
);
|
|
292
|
+
}
|
|
252
293
|
const SUBSTRATE_CONFIG_TEMPLATE_VERSION = "0.0.1";
|
|
253
294
|
function substrateConfigMdTemplate(pkgVersion) {
|
|
254
295
|
return [
|
|
@@ -526,6 +567,7 @@ function copySubstrate(targetDir, options = {}) {
|
|
|
526
567
|
copied: [],
|
|
527
568
|
copiedEntries: [],
|
|
528
569
|
refused: [],
|
|
570
|
+
unchanged: [],
|
|
529
571
|
errored: [],
|
|
530
572
|
erroredMessages: [],
|
|
531
573
|
hookCount: 0,
|
|
@@ -713,6 +755,16 @@ function copyOne(relPath, bundleRoot, options, result, scopeDecision) {
|
|
|
713
755
|
} catch (e) {
|
|
714
756
|
if (e instanceof WriteError) {
|
|
715
757
|
if (e.kind === "AlreadyExists") {
|
|
758
|
+
if (scope === "user") {
|
|
759
|
+
try {
|
|
760
|
+
const existing = readFileSync(targetPath, "utf8");
|
|
761
|
+
if (hashContent(existing) === hashContent(outputContent)) {
|
|
762
|
+
result.unchanged.push(adopterRelPath);
|
|
763
|
+
return "unchanged";
|
|
764
|
+
}
|
|
765
|
+
} catch {
|
|
766
|
+
}
|
|
767
|
+
}
|
|
716
768
|
result.refused.push(adopterRelPath);
|
|
717
769
|
return "refused";
|
|
718
770
|
}
|
|
@@ -1005,6 +1057,24 @@ function matchesDesired(current) {
|
|
|
1005
1057
|
const c = current;
|
|
1006
1058
|
return c.type === STATUSLINE_FIELD.type && c.command === STATUSLINE_FIELD.command;
|
|
1007
1059
|
}
|
|
1060
|
+
const VALUE_TEST_BLOCK = `Bassclef is ready.
|
|
1061
|
+
|
|
1062
|
+
It added engineering workflows and automatic checks to Claude Code.
|
|
1063
|
+
Nothing else needs configuring.
|
|
1064
|
+
|
|
1065
|
+
Try it on something small:
|
|
1066
|
+
|
|
1067
|
+
claude
|
|
1068
|
+
/riff
|
|
1069
|
+
|
|
1070
|
+
Describe a feature you're considering. You'll get three approaches before any code is written.
|
|
1071
|
+
|
|
1072
|
+
Then choose one:
|
|
1073
|
+
/launch
|
|
1074
|
+
|
|
1075
|
+
When the plan looks right:
|
|
1076
|
+
/build
|
|
1077
|
+
`;
|
|
1008
1078
|
const FAMILIES = [
|
|
1009
1079
|
"skills",
|
|
1010
1080
|
"rules",
|
|
@@ -1056,13 +1126,14 @@ function buildInitReport(input) {
|
|
|
1056
1126
|
else project += 1;
|
|
1057
1127
|
}
|
|
1058
1128
|
const refused = input.refused.length;
|
|
1129
|
+
const unchanged = input.unchanged?.length ?? 0;
|
|
1059
1130
|
const errored = input.errored.length;
|
|
1060
1131
|
const written = input.configs.length + input.entries.length;
|
|
1061
1132
|
return {
|
|
1062
1133
|
schema_version: 3,
|
|
1063
1134
|
tier: input.tier,
|
|
1064
1135
|
totals: {
|
|
1065
|
-
files: written + refused + errored,
|
|
1136
|
+
files: written + refused + unchanged + errored,
|
|
1066
1137
|
written,
|
|
1067
1138
|
project,
|
|
1068
1139
|
user,
|
|
@@ -1075,6 +1146,7 @@ function buildInitReport(input) {
|
|
|
1075
1146
|
files: catalog.hooks
|
|
1076
1147
|
},
|
|
1077
1148
|
refused,
|
|
1149
|
+
unchanged,
|
|
1078
1150
|
errored,
|
|
1079
1151
|
failed: refused + errored
|
|
1080
1152
|
};
|
|
@@ -1180,6 +1252,7 @@ function runInit(argv) {
|
|
|
1180
1252
|
entries: outcome.result?.wouldCopyEntries ?? [],
|
|
1181
1253
|
configs: plans.map((pl) => ({ path: pl.relativePath })),
|
|
1182
1254
|
refused: outcome.result?.refused ?? [],
|
|
1255
|
+
unchanged: outcome.result?.unchanged ?? [],
|
|
1183
1256
|
// A dry run still reads every source file, so it can still fail
|
|
1184
1257
|
// to read one. Hard-coding this empty hid those failures from
|
|
1185
1258
|
// the JSON (RFC-0005 A-3).
|
|
@@ -1278,6 +1351,7 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1278
1351
|
}
|
|
1279
1352
|
const parts = [];
|
|
1280
1353
|
if (result.copied.length > 0) parts.push(`${result.copied.length} substrate files copied`);
|
|
1354
|
+
if (result.unchanged.length > 0) parts.push(`${result.unchanged.length} already-present`);
|
|
1281
1355
|
if (result.refused.length > 0) parts.push(`${result.refused.length} refused`);
|
|
1282
1356
|
if (result.errored.length > 0) parts.push(`${result.errored.length} error(s)`);
|
|
1283
1357
|
say(`bassclef init: ${parts.join(", ")}.
|
|
@@ -1343,32 +1417,34 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1343
1417
|
catalogCounts["root-docs"] += 1;
|
|
1344
1418
|
}
|
|
1345
1419
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1420
|
+
if (verbose) {
|
|
1421
|
+
const claudeCounts = [
|
|
1422
|
+
catalogCounts.skills > 0 ? `${catalogCounts.skills} skills` : null,
|
|
1423
|
+
catalogCounts.rules > 0 ? `${catalogCounts.rules} rules` : null,
|
|
1424
|
+
catalogCounts.agents > 0 ? `${catalogCounts.agents} agents` : null,
|
|
1425
|
+
catalogCounts.luminaries > 0 ? `${catalogCounts.luminaries} luminaries` : null
|
|
1426
|
+
].filter((s) => s !== null);
|
|
1427
|
+
if (claudeCounts.length > 0) {
|
|
1428
|
+
say(
|
|
1429
|
+
`bassclef init: Installed ${claudeCounts.join(", ")} under <repo>/.claude/.
|
|
1355
1430
|
`
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
const otherCounts = [
|
|
1434
|
+
catalogCounts.libs > 0 ? `${catalogCounts.libs} libs` : null,
|
|
1435
|
+
catalogCounts.adrs > 0 ? `${catalogCounts.adrs} ADRs` : null,
|
|
1436
|
+
catalogCounts.templates > 0 ? `${catalogCounts.templates} templates` : null,
|
|
1437
|
+
catalogCounts["presence-templates"] > 0 ? `${catalogCounts["presence-templates"]} presence-templates` : null,
|
|
1438
|
+
catalogCounts.standards > 0 ? `${catalogCounts.standards} standards` : null,
|
|
1439
|
+
catalogCounts["root-docs"] > 0 ? `${catalogCounts["root-docs"]} root-docs` : null,
|
|
1440
|
+
catalogCounts.scripts > 0 ? `${catalogCounts.scripts} scripts` : null
|
|
1441
|
+
].filter((s) => s !== null);
|
|
1442
|
+
if (otherCounts.length > 0) {
|
|
1443
|
+
say(
|
|
1444
|
+
`bassclef init: Installed ${otherCounts.join(", ")} under <repo>/.
|
|
1370
1445
|
`
|
|
1371
|
-
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1372
1448
|
}
|
|
1373
1449
|
if (result.refused.length > 0) {
|
|
1374
1450
|
say(
|
|
@@ -1508,12 +1584,25 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1508
1584
|
entries: walker.result?.copiedEntries ?? [],
|
|
1509
1585
|
configs: results.map((r) => ({ path: r.plan.relativePath })),
|
|
1510
1586
|
refused: walker.result?.refused ?? [],
|
|
1587
|
+
unchanged: walker.result?.unchanged ?? [],
|
|
1511
1588
|
errored: walker.result?.errored ?? [],
|
|
1512
1589
|
hookCount: walker.result?.hookCount ?? 0,
|
|
1513
1590
|
declaredHooksCopied,
|
|
1514
1591
|
tier: RESOLVED_TIER
|
|
1515
1592
|
});
|
|
1516
1593
|
writeManifest(targetDir, results, walker.result);
|
|
1594
|
+
const createdConfigPaths = results.filter((r) => r.outcome === "created").map((r) => ({
|
|
1595
|
+
relativePath: r.plan.relativePath,
|
|
1596
|
+
contentHashSha256: hashContent(r.plan.content)
|
|
1597
|
+
}));
|
|
1598
|
+
const createdBundlePaths = (walker.result?.copiedEntries ?? []).filter((e) => typeof e.content_hash_sha256 === "string").map((e) => ({
|
|
1599
|
+
relativePath: e.path,
|
|
1600
|
+
contentHashSha256: e.content_hash_sha256
|
|
1601
|
+
}));
|
|
1602
|
+
registerInstallWrittenPaths(targetDir, [
|
|
1603
|
+
...createdConfigPaths,
|
|
1604
|
+
...createdBundlePaths
|
|
1605
|
+
]);
|
|
1517
1606
|
if (walker.code === 0) {
|
|
1518
1607
|
say(
|
|
1519
1608
|
`bassclef init: your substrate lives under .claude/. Add .claude/ to .gitignore if you have not.
|
|
@@ -1539,6 +1628,9 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1539
1628
|
process.stdout.write(t);
|
|
1540
1629
|
});
|
|
1541
1630
|
}
|
|
1631
|
+
if (!json && walker.code === 0) {
|
|
1632
|
+
say(VALUE_TEST_BLOCK);
|
|
1633
|
+
}
|
|
1542
1634
|
return walker.code;
|
|
1543
1635
|
}
|
|
1544
1636
|
function shouldRefuseRoot(currentUid, allowRoot) {
|
|
@@ -1583,6 +1675,15 @@ function writeManifest(targetDir, results, walkerResult) {
|
|
|
1583
1675
|
source: "bundle"
|
|
1584
1676
|
});
|
|
1585
1677
|
}
|
|
1678
|
+
for (const path of walkerResult.unchanged) {
|
|
1679
|
+
entries.push({
|
|
1680
|
+
path,
|
|
1681
|
+
template: `bundle:${path}`,
|
|
1682
|
+
template_version: version,
|
|
1683
|
+
outcome: "unchanged",
|
|
1684
|
+
source: "bundle"
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1586
1687
|
for (const path of walkerResult.errored) {
|
|
1587
1688
|
entries.push({
|
|
1588
1689
|
path,
|
package/dist/index.cjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version: "1.9.
|
|
1
|
+
export declare const version: "1.9.13";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED