learning-agent 0.2.1 → 0.2.2
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 +47 -1
- package/README.md +26 -101
- package/dist/cli.js +1326 -1236
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +38 -0
- package/dist/index.js +85 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,24 @@ declare const LessonSchema: z.ZodObject<{
|
|
|
63
63
|
}>>;
|
|
64
64
|
deleted: z.ZodOptional<z.ZodBoolean>;
|
|
65
65
|
retrievalCount: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
citation: z.ZodOptional<z.ZodObject<{
|
|
67
|
+
file: z.ZodString;
|
|
68
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
commit: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, "strip", z.ZodTypeAny, {
|
|
71
|
+
file: string;
|
|
72
|
+
line?: number | undefined;
|
|
73
|
+
commit?: string | undefined;
|
|
74
|
+
}, {
|
|
75
|
+
file: string;
|
|
76
|
+
line?: number | undefined;
|
|
77
|
+
commit?: string | undefined;
|
|
78
|
+
}>>;
|
|
79
|
+
compactionLevel: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<0>, z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
|
|
80
|
+
compactedAt: z.ZodOptional<z.ZodString>;
|
|
81
|
+
lastRetrieved: z.ZodOptional<z.ZodString>;
|
|
82
|
+
invalidatedAt: z.ZodOptional<z.ZodString>;
|
|
83
|
+
invalidationReason: z.ZodOptional<z.ZodString>;
|
|
66
84
|
}, "strip", z.ZodTypeAny, {
|
|
67
85
|
type: "quick" | "full";
|
|
68
86
|
id: string;
|
|
@@ -86,6 +104,16 @@ declare const LessonSchema: z.ZodObject<{
|
|
|
86
104
|
} | undefined;
|
|
87
105
|
deleted?: boolean | undefined;
|
|
88
106
|
retrievalCount?: number | undefined;
|
|
107
|
+
citation?: {
|
|
108
|
+
file: string;
|
|
109
|
+
line?: number | undefined;
|
|
110
|
+
commit?: string | undefined;
|
|
111
|
+
} | undefined;
|
|
112
|
+
compactionLevel?: 0 | 1 | 2 | undefined;
|
|
113
|
+
compactedAt?: string | undefined;
|
|
114
|
+
lastRetrieved?: string | undefined;
|
|
115
|
+
invalidatedAt?: string | undefined;
|
|
116
|
+
invalidationReason?: string | undefined;
|
|
89
117
|
}, {
|
|
90
118
|
type: "quick" | "full";
|
|
91
119
|
id: string;
|
|
@@ -109,6 +137,16 @@ declare const LessonSchema: z.ZodObject<{
|
|
|
109
137
|
} | undefined;
|
|
110
138
|
deleted?: boolean | undefined;
|
|
111
139
|
retrievalCount?: number | undefined;
|
|
140
|
+
citation?: {
|
|
141
|
+
file: string;
|
|
142
|
+
line?: number | undefined;
|
|
143
|
+
commit?: string | undefined;
|
|
144
|
+
} | undefined;
|
|
145
|
+
compactionLevel?: 0 | 1 | 2 | undefined;
|
|
146
|
+
compactedAt?: string | undefined;
|
|
147
|
+
lastRetrieved?: string | undefined;
|
|
148
|
+
invalidatedAt?: string | undefined;
|
|
149
|
+
invalidationReason?: string | undefined;
|
|
112
150
|
}>;
|
|
113
151
|
declare const TombstoneSchema: z.ZodObject<{
|
|
114
152
|
id: z.ZodString;
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,23 @@ var PatternSchema = z.object({
|
|
|
22
22
|
bad: z.string(),
|
|
23
23
|
good: z.string()
|
|
24
24
|
});
|
|
25
|
+
var CitationSchema = z.object({
|
|
26
|
+
file: z.string().min(1),
|
|
27
|
+
// Source file path (required, non-empty)
|
|
28
|
+
line: z.number().int().positive().optional(),
|
|
29
|
+
// Line number (optional, must be positive)
|
|
30
|
+
commit: z.string().optional()
|
|
31
|
+
// Git commit hash (optional)
|
|
32
|
+
});
|
|
25
33
|
var SeveritySchema = z.enum(["high", "medium", "low"]);
|
|
34
|
+
var CompactionLevelSchema = z.union([
|
|
35
|
+
z.literal(0),
|
|
36
|
+
// Active
|
|
37
|
+
z.literal(1),
|
|
38
|
+
// Flagged (>90 days)
|
|
39
|
+
z.literal(2)
|
|
40
|
+
// Archived
|
|
41
|
+
]);
|
|
26
42
|
var LessonTypeSchema = z.enum(["quick", "full"]);
|
|
27
43
|
var LessonSchema = z.object({
|
|
28
44
|
// Core identity (required)
|
|
@@ -46,7 +62,20 @@ var LessonSchema = z.object({
|
|
|
46
62
|
pattern: PatternSchema.optional(),
|
|
47
63
|
// Lifecycle fields (optional)
|
|
48
64
|
deleted: z.boolean().optional(),
|
|
49
|
-
retrievalCount: z.number().optional()
|
|
65
|
+
retrievalCount: z.number().optional(),
|
|
66
|
+
// Provenance tracking (optional)
|
|
67
|
+
citation: CitationSchema.optional(),
|
|
68
|
+
// Age-based validity fields (optional)
|
|
69
|
+
compactionLevel: CompactionLevelSchema.optional(),
|
|
70
|
+
// 0=active, 1=flagged, 2=archived
|
|
71
|
+
compactedAt: z.string().optional(),
|
|
72
|
+
// ISO8601 when compaction happened
|
|
73
|
+
lastRetrieved: z.string().optional(),
|
|
74
|
+
// ISO8601 last retrieval time
|
|
75
|
+
// Invalidation fields (optional - for marking lessons as wrong)
|
|
76
|
+
invalidatedAt: z.string().optional(),
|
|
77
|
+
// ISO8601
|
|
78
|
+
invalidationReason: z.string().optional()
|
|
50
79
|
});
|
|
51
80
|
var TombstoneSchema = z.object({
|
|
52
81
|
id: z.string(),
|
|
@@ -150,7 +179,15 @@ var SCHEMA_SQL = `
|
|
|
150
179
|
retrieval_count INTEGER NOT NULL DEFAULT 0,
|
|
151
180
|
last_retrieved TEXT,
|
|
152
181
|
embedding BLOB,
|
|
153
|
-
content_hash TEXT
|
|
182
|
+
content_hash TEXT,
|
|
183
|
+
-- v0.2.2 fields
|
|
184
|
+
invalidated_at TEXT,
|
|
185
|
+
invalidation_reason TEXT,
|
|
186
|
+
citation_file TEXT,
|
|
187
|
+
citation_line INTEGER,
|
|
188
|
+
citation_commit TEXT,
|
|
189
|
+
compaction_level INTEGER DEFAULT 0,
|
|
190
|
+
compacted_at TEXT
|
|
154
191
|
);
|
|
155
192
|
|
|
156
193
|
-- FTS5 virtual table for full-text search
|
|
@@ -265,6 +302,28 @@ function rowToLesson(row) {
|
|
|
265
302
|
if (row.retrieval_count > 0) {
|
|
266
303
|
lesson.retrievalCount = row.retrieval_count;
|
|
267
304
|
}
|
|
305
|
+
if (row.invalidated_at !== null) {
|
|
306
|
+
lesson.invalidatedAt = row.invalidated_at;
|
|
307
|
+
}
|
|
308
|
+
if (row.invalidation_reason !== null) {
|
|
309
|
+
lesson.invalidationReason = row.invalidation_reason;
|
|
310
|
+
}
|
|
311
|
+
if (row.citation_file !== null) {
|
|
312
|
+
lesson.citation = {
|
|
313
|
+
file: row.citation_file,
|
|
314
|
+
...row.citation_line !== null && { line: row.citation_line },
|
|
315
|
+
...row.citation_commit !== null && { commit: row.citation_commit }
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
if (row.compaction_level !== null && row.compaction_level !== 0) {
|
|
319
|
+
lesson.compactionLevel = row.compaction_level;
|
|
320
|
+
}
|
|
321
|
+
if (row.compacted_at !== null) {
|
|
322
|
+
lesson.compactedAt = row.compacted_at;
|
|
323
|
+
}
|
|
324
|
+
if (row.last_retrieved !== null) {
|
|
325
|
+
lesson.lastRetrieved = row.last_retrieved;
|
|
326
|
+
}
|
|
268
327
|
return lesson;
|
|
269
328
|
}
|
|
270
329
|
function collectCachedEmbeddings(database) {
|
|
@@ -278,8 +337,8 @@ function collectCachedEmbeddings(database) {
|
|
|
278
337
|
return cache;
|
|
279
338
|
}
|
|
280
339
|
var INSERT_LESSON_SQL = `
|
|
281
|
-
INSERT INTO lessons (id, type, trigger, insight, evidence, severity, tags, source, context, supersedes, related, created, confirmed, deleted, retrieval_count, last_retrieved, embedding, content_hash)
|
|
282
|
-
VALUES (@id, @type, @trigger, @insight, @evidence, @severity, @tags, @source, @context, @supersedes, @related, @created, @confirmed, @deleted, @retrieval_count, @last_retrieved, @embedding, @content_hash)
|
|
340
|
+
INSERT INTO lessons (id, type, trigger, insight, evidence, severity, tags, source, context, supersedes, related, created, confirmed, deleted, retrieval_count, last_retrieved, embedding, content_hash, invalidated_at, invalidation_reason, citation_file, citation_line, citation_commit, compaction_level, compacted_at)
|
|
341
|
+
VALUES (@id, @type, @trigger, @insight, @evidence, @severity, @tags, @source, @context, @supersedes, @related, @created, @confirmed, @deleted, @retrieval_count, @last_retrieved, @embedding, @content_hash, @invalidated_at, @invalidation_reason, @citation_file, @citation_line, @citation_commit, @compaction_level, @compacted_at)
|
|
283
342
|
`;
|
|
284
343
|
function getJsonlMtime(repoRoot) {
|
|
285
344
|
const jsonlPath = join(repoRoot, LESSONS_PATH);
|
|
@@ -331,10 +390,17 @@ async function rebuildIndex(repoRoot) {
|
|
|
331
390
|
confirmed: lesson.confirmed ? 1 : 0,
|
|
332
391
|
deleted: lesson.deleted ? 1 : 0,
|
|
333
392
|
retrieval_count: lesson.retrievalCount ?? 0,
|
|
334
|
-
last_retrieved: null,
|
|
335
|
-
// Reset on rebuild since we're rebuilding from source
|
|
393
|
+
last_retrieved: lesson.lastRetrieved ?? null,
|
|
336
394
|
embedding: hasValidCache ? cached.embedding : null,
|
|
337
|
-
content_hash: hasValidCache ? cached.contentHash : null
|
|
395
|
+
content_hash: hasValidCache ? cached.contentHash : null,
|
|
396
|
+
// v0.2.2 fields
|
|
397
|
+
invalidated_at: lesson.invalidatedAt ?? null,
|
|
398
|
+
invalidation_reason: lesson.invalidationReason ?? null,
|
|
399
|
+
citation_file: lesson.citation?.file ?? null,
|
|
400
|
+
citation_line: lesson.citation?.line ?? null,
|
|
401
|
+
citation_commit: lesson.citation?.commit ?? null,
|
|
402
|
+
compaction_level: lesson.compactionLevel ?? 0,
|
|
403
|
+
compacted_at: lesson.compactedAt ?? null
|
|
338
404
|
});
|
|
339
405
|
}
|
|
340
406
|
});
|
|
@@ -369,6 +435,7 @@ async function searchKeyword(repoRoot, query, limit) {
|
|
|
369
435
|
FROM lessons l
|
|
370
436
|
JOIN lessons_fts fts ON l.rowid = fts.rowid
|
|
371
437
|
WHERE lessons_fts MATCH ?
|
|
438
|
+
AND l.invalidated_at IS NULL
|
|
372
439
|
LIMIT ?
|
|
373
440
|
`
|
|
374
441
|
).all(query, limit);
|
|
@@ -462,6 +529,7 @@ async function searchVector(repoRoot, query, options) {
|
|
|
462
529
|
const queryVector = await embedText(query);
|
|
463
530
|
const scored = [];
|
|
464
531
|
for (const lesson of lessons) {
|
|
532
|
+
if (lesson.invalidatedAt) continue;
|
|
465
533
|
const lessonText = `${lesson.trigger} ${lesson.insight}`;
|
|
466
534
|
const hash = contentHash(lesson.trigger, lesson.insight);
|
|
467
535
|
let lessonVector = getCachedEmbedding(repoRoot, lesson.id, hash);
|
|
@@ -476,6 +544,14 @@ async function searchVector(repoRoot, query, options) {
|
|
|
476
544
|
return scored.slice(0, limit);
|
|
477
545
|
}
|
|
478
546
|
|
|
547
|
+
// src/utils.ts
|
|
548
|
+
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
549
|
+
function getLessonAgeDays(lesson) {
|
|
550
|
+
const created = new Date(lesson.created).getTime();
|
|
551
|
+
const now = Date.now();
|
|
552
|
+
return Math.floor((now - created) / MS_PER_DAY);
|
|
553
|
+
}
|
|
554
|
+
|
|
479
555
|
// src/search/ranking.ts
|
|
480
556
|
var RECENCY_THRESHOLD_DAYS = 30;
|
|
481
557
|
var HIGH_SEVERITY_BOOST = 1.5;
|
|
@@ -496,10 +572,7 @@ function severityBoost(lesson) {
|
|
|
496
572
|
}
|
|
497
573
|
}
|
|
498
574
|
function recencyBoost(lesson) {
|
|
499
|
-
const
|
|
500
|
-
const now = /* @__PURE__ */ new Date();
|
|
501
|
-
const ageMs = now.getTime() - created.getTime();
|
|
502
|
-
const ageDays = Math.floor(ageMs / (1e3 * 60 * 60 * 24));
|
|
575
|
+
const ageDays = getLessonAgeDays(lesson);
|
|
503
576
|
return ageDays <= RECENCY_THRESHOLD_DAYS ? RECENCY_BOOST : 1;
|
|
504
577
|
}
|
|
505
578
|
function confirmationBoost(lesson) {
|
|
@@ -690,7 +763,7 @@ function isFullLesson(lesson) {
|
|
|
690
763
|
async function loadSessionLessons(repoRoot, limit = DEFAULT_LIMIT2) {
|
|
691
764
|
const { lessons: allLessons } = await readLessons(repoRoot);
|
|
692
765
|
const highSeverityLessons = allLessons.filter(
|
|
693
|
-
(lesson) => isFullLesson(lesson) && lesson.severity === "high" && lesson.confirmed
|
|
766
|
+
(lesson) => isFullLesson(lesson) && lesson.severity === "high" && lesson.confirmed && !lesson.invalidatedAt
|
|
694
767
|
);
|
|
695
768
|
highSeverityLessons.sort((a, b) => {
|
|
696
769
|
const dateA = new Date(a.created).getTime();
|