@gamaze/hicortex 0.20.7 → 0.20.9

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.
Files changed (61) hide show
  1. package/README.md +10 -41
  2. package/dist/calibration.d.ts +174 -0
  3. package/dist/calibration.js +231 -0
  4. package/dist/capture.d.ts +15 -3
  5. package/dist/capture.js +10 -1
  6. package/dist/classify-domains.d.ts +6 -0
  7. package/dist/classify-domains.js +7 -1
  8. package/dist/cli.js +2 -3
  9. package/dist/config-read.d.ts +1 -1
  10. package/dist/config-read.js +96 -9
  11. package/dist/consolidate.d.ts +79 -68
  12. package/dist/consolidate.js +218 -174
  13. package/dist/dashboard.d.ts +4 -3
  14. package/dist/dedup.d.ts +34 -26
  15. package/dist/dedup.js +91 -57
  16. package/dist/distiller.js +1 -1
  17. package/dist/domain-classify.d.ts +7 -6
  18. package/dist/domain-classify.js +12 -10
  19. package/dist/eval/decay-eval.d.ts +3 -3
  20. package/dist/eval/decay-eval.js +4 -4
  21. package/dist/eval/planted-eval.d.ts +26 -0
  22. package/dist/eval/planted-eval.js +97 -0
  23. package/dist/eval/planted-fixtures.d.ts +107 -0
  24. package/dist/eval/planted-fixtures.js +283 -0
  25. package/dist/eval/planted-harness.d.ts +176 -0
  26. package/dist/eval/planted-harness.js +649 -0
  27. package/dist/index.js +4 -3
  28. package/dist/init.d.ts +9 -3
  29. package/dist/init.js +52 -9
  30. package/dist/llm.d.ts +43 -58
  31. package/dist/llm.js +87 -101
  32. package/dist/mcp-server.js +29 -29
  33. package/dist/nightly.js +105 -103
  34. package/dist/nofit.d.ts +4 -11
  35. package/dist/nofit.js +6 -23
  36. package/dist/recall-index.d.ts +30 -28
  37. package/dist/recall-index.js +21 -18
  38. package/dist/recall-registry.d.ts +2 -1
  39. package/dist/recall-registry.js +35 -1
  40. package/dist/reconsolidation.d.ts +124 -72
  41. package/dist/reconsolidation.js +359 -148
  42. package/dist/relink.js +3 -4
  43. package/dist/retrieval.d.ts +68 -35
  44. package/dist/retrieval.js +292 -104
  45. package/dist/run-deadline.d.ts +62 -0
  46. package/dist/run-deadline.js +73 -0
  47. package/dist/schema-prototypes.d.ts +3 -3
  48. package/dist/schema-prototypes.js +3 -3
  49. package/dist/state.d.ts +2 -3
  50. package/dist/storage.d.ts +16 -16
  51. package/dist/storage.js +62 -24
  52. package/dist/telemetry.d.ts +8 -7
  53. package/dist/token-budget.js +3 -4
  54. package/dist/type-classify.js +4 -4
  55. package/dist/types.d.ts +95 -155
  56. package/domains.example.json +4 -5
  57. package/hermes-plugin/hicortex/README.md +2 -2
  58. package/openclaw.plugin.json +1 -1
  59. package/package.json +2 -1
  60. package/pi-extension/hicortex/README.md +1 -1
  61. package/server.json +3 -3
