@stoneforge/quarry 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -0
- package/README.md +160 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/quarry-api.d.ts +268 -0
- package/dist/api/quarry-api.d.ts.map +1 -0
- package/dist/api/quarry-api.js +3905 -0
- package/dist/api/quarry-api.js.map +1 -0
- package/dist/api/types.d.ts +1359 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +204 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/sf.d.ts +3 -0
- package/dist/bin/sf.d.ts.map +1 -0
- package/dist/bin/sf.js +9 -0
- package/dist/bin/sf.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +11 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +465 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/alias.d.ts +8 -0
- package/dist/cli/commands/alias.d.ts.map +1 -0
- package/dist/cli/commands/alias.js +70 -0
- package/dist/cli/commands/alias.js.map +1 -0
- package/dist/cli/commands/channel.d.ts +13 -0
- package/dist/cli/commands/channel.d.ts.map +1 -0
- package/dist/cli/commands/channel.js +680 -0
- package/dist/cli/commands/channel.js.map +1 -0
- package/dist/cli/commands/completion.d.ts +8 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/completion.js +87 -0
- package/dist/cli/commands/completion.js.map +1 -0
- package/dist/cli/commands/config.d.ts +12 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +242 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/crud.d.ts +64 -0
- package/dist/cli/commands/crud.d.ts.map +1 -0
- package/dist/cli/commands/crud.js +805 -0
- package/dist/cli/commands/crud.js.map +1 -0
- package/dist/cli/commands/dep.d.ts +16 -0
- package/dist/cli/commands/dep.d.ts.map +1 -0
- package/dist/cli/commands/dep.js +499 -0
- package/dist/cli/commands/dep.js.map +1 -0
- package/dist/cli/commands/document.d.ts +12 -0
- package/dist/cli/commands/document.d.ts.map +1 -0
- package/dist/cli/commands/document.js +1039 -0
- package/dist/cli/commands/document.js.map +1 -0
- package/dist/cli/commands/embeddings.d.ts +12 -0
- package/dist/cli/commands/embeddings.d.ts.map +1 -0
- package/dist/cli/commands/embeddings.js +273 -0
- package/dist/cli/commands/embeddings.js.map +1 -0
- package/dist/cli/commands/entity.d.ts +16 -0
- package/dist/cli/commands/entity.d.ts.map +1 -0
- package/dist/cli/commands/entity.js +522 -0
- package/dist/cli/commands/entity.js.map +1 -0
- package/dist/cli/commands/gc.d.ts +10 -0
- package/dist/cli/commands/gc.d.ts.map +1 -0
- package/dist/cli/commands/gc.js +257 -0
- package/dist/cli/commands/gc.js.map +1 -0
- package/dist/cli/commands/help.d.ts +11 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +169 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/history.d.ts +9 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +160 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/identity.d.ts +18 -0
- package/dist/cli/commands/identity.d.ts.map +1 -0
- package/dist/cli/commands/identity.js +698 -0
- package/dist/cli/commands/identity.js.map +1 -0
- package/dist/cli/commands/inbox.d.ts +20 -0
- package/dist/cli/commands/inbox.d.ts.map +1 -0
- package/dist/cli/commands/inbox.js +493 -0
- package/dist/cli/commands/inbox.js.map +1 -0
- package/dist/cli/commands/init.d.ts +20 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +144 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +9 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +200 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/library.d.ts +12 -0
- package/dist/cli/commands/library.d.ts.map +1 -0
- package/dist/cli/commands/library.js +665 -0
- package/dist/cli/commands/library.js.map +1 -0
- package/dist/cli/commands/message.d.ts +11 -0
- package/dist/cli/commands/message.d.ts.map +1 -0
- package/dist/cli/commands/message.js +608 -0
- package/dist/cli/commands/message.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +17 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +698 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/playbook.d.ts +12 -0
- package/dist/cli/commands/playbook.d.ts.map +1 -0
- package/dist/cli/commands/playbook.js +730 -0
- package/dist/cli/commands/playbook.js.map +1 -0
- package/dist/cli/commands/reset.d.ts +12 -0
- package/dist/cli/commands/reset.d.ts.map +1 -0
- package/dist/cli/commands/reset.js +306 -0
- package/dist/cli/commands/reset.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +11 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +106 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +82 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +14 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +370 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/task.d.ts +25 -0
- package/dist/cli/commands/task.d.ts.map +1 -0
- package/dist/cli/commands/task.js +1153 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/team.d.ts +13 -0
- package/dist/cli/commands/team.d.ts.map +1 -0
- package/dist/cli/commands/team.js +471 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/commands/workflow.d.ts +16 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +753 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/completion.d.ts +28 -0
- package/dist/cli/completion.d.ts.map +1 -0
- package/dist/cli/completion.js +295 -0
- package/dist/cli/completion.js.map +1 -0
- package/dist/cli/db.d.ts +38 -0
- package/dist/cli/db.d.ts.map +1 -0
- package/dist/cli/db.js +90 -0
- package/dist/cli/db.js.map +1 -0
- package/dist/cli/formatter.d.ts +87 -0
- package/dist/cli/formatter.d.ts.map +1 -0
- package/dist/cli/formatter.js +464 -0
- package/dist/cli/formatter.js.map +1 -0
- package/dist/cli/index.d.ts +33 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +38 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parser.d.ts +45 -0
- package/dist/cli/parser.d.ts.map +1 -0
- package/dist/cli/parser.js +256 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/cli/plugin-loader.d.ts +39 -0
- package/dist/cli/plugin-loader.d.ts.map +1 -0
- package/dist/cli/plugin-loader.js +165 -0
- package/dist/cli/plugin-loader.js.map +1 -0
- package/dist/cli/plugin-registry.d.ts +50 -0
- package/dist/cli/plugin-registry.d.ts.map +1 -0
- package/dist/cli/plugin-registry.js +206 -0
- package/dist/cli/plugin-registry.js.map +1 -0
- package/dist/cli/plugin-types.d.ts +106 -0
- package/dist/cli/plugin-types.d.ts.map +1 -0
- package/dist/cli/plugin-types.js +103 -0
- package/dist/cli/plugin-types.js.map +1 -0
- package/dist/cli/runner.d.ts +35 -0
- package/dist/cli/runner.d.ts.map +1 -0
- package/dist/cli/runner.js +340 -0
- package/dist/cli/runner.js.map +1 -0
- package/dist/cli/suggest.d.ts +15 -0
- package/dist/cli/suggest.d.ts.map +1 -0
- package/dist/cli/suggest.js +49 -0
- package/dist/cli/suggest.js.map +1 -0
- package/dist/cli/types.d.ts +138 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +63 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config/config.d.ts +86 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +348 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +66 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +114 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/duration.d.ts +75 -0
- package/dist/config/duration.d.ts.map +1 -0
- package/dist/config/duration.js +190 -0
- package/dist/config/duration.js.map +1 -0
- package/dist/config/env.d.ts +67 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +207 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/file.d.ts +97 -0
- package/dist/config/file.d.ts.map +1 -0
- package/dist/config/file.js +365 -0
- package/dist/config/file.js.map +1 -0
- package/dist/config/index.d.ts +35 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +41 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/merge.d.ts +53 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +226 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/types.d.ts +257 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +72 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +55 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +251 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/http/index.d.ts +8 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +12 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/sync-handlers.d.ts +162 -0
- package/dist/http/sync-handlers.d.ts.map +1 -0
- package/dist/http/sync-handlers.js +271 -0
- package/dist/http/sync-handlers.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/server/index.d.ts +34 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3329 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/static.d.ts +18 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +71 -0
- package/dist/server/static.js.map +1 -0
- package/dist/server/ws/broadcaster.d.ts +8 -0
- package/dist/server/ws/broadcaster.d.ts.map +1 -0
- package/dist/server/ws/broadcaster.js +7 -0
- package/dist/server/ws/broadcaster.js.map +1 -0
- package/dist/server/ws/handler.d.ts +55 -0
- package/dist/server/ws/handler.d.ts.map +1 -0
- package/dist/server/ws/handler.js +160 -0
- package/dist/server/ws/handler.js.map +1 -0
- package/dist/services/blocked-cache.d.ts +297 -0
- package/dist/services/blocked-cache.d.ts.map +1 -0
- package/dist/services/blocked-cache.js +755 -0
- package/dist/services/blocked-cache.js.map +1 -0
- package/dist/services/dependency.d.ts +205 -0
- package/dist/services/dependency.d.ts.map +1 -0
- package/dist/services/dependency.js +566 -0
- package/dist/services/dependency.js.map +1 -0
- package/dist/services/embeddings/fusion.d.ts +33 -0
- package/dist/services/embeddings/fusion.d.ts.map +1 -0
- package/dist/services/embeddings/fusion.js +34 -0
- package/dist/services/embeddings/fusion.js.map +1 -0
- package/dist/services/embeddings/index.d.ts +12 -0
- package/dist/services/embeddings/index.d.ts.map +1 -0
- package/dist/services/embeddings/index.js +10 -0
- package/dist/services/embeddings/index.js.map +1 -0
- package/dist/services/embeddings/local-provider.d.ts +31 -0
- package/dist/services/embeddings/local-provider.d.ts.map +1 -0
- package/dist/services/embeddings/local-provider.js +80 -0
- package/dist/services/embeddings/local-provider.js.map +1 -0
- package/dist/services/embeddings/service.d.ts +76 -0
- package/dist/services/embeddings/service.d.ts.map +1 -0
- package/dist/services/embeddings/service.js +153 -0
- package/dist/services/embeddings/service.js.map +1 -0
- package/dist/services/embeddings/types.d.ts +70 -0
- package/dist/services/embeddings/types.d.ts.map +1 -0
- package/dist/services/embeddings/types.js +8 -0
- package/dist/services/embeddings/types.js.map +1 -0
- package/dist/services/id-length-cache.d.ts +156 -0
- package/dist/services/id-length-cache.d.ts.map +1 -0
- package/dist/services/id-length-cache.js +197 -0
- package/dist/services/id-length-cache.js.map +1 -0
- package/dist/services/inbox.d.ts +147 -0
- package/dist/services/inbox.d.ts.map +1 -0
- package/dist/services/inbox.js +428 -0
- package/dist/services/inbox.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +10 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/priority-service.d.ts +145 -0
- package/dist/services/priority-service.d.ts.map +1 -0
- package/dist/services/priority-service.js +272 -0
- package/dist/services/priority-service.js.map +1 -0
- package/dist/services/search-utils.d.ts +47 -0
- package/dist/services/search-utils.d.ts.map +1 -0
- package/dist/services/search-utils.js +83 -0
- package/dist/services/search-utils.js.map +1 -0
- package/dist/sync/hash.d.ts +48 -0
- package/dist/sync/hash.d.ts.map +1 -0
- package/dist/sync/hash.js +136 -0
- package/dist/sync/hash.js.map +1 -0
- package/dist/sync/index.d.ts +11 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +16 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/merge.d.ts +80 -0
- package/dist/sync/merge.d.ts.map +1 -0
- package/dist/sync/merge.js +310 -0
- package/dist/sync/merge.js.map +1 -0
- package/dist/sync/serialization.d.ts +132 -0
- package/dist/sync/serialization.d.ts.map +1 -0
- package/dist/sync/serialization.js +306 -0
- package/dist/sync/serialization.js.map +1 -0
- package/dist/sync/service.d.ts +102 -0
- package/dist/sync/service.d.ts.map +1 -0
- package/dist/sync/service.js +493 -0
- package/dist/sync/service.js.map +1 -0
- package/dist/sync/types.d.ts +275 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +76 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/systems/identity.d.ts +479 -0
- package/dist/systems/identity.d.ts.map +1 -0
- package/dist/systems/identity.js +817 -0
- package/dist/systems/identity.js.map +1 -0
- package/dist/systems/index.d.ts +8 -0
- package/dist/systems/index.d.ts.map +1 -0
- package/dist/systems/index.js +29 -0
- package/dist/systems/index.js.map +1 -0
- package/package.json +121 -0
- package/web/assets/charts-vendor-D1YcbGux.js +55 -0
- package/web/assets/dnd-vendor-DmxE-_ZH.js +5 -0
- package/web/assets/editor-vendor-BxraAWts.js +279 -0
- package/web/assets/index-B77vv208.js +341 -0
- package/web/assets/index-CF_XnVLh.css +1 -0
- package/web/assets/router-vendor-BCKpRBrB.js +41 -0
- package/web/assets/ui-vendor-DUahGnbT.js +45 -0
- package/web/assets/utils-vendor-CfYKiENT.js +813 -0
- package/web/favicon.ico +0 -0
- package/web/index.html +23 -0
- package/web/logo.png +0 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority Service - Dependency-based priority calculation and complexity inheritance
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Effective Priority: Computes a task's priority based on what depends on it
|
|
6
|
+
* (tasks blocking high-priority work inherit that urgency)
|
|
7
|
+
* - Aggregate Complexity: Computes total effort including dependent task complexity
|
|
8
|
+
*/
|
|
9
|
+
import { Priority as PriorityEnum, Complexity as ComplexityEnum, DependencyType as DT } from '@stoneforge/core';
|
|
10
|
+
/**
|
|
11
|
+
* Default priority calculation configuration
|
|
12
|
+
*/
|
|
13
|
+
export const DEFAULT_PRIORITY_CONFIG = {
|
|
14
|
+
maxDepth: 10,
|
|
15
|
+
includeComplexity: false,
|
|
16
|
+
};
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// PriorityService Class
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Service for computing dependency-based priority and complexity
|
|
22
|
+
*/
|
|
23
|
+
export class PriorityService {
|
|
24
|
+
db;
|
|
25
|
+
constructor(db) {
|
|
26
|
+
this.db = db;
|
|
27
|
+
}
|
|
28
|
+
// --------------------------------------------------------------------------
|
|
29
|
+
// Effective Priority Calculation
|
|
30
|
+
// --------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Calculate the effective priority of a task based on its dependents.
|
|
33
|
+
*
|
|
34
|
+
* A task that blocks high-priority tasks should inherit that urgency.
|
|
35
|
+
* The effective priority is the minimum (highest urgency) of:
|
|
36
|
+
* - The task's own priority
|
|
37
|
+
* - The priorities of all tasks that directly or transitively depend on it
|
|
38
|
+
*
|
|
39
|
+
* @param taskId - The task to calculate effective priority for
|
|
40
|
+
* @param config - Optional configuration
|
|
41
|
+
* @returns EffectivePriorityResult with calculation details
|
|
42
|
+
*/
|
|
43
|
+
calculateEffectivePriority(taskId, config = DEFAULT_PRIORITY_CONFIG) {
|
|
44
|
+
// Get the task's base priority
|
|
45
|
+
const task = this.getTaskPriority(taskId);
|
|
46
|
+
if (!task) {
|
|
47
|
+
return {
|
|
48
|
+
basePriority: PriorityEnum.MEDIUM,
|
|
49
|
+
effectivePriority: PriorityEnum.MEDIUM,
|
|
50
|
+
dependentInfluencers: [],
|
|
51
|
+
isInfluenced: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const basePriority = task.priority;
|
|
55
|
+
// Find all tasks that depend on this task (direct and transitive)
|
|
56
|
+
const dependentPriorities = this.collectDependentPriorities(taskId, config.maxDepth);
|
|
57
|
+
// Find the highest priority (lowest number) among dependents
|
|
58
|
+
let effectivePriority = basePriority;
|
|
59
|
+
const influencers = [];
|
|
60
|
+
for (const { id, priority } of dependentPriorities) {
|
|
61
|
+
if (priority < effectivePriority) {
|
|
62
|
+
effectivePriority = priority;
|
|
63
|
+
influencers.length = 0; // Reset - new highest priority found
|
|
64
|
+
influencers.push(id);
|
|
65
|
+
}
|
|
66
|
+
else if (priority === effectivePriority && priority < basePriority) {
|
|
67
|
+
influencers.push(id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
basePriority,
|
|
72
|
+
effectivePriority,
|
|
73
|
+
dependentInfluencers: influencers,
|
|
74
|
+
isInfluenced: effectivePriority !== basePriority,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Calculate effective priorities for multiple tasks efficiently
|
|
79
|
+
*
|
|
80
|
+
* @param taskIds - Array of task IDs to calculate priorities for
|
|
81
|
+
* @param config - Optional configuration
|
|
82
|
+
* @returns Map of taskId to EffectivePriorityResult
|
|
83
|
+
*/
|
|
84
|
+
calculateEffectivePriorities(taskIds, config = DEFAULT_PRIORITY_CONFIG) {
|
|
85
|
+
const results = new Map();
|
|
86
|
+
for (const taskId of taskIds) {
|
|
87
|
+
results.set(taskId, this.calculateEffectivePriority(taskId, config));
|
|
88
|
+
}
|
|
89
|
+
return results;
|
|
90
|
+
}
|
|
91
|
+
// --------------------------------------------------------------------------
|
|
92
|
+
// Aggregate Complexity Calculation
|
|
93
|
+
// --------------------------------------------------------------------------
|
|
94
|
+
/**
|
|
95
|
+
* Calculate the aggregate complexity of a task including its blockers.
|
|
96
|
+
*
|
|
97
|
+
* This represents the total effort needed before this task can be considered
|
|
98
|
+
* truly "done" - including all tasks it's waiting on.
|
|
99
|
+
*
|
|
100
|
+
* Note: This calculates complexity of tasks that THIS task depends on (blockers),
|
|
101
|
+
* not tasks that depend on it.
|
|
102
|
+
*
|
|
103
|
+
* @param taskId - The task to calculate aggregate complexity for
|
|
104
|
+
* @param config - Optional configuration
|
|
105
|
+
* @returns AggregateComplexityResult with calculation details
|
|
106
|
+
*/
|
|
107
|
+
calculateAggregateComplexity(taskId, config = DEFAULT_PRIORITY_CONFIG) {
|
|
108
|
+
// Get the task's base complexity
|
|
109
|
+
const task = this.getTaskPriority(taskId);
|
|
110
|
+
if (!task) {
|
|
111
|
+
return {
|
|
112
|
+
baseComplexity: ComplexityEnum.MEDIUM,
|
|
113
|
+
aggregateComplexity: ComplexityEnum.MEDIUM,
|
|
114
|
+
dependentCount: 0,
|
|
115
|
+
dependentComplexities: [],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const baseComplexity = task.complexity;
|
|
119
|
+
// Find all tasks that this task depends on (blockers, direct and transitive)
|
|
120
|
+
const blockerComplexities = this.collectBlockerComplexities(taskId, config.maxDepth);
|
|
121
|
+
// Sum up complexities
|
|
122
|
+
let totalComplexity = baseComplexity;
|
|
123
|
+
const dependentComplexities = [];
|
|
124
|
+
for (const { id, complexity } of blockerComplexities) {
|
|
125
|
+
totalComplexity += complexity;
|
|
126
|
+
dependentComplexities.push({ id, complexity: complexity });
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
baseComplexity,
|
|
130
|
+
aggregateComplexity: totalComplexity,
|
|
131
|
+
dependentCount: dependentComplexities.length,
|
|
132
|
+
dependentComplexities,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// --------------------------------------------------------------------------
|
|
136
|
+
// Bulk Operations for ready() query optimization
|
|
137
|
+
// --------------------------------------------------------------------------
|
|
138
|
+
/**
|
|
139
|
+
* Enhance an array of tasks with effective priority (for sorting)
|
|
140
|
+
*
|
|
141
|
+
* @param tasks - Array of tasks to enhance
|
|
142
|
+
* @param config - Optional configuration
|
|
143
|
+
* @returns Array of tasks with effectivePriority field
|
|
144
|
+
*/
|
|
145
|
+
enhanceTasksWithEffectivePriority(tasks, config = DEFAULT_PRIORITY_CONFIG) {
|
|
146
|
+
if (tasks.length === 0) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
// Get task IDs
|
|
150
|
+
const taskIds = tasks.map((t) => t.id);
|
|
151
|
+
// Calculate effective priorities for all tasks
|
|
152
|
+
const priorityResults = this.calculateEffectivePriorities(taskIds, config);
|
|
153
|
+
// Enhance tasks
|
|
154
|
+
return tasks.map((task) => {
|
|
155
|
+
const result = priorityResults.get(task.id);
|
|
156
|
+
return {
|
|
157
|
+
...task,
|
|
158
|
+
effectivePriority: result?.effectivePriority ?? task.priority,
|
|
159
|
+
priorityInfluenced: result?.isInfluenced ?? false,
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Sort tasks by effective priority (highest priority first)
|
|
165
|
+
*
|
|
166
|
+
* @param tasks - Array of tasks with effective priority
|
|
167
|
+
* @returns Sorted array (mutates in place and returns reference)
|
|
168
|
+
*/
|
|
169
|
+
sortByEffectivePriority(tasks) {
|
|
170
|
+
return tasks.sort((a, b) => {
|
|
171
|
+
// Primary sort: effective priority (lower number = higher priority)
|
|
172
|
+
if (a.effectivePriority !== b.effectivePriority) {
|
|
173
|
+
return a.effectivePriority - b.effectivePriority;
|
|
174
|
+
}
|
|
175
|
+
// Secondary sort: base priority (for ties in effective priority)
|
|
176
|
+
return a.priority - b.priority;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
// --------------------------------------------------------------------------
|
|
180
|
+
// Private Helpers
|
|
181
|
+
// --------------------------------------------------------------------------
|
|
182
|
+
/**
|
|
183
|
+
* Get a task's priority and complexity from the database
|
|
184
|
+
*/
|
|
185
|
+
getTaskPriority(taskId) {
|
|
186
|
+
const sql = `
|
|
187
|
+
SELECT e.id, json_extract(e.data, '$.priority') as priority,
|
|
188
|
+
json_extract(e.data, '$.complexity') as complexity
|
|
189
|
+
FROM elements e
|
|
190
|
+
WHERE e.id = ? AND e.type = 'task'
|
|
191
|
+
`;
|
|
192
|
+
return this.db.queryOne(sql, [taskId]);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Collect priorities of all tasks that depend on a given task (transitively).
|
|
196
|
+
*
|
|
197
|
+
* blockedId = the element waiting, blockerId = the element doing the blocking.
|
|
198
|
+
* To find tasks blocked by current.id, query WHERE blocker_id = current.id,
|
|
199
|
+
* then read blocked_id to get the dependent tasks.
|
|
200
|
+
*/
|
|
201
|
+
collectDependentPriorities(taskId, maxDepth) {
|
|
202
|
+
const result = [];
|
|
203
|
+
const visited = new Set();
|
|
204
|
+
const queue = [{ id: taskId, depth: 0 }];
|
|
205
|
+
while (queue.length > 0) {
|
|
206
|
+
const current = queue.shift();
|
|
207
|
+
if (current.depth >= maxDepth || visited.has(current.id)) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
visited.add(current.id);
|
|
211
|
+
// Find tasks that are blocked by this task (current.id is the blocker)
|
|
212
|
+
const dependents = this.db.query(`SELECT d.blocked_id, d.blocker_id, d.type
|
|
213
|
+
FROM dependencies d
|
|
214
|
+
WHERE d.blocker_id = ? AND d.type = ?`, [current.id, DT.BLOCKS]);
|
|
215
|
+
for (const dep of dependents) {
|
|
216
|
+
const blockedId = dep.blocked_id;
|
|
217
|
+
if (!visited.has(blockedId)) {
|
|
218
|
+
const task = this.getTaskPriority(blockedId);
|
|
219
|
+
if (task) {
|
|
220
|
+
result.push({ id: blockedId, priority: task.priority });
|
|
221
|
+
queue.push({ id: blockedId, depth: current.depth + 1 });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Collect complexities of all tasks that this task depends on (blockers, transitively).
|
|
230
|
+
*
|
|
231
|
+
* blockedId = the element waiting, blockerId = the element doing the blocking.
|
|
232
|
+
* To find tasks that block current.id, query WHERE blocked_id = current.id,
|
|
233
|
+
* then read blocker_id to get the blocking tasks.
|
|
234
|
+
*/
|
|
235
|
+
collectBlockerComplexities(taskId, maxDepth) {
|
|
236
|
+
const result = [];
|
|
237
|
+
const visited = new Set();
|
|
238
|
+
const queue = [{ id: taskId, depth: 0 }];
|
|
239
|
+
while (queue.length > 0) {
|
|
240
|
+
const current = queue.shift();
|
|
241
|
+
if (current.depth >= maxDepth || visited.has(current.id)) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
visited.add(current.id);
|
|
245
|
+
// Find tasks that block this task (current.id is the blocked element)
|
|
246
|
+
const blockers = this.db.query(`SELECT d.blocked_id, d.blocker_id, d.type
|
|
247
|
+
FROM dependencies d
|
|
248
|
+
WHERE d.blocked_id = ? AND d.type = ?`, [current.id, DT.BLOCKS]);
|
|
249
|
+
for (const dep of blockers) {
|
|
250
|
+
const blockerId = dep.blocker_id;
|
|
251
|
+
if (!visited.has(blockerId)) {
|
|
252
|
+
const task = this.getTaskPriority(blockerId);
|
|
253
|
+
if (task) {
|
|
254
|
+
result.push({ id: blockerId, complexity: task.complexity });
|
|
255
|
+
queue.push({ id: blockerId, depth: current.depth + 1 });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// ============================================================================
|
|
264
|
+
// Factory Function
|
|
265
|
+
// ============================================================================
|
|
266
|
+
/**
|
|
267
|
+
* Create a new PriorityService instance
|
|
268
|
+
*/
|
|
269
|
+
export function createPriorityService(db) {
|
|
270
|
+
return new PriorityService(db);
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=priority-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority-service.js","sourceRoot":"","sources":["../../src/services/priority-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides adaptive top-K result filtering and FTS5 query sanitization
|
|
5
|
+
* for the document full-text search system.
|
|
6
|
+
*/
|
|
7
|
+
export interface ScoredResult<T> {
|
|
8
|
+
item: T;
|
|
9
|
+
score: number;
|
|
10
|
+
}
|
|
11
|
+
export interface AdaptiveTopKConfig {
|
|
12
|
+
/** Sensitivity for elbow detection (higher = more aggressive cutoff). Default: 1.5 */
|
|
13
|
+
sensitivity?: number;
|
|
14
|
+
/** Minimum number of results to return regardless of elbow. Default: 1 */
|
|
15
|
+
minResults?: number;
|
|
16
|
+
/** Hard cap on maximum results. Default: 50 */
|
|
17
|
+
maxResults?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Apply adaptive top-K filtering using elbow detection on score distribution.
|
|
21
|
+
*
|
|
22
|
+
* Analyzes gaps between consecutive BM25 scores to find a natural cutoff point
|
|
23
|
+
* where result quality drops significantly. Returns results up to that cutoff.
|
|
24
|
+
*
|
|
25
|
+
* Algorithm:
|
|
26
|
+
* 1. Compute gaps between consecutive scores (already sorted descending by BM25)
|
|
27
|
+
* 2. Calculate mean and stddev of gaps
|
|
28
|
+
* 3. Find first gap exceeding mean + (sensitivity * stddev)
|
|
29
|
+
* 4. Return results up to that cutoff
|
|
30
|
+
*
|
|
31
|
+
* @param results - Scored results sorted by score descending
|
|
32
|
+
* @param config - Configuration for elbow detection
|
|
33
|
+
* @returns Filtered results with natural cutoff applied
|
|
34
|
+
*/
|
|
35
|
+
export declare function applyAdaptiveTopK<T>(results: ScoredResult<T>[], config?: AdaptiveTopKConfig): ScoredResult<T>[];
|
|
36
|
+
/**
|
|
37
|
+
* Escape user input for safe use in FTS5 MATCH queries.
|
|
38
|
+
*
|
|
39
|
+
* FTS5 has special syntax characters that can cause query parse errors.
|
|
40
|
+
* This function wraps each token in quotes to prevent interpretation
|
|
41
|
+
* as FTS5 operators.
|
|
42
|
+
*
|
|
43
|
+
* @param input - Raw user search query
|
|
44
|
+
* @returns Sanitized query safe for FTS5 MATCH
|
|
45
|
+
*/
|
|
46
|
+
export declare function escapeFts5Query(input: string): string;
|
|
47
|
+
//# sourceMappingURL=search-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-utils.d.ts","sourceRoot":"","sources":["../../src/services/search-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,MAAM,GAAE,kBAAuB,GAC9B,YAAY,CAAC,CAAC,CAAC,EAAE,CAyCnB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYrD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides adaptive top-K result filtering and FTS5 query sanitization
|
|
5
|
+
* for the document full-text search system.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Adaptive Top-K
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Apply adaptive top-K filtering using elbow detection on score distribution.
|
|
12
|
+
*
|
|
13
|
+
* Analyzes gaps between consecutive BM25 scores to find a natural cutoff point
|
|
14
|
+
* where result quality drops significantly. Returns results up to that cutoff.
|
|
15
|
+
*
|
|
16
|
+
* Algorithm:
|
|
17
|
+
* 1. Compute gaps between consecutive scores (already sorted descending by BM25)
|
|
18
|
+
* 2. Calculate mean and stddev of gaps
|
|
19
|
+
* 3. Find first gap exceeding mean + (sensitivity * stddev)
|
|
20
|
+
* 4. Return results up to that cutoff
|
|
21
|
+
*
|
|
22
|
+
* @param results - Scored results sorted by score descending
|
|
23
|
+
* @param config - Configuration for elbow detection
|
|
24
|
+
* @returns Filtered results with natural cutoff applied
|
|
25
|
+
*/
|
|
26
|
+
export function applyAdaptiveTopK(results, config = {}) {
|
|
27
|
+
const { sensitivity = 1.5, minResults = 1, maxResults = 50, } = config;
|
|
28
|
+
if (results.length === 0)
|
|
29
|
+
return [];
|
|
30
|
+
// Apply hard cap first
|
|
31
|
+
const capped = results.slice(0, maxResults);
|
|
32
|
+
// Need at least 3 results to detect an elbow
|
|
33
|
+
if (capped.length <= 2)
|
|
34
|
+
return capped;
|
|
35
|
+
// Compute gaps between consecutive scores
|
|
36
|
+
const gaps = [];
|
|
37
|
+
for (let i = 0; i < capped.length - 1; i++) {
|
|
38
|
+
gaps.push(capped[i].score - capped[i + 1].score);
|
|
39
|
+
}
|
|
40
|
+
// Calculate mean and standard deviation of gaps
|
|
41
|
+
const mean = gaps.reduce((sum, g) => sum + g, 0) / gaps.length;
|
|
42
|
+
const variance = gaps.reduce((sum, g) => sum + (g - mean) ** 2, 0) / gaps.length;
|
|
43
|
+
const stddev = Math.sqrt(variance);
|
|
44
|
+
// Find the elbow: first gap exceeding mean + sensitivity * stddev
|
|
45
|
+
const threshold = mean + sensitivity * stddev;
|
|
46
|
+
let cutoffIndex = capped.length; // Default: keep all
|
|
47
|
+
for (let i = 0; i < gaps.length; i++) {
|
|
48
|
+
if (gaps[i] > threshold) {
|
|
49
|
+
cutoffIndex = i + 1; // Include the result before the gap
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Ensure minimum results
|
|
54
|
+
cutoffIndex = Math.max(cutoffIndex, Math.min(minResults, capped.length));
|
|
55
|
+
return capped.slice(0, cutoffIndex);
|
|
56
|
+
}
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// FTS5 Query Sanitization
|
|
59
|
+
// ============================================================================
|
|
60
|
+
/**
|
|
61
|
+
* Escape user input for safe use in FTS5 MATCH queries.
|
|
62
|
+
*
|
|
63
|
+
* FTS5 has special syntax characters that can cause query parse errors.
|
|
64
|
+
* This function wraps each token in quotes to prevent interpretation
|
|
65
|
+
* as FTS5 operators.
|
|
66
|
+
*
|
|
67
|
+
* @param input - Raw user search query
|
|
68
|
+
* @returns Sanitized query safe for FTS5 MATCH
|
|
69
|
+
*/
|
|
70
|
+
export function escapeFts5Query(input) {
|
|
71
|
+
const trimmed = input.trim();
|
|
72
|
+
if (trimmed.length === 0)
|
|
73
|
+
return '';
|
|
74
|
+
// Split into tokens and wrap each in double quotes to escape operators
|
|
75
|
+
// Remove any existing quotes from user input to prevent injection
|
|
76
|
+
const sanitized = trimmed.replace(/"/g, '');
|
|
77
|
+
if (sanitized.length === 0)
|
|
78
|
+
return '';
|
|
79
|
+
// Wrap each word in quotes to prevent FTS5 operator interpretation
|
|
80
|
+
const tokens = sanitized.split(/\s+/).filter(Boolean);
|
|
81
|
+
return tokens.map((token) => `"${token}"`).join(' ');
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=search-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-utils.js","sourceRoot":"","sources":["../../src/services/search-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Hashing - SHA256 hashing for conflict detection
|
|
3
|
+
*
|
|
4
|
+
* Computes content hashes for elements to detect actual content changes
|
|
5
|
+
* during merge operations. Excludes identity and attribution fields.
|
|
6
|
+
*/
|
|
7
|
+
import type { Element } from '@stoneforge/core';
|
|
8
|
+
import type { ContentHashResult } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Compute content hash for an element
|
|
11
|
+
*
|
|
12
|
+
* Hash computation:
|
|
13
|
+
* 1. Collect content fields (exclude identity/attribution)
|
|
14
|
+
* 2. Sort object keys for determinism
|
|
15
|
+
* 3. JSON stringify
|
|
16
|
+
* 4. Prepend type for type-specific hashing
|
|
17
|
+
* 5. SHA256 hash
|
|
18
|
+
*
|
|
19
|
+
* @param element - Element to hash
|
|
20
|
+
* @returns Hash result with hex-encoded SHA256 hash
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeContentHash(element: Element): Promise<ContentHashResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Compute content hash synchronously using Node.js crypto
|
|
25
|
+
*
|
|
26
|
+
* Works in both Bun and Node.js runtimes.
|
|
27
|
+
*
|
|
28
|
+
* @param element - Element to hash
|
|
29
|
+
* @returns Hash result with hex-encoded SHA256 hash
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeContentHashSync(element: Element): ContentHashResult;
|
|
32
|
+
/**
|
|
33
|
+
* Check if two elements have the same content hash
|
|
34
|
+
*
|
|
35
|
+
* @param a - First element
|
|
36
|
+
* @param b - Second element
|
|
37
|
+
* @returns True if content hashes match
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasSameContentHash(a: Element, b: Element): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Compare pre-computed hash with element
|
|
42
|
+
*
|
|
43
|
+
* @param element - Element to check
|
|
44
|
+
* @param expectedHash - Expected hash value
|
|
45
|
+
* @returns True if hash matches
|
|
46
|
+
*/
|
|
47
|
+
export declare function matchesContentHash(element: Element, expectedHash: string): boolean;
|
|
48
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/sync/hash.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOpD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6BrF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,CA6B1E;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAIlE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGlF"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Hashing - SHA256 hashing for conflict detection
|
|
3
|
+
*
|
|
4
|
+
* Computes content hashes for elements to detect actual content changes
|
|
5
|
+
* during merge operations. Excludes identity and attribution fields.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import { HASH_EXCLUDED_FIELDS } from './types.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Content Hash Computation
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Compute content hash for an element
|
|
14
|
+
*
|
|
15
|
+
* Hash computation:
|
|
16
|
+
* 1. Collect content fields (exclude identity/attribution)
|
|
17
|
+
* 2. Sort object keys for determinism
|
|
18
|
+
* 3. JSON stringify
|
|
19
|
+
* 4. Prepend type for type-specific hashing
|
|
20
|
+
* 5. SHA256 hash
|
|
21
|
+
*
|
|
22
|
+
* @param element - Element to hash
|
|
23
|
+
* @returns Hash result with hex-encoded SHA256 hash
|
|
24
|
+
*/
|
|
25
|
+
export async function computeContentHash(element) {
|
|
26
|
+
// Collect content fields
|
|
27
|
+
const contentFields = {};
|
|
28
|
+
const includedFields = [];
|
|
29
|
+
for (const [key, value] of Object.entries(element)) {
|
|
30
|
+
if (!HASH_EXCLUDED_FIELDS.includes(key)) {
|
|
31
|
+
contentFields[key] = value;
|
|
32
|
+
includedFields.push(key);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Sort keys for determinism
|
|
36
|
+
const sortedFields = {};
|
|
37
|
+
const sortedKeys = Object.keys(contentFields).sort();
|
|
38
|
+
for (const key of sortedKeys) {
|
|
39
|
+
sortedFields[key] = contentFields[key];
|
|
40
|
+
}
|
|
41
|
+
// Create hash input: type prefix + JSON content
|
|
42
|
+
const hashInput = `${element.type}:${JSON.stringify(sortedFields, sortKeyReplacer)}`;
|
|
43
|
+
// Compute SHA256 hash
|
|
44
|
+
const hash = await sha256Hex(hashInput);
|
|
45
|
+
return {
|
|
46
|
+
hash,
|
|
47
|
+
fields: includedFields.sort(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compute content hash synchronously using Node.js crypto
|
|
52
|
+
*
|
|
53
|
+
* Works in both Bun and Node.js runtimes.
|
|
54
|
+
*
|
|
55
|
+
* @param element - Element to hash
|
|
56
|
+
* @returns Hash result with hex-encoded SHA256 hash
|
|
57
|
+
*/
|
|
58
|
+
export function computeContentHashSync(element) {
|
|
59
|
+
// Collect content fields
|
|
60
|
+
const contentFields = {};
|
|
61
|
+
const includedFields = [];
|
|
62
|
+
for (const [key, value] of Object.entries(element)) {
|
|
63
|
+
if (!HASH_EXCLUDED_FIELDS.includes(key)) {
|
|
64
|
+
contentFields[key] = value;
|
|
65
|
+
includedFields.push(key);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Sort keys for determinism
|
|
69
|
+
const sortedFields = {};
|
|
70
|
+
const sortedKeys = Object.keys(contentFields).sort();
|
|
71
|
+
for (const key of sortedKeys) {
|
|
72
|
+
sortedFields[key] = contentFields[key];
|
|
73
|
+
}
|
|
74
|
+
// Create hash input: type prefix + JSON content
|
|
75
|
+
const hashInput = `${element.type}:${JSON.stringify(sortedFields, sortKeyReplacer)}`;
|
|
76
|
+
// Compute SHA256 hash using Node.js crypto (works in both Bun and Node.js)
|
|
77
|
+
const hash = createHash('sha256').update(hashInput).digest('hex');
|
|
78
|
+
return {
|
|
79
|
+
hash,
|
|
80
|
+
fields: includedFields.sort(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Hash Comparison
|
|
85
|
+
// ============================================================================
|
|
86
|
+
/**
|
|
87
|
+
* Check if two elements have the same content hash
|
|
88
|
+
*
|
|
89
|
+
* @param a - First element
|
|
90
|
+
* @param b - Second element
|
|
91
|
+
* @returns True if content hashes match
|
|
92
|
+
*/
|
|
93
|
+
export function hasSameContentHash(a, b) {
|
|
94
|
+
const hashA = computeContentHashSync(a);
|
|
95
|
+
const hashB = computeContentHashSync(b);
|
|
96
|
+
return hashA.hash === hashB.hash;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Compare pre-computed hash with element
|
|
100
|
+
*
|
|
101
|
+
* @param element - Element to check
|
|
102
|
+
* @param expectedHash - Expected hash value
|
|
103
|
+
* @returns True if hash matches
|
|
104
|
+
*/
|
|
105
|
+
export function matchesContentHash(element, expectedHash) {
|
|
106
|
+
const result = computeContentHashSync(element);
|
|
107
|
+
return result.hash === expectedHash;
|
|
108
|
+
}
|
|
109
|
+
// ============================================================================
|
|
110
|
+
// Helpers
|
|
111
|
+
// ============================================================================
|
|
112
|
+
/**
|
|
113
|
+
* JSON replacer that sorts object keys for deterministic stringification
|
|
114
|
+
*/
|
|
115
|
+
function sortKeyReplacer(_key, value) {
|
|
116
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
117
|
+
const sorted = {};
|
|
118
|
+
for (const k of Object.keys(value).sort()) {
|
|
119
|
+
sorted[k] = value[k];
|
|
120
|
+
}
|
|
121
|
+
return sorted;
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Compute SHA256 hash of a string, returning hex-encoded result
|
|
127
|
+
* Uses Web Crypto API for async operation
|
|
128
|
+
*/
|
|
129
|
+
async function sha256Hex(input) {
|
|
130
|
+
const encoder = new TextEncoder();
|
|
131
|
+
const data = encoder.encode(input);
|
|
132
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
133
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
134
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/sync/hash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync System - JSONL-based synchronization
|
|
3
|
+
*
|
|
4
|
+
* Provides bidirectional sync between SQLite and git-friendly JSONL format.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export { serializeElement, serializeDependency, parseElement, parseDependency, tryParseElement, tryParseDependency, serializeElements, serializeDependencies, parseElements, parseDependencies, sortElementsForExport, sortDependenciesForExport, isSerializedElement, isSerializedDependency, type ParseError, } from './serialization.js';
|
|
8
|
+
export { computeContentHash, computeContentHashSync, hasSameContentHash, matchesContentHash, } from './hash.js';
|
|
9
|
+
export { mergeElements, mergeTags, mergeDependencies, getTombstoneStatus, type ElementMergeResult, type DependencyMergeResult, } from './merge.js';
|
|
10
|
+
export { SyncService, createSyncService } from './service.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync System - JSONL-based synchronization
|
|
3
|
+
*
|
|
4
|
+
* Provides bidirectional sync between SQLite and git-friendly JSONL format.
|
|
5
|
+
*/
|
|
6
|
+
// Types
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
// Serialization
|
|
9
|
+
export { serializeElement, serializeDependency, parseElement, parseDependency, tryParseElement, tryParseDependency, serializeElements, serializeDependencies, parseElements, parseDependencies, sortElementsForExport, sortDependenciesForExport, isSerializedElement, isSerializedDependency, } from './serialization.js';
|
|
10
|
+
// Content Hashing
|
|
11
|
+
export { computeContentHash, computeContentHashSync, hasSameContentHash, matchesContentHash, } from './hash.js';
|
|
12
|
+
// Merge Strategy
|
|
13
|
+
export { mergeElements, mergeTags, mergeDependencies, getTombstoneStatus, } from './merge.js';
|
|
14
|
+
// Sync Service
|
|
15
|
+
export { SyncService, createSyncService } from './service.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,GAEvB,MAAM,oBAAoB,CAAC;AAE5B,kBAAkB;AAClB,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAEnB,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,kBAAkB,GAGnB,MAAM,YAAY,CAAC;AAEpB,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|