@jamesaphoenix/tx-core 0.8.0 → 0.9.0

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 (517) hide show
  1. package/dist/db.d.ts +6 -6
  2. package/dist/db.d.ts.map +1 -1
  3. package/dist/db.js +29 -2
  4. package/dist/db.js.map +1 -1
  5. package/dist/index.d.ts +8 -3
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +8 -3
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal/cycle-scan-service-impl.d.ts +28 -0
  10. package/dist/internal/cycle-scan-service-impl.d.ts.map +1 -0
  11. package/dist/internal/cycle-scan-service-impl.js +877 -0
  12. package/dist/internal/cycle-scan-service-impl.js.map +1 -0
  13. package/dist/internal/doc-service-impl.d.ts +42 -0
  14. package/dist/internal/doc-service-impl.d.ts.map +1 -0
  15. package/dist/internal/doc-service-impl.js +812 -0
  16. package/dist/internal/doc-service-impl.js.map +1 -0
  17. package/dist/internal/embedding-service-impl.d.ts +202 -0
  18. package/dist/internal/embedding-service-impl.d.ts.map +1 -0
  19. package/dist/internal/embedding-service-impl.js +466 -0
  20. package/dist/internal/embedding-service-impl.js.map +1 -0
  21. package/dist/internal/memory-service-impl.d.ts +49 -0
  22. package/dist/internal/memory-service-impl.d.ts.map +1 -0
  23. package/dist/internal/memory-service-impl.js +1061 -0
  24. package/dist/internal/memory-service-impl.js.map +1 -0
  25. package/dist/internal/spec-trace-service-impl.d.ts +50 -0
  26. package/dist/internal/spec-trace-service-impl.d.ts.map +1 -0
  27. package/dist/internal/spec-trace-service-impl.js +707 -0
  28. package/dist/internal/spec-trace-service-impl.js.map +1 -0
  29. package/dist/internal/sync/service-impl.d.ts +41 -0
  30. package/dist/internal/sync/service-impl.d.ts.map +1 -0
  31. package/dist/{services/sync-service.js → internal/sync/service-impl.js} +954 -499
  32. package/dist/internal/sync/service-impl.js.map +1 -0
  33. package/dist/layer.d.ts +8 -5
  34. package/dist/layer.d.ts.map +1 -1
  35. package/dist/layer.js +22 -10
  36. package/dist/layer.js.map +1 -1
  37. package/dist/mappers/anchor.d.ts.map +1 -1
  38. package/dist/mappers/anchor.js +5 -4
  39. package/dist/mappers/anchor.js.map +1 -1
  40. package/dist/mappers/attempt.d.ts.map +1 -1
  41. package/dist/mappers/attempt.js +2 -1
  42. package/dist/mappers/attempt.js.map +1 -1
  43. package/dist/mappers/candidate.d.ts.map +1 -1
  44. package/dist/mappers/candidate.js +2 -1
  45. package/dist/mappers/candidate.js.map +1 -1
  46. package/dist/mappers/claim.d.ts.map +1 -1
  47. package/dist/mappers/claim.js +2 -1
  48. package/dist/mappers/claim.js.map +1 -1
  49. package/dist/mappers/doc.d.ts.map +1 -1
  50. package/dist/mappers/doc.js +9 -8
  51. package/dist/mappers/doc.js.map +1 -1
  52. package/dist/mappers/edge.d.ts.map +1 -1
  53. package/dist/mappers/edge.js +4 -3
  54. package/dist/mappers/edge.js.map +1 -1
  55. package/dist/mappers/file-learning.d.ts.map +1 -1
  56. package/dist/mappers/file-learning.js +2 -1
  57. package/dist/mappers/file-learning.js.map +1 -1
  58. package/dist/mappers/index.d.ts +1 -0
  59. package/dist/mappers/index.d.ts.map +1 -1
  60. package/dist/mappers/index.js +2 -0
  61. package/dist/mappers/index.js.map +1 -1
  62. package/dist/mappers/learning.d.ts.map +1 -1
  63. package/dist/mappers/learning.js +4 -3
  64. package/dist/mappers/learning.js.map +1 -1
  65. package/dist/mappers/memory.d.ts.map +1 -1
  66. package/dist/mappers/memory.js +7 -6
  67. package/dist/mappers/memory.js.map +1 -1
  68. package/dist/mappers/orchestrator-state.d.ts.map +1 -1
  69. package/dist/mappers/orchestrator-state.js +2 -1
  70. package/dist/mappers/orchestrator-state.js.map +1 -1
  71. package/dist/mappers/pin.d.ts.map +1 -1
  72. package/dist/mappers/pin.js +2 -1
  73. package/dist/mappers/pin.js.map +1 -1
  74. package/dist/mappers/run.d.ts.map +1 -1
  75. package/dist/mappers/run.js +4 -3
  76. package/dist/mappers/run.js.map +1 -1
  77. package/dist/mappers/spec-trace.d.ts +11 -0
  78. package/dist/mappers/spec-trace.d.ts.map +1 -0
  79. package/dist/mappers/spec-trace.js +59 -0
  80. package/dist/mappers/spec-trace.js.map +1 -0
  81. package/dist/mappers/task.d.ts.map +1 -1
  82. package/dist/mappers/task.js +4 -4
  83. package/dist/mappers/task.js.map +1 -1
  84. package/dist/mappers/worker.d.ts.map +1 -1
  85. package/dist/mappers/worker.js +2 -1
  86. package/dist/mappers/worker.js.map +1 -1
  87. package/dist/migrations-embedded.d.ts.map +1 -1
  88. package/dist/migrations-embedded.js +15 -0
  89. package/dist/migrations-embedded.js.map +1 -1
  90. package/dist/repo/anchor-repo.d.ts +2 -2
  91. package/dist/repo/anchor-repo.d.ts.map +1 -1
  92. package/dist/repo/anchor-repo.js +18 -17
  93. package/dist/repo/anchor-repo.js.map +1 -1
  94. package/dist/repo/attempt-repo.d.ts.map +1 -1
  95. package/dist/repo/attempt-repo.js +11 -10
  96. package/dist/repo/attempt-repo.js.map +1 -1
  97. package/dist/repo/candidate-repo.d.ts.map +1 -1
  98. package/dist/repo/candidate-repo.js +8 -7
  99. package/dist/repo/candidate-repo.js.map +1 -1
  100. package/dist/repo/claim-repo.d.ts +4 -4
  101. package/dist/repo/claim-repo.d.ts.map +1 -1
  102. package/dist/repo/claim-repo.js +14 -13
  103. package/dist/repo/claim-repo.js.map +1 -1
  104. package/dist/repo/compaction-repo.d.ts +4 -4
  105. package/dist/repo/compaction-repo.d.ts.map +1 -1
  106. package/dist/repo/compaction-repo.js +7 -6
  107. package/dist/repo/compaction-repo.js.map +1 -1
  108. package/dist/repo/deduplication-repo.d.ts.map +1 -1
  109. package/dist/repo/deduplication-repo.js +80 -57
  110. package/dist/repo/deduplication-repo.js.map +1 -1
  111. package/dist/repo/dep-repo.d.ts.map +1 -1
  112. package/dist/repo/dep-repo.js +90 -88
  113. package/dist/repo/dep-repo.js.map +1 -1
  114. package/dist/repo/doc-repo.d.ts +2 -63
  115. package/dist/repo/doc-repo.d.ts.map +1 -1
  116. package/dist/repo/doc-repo.js +6 -4
  117. package/dist/repo/doc-repo.js.map +1 -1
  118. package/dist/repo/doc-repo.types.d.ts +64 -0
  119. package/dist/repo/doc-repo.types.d.ts.map +1 -0
  120. package/dist/repo/doc-repo.types.js +2 -0
  121. package/dist/repo/doc-repo.types.js.map +1 -0
  122. package/dist/repo/edge-repo.d.ts.map +1 -1
  123. package/dist/repo/edge-repo.js +91 -81
  124. package/dist/repo/edge-repo.js.map +1 -1
  125. package/dist/repo/file-learning-repo.d.ts.map +1 -1
  126. package/dist/repo/file-learning-repo.js +7 -6
  127. package/dist/repo/file-learning-repo.js.map +1 -1
  128. package/dist/repo/guard-repo.d.ts +4 -4
  129. package/dist/repo/guard-repo.d.ts.map +1 -1
  130. package/dist/repo/guard-repo.js +8 -7
  131. package/dist/repo/guard-repo.js.map +1 -1
  132. package/dist/repo/index.d.ts +1 -0
  133. package/dist/repo/index.d.ts.map +1 -1
  134. package/dist/repo/index.js +1 -0
  135. package/dist/repo/index.js.map +1 -1
  136. package/dist/repo/label-repo.d.ts +4 -4
  137. package/dist/repo/label-repo.d.ts.map +1 -1
  138. package/dist/repo/label-repo.js +9 -8
  139. package/dist/repo/label-repo.js.map +1 -1
  140. package/dist/repo/learning-repo.d.ts +2 -2
  141. package/dist/repo/learning-repo.d.ts.map +1 -1
  142. package/dist/repo/learning-repo.js +37 -31
  143. package/dist/repo/learning-repo.js.map +1 -1
  144. package/dist/repo/memory-repo/document.d.ts +4 -0
  145. package/dist/repo/memory-repo/document.d.ts.map +1 -0
  146. package/dist/repo/memory-repo/document.js +205 -0
  147. package/dist/repo/memory-repo/document.js.map +1 -0
  148. package/dist/repo/memory-repo/link.d.ts +4 -0
  149. package/dist/repo/memory-repo/link.d.ts.map +1 -0
  150. package/dist/repo/memory-repo/link.js +124 -0
  151. package/dist/repo/memory-repo/link.js.map +1 -0
  152. package/dist/repo/memory-repo/property.d.ts +4 -0
  153. package/dist/repo/memory-repo/property.d.ts.map +1 -0
  154. package/dist/repo/memory-repo/property.js +56 -0
  155. package/dist/repo/memory-repo/property.js.map +1 -0
  156. package/dist/repo/memory-repo/shared.d.ts +28 -0
  157. package/dist/repo/memory-repo/shared.d.ts.map +1 -0
  158. package/dist/repo/memory-repo/shared.js +63 -0
  159. package/dist/repo/memory-repo/shared.js.map +1 -0
  160. package/dist/repo/memory-repo/source.d.ts +4 -0
  161. package/dist/repo/memory-repo/source.d.ts.map +1 -0
  162. package/dist/repo/memory-repo/source.js +58 -0
  163. package/dist/repo/memory-repo/source.js.map +1 -0
  164. package/dist/repo/memory-repo.d.ts +14 -10
  165. package/dist/repo/memory-repo.d.ts.map +1 -1
  166. package/dist/repo/memory-repo.js +8 -527
  167. package/dist/repo/memory-repo.js.map +1 -1
  168. package/dist/repo/message-repo.d.ts.map +1 -1
  169. package/dist/repo/message-repo.js +9 -8
  170. package/dist/repo/message-repo.js.map +1 -1
  171. package/dist/repo/orchestrator-state-repo.d.ts.map +1 -1
  172. package/dist/repo/orchestrator-state-repo.js +2 -1
  173. package/dist/repo/orchestrator-state-repo.js.map +1 -1
  174. package/dist/repo/pin-repo.d.ts.map +1 -1
  175. package/dist/repo/pin-repo.js +5 -4
  176. package/dist/repo/pin-repo.js.map +1 -1
  177. package/dist/repo/run-repo.d.ts.map +1 -1
  178. package/dist/repo/run-repo.js +11 -10
  179. package/dist/repo/run-repo.js.map +1 -1
  180. package/dist/repo/spec-trace-repo.d.ts +9 -0
  181. package/dist/repo/spec-trace-repo.d.ts.map +1 -0
  182. package/dist/repo/spec-trace-repo.filter.d.ts +3 -0
  183. package/dist/repo/spec-trace-repo.filter.d.ts.map +1 -0
  184. package/dist/repo/spec-trace-repo.filter.js +13 -0
  185. package/dist/repo/spec-trace-repo.filter.js.map +1 -0
  186. package/dist/repo/spec-trace-repo.js +323 -0
  187. package/dist/repo/spec-trace-repo.js.map +1 -0
  188. package/dist/repo/spec-trace-repo.types.d.ts +60 -0
  189. package/dist/repo/spec-trace-repo.types.d.ts.map +1 -0
  190. package/dist/repo/spec-trace-repo.types.js +2 -0
  191. package/dist/repo/spec-trace-repo.types.js.map +1 -0
  192. package/dist/repo/task-repo/factory.d.ts +4 -0
  193. package/dist/repo/task-repo/factory.d.ts.map +1 -0
  194. package/dist/repo/task-repo/factory.js +7 -0
  195. package/dist/repo/task-repo/factory.js.map +1 -0
  196. package/dist/repo/task-repo/read.d.ts +6 -0
  197. package/dist/repo/task-repo/read.d.ts.map +1 -0
  198. package/dist/repo/task-repo/read.js +332 -0
  199. package/dist/repo/task-repo/read.js.map +1 -0
  200. package/dist/repo/task-repo/shared.d.ts +10 -0
  201. package/dist/repo/task-repo/shared.d.ts.map +1 -0
  202. package/dist/repo/task-repo/shared.js +29 -0
  203. package/dist/repo/task-repo/shared.js.map +1 -0
  204. package/dist/repo/task-repo/write.d.ts +6 -0
  205. package/dist/repo/task-repo/write.d.ts.map +1 -0
  206. package/dist/repo/task-repo/write.js +182 -0
  207. package/dist/repo/task-repo/write.js.map +1 -0
  208. package/dist/repo/task-repo.d.ts +5 -4
  209. package/dist/repo/task-repo.d.ts.map +1 -1
  210. package/dist/repo/task-repo.js +2 -520
  211. package/dist/repo/task-repo.js.map +1 -1
  212. package/dist/repo/tracked-project-repo.d.ts.map +1 -1
  213. package/dist/repo/tracked-project-repo.js +6 -5
  214. package/dist/repo/tracked-project-repo.js.map +1 -1
  215. package/dist/repo/worker-repo.d.ts.map +1 -1
  216. package/dist/repo/worker-repo.js +60 -47
  217. package/dist/repo/worker-repo.js.map +1 -1
  218. package/dist/schemas/index.d.ts +4 -2
  219. package/dist/schemas/index.d.ts.map +1 -1
  220. package/dist/schemas/index.js +2 -1
  221. package/dist/schemas/index.js.map +1 -1
  222. package/dist/schemas/sync-events.d.ts +25 -0
  223. package/dist/schemas/sync-events.d.ts.map +1 -0
  224. package/dist/schemas/sync-events.js +23 -0
  225. package/dist/schemas/sync-events.js.map +1 -0
  226. package/dist/schemas/sync.d.ts +20 -10
  227. package/dist/schemas/sync.d.ts.map +1 -1
  228. package/dist/schemas/sync.js +10 -4
  229. package/dist/schemas/sync.js.map +1 -1
  230. package/dist/services/agent-service.d.ts +4 -4
  231. package/dist/services/agent-service.d.ts.map +1 -1
  232. package/dist/services/agent-service.js.map +1 -1
  233. package/dist/services/anchor/anchor-service-core-ops.d.ts +125 -0
  234. package/dist/services/anchor/anchor-service-core-ops.d.ts.map +1 -0
  235. package/dist/services/anchor/anchor-service-core-ops.js +41 -0
  236. package/dist/services/anchor/anchor-service-core-ops.js.map +1 -0
  237. package/dist/services/anchor/anchor-service-deps.d.ts +10 -0
  238. package/dist/services/anchor/anchor-service-deps.d.ts.map +1 -0
  239. package/dist/services/anchor/anchor-service-deps.js +2 -0
  240. package/dist/services/anchor/anchor-service-deps.js.map +1 -0
  241. package/dist/services/anchor/anchor-service-ops.d.ts +296 -0
  242. package/dist/services/anchor/anchor-service-ops.d.ts.map +1 -0
  243. package/dist/services/anchor/anchor-service-ops.js +9 -0
  244. package/dist/services/anchor/anchor-service-ops.js.map +1 -0
  245. package/dist/services/anchor/anchor-service-state-ops.d.ts +116 -0
  246. package/dist/services/anchor/anchor-service-state-ops.d.ts.map +1 -0
  247. package/dist/services/anchor/anchor-service-state-ops.js +150 -0
  248. package/dist/services/anchor/anchor-service-state-ops.js.map +1 -0
  249. package/dist/services/anchor/anchor-service-validation.d.ts +7 -0
  250. package/dist/services/anchor/anchor-service-validation.d.ts.map +1 -0
  251. package/dist/services/anchor/anchor-service-validation.js +114 -0
  252. package/dist/services/anchor/anchor-service-validation.js.map +1 -0
  253. package/dist/services/anchor/anchor-service-verification-ops.d.ts +71 -0
  254. package/dist/services/anchor/anchor-service-verification-ops.d.ts.map +1 -0
  255. package/dist/services/anchor/anchor-service-verification-ops.js +169 -0
  256. package/dist/services/anchor/anchor-service-verification-ops.js.map +1 -0
  257. package/dist/services/anchor/anchor-verification-batch.d.ts +12 -0
  258. package/dist/services/anchor/anchor-verification-batch.d.ts.map +1 -0
  259. package/dist/services/anchor/anchor-verification-batch.js +109 -0
  260. package/dist/services/anchor/anchor-verification-batch.js.map +1 -0
  261. package/dist/services/anchor/anchor-verification-single.d.ts +7 -0
  262. package/dist/services/anchor/anchor-verification-single.d.ts.map +1 -0
  263. package/dist/services/anchor/anchor-verification-single.js +407 -0
  264. package/dist/services/anchor/anchor-verification-single.js.map +1 -0
  265. package/dist/services/anchor/anchor-verification-utils.d.ts +19 -0
  266. package/dist/services/anchor/anchor-verification-utils.d.ts.map +1 -0
  267. package/dist/services/anchor/anchor-verification-utils.js +107 -0
  268. package/dist/services/anchor/anchor-verification-utils.js.map +1 -0
  269. package/dist/services/anchor-service.d.ts +12 -90
  270. package/dist/services/anchor-service.d.ts.map +1 -1
  271. package/dist/services/anchor-service.js +5 -530
  272. package/dist/services/anchor-service.js.map +1 -1
  273. package/dist/services/anchor-verification.d.ts +9 -60
  274. package/dist/services/anchor-verification.d.ts.map +1 -1
  275. package/dist/services/anchor-verification.js +5 -796
  276. package/dist/services/anchor-verification.js.map +1 -1
  277. package/dist/services/ast-grep-service/patterns.d.ts +90 -0
  278. package/dist/services/ast-grep-service/patterns.d.ts.map +1 -0
  279. package/dist/services/ast-grep-service/patterns.js +261 -0
  280. package/dist/services/ast-grep-service/patterns.js.map +1 -0
  281. package/dist/services/ast-grep-service.d.ts +2 -13
  282. package/dist/services/ast-grep-service.d.ts.map +1 -1
  283. package/dist/services/ast-grep-service.js +3 -261
  284. package/dist/services/ast-grep-service.js.map +1 -1
  285. package/dist/services/auto-sync-service.d.ts +3 -3
  286. package/dist/services/auto-sync-service.d.ts.map +1 -1
  287. package/dist/services/auto-sync-service.js +12 -13
  288. package/dist/services/auto-sync-service.js.map +1 -1
  289. package/dist/services/compaction-service.d.ts +6 -6
  290. package/dist/services/compaction-service.d.ts.map +1 -1
  291. package/dist/services/compaction-service.js +11 -7
  292. package/dist/services/compaction-service.js.map +1 -1
  293. package/dist/services/cycle-scan-service.d.ts +1 -27
  294. package/dist/services/cycle-scan-service.d.ts.map +1 -1
  295. package/dist/services/cycle-scan-service.js +1 -876
  296. package/dist/services/cycle-scan-service.js.map +1 -1
  297. package/dist/services/daemon-service/process.d.ts +93 -0
  298. package/dist/services/daemon-service/process.d.ts.map +1 -0
  299. package/dist/services/daemon-service/process.js +325 -0
  300. package/dist/services/daemon-service/process.js.map +1 -0
  301. package/dist/services/daemon-service/templates.d.ts +88 -0
  302. package/dist/services/daemon-service/templates.d.ts.map +1 -0
  303. package/dist/services/daemon-service/templates.js +119 -0
  304. package/dist/services/daemon-service/templates.js.map +1 -0
  305. package/dist/services/daemon-service.d.ts +8 -160
  306. package/dist/services/daemon-service.d.ts.map +1 -1
  307. package/dist/services/daemon-service.js +4 -440
  308. package/dist/services/daemon-service.js.map +1 -1
  309. package/dist/services/doc-service.d.ts +1 -41
  310. package/dist/services/doc-service.d.ts.map +1 -1
  311. package/dist/services/doc-service.js +1 -780
  312. package/dist/services/doc-service.js.map +1 -1
  313. package/dist/services/edge-service.d.ts +6 -6
  314. package/dist/services/edge-service.d.ts.map +1 -1
  315. package/dist/services/edge-service.js.map +1 -1
  316. package/dist/services/embedding-service.d.ts +1 -201
  317. package/dist/services/embedding-service.d.ts.map +1 -1
  318. package/dist/services/embedding-service.js +1 -465
  319. package/dist/services/embedding-service.js.map +1 -1
  320. package/dist/services/feedback-tracker.d.ts +2 -2
  321. package/dist/services/feedback-tracker.d.ts.map +1 -1
  322. package/dist/services/feedback-tracker.js.map +1 -1
  323. package/dist/services/file-watcher-service/shared.d.ts +76 -0
  324. package/dist/services/file-watcher-service/shared.d.ts.map +1 -0
  325. package/dist/services/file-watcher-service/shared.js +43 -0
  326. package/dist/services/file-watcher-service/shared.js.map +1 -0
  327. package/dist/services/file-watcher-service.d.ts +2 -42
  328. package/dist/services/file-watcher-service.d.ts.map +1 -1
  329. package/dist/services/file-watcher-service.js +1 -46
  330. package/dist/services/file-watcher-service.js.map +1 -1
  331. package/dist/services/graph-expansion/from-files.d.ts +14 -0
  332. package/dist/services/graph-expansion/from-files.d.ts.map +1 -0
  333. package/dist/services/graph-expansion/from-files.js +187 -0
  334. package/dist/services/graph-expansion/from-files.js.map +1 -0
  335. package/dist/services/graph-expansion/live.d.ts +11 -0
  336. package/dist/services/graph-expansion/live.d.ts.map +1 -0
  337. package/dist/services/graph-expansion/live.js +263 -0
  338. package/dist/services/graph-expansion/live.js.map +1 -0
  339. package/dist/services/graph-expansion.d.ts +17 -20
  340. package/dist/services/graph-expansion.d.ts.map +1 -1
  341. package/dist/services/graph-expansion.js +2 -439
  342. package/dist/services/graph-expansion.js.map +1 -1
  343. package/dist/services/guard-service.d.ts +2 -2
  344. package/dist/services/guard-service.d.ts.map +1 -1
  345. package/dist/services/guard-service.js.map +1 -1
  346. package/dist/services/index.d.ts +3 -1
  347. package/dist/services/index.d.ts.map +1 -1
  348. package/dist/services/index.js +3 -1
  349. package/dist/services/index.js.map +1 -1
  350. package/dist/services/learning-service.d.ts +4 -4
  351. package/dist/services/learning-service.d.ts.map +1 -1
  352. package/dist/services/learning-service.js.map +1 -1
  353. package/dist/services/llm-service.d.ts +4 -4
  354. package/dist/services/llm-service.d.ts.map +1 -1
  355. package/dist/services/llm-service.js.map +1 -1
  356. package/dist/services/memory-retriever-service.d.ts.map +1 -1
  357. package/dist/services/memory-retriever-service.js.map +1 -1
  358. package/dist/services/memory-service.d.ts +1 -48
  359. package/dist/services/memory-service.d.ts.map +1 -1
  360. package/dist/services/memory-service.js +1 -1060
  361. package/dist/services/memory-service.js.map +1 -1
  362. package/dist/services/migration-service.d.ts +6 -6
  363. package/dist/services/migration-service.d.ts.map +1 -1
  364. package/dist/services/migration-service.js +6 -2
  365. package/dist/services/migration-service.js.map +1 -1
  366. package/dist/services/orchestrator-service.d.ts +2 -2
  367. package/dist/services/orchestrator-service.d.ts.map +1 -1
  368. package/dist/services/orchestrator-service.js.map +1 -1
  369. package/dist/services/pin-service.d.ts.map +1 -1
  370. package/dist/services/pin-service.js +21 -28
  371. package/dist/services/pin-service.js.map +1 -1
  372. package/dist/services/promotion-service.d.ts +4 -4
  373. package/dist/services/promotion-service.d.ts.map +1 -1
  374. package/dist/services/promotion-service.js.map +1 -1
  375. package/dist/services/query-expansion-service.d.ts +2 -2
  376. package/dist/services/query-expansion-service.d.ts.map +1 -1
  377. package/dist/services/query-expansion-service.js.map +1 -1
  378. package/dist/services/reflect-service.d.ts +6 -6
  379. package/dist/services/reflect-service.d.ts.map +1 -1
  380. package/dist/services/reflect-service.js.map +1 -1
  381. package/dist/services/reranker-service.d.ts +2 -2
  382. package/dist/services/reranker-service.d.ts.map +1 -1
  383. package/dist/services/reranker-service.js.map +1 -1
  384. package/dist/services/retriever-scoring.d.ts +52 -0
  385. package/dist/services/retriever-scoring.d.ts.map +1 -0
  386. package/dist/services/retriever-scoring.js +146 -0
  387. package/dist/services/retriever-scoring.js.map +1 -0
  388. package/dist/services/retriever-service.d.ts.map +1 -1
  389. package/dist/services/retriever-service.js +1 -191
  390. package/dist/services/retriever-service.js.map +1 -1
  391. package/dist/services/run-heartbeat-service.d.ts +10 -10
  392. package/dist/services/run-heartbeat-service.d.ts.map +1 -1
  393. package/dist/services/run-heartbeat-service.js.map +1 -1
  394. package/dist/services/score-service.d.ts +2 -2
  395. package/dist/services/score-service.d.ts.map +1 -1
  396. package/dist/services/score-service.js.map +1 -1
  397. package/dist/services/spec-trace-service.d.ts +2 -0
  398. package/dist/services/spec-trace-service.d.ts.map +1 -0
  399. package/dist/services/spec-trace-service.js +2 -0
  400. package/dist/services/spec-trace-service.js.map +1 -0
  401. package/dist/services/stream-service.d.ts +31 -0
  402. package/dist/services/stream-service.d.ts.map +1 -0
  403. package/dist/services/stream-service.js +162 -0
  404. package/dist/services/stream-service.js.map +1 -0
  405. package/dist/services/swarm-verification/shared.d.ts +71 -0
  406. package/dist/services/swarm-verification/shared.d.ts.map +1 -0
  407. package/dist/services/swarm-verification/shared.js +108 -0
  408. package/dist/services/swarm-verification/shared.js.map +1 -0
  409. package/dist/services/swarm-verification.d.ts +4 -68
  410. package/dist/services/swarm-verification.d.ts.map +1 -1
  411. package/dist/services/swarm-verification.js +2 -122
  412. package/dist/services/swarm-verification.js.map +1 -1
  413. package/dist/services/sync/converters.d.ts +63 -0
  414. package/dist/services/sync/converters.d.ts.map +1 -0
  415. package/dist/services/sync/converters.js +253 -0
  416. package/dist/services/sync/converters.js.map +1 -0
  417. package/dist/services/sync/entity-export.d.ts +22 -0
  418. package/dist/services/sync/entity-export.d.ts.map +1 -0
  419. package/dist/services/sync/entity-export.js +15 -0
  420. package/dist/services/sync/entity-export.js.map +1 -0
  421. package/dist/services/sync/entity-import.d.ts +22 -0
  422. package/dist/services/sync/entity-import.d.ts.map +1 -0
  423. package/dist/services/sync/entity-import.js +15 -0
  424. package/dist/services/sync/entity-import.js.map +1 -0
  425. package/dist/services/sync/file-utils.d.ts +23 -0
  426. package/dist/services/sync/file-utils.d.ts.map +1 -0
  427. package/dist/services/sync/file-utils.js +97 -0
  428. package/dist/services/sync/file-utils.js.map +1 -0
  429. package/dist/services/sync/index.d.ts +3 -0
  430. package/dist/services/sync/index.d.ts.map +1 -0
  431. package/dist/services/sync/index.js +2 -0
  432. package/dist/services/sync/index.js.map +1 -0
  433. package/dist/services/sync/service.d.ts +2 -0
  434. package/dist/services/sync/service.d.ts.map +1 -0
  435. package/dist/services/sync/service.js +2 -0
  436. package/dist/services/sync/service.js.map +1 -0
  437. package/dist/services/sync/sync-helpers.d.ts +54 -0
  438. package/dist/services/sync/sync-helpers.d.ts.map +1 -0
  439. package/dist/services/sync/sync-helpers.js +245 -0
  440. package/dist/services/sync/sync-helpers.js.map +1 -0
  441. package/dist/services/sync/types.d.ts +104 -0
  442. package/dist/services/sync/types.d.ts.map +1 -0
  443. package/dist/services/sync/types.js +5 -0
  444. package/dist/services/sync/types.js.map +1 -0
  445. package/dist/services/task-service/internals.d.ts +36 -0
  446. package/dist/services/task-service/internals.d.ts.map +1 -0
  447. package/dist/services/task-service/internals.js +270 -0
  448. package/dist/services/task-service/internals.js.map +1 -0
  449. package/dist/services/task-service.d.ts +2 -1
  450. package/dist/services/task-service.d.ts.map +1 -1
  451. package/dist/services/task-service.js +28 -236
  452. package/dist/services/task-service.js.map +1 -1
  453. package/dist/services/tracing-service.d.ts +2 -2
  454. package/dist/services/tracing-service.d.ts.map +1 -1
  455. package/dist/services/tracing-service.js.map +1 -1
  456. package/dist/services/transcript-adapter.d.ts +6 -6
  457. package/dist/services/transcript-adapter.d.ts.map +1 -1
  458. package/dist/services/transcript-adapter.js +3 -8
  459. package/dist/services/transcript-adapter.js.map +1 -1
  460. package/dist/services/validation-service.d.ts +8 -8
  461. package/dist/services/validation-service.d.ts.map +1 -1
  462. package/dist/services/validation-service.js.map +1 -1
  463. package/dist/services/verify-service.d.ts +2 -2
  464. package/dist/services/verify-service.d.ts.map +1 -1
  465. package/dist/services/verify-service.js.map +1 -1
  466. package/dist/services/worker-process/runtime.d.ts +51 -0
  467. package/dist/services/worker-process/runtime.d.ts.map +1 -0
  468. package/dist/services/worker-process/runtime.js +150 -0
  469. package/dist/services/worker-process/runtime.js.map +1 -0
  470. package/dist/services/worker-process.d.ts +3 -18
  471. package/dist/services/worker-process.d.ts.map +1 -1
  472. package/dist/services/worker-process.js +3 -173
  473. package/dist/services/worker-process.js.map +1 -1
  474. package/dist/services/worker-service.d.ts +6 -6
  475. package/dist/services/worker-service.d.ts.map +1 -1
  476. package/dist/services/worker-service.js.map +1 -1
  477. package/dist/utils/db-result.d.ts +14 -0
  478. package/dist/utils/db-result.d.ts.map +1 -0
  479. package/dist/utils/db-result.js +37 -0
  480. package/dist/utils/db-result.js.map +1 -0
  481. package/dist/utils/doc-renderer.d.ts +10 -10
  482. package/dist/utils/doc-renderer.d.ts.map +1 -1
  483. package/dist/utils/doc-renderer.js.map +1 -1
  484. package/dist/utils/ears-validator.d.ts +2 -2
  485. package/dist/utils/ears-validator.d.ts.map +1 -1
  486. package/dist/utils/ears-validator.js.map +1 -1
  487. package/dist/utils/file-path.d.ts +27 -0
  488. package/dist/utils/file-path.d.ts.map +1 -0
  489. package/dist/utils/file-path.js +77 -0
  490. package/dist/utils/file-path.js.map +1 -0
  491. package/dist/utils/glob.d.ts +2 -11
  492. package/dist/utils/glob.d.ts.map +1 -1
  493. package/dist/utils/glob.js +22 -13
  494. package/dist/utils/glob.js.map +1 -1
  495. package/dist/utils/spec-discovery.d.ts +34 -0
  496. package/dist/utils/spec-discovery.d.ts.map +1 -0
  497. package/dist/utils/spec-discovery.js +344 -0
  498. package/dist/utils/spec-discovery.js.map +1 -0
  499. package/dist/utils/toml-config.d.ts +7 -2
  500. package/dist/utils/toml-config.d.ts.map +1 -1
  501. package/dist/utils/toml-config.js +106 -2
  502. package/dist/utils/toml-config.js.map +1 -1
  503. package/dist/utils/ulid.d.ts +8 -0
  504. package/dist/utils/ulid.d.ts.map +1 -0
  505. package/dist/utils/ulid.js +30 -0
  506. package/dist/utils/ulid.js.map +1 -0
  507. package/dist/worker/hooks.d.ts +10 -10
  508. package/dist/worker/hooks.d.ts.map +1 -1
  509. package/dist/worker/run-worker.d.ts.map +1 -1
  510. package/dist/worker/run-worker.js.map +1 -1
  511. package/migrations/033_sync_events.sql +33 -0
  512. package/migrations/034_spec_test_traceability.sql +51 -0
  513. package/migrations/035_anchor_schema_repair.sql +82 -0
  514. package/package.json +3 -2
  515. package/dist/services/sync-service.d.ts +0 -247
  516. package/dist/services/sync-service.d.ts.map +0 -1
  517. package/dist/services/sync-service.js.map +0 -1
