claude-brain 0.14.2 → 0.14.4
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 +191 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +11 -11
- package/bunfig.toml +8 -8
- package/package.json +80 -80
- package/packs/backend/node.json +173 -173
- package/packs/core/javascript.json +176 -176
- package/packs/core/typescript.json +222 -222
- package/packs/frontend/react.json +254 -254
- package/packs/meta/testing.json +172 -172
- package/src/automation/auto-context.ts +240 -240
- package/src/automation/decision-detector.ts +452 -452
- package/src/automation/index.ts +11 -11
- package/src/automation/phase12-manager.ts +456 -456
- package/src/automation/proactive-recall.ts +373 -373
- package/src/automation/project-detector.ts +310 -310
- package/src/automation/repo-scanner.ts +205 -205
- package/src/cli/auto-setup.ts +82 -82
- package/src/cli/bin.ts +202 -202
- package/src/cli/commands/chroma.ts +573 -573
- package/src/cli/commands/git-hook.ts +189 -189
- package/src/cli/commands/hooks.ts +213 -213
- package/src/cli/commands/init.ts +122 -122
- package/src/cli/commands/install-mcp.ts +92 -92
- package/src/cli/commands/pack.ts +197 -197
- package/src/cli/commands/serve.ts +167 -167
- package/src/cli/commands/start.ts +42 -42
- package/src/cli/commands/uninstall-mcp.ts +41 -41
- package/src/cli/commands/update.ts +121 -121
- package/src/cli/diagnose.ts +4 -4
- package/src/cli/health-check.ts +4 -4
- package/src/cli/migrate-chroma.ts +106 -106
- package/src/cli/setup.ts +4 -4
- package/src/cli/ui/animations.ts +80 -80
- package/src/cli/ui/components.ts +82 -82
- package/src/cli/ui/index.ts +4 -4
- package/src/cli/ui/logo.ts +36 -36
- package/src/cli/ui/theme.ts +55 -55
- package/src/config/defaults.ts +50 -50
- package/src/config/home.ts +55 -55
- package/src/config/index.ts +7 -7
- package/src/config/loader.ts +166 -166
- package/src/config/migration.ts +76 -76
- package/src/config/schema.ts +360 -360
- package/src/config/validator.ts +184 -184
- package/src/config/watcher.ts +86 -86
- package/src/context/assembler.ts +398 -398
- package/src/context/cache-manager.ts +101 -101
- package/src/context/formatter.ts +84 -84
- package/src/context/hierarchy.ts +85 -85
- package/src/context/index.ts +83 -83
- package/src/context/progress-tracker.ts +174 -174
- package/src/context/standards-manager.ts +287 -287
- package/src/context/types.ts +252 -252
- package/src/context/validator.ts +58 -58
- package/src/diagnostics/index.ts +123 -123
- package/src/health/index.ts +229 -229
- package/src/hooks/brain-hook.ts +112 -112
- package/src/hooks/capture.ts +168 -168
- package/src/hooks/deduplicator.ts +72 -72
- package/src/hooks/git-capture.ts +109 -109
- package/src/hooks/git-hook-installer.ts +207 -207
- package/src/hooks/index.ts +20 -20
- package/src/hooks/installer.ts +191 -194
- package/src/hooks/passive-classifier.ts +366 -366
- package/src/hooks/queue.ts +129 -129
- package/src/hooks/session-tracker.ts +275 -275
- package/src/hooks/types.ts +47 -47
- package/src/index.ts +7 -7
- package/src/intelligence/cross-project/affinity.ts +162 -162
- package/src/intelligence/cross-project/generalizer.ts +283 -283
- package/src/intelligence/cross-project/index.ts +13 -13
- package/src/intelligence/cross-project/transfer.ts +201 -201
- package/src/intelligence/index.ts +24 -24
- package/src/intelligence/optimization/index.ts +10 -10
- package/src/intelligence/optimization/precompute.ts +202 -202
- package/src/intelligence/optimization/semantic-cache.ts +207 -207
- package/src/intelligence/prediction/context-anticipator.ts +198 -198
- package/src/intelligence/prediction/decision-predictor.ts +184 -184
- package/src/intelligence/prediction/index.ts +13 -13
- package/src/intelligence/prediction/recommender.ts +268 -268
- package/src/intelligence/reasoning/chain-retrieval.ts +247 -247
- package/src/intelligence/reasoning/counterfactual.ts +248 -248
- package/src/intelligence/reasoning/index.ts +13 -13
- package/src/intelligence/reasoning/synthesizer.ts +169 -169
- package/src/intelligence/temporal/evolution.ts +197 -197
- package/src/intelligence/temporal/index.ts +16 -16
- package/src/intelligence/temporal/query-processor.ts +190 -190
- package/src/intelligence/temporal/timeline.ts +259 -259
- package/src/intelligence/temporal/trends.ts +263 -263
- package/src/knowledge/entity-extractor.ts +416 -416
- package/src/knowledge/graph/builder.ts +185 -185
- package/src/knowledge/graph/linker.ts +201 -201
- package/src/knowledge/graph/memory-graph.ts +359 -359
- package/src/knowledge/graph/schema.ts +99 -99
- package/src/knowledge/graph/search.ts +168 -168
- package/src/knowledge/relationship-extractor.ts +108 -108
- package/src/memory/chroma/client.ts +174 -174
- package/src/memory/chroma/collection-manager.ts +94 -94
- package/src/memory/chroma/config.ts +57 -57
- package/src/memory/chroma/embeddings.ts +153 -153
- package/src/memory/chroma/index.ts +82 -82
- package/src/memory/chroma/migration.ts +270 -270
- package/src/memory/chroma/schemas.ts +69 -69
- package/src/memory/chroma/search.ts +315 -315
- package/src/memory/chroma/store.ts +741 -741
- package/src/memory/consolidation/archiver.ts +164 -164
- package/src/memory/consolidation/merger.ts +186 -186
- package/src/memory/consolidation/scorer.ts +138 -138
- package/src/memory/context-builder.ts +236 -236
- package/src/memory/database.ts +169 -169
- package/src/memory/embedding-utils.ts +156 -156
- package/src/memory/embeddings.ts +226 -226
- package/src/memory/episodic/detector.ts +108 -108
- package/src/memory/episodic/manager.ts +351 -351
- package/src/memory/episodic/summarizer.ts +179 -179
- package/src/memory/episodic/types.ts +52 -52
- package/src/memory/index.ts +582 -582
- package/src/memory/knowledge-extractor.ts +455 -455
- package/src/memory/learning.ts +378 -378
- package/src/memory/patterns.ts +396 -396
- package/src/memory/schema.ts +88 -88
- package/src/memory/search.ts +309 -309
- package/src/memory/store.ts +787 -787
- package/src/memory/types.ts +121 -121
- package/src/orchestrator/coordinator.ts +272 -272
- package/src/orchestrator/decision-logger.ts +228 -228
- package/src/orchestrator/event-emitter.ts +198 -198
- package/src/orchestrator/event-queue.ts +184 -184
- package/src/orchestrator/handlers/base-handler.ts +70 -70
- package/src/orchestrator/handlers/context-handler.ts +73 -73
- package/src/orchestrator/handlers/decision-handler.ts +204 -204
- package/src/orchestrator/handlers/index.ts +10 -10
- package/src/orchestrator/handlers/status-handler.ts +131 -131
- package/src/orchestrator/handlers/task-handler.ts +171 -171
- package/src/orchestrator/index.ts +275 -275
- package/src/orchestrator/task-parser.ts +284 -284
- package/src/orchestrator/types.ts +98 -98
- package/src/packs/index.ts +9 -9
- package/src/packs/loader.ts +134 -134
- package/src/packs/manager.ts +204 -204
- package/src/packs/ranker.ts +78 -78
- package/src/packs/types.ts +81 -81
- package/src/phase12/index.ts +5 -5
- package/src/retrieval/bm25/index.ts +300 -300
- package/src/retrieval/bm25/tokenizer.ts +184 -184
- package/src/retrieval/feedback/adaptive.ts +223 -223
- package/src/retrieval/feedback/index.ts +16 -16
- package/src/retrieval/feedback/metrics.ts +223 -223
- package/src/retrieval/feedback/store.ts +283 -283
- package/src/retrieval/fusion/index.ts +194 -194
- package/src/retrieval/fusion/rrf.ts +163 -163
- package/src/retrieval/index.ts +12 -12
- package/src/retrieval/pipeline.ts +375 -375
- package/src/retrieval/query/expander.ts +198 -198
- package/src/retrieval/query/index.ts +27 -27
- package/src/retrieval/query/intent-classifier.ts +236 -236
- package/src/retrieval/query/temporal-parser.ts +295 -295
- package/src/retrieval/reranker/index.ts +188 -188
- package/src/retrieval/reranker/model.ts +95 -95
- package/src/retrieval/service.ts +125 -125
- package/src/retrieval/types.ts +162 -162
- package/src/routing/entity-extractor.ts +428 -428
- package/src/routing/intent-classifier.ts +436 -436
- package/src/routing/response-filter.ts +258 -254
- package/src/routing/router.ts +1322 -1314
- package/src/routing/search-engine.ts +475 -475
- package/src/routing/types.ts +94 -84
- package/src/scripts/health-check.ts +118 -118
- package/src/scripts/setup.ts +122 -122
- package/src/server/handlers/call-tool.ts +156 -156
- package/src/server/handlers/index.ts +9 -9
- package/src/server/handlers/list-tools.ts +35 -35
- package/src/server/handlers/tools/analyze-decision-evolution.ts +151 -151
- package/src/server/handlers/tools/auto-remember.ts +200 -200
- package/src/server/handlers/tools/brain.ts +85 -85
- package/src/server/handlers/tools/create-project.ts +135 -135
- package/src/server/handlers/tools/detect-trends.ts +144 -144
- package/src/server/handlers/tools/find-cross-project-patterns.ts +168 -168
- package/src/server/handlers/tools/get-activity-log.ts +194 -194
- package/src/server/handlers/tools/get-code-standards.ts +124 -124
- package/src/server/handlers/tools/get-corrections.ts +154 -154
- package/src/server/handlers/tools/get-decision-timeline.ts +172 -172
- package/src/server/handlers/tools/get-episode.ts +103 -103
- package/src/server/handlers/tools/get-patterns.ts +158 -158
- package/src/server/handlers/tools/get-phase12-status.ts +63 -63
- package/src/server/handlers/tools/get-project-context.ts +75 -75
- package/src/server/handlers/tools/get-recommendations.ts +145 -145
- package/src/server/handlers/tools/index.ts +31 -31
- package/src/server/handlers/tools/init-project.ts +757 -757
- package/src/server/handlers/tools/list-episodes.ts +90 -90
- package/src/server/handlers/tools/list-projects.ts +125 -125
- package/src/server/handlers/tools/rate-memory.ts +101 -101
- package/src/server/handlers/tools/recall-similar.ts +87 -87
- package/src/server/handlers/tools/recognize-pattern.ts +126 -126
- package/src/server/handlers/tools/record-correction.ts +125 -125
- package/src/server/handlers/tools/remember-decision.ts +153 -153
- package/src/server/handlers/tools/schemas.ts +253 -253
- package/src/server/handlers/tools/search-knowledge-graph.ts +102 -102
- package/src/server/handlers/tools/smart-context.ts +146 -146
- package/src/server/handlers/tools/update-progress.ts +131 -131
- package/src/server/handlers/tools/what-if-analysis.ts +135 -135
- package/src/server/http-api.ts +693 -693
- package/src/server/index.ts +40 -40
- package/src/server/mcp-server.ts +283 -283
- package/src/server/providers/index.ts +7 -7
- package/src/server/providers/prompts.ts +327 -327
- package/src/server/providers/resources.ts +622 -622
- package/src/server/services.ts +468 -468
- package/src/server/types.ts +39 -39
- package/src/server/utils/error-handler.ts +155 -155
- package/src/server/utils/index.ts +13 -13
- package/src/server/utils/memory-indicator.ts +83 -83
- package/src/server/utils/request-context.ts +122 -122
- package/src/server/utils/response-formatter.ts +129 -124
- package/src/server/utils/validators.ts +210 -210
- package/src/setup/index.ts +48 -48
- package/src/setup/wizard.ts +461 -461
- package/src/tools/index.ts +24 -24
- package/src/tools/registry.ts +115 -115
- package/src/tools/schemas.test.ts +30 -30
- package/src/tools/schemas.ts +617 -617
- package/src/tools/types.ts +412 -412
- package/src/utils/circuit-breaker.ts +130 -130
- package/src/utils/cleanup.ts +34 -34
- package/src/utils/error-handler.ts +132 -132
- package/src/utils/error-messages.ts +60 -60
- package/src/utils/fallback.ts +45 -45
- package/src/utils/index.ts +54 -54
- package/src/utils/logger-utils.ts +80 -80
- package/src/utils/logger.ts +88 -88
- package/src/utils/phase12-helper.ts +56 -56
- package/src/utils/retry.ts +94 -94
- package/src/utils/timing.ts +47 -47
- package/src/utils/transaction.ts +63 -63
- package/src/vault/frontmatter.ts +264 -264
- package/src/vault/index.ts +318 -318
- package/src/vault/paths.ts +106 -106
- package/src/vault/query.ts +422 -422
- package/src/vault/reader.ts +264 -264
- package/src/vault/templates.ts +186 -186
- package/src/vault/types.ts +73 -73
- package/src/vault/watcher.ts +277 -277
- package/src/vault/writer.ts +413 -413
- package/tsconfig.json +30 -30
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision Evolution Tracker
|
|
3
|
-
* Tracks how decisions change over time per topic
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Logger } from 'pino'
|
|
7
|
-
import type { CollectionManager } from '@/memory/chroma/collection-manager'
|
|
8
|
-
import type { EmbeddingProvider } from '@/memory/chroma/embeddings'
|
|
9
|
-
|
|
10
|
-
export interface EvolutionEntry {
|
|
11
|
-
id: string
|
|
12
|
-
date: string
|
|
13
|
-
decision: string
|
|
14
|
-
reasoning: string
|
|
15
|
-
context: string
|
|
16
|
-
tags: string[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface EvolutionAnalysis {
|
|
20
|
-
topic: string
|
|
21
|
-
project?: string
|
|
22
|
-
totalDecisions: number
|
|
23
|
-
timeline: EvolutionEntry[]
|
|
24
|
-
changes: EvolutionChange[]
|
|
25
|
-
currentState: string
|
|
26
|
-
stability: 'stable' | 'evolving' | 'volatile'
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface EvolutionChange {
|
|
30
|
-
from: EvolutionEntry
|
|
31
|
-
to: EvolutionEntry
|
|
32
|
-
daysBetween: number
|
|
33
|
-
summary: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class DecisionEvolutionTracker {
|
|
37
|
-
private logger: Logger
|
|
38
|
-
private collections: CollectionManager
|
|
39
|
-
private embeddings?: EmbeddingProvider
|
|
40
|
-
|
|
41
|
-
constructor(logger: Logger, collections: CollectionManager, embeddings?: EmbeddingProvider) {
|
|
42
|
-
this.logger = logger.child({ component: 'decision-evolution' })
|
|
43
|
-
this.collections = collections
|
|
44
|
-
this.embeddings = embeddings
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Analyze how decisions on a topic have evolved over time
|
|
49
|
-
*/
|
|
50
|
-
async analyzeEvolution(topic: string, options: {
|
|
51
|
-
project?: string
|
|
52
|
-
limit?: number
|
|
53
|
-
} = {}): Promise<EvolutionAnalysis> {
|
|
54
|
-
const { project, limit = 20 } = options
|
|
55
|
-
|
|
56
|
-
// Find all decisions related to this topic
|
|
57
|
-
const decisions = await this.findRelatedDecisions(topic, project, limit)
|
|
58
|
-
|
|
59
|
-
// Sort chronologically
|
|
60
|
-
decisions.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
|
|
61
|
-
|
|
62
|
-
// Detect changes between consecutive decisions
|
|
63
|
-
const changes = this.detectChanges(decisions)
|
|
64
|
-
|
|
65
|
-
// Determine stability
|
|
66
|
-
const stability = this.assessStability(decisions, changes)
|
|
67
|
-
|
|
68
|
-
// Current state is the most recent decision
|
|
69
|
-
const currentState = decisions.length > 0
|
|
70
|
-
? decisions[decisions.length - 1].decision
|
|
71
|
-
: 'No decisions found for this topic'
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
topic,
|
|
75
|
-
project,
|
|
76
|
-
totalDecisions: decisions.length,
|
|
77
|
-
timeline: decisions,
|
|
78
|
-
changes,
|
|
79
|
-
currentState,
|
|
80
|
-
stability
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private async findRelatedDecisions(
|
|
85
|
-
topic: string,
|
|
86
|
-
project?: string,
|
|
87
|
-
limit: number = 20
|
|
88
|
-
): Promise<EvolutionEntry[]> {
|
|
89
|
-
try {
|
|
90
|
-
const collection = await this.collections.getDecisions()
|
|
91
|
-
|
|
92
|
-
const where: any = project ? { project: { $eq: project } } : undefined
|
|
93
|
-
|
|
94
|
-
let results: any
|
|
95
|
-
|
|
96
|
-
if (this.embeddings) {
|
|
97
|
-
const embedding = await this.embeddings.generate(topic)
|
|
98
|
-
results = await collection.query({
|
|
99
|
-
queryEmbeddings: [embedding],
|
|
100
|
-
nResults: limit,
|
|
101
|
-
where,
|
|
102
|
-
include: ['documents', 'metadatas', 'distances']
|
|
103
|
-
})
|
|
104
|
-
} else {
|
|
105
|
-
results = await collection.query({
|
|
106
|
-
queryTexts: [topic],
|
|
107
|
-
nResults: limit,
|
|
108
|
-
where,
|
|
109
|
-
include: ['documents', 'metadatas', 'distances']
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!results.ids || !results.ids[0]) return []
|
|
114
|
-
|
|
115
|
-
const entries: EvolutionEntry[] = []
|
|
116
|
-
const ids = results.ids[0]
|
|
117
|
-
const documents = results.documents?.[0] || []
|
|
118
|
-
const metadatas = results.metadatas?.[0] || []
|
|
119
|
-
const distances = results.distances?.[0] || []
|
|
120
|
-
|
|
121
|
-
for (let i = 0; i < ids.length; i++) {
|
|
122
|
-
const similarity = 1 - (distances[i] || 0)
|
|
123
|
-
// Only include reasonably relevant results
|
|
124
|
-
if (similarity < 0.3) continue
|
|
125
|
-
|
|
126
|
-
const meta = metadatas[i] || {}
|
|
127
|
-
entries.push({
|
|
128
|
-
id: ids[i],
|
|
129
|
-
date: meta.created_at || new Date().toISOString(),
|
|
130
|
-
decision: documents[i] || '',
|
|
131
|
-
reasoning: meta.reasoning || '',
|
|
132
|
-
context: meta.context || '',
|
|
133
|
-
tags: (meta.tags || '').split(',').filter((t: string) => t)
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return entries
|
|
138
|
-
} catch (error) {
|
|
139
|
-
this.logger.warn({ error, topic }, 'Failed to find related decisions')
|
|
140
|
-
return []
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private detectChanges(entries: EvolutionEntry[]): EvolutionChange[] {
|
|
145
|
-
const changes: EvolutionChange[] = []
|
|
146
|
-
|
|
147
|
-
for (let i = 1; i < entries.length; i++) {
|
|
148
|
-
const prev = entries[i - 1]
|
|
149
|
-
const curr = entries[i]
|
|
150
|
-
|
|
151
|
-
const daysBetween = Math.round(
|
|
152
|
-
(new Date(curr.date).getTime() - new Date(prev.date).getTime()) / (1000 * 60 * 60 * 24)
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
// Simple heuristic: if decisions differ substantially, it's a change
|
|
156
|
-
const prevWords = new Set(prev.decision.toLowerCase().split(/\s+/))
|
|
157
|
-
const currWords = new Set(curr.decision.toLowerCase().split(/\s+/))
|
|
158
|
-
|
|
159
|
-
const intersection = new Set([...prevWords].filter(w => currWords.has(w)))
|
|
160
|
-
const union = new Set([...prevWords, ...currWords])
|
|
161
|
-
const jaccard = union.size > 0 ? intersection.size / union.size : 1
|
|
162
|
-
|
|
163
|
-
// If less than 60% overlap, consider it a meaningful change
|
|
164
|
-
if (jaccard < 0.6) {
|
|
165
|
-
const summary = this.summarizeChange(prev, curr)
|
|
166
|
-
changes.push({
|
|
167
|
-
from: prev,
|
|
168
|
-
to: curr,
|
|
169
|
-
daysBetween,
|
|
170
|
-
summary
|
|
171
|
-
})
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return changes
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
private summarizeChange(from: EvolutionEntry, to: EvolutionEntry): string {
|
|
179
|
-
const fromDate = new Date(from.date).toLocaleDateString()
|
|
180
|
-
const toDate = new Date(to.date).toLocaleDateString()
|
|
181
|
-
|
|
182
|
-
return `Changed from "${from.decision.slice(0, 80)}..." to "${to.decision.slice(0, 80)}..." (${fromDate} -> ${toDate})`
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private assessStability(
|
|
186
|
-
entries: EvolutionEntry[],
|
|
187
|
-
changes: EvolutionChange[]
|
|
188
|
-
): 'stable' | 'evolving' | 'volatile' {
|
|
189
|
-
if (entries.length <= 1) return 'stable'
|
|
190
|
-
|
|
191
|
-
const changeRatio = changes.length / (entries.length - 1)
|
|
192
|
-
|
|
193
|
-
if (changeRatio <= 0.2) return 'stable'
|
|
194
|
-
if (changeRatio <= 0.5) return 'evolving'
|
|
195
|
-
return 'volatile'
|
|
196
|
-
}
|
|
197
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Decision Evolution Tracker
|
|
3
|
+
* Tracks how decisions change over time per topic
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Logger } from 'pino'
|
|
7
|
+
import type { CollectionManager } from '@/memory/chroma/collection-manager'
|
|
8
|
+
import type { EmbeddingProvider } from '@/memory/chroma/embeddings'
|
|
9
|
+
|
|
10
|
+
export interface EvolutionEntry {
|
|
11
|
+
id: string
|
|
12
|
+
date: string
|
|
13
|
+
decision: string
|
|
14
|
+
reasoning: string
|
|
15
|
+
context: string
|
|
16
|
+
tags: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface EvolutionAnalysis {
|
|
20
|
+
topic: string
|
|
21
|
+
project?: string
|
|
22
|
+
totalDecisions: number
|
|
23
|
+
timeline: EvolutionEntry[]
|
|
24
|
+
changes: EvolutionChange[]
|
|
25
|
+
currentState: string
|
|
26
|
+
stability: 'stable' | 'evolving' | 'volatile'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface EvolutionChange {
|
|
30
|
+
from: EvolutionEntry
|
|
31
|
+
to: EvolutionEntry
|
|
32
|
+
daysBetween: number
|
|
33
|
+
summary: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class DecisionEvolutionTracker {
|
|
37
|
+
private logger: Logger
|
|
38
|
+
private collections: CollectionManager
|
|
39
|
+
private embeddings?: EmbeddingProvider
|
|
40
|
+
|
|
41
|
+
constructor(logger: Logger, collections: CollectionManager, embeddings?: EmbeddingProvider) {
|
|
42
|
+
this.logger = logger.child({ component: 'decision-evolution' })
|
|
43
|
+
this.collections = collections
|
|
44
|
+
this.embeddings = embeddings
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Analyze how decisions on a topic have evolved over time
|
|
49
|
+
*/
|
|
50
|
+
async analyzeEvolution(topic: string, options: {
|
|
51
|
+
project?: string
|
|
52
|
+
limit?: number
|
|
53
|
+
} = {}): Promise<EvolutionAnalysis> {
|
|
54
|
+
const { project, limit = 20 } = options
|
|
55
|
+
|
|
56
|
+
// Find all decisions related to this topic
|
|
57
|
+
const decisions = await this.findRelatedDecisions(topic, project, limit)
|
|
58
|
+
|
|
59
|
+
// Sort chronologically
|
|
60
|
+
decisions.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
|
|
61
|
+
|
|
62
|
+
// Detect changes between consecutive decisions
|
|
63
|
+
const changes = this.detectChanges(decisions)
|
|
64
|
+
|
|
65
|
+
// Determine stability
|
|
66
|
+
const stability = this.assessStability(decisions, changes)
|
|
67
|
+
|
|
68
|
+
// Current state is the most recent decision
|
|
69
|
+
const currentState = decisions.length > 0
|
|
70
|
+
? decisions[decisions.length - 1].decision
|
|
71
|
+
: 'No decisions found for this topic'
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
topic,
|
|
75
|
+
project,
|
|
76
|
+
totalDecisions: decisions.length,
|
|
77
|
+
timeline: decisions,
|
|
78
|
+
changes,
|
|
79
|
+
currentState,
|
|
80
|
+
stability
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async findRelatedDecisions(
|
|
85
|
+
topic: string,
|
|
86
|
+
project?: string,
|
|
87
|
+
limit: number = 20
|
|
88
|
+
): Promise<EvolutionEntry[]> {
|
|
89
|
+
try {
|
|
90
|
+
const collection = await this.collections.getDecisions()
|
|
91
|
+
|
|
92
|
+
const where: any = project ? { project: { $eq: project } } : undefined
|
|
93
|
+
|
|
94
|
+
let results: any
|
|
95
|
+
|
|
96
|
+
if (this.embeddings) {
|
|
97
|
+
const embedding = await this.embeddings.generate(topic)
|
|
98
|
+
results = await collection.query({
|
|
99
|
+
queryEmbeddings: [embedding],
|
|
100
|
+
nResults: limit,
|
|
101
|
+
where,
|
|
102
|
+
include: ['documents', 'metadatas', 'distances']
|
|
103
|
+
})
|
|
104
|
+
} else {
|
|
105
|
+
results = await collection.query({
|
|
106
|
+
queryTexts: [topic],
|
|
107
|
+
nResults: limit,
|
|
108
|
+
where,
|
|
109
|
+
include: ['documents', 'metadatas', 'distances']
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!results.ids || !results.ids[0]) return []
|
|
114
|
+
|
|
115
|
+
const entries: EvolutionEntry[] = []
|
|
116
|
+
const ids = results.ids[0]
|
|
117
|
+
const documents = results.documents?.[0] || []
|
|
118
|
+
const metadatas = results.metadatas?.[0] || []
|
|
119
|
+
const distances = results.distances?.[0] || []
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < ids.length; i++) {
|
|
122
|
+
const similarity = 1 - (distances[i] || 0)
|
|
123
|
+
// Only include reasonably relevant results
|
|
124
|
+
if (similarity < 0.3) continue
|
|
125
|
+
|
|
126
|
+
const meta = metadatas[i] || {}
|
|
127
|
+
entries.push({
|
|
128
|
+
id: ids[i],
|
|
129
|
+
date: meta.created_at || new Date().toISOString(),
|
|
130
|
+
decision: documents[i] || '',
|
|
131
|
+
reasoning: meta.reasoning || '',
|
|
132
|
+
context: meta.context || '',
|
|
133
|
+
tags: (meta.tags || '').split(',').filter((t: string) => t)
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return entries
|
|
138
|
+
} catch (error) {
|
|
139
|
+
this.logger.warn({ error, topic }, 'Failed to find related decisions')
|
|
140
|
+
return []
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private detectChanges(entries: EvolutionEntry[]): EvolutionChange[] {
|
|
145
|
+
const changes: EvolutionChange[] = []
|
|
146
|
+
|
|
147
|
+
for (let i = 1; i < entries.length; i++) {
|
|
148
|
+
const prev = entries[i - 1]
|
|
149
|
+
const curr = entries[i]
|
|
150
|
+
|
|
151
|
+
const daysBetween = Math.round(
|
|
152
|
+
(new Date(curr.date).getTime() - new Date(prev.date).getTime()) / (1000 * 60 * 60 * 24)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
// Simple heuristic: if decisions differ substantially, it's a change
|
|
156
|
+
const prevWords = new Set(prev.decision.toLowerCase().split(/\s+/))
|
|
157
|
+
const currWords = new Set(curr.decision.toLowerCase().split(/\s+/))
|
|
158
|
+
|
|
159
|
+
const intersection = new Set([...prevWords].filter(w => currWords.has(w)))
|
|
160
|
+
const union = new Set([...prevWords, ...currWords])
|
|
161
|
+
const jaccard = union.size > 0 ? intersection.size / union.size : 1
|
|
162
|
+
|
|
163
|
+
// If less than 60% overlap, consider it a meaningful change
|
|
164
|
+
if (jaccard < 0.6) {
|
|
165
|
+
const summary = this.summarizeChange(prev, curr)
|
|
166
|
+
changes.push({
|
|
167
|
+
from: prev,
|
|
168
|
+
to: curr,
|
|
169
|
+
daysBetween,
|
|
170
|
+
summary
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return changes
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private summarizeChange(from: EvolutionEntry, to: EvolutionEntry): string {
|
|
179
|
+
const fromDate = new Date(from.date).toLocaleDateString()
|
|
180
|
+
const toDate = new Date(to.date).toLocaleDateString()
|
|
181
|
+
|
|
182
|
+
return `Changed from "${from.decision.slice(0, 80)}..." to "${to.decision.slice(0, 80)}..." (${fromDate} -> ${toDate})`
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private assessStability(
|
|
186
|
+
entries: EvolutionEntry[],
|
|
187
|
+
changes: EvolutionChange[]
|
|
188
|
+
): 'stable' | 'evolving' | 'volatile' {
|
|
189
|
+
if (entries.length <= 1) return 'stable'
|
|
190
|
+
|
|
191
|
+
const changeRatio = changes.length / (entries.length - 1)
|
|
192
|
+
|
|
193
|
+
if (changeRatio <= 0.2) return 'stable'
|
|
194
|
+
if (changeRatio <= 0.5) return 'evolving'
|
|
195
|
+
return 'volatile'
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Temporal Intelligence Module
|
|
3
|
-
* Phase 15.1 - Timeline construction, temporal queries, evolution tracking, trend detection
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export { TimelineBuilder } from './timeline'
|
|
7
|
-
export type { TimelineEntry, Timeline } from './timeline'
|
|
8
|
-
|
|
9
|
-
export { TemporalQueryProcessor } from './query-processor'
|
|
10
|
-
export type { TemporalQuery } from './query-processor'
|
|
11
|
-
|
|
12
|
-
export { DecisionEvolutionTracker } from './evolution'
|
|
13
|
-
export type { EvolutionAnalysis, EvolutionChange, EvolutionEntry } from './evolution'
|
|
14
|
-
|
|
15
|
-
export { TrendDetector } from './trends'
|
|
16
|
-
export type { TrendAnalysis, TrendItem } from './trends'
|
|
1
|
+
/**
|
|
2
|
+
* Temporal Intelligence Module
|
|
3
|
+
* Phase 15.1 - Timeline construction, temporal queries, evolution tracking, trend detection
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { TimelineBuilder } from './timeline'
|
|
7
|
+
export type { TimelineEntry, Timeline } from './timeline'
|
|
8
|
+
|
|
9
|
+
export { TemporalQueryProcessor } from './query-processor'
|
|
10
|
+
export type { TemporalQuery } from './query-processor'
|
|
11
|
+
|
|
12
|
+
export { DecisionEvolutionTracker } from './evolution'
|
|
13
|
+
export type { EvolutionAnalysis, EvolutionChange, EvolutionEntry } from './evolution'
|
|
14
|
+
|
|
15
|
+
export { TrendDetector } from './trends'
|
|
16
|
+
export type { TrendAnalysis, TrendItem } from './trends'
|