@gamaze/hicortex 0.22.2 → 0.23.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 +4 -2
- package/assets/dashboard.html +9 -35
- package/dist/calibration.d.ts +26 -11
- package/dist/calibration.js +33 -13
- package/dist/capture.js +4 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +26 -0
- package/dist/cluster.d.ts +8 -5
- package/dist/cluster.js +3 -7
- package/dist/consolidate.d.ts +4 -64
- package/dist/consolidate.js +15 -285
- package/dist/db.js +21 -0
- package/dist/dedup.d.ts +14 -9
- package/dist/dedup.js +33 -25
- package/dist/distiller.d.ts +18 -0
- package/dist/distiller.js +94 -9
- package/dist/eval/planted-harness.js +1 -1
- package/dist/eval/run-eval.js +2 -4
- package/dist/nightly.js +2 -4
- package/dist/recall-hook-cli.js +10 -0
- package/dist/recall-index.js +12 -0
- package/dist/reconsolidation.d.ts +17 -11
- package/dist/reconsolidation.js +38 -28
- package/dist/relink.d.ts +2 -2
- package/dist/relink.js +2 -2
- package/dist/retrieval.d.ts +5 -4
- package/dist/retrieval.js +5 -4
- package/dist/state.d.ts +8 -8
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +2 -2
- package/dist/sweep-volatile.d.ts +55 -0
- package/dist/sweep-volatile.js +184 -0
- package/dist/types.d.ts +26 -28
- package/dist/wrapper-prompt.d.ts +43 -0
- package/dist/wrapper-prompt.js +122 -0
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -91,8 +91,8 @@ Bare top-level keys (`"serverUrl": …` at the root of `openclaw.json`) still wo
|
|
|
91
91
|
| When | What | How |
|
|
92
92
|
|------|------|-----|
|
|
93
93
|
| Agent start | Standing identity (`## Identity`) + recent lessons fetched fresh and injected | CC SessionStart hook (calls `hicortex learnings-identity`; `lessons-context` kept as an alias so existing installed hooks don't break) / Hermes plugin `system_prompt_block` / OC `before_agent_start` hook |
|
|
94
|
-
| Every prompt (0.14) | A compact **recall index** of relevant memories is injected — one line per memory; the agent lazy-loads full content with `hicortex_get` only when needed | All five harnesses call server `POST /recall-index` per turn: CC UserPromptSubmit hook (`hicortex recall-hook`), Hermes plugin `prefetch` (0.7.0; falls back to `/search` injection against a pre-0.14 server), OC `before_agent_start` hook (fires per inbound message), Pi extension `before_agent_start` (0.20), opencode plugin messages-transform hook (0.21). Turn-based dedup per session; resets on new session/compaction. Fail-soft |
|
|
95
|
-
| Nightly | Denoise sessions → POST /distill → server distills + embeds + stores → consolidate (score, reflect, link, decay) | Automatic pipeline — no manual steps |
|
|
94
|
+
| Every prompt (0.14) | A compact **recall index** of relevant memories is injected — one line per memory; the agent lazy-loads full content with `hicortex_get` only when needed | All five harnesses call server `POST /recall-index` per turn: CC UserPromptSubmit hook (`hicortex recall-hook`), Hermes plugin `prefetch` (0.7.0; falls back to `/search` injection against a pre-0.14 server), OC `before_agent_start` hook (fires per inbound message), Pi extension `before_agent_start` (0.20), opencode plugin messages-transform hook (0.21). Turn-based dedup per session; resets on new session/compaction. Fail-soft. Harness plumbing (task-notifications, command envelopes) is skipped deterministically at BOTH the hook and the server — a wrapper carrying real prose still recalls on the full text |
|
|
95
|
+
| Nightly | Denoise sessions → POST /distill → server distills + embeds + stores → consolidate (score, reflect, link, decay) | Automatic pipeline — no manual steps. Volatile status entries (GitHub ticket states, version bumps, commit/push states) are dropped at a deterministic entry gate beside the substance gate — every drop rides the `/distill` response's `dropped` audit trail; decision/policy wording ("switched from X to Y", "never relicense…") always escapes the gate |
|
|
96
96
|
|
|
97
97
|
**Exposure vs use (0.14):** appearing in the recall index only marks a memory as *shown* (it stops decaying while topically active); fetching it with `hicortex_get` marks it as *used* (durable strengthening). Memory importance is driven by what agents actually use, not by what was pushed at them.
|
|
98
98
|
|
|
@@ -216,6 +216,8 @@ npx @gamaze/hicortex classify-domains # Backfill domain tags over the c
|
|
|
216
216
|
npx @gamaze/hicortex classify-types # Reclassify memory types (episode/fact/decision)
|
|
217
217
|
npx @gamaze/hicortex dedup # Preview near-duplicate memory clusters (dry run, no changes)
|
|
218
218
|
npx @gamaze/hicortex dedup --apply # Merge near-duplicate clusters (backs up the DB first)
|
|
219
|
+
npx @gamaze/hicortex sweep-volatile # Preview volatile GitHub-status/version rows the gate would retire (dry run)
|
|
220
|
+
npx @gamaze/hicortex sweep-volatile --apply # Retire them via absorb (backs up the DB first; audit trail; never deletes)
|
|
219
221
|
npx @gamaze/hicortex identity show [name] # Print the standing identity layer (see Identity Layer)
|
|
220
222
|
npx @gamaze/hicortex identity edit <name> # Edit an identity section in $EDITOR
|
|
221
223
|
npx @gamaze/hicortex identity show --agent <id> # Show a specific agent's resolved identity (0.13)
|
package/assets/dashboard.html
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
- Overview: the counter/bar/headroom key off LIVE memories (absorbed
|
|
40
40
|
rows show as an "absorbed (kept as evidence)" note); the counter is
|
|
41
41
|
STATIC (no replay tracking — owner ruling 2026-09-13).
|
|
42
|
-
- Recall card: the RAW uses-per-showing ratio
|
|
42
|
+
- Recall card: the RAW uses-per-showing ratio, NO
|
|
43
43
|
grade verdict (#426 owner semantics ruling: recall depends on the
|
|
44
44
|
conversation, higher is not a target).
|
|
45
45
|
- Rail header: "Fleet".
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
default, which used to degrade the corner to a standalone Upgrade
|
|
90
90
|
button. The upgrade CTA is a MENU ITEM (same plan-unset eligibility
|
|
91
91
|
the shipped #365 code used); no standalone upgrade button remains.
|
|
92
|
-
- RECALL CARD: below the band at most ONE subtle line (
|
|
92
|
+
- RECALL CARD: below the band at most ONE subtle line (zone word +
|
|
93
93
|
muted "provisional"; pill chrome dropped); the zone word rides the
|
|
94
94
|
marker, the zone-label row is gone — the card stops setting the row
|
|
95
95
|
height.
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
DOWN into the siblings' chart slot (header → big → band → foot).
|
|
136
136
|
"provisional" is hover-only now — a tooltip on the band (the card
|
|
137
137
|
stays marked; the visible word failed to communicate). Vocabulary
|
|
138
|
-
amendment: Low / HEALTHY / Overfetching. Marker +
|
|
138
|
+
amendment: Low / HEALTHY / Overfetching. Marker + zone word stay.
|
|
139
139
|
|
|
140
140
|
REPLAY + RANGE (#452, owner directives 2026-09-16):
|
|
141
141
|
- 30-DAY DEFAULT FOR ALL VIEWS: the replay ledger, the band and the
|
|
@@ -397,10 +397,6 @@
|
|
|
397
397
|
.big .n.noconf{ font-size:14.5px; font-weight:520; letter-spacing:0; color:var(--dim); }
|
|
398
398
|
html:not([data-theme="light"]) .big .n.noconf{ text-shadow:none; }
|
|
399
399
|
.big .l{ font-size:10px; color:var(--faint); text-transform:uppercase; letter-spacing:.13em; }
|
|
400
|
-
.trend{ font-size:12px; line-height:1; flex:none; }
|
|
401
|
-
.trend.up{ color:var(--green-mid); }
|
|
402
|
-
.trend.down{ color:var(--red); }
|
|
403
|
-
.trend.flat{ color:var(--dim); }
|
|
404
400
|
/* THE card sub-line — one text type */
|
|
405
401
|
.csub{ font-size:11px; color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
406
402
|
.csub b{ color:var(--green-mid); font-weight:600; }
|
|
@@ -419,7 +415,7 @@
|
|
|
419
415
|
row). The visible "provisional" word is GONE — the marking is hover-only
|
|
420
416
|
now, a tooltip on the band (the visible word failed to communicate).
|
|
421
417
|
Vocabulary (owner 2026-09-14): Low / Healthy / Overfetching. The raw
|
|
422
|
-
number stays tooltip-only on the marker
|
|
418
|
+
number stays tooltip-only on the marker (mock
|
|
423
419
|
family). Colors: the band + word carry concrete per-theme colors from
|
|
424
420
|
the JS stop table (setTheme re-renders), the dot rides theme tokens. */
|
|
425
421
|
.rec-word.none{ color:var(--dim); }
|
|
@@ -3178,23 +3174,6 @@ function buildTokNights(used, cap, periodStart){
|
|
|
3178
3174
|
}
|
|
3179
3175
|
}
|
|
3180
3176
|
|
|
3181
|
-
/* trend = mean of the last 7 nights vs the prior 7 (a DEFINED window — the
|
|
3182
|
-
old first-vs-last-over-the-range comparison had no window at all). Titles
|
|
3183
|
-
state the window so the arrow is never mysterious. */
|
|
3184
|
-
function recallTrend(){
|
|
3185
|
-
const flat={cls:'flat',sym:'▬'};
|
|
3186
|
-
if(!D||!D.series) return Object.assign(flat,{title:'no snapshot data'});
|
|
3187
|
-
const vals=D.series.map(s=>s.metrics&&s.metrics.adoption?s.metrics.adoption.uses_per_showing:null).filter(v=>typeof v==='number');
|
|
3188
|
-
const last7=vals.slice(-7), prior7=vals.slice(-14,-7);
|
|
3189
|
-
const mean=a=>a.length?a.reduce((x,y)=>x+y,0)/a.length:null;
|
|
3190
|
-
const a=mean(prior7), b=mean(last7);
|
|
3191
|
-
if(a===null||b===null) return Object.assign(flat,{title:'trend needs 7+ nights of history'});
|
|
3192
|
-
const d=b-a;
|
|
3193
|
-
if(d>0.005) return {cls:'up',sym:'↗',title:'up — mean of the last 7 nights vs the prior 7 ('+b.toFixed(3)+' vs '+a.toFixed(3)+')'};
|
|
3194
|
-
if(d<-0.005) return {cls:'down',sym:'↘',title:'down — mean of the last 7 nights vs the prior 7 ('+b.toFixed(3)+' vs '+a.toFixed(3)+')'};
|
|
3195
|
-
return Object.assign(flat,{title:'flat — mean of the last 7 nights vs the prior 7 ('+b.toFixed(3)+' vs '+a.toFixed(3)+')'});
|
|
3196
|
-
}
|
|
3197
|
-
|
|
3198
3177
|
/* ---------- Recall level — the designed U-band (#426 final ruling
|
|
3199
3178
|
2026-09-13). A continuous red→green→red gradient spans the PROVISIONAL
|
|
3200
3179
|
zone edges (echoed by /dashboard/field as thresholds.recall_uses — the
|
|
@@ -3291,16 +3270,11 @@ function renderRecBand(ups){
|
|
|
3291
3270
|
word.style.color=''; word.style.textShadow='none';
|
|
3292
3271
|
word.title='no showings yet';
|
|
3293
3272
|
}
|
|
3294
|
-
/* trend arrow
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
el('rec-trend').title=tr.title;
|
|
3300
|
-
}else{
|
|
3301
|
-
el('rec-trend').className='trend flat'; el('rec-trend').innerHTML='▬';
|
|
3302
|
-
el('rec-trend').title='no showings yet';
|
|
3303
|
-
}
|
|
3273
|
+
/* No trend arrow (owner 2026-09-20: removed — unclear). Its renderer and
|
|
3274
|
+
the element writes are removed WITH it: a leftover write to a removed
|
|
3275
|
+
element is a boot-killing TypeError whenever the recall band carries
|
|
3276
|
+
real data (bedrock 0.22.2: "0 memories" — boot died before the counter
|
|
3277
|
+
was ever seeded). */
|
|
3304
3278
|
}
|
|
3305
3279
|
|
|
3306
3280
|
/* ---------- Memory Precision — Level 1, the pushed index (#476). A compact
|
package/dist/calibration.d.ts
CHANGED
|
@@ -117,11 +117,11 @@ export declare const MEMORY_PRECISION_WINDOW_DAYS = 90;
|
|
|
117
117
|
/**
|
|
118
118
|
* Cosine at/above which a pushed line reads "redundant" (restating the
|
|
119
119
|
* session's standing context — the top lessons + identity every session-start
|
|
120
|
-
* hook injects). Direction-only display guidance, never a gate. 0.80
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* the judged-calibration follow-up
|
|
124
|
-
* #426 provisional-anchor posture).
|
|
120
|
+
* hook injects). Direction-only display guidance, never a gate. 0.80 — the
|
|
121
|
+
* anchor it was seeded from (the retired supersession stage's floor, #206-B)
|
|
122
|
+
* at/above which a pair reads as the same statement, below it as topical
|
|
123
|
+
* overlap — a reasonable first anchor until the judged-calibration follow-up
|
|
124
|
+
* measures the real distribution (the #426 provisional-anchor posture).
|
|
125
125
|
*/
|
|
126
126
|
export declare const MEMORY_PRECISION_REDUNDANT_ABOVE = 0.8;
|
|
127
127
|
/**
|
|
@@ -138,6 +138,23 @@ export declare const MEMORY_PRECISION_DIVERGENCE_MIN_SHOWN = 5;
|
|
|
138
138
|
* the same trust boundary as /distill's denoised conversation text).
|
|
139
139
|
*/
|
|
140
140
|
export declare const MEMORY_PRECISION_PROMPT_EXCERPT_CHARS = 256;
|
|
141
|
+
/**
|
|
142
|
+
* Kill-switch for the deterministic volatility gate (#489, owner decision 5):
|
|
143
|
+
* false disables isVolatileStatusEntry's use in the distill path (entries
|
|
144
|
+
* keep flowing as before) AND the sweep's candidacy rule — one release-managed
|
|
145
|
+
* constant, no config knob (#408 discipline: moving it is a release decision,
|
|
146
|
+
* never a runtime one).
|
|
147
|
+
*/
|
|
148
|
+
export declare const VOLATILE_STATUS_FILTER = true;
|
|
149
|
+
/**
|
|
150
|
+
* Max entry length the volatility gate will classify as volatile (#489) — the
|
|
151
|
+
* operationalization of the spec's "DOMINANT content matches": distiller
|
|
152
|
+
* bullets are one-liners, so a status shape in a SHORT entry dominates it,
|
|
153
|
+
* while the same clause riding inside long mixed prose does not (kept — the
|
|
154
|
+
* substance gate's precision-over-recall bias, applied to a second gate).
|
|
155
|
+
* 300 chars ≈ 3× the longest shape in the #489 KEEP/DROP corpus.
|
|
156
|
+
*/
|
|
157
|
+
export declare const VOLATILE_GATE_MAX_CHARS = 300;
|
|
141
158
|
/** Semantic-similarity share of the composite score. 0.50 (raised from 0.40
|
|
142
159
|
* in the 0.15.2 rebalance, #191 Phase B): on the production corpus effective
|
|
143
160
|
* strength (0.30) outweighed what similarity could recover — hardened old
|
|
@@ -273,13 +290,11 @@ export declare const IMPORTANCE_SETTLE_WINDOW_DAYS = 3;
|
|
|
273
290
|
* get the one verdict call. 0.92 — measured on the #191 mechanical audit
|
|
274
291
|
* corpus (89 clusters / 110 excess rows; data/audit-20260729). */
|
|
275
292
|
export declare const DEDUP_AUTO_MERGE_THRESHOLD = 0.92;
|
|
276
|
-
/** Minimum cosine for a nightly supersession candidate pair (#100 stage,
|
|
277
|
-
* 0.15.0): one classify-tier call per pair above the bar. */
|
|
278
|
-
export declare const SUPERSESSION_MIN_SIMILARITY = 0.8;
|
|
279
293
|
/** Minimum cosine for a reconsolidation correction pair (#384). Deliberately
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
294
|
+
* wide: a retraction often rides inside an otherwise unrelated memory; the
|
|
295
|
+
* verdict + confidence gate carry the precision. (The retired Stage 3.7
|
|
296
|
+
* supersession scan's 0.80 floor — #206-B, owner decision 6 — is subsumed:
|
|
297
|
+
* 3.8 scans all shapes from this wider floor.) */
|
|
283
298
|
export declare const CORRECTION_MIN_SIMILARITY = 0.75;
|
|
284
299
|
/** Minimum verdict confidence for the REWRITE (and #392 merge-apply) fork
|
|
285
300
|
* (#384): below it a `corrects` degrades to mark-only — a weak mark is
|
package/dist/calibration.js
CHANGED
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* the removal is never silent.
|
|
25
25
|
*/
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
-
exports.
|
|
28
|
-
exports.DIAGNOSTIC_ENV_TIER = exports.OLLAMA_FLUSH_WAIT_MS = exports.OLLAMA_FLUSH_EVERY = exports.NUM_CTX = exports.DEFAULT_FIRST_RUN_LOOKBACK_DAYS = exports.ENRICH_STRENGTH_DELTA = void 0;
|
|
27
|
+
exports.STAGE_BELIEF_STRENGTH = exports.STAGE_FADING_STRENGTH = exports.STAGE_FADING_DAYS = exports.WEAK_PRIMARY_FLOOR = exports.CORRECTION_REWRITE_MIN_CONFIDENCE = exports.CORRECTION_MIN_SIMILARITY = exports.DEDUP_AUTO_MERGE_THRESHOLD = exports.IMPORTANCE_SETTLE_WINDOW_DAYS = exports.IMPORTANCE_CEILING = exports.BM25_WEIGHT_DOMAIN = exports.BM25_WEIGHT_PROJECT = exports.BM25_WEIGHT_BODY = exports.BOTH_CHANNEL_BOOST = exports.RRF_VECTOR_WEIGHT = exports.RRF_FTS_WEIGHT = exports.RRF_COMPOSITE_WEIGHT = exports.RRF_K = exports.SCOPE_AFFINITY_WEIGHT = exports.SUPERSEDED_DEMOTION = exports.RECENCY_HEAD_DAYS = exports.RECENCY_HEAD_WEIGHT = exports.RECENCY_HOURLY_DECAY = exports.SCORE_RECENCY_WEIGHT = exports.CONNECTIONS_SATURATION_DEGREE = exports.SCORE_CONNECTIONS_WEIGHT = exports.SCORE_STRENGTH_WEIGHT = exports.SCORE_SIMILARITY_WEIGHT = exports.VOLATILE_GATE_MAX_CHARS = exports.VOLATILE_STATUS_FILTER = exports.MEMORY_PRECISION_PROMPT_EXCERPT_CHARS = exports.MEMORY_PRECISION_DIVERGENCE_MIN_SHOWN = exports.MEMORY_PRECISION_REDUNDANT_ABOVE = exports.MEMORY_PRECISION_WINDOW_DAYS = exports.RECALL_USES_AXIS_MAX = exports.RECALL_USES_NORMAL_MAX = exports.RECALL_USES_LOW_MAX = exports.RECALL_RESHOW_TURNS = exports.NOVELTY_FLOOR_SLOTS = exports.RECALL_TITLE_CHARS = exports.RECALL_MIN_PROMPT_CHARS = exports.RECALL_MAX_ITEMS = exports.RECALL_MIN_SIMILARITY = exports.SESSION_INTENT_WEIGHT = exports.COLD_EXPOSURE_SLOTS = exports.RECENT_WINDOW_DAYS = exports.RECENT_LIMIT = exports.SEARCH_LIMIT = exports.PROMOTION_STRENGTH_FLOOR = exports.PROMOTION_RATE = exports.DECAY_HALF_LIFE_DAYS = void 0;
|
|
28
|
+
exports.DIAGNOSTIC_ENV_TIER = exports.OLLAMA_FLUSH_WAIT_MS = exports.OLLAMA_FLUSH_EVERY = exports.NUM_CTX = exports.DEFAULT_FIRST_RUN_LOOKBACK_DAYS = exports.ENRICH_STRENGTH_DELTA = exports.STAGE_TRUTH_STRENGTH = void 0;
|
|
29
29
|
exports.resolveNumCtx = resolveNumCtx;
|
|
30
30
|
exports.resolveOllamaFlushEvery = resolveOllamaFlushEvery;
|
|
31
31
|
exports.resolveOllamaFlushWaitMs = resolveOllamaFlushWaitMs;
|
|
@@ -144,11 +144,11 @@ exports.MEMORY_PRECISION_WINDOW_DAYS = 90;
|
|
|
144
144
|
/**
|
|
145
145
|
* Cosine at/above which a pushed line reads "redundant" (restating the
|
|
146
146
|
* session's standing context — the top lessons + identity every session-start
|
|
147
|
-
* hook injects). Direction-only display guidance, never a gate. 0.80
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* the judged-calibration follow-up
|
|
151
|
-
* #426 provisional-anchor posture).
|
|
147
|
+
* hook injects). Direction-only display guidance, never a gate. 0.80 — the
|
|
148
|
+
* anchor it was seeded from (the retired supersession stage's floor, #206-B)
|
|
149
|
+
* at/above which a pair reads as the same statement, below it as topical
|
|
150
|
+
* overlap — a reasonable first anchor until the judged-calibration follow-up
|
|
151
|
+
* measures the real distribution (the #426 provisional-anchor posture).
|
|
152
152
|
*/
|
|
153
153
|
exports.MEMORY_PRECISION_REDUNDANT_ABOVE = 0.8;
|
|
154
154
|
/**
|
|
@@ -166,6 +166,28 @@ exports.MEMORY_PRECISION_DIVERGENCE_MIN_SHOWN = 5;
|
|
|
166
166
|
*/
|
|
167
167
|
exports.MEMORY_PRECISION_PROMPT_EXCERPT_CHARS = 256;
|
|
168
168
|
// ---------------------------------------------------------------------------
|
|
169
|
+
// Volatility gate (#489) — deterministic drop of GH-ticket-status /
|
|
170
|
+
// version-bump / commit-state entries at the distill gate, and the one-shot
|
|
171
|
+
// store sweep that reuses the same gate.
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
/**
|
|
174
|
+
* Kill-switch for the deterministic volatility gate (#489, owner decision 5):
|
|
175
|
+
* false disables isVolatileStatusEntry's use in the distill path (entries
|
|
176
|
+
* keep flowing as before) AND the sweep's candidacy rule — one release-managed
|
|
177
|
+
* constant, no config knob (#408 discipline: moving it is a release decision,
|
|
178
|
+
* never a runtime one).
|
|
179
|
+
*/
|
|
180
|
+
exports.VOLATILE_STATUS_FILTER = true;
|
|
181
|
+
/**
|
|
182
|
+
* Max entry length the volatility gate will classify as volatile (#489) — the
|
|
183
|
+
* operationalization of the spec's "DOMINANT content matches": distiller
|
|
184
|
+
* bullets are one-liners, so a status shape in a SHORT entry dominates it,
|
|
185
|
+
* while the same clause riding inside long mixed prose does not (kept — the
|
|
186
|
+
* substance gate's precision-over-recall bias, applied to a second gate).
|
|
187
|
+
* 300 chars ≈ 3× the longest shape in the #489 KEEP/DROP corpus.
|
|
188
|
+
*/
|
|
189
|
+
exports.VOLATILE_GATE_MAX_CHARS = 300;
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
169
191
|
// Composite ranking weights (was: score*Weight, supersededDemotion,
|
|
170
192
|
// *AffinityWeight, rrf*; the pre-#430 freshness bonus constants merged into
|
|
171
193
|
// the RECENCY family below)
|
|
@@ -315,13 +337,11 @@ exports.IMPORTANCE_SETTLE_WINDOW_DAYS = 3;
|
|
|
315
337
|
* get the one verdict call. 0.92 — measured on the #191 mechanical audit
|
|
316
338
|
* corpus (89 clusters / 110 excess rows; data/audit-20260729). */
|
|
317
339
|
exports.DEDUP_AUTO_MERGE_THRESHOLD = 0.92;
|
|
318
|
-
/** Minimum cosine for a nightly supersession candidate pair (#100 stage,
|
|
319
|
-
* 0.15.0): one classify-tier call per pair above the bar. */
|
|
320
|
-
exports.SUPERSESSION_MIN_SIMILARITY = 0.80;
|
|
321
340
|
/** Minimum cosine for a reconsolidation correction pair (#384). Deliberately
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
341
|
+
* wide: a retraction often rides inside an otherwise unrelated memory; the
|
|
342
|
+
* verdict + confidence gate carry the precision. (The retired Stage 3.7
|
|
343
|
+
* supersession scan's 0.80 floor — #206-B, owner decision 6 — is subsumed:
|
|
344
|
+
* 3.8 scans all shapes from this wider floor.) */
|
|
325
345
|
exports.CORRECTION_MIN_SIMILARITY = 0.75;
|
|
326
346
|
/** Minimum verdict confidence for the REWRITE (and #392 merge-apply) fork
|
|
327
347
|
* (#384): below it a `corrects` degrades to mark-only — a weak mark is
|
package/dist/capture.js
CHANGED
|
@@ -303,7 +303,10 @@ async function captureBatches(batches, opts) {
|
|
|
303
303
|
lastConfirmedEnd = seg.segEnd;
|
|
304
304
|
console.log(`[hicortex] → ${result.distilled ?? 0} memories (segment ${body.segment_id})`);
|
|
305
305
|
for (const d of result.dropped ?? []) {
|
|
306
|
-
|
|
306
|
+
// #489: the response array carries BOTH gate kinds (substance +
|
|
307
|
+
// volatility) — the server's own log names the exact gate; this
|
|
308
|
+
// client-side line is the same #156 trail, labeled generically.
|
|
309
|
+
console.log(`[hicortex] Distill gate: dropped "${d}"`);
|
|
307
310
|
}
|
|
308
311
|
}
|
|
309
312
|
else if (result.status === 200) {
|
package/dist/cli.d.ts
CHANGED
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
* dedup --apply Execute the merge (default: dry run);
|
|
17
17
|
* losers are absorbed (kept as evidence,
|
|
18
18
|
* hidden from recall), not deleted
|
|
19
|
+
* sweep-volatile One-shot sweep of volatile GH-status/version rows (#489)
|
|
20
|
+
* sweep-volatile --apply Demote matches via absorb (default:
|
|
21
|
+
* dry run; backup first, audit trail)
|
|
19
22
|
* history Show a memory's rewrite history, or roll one back (issue #384)
|
|
20
23
|
* history --rollback <row> Undo one rewrite + un-absorb triggers
|
|
21
24
|
* status Show config, DB stats, adapter status
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
* dedup --apply Execute the merge (default: dry run);
|
|
18
18
|
* losers are absorbed (kept as evidence,
|
|
19
19
|
* hidden from recall), not deleted
|
|
20
|
+
* sweep-volatile One-shot sweep of volatile GH-status/version rows (#489)
|
|
21
|
+
* sweep-volatile --apply Demote matches via absorb (default:
|
|
22
|
+
* dry run; backup first, audit trail)
|
|
20
23
|
* history Show a memory's rewrite history, or roll one back (issue #384)
|
|
21
24
|
* history --rollback <row> Undo one rewrite + un-absorb triggers
|
|
22
25
|
* status Show config, DB stats, adapter status
|
|
@@ -306,6 +309,29 @@ switch (command) {
|
|
|
306
309
|
});
|
|
307
310
|
break;
|
|
308
311
|
}
|
|
312
|
+
case "sweep-volatile": {
|
|
313
|
+
// One-shot store sweep of volatile GH-status/version rows (#489,
|
|
314
|
+
// deliverable iii): reuses the distill path's deterministic gate over the
|
|
315
|
+
// stored corpus. Mirrors `dedup`: dry-run default, --apply explicit
|
|
316
|
+
// (backup first, absorb — never delete, volatile_sweep_log audit trail).
|
|
317
|
+
const args = process.argv.slice(3);
|
|
318
|
+
let dbPath;
|
|
319
|
+
try {
|
|
320
|
+
dbPath = (0, cli_args_js_1.readValueFlag)(args, "--db");
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
console.error("[hicortex] sweep-volatile: --db requires a path value");
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
const sweepOptions = { apply: args.includes("--apply"), dbPath };
|
|
327
|
+
import("./sweep-volatile.js").then(({ runSweepVolatile }) => {
|
|
328
|
+
runSweepVolatile(sweepOptions).catch((err) => {
|
|
329
|
+
console.error(err instanceof Error ? err.message : `[hicortex] sweep-volatile failed: ${err}`);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
309
335
|
case "history": {
|
|
310
336
|
// Rewrite history: audit + one-command rollback (#384). Listing is
|
|
311
337
|
// read-only; --rollback mutates (restores prior content/status and
|
package/dist/cluster.d.ts
CHANGED
|
@@ -25,8 +25,12 @@ export declare class UnionFind {
|
|
|
25
25
|
export declare function clusterEdges(edges: Edge[], threshold: number): string[][];
|
|
26
26
|
/** Excess = sum(cluster size − 1) — rows that would disappear if every cluster merged to one. */
|
|
27
27
|
export declare function clusterExcess(clusters: string[][]): number;
|
|
28
|
-
/** Metadata
|
|
29
|
-
*
|
|
28
|
+
/** Metadata row shape for the merge-safety check. `privacy` and `source_agent`
|
|
29
|
+
* are on the row (the columns still exist) but are NOT merge-safety fields:
|
|
30
|
+
* privacy is vestigial since 0.16.2, and the agent rail was REMOVED by owner
|
|
31
|
+
* decision (#206 decision 2, 2026-09-21) — cross-agent clusters merge, because
|
|
32
|
+
* attribution survives on the retained absorbed-loser row and no recall path
|
|
33
|
+
* filters by source_agent. Project is the only rail. */
|
|
30
34
|
export interface ClusterMetaRow {
|
|
31
35
|
project: string | null;
|
|
32
36
|
privacy: string | null;
|
|
@@ -34,10 +38,9 @@ export interface ClusterMetaRow {
|
|
|
34
38
|
}
|
|
35
39
|
export interface ClusterMetadataMismatch {
|
|
36
40
|
projectMismatch: boolean;
|
|
37
|
-
sourceAgentMismatch: boolean;
|
|
38
41
|
}
|
|
39
|
-
/** Do cluster members disagree on project
|
|
40
|
-
* Privacy
|
|
42
|
+
/** Do cluster members disagree on project? (merge-safety input for #100/#206.)
|
|
43
|
+
* Privacy and source_agent are intentionally NOT checked — see ClusterMetaRow. */
|
|
41
44
|
export declare function clusterMetadataMismatch(members: ClusterMetaRow[]): ClusterMetadataMismatch;
|
|
42
45
|
/**
|
|
43
46
|
* Build the max-cosine edge set via top-K KNN on `memory_vectors`, keeping
|
package/dist/cluster.js
CHANGED
|
@@ -69,15 +69,11 @@ function clusterEdges(edges, threshold) {
|
|
|
69
69
|
function clusterExcess(clusters) {
|
|
70
70
|
return clusters.reduce((sum, c) => sum + (c.length - 1), 0);
|
|
71
71
|
}
|
|
72
|
-
/** Do cluster members disagree on project
|
|
73
|
-
* Privacy
|
|
72
|
+
/** Do cluster members disagree on project? (merge-safety input for #100/#206.)
|
|
73
|
+
* Privacy and source_agent are intentionally NOT checked — see ClusterMetaRow. */
|
|
74
74
|
function clusterMetadataMismatch(members) {
|
|
75
75
|
const projects = new Set(members.map((m) => m.project ?? "\u0000null"));
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
projectMismatch: projects.size > 1,
|
|
79
|
-
sourceAgentMismatch: agents.size > 1,
|
|
80
|
-
};
|
|
76
|
+
return { projectMismatch: projects.size > 1 };
|
|
81
77
|
}
|
|
82
78
|
// ---------------------------------------------------------------------------
|
|
83
79
|
// KNN edge building
|
package/dist/consolidate.d.ts
CHANGED
|
@@ -257,65 +257,6 @@ export declare function classifyLinkCandidates(candidates: LinkCandidate[]): Pro
|
|
|
257
257
|
* boundary from the l2ToCosine calibration is preserved.
|
|
258
258
|
*/
|
|
259
259
|
export declare function classifyRelationship(source: Memory, target: Memory, similarity: number): string;
|
|
260
|
-
/** Default minimum COSINE similarity for a supersession candidate pair —
|
|
261
|
-
* RELEASE-MANAGED since #408 (calibration.ts SUPERSESSION_MIN_SIMILARITY). */
|
|
262
|
-
export declare const DEFAULT_SUPERSESSION_MIN_SIMILARITY = 0.8;
|
|
263
|
-
export interface SupersessionOptions {
|
|
264
|
-
/** Candidate-pair cosine floor. Release-managed default (calibration.ts);
|
|
265
|
-
* this field is the eval/test seam. Invalid → default. */
|
|
266
|
-
minSimilarity?: number;
|
|
267
|
-
/** The run-wide pipeline deadline (#405) — checked at each candidate
|
|
268
|
-
* boundary; on expiry the scan stops and the cursor holds at the last
|
|
269
|
-
* fully-considered candidate (resumed next run). */
|
|
270
|
-
deadline?: RunDeadline;
|
|
271
|
-
}
|
|
272
|
-
export interface SupersessionStageResult {
|
|
273
|
-
scanned: number;
|
|
274
|
-
evaluated: number;
|
|
275
|
-
superseded: number;
|
|
276
|
-
skipped_infra: number;
|
|
277
|
-
skipped_idempotent: number;
|
|
278
|
-
cursor: number;
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Build the constrained supersession-check prompt. Content is truncated the
|
|
282
|
-
* same width as domain-classify.ts's classifier (1500 chars) — this is a
|
|
283
|
-
* classify-tier call with the same cost profile.
|
|
284
|
-
*/
|
|
285
|
-
export declare function buildSupersessionPrompt(oldContent: string, newContent: string): string;
|
|
286
|
-
/**
|
|
287
|
-
* Parse the model's supersession verdict. Returns the boolean on a valid
|
|
288
|
-
* reply, or null on anything unparseable (caller skips the pair — no retry,
|
|
289
|
-
* unlike domain-classify's tag classifier; a missed pair is retried naturally
|
|
290
|
-
* when this stage revisits the corpus).
|
|
291
|
-
*/
|
|
292
|
-
export declare function parseSupersessionReply(reply: string): boolean | null;
|
|
293
|
-
/**
|
|
294
|
-
* Nightly supersession-detection stage. Scans memories/rowid > cursor whose
|
|
295
|
-
* shape is supersedable (decision/correction/fact/state — isSupersedableShape),
|
|
296
|
-
* checks each against its older same-shape neighbors, and links confirmed
|
|
297
|
-
* supersessions. Dry-run performs discovery + the free idempotency check only —
|
|
298
|
-
* no LLM calls, no writes, no
|
|
299
|
-
* cursor persistence (mirrors stageImportance/stageContentDomains's dry-run
|
|
300
|
-
* convention of never spending budget on a preview).
|
|
301
|
-
*
|
|
302
|
-
* Cursor discipline is DELIBERATELY simple (owner amendment): the cursor
|
|
303
|
-
* advances past a candidate once its neighbor set has been considered,
|
|
304
|
-
* REGARDLESS of whether every pair got an LLM call (call budget) or a clean
|
|
305
|
-
* verdict (infra skip) — missing one pair is acceptable and self-heals next
|
|
306
|
-
* time this memory's neighborhood is re-examined via a NEWER memory's own
|
|
307
|
-
* candidacy. It only stops SHORT of a candidate when the budget is already
|
|
308
|
-
* exhausted before that candidate starts, so the cursor never skips a
|
|
309
|
-
* candidate that was never looked at.
|
|
310
|
-
*
|
|
311
|
-
* #405: the cursor persists after EVERY fully-considered candidate (the
|
|
312
|
-
* post-#404 reconsolidation pattern), not at stage end — a run killed or
|
|
313
|
-
* deadline-deferred mid-stage loses at most the candidate in flight. No
|
|
314
|
-
* orphan clamp is needed (unlike reconsolidation): supersession applies each
|
|
315
|
-
* verdict's link immediately, so `cursor = candidate.__rowid` always sits
|
|
316
|
-
* after all of that candidate's writes.
|
|
317
|
-
*/
|
|
318
|
-
export declare function stageSupersession(db: Database.Database, llm: LlmClient, budget: BudgetTracker, embedFn: EmbedFn, dryRun: boolean, stateDir: string | undefined, options?: SupersessionOptions): Promise<SupersessionStageResult>;
|
|
319
260
|
/**
|
|
320
261
|
* Exported for the #191 eval baseline (src/eval/decay-eval.ts) so the audit
|
|
321
262
|
* runs the REAL production prune predicate against a DB snapshot instead of
|
|
@@ -404,7 +345,7 @@ export interface DomainStageOptions {
|
|
|
404
345
|
*/
|
|
405
346
|
weakPrimaryFloor?: number;
|
|
406
347
|
}
|
|
407
|
-
export declare function runConsolidation(db: Database.Database, llm: LlmClient, embedFn: EmbedFn, dryRun?: boolean, skipReflection?: boolean, stateDir?: string, domainOptions?: DomainStageOptions,
|
|
348
|
+
export declare function runConsolidation(db: Database.Database, llm: LlmClient, embedFn: EmbedFn, dryRun?: boolean, skipReflection?: boolean, stateDir?: string, domainOptions?: DomainStageOptions,
|
|
408
349
|
/** The ONE per-run LLM-call ceiling (#405/#241). The caller resolves
|
|
409
350
|
* `nightlyLlmCallBudget` from config (consolidateMaxLlmCalls is a
|
|
410
351
|
* deprecated alias — resolveNightlyLlmCallBudget) and passes it; unset →
|
|
@@ -416,10 +357,9 @@ budgetMaxCalls?: number,
|
|
|
416
357
|
memorySoftCap?: number,
|
|
417
358
|
/** Reconsolidation-stage knobs (#384) — eval/test seams since #408 (the
|
|
418
359
|
* values are release-managed calibration constants; nightly.ts threads
|
|
419
|
-
* NOTHING)
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* argument meaning. */
|
|
360
|
+
* NOTHING); unset fields → the stage's calibration defaults. The
|
|
361
|
+
* pre-#206-B supersessionOptions param that sat here is retired with its
|
|
362
|
+
* stage — callers updated in the same change. */
|
|
423
363
|
reconsolidationOptions?: ReconsolidationOptions,
|
|
424
364
|
/**
|
|
425
365
|
* The run-wide pipeline deadline (#405), created at nightly start and
|