@slats/claude-assets-sync 0.2.0 → 0.3.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 +47 -63
- package/bin/inject-claude-settings.mjs +4 -0
- package/dist/claude-hashes.json +9 -9
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/runCli/index.d.ts +1 -1
- package/dist/commands/runCli/runCli.d.ts +10 -6
- package/dist/commands/runCli/runCli.mjs +33 -6
- package/dist/commands/runCli/type.d.ts +4 -12
- package/dist/commands/runCli/utils/classifyTarget.d.ts +19 -0
- package/dist/commands/runCli/utils/classifyTarget.mjs +46 -0
- package/dist/commands/runCli/utils/renderOrFallback.d.ts +6 -0
- package/dist/commands/runCli/utils/renderOrFallback.mjs +12 -0
- package/dist/commands/runCli/utils/renderPlain.d.ts +11 -0
- package/dist/commands/runCli/utils/renderPlain.mjs +89 -0
- package/dist/commands/runCli/utils/resolvePackage.d.ts +16 -0
- package/dist/commands/runCli/utils/resolvePackage.mjs +74 -0
- package/dist/commands/runCli/utils/resolveScopeAlias.d.ts +2 -0
- package/dist/commands/runCli/utils/resolveScopeAlias.mjs +67 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +9 -1
- package/dist/commands/runCli/utils/resolveScopeFlag.mjs +5 -11
- package/dist/commands/runCli/utils/resolveTargets.d.ts +15 -0
- package/dist/commands/runCli/utils/resolveTargets.mjs +38 -0
- package/dist/commands/runCli/utils/toConsumerPackages.d.ts +9 -0
- package/dist/commands/runCli/utils/toConsumerPackages.mjs +26 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/injectDocs/index.d.ts +3 -2
- package/dist/core/injectDocs/type.d.ts +0 -19
- package/dist/core/injectDocs/utils/applyAction.mjs +1 -1
- package/dist/core/scope/index.d.ts +1 -1
- package/dist/core/scope/scope.d.ts +0 -1
- package/dist/core/scope/scope.mjs +1 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/ui/InjectApp/InjectApp.d.ts +2 -0
- package/dist/ui/InjectApp/InjectApp.mjs +82 -0
- package/dist/ui/InjectApp/index.d.ts +2 -0
- package/dist/ui/InjectApp/utils/eventSelectors.d.ts +5 -0
- package/dist/ui/InjectApp/utils/eventSelectors.mjs +24 -0
- package/dist/ui/InjectApp/utils/phaseReducer.d.ts +2 -0
- package/dist/ui/InjectApp/utils/phaseReducer.mjs +130 -0
- package/dist/ui/InjectApp/utils/renderInjectApp.d.ts +2 -0
- package/dist/ui/InjectApp/utils/renderInjectApp.mjs +19 -0
- package/dist/ui/InjectApp/utils/type.d.ts +5 -0
- package/dist/ui/components/ActionRow.d.ts +7 -0
- package/dist/ui/components/ActionRow.mjs +45 -0
- package/dist/ui/components/Banner.d.ts +7 -0
- package/dist/ui/components/Banner.mjs +9 -0
- package/dist/ui/components/ConfirmForce.d.ts +8 -0
- package/dist/ui/components/ConfirmForce.mjs +35 -0
- package/dist/ui/components/ErrorPanel.d.ts +6 -0
- package/dist/ui/components/ErrorPanel.mjs +14 -0
- package/dist/ui/components/Footer.d.ts +8 -0
- package/dist/ui/components/Footer.mjs +27 -0
- package/dist/ui/components/PlanTable.d.ts +8 -0
- package/dist/ui/components/PlanTable.mjs +15 -0
- package/dist/ui/components/ProgressBar.d.ts +10 -0
- package/dist/ui/components/ProgressBar.mjs +28 -0
- package/dist/ui/components/ScopePicker.d.ts +7 -0
- package/dist/ui/components/ScopePicker.mjs +26 -0
- package/dist/ui/components/Spinner.d.ts +8 -0
- package/dist/ui/components/Spinner.mjs +10 -0
- package/dist/ui/components/StatusBadge.d.ts +8 -0
- package/dist/ui/components/StepTracker.d.ts +9 -0
- package/dist/ui/components/StepTracker.mjs +43 -0
- package/dist/ui/components/Summary.d.ts +9 -0
- package/dist/ui/components/Summary.mjs +30 -0
- package/dist/ui/components/TargetCard.d.ts +11 -0
- package/dist/ui/components/TargetCard.mjs +29 -0
- package/dist/ui/hooks/useApplyStep.d.ts +12 -0
- package/dist/ui/hooks/useApplyStep.mjs +30 -0
- package/dist/ui/hooks/useExitApp.d.ts +8 -0
- package/dist/ui/hooks/useExitApp.mjs +19 -0
- package/dist/ui/hooks/useForceConfirmStep.d.ts +9 -0
- package/dist/ui/hooks/useForceConfirmStep.mjs +24 -0
- package/dist/ui/hooks/useInjectSession.d.ts +10 -0
- package/dist/ui/hooks/useInjectSession.mjs +63 -0
- package/dist/ui/hooks/useInterval.d.ts +1 -0
- package/dist/ui/hooks/usePhase.d.ts +2 -0
- package/dist/ui/hooks/usePhase.mjs +9 -0
- package/dist/ui/hooks/usePlanStep.d.ts +13 -0
- package/dist/ui/hooks/usePlanStep.mjs +94 -0
- package/dist/ui/hooks/useResolveStep.d.ts +18 -0
- package/dist/ui/hooks/useResolveStep.mjs +21 -0
- package/dist/ui/hooks/useTerminalWidth.d.ts +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.mjs +16 -0
- package/dist/ui/theme/colors.d.ts +12 -0
- package/dist/ui/theme/colors.mjs +9 -0
- package/dist/ui/theme/icons.d.ts +29 -0
- package/dist/ui/theme/icons.mjs +17 -0
- package/dist/ui/theme/layout.d.ts +20 -0
- package/dist/ui/theme/layout.mjs +9 -0
- package/dist/ui/types/event.d.ts +45 -0
- package/dist/ui/types/index.d.ts +4 -0
- package/dist/ui/types/phase.d.ts +44 -0
- package/dist/ui/types/render.d.ts +6 -0
- package/dist/ui/types/target.d.ts +25 -0
- package/dist/utils/version.d.ts +1 -1
- package/dist/utils/version.mjs +1 -1
- package/docs/claude/skills/claude-docs-asset-wiring/SKILL.md +159 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/claude-md-template.md +78 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/dependency-cruiser.md +54 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/gotchas.md +125 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/package-json-patches.md +150 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/reference-files.md +37 -0
- package/docs/claude/skills/claude-docs-asset-wiring/knowledge/smoke-tests.md +111 -0
- package/docs/consumer-integration.md +43 -101
- package/package.json +13 -8
- package/scripts/dev-ui-fixtures.ts +288 -0
- package/scripts/dev-ui.tsx +289 -0
- package/bin/claude-sync.mjs +0 -24
- package/dist/commands/runCli/runCli.cjs +0 -31
- package/dist/commands/runCli/utils/injectOne.cjs +0 -48
- package/dist/commands/runCli/utils/injectOne.d.ts +0 -3
- package/dist/commands/runCli/utils/injectOne.mjs +0 -46
- package/dist/commands/runCli/utils/resolveScopeFlag.cjs +0 -28
- package/dist/commands/runCli/utils/runInject.cjs +0 -36
- package/dist/commands/runCli/utils/runInject.d.ts +0 -2
- package/dist/commands/runCli/utils/runInject.mjs +0 -34
- package/dist/core/buildPlan/buildPlan.cjs +0 -42
- package/dist/core/buildPlan/utils/toPosix.cjs +0 -9
- package/dist/core/buildPlan/utils/walkFiles.cjs +0 -25
- package/dist/core/hash/hash.cjs +0 -30
- package/dist/core/hashManifest/hashManifest.cjs +0 -27
- package/dist/core/injectDocs/injectDocs.cjs +0 -43
- package/dist/core/injectDocs/injectDocs.d.ts +0 -2
- package/dist/core/injectDocs/injectDocs.mjs +0 -41
- package/dist/core/injectDocs/utils/applyAction.cjs +0 -21
- package/dist/core/injectDocs/utils/emitCiForceList.cjs +0 -10
- package/dist/core/injectDocs/utils/emitCiForceList.d.ts +0 -2
- package/dist/core/injectDocs/utils/emitCiForceList.mjs +0 -8
- package/dist/core/injectDocs/utils/printPlan.cjs +0 -20
- package/dist/core/injectDocs/utils/printPlan.d.ts +0 -2
- package/dist/core/injectDocs/utils/printPlan.mjs +0 -18
- package/dist/core/injectDocs/utils/summarize.cjs +0 -27
- package/dist/core/scope/scope.cjs +0 -46
- package/dist/core/scope/utils/isDirectory.cjs +0 -14
- package/dist/index.cjs +0 -20
- package/dist/prompts/confirmForce.cjs +0 -27
- package/dist/prompts/confirmForce.d.ts +0 -1
- package/dist/prompts/confirmForce.mjs +0 -25
- package/dist/prompts/index.d.ts +0 -2
- package/dist/prompts/selectScope.cjs +0 -30
- package/dist/prompts/selectScope.d.ts +0 -2
- package/dist/prompts/selectScope.mjs +0 -28
- package/dist/utils/asyncPool.cjs +0 -26
- package/dist/utils/heartbeat.cjs +0 -25
- package/dist/utils/heartbeat.d.ts +0 -16
- package/dist/utils/heartbeat.mjs +0 -23
- package/dist/utils/logger.cjs +0 -74
- package/dist/utils/version.cjs +0 -5
- package/docs/claude/skills/claude-sync-applier/SKILL.md +0 -195
- package/docs/claude/skills/claude-sync-applier/knowledge/claude-md-template.md +0 -77
- package/docs/claude/skills/claude-sync-applier/knowledge/dependency-cruiser.md +0 -126
- package/docs/claude/skills/claude-sync-applier/knowledge/gotchas.md +0 -139
- package/docs/claude/skills/claude-sync-applier/knowledge/package-json-patches.md +0 -130
- package/docs/claude/skills/claude-sync-applier/knowledge/reference-files.md +0 -120
- package/docs/claude/skills/claude-sync-applier/knowledge/smoke-tests.md +0 -102
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
import 'node:crypto';
|
|
3
|
+
import 'node:fs/promises';
|
|
4
|
+
import { readHashManifest, computeNamespacePrefixes } from '../../core/hashManifest/hashManifest.mjs';
|
|
5
|
+
import 'node:path';
|
|
6
|
+
import 'picocolors';
|
|
7
|
+
import { buildPlan } from '../../core/buildPlan/buildPlan.mjs';
|
|
8
|
+
import { resolveScope } from '../../core/scope/scope.mjs';
|
|
9
|
+
|
|
10
|
+
function usePlanStep({ targets, scope, originCwd, force, dispatch, onPlansReady, }) {
|
|
11
|
+
const startedRef = useRef(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!scope || startedRef.current)
|
|
14
|
+
return;
|
|
15
|
+
startedRef.current = true;
|
|
16
|
+
let cancelled = false;
|
|
17
|
+
(async () => {
|
|
18
|
+
const results = [];
|
|
19
|
+
const warnings = [];
|
|
20
|
+
for (const target of targets) {
|
|
21
|
+
if (cancelled)
|
|
22
|
+
return;
|
|
23
|
+
dispatch({
|
|
24
|
+
type: 'plan-step',
|
|
25
|
+
step: { packageName: target.name, status: 'running' },
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
if (!target.hashesPresent) {
|
|
29
|
+
dispatch({
|
|
30
|
+
type: 'plan-step',
|
|
31
|
+
step: {
|
|
32
|
+
packageName: target.name,
|
|
33
|
+
status: 'failed',
|
|
34
|
+
error: 'dist/claude-hashes.json missing',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const manifest = await readHashManifest(target.packageRoot);
|
|
40
|
+
const scopeResolution = resolveScope(scope, originCwd);
|
|
41
|
+
const plan = await buildPlan({
|
|
42
|
+
sourceHashes: manifest.files,
|
|
43
|
+
targetRoot: scopeResolution.targetRoot,
|
|
44
|
+
namespacePrefixes: computeNamespacePrefixes(manifest),
|
|
45
|
+
force,
|
|
46
|
+
});
|
|
47
|
+
results.push({ target, scope: scopeResolution, plan });
|
|
48
|
+
for (const action of plan.actions) {
|
|
49
|
+
if (action.kind === 'warn-diverged' || action.kind === 'warn-orphan') {
|
|
50
|
+
warnings.push({
|
|
51
|
+
packageName: target.name,
|
|
52
|
+
kind: action.kind,
|
|
53
|
+
relPath: action.relPath,
|
|
54
|
+
description: action.kind === 'warn-diverged'
|
|
55
|
+
? 'local differs from source (user edit or version change)'
|
|
56
|
+
: 'exists locally but not in manifest',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
dispatch({
|
|
61
|
+
type: 'plan-step',
|
|
62
|
+
step: { packageName: target.name, status: 'done' },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
dispatch({
|
|
67
|
+
type: 'plan-step',
|
|
68
|
+
step: {
|
|
69
|
+
packageName: target.name,
|
|
70
|
+
status: 'failed',
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (cancelled)
|
|
77
|
+
return;
|
|
78
|
+
dispatch({ type: 'plans-ready', plans: results });
|
|
79
|
+
onPlansReady(results, warnings);
|
|
80
|
+
})().catch((error) => {
|
|
81
|
+
if (!cancelled) {
|
|
82
|
+
dispatch({
|
|
83
|
+
type: 'fail',
|
|
84
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return () => {
|
|
89
|
+
cancelled = true;
|
|
90
|
+
};
|
|
91
|
+
}, [targets, scope, originCwd, force, dispatch, onPlansReady]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { usePlanStep };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ConsumerPackage } from '../../commands/runCli/type.js';
|
|
2
|
+
import type { Scope } from '../../core/index.js';
|
|
3
|
+
import type { InjectEvent } from '../types/index.js';
|
|
4
|
+
interface UseResolveStepOptions {
|
|
5
|
+
readonly targets: readonly ConsumerPackage[];
|
|
6
|
+
readonly flags: {
|
|
7
|
+
readonly scope?: string;
|
|
8
|
+
};
|
|
9
|
+
readonly dispatch: (event: InjectEvent) => void;
|
|
10
|
+
readonly onScopeResolved: (scope: Scope) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Ink path is guaranteed TTY by `renderOrFallback`, so interactive
|
|
14
|
+
* scope selection is always safe. Non-TTY invocations go through
|
|
15
|
+
* `renderPlain` + `resolveScopeFlag` which exits 2 on missing scope.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useResolveStep({ targets, flags, dispatch, onScopeResolved, }: UseResolveStepOptions): void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
function useResolveStep({ targets, flags, dispatch, onScopeResolved, }) {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
if (flags.scope === 'user' || flags.scope === 'project') {
|
|
6
|
+
const resolved = flags.scope;
|
|
7
|
+
dispatch({ type: 'scope-selected', scope: resolved });
|
|
8
|
+
dispatch({ type: 'planning-started', targets, scope: resolved });
|
|
9
|
+
onScopeResolved(resolved);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const pending = (scope) => {
|
|
13
|
+
dispatch({ type: 'scope-selected', scope });
|
|
14
|
+
dispatch({ type: 'planning-started', targets, scope });
|
|
15
|
+
onScopeResolved(scope);
|
|
16
|
+
};
|
|
17
|
+
dispatch({ type: 'scope-needed', pending });
|
|
18
|
+
}, [targets, flags.scope, dispatch, onScopeResolved]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { useResolveStep };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useTerminalWidth(): number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { renderInjectApp } from './InjectApp/utils/renderInjectApp.mjs';
|
|
2
|
+
import 'react/jsx-runtime';
|
|
3
|
+
import 'react';
|
|
4
|
+
import 'ink';
|
|
5
|
+
import 'ink-select-input';
|
|
6
|
+
import 'ink-spinner';
|
|
7
|
+
import 'node:fs/promises';
|
|
8
|
+
import 'node:path';
|
|
9
|
+
import 'picocolors';
|
|
10
|
+
import 'node:crypto';
|
|
11
|
+
import 'node:os';
|
|
12
|
+
import 'node:fs';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export { renderInjectApp };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const colors: {
|
|
2
|
+
readonly primary: "cyan";
|
|
3
|
+
readonly success: "green";
|
|
4
|
+
readonly warn: "yellow";
|
|
5
|
+
readonly danger: "red";
|
|
6
|
+
readonly muted: "gray";
|
|
7
|
+
readonly accent: "magenta";
|
|
8
|
+
readonly info: "blue";
|
|
9
|
+
readonly dim: "gray";
|
|
10
|
+
};
|
|
11
|
+
export declare const gradientStops: readonly ["#22d3ee", "#a78bfa", "#f59e0b"];
|
|
12
|
+
export type ColorName = (typeof colors)[keyof typeof colors];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const icons: {
|
|
2
|
+
readonly bulletDone: "●";
|
|
3
|
+
readonly bulletActive: "◐";
|
|
4
|
+
readonly bulletPending: "○";
|
|
5
|
+
readonly triangleRight: "▸";
|
|
6
|
+
readonly check: "✓";
|
|
7
|
+
readonly cross: "✗";
|
|
8
|
+
readonly warning: "⚠";
|
|
9
|
+
readonly question: "?";
|
|
10
|
+
readonly plus: "+";
|
|
11
|
+
readonly equals: "=";
|
|
12
|
+
readonly minus: "−";
|
|
13
|
+
readonly tilde: "~";
|
|
14
|
+
readonly blockFull: "█";
|
|
15
|
+
readonly blockEmpty: "░";
|
|
16
|
+
readonly dash: "─";
|
|
17
|
+
readonly divider: "───";
|
|
18
|
+
readonly boxTopLeft: "╭";
|
|
19
|
+
readonly boxTopRight: "╮";
|
|
20
|
+
readonly boxBottomLeft: "╰";
|
|
21
|
+
readonly boxBottomRight: "╯";
|
|
22
|
+
readonly boxHorizontal: "─";
|
|
23
|
+
readonly boxVertical: "│";
|
|
24
|
+
readonly boxDoubleTopLeft: "┌";
|
|
25
|
+
readonly boxDoubleTopRight: "┐";
|
|
26
|
+
readonly boxDoubleBottomLeft: "└";
|
|
27
|
+
readonly boxDoubleBottomRight: "┘";
|
|
28
|
+
};
|
|
29
|
+
export type IconName = keyof typeof icons;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const icons = {
|
|
2
|
+
bulletDone: '●',
|
|
3
|
+
bulletActive: '◐',
|
|
4
|
+
bulletPending: '○',
|
|
5
|
+
triangleRight: '▸',
|
|
6
|
+
check: '✓',
|
|
7
|
+
cross: '✗',
|
|
8
|
+
warning: '⚠',
|
|
9
|
+
question: '?',
|
|
10
|
+
plus: '+',
|
|
11
|
+
equals: '=',
|
|
12
|
+
minus: '−',
|
|
13
|
+
blockFull: '█',
|
|
14
|
+
blockEmpty: '░',
|
|
15
|
+
divider: '───'};
|
|
16
|
+
|
|
17
|
+
export { icons };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const spacing: {
|
|
2
|
+
readonly xs: 0;
|
|
3
|
+
readonly sm: 1;
|
|
4
|
+
readonly md: 2;
|
|
5
|
+
readonly lg: 3;
|
|
6
|
+
readonly xl: 4;
|
|
7
|
+
};
|
|
8
|
+
export declare const widths: {
|
|
9
|
+
readonly statusBadge: 10;
|
|
10
|
+
readonly pathColumn: 60;
|
|
11
|
+
readonly progressBarDefault: 28;
|
|
12
|
+
readonly targetCardCount: 18;
|
|
13
|
+
readonly minTerminalWidth: 60;
|
|
14
|
+
readonly idealTerminalWidth: 120;
|
|
15
|
+
};
|
|
16
|
+
export declare const limits: {
|
|
17
|
+
readonly maxWarningsBeforeCollapse: 10;
|
|
18
|
+
readonly maxPlanRowsBeforeTruncate: 40;
|
|
19
|
+
readonly planTruncatedReveal: 15;
|
|
20
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ConsumerPackage } from '../../commands/runCli/type.js';
|
|
2
|
+
import type { InjectReport, Scope } from '../../core/index.js';
|
|
3
|
+
import type { PlanStepState, TargetPlan, Warning } from './target.js';
|
|
4
|
+
export type InjectEvent = {
|
|
5
|
+
readonly type: 'scope-needed';
|
|
6
|
+
readonly pending: (scope: Scope) => void;
|
|
7
|
+
} | {
|
|
8
|
+
readonly type: 'scope-selected';
|
|
9
|
+
readonly scope: Scope;
|
|
10
|
+
} | {
|
|
11
|
+
readonly type: 'planning-started';
|
|
12
|
+
readonly targets: readonly ConsumerPackage[];
|
|
13
|
+
readonly scope: Scope;
|
|
14
|
+
} | {
|
|
15
|
+
readonly type: 'plan-step';
|
|
16
|
+
readonly step: PlanStepState;
|
|
17
|
+
} | {
|
|
18
|
+
readonly type: 'plans-ready';
|
|
19
|
+
readonly plans: readonly TargetPlan[];
|
|
20
|
+
} | {
|
|
21
|
+
readonly type: 'force-confirm-required';
|
|
22
|
+
readonly warnings: readonly Warning[];
|
|
23
|
+
readonly pending: (ok: boolean) => void;
|
|
24
|
+
} | {
|
|
25
|
+
readonly type: 'force-answer';
|
|
26
|
+
readonly ok: boolean;
|
|
27
|
+
} | {
|
|
28
|
+
readonly type: 'apply-start';
|
|
29
|
+
readonly total: number;
|
|
30
|
+
} | {
|
|
31
|
+
readonly type: 'apply-progress';
|
|
32
|
+
readonly done: number;
|
|
33
|
+
readonly current?: string;
|
|
34
|
+
} | {
|
|
35
|
+
readonly type: 'done';
|
|
36
|
+
readonly reports: readonly InjectReport[];
|
|
37
|
+
readonly exitCode: 0 | 1 | 2;
|
|
38
|
+
readonly dryRun: boolean;
|
|
39
|
+
} | {
|
|
40
|
+
readonly type: 'fail';
|
|
41
|
+
readonly error: Error;
|
|
42
|
+
} | {
|
|
43
|
+
readonly type: 'focus-target';
|
|
44
|
+
readonly index: number;
|
|
45
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ConsumerPackage } from '../../commands/runCli/type.js';
|
|
2
|
+
import type { InjectReport, Scope } from '../../core/index.js';
|
|
3
|
+
import type { ApplyProgress, PlanStepState, TargetPlan, Warning } from './target.js';
|
|
4
|
+
export type Phase = {
|
|
5
|
+
readonly kind: 'booting';
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: 'resolving';
|
|
8
|
+
readonly targets: readonly ConsumerPackage[];
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: 'scope-select';
|
|
11
|
+
readonly targets: readonly ConsumerPackage[];
|
|
12
|
+
readonly pending: (scope: Scope) => void;
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: 'planning';
|
|
15
|
+
readonly targets: readonly ConsumerPackage[];
|
|
16
|
+
readonly scope: Scope;
|
|
17
|
+
readonly progress: ReadonlyMap<string, PlanStepState>;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'diff-review';
|
|
20
|
+
readonly plans: readonly TargetPlan[];
|
|
21
|
+
readonly focusedIndex: number;
|
|
22
|
+
readonly scope: Scope;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'force-confirm';
|
|
25
|
+
readonly plans: readonly TargetPlan[];
|
|
26
|
+
readonly warnings: readonly Warning[];
|
|
27
|
+
readonly pending: (ok: boolean) => void;
|
|
28
|
+
readonly scope: Scope;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: 'applying';
|
|
31
|
+
readonly plans: readonly TargetPlan[];
|
|
32
|
+
readonly progress: ApplyProgress;
|
|
33
|
+
readonly scope: Scope;
|
|
34
|
+
} | {
|
|
35
|
+
readonly kind: 'summary';
|
|
36
|
+
readonly reports: readonly InjectReport[];
|
|
37
|
+
readonly plans: readonly TargetPlan[];
|
|
38
|
+
readonly exitCode: 0 | 1 | 2;
|
|
39
|
+
readonly scope: Scope;
|
|
40
|
+
readonly dryRun: boolean;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: 'error';
|
|
43
|
+
readonly error: Error;
|
|
44
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { InjectPlan } from '../../core/buildPlan/index.js';
|
|
2
|
+
import type { ScopeResolution } from '../../core/index.js';
|
|
3
|
+
import type { ConsumerPackage } from '../../commands/runCli/type.js';
|
|
4
|
+
export interface PlanStepState {
|
|
5
|
+
readonly packageName: string;
|
|
6
|
+
readonly status: 'pending' | 'running' | 'done' | 'failed';
|
|
7
|
+
readonly error?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface TargetPlan {
|
|
10
|
+
readonly target: ConsumerPackage;
|
|
11
|
+
readonly scope: ScopeResolution;
|
|
12
|
+
readonly plan: InjectPlan;
|
|
13
|
+
}
|
|
14
|
+
export interface Warning {
|
|
15
|
+
readonly packageName: string;
|
|
16
|
+
readonly kind: 'warn-diverged' | 'warn-orphan';
|
|
17
|
+
readonly relPath: string;
|
|
18
|
+
readonly description: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ApplyProgress {
|
|
21
|
+
readonly total: number;
|
|
22
|
+
readonly done: number;
|
|
23
|
+
readonly current?: string;
|
|
24
|
+
readonly startedAt: number;
|
|
25
|
+
}
|
package/dist/utils/version.d.ts
CHANGED
package/dist/utils/version.mjs
CHANGED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude-docs-asset-wiring
|
|
3
|
+
description: "Wire a consumer package's docs/claude assets into the @slats/claude-assets-sync engine. Adds package.json.claude.assetPath, points scripts.build:hashes at claude-build-hashes, declares the engine as a dependency, updates CLAUDE.md, and runs the dispatcher smoke test. Idempotent — asks before clobbering."
|
|
4
|
+
user-invocable: true
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
argument-hint: <target-package-path>
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# claude-docs-asset-wiring
|
|
10
|
+
|
|
11
|
+
Wire a consumer package's `docs/claude/**` into `@slats/claude-assets-sync`
|
|
12
|
+
so end users can inject those assets via the engine's `inject-claude-settings`
|
|
13
|
+
bin. Reference consumer: `packages/canard/schema-form`.
|
|
14
|
+
|
|
15
|
+
The engine is single-dispatcher. Consumers do NOT ship their own bin stubs
|
|
16
|
+
— they declare `claude.assetPath` in `package.json` and let the engine's
|
|
17
|
+
`claude-build-hashes` bin regenerate `dist/claude-hashes.json` during
|
|
18
|
+
build. `src/core/**` never reads `package.json`; only the engine's `bin/`
|
|
19
|
+
layer resolves a single explicitly-named target.
|
|
20
|
+
|
|
21
|
+
**Outcome**
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx -p @slats/claude-assets-sync inject-claude-settings \
|
|
25
|
+
--package=<PACKAGE_NAME> \
|
|
26
|
+
--scope=user|project [--dry-run] [--force]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Role
|
|
30
|
+
|
|
31
|
+
You are a monorepo wiring specialist. Execute the 6 steps below as a
|
|
32
|
+
single, idempotent procedure. On any conflicting existing value — ask
|
|
33
|
+
the user before overwriting. Never clobber silently.
|
|
34
|
+
|
|
35
|
+
## Knowledge Resources
|
|
36
|
+
|
|
37
|
+
Consult these files as needed during execution. Do NOT preload everything;
|
|
38
|
+
load on demand.
|
|
39
|
+
|
|
40
|
+
- `knowledge/reference-files.md` — what the consumer should (and should not) own
|
|
41
|
+
- `knowledge/package-json-patches.md` — every required `package.json` edit, with guard conditions
|
|
42
|
+
- `knowledge/claude-md-template.md` — the `## Claude Docs Injector` section to inject into the target `CLAUDE.md`
|
|
43
|
+
- `knowledge/smoke-tests.md` — E2E 8-path matrix via the engine dispatcher
|
|
44
|
+
- `knowledge/dependency-cruiser.md` — optional CI-time isolation rule
|
|
45
|
+
- `knowledge/gotchas.md` — invariants and pitfalls
|
|
46
|
+
|
|
47
|
+
## Inputs
|
|
48
|
+
|
|
49
|
+
Resolve these before starting. If any is missing, stop and ask.
|
|
50
|
+
|
|
51
|
+
| Variable | Source |
|
|
52
|
+
|----------------|-----------------------------------------------------------------------------------------------------------|
|
|
53
|
+
| `TARGET_PATH` | Skill argument (e.g. `packages/lerx/promise-modal`). If absent, ask the user. |
|
|
54
|
+
| `PACKAGE_NAME` | `name` field of `${TARGET_PATH}/package.json`. |
|
|
55
|
+
| `SHORTCUT` | Root `package.json` `scripts` entry whose value equals `yarn workspace ${PACKAGE_NAME}`; else unset. |
|
|
56
|
+
|
|
57
|
+
`SHORTCUT` is a convenience only. When unset, fall back to full workspace
|
|
58
|
+
syntax: `yarn workspace ${PACKAGE_NAME} <subcommand>`.
|
|
59
|
+
|
|
60
|
+
## Pre-Flight
|
|
61
|
+
|
|
62
|
+
Stop and report on any failure. Do not attempt to fix silently.
|
|
63
|
+
|
|
64
|
+
- [ ] `${TARGET_PATH}/docs/claude/skills/<name>/SKILL.md` and `knowledge/*.md` exist — the docs to be injected.
|
|
65
|
+
- [ ] `${TARGET_PATH}/package.json` has `"type": "module"` and `"sideEffects": false`.
|
|
66
|
+
- [ ] Build pipeline uses `rollup -c && yarn build:types` where `build:types` runs `node ../../aileron/script/build/buildTypes.mjs`.
|
|
67
|
+
- [ ] `git status` in `${TARGET_PATH}` is clean. Unrelated changes present → confirm with user before proceeding.
|
|
68
|
+
|
|
69
|
+
## Steps
|
|
70
|
+
|
|
71
|
+
Execute in order. Each step is idempotent; on conflict, ask rather than overwrite.
|
|
72
|
+
|
|
73
|
+
### Step 1 — Patch `${TARGET_PATH}/package.json`
|
|
74
|
+
|
|
75
|
+
See `knowledge/package-json-patches.md` for the complete patch list:
|
|
76
|
+
|
|
77
|
+
- `claude.assetPath` — set to `docs/claude` (or the consumer's chosen path).
|
|
78
|
+
- `scripts.build` — ensure the chain ends with `&& yarn build:hashes`.
|
|
79
|
+
- `scripts.build:hashes` — set to `claude-build-hashes` (the engine's bin).
|
|
80
|
+
- `scripts.prepublishOnly` — `yarn build` if not already present.
|
|
81
|
+
- `devDependencies."@slats/claude-assets-sync"` — add (NOT `dependencies`, NOT `peerDependencies`). The engine is CLI-only and must not leak into end-user production installs.
|
|
82
|
+
- `files` — ensure `"dist"`, `"docs"`, `"README.md"` are listed. Never include `"bin"` or `"scripts"`.
|
|
83
|
+
|
|
84
|
+
Do NOT add any `bin` entry. Do NOT add `./bin/*` or `./docs/*` to `exports`.
|
|
85
|
+
Do NOT create `bin/` or `scripts/` directories in the consumer.
|
|
86
|
+
|
|
87
|
+
### Step 2 — Patch `${TARGET_PATH}/CLAUDE.md`
|
|
88
|
+
|
|
89
|
+
If `CLAUDE.md` exists, append or replace the `## Claude Docs Injector`
|
|
90
|
+
section from `knowledge/claude-md-template.md`, substituting
|
|
91
|
+
`${PACKAGE_NAME}`. Skip if `CLAUDE.md` does not exist (do not create one).
|
|
92
|
+
|
|
93
|
+
### Step 3 — (Optional) Dependency-cruiser isolation gate
|
|
94
|
+
|
|
95
|
+
Skip unless `${TARGET_PATH}/.dependency-cruiser.cjs` already exists or the
|
|
96
|
+
user explicitly asks. See `knowledge/dependency-cruiser.md` for the single
|
|
97
|
+
remaining forbidden rule (`src/**` → `docs/**`) and the `depcheck` script.
|
|
98
|
+
|
|
99
|
+
### Step 4 — Install and build
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
yarn install
|
|
103
|
+
yarn ${SHORTCUT:-workspace ${PACKAGE_NAME}} build
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Expected: `rollup` → `buildTypes` → `claude-build-hashes` succeed, and
|
|
107
|
+
`${TARGET_PATH}/dist/claude-hashes.json` is written.
|
|
108
|
+
|
|
109
|
+
### Step 5 — E2E smoke via engine dispatcher
|
|
110
|
+
|
|
111
|
+
Run from `/tmp/...`, never from the monorepo root or `${TARGET_PATH}/` —
|
|
112
|
+
`--scope=project` walks `cwd` upward looking for an existing `.claude`,
|
|
113
|
+
which would mutate the real repo's. See `knowledge/smoke-tests.md` for
|
|
114
|
+
the full 8-path matrix, expected exit codes, and rationale.
|
|
115
|
+
|
|
116
|
+
### Step 6 — Report
|
|
117
|
+
|
|
118
|
+
Summarize:
|
|
119
|
+
|
|
120
|
+
- Files patched vs. skipped (with reason for each skip).
|
|
121
|
+
- Manifest file count from `dist/claude-hashes.json`.
|
|
122
|
+
- Smoke-test exit codes (all 8).
|
|
123
|
+
- Recommendation: commit this change on its own, separate from other work.
|
|
124
|
+
|
|
125
|
+
## Report Template
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
## claude-docs-asset-wiring — ${PACKAGE_NAME}
|
|
129
|
+
|
|
130
|
+
**Files patched**
|
|
131
|
+
- package.json — patched: [claude.assetPath, scripts.build, scripts.build:hashes, dependencies, files]
|
|
132
|
+
- CLAUDE.md — section added | skipped (no CLAUDE.md)
|
|
133
|
+
- .dependency-cruiser.cjs — updated | skipped (not present)
|
|
134
|
+
|
|
135
|
+
**Manifest**
|
|
136
|
+
- dist/claude-hashes.json: <N> files
|
|
137
|
+
|
|
138
|
+
**Smoke tests**
|
|
139
|
+
| # | command | expected | actual |
|
|
140
|
+
|---|-------------------------------------------------------------|----------|--------|
|
|
141
|
+
| 1 | --package=${PACKAGE_NAME} --scope=project --dry-run | 0 | <n> |
|
|
142
|
+
| 2 | --package=${PACKAGE_NAME} --scope=project | 0 | <n> |
|
|
143
|
+
| 3 | --package=${PACKAGE_NAME} --scope=project (up-to-date) | 0 | <n> |
|
|
144
|
+
| 4 | CI=true --package=${PACKAGE_NAME} --scope=project (tampered)| 2 | <n> |
|
|
145
|
+
| 5 | CI=true --package=${PACKAGE_NAME} --scope=project --force | 0 | <n> |
|
|
146
|
+
| 6 | CI=true --package=${PACKAGE_NAME} (missing --scope) | 2 | <n> |
|
|
147
|
+
| 7 | (missing --package) | 2 | <n> |
|
|
148
|
+
| 8 | --package=@does/not-exist | 2 | <n> |
|
|
149
|
+
|
|
150
|
+
**Next**: commit on its own — do not bundle with unrelated changes.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Termination Conditions
|
|
154
|
+
|
|
155
|
+
- **Pre-Flight fails** → stop, report the failing check. Do not proceed.
|
|
156
|
+
- **Conflict during patch** → stop, show the diff, ask user whether to overwrite.
|
|
157
|
+
- **Build fails at Step 4** → stop, report error. Do not run smoke tests on a broken build.
|
|
158
|
+
- **Smoke test mismatch** → stop, report the failing path with captured exit code.
|
|
159
|
+
- **All steps pass** → emit the report from the template above.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# `CLAUDE.md` — `## Claude Docs Injector` section
|
|
2
|
+
|
|
3
|
+
Reference: `packages/canard/schema-form/CLAUDE.md`.
|
|
4
|
+
|
|
5
|
+
Append the section below to `${TARGET_PATH}/CLAUDE.md` if the file
|
|
6
|
+
exists. Substitute the sample package name in the chosen template
|
|
7
|
+
with `${PACKAGE_NAME}` — four occurrences. Skip the entire step if
|
|
8
|
+
`CLAUDE.md` does not exist (do not create one).
|
|
9
|
+
|
|
10
|
+
The template is intentionally terse: CLI usage + essential isolation
|
|
11
|
+
warnings. Architectural rationale lives in `knowledge/gotchas.md` —
|
|
12
|
+
do not duplicate it into every consumer's `CLAUDE.md`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Template (Korean — used by all consumers except `@winglet/style-utils`)
|
|
17
|
+
|
|
18
|
+
````markdown
|
|
19
|
+
## Claude Docs Injector
|
|
20
|
+
|
|
21
|
+
`docs/claude/**` 자산을 사용자 `.claude/` 에 주입. 엔진: `@slats/claude-assets-sync` (bin: `inject-claude-settings`). 엔진은 `devDependencies` 에만 있으므로 항상 `npx -p @slats/claude-assets-sync ...` 로 호출합니다.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@canard/schema-form --scope=user
|
|
25
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@canard/schema-form --scope=project
|
|
26
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@canard/schema-form --scope=user --dry-run
|
|
27
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@canard/schema-form --scope=user --force
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Isolation Guardrails
|
|
31
|
+
|
|
32
|
+
- `src/**` 는 `docs/**` 와 `@slats/claude-assets-sync` 어느 것도 import 금지.
|
|
33
|
+
- **절대 `exports` 에 `./docs/*` 를 추가하지 말 것.**
|
|
34
|
+
````
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Template (English — `@winglet/style-utils` convention)
|
|
39
|
+
|
|
40
|
+
````markdown
|
|
41
|
+
## Claude Docs Injector
|
|
42
|
+
|
|
43
|
+
Inject `docs/claude/**` into the user's `.claude/`. Engine: `@slats/claude-assets-sync` (bin: `inject-claude-settings`). The engine is declared only in `devDependencies`, so always invoke via `npx -p @slats/claude-assets-sync ...`.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@winglet/style-utils --scope=user
|
|
47
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@winglet/style-utils --scope=project
|
|
48
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@winglet/style-utils --scope=user --dry-run
|
|
49
|
+
npx -p @slats/claude-assets-sync inject-claude-settings --package=@winglet/style-utils --scope=user --force
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Isolation Guardrails
|
|
53
|
+
|
|
54
|
+
- `src/**` MUST NOT import from `docs/**` or `@slats/claude-assets-sync`.
|
|
55
|
+
- **Never add `./docs/*` to `exports`.**
|
|
56
|
+
````
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Substitution Rules
|
|
61
|
+
|
|
62
|
+
- Replace the sample package name in the chosen template with
|
|
63
|
+
`${PACKAGE_NAME}` — four occurrences.
|
|
64
|
+
- Preserve the Isolation Guardrails bullets verbatim — these are
|
|
65
|
+
the sharp invariants that must stay consistent across consumers.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Placement & Skip Conditions
|
|
70
|
+
|
|
71
|
+
- Append to end of `CLAUDE.md`. Ensure one blank line before the
|
|
72
|
+
injected section.
|
|
73
|
+
- `${TARGET_PATH}/CLAUDE.md` does not exist → skip, report
|
|
74
|
+
"skipped (no CLAUDE.md)".
|
|
75
|
+
- Section already present with identical content → skip, report
|
|
76
|
+
"unchanged".
|
|
77
|
+
- Section present with different content → ask user, do not
|
|
78
|
+
clobber.
|