@gamaze/hicortex 0.20.9 → 0.21.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/README.md +8 -0
- package/assets/dashboard.html +4174 -835
- package/dist/calibration.d.ts +119 -0
- package/dist/calibration.js +149 -1
- package/dist/capture-health.d.ts +87 -0
- package/dist/capture-health.js +106 -0
- package/dist/capture-pause.d.ts +86 -0
- package/dist/capture-pause.js +127 -0
- package/dist/capture.d.ts +9 -0
- package/dist/capture.js +2 -1
- package/dist/cli.js +36 -0
- package/dist/consolidate.d.ts +35 -0
- package/dist/consolidate.js +85 -9
- package/dist/dashboard.d.ts +322 -3
- package/dist/dashboard.js +592 -7
- package/dist/db.js +105 -0
- package/dist/eval/importance-eval.d.ts +85 -0
- package/dist/eval/importance-eval.js +286 -0
- package/dist/eval/planted-fixtures.d.ts +1 -1
- package/dist/eval/ranking-battery.d.ts +78 -0
- package/dist/eval/ranking-battery.js +181 -0
- package/dist/eval/ranking-eval.d.ts +41 -0
- package/dist/eval/ranking-eval.js +391 -0
- package/dist/eval/ranking-fixtures.d.ts +77 -0
- package/dist/eval/ranking-fixtures.js +226 -0
- package/dist/identity-store.d.ts +21 -0
- package/dist/identity-store.js +49 -0
- package/dist/init.d.ts +14 -0
- package/dist/init.js +32 -0
- package/dist/mcp-server.d.ts +12 -0
- package/dist/mcp-server.js +184 -3
- package/dist/nightly.d.ts +9 -1
- package/dist/nightly.js +59 -7
- package/dist/prompts.d.ts +10 -0
- package/dist/prompts.js +28 -5
- package/dist/reconsolidation.d.ts +59 -30
- package/dist/reconsolidation.js +526 -296
- package/dist/rescore-importance.d.ts +80 -0
- package/dist/rescore-importance.js +236 -0
- package/dist/retrieval.d.ts +12 -0
- package/dist/retrieval.js +30 -1
- package/dist/stages.d.ts +37 -0
- package/dist/stages.js +51 -0
- package/dist/state.d.ts +32 -6
- package/dist/storage.d.ts +34 -2
- package/dist/storage.js +63 -6
- package/dist/types.d.ts +48 -0
- package/package.json +3 -1
package/dist/storage.js
CHANGED
|
@@ -39,11 +39,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
exports.FTS_MATCH_MAX_TOKENS = void 0;
|
|
41
41
|
exports.embedToBlob = embedToBlob;
|
|
42
|
+
exports.sanitizeSourceMachine = sanitizeSourceMachine;
|
|
42
43
|
exports.insertMemory = insertMemory;
|
|
43
44
|
exports.resolveMemoryId = resolveMemoryId;
|
|
44
45
|
exports.getMemory = getMemory;
|
|
45
46
|
exports.updateMemory = updateMemory;
|
|
46
47
|
exports.strengthenMemory = strengthenMemory;
|
|
48
|
+
exports.enrichMemory = enrichMemory;
|
|
47
49
|
exports.touchMemoriesShown = touchMemoriesShown;
|
|
48
50
|
exports.deleteMemory = deleteMemory;
|
|
49
51
|
exports.memoryRowid = memoryRowid;
|
|
@@ -90,6 +92,18 @@ function rowToMemory(row) {
|
|
|
90
92
|
// ---------------------------------------------------------------------------
|
|
91
93
|
// Single memory CRUD
|
|
92
94
|
// ---------------------------------------------------------------------------
|
|
95
|
+
/**
|
|
96
|
+
* #421 machine × harness identity: optional capture-machine provenance on
|
|
97
|
+
* /ingest + /distill. A string, trimmed, capped at 128 chars; anything else
|
|
98
|
+
* (absent, wrong type, blank) becomes NULL — a wrong machine name is worse
|
|
99
|
+
* than none. Never filtered; presentation grouping only.
|
|
100
|
+
*/
|
|
101
|
+
function sanitizeSourceMachine(v) {
|
|
102
|
+
if (typeof v !== "string")
|
|
103
|
+
return null;
|
|
104
|
+
const t = v.trim();
|
|
105
|
+
return t.length > 0 ? t.slice(0, 128) : null;
|
|
106
|
+
}
|
|
93
107
|
/**
|
|
94
108
|
* Insert a memory and its vector embedding. Returns the memory's UUID.
|
|
95
109
|
*
|
|
@@ -108,9 +122,9 @@ function insertMemory(db, content, embedding, opts = {}) {
|
|
|
108
122
|
.prepare(`INSERT OR IGNORE INTO memories
|
|
109
123
|
(id, content, base_strength, last_accessed, access_count,
|
|
110
124
|
created_at, ingested_at, source_agent, source_agent_id, source_session,
|
|
111
|
-
source_domain, project, privacy, memory_type)
|
|
112
|
-
VALUES (?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
113
|
-
.run(id, content, opts.baseStrength ?? 0.5, ts, ts, ingestedTs, opts.sourceAgent ?? "default", opts.sourceAgentId ?? null, sourceSession, opts.sourceDomain ?? null, opts.project ?? null, opts.privacy ?? null, opts.memoryType ?? "experience");
|
|
125
|
+
source_domain, project, privacy, memory_type, source_machine)
|
|
126
|
+
VALUES (?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
127
|
+
.run(id, content, opts.baseStrength ?? 0.5, ts, ts, ingestedTs, opts.sourceAgent ?? "default", opts.sourceAgentId ?? null, sourceSession, opts.sourceDomain ?? null, opts.project ?? null, opts.privacy ?? null, opts.memoryType ?? "experience", opts.sourceMachine ?? null);
|
|
114
128
|
if (result.changes > 0) {
|
|
115
129
|
// New row — store its vector.
|
|
116
130
|
db.prepare("INSERT INTO memory_vectors (id, embedding) VALUES (?, ?)").run(id, embedToBlob(embedding));
|
|
@@ -172,6 +186,10 @@ const ALLOWED_UPDATE_FIELDS = new Set([
|
|
|
172
186
|
// reconsolidation stage, explicit ingest marks, and history rollback.
|
|
173
187
|
// Code-defined vocabulary — see Memory.status.
|
|
174
188
|
"status",
|
|
189
|
+
// Importance scored-at watermark (#425, migration v19): written by
|
|
190
|
+
// stageImportance, the enrich path, and the rescore-importance backfill —
|
|
191
|
+
// the moment a row's base_strength is settled under some rubric.
|
|
192
|
+
"importance_scored_at",
|
|
175
193
|
]);
|
|
176
194
|
/**
|
|
177
195
|
* Update specific fields on a memory.
|
|
@@ -198,6 +216,42 @@ function strengthenMemory(db, memoryId, nowIsoStr) {
|
|
|
198
216
|
SET access_count = access_count + 1, last_accessed = ?
|
|
199
217
|
WHERE id = ?`).run(nowIsoStr, memoryId);
|
|
200
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Record an owner corroboration (#423 phase 3): one UPDATE that bumps
|
|
221
|
+
* corroboration_count, nudges base_strength up by the calibration delta
|
|
222
|
+
* (MIN-capped at the importance ceiling, #425; COALESCE keeps NULL bases
|
|
223
|
+
* honest — the unscored default), stamps the importance watermark, and
|
|
224
|
+
* refreshes last_accessed (the console's "last confirmed" cell reads it: an
|
|
225
|
+
* enrich IS a confirmation, and it keeps the stage fading gate honest).
|
|
226
|
+
* EVIDENCE ABOUT IMPORTANCE ONLY — never access_count (reserved for real
|
|
227
|
+
* recall use) nor shown_count (index exposure): faking either corrupts the
|
|
228
|
+
* uses-per-showing adoption metric.
|
|
229
|
+
*
|
|
230
|
+
* Nightly interaction: the importance pool keys on importance_scored_at IS
|
|
231
|
+
* NULL (#425), so the watermark stamp here keeps the pre-#425 contract — an
|
|
232
|
+
* enriched memory leaves the pool and the owner's mark stands in for (and is
|
|
233
|
+
* never stomped by) the first LLM score. Dedup merges take
|
|
234
|
+
* max(base_strength), so a merge never loses the mark. Returns the fresh row
|
|
235
|
+
* values (re-read after the update); null when the id matches nothing.
|
|
236
|
+
*/
|
|
237
|
+
function enrichMemory(db, memoryId, nowIsoStr) {
|
|
238
|
+
const result = db
|
|
239
|
+
.prepare(`UPDATE memories
|
|
240
|
+
SET corroboration_count = corroboration_count + 1,
|
|
241
|
+
base_strength = MIN(?, COALESCE(base_strength, 0.5) + ?),
|
|
242
|
+
importance_scored_at = COALESCE(importance_scored_at, ?),
|
|
243
|
+
last_accessed = ?
|
|
244
|
+
WHERE id = ?`)
|
|
245
|
+
.run(CALIBRATION.IMPORTANCE_CEILING, CALIBRATION.ENRICH_STRENGTH_DELTA, nowIsoStr, nowIsoStr, memoryId);
|
|
246
|
+
if (result.changes === 0)
|
|
247
|
+
return null;
|
|
248
|
+
const row = db
|
|
249
|
+
.prepare("SELECT corroboration_count, base_strength FROM memories WHERE id = ?")
|
|
250
|
+
.get(memoryId);
|
|
251
|
+
return row
|
|
252
|
+
? { corroborationCount: row.corroboration_count, baseStrength: row.base_strength }
|
|
253
|
+
: null;
|
|
254
|
+
}
|
|
201
255
|
/**
|
|
202
256
|
* Record that memories appeared in a pushed recall index (#192): bump
|
|
203
257
|
* shown_count and refresh last_accessed (a mild strengthen — the decay clock
|
|
@@ -679,14 +733,17 @@ function getAllLinkCounts(db) {
|
|
|
679
733
|
return counts;
|
|
680
734
|
}
|
|
681
735
|
/**
|
|
682
|
-
* Get all memories
|
|
683
|
-
*
|
|
736
|
+
* Get all never-scored memories — the nightly importance pool, keyed on the
|
|
737
|
+
* importance_scored_at watermark (#425, migration v19). The pre-v19 sentinel
|
|
738
|
+
* (`base_strength = 0.5`) re-rolled every row the model genuinely scored
|
|
739
|
+
* 0.5, every night; NULL watermark = never scored under ANY rubric. Absorbed
|
|
740
|
+
* memories are excluded (#384): they are invisible to recall, so
|
|
684
741
|
* importance-scoring one would spend an LLM call on dead evidence.
|
|
685
742
|
*/
|
|
686
743
|
function getUnscoredMemories(db) {
|
|
687
744
|
const rows = db
|
|
688
745
|
.prepare(`SELECT * FROM memories
|
|
689
|
-
WHERE
|
|
746
|
+
WHERE importance_scored_at IS NULL AND COALESCE(status, '') != 'absorbed'
|
|
690
747
|
ORDER BY ingested_at ASC`)
|
|
691
748
|
.all();
|
|
692
749
|
return rows.map(rowToMemory);
|
package/dist/types.d.ts
CHANGED
|
@@ -42,6 +42,26 @@ export interface Memory {
|
|
|
42
42
|
* kept as evidence and rollback reference).
|
|
43
43
|
*/
|
|
44
44
|
status?: string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Explicit owner corroboration count (#423 phase 3, migration v17). Each
|
|
47
|
+
* POST /enrich bumps it together with base_strength (+the calibration
|
|
48
|
+
* delta, capped at the importance ceiling) — EVIDENCE ABOUT IMPORTANCE,
|
|
49
|
+
* never access (access_count) nor index exposure (shown_count). Optional
|
|
50
|
+
* because rowToMemory is a cast over SELECT * rows; 0 (the column default)
|
|
51
|
+
* on all pre-v17 rows and until first enriched.
|
|
52
|
+
*/
|
|
53
|
+
corroboration_count?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Importance scored-at watermark (#425, migration v19). NULL = never
|
|
56
|
+
* scored (the nightly's unscored pool); a timestamp = this row's
|
|
57
|
+
* base_strength is settled under some rubric and the nightly will not
|
|
58
|
+
* re-roll it. Written by stageImportance, the enrich path (the owner's
|
|
59
|
+
* mark stands in for the first LLM score), and the rescore-importance
|
|
60
|
+
* backfill. Optional because rowToMemory is a cast over SELECT * rows;
|
|
61
|
+
* pre-v19 rows were stamped by the migration backfill (except sentinel
|
|
62
|
+
* rows, which stay NULL for exactly one scoring under the new rubric).
|
|
63
|
+
*/
|
|
64
|
+
importance_scored_at?: string | null;
|
|
45
65
|
}
|
|
46
66
|
/** A link between two memories. */
|
|
47
67
|
export interface MemoryLink {
|
|
@@ -282,6 +302,30 @@ export interface ConsolidationReport {
|
|
|
282
302
|
explicit_divergent: number;
|
|
283
303
|
/** reconsolidationCursor after this run (unchanged in dry-run). */
|
|
284
304
|
cursor: number;
|
|
305
|
+
/**
|
|
306
|
+
* #439: verdict calls on pairs whose candidate rowid was at/below the
|
|
307
|
+
* run-start scan high-water (state.reconsolidationScannedRowid) —
|
|
308
|
+
* re-judgments of work a prior run already judged but could not apply
|
|
309
|
+
* (the cursor held below it). Convergence evidence: this number must
|
|
310
|
+
* fall to 0 once the backlog drains. pairs_evaluated =
|
|
311
|
+
* pairs_reevaluated + pairs_new.
|
|
312
|
+
*/
|
|
313
|
+
pairs_reevaluated: number;
|
|
314
|
+
/** #439: verdict calls on candidates ABOVE the high-water — first-time judgments. */
|
|
315
|
+
pairs_new: number;
|
|
316
|
+
/**
|
|
317
|
+
* #439: snapshot candidates skipped because a mid-scan absorb (a merge
|
|
318
|
+
* loser or rewrite trigger absorbed at an earlier candidate's boundary)
|
|
319
|
+
* had already absorbed them — the scan-stability guard.
|
|
320
|
+
*/
|
|
321
|
+
skipped_absorbed: number;
|
|
322
|
+
/**
|
|
323
|
+
* #439: confirmed merge pairs still un-applied at run end — deadline
|
|
324
|
+
* deferrals at a boundary, a failed pre-merge backup, and lock-busy
|
|
325
|
+
* survivors of the final drain. Each holds the cursor below its
|
|
326
|
+
* candidate and re-detects next run.
|
|
327
|
+
*/
|
|
328
|
+
merge_pairs_deferred: number;
|
|
285
329
|
/**
|
|
286
330
|
* #392: the deterministic merge zone's own report (pairs >= the
|
|
287
331
|
* ceiling, union-find merged, zero LLM). Present on every run —
|
|
@@ -746,6 +790,10 @@ export interface InsertMemoryOptions {
|
|
|
746
790
|
sourceAgentId?: string | null;
|
|
747
791
|
/** Client-declared topic/domain of the capturing agent. Provenance only. */
|
|
748
792
|
sourceDomain?: string | null;
|
|
793
|
+
/** Machine the capture ran on (#421 machine × harness identity). Provenance
|
|
794
|
+
* only — stamped by the nightly (config `machineName` ?? os.hostname()),
|
|
795
|
+
* accepted optionally from /distill + /ingest. Null on pre-v15 rows. */
|
|
796
|
+
sourceMachine?: string | null;
|
|
749
797
|
project?: string | null;
|
|
750
798
|
/** 0.16.x: vestigial — stored but never filtered. null (or absent) when the
|
|
751
799
|
* caller doesn't declare one; an explicit value is honored as-is. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamaze/hicortex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Persistent agent identity for AI agents \u2014 a hand-edited identity layer, nightly-distilled experience, and lessons injected every session, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, Pi, and opencode.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"test:watch": "vitest",
|
|
44
44
|
"eval": "node dist/eval/run-eval.js",
|
|
45
45
|
"eval:planted": "node dist/eval/planted-eval.js",
|
|
46
|
+
"eval:ranking": "node dist/eval/ranking-eval.js",
|
|
47
|
+
"eval:importance": "node dist/eval/importance-eval.js",
|
|
46
48
|
"eval:recall-sweep": "node dist/eval/recall-sweep.js",
|
|
47
49
|
"eval:relevance": "node dist/eval/relevance-eval.js",
|
|
48
50
|
"prepack": "npm run build && rm -rf ./hermes-plugin && mkdir -p ./hermes-plugin && cp -r ../../hermes-plugin/hicortex ./hermes-plugin/ && find ./hermes-plugin -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true && rm -rf ./pi-extension && mkdir -p ./pi-extension && cp -r ../../pi-extension/hicortex ./pi-extension/ && rm -rf ./opencode-plugin && mkdir -p ./opencode-plugin && cp -r ../../opencode-plugin/hicortex ./opencode-plugin/",
|