sela-core 0.1.0-alpha.1

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 (267) hide show
  1. package/README.md +103 -0
  2. package/bin/sela.js +3 -0
  3. package/dist/cli/ErrorHandler.d.ts +10 -0
  4. package/dist/cli/ErrorHandler.d.ts.map +1 -0
  5. package/dist/cli/ErrorHandler.js +70 -0
  6. package/dist/cli/commands/bulk.d.ts +3 -0
  7. package/dist/cli/commands/bulk.d.ts.map +1 -0
  8. package/dist/cli/commands/bulk.js +158 -0
  9. package/dist/cli/commands/find.d.ts +3 -0
  10. package/dist/cli/commands/find.d.ts.map +1 -0
  11. package/dist/cli/commands/find.js +51 -0
  12. package/dist/cli/commands/init.d.ts +3 -0
  13. package/dist/cli/commands/init.d.ts.map +1 -0
  14. package/dist/cli/commands/init.js +166 -0
  15. package/dist/cli/commands/list.d.ts +3 -0
  16. package/dist/cli/commands/list.d.ts.map +1 -0
  17. package/dist/cli/commands/list.js +56 -0
  18. package/dist/cli/commands/merge.d.ts +13 -0
  19. package/dist/cli/commands/merge.d.ts.map +1 -0
  20. package/dist/cli/commands/merge.js +119 -0
  21. package/dist/cli/commands/refactor.d.ts +3 -0
  22. package/dist/cli/commands/refactor.d.ts.map +1 -0
  23. package/dist/cli/commands/refactor.js +30 -0
  24. package/dist/cli/commands/showReport.d.ts +3 -0
  25. package/dist/cli/commands/showReport.d.ts.map +1 -0
  26. package/dist/cli/commands/showReport.js +82 -0
  27. package/dist/cli/commands/status.d.ts +3 -0
  28. package/dist/cli/commands/status.d.ts.map +1 -0
  29. package/dist/cli/commands/status.js +51 -0
  30. package/dist/cli/commands/sync.d.ts +3 -0
  31. package/dist/cli/commands/sync.d.ts.map +1 -0
  32. package/dist/cli/commands/sync.js +131 -0
  33. package/dist/cli/index.d.ts +2 -0
  34. package/dist/cli/index.d.ts.map +1 -0
  35. package/dist/cli/index.js +94 -0
  36. package/dist/cli/ui/DnaTable.d.ts +3 -0
  37. package/dist/cli/ui/DnaTable.d.ts.map +1 -0
  38. package/dist/cli/ui/DnaTable.js +77 -0
  39. package/dist/cli/ui/LocatorPicker.d.ts +8 -0
  40. package/dist/cli/ui/LocatorPicker.d.ts.map +1 -0
  41. package/dist/cli/ui/LocatorPicker.js +33 -0
  42. package/dist/cli/ui/ProgressReporter.d.ts +11 -0
  43. package/dist/cli/ui/ProgressReporter.d.ts.map +1 -0
  44. package/dist/cli/ui/ProgressReporter.js +33 -0
  45. package/dist/cli/ui/RefactorWizard.d.ts +26 -0
  46. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -0
  47. package/dist/cli/ui/RefactorWizard.js +295 -0
  48. package/dist/config/ConfigLoader.d.ts +16 -0
  49. package/dist/config/ConfigLoader.d.ts.map +1 -0
  50. package/dist/config/ConfigLoader.js +185 -0
  51. package/dist/config/DryRunGuard.d.ts +14 -0
  52. package/dist/config/DryRunGuard.d.ts.map +1 -0
  53. package/dist/config/DryRunGuard.js +80 -0
  54. package/dist/config/PathScopeGuard.d.ts +42 -0
  55. package/dist/config/PathScopeGuard.d.ts.map +1 -0
  56. package/dist/config/PathScopeGuard.js +192 -0
  57. package/dist/config/SelaConfig.d.ts +178 -0
  58. package/dist/config/SelaConfig.d.ts.map +1 -0
  59. package/dist/config/SelaConfig.js +141 -0
  60. package/dist/config/defineConfig.d.ts +3 -0
  61. package/dist/config/defineConfig.d.ts.map +1 -0
  62. package/dist/config/defineConfig.js +9 -0
  63. package/dist/engine/FixwrightEngine.d.ts +24 -0
  64. package/dist/engine/FixwrightEngine.d.ts.map +1 -0
  65. package/dist/engine/FixwrightEngine.js +403 -0
  66. package/dist/engine/HealingRegistry.d.ts +40 -0
  67. package/dist/engine/HealingRegistry.d.ts.map +1 -0
  68. package/dist/engine/HealingRegistry.js +99 -0
  69. package/dist/engine/SelaEngine.d.ts +57 -0
  70. package/dist/engine/SelaEngine.d.ts.map +1 -0
  71. package/dist/engine/SelaEngine.js +1146 -0
  72. package/dist/engine/singleton.d.ts +3 -0
  73. package/dist/engine/singleton.d.ts.map +1 -0
  74. package/dist/engine/singleton.js +5 -0
  75. package/dist/errors/SelaError.d.ts +146 -0
  76. package/dist/errors/SelaError.d.ts.map +1 -0
  77. package/dist/errors/SelaError.js +168 -0
  78. package/dist/fixtures/expectProxy.d.ts +12 -0
  79. package/dist/fixtures/expectProxy.d.ts.map +1 -0
  80. package/dist/fixtures/expectProxy.js +246 -0
  81. package/dist/fixtures/index.d.ts +30 -0
  82. package/dist/fixtures/index.d.ts.map +1 -0
  83. package/dist/fixtures/index.js +765 -0
  84. package/dist/fixtures/moduleExpect.d.ts +2 -0
  85. package/dist/fixtures/moduleExpect.d.ts.map +1 -0
  86. package/dist/fixtures/moduleExpect.js +54 -0
  87. package/dist/fixtures/proxyTag.d.ts +12 -0
  88. package/dist/fixtures/proxyTag.d.ts.map +1 -0
  89. package/dist/fixtures/proxyTag.js +45 -0
  90. package/dist/index.d.ts +9 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +31 -0
  93. package/dist/reporter/SelaReporter.d.ts +165 -0
  94. package/dist/reporter/SelaReporter.d.ts.map +1 -0
  95. package/dist/reporter/SelaReporter.js +517 -0
  96. package/dist/services/ASTSourceUpdater.d.ts +143 -0
  97. package/dist/services/ASTSourceUpdater.d.ts.map +1 -0
  98. package/dist/services/ASTSourceUpdater.js +3514 -0
  99. package/dist/services/AnchorResolver.d.ts +157 -0
  100. package/dist/services/AnchorResolver.d.ts.map +1 -0
  101. package/dist/services/AnchorResolver.js +289 -0
  102. package/dist/services/ArgumentTypeAnalyzer.d.ts +26 -0
  103. package/dist/services/ArgumentTypeAnalyzer.d.ts.map +1 -0
  104. package/dist/services/ArgumentTypeAnalyzer.js +92 -0
  105. package/dist/services/BlastRadiusAnalyzer.d.ts +15 -0
  106. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -0
  107. package/dist/services/BlastRadiusAnalyzer.js +107 -0
  108. package/dist/services/ChainValidator.d.ts +76 -0
  109. package/dist/services/ChainValidator.d.ts.map +1 -0
  110. package/dist/services/ChainValidator.js +570 -0
  111. package/dist/services/CrossFileHealer.d.ts +6 -0
  112. package/dist/services/CrossFileHealer.d.ts.map +1 -0
  113. package/dist/services/CrossFileHealer.js +135 -0
  114. package/dist/services/DecisionEngine.d.ts +51 -0
  115. package/dist/services/DecisionEngine.d.ts.map +1 -0
  116. package/dist/services/DecisionEngine.js +260 -0
  117. package/dist/services/DefinitionTracer.d.ts +41 -0
  118. package/dist/services/DefinitionTracer.d.ts.map +1 -0
  119. package/dist/services/DefinitionTracer.js +366 -0
  120. package/dist/services/DnaEditorService.d.ts +31 -0
  121. package/dist/services/DnaEditorService.d.ts.map +1 -0
  122. package/dist/services/DnaEditorService.js +217 -0
  123. package/dist/services/DnaIndexService.d.ts +24 -0
  124. package/dist/services/DnaIndexService.d.ts.map +1 -0
  125. package/dist/services/DnaIndexService.js +131 -0
  126. package/dist/services/HealBudget.d.ts +32 -0
  127. package/dist/services/HealBudget.d.ts.map +1 -0
  128. package/dist/services/HealBudget.js +85 -0
  129. package/dist/services/HealReportService.d.ts +161 -0
  130. package/dist/services/HealReportService.d.ts.map +1 -0
  131. package/dist/services/HealReportService.js +1039 -0
  132. package/dist/services/HealingAdvisory.d.ts +30 -0
  133. package/dist/services/HealingAdvisory.d.ts.map +1 -0
  134. package/dist/services/HealingAdvisory.js +51 -0
  135. package/dist/services/HealingCacheService.d.ts +135 -0
  136. package/dist/services/HealingCacheService.d.ts.map +1 -0
  137. package/dist/services/HealingCacheService.js +404 -0
  138. package/dist/services/HealthReportService.d.ts +10 -0
  139. package/dist/services/HealthReportService.d.ts.map +1 -0
  140. package/dist/services/HealthReportService.js +84 -0
  141. package/dist/services/InitializerUpdater.d.ts +16 -0
  142. package/dist/services/InitializerUpdater.d.ts.map +1 -0
  143. package/dist/services/InitializerUpdater.js +73 -0
  144. package/dist/services/IntentAuditor.d.ts +56 -0
  145. package/dist/services/IntentAuditor.d.ts.map +1 -0
  146. package/dist/services/IntentAuditor.js +326 -0
  147. package/dist/services/InteractiveReview.d.ts +15 -0
  148. package/dist/services/InteractiveReview.d.ts.map +1 -0
  149. package/dist/services/InteractiveReview.js +128 -0
  150. package/dist/services/LLMService.d.ts +121 -0
  151. package/dist/services/LLMService.d.ts.map +1 -0
  152. package/dist/services/LLMService.js +475 -0
  153. package/dist/services/MutationApplier.d.ts +69 -0
  154. package/dist/services/MutationApplier.d.ts.map +1 -0
  155. package/dist/services/MutationApplier.js +360 -0
  156. package/dist/services/PRAutomationService.d.ts +50 -0
  157. package/dist/services/PRAutomationService.d.ts.map +1 -0
  158. package/dist/services/PRAutomationService.js +760 -0
  159. package/dist/services/PendingPromptLedger.d.ts +51 -0
  160. package/dist/services/PendingPromptLedger.d.ts.map +1 -0
  161. package/dist/services/PendingPromptLedger.js +205 -0
  162. package/dist/services/ReportGenerator.d.ts +156 -0
  163. package/dist/services/ReportGenerator.d.ts.map +1 -0
  164. package/dist/services/ReportGenerator.js +278 -0
  165. package/dist/services/ReportMergeService.d.ts +95 -0
  166. package/dist/services/ReportMergeService.d.ts.map +1 -0
  167. package/dist/services/ReportMergeService.js +0 -0
  168. package/dist/services/SafetyGuard.d.ts +112 -0
  169. package/dist/services/SafetyGuard.d.ts.map +1 -0
  170. package/dist/services/SafetyGuard.js +87 -0
  171. package/dist/services/Sanitizer.d.ts +28 -0
  172. package/dist/services/Sanitizer.d.ts.map +1 -0
  173. package/dist/services/Sanitizer.js +142 -0
  174. package/dist/services/SanitizingAnthropic.d.ts +19 -0
  175. package/dist/services/SanitizingAnthropic.d.ts.map +1 -0
  176. package/dist/services/SanitizingAnthropic.js +84 -0
  177. package/dist/services/SelectorSanitizer.d.ts +52 -0
  178. package/dist/services/SelectorSanitizer.d.ts.map +1 -0
  179. package/dist/services/SelectorSanitizer.js +318 -0
  180. package/dist/services/SnapshotService.d.ts +11 -0
  181. package/dist/services/SnapshotService.d.ts.map +1 -0
  182. package/dist/services/SnapshotService.js +352 -0
  183. package/dist/services/SourceLinkService.d.ts +26 -0
  184. package/dist/services/SourceLinkService.d.ts.map +1 -0
  185. package/dist/services/SourceLinkService.js +165 -0
  186. package/dist/services/SourceUpdater.d.ts +45 -0
  187. package/dist/services/SourceUpdater.d.ts.map +1 -0
  188. package/dist/services/SourceUpdater.js +1091 -0
  189. package/dist/services/TemplateDiffService.d.ts +25 -0
  190. package/dist/services/TemplateDiffService.d.ts.map +1 -0
  191. package/dist/services/TemplateDiffService.js +334 -0
  192. package/dist/services/TraceBackEngine.d.ts +67 -0
  193. package/dist/services/TraceBackEngine.d.ts.map +1 -0
  194. package/dist/services/TraceBackEngine.js +672 -0
  195. package/dist/services/WorkspaceSnapshotService.d.ts +71 -0
  196. package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -0
  197. package/dist/services/WorkspaceSnapshotService.js +200 -0
  198. package/dist/services/safety/PipelineContext.d.ts +63 -0
  199. package/dist/services/safety/PipelineContext.d.ts.map +1 -0
  200. package/dist/services/safety/PipelineContext.js +34 -0
  201. package/dist/services/safety/roleClassifier.d.ts +4 -0
  202. package/dist/services/safety/roleClassifier.d.ts.map +1 -0
  203. package/dist/services/safety/roleClassifier.js +233 -0
  204. package/dist/services/safety/rules/ConfidenceTierRule.d.ts +3 -0
  205. package/dist/services/safety/rules/ConfidenceTierRule.d.ts.map +1 -0
  206. package/dist/services/safety/rules/ConfidenceTierRule.js +32 -0
  207. package/dist/services/safety/rules/DangerousSinkRule.d.ts +10 -0
  208. package/dist/services/safety/rules/DangerousSinkRule.d.ts.map +1 -0
  209. package/dist/services/safety/rules/DangerousSinkRule.js +53 -0
  210. package/dist/services/safety/rules/FunctionalRoleRule.d.ts +3 -0
  211. package/dist/services/safety/rules/FunctionalRoleRule.d.ts.map +1 -0
  212. package/dist/services/safety/rules/FunctionalRoleRule.js +64 -0
  213. package/dist/services/safety/rules/HardConfidenceRule.d.ts +3 -0
  214. package/dist/services/safety/rules/HardConfidenceRule.d.ts.map +1 -0
  215. package/dist/services/safety/rules/HardConfidenceRule.js +22 -0
  216. package/dist/services/safety/rules/IntentAuditorRule.d.ts +3 -0
  217. package/dist/services/safety/rules/IntentAuditorRule.d.ts.map +1 -0
  218. package/dist/services/safety/rules/IntentAuditorRule.js +97 -0
  219. package/dist/services/safety/rules/SemanticOppositeRule.d.ts +3 -0
  220. package/dist/services/safety/rules/SemanticOppositeRule.d.ts.map +1 -0
  221. package/dist/services/safety/rules/SemanticOppositeRule.js +30 -0
  222. package/dist/services/safety/rules/StructuralOnlyRule.d.ts +3 -0
  223. package/dist/services/safety/rules/StructuralOnlyRule.d.ts.map +1 -0
  224. package/dist/services/safety/rules/StructuralOnlyRule.js +38 -0
  225. package/dist/services/safety/rules/VisibilityRule.d.ts +3 -0
  226. package/dist/services/safety/rules/VisibilityRule.d.ts.map +1 -0
  227. package/dist/services/safety/rules/VisibilityRule.js +53 -0
  228. package/dist/services/safety/rules/ZeroTrustRule.d.ts +3 -0
  229. package/dist/services/safety/rules/ZeroTrustRule.d.ts.map +1 -0
  230. package/dist/services/safety/rules/ZeroTrustRule.js +37 -0
  231. package/dist/services/safety/rules/index.d.ts +3 -0
  232. package/dist/services/safety/rules/index.d.ts.map +1 -0
  233. package/dist/services/safety/rules/index.js +34 -0
  234. package/dist/services/types.d.ts +59 -0
  235. package/dist/services/types.d.ts.map +1 -0
  236. package/dist/services/types.js +2 -0
  237. package/dist/storage/SnapshotManager.d.ts +5 -0
  238. package/dist/storage/SnapshotManager.d.ts.map +1 -0
  239. package/dist/storage/SnapshotManager.js +32 -0
  240. package/dist/types/index.d.ts +95 -0
  241. package/dist/types/index.d.ts.map +1 -0
  242. package/dist/types/index.js +7 -0
  243. package/dist/utils/DOMUtils.d.ts +49 -0
  244. package/dist/utils/DOMUtils.d.ts.map +1 -0
  245. package/dist/utils/DOMUtils.js +466 -0
  246. package/dist/utils/FileLock.d.ts +44 -0
  247. package/dist/utils/FileLock.d.ts.map +1 -0
  248. package/dist/utils/FileLock.js +189 -0
  249. package/dist/utils/IsolatedDiff.d.ts +45 -0
  250. package/dist/utils/IsolatedDiff.d.ts.map +1 -0
  251. package/dist/utils/IsolatedDiff.js +382 -0
  252. package/dist/utils/StackUtils.d.ts +11 -0
  253. package/dist/utils/StackUtils.d.ts.map +1 -0
  254. package/dist/utils/StackUtils.js +120 -0
  255. package/dist/utils/SummaryTable.d.ts +17 -0
  256. package/dist/utils/SummaryTable.d.ts.map +1 -0
  257. package/dist/utils/SummaryTable.js +37 -0
  258. package/dist/utils/atomicWrite.d.ts +9 -0
  259. package/dist/utils/atomicWrite.d.ts.map +1 -0
  260. package/dist/utils/atomicWrite.js +83 -0
  261. package/dist/utils/logger.d.ts +59 -0
  262. package/dist/utils/logger.d.ts.map +1 -0
  263. package/dist/utils/logger.js +123 -0
  264. package/dist/vendor/enquirer.d.ts +33 -0
  265. package/dist/vendor/enquirer.d.ts.map +1 -0
  266. package/dist/vendor/enquirer.js +11 -0
  267. package/package.json +71 -0
