@solaqua/skul 0.1.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/LICENSE +15 -0
- package/README.md +282 -0
- package/bin/skul.js +13 -0
- package/dist/bundle-discovery.d.ts +30 -0
- package/dist/bundle-discovery.js +284 -0
- package/dist/bundle-discovery.js.map +1 -0
- package/dist/bundle-fetch.d.ts +67 -0
- package/dist/bundle-fetch.js +378 -0
- package/dist/bundle-fetch.js.map +1 -0
- package/dist/bundle-items.d.ts +34 -0
- package/dist/bundle-items.js +149 -0
- package/dist/bundle-items.js.map +1 -0
- package/dist/bundle-manifest.d.ts +26 -0
- package/dist/bundle-manifest.js +196 -0
- package/dist/bundle-manifest.js.map +1 -0
- package/dist/bundle-materialization.d.ts +52 -0
- package/dist/bundle-materialization.js +587 -0
- package/dist/bundle-materialization.js.map +1 -0
- package/dist/bundle-translation.d.ts +38 -0
- package/dist/bundle-translation.js +502 -0
- package/dist/bundle-translation.js.map +1 -0
- package/dist/cli.d.ts +126 -0
- package/dist/cli.js +648 -0
- package/dist/cli.js.map +1 -0
- package/dist/fs-utils.d.ts +7 -0
- package/dist/fs-utils.js +27 -0
- package/dist/fs-utils.js.map +1 -0
- package/dist/git-context.d.ts +14 -0
- package/dist/git-context.js +53 -0
- package/dist/git-context.js.map +1 -0
- package/dist/git-exclude.d.ts +13 -0
- package/dist/git-exclude.js +76 -0
- package/dist/git-exclude.js.map +1 -0
- package/dist/git-index.d.ts +106 -0
- package/dist/git-index.js +224 -0
- package/dist/git-index.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +4190 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +91 -0
- package/dist/registry.js +551 -0
- package/dist/registry.js.map +1 -0
- package/dist/root-instruction-content.d.ts +11 -0
- package/dist/root-instruction-content.js +61 -0
- package/dist/root-instruction-content.js.map +1 -0
- package/dist/root-instruction-render.d.ts +31 -0
- package/dist/root-instruction-render.js +121 -0
- package/dist/root-instruction-render.js.map +1 -0
- package/dist/root-instruction-state.d.ts +41 -0
- package/dist/root-instruction-state.js +273 -0
- package/dist/root-instruction-state.js.map +1 -0
- package/dist/state-layout.d.ts +11 -0
- package/dist/state-layout.js +26 -0
- package/dist/state-layout.js.map +1 -0
- package/dist/tool-mapping.d.ts +35 -0
- package/dist/tool-mapping.js +227 -0
- package/dist/tool-mapping.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ToolName } from "./tool-mapping";
|
|
2
|
+
/** Joins root-instruction parts into one normalized document body. */
|
|
3
|
+
export declare function composeRootInstructionContent(parts: Array<string | undefined>): string;
|
|
4
|
+
export interface RenderTrackedRootInstructionShadowOptions {
|
|
5
|
+
baseContent?: string;
|
|
6
|
+
overlayContent: string;
|
|
7
|
+
bundleName: string;
|
|
8
|
+
toolName: ToolName;
|
|
9
|
+
strategy: "append" | "prepend" | "replace";
|
|
10
|
+
allowReplace?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RenderTrackedRootInstructionShadowResult {
|
|
13
|
+
overlay: string;
|
|
14
|
+
rendered: string;
|
|
15
|
+
overlayFingerprint: string;
|
|
16
|
+
renderedFingerprint: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders a deterministic tracked root-instruction shadow plus the
|
|
20
|
+
* fingerprints later lifecycle commands use to detect stale overlays and
|
|
21
|
+
* local manual edits.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderTrackedRootInstructionShadow(options: RenderTrackedRootInstructionShadowOptions): RenderTrackedRootInstructionShadowResult;
|
|
24
|
+
/** Wraps one bundle's root-instruction content with explicit boundary markers. */
|
|
25
|
+
export declare function wrapRootInstructionBundleContent(options: {
|
|
26
|
+
bundleName: string;
|
|
27
|
+
source?: string;
|
|
28
|
+
content: string;
|
|
29
|
+
}): string;
|
|
30
|
+
/** Returns whether a repo-relative path is a managed root-instruction file. */
|
|
31
|
+
export declare function isRootInstructionPath(repoRelativePath: string): boolean;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.composeRootInstructionContent = composeRootInstructionContent;
|
|
4
|
+
exports.renderTrackedRootInstructionShadow = renderTrackedRootInstructionShadow;
|
|
5
|
+
exports.wrapRootInstructionBundleContent = wrapRootInstructionBundleContent;
|
|
6
|
+
exports.isRootInstructionPath = isRootInstructionPath;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const tool_mapping_1 = require("./tool-mapping");
|
|
9
|
+
const ROOT_INSTRUCTION_PATHS = new Set([
|
|
10
|
+
...(0, tool_mapping_1.listToolDefinitions)()
|
|
11
|
+
.map((tool) => tool.targets.root_instruction?.path)
|
|
12
|
+
.filter((p) => p !== undefined),
|
|
13
|
+
...(0, tool_mapping_1.listGlobalToolDefinitions)()
|
|
14
|
+
.map((tool) => tool.targets.root_instruction?.path)
|
|
15
|
+
.filter((p) => p !== undefined),
|
|
16
|
+
]);
|
|
17
|
+
/** Joins root-instruction parts into one normalized document body. */
|
|
18
|
+
function composeRootInstructionContent(parts) {
|
|
19
|
+
return parts
|
|
20
|
+
.map((part) => normalizeRootInstructionPart(part))
|
|
21
|
+
.filter((part) => part.length > 0)
|
|
22
|
+
.join("\n\n");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Renders a deterministic tracked root-instruction shadow plus the
|
|
26
|
+
* fingerprints later lifecycle commands use to detect stale overlays and
|
|
27
|
+
* local manual edits.
|
|
28
|
+
*/
|
|
29
|
+
function renderTrackedRootInstructionShadow(options) {
|
|
30
|
+
if (options.strategy === "replace" && options.allowReplace !== true) {
|
|
31
|
+
throw new Error(`Tracked root-instruction replace strategy for ${options.toolName} requires explicit confirmation`);
|
|
32
|
+
}
|
|
33
|
+
const normalizedOverlayContent = normalizeRootInstructionPart(options.overlayContent);
|
|
34
|
+
const overlay = options.strategy === "replace"
|
|
35
|
+
? normalizedOverlayContent
|
|
36
|
+
: formatTrackedRootInstructionShadowBlock({
|
|
37
|
+
bundleName: options.bundleName,
|
|
38
|
+
content: normalizedOverlayContent,
|
|
39
|
+
});
|
|
40
|
+
const rendered = renderTrackedRootInstructionDocument({
|
|
41
|
+
baseContent: options.baseContent,
|
|
42
|
+
overlay,
|
|
43
|
+
strategy: options.strategy,
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
overlay,
|
|
47
|
+
rendered,
|
|
48
|
+
overlayFingerprint: fingerprintRootInstructionContent(overlay),
|
|
49
|
+
renderedFingerprint: fingerprintRootInstructionContent(rendered),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Wraps one bundle's root-instruction content with explicit boundary markers. */
|
|
53
|
+
function wrapRootInstructionBundleContent(options) {
|
|
54
|
+
const normalizedContent = normalizeRootInstructionPart(options.content);
|
|
55
|
+
if (normalizedContent.length === 0) {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
const label = options.source
|
|
59
|
+
? `${options.bundleName} (${options.source})`
|
|
60
|
+
: options.bundleName;
|
|
61
|
+
return [
|
|
62
|
+
`<!-- BEGIN SKUL BUNDLE: ${label} -->`,
|
|
63
|
+
normalizedContent,
|
|
64
|
+
`<!-- END SKUL BUNDLE: ${label} -->`,
|
|
65
|
+
].join("\n");
|
|
66
|
+
}
|
|
67
|
+
/** Wraps tracked shadow overlay content with deterministic marker boundaries. */
|
|
68
|
+
function formatTrackedRootInstructionShadowBlock(options) {
|
|
69
|
+
const normalizedContent = normalizeRootInstructionPart(options.content);
|
|
70
|
+
if (normalizedContent.length === 0) {
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
return [
|
|
74
|
+
`<!-- SKUL SHADOW START bundle=${options.bundleName} -->`,
|
|
75
|
+
normalizedContent,
|
|
76
|
+
"<!-- SKUL SHADOW END -->",
|
|
77
|
+
].join("\n");
|
|
78
|
+
}
|
|
79
|
+
/** Returns whether content still matches the recorded shadow render fingerprint. */
|
|
80
|
+
function hasTrackedRootInstructionManualEdit(options) {
|
|
81
|
+
return (fingerprintRootInstructionContent(options.content) !==
|
|
82
|
+
options.renderedFingerprint);
|
|
83
|
+
}
|
|
84
|
+
/** Returns whether a repo-relative path is a managed root-instruction file. */
|
|
85
|
+
function isRootInstructionPath(repoRelativePath) {
|
|
86
|
+
return ROOT_INSTRUCTION_PATHS.has(repoRelativePath);
|
|
87
|
+
}
|
|
88
|
+
function renderTrackedRootInstructionDocument(options) {
|
|
89
|
+
if (options.strategy === "replace") {
|
|
90
|
+
return ensureTrailingNewline(options.overlay);
|
|
91
|
+
}
|
|
92
|
+
if (options.overlay.length === 0) {
|
|
93
|
+
return options.baseContent ?? "";
|
|
94
|
+
}
|
|
95
|
+
if (!options.baseContent || options.baseContent.length === 0) {
|
|
96
|
+
return ensureTrailingNewline(options.overlay);
|
|
97
|
+
}
|
|
98
|
+
if (options.strategy === "prepend") {
|
|
99
|
+
return `${options.overlay}\n\n${options.baseContent}`;
|
|
100
|
+
}
|
|
101
|
+
return `${options.baseContent}${selectAppendSeparator(options.baseContent)}${options.overlay}\n`;
|
|
102
|
+
}
|
|
103
|
+
function fingerprintRootInstructionContent(content) {
|
|
104
|
+
return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
|
|
105
|
+
}
|
|
106
|
+
function ensureTrailingNewline(content) {
|
|
107
|
+
return content.length === 0 ? "" : `${content}\n`;
|
|
108
|
+
}
|
|
109
|
+
function selectAppendSeparator(baseContent) {
|
|
110
|
+
if (baseContent.endsWith("\n\n")) {
|
|
111
|
+
return "";
|
|
112
|
+
}
|
|
113
|
+
if (baseContent.endsWith("\n")) {
|
|
114
|
+
return "\n";
|
|
115
|
+
}
|
|
116
|
+
return "\n\n";
|
|
117
|
+
}
|
|
118
|
+
function normalizeRootInstructionPart(part) {
|
|
119
|
+
return part?.replace(/\s+$/, "") ?? "";
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=root-instruction-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-instruction-render.js","sourceRoot":"","sources":["../src/root-instruction-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CachedBundle } from "./bundle-discovery";
|
|
2
|
+
import type { DesiredBundleEntry, MaterializedState } from "./registry";
|
|
3
|
+
/** Captures pre-existing root-instruction file contents before Skul starts managing them. */
|
|
4
|
+
export declare function captureRootInstructionBaseContents(options: {
|
|
5
|
+
repoRoot: string;
|
|
6
|
+
targetPaths: Set<string>;
|
|
7
|
+
existingBaseContents?: Record<string, string>;
|
|
8
|
+
managedTargetPaths?: Set<string>;
|
|
9
|
+
}): Record<string, string> | undefined;
|
|
10
|
+
/** Rebuilds shared root-instruction files from desired bundle state and returns the rewritten paths. */
|
|
11
|
+
export declare function syncManagedRootInstructionFiles(options: {
|
|
12
|
+
repoRoot: string;
|
|
13
|
+
desiredState: DesiredBundleEntry[];
|
|
14
|
+
materializedBundles: MaterializedState["bundles"];
|
|
15
|
+
rootInstructionBaseContents?: Record<string, string>;
|
|
16
|
+
targetPaths?: Set<string>;
|
|
17
|
+
resolveCachedBundle: (entry: DesiredBundleEntry) => CachedBundle;
|
|
18
|
+
repoRelPathRemapper?: (toolName: string, relPath: string) => string;
|
|
19
|
+
}): Set<string>;
|
|
20
|
+
/** Restores preserved base content for root-instruction files that Skul no longer manages. */
|
|
21
|
+
export declare function restoreRootInstructionBaseContents(options: {
|
|
22
|
+
repoRoot: string;
|
|
23
|
+
baseContents?: Record<string, string>;
|
|
24
|
+
targetPaths: Set<string>;
|
|
25
|
+
}): Set<string>;
|
|
26
|
+
/** Refreshes fingerprints for a subset of managed files after they are rewritten in place. */
|
|
27
|
+
export declare function refreshManagedFileFingerprintsForPaths(repoRoot: string, bundles: MaterializedState["bundles"], filePaths: Set<string>): MaterializedState["bundles"];
|
|
28
|
+
/** Returns every root-instruction path currently owned by managed bundles. */
|
|
29
|
+
export declare function collectManagedRootInstructionTargets(bundles: MaterializedState["bundles"]): Set<string>;
|
|
30
|
+
/** Verifies that every bundle needed for shared root-instruction recomposition is cached. */
|
|
31
|
+
export declare function assertManagedRootInstructionSyncSourcesCached(options: {
|
|
32
|
+
desiredState: DesiredBundleEntry[];
|
|
33
|
+
materializedBundles: MaterializedState["bundles"];
|
|
34
|
+
targetPaths: Set<string>;
|
|
35
|
+
resolveCachedBundle: (entry: DesiredBundleEntry) => CachedBundle;
|
|
36
|
+
}): void;
|
|
37
|
+
/** Collects other bundles that already own root-instruction paths targeted by an upcoming write. */
|
|
38
|
+
export declare function collectSharedRootInstructionState(bundles: MaterializedState["bundles"], plannedWriteTargets: string[], excludedBundleName: string): {
|
|
39
|
+
files: string[];
|
|
40
|
+
file_fingerprints: Record<string, string>;
|
|
41
|
+
};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.captureRootInstructionBaseContents = captureRootInstructionBaseContents;
|
|
7
|
+
exports.syncManagedRootInstructionFiles = syncManagedRootInstructionFiles;
|
|
8
|
+
exports.restoreRootInstructionBaseContents = restoreRootInstructionBaseContents;
|
|
9
|
+
exports.refreshManagedFileFingerprintsForPaths = refreshManagedFileFingerprintsForPaths;
|
|
10
|
+
exports.collectManagedRootInstructionTargets = collectManagedRootInstructionTargets;
|
|
11
|
+
exports.assertManagedRootInstructionSyncSourcesCached = assertManagedRootInstructionSyncSourcesCached;
|
|
12
|
+
exports.collectSharedRootInstructionState = collectSharedRootInstructionState;
|
|
13
|
+
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
15
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
16
|
+
const root_instruction_content_1 = require("./root-instruction-content");
|
|
17
|
+
const root_instruction_render_1 = require("./root-instruction-render");
|
|
18
|
+
const tool_mapping_1 = require("./tool-mapping");
|
|
19
|
+
/** Captures pre-existing root-instruction file contents before Skul starts managing them. */
|
|
20
|
+
function captureRootInstructionBaseContents(options) {
|
|
21
|
+
if (options.targetPaths.size === 0) {
|
|
22
|
+
return options.existingBaseContents;
|
|
23
|
+
}
|
|
24
|
+
const nextBaseContents = { ...(options.existingBaseContents ?? {}) };
|
|
25
|
+
for (const repoRelativePath of options.targetPaths) {
|
|
26
|
+
if (repoRelativePath in nextBaseContents) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (options.managedTargetPaths?.has(repoRelativePath)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const targetPath = node_path_1.default.join(options.repoRoot, repoRelativePath);
|
|
33
|
+
if (!node_fs_1.default.existsSync(targetPath) || !node_fs_1.default.statSync(targetPath).isFile()) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
nextBaseContents[repoRelativePath] = node_fs_1.default.readFileSync(targetPath, "utf8");
|
|
37
|
+
}
|
|
38
|
+
return Object.keys(nextBaseContents).length > 0
|
|
39
|
+
? nextBaseContents
|
|
40
|
+
: undefined;
|
|
41
|
+
}
|
|
42
|
+
/** Rebuilds shared root-instruction files from desired bundle state and returns the rewritten paths. */
|
|
43
|
+
function syncManagedRootInstructionFiles(options) {
|
|
44
|
+
const contentByPath = collectRootInstructionContentByPath(options);
|
|
45
|
+
const writtenPaths = new Set();
|
|
46
|
+
for (const [repoRelativePath, parts] of contentByPath.entries()) {
|
|
47
|
+
const baseContent = options.rootInstructionBaseContents?.[repoRelativePath];
|
|
48
|
+
const targetPath = node_path_1.default.join(options.repoRoot, repoRelativePath);
|
|
49
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(targetPath), { recursive: true });
|
|
50
|
+
node_fs_1.default.writeFileSync(targetPath, `${(0, root_instruction_render_1.composeRootInstructionContent)([baseContent, ...parts])}\n`);
|
|
51
|
+
writtenPaths.add(repoRelativePath);
|
|
52
|
+
}
|
|
53
|
+
return writtenPaths;
|
|
54
|
+
}
|
|
55
|
+
function collectRootInstructionContentByPath(options) {
|
|
56
|
+
const contentByPath = new Map();
|
|
57
|
+
const seenBundleTargets = new Set();
|
|
58
|
+
for (const desiredEntry of options.desiredState) {
|
|
59
|
+
const materializedBundleState = options.materializedBundles[desiredEntry.bundle];
|
|
60
|
+
if (!materializedBundleState) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const cachedBundle = options.resolveCachedBundle(desiredEntry);
|
|
64
|
+
const toolNames = Object.keys(materializedBundleState.tools);
|
|
65
|
+
if (options.repoRelPathRemapper) {
|
|
66
|
+
// In global mode, tools that share a project path (e.g. AGENTS.md) may remap to different
|
|
67
|
+
// global targets (e.g. .github/copilot-instructions.md vs .gemini/GEMINI.md). Collect and
|
|
68
|
+
// remap per-tool so each tool maps to its own global path independently.
|
|
69
|
+
// Only process globally-capable tools; non-global tools in the materialized state (e.g. from
|
|
70
|
+
// registry corruption) would pass through the remapper unchanged and write to homeDir at the
|
|
71
|
+
// project-level path.
|
|
72
|
+
const globalTools = (0, tool_mapping_1.globalCapableToolNames)();
|
|
73
|
+
for (const toolName of toolNames.filter((t) => globalTools.includes(t))) {
|
|
74
|
+
const rawToolContentByPath = (0, root_instruction_content_1.collectComposedRootInstructionContents)({
|
|
75
|
+
bundleDir: node_path_1.default.dirname(cachedBundle.manifestFile),
|
|
76
|
+
manifest: cachedBundle.manifest,
|
|
77
|
+
toolNames: [toolName],
|
|
78
|
+
targetPaths: undefined,
|
|
79
|
+
itemSelectors: desiredEntry.items,
|
|
80
|
+
});
|
|
81
|
+
const toolContentByPath = Object.fromEntries(Object.entries(rawToolContentByPath).map(([k, v]) => [
|
|
82
|
+
options.repoRelPathRemapper(toolName, k),
|
|
83
|
+
v,
|
|
84
|
+
]));
|
|
85
|
+
for (const repoRelativePath of materializedBundleState.tools[toolName]
|
|
86
|
+
.files) {
|
|
87
|
+
if (!(0, root_instruction_render_1.isRootInstructionPath)(repoRelativePath)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (options.targetPaths &&
|
|
91
|
+
!options.targetPaths.has(repoRelativePath)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const content = toolContentByPath[repoRelativePath];
|
|
95
|
+
if (content === undefined) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const bundleTargetKey = `${desiredEntry.bundle}:${repoRelativePath}`;
|
|
99
|
+
if (seenBundleTargets.has(bundleTargetKey)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
seenBundleTargets.add(bundleTargetKey);
|
|
103
|
+
const existingParts = contentByPath.get(repoRelativePath) ?? [];
|
|
104
|
+
existingParts.push((0, root_instruction_render_1.wrapRootInstructionBundleContent)({
|
|
105
|
+
bundleName: desiredEntry.bundle,
|
|
106
|
+
source: desiredEntry.source,
|
|
107
|
+
content,
|
|
108
|
+
}));
|
|
109
|
+
contentByPath.set(repoRelativePath, existingParts);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Non-global mode: collect all tools at once so tools sharing a path (e.g. multiple tools
|
|
115
|
+
// targeting AGENTS.md) have their content properly aggregated before writing.
|
|
116
|
+
const rawBundleContentByPath = (0, root_instruction_content_1.collectComposedRootInstructionContents)({
|
|
117
|
+
bundleDir: node_path_1.default.dirname(cachedBundle.manifestFile),
|
|
118
|
+
manifest: cachedBundle.manifest,
|
|
119
|
+
toolNames,
|
|
120
|
+
targetPaths: options.targetPaths,
|
|
121
|
+
itemSelectors: desiredEntry.items,
|
|
122
|
+
});
|
|
123
|
+
for (const toolName of toolNames) {
|
|
124
|
+
for (const repoRelativePath of materializedBundleState.tools[toolName]
|
|
125
|
+
.files) {
|
|
126
|
+
if (!(0, root_instruction_render_1.isRootInstructionPath)(repoRelativePath)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (options.targetPaths &&
|
|
130
|
+
!options.targetPaths.has(repoRelativePath)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const content = rawBundleContentByPath[repoRelativePath];
|
|
134
|
+
if (content === undefined) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const bundleTargetKey = `${desiredEntry.bundle}:${repoRelativePath}`;
|
|
138
|
+
if (seenBundleTargets.has(bundleTargetKey)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
seenBundleTargets.add(bundleTargetKey);
|
|
142
|
+
const existingParts = contentByPath.get(repoRelativePath) ?? [];
|
|
143
|
+
existingParts.push((0, root_instruction_render_1.wrapRootInstructionBundleContent)({
|
|
144
|
+
bundleName: desiredEntry.bundle,
|
|
145
|
+
source: desiredEntry.source,
|
|
146
|
+
content,
|
|
147
|
+
}));
|
|
148
|
+
contentByPath.set(repoRelativePath, existingParts);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return contentByPath;
|
|
154
|
+
}
|
|
155
|
+
/** Restores preserved base content for root-instruction files that Skul no longer manages. */
|
|
156
|
+
function restoreRootInstructionBaseContents(options) {
|
|
157
|
+
if (!options.baseContents || options.targetPaths.size === 0) {
|
|
158
|
+
return new Set();
|
|
159
|
+
}
|
|
160
|
+
const restoredPaths = new Set();
|
|
161
|
+
for (const repoRelativePath of options.targetPaths) {
|
|
162
|
+
const baseContent = options.baseContents[repoRelativePath];
|
|
163
|
+
if (baseContent === undefined) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const targetPath = node_path_1.default.join(options.repoRoot, repoRelativePath);
|
|
167
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(targetPath), { recursive: true });
|
|
168
|
+
node_fs_1.default.writeFileSync(targetPath, baseContent);
|
|
169
|
+
restoredPaths.add(repoRelativePath);
|
|
170
|
+
}
|
|
171
|
+
return restoredPaths;
|
|
172
|
+
}
|
|
173
|
+
/** Refreshes fingerprints for a subset of managed files after they are rewritten in place. */
|
|
174
|
+
function refreshManagedFileFingerprintsForPaths(repoRoot, bundles, filePaths) {
|
|
175
|
+
if (filePaths.size === 0) {
|
|
176
|
+
return bundles;
|
|
177
|
+
}
|
|
178
|
+
return Object.fromEntries(Object.entries(bundles).map(([bundleName, bundleState]) => [
|
|
179
|
+
bundleName,
|
|
180
|
+
{
|
|
181
|
+
...bundleState,
|
|
182
|
+
tools: Object.fromEntries(Object.entries(bundleState.tools).map(([toolName, toolState]) => [
|
|
183
|
+
toolName,
|
|
184
|
+
{
|
|
185
|
+
...toolState,
|
|
186
|
+
file_fingerprints: {
|
|
187
|
+
...(toolState.file_fingerprints ?? {}),
|
|
188
|
+
...captureManagedFileFingerprints(repoRoot, toolState.files.filter((filePath) => filePaths.has(filePath))),
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
])),
|
|
192
|
+
},
|
|
193
|
+
]));
|
|
194
|
+
}
|
|
195
|
+
function captureManagedFileFingerprints(repoRoot, files) {
|
|
196
|
+
return Object.fromEntries(files.map((relativePath) => [
|
|
197
|
+
relativePath,
|
|
198
|
+
fingerprintFile(node_path_1.default.join(repoRoot, relativePath)),
|
|
199
|
+
]));
|
|
200
|
+
}
|
|
201
|
+
function fingerprintFile(filePath) {
|
|
202
|
+
try {
|
|
203
|
+
return (0, node_crypto_1.createHash)("sha256").update(node_fs_1.default.readFileSync(filePath)).digest("hex");
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// On read failure treat the file as modified so callers prompt before deletion
|
|
207
|
+
// rather than silently skipping a managed file that may still exist.
|
|
208
|
+
return "";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** Returns every root-instruction path currently owned by managed bundles. */
|
|
212
|
+
function collectManagedRootInstructionTargets(bundles) {
|
|
213
|
+
return new Set(Object.values(bundles).flatMap((bundleState) => Object.values(bundleState.tools).flatMap((toolState) => toolState.files.filter((filePath) => (0, root_instruction_render_1.isRootInstructionPath)(filePath)))));
|
|
214
|
+
}
|
|
215
|
+
/** Verifies that every bundle needed for shared root-instruction recomposition is cached. */
|
|
216
|
+
function assertManagedRootInstructionSyncSourcesCached(options) {
|
|
217
|
+
if (options.targetPaths.size === 0) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
for (const desiredEntry of options.desiredState) {
|
|
221
|
+
const materializedBundleState = options.materializedBundles[desiredEntry.bundle];
|
|
222
|
+
if (!materializedBundleState) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const ownsTargetPath = Object.values(materializedBundleState.tools).some((toolState) => toolState.files.some((filePath) => options.targetPaths.has(filePath)));
|
|
226
|
+
if (!ownsTargetPath) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
options.resolveCachedBundle(desiredEntry);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** Collects other bundles that already own root-instruction paths targeted by an upcoming write. */
|
|
233
|
+
function collectSharedRootInstructionState(bundles, plannedWriteTargets, excludedBundleName) {
|
|
234
|
+
const sharedRootTargets = new Set(plannedWriteTargets.filter((filePath) => (0, root_instruction_render_1.isRootInstructionPath)(filePath)));
|
|
235
|
+
const files = new Set();
|
|
236
|
+
const fileFingerprints = {};
|
|
237
|
+
for (const [bundleName, bundleState] of Object.entries(bundles)) {
|
|
238
|
+
if (bundleName === excludedBundleName) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const flattenedState = flattenBundleState(bundleState);
|
|
242
|
+
for (const filePath of flattenedState.files) {
|
|
243
|
+
if (!sharedRootTargets.has(filePath)) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
files.add(filePath);
|
|
247
|
+
if (flattenedState.file_fingerprints[filePath]) {
|
|
248
|
+
fileFingerprints[filePath] = flattenedState.file_fingerprints[filePath];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
files: Array.from(files),
|
|
254
|
+
file_fingerprints: fileFingerprints,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function flattenBundleState(bundleState) {
|
|
258
|
+
const files = new Set();
|
|
259
|
+
const fileFingerprints = {};
|
|
260
|
+
for (const toolState of Object.values(bundleState.tools)) {
|
|
261
|
+
for (const file of toolState.files) {
|
|
262
|
+
files.add(file);
|
|
263
|
+
}
|
|
264
|
+
if (toolState.file_fingerprints) {
|
|
265
|
+
Object.assign(fileFingerprints, toolState.file_fingerprints);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
files: Array.from(files),
|
|
270
|
+
file_fingerprints: fileFingerprints,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=root-instruction-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-instruction-state.js","sourceRoot":"","sources":["../src/root-instruction-state.ts"],"names":[],"mappings":";;;;;AAoBA,gFAiCC;AAGD,0EAwBC;AA4ID,gFAyBC;AAGD,wFAgCC;AAyBD,oFAUC;AAGD,sGA6BC;AAGD,8EAmCC;AAjYD,6CAAyC;AACzC,sDAAyB;AACzB,0DAA6B;AAQ7B,yEAAoF;AACpF,uEAImC;AAEnC,iDAAwD;AAExD,6FAA6F;AAC7F,SAAgB,kCAAkC,CAAC,OAKlD;IACC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC,oBAAoB,CAAC;IACtC,CAAC;IAED,MAAM,gBAAgB,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,EAAE,CAAC;IAErE,KAAK,MAAM,gBAAgB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACnD,IAAI,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;YACzC,SAAS;QACX,CAAC;QAED,IAAI,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACtD,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAEjE,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YACpE,SAAS;QACX,CAAC;QAED,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,iBAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC;QAC7C,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,wGAAwG;AACxG,SAAgB,+BAA+B,CAAC,OAQ/C;IACC,MAAM,aAAa,GAAG,mCAAmC,CAAC,OAAO,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;QAChE,MAAM,WAAW,GAAG,OAAO,CAAC,2BAA2B,EAAE,CAAC,gBAAgB,CAAC,CAAC;QAC5E,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACjE,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,iBAAE,CAAC,aAAa,CACd,UAAU,EACV,GAAG,IAAA,uDAA6B,EAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAC9D,CAAC;QACF,YAAY,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,mCAAmC,CAAC,OAM5C;IACC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAC;IAClD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE5C,KAAK,MAAM,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAChD,MAAM,uBAAuB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAEnD,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAe,CAAC;QAE3E,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAChC,0FAA0F;YAC1F,0FAA0F;YAC1F,yEAAyE;YACzE,6FAA6F;YAC7F,6FAA6F;YAC7F,sBAAsB;YACtB,MAAM,WAAW,GAAG,IAAA,qCAAsB,GAAE,CAAC;YAC7C,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,MAAM,oBAAoB,GAAG,IAAA,iEAAsC,EAAC;oBAClE,SAAS,EAAE,mBAAI,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC;oBAClD,QAAQ,EAAE,YAAY,CAAC,QAAQ;oBAC/B,SAAS,EAAE,CAAC,QAAQ,CAAC;oBACrB,WAAW,EAAE,SAAS;oBACtB,aAAa,EAAE,YAAY,CAAC,KAAK;iBAClC,CAAC,CAAC;gBAEH,MAAM,iBAAiB,GAAG,MAAM,CAAC,WAAW,CAC1C,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;oBACnD,OAAO,CAAC,mBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACzC,CAAC;iBACF,CAAC,CACH,CAAC;gBAEF,KAAK,MAAM,gBAAgB,IAAI,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAE;qBACpE,KAAK,EAAE,CAAC;oBACT,IAAI,CAAC,IAAA,+CAAqB,EAAC,gBAAgB,CAAC,EAAE,CAAC;wBAC7C,SAAS;oBACX,CAAC;oBAED,IACE,OAAO,CAAC,WAAW;wBACnB,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAC1C,CAAC;wBACD,SAAS;oBACX,CAAC;oBAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;oBAEpD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBAC1B,SAAS;oBACX,CAAC;oBAED,MAAM,eAAe,GAAG,GAAG,YAAY,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;oBAErE,IAAI,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;wBAC3C,SAAS;oBACX,CAAC;oBAED,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBACvC,MAAM,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;oBAChE,aAAa,CAAC,IAAI,CAChB,IAAA,0DAAgC,EAAC;wBAC/B,UAAU,EAAE,YAAY,CAAC,MAAM;wBAC/B,MAAM,EAAE,YAAY,CAAC,MAAM;wBAC3B,OAAO;qBACR,CAAC,CACH,CAAC;oBACF,aAAa,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,0FAA0F;YAC1F,8EAA8E;YAC9E,MAAM,sBAAsB,GAAG,IAAA,iEAAsC,EAAC;gBACpE,SAAS,EAAE,mBAAI,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC;gBAClD,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,SAAS;gBACT,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,aAAa,EAAE,YAAY,CAAC,KAAK;aAClC,CAAC,CAAC;YAEH,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,KAAK,MAAM,gBAAgB,IAAI,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAE;qBACpE,KAAK,EAAE,CAAC;oBACT,IAAI,CAAC,IAAA,+CAAqB,EAAC,gBAAgB,CAAC,EAAE,CAAC;wBAC7C,SAAS;oBACX,CAAC;oBAED,IACE,OAAO,CAAC,WAAW;wBACnB,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAC1C,CAAC;wBACD,SAAS;oBACX,CAAC;oBAED,MAAM,OAAO,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;oBAEzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBAC1B,SAAS;oBACX,CAAC;oBAED,MAAM,eAAe,GAAG,GAAG,YAAY,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;oBAErE,IAAI,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;wBAC3C,SAAS;oBACX,CAAC;oBAED,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBACvC,MAAM,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;oBAChE,aAAa,CAAC,IAAI,CAChB,IAAA,0DAAgC,EAAC;wBAC/B,UAAU,EAAE,YAAY,CAAC,MAAM;wBAC/B,MAAM,EAAE,YAAY,CAAC,MAAM;wBAC3B,OAAO;qBACR,CAAC,CACH,CAAC;oBACF,aAAa,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,8FAA8F;AAC9F,SAAgB,kCAAkC,CAAC,OAIlD;IACC,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO,IAAI,GAAG,EAAU,CAAC;IAC3B,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IAExC,KAAK,MAAM,gBAAgB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAE3D,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACjE,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,iBAAE,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC1C,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,8FAA8F;AAC9F,SAAgB,sCAAsC,CACpD,QAAgB,EAChB,OAAqC,EACrC,SAAsB;IAEtB,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC;QACzD,UAAU;QACV;YACE,GAAG,WAAW;YACd,KAAK,EAAE,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;gBAC/D,QAAQ;gBACR;oBACE,GAAG,SAAS;oBACZ,iBAAiB,EAAE;wBACjB,GAAG,CAAC,SAAS,CAAC,iBAAiB,IAAI,EAAE,CAAC;wBACtC,GAAG,8BAA8B,CAC/B,QAAQ,EACR,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAC9D;qBACF;iBACF;aACF,CAAC,CACH;SACgC;KACpC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,8BAA8B,CACrC,QAAgB,EAChB,KAAe;IAEf,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC;QAC1B,YAAY;QACZ,eAAe,CAAC,mBAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;KACnD,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,iBAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;QAC/E,qEAAqE;QACrE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,SAAgB,oCAAoC,CAClD,OAAqC;IAErC,OAAO,IAAI,GAAG,CACZ,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAC7C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CACrD,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAA,+CAAqB,EAAC,QAAQ,CAAC,CAAC,CACtE,CACF,CACF,CAAC;AACJ,CAAC;AAED,6FAA6F;AAC7F,SAAgB,6CAA6C,CAAC,OAK7D;IACC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IAED,KAAK,MAAM,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAChD,MAAM,uBAAuB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAEnD,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,IAAI,CACtE,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CACxE,CAAC;QAEF,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,SAAS;QACX,CAAC;QAED,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,oGAAoG;AACpG,SAAgB,iCAAiC,CAC/C,OAAqC,EACrC,mBAA6B,EAC7B,kBAA0B;IAE1B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAC/B,mBAAmB,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAA,+CAAqB,EAAC,QAAQ,CAAC,CAAC,CAC1E,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,gBAAgB,GAA2B,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,IAAI,UAAU,KAAK,kBAAkB,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QAED,MAAM,cAAc,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAEvD,KAAK,MAAM,QAAQ,IAAI,cAAc,CAAC,KAAK,EAAE,CAAC;YAC5C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrC,SAAS;YACX,CAAC;YAED,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAEpB,IAAI,cAAc,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/C,gBAAgB,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QACxB,iBAAiB,EAAE,gBAAgB;KACpC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,WAAoC;IAI9D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,gBAAgB,GAA2B,EAAE,CAAC;IAEpD,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACnC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QACxB,iBAAiB,EAAE,gBAAgB;KACpC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface GlobalStateLayout {
|
|
2
|
+
rootDir: string;
|
|
3
|
+
registryFile: string;
|
|
4
|
+
libraryDir: string;
|
|
5
|
+
resolveLibraryPath(...segments: string[]): string;
|
|
6
|
+
}
|
|
7
|
+
export interface ResolveGlobalStateLayoutOptions {
|
|
8
|
+
homeDir: string;
|
|
9
|
+
}
|
|
10
|
+
/** Resolves the on-disk layout Skul uses for global state under one home directory. */
|
|
11
|
+
export declare function resolveGlobalStateLayout(options: ResolveGlobalStateLayoutOptions): GlobalStateLayout;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveGlobalStateLayout = resolveGlobalStateLayout;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const STATE_DIR_NAME = ".skul";
|
|
9
|
+
const REGISTRY_FILE_NAME = "registry.json";
|
|
10
|
+
const LIBRARY_DIR_NAME = "library";
|
|
11
|
+
/** Resolves the on-disk layout Skul uses for global state under one home directory. */
|
|
12
|
+
function resolveGlobalStateLayout(options) {
|
|
13
|
+
const homeDir = options.homeDir.trim();
|
|
14
|
+
if (!homeDir) {
|
|
15
|
+
throw new Error("A home directory is required to resolve the global state layout");
|
|
16
|
+
}
|
|
17
|
+
const rootDir = node_path_1.default.join(homeDir, STATE_DIR_NAME);
|
|
18
|
+
const libraryDir = node_path_1.default.join(rootDir, LIBRARY_DIR_NAME);
|
|
19
|
+
return {
|
|
20
|
+
rootDir,
|
|
21
|
+
registryFile: node_path_1.default.join(rootDir, REGISTRY_FILE_NAME),
|
|
22
|
+
libraryDir,
|
|
23
|
+
resolveLibraryPath: (...segments) => node_path_1.default.join(libraryDir, ...segments),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=state-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-layout.js","sourceRoot":"","sources":["../src/state-layout.ts"],"names":[],"mappings":";;;;;AAkBA,4DAqBC;AAvCD,0DAA6B;AAE7B,MAAM,cAAc,GAAG,OAAO,CAAC;AAC/B,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAC3C,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAanC,uFAAuF;AACvF,SAAgB,wBAAwB,CACtC,OAAwC;IAExC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAExD,OAAO;QACL,OAAO;QACP,YAAY,EAAE,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;QACpD,UAAU;QACV,kBAAkB,EAAE,CAAC,GAAG,QAAkB,EAAE,EAAE,CAC5C,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type ToolName = "claude-code" | "cursor" | "opencode" | "codex" | "copilot" | "kiro" | "antigravity";
|
|
2
|
+
export type ToolTargetName = "skills" | "commands" | "agents" | "root_instruction";
|
|
3
|
+
export type ToolTargetEntryKind = "directory" | "file";
|
|
4
|
+
export interface ToolTargetDefinition {
|
|
5
|
+
path: string;
|
|
6
|
+
kind: ToolTargetEntryKind;
|
|
7
|
+
}
|
|
8
|
+
export interface ToolDefinition {
|
|
9
|
+
name: ToolName;
|
|
10
|
+
targets: Partial<Record<ToolTargetName, ToolTargetDefinition>>;
|
|
11
|
+
}
|
|
12
|
+
export interface ToolMaterializationLayout {
|
|
13
|
+
remapRepoRelPath(toolName: string, repoRelPath: string): string;
|
|
14
|
+
resolveToolTargetPath(toolName: string, targetName: ToolTargetName, rootDir: string): string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Returns a defensive copy of all supported tool definitions. */
|
|
17
|
+
export declare function listToolDefinitions(): ToolDefinition[];
|
|
18
|
+
/** Returns all tool definitions for global (~/) materialization. */
|
|
19
|
+
export declare function listGlobalToolDefinitions(): ToolDefinition[];
|
|
20
|
+
/** Returns the global tool definition for one tool, or null if not supported globally.
|
|
21
|
+
* Exported for use by external consumers inspecting global installation layout. */
|
|
22
|
+
export declare function getGlobalToolDefinition(name: string): ToolDefinition | null;
|
|
23
|
+
/** Returns the names of tools that support global installation. */
|
|
24
|
+
export declare function globalCapableToolNames(): ToolName[];
|
|
25
|
+
/** Returns the path remapper for global mode. Takes the tool name so that tools sharing
|
|
26
|
+
* the same project path (e.g. AGENTS.md) can each remap to their own global path. */
|
|
27
|
+
export declare function buildGlobalRepoRelPathRemapper(): (toolName: string, p: string) => string;
|
|
28
|
+
/** Looks up one tool definition by name and returns a defensive copy when found. */
|
|
29
|
+
export declare function getToolDefinition(name: string): ToolDefinition | null;
|
|
30
|
+
/** Resolves the absolute target root path for one tool target inside a repository. */
|
|
31
|
+
export declare function resolveToolTargetPath(toolName: string, targetName: ToolTargetName, repoRoot: string): string | null;
|
|
32
|
+
/** Resolves the absolute target root path for one global tool target under a home directory. */
|
|
33
|
+
export declare function resolveGlobalToolTargetPath(toolName: string, targetName: ToolTargetName, homeDir: string): string | null;
|
|
34
|
+
export declare const PROJECT_TOOL_MATERIALIZATION_LAYOUT: ToolMaterializationLayout;
|
|
35
|
+
export declare const GLOBAL_TOOL_MATERIALIZATION_LAYOUT: ToolMaterializationLayout;
|