learning-agent 0.1.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.
@@ -0,0 +1,780 @@
1
+ import { z } from 'zod';
2
+ import { LlamaEmbeddingContext } from 'node-llama-cpp';
3
+
4
+ /**
5
+ * Lesson type definitions using Zod schemas
6
+ */
7
+
8
+ declare const SourceSchema: z.ZodEnum<["user_correction", "self_correction", "test_failure", "manual"]>;
9
+ declare const ContextSchema: z.ZodObject<{
10
+ tool: z.ZodString;
11
+ intent: z.ZodString;
12
+ }, "strip", z.ZodTypeAny, {
13
+ tool: string;
14
+ intent: string;
15
+ }, {
16
+ tool: string;
17
+ intent: string;
18
+ }>;
19
+ declare const SeveritySchema: z.ZodEnum<["high", "medium", "low"]>;
20
+ declare const LessonTypeSchema: z.ZodEnum<["quick", "full"]>;
21
+ /**
22
+ * Unified Lesson schema.
23
+ *
24
+ * The `type` field is a semantic marker:
25
+ * - 'quick': Minimal lesson for fast capture
26
+ * - 'full': Important lesson (typically has evidence/severity)
27
+ *
28
+ * All fields except core identity are optional for flexibility.
29
+ * Semantic meaning is preserved through convention, not schema enforcement.
30
+ */
31
+ declare const LessonSchema: z.ZodObject<{
32
+ id: z.ZodString;
33
+ type: z.ZodEnum<["quick", "full"]>;
34
+ trigger: z.ZodString;
35
+ insight: z.ZodString;
36
+ tags: z.ZodArray<z.ZodString, "many">;
37
+ source: z.ZodEnum<["user_correction", "self_correction", "test_failure", "manual"]>;
38
+ context: z.ZodObject<{
39
+ tool: z.ZodString;
40
+ intent: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ tool: string;
43
+ intent: string;
44
+ }, {
45
+ tool: string;
46
+ intent: string;
47
+ }>;
48
+ created: z.ZodString;
49
+ confirmed: z.ZodBoolean;
50
+ supersedes: z.ZodArray<z.ZodString, "many">;
51
+ related: z.ZodArray<z.ZodString, "many">;
52
+ evidence: z.ZodOptional<z.ZodString>;
53
+ severity: z.ZodOptional<z.ZodEnum<["high", "medium", "low"]>>;
54
+ pattern: z.ZodOptional<z.ZodObject<{
55
+ bad: z.ZodString;
56
+ good: z.ZodString;
57
+ }, "strip", z.ZodTypeAny, {
58
+ bad: string;
59
+ good: string;
60
+ }, {
61
+ bad: string;
62
+ good: string;
63
+ }>>;
64
+ deleted: z.ZodOptional<z.ZodBoolean>;
65
+ retrievalCount: z.ZodOptional<z.ZodNumber>;
66
+ }, "strip", z.ZodTypeAny, {
67
+ type: "quick" | "full";
68
+ id: string;
69
+ trigger: string;
70
+ insight: string;
71
+ tags: string[];
72
+ source: "user_correction" | "self_correction" | "test_failure" | "manual";
73
+ context: {
74
+ tool: string;
75
+ intent: string;
76
+ };
77
+ created: string;
78
+ confirmed: boolean;
79
+ supersedes: string[];
80
+ related: string[];
81
+ evidence?: string | undefined;
82
+ severity?: "high" | "medium" | "low" | undefined;
83
+ pattern?: {
84
+ bad: string;
85
+ good: string;
86
+ } | undefined;
87
+ deleted?: boolean | undefined;
88
+ retrievalCount?: number | undefined;
89
+ }, {
90
+ type: "quick" | "full";
91
+ id: string;
92
+ trigger: string;
93
+ insight: string;
94
+ tags: string[];
95
+ source: "user_correction" | "self_correction" | "test_failure" | "manual";
96
+ context: {
97
+ tool: string;
98
+ intent: string;
99
+ };
100
+ created: string;
101
+ confirmed: boolean;
102
+ supersedes: string[];
103
+ related: string[];
104
+ evidence?: string | undefined;
105
+ severity?: "high" | "medium" | "low" | undefined;
106
+ pattern?: {
107
+ bad: string;
108
+ good: string;
109
+ } | undefined;
110
+ deleted?: boolean | undefined;
111
+ retrievalCount?: number | undefined;
112
+ }>;
113
+ declare const TombstoneSchema: z.ZodObject<{
114
+ id: z.ZodString;
115
+ deleted: z.ZodLiteral<true>;
116
+ deletedAt: z.ZodString;
117
+ }, "strip", z.ZodTypeAny, {
118
+ id: string;
119
+ deleted: true;
120
+ deletedAt: string;
121
+ }, {
122
+ id: string;
123
+ deleted: true;
124
+ deletedAt: string;
125
+ }>;
126
+ type Lesson = z.infer<typeof LessonSchema>;
127
+ type LessonType = z.infer<typeof LessonTypeSchema>;
128
+ type Tombstone = z.infer<typeof TombstoneSchema>;
129
+ type Source = z.infer<typeof SourceSchema>;
130
+ type Severity = z.infer<typeof SeveritySchema>;
131
+ type Context = z.infer<typeof ContextSchema>;
132
+ /**
133
+ * Generate deterministic lesson ID from insight text.
134
+ * Format: L + 8 hex characters from SHA-256 hash
135
+ */
136
+ declare function generateId(insight: string): string;
137
+
138
+ /**
139
+ * JSONL storage layer for lessons
140
+ *
141
+ * Append-only storage with last-write-wins deduplication.
142
+ * Source of truth - git trackable.
143
+ */
144
+
145
+ /** Relative path to lessons file from repo root */
146
+ declare const LESSONS_PATH = ".claude/lessons/index.jsonl";
147
+ /** Options for reading lessons */
148
+ interface ReadLessonsOptions {
149
+ /** If true, throw on first parse error. Default: false (skip errors) */
150
+ strict?: boolean;
151
+ /** Callback for each parse error in non-strict mode */
152
+ onParseError?: (error: ParseError) => void;
153
+ }
154
+ /** Parse error details */
155
+ interface ParseError {
156
+ /** 1-based line number */
157
+ line: number;
158
+ /** Error message */
159
+ message: string;
160
+ /** Original error */
161
+ cause: unknown;
162
+ }
163
+ /** Result of reading lessons */
164
+ interface ReadLessonsResult {
165
+ /** Successfully parsed lessons */
166
+ lessons: Lesson[];
167
+ /** Number of lines skipped due to errors */
168
+ skippedCount: number;
169
+ }
170
+ /**
171
+ * Append a lesson to the JSONL file.
172
+ * Creates directory structure if missing.
173
+ */
174
+ declare function appendLesson(repoRoot: string, lesson: Lesson): Promise<void>;
175
+ /**
176
+ * Read all non-deleted lessons from the JSONL file.
177
+ * Applies last-write-wins deduplication by ID.
178
+ * Returns result object with lessons and skippedCount.
179
+ *
180
+ * @param repoRoot - Repository root directory
181
+ * @param options - Optional settings for error handling
182
+ * @returns Result with lessons array and count of skipped lines
183
+ */
184
+ declare function readLessons(repoRoot: string, options?: ReadLessonsOptions): Promise<ReadLessonsResult>;
185
+
186
+ /**
187
+ * SQLite storage layer with FTS5 for full-text search
188
+ *
189
+ * Rebuildable index - not the source of truth.
190
+ * Stored in .claude/.cache (gitignored).
191
+ */
192
+
193
+ /** Relative path to database file from repo root */
194
+ declare const DB_PATH = ".claude/.cache/lessons.sqlite";
195
+ /**
196
+ * Close the database connection and release resources.
197
+ *
198
+ * **Resource lifecycle:**
199
+ * - The database is opened lazily on first call to `openDb()` or any function that uses it
200
+ * (e.g., `searchKeyword`, `rebuildIndex`, `syncIfNeeded`, `getCachedEmbedding`)
201
+ * - Once opened, the connection remains active until `closeDb()` is called
202
+ * - After closing, subsequent database operations will reopen the connection
203
+ *
204
+ * **When to call:**
205
+ * - At the end of CLI commands to ensure clean process exit
206
+ * - When transitioning between repositories in long-running processes
207
+ * - Before process exit in graceful shutdown handlers
208
+ *
209
+ * **Best practices for long-running processes:**
210
+ * - In single-operation scripts: call before exit
211
+ * - In daemon/server processes: call in shutdown handler
212
+ * - Not necessary to call between operations in the same repository
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * // CLI command pattern
217
+ * try {
218
+ * await searchKeyword(repoRoot, 'typescript', 10);
219
+ * // ... process results
220
+ * } finally {
221
+ * closeDb();
222
+ * }
223
+ *
224
+ * // Graceful shutdown pattern
225
+ * process.on('SIGTERM', () => {
226
+ * closeDb();
227
+ * process.exit(0);
228
+ * });
229
+ * ```
230
+ */
231
+ declare function closeDb(): void;
232
+ /**
233
+ * Rebuild the SQLite index from the JSONL source of truth.
234
+ * Preserves embeddings where content hash is unchanged.
235
+ * Updates the last sync mtime after successful rebuild.
236
+ */
237
+ declare function rebuildIndex(repoRoot: string): Promise<void>;
238
+ /**
239
+ * Search lessons using FTS5 keyword search.
240
+ * Returns matching lessons up to the specified limit.
241
+ * Increments retrieval count for all returned lessons.
242
+ */
243
+ declare function searchKeyword(repoRoot: string, query: string, limit: number): Promise<Lesson[]>;
244
+
245
+ /**
246
+ * Embedding model resolution using node-llama-cpp's built-in resolver.
247
+ *
248
+ * Uses resolveModelFile for automatic download and caching.
249
+ * Model is stored in ~/.node-llama-cpp/models/ by default.
250
+ */
251
+ /**
252
+ * HuggingFace URI for EmbeddingGemma-300M (Q4_0 quantization).
253
+ *
254
+ * - Size: ~278MB
255
+ * - Dimensions: 768 (default), supports MRL truncation to 512/256/128
256
+ * - Context: 2048 tokens
257
+ */
258
+ declare const MODEL_URI = "hf:ggml-org/embeddinggemma-300M-qat-q4_0-GGUF/embeddinggemma-300M-qat-Q4_0.gguf";
259
+ /**
260
+ * Expected model filename after download.
261
+ * node-llama-cpp uses format: hf_{org}_{filename}
262
+ */
263
+ declare const MODEL_FILENAME = "hf_ggml-org_embeddinggemma-300M-qat-Q4_0.gguf";
264
+ /**
265
+ * Check if the embedding model is available locally.
266
+ *
267
+ * @returns true if model file exists
268
+ */
269
+ declare function isModelAvailable(): boolean;
270
+ /**
271
+ * Resolve the embedding model path, downloading if necessary.
272
+ *
273
+ * Uses node-llama-cpp's resolveModelFile for automatic download with progress.
274
+ *
275
+ * @param options - Optional configuration
276
+ * @param options.cli - Show download progress in console (default: true)
277
+ * @returns Path to the resolved model file
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const modelPath = await resolveModel();
282
+ * const llama = await getLlama();
283
+ * const model = await llama.loadModel({ modelPath });
284
+ * ```
285
+ */
286
+ declare function resolveModel(options?: {
287
+ cli?: boolean;
288
+ }): Promise<string>;
289
+
290
+ /**
291
+ * Text embedding via node-llama-cpp with EmbeddingGemma model
292
+ *
293
+ * **Resource lifecycle:**
294
+ * - Model is loaded lazily on first embedding call (~150MB in memory)
295
+ * - Once loaded, the model remains in memory until `unloadEmbedding()` is called
296
+ * - Loading is slow (~1-3s); keeping loaded improves subsequent call performance
297
+ *
298
+ * **Memory usage:**
299
+ * - Embedding model: ~150MB RAM when loaded
300
+ * - Embeddings themselves: ~3KB per embedding (768 dimensions x 4 bytes)
301
+ *
302
+ * @see {@link unloadEmbedding} for releasing memory
303
+ * @see {@link getEmbedding} for the lazy-loading mechanism
304
+ */
305
+
306
+ /**
307
+ * Get the LlamaEmbeddingContext instance for generating embeddings.
308
+ *
309
+ * **Lazy loading behavior:**
310
+ * - First call loads the embedding model (~150MB) into memory
311
+ * - Loading takes ~1-3 seconds depending on hardware
312
+ * - Subsequent calls return the cached instance immediately
313
+ * - Downloads model automatically if not present
314
+ *
315
+ * **Resource lifecycle:**
316
+ * - Once loaded, model stays in memory until `unloadEmbedding()` is called
317
+ * - For CLI commands: typically load once, use, then unload on exit
318
+ * - For long-running processes: keep loaded for performance
319
+ *
320
+ * @returns The singleton embedding context
321
+ * @throws Error if model download fails
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * // Direct usage (prefer embedText for simple cases)
326
+ * const ctx = await getEmbedding();
327
+ * const result = await ctx.getEmbeddingFor('some text');
328
+ *
329
+ * // Ensure cleanup
330
+ * process.on('exit', () => unloadEmbedding());
331
+ * ```
332
+ *
333
+ * @see {@link embedText} for simpler text-to-vector conversion
334
+ * @see {@link unloadEmbedding} for releasing memory
335
+ */
336
+ declare function getEmbedding(): Promise<LlamaEmbeddingContext>;
337
+ /**
338
+ * Unload the embedding context to free memory (~150MB).
339
+ *
340
+ * **Resource lifecycle:**
341
+ * - Disposes the underlying LlamaEmbeddingContext
342
+ * - Releases ~150MB of RAM used by the model
343
+ * - After unloading, subsequent embedding calls will reload the model
344
+ *
345
+ * **When to call:**
346
+ * - At the end of CLI commands to ensure clean process exit
347
+ * - In memory-constrained environments after batch processing
348
+ * - Before process exit in graceful shutdown handlers
349
+ * - When switching to a different model (if supported in future)
350
+ *
351
+ * **Best practices:**
352
+ * - For single-operation scripts: call before exit
353
+ * - For daemon/server processes: call in shutdown handler
354
+ * - Not needed between embedding calls in the same process
355
+ *
356
+ * @example
357
+ * ```typescript
358
+ * // CLI command pattern
359
+ * try {
360
+ * const embedding = await embedText('some text');
361
+ * // ... use embedding
362
+ * } finally {
363
+ * unloadEmbedding();
364
+ * closeDb();
365
+ * }
366
+ *
367
+ * // Graceful shutdown pattern
368
+ * process.on('SIGTERM', () => {
369
+ * unloadEmbedding();
370
+ * closeDb();
371
+ * process.exit(0);
372
+ * });
373
+ * ```
374
+ *
375
+ * @see {@link getEmbedding} for loading the model
376
+ * @see {@link closeDb} for database cleanup (often used together)
377
+ */
378
+ declare function unloadEmbedding(): void;
379
+ /**
380
+ * Embed a single text string into a vector.
381
+ *
382
+ * **Lazy loading:** First call loads the embedding model (~150MB, ~1-3s).
383
+ * Subsequent calls use the cached model and complete in milliseconds.
384
+ *
385
+ * @param text - The text to embed
386
+ * @returns A 768-dimensional vector (number[])
387
+ * @throws Error if model download fails
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * const vector = await embedText('TypeScript error handling');
392
+ * console.log(vector.length); // 768
393
+ *
394
+ * // Remember to clean up when done
395
+ * unloadEmbedding();
396
+ * ```
397
+ *
398
+ * @see {@link embedTexts} for batch embedding
399
+ * @see {@link unloadEmbedding} for releasing memory
400
+ */
401
+ declare function embedText(text: string): Promise<number[]>;
402
+ /**
403
+ * Embed multiple texts into vectors.
404
+ *
405
+ * **Lazy loading:** First call loads the embedding model (~150MB, ~1-3s).
406
+ * Subsequent calls use the cached model.
407
+ *
408
+ * **Performance:** More efficient than calling `embedText` in a loop
409
+ * when processing multiple texts, as model loading happens only once.
410
+ *
411
+ * @param texts - Array of texts to embed
412
+ * @returns Array of 768-dimensional vectors, same order as input
413
+ * @throws Error if model download fails
414
+ *
415
+ * @example
416
+ * ```typescript
417
+ * const texts = ['first text', 'second text'];
418
+ * const vectors = await embedTexts(texts);
419
+ * console.log(vectors.length); // 2
420
+ * console.log(vectors[0].length); // 768
421
+ *
422
+ * // Remember to clean up when done
423
+ * unloadEmbedding();
424
+ * ```
425
+ *
426
+ * @see {@link embedText} for single text embedding
427
+ * @see {@link unloadEmbedding} for releasing memory
428
+ */
429
+ declare function embedTexts(texts: string[]): Promise<number[][]>;
430
+
431
+ /**
432
+ * Vector search with cosine similarity
433
+ *
434
+ * Embeds query text and ranks lessons by semantic similarity.
435
+ * Uses SQLite cache to avoid recomputing embeddings.
436
+ */
437
+
438
+ /**
439
+ * Calculate cosine similarity between two vectors.
440
+ * Returns value between -1 (opposite) and 1 (identical).
441
+ */
442
+ declare function cosineSimilarity(a: number[], b: number[]): number;
443
+ /** Lesson with similarity score */
444
+ interface ScoredLesson {
445
+ lesson: Lesson;
446
+ score: number;
447
+ }
448
+ /** Options for vector search */
449
+ interface SearchVectorOptions {
450
+ /** Maximum number of results to return (default: 10) */
451
+ limit?: number;
452
+ }
453
+ /**
454
+ * Search lessons by vector similarity to query text.
455
+ * Returns top N lessons sorted by similarity score (descending).
456
+ * Uses embedding cache to avoid recomputing embeddings.
457
+ */
458
+ declare function searchVector(repoRoot: string, query: string, options?: SearchVectorOptions): Promise<ScoredLesson[]>;
459
+
460
+ /**
461
+ * Multi-factor lesson ranking system
462
+ *
463
+ * Combines vector similarity with semantic boosts:
464
+ * - Severity: high=1.5, medium=1.0, low=0.8
465
+ * - Recency: 1.2 for lessons ≤30 days old
466
+ * - Confirmation: 1.3 for confirmed lessons
467
+ */
468
+
469
+ /** Lesson with final ranked score */
470
+ interface RankedLesson extends ScoredLesson {
471
+ finalScore?: number;
472
+ }
473
+ /**
474
+ * Calculate severity boost based on lesson severity.
475
+ * Lessons without severity get 1.0 (medium boost).
476
+ */
477
+ declare function severityBoost(lesson: Lesson): number;
478
+ /**
479
+ * Calculate recency boost based on lesson age.
480
+ * Lessons ≤30 days old get 1.2, older get 1.0.
481
+ */
482
+ declare function recencyBoost(lesson: Lesson): number;
483
+ /**
484
+ * Calculate confirmation boost.
485
+ * Confirmed lessons get 1.3, unconfirmed get 1.0.
486
+ */
487
+ declare function confirmationBoost(lesson: Lesson): number;
488
+ /**
489
+ * Calculate combined score for a lesson.
490
+ * score = vectorSimilarity * severity * recency * confirmation
491
+ */
492
+ declare function calculateScore(lesson: Lesson, vectorSimilarity: number): number;
493
+ /**
494
+ * Rank lessons by combined score.
495
+ * Returns new array sorted by finalScore descending.
496
+ */
497
+ declare function rankLessons(lessons: ScoredLesson[]): RankedLesson[];
498
+
499
+ /**
500
+ * Quality filters for lesson capture
501
+ *
502
+ * Filters to ensure lessons are:
503
+ * - Novel (not duplicate)
504
+ * - Specific (not vague)
505
+ * - Actionable (contains action words)
506
+ */
507
+ /** Result of novelty check */
508
+ interface NoveltyResult {
509
+ novel: boolean;
510
+ reason?: string;
511
+ existingId?: string;
512
+ }
513
+ /** Options for novelty check */
514
+ interface NoveltyOptions {
515
+ threshold?: number;
516
+ }
517
+ /**
518
+ * Check if an insight is novel (not a duplicate of existing lessons).
519
+ * Uses keyword search to find potentially similar lessons.
520
+ */
521
+ declare function isNovel(repoRoot: string, insight: string, options?: NoveltyOptions): Promise<NoveltyResult>;
522
+ /** Result of specificity check */
523
+ interface SpecificityResult {
524
+ specific: boolean;
525
+ reason?: string;
526
+ }
527
+ /**
528
+ * Check if an insight is specific enough to be useful.
529
+ * Rejects vague, generic advice that doesn't provide actionable guidance.
530
+ */
531
+ declare function isSpecific(insight: string): SpecificityResult;
532
+ /** Result of actionability check */
533
+ interface ActionabilityResult {
534
+ actionable: boolean;
535
+ reason?: string;
536
+ }
537
+ /**
538
+ * Check if an insight contains actionable guidance.
539
+ * Returns false for pure observations or questions.
540
+ */
541
+ declare function isActionable(insight: string): ActionabilityResult;
542
+ /** Result of combined quality check */
543
+ interface ProposeResult {
544
+ shouldPropose: boolean;
545
+ reason?: string;
546
+ }
547
+ /**
548
+ * Combined quality check for lesson proposals.
549
+ * Returns true only if insight is novel, specific, AND actionable.
550
+ */
551
+ declare function shouldPropose(repoRoot: string, insight: string): Promise<ProposeResult>;
552
+
553
+ /**
554
+ * Trigger detection for automatic lesson capture
555
+ *
556
+ * Detects patterns that indicate potential learning opportunities:
557
+ * - User corrections
558
+ * - Self-corrections
559
+ * - Test failures
560
+ */
561
+
562
+ /** Signal data for correction detection */
563
+ interface CorrectionSignal {
564
+ messages: string[];
565
+ context: Context;
566
+ }
567
+ /** Detected correction result */
568
+ interface DetectedCorrection {
569
+ trigger: string;
570
+ correctionMessage: string;
571
+ context: Context;
572
+ }
573
+ /**
574
+ * Detect user correction signals in conversation.
575
+ *
576
+ * Looks for patterns that indicate the user is correcting Claude's
577
+ * understanding or actions.
578
+ *
579
+ * @param signals - Messages and context to analyze
580
+ * @returns Detected correction or null if none found
581
+ */
582
+ declare function detectUserCorrection(signals: CorrectionSignal): DetectedCorrection | null;
583
+ /** Edit history entry */
584
+ interface EditEntry {
585
+ file: string;
586
+ success: boolean;
587
+ timestamp: number;
588
+ }
589
+ /** Edit history for self-correction detection */
590
+ interface EditHistory {
591
+ edits: EditEntry[];
592
+ }
593
+ /** Detected self-correction */
594
+ interface DetectedSelfCorrection {
595
+ file: string;
596
+ trigger: string;
597
+ }
598
+ /**
599
+ * Detect self-correction patterns in edit history.
600
+ *
601
+ * Looks for edit→fail→re-edit patterns on the same file,
602
+ * which indicate Claude had to correct its own work.
603
+ *
604
+ * @param history - Edit history to analyze
605
+ * @returns Detected self-correction or null if none found
606
+ */
607
+ declare function detectSelfCorrection(history: EditHistory): DetectedSelfCorrection | null;
608
+ /** Test result for failure detection */
609
+ interface TestResult {
610
+ passed: boolean;
611
+ output: string;
612
+ testFile: string;
613
+ }
614
+ /** Detected test failure */
615
+ interface DetectedTestFailure {
616
+ testFile: string;
617
+ errorOutput: string;
618
+ trigger: string;
619
+ }
620
+ /**
621
+ * Detect test failure patterns.
622
+ *
623
+ * When tests fail, this creates a potential learning opportunity
624
+ * if the failure is later fixed.
625
+ *
626
+ * @param testResult - Test result to analyze
627
+ * @returns Detected test failure or null if tests passed
628
+ */
629
+ declare function detectTestFailure(testResult: TestResult): DetectedTestFailure | null;
630
+
631
+ /**
632
+ * Session-start lesson retrieval
633
+ *
634
+ * Loads high-severity lessons at the start of a session.
635
+ * No vector search - just filter by severity and recency.
636
+ */
637
+
638
+ /** A full lesson with severity field present */
639
+ type FullLesson = Lesson & {
640
+ type: 'full';
641
+ severity: Severity;
642
+ };
643
+ /**
644
+ * Load high-severity lessons for session start.
645
+ *
646
+ * Returns confirmed, high-severity lessons sorted by recency.
647
+ * These are the most important lessons to surface at the start
648
+ * of a coding session.
649
+ *
650
+ * @param repoRoot - Repository root directory
651
+ * @param limit - Maximum number of lessons to return (default: 5)
652
+ * @returns Array of high-severity lessons, most recent first
653
+ */
654
+ declare function loadSessionLessons(repoRoot: string, limit?: number): Promise<FullLesson[]>;
655
+
656
+ /**
657
+ * Plan-time lesson retrieval
658
+ *
659
+ * Retrieves relevant lessons when planning an implementation.
660
+ * Uses vector search to find semantically similar lessons.
661
+ */
662
+
663
+ /** Result of plan-time retrieval */
664
+ interface PlanRetrievalResult {
665
+ lessons: RankedLesson[];
666
+ message: string;
667
+ }
668
+ /**
669
+ * Retrieve relevant lessons for a plan.
670
+ *
671
+ * Uses vector search to find semantically similar lessons,
672
+ * then applies ranking boosts for severity, recency, and confirmation.
673
+ *
674
+ * Hard-fails if embeddings are unavailable (propagates error from embedText).
675
+ *
676
+ * @param repoRoot - Repository root directory
677
+ * @param planText - The plan text to search against
678
+ * @param limit - Maximum number of lessons to return (default: 5)
679
+ * @returns Ranked lessons and formatted message
680
+ */
681
+ declare function retrieveForPlan(repoRoot: string, planText: string, limit?: number): Promise<PlanRetrievalResult>;
682
+ /**
683
+ * Format a "Lessons Check" message for display.
684
+ *
685
+ * This message is intended to be shown at plan-time to remind
686
+ * the developer of relevant lessons before implementation.
687
+ *
688
+ * @param lessons - Ranked lessons to include in the message
689
+ * @returns Formatted message string
690
+ */
691
+ declare function formatLessonsCheck(lessons: ScoredLesson[]): string;
692
+
693
+ /**
694
+ * Learning Agent - Repository-scoped learning system for Claude Code
695
+ *
696
+ * This package helps Claude Code learn from mistakes and avoid repeating them.
697
+ * It captures lessons during coding sessions and retrieves relevant lessons
698
+ * when planning new work.
699
+ *
700
+ * ## Quick Start
701
+ *
702
+ * ```typescript
703
+ * import { appendLesson, retrieveForPlan, loadSessionLessons } from 'learning-agent';
704
+ *
705
+ * // At session start, load high-severity lessons
706
+ * const criticalLessons = await loadSessionLessons(repoRoot);
707
+ *
708
+ * // When planning, retrieve relevant lessons
709
+ * const { lessons, message } = await retrieveForPlan(repoRoot, planText);
710
+ *
711
+ * // When capturing a lesson
712
+ * await appendLesson(repoRoot, lesson);
713
+ * ```
714
+ *
715
+ * ## Hook Integration
716
+ *
717
+ * Add to your `.claude/settings.json`:
718
+ *
719
+ * ```json
720
+ * {
721
+ * "hooks": {
722
+ * "session_start": "npx learning-agent load-session",
723
+ * "pre_tool": "npx learning-agent check-plan"
724
+ * }
725
+ * }
726
+ * ```
727
+ *
728
+ * ## Resource Management
729
+ *
730
+ * This library manages two heavyweight resources that require cleanup:
731
+ *
732
+ * ### SQLite Database
733
+ * - **Acquired:** Lazily on first database operation (search, rebuild, etc.)
734
+ * - **Memory:** Minimal (~few KB for connection, index cached by OS)
735
+ * - **Cleanup:** Call `closeDb()` before process exit
736
+ *
737
+ * ### Embedding Model
738
+ * - **Acquired:** Lazily on first embedding call (embedText, embedTexts, searchVector)
739
+ * - **Memory:** ~150MB RAM for the EmbeddingGemma model
740
+ * - **Cleanup:** Call `unloadEmbedding()` before process exit
741
+ *
742
+ * ### Recommended Cleanup Pattern
743
+ *
744
+ * ```typescript
745
+ * import { closeDb, unloadEmbedding } from 'learning-agent';
746
+ *
747
+ * // For CLI commands - use try/finally
748
+ * async function main() {
749
+ * try {
750
+ * // ... your code that uses learning-agent
751
+ * } finally {
752
+ * unloadEmbedding();
753
+ * closeDb();
754
+ * }
755
+ * }
756
+ *
757
+ * // For long-running processes - use shutdown handlers
758
+ * process.on('SIGTERM', () => {
759
+ * unloadEmbedding();
760
+ * closeDb();
761
+ * process.exit(0);
762
+ * });
763
+ * process.on('SIGINT', () => {
764
+ * unloadEmbedding();
765
+ * closeDb();
766
+ * process.exit(0);
767
+ * });
768
+ * ```
769
+ *
770
+ * **Note:** Failing to clean up will not corrupt data, but may cause:
771
+ * - Memory leaks in long-running processes
772
+ * - Unclean process exits (warnings in some environments)
773
+ *
774
+ * @see {@link closeDb} for database cleanup
775
+ * @see {@link unloadEmbedding} for embedding model cleanup
776
+ * @module learning-agent
777
+ */
778
+ declare const VERSION = "0.1.0";
779
+
780
+ export { type ActionabilityResult, type Context, type CorrectionSignal, DB_PATH, type DetectedCorrection, type DetectedSelfCorrection, type DetectedTestFailure, type EditEntry, type EditHistory, LESSONS_PATH, type Lesson, LessonSchema, type LessonType, LessonTypeSchema, MODEL_FILENAME, MODEL_URI, type NoveltyOptions, type NoveltyResult, type ParseError, type PlanRetrievalResult, type ProposeResult, type RankedLesson, type ReadLessonsOptions, type ReadLessonsResult, type ScoredLesson, type SearchVectorOptions, type Severity, type Source, type SpecificityResult, type TestResult, type Tombstone, TombstoneSchema, VERSION, appendLesson, calculateScore, closeDb, confirmationBoost, cosineSimilarity, detectSelfCorrection, detectTestFailure, detectUserCorrection, embedText, embedTexts, formatLessonsCheck, generateId, getEmbedding, isActionable, isModelAvailable, isNovel, isSpecific, loadSessionLessons, rankLessons, readLessons, rebuildIndex, recencyBoost, resolveModel, retrieveForPlan, searchKeyword, searchVector, severityBoost, shouldPropose, unloadEmbedding };