@gamaze/hicortex 0.22.1 → 0.22.3
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/assets/dashboard.html +209 -108
- package/dist/calibration.d.ts +45 -0
- package/dist/calibration.js +52 -2
- package/dist/classify-domains.js +6 -1
- package/dist/consolidate.js +73 -14
- package/dist/dashboard.d.ts +11 -0
- package/dist/dashboard.js +9 -0
- package/dist/db.js +74 -0
- package/dist/mcp-server.js +35 -8
- package/dist/nightly.js +14 -0
- package/dist/recall-index.d.ts +46 -3
- package/dist/recall-index.js +83 -26
- package/dist/recall-precision.d.ts +212 -0
- package/dist/recall-precision.js +381 -0
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
- package/server.json +3 -3
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); }
|
|
@@ -427,6 +423,24 @@
|
|
|
427
423
|
.rec-band{ position:absolute; inset:0; border-radius:4px; }
|
|
428
424
|
.rec-dot{ position:absolute; top:50%; transform:translate(-50%,-50%); width:11px; height:11px; border-radius:50%; background:var(--text); border:2px solid var(--panel); box-shadow:0 0 0 1px color-mix(in srgb, var(--text) 40%, transparent), 0 0 8px color-mix(in srgb, var(--text) 30%, transparent); }
|
|
429
425
|
.rec-foot{ display:flex; align-items:center; gap:7px; }
|
|
426
|
+
/* Memory Precision Level 1 (#476) — the pushed-index row: a compact
|
|
427
|
+
second line in the .csub scale (the sibling-rhythm ruling 2026-09-14:
|
|
428
|
+
the card keeps the shared .bseg gap rhythm, header → big → band →
|
|
429
|
+
index row → foot). Direction-only coloring: green at/above the echoed
|
|
430
|
+
recall floor, muted below (the index bar reads conservative); the
|
|
431
|
+
floor tick is amber like the pace marker. Theme tokens only — both
|
|
432
|
+
themes render from their own table, no JS colors here. */
|
|
433
|
+
.rec-l1{ display:block; font-size:10.5px; color:var(--dim); min-width:0; line-height:1.6; }
|
|
434
|
+
.rec-l1 .l1row{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
435
|
+
.rec-l1 .lbl{ display:none; } /* #476 rename: the three-bucket text is self-labeled */
|
|
436
|
+
.rec-l1 .l1bar{ position:relative; flex:1 1 46px; height:5px; border-radius:3px; background:var(--tbar-bg); min-width:36px; }
|
|
437
|
+
.rec-l1 .l1bar .l1-fill{ position:absolute; left:0; top:0; bottom:0; border-radius:3px; background:color-mix(in srgb, var(--green) 65%, transparent); }
|
|
438
|
+
.rec-l1.below .l1bar .l1-fill{ background:color-mix(in srgb, var(--dim) 55%, transparent); }
|
|
439
|
+
.rec-l1 .l1bar .l1-floor{ position:absolute; top:-2px; bottom:-2px; width:1px; background:var(--amber); }
|
|
440
|
+
.rec-l1 .l1txt{ color:var(--dim); overflow:hidden; text-overflow:ellipsis; font-size:10.5px; letter-spacing:-.01em; }
|
|
441
|
+
.rec-l1 b{ color:var(--green-mid); font-weight:600; }
|
|
442
|
+
.rec-l1.below b{ color:var(--dim); }
|
|
443
|
+
#rec-div{ color:var(--amber); overflow:hidden; text-overflow:ellipsis; }
|
|
430
444
|
.b-health{ display:flex; align-items:center; gap:7px; font-size:11px; color:var(--dim); white-space:nowrap; }
|
|
431
445
|
.dot{ width:6px; height:6px; border-radius:50%; background:var(--green); box-shadow:0 0 10px color-mix(in srgb, var(--green) 70%, transparent); animation:breathe 3.2s ease-in-out infinite; flex:none; }
|
|
432
446
|
.dot.blue{ background:var(--blue); box-shadow:0 0 10px color-mix(in srgb, var(--blue) 70%, transparent); }
|
|
@@ -1159,21 +1173,32 @@
|
|
|
1159
1173
|
<div class="csub" id="tok-sub"> </div>
|
|
1160
1174
|
<div id="tok-nights" aria-label="LLM tokens per nightly run this billing period"></div>
|
|
1161
1175
|
</div>
|
|
1162
|
-
<!--
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1176
|
+
<!-- Memory Precision (#476, owner retitle) — ONE card, two context
|
|
1177
|
+
levels. Level 2 (recall depth) keeps the #426 U-band + zone word +
|
|
1178
|
+
provisional-hover semantics; the marker/tooltip read the WINDOW
|
|
1179
|
+
ratio off D.memory_precision.level2 (a pre-#476 server has no block
|
|
1180
|
+
→ the headline ratio — today's rendering exactly). Level 1 (pushed
|
|
1181
|
+
index) is a compact second row: mean similarity of pushed lines to
|
|
1182
|
+
their prompt, with a floor marker at the echoed
|
|
1183
|
+
recall_min_similarity and muted below it (the index's bar reads
|
|
1184
|
+
conservative — its noise costs compound per prompt) + the
|
|
1185
|
+
redundancy share; direction-only coloring, NO verdict words (the
|
|
1186
|
+
#426 semantics ruling extended: similarity is
|
|
1187
|
+
conversation-dependent). Divergence count on the FACE, the ≤3
|
|
1188
|
+
titles hover-only (no memory lists on the main page — owner ruling
|
|
1189
|
+
2026-09-12; the header search panel is the list surface). The
|
|
1190
|
+
window rides the #452 selector via the echoed window_days — never
|
|
1191
|
+
hardcoded, never a second range control. -->
|
|
1172
1192
|
<div class="bseg" id="lim-rec">
|
|
1173
|
-
<div class="gh"><span class="t">
|
|
1193
|
+
<div class="gh"><span class="t">Memory Precision</span><span class="sub" id="rec-sub">uses per showing</span></div>
|
|
1174
1194
|
<div class="big"><b class="n rec-word" id="rec-zone">—</b></div>
|
|
1175
1195
|
<div class="rec-bandrow" id="rec-bandrow"><div class="rec-band" id="rec-band"></div><i class="rec-dot" id="rec-dot" hidden></i></div>
|
|
1176
|
-
<div class="
|
|
1196
|
+
<div class="rec-l1" id="rec-l1" hidden style="display:block">
|
|
1197
|
+
<div class="l1row" id="l1-rel"> </div>
|
|
1198
|
+
<div class="l1row" id="l1-rep"> </div>
|
|
1199
|
+
<div class="l1row" id="l1-off"> </div>
|
|
1200
|
+
</div>
|
|
1201
|
+
<div class="csub rec-foot"><span id="rec-div" hidden></span></div>
|
|
1177
1202
|
</div>
|
|
1178
1203
|
</div>
|
|
1179
1204
|
<!-- row 2 · ops & maturity — capture health · 30 nights · maturity split · model -->
|
|
@@ -1488,8 +1513,11 @@ const DEPTH_BANDS = { truth:[.9,1.05], belief:[1.05,1.3], forming:[1.3,1.55], fa
|
|
|
1488
1513
|
post-backfill store still shows a visible gradient and the inflated
|
|
1489
1514
|
pre-#425 store shows no monsters. Robust by construction: the mapping is
|
|
1490
1515
|
absolute (no min/max over the live distribution), so it cannot explode on
|
|
1491
|
-
a skewed store. Pure functions — the ratio is behaviorally tested.
|
|
1492
|
-
|
|
1516
|
+
a skewed store. Pure functions — the ratio is behaviorally tested.
|
|
1517
|
+
#474 graph final (owner 2026-09-19): the balls at 30% — 1.8→2.7, exactly
|
|
1518
|
+
0.30× of the 6→9 law; the depth divisor and the ruled ratio band are
|
|
1519
|
+
scale-invariant and unchanged. */
|
|
1520
|
+
function bubbleRadius(s){ return 1.8 + Math.sqrt(clamp(s??0,0,1))*0.9; }
|
|
1493
1521
|
function depthSizeDivisor(dz){ return Math.pow(Math.max(.14,dz),0.35); }
|
|
1494
1522
|
|
|
1495
1523
|
/* ---------- live-data state ---------- */
|
|
@@ -1506,7 +1534,7 @@ let TOTAL=0, removedNow=0;
|
|
|
1506
1534
|
clock (owner ruling 2026-09-13; only the boot reveal counts up) */
|
|
1507
1535
|
|
|
1508
1536
|
/* =====================================================================
|
|
1509
|
-
WORLD — domains, memories
|
|
1537
|
+
WORLD — domains, memories, the dateline window (the visible set), real
|
|
1510
1538
|
links, the replay ledger. All positions derive from id hashes → stable
|
|
1511
1539
|
across reloads and across the refreshes after Update/Remove.
|
|
1512
1540
|
===================================================================== */
|
|
@@ -1515,8 +1543,14 @@ const PORT = [ [.50,.20,.15],[.28,.38,.12],[.74,.40,.12],[.50,.62,.13],[.25,.68,
|
|
|
1515
1543
|
let DOMAINS = []; // {name,count,land,port,cx,cy,cr}
|
|
1516
1544
|
const mems = new Map(); // id -> memory object (live + replay ghosts)
|
|
1517
1545
|
const links = []; // real link edges, engine-decorated
|
|
1518
|
-
const bubbles = []; // the ~120-mem interactive importance sample
|
|
1519
1546
|
let crowdByStage = {}; // stage -> [mem refs] (EVERY memory paints)
|
|
1547
|
+
const bubbles = []; // the latest-N-by-dateline visible set (#474
|
|
1548
|
+
// return; owned by refreshWindow, rebuilt on T)
|
|
1549
|
+
const FIELD_WINDOW_N = 1000; // #474 graph final (owner 2026-09-19): the field shows the latest N memories by dateline
|
|
1550
|
+
let WIN_ORDER = []; // every mem (live + ghosts), effCreated DESC, id ASC
|
|
1551
|
+
let winSet = new Set(); // ids in the window at the current T
|
|
1552
|
+
let winCount = []; // per-domain window counts (labels + tip)
|
|
1553
|
+
let winT = -1;
|
|
1520
1554
|
let byAgentCounts = {}; // source_agent -> count
|
|
1521
1555
|
let CONTEXTS = []; // [{id,name,machine,count}] — #421 machine × harness grouping
|
|
1522
1556
|
let adj = new Map(); // id -> [neighbor ids] (real links)
|
|
@@ -1525,6 +1559,13 @@ let learnedL = [], mergedL = [], enrichedL = [];
|
|
|
1525
1559
|
let NIGHTS = []; // the events payload's night list
|
|
1526
1560
|
let WINDOW = 1, NOW_T = .999, REPLAY_OK = false;
|
|
1527
1561
|
|
|
1562
|
+
/* Replay pacing (owner 2026-09-19: 2x faster default). Event-driven cruise:
|
|
1563
|
+
each ledger event lands every REPLAY_TICK_MS; a heralded (birth/merge)
|
|
1564
|
+
event holds the clock REPLAY_HERALD_MS then applies; boundary beats rest
|
|
1565
|
+
REPLAY_REST_MS. Halve all three to run 2x; the constants are the only
|
|
1566
|
+
pacing surface. */
|
|
1567
|
+
const REPLAY_TICK_MS=205, REPLAY_HERALD_MS=108, REPLAY_REST_MS=800;
|
|
1568
|
+
|
|
1528
1569
|
function domIndex(domain){ const i = DOMAINS.findIndex(d=>d.name===domain); return i<0?0:i; }
|
|
1529
1570
|
function titleOf(id){ const m=mems.get(id); return m?m.title:'(absorbed)'; }
|
|
1530
1571
|
|
|
@@ -1589,6 +1630,10 @@ function buildWorld(){
|
|
|
1589
1630
|
if(!m.ghost && !keep.has(id)) mems.delete(id);
|
|
1590
1631
|
}
|
|
1591
1632
|
|
|
1633
|
+
// the crowd: EVERY memory, bucketed by stage for one fillStyle per pass
|
|
1634
|
+
crowdByStage = { forming:[], belief:[], truth:[], fading:[] };
|
|
1635
|
+
for(const m of mems.values()) (crowdByStage[m.stage]||crowdByStage.forming).push(m);
|
|
1636
|
+
|
|
1592
1637
|
// replay metadata from the events ledger: in-window births + merge-outs
|
|
1593
1638
|
// (absorbed losers get ghost entries so their merge animation has a
|
|
1594
1639
|
// position and their birth a bloom — they are not part of the live field).
|
|
@@ -1657,34 +1702,12 @@ function buildWorld(){
|
|
|
1657
1702
|
}
|
|
1658
1703
|
}
|
|
1659
1704
|
|
|
1660
|
-
//
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
//
|
|
1665
|
-
|
|
1666
|
-
// (largest-remainder to the fixed total, minimum 1 each), each quota filled
|
|
1667
|
-
// by that stage's OWN strength→access ranking with an id-ASC tie-break —
|
|
1668
|
-
// fully deterministic, no Math.random. The old global top-120-by-strength
|
|
1669
|
-
// sample was 100% truth BY CONSTRUCTION (truth IS the top strength band),
|
|
1670
|
-
// so every touchable dot read green and the 1–2px crowd was visually
|
|
1671
|
-
// negligible; on an even store this yields ~30/30/30/30.
|
|
1672
|
-
bubbles.length = 0;
|
|
1673
|
-
{
|
|
1674
|
-
const BUBBLE_N=120;
|
|
1675
|
-
const stageArrs=STAGE_KEYS.map(k=>crowdByStage[k].filter(m=>!m.ghost)
|
|
1676
|
-
.sort((a,b)=> b.strength-a.strength || b.access-a.access || (a.id<b.id?-1:a.id>b.id?1:0)));
|
|
1677
|
-
const liveCount=stageArrs.reduce((n,a)=>n+a.length,0);
|
|
1678
|
-
if(liveCount>0){
|
|
1679
|
-
const exact=stageArrs.map(a=>a.length/liveCount*BUBBLE_N);
|
|
1680
|
-
const quota=exact.map(Math.floor);
|
|
1681
|
-
for(let i=0;i<quota.length;i++) if(quota[i]===0&&stageArrs[i].length>0) quota[i]=1;
|
|
1682
|
-
let left=BUBBLE_N-quota.reduce((n,q)=>n+q,0);
|
|
1683
|
-
const order=exact.map((_,i)=>i).sort((a,b)=>(exact[b]%1)-(exact[a]%1)); // remainder DESC, stage order tie
|
|
1684
|
-
for(let oi=0; left>0; oi++, left--) quota[order[oi%order.length]]++;
|
|
1685
|
-
stageArrs.forEach((a,i)=>{ bubbles.push(...a.slice(0,Math.min(quota[i],a.length))); });
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1705
|
+
// #474 return: the visible set is the dateline WINDOW, not a sample —
|
|
1706
|
+
// WIN_ORDER walks every mem (live + ghosts) newest-first (effCreated DESC,
|
|
1707
|
+
// id ASC tie-break; ghosts sort via their birth night's date), and
|
|
1708
|
+
// refreshWindow (draw) slices the latest FIELD_WINDOW_N alive-at-T rows
|
|
1709
|
+
// out of it each time T moves.
|
|
1710
|
+
WIN_ORDER = Array.from(mems.values()).sort(winCmp);
|
|
1688
1711
|
|
|
1689
1712
|
// contexts (source_agent values) with their machine stamps (#421 machine ×
|
|
1690
1713
|
// harness): the rail + capture card group on (machine ?? legacy) × harness.
|
|
@@ -1746,6 +1769,31 @@ function aliveAt(b,t){
|
|
|
1746
1769
|
return true;
|
|
1747
1770
|
}
|
|
1748
1771
|
function dateAt(t){ const i=clamp(Math.floor(t),0,NIGHTS.length-1); return NIGHTS[i]?NIGHTS[i].date:''; }
|
|
1772
|
+
/* #474 return: the visible set is a DATELINE WINDOW — at replay clock T the
|
|
1773
|
+
field draws the latest FIELD_WINDOW_N memories by effective created date
|
|
1774
|
+
(created_at; ghosts via their birth night), not a sample and not the whole
|
|
1775
|
+
store. Pure helpers (behaviorally tested). */
|
|
1776
|
+
function effCreated(m){ return m.created || (m.born>=0 ? dateAt(m.born) : ''); }
|
|
1777
|
+
function windowPick(order, t, n, dl, isNow){
|
|
1778
|
+
const out=[];
|
|
1779
|
+
for(const m of order){
|
|
1780
|
+
if(out.length>=n) break;
|
|
1781
|
+
if(!aliveAt(m,t)) continue;
|
|
1782
|
+
if(!isNow && m.born<0 && effCreated(m)>dl) continue; // untracked + newer than the dateline
|
|
1783
|
+
out.push(m);
|
|
1784
|
+
}
|
|
1785
|
+
return out;
|
|
1786
|
+
}
|
|
1787
|
+
function winCmp(a,b){ return effCreated(b)<effCreated(a)?-1: effCreated(b)>effCreated(a)?1: a.id<b.id?-1:1; }
|
|
1788
|
+
function refreshWindow(t){
|
|
1789
|
+
if(t===winT) return;
|
|
1790
|
+
winT=t;
|
|
1791
|
+
const picked = windowPick(WIN_ORDER, t, FIELD_WINDOW_N, dateAt(t), t>=NOW_T);
|
|
1792
|
+
winSet = new Set(picked.map(m=>m.id));
|
|
1793
|
+
winCount = new Array(DOMAINS.length).fill(0);
|
|
1794
|
+
for(const m of picked) winCount[m.dom]++;
|
|
1795
|
+
bubbles.length=0; bubbles.push(...picked);
|
|
1796
|
+
}
|
|
1749
1797
|
|
|
1750
1798
|
/* =====================================================================
|
|
1751
1799
|
THEME — one engine, two palettes. Dark (the brand night: glow) is the
|
|
@@ -1903,22 +1951,16 @@ function sprite(stage, r){
|
|
|
1903
1951
|
const st = PAL.stages[stage] || PAL.stages.forming;
|
|
1904
1952
|
const rgb = st.rgb;
|
|
1905
1953
|
if(PAL.name==='dark'){
|
|
1954
|
+
/* #474 final polish (owner 2026-09-20): plain dot — no glow halo, no
|
|
1955
|
+
white core gradient. A filled circle with a slightly brighter edge;
|
|
1956
|
+
the maturity color carries the reading, the size stays small. */
|
|
1906
1957
|
const S = Math.ceil(rad*PAL.sprK), c2 = document.createElement('canvas');
|
|
1907
1958
|
c2.width=S; c2.height=S;
|
|
1908
1959
|
const g = c2.getContext('2d'), cxp=S/2;
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
g.fillStyle=gr; g.fillRect(0,0,S,S);
|
|
1914
|
-
gr = g.createRadialGradient(cxp-rad*.28,cxp-rad*.32,rad*.1, cxp,cxp,rad);
|
|
1915
|
-
gr.addColorStop(0,'rgba(255,255,255,'+(.5*st.alpha)+')');
|
|
1916
|
-
gr.addColorStop(.35, rgba(rgb,.55*st.alpha));
|
|
1917
|
-
gr.addColorStop(.82, rgba(rgb,.22*st.alpha));
|
|
1918
|
-
gr.addColorStop(1, rgba(rgb,.04));
|
|
1919
|
-
g.fillStyle=gr; g.beginPath(); g.arc(cxp,cxp,rad,0,7); g.fill();
|
|
1920
|
-
g.strokeStyle=rgba(rgb,.34*st.alpha); g.lineWidth=1;
|
|
1921
|
-
g.beginPath(); g.arc(cxp,cxp,rad-.5,0,7); g.stroke();
|
|
1960
|
+
g.fillStyle=rgba(rgb,.88*st.alpha);
|
|
1961
|
+
g.beginPath(); g.arc(cxp,cxp,rad*.82,0,7); g.fill();
|
|
1962
|
+
g.strokeStyle=rgba(rgb,.45*st.alpha); g.lineWidth=1;
|
|
1963
|
+
g.beginPath(); g.arc(cxp,cxp,rad*.82,0,7); g.stroke();
|
|
1922
1964
|
/* #422 round 2: fading's DISTINCT outer ring — the rim stage's fill runs
|
|
1923
1965
|
at low alpha by design; without its own edge treatment the dots were
|
|
1924
1966
|
illegible against the night ground */
|
|
@@ -2001,7 +2043,7 @@ function buildPaths(){
|
|
|
2001
2043
|
}
|
|
2002
2044
|
}
|
|
2003
2045
|
function pathAlive(p,t){
|
|
2004
|
-
for(const id of p.nodes){ const b=mems.get(id); if(!b||!aliveAt(b,t)) return false; }
|
|
2046
|
+
for(const id of p.nodes){ const b=mems.get(id); if(!b||!aliveAt(b,t)||!winSet.has(id)) return false; }
|
|
2005
2047
|
return t>=p.born;
|
|
2006
2048
|
}
|
|
2007
2049
|
function spawnSignal(showcase){
|
|
@@ -2060,8 +2102,10 @@ function advanceSignals(now, dt){
|
|
|
2060
2102
|
}
|
|
2061
2103
|
|
|
2062
2104
|
/* =====================================================================
|
|
2063
|
-
THE FRAME — theme-aware;
|
|
2064
|
-
|
|
2105
|
+
THE FRAME — theme-aware; synapses, signals, bubbles (painter-sorted
|
|
2106
|
+
far→near), waymarkers, furniture. #474 return: the ONLY dots drawn are
|
|
2107
|
+
the dateline window (latest FIELD_WINDOW_N by effective created date at
|
|
2108
|
+
the replay clock — see refreshWindow); no crowd pass, no sample.
|
|
2065
2109
|
===================================================================== */
|
|
2066
2110
|
let labelRects=[];
|
|
2067
2111
|
/* emergence queue (#422 live review): a night's births/links become VISIBLE
|
|
@@ -2105,6 +2149,7 @@ function processEmergence(t){
|
|
|
2105
2149
|
}
|
|
2106
2150
|
function draw(now, dt){
|
|
2107
2151
|
const t=T;
|
|
2152
|
+
refreshWindow(t); // #474: the visible set = latest-N by dateline at this T (bubbles, winSet, winCount)
|
|
2108
2153
|
const dark = PAL.name==='dark';
|
|
2109
2154
|
const ADD = dark ? 'lighter' : 'source-over';
|
|
2110
2155
|
ctx.clearRect(0,0,view.w,view.h);
|
|
@@ -2170,6 +2215,12 @@ function draw(now, dt){
|
|
|
2170
2215
|
}
|
|
2171
2216
|
ctx.globalAlpha=1;
|
|
2172
2217
|
|
|
2218
|
+
/* emergence flags resolve FIRST (once per frame) — the visible set and
|
|
2219
|
+
the link pass below read them; dots still queued (_emerged===false)
|
|
2220
|
+
stay invisible until their frame budget comes up. (#474: the old
|
|
2221
|
+
every-memory crowd pass is gone — the window IS the field.) */
|
|
2222
|
+
processEmergence(t);
|
|
2223
|
+
|
|
2173
2224
|
/* THE CROWD — every memory in the store as maturity-colored micro-stars
|
|
2174
2225
|
behind the touchable sample (no sampling: the dot count IS the store).
|
|
2175
2226
|
One fillStyle per stage pass. The emergence queue is resolved FIRST
|
|
@@ -2187,7 +2238,7 @@ function draw(now, dt){
|
|
|
2187
2238
|
if(fog<.15) continue;
|
|
2188
2239
|
const [sx,sy]=proj3(m.nx||.5,m.ny||.5,dz);
|
|
2189
2240
|
if(sx<-2||sy<-2||sx>view.w+2||sy>view.h+2) continue;
|
|
2190
|
-
ctx.globalAlpha=fog*.5;
|
|
2241
|
+
ctx.globalAlpha=fog*.5*(focusDom!=null&&m.dom!==focusDom?.15:1);
|
|
2191
2242
|
const px=Math.max(1,Math.round((rand01(m.id,9)<.85?1:1.8)/dz*1.4));
|
|
2192
2243
|
ctx.fillRect(sx,sy,px,px);
|
|
2193
2244
|
}
|
|
@@ -2241,6 +2292,7 @@ function draw(now, dt){
|
|
|
2241
2292
|
if(L.rk>=lodK) continue; // zoom LOD (lines only)
|
|
2242
2293
|
const a=mems.get(L.a), b=mems.get(L.b);
|
|
2243
2294
|
if(!a||!b||!aliveAt(a,t)||!aliveAt(b,t)) continue;
|
|
2295
|
+
/* #474 final polish: the both-endpoints-in-window gate killed the mesh — links draw between ANY placed memories (bedrock parity: the full LOD-tamed mesh), endpoints carry positions regardless of window membership */
|
|
2244
2296
|
if(a._emerged===false||b._emerged===false) continue; // thread waits for both endpoints
|
|
2245
2297
|
const [ax,ay]=bpos(a,now,t), [bx,by]=bpos(b,now,t);
|
|
2246
2298
|
const ctrl=segCtrlN(ax,ay,bx,by,(L.use>18?1:-1));
|
|
@@ -2255,6 +2307,9 @@ function draw(now, dt){
|
|
|
2255
2307
|
const prog = L.forming ? clamp((t-(L._emergeT!==undefined?L._emergeT:L.born))/1.4,0,1) : 1;
|
|
2256
2308
|
const drawP=Math.min(prog,linkBoot);
|
|
2257
2309
|
if(drawP<=0) continue;
|
|
2310
|
+
/* #474 final polish: domain focus — a thread stays lit only if an
|
|
2311
|
+
endpoint belongs to the focused domain (owner 2026-09-20) */
|
|
2312
|
+
const focusDim = (focusDom!=null && a.dom!==focusDom && b.dom!==focusDom) ? .15 : 1;
|
|
2258
2313
|
const len=Math.hypot(x2-x1,y2-y1)*1.15;
|
|
2259
2314
|
const superFam = L.rel==='superseded_by'||L.rel==='corrected_by';
|
|
2260
2315
|
/* fix-round-3 weights: settled alphas roughly halved (both themes) so the
|
|
@@ -2262,7 +2317,7 @@ function draw(now, dt){
|
|
|
2262
2317
|
const bright=(a.stage==='truth'||b.stage==='truth') ? (dark?.07:.11) : (dark?.035:.06);
|
|
2263
2318
|
const baseW=.34+useF*.55+heat*.5;
|
|
2264
2319
|
/* the SETTLED stroke is always the base */
|
|
2265
|
-
ctx.strokeStyle=rgba(PAL.thread,(bright*(superFam?.45:1)+useF*(dark?.05:.07)+heat*.28)*linkBoot*tfog);
|
|
2320
|
+
ctx.strokeStyle=rgba(PAL.thread,(bright*(superFam?.45:1)+useF*(dark?.05:.07)+heat*.28)*linkBoot*tfog*focusDim);
|
|
2266
2321
|
ctx.lineWidth=baseW;
|
|
2267
2322
|
ctx.setLineDash(superFam?[4,4]:[len*drawP,1e5]);
|
|
2268
2323
|
ctx.beginPath(); ctx.moveTo(x1,y1); ctx.quadraticCurveTo(cx1,cy1,x2,y2); ctx.stroke();
|
|
@@ -2271,7 +2326,7 @@ function draw(now, dt){
|
|
|
2271
2326
|
in the same proportion as the settled stroke) */
|
|
2272
2327
|
const settle=1-prog;
|
|
2273
2328
|
const baseA=(dark? .07 : .09)+((dark?.15:.17)-(dark?.07:.09))*drawP;
|
|
2274
|
-
ctx.strokeStyle=rgba(PAL.threadHot,(baseA+.14*heat)*tfog*(superFam?.5:1)*settle);
|
|
2329
|
+
ctx.strokeStyle=rgba(PAL.threadHot,(baseA+.14*heat)*tfog*(superFam?.5:1)*settle*focusDim);
|
|
2275
2330
|
ctx.lineWidth=baseW+(.18+drawP*.3)*settle;
|
|
2276
2331
|
ctx.setLineDash(superFam?[4,4]:[len*drawP,1e5]);
|
|
2277
2332
|
ctx.beginPath(); ctx.moveTo(x1,y1); ctx.quadraticCurveTo(cx1,cy1,x2,y2); ctx.stroke();
|
|
@@ -2346,8 +2401,9 @@ function draw(now, dt){
|
|
|
2346
2401
|
dark-blue-on-near-black at ~4px read invisible to a vision model);
|
|
2347
2402
|
the projection factor is known here, and far-stage bubbles (rim depth
|
|
2348
2403
|
/ small viewports) were collapsing to ~1-2px. Every stage stays a
|
|
2349
|
-
legible glimmer; ordering untouched.
|
|
2350
|
-
|
|
2404
|
+
legible glimmer; ordering untouched. #474 graph final: floor 1.5 —
|
|
2405
|
+
0.30× of 5, proportional with the 30% balls. */
|
|
2406
|
+
r=Math.max(r,1.5);
|
|
2351
2407
|
let remA=1;
|
|
2352
2408
|
if(b.removing){ const p=clamp((now-b.removing)/700,0,1); remA=1-p; if(p>=1){ b.removed=true; b.removing=undefined; } }
|
|
2353
2409
|
const ex=b._ex||0;
|
|
@@ -2447,8 +2503,11 @@ function draw(now, dt){
|
|
|
2447
2503
|
ctx.font=(9.5*k).toFixed(1)+'px '+FF;
|
|
2448
2504
|
try{ ctx.letterSpacing=(1*k).toFixed(1)+'px'; }catch(e){}
|
|
2449
2505
|
ctx.fillStyle= dark? 'rgba(90,90,90,'+(.85*dimming*lp)+')' : hexA(PAL.labelCount,dimming*lp);
|
|
2450
|
-
|
|
2451
|
-
|
|
2506
|
+
/* #474: the label count is the WINDOW count (what is drawn at this T),
|
|
2507
|
+
not the store total — honest with the dateline view. */
|
|
2508
|
+
const cnt=fmt(winCount[i]||0);
|
|
2509
|
+
ctx.fillText(cnt, sx+w+9*k, sy);
|
|
2510
|
+
const bw=w+9*k+ctx.measureText(cnt).width;
|
|
2452
2511
|
ctx.strokeStyle= active? rgba(PAL.stages.truth.rgb,.55*lp) : (dark? 'rgba(120,130,140,'+(.4*dimming*lp)+')' : 'rgba(96,92,78,'+(.5*dimming*lp)+')');
|
|
2453
2512
|
ctx.lineWidth=1;
|
|
2454
2513
|
const bx=sx-9*k, by=sy-11*k, bxx=bx+bw+9*k, byy=by+15*k, tk=4*k;
|
|
@@ -2613,18 +2672,18 @@ function autoTick(now){
|
|
|
2613
2672
|
if(T>=NOW_T-.001){
|
|
2614
2673
|
/* a beat at "now": re-kick to the range start ONLY before the first
|
|
2615
2674
|
full playback; after it, REST here — plays once, never loops (#452) */
|
|
2616
|
-
if(played){ autoPlay=false; autoNextAt=now+
|
|
2617
|
-
autoEvIdx=0; autoNextAt=now+
|
|
2675
|
+
if(played){ autoPlay=false; autoNextAt=now+REPLAY_REST_MS; return; }
|
|
2676
|
+
autoEvIdx=0; autoNextAt=now+REPLAY_REST_MS; seek(.001); return;
|
|
2618
2677
|
}
|
|
2619
2678
|
while(autoEvIdx<EVENTS.length && EVENTS[autoEvIdx].t<=T+.0001) autoEvIdx++;
|
|
2620
2679
|
if(autoEvIdx>=EVENTS.length){
|
|
2621
2680
|
/* ledger exhausted: arrive at today and complete the playback (the
|
|
2622
2681
|
flags go BEFORE the seek so onTChanged's control swap sees them) */
|
|
2623
|
-
autoNextAt=now+
|
|
2682
|
+
autoNextAt=now+REPLAY_REST_MS; played=true; autoPlay=false; seek(WINDOW); return;
|
|
2624
2683
|
}
|
|
2625
2684
|
const ev=EVENTS[autoEvIdx++];
|
|
2626
|
-
if(ev.id && signals.length<8){ heraldTo(ev.id); pendingApply={t:ev.t+.001, at:now+
|
|
2627
|
-
else { seek(ev.t+.001); autoNextAt=now+
|
|
2685
|
+
if(ev.id && signals.length<8){ heraldTo(ev.id); pendingApply={t:ev.t+.001, at:now+REPLAY_HERALD_MS}; }
|
|
2686
|
+
else { seek(ev.t+.001); autoNextAt=now+REPLAY_TICK_MS; }
|
|
2628
2687
|
}
|
|
2629
2688
|
track.addEventListener('pointerdown',e=>{ if(!REPLAY_OK) return; scrubbing=true; manualTake(); track.setPointerCapture(e.pointerId); seek(trackFrac(e)*WINDOW); });
|
|
2630
2689
|
track.addEventListener('pointermove',e=>{ if(scrubbing) seek(trackFrac(e)*WINDOW); });
|
|
@@ -2841,7 +2900,8 @@ cv.addEventListener('pointermove',e=>{
|
|
|
2841
2900
|
tip.style.display='block';
|
|
2842
2901
|
tip.style.left=Math.min(e.clientX+14,window.innerWidth-300)+'px';
|
|
2843
2902
|
tip.style.top=(e.clientY+16)+'px';
|
|
2844
|
-
|
|
2903
|
+
/* #474: the window count at this T — honest with what is drawn */
|
|
2904
|
+
tip.innerHTML='<b>'+esc(d.name)+'</b><span style="color:var(--dim)">'+fmt(winCount[lb]||0)+' in view</span>';
|
|
2845
2905
|
}else tip.style.display='none';
|
|
2846
2906
|
dirty=true;
|
|
2847
2907
|
});
|
|
@@ -3114,23 +3174,6 @@ function buildTokNights(used, cap, periodStart){
|
|
|
3114
3174
|
}
|
|
3115
3175
|
}
|
|
3116
3176
|
|
|
3117
|
-
/* trend = mean of the last 7 nights vs the prior 7 (a DEFINED window — the
|
|
3118
|
-
old first-vs-last-over-the-range comparison had no window at all). Titles
|
|
3119
|
-
state the window so the arrow is never mysterious. */
|
|
3120
|
-
function recallTrend(){
|
|
3121
|
-
const flat={cls:'flat',sym:'▬'};
|
|
3122
|
-
if(!D||!D.series) return Object.assign(flat,{title:'no snapshot data'});
|
|
3123
|
-
const vals=D.series.map(s=>s.metrics&&s.metrics.adoption?s.metrics.adoption.uses_per_showing:null).filter(v=>typeof v==='number');
|
|
3124
|
-
const last7=vals.slice(-7), prior7=vals.slice(-14,-7);
|
|
3125
|
-
const mean=a=>a.length?a.reduce((x,y)=>x+y,0)/a.length:null;
|
|
3126
|
-
const a=mean(prior7), b=mean(last7);
|
|
3127
|
-
if(a===null||b===null) return Object.assign(flat,{title:'trend needs 7+ nights of history'});
|
|
3128
|
-
const d=b-a;
|
|
3129
|
-
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)+')'};
|
|
3130
|
-
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)+')'};
|
|
3131
|
-
return Object.assign(flat,{title:'flat — mean of the last 7 nights vs the prior 7 ('+b.toFixed(3)+' vs '+a.toFixed(3)+')'});
|
|
3132
|
-
}
|
|
3133
|
-
|
|
3134
3177
|
/* ---------- Recall level — the designed U-band (#426 final ruling
|
|
3135
3178
|
2026-09-13). A continuous red→green→red gradient spans the PROVISIONAL
|
|
3136
3179
|
zone edges (echoed by /dashboard/field as thresholds.recall_uses — the
|
|
@@ -3180,7 +3223,14 @@ function recallGradAt(frac,z,theme){
|
|
|
3180
3223
|
}
|
|
3181
3224
|
let lastRecUses=null; /* setTheme's re-render carries the last value */
|
|
3182
3225
|
function renderRecBand(ups){
|
|
3226
|
+
/* #476: the marker/tooltip read the WINDOW ratio when the memory_precision
|
|
3227
|
+
block is present; a pre-#476 server (no block) degrades to the headline
|
|
3228
|
+
ratio — today's rendering exactly (the capture card's block-absence
|
|
3229
|
+
guard pattern). A null window value honestly renders "—" below. */
|
|
3230
|
+
const mp=D&&D.memory_precision?D.memory_precision:null;
|
|
3231
|
+
if(mp&&mp.level2) ups=mp.level2.uses_per_showing;
|
|
3183
3232
|
lastRecUses=ups;
|
|
3233
|
+
renderRecL1(mp);
|
|
3184
3234
|
const z=F&&F.thresholds?F.thresholds.recall_uses:null;
|
|
3185
3235
|
const axis=z&&typeof z.axis_max==='number'&&z.axis_max>0?z.axis_max:null;
|
|
3186
3236
|
const row=el('rec-bandrow'), band=el('rec-band'), dot=el('rec-dot'), word=el('rec-zone');
|
|
@@ -3204,7 +3254,7 @@ function renderRecBand(ups){
|
|
|
3204
3254
|
if(zk){
|
|
3205
3255
|
dot.hidden=false;
|
|
3206
3256
|
dot.style.left=pct(ups)+'%';
|
|
3207
|
-
dot.title=ups.toFixed(3)+' uses per showing — last 30
|
|
3257
|
+
dot.title=ups.toFixed(3)+' uses per showing — last '+(mp&&mp.window_days?mp.window_days:30)+' days';
|
|
3208
3258
|
word.textContent=RECALL_ZONE_WORD[zk];
|
|
3209
3259
|
word.className='n rec-word';
|
|
3210
3260
|
/* the big word's color = the gradient sampled AT the marker — the word
|
|
@@ -3220,16 +3270,67 @@ function renderRecBand(ups){
|
|
|
3220
3270
|
word.style.color=''; word.style.textShadow='none';
|
|
3221
3271
|
word.title='no showings yet';
|
|
3222
3272
|
}
|
|
3223
|
-
/* trend arrow
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
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). */
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
/* ---------- Memory Precision — Level 1, the pushed index (#476). A compact
|
|
3281
|
+
second row beside Level 2's U-band: mean similarity of pushed lines to
|
|
3282
|
+
their prompt (a 0..1 bar with a floor tick at the /dashboard/field echo of
|
|
3283
|
+
recall_min_similarity — the server's own recall floor, never a page
|
|
3284
|
+
literal), muted below the floor (the index row reads conservative: its
|
|
3285
|
+
noise lands on every prompt), plus the redundancy share (lines restating
|
|
3286
|
+
the session's standing context at/above the echoed cosine). Direction-only
|
|
3287
|
+
coloring, NO verdict words — the #426 semantics ruling extended.
|
|
3288
|
+
Divergence: the COUNT on the card face, the ≤3 titles hover-only (no
|
|
3289
|
+
memory lists on the main page, owner 2026-09-12 — the search panel is the
|
|
3290
|
+
list surface). Absent block (pre-#476 server) → the whole row hides and
|
|
3291
|
+
the sub keeps the old label — today's rendering exactly. */
|
|
3292
|
+
function renderRecL1(mp){
|
|
3293
|
+
const row=el('rec-l1'), sub=el('rec-sub'), dv=el('rec-div');
|
|
3294
|
+
if(!mp||!mp.level1||!mp.level2){
|
|
3295
|
+
row.hidden=true; dv.hidden=true; dv.title='';
|
|
3296
|
+
if(sub) sub.textContent='uses per showing';
|
|
3297
|
+
return;
|
|
3232
3298
|
}
|
|
3299
|
+
if(sub) sub.textContent='last '+(mp.window_days||90)+' days';
|
|
3300
|
+
const l1=mp.level1;
|
|
3301
|
+
const floor=(F&&F.thresholds&&typeof F.thresholds.recall_min_similarity==='number')?F.thresholds.recall_min_similarity:null;
|
|
3302
|
+
const ra=(l1.thresholds&&typeof l1.thresholds.redundant_above==='number')?l1.thresholds.redundant_above:null;
|
|
3303
|
+
const mins=(l1.thresholds&&typeof l1.thresholds.divergence_min_shown==='number')?l1.thresholds.divergence_min_shown:5;
|
|
3304
|
+
const sim=(typeof l1.mean_similarity==='number'&&isFinite(l1.mean_similarity))?l1.mean_similarity:null;
|
|
3305
|
+
const red=(typeof l1.redundant_share==='number'&&isFinite(l1.redundant_share))?l1.redundant_share:null;
|
|
3306
|
+
if(sim===null){
|
|
3307
|
+
row.hidden=true; /* nothing measured in the window — the row degrades away */
|
|
3308
|
+
}else{
|
|
3309
|
+
row.hidden=false;
|
|
3310
|
+
row.classList.toggle('below',floor!==null&&sim<floor);
|
|
3311
|
+
/* numbers only on the face — direction carries the meaning, no verdict words */
|
|
3312
|
+
/* #476 owner rename (2026-09-20): the three buckets as named — Relevant /
|
|
3313
|
+
Repeated known / Off-target. Relevant = the mean relevance; Repeated =
|
|
3314
|
+
the redundant share; Off-target = the remainder (pushed lines that were
|
|
3315
|
+
neither relevant nor new). Numbers, no verdict words (#426). */
|
|
3316
|
+
const relPct=Math.round(clamp(sim,0,1)*100);
|
|
3317
|
+
const repPct=red!==null?Math.round(clamp(red,0,1)*100):0;
|
|
3318
|
+
const offPct=Math.max(0,100-relPct-repPct);
|
|
3319
|
+
const dv=mp.divergence, nUsed=(dv&&typeof dv.count==='number')?dv.count:0;
|
|
3320
|
+
el('l1-rel').innerHTML='<b>Relevant: '+relPct+'%</b>';
|
|
3321
|
+
el('l1-rep').textContent='Repeated known: '+repPct+'%';
|
|
3322
|
+
el('l1-off').textContent='Off-target: '+offPct+'%'+(nUsed>0?' ('+nUsed+' never used)':'');
|
|
3323
|
+
row.title='pushed index, last '+(mp.window_days||90)+' days — mean similarity of pushed lines to their prompt (tick at the recall floor '+
|
|
3324
|
+
(floor!==null?floor.toFixed(2):'—')+'; muted below it)'+
|
|
3325
|
+
(ra!==null?'; redundant = share of lines at ≥'+ra.toFixed(2)+' cosine vs the session\'s standing context (lessons + identity)':'')+
|
|
3326
|
+
' · '+fmt(l1.pushes)+' pushes, '+fmt(l1.lines)+' lines';
|
|
3327
|
+
}
|
|
3328
|
+
/* divergence — the face count is amber; the ≤3 lines ride the native
|
|
3329
|
+
tooltip ONLY (text via .title, never face content) */
|
|
3330
|
+
/* #476 owner bundling (2026-09-20): the never-used count rides inside
|
|
3331
|
+
Off-target; the separate face element stays hidden (titles on hover) */
|
|
3332
|
+
const dEl=el('rec-div');
|
|
3333
|
+
if(dEl){ dEl.hidden=true; }
|
|
3233
3334
|
}
|
|
3234
3335
|
|
|
3235
3336
|
let MODEL_LABEL='';
|
package/dist/calibration.d.ts
CHANGED
|
@@ -105,6 +105,39 @@ export declare const RECALL_USES_NORMAL_MAX = 0.25;
|
|
|
105
105
|
* PROVISIONAL (owner anchor 2026-09-13, #426) — chosen so Overfetching
|
|
106
106
|
* keeps a visible span, not a measured bound. */
|
|
107
107
|
export declare const RECALL_USES_AXIS_MAX = 0.3;
|
|
108
|
+
/**
|
|
109
|
+
* Retention horizon for the recall_pushes/recall_events sidecar tables AND the
|
|
110
|
+
* longest window the Memory Precision card shows — ONE constant feeds both
|
|
111
|
+
* (the CAPTURE_HEALTH_WINDOW_DAYS single-constant law: the card can never
|
|
112
|
+
* claim a window the store no longer has rows for). 90 = the longest #452
|
|
113
|
+
* range option that the retention can honestly serve; 180d and all clamp to
|
|
114
|
+
* it server-side and the payload echoes the effective window_days.
|
|
115
|
+
*/
|
|
116
|
+
export declare const MEMORY_PRECISION_WINDOW_DAYS = 90;
|
|
117
|
+
/**
|
|
118
|
+
* Cosine at/above which a pushed line reads "redundant" (restating the
|
|
119
|
+
* session's standing context — the top lessons + identity every session-start
|
|
120
|
+
* hook injects). Direction-only display guidance, never a gate. 0.80 mirrors
|
|
121
|
+
* SUPERSESSION_MIN_SIMILARITY: at/above it a pair reads as the same
|
|
122
|
+
* statement, below it as topical overlap — a reasonable first anchor until
|
|
123
|
+
* the judged-calibration follow-up measures the real distribution (the
|
|
124
|
+
* #426 provisional-anchor posture).
|
|
125
|
+
*/
|
|
126
|
+
export declare const MEMORY_PRECISION_REDUNDANT_ABOVE = 0.8;
|
|
127
|
+
/**
|
|
128
|
+
* Window showings a live memory needs (with zero window fetches) to count as
|
|
129
|
+
* DIVERGING — the index keeps pushing it, nothing ever reads it. 5 is the
|
|
130
|
+
* spec's anchor (#476): enough showings that the silence is a pattern, not
|
|
131
|
+
* one prompt's turn-suppression.
|
|
132
|
+
*/
|
|
133
|
+
export declare const MEMORY_PRECISION_DIVERGENCE_MIN_SHOWN = 5;
|
|
134
|
+
/**
|
|
135
|
+
* Cap on the prompt excerpt persisted per recall_pushes row (Option A,
|
|
136
|
+
* owner-blessed 2026-09-19: the first-ever server-side persistence of raw
|
|
137
|
+
* prompt text, bounded to 256 chars and pruned at the retention horizon —
|
|
138
|
+
* the same trust boundary as /distill's denoised conversation text).
|
|
139
|
+
*/
|
|
140
|
+
export declare const MEMORY_PRECISION_PROMPT_EXCERPT_CHARS = 256;
|
|
108
141
|
/** Semantic-similarity share of the composite score. 0.50 (raised from 0.40
|
|
109
142
|
* in the 0.15.2 rebalance, #191 Phase B): on the production corpus effective
|
|
110
143
|
* strength (0.30) outweighed what similarity could recover — hardened old
|
|
@@ -223,6 +256,18 @@ export declare const BM25_WEIGHT_DOMAIN = 2;
|
|
|
223
256
|
* base-1.0 rows decay again.
|
|
224
257
|
*/
|
|
225
258
|
export declare const IMPORTANCE_CEILING = 0.95;
|
|
259
|
+
/**
|
|
260
|
+
* How many days a memory stays in the nightly importance-settle pool after
|
|
261
|
+
* ingest (#478): a row's importance re-settles nightly while young — keyed
|
|
262
|
+
* on PER-ROW age (ingested_at), never the global lastConsolidated
|
|
263
|
+
* watermark, which sticks whenever a run defers and used to drag a growing
|
|
264
|
+
* cohort back through re-scoring (each re-settle overwrites base_strength,
|
|
265
|
+
* erasing promotion gains). Rows leave the pool after the window; promoted
|
|
266
|
+
* or enriched rows leave earlier via the paid-gain guard. Release-managed
|
|
267
|
+
* (#408 discipline): moving it is a release decision with soak evidence,
|
|
268
|
+
* not a config knob.
|
|
269
|
+
*/
|
|
270
|
+
export declare const IMPORTANCE_SETTLE_WINDOW_DAYS = 3;
|
|
226
271
|
/** Deterministic merge ceiling of the unified resolution pass (#392): pairs
|
|
227
272
|
* at/above this cosine merge LLM-free; [CORRECTION_MIN_SIMILARITY, this)
|
|
228
273
|
* get the one verdict call. 0.92 — measured on the #191 mechanical audit
|