cmp-standards 2.4.0 → 2.6.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 +633 -611
- package/dist/db/drizzle-client.d.ts +3 -3
- package/dist/db/drizzle-client.d.ts.map +1 -1
- package/dist/db/drizzle-client.js +57 -58
- package/dist/db/drizzle-client.js.map +1 -1
- package/dist/db/turso-client.js +11 -11
- package/dist/eslint/rules/no-async-useeffect.js +6 -6
- package/dist/hooks/cloud-pre-tool-use.js +20 -20
- package/dist/hooks/cloud-session-start.d.ts +15 -3
- package/dist/hooks/cloud-session-start.d.ts.map +1 -1
- package/dist/hooks/cloud-session-start.js +135 -8
- package/dist/hooks/cloud-session-start.js.map +1 -1
- package/dist/hooks/session-start.d.ts +2 -1
- package/dist/hooks/session-start.d.ts.map +1 -1
- package/dist/hooks/session-start.js +99 -74
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/schema/plans.d.ts +194 -0
- package/dist/schema/plans.d.ts.map +1 -0
- package/dist/schema/plans.js +180 -0
- package/dist/schema/plans.js.map +1 -0
- package/dist/services/ContextGenerator.d.ts +16 -0
- package/dist/services/ContextGenerator.d.ts.map +1 -0
- package/dist/services/ContextGenerator.js +62 -0
- package/dist/services/ContextGenerator.js.map +1 -0
- package/dist/services/PlanManager.d.ts +99 -0
- package/dist/services/PlanManager.d.ts.map +1 -0
- package/dist/services/PlanManager.js +372 -0
- package/dist/services/PlanManager.js.map +1 -0
- package/dist/services/ProjectScaffold.js +76 -76
- package/dist/services/context-injector.d.ts +105 -0
- package/dist/services/context-injector.d.ts.map +1 -0
- package/dist/services/context-injector.js +357 -0
- package/dist/services/context-injector.js.map +1 -0
- package/dist/services/index.d.ts +15 -15
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +18 -20
- package/dist/services/index.js.map +1 -1
- package/dist/services/memory-router.d.ts +98 -0
- package/dist/services/memory-router.d.ts.map +1 -0
- package/dist/services/memory-router.js +373 -0
- package/dist/services/memory-router.js.map +1 -0
- package/dist/services/pattern-tracker.d.ts +93 -0
- package/dist/services/pattern-tracker.d.ts.map +1 -0
- package/dist/services/pattern-tracker.js +347 -0
- package/dist/services/pattern-tracker.js.map +1 -0
- package/dist/services/semantic-search.d.ts +33 -35
- package/dist/services/semantic-search.d.ts.map +1 -1
- package/dist/services/semantic-search.js +207 -165
- package/dist/services/semantic-search.js.map +1 -1
- package/package.json +100 -100
- package/standards/README.md +50 -50
- package/standards/experts/expert-routing.md +215 -215
- package/standards/general/code-quality.md +86 -86
- package/standards/general/memory-usage.md +205 -205
- package/standards/general/sync-workflow.md +235 -235
- package/standards/general/workflow.md +82 -82
- package/standards/hooks/mandatory-tracking.md +446 -446
- package/standards/infrastructure/cloud-database.md +287 -287
- package/standards/mcp/server-design.md +243 -243
- package/standards/mcp/tool-patterns.md +354 -354
- package/standards/skills/skill-structure.md +286 -286
- package/standards/skills/workflow-design.md +323 -323
- package/standards/tools/tool-design.md +297 -297
- package/templates/agents/architecture-expert.md +61 -61
- package/templates/agents/database-expert.md +62 -62
- package/templates/agents/documentation-expert.md +57 -57
- package/templates/agents/memory-expert.md +88 -88
- package/templates/agents/performance-expert.md +61 -61
- package/templates/agents/security-expert.md +59 -59
- package/templates/agents/ux-expert.md +63 -63
- package/templates/agents/worker.md +75 -75
- package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
- package/templates/claude-settings.json +72 -72
- package/templates/commands/experts.md +138 -138
- package/templates/hooks/README.md +158 -158
- package/templates/hooks/project.config.json.template +77 -77
- package/templates/hooks/settings.local.json.template +57 -57
- package/templates/memory-config.json +56 -56
- package/templates/memory-config.schema.json +212 -212
- package/templates/settings.json +58 -58
- package/templates/skills/continue.md +205 -205
- package/templates/workflows/business-improvement.md +264 -264
- package/templates/workflows/expert-review.md +153 -153
- package/templates/workflows/internal-app.md +245 -245
- package/templates/workflows/sync-docs.md +187 -187
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Memory Router Service
|
|
3
|
+
* @description Unified memory layer that routes queries across all backends
|
|
4
|
+
*
|
|
5
|
+
* Backends:
|
|
6
|
+
* - DEV_Items (Turso/SQLite) - Persistent structured storage
|
|
7
|
+
* - Upstash Vector - Semantic search with embeddings
|
|
8
|
+
* - Upstash Redis - Session cache and quick lookups
|
|
9
|
+
*/
|
|
10
|
+
import type { DevSystem, PatternContent } from '../types/index.js';
|
|
11
|
+
export interface UnifiedMemory {
|
|
12
|
+
id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
body: string;
|
|
15
|
+
domain?: string;
|
|
16
|
+
source: 'turso' | 'vector' | 'redis' | 'claude-mem';
|
|
17
|
+
score?: number;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
tags?: string[];
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
export interface SearchOptions {
|
|
23
|
+
query: string;
|
|
24
|
+
system: DevSystem;
|
|
25
|
+
domain?: string;
|
|
26
|
+
limit?: number;
|
|
27
|
+
includeArchived?: boolean;
|
|
28
|
+
minScore?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface SearchResult {
|
|
31
|
+
memories: UnifiedMemory[];
|
|
32
|
+
sources: {
|
|
33
|
+
turso: number;
|
|
34
|
+
vector: number;
|
|
35
|
+
redis: number;
|
|
36
|
+
};
|
|
37
|
+
took: number;
|
|
38
|
+
}
|
|
39
|
+
export interface WriteOptions {
|
|
40
|
+
system: DevSystem;
|
|
41
|
+
title: string;
|
|
42
|
+
body: string;
|
|
43
|
+
domain?: string;
|
|
44
|
+
tags?: string[];
|
|
45
|
+
source?: 'claude' | 'gemini' | 'user' | 'system' | 'checkpoint';
|
|
46
|
+
priority?: 'critical' | 'high' | 'medium' | 'low';
|
|
47
|
+
sessionId?: string;
|
|
48
|
+
relatedFiles?: string[];
|
|
49
|
+
}
|
|
50
|
+
declare class MemoryRouterService {
|
|
51
|
+
private initialized;
|
|
52
|
+
/**
|
|
53
|
+
* Initialize all backends
|
|
54
|
+
*/
|
|
55
|
+
init(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Unified search across all memory backends
|
|
58
|
+
*/
|
|
59
|
+
search(options: SearchOptions): Promise<SearchResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Write memory to all backends atomically
|
|
62
|
+
*/
|
|
63
|
+
write(options: WriteOptions): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Get memories by domain for context loading
|
|
66
|
+
*/
|
|
67
|
+
getByDomain(system: DevSystem, domain: string, limit?: number): Promise<UnifiedMemory[]>;
|
|
68
|
+
/**
|
|
69
|
+
* Get unresolved issues/gotchas for a domain
|
|
70
|
+
*/
|
|
71
|
+
getUnresolved(system: DevSystem, domain?: string): Promise<UnifiedMemory[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Get recent memories across all domains
|
|
74
|
+
*/
|
|
75
|
+
getRecent(system: DevSystem, limit?: number): Promise<UnifiedMemory[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Get patterns that have reached threshold
|
|
78
|
+
*/
|
|
79
|
+
getTriggeredPatterns(system: DevSystem): Promise<PatternContent[]>;
|
|
80
|
+
/**
|
|
81
|
+
* Sync claude-mem observations to DEV_Items
|
|
82
|
+
* Call this periodically or on session start
|
|
83
|
+
*/
|
|
84
|
+
syncFromClaudeMem(_system: DevSystem): Promise<number>;
|
|
85
|
+
private searchTurso;
|
|
86
|
+
private searchVector;
|
|
87
|
+
private searchRedis;
|
|
88
|
+
private writeToTurso;
|
|
89
|
+
private writeToVector;
|
|
90
|
+
private writeToRedis;
|
|
91
|
+
/**
|
|
92
|
+
* Convert a raw database row to UnifiedMemory
|
|
93
|
+
*/
|
|
94
|
+
private rowToUnifiedMemory;
|
|
95
|
+
}
|
|
96
|
+
export declare const memoryRouter: MemoryRouterService;
|
|
97
|
+
export default memoryRouter;
|
|
98
|
+
//# sourceMappingURL=memory-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-router.d.ts","sourceRoot":"","sources":["../../src/services/memory-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAiB,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAMjF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAA;IACnD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAA;IAC/D,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AAMD,cAAM,mBAAmB;IACvB,OAAO,CAAC,WAAW,CAAQ;IAE3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAyD3D;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA0CnD;;OAEG;IACG,WAAW,CACf,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,SAAI,GACR,OAAO,CAAC,aAAa,EAAE,CAAC;IAsB3B;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAiCjF;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAqBxE;;OAEG;IACG,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA+BxE;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;YAW9C,WAAW;YA+CX,YAAY;YA8BZ,WAAW;YAoBX,YAAY;YAWZ,aAAa;YAwBb,YAAY;IA+B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAsB3B;AAMD,eAAO,MAAM,YAAY,qBAA4B,CAAA;AACrD,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Memory Router Service
|
|
3
|
+
* @description Unified memory layer that routes queries across all backends
|
|
4
|
+
*
|
|
5
|
+
* Backends:
|
|
6
|
+
* - DEV_Items (Turso/SQLite) - Persistent structured storage
|
|
7
|
+
* - Upstash Vector - Semantic search with embeddings
|
|
8
|
+
* - Upstash Redis - Session cache and quick lookups
|
|
9
|
+
*/
|
|
10
|
+
import { cloud } from '../db/cloud.js';
|
|
11
|
+
import { upstash } from '../db/upstash-client.js';
|
|
12
|
+
import { turso } from '../db/turso-client.js';
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Memory Router Implementation
|
|
15
|
+
// =============================================================================
|
|
16
|
+
class MemoryRouterService {
|
|
17
|
+
initialized = false;
|
|
18
|
+
/**
|
|
19
|
+
* Initialize all backends
|
|
20
|
+
*/
|
|
21
|
+
async init() {
|
|
22
|
+
if (this.initialized)
|
|
23
|
+
return;
|
|
24
|
+
await cloud.ensure();
|
|
25
|
+
this.initialized = true;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Unified search across all memory backends
|
|
29
|
+
*/
|
|
30
|
+
async search(options) {
|
|
31
|
+
await this.init();
|
|
32
|
+
const start = Date.now();
|
|
33
|
+
const { query, system, domain, limit = 10, minScore = 0.5 } = options;
|
|
34
|
+
const results = [];
|
|
35
|
+
const sources = { turso: 0, vector: 0, redis: 0 };
|
|
36
|
+
// 1. Search Turso (keyword-based)
|
|
37
|
+
try {
|
|
38
|
+
const tursoResults = await this.searchTurso(query, system, domain, limit);
|
|
39
|
+
results.push(...tursoResults);
|
|
40
|
+
sources.turso = tursoResults.length;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error('[MemoryRouter] Turso search failed:', error);
|
|
44
|
+
}
|
|
45
|
+
// 2. Search Vector (semantic)
|
|
46
|
+
try {
|
|
47
|
+
const vectorResults = await this.searchVector(query, system, limit, minScore);
|
|
48
|
+
// Deduplicate by title
|
|
49
|
+
const existingTitles = new Set(results.map(r => r.title.toLowerCase()));
|
|
50
|
+
const newVectorResults = vectorResults.filter(r => !existingTitles.has(r.title.toLowerCase()));
|
|
51
|
+
results.push(...newVectorResults);
|
|
52
|
+
sources.vector = newVectorResults.length;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('[MemoryRouter] Vector search failed:', error);
|
|
56
|
+
}
|
|
57
|
+
// 3. Check Redis cache for recent memories
|
|
58
|
+
try {
|
|
59
|
+
const redisResults = await this.searchRedis(query, system, limit);
|
|
60
|
+
const existingIds = new Set(results.map(r => r.id));
|
|
61
|
+
const newRedisResults = redisResults.filter(r => !existingIds.has(r.id));
|
|
62
|
+
results.push(...newRedisResults);
|
|
63
|
+
sources.redis = newRedisResults.length;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('[MemoryRouter] Redis search failed:', error);
|
|
67
|
+
}
|
|
68
|
+
// Sort by score (if available) or recency
|
|
69
|
+
results.sort((a, b) => {
|
|
70
|
+
if (a.score !== undefined && b.score !== undefined) {
|
|
71
|
+
return b.score - a.score;
|
|
72
|
+
}
|
|
73
|
+
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
memories: results.slice(0, limit),
|
|
77
|
+
sources,
|
|
78
|
+
took: Date.now() - start
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Write memory to all backends atomically
|
|
83
|
+
*/
|
|
84
|
+
async write(options) {
|
|
85
|
+
await this.init();
|
|
86
|
+
const { system, title, body, domain, tags = [], source = 'system', priority = 'medium', sessionId, relatedFiles = [] } = options;
|
|
87
|
+
const id = `mem_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
88
|
+
const createdAt = new Date().toISOString();
|
|
89
|
+
const content = {
|
|
90
|
+
title,
|
|
91
|
+
body,
|
|
92
|
+
domain,
|
|
93
|
+
source,
|
|
94
|
+
sessionId,
|
|
95
|
+
relatedFiles
|
|
96
|
+
};
|
|
97
|
+
// Write to all backends in parallel
|
|
98
|
+
await Promise.all([
|
|
99
|
+
// 1. Turso (primary)
|
|
100
|
+
this.writeToTurso(id, system, content, tags, priority),
|
|
101
|
+
// 2. Vector (for semantic search)
|
|
102
|
+
this.writeToVector(id, title, body, system, domain),
|
|
103
|
+
// 3. Redis (for quick access cache)
|
|
104
|
+
this.writeToRedis(id, system, { ...content, createdAt }, tags)
|
|
105
|
+
]);
|
|
106
|
+
return id;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get memories by domain for context loading
|
|
110
|
+
*/
|
|
111
|
+
async getByDomain(system, domain, limit = 5) {
|
|
112
|
+
await this.init();
|
|
113
|
+
try {
|
|
114
|
+
const db = turso.getClient();
|
|
115
|
+
const result = await db.execute({
|
|
116
|
+
sql: `SELECT * FROM items
|
|
117
|
+
WHERE system = ? AND type = 'memory'
|
|
118
|
+
AND json_extract(content, '$.domain') = ?
|
|
119
|
+
AND status != 'archived'
|
|
120
|
+
ORDER BY updated_at DESC
|
|
121
|
+
LIMIT ?`,
|
|
122
|
+
args: [system, domain, limit]
|
|
123
|
+
});
|
|
124
|
+
return result.rows.map(row => this.rowToUnifiedMemory(row));
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.error('[MemoryRouter] getByDomain failed:', error);
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get unresolved issues/gotchas for a domain
|
|
133
|
+
*/
|
|
134
|
+
async getUnresolved(system, domain) {
|
|
135
|
+
await this.init();
|
|
136
|
+
try {
|
|
137
|
+
const db = turso.getClient();
|
|
138
|
+
let sql = `
|
|
139
|
+
SELECT * FROM items
|
|
140
|
+
WHERE system = ? AND type = 'memory'
|
|
141
|
+
AND status = 'active'
|
|
142
|
+
AND (
|
|
143
|
+
json_extract(content, '$.title') LIKE '%gotcha%'
|
|
144
|
+
OR json_extract(content, '$.title') LIKE '%bug%'
|
|
145
|
+
OR json_extract(content, '$.title') LIKE '%issue%'
|
|
146
|
+
OR json_extract(content, '$.title') LIKE '%warning%'
|
|
147
|
+
)
|
|
148
|
+
`;
|
|
149
|
+
const args = [system];
|
|
150
|
+
if (domain) {
|
|
151
|
+
sql += ` AND json_extract(content, '$.domain') = ?`;
|
|
152
|
+
args.push(domain);
|
|
153
|
+
}
|
|
154
|
+
sql += ` ORDER BY updated_at DESC LIMIT 10`;
|
|
155
|
+
const result = await db.execute({ sql, args });
|
|
156
|
+
return result.rows.map(row => this.rowToUnifiedMemory(row));
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error('[MemoryRouter] getUnresolved failed:', error);
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get recent memories across all domains
|
|
165
|
+
*/
|
|
166
|
+
async getRecent(system, limit = 10) {
|
|
167
|
+
await this.init();
|
|
168
|
+
try {
|
|
169
|
+
const db = turso.getClient();
|
|
170
|
+
const result = await db.execute({
|
|
171
|
+
sql: `SELECT * FROM items
|
|
172
|
+
WHERE system = ? AND type = 'memory'
|
|
173
|
+
AND status != 'archived'
|
|
174
|
+
ORDER BY updated_at DESC
|
|
175
|
+
LIMIT ?`,
|
|
176
|
+
args: [system, limit]
|
|
177
|
+
});
|
|
178
|
+
return result.rows.map(row => this.rowToUnifiedMemory(row));
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error('[MemoryRouter] getRecent failed:', error);
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get patterns that have reached threshold
|
|
187
|
+
*/
|
|
188
|
+
async getTriggeredPatterns(system) {
|
|
189
|
+
await this.init();
|
|
190
|
+
try {
|
|
191
|
+
const db = turso.getClient();
|
|
192
|
+
const result = await db.execute({
|
|
193
|
+
sql: `SELECT * FROM items
|
|
194
|
+
WHERE system = ? AND type = 'pattern'
|
|
195
|
+
AND status = 'triggered'
|
|
196
|
+
ORDER BY updated_at DESC`,
|
|
197
|
+
args: [system]
|
|
198
|
+
});
|
|
199
|
+
return result.rows
|
|
200
|
+
.map(row => {
|
|
201
|
+
try {
|
|
202
|
+
const content = typeof row.content === 'string'
|
|
203
|
+
? JSON.parse(row.content)
|
|
204
|
+
: row.content;
|
|
205
|
+
return content;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
.filter((p) => p !== null);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
console.error('[MemoryRouter] getTriggeredPatterns failed:', error);
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Sync claude-mem observations to DEV_Items
|
|
220
|
+
* Call this periodically or on session start
|
|
221
|
+
*/
|
|
222
|
+
async syncFromClaudeMem(_system) {
|
|
223
|
+
// This would integrate with claude-mem MCP
|
|
224
|
+
// For now, return 0 as placeholder
|
|
225
|
+
// TODO: Implement claude-mem integration
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
// =============================================================================
|
|
229
|
+
// Private Backend Methods
|
|
230
|
+
// =============================================================================
|
|
231
|
+
async searchTurso(query, system, domain, limit) {
|
|
232
|
+
const searchTerms = query.toLowerCase().split(' ').filter(t => t.length > 2);
|
|
233
|
+
if (searchTerms.length === 0) {
|
|
234
|
+
return this.getRecent(system, limit);
|
|
235
|
+
}
|
|
236
|
+
// Build LIKE conditions for each term
|
|
237
|
+
const likeConditions = searchTerms.map(() => `(LOWER(json_extract(content, '$.title')) LIKE ? OR LOWER(json_extract(content, '$.body')) LIKE ?)`).join(' AND ');
|
|
238
|
+
const args = [system];
|
|
239
|
+
for (const term of searchTerms) {
|
|
240
|
+
args.push(`%${term}%`, `%${term}%`);
|
|
241
|
+
}
|
|
242
|
+
let sql = `
|
|
243
|
+
SELECT * FROM items
|
|
244
|
+
WHERE system = ? AND type = 'memory'
|
|
245
|
+
AND status != 'archived'
|
|
246
|
+
AND (${likeConditions})
|
|
247
|
+
`;
|
|
248
|
+
if (domain) {
|
|
249
|
+
sql += ` AND json_extract(content, '$.domain') = ?`;
|
|
250
|
+
args.push(domain);
|
|
251
|
+
}
|
|
252
|
+
sql += ` ORDER BY updated_at DESC LIMIT ?`;
|
|
253
|
+
args.push(limit);
|
|
254
|
+
try {
|
|
255
|
+
const db = turso.getClient();
|
|
256
|
+
const result = await db.execute({ sql, args });
|
|
257
|
+
return result.rows.map(row => this.rowToUnifiedMemory(row));
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
console.error('[MemoryRouter] searchTurso failed:', error);
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async searchVector(query, system, limit, minScore) {
|
|
265
|
+
try {
|
|
266
|
+
const results = await upstash.searchVectors(query, {
|
|
267
|
+
topK: limit,
|
|
268
|
+
filter: `system = "${system}"`,
|
|
269
|
+
includeMetadata: true
|
|
270
|
+
});
|
|
271
|
+
return results
|
|
272
|
+
.filter(r => r.score >= minScore)
|
|
273
|
+
.map(r => ({
|
|
274
|
+
id: r.id,
|
|
275
|
+
title: r.metadata?.title || 'Untitled',
|
|
276
|
+
body: r.metadata?.body || '',
|
|
277
|
+
domain: r.metadata?.domain,
|
|
278
|
+
source: 'vector',
|
|
279
|
+
score: r.score,
|
|
280
|
+
createdAt: r.metadata?.createdAt || new Date().toISOString(),
|
|
281
|
+
tags: r.metadata?.tags
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async searchRedis(_query, system, limit) {
|
|
289
|
+
try {
|
|
290
|
+
// Get recent memories from Redis cache
|
|
291
|
+
const cacheKey = `recent_memories:${system}`;
|
|
292
|
+
const cached = await upstash.getCache(cacheKey);
|
|
293
|
+
if (cached) {
|
|
294
|
+
return cached.slice(0, limit);
|
|
295
|
+
}
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async writeToTurso(id, system, content, _tags, _priority) {
|
|
303
|
+
// Use the turso.create method which handles the insert properly
|
|
304
|
+
await turso.create('memory', system, content, 'active');
|
|
305
|
+
}
|
|
306
|
+
async writeToVector(id, title, body, system, domain) {
|
|
307
|
+
try {
|
|
308
|
+
await upstash.upsertVector(id, `${title}\n\n${body}`, {
|
|
309
|
+
title,
|
|
310
|
+
body: body.slice(0, 500), // Limit body size in metadata
|
|
311
|
+
system,
|
|
312
|
+
domain,
|
|
313
|
+
createdAt: new Date().toISOString()
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.error('[MemoryRouter] Vector write failed:', error);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async writeToRedis(id, system, content, tags) {
|
|
321
|
+
try {
|
|
322
|
+
// Cache individual memory
|
|
323
|
+
await upstash.setCache(`memory:${id}`, { ...content, tags }, 3600 * 24); // 24h TTL
|
|
324
|
+
// Update recent memories list
|
|
325
|
+
const recentKey = `recent_memories:${system}`;
|
|
326
|
+
const existing = await upstash.getCache(recentKey) || [];
|
|
327
|
+
const newMemory = {
|
|
328
|
+
id,
|
|
329
|
+
title: content.title,
|
|
330
|
+
body: content.body,
|
|
331
|
+
domain: content.domain,
|
|
332
|
+
source: 'redis',
|
|
333
|
+
createdAt: content.createdAt,
|
|
334
|
+
tags
|
|
335
|
+
};
|
|
336
|
+
const updated = [newMemory, ...existing].slice(0, 20); // Keep last 20
|
|
337
|
+
await upstash.setCache(recentKey, updated, 3600); // 1h TTL
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
console.error('[MemoryRouter] Redis write failed:', error);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Convert a raw database row to UnifiedMemory
|
|
345
|
+
*/
|
|
346
|
+
rowToUnifiedMemory(row) {
|
|
347
|
+
let content;
|
|
348
|
+
try {
|
|
349
|
+
content = typeof row.content === 'string'
|
|
350
|
+
? JSON.parse(row.content)
|
|
351
|
+
: row.content || { title: 'Untitled', body: '' };
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
content = { title: 'Untitled', body: '' };
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
id: row.id || '',
|
|
358
|
+
title: content.title || 'Untitled',
|
|
359
|
+
body: content.body || '',
|
|
360
|
+
domain: content.domain,
|
|
361
|
+
source: 'turso',
|
|
362
|
+
createdAt: row.created_at || row.updated_at || new Date().toISOString(),
|
|
363
|
+
tags: undefined,
|
|
364
|
+
metadata: content
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// =============================================================================
|
|
369
|
+
// Export Singleton
|
|
370
|
+
// =============================================================================
|
|
371
|
+
export const memoryRouter = new MemoryRouterService();
|
|
372
|
+
export default memoryRouter;
|
|
373
|
+
//# sourceMappingURL=memory-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-router.js","sourceRoot":"","sources":["../../src/services/memory-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Pattern Tracker Service
|
|
3
|
+
* @description Tracks code patterns and triggers auto-improvement when threshold is reached
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Track pattern occurrences across sessions
|
|
7
|
+
* - Detect when patterns reach threshold (default: 3)
|
|
8
|
+
* - Generate ESLint rules automatically
|
|
9
|
+
* - Create memory entries for gotchas
|
|
10
|
+
*/
|
|
11
|
+
import type { DevSystem } from '../types/index.js';
|
|
12
|
+
export interface PatternContext {
|
|
13
|
+
file: string;
|
|
14
|
+
line?: number;
|
|
15
|
+
code?: string;
|
|
16
|
+
sessionId?: string;
|
|
17
|
+
description: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TrackedPattern {
|
|
20
|
+
id: string;
|
|
21
|
+
patternId: string;
|
|
22
|
+
description: string;
|
|
23
|
+
count: number;
|
|
24
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
25
|
+
contexts: PatternContext[];
|
|
26
|
+
firstSeen: string;
|
|
27
|
+
lastSeen: string;
|
|
28
|
+
autoImproveTriggered: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface ESLintRuleSpec {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
meta: {
|
|
34
|
+
type: 'problem' | 'suggestion' | 'layout';
|
|
35
|
+
docs: {
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
fixable?: 'code' | 'whitespace';
|
|
39
|
+
messages: Record<string, string>;
|
|
40
|
+
};
|
|
41
|
+
pattern: RegExp | string;
|
|
42
|
+
fix?: string;
|
|
43
|
+
}
|
|
44
|
+
declare class PatternTrackerService {
|
|
45
|
+
private violationThreshold;
|
|
46
|
+
/**
|
|
47
|
+
* Track a pattern occurrence
|
|
48
|
+
*/
|
|
49
|
+
track(patternId: string, context: PatternContext, system: DevSystem): Promise<{
|
|
50
|
+
count: number;
|
|
51
|
+
triggered: boolean;
|
|
52
|
+
rule?: ESLintRuleSpec;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Check current count for a pattern
|
|
56
|
+
*/
|
|
57
|
+
getCount(patternId: string, system: DevSystem): Promise<number>;
|
|
58
|
+
/**
|
|
59
|
+
* Get all patterns near threshold
|
|
60
|
+
*/
|
|
61
|
+
getPendingPatterns(system: DevSystem): Promise<TrackedPattern[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Trigger auto-improvement for a pattern
|
|
64
|
+
*/
|
|
65
|
+
triggerAutoImprovement(pattern: TrackedPattern, system: DevSystem): Promise<ESLintRuleSpec | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Generate ESLint rule from pattern
|
|
68
|
+
*/
|
|
69
|
+
private generateEslintRule;
|
|
70
|
+
/**
|
|
71
|
+
* Convert ESLint rule spec to code
|
|
72
|
+
*/
|
|
73
|
+
private eslintRuleToCode;
|
|
74
|
+
/**
|
|
75
|
+
* Format gotcha memory body
|
|
76
|
+
*/
|
|
77
|
+
private formatGotchaBody;
|
|
78
|
+
/**
|
|
79
|
+
* Convert pattern ID to regex
|
|
80
|
+
*/
|
|
81
|
+
private patternToRegex;
|
|
82
|
+
/**
|
|
83
|
+
* Detect domain from contexts
|
|
84
|
+
*/
|
|
85
|
+
private detectDomain;
|
|
86
|
+
private findPattern;
|
|
87
|
+
private createPattern;
|
|
88
|
+
private savePattern;
|
|
89
|
+
private saveAutoImprovement;
|
|
90
|
+
}
|
|
91
|
+
export declare const patternTracker: PatternTrackerService;
|
|
92
|
+
export default patternTracker;
|
|
93
|
+
//# sourceMappingURL=pattern-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-tracker.d.ts","sourceRoot":"","sources":["../../src/services/pattern-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,SAAS,EAA0C,MAAM,mBAAmB,CAAA;AAM1F,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;IAChD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,OAAO,CAAA;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAA;QACzC,IAAI,EAAE;YAAE,WAAW,EAAE,MAAM,CAAA;SAAE,CAAA;QAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;QAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACjC,CAAA;IACD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAyDD,cAAM,qBAAqB;IACzB,OAAO,CAAC,kBAAkB,CAAI;IAE9B;;OAEG;IACG,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,cAAc,CAAA;KACtB,CAAC;IA0CF;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAKrE;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA8BtE;;OAEG;IACG,sBAAsB,CAC1B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IA+CtC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA8BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,YAAY;YAkBN,WAAW;YA0BX,aAAa;YAab,WAAW;YAYX,mBAAmB;CAalC;AAMD,eAAO,MAAM,cAAc,uBAA8B,CAAA;AACzD,eAAe,cAAc,CAAA"}
|