@jamesaphoenix/tx-core 0.4.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 (289) hide show
  1. package/dist/db.d.ts +42 -0
  2. package/dist/db.d.ts.map +1 -0
  3. package/dist/db.js +46 -0
  4. package/dist/db.js.map +1 -0
  5. package/dist/errors.d.ts +231 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +139 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/id.d.ts +6 -0
  10. package/dist/id.d.ts.map +1 -0
  11. package/dist/id.js +21 -0
  12. package/dist/id.js.map +1 -0
  13. package/dist/index.d.ts +25 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +56 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/layer.d.ts +50 -0
  18. package/dist/layer.d.ts.map +1 -0
  19. package/dist/layer.js +155 -0
  20. package/dist/layer.js.map +1 -0
  21. package/dist/mappers/anchor.d.ts +14 -0
  22. package/dist/mappers/anchor.d.ts.map +1 -0
  23. package/dist/mappers/anchor.js +38 -0
  24. package/dist/mappers/anchor.js.map +1 -0
  25. package/dist/mappers/attempt.d.ts +15 -0
  26. package/dist/mappers/attempt.d.ts.map +1 -0
  27. package/dist/mappers/attempt.js +23 -0
  28. package/dist/mappers/attempt.js.map +1 -0
  29. package/dist/mappers/candidate.d.ts +23 -0
  30. package/dist/mappers/candidate.d.ts.map +1 -0
  31. package/dist/mappers/candidate.js +53 -0
  32. package/dist/mappers/candidate.js.map +1 -0
  33. package/dist/mappers/claim.d.ts +30 -0
  34. package/dist/mappers/claim.d.ts.map +1 -0
  35. package/dist/mappers/claim.js +32 -0
  36. package/dist/mappers/claim.js.map +1 -0
  37. package/dist/mappers/deduplication.d.ts +39 -0
  38. package/dist/mappers/deduplication.d.ts.map +1 -0
  39. package/dist/mappers/deduplication.js +53 -0
  40. package/dist/mappers/deduplication.js.map +1 -0
  41. package/dist/mappers/edge.d.ts +10 -0
  42. package/dist/mappers/edge.d.ts.map +1 -0
  43. package/dist/mappers/edge.js +19 -0
  44. package/dist/mappers/edge.js.map +1 -0
  45. package/dist/mappers/file-learning.d.ts +14 -0
  46. package/dist/mappers/file-learning.d.ts.map +1 -0
  47. package/dist/mappers/file-learning.js +75 -0
  48. package/dist/mappers/file-learning.js.map +1 -0
  49. package/dist/mappers/index.d.ts +17 -0
  50. package/dist/mappers/index.d.ts.map +1 -0
  51. package/dist/mappers/index.js +30 -0
  52. package/dist/mappers/index.js.map +1 -0
  53. package/dist/mappers/learning.d.ts +19 -0
  54. package/dist/mappers/learning.d.ts.map +1 -0
  55. package/dist/mappers/learning.js +41 -0
  56. package/dist/mappers/learning.js.map +1 -0
  57. package/dist/mappers/orchestrator-state.d.ts +33 -0
  58. package/dist/mappers/orchestrator-state.d.ts.map +1 -0
  59. package/dist/mappers/orchestrator-state.js +34 -0
  60. package/dist/mappers/orchestrator-state.js.map +1 -0
  61. package/dist/mappers/run.d.ts +32 -0
  62. package/dist/mappers/run.d.ts.map +1 -0
  63. package/dist/mappers/run.js +64 -0
  64. package/dist/mappers/run.js.map +1 -0
  65. package/dist/mappers/task.d.ts +23 -0
  66. package/dist/mappers/task.d.ts.map +1 -0
  67. package/dist/mappers/task.js +54 -0
  68. package/dist/mappers/task.js.map +1 -0
  69. package/dist/mappers/tracked-project.d.ts +15 -0
  70. package/dist/mappers/tracked-project.d.ts.map +1 -0
  71. package/dist/mappers/tracked-project.js +23 -0
  72. package/dist/mappers/tracked-project.js.map +1 -0
  73. package/dist/mappers/worker.d.ts +33 -0
  74. package/dist/mappers/worker.d.ts.map +1 -0
  75. package/dist/mappers/worker.js +35 -0
  76. package/dist/mappers/worker.js.map +1 -0
  77. package/dist/repo/anchor-repo.d.ts +52 -0
  78. package/dist/repo/anchor-repo.d.ts.map +1 -0
  79. package/dist/repo/anchor-repo.js +204 -0
  80. package/dist/repo/anchor-repo.js.map +1 -0
  81. package/dist/repo/attempt-repo.d.ts +25 -0
  82. package/dist/repo/attempt-repo.d.ts.map +1 -0
  83. package/dist/repo/attempt-repo.js +78 -0
  84. package/dist/repo/attempt-repo.js.map +1 -0
  85. package/dist/repo/candidate-repo.d.ts +16 -0
  86. package/dist/repo/candidate-repo.d.ts.map +1 -0
  87. package/dist/repo/candidate-repo.js +143 -0
  88. package/dist/repo/candidate-repo.js.map +1 -0
  89. package/dist/repo/claim-repo.d.ts +17 -0
  90. package/dist/repo/claim-repo.d.ts.map +1 -0
  91. package/dist/repo/claim-repo.js +62 -0
  92. package/dist/repo/claim-repo.js.map +1 -0
  93. package/dist/repo/deduplication-repo.d.ts +37 -0
  94. package/dist/repo/deduplication-repo.d.ts.map +1 -0
  95. package/dist/repo/deduplication-repo.js +133 -0
  96. package/dist/repo/deduplication-repo.js.map +1 -0
  97. package/dist/repo/dep-repo.d.ts +19 -0
  98. package/dist/repo/dep-repo.d.ts.map +1 -0
  99. package/dist/repo/dep-repo.js +104 -0
  100. package/dist/repo/dep-repo.js.map +1 -0
  101. package/dist/repo/edge-repo.d.ts +26 -0
  102. package/dist/repo/edge-repo.d.ts.map +1 -0
  103. package/dist/repo/edge-repo.js +227 -0
  104. package/dist/repo/edge-repo.js.map +1 -0
  105. package/dist/repo/file-learning-repo.d.ts +17 -0
  106. package/dist/repo/file-learning-repo.d.ts.map +1 -0
  107. package/dist/repo/file-learning-repo.js +60 -0
  108. package/dist/repo/file-learning-repo.js.map +1 -0
  109. package/dist/repo/index.d.ts +18 -0
  110. package/dist/repo/index.d.ts.map +1 -0
  111. package/dist/repo/index.js +18 -0
  112. package/dist/repo/index.js.map +1 -0
  113. package/dist/repo/learning-repo.d.ts +31 -0
  114. package/dist/repo/learning-repo.d.ts.map +1 -0
  115. package/dist/repo/learning-repo.js +165 -0
  116. package/dist/repo/learning-repo.js.map +1 -0
  117. package/dist/repo/orchestrator-state-repo.d.ts +27 -0
  118. package/dist/repo/orchestrator-state-repo.d.ts.map +1 -0
  119. package/dist/repo/orchestrator-state-repo.js +96 -0
  120. package/dist/repo/orchestrator-state-repo.js.map +1 -0
  121. package/dist/repo/run-repo.d.ts +31 -0
  122. package/dist/repo/run-repo.d.ts.map +1 -0
  123. package/dist/repo/run-repo.js +132 -0
  124. package/dist/repo/run-repo.js.map +1 -0
  125. package/dist/repo/task-repo.d.ts +21 -0
  126. package/dist/repo/task-repo.d.ts.map +1 -0
  127. package/dist/repo/task-repo.js +169 -0
  128. package/dist/repo/task-repo.js.map +1 -0
  129. package/dist/repo/tracked-project-repo.d.ts +16 -0
  130. package/dist/repo/tracked-project-repo.d.ts.map +1 -0
  131. package/dist/repo/tracked-project-repo.js +54 -0
  132. package/dist/repo/tracked-project-repo.js.map +1 -0
  133. package/dist/repo/worker-repo.d.ts +19 -0
  134. package/dist/repo/worker-repo.d.ts.map +1 -0
  135. package/dist/repo/worker-repo.js +72 -0
  136. package/dist/repo/worker-repo.js.map +1 -0
  137. package/dist/schemas/index.d.ts +8 -0
  138. package/dist/schemas/index.d.ts.map +1 -0
  139. package/dist/schemas/index.js +7 -0
  140. package/dist/schemas/index.js.map +1 -0
  141. package/dist/schemas/sync.d.ts +296 -0
  142. package/dist/schemas/sync.d.ts.map +1 -0
  143. package/dist/schemas/sync.js +146 -0
  144. package/dist/schemas/sync.js.map +1 -0
  145. package/dist/schemas/worker.d.ts +77 -0
  146. package/dist/schemas/worker.d.ts.map +1 -0
  147. package/dist/schemas/worker.js +80 -0
  148. package/dist/schemas/worker.js.map +1 -0
  149. package/dist/services/anchor-service.d.ts +147 -0
  150. package/dist/services/anchor-service.d.ts.map +1 -0
  151. package/dist/services/anchor-service.js +540 -0
  152. package/dist/services/anchor-service.js.map +1 -0
  153. package/dist/services/anchor-verification.d.ts +94 -0
  154. package/dist/services/anchor-verification.d.ts.map +1 -0
  155. package/dist/services/anchor-verification.js +617 -0
  156. package/dist/services/anchor-verification.js.map +1 -0
  157. package/dist/services/ast-grep-service.d.ts +58 -0
  158. package/dist/services/ast-grep-service.d.ts.map +1 -0
  159. package/dist/services/ast-grep-service.js +356 -0
  160. package/dist/services/ast-grep-service.js.map +1 -0
  161. package/dist/services/attempt-service.d.ts +24 -0
  162. package/dist/services/attempt-service.d.ts.map +1 -0
  163. package/dist/services/attempt-service.js +55 -0
  164. package/dist/services/attempt-service.js.map +1 -0
  165. package/dist/services/auto-sync-service.d.ts +56 -0
  166. package/dist/services/auto-sync-service.d.ts.map +1 -0
  167. package/dist/services/auto-sync-service.js +66 -0
  168. package/dist/services/auto-sync-service.js.map +1 -0
  169. package/dist/services/candidate-extractor-service.d.ts +56 -0
  170. package/dist/services/candidate-extractor-service.d.ts.map +1 -0
  171. package/dist/services/candidate-extractor-service.js +365 -0
  172. package/dist/services/candidate-extractor-service.js.map +1 -0
  173. package/dist/services/claim-service.d.ts +52 -0
  174. package/dist/services/claim-service.d.ts.map +1 -0
  175. package/dist/services/claim-service.js +134 -0
  176. package/dist/services/claim-service.js.map +1 -0
  177. package/dist/services/daemon-service.d.ts +214 -0
  178. package/dist/services/daemon-service.d.ts.map +1 -0
  179. package/dist/services/daemon-service.js +522 -0
  180. package/dist/services/daemon-service.js.map +1 -0
  181. package/dist/services/deduplication-service.d.ts +67 -0
  182. package/dist/services/deduplication-service.d.ts.map +1 -0
  183. package/dist/services/deduplication-service.js +145 -0
  184. package/dist/services/deduplication-service.js.map +1 -0
  185. package/dist/services/dep-service.d.ts +14 -0
  186. package/dist/services/dep-service.d.ts.map +1 -0
  187. package/dist/services/dep-service.js +34 -0
  188. package/dist/services/dep-service.js.map +1 -0
  189. package/dist/services/diversifier-service.d.ts +46 -0
  190. package/dist/services/diversifier-service.d.ts.map +1 -0
  191. package/dist/services/diversifier-service.js +197 -0
  192. package/dist/services/diversifier-service.js.map +1 -0
  193. package/dist/services/edge-service.d.ts +78 -0
  194. package/dist/services/edge-service.d.ts.map +1 -0
  195. package/dist/services/edge-service.js +158 -0
  196. package/dist/services/edge-service.js.map +1 -0
  197. package/dist/services/embedding-service.d.ts +138 -0
  198. package/dist/services/embedding-service.d.ts.map +1 -0
  199. package/dist/services/embedding-service.js +318 -0
  200. package/dist/services/embedding-service.js.map +1 -0
  201. package/dist/services/feedback-tracker.d.ts +64 -0
  202. package/dist/services/feedback-tracker.d.ts.map +1 -0
  203. package/dist/services/feedback-tracker.js +110 -0
  204. package/dist/services/feedback-tracker.js.map +1 -0
  205. package/dist/services/file-learning-service.d.ts +17 -0
  206. package/dist/services/file-learning-service.d.ts.map +1 -0
  207. package/dist/services/file-learning-service.js +41 -0
  208. package/dist/services/file-learning-service.js.map +1 -0
  209. package/dist/services/file-watcher-service.d.ts +141 -0
  210. package/dist/services/file-watcher-service.d.ts.map +1 -0
  211. package/dist/services/file-watcher-service.js +278 -0
  212. package/dist/services/file-watcher-service.js.map +1 -0
  213. package/dist/services/graph-expansion.d.ts +155 -0
  214. package/dist/services/graph-expansion.d.ts.map +1 -0
  215. package/dist/services/graph-expansion.js +466 -0
  216. package/dist/services/graph-expansion.js.map +1 -0
  217. package/dist/services/hierarchy-service.d.ts +16 -0
  218. package/dist/services/hierarchy-service.d.ts.map +1 -0
  219. package/dist/services/hierarchy-service.js +66 -0
  220. package/dist/services/hierarchy-service.js.map +1 -0
  221. package/dist/services/index.d.ts +36 -0
  222. package/dist/services/index.d.ts.map +1 -0
  223. package/dist/services/index.js +36 -0
  224. package/dist/services/index.js.map +1 -0
  225. package/dist/services/learning-service.d.ts +39 -0
  226. package/dist/services/learning-service.d.ts.map +1 -0
  227. package/dist/services/learning-service.js +151 -0
  228. package/dist/services/learning-service.js.map +1 -0
  229. package/dist/services/migration-service.d.ts +67 -0
  230. package/dist/services/migration-service.d.ts.map +1 -0
  231. package/dist/services/migration-service.js +144 -0
  232. package/dist/services/migration-service.js.map +1 -0
  233. package/dist/services/orchestrator-service.d.ts +52 -0
  234. package/dist/services/orchestrator-service.d.ts.map +1 -0
  235. package/dist/services/orchestrator-service.js +203 -0
  236. package/dist/services/orchestrator-service.js.map +1 -0
  237. package/dist/services/promotion-service.d.ts +67 -0
  238. package/dist/services/promotion-service.d.ts.map +1 -0
  239. package/dist/services/promotion-service.js +151 -0
  240. package/dist/services/promotion-service.js.map +1 -0
  241. package/dist/services/query-expansion-service.d.ts +55 -0
  242. package/dist/services/query-expansion-service.d.ts.map +1 -0
  243. package/dist/services/query-expansion-service.js +174 -0
  244. package/dist/services/query-expansion-service.js.map +1 -0
  245. package/dist/services/ready-service.d.ts +16 -0
  246. package/dist/services/ready-service.d.ts.map +1 -0
  247. package/dist/services/ready-service.js +70 -0
  248. package/dist/services/ready-service.js.map +1 -0
  249. package/dist/services/reranker-service.d.ts +51 -0
  250. package/dist/services/reranker-service.d.ts.map +1 -0
  251. package/dist/services/reranker-service.js +128 -0
  252. package/dist/services/reranker-service.js.map +1 -0
  253. package/dist/services/retriever-service.d.ts +49 -0
  254. package/dist/services/retriever-service.d.ts.map +1 -0
  255. package/dist/services/retriever-service.js +419 -0
  256. package/dist/services/retriever-service.js.map +1 -0
  257. package/dist/services/score-service.d.ts +43 -0
  258. package/dist/services/score-service.d.ts.map +1 -0
  259. package/dist/services/score-service.js +82 -0
  260. package/dist/services/score-service.js.map +1 -0
  261. package/dist/services/swarm-verification.d.ts +104 -0
  262. package/dist/services/swarm-verification.d.ts.map +1 -0
  263. package/dist/services/swarm-verification.js +400 -0
  264. package/dist/services/swarm-verification.js.map +1 -0
  265. package/dist/services/sync-service.d.ts +115 -0
  266. package/dist/services/sync-service.d.ts.map +1 -0
  267. package/dist/services/sync-service.js +350 -0
  268. package/dist/services/sync-service.js.map +1 -0
  269. package/dist/services/task-service.d.ts +22 -0
  270. package/dist/services/task-service.d.ts.map +1 -0
  271. package/dist/services/task-service.js +221 -0
  272. package/dist/services/task-service.js.map +1 -0
  273. package/dist/services/worker-process.d.ts +41 -0
  274. package/dist/services/worker-process.d.ts.map +1 -0
  275. package/dist/services/worker-process.js +280 -0
  276. package/dist/services/worker-process.js.map +1 -0
  277. package/dist/services/worker-service.d.ts +74 -0
  278. package/dist/services/worker-service.d.ts.map +1 -0
  279. package/dist/services/worker-service.js +148 -0
  280. package/dist/services/worker-service.js.map +1 -0
  281. package/dist/utils/glob.d.ts +15 -0
  282. package/dist/utils/glob.d.ts.map +1 -0
  283. package/dist/utils/glob.js +27 -0
  284. package/dist/utils/glob.js.map +1 -0
  285. package/dist/utils/math.d.ts +6 -0
  286. package/dist/utils/math.d.ts.map +1 -0
  287. package/dist/utils/math.js +21 -0
  288. package/dist/utils/math.js.map +1 -0
  289. package/package.json +72 -0