@@ -0,0 +1,71 @@
1
+ export interface FileSnapshot {
2
+ /** Absolute, normalised path of the tracked file. */
3
+ absolutePath: string;
4
+ /** Project-relative path (posix slashes) - for diff headers + PR commits. */
5
+ relativePath: string;
6
+ /**
7
+ * Disk content captured BEFORE Sela's first write to this file.
8
+ * May contain the developer's uncommitted edits - that's the point.
9
+ */
10
+ contentBefore: string;
11
+ /** Disk content captured AFTER Sela's latest write. `null` until first postWrite(). */
12
+ contentAfter: string | null;
13
+ /** Content of the file at `HEAD` (last committed) - `null` when untracked / no git. */
14
+ headContent: string | null;
15
+ /** True when `contentBefore !== headContent`, i.e. developer had dirty edits. */
16
+ hadUncommittedChanges: boolean;
17
+ /** True when the file did not exist on disk before Sela touched it. */
18
+ createdBySela: boolean;
19
+ }
20
+ export declare class WorkspaceSnapshotService {
21
+ private snapshots;
22
+ private cwd;
23
+ constructor(cwd?: string);
24
+ /** Override the cwd used for relative-path + HEAD lookups (tests). */
25
+ setCwd(cwd: string): void;
26
+ /**
27
+ * Record the pre-mutation state of `filePath` if not already tracked.
28
+ * Idempotent - only the FIRST call per file matters.
29
+ */
30
+ preWrite(filePath: string): void;
31
+ /**
32
+ * Refresh the post-mutation state. Safe to call multiple times - each
33
+ * call overwrites `contentAfter` with the latest disk state.
34
+ */
35
+ postWrite(filePath: string): void;
36
+ /** Lookup by absolute or relative path. Returns `null` when untracked. */
37
+ getSnapshot(filePath: string): FileSnapshot | null;
38
+ /** Every tracked snapshot. Insertion order. */
39
+ getAllSnapshots(): FileSnapshot[];
40
+ /**
41
+ * Did Sela actually mutate this file? True when contentAfter exists and
42
+ * differs from contentBefore.
43
+ */
44
+ isMutated(filePath: string): boolean;
45
+ /** All snapshots with a real mutation recorded. */
46
+ getMutatedSnapshots(): FileSnapshot[];
47
+ /**
48
+ * Rewind every tracked file on disk to `contentBefore` - restoring the
49
+ * developer's pre-Sela workspace state byte-for-byte.
50
+ */
51
+ restoreOriginal(): void;
52
+ /**
53
+ * Rewind a SINGLE tracked file on disk to `contentBefore`. Used by the
54
+ * Local DX interactive review flow when the developer rejects a fix.
55
+ * Returns true when the rewind happened, false when the file is untracked.
56
+ */
57
+ restoreOriginalByPath(filePath: string): boolean;
58
+ private rewindSnapshot;
59
+ /**
60
+ * Forward every tracked file on disk to `contentAfter` (no-op for files
61
+ * that were never written). Used by PRAutomationService to reapply
62
+ * Sela's mutations after a `git stash pop` round-trip.
63
+ */
64
+ restoreMutated(): void;
65
+ clear(): void;
66
+ private normalise;
67
+ private toRelative;
68
+ private readHeadContent;
69
+ }
70
+ export declare const sharedWorkspaceSnapshot: WorkspaceSnapshotService;
71
+ //# sourceMappingURL=WorkspaceSnapshotService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceSnapshotService.d.ts","sourceRoot":"","sources":["../../src/services/WorkspaceSnapshotService.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uFAAuF;IACvF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iFAAiF;IACjF,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uEAAuE;IACvE,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,qBAAa,wBAAwB;IACnC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,GAAG,CAAS;gBAER,GAAG,GAAE,MAAsB;IAIvC,sEAAsE;IACtE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAqBhC;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOjC,0EAA0E;IAC1E,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAIlD,+CAA+C;IAC/C,eAAe,IAAI,YAAY,EAAE;IAIjC;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAMpC,mDAAmD;IACnD,mBAAmB,IAAI,YAAY,EAAE;IAMrC;;;OAGG;IACH,eAAe,IAAI,IAAI;IAMvB;;;;OAIG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAOhD,OAAO,CAAC,cAAc;IAUtB;;;;OAIG;IACH,cAAc,IAAI,IAAI;IAOtB,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,eAAe;CAcxB;AAED,eAAO,MAAM,uBAAuB,0BAAiC,CAAC"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ // src/services/WorkspaceSnapshotService.ts
3
+ //
4
+ // Clean-Room Architecture - file 1 of 2.
5
+ //
6
+ // Tracks the EXACT content of every file Sela mutates during a session, so:
7
+ // • The HTML report diff can be generated from an isolated in-memory diff
8
+ // (developer's dirty pre-existing edits NEVER bleed in).
9
+ // • PRAutomationService can restore the developer's pre-Sela workspace
10
+ // byte-for-byte after a PR is opened on an isolated branch.
11
+ //
12
+ // Lifecycle:
13
+ // preWrite(path) - first call per file records `contentBefore` (disk
14
+ // snapshot right before Sela touches it) + HEAD blob.
15
+ // postWrite(path) - refreshes `contentAfter` (latest disk state).
16
+ // restoreOriginal()- writes contentBefore back to every tracked file.
17
+ // restoreMutated() - writes contentAfter back to every tracked file.
18
+ // clear() - empties the ledger.
19
+ //
20
+ // Singleton `sharedWorkspaceSnapshot` is the canonical instance the
21
+ // SourceUpdater / ASTSourceUpdater write hooks talk to.
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
35
+ }) : function(o, v) {
36
+ o["default"] = v;
37
+ });
38
+ var __importStar = (this && this.__importStar) || (function () {
39
+ var ownKeys = function(o) {
40
+ ownKeys = Object.getOwnPropertyNames || function (o) {
41
+ var ar = [];
42
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
43
+ return ar;
44
+ };
45
+ return ownKeys(o);
46
+ };
47
+ return function (mod) {
48
+ if (mod && mod.__esModule) return mod;
49
+ var result = {};
50
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
51
+ __setModuleDefault(result, mod);
52
+ return result;
53
+ };
54
+ })();
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ exports.sharedWorkspaceSnapshot = exports.WorkspaceSnapshotService = void 0;
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const child_process_1 = require("child_process");
60
+ class WorkspaceSnapshotService {
61
+ snapshots = new Map();
62
+ cwd;
63
+ constructor(cwd = process.cwd()) {
64
+ this.cwd = cwd;
65
+ }
66
+ /** Override the cwd used for relative-path + HEAD lookups (tests). */
67
+ setCwd(cwd) {
68
+ this.cwd = cwd;
69
+ }
70
+ /**
71
+ * Record the pre-mutation state of `filePath` if not already tracked.
72
+ * Idempotent - only the FIRST call per file matters.
73
+ */
74
+ preWrite(filePath) {
75
+ const abs = this.normalise(filePath);
76
+ if (this.snapshots.has(abs))
77
+ return;
78
+ const exists = fs.existsSync(abs);
79
+ const contentBefore = exists ? fs.readFileSync(abs, "utf8") : "";
80
+ const headContent = this.readHeadContent(abs);
81
+ const hadUncommittedChanges = headContent !== null && headContent !== contentBefore;
82
+ this.snapshots.set(abs, {
83
+ absolutePath: abs,
84
+ relativePath: this.toRelative(abs),
85
+ contentBefore,
86
+ contentAfter: null,
87
+ headContent,
88
+ hadUncommittedChanges,
89
+ createdBySela: !exists,
90
+ });
91
+ }
92
+ /**
93
+ * Refresh the post-mutation state. Safe to call multiple times - each
94
+ * call overwrites `contentAfter` with the latest disk state.
95
+ */
96
+ postWrite(filePath) {
97
+ const abs = this.normalise(filePath);
98
+ const snap = this.snapshots.get(abs);
99
+ if (!snap)
100
+ return;
101
+ snap.contentAfter = fs.existsSync(abs) ? fs.readFileSync(abs, "utf8") : "";
102
+ }
103
+ /** Lookup by absolute or relative path. Returns `null` when untracked. */
104
+ getSnapshot(filePath) {
105
+ return this.snapshots.get(this.normalise(filePath)) ?? null;
106
+ }
107
+ /** Every tracked snapshot. Insertion order. */
108
+ getAllSnapshots() {
109
+ return Array.from(this.snapshots.values());
110
+ }
111
+ /**
112
+ * Did Sela actually mutate this file? True when contentAfter exists and
113
+ * differs from contentBefore.
114
+ */
115
+ isMutated(filePath) {
116
+ const snap = this.getSnapshot(filePath);
117
+ if (!snap || snap.contentAfter === null)
118
+ return false;
119
+ return snap.contentAfter !== snap.contentBefore;
120
+ }
121
+ /** All snapshots with a real mutation recorded. */
122
+ getMutatedSnapshots() {
123
+ return this.getAllSnapshots().filter((s) => s.contentAfter !== null && s.contentAfter !== s.contentBefore);
124
+ }
125
+ /**
126
+ * Rewind every tracked file on disk to `contentBefore` - restoring the
127
+ * developer's pre-Sela workspace state byte-for-byte.
128
+ */
129
+ restoreOriginal() {
130
+ for (const snap of this.snapshots.values()) {
131
+ this.rewindSnapshot(snap);
132
+ }
133
+ }
134
+ /**
135
+ * Rewind a SINGLE tracked file on disk to `contentBefore`. Used by the
136
+ * Local DX interactive review flow when the developer rejects a fix.
137
+ * Returns true when the rewind happened, false when the file is untracked.
138
+ */
139
+ restoreOriginalByPath(filePath) {
140
+ const snap = this.getSnapshot(filePath);
141
+ if (!snap)
142
+ return false;
143
+ this.rewindSnapshot(snap);
144
+ return true;
145
+ }
146
+ rewindSnapshot(snap) {
147
+ if (snap.createdBySela) {
148
+ if (fs.existsSync(snap.absolutePath)) {
149
+ fs.unlinkSync(snap.absolutePath);
150
+ }
151
+ return;
152
+ }
153
+ fs.writeFileSync(snap.absolutePath, snap.contentBefore, "utf8");
154
+ }
155
+ /**
156
+ * Forward every tracked file on disk to `contentAfter` (no-op for files
157
+ * that were never written). Used by PRAutomationService to reapply
158
+ * Sela's mutations after a `git stash pop` round-trip.
159
+ */
160
+ restoreMutated() {
161
+ for (const snap of this.snapshots.values()) {
162
+ if (snap.contentAfter === null)
163
+ continue;
164
+ fs.writeFileSync(snap.absolutePath, snap.contentAfter, "utf8");
165
+ }
166
+ }
167
+ clear() {
168
+ this.snapshots.clear();
169
+ }
170
+ // ────────────────────────────────────────────────────────────────
171
+ // INTERNAL
172
+ // ────────────────────────────────────────────────────────────────
173
+ normalise(raw) {
174
+ if (!raw)
175
+ return raw;
176
+ const abs = path.isAbsolute(raw) ? raw : path.resolve(this.cwd, raw);
177
+ return path.normalize(abs);
178
+ }
179
+ toRelative(abs) {
180
+ const rel = path.relative(this.cwd, abs);
181
+ return rel.split(path.sep).join("/");
182
+ }
183
+ readHeadContent(abs) {
184
+ try {
185
+ const rel = this.toRelative(abs);
186
+ const out = (0, child_process_1.execSync)(`git show HEAD:"${rel}"`, {
187
+ cwd: this.cwd,
188
+ encoding: "utf8",
189
+ stdio: ["pipe", "pipe", "pipe"],
190
+ windowsHide: true,
191
+ });
192
+ return out.toString();
193
+ }
194
+ catch {
195
+ return null;
196
+ }
197
+ }
198
+ }
199
+ exports.WorkspaceSnapshotService = WorkspaceSnapshotService;
200
+ exports.sharedWorkspaceSnapshot = new WorkspaceSnapshotService();
@@ -0,0 +1,63 @@
1
+ import type { IntentAuditor } from "../IntentAuditor";
2
+ import type { ResolvedThresholds } from "../../config/SelaConfig";
3
+ import type { AIFixSummary, HealMode, SafetyDecision } from "../SafetyGuard";
4
+ import type { FunctionalRole } from "./roleClassifier";
5
+ /**
6
+ * Mutable bag of state shared across the rule pipeline for a single
7
+ * evaluate() call. Immutable inputs are readonly; fields derived
8
+ * mid-pipeline by context-mutator rules are writable.
9
+ */
10
+ export interface PipelineContext {
11
+ readonly aiFix: AIFixSummary;
12
+ readonly mode: HealMode;
13
+ readonly branch?: string;
14
+ /**
15
+ * AI confidence coerced to a finite number. Missing / NaN / Infinity
16
+ * collapses to 0 so the hard-stop and review-threshold rules still gate
17
+ * the heal (conservative worst case).
18
+ */
19
+ readonly confidence: number;
20
+ readonly thresholds: ResolvedThresholds;
21
+ readonly auditor: IntentAuditor;
22
+ /**
23
+ * The content change the pipeline actually reasons about: the
24
+ * AI-reported pair when present, otherwise a zero-trust synthesized
25
+ * pair from live vs DNA text. Undefined ⇒ structural-only heal.
26
+ */
27
+ effectiveContentChange?: {
28
+ oldText: string;
29
+ newText: string;
30
+ };
31
+ /** Provenance of effectiveContentChange for logging + auditor gating. */
32
+ source?: "AI-reported" | "zero-trust";
33
+ oldText?: string;
34
+ newText?: string;
35
+ oldRole?: FunctionalRole;
36
+ newRole?: FunctionalRole;
37
+ /**
38
+ * Set by DangerousSinkRule when the heal transitions INTO a destructive /
39
+ * auth role. Forces the Intent Auditor gate to fire regardless of source
40
+ * or mode (decision #2), closing the UNKNOWN→DELETE blind spot.
41
+ */
42
+ forceAudit?: boolean;
43
+ /** Auditor score breakdown forwarded to the final confidence-tier decision. */
44
+ localAuditMeta?: SafetyDecision["meta"];
45
+ }
46
+ /** A rule returns a decision to short-circuit, or null to continue. */
47
+ export type SafetyRuleResult = SafetyDecision | null;
48
+ export interface SafetyRule {
49
+ /** Stable identifier for logging / debugging. */
50
+ readonly id: string;
51
+ run(ctx: PipelineContext): SafetyRuleResult | Promise<SafetyRuleResult>;
52
+ }
53
+ /**
54
+ * Builds the initial pipeline context. Mirrors the head of the
55
+ * pre-refactor evaluate() exactly (confidence coercion + input
56
+ * passthrough). Derived fields are populated later by the rules.
57
+ */
58
+ export declare function buildContext(context: {
59
+ mode: HealMode;
60
+ action?: string;
61
+ branch?: string;
62
+ }, aiFix: AIFixSummary, thresholds: ResolvedThresholds, auditor: IntentAuditor): PipelineContext;
63
+ //# sourceMappingURL=PipelineContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineContext.d.ts","sourceRoot":"","sources":["../../../src/services/safety/PipelineContext.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,EACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAE9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAGhC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,yEAAyE;IACzE,MAAM,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CACzC;AAED,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,IAAI,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7D,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,aAAa,GACrB,eAAe,CAcjB"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ // src/services/safety/PipelineContext.ts
3
+ //
4
+ // Shared state threaded through the SafetyGuard rule pipeline, plus the
5
+ // SafetyRule contract every rule implements.
6
+ //
7
+ // Phase 1 refactor: the monolithic SafetyGuard.evaluate() became an
8
+ // ordered array of rules (chain-of-responsibility). A rule returns a
9
+ // SafetyDecision to short-circuit the pipeline, or null to fall through
10
+ // to the next rule. Some rules are pure deciders; a few are
11
+ // *context-mutators* that derive shared fields (effectiveContentChange,
12
+ // roles) and always return null so later rules can consume them without
13
+ // re-deriving. This keeps the exact priority order and the exact
14
+ // derived values of the pre-refactor implementation.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.buildContext = buildContext;
17
+ /**
18
+ * Builds the initial pipeline context. Mirrors the head of the
19
+ * pre-refactor evaluate() exactly (confidence coercion + input
20
+ * passthrough). Derived fields are populated later by the rules.
21
+ */
22
+ function buildContext(context, aiFix, thresholds, auditor) {
23
+ const confidence = typeof aiFix.confidence === "number" && Number.isFinite(aiFix.confidence)
24
+ ? aiFix.confidence
25
+ : 0;
26
+ return {
27
+ aiFix,
28
+ mode: context.mode,
29
+ branch: context.branch,
30
+ confidence,
31
+ thresholds,
32
+ auditor,
33
+ };
34
+ }
@@ -0,0 +1,4 @@
1
+ export type FunctionalRole = "SUBMIT" | "CANCEL" | "DELETE" | "NAVIGATE" | "AUTH" | "STATUS_POSITIVE" | "STATUS_NEGATIVE" | "UNKNOWN";
2
+ export declare function classifyFunctionalRole(text: string): FunctionalRole;
3
+ export declare function isSemanticOpposite(oldText: string, newText: string): boolean;
4
+ //# sourceMappingURL=roleClassifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roleClassifier.d.ts","sourceRoot":"","sources":["../../../src/services/safety/roleClassifier.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,MAAM,GACN,iBAAiB,GACjB,iBAAiB,GACjB,SAAS,CAAC;AA4Kd,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CASnE;AAgDD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG5E"}
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ // src/services/safety/roleClassifier.ts
3
+ //
4
+ // Pure functional-role classification + binary semantic-opposite lookup.
5
+ //
6
+ // Extracted verbatim from SafetyGuard.ts during the Phase 1 pipeline
7
+ // refactor. Behavior is byte-for-byte identical to the pre-refactor
8
+ // implementation - the role taxonomy, keyword sets, word-boundary regex
9
+ // compilation, and the 36-entry opposite-pair set are unchanged. Keeping
10
+ // this module dependency-free (no SafetyGuard import) avoids a runtime
11
+ // import cycle: SafetyGuard and the rule modules consume it, never the
12
+ // reverse.
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.classifyFunctionalRole = classifyFunctionalRole;
15
+ exports.isSemanticOpposite = isSemanticOpposite;
16
+ function escapeRegExp(s) {
17
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18
+ }
19
+ const ROLE_KEYWORDS = new Map([
20
+ [
21
+ "SUBMIT",
22
+ new Set([
23
+ "submit",
24
+ "send",
25
+ "confirm",
26
+ "save",
27
+ "ok",
28
+ "done",
29
+ "apply",
30
+ "proceed",
31
+ "continue",
32
+ "execute",
33
+ "finish",
34
+ "complete",
35
+ "publish",
36
+ "post",
37
+ ]),
38
+ ],
39
+ [
40
+ "CANCEL",
41
+ new Set([
42
+ "cancel",
43
+ "abort",
44
+ "dismiss",
45
+ "close",
46
+ "back",
47
+ "exit",
48
+ "skip",
49
+ "no",
50
+ "discard",
51
+ "reject",
52
+ "decline",
53
+ ]),
54
+ ],
55
+ [
56
+ "DELETE",
57
+ new Set([
58
+ "delete",
59
+ "remove",
60
+ "clear",
61
+ "erase",
62
+ "destroy",
63
+ "trash",
64
+ "purge",
65
+ "drop",
66
+ "wipe",
67
+ ]),
68
+ ],
69
+ [
70
+ "NAVIGATE",
71
+ new Set([
72
+ "next",
73
+ "previous",
74
+ "prev",
75
+ "forward",
76
+ "backward",
77
+ "go",
78
+ "navigate",
79
+ "open",
80
+ "view",
81
+ "home",
82
+ "return",
83
+ "redirect",
84
+ ]),
85
+ ],
86
+ [
87
+ "AUTH",
88
+ new Set([
89
+ "login",
90
+ "logout",
91
+ "sign in",
92
+ "sign out",
93
+ "register",
94
+ "sign up",
95
+ "log in",
96
+ "log out",
97
+ "authenticate",
98
+ "authorize",
99
+ ]),
100
+ ],
101
+ [
102
+ "STATUS_POSITIVE",
103
+ new Set([
104
+ "success",
105
+ "approved",
106
+ "active",
107
+ "enabled",
108
+ "visible",
109
+ "on",
110
+ "open",
111
+ "allowed",
112
+ "welcome",
113
+ "pass",
114
+ "passed",
115
+ "valid",
116
+ "granted",
117
+ "connected",
118
+ "running",
119
+ "unlocked",
120
+ "online",
121
+ "available",
122
+ ]),
123
+ ],
124
+ [
125
+ "STATUS_NEGATIVE",
126
+ new Set([
127
+ "error",
128
+ "failure",
129
+ "failed",
130
+ "denied",
131
+ "inactive",
132
+ "disabled",
133
+ "hidden",
134
+ "off",
135
+ "closed",
136
+ "blocked",
137
+ "rejected",
138
+ "invalid",
139
+ "locked",
140
+ "disconnected",
141
+ "stopped",
142
+ "offline",
143
+ "unavailable",
144
+ "forbidden",
145
+ "unauthorized",
146
+ ]),
147
+ ],
148
+ ]);
149
+ // Pre-compiled word-boundary regexes for the role classifier. Built
150
+ // once at module load - classifyFunctionalRole() is on the hot heal
151
+ // path, so we don't pay for regex construction per call.
152
+ const ROLE_KEYWORD_REGEXES = Array.from(ROLE_KEYWORDS, ([role, keywords]) => ({
153
+ role,
154
+ regexes: Array.from(keywords, (kw) => new RegExp(`\\b${escapeRegExp(kw)}\\b`, "i")),
155
+ }));
156
+ // ─────────────────────────────────────────────────────────────
157
+ // FUNCTIONAL ROLE CLASSIFICATION
158
+ //
159
+ // Returns the first role whose keyword matches the text as a whole
160
+ // word (delimited by \b boundaries). Returns UNKNOWN when no role
161
+ // matches.
162
+ //
163
+ // Why \b instead of `.includes(kw)`:
164
+ // - "unauthorized".includes("authorize") → true ← bug
165
+ // - "offline".includes("on") → true ← bug
166
+ // - "disconnected".includes("connected") → true ← bug
167
+ // - "inactive".includes("active") → true ← bug
168
+ // The substring approach mis-classified negations into the
169
+ // positive role of their root word, silently bypassing
170
+ // FAIL_HARD_STATUS_INVERSION. Word-boundary regex eliminates
171
+ // these collisions while keeping multi-word keywords ("sign in")
172
+ // and punctuation-flanked matches ("Submit!") working.
173
+ // ─────────────────────────────────────────────────────────────
174
+ function classifyFunctionalRole(text) {
175
+ const normalized = text.toLowerCase().trim();
176
+ if (normalized.length === 0)
177
+ return "UNKNOWN";
178
+ for (const { role, regexes } of ROLE_KEYWORD_REGEXES) {
179
+ for (const re of regexes) {
180
+ if (re.test(normalized))
181
+ return role;
182
+ }
183
+ }
184
+ return "UNKNOWN";
185
+ }
186
+ // ═══════════════════════════════════════════════════════════════════
187
+ // BINARY SEMANTIC OPPOSITES
188
+ // ═══════════════════════════════════════════════════════════════════
189
+ // Binary semantic opposites - always trigger FAIL_HARD regardless of mode,
190
+ // because they indicate a state inversion (pass→fail, success→error, etc.)
191
+ // that almost certainly masks a real logical regression.
192
+ const SEMANTIC_OPPOSITE_PAIRS = new Set([
193
+ "denied|welcome",
194
+ "welcome|denied",
195
+ "login|logout",
196
+ "logout|login",
197
+ "success|failure",
198
+ "failure|success",
199
+ "success|error",
200
+ "error|success",
201
+ "pass|fail",
202
+ "fail|pass",
203
+ "approved|rejected",
204
+ "rejected|approved",
205
+ "active|inactive",
206
+ "inactive|active",
207
+ "enabled|disabled",
208
+ "disabled|enabled",
209
+ "open|closed",
210
+ "closed|open",
211
+ "visible|hidden",
212
+ "hidden|visible",
213
+ "on|off",
214
+ "off|on",
215
+ "true|false",
216
+ "false|true",
217
+ "allowed|denied",
218
+ "denied|allowed",
219
+ "granted|denied",
220
+ "denied|granted",
221
+ "locked|unlocked",
222
+ "unlocked|locked",
223
+ "connected|disconnected",
224
+ "disconnected|connected",
225
+ "running|stopped",
226
+ "stopped|running",
227
+ "valid|invalid",
228
+ "invalid|valid",
229
+ ]);
230
+ function isSemanticOpposite(oldText, newText) {
231
+ const key = `${oldText.toLowerCase().trim()}|${newText.toLowerCase().trim()}`;
232
+ return SEMANTIC_OPPOSITE_PAIRS.has(key);
233
+ }
@@ -0,0 +1,3 @@
1
+ import type { SafetyRule } from "../PipelineContext";
2
+ export declare const ConfidenceTierRule: SafetyRule;
3
+ //# sourceMappingURL=ConfidenceTierRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfidenceTierRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/ConfidenceTierRule.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF,eAAO,MAAM,kBAAkB,EAAE,UAqBhC,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ // src/services/safety/rules/ConfidenceTierRule.ts
3
+ //
4
+ // Step 8 - Confidence tiers (terminal rule). All inversion checks have
5
+ // passed; the only remaining question is whether confidence clears the
6
+ // review threshold. Below it → REQUIRES_REVIEW, at/above → SAFE. This
7
+ // rule always returns a decision, so the pipeline never falls past it.
8
+ //
9
+ // Extracted verbatim - identical reasons and the auditor score-breakdown
10
+ // meta forwarded from the IntentAuditor gate.
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ConfidenceTierRule = void 0;
13
+ exports.ConfidenceTierRule = {
14
+ id: "confidence-tiers",
15
+ run(ctx) {
16
+ if (ctx.confidence < ctx.thresholds.confidenceReviewThreshold) {
17
+ return {
18
+ level: "REQUIRES_REVIEW",
19
+ reason: `Low-confidence fix (${ctx.confidence}/100) - tagging for manual review`,
20
+ canProceed: true,
21
+ meta: ctx.localAuditMeta,
22
+ };
23
+ }
24
+ return {
25
+ level: "SAFE",
26
+ reason: `All safety checks passed (confidence=${ctx.confidence}, source=${ctx.source}, ` +
27
+ `oldRole=${ctx.oldRole}, newRole=${ctx.newRole})`,
28
+ canProceed: true,
29
+ meta: ctx.localAuditMeta,
30
+ };
31
+ },
32
+ };
@@ -0,0 +1,10 @@
1
+ import type { FunctionalRole } from "../roleClassifier";
2
+ import type { SafetyRule } from "../PipelineContext";
3
+ /**
4
+ * Roles whose ARRIVAL is treated as high-risk: a control that did not
5
+ * obviously mean "delete" or "authenticate" before, but now does.
6
+ */
7
+ export declare const DANGEROUS_SINK_ROLES: ReadonlySet<FunctionalRole>;
8
+ export declare function isDangerousSinkTransition(oldRole: FunctionalRole, newRole: FunctionalRole): boolean;
9
+ export declare const DangerousSinkRule: SafetyRule;
10
+ //# sourceMappingURL=DangerousSinkRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DangerousSinkRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/DangerousSinkRule.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAG3D,CAAC;AAEH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,GACtB,OAAO,CAET;AAED,eAAO,MAAM,iBAAiB,EAAE,UAmB/B,CAAC"}