claude-brain 0.15.2 → 0.16.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/README.md +191 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +29 -11
- package/bunfig.toml +8 -8
- package/package.json +82 -82
- 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/scripts/postinstall.mjs +341 -341
- 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 +209 -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/refresh.ts +323 -0
- package/src/cli/commands/serve.ts +167 -173
- package/src/cli/commands/start.ts +42 -42
- package/src/cli/commands/uninstall-mcp.ts +41 -41
- package/src/cli/commands/update.ts +124 -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 +128 -112
- package/src/hooks/capture.ts +168 -205
- 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 +194 -194
- package/src/hooks/passive-classifier.ts +404 -723
- package/src/hooks/queue.ts +129 -129
- package/src/hooks/session-tracker.ts +312 -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 +155 -155
- 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 +450 -436
- package/src/routing/response-filter.ts +261 -258
- package/src/routing/router.ts +1441 -1322
- package/src/routing/search-engine.ts +515 -475
- package/src/routing/types.ts +94 -94
- 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 -129
- 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
- package/src/cli/auto-update.ts +0 -157
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 17: Smart Deduplicator
|
|
3
|
-
* Three-tier dedup before storage:
|
|
4
|
-
* >0.95 similarity → skip (exact duplicate)
|
|
5
|
-
* 0.85–0.95 similarity → merge (update existing)
|
|
6
|
-
* <0.85 similarity → store_new
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { MemoryManager } from '@/memory'
|
|
10
|
-
import type { CapturedKnowledge, StoreAction } from './types'
|
|
11
|
-
import type { HooksConfig } from '@/config/schema'
|
|
12
|
-
|
|
13
|
-
export class SmartDeduplicator {
|
|
14
|
-
private skipThreshold: number
|
|
15
|
-
private mergeThreshold: number
|
|
16
|
-
|
|
17
|
-
constructor(config?: HooksConfig['deduplication']) {
|
|
18
|
-
this.skipThreshold = config?.skipThreshold ?? 0.95
|
|
19
|
-
this.mergeThreshold = config?.mergeThreshold ?? 0.85
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Check captured knowledge against existing memory
|
|
24
|
-
* and decide: store_new, merge, or skip
|
|
25
|
-
*/
|
|
26
|
-
async beforeStore(
|
|
27
|
-
knowledge: CapturedKnowledge,
|
|
28
|
-
memoryManager: MemoryManager
|
|
29
|
-
): Promise<StoreAction> {
|
|
30
|
-
try {
|
|
31
|
-
const results = await memoryManager.searchRaw(knowledge.content, {
|
|
32
|
-
project: knowledge.project,
|
|
33
|
-
limit: 3,
|
|
34
|
-
minSimilarity: this.mergeThreshold,
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
if (!results || results.length === 0) {
|
|
38
|
-
return { action: 'store_new' }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const topResult = results[0]
|
|
42
|
-
const similarity = topResult.similarity ?? 0
|
|
43
|
-
|
|
44
|
-
if (similarity >= this.skipThreshold) {
|
|
45
|
-
return {
|
|
46
|
-
action: 'skip',
|
|
47
|
-
reason: `Duplicate (similarity: ${similarity.toFixed(3)})`,
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (similarity >= this.mergeThreshold) {
|
|
52
|
-
const existingId = topResult.memory?.id || topResult.id
|
|
53
|
-
const existingContent = topResult.memory?.content ||
|
|
54
|
-
topResult.decision?.decision ||
|
|
55
|
-
''
|
|
56
|
-
const datestamp = new Date().toISOString().split('T')[0]
|
|
57
|
-
const mergedContent = `${existingContent}\n[Updated ${datestamp}]: ${knowledge.content}`
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
action: 'merge',
|
|
61
|
-
existingId,
|
|
62
|
-
mergedContent,
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { action: 'store_new' }
|
|
67
|
-
} catch {
|
|
68
|
-
// If search fails, store as new to avoid data loss
|
|
69
|
-
return { action: 'store_new' }
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Phase 17: Smart Deduplicator
|
|
3
|
+
* Three-tier dedup before storage:
|
|
4
|
+
* >0.95 similarity → skip (exact duplicate)
|
|
5
|
+
* 0.85–0.95 similarity → merge (update existing)
|
|
6
|
+
* <0.85 similarity → store_new
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { MemoryManager } from '@/memory'
|
|
10
|
+
import type { CapturedKnowledge, StoreAction } from './types'
|
|
11
|
+
import type { HooksConfig } from '@/config/schema'
|
|
12
|
+
|
|
13
|
+
export class SmartDeduplicator {
|
|
14
|
+
private skipThreshold: number
|
|
15
|
+
private mergeThreshold: number
|
|
16
|
+
|
|
17
|
+
constructor(config?: HooksConfig['deduplication']) {
|
|
18
|
+
this.skipThreshold = config?.skipThreshold ?? 0.95
|
|
19
|
+
this.mergeThreshold = config?.mergeThreshold ?? 0.85
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check captured knowledge against existing memory
|
|
24
|
+
* and decide: store_new, merge, or skip
|
|
25
|
+
*/
|
|
26
|
+
async beforeStore(
|
|
27
|
+
knowledge: CapturedKnowledge,
|
|
28
|
+
memoryManager: MemoryManager
|
|
29
|
+
): Promise<StoreAction> {
|
|
30
|
+
try {
|
|
31
|
+
const results = await memoryManager.searchRaw(knowledge.content, {
|
|
32
|
+
project: knowledge.project,
|
|
33
|
+
limit: 3,
|
|
34
|
+
minSimilarity: this.mergeThreshold,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
if (!results || results.length === 0) {
|
|
38
|
+
return { action: 'store_new' }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const topResult = results[0]
|
|
42
|
+
const similarity = topResult.similarity ?? 0
|
|
43
|
+
|
|
44
|
+
if (similarity >= this.skipThreshold) {
|
|
45
|
+
return {
|
|
46
|
+
action: 'skip',
|
|
47
|
+
reason: `Duplicate (similarity: ${similarity.toFixed(3)})`,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (similarity >= this.mergeThreshold) {
|
|
52
|
+
const existingId = topResult.memory?.id || topResult.id
|
|
53
|
+
const existingContent = topResult.memory?.content ||
|
|
54
|
+
topResult.decision?.decision ||
|
|
55
|
+
''
|
|
56
|
+
const datestamp = new Date().toISOString().split('T')[0]
|
|
57
|
+
const mergedContent = `${existingContent}\n[Updated ${datestamp}]: ${knowledge.content}`
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
action: 'merge',
|
|
61
|
+
existingId,
|
|
62
|
+
mergedContent,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { action: 'store_new' }
|
|
67
|
+
} catch {
|
|
68
|
+
// If search fails, store as new to avoid data loss
|
|
69
|
+
return { action: 'store_new' }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/hooks/git-capture.ts
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 21: Git Commit Capture
|
|
3
|
-
* Receives commit data from the post-commit hook and sends it to brain.
|
|
4
|
-
* Called as: claude-brain git-capture <project> <branch> <message> <files> <port>
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { appendToQueue } from './queue'
|
|
8
|
-
import type { CapturedKnowledge } from './types'
|
|
9
|
-
|
|
10
|
-
export async function handleGitCapture(): Promise<void> {
|
|
11
|
-
// Parse positional args: project, branch, message, files, port
|
|
12
|
-
const [, , , rawProject, branch, message, filesStr, portStr] = process.argv
|
|
13
|
-
|
|
14
|
-
if (!rawProject || !message) {
|
|
15
|
-
process.exit(0)
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Phase 23b: Resolve project name — strip scoped package prefix, validate
|
|
20
|
-
const project = resolveProjectName(rawProject)
|
|
21
|
-
const port = parseInt(portStr || process.env.CLAUDE_BRAIN_PORT || '3000', 10)
|
|
22
|
-
const files = filesStr ? filesStr.split(',').filter(Boolean) : []
|
|
23
|
-
|
|
24
|
-
// Build captured knowledge
|
|
25
|
-
const knowledge: CapturedKnowledge = {
|
|
26
|
-
type: 'progress',
|
|
27
|
-
confidence: 0.9,
|
|
28
|
-
content: `Git commit on ${branch || 'unknown'}: ${message.trim()}${files.length > 0 ? ` (files: ${files.join(', ')})` : ''}`,
|
|
29
|
-
project: project || undefined,
|
|
30
|
-
technologies: detectTechnologies(files),
|
|
31
|
-
metadata: {
|
|
32
|
-
source: 'git-hook',
|
|
33
|
-
branch: branch || 'unknown',
|
|
34
|
-
commit_message: message.trim(),
|
|
35
|
-
files,
|
|
36
|
-
file_count: files.length,
|
|
37
|
-
},
|
|
38
|
-
source: 'hook-passive',
|
|
39
|
-
timestamp: new Date().toISOString(),
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// POST to HTTP API server
|
|
43
|
-
try {
|
|
44
|
-
const res = await fetch(`http://localhost:${port}/api/hooks/ingest`, {
|
|
45
|
-
method: 'POST',
|
|
46
|
-
headers: { 'Content-Type': 'application/json' },
|
|
47
|
-
body: JSON.stringify({
|
|
48
|
-
knowledge: [knowledge],
|
|
49
|
-
sessionId: `git-${project}-${Date.now()}`,
|
|
50
|
-
}),
|
|
51
|
-
signal: AbortSignal.timeout(3000),
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
if (!res.ok) {
|
|
55
|
-
appendToQueue([knowledge])
|
|
56
|
-
}
|
|
57
|
-
} catch {
|
|
58
|
-
// Server unreachable — queue for later
|
|
59
|
-
appendToQueue([knowledge])
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
process.exit(0)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Phase 23b: Resolve project name from raw input.
|
|
67
|
-
* Strips npm scoped prefixes (@scope/name → name) and normalizes.
|
|
68
|
-
*/
|
|
69
|
-
function resolveProjectName(raw: string): string {
|
|
70
|
-
let name = raw.trim()
|
|
71
|
-
// Strip npm scoped prefix: @scope/name → name
|
|
72
|
-
if (name.startsWith('@') && name.includes('/')) {
|
|
73
|
-
name = name.split('/').pop() || name
|
|
74
|
-
}
|
|
75
|
-
return name || raw
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Detect technologies from file extensions.
|
|
80
|
-
*/
|
|
81
|
-
function detectTechnologies(files: string[]): string[] {
|
|
82
|
-
const techMap: Record<string, string> = {
|
|
83
|
-
'.ts': 'typescript',
|
|
84
|
-
'.tsx': 'react',
|
|
85
|
-
'.js': 'javascript',
|
|
86
|
-
'.jsx': 'react',
|
|
87
|
-
'.py': 'python',
|
|
88
|
-
'.rs': 'rust',
|
|
89
|
-
'.go': 'go',
|
|
90
|
-
'.rb': 'ruby',
|
|
91
|
-
'.java': 'java',
|
|
92
|
-
'.swift': 'swift',
|
|
93
|
-
'.kt': 'kotlin',
|
|
94
|
-
'.vue': 'vue',
|
|
95
|
-
'.svelte': 'svelte',
|
|
96
|
-
'.css': 'css',
|
|
97
|
-
'.scss': 'scss',
|
|
98
|
-
'.sql': 'sql',
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const techs = new Set<string>()
|
|
102
|
-
for (const file of files) {
|
|
103
|
-
const ext = '.' + file.split('.').pop()
|
|
104
|
-
if (techMap[ext]) {
|
|
105
|
-
techs.add(techMap[ext])
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return [...techs]
|
|
109
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Phase 21: Git Commit Capture
|
|
3
|
+
* Receives commit data from the post-commit hook and sends it to brain.
|
|
4
|
+
* Called as: claude-brain git-capture <project> <branch> <message> <files> <port>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { appendToQueue } from './queue'
|
|
8
|
+
import type { CapturedKnowledge } from './types'
|
|
9
|
+
|
|
10
|
+
export async function handleGitCapture(): Promise<void> {
|
|
11
|
+
// Parse positional args: project, branch, message, files, port
|
|
12
|
+
const [, , , rawProject, branch, message, filesStr, portStr] = process.argv
|
|
13
|
+
|
|
14
|
+
if (!rawProject || !message) {
|
|
15
|
+
process.exit(0)
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Phase 23b: Resolve project name — strip scoped package prefix, validate
|
|
20
|
+
const project = resolveProjectName(rawProject)
|
|
21
|
+
const port = parseInt(portStr || process.env.CLAUDE_BRAIN_PORT || '3000', 10)
|
|
22
|
+
const files = filesStr ? filesStr.split(',').filter(Boolean) : []
|
|
23
|
+
|
|
24
|
+
// Build captured knowledge
|
|
25
|
+
const knowledge: CapturedKnowledge = {
|
|
26
|
+
type: 'progress',
|
|
27
|
+
confidence: 0.9,
|
|
28
|
+
content: `Git commit on ${branch || 'unknown'}: ${message.trim()}${files.length > 0 ? ` (files: ${files.join(', ')})` : ''}`,
|
|
29
|
+
project: project || undefined,
|
|
30
|
+
technologies: detectTechnologies(files),
|
|
31
|
+
metadata: {
|
|
32
|
+
source: 'git-hook',
|
|
33
|
+
branch: branch || 'unknown',
|
|
34
|
+
commit_message: message.trim(),
|
|
35
|
+
files,
|
|
36
|
+
file_count: files.length,
|
|
37
|
+
},
|
|
38
|
+
source: 'hook-passive',
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// POST to HTTP API server
|
|
43
|
+
try {
|
|
44
|
+
const res = await fetch(`http://localhost:${port}/api/hooks/ingest`, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
knowledge: [knowledge],
|
|
49
|
+
sessionId: `git-${project}-${Date.now()}`,
|
|
50
|
+
}),
|
|
51
|
+
signal: AbortSignal.timeout(3000),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
appendToQueue([knowledge])
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// Server unreachable — queue for later
|
|
59
|
+
appendToQueue([knowledge])
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
process.exit(0)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Phase 23b: Resolve project name from raw input.
|
|
67
|
+
* Strips npm scoped prefixes (@scope/name → name) and normalizes.
|
|
68
|
+
*/
|
|
69
|
+
function resolveProjectName(raw: string): string {
|
|
70
|
+
let name = raw.trim()
|
|
71
|
+
// Strip npm scoped prefix: @scope/name → name
|
|
72
|
+
if (name.startsWith('@') && name.includes('/')) {
|
|
73
|
+
name = name.split('/').pop() || name
|
|
74
|
+
}
|
|
75
|
+
return name || raw
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Detect technologies from file extensions.
|
|
80
|
+
*/
|
|
81
|
+
function detectTechnologies(files: string[]): string[] {
|
|
82
|
+
const techMap: Record<string, string> = {
|
|
83
|
+
'.ts': 'typescript',
|
|
84
|
+
'.tsx': 'react',
|
|
85
|
+
'.js': 'javascript',
|
|
86
|
+
'.jsx': 'react',
|
|
87
|
+
'.py': 'python',
|
|
88
|
+
'.rs': 'rust',
|
|
89
|
+
'.go': 'go',
|
|
90
|
+
'.rb': 'ruby',
|
|
91
|
+
'.java': 'java',
|
|
92
|
+
'.swift': 'swift',
|
|
93
|
+
'.kt': 'kotlin',
|
|
94
|
+
'.vue': 'vue',
|
|
95
|
+
'.svelte': 'svelte',
|
|
96
|
+
'.css': 'css',
|
|
97
|
+
'.scss': 'scss',
|
|
98
|
+
'.sql': 'sql',
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const techs = new Set<string>()
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
const ext = '.' + file.split('.').pop()
|
|
104
|
+
if (techMap[ext]) {
|
|
105
|
+
techs.add(techMap[ext])
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return [...techs]
|
|
109
|
+
}
|