@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,66 @@
1
+ /**
2
+ * AutoSyncService provides hooks for automatic JSONL export on data mutations.
3
+ *
4
+ * When auto-sync is enabled, any create/update/delete operation on tasks,
5
+ * learnings, file-learnings, attempts, or dependencies triggers an export
6
+ * to keep JSONL files in sync with SQLite.
7
+ *
8
+ * Design:
9
+ * - Non-blocking: Exports run in background fiber to avoid latency impact
10
+ * - Error-resilient: Export errors are logged but never propagate to caller
11
+ * - Configurable: Controlled via sync_config "auto_sync" setting
12
+ */
13
+ import { Context, Effect, Layer } from "effect";
14
+ import { SqliteClient } from "../db.js";
15
+ import { SyncService } from "./sync-service.js";
16
+ import { DatabaseError } from "../errors.js";
17
+ export class AutoSyncService extends Context.Tag("AutoSyncService")() {
18
+ }
19
+ export const AutoSyncServiceLive = Layer.effect(AutoSyncService, Effect.gen(function* () {
20
+ const db = yield* SqliteClient;
21
+ const syncService = yield* SyncService;
22
+ // Check if auto-sync is enabled
23
+ const isEnabled = () => Effect.try({
24
+ try: () => {
25
+ const row = db.prepare("SELECT value FROM sync_config WHERE key = ?").get("auto_sync");
26
+ return row?.value === "true";
27
+ },
28
+ catch: (cause) => new DatabaseError({ cause })
29
+ });
30
+ // Run export in background, catching and logging any errors
31
+ const runInBackground = (exportEffect) => Effect.gen(function* () {
32
+ const enabled = yield* isEnabled().pipe(Effect.catchAll(() => Effect.succeed(false)));
33
+ if (!enabled) {
34
+ return;
35
+ }
36
+ // Fork the export and ignore the fiber - fire and forget
37
+ yield* Effect.fork(exportEffect.pipe(Effect.catchAll((error) => Effect.sync(() => {
38
+ // Log error but don't propagate
39
+ console.error("[auto-sync] Export failed:", error);
40
+ }))));
41
+ });
42
+ return {
43
+ // Tasks use the standard export
44
+ afterTaskMutation: () => runInBackground(syncService.export()),
45
+ // TODO: Implement when learning sync is added to SyncService
46
+ afterLearningMutation: () => runInBackground(syncService.export()),
47
+ // TODO: Implement when file-learning sync is added to SyncService
48
+ afterFileLearningMutation: () => runInBackground(syncService.export()),
49
+ // TODO: Implement when attempt sync is added to SyncService
50
+ afterAttemptMutation: () => runInBackground(syncService.export()),
51
+ // For now, just exports tasks - extend when other entity types are supported
52
+ afterAnyMutation: () => runInBackground(syncService.export())
53
+ };
54
+ }));
55
+ /**
56
+ * Noop implementation for use when auto-sync is not needed.
57
+ * All hooks do nothing.
58
+ */
59
+ export const AutoSyncServiceNoop = Layer.succeed(AutoSyncService, AutoSyncService.of({
60
+ afterTaskMutation: () => Effect.void,
61
+ afterLearningMutation: () => Effect.void,
62
+ afterFileLearningMutation: () => Effect.void,
63
+ afterAttemptMutation: () => Effect.void,
64
+ afterAnyMutation: () => Effect.void
65
+ }));
66
+ //# sourceMappingURL=auto-sync-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-sync-service.js","sourceRoot":"","sources":["../../src/services/auto-sync-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { ExtractionUnavailableError } from "../errors.js";
3
+ import type { TranscriptChunk, ExtractionResult } from "@jamesaphoenix/tx-types";
4
+ declare const CandidateExtractorService_base: Context.TagClass<CandidateExtractorService, "CandidateExtractorService", {
5
+ /**
6
+ * Extract learning candidates from a transcript chunk.
7
+ * Returns structured candidates with confidence and category.
8
+ */
9
+ readonly extract: (chunk: TranscriptChunk) => Effect.Effect<ExtractionResult, ExtractionUnavailableError>;
10
+ /** Check if extraction functionality is available */
11
+ readonly isAvailable: () => Effect.Effect<boolean>;
12
+ }>;
13
+ /**
14
+ * CandidateExtractorService extracts learning candidates from Claude Code transcripts.
15
+ *
16
+ * This service uses LLM to analyze transcript content and identify:
17
+ * - Technical decisions with rationale
18
+ * - Gotchas and pitfalls to avoid
19
+ * - Patterns that worked well
20
+ * - Future improvements
21
+ *
22
+ * Design: Following DD-006 patterns for LLM integration with pluggable backends.
23
+ * Supports Anthropic, OpenAI, and noop backends with graceful degradation.
24
+ *
25
+ * @see PRD-015 for the JSONL daemon and knowledge promotion pipeline
26
+ */
27
+ export declare class CandidateExtractorService extends CandidateExtractorService_base {
28
+ }
29
+ /**
30
+ * Noop implementation - returns empty results without LLM processing.
31
+ * Used when no LLM API key is configured or for testing.
32
+ */
33
+ export declare const CandidateExtractorServiceNoop: Layer.Layer<CandidateExtractorService, never, never>;
34
+ /**
35
+ * Anthropic (Claude) implementation.
36
+ * Uses Claude to extract learning candidates from transcripts.
37
+ */
38
+ export declare const CandidateExtractorServiceAnthropic: Layer.Layer<CandidateExtractorService, ExtractionUnavailableError, never>;
39
+ /**
40
+ * OpenAI (GPT) implementation.
41
+ * Uses GPT to extract learning candidates from transcripts.
42
+ */
43
+ export declare const CandidateExtractorServiceOpenAI: Layer.Layer<CandidateExtractorService, ExtractionUnavailableError, never>;
44
+ /**
45
+ * Auto-detecting layer that selects the appropriate backend based on environment.
46
+ *
47
+ * Priority:
48
+ * 1. ANTHROPIC_API_KEY set → Use Anthropic (Claude)
49
+ * 2. OPENAI_API_KEY set → Use OpenAI (GPT)
50
+ * 3. Neither set → Use Noop (graceful degradation)
51
+ *
52
+ * This allows graceful degradation when no LLM API keys are configured.
53
+ */
54
+ export declare const CandidateExtractorServiceAuto: Layer.Layer<CandidateExtractorService, ExtractionUnavailableError, never>;
55
+ export {};
56
+ //# sourceMappingURL=candidate-extractor-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-extractor-service.d.ts","sourceRoot":"","sources":["../../src/services/candidate-extractor-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAA;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,KAAK,EACV,eAAe,EAEf,gBAAgB,EAGjB,MAAM,yBAAyB,CAAA;;IAgL5B;;;OAGG;sBACe,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,0BAA0B,CAAC;IACzG,qDAAqD;0BAC/B,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;AAvBtD;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,SAAQ,8BAW5C;CAAG;AAEN;;;GAGG;AACH,eAAO,MAAM,6BAA6B,sDAUzC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kCAAkC,2EA0G9C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,+BAA+B,2EA4G3C,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,2EAmBzC,CAAA"}
@@ -0,0 +1,365 @@
1
+ import { Context, Effect, Layer, Config, Option } from "effect";
2
+ import { ExtractionUnavailableError } from "../errors.js";
3
+ /**
4
+ * The prompt template for learning candidate extraction.
5
+ * Designed to extract actionable, generalizable learnings from Claude Code transcripts.
6
+ * @see PRD-015 for specification
7
+ */
8
+ const EXTRACTION_PROMPT = `Analyze this Claude Code session transcript and extract actionable learnings.
9
+
10
+ <transcript>
11
+ {transcript_excerpt}
12
+ </transcript>
13
+
14
+ Extract learnings that meet these criteria:
15
+ 1. **Technical decisions**: Describes a choice and its rationale
16
+ 2. **Gotchas/pitfalls**: Something to avoid next time
17
+ 3. **Patterns that worked**: Reusable approaches
18
+ 4. **Future improvements**: Things to do differently
19
+
20
+ For each learning, provide:
21
+ - content: The learning text (1-3 sentences, actionable)
22
+ - confidence: "high" (certain, tested), "medium" (likely useful), "low" (speculative)
23
+ - category: One of [architecture, testing, performance, security, debugging, tooling, patterns, other]
24
+
25
+ Return JSON array:
26
+ [
27
+ {
28
+ "content": "Always wrap database operations in transactions to ensure atomicity",
29
+ "confidence": "high",
30
+ "category": "patterns"
31
+ }
32
+ ]
33
+
34
+ Rules:
35
+ - Skip generic advice (things any developer knows)
36
+ - Skip context-specific details that won't generalize
37
+ - Prefer actionable "do X when Y" format
38
+ - Maximum 5 learnings per transcript
39
+ - If no meaningful learnings found, return empty array: []`;
40
+ /**
41
+ * Valid confidence levels for validation.
42
+ */
43
+ const VALID_CONFIDENCES = ["high", "medium", "low"];
44
+ /**
45
+ * Valid categories for validation.
46
+ */
47
+ const VALID_CATEGORIES = [
48
+ "architecture",
49
+ "testing",
50
+ "performance",
51
+ "security",
52
+ "debugging",
53
+ "tooling",
54
+ "patterns",
55
+ "other"
56
+ ];
57
+ /**
58
+ * Parse LLM JSON response, handling common formatting issues.
59
+ * Robust parser following DD-006 patterns.
60
+ */
61
+ const parseLlmJson = (raw) => {
62
+ // Step 1: Try direct parse
63
+ try {
64
+ return JSON.parse(raw);
65
+ }
66
+ catch { /* continue */ }
67
+ // Step 2: Strip markdown code fences
68
+ const fenceMatch = raw.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
69
+ if (fenceMatch && fenceMatch[1]) {
70
+ try {
71
+ return JSON.parse(fenceMatch[1].trim());
72
+ }
73
+ catch { /* continue */ }
74
+ }
75
+ // Step 3: Find first [ or { and parse from there
76
+ const jsonStart = raw.search(/[[{]/);
77
+ if (jsonStart >= 0) {
78
+ const candidate = raw.slice(jsonStart);
79
+ try {
80
+ return JSON.parse(candidate);
81
+ }
82
+ catch { /* continue */ }
83
+ // Step 4: Find matching bracket and extract
84
+ const openChar = candidate[0];
85
+ const closeChar = openChar === "[" ? "]" : "}";
86
+ const lastClose = candidate.lastIndexOf(closeChar);
87
+ if (lastClose > 0) {
88
+ try {
89
+ return JSON.parse(candidate.slice(0, lastClose + 1));
90
+ }
91
+ catch { /* continue */ }
92
+ }
93
+ }
94
+ return null;
95
+ };
96
+ /**
97
+ * Validate and normalize an extracted candidate from LLM response.
98
+ * Returns null if the candidate is invalid.
99
+ */
100
+ const validateCandidate = (raw) => {
101
+ if (!raw || typeof raw !== "object")
102
+ return null;
103
+ const obj = raw;
104
+ // Validate content
105
+ if (typeof obj.content !== "string" || obj.content.trim().length === 0)
106
+ return null;
107
+ const content = obj.content.trim();
108
+ // Skip if content is too short (likely not actionable)
109
+ if (content.length < 10)
110
+ return null;
111
+ // Validate confidence
112
+ const rawConfidence = String(obj.confidence || "").toLowerCase();
113
+ const confidence = VALID_CONFIDENCES.includes(rawConfidence)
114
+ ? rawConfidence
115
+ : "medium"; // Default to medium if invalid
116
+ // Validate category
117
+ const rawCategory = String(obj.category || "").toLowerCase();
118
+ const category = VALID_CATEGORIES.includes(rawCategory)
119
+ ? rawCategory
120
+ : "other"; // Default to other if invalid
121
+ return { content, confidence, category };
122
+ };
123
+ /**
124
+ * CandidateExtractorService extracts learning candidates from Claude Code transcripts.
125
+ *
126
+ * This service uses LLM to analyze transcript content and identify:
127
+ * - Technical decisions with rationale
128
+ * - Gotchas and pitfalls to avoid
129
+ * - Patterns that worked well
130
+ * - Future improvements
131
+ *
132
+ * Design: Following DD-006 patterns for LLM integration with pluggable backends.
133
+ * Supports Anthropic, OpenAI, and noop backends with graceful degradation.
134
+ *
135
+ * @see PRD-015 for the JSONL daemon and knowledge promotion pipeline
136
+ */
137
+ export class CandidateExtractorService extends Context.Tag("CandidateExtractorService")() {
138
+ }
139
+ /**
140
+ * Noop implementation - returns empty results without LLM processing.
141
+ * Used when no LLM API key is configured or for testing.
142
+ */
143
+ export const CandidateExtractorServiceNoop = Layer.succeed(CandidateExtractorService, {
144
+ extract: (chunk) => Effect.succeed({
145
+ candidates: [],
146
+ sourceChunk: chunk,
147
+ wasExtracted: false
148
+ }),
149
+ isAvailable: () => Effect.succeed(false)
150
+ });
151
+ /**
152
+ * Anthropic (Claude) implementation.
153
+ * Uses Claude to extract learning candidates from transcripts.
154
+ */
155
+ export const CandidateExtractorServiceAnthropic = Layer.effect(CandidateExtractorService, Effect.gen(function* () {
156
+ // Read API key from environment
157
+ const apiKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.mapError(() => new ExtractionUnavailableError({
158
+ reason: "ANTHROPIC_API_KEY environment variable is not set"
159
+ })));
160
+ // Lazy-load client
161
+ let client = null;
162
+ const ensureClient = Effect.gen(function* () {
163
+ if (client)
164
+ return client;
165
+ // Dynamic import of Anthropic SDK (optional peer dependency)
166
+ const Anthropic = yield* Effect.tryPromise({
167
+ try: async () => {
168
+ // @ts-expect-error - @anthropic-ai/sdk is an optional peer dependency
169
+ const mod = await import("@anthropic-ai/sdk");
170
+ return mod.default;
171
+ },
172
+ catch: () => new ExtractionUnavailableError({
173
+ reason: "@anthropic-ai/sdk is not installed"
174
+ })
175
+ });
176
+ client = new Anthropic({ apiKey });
177
+ return client;
178
+ });
179
+ return {
180
+ extract: (chunk) => Effect.gen(function* () {
181
+ const startTime = Date.now();
182
+ const anthropic = yield* ensureClient;
183
+ // Build prompt with transcript content
184
+ const prompt = EXTRACTION_PROMPT.replace("{transcript_excerpt}", chunk.content);
185
+ const response = yield* Effect.tryPromise({
186
+ try: () => anthropic.messages.create({
187
+ model: "claude-haiku-4-20250514",
188
+ max_tokens: 1024,
189
+ messages: [{
190
+ role: "user",
191
+ content: prompt
192
+ }]
193
+ }),
194
+ catch: (e) => new ExtractionUnavailableError({
195
+ reason: `Anthropic API call failed: ${String(e)}`
196
+ })
197
+ });
198
+ // Extract text from response
199
+ const textContent = response.content.find(c => c.type === "text");
200
+ if (!textContent || !textContent.text) {
201
+ return {
202
+ candidates: [],
203
+ sourceChunk: chunk,
204
+ wasExtracted: true,
205
+ metadata: {
206
+ model: "claude-haiku-4-20250514",
207
+ tokensUsed: (response.usage?.input_tokens ?? 0) + (response.usage?.output_tokens ?? 0),
208
+ durationMs: Date.now() - startTime
209
+ }
210
+ };
211
+ }
212
+ // Parse the JSON array of candidates
213
+ const rawCandidates = parseLlmJson(textContent.text);
214
+ if (!rawCandidates || !Array.isArray(rawCandidates)) {
215
+ return {
216
+ candidates: [],
217
+ sourceChunk: chunk,
218
+ wasExtracted: true,
219
+ metadata: {
220
+ model: "claude-haiku-4-20250514",
221
+ tokensUsed: (response.usage?.input_tokens ?? 0) + (response.usage?.output_tokens ?? 0),
222
+ durationMs: Date.now() - startTime
223
+ }
224
+ };
225
+ }
226
+ // Validate and normalize each candidate
227
+ const candidates = rawCandidates
228
+ .map(validateCandidate)
229
+ .filter((c) => c !== null)
230
+ .slice(0, 5); // Max 5 candidates per chunk
231
+ return {
232
+ candidates,
233
+ sourceChunk: chunk,
234
+ wasExtracted: true,
235
+ metadata: {
236
+ model: "claude-haiku-4-20250514",
237
+ tokensUsed: (response.usage?.input_tokens ?? 0) + (response.usage?.output_tokens ?? 0),
238
+ durationMs: Date.now() - startTime
239
+ }
240
+ };
241
+ }),
242
+ isAvailable: () => Effect.succeed(true)
243
+ };
244
+ }));
245
+ /**
246
+ * OpenAI (GPT) implementation.
247
+ * Uses GPT to extract learning candidates from transcripts.
248
+ */
249
+ export const CandidateExtractorServiceOpenAI = Layer.effect(CandidateExtractorService, Effect.gen(function* () {
250
+ // Read API key from environment
251
+ const apiKey = yield* Config.string("OPENAI_API_KEY").pipe(Effect.mapError(() => new ExtractionUnavailableError({
252
+ reason: "OPENAI_API_KEY environment variable is not set"
253
+ })));
254
+ // Lazy-load client
255
+ let client = null;
256
+ const ensureClient = Effect.gen(function* () {
257
+ if (client)
258
+ return client;
259
+ // Dynamic import of OpenAI SDK (optional peer dependency)
260
+ const OpenAI = yield* Effect.tryPromise({
261
+ try: async () => {
262
+ // @ts-expect-error - openai is an optional peer dependency
263
+ const mod = await import("openai");
264
+ return mod.default;
265
+ },
266
+ catch: () => new ExtractionUnavailableError({
267
+ reason: "openai package is not installed"
268
+ })
269
+ });
270
+ client = new OpenAI({ apiKey });
271
+ return client;
272
+ });
273
+ return {
274
+ extract: (chunk) => Effect.gen(function* () {
275
+ const startTime = Date.now();
276
+ const openai = yield* ensureClient;
277
+ // Build prompt with transcript content
278
+ const prompt = EXTRACTION_PROMPT.replace("{transcript_excerpt}", chunk.content);
279
+ const response = yield* Effect.tryPromise({
280
+ try: () => openai.chat.completions.create({
281
+ model: "gpt-4o-mini",
282
+ max_tokens: 1024,
283
+ messages: [{
284
+ role: "user",
285
+ content: prompt
286
+ }],
287
+ response_format: { type: "json_object" }
288
+ }),
289
+ catch: (e) => new ExtractionUnavailableError({
290
+ reason: `OpenAI API call failed: ${String(e)}`
291
+ })
292
+ });
293
+ // Extract text from response
294
+ const textContent = response.choices[0]?.message?.content;
295
+ if (!textContent) {
296
+ return {
297
+ candidates: [],
298
+ sourceChunk: chunk,
299
+ wasExtracted: true,
300
+ metadata: {
301
+ model: "gpt-4o-mini",
302
+ tokensUsed: (response.usage?.prompt_tokens ?? 0) + (response.usage?.completion_tokens ?? 0),
303
+ durationMs: Date.now() - startTime
304
+ }
305
+ };
306
+ }
307
+ // Parse the JSON array of candidates
308
+ // OpenAI with json_object mode might wrap in an object
309
+ const parsed = parseLlmJson(textContent);
310
+ let rawCandidates = [];
311
+ if (Array.isArray(parsed)) {
312
+ rawCandidates = parsed;
313
+ }
314
+ else if (parsed && typeof parsed === "object") {
315
+ // Handle wrapped response like { candidates: [...] } or { learnings: [...] }
316
+ const obj = parsed;
317
+ const arrayField = Object.values(obj).find(Array.isArray);
318
+ if (arrayField) {
319
+ rawCandidates = arrayField;
320
+ }
321
+ }
322
+ // Validate and normalize each candidate
323
+ const candidates = rawCandidates
324
+ .map(validateCandidate)
325
+ .filter((c) => c !== null)
326
+ .slice(0, 5); // Max 5 candidates per chunk
327
+ return {
328
+ candidates,
329
+ sourceChunk: chunk,
330
+ wasExtracted: true,
331
+ metadata: {
332
+ model: "gpt-4o-mini",
333
+ tokensUsed: (response.usage?.prompt_tokens ?? 0) + (response.usage?.completion_tokens ?? 0),
334
+ durationMs: Date.now() - startTime
335
+ }
336
+ };
337
+ }),
338
+ isAvailable: () => Effect.succeed(true)
339
+ };
340
+ }));
341
+ /**
342
+ * Auto-detecting layer that selects the appropriate backend based on environment.
343
+ *
344
+ * Priority:
345
+ * 1. ANTHROPIC_API_KEY set → Use Anthropic (Claude)
346
+ * 2. OPENAI_API_KEY set → Use OpenAI (GPT)
347
+ * 3. Neither set → Use Noop (graceful degradation)
348
+ *
349
+ * This allows graceful degradation when no LLM API keys are configured.
350
+ */
351
+ export const CandidateExtractorServiceAuto = Layer.unwrapEffect(Effect.gen(function* () {
352
+ // Check for Anthropic API key first (preferred)
353
+ const anthropicKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.option);
354
+ if (Option.isSome(anthropicKey) && anthropicKey.value.trim().length > 0) {
355
+ return CandidateExtractorServiceAnthropic;
356
+ }
357
+ // Fall back to OpenAI if available
358
+ const openaiKey = yield* Config.string("OPENAI_API_KEY").pipe(Effect.option);
359
+ if (Option.isSome(openaiKey) && openaiKey.value.trim().length > 0) {
360
+ return CandidateExtractorServiceOpenAI;
361
+ }
362
+ // No API keys configured - use noop
363
+ return CandidateExtractorServiceNoop;
364
+ }));
365
+ //# sourceMappingURL=candidate-extractor-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-extractor-service.js","sourceRoot":"","sources":["../../src/services/candidate-extractor-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * ClaimService - PRD-018
3
+ *
4
+ * Manages task claims with lease-based expiration.
5
+ * Uses Effect-TS patterns per DD-002.
6
+ */
7
+ import { Context, Effect, Layer } from "effect";
8
+ import { ClaimRepository } from "../repo/claim-repo.js";
9
+ import { TaskRepository } from "../repo/task-repo.js";
10
+ import { OrchestratorStateRepository } from "../repo/orchestrator-state-repo.js";
11
+ import { AlreadyClaimedError, ClaimIdNotFoundError, ClaimNotFoundError, DatabaseError, LeaseExpiredError, MaxRenewalsExceededError, TaskNotFoundError } from "../errors.js";
12
+ import type { TaskClaim } from "../schemas/worker.js";
13
+ declare const ClaimService_base: Context.TagClass<ClaimService, "ClaimService", {
14
+ /**
15
+ * Claim a task for a worker with a lease.
16
+ * The lease duration is taken from orchestrator config or defaults to 30 minutes.
17
+ */
18
+ readonly claim: (taskId: string, workerId: string, leaseDurationMinutes?: number) => Effect.Effect<TaskClaim, TaskNotFoundError | AlreadyClaimedError | DatabaseError>;
19
+ /**
20
+ * Release a claim on a task.
21
+ * Only the worker who holds the claim can release it.
22
+ */
23
+ readonly release: (taskId: string, workerId: string) => Effect.Effect<void, ClaimNotFoundError | DatabaseError>;
24
+ /**
25
+ * Renew the lease on an existing claim.
26
+ * Fails if the claim is expired or max renewals exceeded.
27
+ */
28
+ readonly renew: (taskId: string, workerId: string) => Effect.Effect<TaskClaim, ClaimNotFoundError | LeaseExpiredError | MaxRenewalsExceededError | DatabaseError>;
29
+ /**
30
+ * Get all claims that have expired but are still marked as active.
31
+ */
32
+ readonly getExpired: () => Effect.Effect<readonly TaskClaim[], DatabaseError>;
33
+ /**
34
+ * Mark a claim as expired.
35
+ * Used during reconciliation to handle stale claims.
36
+ */
37
+ readonly expire: (claimId: number) => Effect.Effect<void, ClaimIdNotFoundError | DatabaseError>;
38
+ /**
39
+ * Release all active claims held by a worker.
40
+ * Used during worker deregistration.
41
+ */
42
+ readonly releaseByWorker: (workerId: string) => Effect.Effect<number, DatabaseError>;
43
+ /**
44
+ * Get the active claim for a task, if any.
45
+ */
46
+ readonly getActiveClaim: (taskId: string) => Effect.Effect<TaskClaim | null, DatabaseError>;
47
+ }>;
48
+ export declare class ClaimService extends ClaimService_base {
49
+ }
50
+ export declare const ClaimServiceLive: Layer.Layer<ClaimService, never, TaskRepository | ClaimRepository | OrchestratorStateRepository>;
51
+ export {};
52
+ //# sourceMappingURL=claim-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-service.d.ts","sourceRoot":"","sources":["../../src/services/claim-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;;IAWjD;;;OAGG;oBACa,CACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,oBAAoB,CAAC,EAAE,MAAM,KAC1B,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,iBAAiB,GAAG,mBAAmB,GAAG,aAAa,CAAC;IAEtF;;;OAGG;sBACe,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC;IAE5D;;;OAGG;oBACa,CACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,CAAC;IAEhH;;OAEG;yBACkB,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,SAAS,EAAE,EAAE,aAAa,CAAC;IAE7E;;;OAGG;qBACc,CACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,oBAAoB,GAAG,aAAa,CAAC;IAE9D;;;OAGG;8BACuB,CACxB,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAEzC;;OAEG;6BACsB,CACvB,MAAM,EAAE,MAAM,KACX,MAAM,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,EAAE,aAAa,CAAC;;AAzDvD,qBAAa,YAAa,SAAQ,iBA2D/B;CAAG;AAEN,eAAO,MAAM,gBAAgB,kGA6J5B,CAAA"}