hippo-memory 1.36.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autolearn.d.ts +16 -0
- package/dist/autolearn.d.ts.map +1 -1
- package/dist/autolearn.js +26 -0
- package/dist/autolearn.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +48 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +14 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/src/autolearn.js +26 -0
- package/dist/src/autolearn.js.map +1 -1
- package/dist/src/cli.js +48 -8
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/server.js +14 -3
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/autolearn.d.ts
CHANGED
|
@@ -13,6 +13,22 @@ export declare function captureError(exitCode: number, stderr: string, command:
|
|
|
13
13
|
* Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
|
|
14
14
|
*/
|
|
15
15
|
export declare function extractLessons(gitLog: string, customPatterns?: string[]): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Split parsed lessons into ones worth storing and low-information ones.
|
|
18
|
+
*
|
|
19
|
+
* `extractLessons` is a published API surface (exported from src/index.ts)
|
|
20
|
+
* and does one job: parse a git log into candidate lesson strings. Adding a
|
|
21
|
+
* quality check inside it would break that contract and silently change
|
|
22
|
+
* what external callers get back. So parsing and admission are separate
|
|
23
|
+
* steps: this function is the write-path gate, called by each caller that
|
|
24
|
+
* actually stores a lesson, not by the parser itself.
|
|
25
|
+
*
|
|
26
|
+
* Order is preserved in both output arrays.
|
|
27
|
+
*/
|
|
28
|
+
export declare function partitionLessons(lessons: string[]): {
|
|
29
|
+
kept: string[];
|
|
30
|
+
dropped: string[];
|
|
31
|
+
};
|
|
16
32
|
/**
|
|
17
33
|
* Check if a substantially similar memory already exists.
|
|
18
34
|
* Returns true if overlap > threshold (default 0.7).
|
package/dist/autolearn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autolearn.d.ts","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"autolearn.d.ts","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAK/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,WAAW,CAoBb;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAsClF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAWzF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,kBAAkB,EAAE,MAAM,GAAG,WAAW,EAAE,EAC1C,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAWT;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBzF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAY9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7D"}
|
package/dist/autolearn.js
CHANGED
|
@@ -6,6 +6,7 @@ import { execSync, execFileSync, spawn } from 'child_process';
|
|
|
6
6
|
import { createMemory, Layer } from './memory.js';
|
|
7
7
|
import { loadAllEntries } from './store.js';
|
|
8
8
|
import { textOverlap } from './search.js';
|
|
9
|
+
import { isContentWorthStoring } from './audit.js';
|
|
9
10
|
/**
|
|
10
11
|
* Create a MemoryEntry capturing a command failure.
|
|
11
12
|
* Content format: "Command '<cmd>' failed: <truncated stderr>"
|
|
@@ -68,6 +69,31 @@ export function extractLessons(gitLog, customPatterns) {
|
|
|
68
69
|
// Deduplicate exact matches at extraction time
|
|
69
70
|
return [...new Set(lessons)];
|
|
70
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Split parsed lessons into ones worth storing and low-information ones.
|
|
74
|
+
*
|
|
75
|
+
* `extractLessons` is a published API surface (exported from src/index.ts)
|
|
76
|
+
* and does one job: parse a git log into candidate lesson strings. Adding a
|
|
77
|
+
* quality check inside it would break that contract and silently change
|
|
78
|
+
* what external callers get back. So parsing and admission are separate
|
|
79
|
+
* steps: this function is the write-path gate, called by each caller that
|
|
80
|
+
* actually stores a lesson, not by the parser itself.
|
|
81
|
+
*
|
|
82
|
+
* Order is preserved in both output arrays.
|
|
83
|
+
*/
|
|
84
|
+
export function partitionLessons(lessons) {
|
|
85
|
+
const kept = [];
|
|
86
|
+
const dropped = [];
|
|
87
|
+
for (const lesson of lessons) {
|
|
88
|
+
if (isContentWorthStoring(lesson)) {
|
|
89
|
+
kept.push(lesson);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
dropped.push(lesson);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { kept, dropped };
|
|
96
|
+
}
|
|
71
97
|
/**
|
|
72
98
|
* Check if a substantially similar memory already exists.
|
|
73
99
|
* Returns true if overlap > threshold (default 0.7).
|
package/dist/autolearn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autolearn.js","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAe,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"autolearn.js","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAe,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,MAAc,EACd,OAAe;IAEf,uEAAuE;IACvE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,wFAAwF;IACxF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,YAAY,CAAC;IAChG,MAAM,OAAO,GAAG,YAAY,OAAO,kBAAkB,QAAQ,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;IAExF,wEAAwE;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACpC,IAAI,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAE3D,OAAO,YAAY,CAAC,OAAO,EAAE;QAC3B,KAAK,EAAE,KAAK,CAAC,QAAQ;QACrB,IAAI;QACJ,MAAM,EAAE,WAAW;QACnB,UAAU,EAAE,UAAU;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,cAAyB;IACtE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjC,gDAAgD;IAChD,sFAAsF;IACtF,MAAM,QAAQ,GAAG,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,2EAA2E,CAAC;IAC1H,MAAM,QAAQ,GAAG;QACf,IAAI,MAAM,CAAC,kBAAkB,QAAQ,yBAAyB,EAAE,GAAG,CAAC;QACpE,IAAI,MAAM,CAAC,KAAK,QAAQ,yBAAyB,EAAE,GAAG,CAAC;QACvD,sDAAsD;QACtD,kFAAkF;KACnF,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9G,SAAS;QACX,CAAC;QAED,qGAAqG;QACrG,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QAE3D,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,EAAE,CAAC;gBACN,uFAAuF;gBACvF,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;oBAC7C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAChD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,kBAA0C,EAC1C,MAAc,EACd,SAAS,GAAG,GAAG,EACf,QAAiB;IAEjB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;QAC/C,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAEjD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,OAAO,GAAG,SAAS;YAAE,OAAO,IAAI,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,sEAAsE;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAErF,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,gCAAgC;YAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACxC,OAAO,CAAC;gBACN,QAAQ,EAAE,IAAI,IAAI,CAAC;gBACnB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;aACrD,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC/B,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,qCAAqC,EAAE;YAC1D,QAAQ,EAAE,MAAM;YAChB,GAAG;YACH,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,IAAY;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE;YAC9B,KAAK,EAAE,WAAW,IAAI,WAAW,EAAE,oBAAoB;SACxD,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/E,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AA2BH,OAAO,EASL,WAAW,EAEZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AA2BH,OAAO,EASL,WAAW,EAEZ,MAAM,aAAa,CAAC;AA6GrB,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AA4ChC,kFAAkF;AAClF,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AA4ID,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,CAwCjI;AA+tED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,MAAqB,GAAG,MAAM,CAyF3F;AAyGD;;;GAGG;AACH,oHAAoH;AACpH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAuD/D;AA2jGD,oHAAoH;AACpH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,EACtF,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,MAAkB,GAC1B,IAAI,CA6BN"}
|
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ import { loadConfig } from './config.js';
|
|
|
54
54
|
import { openHippoDb, closeHippoDb } from './db.js';
|
|
55
55
|
import { pushGoal, getActiveGoals, completeGoal, suspendGoal, resumeGoal, applyGoalStackBoost } from './goals.js';
|
|
56
56
|
import { rowToGoal } from './goals.js';
|
|
57
|
-
import { captureError, extractLessons, deduplicateLesson, runWatched, fetchGitLog, isGitRepo, } from './autolearn.js';
|
|
57
|
+
import { captureError, extractLessons, partitionLessons, deduplicateLesson, runWatched, fetchGitLog, isGitRepo, } from './autolearn.js';
|
|
58
58
|
import { extractInvalidationTarget, invalidateMatching } from './invalidation.js';
|
|
59
59
|
import { extractPathTags } from './path-context.js';
|
|
60
60
|
import { detectScope } from './scope.js';
|
|
@@ -316,6 +316,11 @@ function cmdInitScan(scanDir, flags) {
|
|
|
316
316
|
console.log(`Initialized global store at ${globalRoot}\n`);
|
|
317
317
|
}
|
|
318
318
|
let totalLessons = 0;
|
|
319
|
+
// Rolled up so the cross-repo summary reports the gate too. Each repo
|
|
320
|
+
// already prints its own count inside learnFromRepo, but the aggregate
|
|
321
|
+
// line showed only what was ADDED - and the point of this change is
|
|
322
|
+
// that a dropped subject is never invisible.
|
|
323
|
+
let totalLowInfo = 0;
|
|
319
324
|
const seedDays = parseInt(String(flags['days'] ?? '365'), 10);
|
|
320
325
|
for (const repo of repos) {
|
|
321
326
|
const name = path.basename(repo);
|
|
@@ -331,12 +336,15 @@ function cmdInitScan(scanDir, flags) {
|
|
|
331
336
|
const result = learnFromRepo(repoHippo, repo, seedDays, name);
|
|
332
337
|
added = result.added;
|
|
333
338
|
totalLessons += added;
|
|
339
|
+
totalLowInfo += result.lowInfo;
|
|
334
340
|
}
|
|
335
341
|
const status = alreadyExists ? 'existing' : 'new';
|
|
336
342
|
const entries = loadAllEntries(repoHippo);
|
|
337
343
|
console.log(` ${name.padEnd(25)} ${status.padEnd(10)} ${entries.length} memories${added > 0 ? ` (+${added} from git)` : ''}`);
|
|
338
344
|
}
|
|
339
|
-
console.log(`\n${repos.length} repositories, ${totalLessons} new lessons learned
|
|
345
|
+
console.log(`\n${repos.length} repositories, ${totalLessons} new lessons learned` +
|
|
346
|
+
(totalLowInfo > 0 ? `, ${totalLowInfo} low-information subject(s) dropped` : '') +
|
|
347
|
+
'.');
|
|
340
348
|
console.log(`Global store: ${globalRoot}`);
|
|
341
349
|
if (!flags['no-schedule']) {
|
|
342
350
|
setupDailySchedule(globalRoot);
|
|
@@ -5770,18 +5778,49 @@ function learnFromRepo(hippoRoot, repoPath, days, label) {
|
|
|
5770
5778
|
const prefix = label ? `[${label}] ` : '';
|
|
5771
5779
|
if (!isGitRepo(repoPath)) {
|
|
5772
5780
|
console.log(`${prefix}No git history found (or not a git repository).`);
|
|
5773
|
-
return { added: 0, skipped: 0 };
|
|
5781
|
+
return { added: 0, skipped: 0, lowInfo: 0 };
|
|
5774
5782
|
}
|
|
5775
5783
|
const gitLog = fetchGitLog(repoPath, days);
|
|
5776
5784
|
if (!gitLog.trim()) {
|
|
5777
5785
|
console.log(`${prefix}No fix/revert/bug commits found in the specified period.`);
|
|
5778
|
-
return { added: 0, skipped: 0 };
|
|
5786
|
+
return { added: 0, skipped: 0, lowInfo: 0 };
|
|
5779
5787
|
}
|
|
5780
|
-
const
|
|
5781
|
-
if (
|
|
5788
|
+
const parsedLessons = extractLessons(gitLog);
|
|
5789
|
+
if (parsedLessons.length === 0) {
|
|
5782
5790
|
console.log(`${prefix}No fix/revert/bug commits found in the specified period.`);
|
|
5783
|
-
return { added: 0, skipped: 0 };
|
|
5791
|
+
return { added: 0, skipped: 0, lowInfo: 0 };
|
|
5784
5792
|
}
|
|
5793
|
+
// DF4: admission gate lives at the write path, not in extractLessons
|
|
5794
|
+
// (a published API surface that only parses). Bare subjects like "fixed
|
|
5795
|
+
// signals" are dropped here, before they ever become a memory.
|
|
5796
|
+
// The gate filters the loop INPUT, so a dropped lesson neither stores nor
|
|
5797
|
+
// invalidates. That is deliberate, and it was argued both ways.
|
|
5798
|
+
//
|
|
5799
|
+
// Round 1 of review called the lost invalidation a P1: a migration subject
|
|
5800
|
+
// too thin to store ("replace webpack with vite") would stop weakening
|
|
5801
|
+
// stale webpack memories. True. So the loop was widened to walk every
|
|
5802
|
+
// parsed lesson with the gate on the write alone.
|
|
5803
|
+
//
|
|
5804
|
+
// Round 2 then found the cure was worse. STORAGE is what makes invalidation
|
|
5805
|
+
// idempotent here: a stored lesson is recognised by deduplicateLesson on
|
|
5806
|
+
// the next scan and short-circuits before invalidating again. A lesson that
|
|
5807
|
+
// invalidates but is never stored has no such record, so every rescan
|
|
5808
|
+
// re-invalidates, and invalidateMatching halves half_life_days each time.
|
|
5809
|
+
// Measured: 7 -> 3 -> 1 over two runs. That is compounding data damage.
|
|
5810
|
+
//
|
|
5811
|
+
// Measured frequency decided it. Across 413 real auto-learn rows in 4
|
|
5812
|
+
// stores, 24 are gated and ZERO of those carry an invalidation target; the
|
|
5813
|
+
// 45 lessons that do carry targets all pass the gate and are unaffected
|
|
5814
|
+
// either way. Both failure modes are empty on real data, so the tie breaks
|
|
5815
|
+
// on which one is benign if it ever fires: not invalidating is a missed
|
|
5816
|
+
// improvement, re-invalidating forever is damage.
|
|
5817
|
+
//
|
|
5818
|
+
// Documented limitation, pinned by test: a migration subject too thin to
|
|
5819
|
+
// store also does not invalidate. Making invalidateMatching idempotent
|
|
5820
|
+
// would allow both, and is backlogged - it is a latent issue for the manual
|
|
5821
|
+
// `hippo invalidate` path too, not just this one.
|
|
5822
|
+
const { kept: lessons, dropped } = partitionLessons(parsedLessons);
|
|
5823
|
+
const lowInfo = dropped.length;
|
|
5785
5824
|
let added = 0;
|
|
5786
5825
|
let skipped = 0;
|
|
5787
5826
|
// AT1 (plan §3 containment): per-lesson refusal must not abort the rest
|
|
@@ -5841,8 +5880,9 @@ function learnFromRepo(hippoRoot, repoPath, days, label) {
|
|
|
5841
5880
|
}
|
|
5842
5881
|
console.log(`${prefix}${added} new lessons added, ${skipped} duplicates skipped` +
|
|
5843
5882
|
(rejected > 0 ? `, ${rejected} rejected value(s) skipped` : '') +
|
|
5883
|
+
(lowInfo > 0 ? `, ${lowInfo} low-information subject(s) dropped` : '') +
|
|
5844
5884
|
'.');
|
|
5845
|
-
return { added, skipped };
|
|
5885
|
+
return { added, skipped, lowInfo };
|
|
5846
5886
|
}
|
|
5847
5887
|
function cmdLearn(hippoRoot, flags) {
|
|
5848
5888
|
requireInit(hippoRoot);
|