@@ -0,0 +1,812 @@
1
+ /**
2
+ * DocService — business logic for docs-as-primitives (DD-023).
3
+ *
4
+ * Manages doc lifecycle (create/update/lock/version), rendering (YAML→MD),
5
+ * linking (doc-doc, task-doc), invariant sync, drift detection, and graph data.
6
+ *
7
+ * YAML content lives on disk (.tx/docs/); DB stores metadata + links only.
8
+ */
9
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, } from "node:fs";
10
+ import { resolve, dirname, join } from "node:path";
11
+ import { Cause, Context, Effect, Layer, Option } from "effect";
12
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
13
+ import { DocRepository } from "../repo/doc-repo.js";
14
+ import { ValidationError, DocNotFoundError, DocLockedError, InvalidDocYamlError, InvariantNotFoundError, } from "../errors.js";
15
+ import { computeDocHash } from "../utils/doc-hash.js";
16
+ import { renderDocToMarkdown, renderIndexToMarkdown, } from "../utils/doc-renderer.js";
17
+ import { formatEarsValidationErrors, validateEarsRequirements, } from "../utils/ears-validator.js";
18
+ import { readTxConfig } from "../utils/toml-config.js";
19
+ import { resolvePathWithin } from "../utils/file-path.js";
20
+ import { DOC_KINDS, INVARIANT_ENFORCEMENT_TYPES, } from "@jamesaphoenix/tx-types";
21
+ // Local string arrays for .includes() (avoids readonly cast)
22
+ const docKindStrings = DOC_KINDS;
23
+ const enforcementStrings = INVARIANT_ENFORCEMENT_TYPES;
24
+ /** Infer link type from doc kinds (from → to). */
25
+ const inferLinkType = (fromKind, toKind) => {
26
+ if (fromKind === "overview" && toKind === "prd")
27
+ return "overview_to_prd";
28
+ if (fromKind === "overview" && toKind === "design")
29
+ return "overview_to_design";
30
+ if (fromKind === "prd" && toKind === "design")
31
+ return "prd_to_design";
32
+ return null;
33
+ };
34
+ /** Get the subdirectory for a doc kind. overview lives at root. */
35
+ const kindSubdir = (kind) => {
36
+ if (kind === "overview")
37
+ return "";
38
+ return kind;
39
+ };
40
+ /** Resolve the YAML file path for a doc. */
41
+ const resolveYamlPath = (docsPath, kind, name) => {
42
+ const sub = kindSubdir(kind);
43
+ const relativeDocPath = sub ? join(sub, `${name}.yml`) : `${name}.yml`;
44
+ const resolvedDocPath = resolvePathWithin(docsPath, relativeDocPath, {
45
+ useRealpath: true,
46
+ });
47
+ if (!resolvedDocPath) {
48
+ throw new ValidationError({
49
+ reason: `Invalid doc path for name '${name}'`,
50
+ });
51
+ }
52
+ return resolvedDocPath;
53
+ };
54
+ /** Resolve the MD file path for a doc. */
55
+ const resolveMdPath = (docsPath, kind, name) => {
56
+ const sub = kindSubdir(kind);
57
+ const relativeDocPath = sub ? join(sub, `${name}.md`) : `${name}.md`;
58
+ const resolvedDocPath = resolvePathWithin(docsPath, relativeDocPath, {
59
+ useRealpath: true,
60
+ });
61
+ if (!resolvedDocPath) {
62
+ throw new ValidationError({
63
+ reason: `Invalid doc path for name '${name}'`,
64
+ });
65
+ }
66
+ return resolvedDocPath;
67
+ };
68
+ const collectLegacyRequirements = (value) => {
69
+ const normalize = (item) => {
70
+ const stripped = item
71
+ .trim()
72
+ .replace(/^[-*]\s+/, "")
73
+ .replace(/^\d+\.\s+/, "")
74
+ .trim();
75
+ return stripped.length > 0 ? stripped : null;
76
+ };
77
+ if (Array.isArray(value)) {
78
+ const out = [];
79
+ for (const item of value) {
80
+ if (typeof item !== "string")
81
+ continue;
82
+ const normalized = normalize(item);
83
+ if (!normalized)
84
+ continue;
85
+ out.push(normalized);
86
+ }
87
+ return out;
88
+ }
89
+ if (typeof value === "string") {
90
+ const out = [];
91
+ for (const line of value.split(/\r?\n/)) {
92
+ const normalized = normalize(line);
93
+ if (!normalized)
94
+ continue;
95
+ out.push(normalized);
96
+ }
97
+ return out;
98
+ }
99
+ return [];
100
+ };
101
+ const isEarsRequiredForLegacyPrds = () => readTxConfig().docs.requireEars;
102
+ /** Validate YAML content and return parsed object. */
103
+ const validateYaml = (name, content, expectedKind) => {
104
+ let parsed;
105
+ try {
106
+ parsed = parseYaml(content);
107
+ }
108
+ catch (e) {
109
+ throw new InvalidDocYamlError({
110
+ name,
111
+ reason: `YAML parse error: ${String(e)}`,
112
+ });
113
+ }
114
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
115
+ throw new InvalidDocYamlError({
116
+ name,
117
+ reason: "YAML must be an object (not array or scalar)",
118
+ });
119
+ }
120
+ const parsedObject = parsed;
121
+ const yamlKind = typeof parsedObject.kind === "string" && docKindStrings.includes(parsedObject.kind)
122
+ ? parsedObject.kind
123
+ : null;
124
+ const effectiveKind = expectedKind ?? yamlKind;
125
+ if (effectiveKind === "prd" && parsedObject.ears_requirements !== undefined) {
126
+ if (!Array.isArray(parsedObject.ears_requirements)) {
127
+ throw new InvalidDocYamlError({
128
+ name,
129
+ reason: "EARS: 'ears_requirements' must be an array",
130
+ });
131
+ }
132
+ const errors = validateEarsRequirements(parsedObject.ears_requirements);
133
+ if (errors.length > 0) {
134
+ throw new InvalidDocYamlError({
135
+ name,
136
+ reason: `EARS: ${formatEarsValidationErrors(errors)}`,
137
+ earsErrors: errors,
138
+ });
139
+ }
140
+ }
141
+ if (effectiveKind === "prd" &&
142
+ isEarsRequiredForLegacyPrds() &&
143
+ collectLegacyRequirements(parsedObject.requirements).length > 0 &&
144
+ (!Array.isArray(parsedObject.ears_requirements) ||
145
+ parsedObject.ears_requirements.length === 0)) {
146
+ throw new InvalidDocYamlError({
147
+ name,
148
+ reason: "EARS: PRDs with legacy 'requirements' must also define a non-empty " +
149
+ "'ears_requirements' array while [docs].require_ears = true. " +
150
+ "Set [docs].require_ears = false to opt out.",
151
+ });
152
+ }
153
+ return parsedObject;
154
+ };
155
+ /** Validate doc kind from YAML. */
156
+ const validateKind = (name, parsed, expectedKind) => {
157
+ const yamlKind = parsed.kind;
158
+ if (yamlKind && typeof yamlKind === "string" && yamlKind !== expectedKind) {
159
+ throw new InvalidDocYamlError({
160
+ name,
161
+ reason: `YAML kind '${yamlKind}' does not match expected kind '${expectedKind}'`,
162
+ });
163
+ }
164
+ };
165
+ const normalizeInvariantSegment = (value) => {
166
+ const normalized = value
167
+ .toUpperCase()
168
+ .replace(/[^A-Z0-9]+/g, "-")
169
+ .replace(/^-+|-+$/g, "")
170
+ .replace(/-+/g, "-");
171
+ return normalized.length > 0 ? normalized : "DOC";
172
+ };
173
+ const collectStringList = (value) => {
174
+ return collectLegacyRequirements(value);
175
+ };
176
+ const extractSubsystemFromEarsId = (id) => {
177
+ const match = /^EARS-([A-Z0-9]+)-\d{3}$/.exec(id);
178
+ return match?.[1]?.toLowerCase();
179
+ };
180
+ const extractExplicitInvariants = (raw) => {
181
+ if (!Array.isArray(raw))
182
+ return [];
183
+ const candidates = [];
184
+ for (const item of raw) {
185
+ if (typeof item !== "object" || item === null)
186
+ continue;
187
+ const inv = item;
188
+ const id = typeof inv.id === "string" ? inv.id : null;
189
+ const rule = typeof inv.rule === "string" ? inv.rule : null;
190
+ const enforcement = typeof inv.enforcement === "string" ? inv.enforcement : null;
191
+ if (!id || !rule || !enforcement)
192
+ continue;
193
+ if (!enforcementStrings.includes(enforcement))
194
+ continue;
195
+ candidates.push({
196
+ id,
197
+ rule,
198
+ enforcement,
199
+ subsystem: typeof inv.subsystem === "string"
200
+ ? inv.subsystem
201
+ : inv.subsystem === null
202
+ ? null
203
+ : undefined,
204
+ testRef: typeof inv.test_ref === "string" ? inv.test_ref : undefined,
205
+ lintRule: typeof inv.lint_rule === "string" ? inv.lint_rule : undefined,
206
+ promptRef: typeof inv.prompt_ref === "string" ? inv.prompt_ref : undefined,
207
+ });
208
+ }
209
+ return candidates;
210
+ };
211
+ const deriveEarsInvariants = (doc, parsed) => {
212
+ if (doc.kind !== "prd")
213
+ return [];
214
+ const raw = parsed.ears_requirements;
215
+ if (!Array.isArray(raw))
216
+ return [];
217
+ const candidates = [];
218
+ for (const item of raw) {
219
+ if (typeof item !== "object" || item === null)
220
+ continue;
221
+ const req = item;
222
+ const earsId = typeof req.id === "string" ? req.id : null;
223
+ const system = typeof req.system === "string" ? req.system.trim() : "";
224
+ const response = typeof req.response === "string" ? req.response.trim() : "";
225
+ if (!earsId || !system || !response)
226
+ continue;
227
+ candidates.push({
228
+ id: `INV-${earsId}`,
229
+ rule: `${system} shall ${response}`,
230
+ enforcement: "integration_test",
231
+ subsystem: extractSubsystemFromEarsId(earsId),
232
+ testRef: typeof req.test_hint === "string" ? req.test_hint : undefined,
233
+ });
234
+ }
235
+ return candidates;
236
+ };
237
+ const derivePrdRequirementInvariants = (doc, parsed) => {
238
+ if (doc.kind !== "prd")
239
+ return [];
240
+ const requirements = collectStringList(parsed.requirements);
241
+ if (requirements.length === 0)
242
+ return [];
243
+ const docSegment = normalizeInvariantSegment(doc.name);
244
+ return requirements.map((rule, index) => ({
245
+ id: `INV-PRD-${docSegment}-REQ-${String(index + 1).padStart(3, "0")}`,
246
+ rule,
247
+ enforcement: "integration_test",
248
+ subsystem: "prd",
249
+ }));
250
+ };
251
+ const deriveDesignGoalInvariants = (doc, parsed) => {
252
+ if (doc.kind !== "design")
253
+ return [];
254
+ const goals = collectStringList(parsed.goals);
255
+ if (goals.length === 0)
256
+ return [];
257
+ const docSegment = normalizeInvariantSegment(doc.name);
258
+ return goals.map((rule, index) => ({
259
+ id: `INV-DESIGN-${docSegment}-GOAL-${String(index + 1).padStart(3, "0")}`,
260
+ rule,
261
+ enforcement: "integration_test",
262
+ subsystem: "design",
263
+ }));
264
+ };
265
+ export class DocService extends Context.Tag("DocService")() {
266
+ }
267
+ export const DocServiceLive = Layer.effect(DocService, Effect.gen(function* () {
268
+ const docRepo = yield* DocRepository;
269
+ const getDocsPath = () => {
270
+ const config = readTxConfig();
271
+ return resolve(config.docs.path);
272
+ };
273
+ const ensureDir = (filePath) => {
274
+ const dir = dirname(filePath);
275
+ if (!existsSync(dir)) {
276
+ mkdirSync(dir, { recursive: true });
277
+ }
278
+ };
279
+ /** Render a single doc and return its MD file path. */
280
+ const renderSingleDoc = (doc, docsPath) => {
281
+ const yamlPath = resolveYamlPath(docsPath, doc.kind, doc.name);
282
+ if (!existsSync(yamlPath)) {
283
+ throw new DocNotFoundError({ name: doc.name });
284
+ }
285
+ const yamlContent = readFileSync(yamlPath, "utf8");
286
+ const parsed = validateYaml(doc.name, yamlContent, doc.kind);
287
+ const md = renderDocToMarkdown(parsed, doc.kind);
288
+ const mdPath = resolveMdPath(docsPath, doc.kind, doc.name);
289
+ ensureDir(mdPath);
290
+ writeFileSync(mdPath, md, "utf8");
291
+ return mdPath;
292
+ };
293
+ /** Generate index.yml and index.md from all docs in DB. */
294
+ function generateIndexEffect(docsPath) {
295
+ return Effect.gen(function* () {
296
+ const allDocs = yield* docRepo.findAll();
297
+ const allLinks = yield* docRepo.getAllLinks();
298
+ const overviewDoc = allDocs.find((d) => d.kind === "overview");
299
+ const prds = allDocs
300
+ .filter((d) => d.kind === "prd")
301
+ .map((d) => ({ name: d.name, title: d.title, status: d.status }));
302
+ const designDocs = allDocs
303
+ .filter((d) => d.kind === "design")
304
+ .map((d) => {
305
+ const implLink = allLinks.find((l) => l.toDocId === d.id && l.linkType === "prd_to_design");
306
+ const implDoc = implLink
307
+ ? allDocs.find((dd) => dd.id === implLink.fromDocId)
308
+ : undefined;
309
+ return {
310
+ name: d.name,
311
+ title: d.title,
312
+ status: d.status,
313
+ implements: implDoc?.name,
314
+ };
315
+ });
316
+ const links = allLinks.map((l) => {
317
+ const from = allDocs.find((d) => d.id === l.fromDocId);
318
+ const to = allDocs.find((d) => d.id === l.toDocId);
319
+ return {
320
+ from: from?.name ?? String(l.fromDocId),
321
+ to: to?.name ?? String(l.toDocId),
322
+ type: l.linkType,
323
+ };
324
+ });
325
+ // Invariant summary
326
+ const allInvariants = yield* docRepo.findInvariants();
327
+ const activeInvariants = allInvariants.filter((i) => i.status === "active");
328
+ const byEnforcement = {};
329
+ const bySubsystem = {};
330
+ for (const inv of activeInvariants) {
331
+ byEnforcement[inv.enforcement] =
332
+ (byEnforcement[inv.enforcement] ?? 0) + 1;
333
+ const sub = inv.subsystem ?? "system";
334
+ bySubsystem[sub] = (bySubsystem[sub] ?? 0) + 1;
335
+ }
336
+ const indexData = {
337
+ overview: overviewDoc?.name,
338
+ prds,
339
+ design_docs: designDocs,
340
+ links,
341
+ invariant_summary: activeInvariants.length > 0
342
+ ? {
343
+ total: activeInvariants.length,
344
+ by_enforcement: byEnforcement,
345
+ by_subsystem: bySubsystem,
346
+ }
347
+ : undefined,
348
+ };
349
+ // Write index.yml
350
+ const indexYamlObj = {
351
+ generated: true,
352
+ generated_at: new Date().toISOString(),
353
+ };
354
+ if (indexData.overview) {
355
+ indexYamlObj.overview = indexData.overview;
356
+ }
357
+ if (prds.length > 0) {
358
+ indexYamlObj.prds = prds.map((p) => ({
359
+ name: p.name,
360
+ title: p.title,
361
+ status: p.status,
362
+ }));
363
+ }
364
+ if (designDocs.length > 0) {
365
+ indexYamlObj.design_docs = designDocs.map((dd) => {
366
+ const entry = {
367
+ name: dd.name,
368
+ title: dd.title,
369
+ status: dd.status,
370
+ };
371
+ if (dd.implements)
372
+ entry.implements = dd.implements;
373
+ return entry;
374
+ });
375
+ }
376
+ const indexYamlPath = resolve(docsPath, "index.yml");
377
+ ensureDir(indexYamlPath);
378
+ writeFileSync(indexYamlPath, stringifyYaml(indexYamlObj), "utf8");
379
+ // Write index.md
380
+ const indexMd = renderIndexToMarkdown(indexData);
381
+ const indexMdPath = resolve(docsPath, "index.md");
382
+ writeFileSync(indexMdPath, indexMd, "utf8");
383
+ });
384
+ }
385
+ /** Sync invariants from a single doc's YAML into DB. */
386
+ function syncInvariantsForDoc(doc) {
387
+ return Effect.gen(function* () {
388
+ const docsPath = getDocsPath();
389
+ const yamlPath = resolveYamlPath(docsPath, doc.kind, doc.name);
390
+ if (!existsSync(yamlPath)) {
391
+ return [];
392
+ }
393
+ const yamlContent = readFileSync(yamlPath, "utf8");
394
+ const parsed = validateYaml(doc.name, yamlContent, doc.kind);
395
+ const explicit = extractExplicitInvariants(parsed.invariants);
396
+ const derived = [
397
+ ...deriveEarsInvariants(doc, parsed),
398
+ ...derivePrdRequirementInvariants(doc, parsed),
399
+ ...deriveDesignGoalInvariants(doc, parsed),
400
+ ];
401
+ const candidates = [];
402
+ const seen = new Set();
403
+ for (const candidate of [...explicit, ...derived]) {
404
+ if (seen.has(candidate.id))
405
+ continue;
406
+ candidates.push(candidate);
407
+ seen.add(candidate.id);
408
+ }
409
+ if (candidates.length === 0) {
410
+ yield* docRepo.deprecateInvariantsNotIn(doc.id, []);
411
+ return [];
412
+ }
413
+ const synced = [];
414
+ const activeIds = [];
415
+ for (const candidate of candidates) {
416
+ const input = {
417
+ id: candidate.id,
418
+ rule: candidate.rule,
419
+ enforcement: candidate.enforcement,
420
+ docId: doc.id,
421
+ subsystem: candidate.subsystem,
422
+ testRef: candidate.testRef,
423
+ lintRule: candidate.lintRule,
424
+ promptRef: candidate.promptRef,
425
+ };
426
+ const result = yield* docRepo.upsertInvariant(input);
427
+ synced.push(result);
428
+ activeIds.push(candidate.id);
429
+ }
430
+ yield* docRepo.deprecateInvariantsNotIn(doc.id, activeIds);
431
+ return synced;
432
+ });
433
+ }
434
+ return {
435
+ create: (input) => Effect.gen(function* () {
436
+ const { kind, name, title, yamlContent, metadata } = input;
437
+ if (!docKindStrings.includes(kind)) {
438
+ return yield* Effect.fail(new ValidationError({ reason: `Invalid doc kind: ${kind}` }));
439
+ }
440
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name)) {
441
+ return yield* Effect.fail(new ValidationError({
442
+ reason: `Invalid doc name: ${name}. Use alphanumeric with dashes/dots.`,
443
+ }));
444
+ }
445
+ const parsed = validateYaml(name, yamlContent, kind);
446
+ validateKind(name, parsed, kind);
447
+ const existing = yield* docRepo.findByName(name);
448
+ if (existing) {
449
+ return yield* Effect.fail(new ValidationError({
450
+ reason: `Doc '${name}' already exists (v${existing.version})`,
451
+ }));
452
+ }
453
+ const hash = computeDocHash(yamlContent);
454
+ const docsPath = getDocsPath();
455
+ const filePath = resolveYamlPath(docsPath, kind, name);
456
+ ensureDir(filePath);
457
+ writeFileSync(filePath, yamlContent, "utf8");
458
+ const relPath = kind === "overview" ? `${name}.yml` : join(kind, `${name}.yml`);
459
+ const doc = yield* docRepo.insert({
460
+ hash,
461
+ kind,
462
+ name,
463
+ title,
464
+ version: 1,
465
+ filePath: relPath,
466
+ parentDocId: null,
467
+ metadata: metadata ? JSON.stringify(metadata) : undefined,
468
+ });
469
+ try {
470
+ renderSingleDoc(doc, docsPath);
471
+ }
472
+ catch {
473
+ /* non-fatal */
474
+ }
475
+ yield* generateIndexEffect(docsPath);
476
+ return doc;
477
+ }),
478
+ get: (name, version) => Effect.gen(function* () {
479
+ const doc = yield* docRepo.findByName(name, version);
480
+ if (!doc) {
481
+ return yield* Effect.fail(new DocNotFoundError({ name }));
482
+ }
483
+ return doc;
484
+ }),
485
+ update: (name, yamlContent) => Effect.gen(function* () {
486
+ const doc = yield* docRepo.findByName(name);
487
+ if (!doc) {
488
+ return yield* Effect.fail(new DocNotFoundError({ name }));
489
+ }
490
+ if (doc.status === "locked") {
491
+ return yield* Effect.fail(new DocLockedError({ name, version: doc.version }));
492
+ }
493
+ const parsed = validateYaml(name, yamlContent, doc.kind);
494
+ validateKind(name, parsed, doc.kind);
495
+ const hash = computeDocHash(yamlContent);
496
+ const docsPath = getDocsPath();
497
+ const filePath = resolveYamlPath(docsPath, doc.kind, name);
498
+ ensureDir(filePath);
499
+ writeFileSync(filePath, yamlContent, "utf8");
500
+ const title = typeof parsed.title === "string" ? parsed.title : doc.title;
501
+ yield* docRepo.update(doc.id, { hash, title });
502
+ const updated = yield* docRepo.findById(doc.id);
503
+ if (!updated) {
504
+ return yield* Effect.fail(new DocNotFoundError({ name }));
505
+ }
506
+ try {
507
+ renderSingleDoc(updated, docsPath);
508
+ }
509
+ catch {
510
+ /* non-fatal */
511
+ }
512
+ yield* generateIndexEffect(docsPath);
513
+ return updated;
514
+ }),
515
+ lock: (name) => Effect.gen(function* () {
516
+ const doc = yield* docRepo.findByName(name);
517
+ if (!doc) {
518
+ return yield* Effect.fail(new DocNotFoundError({ name }));
519
+ }
520
+ if (doc.status === "locked") {
521
+ return doc;
522
+ }
523
+ const lockedAt = new Date().toISOString();
524
+ yield* docRepo.lock(doc.id, lockedAt);
525
+ const locked = yield* docRepo.findById(doc.id);
526
+ if (!locked) {
527
+ return yield* Effect.fail(new DocNotFoundError({ name }));
528
+ }
529
+ const docsPath = getDocsPath();
530
+ try {
531
+ renderSingleDoc(locked, docsPath);
532
+ }
533
+ catch {
534
+ /* non-fatal */
535
+ }
536
+ yield* generateIndexEffect(docsPath);
537
+ return locked;
538
+ }),
539
+ list: (filter) => docRepo.findAll(filter),
540
+ remove: (name) => Effect.gen(function* () {
541
+ const doc = yield* docRepo.findByName(name);
542
+ if (!doc) {
543
+ return yield* Effect.fail(new DocNotFoundError({ name }));
544
+ }
545
+ if (doc.status === "locked") {
546
+ return yield* Effect.fail(new DocLockedError({ name, version: doc.version }));
547
+ }
548
+ yield* docRepo.remove(doc.id);
549
+ const docsPath = getDocsPath();
550
+ const yamlPath = resolveYamlPath(docsPath, doc.kind, name);
551
+ const mdPath = resolveMdPath(docsPath, doc.kind, name);
552
+ try {
553
+ if (existsSync(yamlPath))
554
+ unlinkSync(yamlPath);
555
+ }
556
+ catch {
557
+ /* non-fatal */
558
+ }
559
+ try {
560
+ if (existsSync(mdPath))
561
+ unlinkSync(mdPath);
562
+ }
563
+ catch {
564
+ /* non-fatal */
565
+ }
566
+ yield* generateIndexEffect(docsPath);
567
+ }),
568
+ render: (name) => Effect.gen(function* () {
569
+ const docsPath = getDocsPath();
570
+ const rendered = [];
571
+ if (name) {
572
+ const doc = yield* docRepo.findByName(name);
573
+ if (!doc) {
574
+ return yield* Effect.fail(new DocNotFoundError({ name }));
575
+ }
576
+ rendered.push(renderSingleDoc(doc, docsPath));
577
+ }
578
+ else {
579
+ const allDocs = yield* docRepo.findAll();
580
+ for (const doc of allDocs) {
581
+ try {
582
+ rendered.push(renderSingleDoc(doc, docsPath));
583
+ }
584
+ catch {
585
+ /* skip docs with missing YAML */
586
+ }
587
+ }
588
+ }
589
+ yield* generateIndexEffect(docsPath);
590
+ return rendered;
591
+ }),
592
+ createVersion: (name) => Effect.gen(function* () {
593
+ const doc = yield* docRepo.findByName(name);
594
+ if (!doc) {
595
+ return yield* Effect.fail(new DocNotFoundError({ name }));
596
+ }
597
+ if (doc.status !== "locked") {
598
+ return yield* Effect.fail(new ValidationError({
599
+ reason: `Doc '${name}' must be locked before creating a new version`,
600
+ }));
601
+ }
602
+ const docsPath = getDocsPath();
603
+ const yamlPath = resolveYamlPath(docsPath, doc.kind, name);
604
+ if (!existsSync(yamlPath)) {
605
+ return yield* Effect.fail(new ValidationError({
606
+ reason: `YAML file not found for '${name}'`,
607
+ }));
608
+ }
609
+ const yamlContent = readFileSync(yamlPath, "utf8");
610
+ const hash = computeDocHash(yamlContent);
611
+ const newVersion = doc.version + 1;
612
+ const relPath = doc.kind === "overview"
613
+ ? `${name}.yml`
614
+ : join(doc.kind, `${name}.yml`);
615
+ const newDoc = yield* docRepo.insert({
616
+ hash,
617
+ kind: doc.kind,
618
+ name,
619
+ title: doc.title,
620
+ version: newVersion,
621
+ filePath: relPath,
622
+ parentDocId: doc.id,
623
+ });
624
+ try {
625
+ renderSingleDoc(newDoc, docsPath);
626
+ }
627
+ catch {
628
+ /* non-fatal */
629
+ }
630
+ yield* generateIndexEffect(docsPath);
631
+ return newDoc;
632
+ }),
633
+ linkDocs: (fromName, toName, linkType) => Effect.gen(function* () {
634
+ const fromDoc = yield* docRepo.findByName(fromName);
635
+ if (!fromDoc) {
636
+ return yield* Effect.fail(new DocNotFoundError({ name: fromName }));
637
+ }
638
+ const toDoc = yield* docRepo.findByName(toName);
639
+ if (!toDoc) {
640
+ return yield* Effect.fail(new DocNotFoundError({ name: toName }));
641
+ }
642
+ const resolvedType = linkType ?? inferLinkType(fromDoc.kind, toDoc.kind);
643
+ if (!resolvedType) {
644
+ return yield* Effect.fail(new ValidationError({
645
+ reason: `Cannot infer link type from ${fromDoc.kind} → ${toDoc.kind}. Provide explicit linkType.`,
646
+ }));
647
+ }
648
+ return yield* docRepo.createLink(fromDoc.id, toDoc.id, resolvedType);
649
+ }),
650
+ attachTask: (taskId, docName, linkType = "implements") => Effect.gen(function* () {
651
+ const doc = yield* docRepo.findByName(docName);
652
+ if (!doc) {
653
+ return yield* Effect.fail(new DocNotFoundError({ name: docName }));
654
+ }
655
+ yield* docRepo.createTaskLink(taskId, doc.id, linkType);
656
+ }),
657
+ createPatch: (designName, patchName, patchTitle) => Effect.gen(function* () {
658
+ const parentDoc = yield* docRepo.findByName(designName);
659
+ if (!parentDoc) {
660
+ return yield* Effect.fail(new DocNotFoundError({ name: designName }));
661
+ }
662
+ if (parentDoc.kind !== "design") {
663
+ return yield* Effect.fail(new ValidationError({
664
+ reason: `Patches can only be created on design docs, got '${parentDoc.kind}'`,
665
+ }));
666
+ }
667
+ const patchYaml = stringifyYaml({
668
+ kind: "design",
669
+ name: patchName,
670
+ title: patchTitle,
671
+ status: "changing",
672
+ version: 1,
673
+ implements: parentDoc.name,
674
+ problem_definition: `Patch for ${parentDoc.name}: ${patchTitle}`,
675
+ });
676
+ const hash = computeDocHash(patchYaml);
677
+ const docsPath = getDocsPath();
678
+ const filePath = resolveYamlPath(docsPath, "design", patchName);
679
+ ensureDir(filePath);
680
+ writeFileSync(filePath, patchYaml, "utf8");
681
+ const relPath = join("design", `${patchName}.yml`);
682
+ const patchDoc = yield* docRepo.insert({
683
+ hash,
684
+ kind: "design",
685
+ name: patchName,
686
+ title: patchTitle,
687
+ version: 1,
688
+ filePath: relPath,
689
+ parentDocId: null,
690
+ });
691
+ yield* docRepo.createLink(patchDoc.id, parentDoc.id, "design_patch");
692
+ try {
693
+ renderSingleDoc(patchDoc, docsPath);
694
+ }
695
+ catch {
696
+ /* non-fatal */
697
+ }
698
+ yield* generateIndexEffect(docsPath);
699
+ return patchDoc;
700
+ }),
701
+ validate: () => Effect.gen(function* () {
702
+ const warnings = [];
703
+ const unlinked = yield* docRepo.getUnlinkedTaskIds();
704
+ for (const taskId of unlinked) {
705
+ warnings.push(`Task ${taskId} is not linked to any doc`);
706
+ }
707
+ return warnings;
708
+ }),
709
+ detectDrift: (name) => Effect.gen(function* () {
710
+ const doc = yield* docRepo.findByName(name);
711
+ if (!doc) {
712
+ return yield* Effect.fail(new DocNotFoundError({ name }));
713
+ }
714
+ const warnings = [];
715
+ const docsPath = getDocsPath();
716
+ const yamlPath = resolveYamlPath(docsPath, doc.kind, name);
717
+ if (existsSync(yamlPath)) {
718
+ const content = readFileSync(yamlPath, "utf8");
719
+ const currentHash = computeDocHash(content);
720
+ if (currentHash !== doc.hash) {
721
+ warnings.push(`Content hash mismatch: DB has ${doc.hash.slice(0, 8)}..., file has ${currentHash.slice(0, 8)}...`);
722
+ }
723
+ }
724
+ else {
725
+ warnings.push(`YAML file missing: ${yamlPath}`);
726
+ }
727
+ const taskLinks = yield* docRepo.getTaskLinksForDoc(doc.id);
728
+ if (taskLinks.length === 0 && doc.kind === "design") {
729
+ warnings.push(`Design doc '${name}' has no linked tasks`);
730
+ }
731
+ return warnings;
732
+ }),
733
+ generateIndex: () => generateIndexEffect(getDocsPath()),
734
+ syncInvariants: (docName) => Effect.gen(function* () {
735
+ const synced = [];
736
+ if (docName) {
737
+ const doc = yield* docRepo.findByName(docName);
738
+ if (!doc) {
739
+ return yield* Effect.fail(new DocNotFoundError({ name: docName }));
740
+ }
741
+ const result = yield* syncInvariantsForDoc(doc);
742
+ synced.push(...result);
743
+ }
744
+ else {
745
+ const allDocs = yield* docRepo.findAll();
746
+ for (const doc of allDocs) {
747
+ // Keep whole-repo sync resilient: one malformed YAML file should not
748
+ // prevent invariants from being refreshed for every other doc.
749
+ const result = yield* syncInvariantsForDoc(doc).pipe(Effect.catchAllCause((cause) => {
750
+ const defect = Cause.dieOption(cause);
751
+ if (Option.isSome(defect) &&
752
+ defect.value instanceof InvalidDocYamlError) {
753
+ return Effect.succeed([]);
754
+ }
755
+ return Effect.failCause(cause);
756
+ }));
757
+ synced.push(...result);
758
+ }
759
+ }
760
+ return synced;
761
+ }),
762
+ listInvariants: (filter) => docRepo.findInvariants(filter),
763
+ recordInvariantCheck: (id, passed, details, durationMs) => Effect.gen(function* () {
764
+ const inv = yield* docRepo.findInvariantById(id);
765
+ if (!inv) {
766
+ return yield* Effect.fail(new InvariantNotFoundError({ id }));
767
+ }
768
+ return yield* docRepo.insertInvariantCheck(id, passed, details ?? null, durationMs ?? null);
769
+ }),
770
+ getDocGraph: () => Effect.gen(function* () {
771
+ const allDocs = yield* docRepo.findAll();
772
+ const allLinks = yield* docRepo.getAllLinks();
773
+ const nodes = [];
774
+ const edges = [];
775
+ for (const doc of allDocs) {
776
+ nodes.push({
777
+ id: `doc:${doc.id}`,
778
+ label: doc.name,
779
+ kind: doc.kind,
780
+ status: doc.status,
781
+ });
782
+ }
783
+ for (const link of allLinks) {
784
+ edges.push({
785
+ source: `doc:${link.fromDocId}`,
786
+ target: `doc:${link.toDocId}`,
787
+ type: link.linkType,
788
+ });
789
+ }
790
+ for (const doc of allDocs) {
791
+ const taskLinks = yield* docRepo.getTaskLinksForDoc(doc.id);
792
+ for (const tl of taskLinks) {
793
+ const taskNodeId = `task:${tl.taskId}`;
794
+ if (!nodes.some((n) => n.id === taskNodeId)) {
795
+ nodes.push({
796
+ id: taskNodeId,
797
+ label: tl.taskId,
798
+ kind: "task",
799
+ });
800
+ }
801
+ edges.push({
802
+ source: taskNodeId,
803
+ target: `doc:${doc.id}`,
804
+ type: tl.linkType,
805
+ });
806
+ }
807
+ }
808
+ return { nodes, edges };
809
+ }),
810
+ };
811
+ }));
812
+ //# sourceMappingURL=doc-service-impl.js.map