@skillsmith/core 0.12.2 → 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 +173 -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 +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +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/scripts/__tests__/scan-imported-skills.test.js +9 -1
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
- package/dist/src/scripts/scan-imported-skills.d.ts +7 -1
- package/dist/src/scripts/scan-imported-skills.d.ts.map +1 -1
- package/dist/src/scripts/scan-imported-skills.js +15 -2
- package/dist/src/scripts/scan-imported-skills.js.map +1 -1
- package/dist/src/scripts/skill-scanner/allowlist.d.ts +10 -0
- package/dist/src/scripts/skill-scanner/allowlist.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/allowlist.js +10 -0
- package/dist/src/scripts/skill-scanner/allowlist.js.map +1 -1
- package/dist/src/scripts/skill-scanner/index.d.ts +8 -0
- package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/index.js +13 -5
- package/dist/src/scripts/skill-scanner/index.js.map +1 -1
- package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/trust-scorer.js +6 -0
- package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.action-context.d.ts +15 -0
- package/dist/src/security/scanner/SecurityScanner.action-context.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.action-context.js +209 -0
- package/dist/src/security/scanner/SecurityScanner.action-context.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts +25 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.d.ts +40 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.js +88 -51
- package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.js +39 -6
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.pii.d.ts +30 -0
- package/dist/src/security/scanner/SecurityScanner.pii.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.pii.js +8 -1
- package/dist/src/security/scanner/SecurityScanner.pii.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.prose-lexicon.d.ts +60 -0
- package/dist/src/security/scanner/SecurityScanner.prose-lexicon.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.prose-lexicon.js +228 -0
- package/dist/src/security/scanner/SecurityScanner.prose-lexicon.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js +42 -5
- package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts +69 -0
- package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.value-gate.js +271 -0
- package/dist/src/security/scanner/SecurityScanner.value-gate.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts +55 -0
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.js +308 -0
- package/dist/src/security/scanner/SecurityScanner.weak-passwords.js.map +1 -0
- package/dist/src/security/scanner/patterns.d.ts +61 -6
- package/dist/src/security/scanner/patterns.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.js +70 -61
- package/dist/src/security/scanner/patterns.js.map +1 -1
- package/dist/src/security/scanner/patterns.sensitive-path.d.ts +73 -0
- package/dist/src/security/scanner/patterns.sensitive-path.d.ts.map +1 -0
- package/dist/src/security/scanner/patterns.sensitive-path.js +192 -0
- package/dist/src/security/scanner/patterns.sensitive-path.js.map +1 -0
- package/dist/src/security/scanner/regex-utils.d.ts +31 -17
- package/dist/src/security/scanner/regex-utils.d.ts.map +1 -1
- package/dist/src/security/scanner/regex-utils.js +31 -17
- package/dist/src/security/scanner/regex-utils.js.map +1 -1
- package/dist/src/security/scanner/types.d.ts +9 -0
- package/dist/src/security/scanner/types.d.ts.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/index.d.ts +1 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -0
- package/dist/src/utils/index.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/src/utils/skill-name.d.ts +19 -0
- package/dist/src/utils/skill-name.d.ts.map +1 -0
- package/dist/src/utils/skill-name.js +26 -0
- package/dist/src/utils/skill-name.js.map +1 -0
- package/dist/src/utils/skill-name.test.d.ts +2 -0
- package/dist/src/utils/skill-name.test.d.ts.map +1 -0
- package/dist/src/utils/skill-name.test.js +34 -0
- package/dist/src/utils/skill-name.test.js.map +1 -0
- 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/ContinuousSecurity.performance.test.js +12 -7
- package/dist/tests/security/ContinuousSecurity.performance.test.js.map +1 -1
- package/dist/tests/security/ContinuousSecurity.test.js +14 -2
- package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
- package/dist/tests/security/ai-defence-multiline-promotion.test.d.ts +10 -12
- package/dist/tests/security/ai-defence-multiline-promotion.test.d.ts.map +1 -1
- package/dist/tests/security/ai-defence-multiline-promotion.test.js +26 -33
- package/dist/tests/security/ai-defence-multiline-promotion.test.js.map +1 -1
- package/dist/tests/security/nested-instruction-long-attribute.test.js +20 -10
- package/dist/tests/security/nested-instruction-long-attribute.test.js.map +1 -1
- package/dist/tests/security/scanner-evidence-tiers.test.js +15 -0
- package/dist/tests/security/scanner-evidence-tiers.test.js.map +1 -1
- package/dist/tests/security/scanner-multiline-cap.test.d.ts +21 -0
- package/dist/tests/security/scanner-multiline-cap.test.d.ts.map +1 -0
- package/dist/tests/security/scanner-multiline-cap.test.js +152 -0
- package/dist/tests/security/scanner-multiline-cap.test.js.map +1 -0
- package/dist/tests/security/scanner-regression-guard.test.js +66 -1
- package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
- package/dist/tests/security/scanner-witness-sw1.test.d.ts +32 -0
- package/dist/tests/security/scanner-witness-sw1.test.d.ts.map +1 -0
- package/dist/tests/security/scanner-witness-sw1.test.js +255 -0
- package/dist/tests/security/scanner-witness-sw1.test.js.map +1 -0
- package/dist/tests/security/sensitive-path-adversarial-review.test.d.ts +2 -0
- package/dist/tests/security/sensitive-path-adversarial-review.test.d.ts.map +1 -0
- package/dist/tests/security/sensitive-path-adversarial-review.test.js +313 -0
- package/dist/tests/security/sensitive-path-adversarial-review.test.js.map +1 -0
- 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 +314 -0
- 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/smi5879-corroboration.core.test.js +44 -0
- package/dist/tests/security/smi5879-corroboration.core.test.js.map +1 -1
- package/dist/tests/security/weak-password-lexicon.test.d.ts +18 -0
- package/dist/tests/security/weak-password-lexicon.test.d.ts.map +1 -0
- package/dist/tests/security/weak-password-lexicon.test.js +132 -0
- package/dist/tests/security/weak-password-lexicon.test.js.map +1 -0
- package/dist/tests/skill-scanner/allowlist.test.js +58 -4
- package/dist/tests/skill-scanner/allowlist.test.js.map +1 -1
- package/dist/tests/skill-scanner/categorizer.test.d.ts +2 -0
- package/dist/tests/skill-scanner/categorizer.test.d.ts.map +1 -0
- package/dist/tests/skill-scanner/categorizer.test.js +71 -0
- package/dist/tests/skill-scanner/categorizer.test.js.map +1 -0
- package/dist/tests/skill-scanner/cli-guard.test.d.ts +23 -0
- package/dist/tests/skill-scanner/cli-guard.test.d.ts.map +1 -0
- package/dist/tests/skill-scanner/cli-guard.test.js +71 -0
- package/dist/tests/skill-scanner/cli-guard.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.content.test.js +59 -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.sensitive-path-fp.test.d.ts +29 -0
- package/dist/tests/unit/services/skill-installation.service.sensitive-path-fp.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.sensitive-path-fp.test.js +200 -0
- package/dist/tests/unit/services/skill-installation.service.sensitive-path-fp.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 +6 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helpers for `performUninstall`: what it found before removing,
|
|
3
|
+
* progress reporting that cannot change the outcome, record comparison, and
|
|
4
|
+
* the parked-leftover warnings.
|
|
5
|
+
* @module @skillsmith/core/services/skill-installation.uninstall.helpers
|
|
6
|
+
*
|
|
7
|
+
* Split out of `skill-installation.uninstall.ts` in SMI-6529 round 25, when
|
|
8
|
+
* that file reached 504 lines against the 500-line standard — the same
|
|
9
|
+
* sibling-split convention as `skill-installation.io.ts`. These are the pieces
|
|
10
|
+
* `performUninstall` calls but does not itself define; nothing here is part of
|
|
11
|
+
* `@skillsmith/core`'s public export surface.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs/promises';
|
|
14
|
+
import { checkGitAtRoot } from '../install/fan-out.overwrite.js';
|
|
15
|
+
import { listParkedLeftovers, parkedLeftoverWarning } from '../install/remove-if-same.js';
|
|
16
|
+
/**
|
|
17
|
+
* SMI-6529 round 15 (cross-model review, Critical): what uninstall found at
|
|
18
|
+
* `installPath` before removing it. A folder with `.git` at its root is a git
|
|
19
|
+
* working tree, which git owns (ADR-155), so it is refused with or without
|
|
20
|
+
* `force`: deleting it would take unpushed commits and uncommitted edits with
|
|
21
|
+
* it. A symlink or a file needs no such check, since removing it leaves what
|
|
22
|
+
* it points at alone. Returns the entry's identity (null when nothing is
|
|
23
|
+
* there), so the delete can confirm it is still the same entry.
|
|
24
|
+
*/
|
|
25
|
+
export async function inspectForRemoval(installPath) {
|
|
26
|
+
let stat;
|
|
27
|
+
try {
|
|
28
|
+
stat = await fs.lstat(installPath);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const code = error.code;
|
|
32
|
+
if (code === 'ENOENT')
|
|
33
|
+
return { stat: null };
|
|
34
|
+
return {
|
|
35
|
+
refusal: 'Could not check ' +
|
|
36
|
+
installPath +
|
|
37
|
+
' (' +
|
|
38
|
+
(code ?? String(error)) +
|
|
39
|
+
'); nothing was removed.',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
43
|
+
const git = await checkGitAtRoot(installPath);
|
|
44
|
+
if (git.kind === 'present') {
|
|
45
|
+
return {
|
|
46
|
+
refusal: installPath +
|
|
47
|
+
' is a git working tree (it has .git at its root), so Skillsmith will not delete it, ' +
|
|
48
|
+
'even with force. Check `git -C ' +
|
|
49
|
+
installPath +
|
|
50
|
+
' status`, then remove the folder yourself.',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (git.kind === 'unknown') {
|
|
54
|
+
return {
|
|
55
|
+
refusal: 'Could not check ' +
|
|
56
|
+
installPath +
|
|
57
|
+
' for a .git directory (' +
|
|
58
|
+
git.reason +
|
|
59
|
+
'); nothing was removed.',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { stat };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Report progress without letting a caller's listener change the outcome.
|
|
67
|
+
* Round 18 (cross-model review): a listener that threw after the folder was
|
|
68
|
+
* already removed reached the generic catch, which reported neither what had
|
|
69
|
+
* been removed nor what was left parked.
|
|
70
|
+
*
|
|
71
|
+
* Round 28 (pre-merge gate, PR-07): the failure is still swallowed as far as
|
|
72
|
+
* the uninstall's outcome goes — that part was deliberate and stays — but it
|
|
73
|
+
* is no longer swallowed as far as the USER goes. It is pushed onto
|
|
74
|
+
* `problems`, which the caller surfaces alongside its other warnings. An empty
|
|
75
|
+
* catch here was the same "could not tell" silence this wave removed
|
|
76
|
+
* everywhere else, in the one place that reports to the user for a living.
|
|
77
|
+
*/
|
|
78
|
+
export function notify(onProgress, problems, ...args) {
|
|
79
|
+
try {
|
|
80
|
+
onProgress(...args);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const stage = String(args[0] ?? 'unknown');
|
|
84
|
+
problems.push(`the progress listener threw while reporting the "${stage}" step ` +
|
|
85
|
+
`(${err instanceof Error ? err.message : String(err)}); the uninstall itself was not ` +
|
|
86
|
+
`affected.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Whether `entry` is still, field for field, the record this uninstall
|
|
91
|
+
* loaded. Round 18 (cross-model review): timestamps alone are not a unique
|
|
92
|
+
* generation token — two installs can share a millisecond, an older writer
|
|
93
|
+
* can omit them, and a copied record keeps them — so every field has to
|
|
94
|
+
* match. An install that claims the same name writes its own values, so any
|
|
95
|
+
* difference means a different generation. A durable generation id belongs
|
|
96
|
+
* with A1's manifest work (SMI-6531).
|
|
97
|
+
*/
|
|
98
|
+
export function sameRecord(entry, loaded) {
|
|
99
|
+
return stableJson(entry) === stableJson(loaded);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* JSON with every object's keys in a fixed order, so two records compare by
|
|
103
|
+
* value. Round 19 (Opus): comparing field by field with `!==` was correct only
|
|
104
|
+
* while every field is a string — one array or object field, written by a
|
|
105
|
+
* newer version or another tool, would never compare equal, and the record
|
|
106
|
+
* would be kept forever with a warning that says an install claimed the name.
|
|
107
|
+
*/
|
|
108
|
+
function stableJson(value) {
|
|
109
|
+
return JSON.stringify(value, (_key, nested) => nested !== null && typeof nested === 'object' && !Array.isArray(nested)
|
|
110
|
+
? Object.fromEntries(Object.entries(nested).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0))
|
|
111
|
+
: nested);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Warnings naming anything an earlier removal left parked next to
|
|
115
|
+
* `installPath`. Round 17 (cross-model review): every exit after the removal
|
|
116
|
+
* reports these, not only the successful one.
|
|
117
|
+
*/
|
|
118
|
+
export async function parkedWarnings(installPath) {
|
|
119
|
+
const scan = await listParkedLeftovers(installPath);
|
|
120
|
+
const warnings = scan.parked.map(parkedLeftoverWarning);
|
|
121
|
+
// Round 25 (cross-model review): say when the scan could not look at all.
|
|
122
|
+
return scan.unreadable ? [...warnings, scan.unreadable] : warnings;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=skill-installation.uninstall.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-installation.uninstall.helpers.js","sourceRoot":"","sources":["../../../src/services/skill-installation.uninstall.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAGzF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB;IAEnB,IAAI,IAAW,CAAA;IACf,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAA;QAClD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;QAC5C,OAAO;YACL,OAAO,EACL,kBAAkB;gBAClB,WAAW;gBACX,IAAI;gBACJ,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvB,yBAAyB;SAC5B,CAAA;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAA;QAC7C,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EACL,WAAW;oBACX,sFAAsF;oBACtF,iCAAiC;oBACjC,WAAW;oBACX,4CAA4C;aAC/C,CAAA;QACH,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EACL,kBAAkB;oBAClB,WAAW;oBACX,yBAAyB;oBACzB,GAAG,CAAC,MAAM;oBACV,yBAAyB;aAC5B,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,MAAM,CACpB,UAA4B,EAC5B,QAAkB,EAClB,GAAG,IAAkC;IAErC,IAAI,CAAC;QACH,UAAU,CAAC,GAAG,IAAI,CAAC,CAAA;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAA;QAC1C,QAAQ,CAAC,IAAI,CACX,oDAAoD,KAAK,SAAS;YAChE,IAAI,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,kCAAkC;YACtF,WAAW,CACd,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAyB,EAAE,MAA0B;IAC9E,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,CAAA;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAe,EAAE,EAAE,CACrD,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACrE,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAClE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3B,CACF;QACH,CAAC,CAAC,MAAM,CACX,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAA;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IACvD,0EAA0E;IAC1E,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;AACpE,CAAC"}
|
|
@@ -5,15 +5,19 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Split out of `skill-installation.helpers.ts` to stay under the 500-line
|
|
7
7
|
* standard once ADR-139's adoption logic was added — mirrors the existing
|
|
8
|
-
* `skill-installation.io.ts` sibling-split convention.
|
|
8
|
+
* `skill-installation.io.ts` sibling-split convention. Round 25 split its own
|
|
9
|
+
* helpers out again, into `skill-installation.uninstall.helpers.ts`, for the
|
|
10
|
+
* same reason. `performUninstall`
|
|
9
11
|
* has exactly one internal consumer (`skill-installation.service.ts`) and
|
|
10
12
|
* is not part of `@skillsmith/core`'s public export surface.
|
|
11
13
|
*/
|
|
12
14
|
import * as fs from 'fs/promises';
|
|
13
15
|
import * as path from 'path';
|
|
16
|
+
import { removeIfSame } from '../install/remove-if-same.js';
|
|
14
17
|
import { checkForModifications } from './skill-installation.io.js';
|
|
15
18
|
import { hashContent, manifestKeyFor } from './skill-installation.helpers.js';
|
|
16
19
|
import { CANONICAL_CLIENT } from '../install/paths.js';
|
|
20
|
+
import { inspectForRemoval, notify, parkedWarnings, sameRecord, } from './skill-installation.uninstall.helpers.js';
|
|
17
21
|
/**
|
|
18
22
|
* ADR-139 (SMI-6274 Wave 4): build a manifest entry for a skill found on
|
|
19
23
|
* disk with no manifest record — "adoption." Every field is reconstructed
|
|
@@ -143,8 +147,19 @@ export async function adoptUntrackedSkillEntry(skillName, skillDirName, installP
|
|
|
143
147
|
export async function performUninstall(params) {
|
|
144
148
|
const { skillName, force, skillsDir, manifest, skillDependencyRepo, onProgress, client = CANONICAL_CLIENT, } = params;
|
|
145
149
|
const manifestKey = manifestKeyFor(skillName, client);
|
|
150
|
+
// Round 28 (pre-merge gate, PR-07): a progress listener that throws must not
|
|
151
|
+
// change the outcome, but it must not vanish either. Every notify below
|
|
152
|
+
// records into this one array, and every exit that reports warnings carries
|
|
153
|
+
// it.
|
|
154
|
+
const listenerProblems = [];
|
|
155
|
+
// Round 29 (pre-merge gate, confirmation pass): `notify` fires before every
|
|
156
|
+
// exit below, so EVERY exit has to carry what the listener did — not just
|
|
157
|
+
// the ones that already had a warning to give. The previous round covered
|
|
158
|
+
// the reporting exits only, which left a listener failure vanishing on the
|
|
159
|
+
// refusal, not-installed, adoption-failure and outer-error paths.
|
|
160
|
+
const listenerWarning = () => listenerProblems.length > 0 ? { warning: listenerProblems.join(' ') } : {};
|
|
146
161
|
try {
|
|
147
|
-
onProgress
|
|
162
|
+
notify(onProgress, listenerProblems, 'manifest', 'Loading manifest');
|
|
148
163
|
const manifestData = await manifest.load();
|
|
149
164
|
let skillEntry = manifestData.installedSkills[manifestKey];
|
|
150
165
|
let adopted = false;
|
|
@@ -153,8 +168,37 @@ export async function performUninstall(params) {
|
|
|
153
168
|
try {
|
|
154
169
|
await fs.access(potentialPath);
|
|
155
170
|
}
|
|
156
|
-
catch {
|
|
157
|
-
|
|
171
|
+
catch (err) {
|
|
172
|
+
// Round 25 (cross-model review): only absence means "not installed".
|
|
173
|
+
// EACCES or EIO means we could not tell, and saying "not installed"
|
|
174
|
+
// sends the user away from a skill that is still on disk. Round 26
|
|
175
|
+
// (cross-model review): an error carrying no `code` at all is also
|
|
176
|
+
// "could not tell", and the previous guard let it fall through to "not
|
|
177
|
+
// installed" — the same false absence, one step further out. Only
|
|
178
|
+
// ENOENT is absence now, and the thrown value is read null-safely.
|
|
179
|
+
const code = err?.code;
|
|
180
|
+
if (code !== 'ENOENT') {
|
|
181
|
+
const detail = code ?? (err instanceof Error ? err.message : String(err));
|
|
182
|
+
return {
|
|
183
|
+
success: false,
|
|
184
|
+
skillName,
|
|
185
|
+
message: `Could not tell whether "${skillName}" is installed: ${potentialPath} could not be ` +
|
|
186
|
+
`checked (${detail}). Nothing was removed.`,
|
|
187
|
+
...listenerWarning(),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
skillName,
|
|
193
|
+
message: 'Skill "' + skillName + '" is not installed.',
|
|
194
|
+
...listenerWarning(),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// SMI-6529 round 15: refuse a git working tree before adopting it, so a
|
|
198
|
+
// refusal writes nothing to the manifest.
|
|
199
|
+
const early = await inspectForRemoval(potentialPath);
|
|
200
|
+
if ('refusal' in early) {
|
|
201
|
+
return { success: false, skillName, message: early.refusal, ...listenerWarning() };
|
|
158
202
|
}
|
|
159
203
|
// ADR-139 (SMI-6274 Wave 4): a skill present on disk with no manifest
|
|
160
204
|
// entry is ADOPTED — reconciled by writing a manifest entry derived
|
|
@@ -170,20 +214,29 @@ export async function performUninstall(params) {
|
|
|
170
214
|
// real `install()` landing in that window could be silently
|
|
171
215
|
// clobbered. `adopted` now reflects whether OUR guess actually won
|
|
172
216
|
// (false when a concurrent writer's real entry was found instead).
|
|
173
|
-
onProgress
|
|
217
|
+
notify(onProgress, listenerProblems, 'adopt', 'Adopting untracked skill (no manifest entry found)');
|
|
174
218
|
const adoptResult = await adoptUntrackedSkillEntry(skillName, skillName, potentialPath, manifestKey, manifest);
|
|
175
219
|
if ('adoptionError' in adoptResult) {
|
|
176
220
|
// Only if adoption itself fails does the command error — naming the
|
|
177
221
|
// skill, the path, and the manifest it tried to write (ADR-139
|
|
178
222
|
// point 1's stated failure contract).
|
|
179
|
-
return {
|
|
223
|
+
return {
|
|
224
|
+
success: false,
|
|
225
|
+
skillName,
|
|
226
|
+
message: adoptResult.adoptionError,
|
|
227
|
+
...listenerWarning(),
|
|
228
|
+
};
|
|
180
229
|
}
|
|
181
230
|
skillEntry = adoptResult.entry;
|
|
182
231
|
adopted = adoptResult.adopted;
|
|
183
232
|
}
|
|
184
233
|
const installPath = skillEntry.installPath;
|
|
234
|
+
const seen = await inspectForRemoval(installPath);
|
|
235
|
+
if ('refusal' in seen) {
|
|
236
|
+
return { success: false, skillName, message: seen.refusal, ...listenerWarning() };
|
|
237
|
+
}
|
|
185
238
|
if (!force) {
|
|
186
|
-
onProgress
|
|
239
|
+
notify(onProgress, listenerProblems, 'check', 'Checking for modifications');
|
|
187
240
|
const modified = await checkForModifications(installPath, skillEntry.installedAt);
|
|
188
241
|
if (modified) {
|
|
189
242
|
return {
|
|
@@ -192,17 +245,33 @@ export async function performUninstall(params) {
|
|
|
192
245
|
message: 'Skill "' +
|
|
193
246
|
skillName +
|
|
194
247
|
'" has been modified since installation. Use force=true to remove anyway.',
|
|
195
|
-
warning: 'Local modifications will be lost if you force uninstall.',
|
|
248
|
+
warning: ['Local modifications will be lost if you force uninstall.', ...listenerProblems]
|
|
249
|
+
.join(' ')
|
|
250
|
+
.trim(),
|
|
196
251
|
};
|
|
197
252
|
}
|
|
198
253
|
}
|
|
199
|
-
onProgress
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
254
|
+
notify(onProgress, listenerProblems, 'remove', 'Removing skill directory');
|
|
255
|
+
// SMI-6529 round 15 (cross-model review, Critical): remove only the entry
|
|
256
|
+
// checked above. Anything another program put there since is left in
|
|
257
|
+
// place, and so is the manifest entry, so the user can retry.
|
|
258
|
+
if (seen.stat !== null) {
|
|
259
|
+
const removal = await removeIfSame(installPath, seen.stat);
|
|
260
|
+
if (!removal.removed) {
|
|
261
|
+
const parked = [...(await parkedWarnings(installPath)), ...listenerProblems];
|
|
262
|
+
return {
|
|
263
|
+
success: false,
|
|
264
|
+
skillName,
|
|
265
|
+
message: 'Skill "' +
|
|
266
|
+
skillName +
|
|
267
|
+
'" was not removed: ' +
|
|
268
|
+
installPath +
|
|
269
|
+
' ' +
|
|
270
|
+
removal.reason +
|
|
271
|
+
'.',
|
|
272
|
+
...(parked.length > 0 && { warning: parked.join(' ') }),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
206
275
|
}
|
|
207
276
|
try {
|
|
208
277
|
skillDependencyRepo.clearAll(skillEntry.id);
|
|
@@ -210,7 +279,7 @@ export async function performUninstall(params) {
|
|
|
210
279
|
catch {
|
|
211
280
|
// Table may not exist pre-migration
|
|
212
281
|
}
|
|
213
|
-
onProgress
|
|
282
|
+
notify(onProgress, listenerProblems, 'manifest', 'Updating manifest');
|
|
214
283
|
// SMI-6007: route the final mutation through updateSafely() (lock +
|
|
215
284
|
// fresh re-read + save) instead of saving the `manifestData` snapshot
|
|
216
285
|
// loaded above. That snapshot can be stale by the time we get here —
|
|
@@ -225,20 +294,73 @@ export async function performUninstall(params) {
|
|
|
225
294
|
// skill while its uninstall is mid-flight) can still leave disk and
|
|
226
295
|
// manifest inconsistent — only the unrelated-entry data loss is fixed
|
|
227
296
|
// here, not full transactional safety across the whole method.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
297
|
+
//
|
|
298
|
+
// Round 16 (cross-model review): the record is dropped only while it still
|
|
299
|
+
// describes the skill just removed. A concurrent install of the same name
|
|
300
|
+
// rewrites this key, and an unconditional delete would lose that install's
|
|
301
|
+
// record. And a manifest write that fails after the folder is gone is
|
|
302
|
+
// reported for what it is, rather than surfacing as a bare lock error.
|
|
303
|
+
let claimedByAnotherInstall = false;
|
|
304
|
+
try {
|
|
305
|
+
await manifest.updateSafely((current) => {
|
|
306
|
+
const entry = current.installedSkills[manifestKey];
|
|
307
|
+
// Round 17 (cross-model review): a reinstall can land at the SAME
|
|
308
|
+
// path, so the path alone does not identify the generation just
|
|
309
|
+
// removed — and comparing paths alone also keeps a stale record
|
|
310
|
+
// forever whenever the spelling differs (a case-insensitive volume, a
|
|
311
|
+
// symlinked parent). Round 18: the whole record identifies it.
|
|
312
|
+
const describesWhatWasRemoved = entry === undefined || sameRecord(entry, skillEntry);
|
|
313
|
+
if (!describesWhatWasRemoved) {
|
|
314
|
+
claimedByAnotherInstall = true;
|
|
315
|
+
return current;
|
|
316
|
+
}
|
|
317
|
+
const next = { ...current, installedSkills: { ...current.installedSkills } };
|
|
318
|
+
delete next.installedSkills[manifestKey];
|
|
319
|
+
return next;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
const parked = [...(await parkedWarnings(installPath)), ...listenerProblems];
|
|
324
|
+
return {
|
|
325
|
+
success: false,
|
|
326
|
+
skillName,
|
|
327
|
+
removedPath: installPath,
|
|
328
|
+
message: 'Skill "' +
|
|
329
|
+
skillName +
|
|
330
|
+
'" was removed from ' +
|
|
331
|
+
installPath +
|
|
332
|
+
', but its record in ' +
|
|
333
|
+
manifest.path +
|
|
334
|
+
' could not be updated (' +
|
|
335
|
+
(error instanceof Error ? error.message : String(error)) +
|
|
336
|
+
'). Its folder is already gone; run the same remove again once that file is writable, ' +
|
|
337
|
+
'which acts on whatever that record names at the time.',
|
|
338
|
+
...(parked.length > 0 && { warning: parked.join(' ') }),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
notify(onProgress, listenerProblems, 'done', 'Uninstall complete');
|
|
342
|
+
// Round 16 (both reviewers): away from a fan-out destination nothing swept
|
|
343
|
+
// what a failed removal parked, so it was named once and never again.
|
|
344
|
+
const warnings = [
|
|
345
|
+
...(adopted
|
|
346
|
+
? [
|
|
347
|
+
'This skill had no manifest entry (untracked) — it was adopted from disk state before removal.',
|
|
348
|
+
]
|
|
349
|
+
: []),
|
|
350
|
+
...(claimedByAnotherInstall
|
|
351
|
+
? [
|
|
352
|
+
'Another install claimed this name while this one was being removed, so that record was left alone.',
|
|
353
|
+
]
|
|
354
|
+
: []),
|
|
355
|
+
...(await parkedWarnings(installPath)),
|
|
356
|
+
...listenerProblems,
|
|
357
|
+
];
|
|
234
358
|
return {
|
|
235
359
|
success: true,
|
|
236
360
|
skillName,
|
|
237
361
|
message: 'Skill "' + skillName + '" has been uninstalled successfully.',
|
|
238
362
|
removedPath: installPath,
|
|
239
|
-
...(
|
|
240
|
-
warning: 'This skill had no manifest entry (untracked) — it was adopted from disk state before removal.',
|
|
241
|
-
}),
|
|
363
|
+
...(warnings.length > 0 && { warning: warnings.join(' ') }),
|
|
242
364
|
};
|
|
243
365
|
}
|
|
244
366
|
catch (error) {
|
|
@@ -246,6 +368,7 @@ export async function performUninstall(params) {
|
|
|
246
368
|
success: false,
|
|
247
369
|
skillName,
|
|
248
370
|
message: error instanceof Error ? error.message : 'Unknown error during uninstall',
|
|
371
|
+
...listenerWarning(),
|
|
249
372
|
};
|
|
250
373
|
}
|
|
251
374
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-installation.uninstall.js","sourceRoot":"","sources":["../../../src/services/skill-installation.uninstall.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skill-installation.uninstall.js","sourceRoot":"","sources":["../../../src/services/skill-installation.uninstall.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ export { logger, createLogger, silentLogger, type Logger } from './logger.js';
|
|
|
5
5
|
export { withRetry, fetchWithRetry, isTransientError, isRetryableStatus, parseRetryAfter, RetryExhaustedError, DEFAULT_RETRY_CONFIG, type RetryConfig, } from './retry.js';
|
|
6
6
|
export { checkForUpdates, formatUpdateNotification, agentInstallRemediationCommand, checkCursorMcpArtifact, type VersionCheckResult, type CursorMcpArtifactCheck, } from './version-check.js';
|
|
7
7
|
export { parseRepoUrl, isGitHubUrl, type ParsedRepoUrl } from './github-url.js';
|
|
8
|
+
export { VALID_SKILL_NAME_RE, validateSkillName } from './skill-name.js';
|
|
8
9
|
export { safeWriteFile, SymlinkError, HardlinkError } from './safe-fs.js';
|
|
9
10
|
export { isQuietModeEnabled } from './quiet-mode.js';
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,EAC9B,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG/E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAKzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,EAC9B,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG/E,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAGxE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAKzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/src/utils/index.js
CHANGED
|
@@ -7,6 +7,8 @@ export { withRetry, fetchWithRetry, isTransientError, isRetryableStatus, parseRe
|
|
|
7
7
|
export { checkForUpdates, formatUpdateNotification, agentInstallRemediationCommand, checkCursorMcpArtifact, } from './version-check.js';
|
|
8
8
|
// SMI-2171: GitHub URL parsing utilities
|
|
9
9
|
export { parseRepoUrl, isGitHubUrl } from './github-url.js';
|
|
10
|
+
// Shared skill name validation (relocated from @skillsmith/cli — canonical here now)
|
|
11
|
+
export { VALID_SKILL_NAME_RE, validateSkillName } from './skill-name.js';
|
|
10
12
|
// SMI-2274: Safe filesystem operations (symlink protection)
|
|
11
13
|
export { safeWriteFile, SymlinkError, HardlinkError } from './safe-fs.js';
|
|
12
14
|
// SMI-5897 (C-18/C-19, Wave 4 fix): shared SKILLSMITH_QUIET guard — used by
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAe,MAAM,aAAa,CAAA;AAC7E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,YAAY,CAAA;AAEnB,wDAAwD;AACxD,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,EAC9B,sBAAsB,GAGvB,MAAM,oBAAoB,CAAA;AAE3B,yCAAyC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAsB,MAAM,iBAAiB,CAAA;AAE/E,4DAA4D;AAC5D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEzE,4EAA4E;AAC5E,sEAAsE;AACtE,6EAA6E;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAe,MAAM,aAAa,CAAA;AAC7E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,YAAY,CAAA;AAEnB,wDAAwD;AACxD,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,EAC9B,sBAAsB,GAGvB,MAAM,oBAAoB,CAAA;AAE3B,yCAAyC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAsB,MAAM,iBAAiB,CAAA;AAE/E,qFAAqF;AACrF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExE,4DAA4D;AAC5D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEzE,4EAA4E;AAC5E,sEAAsE;AACtE,6EAA6E;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -15,7 +15,35 @@
|
|
|
15
15
|
* - SMI-2290: Checks nlink count to detect hardlinks
|
|
16
16
|
* - SMI-2288: Properly handles string encoding options for permissions
|
|
17
17
|
*/
|
|
18
|
+
import type { FileHandle } from 'fs/promises';
|
|
18
19
|
import type { WriteFileOptions } from 'fs';
|
|
20
|
+
/**
|
|
21
|
+
* O_NOFOLLOW: refuse to open symlinks
|
|
22
|
+
* Prefer runtime constant from fs.constants, fall back to platform-specific values
|
|
23
|
+
* if unavailable (e.g., Windows where O_NOFOLLOW is not defined).
|
|
24
|
+
*
|
|
25
|
+
* Exported (SMI-6529 F2) so other symlink-safe fd-based writers — e.g.
|
|
26
|
+
* writeInstallFiles' own rollback restore — share this exact platform
|
|
27
|
+
* -fallback resolution instead of a second, driftable copy.
|
|
28
|
+
*/
|
|
29
|
+
export declare const O_NOFOLLOW: number;
|
|
30
|
+
/**
|
|
31
|
+
* SMI-6529 N3 (round 4): `FileHandle.write()` is permitted by POSIX (and
|
|
32
|
+
* measured live — 2048/10000 bytes under `RLIMIT_FSIZE`) to write FEWER
|
|
33
|
+
* bytes than requested WITHOUT throwing. Every fd-based writer in this
|
|
34
|
+
* module family used a single unchecked `await fd.write(data)` call, so a
|
|
35
|
+
* short write silently truncated content with no error — for
|
|
36
|
+
* `restoreSnapshots()` specifically, that meant a "successful" restore that
|
|
37
|
+
* left the file smaller than the true original with no `InstallRestoreError`
|
|
38
|
+
* ever raised. Loops until every byte is accounted for, or throws if a call
|
|
39
|
+
* makes zero progress (a short write that returns 0 can otherwise spin
|
|
40
|
+
* forever).
|
|
41
|
+
*
|
|
42
|
+
* @param position - Explicit starting file offset, or `null` to write
|
|
43
|
+
* sequentially from the handle's own current position (which auto-advances
|
|
44
|
+
* after each underlying `write()` call, short or not).
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeFullBuffer(fd: FileHandle, data: Buffer, position?: number | null): Promise<void>;
|
|
19
47
|
/**
|
|
20
48
|
* Error thrown when a symlink is detected at a write destination.
|
|
21
49
|
*/
|
|
@@ -60,4 +88,45 @@ export declare class HardlinkError extends Error {
|
|
|
60
88
|
* ```
|
|
61
89
|
*/
|
|
62
90
|
export declare function safeWriteFile(filePath: string, content: string | Buffer, options?: WriteFileOptions | string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Error thrown when `safeCreateFile`'s exclusive create finds the destination
|
|
93
|
+
* already occupied — created by something else between the caller's own
|
|
94
|
+
* pre-write classification and this call (a race, not a symlink/hardlink).
|
|
95
|
+
* SMI-6529 L14(b).
|
|
96
|
+
*/
|
|
97
|
+
export declare class ExclusiveCreateRaceError extends Error {
|
|
98
|
+
readonly filePath: string;
|
|
99
|
+
constructor(filePath: string);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* SMI-6529 L14(b): create a NEW file exclusively — refuses (throws
|
|
103
|
+
* {@link ExclusiveCreateRaceError}) if anything already exists at `filePath`,
|
|
104
|
+
* symlink or otherwise, instead of silently truncating/overwriting it. Only
|
|
105
|
+
* appropriate for a write target the caller has just classified as `absent`
|
|
106
|
+
* (`classifyPreWrite` in skill-installation.io.rollback.ts) — the atomicity
|
|
107
|
+
* of `O_CREAT|O_EXCL` means "did this call create the file" is knowable
|
|
108
|
+
* without needing `safeWriteFile`'s "record BEFORE writing" hedge (F1, round
|
|
109
|
+
* 1), which exists specifically to survive `O_TRUNC`'s non-atomicity on an
|
|
110
|
+
* OVERWRITE — a case this function is never used for.
|
|
111
|
+
*
|
|
112
|
+
* @param filePath - Absolute path to create (must not already exist)
|
|
113
|
+
* @param content - File content (string or Buffer)
|
|
114
|
+
* @param options - Optional fs.writeFile options (encoding, mode) or encoding string
|
|
115
|
+
* @param onCreated - SMI-6529 N9 (round 4): fired the MOMENT the exclusive
|
|
116
|
+
* `open()` succeeds — i.e. the instant the file is KNOWN to exist on disk —
|
|
117
|
+
* BEFORE any content byte is written. Lets a caller (`writeInstallFiles`)
|
|
118
|
+
* record its rollback "created fresh, safe to unlink" candidate at the
|
|
119
|
+
* earliest correct moment: without this, a write that later fails (e.g.
|
|
120
|
+
* ENOSPC) after `open()` already created the file left a 0-byte/partial
|
|
121
|
+
* orphan that rollback never knew to remove, since the caller previously
|
|
122
|
+
* only recorded it AFTER this whole function resolved.
|
|
123
|
+
* @throws {ExclusiveCreateRaceError} if the destination already exists
|
|
124
|
+
* @throws {SymlinkError} technically unreachable (O_EXCL fails before O_NOFOLLOW
|
|
125
|
+
* would matter) but kept out of the public contract intentionally — this
|
|
126
|
+
* function never follows anything, by construction.
|
|
127
|
+
*/
|
|
128
|
+
export declare function safeCreateFile(filePath: string, content: string | Buffer, options?: WriteFileOptions | string, onCreated?: (identity?: {
|
|
129
|
+
dev: number;
|
|
130
|
+
ino: number;
|
|
131
|
+
}) => void): Promise<void>;
|
|
63
132
|
//# sourceMappingURL=safe-fs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-fs.d.ts","sourceRoot":"","sources":["../../../src/utils/safe-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"safe-fs.d.ts","sourceRoot":"","sources":["../../../src/utils/safe-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAA;AAE1C;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,QAE4B,CAAA;AAEnD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,UAAU,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,QAAQ,EAAE,MAAM,CAAA;gBACpB,QAAQ,EAAE,MAAM;CAK7B;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAgB,QAAQ,EAAE,MAAM,CAAA;gBACpB,QAAQ,EAAE,MAAM;CAK7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,GAClC,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,SAAgB,QAAQ,EAAE,MAAM,CAAA;gBACpB,QAAQ,EAAE,MAAM;CAK7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,EACnC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GAC5D,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
|