@@ -0,0 +1,540 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { AnchorRepository } from "../repo/anchor-repo.js";
3
+ import { LearningRepository } from "../repo/learning-repo.js";
4
+ import { AnchorNotFoundError, ValidationError, LearningNotFoundError } from "../errors.js";
5
+ import { getAnchorTTL, isStale } from "./anchor-verification.js";
6
+ /** Validate anchor types at compile time */
7
+ const VALID_ANCHOR_TYPES = ["glob", "hash", "symbol", "line_range"];
8
+ export class AnchorService extends Context.Tag("AnchorService")() {
9
+ }
10
+ /**
11
+ * Validate anchor input based on type.
12
+ * Each anchor type has specific requirements.
13
+ */
14
+ const validateAnchorInput = (input) => Effect.gen(function* () {
15
+ // Validate anchor type
16
+ if (!VALID_ANCHOR_TYPES.includes(input.anchorType)) {
17
+ return yield* Effect.fail(new ValidationError({
18
+ reason: `Invalid anchor type: ${input.anchorType}. Valid types: ${VALID_ANCHOR_TYPES.join(", ")}`
19
+ }));
20
+ }
21
+ // Validate file path
22
+ if (!input.filePath || input.filePath.trim().length === 0) {
23
+ return yield* Effect.fail(new ValidationError({
24
+ reason: "File path is required"
25
+ }));
26
+ }
27
+ // Validate value
28
+ if (!input.value || input.value.trim().length === 0) {
29
+ return yield* Effect.fail(new ValidationError({
30
+ reason: "Anchor value is required"
31
+ }));
32
+ }
33
+ // Type-specific validation
34
+ switch (input.anchorType) {
35
+ case "glob":
36
+ // Glob patterns should be valid patterns
37
+ // Basic validation: must contain at least a filename or pattern
38
+ if (input.value.length < 1) {
39
+ return yield* Effect.fail(new ValidationError({
40
+ reason: "Glob pattern cannot be empty"
41
+ }));
42
+ }
43
+ return {
44
+ learningId: input.learningId,
45
+ anchorType: input.anchorType,
46
+ anchorValue: input.value,
47
+ filePath: input.filePath,
48
+ symbolFqname: null,
49
+ lineStart: null,
50
+ lineEnd: null,
51
+ contentHash: input.contentHash ?? null,
52
+ contentPreview: input.contentPreview ?? null
53
+ };
54
+ case "hash":
55
+ // Hash should be a valid SHA256 hash (64 hex characters)
56
+ if (!/^[a-f0-9]{64}$/i.test(input.value)) {
57
+ return yield* Effect.fail(new ValidationError({
58
+ reason: "Hash anchor value must be a valid SHA256 hash (64 hex characters)"
59
+ }));
60
+ }
61
+ return {
62
+ learningId: input.learningId,
63
+ anchorType: input.anchorType,
64
+ anchorValue: input.value,
65
+ filePath: input.filePath,
66
+ symbolFqname: null,
67
+ lineStart: input.lineStart ?? null,
68
+ lineEnd: input.lineEnd ?? null,
69
+ contentHash: input.value,
70
+ contentPreview: input.contentPreview ?? null
71
+ };
72
+ case "symbol":
73
+ // Symbol anchors require a symbol FQName
74
+ if (!input.symbolFqname || input.symbolFqname.trim().length === 0) {
75
+ return yield* Effect.fail(new ValidationError({
76
+ reason: "Symbol anchor requires symbolFqname"
77
+ }));
78
+ }
79
+ // Symbol FQName format: file::symbolName or file::class::method
80
+ if (!input.symbolFqname.includes("::")) {
81
+ return yield* Effect.fail(new ValidationError({
82
+ reason: "Symbol FQName must be in format: file::symbol or file::class::method"
83
+ }));
84
+ }
85
+ return {
86
+ learningId: input.learningId,
87
+ anchorType: input.anchorType,
88
+ anchorValue: input.value,
89
+ filePath: input.filePath,
90
+ symbolFqname: input.symbolFqname,
91
+ lineStart: input.lineStart ?? null,
92
+ lineEnd: input.lineEnd ?? null,
93
+ contentHash: input.contentHash ?? null,
94
+ contentPreview: input.contentPreview ?? null
95
+ };
96
+ case "line_range":
97
+ // Line range anchors require valid line numbers
98
+ if (input.lineStart === undefined || input.lineStart < 1) {
99
+ return yield* Effect.fail(new ValidationError({
100
+ reason: "Line range anchor requires valid lineStart (>= 1)"
101
+ }));
102
+ }
103
+ if (input.lineEnd !== undefined && input.lineEnd < input.lineStart) {
104
+ return yield* Effect.fail(new ValidationError({
105
+ reason: "lineEnd must be >= lineStart"
106
+ }));
107
+ }
108
+ return {
109
+ learningId: input.learningId,
110
+ anchorType: input.anchorType,
111
+ anchorValue: input.value,
112
+ filePath: input.filePath,
113
+ symbolFqname: null,
114
+ lineStart: input.lineStart,
115
+ lineEnd: input.lineEnd ?? input.lineStart,
116
+ contentHash: input.contentHash ?? null,
117
+ contentPreview: input.contentPreview ?? null
118
+ };
119
+ default:
120
+ return yield* Effect.fail(new ValidationError({
121
+ reason: `Unknown anchor type: ${input.anchorType}`
122
+ }));
123
+ }
124
+ });
125
+ /**
126
+ * Validate anchor status.
127
+ */
128
+ const VALID_STATUSES = ["valid", "drifted", "invalid"];
129
+ const validateStatus = (status) => Effect.gen(function* () {
130
+ if (!VALID_STATUSES.includes(status)) {
131
+ return yield* Effect.fail(new ValidationError({
132
+ reason: `Invalid anchor status: ${status}. Valid statuses: ${VALID_STATUSES.join(", ")}`
133
+ }));
134
+ }
135
+ return status;
136
+ });
137
+ export const AnchorServiceLive = Layer.effect(AnchorService, Effect.gen(function* () {
138
+ const anchorRepo = yield* AnchorRepository;
139
+ const learningRepo = yield* LearningRepository;
140
+ return {
141
+ createAnchor: (input) => Effect.gen(function* () {
142
+ // Validate the input based on anchor type
143
+ const validatedInput = yield* validateAnchorInput(input);
144
+ // Verify the learning exists
145
+ const learning = yield* learningRepo.findById(input.learningId);
146
+ if (!learning) {
147
+ return yield* Effect.fail(new LearningNotFoundError({ id: input.learningId }));
148
+ }
149
+ // Create the anchor
150
+ return yield* anchorRepo.create(validatedInput);
151
+ }),
152
+ verifyAnchor: (anchorId) => Effect.gen(function* () {
153
+ const anchor = yield* anchorRepo.findById(anchorId);
154
+ if (!anchor) {
155
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
156
+ }
157
+ const previousStatus = anchor.status;
158
+ // Verification logic depends on anchor type
159
+ // For now, we simply update the verified_at timestamp
160
+ // Full verification would check file existence, hash matches, symbol presence, etc.
161
+ // This is a placeholder for future ast-grep integration
162
+ let newStatus = "valid";
163
+ let reason;
164
+ switch (anchor.anchorType) {
165
+ case "glob":
166
+ // Glob anchors are generally considered valid if file path matches pattern
167
+ // Full implementation would check if files matching the pattern exist
168
+ newStatus = "valid";
169
+ break;
170
+ case "hash":
171
+ // Hash anchors would compare stored hash with current file content hash
172
+ // Placeholder: assume valid for now (full implementation requires file access)
173
+ newStatus = "valid";
174
+ reason = "Hash verification requires file content access";
175
+ break;
176
+ case "symbol":
177
+ // Symbol anchors would use ast-grep to verify symbol exists
178
+ // Placeholder: assume valid for now (full implementation requires ast-grep)
179
+ newStatus = "valid";
180
+ reason = "Symbol verification requires ast-grep integration";
181
+ break;
182
+ case "line_range":
183
+ // Line range anchors would check if line range is still within file bounds
184
+ // Placeholder: assume valid for now
185
+ newStatus = "valid";
186
+ reason = "Line range verification requires file access";
187
+ break;
188
+ }
189
+ // Update status and verified_at timestamp
190
+ if (newStatus !== previousStatus) {
191
+ yield* anchorRepo.updateStatus(anchorId, newStatus);
192
+ }
193
+ yield* anchorRepo.updateVerifiedAt(anchorId);
194
+ return {
195
+ anchorId,
196
+ previousStatus,
197
+ newStatus,
198
+ verified: true,
199
+ reason
200
+ };
201
+ }),
202
+ updateAnchorStatus: (anchorId, status, reason, detectedBy = "manual") => Effect.gen(function* () {
203
+ // Validate status
204
+ yield* validateStatus(status);
205
+ // Get anchor to verify it exists
206
+ const anchor = yield* anchorRepo.findById(anchorId);
207
+ if (!anchor) {
208
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
209
+ }
210
+ const oldStatus = anchor.status;
211
+ // Update the status
212
+ yield* anchorRepo.updateStatus(anchorId, status);
213
+ // Log the status change if status actually changed
214
+ if (oldStatus !== status) {
215
+ yield* anchorRepo.logInvalidation({
216
+ anchorId,
217
+ oldStatus,
218
+ newStatus: status,
219
+ reason: reason ?? `Status changed from ${oldStatus} to ${status}`,
220
+ detectedBy,
221
+ oldContentHash: anchor.contentHash
222
+ });
223
+ }
224
+ // Return updated anchor
225
+ const updated = yield* anchorRepo.findById(anchorId);
226
+ if (!updated) {
227
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
228
+ }
229
+ return updated;
230
+ }),
231
+ findAnchorsForFile: (filePath) => anchorRepo.findByFilePath(filePath),
232
+ findAnchorsForLearning: (learningId) => anchorRepo.findByLearningId(learningId),
233
+ get: (id) => Effect.gen(function* () {
234
+ const anchor = yield* anchorRepo.findById(id);
235
+ if (!anchor) {
236
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
237
+ }
238
+ return anchor;
239
+ }),
240
+ getWithVerification: (id, _options = {}) => Effect.gen(function* () {
241
+ // Get the anchor first
242
+ const anchor = yield* anchorRepo.findById(id);
243
+ if (!anchor) {
244
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
245
+ }
246
+ // Get TTL and check staleness
247
+ const ttl = yield* getAnchorTTL();
248
+ const anchorIsStale = isStale(anchor, ttl);
249
+ // If fresh, return immediately without verification
250
+ if (!anchorIsStale) {
251
+ return {
252
+ anchor,
253
+ isFresh: true,
254
+ wasVerified: false
255
+ };
256
+ }
257
+ // Anchor is stale - run verification
258
+ const previousStatus = anchor.status;
259
+ // Verification logic (simplified - uses the same logic as verifyAnchor)
260
+ // For now, we simply update the verified_at timestamp
261
+ // Full verification would check file existence, hash matches, symbol presence, etc.
262
+ // Note: Future implementation will use AnchorVerificationService for full file-based verification
263
+ let newStatus = previousStatus;
264
+ let reason;
265
+ let action = "unchanged";
266
+ switch (anchor.anchorType) {
267
+ case "glob":
268
+ // Glob anchors are generally considered valid if file path matches pattern
269
+ // Full implementation would check if files matching the pattern exist
270
+ break;
271
+ case "hash":
272
+ // Hash anchors would compare stored hash with current file content hash
273
+ // Placeholder: assume unchanged for now (full implementation requires file access)
274
+ reason = "Hash verification requires file content access";
275
+ break;
276
+ case "symbol":
277
+ // Symbol anchors would use ast-grep to verify symbol exists
278
+ // Placeholder: assume unchanged for now (full implementation requires ast-grep)
279
+ reason = "Symbol verification requires ast-grep integration";
280
+ break;
281
+ case "line_range":
282
+ // Line range anchors would check if line range is still within file bounds
283
+ // Placeholder: assume unchanged for now
284
+ reason = "Line range verification requires file access";
285
+ break;
286
+ }
287
+ // Determine action based on status change
288
+ if (newStatus !== previousStatus) {
289
+ yield* anchorRepo.updateStatus(id, newStatus);
290
+ if (newStatus === "drifted") {
291
+ action = "drifted";
292
+ }
293
+ else if (newStatus === "invalid") {
294
+ action = "invalidated";
295
+ }
296
+ else if (previousStatus === "drifted" && newStatus === "valid") {
297
+ action = "self_healed";
298
+ }
299
+ }
300
+ // Update verified_at timestamp
301
+ yield* anchorRepo.updateVerifiedAt(id);
302
+ // Get the updated anchor
303
+ const updatedAnchor = yield* anchorRepo.findById(id);
304
+ if (!updatedAnchor) {
305
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
306
+ }
307
+ return {
308
+ anchor: updatedAnchor,
309
+ isFresh: false,
310
+ wasVerified: true,
311
+ verificationResult: {
312
+ previousStatus,
313
+ newStatus,
314
+ action,
315
+ reason
316
+ }
317
+ };
318
+ }),
319
+ remove: (id, reason = "Soft deleted") => Effect.gen(function* () {
320
+ const anchor = yield* anchorRepo.findById(id);
321
+ if (!anchor) {
322
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
323
+ }
324
+ const oldStatus = anchor.status;
325
+ // Set status to invalid (soft delete)
326
+ yield* anchorRepo.updateStatus(id, "invalid");
327
+ // Log the status change
328
+ yield* anchorRepo.logInvalidation({
329
+ anchorId: id,
330
+ oldStatus,
331
+ newStatus: "invalid",
332
+ reason,
333
+ detectedBy: "manual",
334
+ oldContentHash: anchor.contentHash
335
+ });
336
+ // Return the updated anchor
337
+ const updated = yield* anchorRepo.findById(id);
338
+ if (!updated) {
339
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
340
+ }
341
+ return updated;
342
+ }),
343
+ hardDelete: (id) => Effect.gen(function* () {
344
+ const anchor = yield* anchorRepo.findById(id);
345
+ if (!anchor) {
346
+ return yield* Effect.fail(new AnchorNotFoundError({ id }));
347
+ }
348
+ yield* anchorRepo.delete(id);
349
+ }),
350
+ findDrifted: () => anchorRepo.findDrifted(),
351
+ findInvalid: () => anchorRepo.findInvalid(),
352
+ verifyAnchorsForFile: (filePath) => Effect.gen(function* () {
353
+ const anchors = yield* anchorRepo.findByFilePath(filePath);
354
+ let verified = 0;
355
+ let drifted = 0;
356
+ let invalid = 0;
357
+ for (const anchor of anchors) {
358
+ // Simple verification - full implementation would check actual file state
359
+ yield* anchorRepo.updateVerifiedAt(anchor.id);
360
+ switch (anchor.status) {
361
+ case "valid":
362
+ verified++;
363
+ break;
364
+ case "drifted":
365
+ drifted++;
366
+ break;
367
+ case "invalid":
368
+ invalid++;
369
+ break;
370
+ }
371
+ }
372
+ return {
373
+ total: anchors.length,
374
+ verified,
375
+ drifted,
376
+ invalid
377
+ };
378
+ }),
379
+ pin: (anchorId) => Effect.gen(function* () {
380
+ const anchor = yield* anchorRepo.findById(anchorId);
381
+ if (!anchor) {
382
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
383
+ }
384
+ yield* anchorRepo.setPinned(anchorId, true);
385
+ const updated = yield* anchorRepo.findById(anchorId);
386
+ if (!updated) {
387
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
388
+ }
389
+ return updated;
390
+ }),
391
+ unpin: (anchorId) => Effect.gen(function* () {
392
+ const anchor = yield* anchorRepo.findById(anchorId);
393
+ if (!anchor) {
394
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
395
+ }
396
+ yield* anchorRepo.setPinned(anchorId, false);
397
+ const updated = yield* anchorRepo.findById(anchorId);
398
+ if (!updated) {
399
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
400
+ }
401
+ return updated;
402
+ }),
403
+ invalidate: (anchorId, reason, detectedBy = "manual") => Effect.gen(function* () {
404
+ const anchor = yield* anchorRepo.findById(anchorId);
405
+ if (!anchor) {
406
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
407
+ }
408
+ const oldStatus = anchor.status;
409
+ // Update status to invalid
410
+ yield* anchorRepo.updateStatus(anchorId, "invalid");
411
+ // Log the invalidation
412
+ yield* anchorRepo.logInvalidation({
413
+ anchorId,
414
+ oldStatus,
415
+ newStatus: "invalid",
416
+ reason,
417
+ detectedBy,
418
+ oldContentHash: anchor.contentHash
419
+ });
420
+ const updated = yield* anchorRepo.findById(anchorId);
421
+ if (!updated) {
422
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
423
+ }
424
+ return updated;
425
+ }),
426
+ restore: (anchorId) => Effect.gen(function* () {
427
+ const anchor = yield* anchorRepo.findById(anchorId);
428
+ if (!anchor) {
429
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
430
+ }
431
+ const currentStatus = anchor.status;
432
+ // Find the most recent invalidation log entry with status change TO 'invalid'
433
+ const logs = yield* anchorRepo.getInvalidationLogs(anchorId);
434
+ const invalidationEntry = logs.find(log => log.newStatus === "invalid");
435
+ // Determine restore target status: use oldStatus from log or default to 'valid'
436
+ const restoreToStatus = invalidationEntry?.oldStatus ?? "valid";
437
+ // Update status to the restore target
438
+ yield* anchorRepo.updateStatus(anchorId, restoreToStatus);
439
+ yield* anchorRepo.updateVerifiedAt(anchorId);
440
+ // Optionally restore old_content_hash if it was stored in the log entry
441
+ if (invalidationEntry?.oldContentHash) {
442
+ yield* anchorRepo.update(anchorId, { contentHash: invalidationEntry.oldContentHash });
443
+ }
444
+ // Log the restoration
445
+ yield* anchorRepo.logInvalidation({
446
+ anchorId,
447
+ oldStatus: currentStatus,
448
+ newStatus: restoreToStatus,
449
+ reason: invalidationEntry
450
+ ? `Restored to ${restoreToStatus} (from invalidation log)`
451
+ : "Manual restoration",
452
+ detectedBy: "manual",
453
+ oldContentHash: anchor.contentHash,
454
+ newContentHash: invalidationEntry?.oldContentHash ?? null
455
+ });
456
+ const updated = yield* anchorRepo.findById(anchorId);
457
+ if (!updated) {
458
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
459
+ }
460
+ return updated;
461
+ }),
462
+ prune: (olderThanDays) => Effect.gen(function* () {
463
+ const deleted = yield* anchorRepo.deleteOldInvalid(olderThanDays);
464
+ return { deleted };
465
+ }),
466
+ getStatus: () => Effect.gen(function* () {
467
+ const summary = yield* anchorRepo.getStatusSummary();
468
+ const recentInvalidations = yield* anchorRepo.getInvalidationLogs();
469
+ return {
470
+ total: summary.total,
471
+ valid: summary.valid,
472
+ drifted: summary.drifted,
473
+ invalid: summary.invalid,
474
+ pinned: summary.pinned,
475
+ recentInvalidations: recentInvalidations.slice(0, 10)
476
+ };
477
+ }),
478
+ verifyAll: () => Effect.gen(function* () {
479
+ const anchors = yield* anchorRepo.findAll();
480
+ let verified = 0;
481
+ let drifted = 0;
482
+ let invalid = 0;
483
+ for (const anchor of anchors) {
484
+ // Skip pinned anchors
485
+ if (anchor.pinned) {
486
+ switch (anchor.status) {
487
+ case "valid":
488
+ verified++;
489
+ break;
490
+ case "drifted":
491
+ drifted++;
492
+ break;
493
+ case "invalid":
494
+ invalid++;
495
+ break;
496
+ }
497
+ continue;
498
+ }
499
+ // Simple verification - full implementation would check actual file state
500
+ yield* anchorRepo.updateVerifiedAt(anchor.id);
501
+ switch (anchor.status) {
502
+ case "valid":
503
+ verified++;
504
+ break;
505
+ case "drifted":
506
+ drifted++;
507
+ break;
508
+ case "invalid":
509
+ invalid++;
510
+ break;
511
+ }
512
+ }
513
+ return {
514
+ total: anchors.length,
515
+ verified,
516
+ drifted,
517
+ invalid
518
+ };
519
+ }),
520
+ logStatusChange: (anchorId, oldStatus, newStatus, reason, detectedBy = "manual", oldHash, newHash, similarity) => Effect.gen(function* () {
521
+ // Verify anchor exists
522
+ const anchor = yield* anchorRepo.findById(anchorId);
523
+ if (!anchor) {
524
+ return yield* Effect.fail(new AnchorNotFoundError({ id: anchorId }));
525
+ }
526
+ // Create entry in invalidation_log
527
+ return yield* anchorRepo.logInvalidation({
528
+ anchorId,
529
+ oldStatus,
530
+ newStatus,
531
+ reason,
532
+ detectedBy,
533
+ oldContentHash: oldHash ?? null,
534
+ newContentHash: newHash ?? null,
535
+ similarityScore: similarity ?? null
536
+ });
537
+ })
538
+ };
539
+ }));
540
+ //# sourceMappingURL=anchor-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-service.js","sourceRoot":"","sources":["../../src/services/anchor-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * AnchorVerificationService - Periodic anchor verification for PRD-017
3
+ *
4
+ * Verifies anchors by checking actual file system state:
5
+ * - glob: Check if glob pattern still matches files
6
+ * - hash: Compute content hash and compare
7
+ * - symbol: Grep-based check for symbol presence
8
+ * - line_range: Verify file exists and has enough lines
9
+ *
10
+ * Updates anchor status (valid/drifted/invalid) and logs all changes
11
+ * to invalidation_log via AnchorRepository.
12
+ *
13
+ * @see docs/prd/PRD-017-invalidation-maintenance.md
14
+ * @see docs/design/DD-017-invalidation-maintenance.md
15
+ */
16
+ import { Context, Effect, Layer } from "effect";
17
+ import { AnchorRepository } from "../repo/anchor-repo.js";
18
+ import { DatabaseError } from "../errors.js";
19
+ import type { Anchor, AnchorStatus, InvalidationSource } from "@jamesaphoenix/tx-types";
20
+ /** Result of verifying a single anchor */
21
+ export interface VerificationResult {
22
+ readonly anchorId: number;
23
+ readonly previousStatus: AnchorStatus;
24
+ readonly newStatus: AnchorStatus;
25
+ readonly action: "unchanged" | "self_healed" | "drifted" | "invalidated";
26
+ readonly reason?: string;
27
+ readonly similarity?: number;
28
+ readonly oldContentHash?: string | null;
29
+ readonly newContentHash?: string | null;
30
+ }
31
+ /** Summary of batch verification */
32
+ export interface VerificationSummary {
33
+ readonly total: number;
34
+ readonly unchanged: number;
35
+ readonly selfHealed: number;
36
+ readonly drifted: number;
37
+ readonly invalid: number;
38
+ readonly errors: number;
39
+ readonly duration: number;
40
+ }
41
+ /** Options for verification */
42
+ export interface VerifyOptions {
43
+ /** Detection source for audit logging */
44
+ readonly detectedBy?: InvalidationSource;
45
+ /** Skip pinned anchors (default: true) */
46
+ readonly skipPinned?: boolean;
47
+ /** Base directory for relative file paths */
48
+ readonly baseDir?: string;
49
+ }
50
+ declare const AnchorVerificationService_base: Context.TagClass<AnchorVerificationService, "AnchorVerificationService", {
51
+ /**
52
+ * Verify a single anchor against the file system.
53
+ * Checks file existence, content hash, symbol presence, etc.
54
+ */
55
+ readonly verify: (anchorId: number, options?: VerifyOptions) => Effect.Effect<VerificationResult, DatabaseError>;
56
+ /**
57
+ * Verify all anchors.
58
+ * Returns summary of verification results.
59
+ */
60
+ readonly verifyAll: (options?: VerifyOptions) => Effect.Effect<VerificationSummary, DatabaseError>;
61
+ /**
62
+ * Verify all anchors for a specific file.
63
+ */
64
+ readonly verifyFile: (filePath: string, options?: VerifyOptions) => Effect.Effect<VerificationSummary, DatabaseError>;
65
+ /**
66
+ * Verify anchors matching a glob pattern.
67
+ */
68
+ readonly verifyGlob: (globPattern: string, options?: VerifyOptions) => Effect.Effect<VerificationSummary, DatabaseError>;
69
+ }>;
70
+ export declare class AnchorVerificationService extends AnchorVerificationService_base {
71
+ }
72
+ /** Default anchor cache TTL in seconds (1 hour) */
73
+ export declare const DEFAULT_ANCHOR_CACHE_TTL = 3600;
74
+ /**
75
+ * Get the anchor cache TTL from TX_ANCHOR_CACHE_TTL env var.
76
+ * Used by lazy verification to determine staleness.
77
+ *
78
+ * @returns Effect yielding TTL in seconds (default: 3600)
79
+ */
80
+ export declare const getAnchorTTL: () => Effect.Effect<number, never>;
81
+ /**
82
+ * Check if an anchor is stale based on its verified_at timestamp and TTL.
83
+ * An anchor is stale if:
84
+ * - verified_at is null (never verified), or
85
+ * - verified_at is older than (now - TTL)
86
+ *
87
+ * @param anchor - The anchor to check
88
+ * @param ttlSeconds - TTL in seconds (from getAnchorTTL)
89
+ * @returns true if anchor is stale and needs verification
90
+ */
91
+ export declare const isStale: (anchor: Anchor, ttlSeconds: number) => boolean;
92
+ export declare const AnchorVerificationServiceLive: Layer.Layer<AnchorVerificationService, never, AnchorRepository>;
93
+ export {};
94
+ //# sourceMappingURL=anchor-verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-verification.d.ts","sourceRoot":"","sources":["../../src/services/anchor-verification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAIvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAMvF,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,GAAG,aAAa,CAAA;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxC;AAED,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,+BAA+B;AAC/B,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAA;IACxC,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;;IASG;;;OAGG;qBACc,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAAC;IAErD;;;OAGG;wBACiB,CAClB,OAAO,CAAC,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;IAEtD;;OAEG;yBACkB,CACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;IAEtD;;OAEG;yBACkB,CACnB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;;AAlC1D,qBAAa,yBAA0B,SAAQ,8BAoC5C;CAAG;AAMN,mDAAmD;AACnD,eAAO,MAAM,wBAAwB,OAAO,CAAA;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAIxD,CAAA;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,YAAY,MAAM,KAAG,OAU5D,CAAA;AAgMD,eAAO,MAAM,6BAA6B,iEAkfzC,CAAA"}