@skillsmith/core 0.12.3 → 0.12.5
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/CHANGELOG.md +168 -0
- package/README.md +2 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/config/owned-lock.acquire.d.ts +8 -0
- package/dist/src/config/owned-lock.acquire.d.ts.map +1 -1
- package/dist/src/config/owned-lock.acquire.js +19 -4
- package/dist/src/config/owned-lock.acquire.js.map +1 -1
- package/dist/src/config/owned-lock.claim.d.ts +4 -2
- package/dist/src/config/owned-lock.claim.d.ts.map +1 -1
- package/dist/src/config/owned-lock.claim.js +42 -8
- package/dist/src/config/owned-lock.claim.js.map +1 -1
- package/dist/src/config/owned-lock.d.ts.map +1 -1
- package/dist/src/config/owned-lock.js +1 -0
- package/dist/src/config/owned-lock.js.map +1 -1
- package/dist/src/config/owned-lock.test.js +126 -2
- package/dist/src/config/owned-lock.test.js.map +1 -1
- package/dist/src/config/owned-lock.types.d.ts +9 -0
- package/dist/src/config/owned-lock.types.d.ts.map +1 -1
- package/dist/src/db/createDatabase.d.ts.map +1 -1
- package/dist/src/db/createDatabase.js +0 -2
- package/dist/src/db/createDatabase.js.map +1 -1
- package/dist/src/exports/services.install.d.ts +1 -0
- package/dist/src/exports/services.install.d.ts.map +1 -1
- package/dist/src/exports/services.install.js +5 -0
- package/dist/src/exports/services.install.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/install/fan-out.cleanup.d.ts +37 -0
- package/dist/src/install/fan-out.cleanup.d.ts.map +1 -0
- package/dist/src/install/fan-out.cleanup.js +75 -0
- package/dist/src/install/fan-out.cleanup.js.map +1 -0
- package/dist/src/install/fan-out.d.ts +41 -31
- package/dist/src/install/fan-out.d.ts.map +1 -1
- package/dist/src/install/fan-out.js +213 -112
- package/dist/src/install/fan-out.js.map +1 -1
- package/dist/src/install/fan-out.leftovers.d.ts +60 -0
- package/dist/src/install/fan-out.leftovers.d.ts.map +1 -0
- package/dist/src/install/fan-out.leftovers.js +251 -0
- package/dist/src/install/fan-out.leftovers.js.map +1 -0
- package/dist/src/install/fan-out.locks.d.ts +12 -0
- package/dist/src/install/fan-out.locks.d.ts.map +1 -0
- package/dist/src/install/fan-out.locks.js +114 -0
- package/dist/src/install/fan-out.locks.js.map +1 -0
- package/dist/src/install/fan-out.manifest.d.ts +64 -0
- package/dist/src/install/fan-out.manifest.d.ts.map +1 -0
- package/dist/src/install/fan-out.manifest.js +130 -0
- package/dist/src/install/fan-out.manifest.js.map +1 -0
- package/dist/src/install/fan-out.overwrite.d.ts +51 -0
- package/dist/src/install/fan-out.overwrite.d.ts.map +1 -0
- package/dist/src/install/fan-out.overwrite.js +343 -0
- package/dist/src/install/fan-out.overwrite.js.map +1 -0
- package/dist/src/install/remove-if-same.d.ts +58 -0
- package/dist/src/install/remove-if-same.d.ts.map +1 -0
- package/dist/src/install/remove-if-same.js +222 -0
- package/dist/src/install/remove-if-same.js.map +1 -0
- package/dist/src/provenance/backfill.d.ts.map +1 -1
- package/dist/src/provenance/backfill.js +15 -2
- package/dist/src/provenance/backfill.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js +8 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts +22 -2
- package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.value-gate.js +143 -6
- package/dist/src/security/scanner/SecurityScanner.value-gate.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts +2 -2
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.js +185 -190
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.js.map +1 -1
- package/dist/src/security/scanner/patterns.d.ts +47 -2
- package/dist/src/security/scanner/patterns.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.js +48 -3
- package/dist/src/security/scanner/patterns.js.map +1 -1
- package/dist/src/security/scanner/patterns.sensitive-path.d.ts +31 -3
- package/dist/src/security/scanner/patterns.sensitive-path.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.sensitive-path.js +59 -4
- package/dist/src/security/scanner/patterns.sensitive-path.js.map +1 -1
- package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -1
- package/dist/src/services/agent-pack/prompt-source.js +3 -2
- package/dist/src/services/agent-pack/prompt-source.js.map +1 -1
- package/dist/src/services/skill-installation.content.d.ts +7 -2
- package/dist/src/services/skill-installation.content.d.ts.map +1 -1
- package/dist/src/services/skill-installation.content.js +75 -28
- package/dist/src/services/skill-installation.content.js.map +1 -1
- package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
- package/dist/src/services/skill-installation.helpers.js +8 -0
- package/dist/src/services/skill-installation.helpers.js.map +1 -1
- package/dist/src/services/skill-installation.io.d.ts +1 -29
- package/dist/src/services/skill-installation.io.d.ts.map +1 -1
- package/dist/src/services/skill-installation.io.dirs.d.ts +15 -0
- package/dist/src/services/skill-installation.io.dirs.d.ts.map +1 -0
- package/dist/src/services/skill-installation.io.dirs.js +84 -0
- package/dist/src/services/skill-installation.io.dirs.js.map +1 -0
- package/dist/src/services/skill-installation.io.js +6 -176
- package/dist/src/services/skill-installation.io.js.map +1 -1
- package/dist/src/services/skill-installation.io.rollback.d.ts +138 -0
- package/dist/src/services/skill-installation.io.rollback.d.ts.map +1 -0
- package/dist/src/services/skill-installation.io.rollback.js +218 -0
- package/dist/src/services/skill-installation.io.rollback.js.map +1 -0
- package/dist/src/services/skill-installation.io.write.d.ts +69 -0
- package/dist/src/services/skill-installation.io.write.d.ts.map +1 -0
- package/dist/src/services/skill-installation.io.write.js +417 -0
- package/dist/src/services/skill-installation.io.write.js.map +1 -0
- package/dist/src/services/skill-installation.service.d.ts.map +1 -1
- package/dist/src/services/skill-installation.service.finalize.d.ts +62 -0
- package/dist/src/services/skill-installation.service.finalize.d.ts.map +1 -0
- package/dist/src/services/skill-installation.service.finalize.js +136 -0
- package/dist/src/services/skill-installation.service.finalize.js.map +1 -0
- package/dist/src/services/skill-installation.service.js +66 -80
- package/dist/src/services/skill-installation.service.js.map +1 -1
- package/dist/src/services/skill-installation.target-guard.d.ts +82 -0
- package/dist/src/services/skill-installation.target-guard.d.ts.map +1 -0
- package/dist/src/services/skill-installation.target-guard.js +410 -0
- package/dist/src/services/skill-installation.target-guard.js.map +1 -0
- package/dist/src/services/skill-installation.types.d.ts +13 -1
- package/dist/src/services/skill-installation.types.d.ts.map +1 -1
- package/dist/src/services/skill-installation.types.js.map +1 -1
- package/dist/src/services/skill-installation.uninstall.d.ts +3 -1
- package/dist/src/services/skill-installation.uninstall.d.ts.map +1 -1
- package/dist/src/services/skill-installation.uninstall.helpers.d.ts +59 -0
- package/dist/src/services/skill-installation.uninstall.helpers.d.ts.map +1 -0
- package/dist/src/services/skill-installation.uninstall.helpers.js +124 -0
- package/dist/src/services/skill-installation.uninstall.helpers.js.map +1 -0
- package/dist/src/services/skill-installation.uninstall.js +148 -25
- package/dist/src/services/skill-installation.uninstall.js.map +1 -1
- package/dist/src/utils/safe-fs.d.ts +69 -0
- package/dist/src/utils/safe-fs.d.ts.map +1 -1
- package/dist/src/utils/safe-fs.js +113 -2
- package/dist/src/utils/safe-fs.js.map +1 -1
- package/dist/tests/install/fan-out.test.js +1951 -13
- package/dist/tests/install/fan-out.test.js.map +1 -1
- package/dist/tests/install/remove-if-same.test.d.ts +2 -0
- package/dist/tests/install/remove-if-same.test.d.ts.map +1 -0
- package/dist/tests/install/remove-if-same.test.js +298 -0
- package/dist/tests/install/remove-if-same.test.js.map +1 -0
- package/dist/tests/integration/fan-out-lock-contention.test.d.ts +11 -0
- package/dist/tests/integration/fan-out-lock-contention.test.d.ts.map +1 -0
- package/dist/tests/integration/fan-out-lock-contention.test.js +53 -0
- package/dist/tests/integration/fan-out-lock-contention.test.js.map +1 -0
- package/dist/tests/provenance/backfill.test.js +43 -0
- package/dist/tests/provenance/backfill.test.js.map +1 -1
- package/dist/tests/security/scanner-regression-guard.test.js +33 -5
- package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
- package/dist/tests/security/sensitive-path-adversarial-review.test.js +120 -0
- package/dist/tests/security/sensitive-path-adversarial-review.test.js.map +1 -1
- package/dist/tests/security/sensitive-path-boolean-flag.test.d.ts +2 -0
- package/dist/tests/security/sensitive-path-boolean-flag.test.d.ts.map +1 -0
- package/dist/tests/security/sensitive-path-boolean-flag.test.js +151 -0
- package/dist/tests/security/sensitive-path-boolean-flag.test.js.map +1 -0
- package/dist/tests/security/sensitive-path-fp.test.js +71 -5
- package/dist/tests/security/sensitive-path-fp.test.js.map +1 -1
- package/dist/tests/security/sensitive-path-prefixed-secrets.test.d.ts +2 -0
- package/dist/tests/security/sensitive-path-prefixed-secrets.test.d.ts.map +1 -0
- package/dist/tests/security/sensitive-path-prefixed-secrets.test.js +176 -0
- package/dist/tests/security/sensitive-path-prefixed-secrets.test.js.map +1 -0
- package/dist/tests/security/weak-password-lexicon.test.js +14 -4
- package/dist/tests/security/weak-password-lexicon.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.content.test.js +23 -0
- package/dist/tests/unit/services/skill-installation.content.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js +35 -14
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.io.rollback.test.d.ts +2 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.test.js +984 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.d.ts +2 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.js +148 -0
- package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.js +19 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.service.finalize.test.d.ts +2 -0
- package/dist/tests/unit/services/skill-installation.service.finalize.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.finalize.test.js +147 -0
- package/dist/tests/unit/services/skill-installation.service.finalize.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.test.js +43 -0
- package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.target-guard.test.d.ts +2 -0
- package/dist/tests/unit/services/skill-installation.target-guard.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.target-guard.test.js +590 -0
- package/dist/tests/unit/services/skill-installation.target-guard.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.uninstall.guard.test.d.ts +2 -0
- package/dist/tests/unit/services/skill-installation.uninstall.guard.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.uninstall.guard.test.js +473 -0
- package/dist/tests/unit/services/skill-installation.uninstall.guard.test.js.map +1 -0
- package/dist/tests/utils/safe-fs.test.js +129 -2
- package/dist/tests/utils/safe-fs.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -11,60 +11,18 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Every fan-out is recorded in `~/.skillsmith/links/manifest.json` so
|
|
13
13
|
* `removeLinks(skillId)` can tear down both copies and symlinks atomically
|
|
14
|
-
* during uninstall.
|
|
14
|
+
* during uninstall. The manifest itself lives in fan-out.manifest.ts.
|
|
15
15
|
*
|
|
16
16
|
* @module @skillsmith/core/install/fan-out
|
|
17
17
|
*/
|
|
18
|
-
import { homedir } from 'node:os';
|
|
19
18
|
import * as path from 'node:path';
|
|
20
19
|
import * as fs from 'node:fs';
|
|
21
20
|
import * as fsp from 'node:fs/promises';
|
|
22
21
|
import { CLIENT_NATIVE_PATHS, CANONICAL_CLIENT } from './paths.js';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* the existing allow-list entry for that directory (DEFAULT_ALLOWED_DIRS in
|
|
28
|
-
* `pathValidation.ts`).
|
|
29
|
-
*/
|
|
30
|
-
export function getLinkManifestPath() {
|
|
31
|
-
return path.join(homedir(), '.skillsmith', 'links', 'manifest.json');
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Load the manifest from disk. Returns an empty manifest if the file is
|
|
35
|
-
* missing or unreadable — fan-out is best-effort, never crash on cold start.
|
|
36
|
-
*/
|
|
37
|
-
export async function loadManifest() {
|
|
38
|
-
const manifestPath = getLinkManifestPath();
|
|
39
|
-
try {
|
|
40
|
-
const raw = await fsp.readFile(manifestPath, 'utf-8');
|
|
41
|
-
const parsed = JSON.parse(raw);
|
|
42
|
-
if (parsed?.version !== MANIFEST_VERSION || !Array.isArray(parsed.links)) {
|
|
43
|
-
return { version: MANIFEST_VERSION, links: [] };
|
|
44
|
-
}
|
|
45
|
-
return parsed;
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
return { version: MANIFEST_VERSION, links: [] };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Persist the manifest atomically (write-temp + rename) so a crash mid-write
|
|
53
|
-
* never leaves the file in a partial state.
|
|
54
|
-
*/
|
|
55
|
-
export async function saveManifest(manifest) {
|
|
56
|
-
const manifestPath = getLinkManifestPath();
|
|
57
|
-
// SMI-6343 follow-up (adversarial review): a fourth parallel manifest-write
|
|
58
|
-
// implementation (a different file, `links/manifest.json`, but the same
|
|
59
|
-
// homedir-derived-with-no-override shape). The $HOME sandbox
|
|
60
|
-
// (vitest.setup.ts) was this file's only defense until this guard.
|
|
61
|
-
assertNotRealUserHome(manifestPath, 'write');
|
|
62
|
-
const dir = path.dirname(manifestPath);
|
|
63
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
64
|
-
const tmp = `${manifestPath}.${process.pid}.tmp`;
|
|
65
|
-
await fsp.writeFile(tmp, JSON.stringify(manifest, null, 2), 'utf-8');
|
|
66
|
-
await fsp.rename(tmp, manifestPath);
|
|
67
|
-
}
|
|
22
|
+
import { assertOverwritable, leftoverBackupWarning, listLeftoverBackups, recoverDestination, replaceDestination, withDestinationLock, } from './fan-out.overwrite.js';
|
|
23
|
+
import { getLinkManifestPath, loadManifest, readManifestFile, unreadableManifestError, updateManifest, } from './fan-out.manifest.js';
|
|
24
|
+
import { removeRecordedLink, undoUnrecordedWrite } from './fan-out.cleanup.js';
|
|
25
|
+
export { getLinkManifestPath, loadManifest, saveManifest } from './fan-out.manifest.js';
|
|
68
26
|
/**
|
|
69
27
|
* Detect a fan-out cycle: refuses to link `from → to` when `to` is already
|
|
70
28
|
* the source of any entry, OR when `from` is already the destination of any
|
|
@@ -110,28 +68,22 @@ async function copyDirectoryRecursive(src, dest) {
|
|
|
110
68
|
}
|
|
111
69
|
}
|
|
112
70
|
}
|
|
113
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Round 27 (cross-model review): this returned a plain boolean, so a
|
|
73
|
+
* permission or I/O failure was reported to the user as "does not exist" —
|
|
74
|
+
* sending them to reinstall a skill that is sitting right where they left it.
|
|
75
|
+
* Only absence is absence.
|
|
76
|
+
*/
|
|
77
|
+
async function inspectPath(p) {
|
|
114
78
|
try {
|
|
115
79
|
await fsp.access(p, fs.constants.F_OK);
|
|
116
|
-
return
|
|
80
|
+
return { kind: 'present' };
|
|
117
81
|
}
|
|
118
|
-
catch {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const stat = await fsp.lstat(p);
|
|
125
|
-
if (stat.isSymbolicLink() || stat.isFile()) {
|
|
126
|
-
await fsp.unlink(p);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
await fsp.rm(p, { recursive: true, force: true });
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
// Best-effort — uninstall should not fail because cleanup races with
|
|
134
|
-
// an external editor that already moved the file.
|
|
82
|
+
catch (err) {
|
|
83
|
+
const code = err?.code;
|
|
84
|
+
if (code === 'ENOENT' || code === 'ENOTDIR')
|
|
85
|
+
return { kind: 'absent' };
|
|
86
|
+
return { kind: 'unknown', reason: code ?? (err instanceof Error ? err.message : String(err)) };
|
|
135
87
|
}
|
|
136
88
|
}
|
|
137
89
|
/**
|
|
@@ -151,74 +103,223 @@ export async function addLink(opts) {
|
|
|
151
103
|
}
|
|
152
104
|
const fromDir = path.join(CLIENT_NATIVE_PATHS[fromClient], skillId);
|
|
153
105
|
const toDir = path.join(CLIENT_NATIVE_PATHS[toClient], skillId);
|
|
154
|
-
|
|
106
|
+
const source = await inspectPath(fromDir);
|
|
107
|
+
if (source.kind === 'absent') {
|
|
155
108
|
throw new Error(`addLink: source skill '${skillId}' does not exist at ${fromDir} — install for ${fromClient} first`);
|
|
156
109
|
}
|
|
157
|
-
|
|
158
|
-
|
|
110
|
+
if (source.kind === 'unknown') {
|
|
111
|
+
throw new Error(`addLink: the source skill at ${fromDir} could not be checked (${source.reason}), so ` +
|
|
112
|
+
`nothing was changed.`);
|
|
113
|
+
}
|
|
114
|
+
const cycle = detectCycle(await loadManifest(), fromDir, toDir);
|
|
159
115
|
if (cycle)
|
|
160
116
|
throw new Error(`addLink: ${cycle}`);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const relTarget = path.relative(path.dirname(toDir), fromDir);
|
|
117
|
+
// SMI-6529 round 6: everything that reads or writes the destination runs
|
|
118
|
+
// under its lock, so a concurrent call can never touch another call's
|
|
119
|
+
// staging or backup folder (see fan-out.overwrite.ts).
|
|
120
|
+
return withDestinationLock(toDir, async () => {
|
|
121
|
+
// Round 9: fail before writing anything if the manifest can't be read,
|
|
122
|
+
// since the new copy could never be recorded.
|
|
123
|
+
const read = await readManifestFile();
|
|
124
|
+
if (read.state === 'unreadable')
|
|
125
|
+
throw unreadableManifestError(read.reason);
|
|
126
|
+
const manifest = read.manifest;
|
|
127
|
+
const recovery = await recoverDestination(toDir, manifest);
|
|
128
|
+
let existing = null;
|
|
174
129
|
try {
|
|
175
|
-
await fsp.
|
|
176
|
-
kind = 'symlink';
|
|
130
|
+
existing = await fsp.lstat(toDir);
|
|
177
131
|
}
|
|
178
132
|
catch (err) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
133
|
+
if (err.code !== 'ENOENT')
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
if (existing) {
|
|
137
|
+
if (!force) {
|
|
138
|
+
throw new Error(`addLink: ${toDir} already exists. Pass force: true (CLI: --force) to overwrite. ` +
|
|
139
|
+
`If it is an empty directory, an interrupted install may have left it; Skillsmith ` +
|
|
140
|
+
`does not remove it for you, since an empty directory you made looks the same.`);
|
|
141
|
+
}
|
|
142
|
+
// Round 10: say why there's no record, rather than "not recorded".
|
|
143
|
+
if (read.state === 'corrupt' && !existing.isSymbolicLink()) {
|
|
144
|
+
throw new Error(`addLink: ${toDir} already exists, and the fan-out link manifest at ` +
|
|
145
|
+
`${getLinkManifestPath()} could not be parsed, so nothing shows Skillsmith made ` +
|
|
146
|
+
`this copy. Fix or move the manifest, or remove ${toDir} yourself, then retry.`);
|
|
147
|
+
}
|
|
148
|
+
await assertOverwritable(toDir, existing, manifest);
|
|
149
|
+
}
|
|
150
|
+
// Round 11: a symlink is replaced with no backup, so keep its target in
|
|
151
|
+
// case the new record can't be saved and it has to be put back.
|
|
152
|
+
const oldLinkTarget = existing?.isSymbolicLink() ? await fsp.readlink(toDir) : undefined;
|
|
153
|
+
let kind = 'copy';
|
|
154
|
+
let fellBackToCopy = false;
|
|
155
|
+
// The new copy or symlink is written to a staging path and swapped into
|
|
156
|
+
// place; a failure here never touches the existing destination. `placed`
|
|
157
|
+
// is what this call put in place, so an undo only removes that.
|
|
158
|
+
const { placed, warnings: swapWarnings } = await replaceDestination(toDir, async (staged) => {
|
|
159
|
+
if (preferSymlink) {
|
|
160
|
+
// A relative symlink keeps the manifest entry portable across homedir
|
|
161
|
+
// changes. It is computed for the FINAL location, not the staging path.
|
|
162
|
+
const relTarget = path.relative(path.dirname(toDir), fromDir);
|
|
163
|
+
try {
|
|
164
|
+
await fsp.symlink(relTarget, staged, 'dir');
|
|
165
|
+
kind = 'symlink';
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
const code = err.code;
|
|
169
|
+
if (code === 'EPERM' || code === 'ENOSYS') {
|
|
170
|
+
await copyDirectoryRecursive(fromDir, staged);
|
|
171
|
+
kind = 'copy';
|
|
172
|
+
fellBackToCopy = true;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
throw err;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
184
178
|
}
|
|
185
179
|
else {
|
|
186
|
-
|
|
180
|
+
await copyDirectoryRecursive(fromDir, staged);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
const record = {
|
|
184
|
+
skillId,
|
|
185
|
+
from: fromDir,
|
|
186
|
+
to: toDir,
|
|
187
|
+
kind,
|
|
188
|
+
createdAt: new Date().toISOString(),
|
|
189
|
+
};
|
|
190
|
+
// SMI-6529 N7: a force-overwrite of an already-recorded destination
|
|
191
|
+
// replaces its manifest entry rather than appending a second one.
|
|
192
|
+
const resolvedToDir = path.resolve(toDir);
|
|
193
|
+
let manifestWarning;
|
|
194
|
+
try {
|
|
195
|
+
manifestWarning = await updateManifest((current) => {
|
|
196
|
+
current.links = current.links.filter((l) => path.resolve(l.to) !== resolvedToDir);
|
|
197
|
+
current.links.push(record);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
if (!existing || oldLinkTarget !== undefined) {
|
|
202
|
+
await undoUnrecordedWrite(toDir, err, oldLinkTarget, placed);
|
|
203
|
+
}
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
const leftovers = await listLeftoverBackups(toDir);
|
|
207
|
+
const warnings = [
|
|
208
|
+
...(manifestWarning ? [manifestWarning] : []),
|
|
209
|
+
...swapWarnings,
|
|
210
|
+
...(recovery.unreadable ? [recovery.unreadable] : []),
|
|
211
|
+
...(leftovers.unreadable ? [leftovers.unreadable] : []),
|
|
212
|
+
...leftovers.folders.map(leftoverBackupWarning),
|
|
213
|
+
];
|
|
214
|
+
return warnings.length > 0 ? { record, fellBackToCopy, warnings } : { record, fellBackToCopy };
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Warning for an uninstall that couldn't use the manifest (rounds 11–12). By
|
|
219
|
+
* then the canonical skill is gone, so a second uninstall stops at "not
|
|
220
|
+
* installed" and never gets here: any fan-out copy left is the user's to
|
|
221
|
+
* remove. List the ones on disk so they know where to look.
|
|
222
|
+
*/
|
|
223
|
+
async function unusableManifestWarning(read, skillId) {
|
|
224
|
+
const why = read.state === 'corrupt' ? 'could not be parsed' : `could not be read (${read.reason})`;
|
|
225
|
+
const canonical = path.resolve(CLIENT_NATIVE_PATHS[CANONICAL_CLIENT]);
|
|
226
|
+
const candidates = [];
|
|
227
|
+
const unreadable = [];
|
|
228
|
+
for (const root of new Set(Object.values(CLIENT_NATIVE_PATHS))) {
|
|
229
|
+
if (path.resolve(root) === canonical)
|
|
230
|
+
continue;
|
|
231
|
+
const dir = path.join(root, skillId);
|
|
232
|
+
try {
|
|
233
|
+
await fsp.lstat(dir);
|
|
234
|
+
candidates.push(dir);
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
// Round 27 (cross-model review): a folder that could not be inspected is
|
|
238
|
+
// not a folder that isn't there, and this message went on to promise
|
|
239
|
+
// there was "nothing to clean up".
|
|
240
|
+
const code = err?.code;
|
|
241
|
+
if (code !== 'ENOENT' && code !== 'ENOTDIR') {
|
|
242
|
+
unreadable.push(`${dir} (${code ?? (err instanceof Error ? err.message : String(err))})`);
|
|
187
243
|
}
|
|
188
244
|
}
|
|
189
245
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
246
|
+
const found = candidates.length > 0
|
|
247
|
+
? ` These may be fan-out copies Skillsmith made; check each one and delete it yourself ` +
|
|
248
|
+
`if you don't need it: ${candidates.join(', ')}.`
|
|
249
|
+
: '';
|
|
250
|
+
const couldNotCheck = unreadable.length > 0
|
|
251
|
+
? ` These could not be checked, so anything under them is not reported here: ` +
|
|
252
|
+
`${unreadable.join(', ')}.`
|
|
253
|
+
: '';
|
|
254
|
+
const next = found === '' && couldNotCheck === ''
|
|
255
|
+
? ` No other client's skills folder has a ${skillId} folder, so there is nothing to clean up.`
|
|
256
|
+
: `${found}${couldNotCheck}`;
|
|
257
|
+
return (`the fan-out link manifest at ${getLinkManifestPath()} ${why}, so no fan-out copies of ` +
|
|
258
|
+
`${skillId} were checked or removed.${next}`);
|
|
203
259
|
}
|
|
204
260
|
/**
|
|
205
|
-
* Remove every fan-out link recorded for `skillId`.
|
|
206
|
-
*
|
|
261
|
+
* Remove every fan-out link recorded for `skillId`. Safe to call when no
|
|
262
|
+
* manifest exists (returns `{ removed: 0, refused: [] }`).
|
|
207
263
|
*
|
|
208
264
|
* Uninstall callers should invoke this BEFORE removing the canonical
|
|
209
265
|
* directory so symlinks resolve cleanly during their lstat checks.
|
|
266
|
+
*
|
|
267
|
+
* SMI-6529 N6 (round 4): a destination `removeRecordedLink` refuses (a
|
|
268
|
+
* recorded copy that now contains `.git` at its root, or a removal error)
|
|
269
|
+
* keeps its manifest entry instead of being unconditionally dropped — the
|
|
270
|
+
* old unconditional `manifest.links = manifest.links.filter(...)` discarded
|
|
271
|
+
* the record for EVERY matching link regardless of whether the on-disk
|
|
272
|
+
* removal actually succeeded, so a refused destination could never be
|
|
273
|
+
* retried and its refusal was never reported anywhere.
|
|
210
274
|
*/
|
|
211
275
|
export async function removeLinks(skillId) {
|
|
212
|
-
const
|
|
213
|
-
|
|
276
|
+
const read = await readManifestFile();
|
|
277
|
+
// Round 11: an unusable manifest used to read as empty, so an uninstall
|
|
278
|
+
// said nothing and left every fan-out copy behind. Say so instead, and
|
|
279
|
+
// leave the file alone.
|
|
280
|
+
if (read.state === 'unreadable' || read.state === 'corrupt') {
|
|
281
|
+
return { removed: 0, refused: [], warnings: [await unusableManifestWarning(read, skillId)] };
|
|
282
|
+
}
|
|
283
|
+
const matching = read.manifest.links.filter((l) => l.skillId === skillId);
|
|
214
284
|
if (matching.length === 0)
|
|
215
|
-
return 0;
|
|
285
|
+
return { removed: 0, refused: [] };
|
|
286
|
+
const refused = [];
|
|
287
|
+
const warnings = [];
|
|
288
|
+
const removedTargets = new Set();
|
|
216
289
|
for (const link of matching) {
|
|
217
|
-
|
|
290
|
+
// SMI-6529 round 6: same per-destination lock as addLink. The record is
|
|
291
|
+
// dropped while that lock is still held (round 10): filtering after the
|
|
292
|
+
// loop also dropped a record a later re-link had saved, leaving its copy
|
|
293
|
+
// untracked. Round 11: drop the records the manifest holds for this
|
|
294
|
+
// destination now, not the one read above; a force refresh that ran
|
|
295
|
+
// first had replaced it, and dropping only the old one left a record for
|
|
296
|
+
// the folder just removed. Every writer of a destination's records holds
|
|
297
|
+
// its lock, so this read is current.
|
|
298
|
+
const resolvedTo = path.resolve(link.to);
|
|
299
|
+
const step = await withDestinationLock(link.to, async () => {
|
|
300
|
+
const outcome = await removeRecordedLink(link.to);
|
|
301
|
+
const manifestWarning = outcome.removed
|
|
302
|
+
? await updateManifest((current) => {
|
|
303
|
+
current.links = current.links.filter((l) => l.skillId !== skillId || path.resolve(l.to) !== resolvedTo);
|
|
304
|
+
})
|
|
305
|
+
: undefined;
|
|
306
|
+
return { outcome, manifestWarning, leftovers: await listLeftoverBackups(link.to) };
|
|
307
|
+
});
|
|
308
|
+
if (step.manifestWarning)
|
|
309
|
+
warnings.push(step.manifestWarning);
|
|
310
|
+
if (step.outcome.removed) {
|
|
311
|
+
removedTargets.add(link.to);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
refused.push({ to: link.to, reason: step.outcome.reason });
|
|
315
|
+
}
|
|
316
|
+
if (step.leftovers.unreadable)
|
|
317
|
+
warnings.push(step.leftovers.unreadable);
|
|
318
|
+
warnings.push(...step.leftovers.folders.map(leftoverBackupWarning));
|
|
218
319
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
320
|
+
return warnings.length > 0
|
|
321
|
+
? { removed: removedTargets.size, refused, warnings }
|
|
322
|
+
: { removed: removedTargets.size, refused };
|
|
222
323
|
}
|
|
223
324
|
/**
|
|
224
325
|
* List all fan-out links for a skill (or all skills when `skillId` is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-out.js","sourceRoot":"","sources":["../../../src/install/fan-out.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fan-out.js","sourceRoot":"","sources":["../../../src/install/fan-out.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Stats } from 'node:fs';
|
|
2
|
+
import type { LinkManifest } from './fan-out.manifest.js';
|
|
3
|
+
/** What a leftover scan found, and whether it could look at all. */
|
|
4
|
+
export interface LeftoverScan {
|
|
5
|
+
/** Hidden folders beside the destination that an interrupted operation left. */
|
|
6
|
+
folders: string[];
|
|
7
|
+
/**
|
|
8
|
+
* Set when the parent folder could not be listed. Round 24 (cross-model
|
|
9
|
+
* review): returning an empty list then reports "could not look" as "nothing
|
|
10
|
+
* is there", and the accepted residual's promise is that a displaced entry
|
|
11
|
+
* gets reported.
|
|
12
|
+
*/
|
|
13
|
+
unreadable?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const BACKUP_TAG = ".skillsmith-backup-";
|
|
16
|
+
export declare const STAGING_TAG = ".skillsmith-staging-";
|
|
17
|
+
export declare function escapeRegExp(s: string): string;
|
|
18
|
+
/** Hidden sibling name prefix for `dest`, e.g. `.foo.skillsmith-backup-`. */
|
|
19
|
+
export declare function siblingPrefix(dest: string, tag: string): string;
|
|
20
|
+
/** Exact match for a `mkdtemp` folder made from `siblingPrefix(dest, tag)` (6-char suffix). */
|
|
21
|
+
export declare function siblingPattern(dest: string, tag: string): RegExp;
|
|
22
|
+
export declare function lstatOrNull(p: string): Promise<Stats | null>;
|
|
23
|
+
/** Whether the link manifest records `dest` as a copy Skillsmith made. */
|
|
24
|
+
export declare function isRecordedCopy(dest: string, manifest: LinkManifest): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Housekeeping under the destination lock, before any write:
|
|
27
|
+
* - remove an empty backup folder (a crash before anything was moved in);
|
|
28
|
+
* - restore a backup stranded by a crash between the rename-aside and the
|
|
29
|
+
* swap: the destination is missing, this is the only backup whose
|
|
30
|
+
* `original` is a real directory, and the manifest still records the
|
|
31
|
+
* destination as a copy. Backups are only ever made of recorded copies,
|
|
32
|
+
* so an unrecorded one has been uninstalled since, and restoring it would
|
|
33
|
+
* bring back a stale, untracked copy. With two or more, nothing says which
|
|
34
|
+
* is newest (a name can sort anywhere), so none is restored (round 9).
|
|
35
|
+
*
|
|
36
|
+
* Any other backup is left in place for `listLeftoverBackups` to report, and
|
|
37
|
+
* so is a staging folder left by a crashed write: round 14 (cross-model
|
|
38
|
+
* review) stopped deleting those here, since neither a folder's name nor its
|
|
39
|
+
* contents proves who owns it now. Returns the backup folders restored from.
|
|
40
|
+
*/
|
|
41
|
+
export declare function recoverDestination(dest: string, manifest: LinkManifest): Promise<{
|
|
42
|
+
restored: string[];
|
|
43
|
+
unreadable?: string;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Backup folders for `dest` that are still present: copies an interrupted
|
|
47
|
+
* refresh left behind (after the swap, or unrestorable). Round 7: these are
|
|
48
|
+
* reported to the user rather than kept silently or deleted. Round 8: an
|
|
49
|
+
* empty one holds nothing to report and is removed. Round 9: on a volume
|
|
50
|
+
* that ignores case, a backup made under another spelling of the name
|
|
51
|
+
* (`.Foo.` for `foo`) belongs to this destination too, so it is reported;
|
|
52
|
+
* it is never removed or restored, since on a case-sensitive volume the
|
|
53
|
+
* same name belongs to a different destination. Round 14: a staging folder
|
|
54
|
+
* left by a crashed write is reported the same way. Round 15: so is what a
|
|
55
|
+
* crashed or failed removal left under a parked name. Call under the lock.
|
|
56
|
+
*/
|
|
57
|
+
export declare function listLeftoverBackups(dest: string): Promise<LeftoverScan>;
|
|
58
|
+
/** User-facing warning for a leftover backup, staging folder or parked entry. */
|
|
59
|
+
export declare function leftoverBackupWarning(folder: string): string;
|
|
60
|
+
//# sourceMappingURL=fan-out.leftovers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-out.leftovers.d.ts","sourceRoot":"","sources":["../../../src/install/fan-out.leftovers.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGzD,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,gFAAgF;IAChF,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAqBD,eAAO,MAAM,UAAU,wBAAwB,CAAA;AAC/C,eAAO,MAAM,WAAW,yBAAyB,CAAA;AAEjD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhE;AAiBD,wBAAsB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAOlE;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAG5E;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8CtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8B7E;AAiCD,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoB5D"}
|