claude-brain 0.9.3 → 0.13.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/VERSION +1 -1
- package/assets/CLAUDE.md +9 -1
- package/package.json +1 -1
- package/src/automation/phase12-manager.ts +456 -0
- package/src/automation/project-detector.ts +13 -0
- package/src/automation/repo-scanner.ts +205 -0
- package/src/cli/bin.ts +30 -0
- package/src/cli/commands/git-hook.ts +189 -0
- package/src/cli/commands/hooks.ts +8 -9
- package/src/cli/commands/init.ts +98 -0
- package/src/cli/commands/serve.ts +7 -20
- package/src/cli/commands/update.ts +3 -3
- package/src/config/defaults.ts +4 -1
- package/src/config/schema.ts +27 -7
- package/src/hooks/brain-hook.ts +8 -6
- package/src/hooks/capture.ts +9 -2
- package/src/hooks/git-capture.ts +94 -0
- package/src/hooks/git-hook-installer.ts +197 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/session-tracker.ts +79 -3
- package/src/hooks/types.ts +1 -1
- package/src/intelligence/index.ts +24 -0
- package/src/knowledge/graph/builder.ts +26 -0
- package/src/memory/chroma/store.ts +18 -2
- package/src/memory/episodic/manager.ts +17 -0
- package/src/memory/index.ts +48 -18
- package/src/phase12/index.ts +3 -454
- package/src/routing/intent-classifier.ts +107 -9
- package/src/routing/response-filter.ts +50 -17
- package/src/routing/router.ts +472 -224
- package/src/routing/search-engine.ts +464 -0
- package/src/routing/types.ts +84 -0
- package/src/server/handlers/call-tool.ts +4 -49
- package/src/server/handlers/tools/analyze-decision-evolution.ts +1 -1
- package/src/server/handlers/tools/detect-trends.ts +1 -1
- package/src/server/handlers/tools/find-cross-project-patterns.ts +1 -1
- package/src/server/handlers/tools/get-decision-timeline.ts +2 -2
- package/src/server/handlers/tools/get-recommendations.ts +1 -1
- package/src/server/handlers/tools/index.ts +5 -7
- package/src/server/handlers/tools/what-if-analysis.ts +1 -1
- package/src/server/providers/resources.ts +195 -0
- package/src/server/services.ts +81 -6
- package/src/tools/schemas.ts +7 -329
- package/src/utils/phase12-helper.ts +2 -2
- package/src/utils/timing.ts +47 -0
- package/src/vault/writer.ts +22 -2
- /package/src/{cross-project → intelligence/cross-project}/affinity.ts +0 -0
- /package/src/{cross-project → intelligence/cross-project}/generalizer.ts +0 -0
- /package/src/{cross-project → intelligence/cross-project}/index.ts +0 -0
- /package/src/{cross-project → intelligence/cross-project}/transfer.ts +0 -0
- /package/src/{optimization → intelligence/optimization}/index.ts +0 -0
- /package/src/{optimization → intelligence/optimization}/precompute.ts +0 -0
- /package/src/{optimization → intelligence/optimization}/semantic-cache.ts +0 -0
- /package/src/{prediction → intelligence/prediction}/context-anticipator.ts +0 -0
- /package/src/{prediction → intelligence/prediction}/decision-predictor.ts +0 -0
- /package/src/{prediction → intelligence/prediction}/index.ts +0 -0
- /package/src/{prediction → intelligence/prediction}/recommender.ts +0 -0
- /package/src/{reasoning → intelligence/reasoning}/chain-retrieval.ts +0 -0
- /package/src/{reasoning → intelligence/reasoning}/counterfactual.ts +0 -0
- /package/src/{reasoning → intelligence/reasoning}/index.ts +0 -0
- /package/src/{reasoning → intelligence/reasoning}/synthesizer.ts +0 -0
- /package/src/{temporal → intelligence/temporal}/evolution.ts +0 -0
- /package/src/{temporal → intelligence/temporal}/index.ts +0 -0
- /package/src/{temporal → intelligence/temporal}/query-processor.ts +0 -0
- /package/src/{temporal → intelligence/temporal}/timeline.ts +0 -0
- /package/src/{temporal → intelligence/temporal}/trends.ts +0 -0
package/src/phase12/index.ts
CHANGED
|
@@ -1,456 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Phase 12 Manager
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Orchestrates all Phase 12 features:
|
|
6
|
-
* - Pattern Recognition
|
|
7
|
-
* - Learning System
|
|
8
|
-
* - Knowledge Extraction
|
|
9
|
-
* - Auto-Context Loading
|
|
10
|
-
* - Decision Detection
|
|
11
|
-
* - Proactive Recall
|
|
2
|
+
* Phase 12 Manager — Re-export stub
|
|
3
|
+
* Moved to @/automation/phase12-manager in Phase 22.3
|
|
12
4
|
*/
|
|
13
|
-
|
|
14
|
-
import type { Logger } from 'pino'
|
|
15
|
-
import type { VaultManager } from '@/vault'
|
|
16
|
-
import type { MemoryManager } from '@/memory'
|
|
17
|
-
import type { ContextManager } from '@/context'
|
|
18
|
-
import { PatternRecognizer, type Pattern } from '@/memory/patterns'
|
|
19
|
-
import { LearningSystem, type LearningInsights } from '@/memory/learning'
|
|
20
|
-
import { KnowledgeExtractor, type ExtractedKnowledge } from '@/memory/knowledge-extractor'
|
|
21
|
-
import {
|
|
22
|
-
ProjectDetector,
|
|
23
|
-
AutoContextLoader,
|
|
24
|
-
DecisionDetector,
|
|
25
|
-
ProactiveRecallEngine,
|
|
26
|
-
type DetectedProject,
|
|
27
|
-
type DetectedDecision,
|
|
28
|
-
type RecallResult
|
|
29
|
-
} from '@/automation'
|
|
30
|
-
|
|
31
|
-
export interface Phase12Config {
|
|
32
|
-
/**
|
|
33
|
-
* Enable automatic context loading on startup
|
|
34
|
-
* @default true
|
|
35
|
-
*/
|
|
36
|
-
autoLoadContext: boolean
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Enable automatic decision detection and saving
|
|
40
|
-
* @default true
|
|
41
|
-
*/
|
|
42
|
-
autoDetectDecisions: boolean
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Enable proactive memory recall
|
|
46
|
-
* @default true
|
|
47
|
-
*/
|
|
48
|
-
enableProactiveRecall: boolean
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Minimum confidence for auto-saving decisions
|
|
52
|
-
* @default 0.7
|
|
53
|
-
*/
|
|
54
|
-
decisionConfidenceThreshold: number
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Enable pattern analysis on startup
|
|
58
|
-
* @default false
|
|
59
|
-
*/
|
|
60
|
-
analyzePatternsonStartup: boolean
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Enable knowledge extraction from messages
|
|
64
|
-
* @default true
|
|
65
|
-
*/
|
|
66
|
-
enableKnowledgeExtraction: boolean
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const DEFAULT_CONFIG: Phase12Config = {
|
|
70
|
-
autoLoadContext: true,
|
|
71
|
-
autoDetectDecisions: true,
|
|
72
|
-
enableProactiveRecall: true,
|
|
73
|
-
decisionConfidenceThreshold: 0.7,
|
|
74
|
-
analyzePatternsonStartup: false,
|
|
75
|
-
enableKnowledgeExtraction: true
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface MessageProcessingResult {
|
|
79
|
-
recalledMemories?: RecallResult
|
|
80
|
-
detectedDecision?: DetectedDecision
|
|
81
|
-
extractedKnowledge?: ExtractedKnowledge[]
|
|
82
|
-
detectedProject?: DetectedProject
|
|
83
|
-
decisionSaved?: boolean
|
|
84
|
-
decisionId?: string
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface Phase12Stats {
|
|
88
|
-
patterns: {
|
|
89
|
-
total: number
|
|
90
|
-
byType: Record<string, number>
|
|
91
|
-
}
|
|
92
|
-
learning: LearningInsights
|
|
93
|
-
automation: {
|
|
94
|
-
contextLoaded: boolean
|
|
95
|
-
currentProject: string | null
|
|
96
|
-
recallStats: {
|
|
97
|
-
totalRecalls: number
|
|
98
|
-
successfulRecalls: number
|
|
99
|
-
averageRelevance: number
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export class Phase12Manager {
|
|
105
|
-
private logger: Logger
|
|
106
|
-
private config: Phase12Config
|
|
107
|
-
private initialized = false
|
|
108
|
-
|
|
109
|
-
// Advanced Memory
|
|
110
|
-
public readonly patterns: PatternRecognizer
|
|
111
|
-
public readonly learning: LearningSystem
|
|
112
|
-
public readonly knowledge: KnowledgeExtractor
|
|
113
|
-
|
|
114
|
-
// Intelligent Automation
|
|
115
|
-
public readonly projectDetector: ProjectDetector
|
|
116
|
-
public readonly autoContext: AutoContextLoader
|
|
117
|
-
public readonly decisionDetector: DecisionDetector
|
|
118
|
-
public readonly proactiveRecall: ProactiveRecallEngine
|
|
119
|
-
|
|
120
|
-
constructor(
|
|
121
|
-
logger: Logger,
|
|
122
|
-
vault: VaultManager,
|
|
123
|
-
memory: MemoryManager,
|
|
124
|
-
context: ContextManager,
|
|
125
|
-
config: Partial<Phase12Config> = {}
|
|
126
|
-
) {
|
|
127
|
-
this.logger = logger.child({ component: 'phase12-manager' })
|
|
128
|
-
this.config = { ...DEFAULT_CONFIG, ...config }
|
|
129
|
-
|
|
130
|
-
// Initialize advanced memory features
|
|
131
|
-
this.patterns = new PatternRecognizer(logger, memory)
|
|
132
|
-
this.learning = new LearningSystem(logger, memory)
|
|
133
|
-
this.knowledge = new KnowledgeExtractor(logger, memory)
|
|
134
|
-
|
|
135
|
-
// Initialize intelligent automation
|
|
136
|
-
this.projectDetector = new ProjectDetector(logger, vault)
|
|
137
|
-
this.autoContext = new AutoContextLoader(
|
|
138
|
-
logger,
|
|
139
|
-
context,
|
|
140
|
-
this.projectDetector
|
|
141
|
-
)
|
|
142
|
-
this.decisionDetector = new DecisionDetector(logger, memory)
|
|
143
|
-
this.proactiveRecall = new ProactiveRecallEngine(logger, memory)
|
|
144
|
-
|
|
145
|
-
this.logger.info(
|
|
146
|
-
{ config: this.config },
|
|
147
|
-
'Phase 12 Manager created'
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Initialize all Phase 12 features
|
|
153
|
-
*/
|
|
154
|
-
async initialize(): Promise<void> {
|
|
155
|
-
if (this.initialized) {
|
|
156
|
-
this.logger.warn('Phase 12 already initialized')
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
this.logger.info('Initializing Phase 12 features...')
|
|
161
|
-
|
|
162
|
-
try {
|
|
163
|
-
// Start auto-context loader
|
|
164
|
-
if (this.config.autoLoadContext) {
|
|
165
|
-
await this.autoContext.initialize()
|
|
166
|
-
this.logger.info('Auto-context loader initialized')
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Run initial pattern analysis if enabled
|
|
170
|
-
if (this.config.analyzePatternsonStartup) {
|
|
171
|
-
const patterns = await this.patterns.analyzePatterns()
|
|
172
|
-
this.logger.info(
|
|
173
|
-
{ patternCount: patterns.length },
|
|
174
|
-
'Initial pattern analysis complete'
|
|
175
|
-
)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
this.initialized = true
|
|
179
|
-
this.logger.info('Phase 12 initialization complete')
|
|
180
|
-
} catch (error) {
|
|
181
|
-
this.logger.error({ error }, 'Phase 12 initialization failed')
|
|
182
|
-
throw error
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Check if Phase 12 is initialized
|
|
188
|
-
*/
|
|
189
|
-
isInitialized(): boolean {
|
|
190
|
-
return this.initialized
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Process incoming message with all Phase 12 features
|
|
195
|
-
*/
|
|
196
|
-
async processMessage(
|
|
197
|
-
message: string,
|
|
198
|
-
project?: string
|
|
199
|
-
): Promise<MessageProcessingResult> {
|
|
200
|
-
const results: MessageProcessingResult = {}
|
|
201
|
-
|
|
202
|
-
// Use detected project if not provided
|
|
203
|
-
const targetProject = project || this.autoContext.getCurrentProject() || undefined
|
|
204
|
-
|
|
205
|
-
// 1. Proactive recall
|
|
206
|
-
if (this.config.enableProactiveRecall) {
|
|
207
|
-
if (this.proactiveRecall.shouldRecall(message)) {
|
|
208
|
-
results.recalledMemories = await this.proactiveRecall.recall(
|
|
209
|
-
message,
|
|
210
|
-
targetProject
|
|
211
|
-
) || undefined
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// 2. Decision detection
|
|
216
|
-
if (this.config.autoDetectDecisions && targetProject) {
|
|
217
|
-
const decision = this.decisionDetector.detectDecision(message, targetProject)
|
|
218
|
-
|
|
219
|
-
if (decision && decision.confidence >= this.config.decisionConfidenceThreshold) {
|
|
220
|
-
results.detectedDecision = decision
|
|
221
|
-
|
|
222
|
-
// Auto-save if confidence is high enough
|
|
223
|
-
const decisionId = await this.decisionDetector.autoSaveDecision(
|
|
224
|
-
decision,
|
|
225
|
-
targetProject
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
if (decisionId) {
|
|
229
|
-
results.decisionSaved = true
|
|
230
|
-
results.decisionId = decisionId
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// 3. Knowledge extraction
|
|
236
|
-
if (this.config.enableKnowledgeExtraction) {
|
|
237
|
-
const extracted = await this.knowledge.extractFromConversation(
|
|
238
|
-
message,
|
|
239
|
-
targetProject
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
if (extracted.knowledge.length > 0) {
|
|
243
|
-
results.extractedKnowledge = extracted.knowledge
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Log processing results
|
|
248
|
-
if (Object.keys(results).length > 0) {
|
|
249
|
-
this.logger.debug(
|
|
250
|
-
{
|
|
251
|
-
hasRecall: !!results.recalledMemories,
|
|
252
|
-
hasDecision: !!results.detectedDecision,
|
|
253
|
-
knowledgeCount: results.extractedKnowledge?.length || 0,
|
|
254
|
-
decisionSaved: results.decisionSaved
|
|
255
|
-
},
|
|
256
|
-
'Message processed with Phase 12 features'
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return results
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Process outgoing response for decisions
|
|
265
|
-
* Call this with Claude's responses to detect and save decisions
|
|
266
|
-
*/
|
|
267
|
-
async processResponse(
|
|
268
|
-
response: string,
|
|
269
|
-
project?: string
|
|
270
|
-
): Promise<MessageProcessingResult> {
|
|
271
|
-
const results: MessageProcessingResult = {}
|
|
272
|
-
const targetProject = project || this.autoContext.getCurrentProject() || undefined
|
|
273
|
-
|
|
274
|
-
// Decision detection on responses (Claude's decisions)
|
|
275
|
-
if (this.config.autoDetectDecisions && targetProject) {
|
|
276
|
-
const decision = this.decisionDetector.detectDecision(response, targetProject)
|
|
277
|
-
|
|
278
|
-
if (decision && decision.confidence >= this.config.decisionConfidenceThreshold) {
|
|
279
|
-
results.detectedDecision = decision
|
|
280
|
-
|
|
281
|
-
const decisionId = await this.decisionDetector.autoSaveDecision(
|
|
282
|
-
decision,
|
|
283
|
-
targetProject
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
if (decisionId) {
|
|
287
|
-
results.decisionSaved = true
|
|
288
|
-
results.decisionId = decisionId
|
|
289
|
-
this.logger.info(
|
|
290
|
-
{ decisionId, project: targetProject },
|
|
291
|
-
'Decision auto-saved from response'
|
|
292
|
-
)
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Knowledge extraction from responses
|
|
298
|
-
if (this.config.enableKnowledgeExtraction) {
|
|
299
|
-
const extracted = await this.knowledge.extractFromConversation(
|
|
300
|
-
response,
|
|
301
|
-
targetProject
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
if (extracted.knowledge.length > 0) {
|
|
305
|
-
results.extractedKnowledge = extracted.knowledge
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return results
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Get proactively recalled context for a query
|
|
314
|
-
*/
|
|
315
|
-
async getRecalledContext(query: string, project?: string): Promise<string | null> {
|
|
316
|
-
const result = await this.proactiveRecall.recall(
|
|
317
|
-
query,
|
|
318
|
-
project || this.autoContext.getCurrentProject() || undefined
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
return result?.formattedContext || null
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Get relevant patterns for a query
|
|
326
|
-
*/
|
|
327
|
-
async getRelevantPatterns(query: string): Promise<Pattern[]> {
|
|
328
|
-
return this.patterns.getRelevantPatterns(query)
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Record a correction for learning
|
|
333
|
-
*/
|
|
334
|
-
async recordCorrection(
|
|
335
|
-
original: string,
|
|
336
|
-
corrected: string,
|
|
337
|
-
reasoning: string,
|
|
338
|
-
project?: string
|
|
339
|
-
): Promise<string> {
|
|
340
|
-
const targetProject = project || this.autoContext.getCurrentProject() || 'global'
|
|
341
|
-
return this.learning.recordCorrection(original, corrected, reasoning, targetProject)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Get comprehensive Phase 12 statistics
|
|
346
|
-
*/
|
|
347
|
-
getStats(): Phase12Stats {
|
|
348
|
-
const allPatterns = this.patterns.getAllPatterns()
|
|
349
|
-
const patternsByType: Record<string, number> = {}
|
|
350
|
-
|
|
351
|
-
for (const pattern of allPatterns) {
|
|
352
|
-
patternsByType[pattern.type] = (patternsByType[pattern.type] || 0) + 1
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const recallStats = this.proactiveRecall.getStats()
|
|
356
|
-
|
|
357
|
-
return {
|
|
358
|
-
patterns: {
|
|
359
|
-
total: allPatterns.length,
|
|
360
|
-
byType: patternsByType
|
|
361
|
-
},
|
|
362
|
-
learning: this.learning.getLearningInsights(),
|
|
363
|
-
automation: {
|
|
364
|
-
contextLoaded: this.autoContext.getCurrentContext() !== undefined,
|
|
365
|
-
currentProject: this.autoContext.getCurrentProject(),
|
|
366
|
-
recallStats: {
|
|
367
|
-
totalRecalls: recallStats.totalRecalls,
|
|
368
|
-
successfulRecalls: recallStats.successfulRecalls,
|
|
369
|
-
averageRelevance: recallStats.averageRelevance
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Get formatted status report
|
|
377
|
-
*/
|
|
378
|
-
getStatusReport(): string {
|
|
379
|
-
const stats = this.getStats()
|
|
380
|
-
const parts: string[] = []
|
|
381
|
-
|
|
382
|
-
parts.push('# Phase 12 Status Report\n')
|
|
383
|
-
|
|
384
|
-
// Current project
|
|
385
|
-
parts.push('## Current Context')
|
|
386
|
-
if (stats.automation.currentProject) {
|
|
387
|
-
parts.push(`- **Project:** ${stats.automation.currentProject}`)
|
|
388
|
-
parts.push(`- **Context Loaded:** Yes`)
|
|
389
|
-
} else {
|
|
390
|
-
parts.push('- **Project:** Not detected (use smart_context to load project context)')
|
|
391
|
-
parts.push('- **Context Loaded:** No')
|
|
392
|
-
}
|
|
393
|
-
parts.push('')
|
|
394
|
-
|
|
395
|
-
// Pattern analysis
|
|
396
|
-
parts.push('## Pattern Analysis')
|
|
397
|
-
parts.push(`- **Total Patterns:** ${stats.patterns.total}`)
|
|
398
|
-
if (stats.patterns.total === 0) {
|
|
399
|
-
parts.push(' *No patterns stored yet. Use `recognize_pattern` to document reusable solutions.*')
|
|
400
|
-
} else {
|
|
401
|
-
for (const [type, count] of Object.entries(stats.patterns.byType)) {
|
|
402
|
-
parts.push(` - ${type}: ${count}`)
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
parts.push('')
|
|
406
|
-
|
|
407
|
-
// Learning system
|
|
408
|
-
parts.push('## Learning System')
|
|
409
|
-
parts.push(`- **Total Corrections:** ${stats.learning.correctionCount}`)
|
|
410
|
-
if (stats.learning.correctionCount === 0) {
|
|
411
|
-
parts.push(' *No corrections recorded yet. Use `record_correction` to document lessons learned.*')
|
|
412
|
-
}
|
|
413
|
-
parts.push(`- **Categories Improved:** ${stats.learning.categoriesImproved.join(', ') || 'None'}`)
|
|
414
|
-
if (stats.learning.preferences.length > 0) {
|
|
415
|
-
parts.push('- **Top Preferences:**')
|
|
416
|
-
for (const pref of stats.learning.preferences.slice(0, 3)) {
|
|
417
|
-
parts.push(` - ${pref.category}: ${Math.round(pref.strength * 100)}% confidence`)
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
parts.push('')
|
|
421
|
-
|
|
422
|
-
// Proactive recall
|
|
423
|
-
parts.push('## Proactive Recall')
|
|
424
|
-
parts.push(`- **Total Recalls:** ${stats.automation.recallStats.totalRecalls}`)
|
|
425
|
-
parts.push(`- **Successful:** ${stats.automation.recallStats.successfulRecalls}`)
|
|
426
|
-
const successRate = stats.automation.recallStats.totalRecalls > 0
|
|
427
|
-
? Math.round((stats.automation.recallStats.successfulRecalls / stats.automation.recallStats.totalRecalls) * 100)
|
|
428
|
-
: 0
|
|
429
|
-
parts.push(`- **Success Rate:** ${successRate}%`)
|
|
430
|
-
parts.push(`- **Average Relevance:** ${Math.round(stats.automation.recallStats.averageRelevance * 100)}%`)
|
|
431
|
-
|
|
432
|
-
if (stats.automation.recallStats.totalRecalls === 0) {
|
|
433
|
-
parts.push('\n*Proactive recall activates automatically when you ask questions or request recommendations.*')
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return parts.join('\n')
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Cleanup and reset Phase 12
|
|
441
|
-
*/
|
|
442
|
-
cleanup(): void {
|
|
443
|
-
this.autoContext.clearAllContexts()
|
|
444
|
-
this.patterns.clearPatterns()
|
|
445
|
-
this.learning.clearLearning()
|
|
446
|
-
this.proactiveRecall.resetStats()
|
|
447
|
-
this.initialized = false
|
|
448
|
-
this.logger.info('Phase 12 cleaned up')
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Re-export types
|
|
453
|
-
export type { Pattern } from '@/memory/patterns'
|
|
454
|
-
export type { Correction, Preference, LearningInsights } from '@/memory/learning'
|
|
455
|
-
export type { ExtractedKnowledge, ExtractionResult } from '@/memory/knowledge-extractor'
|
|
456
|
-
export type { DetectedProject, DetectedDecision, RecallResult } from '@/automation'
|
|
5
|
+
export * from '@/automation/phase12-manager'
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Brain Intent Classifier
|
|
3
|
-
* Phase 16: Rule-based intent classification for the unified brain() tool
|
|
3
|
+
* Phase 16 + Phase 19: Rule-based intent classification for the unified brain() tool
|
|
4
4
|
*
|
|
5
5
|
* Priority-ordered — first confident match wins.
|
|
6
6
|
* No LLM calls, pure pattern matching.
|
|
7
|
+
*
|
|
8
|
+
* Phase 19 changes:
|
|
9
|
+
* - B1: Question confidence raised (? → 0.95, question word → 0.90)
|
|
10
|
+
* - B2: session_start narrowed (must be at start + no progress indicators)
|
|
11
|
+
* - B3: Temporal signal detection added to secondary intents
|
|
7
12
|
*/
|
|
8
13
|
|
|
9
14
|
export type Intent =
|
|
@@ -51,7 +56,13 @@ const STORE_PHRASES = [
|
|
|
51
56
|
'we should always', 'we should never',
|
|
52
57
|
'i want to remember', 'don\'t forget',
|
|
53
58
|
'for future reference', 'for the record',
|
|
54
|
-
'important:', 'key decision:', 'takeaway:'
|
|
59
|
+
'important:', 'key decision:', 'takeaway:',
|
|
60
|
+
// Issue 3: Declarative patterns ("X should be Y")
|
|
61
|
+
'should be', 'must be', 'needs to be', 'has to be',
|
|
62
|
+
'is set to', 'will be set', 'is always', 'are always',
|
|
63
|
+
'is configured to', 'is configured as',
|
|
64
|
+
// Issue 6: "I learned that" is a store, not a mistake
|
|
65
|
+
'i learned that'
|
|
55
66
|
]
|
|
56
67
|
|
|
57
68
|
const REASONING_PHRASES = [
|
|
@@ -68,7 +79,7 @@ const MISTAKE_PHRASES = [
|
|
|
68
79
|
'the fix is', 'the fix was', 'fixed by', 'solved by',
|
|
69
80
|
'was wrong', 'was broken', 'was incorrect',
|
|
70
81
|
'gotcha:', 'pitfall:', 'watch out for', 'be careful with',
|
|
71
|
-
'
|
|
82
|
+
'turns out that'
|
|
72
83
|
]
|
|
73
84
|
|
|
74
85
|
// Progress indicators
|
|
@@ -102,13 +113,20 @@ const EXPLORATION_PHRASES = [
|
|
|
102
113
|
'decisions about', 'when did we', 'list episodes'
|
|
103
114
|
]
|
|
104
115
|
|
|
105
|
-
// Session start indicators
|
|
116
|
+
// Session start indicators — Phase 19: narrowed to require start-of-message
|
|
106
117
|
const SESSION_START_PHRASES = [
|
|
107
118
|
'starting work', 'beginning work', 'resuming',
|
|
108
119
|
'picking up', 'getting started', 'opening',
|
|
109
120
|
'starting on', 'working on', 'beginning on'
|
|
110
121
|
]
|
|
111
122
|
|
|
123
|
+
// Progress indicators that disqualify session_start
|
|
124
|
+
const PROGRESS_INDICATORS = [
|
|
125
|
+
'finished', 'completed', 'done', 'fixed', 'resolved',
|
|
126
|
+
'shipped', 'deployed', 'merged', 'released', 'just did',
|
|
127
|
+
'making progress', 'currently working'
|
|
128
|
+
]
|
|
129
|
+
|
|
112
130
|
// Question indicators
|
|
113
131
|
const QUESTION_WORDS = [
|
|
114
132
|
'what', 'how', 'when', 'why', 'where', 'which',
|
|
@@ -128,7 +146,11 @@ const LIST_PHRASES = [
|
|
|
128
146
|
'what have i decided', 'all my decisions', 'all decisions',
|
|
129
147
|
'everything about', 'what do i know', 'what do we know',
|
|
130
148
|
'show me everything', 'list decisions', 'list memories',
|
|
131
|
-
'browse', 'dump all', 'show my'
|
|
149
|
+
'browse', 'dump all', 'show my',
|
|
150
|
+
// Issue 4: Additional list phrases
|
|
151
|
+
'list everything', "everything i've stored", "everything i know",
|
|
152
|
+
"what have i stored", "stored in my brain", "what's in my brain",
|
|
153
|
+
"what have i remembered", "what do i have stored"
|
|
132
154
|
]
|
|
133
155
|
|
|
134
156
|
// Update/correct existing memory
|
|
@@ -148,6 +170,21 @@ const DELETE_PHRASES = [
|
|
|
148
170
|
'remove the memory', 'clear that', 'drop that'
|
|
149
171
|
]
|
|
150
172
|
|
|
173
|
+
// Phase 19 B3: Temporal signal phrases
|
|
174
|
+
const TEMPORAL_PHRASES = [
|
|
175
|
+
'last week', 'last month', 'last year', 'yesterday', 'today',
|
|
176
|
+
'this week', 'this month', 'this year',
|
|
177
|
+
'since january', 'since february', 'since march', 'since april',
|
|
178
|
+
'since may', 'since june', 'since july', 'since august',
|
|
179
|
+
'since september', 'since october', 'since november', 'since december',
|
|
180
|
+
'in january', 'in february', 'in march', 'in april',
|
|
181
|
+
'in may', 'in june', 'in july', 'in august',
|
|
182
|
+
'in september', 'in october', 'in november', 'in december',
|
|
183
|
+
'ago', 'recently', 'before', 'after', 'during',
|
|
184
|
+
'last few days', 'past week', 'past month',
|
|
185
|
+
'earlier this', 'earlier today', 'over the past'
|
|
186
|
+
]
|
|
187
|
+
|
|
151
188
|
export class IntentClassifier {
|
|
152
189
|
/**
|
|
153
190
|
* Classify the intent of a message
|
|
@@ -156,6 +193,9 @@ export class IntentClassifier {
|
|
|
156
193
|
const lower = message.toLowerCase().trim()
|
|
157
194
|
const secondary: Intent[] = []
|
|
158
195
|
|
|
196
|
+
// Phase 19 B3: Detect temporal signals for secondary intent
|
|
197
|
+
const hasTemporal = this.hasTemporalSignal(lower)
|
|
198
|
+
|
|
159
199
|
// Check in priority order — first confident match wins
|
|
160
200
|
|
|
161
201
|
// 1. no_action: very short messages, greetings, acknowledgments
|
|
@@ -204,6 +244,7 @@ export class IntentClassifier {
|
|
|
204
244
|
// 9. comparison: vs, which is better, etc.
|
|
205
245
|
if (this.isComparison(lower)) {
|
|
206
246
|
if (this.isQuestion(lower, message)) secondary.push('question')
|
|
247
|
+
if (hasTemporal) secondary.push('exploration')
|
|
207
248
|
return { primary: 'comparison', confidence: 0.85, secondary }
|
|
208
249
|
}
|
|
209
250
|
|
|
@@ -212,7 +253,7 @@ export class IntentClassifier {
|
|
|
212
253
|
return { primary: 'pattern_found', confidence: 0.80, secondary }
|
|
213
254
|
}
|
|
214
255
|
|
|
215
|
-
// 11. session_start: starting/resuming work
|
|
256
|
+
// 11. session_start: starting/resuming work (Phase 19: narrowed check)
|
|
216
257
|
if (this.isSessionStart(lower)) {
|
|
217
258
|
secondary.push('context_needed')
|
|
218
259
|
return { primary: 'session_start', confidence: 0.90, secondary }
|
|
@@ -221,17 +262,24 @@ export class IntentClassifier {
|
|
|
221
262
|
// 12. exploration: timeline, trends, graph, history
|
|
222
263
|
if (this.isExploration(lower)) {
|
|
223
264
|
if (this.isQuestion(lower, message)) secondary.push('question')
|
|
265
|
+
if (hasTemporal) secondary.push('exploration')
|
|
224
266
|
return { primary: 'exploration', confidence: 0.75, secondary }
|
|
225
267
|
}
|
|
226
268
|
|
|
227
269
|
// 13. question: starts with question word or ends with ?
|
|
270
|
+
// Phase 19 B1: Higher confidence for questions
|
|
228
271
|
if (this.isQuestion(lower, message)) {
|
|
229
272
|
if (this.hasComparisonSignal(lower)) secondary.push('comparison')
|
|
230
273
|
if (this.hasExplorationSignal(lower)) secondary.push('exploration')
|
|
231
|
-
|
|
274
|
+
if (hasTemporal) secondary.push('exploration')
|
|
275
|
+
|
|
276
|
+
// Phase 19 B1: ? → 0.95, question word → 0.90
|
|
277
|
+
const confidence = message.trim().endsWith('?') ? 0.95 : 0.90
|
|
278
|
+
return { primary: 'question', confidence, secondary }
|
|
232
279
|
}
|
|
233
280
|
|
|
234
281
|
// 14. Default: context_needed
|
|
282
|
+
if (hasTemporal) secondary.push('exploration')
|
|
235
283
|
return { primary: 'context_needed', confidence: 0.60, secondary }
|
|
236
284
|
}
|
|
237
285
|
|
|
@@ -247,6 +295,8 @@ export class IntentClassifier {
|
|
|
247
295
|
if (original?.trim().endsWith('?')) return false
|
|
248
296
|
const firstWord = lower.split(/\s+/)[0] || ''
|
|
249
297
|
if (QUESTION_WORDS.includes(firstWord)) return false
|
|
298
|
+
// Phase 19 B4: Additional question guards
|
|
299
|
+
if (this.startsWithQuestionPattern(lower)) return false
|
|
250
300
|
return STORE_PHRASES.some(p => lower.includes(p))
|
|
251
301
|
}
|
|
252
302
|
|
|
@@ -255,6 +305,8 @@ export class IntentClassifier {
|
|
|
255
305
|
if (original?.trim().endsWith('?')) return false
|
|
256
306
|
const firstWord = lower.split(/\s+/)[0] || ''
|
|
257
307
|
if (QUESTION_WORDS.includes(firstWord)) return false
|
|
308
|
+
// Phase 19 B4: Additional question guards
|
|
309
|
+
if (this.startsWithQuestionPattern(lower)) return false
|
|
258
310
|
|
|
259
311
|
const hasDecision = DECISION_PHRASES.some(p => lower.includes(p))
|
|
260
312
|
if (!hasDecision) return false
|
|
@@ -289,8 +341,23 @@ export class IntentClassifier {
|
|
|
289
341
|
return hasPattern && lower.length > 50
|
|
290
342
|
}
|
|
291
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Phase 19 B2: Narrowed session_start detection.
|
|
346
|
+
* Must start at beginning of message AND have no progress indicators.
|
|
347
|
+
* "working on X" in the middle of a sentence is not a session start.
|
|
348
|
+
*/
|
|
292
349
|
private isSessionStart(lower: string): boolean {
|
|
293
|
-
|
|
350
|
+
// Must NOT have progress indicators (e.g. "finished working on X" is progress, not session start)
|
|
351
|
+
if (PROGRESS_INDICATORS.some(p => lower.includes(p))) return false
|
|
352
|
+
|
|
353
|
+
// Phase 19 B2: Session phrases must match near the start of the message
|
|
354
|
+
for (const phrase of SESSION_START_PHRASES) {
|
|
355
|
+
const idx = lower.indexOf(phrase)
|
|
356
|
+
if (idx !== -1 && idx <= 5) {
|
|
357
|
+
return true
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return false
|
|
294
361
|
}
|
|
295
362
|
|
|
296
363
|
private isExploration(lower: string): boolean {
|
|
@@ -300,7 +367,10 @@ export class IntentClassifier {
|
|
|
300
367
|
private isQuestion(lower: string, original: string): boolean {
|
|
301
368
|
if (original.trim().endsWith('?')) return true
|
|
302
369
|
const firstWord = lower.split(/\s+/)[0] || ''
|
|
303
|
-
|
|
370
|
+
if (QUESTION_WORDS.includes(firstWord)) return true
|
|
371
|
+
// Phase 19 B4: "do I", "did we", "have we", "can we" patterns
|
|
372
|
+
if (this.startsWithQuestionPattern(lower)) return true
|
|
373
|
+
return false
|
|
304
374
|
}
|
|
305
375
|
|
|
306
376
|
private isUpdateMemory(lower: string): boolean {
|
|
@@ -327,4 +397,32 @@ export class IntentClassifier {
|
|
|
327
397
|
private hasSessionSignal(lower: string): boolean {
|
|
328
398
|
return SESSION_START_PHRASES.some(p => lower.includes(p))
|
|
329
399
|
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Phase 19 B3: Detect temporal signals in the message.
|
|
403
|
+
* Used to add 'temporal' context to secondary intents.
|
|
404
|
+
*/
|
|
405
|
+
hasTemporalSignal(lower: string): boolean {
|
|
406
|
+
return TEMPORAL_PHRASES.some(p => lower.includes(p))
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Phase 19 B4: Extended question guards.
|
|
411
|
+
* Catches "do I", "did we", "have we", "can we" etc. patterns
|
|
412
|
+
* that start with auxiliary verbs not in the QUESTION_WORDS list.
|
|
413
|
+
*/
|
|
414
|
+
private startsWithQuestionPattern(lower: string): boolean {
|
|
415
|
+
const questionStarters = [
|
|
416
|
+
'do i ', 'do we ', 'do you ',
|
|
417
|
+
'did i ', 'did we ', 'did you ',
|
|
418
|
+
'have i ', 'have we ', 'have you ',
|
|
419
|
+
'has it ', 'has the ',
|
|
420
|
+
'can i ', 'can we ', 'can you ',
|
|
421
|
+
'will i ', 'will we ', 'will you ',
|
|
422
|
+
'am i ', 'was i ', 'were we ',
|
|
423
|
+
'shall we ', 'shall i ',
|
|
424
|
+
'tell me '
|
|
425
|
+
]
|
|
426
|
+
return questionStarters.some(p => lower.startsWith(p))
|
|
427
|
+
}
|
|
330
428
|
}
|