@remnic/core 10.0.17 → 10.0.19
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/dist/access-admin-ops-surface.js +15 -15
- package/dist/access-authorization-probe.js +16 -16
- package/dist/access-boundary.js +15 -15
- package/dist/access-cli.js +56 -56
- package/dist/access-extraction-force-flush.js +15 -15
- package/dist/access-http-briefing.js +16 -16
- package/dist/access-http-query.js +17 -17
- package/dist/access-http.js +32 -32
- package/dist/access-identity-continuity-surface.js +15 -15
- package/dist/access-lcm-surface.js +15 -15
- package/dist/access-mcp.js +25 -25
- package/dist/access-namespace-preflight.js +15 -15
- package/dist/access-observe-write-surface.js +15 -15
- package/dist/access-operations-batch.js +16 -16
- package/dist/access-operations.js +23 -23
- package/dist/access-recall-concurrency.js +15 -15
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +15 -15
- package/dist/access-recall-surface.js +15 -15
- package/dist/access-service.js +15 -15
- package/dist/access-surface-catalog.js +17 -17
- package/dist/active-recall.js +2 -2
- package/dist/briefing.js +3 -3
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-2PYHLSXK.js → chunk-2C5YAVHA.js} +2 -2
- package/dist/{chunk-GWVNGDJW.js → chunk-2I3OREMR.js} +2 -2
- package/dist/{chunk-GCVDFX66.js → chunk-2JGBX5XY.js} +2 -2
- package/dist/{chunk-PEF5LHQU.js → chunk-32FVH5OQ.js} +5 -5
- package/dist/{chunk-XYGQSDTH.js → chunk-3K6J5GO5.js} +3 -3
- package/dist/{chunk-3MO4LWYU.js → chunk-466EGMFQ.js} +1 -1
- package/dist/{chunk-3MO4LWYU.js.map → chunk-466EGMFQ.js.map} +1 -1
- package/dist/{chunk-HQSK2INQ.js → chunk-4OEBL5T3.js} +2 -2
- package/dist/{chunk-IJMDBYCO.js → chunk-5JXNXKKV.js} +2 -2
- package/dist/{chunk-CQOIWJ5E.js → chunk-5NO42IYF.js} +3 -3
- package/dist/{chunk-NHUX6GXA.js → chunk-62CRBI5B.js} +2 -2
- package/dist/{chunk-5ATSXCAG.js → chunk-6VWCL2IZ.js} +3 -3
- package/dist/{chunk-CXOYUANR.js → chunk-7UHCV5B3.js} +2 -2
- package/dist/{chunk-BK2BVLZW.js → chunk-A2IJEV5L.js} +2 -2
- package/dist/{chunk-EH4BQ7LT.js → chunk-AAQ77A44.js} +2 -2
- package/dist/{chunk-R2H4ZFBJ.js → chunk-BI3CIDIH.js} +3 -3
- package/dist/{chunk-GFWRXPF6.js → chunk-CA2R2AD4.js} +12 -12
- package/dist/{chunk-4SCZZ3U7.js → chunk-D42L5SQF.js} +2 -2
- package/dist/{chunk-C6JMGAMO.js → chunk-DJMGVSST.js} +2 -2
- package/dist/{chunk-H5IUN433.js → chunk-EML6HJE6.js} +2 -2
- package/dist/{chunk-ZZTOURJI.js → chunk-EVWDNKQA.js} +13 -4
- package/dist/chunk-EVWDNKQA.js.map +1 -0
- package/dist/{chunk-MJIOGYKX.js → chunk-FBNL4BYD.js} +2 -2
- package/dist/{chunk-5KGYTX5O.js → chunk-GXVLEXIX.js} +2 -2
- package/dist/{chunk-6YEPGWUP.js → chunk-HVIXRLXJ.js} +2 -2
- package/dist/{chunk-AZDTDWS2.js → chunk-IBGRIAE5.js} +2 -2
- package/dist/{chunk-YDBIWGNI.js → chunk-IIK2PD3F.js} +8 -2
- package/dist/{chunk-YDBIWGNI.js.map → chunk-IIK2PD3F.js.map} +1 -1
- package/dist/{chunk-YR4COAEC.js → chunk-INBB7D3V.js} +2 -2
- package/dist/{chunk-VW6VIJOS.js → chunk-IVUCF3QO.js} +2 -2
- package/dist/{chunk-UGYUBENJ.js → chunk-LDZD3OQG.js} +2 -2
- package/dist/{chunk-VNZMZPAC.js → chunk-LT4SMGE4.js} +2 -2
- package/dist/{chunk-7VQ6AI7H.js → chunk-N36PBG4A.js} +2 -2
- package/dist/{chunk-G3UUAQOD.js → chunk-NFB5QTOH.js} +2 -2
- package/dist/{chunk-F2772ATT.js → chunk-NIS3FOMD.js} +2 -2
- package/dist/{chunk-4PDTVVSW.js → chunk-O6ADSFGY.js} +2 -2
- package/dist/{chunk-MAVYEZKM.js → chunk-OFQOOLQQ.js} +2 -2
- package/dist/{chunk-O2YPCFJT.js → chunk-OPNSIFFU.js} +7 -7
- package/dist/{chunk-W3FVQBGF.js → chunk-PDFAX4PK.js} +2 -2
- package/dist/{chunk-NAGMQXWV.js → chunk-QC5TJUSP.js} +2 -2
- package/dist/{chunk-2PTH4PRL.js → chunk-QZ7WOCME.js} +2 -2
- package/dist/{chunk-5MLGY6IY.js → chunk-RQMSD4CN.js} +56 -35
- package/dist/chunk-RQMSD4CN.js.map +1 -0
- package/dist/{chunk-TN4EA4X4.js → chunk-RTV3DB4I.js} +2 -2
- package/dist/{chunk-NZCKG25S.js → chunk-SSUTJLCF.js} +2 -2
- package/dist/{chunk-GUY6L6LL.js → chunk-TXE55Z3X.js} +2 -2
- package/dist/{chunk-XKRXN63M.js → chunk-UHBZK3CK.js} +2 -2
- package/dist/{chunk-PRU7OF3Y.js → chunk-UXXLP2PD.js} +3 -3
- package/dist/{chunk-V3TXIXXY.js → chunk-VOEBHBWG.js} +2 -2
- package/dist/{chunk-RI2KCQHP.js → chunk-VUBVNY3W.js} +2 -2
- package/dist/{chunk-QSEUUQUF.js → chunk-VVSPHTSU.js} +2 -2
- package/dist/{chunk-OXNTOHL6.js → chunk-VYVQZRXF.js} +2 -2
- package/dist/{chunk-L6AZOEXV.js → chunk-W3GFSWKE.js} +4 -4
- package/dist/{chunk-MXV2MY6C.js → chunk-W7NVMERN.js} +2 -2
- package/dist/{chunk-Q7DWEXG2.js → chunk-XKPLERHV.js} +19 -19
- package/dist/{chunk-KLJVTZ3R.js → chunk-YRKKW4KT.js} +3 -3
- package/dist/{chunk-DQR2LD3V.js → chunk-YW4ZYASS.js} +2 -2
- package/dist/{chunk-QS3OLP5I.js → chunk-ZDDDWTC7.js} +2 -2
- package/dist/{chunk-JZTEOBOR.js → chunk-ZDUMF4H6.js} +12 -12
- package/dist/{chunk-H6FREOYX.js → chunk-ZUCNOTNF.js} +7 -7
- package/dist/cli.js +43 -43
- package/dist/coding/export-okf-codegraph.js +2 -2
- package/dist/compounding/engine.js +4 -4
- package/dist/config.js +2 -2
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/index.js +3 -3
- package/dist/convergence-refresh.js +5 -5
- package/dist/corpus-watermark.js +5 -5
- package/dist/entity-retrieval.js +3 -3
- package/dist/external-wiki-access.js +16 -16
- package/dist/extraction.js +3 -3
- package/dist/harmonic-retrieval.js +3 -3
- package/dist/index.js +56 -56
- package/dist/location/index.js +5 -5
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection-runner.js +5 -5
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/memory-browse-operations.js +16 -16
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/storage.js +3 -3
- package/dist/operator-doctor-corpus.js +6 -6
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/maintenance.js +13 -13
- package/dist/orchestration/recall-rerank-coordinator.d.ts.map +1 -1
- package/dist/orchestrator.js +56 -56
- package/dist/preferences/drift-recall.d.ts.map +1 -1
- package/dist/reasoning-trace-recall.d.ts +2 -0
- package/dist/reasoning-trace-recall.d.ts.map +1 -1
- package/dist/reasoning-trace-recall.js +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-mmr.d.ts +5 -0
- package/dist/recall-mmr.d.ts.map +1 -1
- package/dist/recall-mmr.js +1 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +16 -16
- package/dist/recall-navigation.js +15 -15
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/resume-bundles.js +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/source-agent-qualifier.js +3 -3
- package/dist/standup/build.js +3 -3
- package/dist/storage.js +2 -2
- package/dist/support-passport/index.js +18 -18
- package/dist/transfer/export-okf.js +3 -3
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +3 -3
- package/dist/who-knows-cli.js +4 -4
- package/dist/who-knows.js +3 -3
- package/package.json +2 -2
- package/src/orchestration/recall-rerank-coordinator.ts +46 -14
- package/src/preferences/drift-recall.ts +14 -8
- package/src/preferences/preference-drift.test.ts +15 -0
- package/src/reasoning-trace-recall.ts +33 -8
- package/src/recall-mmr.ts +17 -1
- package/src/recall-rerank-coordinator.test.ts +275 -0
- package/src/types.ts +5 -0
- package/dist/chunk-5MLGY6IY.js.map +0 -1
- package/dist/chunk-ZZTOURJI.js.map +0 -1
- /package/dist/{chunk-2PYHLSXK.js.map → chunk-2C5YAVHA.js.map} +0 -0
- /package/dist/{chunk-GWVNGDJW.js.map → chunk-2I3OREMR.js.map} +0 -0
- /package/dist/{chunk-GCVDFX66.js.map → chunk-2JGBX5XY.js.map} +0 -0
- /package/dist/{chunk-PEF5LHQU.js.map → chunk-32FVH5OQ.js.map} +0 -0
- /package/dist/{chunk-XYGQSDTH.js.map → chunk-3K6J5GO5.js.map} +0 -0
- /package/dist/{chunk-HQSK2INQ.js.map → chunk-4OEBL5T3.js.map} +0 -0
- /package/dist/{chunk-IJMDBYCO.js.map → chunk-5JXNXKKV.js.map} +0 -0
- /package/dist/{chunk-CQOIWJ5E.js.map → chunk-5NO42IYF.js.map} +0 -0
- /package/dist/{chunk-NHUX6GXA.js.map → chunk-62CRBI5B.js.map} +0 -0
- /package/dist/{chunk-5ATSXCAG.js.map → chunk-6VWCL2IZ.js.map} +0 -0
- /package/dist/{chunk-CXOYUANR.js.map → chunk-7UHCV5B3.js.map} +0 -0
- /package/dist/{chunk-BK2BVLZW.js.map → chunk-A2IJEV5L.js.map} +0 -0
- /package/dist/{chunk-EH4BQ7LT.js.map → chunk-AAQ77A44.js.map} +0 -0
- /package/dist/{chunk-R2H4ZFBJ.js.map → chunk-BI3CIDIH.js.map} +0 -0
- /package/dist/{chunk-GFWRXPF6.js.map → chunk-CA2R2AD4.js.map} +0 -0
- /package/dist/{chunk-4SCZZ3U7.js.map → chunk-D42L5SQF.js.map} +0 -0
- /package/dist/{chunk-C6JMGAMO.js.map → chunk-DJMGVSST.js.map} +0 -0
- /package/dist/{chunk-H5IUN433.js.map → chunk-EML6HJE6.js.map} +0 -0
- /package/dist/{chunk-MJIOGYKX.js.map → chunk-FBNL4BYD.js.map} +0 -0
- /package/dist/{chunk-5KGYTX5O.js.map → chunk-GXVLEXIX.js.map} +0 -0
- /package/dist/{chunk-6YEPGWUP.js.map → chunk-HVIXRLXJ.js.map} +0 -0
- /package/dist/{chunk-AZDTDWS2.js.map → chunk-IBGRIAE5.js.map} +0 -0
- /package/dist/{chunk-YR4COAEC.js.map → chunk-INBB7D3V.js.map} +0 -0
- /package/dist/{chunk-VW6VIJOS.js.map → chunk-IVUCF3QO.js.map} +0 -0
- /package/dist/{chunk-UGYUBENJ.js.map → chunk-LDZD3OQG.js.map} +0 -0
- /package/dist/{chunk-VNZMZPAC.js.map → chunk-LT4SMGE4.js.map} +0 -0
- /package/dist/{chunk-7VQ6AI7H.js.map → chunk-N36PBG4A.js.map} +0 -0
- /package/dist/{chunk-G3UUAQOD.js.map → chunk-NFB5QTOH.js.map} +0 -0
- /package/dist/{chunk-F2772ATT.js.map → chunk-NIS3FOMD.js.map} +0 -0
- /package/dist/{chunk-4PDTVVSW.js.map → chunk-O6ADSFGY.js.map} +0 -0
- /package/dist/{chunk-MAVYEZKM.js.map → chunk-OFQOOLQQ.js.map} +0 -0
- /package/dist/{chunk-O2YPCFJT.js.map → chunk-OPNSIFFU.js.map} +0 -0
- /package/dist/{chunk-W3FVQBGF.js.map → chunk-PDFAX4PK.js.map} +0 -0
- /package/dist/{chunk-NAGMQXWV.js.map → chunk-QC5TJUSP.js.map} +0 -0
- /package/dist/{chunk-2PTH4PRL.js.map → chunk-QZ7WOCME.js.map} +0 -0
- /package/dist/{chunk-TN4EA4X4.js.map → chunk-RTV3DB4I.js.map} +0 -0
- /package/dist/{chunk-NZCKG25S.js.map → chunk-SSUTJLCF.js.map} +0 -0
- /package/dist/{chunk-GUY6L6LL.js.map → chunk-TXE55Z3X.js.map} +0 -0
- /package/dist/{chunk-XKRXN63M.js.map → chunk-UHBZK3CK.js.map} +0 -0
- /package/dist/{chunk-PRU7OF3Y.js.map → chunk-UXXLP2PD.js.map} +0 -0
- /package/dist/{chunk-V3TXIXXY.js.map → chunk-VOEBHBWG.js.map} +0 -0
- /package/dist/{chunk-RI2KCQHP.js.map → chunk-VUBVNY3W.js.map} +0 -0
- /package/dist/{chunk-QSEUUQUF.js.map → chunk-VVSPHTSU.js.map} +0 -0
- /package/dist/{chunk-OXNTOHL6.js.map → chunk-VYVQZRXF.js.map} +0 -0
- /package/dist/{chunk-L6AZOEXV.js.map → chunk-W3GFSWKE.js.map} +0 -0
- /package/dist/{chunk-MXV2MY6C.js.map → chunk-W7NVMERN.js.map} +0 -0
- /package/dist/{chunk-Q7DWEXG2.js.map → chunk-XKPLERHV.js.map} +0 -0
- /package/dist/{chunk-KLJVTZ3R.js.map → chunk-YRKKW4KT.js.map} +0 -0
- /package/dist/{chunk-DQR2LD3V.js.map → chunk-YW4ZYASS.js.map} +0 -0
- /package/dist/{chunk-QS3OLP5I.js.map → chunk-ZDDDWTC7.js.map} +0 -0
- /package/dist/{chunk-JZTEOBOR.js.map → chunk-ZDUMF4H6.js.map} +0 -0
- /package/dist/{chunk-H6FREOYX.js.map → chunk-ZUCNOTNF.js.map} +0 -0
|
@@ -88,6 +88,8 @@ export interface BoostableResult {
|
|
|
88
88
|
path: string;
|
|
89
89
|
score: number;
|
|
90
90
|
docid?: string;
|
|
91
|
+
/** Effective relevance carried forward by an upstream rerank stage. */
|
|
92
|
+
effectiveScore?: number;
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
/**
|
|
@@ -118,6 +120,17 @@ export interface ApplyReasoningTraceBoostOptions {
|
|
|
118
120
|
boost?: number;
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The relevance a row is compared on: its effective relevance when a rerank
|
|
125
|
+
* stage left one (MMR ranks on the same basis), else the raw retrieval score.
|
|
126
|
+
*/
|
|
127
|
+
function comparisonRelevance(row: BoostableResult): number {
|
|
128
|
+
if (typeof row.effectiveScore === "number" && Number.isFinite(row.effectiveScore)) {
|
|
129
|
+
return row.effectiveScore;
|
|
130
|
+
}
|
|
131
|
+
return typeof row.score === "number" && Number.isFinite(row.score) ? row.score : 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
121
134
|
/**
|
|
122
135
|
* Apply a score boost to results whose path sits under reasoning-traces/
|
|
123
136
|
* when the query looks like a problem-solving ask. Returns a new array;
|
|
@@ -167,7 +180,18 @@ export function applyReasoningTraceBoost<R extends BoostableResult>(
|
|
|
167
180
|
if (isReasoningTracePath(r.path)) {
|
|
168
181
|
changed = true;
|
|
169
182
|
const baseScore = typeof r.score === "number" && Number.isFinite(r.score) ? r.score : 0;
|
|
170
|
-
|
|
183
|
+
// Compose the boost into the effective relevance too: a downstream MMR
|
|
184
|
+
// pass prefers it over the raw score, so a stale value would drop the
|
|
185
|
+
// boost.
|
|
186
|
+
const effective =
|
|
187
|
+
typeof r.effectiveScore === "number" && Number.isFinite(r.effectiveScore)
|
|
188
|
+
? r.effectiveScore + boostAmount
|
|
189
|
+
: undefined;
|
|
190
|
+
boosted.push(
|
|
191
|
+
effective === undefined
|
|
192
|
+
? ({ ...r, score: baseScore + boostAmount } as R)
|
|
193
|
+
: ({ ...r, score: baseScore + boostAmount, effectiveScore: effective } as R),
|
|
194
|
+
);
|
|
171
195
|
} else {
|
|
172
196
|
boosted.push(r);
|
|
173
197
|
}
|
|
@@ -175,21 +199,22 @@ export function applyReasoningTraceBoost<R extends BoostableResult>(
|
|
|
175
199
|
if (!changed) return boosted;
|
|
176
200
|
|
|
177
201
|
// Step 2: promote each boosted trace upward past any non-trace neighbor
|
|
178
|
-
// whose
|
|
179
|
-
//
|
|
180
|
-
//
|
|
202
|
+
// whose relevance is strictly lower than the boosted trace's. The
|
|
203
|
+
// comparison uses the SAME basis MMR ranks on — the effective relevance a
|
|
204
|
+
// rerank stage left behind, else the raw score — so the boost cannot
|
|
205
|
+
// promote a trace the pipeline deliberately demoted. Non-trace items never
|
|
206
|
+
// move past each other, so reranker-driven ordering on non-trace items is
|
|
207
|
+
// preserved.
|
|
181
208
|
const out = boosted.slice();
|
|
182
209
|
for (let i = 0; i < out.length; i++) {
|
|
183
210
|
if (!isReasoningTracePath(out[i].path)) continue;
|
|
184
211
|
const trace = out[i];
|
|
185
|
-
const traceScore =
|
|
186
|
-
typeof trace.score === "number" && Number.isFinite(trace.score) ? trace.score : 0;
|
|
212
|
+
const traceScore = comparisonRelevance(trace);
|
|
187
213
|
let j = i;
|
|
188
214
|
while (j > 0) {
|
|
189
215
|
const prev = out[j - 1];
|
|
190
216
|
if (isReasoningTracePath(prev.path)) break; // don't reorder traces vs each other
|
|
191
|
-
const prevScore =
|
|
192
|
-
typeof prev.score === "number" && Number.isFinite(prev.score) ? prev.score : 0;
|
|
217
|
+
const prevScore = comparisonRelevance(prev);
|
|
193
218
|
if (prevScore >= traceScore) break;
|
|
194
219
|
out[j] = prev;
|
|
195
220
|
j -= 1;
|
package/src/recall-mmr.ts
CHANGED
|
@@ -459,6 +459,11 @@ export interface MmrRecallResult {
|
|
|
459
459
|
readonly path?: string;
|
|
460
460
|
readonly snippet?: string;
|
|
461
461
|
readonly score?: number;
|
|
462
|
+
/**
|
|
463
|
+
* Effective relevance carried forward by the rerank stage that last
|
|
464
|
+
* adjusted the result. Preferred over `score` for MMR's relevance term.
|
|
465
|
+
*/
|
|
466
|
+
readonly effectiveScore?: number;
|
|
462
467
|
}
|
|
463
468
|
|
|
464
469
|
export interface ReorderRecallResultsOptions {
|
|
@@ -545,7 +550,7 @@ export function reorderRecallResultsWithMmr<R extends MmrRecallResult>(
|
|
|
545
550
|
const candidates: MmrCandidate[] = results.map((r, index) => ({
|
|
546
551
|
id: makeRecallKey(r, index),
|
|
547
552
|
content: r.snippet ?? "",
|
|
548
|
-
score:
|
|
553
|
+
score: effectiveRelevance(r),
|
|
549
554
|
embedding: null,
|
|
550
555
|
}));
|
|
551
556
|
// Index lookup by id so we can map MMR-selected candidates back to their
|
|
@@ -601,6 +606,17 @@ export function reorderRecallResultsWithMmr<R extends MmrRecallResult>(
|
|
|
601
606
|
return { reordered, diversity, lambda };
|
|
602
607
|
}
|
|
603
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Relevance for MMR's `sim(d, query)` term: the effective relevance an
|
|
611
|
+
* upstream rerank stage carried forward, else the raw retrieval score.
|
|
612
|
+
*/
|
|
613
|
+
function effectiveRelevance(r: MmrRecallResult): number {
|
|
614
|
+
if (typeof r.effectiveScore === "number" && Number.isFinite(r.effectiveScore)) {
|
|
615
|
+
return r.effectiveScore;
|
|
616
|
+
}
|
|
617
|
+
return typeof r.score === "number" ? r.score : 0;
|
|
618
|
+
}
|
|
619
|
+
|
|
604
620
|
function makeRecallKey(r: MmrRecallResult, index: number): string {
|
|
605
621
|
const baseKey = r.path || r.docid || "";
|
|
606
622
|
return `${baseKey}::${index}`;
|
|
@@ -24,6 +24,8 @@ import test from "node:test";
|
|
|
24
24
|
import { parseConfig } from "./config.js";
|
|
25
25
|
import { resolveCapabilities } from "./capabilities.js";
|
|
26
26
|
import { RecallRerankCoordinator } from "./orchestration/recall-rerank-coordinator.js";
|
|
27
|
+
import { applyReasoningTraceBoost } from "./reasoning-trace-recall.js";
|
|
28
|
+
import { DRIFT_DETECTION_DEFAULTS } from "./preferences/drift-config.js";
|
|
27
29
|
import { Orchestrator } from "./orchestrator.js";
|
|
28
30
|
import type { PluginConfig, QmdSearchResult, MemoryFile } from "./types.js";
|
|
29
31
|
import type { StorageManager } from "./index.js";
|
|
@@ -720,3 +722,276 @@ test("#2859 linkless superseded status does not consume a packet slot", () => {
|
|
|
720
722
|
"status-only superseded rows are rejected before the packet cap",
|
|
721
723
|
);
|
|
722
724
|
});
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
// ─── #3226 — the rerank stages' relevance survives the MMR pass ───────────
|
|
728
|
+
/**
|
|
729
|
+
* The rerank stages decide an order, but the MMR pass re-derived relevance
|
|
730
|
+
* from the RAW retrieval score and undid it. Each stage now carries its own
|
|
731
|
+
* relevance (`QmdSearchResult.effectiveScore`) forward and MMR ranks by that.
|
|
732
|
+
*
|
|
733
|
+
* The raw scores are WIDELY SEPARATED (100 vs 0.1) on purpose: a fix that
|
|
734
|
+
* approximates the stage's decision with `raw score × multiplier` still fails.
|
|
735
|
+
*/
|
|
736
|
+
|
|
737
|
+
/** Frontmatter double at an explicit path (the cast mirrors `mem` above). */
|
|
738
|
+
function memAt(memPath: string, frontmatter: Record<string, unknown>): MemoryFile {
|
|
739
|
+
return { path: memPath, frontmatter: frontmatter as unknown as MemoryFile["frontmatter"], content: memPath };
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** `/facts/<id>.md` frontmatter map from `[id, mw_success?, mw_fail?]` rows. */
|
|
743
|
+
function facts(rows: Array<[string, number?, number?]>): Map<string, MemoryFile> {
|
|
744
|
+
return new Map(rows.map(([id, ok, fail]) => [`/facts/${id}.md`, mem(id, ok, fail)]));
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function coordinatorFor(config: PluginConfig): RecallRerankCoordinator {
|
|
748
|
+
const corpus = makeFakes([]);
|
|
749
|
+
return new RecallRerankCoordinator({
|
|
750
|
+
getConfig: () => config,
|
|
751
|
+
getStorage: corpus.getStorage,
|
|
752
|
+
readQmdResultMemory: async () => null,
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
const WORTH_RESULTS = [result("bad", 100), result("good", 0.1)];
|
|
757
|
+
const WORTH_FM = facts([["bad", 0, 10], ["good", 10, 0]]);
|
|
758
|
+
const TRUST_CONFIG = { recallMemoryWorthFilterEnabled: false, trustScoreEnabled: true, recallMmrEnabled: true, recallMmrLambda: 1 };
|
|
759
|
+
|
|
760
|
+
for (const lambda of [1, 0.7]) {
|
|
761
|
+
test(`#3226: a Memory-Worth promotion survives MMR (lambda ${lambda})`, async () => {
|
|
762
|
+
const coord = coordinatorFor(await baseConfig({ recallMmrEnabled: true, recallMmrLambda: lambda }));
|
|
763
|
+
const before = WORTH_RESULTS.map((r) => ({ ...r }));
|
|
764
|
+
const staged = await coord.applyMemoryWorthRerank(WORTH_RESULTS, ["default"], WORTH_FM);
|
|
765
|
+
const applied = coord.diversifyAndLimitRecallResults("memories", staged, 1);
|
|
766
|
+
assert.deepEqual(applied.map((r) => r.path), ["/facts/good.md"], "MMR must not undo the promotion");
|
|
767
|
+
assert.deepEqual(WORTH_RESULTS, before, "the stage must not mutate its input");
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
type Scenario = {
|
|
772
|
+
name: string;
|
|
773
|
+
config: Partial<PluginConfig>;
|
|
774
|
+
stage: (c: RecallRerankCoordinator, r: QmdSearchResult[], p: Map<string, MemoryFile>) => Promise<QmdSearchResult[]>;
|
|
775
|
+
results: QmdSearchResult[];
|
|
776
|
+
preloaded: Map<string, MemoryFile>;
|
|
777
|
+
applied: string[];
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
const SCENARIOS: Scenario[] = [
|
|
781
|
+
{
|
|
782
|
+
name: "a TrustScore demotion survives MMR",
|
|
783
|
+
config: TRUST_CONFIG,
|
|
784
|
+
stage: async (c, r, p) => (await c.applyTrustScoreRerank(r, ["default"], p)).results,
|
|
785
|
+
results: [result("untrusted", 100), result("trusted", 1), result("plain", 0.1)],
|
|
786
|
+
preloaded: facts([["untrusted", 0, 10], ["trusted", 10, 0], ["plain"]]),
|
|
787
|
+
applied: ["/facts/trusted.md"],
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
name: "a quarantined memory is not resurrected by MMR",
|
|
791
|
+
config: TRUST_CONFIG,
|
|
792
|
+
stage: async (c, r, p) => (await c.applyTrustScoreRerank(r, ["default"], p)).results,
|
|
793
|
+
results: [result("contradicted", 100), result("kept", 0.1)],
|
|
794
|
+
preloaded: new Map([
|
|
795
|
+
["/facts/contradicted.md", memAt("/facts/contradicted.md", { faithfulness: { verdict: "contradicted" } })],
|
|
796
|
+
["/facts/kept.md", mem("kept")],
|
|
797
|
+
]),
|
|
798
|
+
applied: ["/facts/kept.md"],
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
name: "preference-drift damping survives MMR",
|
|
802
|
+
config: { recallMmrEnabled: true, recallMmrLambda: 1, driftDetection: { ...DRIFT_DETECTION_DEFAULTS, recallDamping: true, stalePenalty: 0.25 } },
|
|
803
|
+
stage: (c, r, p) => c.applyPreferenceDriftStage(r, ["default"], p),
|
|
804
|
+
results: [result("stale", 100), result("fresh", 0.1)],
|
|
805
|
+
preloaded: new Map([
|
|
806
|
+
["/facts/stale.md", memAt("/facts/stale.md", { category: "preference", driftState: "stale" })],
|
|
807
|
+
["/facts/fresh.md", memAt("/facts/fresh.md", { category: "fact" })],
|
|
808
|
+
]),
|
|
809
|
+
applied: ["/facts/fresh.md"],
|
|
810
|
+
},
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
for (const scenario of SCENARIOS) {
|
|
814
|
+
test(`#3226: ${scenario.name}`, async () => {
|
|
815
|
+
const coord = coordinatorFor(await baseConfig(scenario.config));
|
|
816
|
+
const before = scenario.results.map((r) => ({ ...r }));
|
|
817
|
+
const staged = await scenario.stage(coord, scenario.results, scenario.preloaded);
|
|
818
|
+
const applied = coord.diversifyAndLimitRecallResults("memories", staged, 1);
|
|
819
|
+
assert.deepEqual(applied.map((r) => r.path), scenario.applied, "MMR must not undo the stage");
|
|
820
|
+
assert.deepEqual(scenario.results, before, "the stage must not mutate its input");
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
test("#3226: MMR off leaves the branch order verbatim", async () => {
|
|
825
|
+
const coord = coordinatorFor(await baseConfig({ recallMmrEnabled: false }));
|
|
826
|
+
// Two near-duplicates plus one orthogonal candidate: with MMR on, lambda 0.3
|
|
827
|
+
// promotes the orthogonal candidate into slot 2 — this pins that MMR was off.
|
|
828
|
+
const branch: QmdSearchResult[] = [
|
|
829
|
+
{ docid: "d1", path: "p/d1", snippet: "rocket thrust vectoring", score: 0.99 },
|
|
830
|
+
{ docid: "d2", path: "p/d2", snippet: "rocket thrust vectoring", score: 0.98 },
|
|
831
|
+
{ docid: "o1", path: "p/o1", snippet: "coffee brewing at high altitude", score: 0.4 },
|
|
832
|
+
];
|
|
833
|
+
const applied = coord.diversifyAndLimitRecallResults("memories", branch, 2);
|
|
834
|
+
assert.deepEqual(applied.map((r) => r.docid), ["d1", "d2"], "MMR off: the branch order is the applied order");
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
test("#3226: without a rerank stage MMR keeps using the raw score", async () => {
|
|
838
|
+
const config = await baseConfig({ recallMemoryWorthFilterEnabled: false, trustScoreEnabled: false });
|
|
839
|
+
const coord = coordinatorFor(config);
|
|
840
|
+
const results = [result("a", 0.9), result("b", 0.8)];
|
|
841
|
+
const outcome = await coord.applyTrustScoreToBranch(results, ["default"], resolveCapabilities(config), "test");
|
|
842
|
+
assert.deepEqual(outcome.results, results, "no stage ran: the results come back untouched");
|
|
843
|
+
for (const r of outcome.results) assert.equal(r.effectiveScore, undefined, "no relevance is attached");
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test("#3226: a no-op stage leaves the results byte-identical", async () => {
|
|
847
|
+
const coord = coordinatorFor(await baseConfig());
|
|
848
|
+
const results = [result("a", 0.9), result("b", 0.8)];
|
|
849
|
+
const staged = await coord.applyMemoryWorthRerank(results, ["default"], facts([["a"], ["b"]]));
|
|
850
|
+
assert.deepEqual(staged, results, "a neutral stage returns the input unchanged");
|
|
851
|
+
for (const r of staged) assert.equal(r.effectiveScore, undefined, "a no-op stage attaches no relevance");
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
test("#3226: an annotation-only drift stage keeps the upstream effective relevance", async () => {
|
|
855
|
+
const config = await baseConfig({ driftDetection: { ...DRIFT_DETECTION_DEFAULTS, annotateAfterDays: 30 } });
|
|
856
|
+
const coord = coordinatorFor(config);
|
|
857
|
+
const preloaded = new Map<string, MemoryFile>([
|
|
858
|
+
["/facts/bad.md", memAt("/facts/bad.md", { mw_success: 0, mw_fail: 10 })],
|
|
859
|
+
["/facts/good.md", memAt("/facts/good.md", { mw_success: 10, mw_fail: 0, category: "preference", lastCorroborated: "2020-01-01" })],
|
|
860
|
+
]);
|
|
861
|
+
const staged = await coord.applyMemoryWorthRerank(WORTH_RESULTS, ["default"], preloaded);
|
|
862
|
+
const annotated = await coord.applyPreferenceDriftStage(staged, ["default"], preloaded);
|
|
863
|
+
assert.deepEqual(annotated.map((r) => r.path), ["/facts/good.md", "/facts/bad.md"], "the order is unchanged");
|
|
864
|
+
assert.ok(annotated[0]?.driftNote, "the age note is still attached");
|
|
865
|
+
assert.equal(typeof staged[0]?.effectiveScore, "number", "the stage attached a relevance");
|
|
866
|
+
assert.equal(annotated[0]?.effectiveScore, staged[0]?.effectiveScore, "the upstream relevance survives");
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
for (const boostCase of [
|
|
870
|
+
{
|
|
871
|
+
name: "a strongly demoted trace does not leapfrog a high-effective fact",
|
|
872
|
+
frontmatter: { mw_success: 0, mw_fail: 10 },
|
|
873
|
+
applied: "/facts/fact.md",
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
name: "a near-equal effective relevance lets the boost promote the trace",
|
|
877
|
+
frontmatter: { mw_success: 1000, mw_fail: 0 },
|
|
878
|
+
applied: "/reasoning-traces/trace.md",
|
|
879
|
+
},
|
|
880
|
+
]) {
|
|
881
|
+
test(`#3226: the reasoning-trace boost — ${boostCase.name}`, async () => {
|
|
882
|
+
// The boost capability is off here: the boost is applied explicitly so the
|
|
883
|
+
// MMR pass sees exactly the boosted array.
|
|
884
|
+
const coord = coordinatorFor(await baseConfig({ recallMmrEnabled: true, recallMmrLambda: 1 }));
|
|
885
|
+
const staged = await coord.applyMemoryWorthRerank(
|
|
886
|
+
[
|
|
887
|
+
{ ...result("fact", 0.9), path: "/facts/fact.md" },
|
|
888
|
+
{ ...result("trace", 0.8), path: "/reasoning-traces/trace.md" },
|
|
889
|
+
],
|
|
890
|
+
["default"],
|
|
891
|
+
new Map([
|
|
892
|
+
["/facts/fact.md", memAt("/facts/fact.md", {})],
|
|
893
|
+
["/reasoning-traces/trace.md", memAt("/reasoning-traces/trace.md", boostCase.frontmatter)],
|
|
894
|
+
]),
|
|
895
|
+
);
|
|
896
|
+
const trace = staged.find((r) => r.path === "/reasoning-traces/trace.md");
|
|
897
|
+
assert.ok(trace, "the trace is staged");
|
|
898
|
+
const boosted = applyReasoningTraceBoost(staged, { enabled: true, query: "how do I fix the build?" });
|
|
899
|
+
const boostedTrace = boosted.find((r) => r.path === "/reasoning-traces/trace.md");
|
|
900
|
+
assert.ok(boostedTrace, "the trace survives the boost");
|
|
901
|
+
assert.equal(boostedTrace.score, trace.score + 0.15, "the raw score keeps its boost");
|
|
902
|
+
assert.equal(
|
|
903
|
+
boostedTrace.effectiveScore,
|
|
904
|
+
trace.effectiveScore! + 0.15,
|
|
905
|
+
"the exact adjustment is attached to the effective relevance",
|
|
906
|
+
);
|
|
907
|
+
const applied = coord.diversifyAndLimitRecallResults("memories", boosted, 1);
|
|
908
|
+
assert.deepEqual(
|
|
909
|
+
applied.map((r) => r.path),
|
|
910
|
+
[boostCase.applied],
|
|
911
|
+
"the final order follows the effective relevance",
|
|
912
|
+
);
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
for (const poolSize of [10, 40]) {
|
|
917
|
+
test(`#3226: reasoning boost keeps its scale in a ${poolSize}-candidate adjusted pool`, async () => {
|
|
918
|
+
const coord = coordinatorFor(await baseConfig({ recallMmrEnabled: true, recallMmrLambda: 1 }));
|
|
919
|
+
const candidates = [
|
|
920
|
+
result("fact", 0.9),
|
|
921
|
+
{ ...result("trace", 0.8), path: "/reasoning-traces/trace.md" },
|
|
922
|
+
...Array.from({ length: poolSize - 3 }, (_, index) => result(`plain-${index}`, 0.7)),
|
|
923
|
+
result("bad", 0.1),
|
|
924
|
+
];
|
|
925
|
+
const frontmatter = new Map(candidates.map((candidate) => [
|
|
926
|
+
candidate.path,
|
|
927
|
+
memAt(candidate.path, candidate.path === "/facts/bad.md" ? { mw_success: 0, mw_fail: 10 } : {}),
|
|
928
|
+
]));
|
|
929
|
+
const staged = await coord.applyMemoryWorthRerank(candidates, ["default"], frontmatter);
|
|
930
|
+
const boosted = applyReasoningTraceBoost(staged, { enabled: true, query: "how do I fix this?" });
|
|
931
|
+
assert.equal(
|
|
932
|
+
coord.diversifyAndLimitRecallResults("memories", boosted, 1)[0]?.path,
|
|
933
|
+
"/reasoning-traces/trace.md",
|
|
934
|
+
"a neutral adjacent trace must retain a meaningful boost when another candidate is adjusted",
|
|
935
|
+
);
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
test("#3226: quarantined prefixes do not compress survivor relevance", async () => {
|
|
940
|
+
const coord = coordinatorFor(await baseConfig(TRUST_CONFIG));
|
|
941
|
+
const survivors = [result("trusted", 0.9), result("untrusted", 0.8)];
|
|
942
|
+
const quarantined = Array.from({ length: 20 }, (_, index) => result(`quarantined-${index}`, 1));
|
|
943
|
+
const frontmatter = new Map([
|
|
944
|
+
...facts([["trusted", 10, 0], ["untrusted", 0, 10]]),
|
|
945
|
+
...quarantined.map((candidate) => [
|
|
946
|
+
candidate.path,
|
|
947
|
+
memAt(candidate.path, { faithfulness: { verdict: "contradicted" } }),
|
|
948
|
+
] as const),
|
|
949
|
+
]);
|
|
950
|
+
const baseline = (await coord.applyTrustScoreRerank(survivors, ["default"], frontmatter)).results;
|
|
951
|
+
const prefixed = (await coord.applyTrustScoreRerank([...quarantined, ...survivors], ["default"], frontmatter)).results;
|
|
952
|
+
assert.deepEqual(
|
|
953
|
+
prefixed.map((candidate) => [candidate.path, candidate.effectiveScore]),
|
|
954
|
+
baseline.map((candidate) => [candidate.path, candidate.effectiveScore]),
|
|
955
|
+
"excluded candidates must not change the surviving pool's relevance scale",
|
|
956
|
+
);
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
test("#3226: quarantine placement does not change survivor relevance", async () => {
|
|
960
|
+
const coord = coordinatorFor(await baseConfig(TRUST_CONFIG));
|
|
961
|
+
const survivors = [result("trusted", 0.9), result("untrusted", 0.8), result("plain", 0.7)];
|
|
962
|
+
const excluded = Array.from({ length: 20 }, (_, index) => result(`excluded-${index}`, 1));
|
|
963
|
+
const frontmatter = new Map([
|
|
964
|
+
...facts([["trusted", 10, 0], ["untrusted", 0, 10], ["plain"]]),
|
|
965
|
+
...excluded.map((candidate) => [
|
|
966
|
+
candidate.path, memAt(candidate.path, { faithfulness: { verdict: "contradicted" } }),
|
|
967
|
+
] as const),
|
|
968
|
+
]);
|
|
969
|
+
const baseline = (await coord.applyTrustScoreRerank(survivors, ["default"], frontmatter)).results;
|
|
970
|
+
for (const split of [0, 1, 2, 3]) {
|
|
971
|
+
const input = [...survivors.slice(0, split), ...excluded, ...survivors.slice(split)];
|
|
972
|
+
const admitted = (await coord.applyTrustScoreRerank(input, ["default"], frontmatter)).results;
|
|
973
|
+
assert.deepEqual(
|
|
974
|
+
admitted.map((candidate) => [candidate.path, candidate.effectiveScore]),
|
|
975
|
+
baseline.map((candidate) => [candidate.path, candidate.effectiveScore]),
|
|
976
|
+
`excluded rows at position ${split} must not leave rank holes`,
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
test("#3226: active drift damping composes upstream effective relevance", async () => {
|
|
982
|
+
const coord = coordinatorFor(await baseConfig({
|
|
983
|
+
driftDetection: { ...DRIFT_DETECTION_DEFAULTS, recallDamping: true, stalePenalty: 0.25 },
|
|
984
|
+
}));
|
|
985
|
+
const candidates = [
|
|
986
|
+
{ ...result("top", 0.1), effectiveScore: 0.95 },
|
|
987
|
+
{ ...result("stale", 100), effectiveScore: 0.9 },
|
|
988
|
+
{ ...result("tail", 0.8), effectiveScore: 0.1 },
|
|
989
|
+
];
|
|
990
|
+
const frontmatter = new Map(candidates.map((candidate) => [
|
|
991
|
+
candidate.path,
|
|
992
|
+
memAt(candidate.path, candidate.path === "/facts/stale.md" ? { category: "preference", driftState: "stale" } : {}),
|
|
993
|
+
]));
|
|
994
|
+
const damped = await coord.applyPreferenceDriftStage(candidates, ["default"], frontmatter);
|
|
995
|
+
assert.deepEqual(damped.map((candidate) => candidate.effectiveScore), [0.95, 0.9 * 0.25, 0.1]);
|
|
996
|
+
assert.deepEqual(candidates.map((candidate) => candidate.effectiveScore), [0.95, 0.9, 0.1], "inputs remain unmodified");
|
|
997
|
+
});
|
package/src/types.ts
CHANGED
|
@@ -3460,6 +3460,11 @@ export interface QmdSearchResult extends OriginMetadata, RecallDriftAnnotation,
|
|
|
3460
3460
|
path: string;
|
|
3461
3461
|
snippet: string;
|
|
3462
3462
|
score: number;
|
|
3463
|
+
/**
|
|
3464
|
+
* Pool-normalized rank × multiplier from the last adjusted rerank stage.
|
|
3465
|
+
* MMR prefers it over `score`; additive boosts compose on this scale.
|
|
3466
|
+
*/
|
|
3467
|
+
effectiveScore?: number;
|
|
3463
3468
|
line?: number;
|
|
3464
3469
|
explain?: QmdSearchExplain;
|
|
3465
3470
|
transport?: "daemon" | "subprocess" | "hybrid" | "scoped_prefilter";
|