package/dist/types.d.ts CHANGED
@@ -91,6 +91,8 @@ export interface ResolutionBandStat {
91
91
  merge: number;
92
92
  corrects: number;
93
93
  supersedes: number;
94
+ /** #393 guard-C: verdicts that flagged a genuine conflict (link, both kept). */
95
+ conflicts: number;
94
96
  none: number;
95
97
  /** Merge verdicts below the confidence gate — both memories kept. */
96
98
  merge_below_gate: number;
@@ -100,16 +102,15 @@ export interface ResolutionBandStat {
100
102
  metadata_skipped?: number;
101
103
  }
102
104
  /**
103
- * Report of the deterministic merge zone (#392) — the >= dedupAutoMergeThreshold
104
- * band, merged by the dedup core's union-find clustering with ZERO LLM calls.
105
+ * Report of the deterministic merge zone (#392) — the band at/above the merge
106
+ * ceiling (release-managed since #408; was the dedupAutoMergeThreshold config
107
+ * key), merged by the dedup core's union-find clustering with ZERO LLM calls.
105
108
  * Computed in dedup.ts (runDeterministicMergeZone); surfaced verbatim as
106
109
  * `stages.reconsolidation.merges`.
107
110
  */
108
111
  export interface DeterministicMergeZoneReport {
109
- /** The cosine ceiling in force (config dedupAutoMergeThreshold; default 0.92). */
112
+ /** The cosine ceiling in force (release-managed calibration; default 0.92). */
110
113
  threshold: number;
111
- /** The pacing cap in force (dedupNightlyMaxMerges; 0 = machinery disabled). */
112
- max_merges: number;
113
114
  /** Every cluster found at the threshold (mergeable + mismatch-skipped). */
114
115
  clusters_found: number;
115
116
  /** Clusters that passed the metadata rails (would merge). */
@@ -122,8 +123,19 @@ export interface DeterministicMergeZoneReport {
122
123
  links_repointed: number;
123
124
  /** Clusters skipped — members disagree on project / source_agent. */
124
125
  skipped_metadata_mismatch: number;
125
- /** Mergeable clusters NOT attempted because the pacing cap was exhausted. */
126
+ /**
127
+ * #393 guard-C: clusters skipped because a member pair holds a `conflicts`
128
+ * link — a judge-flagged genuine conflict is never blended, both records
129
+ * stay live.
130
+ */
131
+ skipped_conflict: number;
132
+ /**
133
+ * Mergeable clusters NOT attempted (pacing cap retired, #405): the run
134
+ * deadline fired before them. Deferred clusters drain on the next run.
135
+ */
126
136
  capped: number;
137
+ /** #405: clusters in `capped` that stopped specifically on the deadline. */
138
+ deadline_deferred?: number;
127
139
  /** Clusters whose merge transaction failed (rolled back; retried next run). */
128
140
  failed: number;
129
141
  /** Apply only: the capture lock was busy — zero merges, fail-soft. */
@@ -144,7 +156,14 @@ export interface ConsolidationReport {
144
156
  started_at: string;
145
157
  completed_at?: string;
146
158
  dry_run: boolean;
147
- status: "completed" | "skipped" | "failed";
159
+ /**
160
+ * "deferred" (#405): the run-wide wall-clock deadline
161
+ * (nightlyTimeBudgetMinutes) fired — at least one stage stopped at a safe
162
+ * boundary and its remaining work drains on the next run (cursors hold
163
+ * below it). Like "endpoint_down" it must NOT advance lastConsolidated,
164
+ * so the pending-set queries re-find the deferred work.
165
+ */
166
+ status: "completed" | "skipped" | "failed" | "deferred";
148
167
  elapsed_seconds?: number;
149
168
  stages: {
150
169
  precheck?: {
@@ -178,7 +197,8 @@ export interface ConsolidationReport {
178
197
  primaries_updated?: number;
179
198
  /**
180
199
  * No-fit path: memories that earned a WEAK primary (argmax prototype
181
- * cosine >= weakPrimaryFloor) after the LLM found no fitting domain.
200
+ * cosine >= the weak-primary floor — release-managed since #408) after
201
+ * the LLM found no fitting domain.
182
202
  */
183
203
  weak_primary?: number;
184
204
  /**
@@ -217,7 +237,8 @@ export interface ConsolidationReport {
217
237
  * Reconsolidation (#384) — runs after supersession, before decay/prune.
218
238
  * Since #392 this is THE unified resolution stage: its verdict also carries
219
239
  * a `merge` disposition, and the deterministic merge zone (pairs at/above
220
- * `dedupAutoMergeThreshold`) runs inside it, LLM-free, before the scan.
240
+ * the merge ceiling — release-managed since #408) runs inside it,
241
+ * LLM-free, before the scan.
221
242
  */
222
243
  reconsolidation?: {
223
244
  /** Candidates examined this run (rowid > cursor; no shape filter). */
@@ -225,14 +246,17 @@ export interface ConsolidationReport {
225
246
  /** Pairs actually sent to the verdict LLM (detection + explicit-mark verification). */
226
247
  pairs_evaluated: number;
227
248
  /**
228
- * #394: pairs the similarity floor discovered this run (KNN neighbors
229
- * at/above correctionMinSimilarity), counted before any skip or
230
- * judgment — the only sizing number a dry-run can show, where
231
- * pairs_evaluated is always 0.
249
+ * #394: pairs the detection sources discovered this run, counted before
250
+ * any skip or judgment — the only sizing number a dry-run can show,
251
+ * where pairs_evaluated is always 0. #393 B: BOTH sources join this
252
+ * total (KNN neighbors at/above the correction floor + the scout's
253
+ * FTS hits on correction-shaped memories; see scout_candidates_found
254
+ * for the scout's share).
232
255
  */
233
256
  pairs_discovered: number;
234
257
  /** #394: discovered pairs with no resolution link yet — the actionable
235
- * candidates (deterministic-zone work + would-be verdict calls). */
258
+ * candidates (deterministic-zone work + would-be verdict calls). #393 B:
259
+ * covers both detection sources. */
236
260
  pairs_discovered_unlinked: number;
237
261
  /** Targets rewritten in place this run (one history row each). */
238
262
  rewritten: number;
@@ -244,7 +268,7 @@ export interface ConsolidationReport {
244
268
  marked_superseded: number;
245
269
  /** Memories marked status 'retracted' (mark-only: below gate / non-fact / failed contract). */
246
270
  marked_retracted: number;
247
- /** Verdicts that were `corrects` but below correctionRewriteMinConfidence. */
271
+ /** Verdicts that were `corrects` but below the rewrite confidence gate. */
248
272
  below_gate: number;
249
273
  /** Rewrite groups degraded to mark-only on a failed rewrite contract. */
250
274
  contract_failed: number;
@@ -267,11 +291,13 @@ export interface ConsolidationReport {
267
291
  merges: DeterministicMergeZoneReport;
268
292
  /** #392: judged-zone pair merges applied this run (merge verdicts at/above the confidence gate). */
269
293
  merge_pairs_applied: number;
270
- /** #392: merge verdicts below correctionRewriteMinConfidence — both memories kept. */
294
+ /** #392: merge verdicts below the rewrite confidence gate — both memories kept. */
271
295
  merge_below_gate: number;
272
296
  /**
273
297
  * #392: pairs the scan saw at/above the ceiling — owned by the
274
298
  * deterministic zone (or waiting for its cap), never LLM-judged.
299
+ * #393 B: similarity-source pairs only; the scout's FTS pairs are
300
+ * exempt (no similarity gate — cosine never blocks that source).
275
301
  */
276
302
  skipped_above_ceiling: number;
277
303
  /**
@@ -280,6 +306,34 @@ export interface ConsolidationReport {
280
306
  * the verdict was rendered, this is not an infra failure.
281
307
  */
282
308
  skipped_metadata_mismatch: number;
309
+ /**
310
+ * #393 guard-C: verdicts that flagged a genuine conflict — a `conflicts`
311
+ * link was written, both memories stay live (no status change, no
312
+ * rewrite, no merge queue).
313
+ */
314
+ conflict_flagged: number;
315
+ /**
316
+ * #393 guard-C: merges refused because the pair (deterministic-zone
317
+ * cluster or judged merge) holds a `conflicts` link — aggregates the
318
+ * judged-path refusals plus the zone's `skipped_conflict`. Both records
319
+ * kept live in every case.
320
+ */
321
+ conflict_skipped: number;
322
+ /**
323
+ * #393 B: memories given the scout's correction-shape call this run
324
+ * (ONE classify-tier call per scanned candidate; always 0 on dry-run —
325
+ * the shape call is LLM work, and dry-runs make zero LLM calls).
326
+ */
327
+ scout_scanned: number;
328
+ /** #393 B: shape verdicts that flagged a correction/retraction/supersession. */
329
+ scout_correction_shaped: number;
330
+ /**
331
+ * #393 B: FTS hits that became candidate pairs — the scout's share of
332
+ * pairs_discovered (after older-only/self filtering and dedup against
333
+ * the KNN neighbors; a pair found by both sources counts as
334
+ * similarity). Counted before the idempotency skip, the #394 discipline.
335
+ */
336
+ scout_candidates_found: number;
283
337
  /**
284
338
  * #392: per-run verdict statistics by cosine band ("0.75-0.8" …
285
339
  * ">=0.92"; labels derive from the live floor/ceiling). Calibration
@@ -407,7 +461,7 @@ export interface HicortexConfig {
407
461
  * Server-mode `init` scaffolds a generic 5-domain default (Work, Personal,
408
462
  * People, Health, Finance — see GENERIC_DEFAULT_DOMAINS in init.ts) when
409
463
  * this key is absent, and NEVER touches an existing list. A power-user
410
- * example (custom weakPrimaryFloor) ships as
464
+ * example (a wider life-sphere set) ships as
411
465
  * domains.example.json in the package root.
412
466
  *
413
467
  * NO fallback bucket is needed or special-cased (owner amendment 07.07):
@@ -437,14 +491,28 @@ export interface HicortexConfig {
437
491
  */
438
492
  consolidationHours?: number[];
439
493
  /**
440
- * Ceiling on total LLM calls across all classify-tier consolidation stages
441
- * (content-domain, link discovery, supersession) per nightly run (0.17, #241).
442
- * A runaway backstop, not a throughput throttle — on a free local model the
443
- * binding constraint is the nightly unit's wall-clock timeout, not call count.
444
- * Default `5000` (was a hard-coded 200 that starved link/supersession during a
445
- * classification backlog and drained large backlogs at ~cap/night).
446
- */
447
- consolidateMaxLlmCalls?: number;
494
+ * The ONE wall-clock budget (minutes) for a nightly run (#405): capture +
495
+ * every consolidation stage share one cooperative deadline, checked at safe
496
+ * boundaries (capture segments, stage boundaries, item loops, the merge
497
+ * zone). A run whose deadline fires reports consolidation status
498
+ * "deferred" and resumes from its cursors next run — no work is lost or
499
+ * redone. Default 240; 0 or invalid → default (a deadline ALWAYS exists —
500
+ * unlike the retired reconsolidationMaxMinutes, 0 is not "off"). The
501
+ * systemd unit's TimeoutStartSec is derived from this (budget + 60 min
502
+ * slack) at init.
503
+ */
504
+ nightlyTimeBudgetMinutes?: number;
505
+ /**
506
+ * The ONE per-run ceiling on LLM calls across the whole nightly pipeline
507
+ * (#405; successor of consolidateMaxLlmCalls, #241). Consumed in run
508
+ * order — run order IS the fair share; a stage that exhausts the budget
509
+ * defers its remainder to the next run via its cursor. Bounds money/load
510
+ * independent of latency: a fast metered or capacity-limited endpoint
511
+ * permits thousands of calls inside the wall-clock budget. Default 5000;
512
+ * 0 or invalid → default. The legacy `consolidateMaxLlmCalls` key is
513
+ * honored as a deprecated alias for one release.
514
+ */
515
+ nightlyLlmCallBudget?: number;
448
516
  /**
449
517
  * Release channel pinned into the generated daemon/timer ExecStart for
450
518
  * **npx-thin** installs (global-binary installs use the absolute binary path
@@ -454,36 +522,6 @@ export interface HicortexConfig {
454
522
  * Absent → auto-detect (bare on `latest`, else `@next`). (0.17.1)
455
523
  */
456
524
  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
525
  /**
488
526
  * Max output tokens for the ONE LLM model used by all phases — distillation,
489
527
  * reflection, classification, and scoring. Default 8192. An explicit value
@@ -492,18 +530,6 @@ export interface HicortexConfig {
492
530
  * when it finishes early. Read in llm.ts; see #220.
493
531
  */
494
532
  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
533
  /**
508
534
  * Toggle the model's internal reasoning ("thinking") stream on the openai-compat
509
535
  * path — applies to ALL phases (distill / reflect / classify / scoring) since one
@@ -519,38 +545,6 @@ export interface HicortexConfig {
519
545
  * anthropic or claude-cli paths. See #220, #231.
520
546
  */
521
547
  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
548
  /**
555
549
  * ONE per-attempt timeout ceiling (ms) for every LLM phase — distill,
556
550
  * reflect, classify, and scoring alike (#337). Default 900000 (15 min). The
@@ -564,21 +558,6 @@ export interface HicortexConfig {
564
558
  * claude-cli (subprocess timeout).
565
559
  */
566
560
  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
561
  /**
583
562
  * Timeout (ms) for the readiness probe's single 1-token generation attempt
584
563
  * (#337). Default 60000. The probe asks "can this endpoint GENERATE", which
@@ -610,8 +589,8 @@ export interface HicortexConfig {
610
589
  /**
611
590
  * Max memories per recall on the OpenClaw plugin's legacy /search fallback
612
591
  * (pre-0.14 servers, #316). Default 8. Does NOT size the pushed
613
- * /recall-index — that is server config (`recallMaxItems`); the server
614
- * accepts no client limit.
592
+ * /recall-index — that is sized by the server's release-managed calibration
593
+ * (#408); the server accepts no client limit.
615
594
  */
616
595
  recallLimit?: number;
617
596
  /**
@@ -706,45 +685,6 @@ export interface HicortexConfig {
706
685
  orgName?: string;
707
686
  /** Plan/tier label rendered as a small badge (e.g. "Cloud · Early bird"). */
708
687
  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
688
  }
749
689
  /** A config-owned life-sphere domain (see HicortexConfig.domains). */
750
690
  export interface DomainDef {
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "_readme": [
3
3
  "Hicortex memory domains — example config.",
4
- "Copy the `domains` key (and optionally `weakPrimaryFloor`) into ~/.hicortex/config.json on the SERVER machine.",
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
- "`weakPrimaryFloor` (default 0.45) is the minimum embedding similarity for a no-fit memory to earn a weak primary; tune it from your corpus."
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`, …) live in the **server** config — the plugin carries none. 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).)
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 SERVER config `recallMaxItems`), `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:
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
@@ -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 SERVER config (recallMaxItems) — the server accepts no client limit."
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.7",
3
+ "version": "0.20.9",
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,7 @@
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",
45
46
  "eval:recall-sweep": "node dist/eval/recall-sweep.js",
46
47
  "eval:relevance": "node dist/eval/relevance-eval.js",
47
48
  "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`, …) live in the **server** config — the extension carries none. 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.
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 \u2014 what one agent learns, the whole fleet knows.",
6
- "version": "0.20.5",
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.5",
11
+ "version": "0.20.9",
12
12
  "transport": {
13
13
  "type": "stdio",
14
14
  "command": "npx",