@gamaze/hicortex 0.20.7 → 0.20.10
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 +18 -41
- package/assets/dashboard.html +3989 -836
- package/dist/calibration.d.ts +293 -0
- package/dist/calibration.js +379 -0
- 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 +24 -3
- package/dist/capture.js +11 -1
- package/dist/classify-domains.d.ts +6 -0
- package/dist/classify-domains.js +7 -1
- package/dist/cli.js +38 -3
- package/dist/config-read.d.ts +1 -1
- package/dist/config-read.js +96 -9
- package/dist/consolidate.d.ts +114 -68
- package/dist/consolidate.js +302 -182
- package/dist/dashboard.d.ts +326 -6
- package/dist/dashboard.js +592 -7
- package/dist/db.js +105 -0
- package/dist/dedup.d.ts +34 -26
- package/dist/dedup.js +91 -57
- package/dist/distiller.js +1 -1
- package/dist/domain-classify.d.ts +7 -6
- package/dist/domain-classify.js +12 -10
- package/dist/eval/decay-eval.d.ts +3 -3
- package/dist/eval/decay-eval.js +4 -4
- package/dist/eval/importance-eval.d.ts +85 -0
- package/dist/eval/importance-eval.js +286 -0
- package/dist/eval/planted-eval.d.ts +26 -0
- package/dist/eval/planted-eval.js +97 -0
- package/dist/eval/planted-fixtures.d.ts +107 -0
- package/dist/eval/planted-fixtures.js +283 -0
- package/dist/eval/planted-harness.d.ts +176 -0
- package/dist/eval/planted-harness.js +649 -0
- 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/index.js +4 -3
- package/dist/init.d.ts +23 -3
- package/dist/init.js +84 -9
- package/dist/llm.d.ts +43 -58
- package/dist/llm.js +87 -101
- package/dist/mcp-server.d.ts +12 -0
- package/dist/mcp-server.js +213 -32
- package/dist/nightly.d.ts +9 -1
- package/dist/nightly.js +164 -110
- package/dist/nofit.d.ts +4 -11
- package/dist/nofit.js +6 -23
- package/dist/prompts.d.ts +10 -0
- package/dist/prompts.js +28 -5
- package/dist/recall-index.d.ts +30 -28
- package/dist/recall-index.js +21 -18
- package/dist/recall-registry.d.ts +2 -1
- package/dist/recall-registry.js +35 -1
- package/dist/reconsolidation.d.ts +168 -87
- package/dist/reconsolidation.js +818 -377
- package/dist/relink.js +3 -4
- package/dist/rescore-importance.d.ts +80 -0
- package/dist/rescore-importance.js +236 -0
- package/dist/retrieval.d.ts +80 -35
- package/dist/retrieval.js +322 -105
- package/dist/run-deadline.d.ts +62 -0
- package/dist/run-deadline.js +73 -0
- package/dist/schema-prototypes.d.ts +3 -3
- package/dist/schema-prototypes.js +3 -3
- package/dist/stages.d.ts +37 -0
- package/dist/stages.js +51 -0
- package/dist/state.d.ts +34 -9
- package/dist/storage.d.ts +50 -18
- package/dist/storage.js +125 -30
- package/dist/telemetry.d.ts +8 -7
- package/dist/token-budget.js +3 -4
- package/dist/type-classify.js +4 -4
- package/dist/types.d.ts +143 -155
- package/domains.example.json +4 -5
- package/hermes-plugin/hicortex/README.md +2 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -1
- package/pi-extension/hicortex/README.md +1 -1
- package/server.json +3 -3
package/dist/type-classify.js
CHANGED
|
@@ -151,10 +151,10 @@ async function classifyMemoryType(content, llm) {
|
|
|
151
151
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
152
152
|
let raw;
|
|
153
153
|
try {
|
|
154
|
-
// No per-call cap (#391): the
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
const r = await llm.
|
|
154
|
+
// No per-call cap (#391/#405): maxTokens — the ONE ceiling — resolves
|
|
155
|
+
// inside complete(); the old hardcoded 20 starved reasoning models
|
|
156
|
+
// whose thinking ate the whole output budget.
|
|
157
|
+
const r = await llm.complete(prompt);
|
|
158
158
|
raw = r.text;
|
|
159
159
|
}
|
|
160
160
|
catch (err) {
|
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 {
|
|
@@ -91,6 +111,8 @@ export interface ResolutionBandStat {
|
|
|
91
111
|
merge: number;
|
|
92
112
|
corrects: number;
|
|
93
113
|
supersedes: number;
|
|
114
|
+
/** #393 guard-C: verdicts that flagged a genuine conflict (link, both kept). */
|
|
115
|
+
conflicts: number;
|
|
94
116
|
none: number;
|
|
95
117
|
/** Merge verdicts below the confidence gate — both memories kept. */
|
|
96
118
|
merge_below_gate: number;
|
|
@@ -100,16 +122,15 @@ export interface ResolutionBandStat {
|
|
|
100
122
|
metadata_skipped?: number;
|
|
101
123
|
}
|
|
102
124
|
/**
|
|
103
|
-
* Report of the deterministic merge zone (#392) — the
|
|
104
|
-
*
|
|
125
|
+
* Report of the deterministic merge zone (#392) — the band at/above the merge
|
|
126
|
+
* ceiling (release-managed since #408; was the dedupAutoMergeThreshold config
|
|
127
|
+
* key), merged by the dedup core's union-find clustering with ZERO LLM calls.
|
|
105
128
|
* Computed in dedup.ts (runDeterministicMergeZone); surfaced verbatim as
|
|
106
129
|
* `stages.reconsolidation.merges`.
|
|
107
130
|
*/
|
|
108
131
|
export interface DeterministicMergeZoneReport {
|
|
109
|
-
/** The cosine ceiling in force (
|
|
132
|
+
/** The cosine ceiling in force (release-managed calibration; default 0.92). */
|
|
110
133
|
threshold: number;
|
|
111
|
-
/** The pacing cap in force (dedupNightlyMaxMerges; 0 = machinery disabled). */
|
|
112
|
-
max_merges: number;
|
|
113
134
|
/** Every cluster found at the threshold (mergeable + mismatch-skipped). */
|
|
114
135
|
clusters_found: number;
|
|
115
136
|
/** Clusters that passed the metadata rails (would merge). */
|
|
@@ -122,8 +143,19 @@ export interface DeterministicMergeZoneReport {
|
|
|
122
143
|
links_repointed: number;
|
|
123
144
|
/** Clusters skipped — members disagree on project / source_agent. */
|
|
124
145
|
skipped_metadata_mismatch: number;
|
|
125
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* #393 guard-C: clusters skipped because a member pair holds a `conflicts`
|
|
148
|
+
* link — a judge-flagged genuine conflict is never blended, both records
|
|
149
|
+
* stay live.
|
|
150
|
+
*/
|
|
151
|
+
skipped_conflict: number;
|
|
152
|
+
/**
|
|
153
|
+
* Mergeable clusters NOT attempted (pacing cap retired, #405): the run
|
|
154
|
+
* deadline fired before them. Deferred clusters drain on the next run.
|
|
155
|
+
*/
|
|
126
156
|
capped: number;
|
|
157
|
+
/** #405: clusters in `capped` that stopped specifically on the deadline. */
|
|
158
|
+
deadline_deferred?: number;
|
|
127
159
|
/** Clusters whose merge transaction failed (rolled back; retried next run). */
|
|
128
160
|
failed: number;
|
|
129
161
|
/** Apply only: the capture lock was busy — zero merges, fail-soft. */
|
|
@@ -144,7 +176,14 @@ export interface ConsolidationReport {
|
|
|
144
176
|
started_at: string;
|
|
145
177
|
completed_at?: string;
|
|
146
178
|
dry_run: boolean;
|
|
147
|
-
|
|
179
|
+
/**
|
|
180
|
+
* "deferred" (#405): the run-wide wall-clock deadline
|
|
181
|
+
* (nightlyTimeBudgetMinutes) fired — at least one stage stopped at a safe
|
|
182
|
+
* boundary and its remaining work drains on the next run (cursors hold
|
|
183
|
+
* below it). Like "endpoint_down" it must NOT advance lastConsolidated,
|
|
184
|
+
* so the pending-set queries re-find the deferred work.
|
|
185
|
+
*/
|
|
186
|
+
status: "completed" | "skipped" | "failed" | "deferred";
|
|
148
187
|
elapsed_seconds?: number;
|
|
149
188
|
stages: {
|
|
150
189
|
precheck?: {
|
|
@@ -178,7 +217,8 @@ export interface ConsolidationReport {
|
|
|
178
217
|
primaries_updated?: number;
|
|
179
218
|
/**
|
|
180
219
|
* No-fit path: memories that earned a WEAK primary (argmax prototype
|
|
181
|
-
* cosine >=
|
|
220
|
+
* cosine >= the weak-primary floor — release-managed since #408) after
|
|
221
|
+
* the LLM found no fitting domain.
|
|
182
222
|
*/
|
|
183
223
|
weak_primary?: number;
|
|
184
224
|
/**
|
|
@@ -217,7 +257,8 @@ export interface ConsolidationReport {
|
|
|
217
257
|
* Reconsolidation (#384) — runs after supersession, before decay/prune.
|
|
218
258
|
* Since #392 this is THE unified resolution stage: its verdict also carries
|
|
219
259
|
* a `merge` disposition, and the deterministic merge zone (pairs at/above
|
|
220
|
-
*
|
|
260
|
+
* the merge ceiling — release-managed since #408) runs inside it,
|
|
261
|
+
* LLM-free, before the scan.
|
|
221
262
|
*/
|
|
222
263
|
reconsolidation?: {
|
|
223
264
|
/** Candidates examined this run (rowid > cursor; no shape filter). */
|
|
@@ -225,14 +266,17 @@ export interface ConsolidationReport {
|
|
|
225
266
|
/** Pairs actually sent to the verdict LLM (detection + explicit-mark verification). */
|
|
226
267
|
pairs_evaluated: number;
|
|
227
268
|
/**
|
|
228
|
-
* #394: pairs the
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
269
|
+
* #394: pairs the detection sources discovered this run, counted before
|
|
270
|
+
* any skip or judgment — the only sizing number a dry-run can show,
|
|
271
|
+
* where pairs_evaluated is always 0. #393 B: BOTH sources join this
|
|
272
|
+
* total (KNN neighbors at/above the correction floor + the scout's
|
|
273
|
+
* FTS hits on correction-shaped memories; see scout_candidates_found
|
|
274
|
+
* for the scout's share).
|
|
232
275
|
*/
|
|
233
276
|
pairs_discovered: number;
|
|
234
277
|
/** #394: discovered pairs with no resolution link yet — the actionable
|
|
235
|
-
* candidates (deterministic-zone work + would-be verdict calls).
|
|
278
|
+
* candidates (deterministic-zone work + would-be verdict calls). #393 B:
|
|
279
|
+
* covers both detection sources. */
|
|
236
280
|
pairs_discovered_unlinked: number;
|
|
237
281
|
/** Targets rewritten in place this run (one history row each). */
|
|
238
282
|
rewritten: number;
|
|
@@ -244,7 +288,7 @@ export interface ConsolidationReport {
|
|
|
244
288
|
marked_superseded: number;
|
|
245
289
|
/** Memories marked status 'retracted' (mark-only: below gate / non-fact / failed contract). */
|
|
246
290
|
marked_retracted: number;
|
|
247
|
-
/** Verdicts that were `corrects` but below
|
|
291
|
+
/** Verdicts that were `corrects` but below the rewrite confidence gate. */
|
|
248
292
|
below_gate: number;
|
|
249
293
|
/** Rewrite groups degraded to mark-only on a failed rewrite contract. */
|
|
250
294
|
contract_failed: number;
|
|
@@ -258,6 +302,30 @@ export interface ConsolidationReport {
|
|
|
258
302
|
explicit_divergent: number;
|
|
259
303
|
/** reconsolidationCursor after this run (unchanged in dry-run). */
|
|
260
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;
|
|
261
329
|
/**
|
|
262
330
|
* #392: the deterministic merge zone's own report (pairs >= the
|
|
263
331
|
* ceiling, union-find merged, zero LLM). Present on every run —
|
|
@@ -267,11 +335,13 @@ export interface ConsolidationReport {
|
|
|
267
335
|
merges: DeterministicMergeZoneReport;
|
|
268
336
|
/** #392: judged-zone pair merges applied this run (merge verdicts at/above the confidence gate). */
|
|
269
337
|
merge_pairs_applied: number;
|
|
270
|
-
/** #392: merge verdicts below
|
|
338
|
+
/** #392: merge verdicts below the rewrite confidence gate — both memories kept. */
|
|
271
339
|
merge_below_gate: number;
|
|
272
340
|
/**
|
|
273
341
|
* #392: pairs the scan saw at/above the ceiling — owned by the
|
|
274
342
|
* deterministic zone (or waiting for its cap), never LLM-judged.
|
|
343
|
+
* #393 B: similarity-source pairs only; the scout's FTS pairs are
|
|
344
|
+
* exempt (no similarity gate — cosine never blocks that source).
|
|
275
345
|
*/
|
|
276
346
|
skipped_above_ceiling: number;
|
|
277
347
|
/**
|
|
@@ -280,6 +350,34 @@ export interface ConsolidationReport {
|
|
|
280
350
|
* the verdict was rendered, this is not an infra failure.
|
|
281
351
|
*/
|
|
282
352
|
skipped_metadata_mismatch: number;
|
|
353
|
+
/**
|
|
354
|
+
* #393 guard-C: verdicts that flagged a genuine conflict — a `conflicts`
|
|
355
|
+
* link was written, both memories stay live (no status change, no
|
|
356
|
+
* rewrite, no merge queue).
|
|
357
|
+
*/
|
|
358
|
+
conflict_flagged: number;
|
|
359
|
+
/**
|
|
360
|
+
* #393 guard-C: merges refused because the pair (deterministic-zone
|
|
361
|
+
* cluster or judged merge) holds a `conflicts` link — aggregates the
|
|
362
|
+
* judged-path refusals plus the zone's `skipped_conflict`. Both records
|
|
363
|
+
* kept live in every case.
|
|
364
|
+
*/
|
|
365
|
+
conflict_skipped: number;
|
|
366
|
+
/**
|
|
367
|
+
* #393 B: memories given the scout's correction-shape call this run
|
|
368
|
+
* (ONE classify-tier call per scanned candidate; always 0 on dry-run —
|
|
369
|
+
* the shape call is LLM work, and dry-runs make zero LLM calls).
|
|
370
|
+
*/
|
|
371
|
+
scout_scanned: number;
|
|
372
|
+
/** #393 B: shape verdicts that flagged a correction/retraction/supersession. */
|
|
373
|
+
scout_correction_shaped: number;
|
|
374
|
+
/**
|
|
375
|
+
* #393 B: FTS hits that became candidate pairs — the scout's share of
|
|
376
|
+
* pairs_discovered (after older-only/self filtering and dedup against
|
|
377
|
+
* the KNN neighbors; a pair found by both sources counts as
|
|
378
|
+
* similarity). Counted before the idempotency skip, the #394 discipline.
|
|
379
|
+
*/
|
|
380
|
+
scout_candidates_found: number;
|
|
283
381
|
/**
|
|
284
382
|
* #392: per-run verdict statistics by cosine band ("0.75-0.8" …
|
|
285
383
|
* ">=0.92"; labels derive from the live floor/ceiling). Calibration
|
|
@@ -407,7 +505,7 @@ export interface HicortexConfig {
|
|
|
407
505
|
* Server-mode `init` scaffolds a generic 5-domain default (Work, Personal,
|
|
408
506
|
* People, Health, Finance — see GENERIC_DEFAULT_DOMAINS in init.ts) when
|
|
409
507
|
* this key is absent, and NEVER touches an existing list. A power-user
|
|
410
|
-
* example (
|
|
508
|
+
* example (a wider life-sphere set) ships as
|
|
411
509
|
* domains.example.json in the package root.
|
|
412
510
|
*
|
|
413
511
|
* NO fallback bucket is needed or special-cased (owner amendment 07.07):
|
|
@@ -437,14 +535,28 @@ export interface HicortexConfig {
|
|
|
437
535
|
*/
|
|
438
536
|
consolidationHours?: number[];
|
|
439
537
|
/**
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
|
|
447
|
-
|
|
538
|
+
* The ONE wall-clock budget (minutes) for a nightly run (#405): capture +
|
|
539
|
+
* every consolidation stage share one cooperative deadline, checked at safe
|
|
540
|
+
* boundaries (capture segments, stage boundaries, item loops, the merge
|
|
541
|
+
* zone). A run whose deadline fires reports consolidation status
|
|
542
|
+
* "deferred" and resumes from its cursors next run — no work is lost or
|
|
543
|
+
* redone. Default 240; 0 or invalid → default (a deadline ALWAYS exists —
|
|
544
|
+
* unlike the retired reconsolidationMaxMinutes, 0 is not "off"). The
|
|
545
|
+
* systemd unit's TimeoutStartSec is derived from this (budget + 60 min
|
|
546
|
+
* slack) at init.
|
|
547
|
+
*/
|
|
548
|
+
nightlyTimeBudgetMinutes?: number;
|
|
549
|
+
/**
|
|
550
|
+
* The ONE per-run ceiling on LLM calls across the whole nightly pipeline
|
|
551
|
+
* (#405; successor of consolidateMaxLlmCalls, #241). Consumed in run
|
|
552
|
+
* order — run order IS the fair share; a stage that exhausts the budget
|
|
553
|
+
* defers its remainder to the next run via its cursor. Bounds money/load
|
|
554
|
+
* independent of latency: a fast metered or capacity-limited endpoint
|
|
555
|
+
* permits thousands of calls inside the wall-clock budget. Default 5000;
|
|
556
|
+
* 0 or invalid → default. The legacy `consolidateMaxLlmCalls` key is
|
|
557
|
+
* honored as a deprecated alias for one release.
|
|
558
|
+
*/
|
|
559
|
+
nightlyLlmCallBudget?: number;
|
|
448
560
|
/**
|
|
449
561
|
* Release channel pinned into the generated daemon/timer ExecStart for
|
|
450
562
|
* **npx-thin** installs (global-binary installs use the absolute binary path
|
|
@@ -454,36 +566,6 @@ export interface HicortexConfig {
|
|
|
454
566
|
* Absent → auto-detect (bare on `latest`, else `@next`). (0.17.1)
|
|
455
567
|
*/
|
|
456
568
|
updateChannel?: string;
|
|
457
|
-
/**
|
|
458
|
-
* Minimum cosine(memory embedding, best domain prototype) for a no-fit
|
|
459
|
-
* memory to earn a WEAK primary instead of decaying (see nofit.ts).
|
|
460
|
-
* Number in (0, 1); default 0.45. Tune from the corpus weight distribution
|
|
461
|
-
* (the memory_tags.weight histogram of LLM-tagged rows — set the floor
|
|
462
|
-
* near its lower tail). See domains.example.json for a worked example.
|
|
463
|
-
*/
|
|
464
|
-
weakPrimaryFloor?: number;
|
|
465
|
-
/**
|
|
466
|
-
* Per-attempt timeout (ms) for the CLIENT nightly's pre-flight GET /health
|
|
467
|
-
* check before capturing (#163). Default 15000. Overridable per machine —
|
|
468
|
-
* a wired Pi vs a sleeping laptop want different values. See runClientNightly
|
|
469
|
-
* in nightly.ts. No effect in server mode (server capture is localhost).
|
|
470
|
-
*/
|
|
471
|
-
preflightTimeoutMs?: number;
|
|
472
|
-
/**
|
|
473
|
-
* Max attempts for the client nightly's pre-flight /health retry loop (#163).
|
|
474
|
-
* Default 3. Attempts are spaced preflightRetryGapMs apart; on exhaustion the
|
|
475
|
-
* run aborts with a non-zero exit code and an ok=false telemetry ping so the
|
|
476
|
-
* failure is visible to systemd/launchd and the activity aggregate.
|
|
477
|
-
*/
|
|
478
|
-
preflightAttempts?: number;
|
|
479
|
-
/**
|
|
480
|
-
* Gap (ms) between pre-flight /health attempts in the client nightly (#163).
|
|
481
|
-
* Default 60000. Wall-clock-optimistic on a sleeping laptop — setTimeout does
|
|
482
|
-
* NOT advance while macOS is asleep, so real elapsed time can exceed the
|
|
483
|
-
* nominal worst case. Not a defect (capture lock isn't held; cursor design is
|
|
484
|
-
* dup-over-loss); just don't treat the nominal sum as a hard bound.
|
|
485
|
-
*/
|
|
486
|
-
preflightRetryGapMs?: number;
|
|
487
569
|
/**
|
|
488
570
|
* Max output tokens for the ONE LLM model used by all phases — distillation,
|
|
489
571
|
* reflection, classification, and scoring. Default 8192. An explicit value
|
|
@@ -492,18 +574,6 @@ export interface HicortexConfig {
|
|
|
492
574
|
* when it finishes early. Read in llm.ts; see #220.
|
|
493
575
|
*/
|
|
494
576
|
maxTokens?: number;
|
|
495
|
-
/**
|
|
496
|
-
* Max output tokens for the classify tier ONLY — the short JSON-verdict
|
|
497
|
-
* calls: correction/supersession verdicts, rewrite contracts, and type +
|
|
498
|
-
* domain tag classification. Default 1024. A ceiling, not a target
|
|
499
|
-
* (generation stops at the model's natural end) — raise it when a
|
|
500
|
-
* reasoning-style model spends the budget on internal reasoning and returns
|
|
501
|
-
* empty verdicts (the pre-#391 hardcoded per-call caps starved exactly that
|
|
502
|
-
* shape; a local non-reasoning model is unaffected by the raise).
|
|
503
|
-
* `maxTokens` continues to govern the heavy phases (distill/reflect).
|
|
504
|
-
* Read in llm.ts; see #391.
|
|
505
|
-
*/
|
|
506
|
-
classifyMaxTokens?: number;
|
|
507
577
|
/**
|
|
508
578
|
* Toggle the model's internal reasoning ("thinking") stream on the openai-compat
|
|
509
579
|
* path — applies to ALL phases (distill / reflect / classify / scoring) since one
|
|
@@ -519,38 +589,6 @@ export interface HicortexConfig {
|
|
|
519
589
|
* anthropic or claude-cli paths. See #220, #231.
|
|
520
590
|
*/
|
|
521
591
|
enableThinking?: boolean;
|
|
522
|
-
/**
|
|
523
|
-
* Context window for ollama (the one model, all phases). Default 8192 — the point
|
|
524
|
-
* where context stops being the binding constraint for a sub-8B model on ollama
|
|
525
|
-
* (above it the SMALL_MODEL_MAX_CHUNK_CHARS speed cap binds instead, so extra
|
|
526
|
-
* context buys nothing). Also drives `detectChunkSize`'s chunk sizing
|
|
527
|
-
* (chunkChars ≤ numCtx × 0.6 × 4 chars), so numCtx is the single dial and the
|
|
528
|
-
* chunker/request agreement is enforced by construction (#228). For an ≥8B model
|
|
529
|
-
* on ollama the speed cap is 60,000 chars, needing numCtx ≈ 25000 to reach — raise
|
|
530
|
-
* it if running 8B+ locally. No effect for non-ollama providers.
|
|
531
|
-
*/
|
|
532
|
-
numCtx?: number;
|
|
533
|
-
/**
|
|
534
|
-
* Flush ollama's accumulated memory every N scoring calls — workaround for
|
|
535
|
-
* ollama's per-request memory growth (the runner's RSS climbs ~171 MB/call and
|
|
536
|
-
* isn't freed between requests), which swap-thrashes RAM-constrained boxes
|
|
537
|
-
* during long consolidations. Default 0 (off). When >0, every Nth scoring call
|
|
538
|
-
* (`completeFast`) triggers a `keep_alive:0` unload + an `ollamaFlushWaitMs`
|
|
539
|
-
* pause for the runner to exit + release, then the next call reloads fresh.
|
|
540
|
-
* N=15 caps a cycle at ~2.5 GB. Scoped to the fast tier (scoring) only. Note:
|
|
541
|
-
* N counts **logical** scoring calls, not raw HTTP requests — `complete()`
|
|
542
|
-
* retries up to 4× on timeout, so under retry pressure the actual accumulation
|
|
543
|
-
* may be up to 4×N calls' worth. In practice the flush prevents the thrash that
|
|
544
|
-
* causes retries, keeping the count accurate.
|
|
545
|
-
*/
|
|
546
|
-
ollamaFlushEvery?: number;
|
|
547
|
-
/**
|
|
548
|
-
* Milliseconds to wait after an ollama flush (`keep_alive:0`) for the runner
|
|
549
|
-
* to exit + release its accumulated memory before the next call reloads.
|
|
550
|
-
* Default 180000 (3 min — the runner takes >90 s to exit after keep_alive:0;
|
|
551
|
-
* doubled for margin). Only relevant when `ollamaFlushEvery` > 0.
|
|
552
|
-
*/
|
|
553
|
-
ollamaFlushWaitMs?: number;
|
|
554
592
|
/**
|
|
555
593
|
* ONE per-attempt timeout ceiling (ms) for every LLM phase — distill,
|
|
556
594
|
* reflect, classify, and scoring alike (#337). Default 900000 (15 min). The
|
|
@@ -564,21 +602,6 @@ export interface HicortexConfig {
|
|
|
564
602
|
* claude-cli (subprocess timeout).
|
|
565
603
|
*/
|
|
566
604
|
llmTimeoutMs?: number;
|
|
567
|
-
/**
|
|
568
|
-
* Consecutive ladder-exhausted TOTAL failures (fetch-failed / ECONNREFUSED /
|
|
569
|
-
* timeout / "Headers Timeout" class) after which the per-endpoint circuit
|
|
570
|
-
* breaker opens (#337). Default 3; `0` disables. While open, calls throw
|
|
571
|
-
* `LlmCircuitOpenError` immediately with NO network I/O. HTTP error statuses
|
|
572
|
-
* with a response, parse errors, and rate limits never count (they throw
|
|
573
|
-
* before the retry ladder can be exhausted). Any success resets the counter.
|
|
574
|
-
*/
|
|
575
|
-
llmBreakerThreshold?: number;
|
|
576
|
-
/**
|
|
577
|
-
* How long (ms) an open circuit breaker stays open before the next call
|
|
578
|
-
* becomes a half-open trial (#337). Default 600000 (10 min). A trial failure
|
|
579
|
-
* re-opens the breaker; a trial success resets it.
|
|
580
|
-
*/
|
|
581
|
-
llmBreakerCooldownMs?: number;
|
|
582
605
|
/**
|
|
583
606
|
* Timeout (ms) for the readiness probe's single 1-token generation attempt
|
|
584
607
|
* (#337). Default 60000. The probe asks "can this endpoint GENERATE", which
|
|
@@ -610,8 +633,8 @@ export interface HicortexConfig {
|
|
|
610
633
|
/**
|
|
611
634
|
* Max memories per recall on the OpenClaw plugin's legacy /search fallback
|
|
612
635
|
* (pre-0.14 servers, #316). Default 8. Does NOT size the pushed
|
|
613
|
-
* /recall-index — that is
|
|
614
|
-
* accepts no client limit.
|
|
636
|
+
* /recall-index — that is sized by the server's release-managed calibration
|
|
637
|
+
* (#408); the server accepts no client limit.
|
|
615
638
|
*/
|
|
616
639
|
recallLimit?: number;
|
|
617
640
|
/**
|
|
@@ -706,45 +729,6 @@ export interface HicortexConfig {
|
|
|
706
729
|
orgName?: string;
|
|
707
730
|
/** Plan/tier label rendered as a small badge (e.g. "Cloud · Early bird"). */
|
|
708
731
|
planLabel?: string;
|
|
709
|
-
/**
|
|
710
|
-
* Minimum cosine similarity for a reconsolidation candidate pair (#384):
|
|
711
|
-
* each new-since-cursor memory is paired with up to 5 older KNN neighbors
|
|
712
|
-
* at/above this bar before the verdict call. Default 0.75 — a touch wider
|
|
713
|
-
* than the supersession stage's 0.80 because a retraction often rides inside
|
|
714
|
-
* an otherwise unrelated memory; the verdict + confidence gate carry the
|
|
715
|
-
* precision. Number in (0, 1]; invalid/absent keeps the default.
|
|
716
|
-
*/
|
|
717
|
-
correctionMinSimilarity?: number;
|
|
718
|
-
/**
|
|
719
|
-
* Minimum verdict confidence for the REWRITE fork of reconsolidation (#384):
|
|
720
|
-
* a `corrects` verdict at/above this bar on a fact-shaped target is rewritten
|
|
721
|
-
* in place; below it the pair degrades to mark-only (a weak mark is
|
|
722
|
-
* recoverable, a weak rewrite is corruption). Default 0.80. Number in
|
|
723
|
-
* (0, 1]; invalid/absent keeps the default. Since #392 this same gate also
|
|
724
|
-
* decides whether a `merge` verdict is applied (analogous reasoning: a weak
|
|
725
|
-
* merge keeps both memories, a confirmed merge hides one).
|
|
726
|
-
*/
|
|
727
|
-
correctionRewriteMinConfidence?: number;
|
|
728
|
-
/**
|
|
729
|
-
* Deterministic merge ceiling for the unified resolution pass (#392): memory
|
|
730
|
-
* pairs at/above this cosine are merged by the dedup core's union-find
|
|
731
|
-
* clustering with ZERO LLM calls; pairs in [correctionMinSimilarity, this
|
|
732
|
-
* value) get the one unified verdict call (merge/corrects/supersedes/none).
|
|
733
|
-
* Default 0.92 (the #100/#191 calibration). The legacy `dedupMergeThreshold`
|
|
734
|
-
* key is honored as a fallback when this key is absent. Number in (0, 1];
|
|
735
|
-
* invalid/absent keeps the default. Also read by the manual `hicortex dedup`
|
|
736
|
-
* CLI (same precedence: --threshold > this key > legacy key > 0.92).
|
|
737
|
-
*/
|
|
738
|
-
dedupAutoMergeThreshold?: number;
|
|
739
|
-
/**
|
|
740
|
-
* Pacing cap on merge OPERATIONS per nightly run (#392): deterministic-zone
|
|
741
|
-
* clusters plus judged pair merges count against ONE cap, so a
|
|
742
|
-
* misbehaving-distiller burst is bounded and a large pre-existing backlog
|
|
743
|
-
* drains over a few nights rather than in one run. Default 250. `0` disables
|
|
744
|
-
* the merge machinery entirely (the deterministic zone is skipped; a
|
|
745
|
-
* confirmed merge verdict keeps both memories). Non-negative integer.
|
|
746
|
-
*/
|
|
747
|
-
dedupNightlyMaxMerges?: number;
|
|
748
732
|
}
|
|
749
733
|
/** A config-owned life-sphere domain (see HicortexConfig.domains). */
|
|
750
734
|
export interface DomainDef {
|
|
@@ -806,6 +790,10 @@ export interface InsertMemoryOptions {
|
|
|
806
790
|
sourceAgentId?: string | null;
|
|
807
791
|
/** Client-declared topic/domain of the capturing agent. Provenance only. */
|
|
808
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;
|
|
809
797
|
project?: string | null;
|
|
810
798
|
/** 0.16.x: vestigial — stored but never filtered. null (or absent) when the
|
|
811
799
|
* caller doesn't declare one; an explicit value is honored as-is. */
|
package/domains.example.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_readme": [
|
|
3
3
|
"Hicortex memory domains — example config.",
|
|
4
|
-
"Copy the `domains` key
|
|
4
|
+
"Copy the `domains` key into ~/.hicortex/config.json on the SERVER machine.",
|
|
5
5
|
"Domains are your top-level memory spheres. Each memory gets multiple weighted tags plus a derived primary.",
|
|
6
6
|
"They can be life areas OR project/topic areas — edit to match how YOU think.",
|
|
7
7
|
"The `domains` list below is the generic default that `hicortex init` scaffolds automatically.",
|
|
8
|
-
"There is NO fallback category: memories that fit nothing are handled automatically (weak-primary floor + decay).",
|
|
8
|
+
"There is NO fallback category: memories that fit nothing are handled automatically (weak-primary floor + decay — release-managed calibration, not config).",
|
|
9
9
|
"Backfill an existing corpus with: hicortex classify-domains"
|
|
10
10
|
],
|
|
11
11
|
"domains": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"_readme": [
|
|
35
35
|
"A narrower life-sphere set for users who want tighter buckets.",
|
|
36
36
|
"The PRIMARY domain is derived by argmax association weight (LLM tag order breaks ties) — no manual override flag.",
|
|
37
|
-
"
|
|
37
|
+
"The weak-primary floor is release-managed since #408 (a calibration constant shipped with each release) — not a config key."
|
|
38
38
|
],
|
|
39
39
|
"domains": [
|
|
40
40
|
{
|
|
@@ -69,7 +69,6 @@
|
|
|
69
69
|
"name": "Travel",
|
|
70
70
|
"description": "Trips, destinations, bookings, travel plans"
|
|
71
71
|
}
|
|
72
|
-
]
|
|
73
|
-
"weakPrimaryFloor": 0.5
|
|
72
|
+
]
|
|
74
73
|
}
|
|
75
74
|
}
|
|
@@ -22,7 +22,7 @@ That's the whole surface. No `sync_turn`, no compaction/session-end capture —
|
|
|
22
22
|
|
|
23
23
|
### Pushed recall index (0.7.0, server ≥ 0.14)
|
|
24
24
|
|
|
25
|
-
Instead of injecting full memory content every turn, `prefetch` sends the user's message to the server's `POST /recall-index` and injects the returned **index block** verbatim — one line per memory (id, title, date), capped and relevance-gated server-side. The agent fetches full content with `hicortex_get(id)` only when a line is actually relevant; that fetch is what strengthens the memory (exposure ≠ use). All tuning knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, `recallMinPromptChars`, …)
|
|
25
|
+
Instead of injecting full memory content every turn, `prefetch` sends the user's message to the server's `POST /recall-index` and injects the returned **index block** verbatim — one line per memory (id, title, date), capped and relevance-gated server-side. The agent fetches full content with `hicortex_get(id)` only when a line is actually relevant; that fetch is what strengthens the memory (exposure ≠ use). All tuning knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, `recallMinPromptChars`, …) are release-managed constants on the server (they ship with each release and change only with published eval evidence) — the plugin carries none, and neither does the server's config. Dedup is turn-based and server-side per session; the plugin resets it at `initialize` (the Hermes `MemoryProvider` interface exposes no compaction signal, so a mid-session context rebuild cannot trigger a reset — the server's turn-based re-show window covers that gap). Against a pre-0.14 server (404) the plugin falls back to the 0.6.x `GET /search` full-content prefetch, fail-soft, re-probing the endpoint every 10 minutes so a later server upgrade is picked up without a gateway restart. The recall calls carry the profile's configured `default_project` (and `mission_domains`) and use a short dedicated timeout (1.5 s) so a slow server can never stall a turn. (`privacy_filter` is deprecated since 0.7.2 — the server ignores privacy; see [Configuration](#configure-activate).)
|
|
26
26
|
|
|
27
27
|
### Per-agent standing context (0.13)
|
|
28
28
|
|
|
@@ -78,7 +78,7 @@ hermes memory setup # select "hicortex", enter the server URL/token when promp
|
|
|
78
78
|
|
|
79
79
|
Run it once per profile if you use Hermes profiles. Hermes allows **one** external memory provider at a time, so disable Honcho (or any other) first, then restart the gateway.
|
|
80
80
|
|
|
81
|
-
Setup asks exactly two questions: the **server URL** and the **auth token**. Everything else has a correct default and is configured — if ever needed — directly in `$HERMES_HOME/plugins/hicortex/config.json`: `default_project` (blank = memories unattributed), `recall_limit` (default 5; sizes the tools and the legacy `/search` fallback only — the pushed recall index is sized by
|
|
81
|
+
Setup asks exactly two questions: the **server URL** and the **auth token**. Everything else has a correct default and is configured — if ever needed — directly in `$HERMES_HOME/plugins/hicortex/config.json`: `default_project` (blank = memories unattributed), `recall_limit` (default 5; sizes the tools and the legacy `/search` fallback only — the pushed recall index is sized by the server's release-managed calibration), `agent_name` (blank auto-derives from the running profile; pin it only for fleet re-installs — see [Per-agent standing context](#per-agent-standing-context-013)), and `mission_domains` (blank = off; an optional recall boost keyed to the server's domain vocabulary). The auth token is a **secret** — set it via env, not the JSON file:
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
export HICORTEX_AUTH_TOKEN=hctx-<your-token> # or your custom token
|
package/openclaw.plugin.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"recallLimit": {
|
|
25
25
|
"type": "number",
|
|
26
26
|
"default": 8,
|
|
27
|
-
"description": "Max memories per recall on the pre-0.14 /search fallback (default 8). The pushed recall index is sized by
|
|
27
|
+
"description": "Max memories per recall on the pre-0.14 /search fallback (default 8). The pushed recall index is sized by the server's release-managed calibration — the server accepts no client limit."
|
|
28
28
|
},
|
|
29
29
|
"scaffoldDeadMan": {
|
|
30
30
|
"type": "boolean",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamaze/hicortex",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.10",
|
|
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": {
|
|
@@ -42,6 +42,9 @@
|
|
|
42
42
|
"test": "vitest run",
|
|
43
43
|
"test:watch": "vitest",
|
|
44
44
|
"eval": "node dist/eval/run-eval.js",
|
|
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",
|
|
45
48
|
"eval:recall-sweep": "node dist/eval/recall-sweep.js",
|
|
46
49
|
"eval:relevance": "node dist/eval/relevance-eval.js",
|
|
47
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/",
|
|
@@ -18,7 +18,7 @@ Gives [Pi](https://pi.dev) agents self-learning memory backed by a Hicortex serv
|
|
|
18
18
|
|
|
19
19
|
### Pushed recall index
|
|
20
20
|
|
|
21
|
-
Each user prompt is POSTed to the server's `/recall-index`; the returned **index block** (one line per relevant memory: id, title, date) is injected into the turn. All gating and dedup knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, …)
|
|
21
|
+
Each user prompt is POSTed to the server's `/recall-index`; the returned **index block** (one line per relevant memory: id, title, date) is injected into the turn. All gating and dedup knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, …) are release-managed constants on the server (they ship with each release and change only with published eval evidence) — the extension carries none, and neither does the server's config. A dedup reset fired at session start is awaited by the first turn's recall POST, so it can never land after it and wipe the turn state.
|
|
22
22
|
|
|
23
23
|
### Identity layer
|
|
24
24
|
|
package/server.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.gamaze-labs/hicortex",
|
|
4
4
|
"title": "Hicortex",
|
|
5
|
-
"description": "Shared fleet memory for AI agents
|
|
6
|
-
"version": "0.20.
|
|
5
|
+
"description": "Shared fleet memory for AI agents: nightly self-correction, recall every prompt (supported agents).",
|
|
6
|
+
"version": "0.20.9",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "@gamaze/hicortex",
|
|
11
|
-
"version": "0.20.
|
|
11
|
+
"version": "0.20.9",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio",
|
|
14
14
|
"command": "npx",
|