mewkit 1.10.1 → 1.10.3
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/dist/commands/doctor-memory-checks.d.ts +3 -0
- package/dist/commands/doctor-memory-checks.d.ts.map +1 -0
- package/dist/commands/doctor-memory-checks.js +39 -0
- package/dist/commands/doctor-memory-checks.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +67 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/memory.d.ts +3 -1
- package/dist/commands/memory.d.ts.map +1 -1
- package/dist/commands/memory.js +97 -19
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +11 -6
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/verdict-gate.d.ts +4 -0
- package/dist/commands/verdict-gate.d.ts.map +1 -0
- package/dist/commands/verdict-gate.js +29 -0
- package/dist/commands/verdict-gate.js.map +1 -0
- package/dist/core/compute-checksums.d.ts +7 -0
- package/dist/core/compute-checksums.d.ts.map +1 -1
- package/dist/core/compute-checksums.js +12 -3
- package/dist/core/compute-checksums.js.map +1 -1
- package/dist/core/file-lock.d.ts +3 -0
- package/dist/core/file-lock.d.ts.map +1 -0
- package/dist/core/file-lock.js +84 -0
- package/dist/core/file-lock.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/install-metadata-backref.d.ts +14 -0
- package/dist/core/install-metadata-backref.d.ts.map +1 -0
- package/dist/core/install-metadata-backref.js +39 -0
- package/dist/core/install-metadata-backref.js.map +1 -0
- package/dist/core/install-metadata-writer.d.ts +4 -0
- package/dist/core/install-metadata-writer.d.ts.map +1 -0
- package/dist/core/install-metadata-writer.js +31 -0
- package/dist/core/install-metadata-writer.js.map +1 -0
- package/dist/core/install-metadata.d.ts +158 -0
- package/dist/core/install-metadata.d.ts.map +1 -0
- package/dist/core/install-metadata.js +180 -0
- package/dist/core/install-metadata.js.map +1 -0
- package/dist/core/release-metadata.d.ts +80 -0
- package/dist/core/release-metadata.d.ts.map +1 -0
- package/dist/core/release-metadata.js +70 -0
- package/dist/core/release-metadata.js.map +1 -0
- package/dist/core/smart-update.d.ts +8 -0
- package/dist/core/smart-update.d.ts.map +1 -1
- package/dist/core/smart-update.js +170 -47
- package/dist/core/smart-update.js.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/memory/render-views.d.ts +18 -0
- package/dist/memory/render-views.d.ts.map +1 -0
- package/dist/memory/render-views.js +114 -0
- package/dist/memory/render-views.js.map +1 -0
- package/dist/memory/schemas.d.ts +642 -0
- package/dist/memory/schemas.d.ts.map +1 -0
- package/dist/memory/schemas.js +94 -0
- package/dist/memory/schemas.js.map +1 -0
- package/dist/memory/seed-from-md.d.ts +7 -0
- package/dist/memory/seed-from-md.d.ts.map +1 -0
- package/dist/memory/seed-from-md.js +167 -0
- package/dist/memory/seed-from-md.js.map +1 -0
- package/dist/memory/validate.d.ts +26 -0
- package/dist/memory/validate.d.ts.map +1 -0
- package/dist/memory/validate.js +102 -0
- package/dist/memory/validate.js.map +1 -0
- package/dist/memory/verdict-schema.d.ts +86 -0
- package/dist/memory/verdict-schema.d.ts.map +1 -0
- package/dist/memory/verdict-schema.js +71 -0
- package/dist/memory/verdict-schema.js.map +1 -0
- package/dist/migrate/migrate-orchestrator.d.ts.map +1 -1
- package/dist/migrate/migrate-orchestrator.js +6 -2
- package/dist/migrate/migrate-orchestrator.js.map +1 -1
- package/dist/migrate/portable-installer.d.ts +3 -0
- package/dist/migrate/portable-installer.d.ts.map +1 -1
- package/dist/migrate/portable-installer.js +3 -0
- package/dist/migrate/portable-installer.js.map +1 -1
- package/dist/migrate/reconcile/portable-registry-lock.d.ts.map +1 -1
- package/dist/migrate/reconcile/portable-registry-lock.js +6 -78
- package/dist/migrate/reconcile/portable-registry-lock.js.map +1 -1
- package/dist/migrate/reconcile/portable-registry.d.ts +24 -6
- package/dist/migrate/reconcile/portable-registry.d.ts.map +1 -1
- package/dist/migrate/reconcile/portable-registry.js +7 -1
- package/dist/migrate/reconcile/portable-registry.js.map +1 -1
- package/dist/migrate/skill-directory-installer.d.ts +2 -0
- package/dist/migrate/skill-directory-installer.d.ts.map +1 -1
- package/dist/migrate/skill-directory-installer.js +3 -0
- package/dist/migrate/skill-directory-installer.js.map +1 -1
- package/dist/migrate/types.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// PID-based advisory file lock generalized over an arbitrary lock path.
|
|
2
|
+
// Acquires by exclusively creating the lock file (`wx`) and writing the
|
|
3
|
+
// owner PID + timestamp; reclaims a lock whose owner PID is dead or whose
|
|
4
|
+
// timestamp is older than STALE_LOCK_MS; serializes concurrent callers via a
|
|
5
|
+
// bounded spin. Replaces a per-call proper-lockfile dependency.
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { mkdir, open, readFile, unlink } from "node:fs/promises";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
const STALE_LOCK_MS = 60 * 1000;
|
|
10
|
+
const ACQUIRE_TIMEOUT_MS = 10 * 1000;
|
|
11
|
+
const RETRY_INTERVAL_MS = 100;
|
|
12
|
+
function isErrnoCode(error, code) {
|
|
13
|
+
return (typeof error === "object" && error !== null && "code" in error && error.code === code);
|
|
14
|
+
}
|
|
15
|
+
async function acquireFileLock(lockPath) {
|
|
16
|
+
const lockDir = dirname(lockPath);
|
|
17
|
+
if (!existsSync(lockDir))
|
|
18
|
+
await mkdir(lockDir, { recursive: true });
|
|
19
|
+
const myPid = process.pid;
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
while (true) {
|
|
22
|
+
try {
|
|
23
|
+
const handle = await open(lockPath, "wx");
|
|
24
|
+
await handle.writeFile(`${myPid}\n${Date.now()}\n`, "utf-8");
|
|
25
|
+
await handle.close();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (!isErrnoCode(err, "EEXIST"))
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const content = await readFile(lockPath, "utf-8");
|
|
34
|
+
const [pidStr, tsStr] = content.split("\n");
|
|
35
|
+
const pid = Number.parseInt(pidStr, 10);
|
|
36
|
+
const ts = Number.parseInt(tsStr, 10);
|
|
37
|
+
let alive = false;
|
|
38
|
+
try {
|
|
39
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
40
|
+
process.kill(pid, 0);
|
|
41
|
+
alive = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
alive = false;
|
|
46
|
+
}
|
|
47
|
+
if (!alive || (Number.isFinite(ts) && Date.now() - ts > STALE_LOCK_MS)) {
|
|
48
|
+
try {
|
|
49
|
+
await unlink(lockPath);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* lost the reclaim race — another waiter cleaned it */
|
|
53
|
+
}
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Lock disappeared or unreadable between create and read — retry.
|
|
59
|
+
}
|
|
60
|
+
if (Date.now() - startTime > ACQUIRE_TIMEOUT_MS) {
|
|
61
|
+
throw new Error(`Could not acquire lock ${lockPath} within ${ACQUIRE_TIMEOUT_MS / 1000}s`);
|
|
62
|
+
}
|
|
63
|
+
await new Promise((r) => setTimeout(r, RETRY_INTERVAL_MS));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function releaseFileLock(lockPath) {
|
|
67
|
+
try {
|
|
68
|
+
await unlink(lockPath);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Best-effort: the lock may already be gone (reclaimed as stale).
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Run `operation` while holding an exclusive lock at `lockPath`. */
|
|
75
|
+
export async function withFileLock(lockPath, operation) {
|
|
76
|
+
await acquireFileLock(lockPath);
|
|
77
|
+
try {
|
|
78
|
+
return await operation();
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await releaseFileLock(lockPath);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=file-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../../src/core/file-lock.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export * from "./validate-install.js";
|
|
|
7
7
|
export * from "./smart-update.js";
|
|
8
8
|
export * from "./smart-update-utils.js";
|
|
9
9
|
export * from "./find-orphans.js";
|
|
10
|
+
export * from "./install-metadata.js";
|
|
11
|
+
export * from "./install-metadata-writer.js";
|
|
12
|
+
export * from "./install-metadata-backref.js";
|
|
13
|
+
export * from "./release-metadata.js";
|
|
10
14
|
export * from "./core-logger.js";
|
|
11
15
|
export * from "./skills-dependencies.js";
|
|
12
16
|
export * from "./dependency-installer.js";
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -7,6 +7,10 @@ export * from "./validate-install.js";
|
|
|
7
7
|
export * from "./smart-update.js";
|
|
8
8
|
export * from "./smart-update-utils.js";
|
|
9
9
|
export * from "./find-orphans.js";
|
|
10
|
+
export * from "./install-metadata.js";
|
|
11
|
+
export * from "./install-metadata-writer.js";
|
|
12
|
+
export * from "./install-metadata-backref.js";
|
|
13
|
+
export * from "./release-metadata.js";
|
|
10
14
|
export * from "./core-logger.js";
|
|
11
15
|
export * from "./skills-dependencies.js";
|
|
12
16
|
export * from "./dependency-installer.js";
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type InstallFileEntry } from "./install-metadata.js";
|
|
2
|
+
export interface InstalledBackRef {
|
|
3
|
+
version: string | null;
|
|
4
|
+
entriesByPath: Record<string, InstallFileEntry>;
|
|
5
|
+
sourceClaudeDir: string;
|
|
6
|
+
}
|
|
7
|
+
/** Build a back-reference from the migration source root, or null if no installed metadata. */
|
|
8
|
+
export declare function buildInstalledBackRef(sourceRoot: string): InstalledBackRef | null;
|
|
9
|
+
/** Resolve the back-ref fields for one exported asset; omits fields that are unavailable. */
|
|
10
|
+
export declare function resolveInstalledBackRef(backRef: InstalledBackRef | null, absSourcePath: string): {
|
|
11
|
+
installedVersion?: string;
|
|
12
|
+
installedChecksum?: string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=install-metadata-backref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata-backref.d.ts","sourceRoot":"","sources":["../../src/core/install-metadata-backref.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhG,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAajF;AAED,6FAA6F;AAC7F,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,gBAAgB,GAAG,IAAI,EAChC,aAAa,EAAE,MAAM,GACnB;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CAU3D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// One-way bridge from a migration source to the installed metadata it was
|
|
2
|
+
// exported from. `mewkit migrate --install` stamps portable-registry entries
|
|
3
|
+
// with these back-references; absent or corrupt source metadata yields null so
|
|
4
|
+
// a migration is never failed or altered by the bridge.
|
|
5
|
+
import { relative, join, isAbsolute } from "node:path";
|
|
6
|
+
import { readInstallMetadata, indexByPath } from "./install-metadata.js";
|
|
7
|
+
/** Build a back-reference from the migration source root, or null if no installed metadata. */
|
|
8
|
+
export function buildInstalledBackRef(sourceRoot) {
|
|
9
|
+
const sourceClaudeDir = join(sourceRoot, ".claude");
|
|
10
|
+
try {
|
|
11
|
+
const read = readInstallMetadata(sourceClaudeDir);
|
|
12
|
+
if (read.source === "none" || !read.meta)
|
|
13
|
+
return null;
|
|
14
|
+
return {
|
|
15
|
+
version: read.meta.version || null,
|
|
16
|
+
entriesByPath: indexByPath(read.meta.files),
|
|
17
|
+
sourceClaudeDir,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null; // corrupt source metadata is not worth failing a migration over
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Resolve the back-ref fields for one exported asset; omits fields that are unavailable. */
|
|
25
|
+
export function resolveInstalledBackRef(backRef, absSourcePath) {
|
|
26
|
+
if (!backRef)
|
|
27
|
+
return {};
|
|
28
|
+
const out = {};
|
|
29
|
+
if (backRef.version)
|
|
30
|
+
out.installedVersion = backRef.version;
|
|
31
|
+
const rel = relative(backRef.sourceClaudeDir, absSourcePath);
|
|
32
|
+
if (rel && !rel.startsWith("..") && !isAbsolute(rel)) {
|
|
33
|
+
const entry = backRef.entriesByPath[rel];
|
|
34
|
+
if (entry)
|
|
35
|
+
out.installedChecksum = entry.checksum;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=install-metadata-backref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata-backref.js","sourceRoot":"","sources":["../../src/core/install-metadata-backref.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,+EAA+E;AAC/E,wDAAwD;AACxD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAyB,MAAM,uBAAuB,CAAC;AAQhG,+FAA+F;AAC/F,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACvD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACtD,OAAO;YACN,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI;YAClC,aAAa,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YAC3C,eAAe;SACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC,CAAC,gEAAgE;IAC9E,CAAC;AACF,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,uBAAuB,CACtC,OAAgC,EAChC,aAAqB;IAErB,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,GAAG,GAA8D,EAAE,CAAC;IAC1E,IAAI,OAAO,CAAC,OAAO;QAAE,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,KAAK;YAAE,GAAG,CAAC,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC;IACnD,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type InstallMetadata } from "./install-metadata.js";
|
|
2
|
+
/** Atomically write `.claude/metadata.json` under a per-project lock. */
|
|
3
|
+
export declare function writeInstallMetadata(claudeDir: string, meta: InstallMetadata): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=install-metadata-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata-writer.d.ts","sourceRoot":"","sources":["../../src/core/install-metadata-writer.ts"],"names":[],"mappings":"AAMA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxF,yEAAyE;AACzE,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBlG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Locked, atomic writer for the canonical installed `.claude/metadata.json`.
|
|
2
|
+
// Serializes concurrent init/upgrade/migrate writers via a per-project lock and
|
|
3
|
+
// publishes via temp-file + rename so a reader never observes a partial file.
|
|
4
|
+
import { rename, unlink, writeFile } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { withFileLock } from "./file-lock.js";
|
|
7
|
+
import { INSTALL_METADATA_FILENAME } from "./install-metadata.js";
|
|
8
|
+
const LOCK_FILENAME = ".metadata.lock";
|
|
9
|
+
/** Atomically write `.claude/metadata.json` under a per-project lock. */
|
|
10
|
+
export async function writeInstallMetadata(claudeDir, meta) {
|
|
11
|
+
const lockPath = join(claudeDir, LOCK_FILENAME);
|
|
12
|
+
const targetPath = join(claudeDir, INSTALL_METADATA_FILENAME);
|
|
13
|
+
const serialized = JSON.stringify(meta, null, 2) + "\n";
|
|
14
|
+
await withFileLock(lockPath, async () => {
|
|
15
|
+
const tempPath = `${targetPath}.tmp-${process.pid}-${Date.now()}`;
|
|
16
|
+
try {
|
|
17
|
+
await writeFile(tempPath, serialized, "utf-8");
|
|
18
|
+
await rename(tempPath, targetPath);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
try {
|
|
22
|
+
await unlink(tempPath);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
/* best-effort cleanup of the temp file */
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=install-metadata-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata-writer.js","sourceRoot":"","sources":["../../src/core/install-metadata-writer.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,8EAA8E;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAwB,MAAM,uBAAuB,CAAC;AAExF,MAAM,aAAa,GAAG,gBAAgB,CAAC;AAEvC,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,SAAiB,EAAE,IAAqB;IAClF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAExD,MAAM,YAAY,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,QAAQ,GAAG,GAAG,UAAU,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAClE,IAAI,CAAC;YACJ,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC;gBACJ,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACR,0CAA0C;YAC3C,CAAC;YACD,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const INSTALL_METADATA_FILENAME = "metadata.json";
|
|
3
|
+
export declare const InstallFileEntrySchema: z.ZodObject<{
|
|
4
|
+
path: z.ZodString;
|
|
5
|
+
owner: z.ZodEnum<["meowkit", "user", "meowkit-modified"]>;
|
|
6
|
+
layer: z.ZodEnum<["core", "skill", "user"]>;
|
|
7
|
+
checksum: z.ZodString;
|
|
8
|
+
baseChecksum: z.ZodString;
|
|
9
|
+
installedVersion: z.ZodOptional<z.ZodString>;
|
|
10
|
+
sourceTimestamp: z.ZodOptional<z.ZodString>;
|
|
11
|
+
installedAt: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
path: string;
|
|
14
|
+
checksum: string;
|
|
15
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
16
|
+
layer: "core" | "skill" | "user";
|
|
17
|
+
baseChecksum: string;
|
|
18
|
+
installedVersion?: string | undefined;
|
|
19
|
+
sourceTimestamp?: string | undefined;
|
|
20
|
+
installedAt?: string | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
path: string;
|
|
23
|
+
checksum: string;
|
|
24
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
25
|
+
layer: "core" | "skill" | "user";
|
|
26
|
+
baseChecksum: string;
|
|
27
|
+
installedVersion?: string | undefined;
|
|
28
|
+
sourceTimestamp?: string | undefined;
|
|
29
|
+
installedAt?: string | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
export type InstallFileEntry = z.infer<typeof InstallFileEntrySchema>;
|
|
32
|
+
export declare const InstallMetadataSchema: z.ZodObject<{
|
|
33
|
+
schemaVersion: z.ZodLiteral<"1.0">;
|
|
34
|
+
tool: z.ZodDefault<z.ZodString>;
|
|
35
|
+
version: z.ZodString;
|
|
36
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
37
|
+
installedAt: z.ZodString;
|
|
38
|
+
files: z.ZodArray<z.ZodObject<{
|
|
39
|
+
path: z.ZodString;
|
|
40
|
+
owner: z.ZodEnum<["meowkit", "user", "meowkit-modified"]>;
|
|
41
|
+
layer: z.ZodEnum<["core", "skill", "user"]>;
|
|
42
|
+
checksum: z.ZodString;
|
|
43
|
+
baseChecksum: z.ZodString;
|
|
44
|
+
installedVersion: z.ZodOptional<z.ZodString>;
|
|
45
|
+
sourceTimestamp: z.ZodOptional<z.ZodString>;
|
|
46
|
+
installedAt: z.ZodOptional<z.ZodString>;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
path: string;
|
|
49
|
+
checksum: string;
|
|
50
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
51
|
+
layer: "core" | "skill" | "user";
|
|
52
|
+
baseChecksum: string;
|
|
53
|
+
installedVersion?: string | undefined;
|
|
54
|
+
sourceTimestamp?: string | undefined;
|
|
55
|
+
installedAt?: string | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
path: string;
|
|
58
|
+
checksum: string;
|
|
59
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
60
|
+
layer: "core" | "skill" | "user";
|
|
61
|
+
baseChecksum: string;
|
|
62
|
+
installedVersion?: string | undefined;
|
|
63
|
+
sourceTimestamp?: string | undefined;
|
|
64
|
+
installedAt?: string | undefined;
|
|
65
|
+
}>, "many">;
|
|
66
|
+
settings: z.ZodOptional<z.ZodObject<{
|
|
67
|
+
merged: z.ZodArray<z.ZodString, "many">;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
merged: string[];
|
|
70
|
+
}, {
|
|
71
|
+
merged: string[];
|
|
72
|
+
}>>;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
version: string;
|
|
75
|
+
files: {
|
|
76
|
+
path: string;
|
|
77
|
+
checksum: string;
|
|
78
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
79
|
+
layer: "core" | "skill" | "user";
|
|
80
|
+
baseChecksum: string;
|
|
81
|
+
installedVersion?: string | undefined;
|
|
82
|
+
sourceTimestamp?: string | undefined;
|
|
83
|
+
installedAt?: string | undefined;
|
|
84
|
+
}[];
|
|
85
|
+
installedAt: string;
|
|
86
|
+
schemaVersion: "1.0";
|
|
87
|
+
tool: string;
|
|
88
|
+
scope?: string | undefined;
|
|
89
|
+
settings?: {
|
|
90
|
+
merged: string[];
|
|
91
|
+
} | undefined;
|
|
92
|
+
}, {
|
|
93
|
+
version: string;
|
|
94
|
+
files: {
|
|
95
|
+
path: string;
|
|
96
|
+
checksum: string;
|
|
97
|
+
owner: "user" | "meowkit" | "meowkit-modified";
|
|
98
|
+
layer: "core" | "skill" | "user";
|
|
99
|
+
baseChecksum: string;
|
|
100
|
+
installedVersion?: string | undefined;
|
|
101
|
+
sourceTimestamp?: string | undefined;
|
|
102
|
+
installedAt?: string | undefined;
|
|
103
|
+
}[];
|
|
104
|
+
installedAt: string;
|
|
105
|
+
schemaVersion: "1.0";
|
|
106
|
+
tool?: string | undefined;
|
|
107
|
+
scope?: string | undefined;
|
|
108
|
+
settings?: {
|
|
109
|
+
merged: string[];
|
|
110
|
+
} | undefined;
|
|
111
|
+
}>;
|
|
112
|
+
export type InstallMetadata = z.infer<typeof InstallMetadataSchema>;
|
|
113
|
+
export type MetadataSource = "new" | "legacy-manifest" | "legacy-metadata" | "none";
|
|
114
|
+
export interface ReadInstallMetadataResult {
|
|
115
|
+
source: MetadataSource;
|
|
116
|
+
meta: InstallMetadata | null;
|
|
117
|
+
}
|
|
118
|
+
/** Thrown when a canonical metadata.json carries `schemaVersion` but fails validation. */
|
|
119
|
+
export declare class CorruptInstallMetadataError extends Error {
|
|
120
|
+
readonly detail: string;
|
|
121
|
+
constructor(detail: string);
|
|
122
|
+
}
|
|
123
|
+
/** Index a file-entry list by its `.claude/`-relative path. */
|
|
124
|
+
export declare function indexByPath(entries: InstallFileEntry[]): Record<string, InstallFileEntry>;
|
|
125
|
+
/**
|
|
126
|
+
* Read installed metadata with explicit source precedence:
|
|
127
|
+
* new (schemaVersion) > legacy checksum manifest > version-only metadata > none.
|
|
128
|
+
* The legacy-manifest branch never trusts `Manifest.version` (hardcoded upstream);
|
|
129
|
+
* it sources the version from a sibling version-only metadata.json when present.
|
|
130
|
+
* Throws CorruptInstallMetadataError when a schemaVersion-bearing file fails Zod.
|
|
131
|
+
*/
|
|
132
|
+
export declare function readInstallMetadata(claudeDir: string): ReadInstallMetadataResult;
|
|
133
|
+
/**
|
|
134
|
+
* Read ONLY the legacy `meowkit.manifest.json` as canonical-shaped metadata,
|
|
135
|
+
* or null when absent. Used as a recovery path when the canonical metadata.json
|
|
136
|
+
* is present but corrupt, so user-edit protection still has a prior baseline.
|
|
137
|
+
*/
|
|
138
|
+
export declare function readLegacyManifestMetadata(claudeDir: string): InstallMetadata | null;
|
|
139
|
+
export interface BuildInstallMetadataOptions {
|
|
140
|
+
/** Installed kit version (from release-manifest). */
|
|
141
|
+
version: string;
|
|
142
|
+
/** Per-path source commit timestamp (release-manifest `lastModified`). */
|
|
143
|
+
sourceTimestamps?: Record<string, string>;
|
|
144
|
+
/** Prior installed entries, indexed by `.claude/`-relative path. */
|
|
145
|
+
priorEntriesByPath?: Record<string, InstallFileEntry>;
|
|
146
|
+
/** Optional install scope marker (e.g. "local"). */
|
|
147
|
+
scope?: string;
|
|
148
|
+
/** settings.json files merged this install. */
|
|
149
|
+
mergedSettings?: string[];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Scan an installed `.claude/` and build canonical metadata. Ownership for kit
|
|
153
|
+
* (core/skill) files is computed against the prior state: a kit file whose disk
|
|
154
|
+
* hash differs from its prior `baseChecksum` is labeled `meowkit-modified`;
|
|
155
|
+
* `baseChecksum` preserves the as-shipped hash across upgrades.
|
|
156
|
+
*/
|
|
157
|
+
export declare function buildInstallMetadata(claudeDir: string, opts: BuildInstallMetadataOptions): InstallMetadata;
|
|
158
|
+
//# sourceMappingURL=install-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata.d.ts","sourceRoot":"","sources":["../../src/core/install-metadata.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,yBAAyB,kBAAkB,CAAC;AAEzD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;EASjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,MAAM,CAAC;AACpF,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;CAC7B;AAED,0FAA0F;AAC1F,qBAAa,2BAA4B,SAAQ,KAAK;aACzB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI1C;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAIzF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,yBAAyB,CAyChF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAGpF;AA6BD,MAAM,WAAW,2BAA2B;IAC3C,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,oEAAoE;IACpE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACtD,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,GAAG,eAAe,CA2C1G"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Canonical installed-metadata model for a MeowKit install under `.claude/`.
|
|
2
|
+
// Declares the Zod schema, a compatibility reader that recognizes the new file,
|
|
3
|
+
// the legacy checksum manifest, and the old version-only metadata, and a builder
|
|
4
|
+
// that labels per-file ownership (meowkit / user / meowkit-modified) against the
|
|
5
|
+
// prior installed state. The locked atomic writer lives in install-metadata-writer.ts.
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { collectFiles, hashFile, classifyLayer, readManifest } from "./compute-checksums.js";
|
|
10
|
+
export const INSTALL_METADATA_FILENAME = "metadata.json";
|
|
11
|
+
export const InstallFileEntrySchema = z.object({
|
|
12
|
+
path: z.string(),
|
|
13
|
+
owner: z.enum(["meowkit", "user", "meowkit-modified"]),
|
|
14
|
+
layer: z.enum(["core", "skill", "user"]),
|
|
15
|
+
checksum: z.string(),
|
|
16
|
+
baseChecksum: z.string(),
|
|
17
|
+
installedVersion: z.string().optional(),
|
|
18
|
+
sourceTimestamp: z.string().optional(),
|
|
19
|
+
installedAt: z.string().optional(),
|
|
20
|
+
});
|
|
21
|
+
export const InstallMetadataSchema = z.object({
|
|
22
|
+
schemaVersion: z.literal("1.0"),
|
|
23
|
+
tool: z.string().default("meowkit"),
|
|
24
|
+
version: z.string(),
|
|
25
|
+
scope: z.string().optional(),
|
|
26
|
+
installedAt: z.string(),
|
|
27
|
+
files: z.array(InstallFileEntrySchema),
|
|
28
|
+
settings: z.object({ merged: z.array(z.string()) }).optional(),
|
|
29
|
+
});
|
|
30
|
+
/** Thrown when a canonical metadata.json carries `schemaVersion` but fails validation. */
|
|
31
|
+
export class CorruptInstallMetadataError extends Error {
|
|
32
|
+
detail;
|
|
33
|
+
constructor(detail) {
|
|
34
|
+
super(`Corrupt .claude/metadata.json: ${detail}`);
|
|
35
|
+
this.detail = detail;
|
|
36
|
+
this.name = "CorruptInstallMetadataError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Index a file-entry list by its `.claude/`-relative path. */
|
|
40
|
+
export function indexByPath(entries) {
|
|
41
|
+
const out = {};
|
|
42
|
+
for (const e of entries)
|
|
43
|
+
out[e.path] = e;
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Read installed metadata with explicit source precedence:
|
|
48
|
+
* new (schemaVersion) > legacy checksum manifest > version-only metadata > none.
|
|
49
|
+
* The legacy-manifest branch never trusts `Manifest.version` (hardcoded upstream);
|
|
50
|
+
* it sources the version from a sibling version-only metadata.json when present.
|
|
51
|
+
* Throws CorruptInstallMetadataError when a schemaVersion-bearing file fails Zod.
|
|
52
|
+
*/
|
|
53
|
+
export function readInstallMetadata(claudeDir) {
|
|
54
|
+
const metadataPath = join(claudeDir, INSTALL_METADATA_FILENAME);
|
|
55
|
+
let legacyMetadataVersion = null;
|
|
56
|
+
if (existsSync(metadataPath)) {
|
|
57
|
+
let parsed;
|
|
58
|
+
try {
|
|
59
|
+
parsed = JSON.parse(readFileSync(metadataPath, "utf-8"));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// mid-write or garbage; `parsed` stays undefined and we fall through.
|
|
63
|
+
}
|
|
64
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
65
|
+
const obj = parsed;
|
|
66
|
+
if ("schemaVersion" in obj) {
|
|
67
|
+
const result = InstallMetadataSchema.safeParse(parsed);
|
|
68
|
+
if (!result.success)
|
|
69
|
+
throw new CorruptInstallMetadataError(result.error.message);
|
|
70
|
+
return { source: "new", meta: result.data };
|
|
71
|
+
}
|
|
72
|
+
if (typeof obj.version === "string")
|
|
73
|
+
legacyMetadataVersion = obj.version;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const legacyManifest = readManifest(claudeDir);
|
|
77
|
+
if (legacyManifest !== null) {
|
|
78
|
+
return { source: "legacy-manifest", meta: mapLegacyManifest(legacyManifest, legacyMetadataVersion) };
|
|
79
|
+
}
|
|
80
|
+
if (legacyMetadataVersion !== null) {
|
|
81
|
+
return {
|
|
82
|
+
source: "legacy-metadata",
|
|
83
|
+
meta: {
|
|
84
|
+
schemaVersion: "1.0",
|
|
85
|
+
tool: "meowkit",
|
|
86
|
+
version: legacyMetadataVersion,
|
|
87
|
+
installedAt: "",
|
|
88
|
+
files: [],
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return { source: "none", meta: null };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Read ONLY the legacy `meowkit.manifest.json` as canonical-shaped metadata,
|
|
96
|
+
* or null when absent. Used as a recovery path when the canonical metadata.json
|
|
97
|
+
* is present but corrupt, so user-edit protection still has a prior baseline.
|
|
98
|
+
*/
|
|
99
|
+
export function readLegacyManifestMetadata(claudeDir) {
|
|
100
|
+
const manifest = readManifest(claudeDir);
|
|
101
|
+
return manifest === null ? null : mapLegacyManifest(manifest, null);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Project a legacy `meowkit.manifest.json` onto the canonical shape. The legacy
|
|
105
|
+
* `sha256` maps to BOTH `checksum` and `baseChecksum` so the user-edit comparison
|
|
106
|
+
* stays equivalent. Version comes from a sibling version-only metadata.json or "".
|
|
107
|
+
*/
|
|
108
|
+
function mapLegacyManifest(manifest, legacyVersion) {
|
|
109
|
+
const files = [];
|
|
110
|
+
for (const [path, entry] of Object.entries(manifest.checksums)) {
|
|
111
|
+
files.push({
|
|
112
|
+
path,
|
|
113
|
+
owner: entry.owner ?? (entry.layer === "user" ? "user" : "meowkit"),
|
|
114
|
+
layer: entry.layer,
|
|
115
|
+
checksum: entry.sha256,
|
|
116
|
+
baseChecksum: entry.baseChecksum ?? entry.sha256,
|
|
117
|
+
installedVersion: entry.installedVersion,
|
|
118
|
+
installedAt: entry.installedAt,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
schemaVersion: "1.0",
|
|
123
|
+
tool: "meowkit",
|
|
124
|
+
version: legacyVersion ?? "",
|
|
125
|
+
installedAt: manifest.generatedAt,
|
|
126
|
+
files,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Scan an installed `.claude/` and build canonical metadata. Ownership for kit
|
|
131
|
+
* (core/skill) files is computed against the prior state: a kit file whose disk
|
|
132
|
+
* hash differs from its prior `baseChecksum` is labeled `meowkit-modified`;
|
|
133
|
+
* `baseChecksum` preserves the as-shipped hash across upgrades.
|
|
134
|
+
*/
|
|
135
|
+
export function buildInstallMetadata(claudeDir, opts) {
|
|
136
|
+
const installedAt = new Date().toISOString();
|
|
137
|
+
const prior = opts.priorEntriesByPath ?? {};
|
|
138
|
+
const timestamps = opts.sourceTimestamps ?? {};
|
|
139
|
+
const files = [];
|
|
140
|
+
for (const relPath of collectFiles(claudeDir, claudeDir)) {
|
|
141
|
+
const diskHash = hashFile(join(claudeDir, relPath));
|
|
142
|
+
const layer = classifyLayer(relPath);
|
|
143
|
+
const priorEntry = prior[relPath];
|
|
144
|
+
const baseChecksum = priorEntry ? priorEntry.baseChecksum : diskHash;
|
|
145
|
+
let owner;
|
|
146
|
+
if (layer === "user")
|
|
147
|
+
owner = "user";
|
|
148
|
+
else if (!priorEntry || diskHash === priorEntry.baseChecksum)
|
|
149
|
+
owner = "meowkit";
|
|
150
|
+
else
|
|
151
|
+
owner = "meowkit-modified";
|
|
152
|
+
const entry = {
|
|
153
|
+
path: relPath,
|
|
154
|
+
owner,
|
|
155
|
+
layer,
|
|
156
|
+
checksum: diskHash,
|
|
157
|
+
baseChecksum,
|
|
158
|
+
installedVersion: opts.version,
|
|
159
|
+
installedAt,
|
|
160
|
+
};
|
|
161
|
+
const sourceTimestamp = timestamps[relPath];
|
|
162
|
+
if (sourceTimestamp)
|
|
163
|
+
entry.sourceTimestamp = sourceTimestamp;
|
|
164
|
+
files.push(entry);
|
|
165
|
+
}
|
|
166
|
+
files.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
167
|
+
const meta = {
|
|
168
|
+
schemaVersion: "1.0",
|
|
169
|
+
tool: "meowkit",
|
|
170
|
+
version: opts.version,
|
|
171
|
+
installedAt,
|
|
172
|
+
files,
|
|
173
|
+
};
|
|
174
|
+
if (opts.scope)
|
|
175
|
+
meta.scope = opts.scope;
|
|
176
|
+
if (opts.mergedSettings && opts.mergedSettings.length > 0)
|
|
177
|
+
meta.settings = { merged: opts.mergedSettings };
|
|
178
|
+
return meta;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=install-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-metadata.js","sourceRoot":"","sources":["../../src/core/install-metadata.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,iFAAiF;AACjF,iFAAiF;AACjF,uFAAuF;AACvF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG7F,MAAM,CAAC,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAEzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACtD,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC9D,CAAC,CAAC;AASH,0FAA0F;AAC1F,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IACzB;IAA5B,YAA4B,MAAc;QACzC,KAAK,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;QADvB,WAAM,GAAN,MAAM,CAAQ;QAEzC,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC3C,CAAC;CACD;AAED,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,OAA2B;IACtD,MAAM,GAAG,GAAqC,EAAE,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IAChE,IAAI,qBAAqB,GAAkB,IAAI,CAAC;IAEhD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACR,sEAAsE;QACvE,CAAC;QACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACnD,MAAM,GAAG,GAAG,MAAiC,CAAC;YAC9C,IAAI,eAAe,IAAI,GAAG,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACvD,IAAI,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM,IAAI,2BAA2B,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACjF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAC7C,CAAC;YACD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAAE,qBAAqB,GAAG,GAAG,CAAC,OAAO,CAAC;QAC1E,CAAC;IACF,CAAC;IAED,MAAM,cAAc,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC7B,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,CAAC,cAAc,EAAE,qBAAqB,CAAC,EAAE,CAAC;IACtG,CAAC;IAED,IAAI,qBAAqB,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO;YACN,MAAM,EAAE,iBAAiB;YACzB,IAAI,EAAE;gBACL,aAAa,EAAE,KAAK;gBACpB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,qBAAqB;gBAC9B,WAAW,EAAE,EAAE;gBACf,KAAK,EAAE,EAAE;aACT;SACD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC3D,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACzC,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,QAAkB,EAAE,aAA4B;IAC1E,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC;YACV,IAAI;YACJ,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACnE,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,QAAQ,EAAE,KAAK,CAAC,MAAM;YACtB,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM;YAChD,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,WAAW,EAAE,KAAK,CAAC,WAAW;SAC9B,CAAC,CAAC;IACJ,CAAC;IACD,OAAO;QACN,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,aAAa,IAAI,EAAE;QAC5B,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,KAAK;KACL,CAAC;AACH,CAAC;AAeD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,IAAiC;IACxF,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,IAAI,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAuB,EAAE,CAAC;IAErC,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;QAErE,IAAI,KAAgC,CAAC;QACrC,IAAI,KAAK,KAAK,MAAM;YAAE,KAAK,GAAG,MAAM,CAAC;aAChC,IAAI,CAAC,UAAU,IAAI,QAAQ,KAAK,UAAU,CAAC,YAAY;YAAE,KAAK,GAAG,SAAS,CAAC;;YAC3E,KAAK,GAAG,kBAAkB,CAAC;QAEhC,MAAM,KAAK,GAAqB;YAC/B,IAAI,EAAE,OAAO;YACb,KAAK;YACL,KAAK;YACL,QAAQ,EAAE,QAAQ;YAClB,YAAY;YACZ,gBAAgB,EAAE,IAAI,CAAC,OAAO;YAC9B,WAAW;SACX,CAAC;QACF,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,eAAe;YAAE,KAAK,CAAC,eAAe,GAAG,eAAe,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,MAAM,IAAI,GAAoB;QAC7B,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW;QACX,KAAK;KACL,CAAC;IACF,IAAI,IAAI,CAAC,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACxC,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;IAC3G,OAAO,IAAI,CAAC;AACb,CAAC"}
|