@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,350 @@
1
+ import { Context, Effect, Layer, Schema } from "effect";
2
+ import { writeFileSync, renameSync, existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
3
+ import { dirname, resolve } from "node:path";
4
+ import { DatabaseError, ValidationError } from "../errors.js";
5
+ import { SqliteClient } from "../db.js";
6
+ import { TaskService } from "./task-service.js";
7
+ import { TaskRepository } from "../repo/task-repo.js";
8
+ import { DependencyRepository } from "../repo/dep-repo.js";
9
+ import { SyncOperation as SyncOperationSchema } from "../schemas/sync.js";
10
+ /**
11
+ * SyncService provides JSONL-based export/import for git-tracked task syncing.
12
+ * See DD-009 for full specification.
13
+ */
14
+ export class SyncService extends Context.Tag("SyncService")() {
15
+ }
16
+ const DEFAULT_JSONL_PATH = ".tx/tasks.jsonl";
17
+ /**
18
+ * Convert a Task to a TaskUpsertOp for JSONL export.
19
+ */
20
+ const taskToUpsertOp = (task) => ({
21
+ v: 1,
22
+ op: "upsert",
23
+ ts: task.updatedAt.toISOString(),
24
+ id: task.id,
25
+ data: {
26
+ title: task.title,
27
+ description: task.description,
28
+ status: task.status,
29
+ score: task.score,
30
+ parentId: task.parentId,
31
+ metadata: task.metadata
32
+ }
33
+ });
34
+ /**
35
+ * Convert a TaskDependency to a DepAddOp for JSONL export.
36
+ */
37
+ const depToAddOp = (dep) => ({
38
+ v: 1,
39
+ op: "dep_add",
40
+ ts: dep.createdAt.toISOString(),
41
+ blockerId: dep.blockerId,
42
+ blockedId: dep.blockedId
43
+ });
44
+ /**
45
+ * Write content to file atomically using temp file + rename.
46
+ */
47
+ const atomicWrite = (filePath, content) => {
48
+ const dir = dirname(filePath);
49
+ if (!existsSync(dir)) {
50
+ mkdirSync(dir, { recursive: true });
51
+ }
52
+ const tempPath = `${filePath}.tmp.${Date.now()}`;
53
+ writeFileSync(tempPath, content, "utf-8");
54
+ renameSync(tempPath, filePath);
55
+ };
56
+ export const SyncServiceLive = Layer.effect(SyncService, Effect.gen(function* () {
57
+ const taskService = yield* TaskService;
58
+ const taskRepo = yield* TaskRepository;
59
+ const depRepo = yield* DependencyRepository;
60
+ const db = yield* SqliteClient;
61
+ // Helper: Get config value from sync_config table
62
+ const getConfig = (key) => Effect.try({
63
+ try: () => {
64
+ const row = db.prepare("SELECT value FROM sync_config WHERE key = ?").get(key);
65
+ return row?.value ?? null;
66
+ },
67
+ catch: (cause) => new DatabaseError({ cause })
68
+ });
69
+ // Helper: Set config value in sync_config table
70
+ const setConfig = (key, value) => Effect.try({
71
+ try: () => {
72
+ db.prepare("INSERT OR REPLACE INTO sync_config (key, value, updated_at) VALUES (?, ?, datetime('now'))").run(key, value);
73
+ },
74
+ catch: (cause) => new DatabaseError({ cause })
75
+ });
76
+ return {
77
+ export: (path) => Effect.gen(function* () {
78
+ const filePath = resolve(path ?? DEFAULT_JSONL_PATH);
79
+ // Get all tasks and dependencies
80
+ const tasks = yield* taskService.list();
81
+ const deps = yield* depRepo.getAll();
82
+ // Convert to sync operations
83
+ const taskOps = tasks.map(taskToUpsertOp);
84
+ const depOps = deps.map(depToAddOp);
85
+ // Combine and sort by timestamp
86
+ const allOps = [...taskOps, ...depOps].sort((a, b) => a.ts.localeCompare(b.ts));
87
+ // Convert to JSONL format (one JSON object per line)
88
+ const jsonl = allOps.map(op => JSON.stringify(op)).join("\n");
89
+ // Write atomically
90
+ yield* Effect.try({
91
+ try: () => atomicWrite(filePath, jsonl + (jsonl.length > 0 ? "\n" : "")),
92
+ catch: (cause) => new DatabaseError({ cause })
93
+ });
94
+ // Record export time
95
+ yield* setConfig("last_export", new Date().toISOString());
96
+ return {
97
+ opCount: allOps.length,
98
+ path: filePath
99
+ };
100
+ }),
101
+ import: (path) => Effect.gen(function* () {
102
+ const filePath = resolve(path ?? DEFAULT_JSONL_PATH);
103
+ // Check if file exists
104
+ if (!existsSync(filePath)) {
105
+ return { imported: 0, skipped: 0, conflicts: 0 };
106
+ }
107
+ // Read and parse JSONL file
108
+ const content = yield* Effect.try({
109
+ try: () => readFileSync(filePath, "utf-8"),
110
+ catch: (cause) => new DatabaseError({ cause })
111
+ });
112
+ const lines = content.trim().split("\n").filter(Boolean);
113
+ if (lines.length === 0) {
114
+ return { imported: 0, skipped: 0, conflicts: 0 };
115
+ }
116
+ // Parse all operations with Schema validation
117
+ const ops = [];
118
+ for (const line of lines) {
119
+ const parsed = yield* Effect.try({
120
+ try: () => JSON.parse(line),
121
+ catch: (cause) => new ValidationError({ reason: `Invalid JSON: ${cause}` })
122
+ });
123
+ const op = yield* Effect.try({
124
+ try: () => Schema.decodeUnknownSync(SyncOperationSchema)(parsed),
125
+ catch: (cause) => new ValidationError({ reason: `Schema validation failed: ${cause}` })
126
+ });
127
+ ops.push(op);
128
+ }
129
+ // Group by entity and find latest state per entity (timestamp wins)
130
+ const taskStates = new Map();
131
+ const depStates = new Map();
132
+ for (const op of ops) {
133
+ if (op.op === "upsert" || op.op === "delete") {
134
+ const existing = taskStates.get(op.id);
135
+ if (!existing || op.ts > existing.ts) {
136
+ taskStates.set(op.id, { op: op, ts: op.ts });
137
+ }
138
+ }
139
+ else if (op.op === "dep_add" || op.op === "dep_remove") {
140
+ const key = `${op.blockerId}:${op.blockedId}`;
141
+ const existing = depStates.get(key);
142
+ if (!existing || op.ts > existing.ts) {
143
+ depStates.set(key, { op: op, ts: op.ts });
144
+ }
145
+ }
146
+ }
147
+ let imported = 0;
148
+ let skipped = 0;
149
+ let conflicts = 0;
150
+ // Apply task operations
151
+ for (const [id, { op }] of taskStates) {
152
+ if (op.op === "upsert") {
153
+ const existing = yield* taskRepo.findById(id);
154
+ if (!existing) {
155
+ // Create new task with the specified ID
156
+ const now = new Date();
157
+ const task = {
158
+ id: id,
159
+ title: op.data.title,
160
+ description: op.data.description,
161
+ status: op.data.status,
162
+ parentId: op.data.parentId,
163
+ score: op.data.score,
164
+ createdAt: new Date(op.ts),
165
+ updatedAt: new Date(op.ts),
166
+ completedAt: op.data.status === "done" ? now : null,
167
+ metadata: op.data.metadata
168
+ };
169
+ yield* taskRepo.insert(task);
170
+ imported++;
171
+ }
172
+ else {
173
+ // Update if JSONL timestamp is newer than existing
174
+ const existingTs = existing.updatedAt.toISOString();
175
+ if (op.ts > existingTs) {
176
+ const updated = {
177
+ ...existing,
178
+ title: op.data.title,
179
+ description: op.data.description,
180
+ status: op.data.status,
181
+ parentId: op.data.parentId,
182
+ score: op.data.score,
183
+ updatedAt: new Date(op.ts),
184
+ completedAt: op.data.status === "done" ? (existing.completedAt ?? new Date()) : null,
185
+ metadata: op.data.metadata
186
+ };
187
+ yield* taskRepo.update(updated);
188
+ imported++;
189
+ }
190
+ else if (op.ts === existingTs) {
191
+ // Same timestamp - skip
192
+ skipped++;
193
+ }
194
+ else {
195
+ // Local is newer - conflict
196
+ conflicts++;
197
+ }
198
+ }
199
+ }
200
+ else if (op.op === "delete") {
201
+ const existing = yield* taskRepo.findById(id);
202
+ if (existing) {
203
+ yield* taskRepo.remove(id);
204
+ imported++;
205
+ }
206
+ }
207
+ }
208
+ // Apply dependency operations
209
+ for (const { op } of depStates.values()) {
210
+ if (op.op === "dep_add") {
211
+ // Add dependency, ignore if already exists
212
+ yield* depRepo.insert(op.blockerId, op.blockedId).pipe(Effect.catchAll(() => Effect.void));
213
+ }
214
+ else if (op.op === "dep_remove") {
215
+ // Remove dependency, ignore if doesn't exist
216
+ yield* depRepo.remove(op.blockerId, op.blockedId).pipe(Effect.catchAll(() => Effect.void));
217
+ }
218
+ }
219
+ // Record import time
220
+ yield* setConfig("last_import", new Date().toISOString());
221
+ return { imported, skipped, conflicts };
222
+ }),
223
+ status: () => Effect.gen(function* () {
224
+ const filePath = resolve(DEFAULT_JSONL_PATH);
225
+ // Count tasks in database
226
+ const tasks = yield* taskService.list();
227
+ const dbTaskCount = tasks.length;
228
+ // Count operations in JSONL file and get file info
229
+ let jsonlOpCount = 0;
230
+ let lastExport = null;
231
+ if (existsSync(filePath)) {
232
+ // Get file modification time as lastExport
233
+ const stats = yield* Effect.try({
234
+ try: () => statSync(filePath),
235
+ catch: (cause) => new DatabaseError({ cause })
236
+ });
237
+ lastExport = stats.mtime;
238
+ // Count non-empty lines (each line is one operation)
239
+ const content = yield* Effect.try({
240
+ try: () => readFileSync(filePath, "utf-8"),
241
+ catch: (cause) => new DatabaseError({ cause })
242
+ });
243
+ const lines = content.trim().split("\n").filter(Boolean);
244
+ jsonlOpCount = lines.length;
245
+ }
246
+ // Get last export/import timestamps from config
247
+ const lastExportConfig = yield* getConfig("last_export");
248
+ const lastImportConfig = yield* getConfig("last_import");
249
+ const lastExportDate = lastExportConfig && lastExportConfig !== "" ? new Date(lastExportConfig) : lastExport;
250
+ const lastImportDate = lastImportConfig && lastImportConfig !== "" ? new Date(lastImportConfig) : null;
251
+ // Get auto-sync status
252
+ const autoSyncConfig = yield* getConfig("auto_sync");
253
+ const autoSyncEnabled = autoSyncConfig === "true";
254
+ // Determine if dirty: DB has changes not in JSONL
255
+ let isDirty = false;
256
+ if (dbTaskCount > 0 && !existsSync(filePath)) {
257
+ isDirty = true;
258
+ }
259
+ else if (lastExportDate !== null && tasks.length > 0) {
260
+ // Check if any task was updated after the last export
261
+ isDirty = tasks.some(task => task.updatedAt > lastExportDate);
262
+ }
263
+ return {
264
+ dbTaskCount,
265
+ jsonlOpCount,
266
+ lastExport: lastExportDate,
267
+ lastImport: lastImportDate,
268
+ isDirty,
269
+ autoSyncEnabled
270
+ };
271
+ }),
272
+ enableAutoSync: () => setConfig("auto_sync", "true"),
273
+ disableAutoSync: () => setConfig("auto_sync", "false"),
274
+ isAutoSyncEnabled: () => Effect.gen(function* () {
275
+ const value = yield* getConfig("auto_sync");
276
+ return value === "true";
277
+ }),
278
+ compact: (path) => Effect.gen(function* () {
279
+ const filePath = resolve(path ?? DEFAULT_JSONL_PATH);
280
+ // Check if file exists
281
+ if (!existsSync(filePath)) {
282
+ return { before: 0, after: 0 };
283
+ }
284
+ // Read and parse JSONL file
285
+ const content = yield* Effect.try({
286
+ try: () => readFileSync(filePath, "utf-8"),
287
+ catch: (cause) => new DatabaseError({ cause })
288
+ });
289
+ const lines = content.trim().split("\n").filter(Boolean);
290
+ if (lines.length === 0) {
291
+ return { before: 0, after: 0 };
292
+ }
293
+ const before = lines.length;
294
+ // Parse and deduplicate - keep only latest state per entity
295
+ const taskStates = new Map();
296
+ const depStates = new Map();
297
+ for (const line of lines) {
298
+ const parsed = yield* Effect.try({
299
+ try: () => JSON.parse(line),
300
+ catch: (cause) => new ValidationError({ reason: `Invalid JSON: ${cause}` })
301
+ });
302
+ const op = yield* Effect.try({
303
+ try: () => Schema.decodeUnknownSync(SyncOperationSchema)(parsed),
304
+ catch: (cause) => new ValidationError({ reason: `Schema validation failed: ${cause}` })
305
+ });
306
+ if (op.op === "upsert" || op.op === "delete") {
307
+ const taskOp = op;
308
+ const existing = taskStates.get(taskOp.id);
309
+ if (!existing || taskOp.ts > existing.ts) {
310
+ taskStates.set(taskOp.id, op);
311
+ }
312
+ }
313
+ else if (op.op === "dep_add" || op.op === "dep_remove") {
314
+ const depOp = op;
315
+ const key = `${depOp.blockerId}:${depOp.blockedId}`;
316
+ const existing = depStates.get(key);
317
+ if (!existing || depOp.ts > existing.ts) {
318
+ depStates.set(key, op);
319
+ }
320
+ }
321
+ }
322
+ // Rebuild compacted JSONL, excluding deleted tasks and removed deps
323
+ const compacted = [];
324
+ for (const op of taskStates.values()) {
325
+ // Only keep upserts, skip deletes (tombstones)
326
+ if (op.op === "upsert") {
327
+ compacted.push(op);
328
+ }
329
+ }
330
+ for (const op of depStates.values()) {
331
+ // Only keep dep_adds, skip dep_removes
332
+ if (op.op === "dep_add") {
333
+ compacted.push(op);
334
+ }
335
+ }
336
+ // Sort by timestamp for deterministic output
337
+ compacted.sort((a, b) => a.ts.localeCompare(b.ts));
338
+ // Write compacted JSONL atomically
339
+ const newContent = compacted.map(op => JSON.stringify(op)).join("\n");
340
+ yield* Effect.try({
341
+ try: () => atomicWrite(filePath, newContent + (newContent.length > 0 ? "\n" : "")),
342
+ catch: (cause) => new DatabaseError({ cause })
343
+ });
344
+ return { before, after: compacted.length };
345
+ }),
346
+ setLastExport: (timestamp) => setConfig("last_export", timestamp.toISOString()),
347
+ setLastImport: (timestamp) => setConfig("last_import", timestamp.toISOString())
348
+ };
349
+ }));
350
+ //# sourceMappingURL=sync-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-service.js","sourceRoot":"","sources":["../../src/services/sync-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { TaskRepository } from "../repo/task-repo.js";
3
+ import { DependencyRepository } from "../repo/dep-repo.js";
4
+ import { TaskNotFoundError, ValidationError, DatabaseError } from "../errors.js";
5
+ import type { Task, TaskId, TaskStatus, TaskWithDeps, TaskFilter, CreateTaskInput, UpdateTaskInput } from "@jamesaphoenix/tx-types";
6
+ declare const TaskService_base: Context.TagClass<TaskService, "TaskService", {
7
+ readonly create: (input: CreateTaskInput) => Effect.Effect<Task, ValidationError | DatabaseError>;
8
+ readonly get: (id: TaskId) => Effect.Effect<Task, TaskNotFoundError | DatabaseError>;
9
+ readonly getWithDeps: (id: TaskId) => Effect.Effect<TaskWithDeps, TaskNotFoundError | DatabaseError>;
10
+ readonly getWithDepsBatch: (ids: readonly TaskId[]) => Effect.Effect<readonly TaskWithDeps[], DatabaseError>;
11
+ readonly update: (id: TaskId, input: UpdateTaskInput) => Effect.Effect<Task, TaskNotFoundError | ValidationError | DatabaseError>;
12
+ readonly forceStatus: (id: TaskId, status: TaskStatus) => Effect.Effect<Task, TaskNotFoundError | ValidationError | DatabaseError>;
13
+ readonly remove: (id: TaskId) => Effect.Effect<void, TaskNotFoundError | DatabaseError>;
14
+ readonly list: (filter?: TaskFilter) => Effect.Effect<readonly Task[], DatabaseError>;
15
+ readonly listWithDeps: (filter?: TaskFilter) => Effect.Effect<readonly TaskWithDeps[], DatabaseError>;
16
+ readonly count: (filter?: TaskFilter) => Effect.Effect<number, DatabaseError>;
17
+ }>;
18
+ export declare class TaskService extends TaskService_base {
19
+ }
20
+ export declare const TaskServiceLive: Layer.Layer<TaskService, never, TaskRepository | DependencyRepository>;
21
+ export {};
22
+ //# sourceMappingURL=task-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-service.d.ts","sourceRoot":"","sources":["../../src/services/task-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGhF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;;qBAK9G,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,CAAC;kBACnF,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;0BAC9D,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,iBAAiB,GAAG,aAAa,CAAC;+BACzE,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,YAAY,EAAE,EAAE,aAAa,CAAC;qBAC3F,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,GAAG,aAAa,CAAC;0BAC3G,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,GAAG,aAAa,CAAC;qBACjH,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;mBACxE,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC;2BAC9D,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,YAAY,EAAE,EAAE,aAAa,CAAC;oBACrF,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;;AAZjF,qBAAa,WAAY,SAAQ,gBAc9B;CAAG;AAEN,eAAO,MAAM,eAAe,wEAqQ3B,CAAA"}
@@ -0,0 +1,221 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { TaskRepository } from "../repo/task-repo.js";
3
+ import { DependencyRepository } from "../repo/dep-repo.js";
4
+ import { TaskNotFoundError, ValidationError } from "../errors.js";
5
+ import { generateTaskId } from "../id.js";
6
+ import { isValidTransition, isValidStatus } from "../mappers/task.js";
7
+ export class TaskService extends Context.Tag("TaskService")() {
8
+ }
9
+ export const TaskServiceLive = Layer.effect(TaskService, Effect.gen(function* () {
10
+ const taskRepo = yield* TaskRepository;
11
+ const depRepo = yield* DependencyRepository;
12
+ const enrichWithDeps = (task) => Effect.gen(function* () {
13
+ const blockerIds = yield* depRepo.getBlockerIds(task.id);
14
+ const blockingIds = yield* depRepo.getBlockingIds(task.id);
15
+ const childIds = yield* taskRepo.getChildIds(task.id);
16
+ let isReady = ["backlog", "ready", "planning"].includes(task.status);
17
+ if (isReady && blockerIds.length > 0) {
18
+ const blockers = yield* taskRepo.findByIds(blockerIds);
19
+ isReady = blockers.every(b => b.status === "done");
20
+ }
21
+ return {
22
+ ...task,
23
+ blockedBy: blockerIds,
24
+ blocks: blockingIds,
25
+ children: childIds,
26
+ isReady
27
+ };
28
+ });
29
+ // Batch version of enrichWithDeps - avoids N+1 queries
30
+ const enrichWithDepsBatch = (tasks) => Effect.gen(function* () {
31
+ if (tasks.length === 0)
32
+ return [];
33
+ const taskIds = tasks.map(t => t.id);
34
+ // Batch fetch all dependency info (3 queries total instead of 3N)
35
+ const blockerIdsMap = yield* depRepo.getBlockerIdsForMany(taskIds);
36
+ const blockingIdsMap = yield* depRepo.getBlockingIdsForMany(taskIds);
37
+ const childIdsMap = yield* taskRepo.getChildIdsForMany(taskIds);
38
+ // Collect all unique blocker IDs to fetch their status
39
+ const allBlockerIds = new Set();
40
+ for (const blockerIds of blockerIdsMap.values()) {
41
+ for (const id of blockerIds) {
42
+ allBlockerIds.add(id);
43
+ }
44
+ }
45
+ // Fetch all blocker tasks to check their status (1 query instead of N)
46
+ const blockerTasks = allBlockerIds.size > 0
47
+ ? yield* taskRepo.findByIds([...allBlockerIds])
48
+ : [];
49
+ const blockerStatusMap = new Map();
50
+ for (const t of blockerTasks) {
51
+ blockerStatusMap.set(t.id, t.status);
52
+ }
53
+ // Build TaskWithDeps for each task
54
+ const results = [];
55
+ for (const task of tasks) {
56
+ const blockerIds = blockerIdsMap.get(task.id) ?? [];
57
+ const blockingIds = blockingIdsMap.get(task.id) ?? [];
58
+ const childIds = childIdsMap.get(task.id) ?? [];
59
+ // Compute isReady
60
+ let isReady = ["backlog", "ready", "planning"].includes(task.status);
61
+ if (isReady && blockerIds.length > 0) {
62
+ isReady = blockerIds.every(bid => blockerStatusMap.get(bid) === "done");
63
+ }
64
+ results.push({
65
+ ...task,
66
+ blockedBy: blockerIds,
67
+ blocks: blockingIds,
68
+ children: childIds,
69
+ isReady
70
+ });
71
+ }
72
+ return results;
73
+ });
74
+ // Auto-complete parent task when all children are done (recursive)
75
+ const autoCompleteParent = (parentId, now) => Effect.gen(function* () {
76
+ const parent = yield* taskRepo.findById(parentId);
77
+ if (!parent || parent.status === "done")
78
+ return;
79
+ const childIds = yield* taskRepo.getChildIds(parentId);
80
+ if (childIds.length === 0)
81
+ return;
82
+ const children = yield* taskRepo.findByIds(childIds);
83
+ const allChildrenDone = children.every(c => c.status === "done");
84
+ if (allChildrenDone) {
85
+ const updatedParent = {
86
+ ...parent,
87
+ status: "done",
88
+ updatedAt: now,
89
+ completedAt: now
90
+ };
91
+ yield* taskRepo.update(updatedParent);
92
+ // Recursively check grandparent
93
+ if (parent.parentId) {
94
+ yield* autoCompleteParent(parent.parentId, now);
95
+ }
96
+ }
97
+ });
98
+ return {
99
+ create: (input) => Effect.gen(function* () {
100
+ if (!input.title || input.title.trim().length === 0) {
101
+ return yield* Effect.fail(new ValidationError({ reason: "Title is required" }));
102
+ }
103
+ if (input.parentId) {
104
+ const parent = yield* taskRepo.findById(input.parentId);
105
+ if (!parent) {
106
+ return yield* Effect.fail(new ValidationError({ reason: `Parent ${input.parentId} not found` }));
107
+ }
108
+ }
109
+ const id = yield* generateTaskId();
110
+ const now = new Date();
111
+ const task = {
112
+ id: id,
113
+ title: input.title.trim(),
114
+ description: input.description ?? "",
115
+ status: "backlog",
116
+ parentId: input.parentId ?? null,
117
+ score: input.score ?? 0,
118
+ createdAt: now,
119
+ updatedAt: now,
120
+ completedAt: null,
121
+ metadata: input.metadata ?? {}
122
+ };
123
+ yield* taskRepo.insert(task);
124
+ return task;
125
+ }),
126
+ get: (id) => Effect.gen(function* () {
127
+ const task = yield* taskRepo.findById(id);
128
+ if (!task) {
129
+ return yield* Effect.fail(new TaskNotFoundError({ id }));
130
+ }
131
+ return task;
132
+ }),
133
+ getWithDeps: (id) => Effect.gen(function* () {
134
+ const task = yield* taskRepo.findById(id);
135
+ if (!task) {
136
+ return yield* Effect.fail(new TaskNotFoundError({ id }));
137
+ }
138
+ return yield* enrichWithDeps(task);
139
+ }),
140
+ getWithDepsBatch: (ids) => Effect.gen(function* () {
141
+ if (ids.length === 0)
142
+ return [];
143
+ const tasks = yield* taskRepo.findByIds(ids);
144
+ return yield* enrichWithDepsBatch(tasks);
145
+ }),
146
+ update: (id, input) => Effect.gen(function* () {
147
+ const existing = yield* taskRepo.findById(id);
148
+ if (!existing) {
149
+ return yield* Effect.fail(new TaskNotFoundError({ id }));
150
+ }
151
+ if (input.status && !isValidStatus(input.status)) {
152
+ return yield* Effect.fail(new ValidationError({ reason: `Invalid status: ${input.status}` }));
153
+ }
154
+ if (input.status && input.status !== existing.status) {
155
+ if (!isValidTransition(existing.status, input.status)) {
156
+ return yield* Effect.fail(new ValidationError({
157
+ reason: `Invalid transition: ${existing.status} -> ${input.status}`
158
+ }));
159
+ }
160
+ }
161
+ if (input.parentId) {
162
+ const parent = yield* taskRepo.findById(input.parentId);
163
+ if (!parent) {
164
+ return yield* Effect.fail(new ValidationError({ reason: `Parent ${input.parentId} not found` }));
165
+ }
166
+ }
167
+ const now = new Date();
168
+ const isDone = input.status === "done" && existing.status !== "done";
169
+ const updated = {
170
+ ...existing,
171
+ title: input.title ?? existing.title,
172
+ description: input.description ?? existing.description,
173
+ status: input.status ?? existing.status,
174
+ parentId: input.parentId !== undefined ? input.parentId : existing.parentId,
175
+ score: input.score ?? existing.score,
176
+ updatedAt: now,
177
+ completedAt: isDone ? now : existing.completedAt,
178
+ metadata: input.metadata ? { ...existing.metadata, ...input.metadata } : existing.metadata
179
+ };
180
+ yield* taskRepo.update(updated);
181
+ // Auto-complete parent if all children are done
182
+ if (isDone && updated.parentId) {
183
+ yield* autoCompleteParent(updated.parentId, now);
184
+ }
185
+ return updated;
186
+ }),
187
+ forceStatus: (id, status) => Effect.gen(function* () {
188
+ const existing = yield* taskRepo.findById(id);
189
+ if (!existing) {
190
+ return yield* Effect.fail(new TaskNotFoundError({ id }));
191
+ }
192
+ if (!isValidStatus(status)) {
193
+ return yield* Effect.fail(new ValidationError({ reason: `Invalid status: ${status}` }));
194
+ }
195
+ const now = new Date();
196
+ const isDone = status === "done" && existing.status !== "done";
197
+ const updated = {
198
+ ...existing,
199
+ status,
200
+ updatedAt: now,
201
+ completedAt: isDone ? now : (status !== "done" ? null : existing.completedAt)
202
+ };
203
+ yield* taskRepo.update(updated);
204
+ return updated;
205
+ }),
206
+ remove: (id) => Effect.gen(function* () {
207
+ const task = yield* taskRepo.findById(id);
208
+ if (!task) {
209
+ return yield* Effect.fail(new TaskNotFoundError({ id }));
210
+ }
211
+ yield* taskRepo.remove(id);
212
+ }),
213
+ list: (filter) => taskRepo.findAll(filter),
214
+ listWithDeps: (filter) => Effect.gen(function* () {
215
+ const tasks = yield* taskRepo.findAll(filter);
216
+ return yield* enrichWithDepsBatch(tasks);
217
+ }),
218
+ count: (filter) => taskRepo.count(filter)
219
+ };
220
+ }));
221
+ //# sourceMappingURL=task-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-service.js","sourceRoot":"","sources":["../../src/services/task-service.ts"],"names":[],"mappings":"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"}