@cachly-dev/mcp-server 0.10.125 → 0.10.127

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.10.125",
3
- "commit": "07251ca",
4
- "gebautAm": "2026-08-20T09:15:12.976Z"
2
+ "version": "0.10.127",
3
+ "commit": "88d2e57e",
4
+ "gebautAm": "2026-08-20T19:58:52.566Z"
5
5
  }
@@ -6,6 +6,7 @@ import { safeJsonParse, scanKeys } from '../utils.js';
6
6
  import { ersparteMinuten, istStarterLektion } from '../wertbeitrag.js';
7
7
  import { lessonPreviewLines, trimTo } from '../lesson-preview.js';
8
8
  import { meldeEinmal, OHNE_VEKTOREN, OHNE_DIENST, OHNE_FRAGEVEKTOR } from '../aussetzer.js';
9
+ import { versuchStart, neueKennung, wendeZuteilungAn, schliesseVersuchAb } from '../versuch.js';
9
10
  /**
10
11
  * Preview for one smart_recall hit.
11
12
  *
@@ -1564,6 +1565,40 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
1564
1565
  return true;
1565
1566
  })
1566
1567
  .sort((a, b) => b.hybridScore - a.hybridScore);
1568
+ // ── Versuch (Messtechnik, siehe versuch.ts) ───────────────────────────────
1569
+ //
1570
+ // Standardmaessig AUS: `versuchStart()` gibt dann `null` zurueck, und
1571
+ // dieser ganze Block tut nichts — `hybridResults` bleibt unangetastet,
1572
+ // nichts wird nach Redis geschrieben, kein Zeichen im Text aendert sich.
1573
+ // Erst mit `CACHLY_VERSUCH=an` UND gesetztem Salz greift die Zuteilung.
1574
+ const versuchSalz = versuchStart();
1575
+ let versuchKennung = '';
1576
+ let versuchTeil = null;
1577
+ if (versuchSalz !== null) {
1578
+ versuchKennung = neueKennung();
1579
+ const hoechstePunktzahl = hybridResults[0]?.hybridScore ?? 0;
1580
+ const ergebnis = wendeZuteilungAn(hybridResults.map((r) => ({ key: r.key, content: r.content, punktzahl: r.hybridScore })), versuchKennung, versuchSalz, hoechstePunktzahl);
1581
+ if (ergebnis.weggelassenesThema !== undefined) {
1582
+ // HOLD: der bisher beste Treffer wird aus der ausgelieferten Liste
1583
+ // entfernt. Die uebrigen Treffer und ihre Reihenfolge bleiben gleich.
1584
+ hybridResults.splice(0, 1);
1585
+ }
1586
+ else if (ergebnis.markierungGesetzt && hybridResults[0] && ergebnis.treffer[0]) {
1587
+ // DELIVER: derselbe Treffer, aber sein Inhalt traegt jetzt die
1588
+ // Kanarien-Markierung am Ende von `what_worked`.
1589
+ hybridResults[0] = { ...hybridResults[0], content: ergebnis.treffer[0].content };
1590
+ }
1591
+ versuchTeil = {
1592
+ frage: query,
1593
+ hoechstePunktzahl,
1594
+ themen: [], // unten befuellt, sobald feststeht, was wirklich sichtbar ist
1595
+ zulassungsfaehig: ergebnis.zulassungsfaehig,
1596
+ zulassungsGrund: ergebnis.zulassungsGrund,
1597
+ zuteilung: ergebnis.zuteilung,
1598
+ weggelassenesThema: ergebnis.weggelassenesThema,
1599
+ markierungGesetzt: ergebnis.markierungGesetzt,
1600
+ };
1601
+ }
1567
1602
  // ── Teaser-Gate: free tier over its recall limit hides the long tail ──────
1568
1603
  const recallGate = await getRecallGate(instance_id, apiFetch);
1569
1604
  // Depth gate: once a free user is over their (monthly, goodwill-adjusted)
@@ -1742,6 +1777,15 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
1742
1777
  lines.push(` • Use \`recall_best_solution("topic")\` for exact topic lookup`);
1743
1778
  }
1744
1779
  }
1780
+ // Versuch, Abschluss: Kanarienvogel gegen die WIRKLICH zusammengebaute
1781
+ // Antwort pruefen, Markierung entfernen, Protokoll schreiben (schlaegt
1782
+ // das fehl, bleibt die Antwort trotzdem stehen — siehe schreibeTurnProtokoll).
1783
+ if (versuchSalz !== null && versuchTeil) {
1784
+ const themen = hybridResults.slice(0, visibleCount)
1785
+ .filter((r) => r.key.startsWith('cachly:lesson:best:'))
1786
+ .map((r) => r.key.slice('cachly:lesson:best:'.length));
1787
+ return schliesseVersuchAb(redis, versuchKennung, { ...versuchTeil, themen }, lines.join('\n'));
1788
+ }
1745
1789
  return lines.join('\n');
1746
1790
  }
1747
1791
  // ── get_api_status ────────────────────────────────────────────────────────
@@ -3584,9 +3628,33 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
3584
3628
  else {
3585
3629
  ttfrLine = `⚪ Not enough data yet — store a lesson, then recall it`;
3586
3630
  }
3587
- // ── Metric 2: Recall-lift (the moat proof) ──────────────────────────────
3588
- // Published headline from Cachly-Bench (CI-defended in rerank.test.ts).
3589
- const recallLiftLine = `**+33.3 % Precision@1**, **+13.6 % MRR**, **+9.9 % nDCG@5** vs. raw BM25 · external-corpus Recall@3 **98.2%**`;
3631
+ // ── Metric 2: Recall-lift ────────────────────────────────────────────────
3632
+ //
3633
+ // HIER STAND EINE FEST EINGEBAUTE ZAHL.
3634
+ //
3635
+ // "+33.3 % Precision@1 vs. raw BM25" war eine Zeichenkette, keine Messung.
3636
+ // Der Kommentar darueber behauptete "CI-defended" und liess sie wie einen
3637
+ // Messwert aussehen. Gefunden am 20.08.2026 beim ersten Lauf der Gegenrede.
3638
+ //
3639
+ // Die Zahl stammte ausserdem aus einer Formel, die am 19.08.2026
3640
+ // ABGELOEST wurde: auf 498 echten Lektionen erreichte sie 15 Prozent, die
3641
+ // Nachfolgerin 30. Der kleine Pruefstand (17 Lektionen, 13 Fragen) belohnte
3642
+ // dabei die schlechtere Fassung mit 92,3 gegen 69,2 Prozent — seine Zahl
3643
+ // bewegt sich ENTGEGENGESETZT zur Wirklichkeit. Belegt in src/bench/gate.ts.
3644
+ //
3645
+ // Eine Kennzahl, die der Server nicht selbst erhebt, gehoert nicht in seine
3646
+ // Ausgabe. Sie kann nicht fallen, also misst sie nichts. Ein leeres Feld ist
3647
+ // ehrlicher als eine Zahl, die immer gut aussieht.
3648
+ //
3649
+ // Dieselbe Entscheidung wurde am 19.08.2026 eine Kennzahl weiter unten schon
3650
+ // einmal getroffen (die erfundenen "1.429,5 h"). Sie galt hier genauso und
3651
+ // wurde nur nicht angewandt.
3652
+ const recallLiftLine = [
3653
+ '⚪ **Nicht gemessen** — diese Zahl erhebt der Server nicht selbst.',
3654
+ ' Selbst messen: `npm run bench` in `sdk/mcp`.',
3655
+ ' Achtung, der Pruefstand hat 17 Lektionen und 13 Fragen — ein Beispielsatz, kein Bestand.',
3656
+ ' Auf 498 ECHTEN Lektionen gemessen am 19.08.2026: Precision@1 **30 %** (vorher 15 %).',
3657
+ ].join('\n');
3590
3658
  // ── Metric 3: Team-knowledge-reuse ──────────────────────────────────────
3591
3659
  const recallsTotal = Number(recallsTotalRaw ?? 0);
3592
3660
  const crossAuthor = Number(crossAuthorRaw ?? 0);