@slats/claude-assets-sync 0.1.4 → 0.2.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 +111 -587
- package/bin/claude-sync.mjs +24 -0
- package/dist/claude-hashes.json +20 -0
- package/dist/commands/index.d.ts +1 -112
- package/dist/commands/runCli/index.d.ts +2 -0
- package/dist/commands/runCli/runCli.cjs +31 -0
- package/dist/commands/runCli/runCli.d.ts +10 -0
- package/dist/commands/runCli/runCli.mjs +29 -0
- package/dist/commands/runCli/type.d.ts +28 -0
- package/dist/commands/runCli/utils/injectOne.cjs +48 -0
- package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
- package/dist/commands/runCli/utils/injectOne.mjs +46 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
- package/dist/commands/runCli/utils/runInject.cjs +36 -0
- package/dist/commands/runCli/utils/runInject.d.ts +2 -0
- package/dist/commands/runCli/utils/runInject.mjs +34 -0
- package/dist/core/buildPlan/buildPlan.cjs +42 -0
- package/dist/core/buildPlan/buildPlan.d.ts +2 -0
- package/dist/core/buildPlan/buildPlan.mjs +40 -0
- package/dist/core/buildPlan/index.d.ts +2 -0
- package/dist/core/buildPlan/type.d.ts +32 -0
- package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
- package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
- package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
- package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
- package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
- package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
- package/dist/core/hash/hash.cjs +30 -0
- package/dist/core/hash/hash.d.ts +4 -0
- package/dist/core/hash/hash.mjs +26 -0
- package/dist/core/hash/index.d.ts +1 -0
- package/dist/core/hashManifest/hashManifest.cjs +27 -0
- package/dist/core/hashManifest/hashManifest.d.ts +17 -0
- package/dist/core/hashManifest/hashManifest.mjs +23 -0
- package/dist/core/hashManifest/index.d.ts +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/injectDocs/index.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.cjs +43 -0
- package/dist/core/injectDocs/injectDocs.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.mjs +41 -0
- package/dist/core/injectDocs/type.d.ts +30 -0
- package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
- package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
- package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
- package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
- package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
- package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
- package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
- package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
- package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
- package/dist/core/injectDocs/utils/summarize.cjs +27 -0
- package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
- package/dist/core/injectDocs/utils/summarize.mjs +25 -0
- package/dist/core/scope/index.d.ts +1 -0
- package/dist/core/scope/scope.cjs +46 -0
- package/dist/core/scope/scope.d.ts +16 -0
- package/dist/core/scope/scope.mjs +41 -0
- package/dist/core/scope/utils/isDirectory.cjs +14 -0
- package/dist/core/scope/utils/isDirectory.d.ts +1 -0
- package/dist/core/scope/utils/isDirectory.mjs +12 -0
- package/dist/index.cjs +15 -9
- package/dist/index.d.ts +3 -5
- package/dist/index.mjs +7 -3
- package/dist/prompts/confirmForce.cjs +27 -0
- package/dist/prompts/confirmForce.d.ts +1 -0
- package/dist/prompts/confirmForce.mjs +25 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/selectScope.cjs +30 -0
- package/dist/prompts/selectScope.d.ts +2 -0
- package/dist/prompts/selectScope.mjs +28 -0
- package/dist/utils/heartbeat.cjs +25 -0
- package/dist/utils/heartbeat.d.ts +16 -0
- package/dist/utils/heartbeat.mjs +23 -0
- package/dist/utils/logger.cjs +7 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.mjs +7 -0
- package/dist/utils/types.d.ts +1 -252
- package/dist/utils/version.cjs +2 -14
- package/dist/utils/version.d.ts +3 -53
- package/dist/utils/version.mjs +2 -13
- package/docs/bundle-size-decision.md +36 -0
- package/docs/claude/skills/claude-sync-applier/SKILL.md +195 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/claude-md-template.md +77 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/dependency-cruiser.md +126 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/gotchas.md +139 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/package-json-patches.md +130 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/reference-files.md +120 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/smoke-tests.md +102 -0
- package/docs/consumer-integration.md +153 -0
- package/package.json +24 -16
- package/scripts/build-hashes.mjs +30 -0
- package/scripts/buildHashes.d.mts +15 -0
- package/scripts/buildHashes.mjs +82 -0
- package/scripts/claude-build-hashes.mjs +42 -0
- package/scripts/inject-version.js +112 -0
- package/dist/cli.cjs +0 -8
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -7
- package/dist/commands/add.cjs +0 -80
- package/dist/commands/add.d.ts +0 -8
- package/dist/commands/add.mjs +0 -78
- package/dist/commands/list.cjs +0 -94
- package/dist/commands/list.d.ts +0 -15
- package/dist/commands/list.mjs +0 -91
- package/dist/commands/migrate.cjs +0 -9
- package/dist/commands/migrate.d.ts +0 -6
- package/dist/commands/migrate.mjs +0 -7
- package/dist/commands/remove.cjs +0 -127
- package/dist/commands/remove.d.ts +0 -6
- package/dist/commands/remove.mjs +0 -105
- package/dist/commands/status.cjs +0 -193
- package/dist/commands/status.d.ts +0 -6
- package/dist/commands/status.mjs +0 -171
- package/dist/commands/sync.cjs +0 -28
- package/dist/commands/sync.d.ts +0 -6
- package/dist/commands/sync.mjs +0 -26
- package/dist/commands/types.d.ts +0 -89
- package/dist/commands/update.cjs +0 -209
- package/dist/commands/update.d.ts +0 -29
- package/dist/commands/update.mjs +0 -206
- package/dist/components/add/AddCommand.cjs +0 -103
- package/dist/components/add/AddCommand.d.ts +0 -14
- package/dist/components/add/AddCommand.mjs +0 -101
- package/dist/components/add/BulkAddView.cjs +0 -165
- package/dist/components/add/BulkAddView.d.ts +0 -11
- package/dist/components/add/BulkAddView.mjs +0 -163
- package/dist/components/add/index.d.ts +0 -2
- package/dist/components/index.d.ts +0 -2
- package/dist/components/list/EditableTreeItem.d.ts +0 -13
- package/dist/components/list/ListCommand.cjs +0 -651
- package/dist/components/list/ListCommand.d.ts +0 -5
- package/dist/components/list/ListCommand.mjs +0 -649
- package/dist/components/list/SyncedPackageTree.d.ts +0 -14
- package/dist/components/list/index.d.ts +0 -10
- package/dist/components/list/types.d.ts +0 -14
- package/dist/components/primitives/Box.d.ts +0 -4
- package/dist/components/primitives/Spinner.d.ts +0 -6
- package/dist/components/primitives/Text.d.ts +0 -4
- package/dist/components/primitives/index.d.ts +0 -3
- package/dist/components/remove/RemoveConfirm.cjs +0 -18
- package/dist/components/remove/RemoveConfirm.d.ts +0 -11
- package/dist/components/remove/RemoveConfirm.mjs +0 -16
- package/dist/components/shared/Confirm.cjs +0 -30
- package/dist/components/shared/Confirm.d.ts +0 -8
- package/dist/components/shared/Confirm.mjs +0 -28
- package/dist/components/shared/MenuItem.cjs +0 -18
- package/dist/components/shared/MenuItem.d.ts +0 -7
- package/dist/components/shared/MenuItem.mjs +0 -16
- package/dist/components/shared/ProgressBar.d.ts +0 -7
- package/dist/components/shared/StepRunner.cjs +0 -58
- package/dist/components/shared/StepRunner.d.ts +0 -15
- package/dist/components/shared/StepRunner.mjs +0 -56
- package/dist/components/shared/Table.cjs +0 -19
- package/dist/components/shared/Table.d.ts +0 -8
- package/dist/components/shared/Table.mjs +0 -17
- package/dist/components/shared/index.d.ts +0 -6
- package/dist/components/status/PackageStatusCard.d.ts +0 -10
- package/dist/components/status/StatusDisplay.cjs +0 -26
- package/dist/components/status/StatusDisplay.d.ts +0 -23
- package/dist/components/status/StatusDisplay.mjs +0 -24
- package/dist/components/status/StatusTreeNode.cjs +0 -40
- package/dist/components/status/StatusTreeNode.d.ts +0 -15
- package/dist/components/status/StatusTreeNode.mjs +0 -38
- package/dist/components/status/index.d.ts +0 -6
- package/dist/components/tree/AssetTreeNode.cjs +0 -54
- package/dist/components/tree/AssetTreeNode.d.ts +0 -12
- package/dist/components/tree/AssetTreeNode.mjs +0 -52
- package/dist/components/tree/TreeSelect.cjs +0 -129
- package/dist/components/tree/TreeSelect.d.ts +0 -12
- package/dist/components/tree/TreeSelect.mjs +0 -127
- package/dist/components/tree/index.d.ts +0 -4
- package/dist/core/assetStructure.cjs +0 -30
- package/dist/core/assetStructure.d.ts +0 -36
- package/dist/core/assetStructure.mjs +0 -27
- package/dist/core/cli.cjs +0 -106
- package/dist/core/cli.d.ts +0 -9
- package/dist/core/cli.mjs +0 -103
- package/dist/core/constants.cjs +0 -28
- package/dist/core/constants.d.ts +0 -94
- package/dist/core/constants.mjs +0 -21
- package/dist/core/filesystem.cjs +0 -98
- package/dist/core/filesystem.d.ts +0 -94
- package/dist/core/filesystem.mjs +0 -88
- package/dist/core/github.cjs +0 -115
- package/dist/core/github.d.ts +0 -61
- package/dist/core/github.mjs +0 -107
- package/dist/core/io.cjs +0 -46
- package/dist/core/io.d.ts +0 -40
- package/dist/core/io.mjs +0 -39
- package/dist/core/listOperations.cjs +0 -228
- package/dist/core/listOperations.d.ts +0 -43
- package/dist/core/listOperations.mjs +0 -205
- package/dist/core/localSource.cjs +0 -126
- package/dist/core/localSource.d.ts +0 -33
- package/dist/core/localSource.mjs +0 -120
- package/dist/core/migration.cjs +0 -201
- package/dist/core/migration.d.ts +0 -57
- package/dist/core/migration.mjs +0 -198
- package/dist/core/packageScanner.cjs +0 -360
- package/dist/core/packageScanner.d.ts +0 -22
- package/dist/core/packageScanner.mjs +0 -356
- package/dist/core/sync.cjs +0 -400
- package/dist/core/sync.d.ts +0 -21
- package/dist/core/sync.mjs +0 -397
- package/dist/core/syncMeta.cjs +0 -242
- package/dist/core/syncMeta.d.ts +0 -75
- package/dist/core/syncMeta.mjs +0 -229
- package/dist/utils/dependencies.cjs +0 -57
- package/dist/utils/dependencies.d.ts +0 -10
- package/dist/utils/dependencies.mjs +0 -34
- package/dist/utils/nameTransform.cjs +0 -13
- package/dist/utils/nameTransform.d.ts +0 -65
- package/dist/utils/nameTransform.mjs +0 -11
- package/dist/utils/package.cjs +0 -170
- package/dist/utils/package.d.ts +0 -105
- package/dist/utils/package.mjs +0 -157
- package/dist/utils/packageName.cjs +0 -24
- package/dist/utils/packageName.d.ts +0 -32
- package/dist/utils/packageName.mjs +0 -21
- package/dist/utils/paths.cjs +0 -18
- package/dist/utils/paths.d.ts +0 -55
- package/dist/utils/paths.mjs +0 -15
- package/dist/version.cjs +0 -5
- package/dist/version.d.ts +0 -5
- package/dist/version.mjs +0 -3
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
var runCli = require('./commands/runCli/runCli.cjs');
|
|
4
|
+
require('node:crypto');
|
|
5
|
+
require('node:fs/promises');
|
|
6
|
+
var hashManifest = require('./core/hashManifest/hashManifest.cjs');
|
|
7
|
+
var injectDocs = require('./core/injectDocs/injectDocs.cjs');
|
|
8
|
+
require('node:path');
|
|
9
|
+
var scope = require('./core/scope/scope.cjs');
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
13
|
+
exports.runCli = runCli.runCli;
|
|
14
|
+
exports.HASH_MANIFEST_FILENAME = hashManifest.HASH_MANIFEST_FILENAME;
|
|
15
|
+
exports.computeNamespacePrefixes = hashManifest.computeNamespacePrefixes;
|
|
16
|
+
exports.readHashManifest = hashManifest.readHashManifest;
|
|
17
|
+
exports.injectDocs = injectDocs.injectDocs;
|
|
18
|
+
exports.isInteractive = scope.isInteractive;
|
|
19
|
+
exports.isValidScope = scope.isValidScope;
|
|
20
|
+
exports.resolveScope = scope.resolveScope;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export type { MigrationResult } from './core/migration.js';
|
|
5
|
-
export type { AssetType, CliOptions, ClaudeConfig, GitHubRepoInfo, PackageInfo, SyncMeta, SyncResult, UnifiedSyncMeta, PackageSyncInfo, FileMapping, } from './utils/types.js';
|
|
1
|
+
export { runCli, type RunCliOptions } from './commands/index.js';
|
|
2
|
+
export { HASH_MANIFEST_FILENAME, computeNamespacePrefixes, injectDocs, isInteractive, isValidScope, readHashManifest, resolveScope, type HashManifest, type InjectOptions, type InjectReport, type Scope, type ScopeResolution, } from './core/index.js';
|
|
3
|
+
export type { AssetType } from './utils/types.js';
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export { runCli } from './commands/runCli/runCli.mjs';
|
|
2
|
+
import 'node:crypto';
|
|
3
|
+
import 'node:fs/promises';
|
|
4
|
+
export { HASH_MANIFEST_FILENAME, computeNamespacePrefixes, readHashManifest } from './core/hashManifest/hashManifest.mjs';
|
|
5
|
+
export { injectDocs } from './core/injectDocs/injectDocs.mjs';
|
|
6
|
+
import 'node:path';
|
|
7
|
+
export { isInteractive, isValidScope, resolveScope } from './core/scope/scope.mjs';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var prompts = require('@inquirer/prompts');
|
|
4
|
+
var pc = require('picocolors');
|
|
5
|
+
|
|
6
|
+
async function confirmForceAsync(divergedCount, orphanCount, relPaths) {
|
|
7
|
+
const extra = Math.max(0, divergedCount + orphanCount - relPaths.length);
|
|
8
|
+
const divergedPart = pc.red(pc.bold(`${divergedCount} diverged file(s)`));
|
|
9
|
+
const orphanPart = orphanCount > 0
|
|
10
|
+
? ` and ${pc.red(pc.bold(`delete ${orphanCount} orphan(s)`))}`
|
|
11
|
+
: '';
|
|
12
|
+
process.stderr.write(`${pc.yellow(pc.bold('!'))} This will overwrite ${divergedPart}${orphanPart}:\n`);
|
|
13
|
+
for (const p of relPaths) {
|
|
14
|
+
process.stderr.write(` ${pc.dim('-')} ${p}\n`);
|
|
15
|
+
}
|
|
16
|
+
if (extra > 0) {
|
|
17
|
+
process.stderr.write(` ${pc.dim(`... and ${extra} more`)}\n`);
|
|
18
|
+
}
|
|
19
|
+
process.stderr.write('\n');
|
|
20
|
+
const answer = await prompts.confirm({
|
|
21
|
+
message: pc.bold('Do you have these in git? Proceed?'),
|
|
22
|
+
default: false,
|
|
23
|
+
});
|
|
24
|
+
return answer;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.confirmForceAsync = confirmForceAsync;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function confirmForceAsync(divergedCount: number, orphanCount: number, relPaths: string[]): Promise<boolean>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
|
|
4
|
+
async function confirmForceAsync(divergedCount, orphanCount, relPaths) {
|
|
5
|
+
const extra = Math.max(0, divergedCount + orphanCount - relPaths.length);
|
|
6
|
+
const divergedPart = pc.red(pc.bold(`${divergedCount} diverged file(s)`));
|
|
7
|
+
const orphanPart = orphanCount > 0
|
|
8
|
+
? ` and ${pc.red(pc.bold(`delete ${orphanCount} orphan(s)`))}`
|
|
9
|
+
: '';
|
|
10
|
+
process.stderr.write(`${pc.yellow(pc.bold('!'))} This will overwrite ${divergedPart}${orphanPart}:\n`);
|
|
11
|
+
for (const p of relPaths) {
|
|
12
|
+
process.stderr.write(` ${pc.dim('-')} ${p}\n`);
|
|
13
|
+
}
|
|
14
|
+
if (extra > 0) {
|
|
15
|
+
process.stderr.write(` ${pc.dim(`... and ${extra} more`)}\n`);
|
|
16
|
+
}
|
|
17
|
+
process.stderr.write('\n');
|
|
18
|
+
const answer = await confirm({
|
|
19
|
+
message: pc.bold('Do you have these in git? Proceed?'),
|
|
20
|
+
default: false,
|
|
21
|
+
});
|
|
22
|
+
return answer;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { confirmForceAsync };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var prompts = require('@inquirer/prompts');
|
|
4
|
+
var pc = require('picocolors');
|
|
5
|
+
|
|
6
|
+
const CHOICES = [
|
|
7
|
+
{
|
|
8
|
+
name: 'user',
|
|
9
|
+
value: 'user',
|
|
10
|
+
description: '~/.claude (applies globally to every project)',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'project',
|
|
14
|
+
value: 'project',
|
|
15
|
+
description: 'nearest ancestor .claude (or <cwd>/.claude)',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
async function selectScopeAsync() {
|
|
19
|
+
const answer = await prompts.select({
|
|
20
|
+
message: pc.bold(pc.cyan('Select injection scope:')),
|
|
21
|
+
choices: CHOICES.map((c) => ({
|
|
22
|
+
name: c.name,
|
|
23
|
+
value: c.value,
|
|
24
|
+
description: pc.dim(c.description),
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
return answer;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
exports.selectScopeAsync = selectScopeAsync;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
|
|
4
|
+
const CHOICES = [
|
|
5
|
+
{
|
|
6
|
+
name: 'user',
|
|
7
|
+
value: 'user',
|
|
8
|
+
description: '~/.claude (applies globally to every project)',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
name: 'project',
|
|
12
|
+
value: 'project',
|
|
13
|
+
description: 'nearest ancestor .claude (or <cwd>/.claude)',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
async function selectScopeAsync() {
|
|
17
|
+
const answer = await select({
|
|
18
|
+
message: pc.bold(pc.cyan('Select injection scope:')),
|
|
19
|
+
choices: CHOICES.map((c) => ({
|
|
20
|
+
name: c.name,
|
|
21
|
+
value: c.value,
|
|
22
|
+
description: pc.dim(c.description),
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
return answer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { selectScopeAsync };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var pc = require('picocolors');
|
|
4
|
+
|
|
5
|
+
function startHeartbeat(options = {}) {
|
|
6
|
+
const intervalMs = options.intervalMs ?? 500;
|
|
7
|
+
const label = options.label ?? 'working';
|
|
8
|
+
const emit = options.emit ??
|
|
9
|
+
((line) => {
|
|
10
|
+
process.stderr.write(line);
|
|
11
|
+
});
|
|
12
|
+
const startedAt = Date.now();
|
|
13
|
+
const timer = setInterval(() => {
|
|
14
|
+
const elapsedMs = Date.now() - startedAt;
|
|
15
|
+
const seconds = (elapsedMs / 1000).toFixed(1);
|
|
16
|
+
emit(`${pc.dim(`[${seconds}s]`)} ${pc.cyan(`${label}...`)}\n`);
|
|
17
|
+
}, intervalMs);
|
|
18
|
+
if (typeof timer.unref === 'function')
|
|
19
|
+
timer.unref();
|
|
20
|
+
return () => {
|
|
21
|
+
clearInterval(timer);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.startHeartbeat = startHeartbeat;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface HeartbeatOptions {
|
|
2
|
+
intervalMs?: number;
|
|
3
|
+
emit?: (line: string) => void;
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
export type StopHeartbeat = () => void;
|
|
7
|
+
/**
|
|
8
|
+
* Wall-clock heartbeat ticker for long-running async operations.
|
|
9
|
+
*
|
|
10
|
+
* Wraps operations at the command layer (NOT core) to provide in-flight
|
|
11
|
+
* visibility when stdout is quiet for several hundred milliseconds.
|
|
12
|
+
*
|
|
13
|
+
* The emitted line is written via the provided `emit` (default: stderr) so
|
|
14
|
+
* it never interferes with programmatic stdout output.
|
|
15
|
+
*/
|
|
16
|
+
export declare function startHeartbeat(options?: HeartbeatOptions): StopHeartbeat;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
|
|
3
|
+
function startHeartbeat(options = {}) {
|
|
4
|
+
const intervalMs = options.intervalMs ?? 500;
|
|
5
|
+
const label = options.label ?? 'working';
|
|
6
|
+
const emit = options.emit ??
|
|
7
|
+
((line) => {
|
|
8
|
+
process.stderr.write(line);
|
|
9
|
+
});
|
|
10
|
+
const startedAt = Date.now();
|
|
11
|
+
const timer = setInterval(() => {
|
|
12
|
+
const elapsedMs = Date.now() - startedAt;
|
|
13
|
+
const seconds = (elapsedMs / 1000).toFixed(1);
|
|
14
|
+
emit(`${pc.dim(`[${seconds}s]`)} ${pc.cyan(`${label}...`)}\n`);
|
|
15
|
+
}, intervalMs);
|
|
16
|
+
if (typeof timer.unref === 'function')
|
|
17
|
+
timer.unref();
|
|
18
|
+
return () => {
|
|
19
|
+
clearInterval(timer);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { startHeartbeat };
|
package/dist/utils/logger.cjs
CHANGED
|
@@ -62,6 +62,13 @@ const logger = {
|
|
|
62
62
|
console.log(pc.yellow(pc.bold('[DRY RUN] No files will be created or modified.')));
|
|
63
63
|
console.log();
|
|
64
64
|
},
|
|
65
|
+
heading(message) {
|
|
66
|
+
console.log();
|
|
67
|
+
console.log(pc.bold(pc.cyan(`▸ ${message}`)));
|
|
68
|
+
},
|
|
69
|
+
accent(message) {
|
|
70
|
+
return pc.cyan(pc.bold(message));
|
|
71
|
+
},
|
|
65
72
|
};
|
|
66
73
|
|
|
67
74
|
exports.logger = logger;
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -54,4 +54,12 @@ export declare const logger: {
|
|
|
54
54
|
* Log dry-run notice
|
|
55
55
|
*/
|
|
56
56
|
dryRunNotice(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Top-level section heading with a distinct accent.
|
|
59
|
+
*/
|
|
60
|
+
heading(message: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Inline accent — cyan bold, for short labels interleaved with content.
|
|
63
|
+
*/
|
|
64
|
+
accent(message: string): string;
|
|
57
65
|
};
|
package/dist/utils/logger.mjs
CHANGED
|
@@ -60,6 +60,13 @@ const logger = {
|
|
|
60
60
|
console.log(pc.yellow(pc.bold('[DRY RUN] No files will be created or modified.')));
|
|
61
61
|
console.log();
|
|
62
62
|
},
|
|
63
|
+
heading(message) {
|
|
64
|
+
console.log();
|
|
65
|
+
console.log(pc.bold(pc.cyan(`▸ ${message}`)));
|
|
66
|
+
},
|
|
67
|
+
accent(message) {
|
|
68
|
+
return pc.cyan(pc.bold(message));
|
|
69
|
+
},
|
|
63
70
|
};
|
|
64
71
|
|
|
65
72
|
export { logger };
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -1,252 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Asset structure type (nested or flat)
|
|
3
|
-
*/
|
|
4
|
-
export type AssetStructure = 'nested' | 'flat';
|
|
5
|
-
/**
|
|
6
|
-
* Configuration for a specific asset type
|
|
7
|
-
*/
|
|
8
|
-
export interface AssetTypeConfig {
|
|
9
|
-
structure: AssetStructure;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Configuration mapping asset types to their structure
|
|
13
|
-
*/
|
|
14
|
-
export interface AssetsConfig {
|
|
15
|
-
[assetType: string]: AssetTypeConfig;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Claude configuration in package.json
|
|
19
|
-
*/
|
|
20
|
-
export interface ClaudeConfig {
|
|
21
|
-
/** Path to Claude assets directory (e.g., "docs/claude") */
|
|
22
|
-
assetPath: string;
|
|
23
|
-
/** Optional configuration for asset types */
|
|
24
|
-
assets?: AssetsConfig;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Repository information from package.json
|
|
28
|
-
*/
|
|
29
|
-
export interface RepositoryInfo {
|
|
30
|
-
type: string;
|
|
31
|
-
url: string;
|
|
32
|
-
directory?: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Parsed package information
|
|
36
|
-
*/
|
|
37
|
-
export interface PackageInfo {
|
|
38
|
-
name: string;
|
|
39
|
-
version: string;
|
|
40
|
-
repository: RepositoryInfo;
|
|
41
|
-
claude?: ClaudeConfig;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Parsed GitHub repository details
|
|
45
|
-
*/
|
|
46
|
-
export interface GitHubRepoInfo {
|
|
47
|
-
owner: string;
|
|
48
|
-
repo: string;
|
|
49
|
-
directory?: string;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* GitHub API file/directory entry
|
|
53
|
-
*/
|
|
54
|
-
export interface GitHubEntry {
|
|
55
|
-
name: string;
|
|
56
|
-
path: string;
|
|
57
|
-
type: 'file' | 'dir';
|
|
58
|
-
download_url: string | null;
|
|
59
|
-
sha: string;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Sync metadata stored in .sync-meta.json
|
|
63
|
-
*/
|
|
64
|
-
export interface SyncMeta {
|
|
65
|
-
/** Package version at sync time */
|
|
66
|
-
version: string;
|
|
67
|
-
/** ISO timestamp of last sync */
|
|
68
|
-
syncedAt: string;
|
|
69
|
-
/** List of synced file names */
|
|
70
|
-
files: string[];
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Asset type (can be any string, not limited to commands/skills/agents)
|
|
74
|
-
*/
|
|
75
|
-
export type AssetType = string;
|
|
76
|
-
/**
|
|
77
|
-
* Sync result for a single package
|
|
78
|
-
*/
|
|
79
|
-
export interface SyncResult {
|
|
80
|
-
packageName: string;
|
|
81
|
-
success: boolean;
|
|
82
|
-
skipped: boolean;
|
|
83
|
-
reason?: string;
|
|
84
|
-
syncedFiles?: Record<string, string[]>;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* CLI options
|
|
88
|
-
*/
|
|
89
|
-
export interface CliOptions {
|
|
90
|
-
package: string[];
|
|
91
|
-
force: boolean;
|
|
92
|
-
dryRun: boolean;
|
|
93
|
-
local: boolean;
|
|
94
|
-
/** Custom git ref (branch, tag, or commit) to fetch from */
|
|
95
|
-
ref?: string;
|
|
96
|
-
/** Use flat structure (default: true in v2) */
|
|
97
|
-
flat?: boolean;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Workspace info from yarn workspaces
|
|
101
|
-
*/
|
|
102
|
-
export interface WorkspaceInfo {
|
|
103
|
-
name: string;
|
|
104
|
-
location: string;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Unified sync metadata for all packages (flat structure)
|
|
108
|
-
*/
|
|
109
|
-
export interface UnifiedSyncMeta {
|
|
110
|
-
/** Schema version for migration support */
|
|
111
|
-
schemaVersion: string;
|
|
112
|
-
/** Last sync timestamp */
|
|
113
|
-
syncedAt: string;
|
|
114
|
-
/** Package metadata keyed by transformed name (e.g., "canard-schemaForm") */
|
|
115
|
-
packages: Record<string, PackageSyncInfo>;
|
|
116
|
-
/** SkillUnit format version marker. Present when data uses SkillUnit[] format. */
|
|
117
|
-
skillUnitFormat?: string;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Individual package sync info within unified meta
|
|
121
|
-
*/
|
|
122
|
-
export interface PackageSyncInfo {
|
|
123
|
-
/** Original package name (e.g., "@canard/schema-form") */
|
|
124
|
-
originalName: string;
|
|
125
|
-
/** Package version at sync time */
|
|
126
|
-
version: string;
|
|
127
|
-
/** Whether this package is from local workspace (true) or remote npm (false/undefined) */
|
|
128
|
-
local?: boolean;
|
|
129
|
-
/** Synced skill units per asset type. Each entry is a SkillUnit (atomic unit of selection). */
|
|
130
|
-
files: Record<string, SkillUnit[]>;
|
|
131
|
-
/** Optional exclusions for selective syncing */
|
|
132
|
-
exclusions?: {
|
|
133
|
-
/** Excluded directory paths (e.g., ["skills/deprecated"]) */
|
|
134
|
-
directories: string[];
|
|
135
|
-
/** Excluded file paths (e.g., ["commands/old-cmd.md"]) */
|
|
136
|
-
files: string[];
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* File name mapping (original to transformed)
|
|
141
|
-
*/
|
|
142
|
-
export interface FileMapping {
|
|
143
|
-
/** Original file name (e.g., "guide.md") */
|
|
144
|
-
original: string;
|
|
145
|
-
/** Transformed file name (e.g., "canard-schemaForm_guide.md") */
|
|
146
|
-
transformed: string;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Represents an atomic skill unit in sync metadata.
|
|
150
|
-
* A skill unit is either a single .md file or a directory skill (containing SKILL.md).
|
|
151
|
-
*/
|
|
152
|
-
export interface SkillUnit {
|
|
153
|
-
/** Skill name (file name without extension, or directory name) */
|
|
154
|
-
name: string;
|
|
155
|
-
/** Whether this is a directory-based skill */
|
|
156
|
-
isDirectory: boolean;
|
|
157
|
-
/** For flat structure: transformed file/directory name */
|
|
158
|
-
transformed?: string;
|
|
159
|
-
/** Internal files within directory skill (for tree browsing, not individual selection).
|
|
160
|
-
* Only present when isDirectory is true.
|
|
161
|
-
* Stores relative paths within the skill directory (e.g., ["SKILL.md", "knowledge/api.md"]) */
|
|
162
|
-
internalFiles?: string[];
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Add command selection result
|
|
166
|
-
*/
|
|
167
|
-
export interface AddCommandSelection {
|
|
168
|
-
/** Package name */
|
|
169
|
-
packageName: string;
|
|
170
|
-
/** Source type */
|
|
171
|
-
source: 'local' | 'npm';
|
|
172
|
-
/** Git ref (branch, tag, or commit) */
|
|
173
|
-
ref?: string;
|
|
174
|
-
/** Included skill units by asset type (skill unit names, not individual file paths) */
|
|
175
|
-
includedAssets: Record<string, string[]>;
|
|
176
|
-
/** Excluded skill units by asset type (skill unit names, not individual file paths) */
|
|
177
|
-
excludedAssets: Record<string, string[]>;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Tree node for asset selection
|
|
181
|
-
*/
|
|
182
|
-
export interface TreeNode {
|
|
183
|
-
/** Unique identifier */
|
|
184
|
-
id: string;
|
|
185
|
-
/** Node label */
|
|
186
|
-
label: string;
|
|
187
|
-
/** Full path */
|
|
188
|
-
path: string;
|
|
189
|
-
/** Node type */
|
|
190
|
-
type: 'directory' | 'file' | 'skill-directory';
|
|
191
|
-
/** Child nodes */
|
|
192
|
-
children?: TreeNode[];
|
|
193
|
-
/** Selection state */
|
|
194
|
-
selected: boolean;
|
|
195
|
-
/** Expanded state */
|
|
196
|
-
expanded: boolean;
|
|
197
|
-
/** Disabled state */
|
|
198
|
-
disabled?: boolean;
|
|
199
|
-
/** If true, this node's children are view-only (cannot be individually selected) */
|
|
200
|
-
viewOnly?: boolean;
|
|
201
|
-
/** Additional metadata */
|
|
202
|
-
metadata?: {
|
|
203
|
-
assetType: string;
|
|
204
|
-
originalName?: string;
|
|
205
|
-
transformedName?: string;
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Re-export asset structure utilities from core module
|
|
210
|
-
*
|
|
211
|
-
* @deprecated These exports are kept for backward compatibility only.
|
|
212
|
-
* Please update your imports to use the recommended paths below.
|
|
213
|
-
*
|
|
214
|
-
* Migration Guide:
|
|
215
|
-
* ================
|
|
216
|
-
*
|
|
217
|
-
* ❌ OLD (Deprecated - will be removed in v1.0.0)
|
|
218
|
-
* ```typescript
|
|
219
|
-
* import {
|
|
220
|
-
* DEFAULT_ASSET_TYPES,
|
|
221
|
-
* DEFAULT_ASSET_STRUCTURES,
|
|
222
|
-
* getAssetStructure,
|
|
223
|
-
* detectStructureType,
|
|
224
|
-
* validateAssetStructure,
|
|
225
|
-
* normalizeAssetStructure,
|
|
226
|
-
* } from './utils/types';
|
|
227
|
-
* ```
|
|
228
|
-
*
|
|
229
|
-
* ✅ NEW (Recommended)
|
|
230
|
-
* ```typescript
|
|
231
|
-
* import {
|
|
232
|
-
* DEFAULT_ASSET_TYPES,
|
|
233
|
-
* DEFAULT_ASSET_STRUCTURES,
|
|
234
|
-
* getAssetStructure,
|
|
235
|
-
* detectStructureType,
|
|
236
|
-
* validateAssetStructure,
|
|
237
|
-
* normalizeAssetStructure,
|
|
238
|
-
* } from './core/assetStructure';
|
|
239
|
-
* ```
|
|
240
|
-
*
|
|
241
|
-
* Why the change?
|
|
242
|
-
* - Clearer module organization (asset structure logic lives in core/)
|
|
243
|
-
* - Direct imports are more maintainable and tree-shake friendly
|
|
244
|
-
* - Reduces coupling between utils and core modules
|
|
245
|
-
*
|
|
246
|
-
* Timeline:
|
|
247
|
-
* - v0.x: Old imports work (with deprecation warnings)
|
|
248
|
-
* - v1.0.0: Re-exports removed
|
|
249
|
-
*
|
|
250
|
-
* @see ../core/assetStructure for the actual implementations
|
|
251
|
-
*/
|
|
252
|
-
export { DEFAULT_ASSET_TYPES, DEFAULT_ASSET_STRUCTURES, getAssetStructure, detectStructureType, validateAssetStructure, normalizeAssetStructure, } from '../core/assetStructure.js';
|
|
1
|
+
export type AssetType = 'skills' | 'commands' | 'rules' | string;
|
package/dist/utils/version.cjs
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
return v1 === v2;
|
|
5
|
-
}
|
|
6
|
-
function needsVersionSync(currentVersion, syncedVersion) {
|
|
7
|
-
if (syncedVersion === undefined) {
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
if (currentVersion === '' || syncedVersion === '') {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
return !compareVersions(currentVersion, syncedVersion);
|
|
14
|
-
}
|
|
3
|
+
const VERSION = '0.2.0';
|
|
15
4
|
|
|
16
|
-
exports.
|
|
17
|
-
exports.needsVersionSync = needsVersionSync;
|
|
5
|
+
exports.VERSION = VERSION;
|
package/dist/utils/version.d.ts
CHANGED
|
@@ -1,55 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* These functions provide exact string-based version comparison
|
|
5
|
-
* for semantic versioning with pre-release and build metadata support.
|
|
2
|
+
* Current package version from package.json
|
|
3
|
+
* Automatically synchronized during build process
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
|
-
* Compare two semantic versions for exact equality
|
|
9
|
-
*
|
|
10
|
-
* Performs case-sensitive exact string comparison of version strings.
|
|
11
|
-
* Supports semver format including pre-release and build metadata:
|
|
12
|
-
* - Major.Minor.Patch (e.g., "1.2.3")
|
|
13
|
-
* - Pre-release (e.g., "1.0.0-alpha", "1.0.0-rc.1")
|
|
14
|
-
* - Build metadata (e.g., "1.0.0+build.123")
|
|
15
|
-
* - Combined (e.g., "1.0.0-rc.1+build.456")
|
|
16
|
-
*
|
|
17
|
-
* @param v1 - First version string
|
|
18
|
-
* @param v2 - Second version string
|
|
19
|
-
* @returns true if versions are exactly equal (case-sensitive)
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* compareVersions('1.0.0', '1.0.0') // true
|
|
23
|
-
* compareVersions('1.0.0', '1.0.1') // false
|
|
24
|
-
* compareVersions('1.0.0-alpha', '1.0.0-Alpha') // false (case-sensitive)
|
|
25
|
-
* compareVersions('1.0.0+build.1', '1.0.0+build.1') // true
|
|
26
|
-
*/
|
|
27
|
-
export declare function compareVersions(v1: string, v2: string): boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Check if version synchronization is needed
|
|
30
|
-
*
|
|
31
|
-
* Determines whether assets need to be re-synced based on version comparison.
|
|
32
|
-
* Sync is needed in the following cases:
|
|
33
|
-
* - First sync (syncedVersion is undefined)
|
|
34
|
-
* - Empty version strings (currentVersion or syncedVersion is empty)
|
|
35
|
-
* - Version mismatch (versions are not exactly equal)
|
|
36
|
-
*
|
|
37
|
-
* @param currentVersion - Current package version from package.json
|
|
38
|
-
* @param syncedVersion - Previously synced version from .sync-meta.json (undefined if never synced)
|
|
39
|
-
* @returns true if sync is needed, false if versions match
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* // First sync
|
|
43
|
-
* needsVersionSync('1.0.0', undefined) // true
|
|
44
|
-
*
|
|
45
|
-
* // Version mismatch
|
|
46
|
-
* needsVersionSync('1.0.1', '1.0.0') // true
|
|
47
|
-
*
|
|
48
|
-
* // Versions match
|
|
49
|
-
* needsVersionSync('1.0.0', '1.0.0') // false
|
|
50
|
-
*
|
|
51
|
-
* // Empty strings
|
|
52
|
-
* needsVersionSync('', '1.0.0') // true
|
|
53
|
-
* needsVersionSync('1.0.0', '') // true
|
|
54
|
-
*/
|
|
55
|
-
export declare function needsVersionSync(currentVersion: string, syncedVersion?: string): boolean;
|
|
5
|
+
export declare const VERSION = "0.2.0";
|
package/dist/utils/version.mjs
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
return v1 === v2;
|
|
3
|
-
}
|
|
4
|
-
function needsVersionSync(currentVersion, syncedVersion) {
|
|
5
|
-
if (syncedVersion === undefined) {
|
|
6
|
-
return true;
|
|
7
|
-
}
|
|
8
|
-
if (currentVersion === '' || syncedVersion === '') {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
return !compareVersions(currentVersion, syncedVersion);
|
|
12
|
-
}
|
|
1
|
+
const VERSION = '0.2.0';
|
|
13
2
|
|
|
14
|
-
export {
|
|
3
|
+
export { VERSION };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Phase 0 — Prompt Library Bundle-Size Decision
|
|
2
|
+
|
|
3
|
+
**Gate threshold**: tree-shaken footprint for `select` + `confirm` ≤ 200 KB.
|
|
4
|
+
|
|
5
|
+
## Measurement setup
|
|
6
|
+
|
|
7
|
+
- Entry: `import { select, confirm } from '@inquirer/prompts'; export { select, confirm };`
|
|
8
|
+
- Bundler: esbuild 0.28.0 via `yarn dlx esbuild`
|
|
9
|
+
- Flags: `--bundle --format=esm --platform=node --external:node:*`
|
|
10
|
+
- Measured from `packages/slats/claude-assets-sync/` with `@inquirer/prompts@^8.4.2` resolved via yarn workspaces.
|
|
11
|
+
|
|
12
|
+
## Results
|
|
13
|
+
|
|
14
|
+
| Variant | Size |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Bundled + minified | **28.5 KB** (29,215 bytes) |
|
|
17
|
+
| Bundled, no minify | 62.0 KB (63,522 bytes) |
|
|
18
|
+
| Raw `node_modules/@inquirer` footprint | 1.6 MB (includes unused prompt families) |
|
|
19
|
+
|
|
20
|
+
The minified bundle represents the realistic runtime cost after slats's Rollup build. The raw node_modules number is not representative because tree-shaking and dead-code elimination eliminate unused prompts from the published `dist/`.
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
**Pinned**: `@inquirer/prompts@^8.4.2` in `dependencies`.
|
|
25
|
+
|
|
26
|
+
**Pinned**: `@inquirer/testing@^3.3.5` in `devDependencies`.
|
|
27
|
+
|
|
28
|
+
The 28.5 KB minified footprint is **7× under the 200 KB threshold**. No fallback to `@clack/prompts` needed.
|
|
29
|
+
|
|
30
|
+
## Fallback plan (unused)
|
|
31
|
+
|
|
32
|
+
If a future `@inquirer/prompts` major release inflates the bundle past 200 KB (e.g., new default imports that resist tree-shaking), replace with `@clack/prompts@^0.7.0` (~30 KB, zero deps) and re-run this measurement. `@clack` lacks a first-party testing kit, so `tests/prompts/*.test.ts` would need to switch to raw stdin mocking.
|
|
33
|
+
|
|
34
|
+
## Artifacts
|
|
35
|
+
|
|
36
|
+
Scratch files removed after measurement: `scratch-entry.mjs`, `scratch-bundle.mjs`, `scratch-bundle-raw.mjs`.
|