learning-agent 0.2.1 → 0.2.3
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/CHANGELOG.md +92 -1
- package/README.md +109 -81
- package/dist/cli.js +2026 -1466
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +66 -45
- package/dist/index.js +214 -83
- package/dist/index.js.map +1 -1
- package/package.json +21 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,95 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.3] - 2026-02-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **SQLite Graceful Degradation** (2f0)
|
|
15
|
+
- Works as dev dependency without native bindings failing
|
|
16
|
+
- JSONL-only mode when SQLite unavailable
|
|
17
|
+
- Keyword search falls back gracefully
|
|
18
|
+
- Warning displayed in degraded mode
|
|
19
|
+
|
|
20
|
+
- **Claude Code Integration** (ctv, 8lp, 6nw, 501, 2jp, lfy)
|
|
21
|
+
- Claude Plugin structure (`.claude-plugin/`) with manifest and commands
|
|
22
|
+
- `/learn` slash command for quick lesson capture
|
|
23
|
+
- `/check-plan` slash command for plan-time retrieval
|
|
24
|
+
- Auto-invoke triggers for lesson capture patterns
|
|
25
|
+
- Detection triggers wired to Claude Code workflow
|
|
26
|
+
- AGENTS.md includes reference to CLAUDE.md
|
|
27
|
+
|
|
28
|
+
- **Context Recovery** (gpv)
|
|
29
|
+
- `lna prime` command for context recovery after compaction/clear
|
|
30
|
+
- Outputs workflow rules, commands, and quality gates
|
|
31
|
+
|
|
32
|
+
- **Diagnostics** (qi0)
|
|
33
|
+
- `setup claude --status` shows integration health
|
|
34
|
+
- Displays settings file, hook status, slash command availability
|
|
35
|
+
- JSON output with `--json` flag
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **Architecture Refactoring** (e73, zpl)
|
|
40
|
+
- Split sqlite.ts (644 lines) into focused modules (<200 lines each)
|
|
41
|
+
- Module imports now use barrel exports (Parnas principles)
|
|
42
|
+
- Cleaner internal boundaries and improved maintainability
|
|
43
|
+
|
|
44
|
+
- **CLI Improvements** (79k, e2r)
|
|
45
|
+
- CLI releases database resources on SIGINT/SIGTERM signals
|
|
46
|
+
- `setup claude --uninstall` removes AGENTS.md section and CLAUDE.md reference
|
|
47
|
+
- Clean uninstall preserves other content
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Claude now uses CLI commands instead of editing JSONL directly (0p5)
|
|
52
|
+
- Plan-time lessons now appear via check-plan hook integration (6nw)
|
|
53
|
+
|
|
54
|
+
## [0.2.2] - 2026-02-01
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **Age-based Temporal Validity** (LANDSCAPE.md: eik)
|
|
59
|
+
- `CompactionLevelSchema` for lesson lifecycle (0=active, 1=flagged, 2=archived)
|
|
60
|
+
- Age distribution display in `stats` command (<30d, 30-90d, >90d)
|
|
61
|
+
- Age warnings in `load-session` for lessons older than 90 days
|
|
62
|
+
- New schema fields: `compactionLevel`, `compactedAt`, `lastRetrieved`
|
|
63
|
+
|
|
64
|
+
- **Manual Invalidation** (LANDSCAPE.md: mov)
|
|
65
|
+
- `learning-agent wrong <id>` - Mark a lesson as invalid/wrong
|
|
66
|
+
- `learning-agent validate <id>` - Re-enable a previously invalidated lesson
|
|
67
|
+
- `list --invalidated` flag to show only invalidated lessons
|
|
68
|
+
- New schema fields: `invalidatedAt`, `invalidationReason`
|
|
69
|
+
|
|
70
|
+
- **Optional Citation Field** (LANDSCAPE.md: tn3)
|
|
71
|
+
- `CitationSchema` for lesson provenance tracking
|
|
72
|
+
- Store file path, line number, and git commit with lessons
|
|
73
|
+
- `learn --citation <file:line>` and `--citation-commit <hash>` flags
|
|
74
|
+
|
|
75
|
+
- **Count Warning** (LANDSCAPE.md: qp9)
|
|
76
|
+
- Warning in `stats` when lesson count exceeds 20 (context pollution prevention)
|
|
77
|
+
- Note in `load-session` when total lessons may degrade retrieval quality
|
|
78
|
+
|
|
79
|
+
### Changed
|
|
80
|
+
|
|
81
|
+
- Lesson schema now includes optional fields for citation, age-tracking, and invalidation
|
|
82
|
+
- `list` command shows `[INVALID]` marker for invalidated lessons
|
|
83
|
+
- `load-session` JSON output includes `totalCount` field
|
|
84
|
+
- CLI refactored into command modules (`src/commands/`) for maintainability
|
|
85
|
+
- Age calculation logic centralized in `src/utils.ts`
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **SQLite schema now stores v0.2.2 fields** (x9y)
|
|
90
|
+
- Added columns: `invalidated_at`, `invalidation_reason`, `citation_*`, `compaction_level`, `compacted_at`
|
|
91
|
+
- `rebuildIndex` preserves all v0.2.2 fields during cache rebuild
|
|
92
|
+
- `rowToLesson` correctly maps all fields back to Lesson objects
|
|
93
|
+
|
|
94
|
+
- **Retrieval paths filter out invalidated lessons** (z8k)
|
|
95
|
+
- `searchKeyword` excludes lessons with `invalidated_at` set
|
|
96
|
+
- `searchVector` skips invalidated lessons during scoring
|
|
97
|
+
- `loadSessionLessons` filters out invalidated high-severity lessons
|
|
98
|
+
|
|
10
99
|
## [0.2.1] - 2026-02-01
|
|
11
100
|
|
|
12
101
|
### Added
|
|
@@ -141,7 +230,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
141
230
|
- Vitest test suite
|
|
142
231
|
- tsup build configuration
|
|
143
232
|
|
|
144
|
-
[Unreleased]: https://github.com/Nathandela/learning_agent/compare/v0.2.
|
|
233
|
+
[Unreleased]: https://github.com/Nathandela/learning_agent/compare/v0.2.3...HEAD
|
|
234
|
+
[0.2.3]: https://github.com/Nathandela/learning_agent/compare/v0.2.2...v0.2.3
|
|
235
|
+
[0.2.2]: https://github.com/Nathandela/learning_agent/compare/v0.2.1...v0.2.2
|
|
145
236
|
[0.2.1]: https://github.com/Nathandela/learning_agent/compare/v0.2.0...v0.2.1
|
|
146
237
|
[0.2.0]: https://github.com/Nathandela/learning_agent/compare/v0.1.0...v0.2.0
|
|
147
238
|
[0.1.0]: https://github.com/Nathandela/learning_agent/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -49,6 +49,27 @@ pnpm test
|
|
|
49
49
|
pnpm download-model
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
### Test Scripts
|
|
55
|
+
|
|
56
|
+
| Script | Duration | Tests | Use Case |
|
|
57
|
+
|--------|----------|-------|----------|
|
|
58
|
+
| `pnpm test:fast` | ~6s | 385 | **Rapid feedback during development** |
|
|
59
|
+
| `pnpm test` | ~60s | 653 | Full suite before committing |
|
|
60
|
+
| `pnpm test:changed` | varies | varies | Only tests affected by recent changes |
|
|
61
|
+
| `pnpm test:watch` | - | - | Watch mode for TDD workflow |
|
|
62
|
+
| `pnpm test:all` | ~60s | 653 | Full suite with model download |
|
|
63
|
+
|
|
64
|
+
**Recommended workflow:**
|
|
65
|
+
1. Use `pnpm test:fast` while coding for rapid feedback
|
|
66
|
+
2. Run `pnpm test` before committing
|
|
67
|
+
3. CI runs the full suite
|
|
68
|
+
|
|
69
|
+
### Why test:fast is fast
|
|
70
|
+
|
|
71
|
+
The CLI integration tests spawn Node.js processes (~400ms overhead each) and account for 95% of test time. `test:fast` skips these, running only unit tests that verify all business logic.
|
|
72
|
+
|
|
52
73
|
## Architecture
|
|
53
74
|
|
|
54
75
|
```
|
|
@@ -93,18 +114,30 @@ pnpm download-model
|
|
|
93
114
|
# Capture a lesson manually
|
|
94
115
|
pnpm learn "Use Polars for large files, not pandas"
|
|
95
116
|
|
|
117
|
+
# Capture with citation (file:line provenance)
|
|
118
|
+
learning-agent learn "API requires auth header" --citation src/api.ts:42
|
|
119
|
+
|
|
96
120
|
# Search lessons
|
|
97
121
|
learning-agent search "data processing"
|
|
98
122
|
|
|
99
|
-
# Rebuild index from JSONL
|
|
100
|
-
learning-agent rebuild
|
|
101
|
-
|
|
102
123
|
# List all lessons
|
|
103
124
|
learning-agent list
|
|
104
125
|
|
|
105
|
-
#
|
|
126
|
+
# List only invalidated lessons
|
|
127
|
+
learning-agent list --invalidated
|
|
128
|
+
|
|
129
|
+
# Mark a lesson as wrong/invalid
|
|
130
|
+
learning-agent wrong L12345678 --reason "This advice was incorrect"
|
|
131
|
+
|
|
132
|
+
# Re-enable an invalidated lesson
|
|
133
|
+
learning-agent validate L12345678
|
|
134
|
+
|
|
135
|
+
# Show database stats (includes age distribution)
|
|
106
136
|
learning-agent stats
|
|
107
137
|
|
|
138
|
+
# Rebuild index from JSONL
|
|
139
|
+
learning-agent rebuild
|
|
140
|
+
|
|
108
141
|
# Compact and archive old lessons
|
|
109
142
|
learning-agent compact
|
|
110
143
|
```
|
|
@@ -184,118 +217,87 @@ See [examples/](examples/) for usage examples.
|
|
|
184
217
|
|
|
185
218
|
## Lesson Schema
|
|
186
219
|
|
|
187
|
-
Lessons are stored
|
|
220
|
+
Lessons are stored as JSONL records with the following schema:
|
|
188
221
|
|
|
189
222
|
### Required Fields
|
|
190
223
|
|
|
191
|
-
|
|
224
|
+
All lessons must have these fields:
|
|
192
225
|
|
|
193
226
|
| Field | Type | Description |
|
|
194
227
|
|-------|------|-------------|
|
|
195
|
-
| `id` | string | Unique identifier (e.g., "
|
|
196
|
-
| `type` | "quick" \| "full" | Lesson
|
|
197
|
-
| `trigger` | string | What caused
|
|
198
|
-
| `insight` | string |
|
|
199
|
-
| `tags` | string[] | Categorization tags
|
|
200
|
-
| `source` |
|
|
201
|
-
| `context` | object |
|
|
202
|
-
| `created` | string |
|
|
203
|
-
| `confirmed` | boolean | Whether user confirmed
|
|
204
|
-
| `supersedes` | string[] | IDs of lessons this replaces (can be empty) |
|
|
205
|
-
| `related` | string[] | IDs of related lessons (can be empty) |
|
|
228
|
+
| `id` | string | Unique identifier (e.g., "L12345678") |
|
|
229
|
+
| `type` | "quick" \| "full" | Lesson complexity level |
|
|
230
|
+
| `trigger` | string | What caused the lesson (context/situation) |
|
|
231
|
+
| `insight` | string | What was learned (the takeaway) |
|
|
232
|
+
| `tags` | string[] | Categorization tags |
|
|
233
|
+
| `source` | string | How it was captured (user_correction, self_correction, test_failure, manual) |
|
|
234
|
+
| `context` | object | Tool/intent context |
|
|
235
|
+
| `created` | ISO string | Creation timestamp |
|
|
236
|
+
| `confirmed` | boolean | Whether user confirmed the lesson |
|
|
206
237
|
|
|
207
238
|
### Optional Fields
|
|
208
239
|
|
|
209
240
|
| Field | Type | Description |
|
|
210
241
|
|-------|------|-------------|
|
|
211
|
-
| `evidence` | string | Supporting evidence (
|
|
212
|
-
| `severity` | "high" \| "medium" \| "low" | Importance level |
|
|
213
|
-
| `
|
|
214
|
-
| `deleted` | boolean | Tombstone marker for deletions |
|
|
215
|
-
| `retrievalCount` | number | Times this lesson was retrieved |
|
|
216
|
-
|
|
217
|
-
### Type vs Severity (Important!)
|
|
218
|
-
|
|
219
|
-
**`type`** and **`severity`** are **separate** fields:
|
|
242
|
+
| `evidence` | string | Supporting evidence (full lessons only) |
|
|
243
|
+
| `severity` | "high" \| "medium" \| "low" | Importance level (separate from type) |
|
|
244
|
+
| `citation` | object | File/line reference (file, line, commit) |
|
|
220
245
|
|
|
221
|
-
|
|
222
|
-
- `"quick"` - Minimal capture, fast to create
|
|
223
|
-
- `"full"` - Detailed lesson with evidence/patterns
|
|
224
|
-
|
|
225
|
-
- **`severity`**: Importance level (optional field)
|
|
226
|
-
- `"high"` - Critical, loaded at every session start
|
|
227
|
-
- `"medium"` - Important, retrieved when relevant
|
|
228
|
-
- `"low"` - Minor, lower retrieval priority
|
|
229
|
-
|
|
230
|
-
**Common mistake**: Using `type: "high"` instead of `type: "full"` with `severity: "high"`.
|
|
246
|
+
**Note**: The `severity` field is separate from `type`. A quick lesson can have high severity, and a full lesson can have low severity.
|
|
231
247
|
|
|
232
248
|
### Session-Start Loading
|
|
233
249
|
|
|
234
|
-
|
|
250
|
+
At session start, lessons are loaded based on:
|
|
251
|
+
- **High severity** lessons are always loaded
|
|
252
|
+
- **Confirmed** lessons are prioritized
|
|
253
|
+
- Only non-invalidated lessons are included
|
|
235
254
|
|
|
236
|
-
|
|
237
|
-
2. `severity` must be `"high"`
|
|
238
|
-
3. `confirmed` must be `true`
|
|
255
|
+
### Complete JSON Example
|
|
239
256
|
|
|
240
|
-
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"id": "L12345678",
|
|
260
|
+
"type": "full",
|
|
261
|
+
"trigger": "API returned 401 despite valid JWT token",
|
|
262
|
+
"insight": "Auth API requires X-Request-ID header in all requests",
|
|
263
|
+
"evidence": "Traced in network tab, discovered missing header requirement",
|
|
264
|
+
"severity": "high",
|
|
265
|
+
"tags": ["api", "auth", "headers"],
|
|
266
|
+
"source": "test_failure",
|
|
267
|
+
"context": { "tool": "fetch", "intent": "API authentication" },
|
|
268
|
+
"created": "2024-01-15T10:30:00.000Z",
|
|
269
|
+
"confirmed": true,
|
|
270
|
+
"citation": { "file": "src/api/client.ts", "line": 42 }
|
|
271
|
+
}
|
|
272
|
+
```
|
|
241
273
|
|
|
242
|
-
|
|
274
|
+
## Lesson Types
|
|
243
275
|
|
|
276
|
+
### Quick Lesson (fast capture)
|
|
244
277
|
```json
|
|
245
278
|
{
|
|
246
|
-
"id": "
|
|
279
|
+
"id": "L001",
|
|
247
280
|
"type": "quick",
|
|
248
281
|
"trigger": "Used pandas for 500MB file",
|
|
249
|
-
"insight": "Polars
|
|
282
|
+
"insight": "Polars 10x faster",
|
|
250
283
|
"tags": ["performance", "polars"],
|
|
251
|
-
"source": "user_correction"
|
|
252
|
-
"context": { "tool": "edit", "intent": "optimize CSV processing" },
|
|
253
|
-
"created": "2025-01-30T14:00:00Z",
|
|
254
|
-
"confirmed": true,
|
|
255
|
-
"supersedes": [],
|
|
256
|
-
"related": []
|
|
284
|
+
"source": "user_correction"
|
|
257
285
|
}
|
|
258
286
|
```
|
|
259
287
|
|
|
260
|
-
|
|
261
|
-
|
|
288
|
+
### Full Lesson (detailed, high-severity)
|
|
262
289
|
```json
|
|
263
290
|
{
|
|
264
|
-
"id": "
|
|
291
|
+
"id": "L002",
|
|
265
292
|
"type": "full",
|
|
266
293
|
"trigger": "Auth API returned 401 despite valid token",
|
|
267
294
|
"insight": "API requires X-Request-ID header",
|
|
268
|
-
"evidence": "Traced in network tab, header
|
|
269
|
-
"tags": ["api", "auth"],
|
|
295
|
+
"evidence": "Traced in network tab, header missing",
|
|
270
296
|
"severity": "high",
|
|
271
|
-
"source": "test_failure"
|
|
272
|
-
"context": { "tool": "bash", "intent": "run auth integration tests" },
|
|
273
|
-
"created": "2025-01-30T15:30:00Z",
|
|
274
|
-
"confirmed": true,
|
|
275
|
-
"supersedes": [],
|
|
276
|
-
"related": ["L1a2b3c4d"],
|
|
277
|
-
"pattern": {
|
|
278
|
-
"bad": "requests.get(url, headers={'Authorization': token})",
|
|
279
|
-
"good": "requests.get(url, headers={'Authorization': token, 'X-Request-ID': uuid4()})"
|
|
280
|
-
}
|
|
297
|
+
"source": "test_failure"
|
|
281
298
|
}
|
|
282
299
|
```
|
|
283
300
|
|
|
284
|
-
### Creating Lessons via CLI
|
|
285
|
-
|
|
286
|
-
Always use the CLI to create lessons (never edit JSONL directly):
|
|
287
|
-
|
|
288
|
-
```bash
|
|
289
|
-
# Quick lesson
|
|
290
|
-
npx lna learn "Use Polars for large files"
|
|
291
|
-
|
|
292
|
-
# Full lesson with high severity (loads at session start)
|
|
293
|
-
npx lna learn "API requires X-Request-ID header" --severity high
|
|
294
|
-
|
|
295
|
-
# With trigger context
|
|
296
|
-
npx lna learn "Use uv not pip" --trigger "pip was slow" --severity medium
|
|
297
|
-
```
|
|
298
|
-
|
|
299
301
|
## Technology Stack
|
|
300
302
|
|
|
301
303
|
| Component | Technology |
|
|
@@ -324,7 +326,7 @@ pnpm lint
|
|
|
324
326
|
|
|
325
327
|
## Project Status
|
|
326
328
|
|
|
327
|
-
Version 0.2.
|
|
329
|
+
Version 0.2.2 - Hardening release with quality gates based on [LANDSCAPE.md](doc/LANDSCAPE.md) reviewer feedback. Adds age-based validity warnings, manual invalidation commands, optional citation tracking, and context pollution warnings. See [CHANGELOG.md](CHANGELOG.md) for details.
|
|
328
330
|
|
|
329
331
|
## Documentation
|
|
330
332
|
|
|
@@ -335,6 +337,32 @@ Version 0.2.1 - Bug fixes and documentation improvements. See [doc/SPEC.md](doc/
|
|
|
335
337
|
| [doc/PLAN.md](doc/PLAN.md) | Implementation plan |
|
|
336
338
|
| [AGENTS.md](AGENTS.md) | Agent instructions overview |
|
|
337
339
|
| [.claude/CLAUDE.md](.claude/CLAUDE.md) | Claude Code project instructions |
|
|
340
|
+
| [doc/test-optimization-baseline.md](doc/test-optimization-baseline.md) | Test performance metrics |
|
|
341
|
+
|
|
342
|
+
## Testing
|
|
343
|
+
|
|
344
|
+
### Test Organization
|
|
345
|
+
|
|
346
|
+
Tests are organized for parallelization:
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
src/
|
|
350
|
+
├── *.test.ts # Unit tests (fast)
|
|
351
|
+
├── cli/ # CLI integration tests (split by command)
|
|
352
|
+
│ ├── cli-test-utils.ts # Shared utilities
|
|
353
|
+
│ ├── learn.test.ts
|
|
354
|
+
│ ├── search.test.ts
|
|
355
|
+
│ └── ...
|
|
356
|
+
├── storage/ # Storage layer tests
|
|
357
|
+
├── embeddings/ # Embedding model tests (skipped if model unavailable)
|
|
358
|
+
└── ...
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Known Limitations
|
|
362
|
+
|
|
363
|
+
**Embedding concurrency**: The `node-llama-cpp` native addon may crash under heavy parallel load. This is a known limitation of the underlying C++ library. Tests pass reliably under normal conditions.
|
|
364
|
+
|
|
365
|
+
**Timing-based tests**: Some tests verify performance thresholds. These use generous limits (5000ms) to avoid flakiness on slow CI machines.
|
|
338
366
|
|
|
339
367
|
## License
|
|
340
368
|
|