pi-recollect 0.1.1 → 0.3.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.
Files changed (166) hide show
  1. package/README.md +73 -0
  2. package/dist/categories/memory-categories.d.ts +33 -0
  3. package/dist/categories/memory-categories.d.ts.map +1 -0
  4. package/dist/categories/memory-categories.js +61 -0
  5. package/dist/categories/memory-categories.js.map +1 -0
  6. package/dist/compound/analyzer.d.ts +15 -0
  7. package/dist/compound/analyzer.d.ts.map +1 -0
  8. package/dist/compound/analyzer.js +145 -0
  9. package/dist/compound/analyzer.js.map +1 -0
  10. package/dist/compound/dedup.d.ts +34 -0
  11. package/dist/compound/dedup.d.ts.map +1 -0
  12. package/dist/compound/dedup.js +80 -0
  13. package/dist/compound/dedup.js.map +1 -0
  14. package/dist/compound/extractor.d.ts +47 -0
  15. package/dist/compound/extractor.d.ts.map +1 -0
  16. package/dist/compound/extractor.js +82 -0
  17. package/dist/compound/extractor.js.map +1 -0
  18. package/dist/compound/router.d.ts +17 -0
  19. package/dist/compound/router.d.ts.map +1 -0
  20. package/dist/compound/router.js +64 -0
  21. package/dist/compound/router.js.map +1 -0
  22. package/dist/compound/writer.d.ts +21 -0
  23. package/dist/compound/writer.d.ts.map +1 -0
  24. package/dist/compound/writer.js +101 -0
  25. package/dist/compound/writer.js.map +1 -0
  26. package/dist/config.d.ts +37 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/config.js +66 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/context/context-saver.d.ts +96 -0
  31. package/dist/context/context-saver.d.ts.map +1 -0
  32. package/dist/context/context-saver.js +234 -0
  33. package/dist/context/context-saver.js.map +1 -0
  34. package/dist/continuity/compaction-hook.d.ts +12 -0
  35. package/dist/continuity/compaction-hook.d.ts.map +1 -0
  36. package/dist/continuity/compaction-hook.js +19 -0
  37. package/dist/continuity/compaction-hook.js.map +1 -0
  38. package/dist/continuity/resumer.d.ts +21 -0
  39. package/dist/continuity/resumer.d.ts.map +1 -0
  40. package/dist/continuity/resumer.js +91 -0
  41. package/dist/continuity/resumer.js.map +1 -0
  42. package/dist/continuity/tracker.d.ts +13 -0
  43. package/dist/continuity/tracker.d.ts.map +1 -0
  44. package/dist/continuity/tracker.js +24 -0
  45. package/dist/continuity/tracker.js.map +1 -0
  46. package/dist/extension/register.d.ts +3 -0
  47. package/dist/extension/register.d.ts.map +1 -0
  48. package/dist/extension/register.js +269 -0
  49. package/dist/extension/register.js.map +1 -0
  50. package/dist/graph/decay.d.ts +52 -0
  51. package/dist/graph/decay.d.ts.map +1 -0
  52. package/dist/graph/decay.js +99 -0
  53. package/dist/graph/decay.js.map +1 -0
  54. package/dist/graph/graph-store.d.ts +47 -0
  55. package/dist/graph/graph-store.d.ts.map +1 -0
  56. package/dist/graph/graph-store.js +107 -0
  57. package/dist/graph/graph-store.js.map +1 -0
  58. package/dist/graph/hash-id.d.ts +31 -0
  59. package/dist/graph/hash-id.d.ts.map +1 -0
  60. package/dist/graph/hash-id.js +51 -0
  61. package/dist/graph/hash-id.js.map +1 -0
  62. package/dist/graph/index.d.ts +8 -0
  63. package/dist/graph/index.d.ts.map +1 -0
  64. package/dist/graph/index.js +8 -0
  65. package/dist/graph/index.js.map +1 -0
  66. package/dist/graph/memory-store.d.ts +55 -0
  67. package/dist/graph/memory-store.d.ts.map +1 -0
  68. package/dist/graph/memory-store.js +213 -0
  69. package/dist/graph/memory-store.js.map +1 -0
  70. package/{index.ts → dist/index.d.ts} +2 -5
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +5 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/memory/hierarchical.d.ts +19 -0
  75. package/dist/memory/hierarchical.d.ts.map +1 -0
  76. package/dist/memory/hierarchical.js +103 -0
  77. package/dist/memory/hierarchical.js.map +1 -0
  78. package/dist/memory/mental-models.d.ts +32 -0
  79. package/dist/memory/mental-models.d.ts.map +1 -0
  80. package/dist/memory/mental-models.js +100 -0
  81. package/dist/memory/mental-models.js.map +1 -0
  82. package/dist/memory/recall.d.ts +19 -0
  83. package/dist/memory/recall.d.ts.map +1 -0
  84. package/dist/memory/recall.js +88 -0
  85. package/dist/memory/recall.js.map +1 -0
  86. package/dist/memory/reflect.d.ts +10 -0
  87. package/dist/memory/reflect.d.ts.map +1 -0
  88. package/dist/memory/reflect.js +21 -0
  89. package/dist/memory/reflect.js.map +1 -0
  90. package/dist/memory/retain.d.ts +23 -0
  91. package/dist/memory/retain.d.ts.map +1 -0
  92. package/dist/memory/retain.js +61 -0
  93. package/dist/memory/retain.js.map +1 -0
  94. package/dist/store/events.d.ts +29 -0
  95. package/dist/store/events.d.ts.map +1 -0
  96. package/dist/store/events.js +33 -0
  97. package/dist/store/events.js.map +1 -0
  98. package/dist/store/fts5-index.d.ts +10 -0
  99. package/dist/store/fts5-index.d.ts.map +1 -0
  100. package/dist/store/fts5-index.js +19 -0
  101. package/dist/store/fts5-index.js.map +1 -0
  102. package/dist/store/schema.d.ts +7 -0
  103. package/dist/store/schema.d.ts.map +1 -0
  104. package/{src/store/schema.ts → dist/store/schema.js} +32 -41
  105. package/dist/store/schema.js.map +1 -0
  106. package/dist/store/search.d.ts +21 -0
  107. package/dist/store/search.d.ts.map +1 -0
  108. package/dist/store/search.js +160 -0
  109. package/dist/store/search.js.map +1 -0
  110. package/dist/store/sqlite.d.ts +20 -0
  111. package/dist/store/sqlite.d.ts.map +1 -0
  112. package/dist/store/sqlite.js +50 -0
  113. package/dist/store/sqlite.js.map +1 -0
  114. package/dist/store/vocabulary.d.ts +15 -0
  115. package/dist/store/vocabulary.d.ts.map +1 -0
  116. package/dist/store/vocabulary.js +26 -0
  117. package/dist/store/vocabulary.js.map +1 -0
  118. package/dist/tools/memory-recall.d.ts +10 -0
  119. package/dist/tools/memory-recall.d.ts.map +1 -0
  120. package/dist/tools/memory-recall.js +11 -0
  121. package/dist/tools/memory-recall.js.map +1 -0
  122. package/dist/tools/memory-search.d.ts +21 -0
  123. package/dist/tools/memory-search.d.ts.map +1 -0
  124. package/dist/tools/memory-search.js +33 -0
  125. package/dist/tools/memory-search.js.map +1 -0
  126. package/dist/tools/memory-status.d.ts +18 -0
  127. package/dist/tools/memory-status.d.ts.map +1 -0
  128. package/dist/tools/memory-status.js +84 -0
  129. package/dist/tools/memory-status.js.map +1 -0
  130. package/dist/tools/memory-store.d.ts +16 -0
  131. package/dist/tools/memory-store.d.ts.map +1 -0
  132. package/dist/tools/memory-store.js +17 -0
  133. package/dist/tools/memory-store.js.map +1 -0
  134. package/dist/trace/correlation.d.ts +111 -0
  135. package/dist/trace/correlation.d.ts.map +1 -0
  136. package/dist/trace/correlation.js +234 -0
  137. package/dist/trace/correlation.js.map +1 -0
  138. package/package.json +26 -39
  139. package/skills/compound-note/skill.md +0 -32
  140. package/skills/memory-search/skill.md +0 -24
  141. package/skills/memory-store/skill.md +0 -26
  142. package/src/compound/analyzer.ts +0 -170
  143. package/src/compound/dedup.ts +0 -111
  144. package/src/compound/extractor.ts +0 -110
  145. package/src/compound/router.ts +0 -82
  146. package/src/compound/writer.ts +0 -110
  147. package/src/config.ts +0 -114
  148. package/src/continuity/compaction-hook.ts +0 -32
  149. package/src/continuity/resumer.ts +0 -104
  150. package/src/continuity/tracker.ts +0 -36
  151. package/src/extension/register.ts +0 -279
  152. package/src/memory/hierarchical.ts +0 -122
  153. package/src/memory/mental-models.ts +0 -141
  154. package/src/memory/recall.ts +0 -110
  155. package/src/memory/reflect.ts +0 -32
  156. package/src/memory/retain.ts +0 -77
  157. package/src/store/events.ts +0 -61
  158. package/src/store/fts5-index.ts +0 -32
  159. package/src/store/search.ts +0 -222
  160. package/src/store/sqlite.ts +0 -53
  161. package/src/store/vocabulary.ts +0 -34
  162. package/src/tools/memory-recall.ts +0 -17
  163. package/src/tools/memory-search.ts +0 -56
  164. package/src/tools/memory-status.ts +0 -113
  165. package/src/tools/memory-store.ts +0 -30
  166. package/tsconfig.json +0 -19
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # pi-recollect
2
+
3
+ Memory and context management extension for coding agents.
4
+
5
+ ## Features
6
+
7
+ - **Graph Memory** - Hash-based ID memory with dependencies
8
+ - **Context Compaction** - Session compaction for long conversations
9
+ - **Memory Decay** - Semantic summarization of old content
10
+ - **Progressive Disclosure** - Layered context presentation
11
+ - **Session Continuity** - Seamless session recovery
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install pi-recollect
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Commands
22
+
23
+ - `/remember [insight]` - Store insight in graph memory
24
+ - `/recall [topic]` - Recall related memories
25
+ - `/compact` - Compact session context
26
+ - `/forget [id]` - Remove from memory
27
+
28
+ ### Graph Store
29
+
30
+ ```typescript
31
+ import { createGraphStore, generateHashId } from 'pi-recollect';
32
+
33
+ const store = createGraphStore();
34
+
35
+ // Add memory node
36
+ const node = store.addNode({
37
+ type: 'insight',
38
+ title: 'Important finding',
39
+ content: '...',
40
+ relations: [{ type: 'relates_to', targetId: otherNode.id }],
41
+ });
42
+
43
+ // Query memories
44
+ const insights = store.query({ type: 'insight', closed: false });
45
+ ```
46
+
47
+ ## Architecture
48
+
49
+ ```
50
+ src/
51
+ ├── graph/
52
+ │ ├── graph-store.ts # Graph memory
53
+ │ ├── hash-id.ts # Hash-based IDs
54
+ │ ├── memory-store.ts # Memory persistence
55
+ │ └── decay.ts # Memory decay
56
+ ├── context/
57
+ │ └── context-saver.ts # Context management
58
+ ├── session/
59
+ │ └── session-continuity.ts
60
+ └── index.ts
61
+ ```
62
+
63
+ ## Patterns Applied
64
+
65
+ - Hash-based IDs from beads
66
+ - Graph memory from beads
67
+ - Memory categories from pi-hermes-memory
68
+ - Context compaction from oh-my-pi
69
+ - Memory decay from beads
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Memory Categories - Pattern from pi-hermes-memory
3
+ *
4
+ * Standardized memory types for organizing persistent knowledge.
5
+ */
6
+ export type MemoryCategory = 'observation' | 'summary' | 'decision' | 'pattern' | 'task' | 'failure' | 'correction' | 'insight' | 'preference' | 'convention' | 'tool-quirk';
7
+ export interface CategorizedMemory {
8
+ category: MemoryCategory;
9
+ content: string;
10
+ failureReason?: string;
11
+ toolState?: string;
12
+ correctedTo?: string;
13
+ created: string;
14
+ lastReferenced: string;
15
+ }
16
+ export declare const MEMORY_CATEGORY_DESCRIPTIONS: Record<MemoryCategory, string>;
17
+ export declare const CATEGORY_COLORS: Record<MemoryCategory, string>;
18
+ /**
19
+ * Format memory content with category tag
20
+ */
21
+ export declare function formatMemoryContent(content: string, category: MemoryCategory, options?: {
22
+ failureReason?: string;
23
+ toolState?: string;
24
+ correctedTo?: string;
25
+ }): string;
26
+ /**
27
+ * Parse category from memory text
28
+ */
29
+ export declare function parseCategory(text: string): {
30
+ category: MemoryCategory | null;
31
+ content: string;
32
+ };
33
+ //# sourceMappingURL=memory-categories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-categories.d.ts","sourceRoot":"","sources":["../../src/categories/memory-categories.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,SAAS,GACT,UAAU,GACV,SAAS,GACT,MAAM,GACN,SAAS,GACT,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAYvE,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAY1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACA,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAShG"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Memory Categories - Pattern from pi-hermes-memory
3
+ *
4
+ * Standardized memory types for organizing persistent knowledge.
5
+ */
6
+ export const MEMORY_CATEGORY_DESCRIPTIONS = {
7
+ observation: 'General observations and facts',
8
+ summary: 'Summarized information',
9
+ decision: 'Decisions made during work',
10
+ pattern: 'Recurring patterns identified',
11
+ task: 'Task-related memories',
12
+ failure: 'What was tried but did not work',
13
+ correction: 'User corrections to agent behavior',
14
+ insight: 'Learning from experience',
15
+ preference: 'User preferences and style',
16
+ convention: 'Project conventions and standards',
17
+ 'tool-quirk': 'Tool-specific behavior and quirks',
18
+ };
19
+ export const CATEGORY_COLORS = {
20
+ observation: '🔵',
21
+ summary: '📝',
22
+ decision: '✅',
23
+ pattern: '🔄',
24
+ task: '📋',
25
+ failure: '❌',
26
+ correction: '🔧',
27
+ insight: '💡',
28
+ preference: '❤️',
29
+ convention: '📐',
30
+ 'tool-quirk': '🔧',
31
+ };
32
+ /**
33
+ * Format memory content with category tag
34
+ */
35
+ export function formatMemoryContent(content, category, options) {
36
+ const parts = [`[${category}] ${content.trim()}`];
37
+ if (options?.failureReason) {
38
+ parts.push(`Failed: ${options.failureReason}`);
39
+ }
40
+ if (options?.toolState) {
41
+ parts.push(`Tool state: ${options.toolState}`);
42
+ }
43
+ if (options?.correctedTo) {
44
+ parts.push(`Corrected to: ${options.correctedTo}`);
45
+ }
46
+ return parts.join(' — ');
47
+ }
48
+ /**
49
+ * Parse category from memory text
50
+ */
51
+ export function parseCategory(text) {
52
+ const match = text.match(/^\[([^\]]+)\]\s+(.*)$/);
53
+ if (match) {
54
+ const category = match[1];
55
+ if (MEMORY_CATEGORY_DESCRIPTIONS[category]) {
56
+ return { category, content: match[2] };
57
+ }
58
+ }
59
+ return { category: null, content: text };
60
+ }
61
+ //# sourceMappingURL=memory-categories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-categories.js","sourceRoot":"","sources":["../../src/categories/memory-categories.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH,MAAM,CAAC,MAAM,4BAA4B,GAAmC;IAC1E,WAAW,EAAE,gCAAgC;IAC7C,OAAO,EAAE,wBAAwB;IACjC,QAAQ,EAAE,4BAA4B;IACtC,OAAO,EAAE,+BAA+B;IACxC,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,iCAAiC;IAC1C,UAAU,EAAE,oCAAoC;IAChD,OAAO,EAAE,0BAA0B;IACnC,UAAU,EAAE,4BAA4B;IACxC,UAAU,EAAE,mCAAmC;IAC/C,YAAY,EAAE,mCAAmC;CAClD,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAmC;IAC7D,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,GAAG;IACZ,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,QAAwB,EACxB,OAIC;IAED,MAAM,KAAK,GAAa,CAAC,IAAI,QAAQ,KAAK,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAE5D,IAAI,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,eAAe,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAmB,CAAC;QAC5C,IAAI,4BAA4B,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type Database from "better-sqlite3";
2
+ export interface AnalysisResult {
3
+ solutionsFound: number;
4
+ solutionsWritten: number;
5
+ duplicatesMerged: number;
6
+ }
7
+ /**
8
+ * Analyze a session at shutdown time:
9
+ * 1. Extract findings from session events
10
+ * 2. Route findings to bug/knowledge/decision types
11
+ * 3. Dedup against existing solutions
12
+ * 4. Write new solutions
13
+ */
14
+ export declare function analyzeSession(db: Database.Database, cwd: string, sessionId: string, dedupThreshold?: number): AnalysisResult;
15
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/compound/analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAQ3C,MAAM,WAAW,cAAc;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,MAAY,GAC1B,cAAc,CAoDhB"}
@@ -0,0 +1,145 @@
1
+ import * as crypto from "node:crypto";
2
+ import { getSessionEvents } from "../store/events.ts";
3
+ import { routeSessionFindings } from "./router.ts";
4
+ import { extractBugSolution, extractDecision, extractKnowledge } from "./extractor.ts";
5
+ import { findPotentialDuplicates, assessOverlap, shouldDedup } from "./dedup.ts";
6
+ import { writeSolution } from "./writer.ts";
7
+ import { indexContent } from "../store/fts5-index.ts";
8
+ /**
9
+ * Analyze a session at shutdown time:
10
+ * 1. Extract findings from session events
11
+ * 2. Route findings to bug/knowledge/decision types
12
+ * 3. Dedup against existing solutions
13
+ * 4. Write new solutions
14
+ */
15
+ export function analyzeSession(db, cwd, sessionId, dedupThreshold = 0.7) {
16
+ const events = getSessionEvents(db, sessionId);
17
+ if (events.length === 0)
18
+ return { solutionsFound: 0, solutionsWritten: 0, duplicatesMerged: 0 };
19
+ const findings = routeSessionFindings(events);
20
+ let solutionsFound = 0;
21
+ let solutionsWritten = 0;
22
+ let duplicatesMerged = 0;
23
+ for (const finding of findings) {
24
+ const solution = extractSolution(finding);
25
+ if (!solution)
26
+ continue;
27
+ solutionsFound++;
28
+ const title = buildTitle(finding, finding.events);
29
+ const solForDedup = {
30
+ title,
31
+ content: solutionContent(solution),
32
+ files: solution.files,
33
+ tags: solution.tags,
34
+ };
35
+ // Check for duplicates
36
+ const dupes = findPotentialDuplicates(db, title);
37
+ let isDuplicate = false;
38
+ for (const dupe of dupes) {
39
+ const dupeForCompare = {
40
+ title: dupe.title,
41
+ content: dupe.content,
42
+ files: dupe.files ? JSON.parse(dupe.files) : [],
43
+ tags: dupe.tags ? JSON.parse(dupe.tags) : [],
44
+ };
45
+ const overlap = assessOverlap(solForDedup, dupeForCompare);
46
+ if (shouldDedup(overlap, dedupThreshold)) {
47
+ isDuplicate = true;
48
+ duplicatesMerged++;
49
+ // Increment access count on the existing solution
50
+ db.prepare(`UPDATE solutions SET access_count = access_count + 1, last_accessed_at = ? WHERE title = ?`).run(new Date().toISOString(), dupe.title);
51
+ break;
52
+ }
53
+ }
54
+ if (!isDuplicate) {
55
+ writeSolutionToDb(db, title, solution);
56
+ writeSolution(cwd, solution, title);
57
+ solutionsWritten++;
58
+ }
59
+ }
60
+ return { solutionsFound, solutionsWritten, duplicatesMerged };
61
+ }
62
+ function extractSolution(finding) {
63
+ const events = finding.events;
64
+ switch (finding.type) {
65
+ case "bug": {
66
+ const error = events.find((e) => e.type === "error");
67
+ const fix = events.find((e) => e.type === "command_success") ?? null;
68
+ if (!error)
69
+ return null;
70
+ return extractBugSolution(error, fix);
71
+ }
72
+ case "decision": {
73
+ const decision = events.find((e) => e.type === "user_decision");
74
+ if (!decision)
75
+ return null;
76
+ return extractDecision(decision);
77
+ }
78
+ case "knowledge":
79
+ return extractKnowledge(events);
80
+ default:
81
+ return null;
82
+ }
83
+ }
84
+ function buildTitle(finding, events) {
85
+ switch (finding.type) {
86
+ case "bug": {
87
+ const error = events.find((e) => e.type === "error");
88
+ if (!error)
89
+ return "Unknown bug";
90
+ try {
91
+ const data = JSON.parse(error.data);
92
+ const msg = typeof data.errorMessage === "string" ? data.errorMessage : "error";
93
+ return msg.slice(0, 80);
94
+ }
95
+ catch {
96
+ return "Unknown bug";
97
+ }
98
+ }
99
+ case "decision": {
100
+ const d = events.find((e) => e.type === "user_decision");
101
+ if (!d)
102
+ return "Decision";
103
+ try {
104
+ const data = JSON.parse(d.data);
105
+ return typeof data.message_summary === "string" ? data.message_summary.slice(0, 80) : "Decision";
106
+ }
107
+ catch {
108
+ return "Decision";
109
+ }
110
+ }
111
+ case "knowledge": {
112
+ const files = events
113
+ .map((e) => { try {
114
+ return JSON.parse(e.data).file;
115
+ }
116
+ catch {
117
+ return "";
118
+ } })
119
+ .filter((f) => f.length > 0);
120
+ return files.length > 0 ? `Pattern: ${files.join(", ")}` : "Knowledge pattern";
121
+ }
122
+ default:
123
+ return "Unknown finding";
124
+ }
125
+ }
126
+ function solutionContent(solution) {
127
+ switch (solution.type) {
128
+ case "bug": return `${solution.problem}\n${solution.rootCause}\n${solution.fix}`;
129
+ case "knowledge": return `${solution.whenToUse}\n${solution.how}`;
130
+ case "decision": return `${solution.context}\n${solution.reasoning}`;
131
+ }
132
+ }
133
+ function writeSolutionToDb(db, title, solution) {
134
+ const id = crypto.randomUUID();
135
+ const now = new Date().toISOString();
136
+ const content = solutionContent(solution);
137
+ const overlapHash = crypto.createHash("sha256").update(title + content).digest("hex");
138
+ db.prepare(`
139
+ INSERT INTO solutions (id, problem_type, category, title, content, files, tags, severity, overlap_hash, created_at, updated_at)
140
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
141
+ `).run(id, solution.type, solution.type, title, content, JSON.stringify(solution.files), JSON.stringify(solution.tags), "medium", overlapHash, now, now);
142
+ // Index for search
143
+ indexContent(db, id, title, content, solution.type);
144
+ }
145
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/compound/analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type Database from "better-sqlite3";
2
+ export interface OverlapAssessment {
3
+ problemOverlap: number;
4
+ rootCauseOverlap: number;
5
+ solutionOverlap: number;
6
+ filesOverlap: number;
7
+ preventionOverlap: number;
8
+ }
9
+ export interface SolutionForDedup {
10
+ title: string;
11
+ content: string;
12
+ files: string[];
13
+ tags: string[];
14
+ }
15
+ /**
16
+ * Assess overlap between a new solution and an existing solution.
17
+ * Uses token-based text similarity + file set intersection.
18
+ */
19
+ export declare function assessOverlap(newSol: SolutionForDedup, existingSol: SolutionForDedup): OverlapAssessment;
20
+ /**
21
+ * Determine if two solutions are duplicates using weighted 5-dimension check.
22
+ */
23
+ export declare function shouldDedup(overlap: OverlapAssessment, threshold?: number): boolean;
24
+ /**
25
+ * Find potential duplicates in the database using FTS5 search.
26
+ */
27
+ export declare function findPotentialDuplicates(db: Database.Database, title: string): Array<{
28
+ id: string;
29
+ title: string;
30
+ content: string;
31
+ files: string;
32
+ tags: string;
33
+ }>;
34
+ //# sourceMappingURL=dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../../src/compound/dedup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAK3C,MAAM,WAAW,iBAAiB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAsCD;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,gBAAgB,GAC3B,iBAAiB,CAcnB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,GAAE,MAAY,GAAG,OAAO,CAQxF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,GACX,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAYpF"}
@@ -0,0 +1,80 @@
1
+ import { porterSearch } from "../store/search.ts";
2
+ // ── Overlap assessment ─────────────────────────────────────────────────────────
3
+ /**
4
+ * Compute text similarity between two strings using simple token overlap.
5
+ */
6
+ function textSimilarity(a, b) {
7
+ const tokenize = (s) => new Set(s.toLowerCase().split(/\s+/).filter((t) => t.length > 2));
8
+ const setA = tokenize(a);
9
+ const setB = tokenize(b);
10
+ if (setA.size === 0 && setB.size === 0)
11
+ return 1;
12
+ if (setA.size === 0 || setB.size === 0)
13
+ return 0;
14
+ let intersection = 0;
15
+ for (const token of setA) {
16
+ if (setB.has(token))
17
+ intersection++;
18
+ }
19
+ const union = setA.size + setB.size - intersection;
20
+ return union > 0 ? intersection / union : 0;
21
+ }
22
+ /**
23
+ * Compute file set overlap (Jaccard similarity).
24
+ */
25
+ function fileOverlap(filesA, filesB) {
26
+ if (filesA.length === 0 && filesB.length === 0)
27
+ return 0;
28
+ if (filesA.length === 0 || filesB.length === 0)
29
+ return 0;
30
+ const setA = new Set(filesA);
31
+ const setB = new Set(filesB);
32
+ let intersection = 0;
33
+ for (const f of setA) {
34
+ if (setB.has(f))
35
+ intersection++;
36
+ }
37
+ const union = setA.size + setB.size - intersection;
38
+ return union > 0 ? intersection / union : 0;
39
+ }
40
+ /**
41
+ * Assess overlap between a new solution and an existing solution.
42
+ * Uses token-based text similarity + file set intersection.
43
+ */
44
+ export function assessOverlap(newSol, existingSol) {
45
+ return {
46
+ problemOverlap: textSimilarity(newSol.title, existingSol.title),
47
+ rootCauseOverlap: textSimilarity(newSol.content.slice(0, 500), existingSol.content.slice(0, 500)),
48
+ solutionOverlap: textSimilarity(newSol.content, existingSol.content),
49
+ filesOverlap: fileOverlap(newSol.files, existingSol.files),
50
+ preventionOverlap: textSimilarity(newSol.tags.join(" "), existingSol.tags.join(" ")),
51
+ };
52
+ }
53
+ /**
54
+ * Determine if two solutions are duplicates using weighted 5-dimension check.
55
+ */
56
+ export function shouldDedup(overlap, threshold = 0.7) {
57
+ const weighted = overlap.problemOverlap * 0.3 +
58
+ overlap.rootCauseOverlap * 0.3 +
59
+ overlap.solutionOverlap * 0.2 +
60
+ overlap.filesOverlap * 0.1 +
61
+ overlap.preventionOverlap * 0.1;
62
+ return weighted > threshold;
63
+ }
64
+ /**
65
+ * Find potential duplicates in the database using FTS5 search.
66
+ */
67
+ export function findPotentialDuplicates(db, title) {
68
+ try {
69
+ const results = porterSearch(db, title, 5);
70
+ const ids = results.map((r) => r.id);
71
+ if (ids.length === 0)
72
+ return [];
73
+ const placeholders = ids.map(() => "?").join(",");
74
+ return db.prepare(`SELECT id, title, content, files, tags FROM solutions WHERE id IN (${placeholders})`).all(...ids);
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ }
80
+ //# sourceMappingURL=dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.js","sourceRoot":"","sources":["../../src/compound/dedup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { SessionEvent } from "../store/events.ts";
2
+ export interface BugSolution {
3
+ type: "bug";
4
+ problem: string;
5
+ rootCause: string;
6
+ fix: string;
7
+ files: string[];
8
+ tags: string[];
9
+ }
10
+ export interface KnowledgeSolution {
11
+ type: "knowledge";
12
+ whenToUse: string;
13
+ how: string;
14
+ tradeoffs: {
15
+ pro: string[];
16
+ con: string[];
17
+ };
18
+ files: string[];
19
+ tags: string[];
20
+ }
21
+ export interface DecisionSolution {
22
+ type: "decision";
23
+ context: string;
24
+ options: Array<{
25
+ name: string;
26
+ pros: string[];
27
+ cons: string[];
28
+ }>;
29
+ choice: string;
30
+ reasoning: string;
31
+ files: string[];
32
+ tags: string[];
33
+ }
34
+ export type Solution = BugSolution | KnowledgeSolution | DecisionSolution;
35
+ /**
36
+ * Extract a bug solution from error + fix events.
37
+ */
38
+ export declare function extractBugSolution(errorEvent: SessionEvent, fixEvent: SessionEvent | null): BugSolution | null;
39
+ /**
40
+ * Extract a knowledge pattern from file edit events.
41
+ */
42
+ export declare function extractKnowledge(events: SessionEvent[]): KnowledgeSolution | null;
43
+ /**
44
+ * Extract a decision from user decision events.
45
+ */
46
+ export declare function extractDecision(event: SessionEvent): DecisionSolution | null;
47
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/compound/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAI1E;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,UAAU,EAAE,YAAY,EACxB,QAAQ,EAAE,YAAY,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CA0BpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,iBAAiB,GAAG,IAAI,CAejF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,GAAG,IAAI,CAgB5E"}
@@ -0,0 +1,82 @@
1
+ // ── Extractors ─────────────────────────────────────────────────────────────────
2
+ /**
3
+ * Extract a bug solution from error + fix events.
4
+ */
5
+ export function extractBugSolution(errorEvent, fixEvent) {
6
+ let errorData;
7
+ try {
8
+ errorData = JSON.parse(errorEvent.data);
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ const errorMessage = typeof errorData.errorMessage === "string" ? errorData.errorMessage :
14
+ typeof errorData.message === "string" ? errorData.message : "Unknown error";
15
+ const tool = typeof errorData.tool === "string" ? errorData.tool : "unknown";
16
+ let fix = "No fix recorded.";
17
+ if (fixEvent) {
18
+ try {
19
+ const fixData = JSON.parse(fixEvent.data);
20
+ const output = typeof fixData.output_summary === "string" ? fixData.output_summary :
21
+ typeof fixData.command === "string" ? `Ran: ${fixData.command}` : "";
22
+ if (output)
23
+ fix = output;
24
+ }
25
+ catch { /* use default */ }
26
+ }
27
+ return {
28
+ type: "bug",
29
+ problem: errorMessage,
30
+ rootCause: `Error from tool: ${tool}`,
31
+ fix,
32
+ files: [],
33
+ tags: [tool, "auto-extracted"],
34
+ };
35
+ }
36
+ /**
37
+ * Extract a knowledge pattern from file edit events.
38
+ */
39
+ export function extractKnowledge(events) {
40
+ if (events.length === 0)
41
+ return null;
42
+ const files = events
43
+ .map((e) => { try {
44
+ return JSON.parse(e.data).file;
45
+ }
46
+ catch {
47
+ return "";
48
+ } })
49
+ .filter((f) => f.length > 0);
50
+ return {
51
+ type: "knowledge",
52
+ whenToUse: `When working with: ${files.join(", ")}`,
53
+ how: "Pattern detected from file edit sequence.",
54
+ tradeoffs: { pro: [], con: [] },
55
+ files,
56
+ tags: ["auto-extracted"],
57
+ };
58
+ }
59
+ /**
60
+ * Extract a decision from user decision events.
61
+ */
62
+ export function extractDecision(event) {
63
+ let data;
64
+ try {
65
+ data = JSON.parse(event.data);
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ const message = typeof data.message_summary === "string" ? data.message_summary :
71
+ typeof data.message === "string" ? data.message : "Decision made";
72
+ return {
73
+ type: "decision",
74
+ context: message,
75
+ options: [],
76
+ choice: message,
77
+ reasoning: "User decision captured from session.",
78
+ files: [],
79
+ tags: ["auto-extracted", "user-decision"],
80
+ };
81
+ }
82
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/compound/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { SessionEvent } from "../store/events.ts";
2
+ export type FindingType = "bug" | "knowledge" | "decision";
3
+ export interface RoutedFinding {
4
+ type: FindingType;
5
+ confidence: number;
6
+ events: SessionEvent[];
7
+ }
8
+ /**
9
+ * Route session events to the appropriate finding type.
10
+ * Classifies as bug/knowledge/decision based on event patterns.
11
+ */
12
+ export declare function routeFinding(events: SessionEvent[]): RoutedFinding | null;
13
+ /**
14
+ * Route multiple sessions' events and return all routed findings.
15
+ */
16
+ export declare function routeSessionFindings(events: SessionEvent[]): RoutedFinding[];
17
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/compound/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,GAAG,IAAI,CA8BzE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAgC5E"}