@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.
Files changed (188) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/README.md +2 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/config/owned-lock.acquire.d.ts +8 -0
  5. package/dist/src/config/owned-lock.acquire.d.ts.map +1 -1
  6. package/dist/src/config/owned-lock.acquire.js +19 -4
  7. package/dist/src/config/owned-lock.acquire.js.map +1 -1
  8. package/dist/src/config/owned-lock.claim.d.ts +4 -2
  9. package/dist/src/config/owned-lock.claim.d.ts.map +1 -1
  10. package/dist/src/config/owned-lock.claim.js +42 -8
  11. package/dist/src/config/owned-lock.claim.js.map +1 -1
  12. package/dist/src/config/owned-lock.d.ts.map +1 -1
  13. package/dist/src/config/owned-lock.js +1 -0
  14. package/dist/src/config/owned-lock.js.map +1 -1
  15. package/dist/src/config/owned-lock.test.js +126 -2
  16. package/dist/src/config/owned-lock.test.js.map +1 -1
  17. package/dist/src/config/owned-lock.types.d.ts +9 -0
  18. package/dist/src/config/owned-lock.types.d.ts.map +1 -1
  19. package/dist/src/db/createDatabase.d.ts.map +1 -1
  20. package/dist/src/db/createDatabase.js +0 -2
  21. package/dist/src/db/createDatabase.js.map +1 -1
  22. package/dist/src/exports/services.install.d.ts +1 -0
  23. package/dist/src/exports/services.install.d.ts.map +1 -1
  24. package/dist/src/exports/services.install.js +5 -0
  25. package/dist/src/exports/services.install.js.map +1 -1
  26. package/dist/src/index.d.ts +1 -1
  27. package/dist/src/index.js +1 -1
  28. package/dist/src/install/fan-out.cleanup.d.ts +37 -0
  29. package/dist/src/install/fan-out.cleanup.d.ts.map +1 -0
  30. package/dist/src/install/fan-out.cleanup.js +75 -0
  31. package/dist/src/install/fan-out.cleanup.js.map +1 -0
  32. package/dist/src/install/fan-out.d.ts +41 -31
  33. package/dist/src/install/fan-out.d.ts.map +1 -1
  34. package/dist/src/install/fan-out.js +213 -112
  35. package/dist/src/install/fan-out.js.map +1 -1
  36. package/dist/src/install/fan-out.leftovers.d.ts +60 -0
  37. package/dist/src/install/fan-out.leftovers.d.ts.map +1 -0
  38. package/dist/src/install/fan-out.leftovers.js +251 -0
  39. package/dist/src/install/fan-out.leftovers.js.map +1 -0
  40. package/dist/src/install/fan-out.locks.d.ts +12 -0
  41. package/dist/src/install/fan-out.locks.d.ts.map +1 -0
  42. package/dist/src/install/fan-out.locks.js +114 -0
  43. package/dist/src/install/fan-out.locks.js.map +1 -0
  44. package/dist/src/install/fan-out.manifest.d.ts +64 -0
  45. package/dist/src/install/fan-out.manifest.d.ts.map +1 -0
  46. package/dist/src/install/fan-out.manifest.js +130 -0
  47. package/dist/src/install/fan-out.manifest.js.map +1 -0
  48. package/dist/src/install/fan-out.overwrite.d.ts +51 -0
  49. package/dist/src/install/fan-out.overwrite.d.ts.map +1 -0
  50. package/dist/src/install/fan-out.overwrite.js +343 -0
  51. package/dist/src/install/fan-out.overwrite.js.map +1 -0
  52. package/dist/src/install/remove-if-same.d.ts +58 -0
  53. package/dist/src/install/remove-if-same.d.ts.map +1 -0
  54. package/dist/src/install/remove-if-same.js +222 -0
  55. package/dist/src/install/remove-if-same.js.map +1 -0
  56. package/dist/src/provenance/backfill.d.ts.map +1 -1
  57. package/dist/src/provenance/backfill.js +15 -2
  58. package/dist/src/provenance/backfill.js.map +1 -1
  59. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
  60. package/dist/src/security/scanner/SecurityScanner.scanners.js +8 -1
  61. package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
  62. package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts +22 -2
  63. package/dist/src/security/scanner/SecurityScanner.value-gate.d.ts.map +1 -1
  64. package/dist/src/security/scanner/SecurityScanner.value-gate.js +143 -6
  65. package/dist/src/security/scanner/SecurityScanner.value-gate.js.map +1 -1
  66. package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts +2 -2
  67. package/dist/src/security/scanner/SecurityScanner.weak-passwords.d.ts.map +1 -1
  68. package/dist/src/security/scanner/SecurityScanner.weak-passwords.js +185 -190
  69. package/dist/src/security/scanner/SecurityScanner.weak-passwords.js.map +1 -1
  70. package/dist/src/security/scanner/patterns.d.ts +47 -2
  71. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  72. package/dist/src/security/scanner/patterns.js +48 -3
  73. package/dist/src/security/scanner/patterns.js.map +1 -1
  74. package/dist/src/security/scanner/patterns.sensitive-path.d.ts +31 -3
  75. package/dist/src/security/scanner/patterns.sensitive-path.d.ts.map +1 -1
  76. package/dist/src/security/scanner/patterns.sensitive-path.js +59 -4
  77. package/dist/src/security/scanner/patterns.sensitive-path.js.map +1 -1
  78. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -1
  79. package/dist/src/services/agent-pack/prompt-source.js +3 -2
  80. package/dist/src/services/agent-pack/prompt-source.js.map +1 -1
  81. package/dist/src/services/skill-installation.content.d.ts +7 -2
  82. package/dist/src/services/skill-installation.content.d.ts.map +1 -1
  83. package/dist/src/services/skill-installation.content.js +75 -28
  84. package/dist/src/services/skill-installation.content.js.map +1 -1
  85. package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
  86. package/dist/src/services/skill-installation.helpers.js +8 -0
  87. package/dist/src/services/skill-installation.helpers.js.map +1 -1
  88. package/dist/src/services/skill-installation.io.d.ts +1 -29
  89. package/dist/src/services/skill-installation.io.d.ts.map +1 -1
  90. package/dist/src/services/skill-installation.io.dirs.d.ts +15 -0
  91. package/dist/src/services/skill-installation.io.dirs.d.ts.map +1 -0
  92. package/dist/src/services/skill-installation.io.dirs.js +84 -0
  93. package/dist/src/services/skill-installation.io.dirs.js.map +1 -0
  94. package/dist/src/services/skill-installation.io.js +6 -176
  95. package/dist/src/services/skill-installation.io.js.map +1 -1
  96. package/dist/src/services/skill-installation.io.rollback.d.ts +138 -0
  97. package/dist/src/services/skill-installation.io.rollback.d.ts.map +1 -0
  98. package/dist/src/services/skill-installation.io.rollback.js +218 -0
  99. package/dist/src/services/skill-installation.io.rollback.js.map +1 -0
  100. package/dist/src/services/skill-installation.io.write.d.ts +69 -0
  101. package/dist/src/services/skill-installation.io.write.d.ts.map +1 -0
  102. package/dist/src/services/skill-installation.io.write.js +417 -0
  103. package/dist/src/services/skill-installation.io.write.js.map +1 -0
  104. package/dist/src/services/skill-installation.service.d.ts.map +1 -1
  105. package/dist/src/services/skill-installation.service.finalize.d.ts +62 -0
  106. package/dist/src/services/skill-installation.service.finalize.d.ts.map +1 -0
  107. package/dist/src/services/skill-installation.service.finalize.js +136 -0
  108. package/dist/src/services/skill-installation.service.finalize.js.map +1 -0
  109. package/dist/src/services/skill-installation.service.js +66 -80
  110. package/dist/src/services/skill-installation.service.js.map +1 -1
  111. package/dist/src/services/skill-installation.target-guard.d.ts +82 -0
  112. package/dist/src/services/skill-installation.target-guard.d.ts.map +1 -0
  113. package/dist/src/services/skill-installation.target-guard.js +410 -0
  114. package/dist/src/services/skill-installation.target-guard.js.map +1 -0
  115. package/dist/src/services/skill-installation.types.d.ts +13 -1
  116. package/dist/src/services/skill-installation.types.d.ts.map +1 -1
  117. package/dist/src/services/skill-installation.types.js.map +1 -1
  118. package/dist/src/services/skill-installation.uninstall.d.ts +3 -1
  119. package/dist/src/services/skill-installation.uninstall.d.ts.map +1 -1
  120. package/dist/src/services/skill-installation.uninstall.helpers.d.ts +59 -0
  121. package/dist/src/services/skill-installation.uninstall.helpers.d.ts.map +1 -0
  122. package/dist/src/services/skill-installation.uninstall.helpers.js +124 -0
  123. package/dist/src/services/skill-installation.uninstall.helpers.js.map +1 -0
  124. package/dist/src/services/skill-installation.uninstall.js +148 -25
  125. package/dist/src/services/skill-installation.uninstall.js.map +1 -1
  126. package/dist/src/utils/safe-fs.d.ts +69 -0
  127. package/dist/src/utils/safe-fs.d.ts.map +1 -1
  128. package/dist/src/utils/safe-fs.js +113 -2
  129. package/dist/src/utils/safe-fs.js.map +1 -1
  130. package/dist/tests/install/fan-out.test.js +1951 -13
  131. package/dist/tests/install/fan-out.test.js.map +1 -1
  132. package/dist/tests/install/remove-if-same.test.d.ts +2 -0
  133. package/dist/tests/install/remove-if-same.test.d.ts.map +1 -0
  134. package/dist/tests/install/remove-if-same.test.js +298 -0
  135. package/dist/tests/install/remove-if-same.test.js.map +1 -0
  136. package/dist/tests/integration/fan-out-lock-contention.test.d.ts +11 -0
  137. package/dist/tests/integration/fan-out-lock-contention.test.d.ts.map +1 -0
  138. package/dist/tests/integration/fan-out-lock-contention.test.js +53 -0
  139. package/dist/tests/integration/fan-out-lock-contention.test.js.map +1 -0
  140. package/dist/tests/provenance/backfill.test.js +43 -0
  141. package/dist/tests/provenance/backfill.test.js.map +1 -1
  142. package/dist/tests/security/scanner-regression-guard.test.js +33 -5
  143. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  144. package/dist/tests/security/sensitive-path-adversarial-review.test.js +120 -0
  145. package/dist/tests/security/sensitive-path-adversarial-review.test.js.map +1 -1
  146. package/dist/tests/security/sensitive-path-boolean-flag.test.d.ts +2 -0
  147. package/dist/tests/security/sensitive-path-boolean-flag.test.d.ts.map +1 -0
  148. package/dist/tests/security/sensitive-path-boolean-flag.test.js +151 -0
  149. package/dist/tests/security/sensitive-path-boolean-flag.test.js.map +1 -0
  150. package/dist/tests/security/sensitive-path-fp.test.js +71 -5
  151. package/dist/tests/security/sensitive-path-fp.test.js.map +1 -1
  152. package/dist/tests/security/sensitive-path-prefixed-secrets.test.d.ts +2 -0
  153. package/dist/tests/security/sensitive-path-prefixed-secrets.test.d.ts.map +1 -0
  154. package/dist/tests/security/sensitive-path-prefixed-secrets.test.js +176 -0
  155. package/dist/tests/security/sensitive-path-prefixed-secrets.test.js.map +1 -0
  156. package/dist/tests/security/weak-password-lexicon.test.js +14 -4
  157. package/dist/tests/security/weak-password-lexicon.test.js.map +1 -1
  158. package/dist/tests/unit/services/skill-installation.content.test.js +23 -0
  159. package/dist/tests/unit/services/skill-installation.content.test.js.map +1 -1
  160. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js +35 -14
  161. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js.map +1 -1
  162. package/dist/tests/unit/services/skill-installation.io.rollback.test.d.ts +2 -0
  163. package/dist/tests/unit/services/skill-installation.io.rollback.test.d.ts.map +1 -0
  164. package/dist/tests/unit/services/skill-installation.io.rollback.test.js +984 -0
  165. package/dist/tests/unit/services/skill-installation.io.rollback.test.js.map +1 -0
  166. package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.d.ts +2 -0
  167. package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.d.ts.map +1 -0
  168. package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.js +148 -0
  169. package/dist/tests/unit/services/skill-installation.io.rollback.unit.test.js.map +1 -0
  170. package/dist/tests/unit/services/skill-installation.service.error-codes.test.js +19 -0
  171. package/dist/tests/unit/services/skill-installation.service.error-codes.test.js.map +1 -1
  172. package/dist/tests/unit/services/skill-installation.service.finalize.test.d.ts +2 -0
  173. package/dist/tests/unit/services/skill-installation.service.finalize.test.d.ts.map +1 -0
  174. package/dist/tests/unit/services/skill-installation.service.finalize.test.js +147 -0
  175. package/dist/tests/unit/services/skill-installation.service.finalize.test.js.map +1 -0
  176. package/dist/tests/unit/services/skill-installation.service.test.js +43 -0
  177. package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -1
  178. package/dist/tests/unit/services/skill-installation.target-guard.test.d.ts +2 -0
  179. package/dist/tests/unit/services/skill-installation.target-guard.test.d.ts.map +1 -0
  180. package/dist/tests/unit/services/skill-installation.target-guard.test.js +590 -0
  181. package/dist/tests/unit/services/skill-installation.target-guard.test.js.map +1 -0
  182. package/dist/tests/unit/services/skill-installation.uninstall.guard.test.d.ts +2 -0
  183. package/dist/tests/unit/services/skill-installation.uninstall.guard.test.d.ts.map +1 -0
  184. package/dist/tests/unit/services/skill-installation.uninstall.guard.test.js +473 -0
  185. package/dist/tests/unit/services/skill-installation.uninstall.guard.test.js.map +1 -0
  186. package/dist/tests/utils/safe-fs.test.js +129 -2
  187. package/dist/tests/utils/safe-fs.test.js.map +1 -1
  188. package/package.json +1 -1
