@skillsmith/core 0.12.3 → 0.12.4
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 +164 -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
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview writeInstallFiles() — the disk-write + rollback core of skill install.
|
|
3
|
+
* @module @skillsmith/core/services/skill-installation.io.write
|
|
4
|
+
* @see SMI-6529 Wave A0 round 2: split out of skill-installation.io.ts to stay
|
|
5
|
+
* under the 500-line CI gate once the M4/M7/M10/L14/L15 fixes landed — pure
|
|
6
|
+
* move for everything that predates this split, no behavior change to it.
|
|
7
|
+
* Re-exported from skill-installation.io.ts so every existing
|
|
8
|
+
* `from './skill-installation.io.js'` import site is unaffected.
|
|
9
|
+
* @see SMI-6529 round 4 (N1/N2/N8/N9/N11/N12): confirmation-review fixes —
|
|
10
|
+
* see each inline comment below for the specific finding it closes.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs/promises';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { safeWriteFile, safeCreateFile } from '../utils/safe-fs.js';
|
|
15
|
+
import { CANONICAL_CLIENT, getCompanionAgentTarget, resolveCompanionAgentPath, } from '../install/paths.js';
|
|
16
|
+
import { classifyPreWrite, cleanupStep, removeCreatedDirectory, restoreSnapshots, InstallRestoreError, } from './skill-installation.io.rollback.js';
|
|
17
|
+
/** Errors a non-recursive rmdir in rollback can ignore: already gone, or holding content this call didn't create. */
|
|
18
|
+
const DIR_GONE_OR_NOT_OURS = ['ENOENT', 'ENOTEMPTY', 'EEXIST'];
|
|
19
|
+
import { mkdirNoFollow } from './skill-installation.io.dirs.js';
|
|
20
|
+
/**
|
|
21
|
+
* Write a skill's files into `installPath`, snapshotting every file it will
|
|
22
|
+
* overwrite first. On failure it restores those files and removes only what
|
|
23
|
+
* it created; a directory that existed before the call is never removed.
|
|
24
|
+
* Callers run `checkInstallTarget` first.
|
|
25
|
+
*/
|
|
26
|
+
export async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, subSkillFiles, subagentContent,
|
|
27
|
+
/**
|
|
28
|
+
* SMI-5980 (Wave 3): the client this companion subagent (if any) is
|
|
29
|
+
* generated for — resolves its output path via
|
|
30
|
+
* `resolveCompanionAgentPath()` (install/paths.ts) instead of a hardcoded
|
|
31
|
+
* `~/.claude/agents/` literal. Optional, defaulting to `CANONICAL_CLIENT`
|
|
32
|
+
* (`claude-code`) so pre-existing callers/tests that never pass it keep
|
|
33
|
+
* today's exact behavior unchanged.
|
|
34
|
+
*/
|
|
35
|
+
client = CANONICAL_CLIENT,
|
|
36
|
+
/**
|
|
37
|
+
* SMI-5982 code-review fix #1: explicit base dir for resolving a RELATIVE
|
|
38
|
+
* `COMPANION_AGENT_TARGETS[client].dir` (Antigravity only — every other
|
|
39
|
+
* client's `dir` is absolute already). Threaded through to
|
|
40
|
+
* `resolveCompanionAgentPath()`'s own `baseDir` param as-is (no
|
|
41
|
+
* `?? process.cwd()` fallback here) — `resolveCompanionAgentPath()` itself
|
|
42
|
+
* now requires an explicit `baseDir` for every `directory-package`-mode
|
|
43
|
+
* client (PR-review follow-up), so whether an omitted `companionBaseDir`
|
|
44
|
+
* is acceptable is that function's call to make, not this one's.
|
|
45
|
+
*/
|
|
46
|
+
companionBaseDir) {
|
|
47
|
+
const writtenFiles = [];
|
|
48
|
+
// SMI-6529: files this call OVERWROTE (snapshotted, restorable) vs. files it
|
|
49
|
+
// CREATED FRESH (safe to unlink). A pre-existing file must never be deleted —
|
|
50
|
+
// only ever restored to its original bytes/mode.
|
|
51
|
+
const overwritten = [];
|
|
52
|
+
// SMI-6529 R5 (round 5): each fresh file carries the (dev, ino) it had when
|
|
53
|
+
// this call created it, so rollback never unlinks a file another process
|
|
54
|
+
// has since put at the same path.
|
|
55
|
+
const createdFresh = [];
|
|
56
|
+
// F4: nested sub-skill directories (e.g. "scripts/") THIS call created fresh —
|
|
57
|
+
// removed on rollback, non-recursively, deepest first.
|
|
58
|
+
const freshDirs = new Set();
|
|
59
|
+
let subagentPath;
|
|
60
|
+
let companionSkipped = false;
|
|
61
|
+
// SMI-6529 L15: whether the directory-package per-skill agent directory
|
|
62
|
+
// (Antigravity's <agentsDir>/<skillName>/) already existed before this call
|
|
63
|
+
// — only a directory THIS call created may ever be rmdir'd on rollback.
|
|
64
|
+
let agentDirPreExisted = true;
|
|
65
|
+
// SMI-6529 M4/N1: per-target write queue — serializes every write racing
|
|
66
|
+
// for the same on-disk target (see `writeTracked`'s own doc comment).
|
|
67
|
+
const writeQueues = new Map();
|
|
68
|
+
// SMI-5359 (retro): lexically reject an escaping installPath BEFORE any filesystem
|
|
69
|
+
// mutation. path.resolve normalizes `..`, so an unsanitized skillName like '..'
|
|
70
|
+
// (e.g. path.basename('foo/..')) or a compromised registry skillName cannot drive
|
|
71
|
+
// installPath outside skillsDir and reach the rollback below. Thrown here, nothing
|
|
72
|
+
// has been created, so no cleanup is needed.
|
|
73
|
+
const resolvedInstall = path.resolve(installPath);
|
|
74
|
+
const resolvedSkillsDir = path.resolve(skillsDir);
|
|
75
|
+
if (resolvedInstall !== resolvedSkillsDir &&
|
|
76
|
+
!resolvedInstall.startsWith(resolvedSkillsDir + path.sep)) {
|
|
77
|
+
throw new Error('Install path escapes skills directory (lexical): ' + installPath);
|
|
78
|
+
}
|
|
79
|
+
// Only set true once installPath is PROVEN inside skillsDir (both the lexical check
|
|
80
|
+
// above and the realpath check below). The recursive rollback rm keys off this so it
|
|
81
|
+
// can never force-delete an out-of-bounds path (e.g. a symlink-escape the realpath
|
|
82
|
+
// check rejects after mkdir).
|
|
83
|
+
let pathValidated = false;
|
|
84
|
+
// Round 13: the identity of the directory this call created, if it did.
|
|
85
|
+
let installDirIdentity;
|
|
86
|
+
// SMI-6529: determine BEFORE any mutation whether installPath already existed — a
|
|
87
|
+
// rollback must NEVER remove a directory that existed before this call started
|
|
88
|
+
// (the data-loss bug: a real user's git-cloned skill directory, `.git` included, got
|
|
89
|
+
// force-deleted by a failed reinstall). `false` only on a genuine ENOENT; any other
|
|
90
|
+
// lstat error is rethrown (fail closed, never guessed).
|
|
91
|
+
let preExisted;
|
|
92
|
+
try {
|
|
93
|
+
await fs.lstat(installPath);
|
|
94
|
+
preExisted = true;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (err.code === 'ENOENT') {
|
|
98
|
+
preExisted = false;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Classify-then-write a single tracked file. F1 (review round 1): the rollback
|
|
106
|
+
* candidate MUST be recorded BEFORE `safeWriteFile` is ever called, never after
|
|
107
|
+
* it "succeeds" — `safeWriteFile` opens with O_TRUNC and writes in place, which
|
|
108
|
+
* is not atomic, so a write that fails mid-way (ENOSPC/EIO after truncation)
|
|
109
|
+
* would otherwise leave a truncated original with no recorded snapshot to
|
|
110
|
+
* restore it from.
|
|
111
|
+
*
|
|
112
|
+
* SMI-6529 M4 (round 2) / N1+N2 (round 4): every write is queued behind any
|
|
113
|
+
* EARLIER write to the identical on-disk target — key =
|
|
114
|
+
* `path.resolve(filePath).toLowerCase()`, so two DIFFERENT literal
|
|
115
|
+
* filenames that normalize to the same path ("examples.md" vs
|
|
116
|
+
* "./examples.md") AND a same-directory case-insensitive filesystem alias
|
|
117
|
+
* ("SKILL.md" vs "skill.md" — literally the same inode on default APFS)
|
|
118
|
+
* both serialize onto the SAME queue entry, closing the data race a naive
|
|
119
|
+
* unserialized check has (measured live, not reasoned: the second write's
|
|
120
|
+
* fast path could complete its own `safeWriteFile` BEFORE the first
|
|
121
|
+
* write's own asynchronous `classifyPreWrite` had finished reading the
|
|
122
|
+
* file).
|
|
123
|
+
*
|
|
124
|
+
* N1 (round 4): the EARLIER "only the first occurrence for a key
|
|
125
|
+
* classifies" optimization was itself broken on a case-SENSITIVE
|
|
126
|
+
* filesystem (Linux/CI): `README.md` and `readme.md` share the SAME
|
|
127
|
+
* lowercased queue key there too, even though they are genuinely TWO
|
|
128
|
+
* DIFFERENT files — the "skip classification" fast path silently
|
|
129
|
+
* overwrote the second one with no snapshot at all, so a later rollback
|
|
130
|
+
* lost it outright. Fixed by removing that optimization entirely — EVERY
|
|
131
|
+
* queued write now classifies and snapshots its OWN target, unconditionally,
|
|
132
|
+
* right before it writes. On a case-sensitive filesystem this correctly
|
|
133
|
+
* snapshots two independent real files (classification always reads
|
|
134
|
+
* `filePath` itself, never the lowercased key). On a case-insensitive
|
|
135
|
+
* alias, the SECOND classification correctly observes the FIRST write's
|
|
136
|
+
* already-applied bytes as "current" and snapshots THAT — `restoreSnapshots`'
|
|
137
|
+
* REVERSE-order undo (its own doc comment) still converges the resulting
|
|
138
|
+
* two-snapshot chain back to the TRUE original either way. N2 (round 4):
|
|
139
|
+
* this also means a queued write whose PREDECESSOR failed (`previous`
|
|
140
|
+
* rejects, swallowed by `.catch(() => {})` below so this write still gets
|
|
141
|
+
* its turn) is unaffected — it classifies fresh, from whatever the real
|
|
142
|
+
* on-disk state is at that moment, and is fully snapshotted/restorable
|
|
143
|
+
* regardless of why the earlier write failed.
|
|
144
|
+
*/
|
|
145
|
+
function writeTracked(filePath, content) {
|
|
146
|
+
const key = path.resolve(filePath).toLowerCase();
|
|
147
|
+
const previous = writeQueues.get(key) ?? Promise.resolve();
|
|
148
|
+
const thisWrite = previous.catch(() => { }).then(() => performTrackedWrite(filePath, content));
|
|
149
|
+
writeQueues.set(key, thisWrite);
|
|
150
|
+
return thisWrite;
|
|
151
|
+
}
|
|
152
|
+
async function performTrackedWrite(filePath, content) {
|
|
153
|
+
const classification = await classifyPreWrite(filePath);
|
|
154
|
+
if (classification.kind === 'regular') {
|
|
155
|
+
overwritten.push(classification.snapshot);
|
|
156
|
+
await safeWriteFile(filePath, content);
|
|
157
|
+
}
|
|
158
|
+
else if (classification.kind === 'absent') {
|
|
159
|
+
// SMI-6529 L14(b): exclusive create. Atomic w.r.t. "did this call
|
|
160
|
+
// create the file" — a race (something appears between this
|
|
161
|
+
// classification and the write) aborts loudly via
|
|
162
|
+
// `ExclusiveCreateRaceError` instead of silently overwriting whatever
|
|
163
|
+
// just landed there.
|
|
164
|
+
//
|
|
165
|
+
// SMI-6529 N9 (round 4): `createdFresh` is now recorded via the
|
|
166
|
+
// `onCreated` callback, which fires the INSTANT the exclusive `open()`
|
|
167
|
+
// succeeds — BEFORE any content byte is written — not after
|
|
168
|
+
// `safeCreateFile()` resolves. Previously, a write that failed AFTER
|
|
169
|
+
// `open()` already created the (now 0-byte or partial) file never got
|
|
170
|
+
// recorded at all, since the `createdFresh.push()` call sat after the
|
|
171
|
+
// awaited call that just threw — leaving an orphan rollback never knew
|
|
172
|
+
// to unlink.
|
|
173
|
+
await safeCreateFile(filePath, content, undefined, (identity) => createdFresh.push({ path: filePath, identity }));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// 'other' (symlink, directory, etc.) — record nothing. `safeWriteFile`
|
|
177
|
+
// itself refuses to touch it before any byte is written, so there is
|
|
178
|
+
// nothing to roll back and it must never be unlinked.
|
|
179
|
+
await safeWriteFile(filePath, content);
|
|
180
|
+
}
|
|
181
|
+
writtenFiles.push(filePath);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* SMI-6529 M7: shared cleanup — restores every overwritten file and
|
|
185
|
+
* removes everything created fresh. Runs from the internal catch block on
|
|
186
|
+
* a write failure, AND is exposed as `rollback()` on the returned result
|
|
187
|
+
* for a caller whose LATER step (after a successful write) fails.
|
|
188
|
+
*/
|
|
189
|
+
async function performRollback() {
|
|
190
|
+
const restoreFailures = await restoreSnapshots(overwritten);
|
|
191
|
+
// Round 13 (cross-model review): every cleanup failure is collected and
|
|
192
|
+
// reported through InstallRestoreError instead of swallowed.
|
|
193
|
+
const cleanupFailures = [];
|
|
194
|
+
for (const entry of createdFresh) {
|
|
195
|
+
if (entry.identity) {
|
|
196
|
+
// R5: skip a path that no longer names the file this call created.
|
|
197
|
+
let current;
|
|
198
|
+
try {
|
|
199
|
+
current = await fs.lstat(entry.path);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
// Round 25 (cross-model review): only absence means "already gone".
|
|
203
|
+
// Any other failure means this call could not tell what is at the
|
|
204
|
+
// path, so it is reported rather than counted as a clean rollback.
|
|
205
|
+
const code = err.code;
|
|
206
|
+
if (code !== 'ENOENT') {
|
|
207
|
+
cleanupFailures.push(`${entry.path} (${code ?? (err instanceof Error ? err.message : String(err))})`);
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (current.dev !== entry.identity.dev || current.ino !== entry.identity.ino)
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
await cleanupStep(entry.path, () => fs.unlink(entry.path), ['ENOENT'], cleanupFailures);
|
|
215
|
+
}
|
|
216
|
+
// F4 (review round 1): remove nested sub-skill directories THIS call created
|
|
217
|
+
// fresh (e.g. "scripts/") — files must be gone first (done above), and a
|
|
218
|
+
// non-recursive rmdir requires children removed before parents, hence the
|
|
219
|
+
// deepest-first ordering (sorted by path-separator count, not string length —
|
|
220
|
+
// a short deep path must still sort before a long shallow one). ENOENT
|
|
221
|
+
// (already removed by a sibling's identical cleanup) and non-empty
|
|
222
|
+
// (content this call didn't create) mean nothing of ours is left.
|
|
223
|
+
const deepestFirst = [...freshDirs].sort((a, b) => b.split(path.sep).length - a.split(path.sep).length);
|
|
224
|
+
for (const dir of deepestFirst) {
|
|
225
|
+
await cleanupStep(dir, () => fs.rmdir(dir), DIR_GONE_OR_NOT_OURS, cleanupFailures);
|
|
226
|
+
}
|
|
227
|
+
// SMI-5982 (Wave 6) / SMI-6529 L15: 'directory-package' mode (Antigravity)
|
|
228
|
+
// creates a skill-named subdirectory OUTSIDE installPath
|
|
229
|
+
// (<agentsDir>/<skillName>/agent.md) that 'flat' mode never needed —
|
|
230
|
+
// every other client's agents dir is a shared, pre-existing directory,
|
|
231
|
+
// never created per-skill. Only rmdir it when THIS call created it
|
|
232
|
+
// (`!agentDirPreExisted`) — a forced reinstall's per-skill directory that
|
|
233
|
+
// pre-existed must never be removed just because this rollback ran; the
|
|
234
|
+
// rmdir is non-recursive regardless (a safe no-op on non-empty content).
|
|
235
|
+
if (subagentPath &&
|
|
236
|
+
!agentDirPreExisted &&
|
|
237
|
+
getCompanionAgentTarget(client).fileMode === 'directory-package') {
|
|
238
|
+
const agentDir = path.dirname(subagentPath);
|
|
239
|
+
await cleanupStep(agentDir, () => fs.rmdir(agentDir), DIR_GONE_OR_NOT_OURS, cleanupFailures);
|
|
240
|
+
}
|
|
241
|
+
// SMI-6529: NEVER remove installPath once it is known to have preExisted — the
|
|
242
|
+
// caller (or a prior install) owned that directory before this call started.
|
|
243
|
+
// Only a directory THIS call created may ever be removed, and only once it has
|
|
244
|
+
// been PROVEN inside skillsDir (pathValidated) — so an untracked orphan from a
|
|
245
|
+
// mid-batch Promise.all write can't survive. If mkdir or the realpath escape
|
|
246
|
+
// guard threw, installPath was never validated; fall back to a non-recursive
|
|
247
|
+
// rmdir, a safe no-op on a non-empty or out-of-bounds directory (NEVER a
|
|
248
|
+
// recursive force-delete of an unvalidated path). Round 13: and the
|
|
249
|
+
// recursive delete runs only while installPath is still the directory
|
|
250
|
+
// this call created; anything put there since is left and reported.
|
|
251
|
+
if (!preExisted) {
|
|
252
|
+
if (pathValidated) {
|
|
253
|
+
await removeCreatedDirectory(installPath, installDirIdentity, cleanupFailures);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
await cleanupStep(installPath, () => fs.rmdir(installPath), DIR_GONE_OR_NOT_OURS, cleanupFailures);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { restoreFailures, cleanupFailures };
|
|
260
|
+
}
|
|
261
|
+
const rollback = async (causeError) => {
|
|
262
|
+
const { restoreFailures, cleanupFailures } = await performRollback();
|
|
263
|
+
if (restoreFailures.length > 0 || cleanupFailures.length > 0) {
|
|
264
|
+
throw new InstallRestoreError(causeError instanceof Error ? causeError.message : String(causeError), restoreFailures, { cause: causeError }, cleanupFailures);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
try {
|
|
268
|
+
if (preExisted) {
|
|
269
|
+
// Already confirmed to exist (by the caller's own pre-write guard AND
|
|
270
|
+
// this function's own lstat above) — nothing to create.
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// SMI-6529 L14(a): create only the FINAL path segment non-recursively.
|
|
274
|
+
// Any missing ANCESTOR (e.g. skillsDir itself, on a first run) is still
|
|
275
|
+
// created recursively — but installPath itself must come into
|
|
276
|
+
// existence via a single, non-racy mkdir: if it appears between the
|
|
277
|
+
// `preExisted` check above and here (a TOCTOU race with a concurrent
|
|
278
|
+
// install or an attacker), EEXIST aborts loudly instead of silently
|
|
279
|
+
// proceeding to write into content that just appeared.
|
|
280
|
+
await fs.mkdir(path.dirname(installPath), { recursive: true });
|
|
281
|
+
try {
|
|
282
|
+
await fs.mkdir(installPath);
|
|
283
|
+
// Round 13: remember which directory this call created, so rollback
|
|
284
|
+
// never recursively deletes something put at this path since.
|
|
285
|
+
const created = await fs.lstat(installPath);
|
|
286
|
+
installDirIdentity = { dev: created.dev, ino: created.ino };
|
|
287
|
+
}
|
|
288
|
+
catch (mkdirErr) {
|
|
289
|
+
if (mkdirErr.code === 'EEXIST') {
|
|
290
|
+
// SMI-6529 N8 (round 4): the directory that "appeared" belongs to
|
|
291
|
+
// whoever won the race, NOT this call — `preExisted` (still false
|
|
292
|
+
// at this point) would otherwise tell `performRollback()` this call
|
|
293
|
+
// owns it and is safe to remove. Measured live: 299/300 raced
|
|
294
|
+
// installs without this flip had rollback `rmdir` the WINNER's
|
|
295
|
+
// freshly-created directory out from under it. Flip it to `true`
|
|
296
|
+
// BEFORE throwing so rollback never touches a directory this call
|
|
297
|
+
// did not create.
|
|
298
|
+
preExisted = true;
|
|
299
|
+
throw new Error('Install target "' + installPath + '" appeared during install (race) — aborting.');
|
|
300
|
+
}
|
|
301
|
+
throw mkdirErr;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// SMI-4692: realpath both sides — macOS /var/folders symlinks to /private/var/folders.
|
|
305
|
+
const realInstallPath = await fs.realpath(installPath);
|
|
306
|
+
const expectedPrefix = await fs.realpath(skillsDir).catch(() => path.resolve(skillsDir));
|
|
307
|
+
if (!realInstallPath.startsWith(expectedPrefix + path.sep) &&
|
|
308
|
+
realInstallPath !== expectedPrefix) {
|
|
309
|
+
throw new Error('Install path escapes skills directory (realpath): ' + installPath);
|
|
310
|
+
}
|
|
311
|
+
pathValidated = true;
|
|
312
|
+
const mainSkillPath = path.join(installPath, 'SKILL.md');
|
|
313
|
+
await writeTracked(mainSkillPath, finalSkillContent);
|
|
314
|
+
// Write sub-skills in parallel. Sol final-code-review findings #2/#4: a nested filename
|
|
315
|
+
// (e.g. "scripts/run.sh", used by private-registry content installs) needs its parent
|
|
316
|
+
// directory created symlink-safely first — writeInstallFiles previously neither created it
|
|
317
|
+
// (ENOENT on any clean install with a nested file) nor checked it for a pre-existing symlink.
|
|
318
|
+
//
|
|
319
|
+
// F3 (review round 1): Promise.all rejects on the FIRST failure while sibling
|
|
320
|
+
// writes are still in flight — the catch block then rolls back while a slow
|
|
321
|
+
// sibling can still land afterward, so its own snapshot/fresh-path is recorded
|
|
322
|
+
// AFTER rollback ran and is never restored or removed. Promise.allSettled lets
|
|
323
|
+
// every write finish (successfully or not) before rollback ever runs, then the
|
|
324
|
+
// FIRST rejection's reason is what the caller sees.
|
|
325
|
+
if (subSkillFiles.length > 0) {
|
|
326
|
+
const results = await Promise.allSettled(subSkillFiles.map(async (subSkill) => {
|
|
327
|
+
const subPath = path.join(installPath, subSkill.filename);
|
|
328
|
+
// SMI-6529 N12 (round 4): containment check — a sub-skill filename
|
|
329
|
+
// like "x/../../../escape.md" normalizes (via path.join, which
|
|
330
|
+
// collapses ".." segments) to a path OUTSIDE installPath entirely.
|
|
331
|
+
// `mkdirNoFollow()` below only guards against a pre-existing
|
|
332
|
+
// SYMLINK at an intermediate segment; it does nothing to stop a
|
|
333
|
+
// purely lexical escape via "..". Checked BEFORE any mkdir/write
|
|
334
|
+
// for this entry, so a violation surfaces as this entry's own
|
|
335
|
+
// Promise.allSettled rejection (triggering the same rollback path
|
|
336
|
+
// as any other write failure) rather than ever touching disk.
|
|
337
|
+
const resolvedSubPath = path.resolve(subPath);
|
|
338
|
+
if (resolvedSubPath !== resolvedInstall &&
|
|
339
|
+
!resolvedSubPath.startsWith(resolvedInstall + path.sep)) {
|
|
340
|
+
throw new Error('Sub-skill filename escapes install directory: ' + subSkill.filename);
|
|
341
|
+
}
|
|
342
|
+
const subDir = path.dirname(subPath);
|
|
343
|
+
if (subDir !== installPath) {
|
|
344
|
+
await mkdirNoFollow(installPath, subDir, freshDirs);
|
|
345
|
+
}
|
|
346
|
+
await writeTracked(subPath, subSkill.content);
|
|
347
|
+
}));
|
|
348
|
+
const firstRejection = results.find((r) => r.status === 'rejected');
|
|
349
|
+
if (firstRejection) {
|
|
350
|
+
throw firstRejection.reason;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Write companion subagent if generated
|
|
354
|
+
if (subagentContent) {
|
|
355
|
+
subagentPath = resolveCompanionAgentPath(skillName, client, companionBaseDir);
|
|
356
|
+
const agentsDir = path.dirname(subagentPath);
|
|
357
|
+
if (getCompanionAgentTarget(client).fileMode === 'directory-package') {
|
|
358
|
+
// Round 27 (cross-model review): only absence means "this call created
|
|
359
|
+
// it". Any other lstat failure used to record `false`, and rollback
|
|
360
|
+
// rmdirs this directory precisely when that is false — so one
|
|
361
|
+
// unreadable moment could cost the user a directory that was already
|
|
362
|
+
// there. Fail closed instead: nothing has been written yet, so
|
|
363
|
+
// throwing here leaves nothing behind.
|
|
364
|
+
try {
|
|
365
|
+
await fs.lstat(agentsDir);
|
|
366
|
+
agentDirPreExisted = true;
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
if (err?.code !== 'ENOENT')
|
|
370
|
+
throw err;
|
|
371
|
+
agentDirPreExisted = false;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
await fs.mkdir(agentsDir, { recursive: true });
|
|
375
|
+
// SMI-6529 M10: a FRESH install must never silently overwrite an
|
|
376
|
+
// existing companion agent file — it could belong to an unrelated
|
|
377
|
+
// skill/agent the user created by hand. A forced reinstall of an
|
|
378
|
+
// already-tracked skill (`preExisted`) still overwrites it, tracked
|
|
379
|
+
// and restorable like everything else.
|
|
380
|
+
if (!preExisted) {
|
|
381
|
+
const companionClassification = await classifyPreWrite(subagentPath);
|
|
382
|
+
// SMI-6529 N11 (round 4): treat ANY existing non-absent entry the
|
|
383
|
+
// same way — not just a 'regular' file. The old check only skipped a
|
|
384
|
+
// 'regular' file, so a SYMLINKED companion path (a stale/planted
|
|
385
|
+
// link) fell to the `else` branch and went through `writeTracked()`,
|
|
386
|
+
// whose `safeWriteFile()` throws `SymlinkError` on it — rolling back
|
|
387
|
+
// the ENTIRE install (SKILL.md, every sub-skill) over an unrelated
|
|
388
|
+
// pre-existing symlink at a completely different path. A fresh
|
|
389
|
+
// install must skip ('other' or 'regular') exactly the same way.
|
|
390
|
+
if (companionClassification.kind !== 'absent') {
|
|
391
|
+
companionSkipped = true;
|
|
392
|
+
subagentPath = undefined;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
await writeTracked(subagentPath, subagentContent);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
await writeTracked(subagentPath, subagentContent);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
catch (writeError) {
|
|
404
|
+
// SMI-6529 rollback: restore every OVERWRITTEN file to its pre-install bytes/mode
|
|
405
|
+
// and unlink only files this call created fresh (subagentPath lives OUTSIDE
|
|
406
|
+
// installPath, under the client's companion-agent dir — see
|
|
407
|
+
// resolveCompanionAgentPath()/COMPANION_AGENT_TARGETS, install/paths.ts — but is
|
|
408
|
+
// tracked via the same overwritten/createdFresh split as everything else).
|
|
409
|
+
const { restoreFailures, cleanupFailures } = await performRollback();
|
|
410
|
+
if (restoreFailures.length > 0 || cleanupFailures.length > 0) {
|
|
411
|
+
throw new InstallRestoreError(writeError instanceof Error ? writeError.message : String(writeError), restoreFailures, { cause: writeError }, cleanupFailures);
|
|
412
|
+
}
|
|
413
|
+
throw writeError;
|
|
414
|
+
}
|
|
415
|
+
return { writtenFiles, subagentPath, companionSkipped, rollback };
|
|
416
|
+
}
|
|
417
|
+
//# sourceMappingURL=skill-installation.io.write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-installation.io.write.js","sourceRoot":"","sources":["../../../src/services/skill-installation.io.write.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-installation.service.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAA;AAC7F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAA;AAC/F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"skill-installation.service.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAA;AAC7F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAA;AAC/F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAA;AAWtC,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAgBrE,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,QAAQ,CAAA;IACZ,SAAS,EAAE,eAAe,CAAA;IAC1B,mBAAmB,EAAE,yBAAyB,CAAA;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAA;IAC/D,eAAe,CAAC,EAAE,0BAA0B,CAAA;IAC5C,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAA;IAEjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AACD,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAU;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA2B;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAmB;IACtD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAA8C;IAChF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAA4B;IAC7D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAmB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoB;gBACzC,MAAM,EAAE,8BAA8B;IAgB5C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAqVpF;;;;OAIG;IACG,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,aAAa,CAAC;IAY9E,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;CAW7F"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Post-write success path for SkillInstallationService.install().
|
|
3
|
+
* @module @skillsmith/core/services/skill-installation.service.finalize
|
|
4
|
+
* @see SMI-6529 Wave A0: pure move out of skill-installation.service.ts to make
|
|
5
|
+
* headroom for the pre-write target guard (checkInstallTarget) — no behavior
|
|
6
|
+
* change. Mirrors this service's existing domain-driven split convention
|
|
7
|
+
* (skill-installation.io.ts, skill-installation.content.ts, etc).
|
|
8
|
+
*
|
|
9
|
+
* Everything `install()` does AFTER `writeInstallFiles()` succeeds: update the
|
|
10
|
+
* manifest, record co-install/dependency-intelligence/AI-defence signals
|
|
11
|
+
* (all best-effort), and assemble the final `success: true` InstallResult.
|
|
12
|
+
*/
|
|
13
|
+
import type { ScanReport } from '../security/index.js';
|
|
14
|
+
import type { TrustTier } from '../types/skill.js';
|
|
15
|
+
import type { SkillDependencyRepository } from '../repositories/SkillDependencyRepository.js';
|
|
16
|
+
import type { RiskScoreHistoryRepository } from '../repositories/RiskScoreHistoryRepository.js';
|
|
17
|
+
import type { ClientId } from '../install/paths.js';
|
|
18
|
+
import type { ManifestManager } from './skill-manifest.js';
|
|
19
|
+
import type { AiDefenceFeedback, CoInstallRecorder, InstallResult, OptimizationInfo, ProgressCallback, QuarantineStatus } from './skill-installation.types.js';
|
|
20
|
+
/** Everything {@link finalizeSuccessfulInstall} needs from the service and the install in progress. */
|
|
21
|
+
export interface FinalizeInstallParams {
|
|
22
|
+
manifest: ManifestManager;
|
|
23
|
+
coInstallRecorder: CoInstallRecorder | undefined;
|
|
24
|
+
/** Mutated in place (pushed to) — same array the service instance owns. */
|
|
25
|
+
sessionInstalledSkillIds: string[];
|
|
26
|
+
skillDependencyRepo: SkillDependencyRepository;
|
|
27
|
+
quarantineLookup: ((skillId: string) => QuarantineStatus | null) | undefined;
|
|
28
|
+
riskHistoryRepo: RiskScoreHistoryRepository | undefined;
|
|
29
|
+
aiDefenceFeedback: AiDefenceFeedback | undefined;
|
|
30
|
+
onProgress: ProgressCallback;
|
|
31
|
+
client: ClientId;
|
|
32
|
+
skillsDir: string;
|
|
33
|
+
skillId: string;
|
|
34
|
+
owner: string;
|
|
35
|
+
repo: string;
|
|
36
|
+
skillName: string;
|
|
37
|
+
installPath: string;
|
|
38
|
+
manifestKey: string;
|
|
39
|
+
contentHash: string;
|
|
40
|
+
skillMdContent: string;
|
|
41
|
+
optimizationInfo: OptimizationInfo;
|
|
42
|
+
securityReport: ScanReport | undefined;
|
|
43
|
+
configWarnings: string[];
|
|
44
|
+
skipScanRequested: boolean | undefined;
|
|
45
|
+
contentHashMismatch: boolean;
|
|
46
|
+
trustTier: TrustTier;
|
|
47
|
+
/**
|
|
48
|
+
* SMI-6529 M10: extra tips to append verbatim after the standard set below
|
|
49
|
+
* (e.g. a warning that a companion agent file was NOT overwritten because
|
|
50
|
+
* it already existed on a fresh install). Optional — omitted callers see
|
|
51
|
+
* no change in behavior.
|
|
52
|
+
*/
|
|
53
|
+
extraTips?: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Everything after a successful `writeInstallFiles()`: manifest update,
|
|
57
|
+
* best-effort dependency/quarantine/trend/AI-defence bookkeeping, and the
|
|
58
|
+
* final `InstallResult`. Never throws for a best-effort step — only the
|
|
59
|
+
* manifest update itself (via `updateSafely`) can propagate.
|
|
60
|
+
*/
|
|
61
|
+
export declare function finalizeSuccessfulInstall(params: FinalizeInstallParams): Promise<InstallResult>;
|
|
62
|
+
//# sourceMappingURL=skill-installation.service.finalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-installation.service.finalize.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.service.finalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAA;AAC7F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAA;AAC/F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,+BAA+B,CAAA;AAYtC,uGAAuG;AACvG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,eAAe,CAAA;IACzB,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAA;IAChD,2EAA2E;IAC3E,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClC,mBAAmB,EAAE,yBAAyB,CAAA;IAC9C,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC,GAAG,SAAS,CAAA;IAC5E,eAAe,EAAE,0BAA0B,GAAG,SAAS,CAAA;IACvD,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAA;IAChD,UAAU,EAAE,gBAAgB,CAAA;IAC5B,MAAM,EAAE,QAAQ,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc,EAAE,UAAU,GAAG,SAAS,CAAA;IACtC,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,iBAAiB,EAAE,OAAO,GAAG,SAAS,CAAA;IACtC,mBAAmB,EAAE,OAAO,CAAA;IAC5B,SAAS,EAAE,SAAS,CAAA;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,aAAa,CAAC,CA8IxB"}
|