@jamesaphoenix/tx-core 0.4.2 → 0.4.3
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.
- package/README.md +480 -0
- package/dist/db.d.ts +28 -14
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +102 -14
- package/dist/db.js.map +1 -1
- package/dist/errors.d.ts +178 -34
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +119 -26
- package/dist/errors.js.map +1 -1
- package/dist/id.d.ts +10 -0
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +17 -1
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +15 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -8
- package/dist/index.js.map +1 -1
- package/dist/layer.d.ts +23 -14
- package/dist/layer.d.ts.map +1 -1
- package/dist/layer.js +75 -76
- package/dist/layer.js.map +1 -1
- package/dist/mappers/anchor.d.ts +15 -1
- package/dist/mappers/anchor.d.ts.map +1 -1
- package/dist/mappers/anchor.js +95 -28
- package/dist/mappers/anchor.js.map +1 -1
- package/dist/mappers/attempt.d.ts +3 -1
- package/dist/mappers/attempt.d.ts.map +1 -1
- package/dist/mappers/attempt.js +23 -9
- package/dist/mappers/attempt.js.map +1 -1
- package/dist/mappers/candidate.d.ts +3 -1
- package/dist/mappers/candidate.d.ts.map +1 -1
- package/dist/mappers/candidate.js +46 -16
- package/dist/mappers/candidate.js.map +1 -1
- package/dist/mappers/claim.d.ts +1 -1
- package/dist/mappers/claim.d.ts.map +1 -1
- package/dist/mappers/claim.js +11 -4
- package/dist/mappers/claim.js.map +1 -1
- package/dist/mappers/deduplication.d.ts +13 -1
- package/dist/mappers/deduplication.d.ts.map +1 -1
- package/dist/mappers/deduplication.js +22 -3
- package/dist/mappers/deduplication.js.map +1 -1
- package/dist/mappers/doc.d.ts +24 -0
- package/dist/mappers/doc.d.ts.map +1 -0
- package/dist/mappers/doc.js +161 -0
- package/dist/mappers/doc.js.map +1 -0
- package/dist/mappers/edge.d.ts +10 -1
- package/dist/mappers/edge.d.ts.map +1 -1
- package/dist/mappers/edge.js +74 -12
- package/dist/mappers/edge.js.map +1 -1
- package/dist/mappers/file-learning.d.ts.map +1 -1
- package/dist/mappers/file-learning.js +2 -1
- package/dist/mappers/file-learning.js.map +1 -1
- package/dist/mappers/index.d.ts +6 -7
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +10 -12
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/learning.d.ts +9 -1
- package/dist/mappers/learning.d.ts.map +1 -1
- package/dist/mappers/learning.js +94 -14
- package/dist/mappers/learning.js.map +1 -1
- package/dist/mappers/orchestrator-state.d.ts +1 -1
- package/dist/mappers/orchestrator-state.d.ts.map +1 -1
- package/dist/mappers/orchestrator-state.js +31 -5
- package/dist/mappers/orchestrator-state.js.map +1 -1
- package/dist/mappers/parse-date.d.ts +11 -0
- package/dist/mappers/parse-date.d.ts.map +1 -0
- package/dist/mappers/parse-date.js +18 -0
- package/dist/mappers/parse-date.js.map +1 -0
- package/dist/mappers/run.d.ts +14 -4
- package/dist/mappers/run.d.ts.map +1 -1
- package/dist/mappers/run.js +49 -18
- package/dist/mappers/run.js.map +1 -1
- package/dist/mappers/task.d.ts +5 -1
- package/dist/mappers/task.d.ts.map +1 -1
- package/dist/mappers/task.js +66 -16
- package/dist/mappers/task.js.map +1 -1
- package/dist/mappers/tracked-project.d.ts +3 -1
- package/dist/mappers/tracked-project.d.ts.map +1 -1
- package/dist/mappers/tracked-project.js +23 -9
- package/dist/mappers/tracked-project.js.map +1 -1
- package/dist/mappers/worker.d.ts +1 -1
- package/dist/mappers/worker.d.ts.map +1 -1
- package/dist/mappers/worker.js +44 -6
- package/dist/mappers/worker.js.map +1 -1
- package/dist/repo/anchor-repo.d.ts +2 -2
- package/dist/repo/anchor-repo.d.ts.map +1 -1
- package/dist/repo/anchor-repo.js +46 -5
- package/dist/repo/anchor-repo.js.map +1 -1
- package/dist/repo/attempt-repo.d.ts +2 -2
- package/dist/repo/attempt-repo.d.ts.map +1 -1
- package/dist/repo/attempt-repo.js +16 -6
- package/dist/repo/attempt-repo.js.map +1 -1
- package/dist/repo/candidate-repo.d.ts.map +1 -1
- package/dist/repo/candidate-repo.js +22 -1
- package/dist/repo/candidate-repo.js.map +1 -1
- package/dist/repo/claim-repo.d.ts +46 -2
- package/dist/repo/claim-repo.d.ts.map +1 -1
- package/dist/repo/claim-repo.js +113 -6
- package/dist/repo/claim-repo.js.map +1 -1
- package/dist/repo/compaction-repo.d.ts +41 -0
- package/dist/repo/compaction-repo.d.ts.map +1 -0
- package/dist/repo/compaction-repo.js +84 -0
- package/dist/repo/compaction-repo.js.map +1 -0
- package/dist/repo/deduplication-repo.d.ts +9 -1
- package/dist/repo/deduplication-repo.d.ts.map +1 -1
- package/dist/repo/deduplication-repo.js +46 -9
- package/dist/repo/deduplication-repo.js.map +1 -1
- package/dist/repo/dep-repo.d.ts +27 -3
- package/dist/repo/dep-repo.d.ts.map +1 -1
- package/dist/repo/dep-repo.js +166 -39
- package/dist/repo/dep-repo.js.map +1 -1
- package/dist/repo/doc-repo.d.ts +59 -0
- package/dist/repo/doc-repo.d.ts.map +1 -0
- package/dist/repo/doc-repo.js +276 -0
- package/dist/repo/doc-repo.js.map +1 -0
- package/dist/repo/edge-repo.d.ts +1 -1
- package/dist/repo/edge-repo.d.ts.map +1 -1
- package/dist/repo/edge-repo.js +65 -34
- package/dist/repo/edge-repo.js.map +1 -1
- package/dist/repo/file-learning-repo.d.ts +3 -3
- package/dist/repo/file-learning-repo.d.ts.map +1 -1
- package/dist/repo/file-learning-repo.js +19 -8
- package/dist/repo/file-learning-repo.js.map +1 -1
- package/dist/repo/index.d.ts +4 -6
- package/dist/repo/index.d.ts.map +1 -1
- package/dist/repo/index.js +3 -5
- package/dist/repo/index.js.map +1 -1
- package/dist/repo/learning-repo.d.ts +10 -3
- package/dist/repo/learning-repo.d.ts.map +1 -1
- package/dist/repo/learning-repo.js +68 -11
- package/dist/repo/learning-repo.js.map +1 -1
- package/dist/repo/orchestrator-state-repo.d.ts.map +1 -1
- package/dist/repo/orchestrator-state-repo.js +8 -1
- package/dist/repo/orchestrator-state-repo.js.map +1 -1
- package/dist/repo/run-repo.d.ts +3 -3
- package/dist/repo/run-repo.d.ts.map +1 -1
- package/dist/repo/run-repo.js +40 -19
- package/dist/repo/run-repo.js.map +1 -1
- package/dist/repo/task-repo.d.ts +14 -3
- package/dist/repo/task-repo.d.ts.map +1 -1
- package/dist/repo/task-repo.js +194 -20
- package/dist/repo/task-repo.js.map +1 -1
- package/dist/repo/tracked-project-repo.d.ts.map +1 -1
- package/dist/repo/tracked-project-repo.js +15 -1
- package/dist/repo/tracked-project-repo.js.map +1 -1
- package/dist/repo/worker-repo.d.ts +3 -2
- package/dist/repo/worker-repo.d.ts.map +1 -1
- package/dist/repo/worker-repo.js +54 -8
- package/dist/repo/worker-repo.js.map +1 -1
- package/dist/schemas/sync.js +2 -2
- package/dist/schemas/sync.js.map +1 -1
- package/dist/schemas/worker.d.ts +1 -0
- package/dist/schemas/worker.d.ts.map +1 -1
- package/dist/schemas/worker.js +1 -0
- package/dist/schemas/worker.js.map +1 -1
- package/dist/services/agent-service.d.ts +57 -0
- package/dist/services/agent-service.d.ts.map +1 -0
- package/dist/services/agent-service.js +81 -0
- package/dist/services/agent-service.js.map +1 -0
- package/dist/services/anchor-service.js +1 -1
- package/dist/services/anchor-service.js.map +1 -1
- package/dist/services/anchor-verification.d.ts +8 -0
- package/dist/services/anchor-verification.d.ts.map +1 -1
- package/dist/services/anchor-verification.js +237 -37
- package/dist/services/anchor-verification.js.map +1 -1
- package/dist/services/ast-grep-service.d.ts.map +1 -1
- package/dist/services/ast-grep-service.js +93 -22
- package/dist/services/ast-grep-service.js.map +1 -1
- package/dist/services/attempt-service.d.ts.map +1 -1
- package/dist/services/attempt-service.js +1 -4
- package/dist/services/attempt-service.js.map +1 -1
- package/dist/services/auto-sync-service.d.ts +1 -1
- package/dist/services/auto-sync-service.d.ts.map +1 -1
- package/dist/services/auto-sync-service.js +18 -10
- package/dist/services/auto-sync-service.js.map +1 -1
- package/dist/services/claim-service.d.ts +8 -2
- package/dist/services/claim-service.d.ts.map +1 -1
- package/dist/services/claim-service.js +37 -23
- package/dist/services/claim-service.js.map +1 -1
- package/dist/services/compaction-service.d.ts +105 -0
- package/dist/services/compaction-service.d.ts.map +1 -0
- package/dist/services/compaction-service.js +369 -0
- package/dist/services/compaction-service.js.map +1 -0
- package/dist/services/cycle-scan-service.d.ts +32 -0
- package/dist/services/cycle-scan-service.d.ts.map +1 -0
- package/dist/services/cycle-scan-service.js +542 -0
- package/dist/services/cycle-scan-service.js.map +1 -0
- package/dist/services/daemon-service.d.ts +40 -2
- package/dist/services/daemon-service.d.ts.map +1 -1
- package/dist/services/daemon-service.js +199 -52
- package/dist/services/daemon-service.js.map +1 -1
- package/dist/services/deduplication-service.d.ts +8 -4
- package/dist/services/deduplication-service.d.ts.map +1 -1
- package/dist/services/deduplication-service.js +79 -25
- package/dist/services/deduplication-service.js.map +1 -1
- package/dist/services/dep-service.d.ts +2 -2
- package/dist/services/dep-service.d.ts.map +1 -1
- package/dist/services/dep-service.js +9 -5
- package/dist/services/dep-service.js.map +1 -1
- package/dist/services/diversifier-service.d.ts +2 -1
- package/dist/services/diversifier-service.d.ts.map +1 -1
- package/dist/services/diversifier-service.js +37 -43
- package/dist/services/diversifier-service.js.map +1 -1
- package/dist/services/doc-service.d.ts +49 -0
- package/dist/services/doc-service.d.ts.map +1 -0
- package/dist/services/doc-service.js +605 -0
- package/dist/services/doc-service.js.map +1 -0
- package/dist/services/edge-service.js +2 -2
- package/dist/services/edge-service.js.map +1 -1
- package/dist/services/embedding-service.d.ts +66 -2
- package/dist/services/embedding-service.d.ts.map +1 -1
- package/dist/services/embedding-service.js +138 -24
- package/dist/services/embedding-service.js.map +1 -1
- package/dist/services/file-learning-service.d.ts.map +1 -1
- package/dist/services/file-learning-service.js +8 -7
- package/dist/services/file-learning-service.js.map +1 -1
- package/dist/services/file-watcher-service.d.ts.map +1 -1
- package/dist/services/file-watcher-service.js +58 -11
- package/dist/services/file-watcher-service.js.map +1 -1
- package/dist/services/graph-expansion.d.ts +3 -0
- package/dist/services/graph-expansion.d.ts.map +1 -1
- package/dist/services/graph-expansion.js +28 -7
- package/dist/services/graph-expansion.js.map +1 -1
- package/dist/services/hierarchy-service.d.ts +1 -1
- package/dist/services/hierarchy-service.d.ts.map +1 -1
- package/dist/services/hierarchy-service.js +50 -32
- package/dist/services/hierarchy-service.js.map +1 -1
- package/dist/services/index.d.ts +13 -15
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +13 -15
- package/dist/services/index.js.map +1 -1
- package/dist/services/learning-service.d.ts +4 -4
- package/dist/services/learning-service.d.ts.map +1 -1
- package/dist/services/learning-service.js +75 -42
- package/dist/services/learning-service.js.map +1 -1
- package/dist/services/llm-service.d.ts +62 -0
- package/dist/services/llm-service.d.ts.map +1 -0
- package/dist/services/llm-service.js +172 -0
- package/dist/services/llm-service.js.map +1 -0
- package/dist/services/migration-service.d.ts +1 -1
- package/dist/services/migration-service.d.ts.map +1 -1
- package/dist/services/migration-service.js +18 -7
- package/dist/services/migration-service.js.map +1 -1
- package/dist/services/orchestrator-service.d.ts +4 -3
- package/dist/services/orchestrator-service.d.ts.map +1 -1
- package/dist/services/orchestrator-service.js +67 -29
- package/dist/services/orchestrator-service.js.map +1 -1
- package/dist/services/promotion-service.d.ts +1 -1
- package/dist/services/promotion-service.js +1 -1
- package/dist/services/promotion-service.js.map +1 -1
- package/dist/services/query-expansion-service.d.ts +30 -9
- package/dist/services/query-expansion-service.d.ts.map +1 -1
- package/dist/services/query-expansion-service.js +54 -63
- package/dist/services/query-expansion-service.js.map +1 -1
- package/dist/services/ready-service.d.ts +21 -1
- package/dist/services/ready-service.d.ts.map +1 -1
- package/dist/services/ready-service.js +44 -21
- package/dist/services/ready-service.js.map +1 -1
- package/dist/services/retriever-service.d.ts +10 -10
- package/dist/services/retriever-service.d.ts.map +1 -1
- package/dist/services/retriever-service.js +53 -161
- package/dist/services/retriever-service.js.map +1 -1
- package/dist/services/swarm-verification.d.ts +2 -2
- package/dist/services/swarm-verification.d.ts.map +1 -1
- package/dist/services/swarm-verification.js +12 -6
- package/dist/services/swarm-verification.js.map +1 -1
- package/dist/services/sync-service.d.ts +17 -4
- package/dist/services/sync-service.d.ts.map +1 -1
- package/dist/services/sync-service.js +378 -114
- package/dist/services/sync-service.js.map +1 -1
- package/dist/services/task-service.d.ts +6 -4
- package/dist/services/task-service.d.ts.map +1 -1
- package/dist/services/task-service.js +162 -33
- package/dist/services/task-service.js.map +1 -1
- package/dist/services/tracing-service.d.ts +55 -0
- package/dist/services/tracing-service.d.ts.map +1 -0
- package/dist/services/tracing-service.js +99 -0
- package/dist/services/tracing-service.js.map +1 -0
- package/dist/services/transcript-adapter.d.ts +99 -0
- package/dist/services/transcript-adapter.d.ts.map +1 -0
- package/dist/services/transcript-adapter.js +283 -0
- package/dist/services/transcript-adapter.js.map +1 -0
- package/dist/services/validation-service.d.ts +85 -0
- package/dist/services/validation-service.d.ts.map +1 -0
- package/dist/services/validation-service.js +289 -0
- package/dist/services/validation-service.js.map +1 -0
- package/dist/services/worker-process.d.ts +23 -4
- package/dist/services/worker-process.d.ts.map +1 -1
- package/dist/services/worker-process.js +159 -70
- package/dist/services/worker-process.js.map +1 -1
- package/dist/services/worker-service.d.ts.map +1 -1
- package/dist/services/worker-service.js +7 -12
- package/dist/services/worker-service.js.map +1 -1
- package/dist/sync/claude-task-writer.d.ts +49 -0
- package/dist/sync/claude-task-writer.d.ts.map +1 -0
- package/dist/sync/claude-task-writer.js +135 -0
- package/dist/sync/claude-task-writer.js.map +1 -0
- package/dist/utils/doc-hash.d.ts +10 -0
- package/dist/utils/doc-hash.d.ts.map +1 -0
- package/dist/utils/doc-hash.js +14 -0
- package/dist/utils/doc-hash.js.map +1 -0
- package/dist/utils/doc-renderer.d.ts +44 -0
- package/dist/utils/doc-renderer.d.ts.map +1 -0
- package/dist/utils/doc-renderer.js +202 -0
- package/dist/utils/doc-renderer.js.map +1 -0
- package/dist/utils/math.d.ts +5 -1
- package/dist/utils/math.d.ts.map +1 -1
- package/dist/utils/math.js +12 -4
- package/dist/utils/math.js.map +1 -1
- package/dist/utils/sql.d.ts +9 -0
- package/dist/utils/sql.d.ts.map +1 -0
- package/dist/utils/sql.js +9 -0
- package/dist/utils/sql.js.map +1 -0
- package/dist/utils/toml-config.d.ts +22 -0
- package/dist/utils/toml-config.d.ts.map +1 -0
- package/dist/utils/toml-config.js +75 -0
- package/dist/utils/toml-config.js.map +1 -0
- package/dist/worker/hooks.d.ts +102 -0
- package/dist/worker/hooks.d.ts.map +1 -0
- package/dist/worker/hooks.js +11 -0
- package/dist/worker/hooks.js.map +1 -0
- package/dist/worker/index.d.ts +9 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +8 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/run-worker.d.ts +33 -0
- package/dist/worker/run-worker.d.ts.map +1 -0
- package/dist/worker/run-worker.js +265 -0
- package/dist/worker/run-worker.js.map +1 -0
- package/package.json +14 -12
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
2
|
import { DeduplicationRepository } from "../repo/deduplication-repo.js";
|
|
3
3
|
import { hashContent } from "../mappers/deduplication.js";
|
|
4
|
+
import { BatchProcessingError } from "../errors.js";
|
|
4
5
|
/**
|
|
5
6
|
* Default batch size for hash checking operations.
|
|
6
7
|
* Balances between query efficiency and memory usage.
|
|
@@ -18,24 +19,19 @@ export const DeduplicationServiceLive = Layer.effect(DeduplicationService, Effec
|
|
|
18
19
|
return {
|
|
19
20
|
processLine: (content, filePath, lineNumber) => Effect.gen(function* () {
|
|
20
21
|
const hash = hashContent(content);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
content
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
// Record the new hash
|
|
31
|
-
yield* repo.insertHash({
|
|
22
|
+
// Use atomic insert-or-ignore to handle race conditions safely.
|
|
23
|
+
// If two concurrent calls try to process the same content:
|
|
24
|
+
// - First one succeeds with inserted=true
|
|
25
|
+
// - Second one gets inserted=false (hash already exists)
|
|
26
|
+
// No race window between check and insert.
|
|
27
|
+
const { inserted } = yield* repo.tryInsertHash({
|
|
32
28
|
contentHash: hash,
|
|
33
29
|
sourceFile: filePath,
|
|
34
30
|
sourceLine: lineNumber
|
|
35
31
|
});
|
|
36
32
|
return {
|
|
37
33
|
hash,
|
|
38
|
-
isNew:
|
|
34
|
+
isNew: inserted,
|
|
39
35
|
lineNumber,
|
|
40
36
|
content
|
|
41
37
|
};
|
|
@@ -66,25 +62,66 @@ export const DeduplicationServiceLive = Layer.effect(DeduplicationService, Effec
|
|
|
66
62
|
...l,
|
|
67
63
|
hash: hashContent(l.content)
|
|
68
64
|
}));
|
|
69
|
-
// Check existing hashes in batches
|
|
65
|
+
// Check existing hashes in batches with error handling
|
|
70
66
|
let existingHashes = new Set();
|
|
67
|
+
const totalBatches = Math.ceil(lineHashes.length / batchSize);
|
|
71
68
|
for (let i = 0; i < lineHashes.length; i += batchSize) {
|
|
69
|
+
const batchIndex = Math.floor(i / batchSize);
|
|
72
70
|
const batch = lineHashes.slice(i, i + batchSize);
|
|
73
71
|
const batchHashes = batch.map(l => l.hash);
|
|
74
|
-
const
|
|
75
|
-
|
|
72
|
+
const batchResult = yield* repo.hashesExist(batchHashes).pipe(Effect.mapError((cause) => {
|
|
73
|
+
// Calculate partial results up to this point
|
|
74
|
+
const checkedLines = lineHashes.slice(0, i);
|
|
75
|
+
const newLinesPartial = checkedLines.filter(l => !existingHashes.has(l.hash));
|
|
76
|
+
const skippedLinesPartial = checkedLines.filter(l => existingHashes.has(l.hash));
|
|
77
|
+
const lastCheckedLine = checkedLines[checkedLines.length - 1];
|
|
78
|
+
return new BatchProcessingError({
|
|
79
|
+
operation: "hashesExist",
|
|
80
|
+
batchIndex,
|
|
81
|
+
totalBatches,
|
|
82
|
+
partialResult: {
|
|
83
|
+
filePath,
|
|
84
|
+
totalLines: lines.length,
|
|
85
|
+
newLines: newLinesPartial.length,
|
|
86
|
+
skippedLines: skippedLinesPartial.length,
|
|
87
|
+
startLine,
|
|
88
|
+
endLine: lastCheckedLine?.lineNumber ?? startLine - 1,
|
|
89
|
+
duration: Date.now() - startTime
|
|
90
|
+
},
|
|
91
|
+
cause
|
|
92
|
+
});
|
|
93
|
+
}));
|
|
94
|
+
existingHashes = new Set([...existingHashes, ...batchResult]);
|
|
76
95
|
}
|
|
77
96
|
// Separate new and existing lines
|
|
78
97
|
const newLines = lineHashes.filter(l => !existingHashes.has(l.hash));
|
|
79
98
|
const skippedLines = lineHashes.filter(l => existingHashes.has(l.hash));
|
|
80
|
-
// Insert new hashes
|
|
99
|
+
// Insert new hashes with error handling
|
|
81
100
|
if (newLines.length > 0) {
|
|
82
101
|
const hashInputs = newLines.map(l => ({
|
|
83
102
|
contentHash: l.hash,
|
|
84
103
|
sourceFile: filePath,
|
|
85
104
|
sourceLine: l.lineNumber
|
|
86
105
|
}));
|
|
87
|
-
yield* repo.insertHashes(hashInputs)
|
|
106
|
+
yield* repo.insertHashes(hashInputs).pipe(Effect.mapError((cause) => {
|
|
107
|
+
// All hash checks completed, but insert failed
|
|
108
|
+
// Return partial result with check phase complete but no inserts
|
|
109
|
+
return new BatchProcessingError({
|
|
110
|
+
operation: "insertHashes",
|
|
111
|
+
batchIndex: 0,
|
|
112
|
+
totalBatches: 1,
|
|
113
|
+
partialResult: {
|
|
114
|
+
filePath,
|
|
115
|
+
totalLines: lines.length,
|
|
116
|
+
newLines: 0, // None were inserted
|
|
117
|
+
skippedLines: skippedLines.length,
|
|
118
|
+
startLine,
|
|
119
|
+
endLine: lineHashes[lineHashes.length - 1]?.lineNumber ?? startLine - 1,
|
|
120
|
+
duration: Date.now() - startTime
|
|
121
|
+
},
|
|
122
|
+
cause
|
|
123
|
+
});
|
|
124
|
+
}));
|
|
88
125
|
}
|
|
89
126
|
// Calculate end line
|
|
90
127
|
const lastLine = linesToProcess[linesToProcess.length - 1];
|
|
@@ -103,21 +140,38 @@ export const DeduplicationServiceLive = Layer.effect(DeduplicationService, Effec
|
|
|
103
140
|
const hash = hashContent(content);
|
|
104
141
|
return yield* repo.hashExists(hash);
|
|
105
142
|
}),
|
|
106
|
-
filterProcessed: (contents) => Effect.gen(function* () {
|
|
143
|
+
filterProcessed: (contents, options = {}) => Effect.gen(function* () {
|
|
107
144
|
if (contents.length === 0)
|
|
108
145
|
return new Set();
|
|
109
|
-
|
|
146
|
+
const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
147
|
+
// Compute hashes and build content-to-hash mapping
|
|
110
148
|
const contentHashMap = new Map();
|
|
111
149
|
for (const content of contents) {
|
|
112
150
|
contentHashMap.set(hashContent(content), content);
|
|
113
151
|
}
|
|
114
|
-
const
|
|
115
|
-
|
|
152
|
+
const allHashes = [...contentHashMap.keys()];
|
|
153
|
+
const totalBatches = Math.ceil(allHashes.length / batchSize);
|
|
116
154
|
const processedContents = new Set();
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
155
|
+
// Check hashes in batches with error handling
|
|
156
|
+
for (let i = 0; i < allHashes.length; i += batchSize) {
|
|
157
|
+
const batchIndex = Math.floor(i / batchSize);
|
|
158
|
+
const batchHashes = allHashes.slice(i, i + batchSize);
|
|
159
|
+
const existingHashes = yield* repo.hashesExist(batchHashes).pipe(Effect.mapError((cause) => {
|
|
160
|
+
// Return partial results collected so far
|
|
161
|
+
return new BatchProcessingError({
|
|
162
|
+
operation: "filterProcessed",
|
|
163
|
+
batchIndex,
|
|
164
|
+
totalBatches,
|
|
165
|
+
partialResult: new Set(processedContents),
|
|
166
|
+
cause
|
|
167
|
+
});
|
|
168
|
+
}));
|
|
169
|
+
// Add found content strings to the result set
|
|
170
|
+
for (const hash of existingHashes) {
|
|
171
|
+
const content = contentHashMap.get(hash);
|
|
172
|
+
if (content)
|
|
173
|
+
processedContents.add(content);
|
|
174
|
+
}
|
|
121
175
|
}
|
|
122
176
|
return processedContents;
|
|
123
177
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deduplication-service.js","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"deduplication-service.js","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
2
|
import { DependencyRepository } from "../repo/dep-repo.js";
|
|
3
3
|
import { TaskRepository } from "../repo/task-repo.js";
|
|
4
|
-
import { ValidationError, CircularDependencyError, TaskNotFoundError, DatabaseError } from "../errors.js";
|
|
4
|
+
import { ValidationError, CircularDependencyError, TaskNotFoundError, DatabaseError, DependencyNotFoundError } from "../errors.js";
|
|
5
5
|
import type { TaskId } from "@jamesaphoenix/tx-types";
|
|
6
6
|
declare const DependencyService_base: Context.TagClass<DependencyService, "DependencyService", {
|
|
7
7
|
readonly addBlocker: (taskId: TaskId, blockerId: TaskId) => Effect.Effect<void, ValidationError | CircularDependencyError | TaskNotFoundError | DatabaseError>;
|
|
8
|
-
readonly removeBlocker: (taskId: TaskId, blockerId: TaskId) => Effect.Effect<void, DatabaseError>;
|
|
8
|
+
readonly removeBlocker: (taskId: TaskId, blockerId: TaskId) => Effect.Effect<void, DatabaseError | DependencyNotFoundError>;
|
|
9
9
|
}>;
|
|
10
10
|
export declare class DependencyService extends DependencyService_base {
|
|
11
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dep-service.d.ts","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"dep-service.d.ts","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAClI,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;;yBAK5B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,uBAAuB,GAAG,iBAAiB,GAAG,aAAa,CAAC;4BACtI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,uBAAuB,CAAC;;AAJ/H,qBAAa,iBAAkB,SAAQ,sBAMpC;CAAG;AAEN,eAAO,MAAM,qBAAqB,8EAwCjC,CAAA"}
|
|
@@ -20,13 +20,17 @@ export const DependencyServiceLive = Layer.effect(DependencyService, Effect.gen(
|
|
|
20
20
|
if (!blocker) {
|
|
21
21
|
return yield* Effect.fail(new TaskNotFoundError({ id: blockerId }));
|
|
22
22
|
}
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// Atomically check for cycles and insert dependency in a single transaction.
|
|
24
|
+
// This prevents race conditions where two concurrent addBlocker calls could
|
|
25
|
+
// both pass cycle detection before either inserts (DOCTRINE RULE 4).
|
|
26
|
+
const result = yield* depRepo.insertWithCycleCheck(blockerId, taskId);
|
|
27
|
+
if (result._tag === "wouldCycle") {
|
|
27
28
|
return yield* Effect.fail(new CircularDependencyError({ taskId, blockerId }));
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
// Idempotent: dependency already exists, nothing to do
|
|
31
|
+
if (result._tag === "alreadyExists") {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
30
34
|
}),
|
|
31
35
|
removeBlocker: (taskId, blockerId) => depRepo.remove(blockerId, taskId)
|
|
32
36
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dep-service.js","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"dep-service.js","sourceRoot":"","sources":["../../src/services/dep-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAA0C,MAAM,cAAc,CAAA;AAGlI,MAAM,OAAO,iBAAkB,SAAQ,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAMpE;CAAG;AAEN,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,CAC/C,iBAAiB,EACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;IAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,cAAc,CAAA;IAEtC,OAAO;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAA;YAC1F,CAAC;YAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;YAClE,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YACrE,CAAC;YAED,6EAA6E;YAC7E,4EAA4E;YAC5E,qEAAqE;YACrE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;YACrE,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACjC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,uBAAuB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YAC/E,CAAC;YACD,uDAAuD;YACvD,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACpC,OAAM;YACR,CAAC;QACH,CAAC,CAAC;QAEJ,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CACnC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;KACpC,CAAA;AACH,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
2
|
import type { LearningWithScore } from "@jamesaphoenix/tx-types";
|
|
3
|
+
import { EmbeddingDimensionMismatchError } from "../errors.js";
|
|
3
4
|
declare const DiversifierService_base: Context.TagClass<DiversifierService, "DiversifierService", {
|
|
4
5
|
/**
|
|
5
6
|
* Apply MMR diversification to scored candidates.
|
|
@@ -9,7 +10,7 @@ declare const DiversifierService_base: Context.TagClass<DiversifierService, "Div
|
|
|
9
10
|
* @param lambda - Balance between relevance (1.0) and diversity (0.0), default 0.7
|
|
10
11
|
* @returns Diversified list of learnings, maintaining score order within diversity constraints
|
|
11
12
|
*/
|
|
12
|
-
readonly mmrDiversify: (candidates: readonly LearningWithScore[], limit: number, lambda?: number) => Effect.Effect<readonly LearningWithScore[]>;
|
|
13
|
+
readonly mmrDiversify: (candidates: readonly LearningWithScore[], limit: number, lambda?: number) => Effect.Effect<readonly LearningWithScore[], EmbeddingDimensionMismatchError>;
|
|
13
14
|
}>;
|
|
14
15
|
/**
|
|
15
16
|
* DiversifierService provides Maximal Marginal Relevance (MMR) diversification
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diversifier-service.d.ts","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;;
|
|
1
|
+
{"version":3,"file":"diversifier-service.d.ts","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAEhE,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAA;;IAe1D;;;;;;;OAOG;2BACoB,CACrB,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,EAAE,+BAA+B,CAAC;;AAzBrF;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,uBAiBrC;CAAG;AAkGN;;;GAGG;AACH,eAAO,MAAM,sBAAsB,+CAMlC,CAAA;AAgCD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,+CAsDlC,CAAA;AA4CD;;GAEG;AACH,eAAO,MAAM,sBAAsB,+CAAyB,CAAA"}
|
|
@@ -31,25 +31,17 @@ const CATEGORY_MAX_PER_TOP_N = 2;
|
|
|
31
31
|
const maxSimilarityToSelected = (candidate, selected) => {
|
|
32
32
|
// No embedding means we can't compute similarity
|
|
33
33
|
if (!candidate.embedding) {
|
|
34
|
-
return 0;
|
|
34
|
+
return Effect.succeed(0);
|
|
35
35
|
}
|
|
36
36
|
// No selected items yet
|
|
37
37
|
if (selected.length === 0) {
|
|
38
|
-
return 0;
|
|
38
|
+
return Effect.succeed(0);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!item.embedding) {
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const sim = cosineSimilarity(candidate.embedding, item.embedding);
|
|
47
|
-
if (sim > maxSim) {
|
|
48
|
-
maxSim = sim;
|
|
49
|
-
}
|
|
40
|
+
const itemsWithEmbeddings = selected.filter((item) => item.embedding !== null);
|
|
41
|
+
if (itemsWithEmbeddings.length === 0) {
|
|
42
|
+
return Effect.succeed(0);
|
|
50
43
|
}
|
|
51
|
-
|
|
52
|
-
return maxSim === -Infinity ? 0 : maxSim;
|
|
44
|
+
return Effect.forEach(itemsWithEmbeddings, item => cosineSimilarity(candidate.embedding, item.embedding)).pipe(Effect.map(similarities => Math.max(...similarities)));
|
|
53
45
|
};
|
|
54
46
|
/**
|
|
55
47
|
* Calculate MMR score for a candidate.
|
|
@@ -61,8 +53,7 @@ const maxSimilarityToSelected = (candidate, selected) => {
|
|
|
61
53
|
*/
|
|
62
54
|
const mmrScore = (candidate, selected, lambda) => {
|
|
63
55
|
const relevance = candidate.relevanceScore;
|
|
64
|
-
|
|
65
|
-
return lambda * relevance - (1 - lambda) * maxSim;
|
|
56
|
+
return maxSimilarityToSelected(candidate, selected).pipe(Effect.map(maxSim => lambda * relevance - (1 - lambda) * maxSim));
|
|
66
57
|
};
|
|
67
58
|
/**
|
|
68
59
|
* Check if adding a candidate would violate category limits in top N.
|
|
@@ -90,6 +81,26 @@ const wouldViolateCategoryLimit = (candidate, selected, topN = CATEGORY_LIMIT_TO
|
|
|
90
81
|
export const DiversifierServiceNoop = Layer.succeed(DiversifierService, {
|
|
91
82
|
mmrDiversify: (candidates, limit, _lambda) => Effect.succeed(candidates.slice(0, limit))
|
|
92
83
|
});
|
|
84
|
+
/**
|
|
85
|
+
* Find the best candidate from remaining items using MMR scoring.
|
|
86
|
+
* Returns the candidate with the highest MMR score that doesn't violate category limits.
|
|
87
|
+
*/
|
|
88
|
+
const findBestCandidate = (remaining, selected, lambda, checkCategoryLimits) => Effect.gen(function* () {
|
|
89
|
+
let bestCandidate = null;
|
|
90
|
+
let bestScore = -Infinity;
|
|
91
|
+
for (const candidate of remaining) {
|
|
92
|
+
// Skip if would violate category limit (when checking is enabled)
|
|
93
|
+
if (checkCategoryLimits && wouldViolateCategoryLimit(candidate, selected)) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const score = yield* mmrScore(candidate, selected, lambda);
|
|
97
|
+
if (score > bestScore) {
|
|
98
|
+
bestScore = score;
|
|
99
|
+
bestCandidate = candidate;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return bestCandidate ? { candidate: bestCandidate, score: bestScore } : null;
|
|
103
|
+
});
|
|
93
104
|
/**
|
|
94
105
|
* Live implementation with full MMR algorithm and category limits.
|
|
95
106
|
*
|
|
@@ -100,7 +111,7 @@ export const DiversifierServiceNoop = Layer.succeed(DiversifierService, {
|
|
|
100
111
|
* 4. Repeat until limit reached or no candidates remain
|
|
101
112
|
*/
|
|
102
113
|
export const DiversifierServiceLive = Layer.succeed(DiversifierService, {
|
|
103
|
-
mmrDiversify: (candidates, limit, lambda = DEFAULT_LAMBDA) => Effect.
|
|
114
|
+
mmrDiversify: (candidates, limit, lambda = DEFAULT_LAMBDA) => Effect.gen(function* () {
|
|
104
115
|
// Edge case: empty candidates
|
|
105
116
|
if (candidates.length === 0) {
|
|
106
117
|
return [];
|
|
@@ -109,8 +120,8 @@ export const DiversifierServiceLive = Layer.succeed(DiversifierService, {
|
|
|
109
120
|
if (limit <= 0) {
|
|
110
121
|
return [];
|
|
111
122
|
}
|
|
112
|
-
// Edge case: only one candidate
|
|
113
|
-
if (candidates.length === 1
|
|
123
|
+
// Edge case: only one candidate
|
|
124
|
+
if (candidates.length === 1) {
|
|
114
125
|
return candidates.slice(0, 1);
|
|
115
126
|
}
|
|
116
127
|
// Check if any candidates have embeddings
|
|
@@ -123,36 +134,19 @@ export const DiversifierServiceLive = Layer.succeed(DiversifierService, {
|
|
|
123
134
|
const selected = [];
|
|
124
135
|
const remaining = new Set(candidates);
|
|
125
136
|
while (selected.length < limit && remaining.size > 0) {
|
|
126
|
-
|
|
127
|
-
let
|
|
128
|
-
for (const candidate of remaining) {
|
|
129
|
-
// Skip if would violate category limit
|
|
130
|
-
if (wouldViolateCategoryLimit(candidate, selected)) {
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
const score = mmrScore(candidate, selected, lambda);
|
|
134
|
-
if (score > bestScore) {
|
|
135
|
-
bestScore = score;
|
|
136
|
-
bestCandidate = candidate;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
137
|
+
// Try to find best candidate respecting category limits
|
|
138
|
+
let result = yield* findBestCandidate(remaining, selected, lambda, true);
|
|
139
139
|
// If no valid candidate found (all remaining violate category limits),
|
|
140
140
|
// try to find any candidate without category limit check
|
|
141
|
-
if (!
|
|
142
|
-
|
|
143
|
-
const score = mmrScore(candidate, selected, lambda);
|
|
144
|
-
if (score > bestScore) {
|
|
145
|
-
bestScore = score;
|
|
146
|
-
bestCandidate = candidate;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
141
|
+
if (!result) {
|
|
142
|
+
result = yield* findBestCandidate(remaining, selected, lambda, false);
|
|
149
143
|
}
|
|
150
144
|
// Still no candidate? We're done
|
|
151
|
-
if (!
|
|
145
|
+
if (!result) {
|
|
152
146
|
break;
|
|
153
147
|
}
|
|
154
|
-
selected.push(
|
|
155
|
-
remaining.delete(
|
|
148
|
+
selected.push(result.candidate);
|
|
149
|
+
remaining.delete(result.candidate);
|
|
156
150
|
}
|
|
157
151
|
return selected;
|
|
158
152
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diversifier-service.js","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"diversifier-service.js","sourceRoot":"","sources":["../../src/services/diversifier-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
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 { Context, Effect, Layer } from "effect";
|
|
10
|
+
import { DocRepository } from "../repo/doc-repo.js";
|
|
11
|
+
import { DatabaseError, ValidationError, DocNotFoundError, DocLockedError, InvalidDocYamlError, InvariantNotFoundError } from "../errors.js";
|
|
12
|
+
import type { Doc, DocKind, DocStatus, DocLink, DocLinkType, Invariant, InvariantCheck, DocGraph } from "@jamesaphoenix/tx-types";
|
|
13
|
+
declare const DocService_base: Context.TagClass<DocService, "DocService", {
|
|
14
|
+
readonly create: (input: {
|
|
15
|
+
kind: DocKind;
|
|
16
|
+
name: string;
|
|
17
|
+
title: string;
|
|
18
|
+
yamlContent: string;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}) => Effect.Effect<Doc, ValidationError | InvalidDocYamlError | DatabaseError>;
|
|
21
|
+
readonly get: (name: string, version?: number) => Effect.Effect<Doc, DocNotFoundError | DatabaseError>;
|
|
22
|
+
readonly update: (name: string, yamlContent: string) => Effect.Effect<Doc, DocNotFoundError | DocLockedError | InvalidDocYamlError | DatabaseError>;
|
|
23
|
+
readonly lock: (name: string) => Effect.Effect<Doc, DocNotFoundError | DatabaseError>;
|
|
24
|
+
readonly list: (filter?: {
|
|
25
|
+
kind?: DocKind;
|
|
26
|
+
status?: DocStatus;
|
|
27
|
+
}) => Effect.Effect<readonly Doc[], DatabaseError>;
|
|
28
|
+
readonly remove: (name: string) => Effect.Effect<void, DocNotFoundError | DocLockedError | DatabaseError>;
|
|
29
|
+
readonly render: (name?: string) => Effect.Effect<readonly string[], DocNotFoundError | InvalidDocYamlError | DatabaseError>;
|
|
30
|
+
readonly createVersion: (name: string) => Effect.Effect<Doc, DocNotFoundError | ValidationError | DatabaseError>;
|
|
31
|
+
readonly linkDocs: (fromName: string, toName: string, linkType?: DocLinkType) => Effect.Effect<DocLink, DocNotFoundError | ValidationError | DatabaseError>;
|
|
32
|
+
readonly attachTask: (taskId: string, docName: string, linkType?: "implements" | "references") => Effect.Effect<void, DocNotFoundError | DatabaseError>;
|
|
33
|
+
readonly createPatch: (designName: string, patchName: string, patchTitle: string) => Effect.Effect<Doc, DocNotFoundError | ValidationError | InvalidDocYamlError | DatabaseError>;
|
|
34
|
+
readonly validate: () => Effect.Effect<readonly string[], DatabaseError>;
|
|
35
|
+
readonly detectDrift: (name: string) => Effect.Effect<readonly string[], DocNotFoundError | DatabaseError>;
|
|
36
|
+
readonly generateIndex: () => Effect.Effect<void, DatabaseError>;
|
|
37
|
+
readonly syncInvariants: (docName?: string) => Effect.Effect<readonly Invariant[], DocNotFoundError | InvalidDocYamlError | DatabaseError>;
|
|
38
|
+
readonly listInvariants: (filter?: {
|
|
39
|
+
subsystem?: string;
|
|
40
|
+
enforcement?: string;
|
|
41
|
+
}) => Effect.Effect<readonly Invariant[], DatabaseError>;
|
|
42
|
+
readonly recordInvariantCheck: (id: string, passed: boolean, details?: string, durationMs?: number) => Effect.Effect<InvariantCheck, InvariantNotFoundError | DatabaseError>;
|
|
43
|
+
readonly getDocGraph: () => Effect.Effect<DocGraph, DatabaseError>;
|
|
44
|
+
}>;
|
|
45
|
+
export declare class DocService extends DocService_base {
|
|
46
|
+
}
|
|
47
|
+
export declare const DocServiceLive: Layer.Layer<DocService, never, DocRepository>;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=doc-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc-service.d.ts","sourceRoot":"","sources":["../../src/services/doc-service.ts"],"names":[],"mappings":"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"}
|