@@ -15,6 +15,7 @@ import { TransformationService } from '../services/TransformationService.js';
15
15
  import { computeQualityScore } from '../scoring/quality-score.js';
16
16
  export { fetchFromGitHub } from './skill-installation.io.js';
17
17
  import { CANONICAL_CLIENT, CLIENT_DISPLAY_LABELS } from '../install/paths.js';
18
+ import { InstallRestoreError } from './skill-installation.io.rollback.js';
18
19
  export function hashContent(content) {
19
20
  return createHash('sha256').update(content).digest('hex');
20
21
  }
@@ -234,6 +235,13 @@ const KNOWN_ERROR_PREFIXES = [
234
235
  'uses directory-package mode',
235
236
  ];
236
237
  export function sanitizeInstallError(error) {
238
+ // SMI-6529 H2: a rollback-restore failure is exactly the case where the
239
+ // generic fallback below is actively harmful — it names which pre-existing
240
+ // files could NOT be restored, which the user needs to recover manually.
241
+ // Bypasses the allowlist entirely (never gated on message content).
242
+ if (error instanceof InstallRestoreError) {
243
+ return error.message;
244
+ }
237
245
  if (error instanceof Error) {
238
246
  if (KNOWN_ERROR_PREFIXES.some((p) => error.message.includes(p))) {
239
247
  return error.message;
@@ -1 +1 @@
1
- {"version":3,"file":"skill-installation.helpers.js","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-installation.helpers.js","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"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"}
@@ -4,38 +4,10 @@
4
4
  * @see SMI-4745: domain-driven split to stay under the 500-line CI gate
5
5
  */
6
6
  import type { ScannerOptions, ScanReport } from '../security/index.js';
7
- import { type ClientId } from '../install/paths.js';
7
+ export { writeInstallFiles, type WriteInstallResult } from './skill-installation.io.write.js';
8
8
  export declare function assertNotEncrypted(content: string, filePath: string): void;
9
9
  export declare function fetchFromGitHub(owner: string, repo: string, filePath: string, branch?: string): Promise<string>;
10
10
  export declare function checkForModifications(skillPath: string, installedAt: string): Promise<boolean>;
11
- export interface WriteInstallResult {
12
- writtenFiles: string[];
13
- subagentPath?: string;
14
- }
15
- export declare function writeInstallFiles(installPath: string, skillsDir: string, skillName: string, finalSkillContent: string, subSkillFiles: Array<{
16
- filename: string;
17
- content: string;
18
- }>, subagentContent: string | undefined,
19
- /**
20
- * SMI-5980 (Wave 3): the client this companion subagent (if any) is
21
- * generated for — resolves its output path via
22
- * `resolveCompanionAgentPath()` (install/paths.ts) instead of a hardcoded
23
- * `~/.claude/agents/` literal. Optional, defaulting to `CANONICAL_CLIENT`
24
- * (`claude-code`) so pre-existing callers/tests that never pass it keep
25
- * today's exact behavior unchanged.
26
- */
27
- client?: ClientId,
28
- /**
29
- * SMI-5982 code-review fix #1: explicit base dir for resolving a RELATIVE
30
- * `COMPANION_AGENT_TARGETS[client].dir` (Antigravity only — every other
31
- * client's `dir` is absolute already). Threaded through to
32
- * `resolveCompanionAgentPath()`'s own `baseDir` param as-is (no
33
- * `?? process.cwd()` fallback here) — `resolveCompanionAgentPath()` itself
34
- * now requires an explicit `baseDir` for every `directory-package`-mode
35
- * client (PR-review follow-up), so whether an omitted `companionBaseDir`
36
- * is acceptable is that function's call to make, not this one's.
37
- */
38
- companionBaseDir?: string): Promise<WriteInstallResult>;
39
11
  export interface OptionalInstallFilesResult {
40
12
  /** Validation warnings from config.json (surfaced as install tips). */
41
13
  configWarnings: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"skill-installation.io.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.io.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,qBAAqB,CAAA;AAS5B,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQ1E;AAkBD,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAe,GACtB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAcD,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAmED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3D,eAAe,EAAE,MAAM,GAAG,SAAS;AACnC;;;;;;;GAOG;AACH,MAAM,GAAE,QAA2B;AACnC;;;;;;;;;GASG;AACH,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,kBAAkB,CAAC,CA4F7B;AAED,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB;;;OAGG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;IACxD,4EAA4E;IAC5E,YAAY,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,OAAO,CAAC,0BAA0B,CAAC,CAgDrC"}
1
+ {"version":3,"file":"skill-installation.io.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.io.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AActE,OAAO,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAE7F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQ1E;AAkBD,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAe,GACtB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAcD,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAED,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB;;;OAGG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;IACxD,4EAA4E;IAC5E,YAAY,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,OAAO,CAAC,0BAA0B,CAAC,CAgDrC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @fileoverview Symlink-safe intermediate-directory creation for writeInstallFiles.
3
+ * @module @skillsmith/core/services/skill-installation.io.dirs
4
+ * @see SMI-6529 Wave A0 (F4): split out of skill-installation.io.ts to stay
5
+ * under the 500-line CI gate once the F1-F4 rollback fixes landed — pure
6
+ * move, no behavior change.
7
+ */
8
+ /**
9
+ * Create every path segment of `dir` (relative to `baseDir`) via `ensureDirNoFollow()`,
10
+ * so no intermediate segment can be a pre-existing symlink. `dir` must already be lexically
11
+ * inside `baseDir` — callers are expected to have proven that (as `writeInstallFiles()`'s
12
+ * `installPath` already is, via its own lexical + realpath checks) before calling this.
13
+ */
14
+ export declare function mkdirNoFollow(baseDir: string, dir: string, freshDirs: Set<string>): Promise<void>;
15
+ //# sourceMappingURL=skill-installation.io.dirs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.io.dirs.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.io.dirs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8DH;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @fileoverview Symlink-safe intermediate-directory creation for writeInstallFiles.
3
+ * @module @skillsmith/core/services/skill-installation.io.dirs
4
+ * @see SMI-6529 Wave A0 (F4): split out of skill-installation.io.ts to stay
5
+ * under the 500-line CI gate once the F1-F4 rollback fixes landed — pure
6
+ * move, no behavior change.
7
+ */
8
+ import * as fs from 'fs/promises';
9
+ import * as path from 'path';
10
+ /**
11
+ * Ensure `dirPath` exists as a real directory, never following (or silently accepting) an
12
+ * existing symlink there.
13
+ *
14
+ * Sol final-code-review finding #2 (confirmed): `safeWriteFile()` only `lstat`s the FINAL
15
+ * path component before writing — a symlinked INTERMEDIATE directory (e.g. `<installPath>/
16
+ * scripts` already existing as a symlink from a prior force-reinstall or a planted attack)
17
+ * is never checked, so a nested sub-skill filename like `"scripts/run.sh"` could write
18
+ * through it to an arbitrary target outside `installPath`. `fs.mkdir(dir, {recursive:true})`
19
+ * alone does not close this either — it silently no-ops on an existing path whether or not
20
+ * that path is a symlink.
21
+ *
22
+ * SMI-6529 F4: `freshDirs` records every segment that did NOT exist when this call started
23
+ * checking it — regardless of which concurrent sibling sub-skill write's own `fs.mkdir`
24
+ * ultimately wins the create below (the benign EEXIST race) — so a failed install can roll
25
+ * a nested directory back instead of leaving it orphaned inside a pre-existing `installPath`.
26
+ */
27
+ async function ensureDirNoFollow(dirPath, freshDirs) {
28
+ const check = async () => {
29
+ let stats;
30
+ try {
31
+ stats = await fs.lstat(dirPath);
32
+ }
33
+ catch (err) {
34
+ if (err.code === 'ENOENT')
35
+ return 'missing';
36
+ throw err;
37
+ }
38
+ if (stats.isSymbolicLink()) {
39
+ throw new Error('Refusing to write through existing symlink: ' + dirPath);
40
+ }
41
+ if (!stats.isDirectory()) {
42
+ throw new Error('Expected a directory, found a file: ' + dirPath);
43
+ }
44
+ return 'ok';
45
+ };
46
+ if ((await check()) === 'ok')
47
+ return;
48
+ // This segment did not exist at the point we checked it — record it as a rollback
49
+ // candidate BEFORE attempting to create it (mirrors F1's write-side ordering).
50
+ freshDirs.add(dirPath);
51
+ try {
52
+ await fs.mkdir(dirPath);
53
+ }
54
+ catch (err) {
55
+ // EEXIST here is a benign race between our own concurrent sub-skill writes under the
56
+ // same new subdirectory (writeInstallFiles writes them in parallel) — re-check below
57
+ // rather than trust that; it ALSO re-confirms nothing hostile won the race.
58
+ if (err.code !== 'EEXIST')
59
+ throw err;
60
+ }
61
+ // Re-check post-create: closes both the benign concurrent-mkdir race above and the TOCTOU
62
+ // window between the first check and this mkdir.
63
+ if ((await check()) !== 'ok') {
64
+ throw new Error('Failed to create directory: ' + dirPath);
65
+ }
66
+ }
67
+ /**
68
+ * Create every path segment of `dir` (relative to `baseDir`) via `ensureDirNoFollow()`,
69
+ * so no intermediate segment can be a pre-existing symlink. `dir` must already be lexically
70
+ * inside `baseDir` — callers are expected to have proven that (as `writeInstallFiles()`'s
71
+ * `installPath` already is, via its own lexical + realpath checks) before calling this.
72
+ */
73
+ export async function mkdirNoFollow(baseDir, dir, freshDirs) {
74
+ const relative = path.relative(baseDir, dir);
75
+ if (relative === '' || relative.startsWith('..'))
76
+ return;
77
+ const segments = relative.split(path.sep);
78
+ let current = baseDir;
79
+ for (const segment of segments) {
80
+ current = path.join(current, segment);
81
+ await ensureDirNoFollow(current, freshDirs);
82
+ }
83
+ }
84
+ //# sourceMappingURL=skill-installation.io.dirs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.io.dirs.js","sourceRoot":"","sources":["../../../src/services/skill-installation.io.dirs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,SAAsB;IACtE,MAAM,KAAK,GAAG,KAAK,IAA+B,EAAE;QAClD,IAAI,KAAK,CAAA;QACT,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAA;YACtE,MAAM,GAAG,CAAA;QACX,CAAC;QACD,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,OAAO,CAAC,CAAA;QAC3E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,OAAO,CAAC,CAAA;QACnE,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,KAAK,IAAI;QAAE,OAAM;IAEpC,kFAAkF;IAClF,+EAA+E;IAC/E,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAEtB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,qFAAqF;QACrF,qFAAqF;QACrF,4EAA4E;QAC5E,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAA;IACjE,CAAC;IAED,0FAA0F;IAC1F,iDAAiD;IACjD,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,OAAO,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,GAAW,EACX,SAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IAC5C,IAAI,QAAQ,KAAK,EAAE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAM;IACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,OAAO,GAAG,OAAO,CAAA;IACrB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACrC,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC"}
@@ -5,11 +5,15 @@
5
5
  */
6
6
  import * as fs from 'fs/promises';
7
7
  import * as path from 'path';
8
- import { safeWriteFile } from '../utils/safe-fs.js';
9
8
  import { SecurityScanner } from '../security/index.js';
10
- import { CANONICAL_CLIENT, getCompanionAgentTarget, resolveCompanionAgentPath, } from '../install/paths.js';
11
9
  import { validateOptionalConfig } from './skill-installation.validate.js';
12
10
  import { BUNDLED_SCAN_FILES, classifyBundledFile, extractPackageJsonLifecycleScripts, isRejectableScan, } from './skill-installation.policy.js';
11
+ // SMI-6529 Wave A0 round 2: writeInstallFiles() + WriteInstallResult moved to
12
+ // a sibling module (pure move, no behavior change to it) to keep this file
13
+ // under the 500-line CI gate once the M4/M7/M10/L14/L15 fixes landed —
14
+ // re-exported here so every existing `from './skill-installation.io.js'`
15
+ // import site is unaffected.
16
+ export { writeInstallFiles } from './skill-installation.io.write.js';
13
17
  export function assertNotEncrypted(content, filePath) {
14
18
  if (content.startsWith('\x00GITCRYPT')) {
15
19
  throw new Error('File "' +
@@ -84,180 +88,6 @@ export async function checkForModifications(skillPath, installedAt) {
84
88
  return false;
85
89
  }
86
90
  }
87
- /**
88
- * Ensure `dirPath` exists as a real directory, never following (or silently accepting) an
89
- * existing symlink there.
90
- *
91
- * Sol final-code-review finding #2 (confirmed): `safeWriteFile()` only `lstat`s the FINAL
92
- * path component before writing — a symlinked INTERMEDIATE directory (e.g. `<installPath>/
93
- * scripts` already existing as a symlink from a prior force-reinstall or a planted attack)
94
- * is never checked, so a nested sub-skill filename like `"scripts/run.sh"` could write
95
- * through it to an arbitrary target outside `installPath`. `fs.mkdir(dir, {recursive:true})`
96
- * alone does not close this either — it silently no-ops on an existing path whether or not
97
- * that path is a symlink.
98
- */
99
- async function ensureDirNoFollow(dirPath) {
100
- const check = async () => {
101
- let stats;
102
- try {
103
- stats = await fs.lstat(dirPath);
104
- }
105
- catch (err) {
106
- if (err.code === 'ENOENT')
107
- return 'missing';
108
- throw err;
109
- }
110
- if (stats.isSymbolicLink()) {
111
- throw new Error('Refusing to write through existing symlink: ' + dirPath);
112
- }
113
- if (!stats.isDirectory()) {
114
- throw new Error('Expected a directory, found a file: ' + dirPath);
115
- }
116
- return 'ok';
117
- };
118
- if ((await check()) === 'ok')
119
- return;
120
- try {
121
- await fs.mkdir(dirPath);
122
- }
123
- catch (err) {
124
- // EEXIST here is a benign race between our own concurrent sub-skill writes under the
125
- // same new subdirectory (writeInstallFiles writes them in parallel) — re-check below
126
- // rather than trust that; it ALSO re-confirms nothing hostile won the race.
127
- if (err.code !== 'EEXIST')
128
- throw err;
129
- }
130
- // Re-check post-create: closes both the benign concurrent-mkdir race above and the TOCTOU
131
- // window between the first check and this mkdir.
132
- if ((await check()) !== 'ok') {
133
- throw new Error('Failed to create directory: ' + dirPath);
134
- }
135
- }
136
- /**
137
- * Create every path segment of `dir` (relative to `baseDir`) via `ensureDirNoFollow()`,
138
- * so no intermediate segment can be a pre-existing symlink. `dir` must already be lexically
139
- * inside `baseDir` — callers are expected to have proven that (as `writeInstallFiles()`'s
140
- * `installPath` already is, via its own lexical + realpath checks) before calling this.
141
- */
142
- async function mkdirNoFollow(baseDir, dir) {
143
- const relative = path.relative(baseDir, dir);
144
- if (relative === '' || relative.startsWith('..'))
145
- return;
146
- const segments = relative.split(path.sep);
147
- let current = baseDir;
148
- for (const segment of segments) {
149
- current = path.join(current, segment);
150
- await ensureDirNoFollow(current);
151
- }
152
- }
153
- export async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, subSkillFiles, subagentContent,
154
- /**
155
- * SMI-5980 (Wave 3): the client this companion subagent (if any) is
156
- * generated for — resolves its output path via
157
- * `resolveCompanionAgentPath()` (install/paths.ts) instead of a hardcoded
158
- * `~/.claude/agents/` literal. Optional, defaulting to `CANONICAL_CLIENT`
159
- * (`claude-code`) so pre-existing callers/tests that never pass it keep
160
- * today's exact behavior unchanged.
161
- */
162
- client = CANONICAL_CLIENT,
163
- /**
164
- * SMI-5982 code-review fix #1: explicit base dir for resolving a RELATIVE
165
- * `COMPANION_AGENT_TARGETS[client].dir` (Antigravity only — every other
166
- * client's `dir` is absolute already). Threaded through to
167
- * `resolveCompanionAgentPath()`'s own `baseDir` param as-is (no
168
- * `?? process.cwd()` fallback here) — `resolveCompanionAgentPath()` itself
169
- * now requires an explicit `baseDir` for every `directory-package`-mode
170
- * client (PR-review follow-up), so whether an omitted `companionBaseDir`
171
- * is acceptable is that function's call to make, not this one's.
172
- */
173
- companionBaseDir) {
174
- const writtenFiles = [];
175
- let subagentPath;
176
- // SMI-5359 (retro): lexically reject an escaping installPath BEFORE any filesystem
177
- // mutation. path.resolve normalizes `..`, so an unsanitized skillName like '..'
178
- // (e.g. path.basename('foo/..')) or a compromised registry skillName cannot drive
179
- // installPath outside skillsDir and reach the rollback below. Thrown here, nothing
180
- // has been created, so no cleanup is needed.
181
- const resolvedInstall = path.resolve(installPath);
182
- const resolvedSkillsDir = path.resolve(skillsDir);
183
- if (resolvedInstall !== resolvedSkillsDir &&
184
- !resolvedInstall.startsWith(resolvedSkillsDir + path.sep)) {
185
- throw new Error('Install path escapes skills directory (lexical): ' + installPath);
186
- }
187
- // Only set true once installPath is PROVEN inside skillsDir (both the lexical check
188
- // above and the realpath check below). The recursive rollback rm keys off this so it
189
- // can never force-delete an out-of-bounds path (e.g. a symlink-escape the realpath
190
- // check rejects after mkdir).
191
- let pathValidated = false;
192
- try {
193
- await fs.mkdir(installPath, { recursive: true });
194
- // SMI-4692: realpath both sides — macOS /var/folders symlinks to /private/var/folders.
195
- const realInstallPath = await fs.realpath(installPath);
196
- const expectedPrefix = await fs.realpath(skillsDir).catch(() => path.resolve(skillsDir));
197
- if (!realInstallPath.startsWith(expectedPrefix + path.sep) &&
198
- realInstallPath !== expectedPrefix) {
199
- throw new Error('Install path escapes skills directory (realpath): ' + installPath);
200
- }
201
- pathValidated = true;
202
- const mainSkillPath = path.join(installPath, 'SKILL.md');
203
- await safeWriteFile(mainSkillPath, finalSkillContent);
204
- writtenFiles.push(mainSkillPath);
205
- // Write sub-skills in parallel. Sol final-code-review findings #2/#4: a nested filename
206
- // (e.g. "scripts/run.sh", used by private-registry content installs) needs its parent
207
- // directory created symlink-safely first — writeInstallFiles previously neither created it
208
- // (ENOENT on any clean install with a nested file) nor checked it for a pre-existing symlink.
209
- if (subSkillFiles.length > 0) {
210
- await Promise.all(subSkillFiles.map(async (subSkill) => {
211
- const subPath = path.join(installPath, subSkill.filename);
212
- const subDir = path.dirname(subPath);
213
- if (subDir !== installPath) {
214
- await mkdirNoFollow(installPath, subDir);
215
- }
216
- await safeWriteFile(subPath, subSkill.content);
217
- writtenFiles.push(subPath);
218
- }));
219
- }
220
- // Write companion subagent if generated
221
- if (subagentContent) {
222
- subagentPath = resolveCompanionAgentPath(skillName, client, companionBaseDir);
223
- const agentsDir = path.dirname(subagentPath);
224
- await fs.mkdir(agentsDir, { recursive: true });
225
- await safeWriteFile(subagentPath, subagentContent);
226
- writtenFiles.push(subagentPath);
227
- }
228
- }
229
- catch (writeError) {
230
- // Rollback on failure. Unlink tracked files first (subagentPath lives OUTSIDE
231
- // installPath, under the client's companion-agent dir — see
232
- // resolveCompanionAgentPath()/COMPANION_AGENT_TARGETS, install/paths.ts).
233
- for (const filePath of writtenFiles) {
234
- await fs.unlink(filePath).catch(() => { });
235
- }
236
- // SMI-5982 (Wave 6): 'directory-package' mode (Antigravity) creates a
237
- // skill-named subdirectory OUTSIDE installPath (<agentsDir>/<skillName>/
238
- // agent.md) that 'flat' mode never needed — every other client's agents
239
- // dir is a shared, pre-existing directory, never created per-skill. A
240
- // failed install must not leave that now-empty per-skill directory
241
- // orphaned. rmdir is non-recursive: a safe no-op if the directory is
242
- // missing (never created) or non-empty (unexpected content survives).
243
- if (subagentPath && getCompanionAgentTarget(client).fileMode === 'directory-package') {
244
- await fs.rmdir(path.dirname(subagentPath)).catch(() => { });
245
- }
246
- // Only recursively remove installPath once it has been PROVEN inside skillsDir
247
- // (pathValidated) — so an untracked orphan from a mid-batch Promise.all write can't
248
- // survive. If mkdir or the realpath escape guard threw, installPath was never
249
- // validated; fall back to a non-recursive rmdir, a safe no-op on a non-empty or
250
- // out-of-bounds directory (NEVER a recursive force-delete of an unvalidated path).
251
- if (pathValidated) {
252
- await fs.rm(installPath, { recursive: true, force: true }).catch(() => { });
253
- }
254
- else {
255
- await fs.rmdir(installPath).catch(() => { });
256
- }
257
- throw writeError;
258
- }
259
- return { writtenFiles, subagentPath };
260
- }
261
91
  /**
262
92
  * SMI-5359 Gap-1 / SMI-5422 Phase 1: fetch + scan the optional install files
263
93
  * WITHOUT writing them. The caller runs this BEFORE writeInstallFiles, rejects
@@ -1 +1 @@
1
- {"version":3,"file":"skill-installation.io.js","sourceRoot":"","sources":["../../../src/services/skill-installation.io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-installation.io.js","sourceRoot":"","sources":["../../../src/services/skill-installation.io.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @fileoverview writeInstallFiles' file-level snapshot/restore rollback helpers.
3
+ * @module @skillsmith/core/services/skill-installation.io.rollback
4
+ * @see SMI-6529 Wave A0
5
+ *
6
+ * Split out of skill-installation.io.ts to stay under the 500-line CI gate
7
+ * once the rollback fix landed (mirrors this module's existing sibling-split
8
+ * convention, e.g. skill-installation.policy.ts).
9
+ *
10
+ * On a real user machine, a rollback in `writeInstallFiles` used to unlink
11
+ * every file it had touched — including files that ALREADY EXISTED before
12
+ * the install started (a real user's git-cloned skill directory, `.git`
13
+ * included). These helpers make that rollback safe: classify a file BEFORE
14
+ * writing into it, snapshot it if it's a pre-existing regular file, and
15
+ * restore it if the install fails partway through.
16
+ *
17
+ * F1 (review round 1): `safeWriteFile` opens with O_TRUNC and writes in
18
+ * place — not atomic. A write that fails mid-way (ENOSPC/EIO after
19
+ * truncation) can leave a truncated original on disk. The snapshot MUST be
20
+ * taken, and recorded as a rollback candidate, BEFORE `safeWriteFile` is
21
+ * ever called — never after it "succeeds," since a failure can occur after
22
+ * the file has already been truncated.
23
+ */
24
+ import { type EntryIdentity } from '../install/remove-if-same.js';
25
+ /** A pre-write copy of a regular file (path, bytes and mode), used to restore it on rollback. */
26
+ export interface FileSnapshot {
27
+ path: string;
28
+ content: Buffer;
29
+ mode: number;
30
+ }
31
+ /**
32
+ * SMI-6529 H2: thrown instead of a plain `Error` whenever a rollback restore
33
+ * fails partway through a failed (or later-cancelled) install — i.e. some
34
+ * pre-existing file could NOT be restored to its original content and the
35
+ * user needs to recover it manually. Before this class existed, the
36
+ * compound message ("Install failed (...) AND could not restore N
37
+ * pre-existing file(s)...") was a plain `Error`, so `sanitizeInstallError()`
38
+ * (skill-installation.helpers.ts) — which only passes through messages
39
+ * matching a small known-prefix allowlist — silently replaced this exact,
40
+ * actionable diagnostic with the generic "Installation failed due to an
41
+ * internal error", hiding the one failure mode where telling the user
42
+ * EXACTLY which files to recover manually matters most. `sanitizeInstallError`
43
+ * special-cases `instanceof InstallRestoreError` to always pass the message
44
+ * through verbatim, bypassing the allowlist entirely.
45
+ */
46
+ export declare class InstallRestoreError extends Error {
47
+ /** The paths that could not be restored (same list as `restoreSnapshots()`'s return). */
48
+ readonly restoreFailures: string[];
49
+ /**
50
+ * SMI-6529 round 13: paths this install created but could not remove, each
51
+ * with its reason (a permission error, or a folder replaced by something
52
+ * else since the install created it). These used to be swallowed.
53
+ */
54
+ readonly cleanupFailures: string[];
55
+ constructor(innerMessage: string, restoreFailures: string[], options?: {
56
+ cause?: unknown;
57
+ }, cleanupFailures?: string[]);
58
+ }
59
+ /** What {@link classifyPreWrite} found at a write target before any write. */
60
+ export type PreWriteClassification = {
61
+ kind: 'absent';
62
+ } | {
63
+ kind: 'regular';
64
+ snapshot: FileSnapshot;
65
+ }
66
+ /** Symlink, directory, or anything else `safeWriteFile` refuses BEFORE touching a byte. */
67
+ | {
68
+ kind: 'other';
69
+ };
70
+ /**
71
+ * Classify a write target BEFORE any write is attempted, so the caller can
72
+ * record a rollback candidate (snapshot for an existing regular file, a
73
+ * fresh-creation marker for an absent path) ahead of the write — never
74
+ * after, since `safeWriteFile`'s O_TRUNC is not atomic and a failure can
75
+ * land between truncation and the write completing.
76
+ */
77
+ export declare function classifyPreWrite(filePath: string): Promise<PreWriteClassification>;
78
+ /**
79
+ * Restore every overwritten file's original bytes + mode. Returns the paths
80
+ * that could NOT be restored rather than throwing — the caller must surface
81
+ * these explicitly (a failed restore is data loss the user needs to recover
82
+ * manually), never swallow them silently.
83
+ *
84
+ * F2 (review round 1):
85
+ * - Skips a no-op restore when the current bytes already equal the
86
+ * snapshot — avoids a false restore failure for a file `safeWriteFile`
87
+ * refused before ever touching it (e.g. a hardlinked file: snapshotted
88
+ * proactively per F1's "regular" classification, but never actually
89
+ * written, since `safeWriteFile`'s own hardlink check runs before any
90
+ * truncation).
91
+ * - Restores WITHOUT following symlinks: `open(O_WRONLY|O_TRUNC|O_NOFOLLOW)`
92
+ * + write + fd-level chmod — never a path-based `fs.writeFile`/`fs.chmod`,
93
+ * both of which follow symlinks and could write through one planted at
94
+ * the snapshot's path between snapshot-time and restore-time.
95
+ *
96
+ * SMI-6529 M4 (round 2): restores in REVERSE order (most-recently-taken
97
+ * snapshot first). This is the correct undo-stack semantics whenever two
98
+ * snapshots can legitimately describe the SAME real on-disk file at
99
+ * different points in time — e.g. a case-insensitive filesystem alias
100
+ * (`SKILL.md`/`skill.md` on default APFS) that this module's caller failed
101
+ * to dedupe: snapshot A ("before write 1") and snapshot B ("before write 2",
102
+ * captured AFTER write 1 already ran) both target the same inode. Restoring
103
+ * forward (A then B) ends on B's value — the intermediate post-write-1 state,
104
+ * not the true original. Restoring in reverse (B then A) always converges on
105
+ * the earliest, TRUE original. A caller that also dedupes at snapshot-time
106
+ * (as `writeInstallFiles` now does) never produces such a pair in the first
107
+ * place — this ordering is defense-in-depth for any snapshot list this
108
+ * function is ever handed, not a substitute for that dedupe.
109
+ *
110
+ * SMI-6529 N3 (round 4): writes via `writeFullBuffer()` (loops until every
111
+ * byte is written — `FileHandle.write()` can short-write without throwing,
112
+ * measured live under `RLIMIT_FSIZE`) and then verifies the ON-DISK size
113
+ * matches the snapshot's exact length before trusting the restore. Either
114
+ * check failing is treated as a restore FAILURE (pushed to `failures`, same
115
+ * as any other error here) — a partially-restored file is exactly the data
116
+ * loss this whole module exists to prevent, so it must never be reported as
117
+ * a clean restore.
118
+ */
119
+ export declare function restoreSnapshots(snapshots: FileSnapshot[]): Promise<string[]>;
120
+ export type { EntryIdentity };
121
+ /**
122
+ * Run one rollback cleanup step. An error whose code is in `ignore` means
123
+ * nothing of ours was left to remove; any other is recorded in `failures`
124
+ * (path and reason) for the caller to report. SMI-6529 round 13
125
+ * (cross-model review): these were all swallowed, so a failed install could
126
+ * leave files behind without saying so.
127
+ */
128
+ export declare function cleanupStep(target: string, step: () => Promise<void>, ignore: readonly string[], failures: string[]): Promise<void>;
129
+ /**
130
+ * Recursively remove a directory this install created, but only while it is
131
+ * still that directory (same device and inode). If something else now sits
132
+ * at the path, it is left alone and recorded as a failure (round 13). Round
133
+ * 15: the entry is checked after it is parked under a random name
134
+ * (`removeIfSame`), so nothing can be swapped in between the check and the
135
+ * delete.
136
+ */
137
+ export declare function removeCreatedDirectory(dir: string, identity: EntryIdentity | undefined, failures: string[]): Promise<void>;
138
+ //# sourceMappingURL=skill-installation.io.rollback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.io.rollback.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.io.rollback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAE/E,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,yFAAyF;IACzF,SAAgB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzC;;;;OAIG;IACH,SAAgB,eAAe,EAAE,MAAM,EAAE,CAAA;gBAGvC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAC7B,eAAe,GAAE,MAAM,EAAO;CA+BjC;AAED,8EAA8E;AAC9E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE;AAC7C,2FAA2F;GACzF;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErB;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAWxF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmCnF;AAED,YAAY,EAAE,aAAa,EAAE,CAAA;AAE7B;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACzB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAgBf"}