@cachly-dev/mcp-server 0.10.128 → 0.10.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +1 -7
  3. package/dist/packages/telegram-notify/client.js +2 -75
  4. package/dist/src/ambient-cli.js +7 -253
  5. package/dist/src/ambient-deps.js +1 -55
  6. package/dist/src/ambient-hooks.js +5 -278
  7. package/dist/src/ambient-ledger.js +6 -95
  8. package/dist/src/ambient-memory.js +1 -67
  9. package/dist/src/ambient-recall.js +1 -221
  10. package/dist/src/aussetzer.js +1 -82
  11. package/dist/src/auth.js +9 -140
  12. package/dist/src/autor-abzeichen.js +1 -56
  13. package/dist/src/autor.js +1 -136
  14. package/dist/src/bauabdruck.js +1 -93
  15. package/dist/src/bedeutung.js +2 -323
  16. package/dist/src/bench/cachly-bench.js +4 -249
  17. package/dist/src/bench/external-corpus.js +4 -135
  18. package/dist/src/bench/fixtures.js +1 -225
  19. package/dist/src/brain-export.js +16 -119
  20. package/dist/src/brain-watch-hook.js +8 -86
  21. package/dist/src/cachly-url.js +1 -21
  22. package/dist/src/ckg.js +1 -108
  23. package/dist/src/cls-hook.js +8 -94
  24. package/dist/src/confidence.js +1 -50
  25. package/dist/src/credentials.js +1 -85
  26. package/dist/src/deutsch.js +1 -223
  27. package/dist/src/doctor.js +2 -248
  28. package/dist/src/editor.js +1 -63
  29. package/dist/src/eingaenge-nachruesten.js +1 -290
  30. package/dist/src/eingaenge.js +2 -228
  31. package/dist/src/embeddings.js +13 -223
  32. package/dist/src/feldreparatur.js +3 -0
  33. package/dist/src/first-contact.js +4 -108
  34. package/dist/src/first-recall-proof.js +4 -41
  35. package/dist/src/funnel-milestones.js +2 -48
  36. package/dist/src/geliefert.js +1 -114
  37. package/dist/src/handlers/advanced.js +38 -537
  38. package/dist/src/handlers/brain.js +69 -4181
  39. package/dist/src/handlers/cache.js +59 -638
  40. package/dist/src/handlers/context.js +17 -182
  41. package/dist/src/handlers/fedbrain.js +40 -1436
  42. package/dist/src/handlers/instances.js +16 -201
  43. package/dist/src/handlers/roadmap.js +13 -175
  44. package/dist/src/handlers/share.js +19 -530
  45. package/dist/src/handlers/syndicate.js +38 -904
  46. package/dist/src/handlers/team.js +89 -1850
  47. package/dist/src/handlers/viz.js +3 -148
  48. package/dist/src/index.js +321 -4281
  49. package/dist/src/interferenz.js +1 -0
  50. package/dist/src/kostprobe.js +7 -125
  51. package/dist/src/lesson-preview.js +2 -133
  52. package/dist/src/namespace.js +1 -128
  53. package/dist/src/notifier.js +1 -6
  54. package/dist/src/rangfolge-stellschrauben.js +1 -0
  55. package/dist/src/rangfolge.js +1 -214
  56. package/dist/src/raumkorrektur.js +1 -197
  57. package/dist/src/recall-tiefe.js +1 -42
  58. package/dist/src/rerank.js +1 -154
  59. package/dist/src/resonanz.js +1 -0
  60. package/dist/src/search.js +1 -2104
  61. package/dist/src/seltenheitsbestand.js +1 -92
  62. package/dist/src/speicherlage.js +1 -84
  63. package/dist/src/spuren.js +1 -150
  64. package/dist/src/starter-corpus.js +1 -165
  65. package/dist/src/telemetry-types.js +0 -13
  66. package/dist/src/tools.js +10 -2465
  67. package/dist/src/toolspecs.js +1 -121
  68. package/dist/src/upgrade-nudge.js +1 -29
  69. package/dist/src/utils.js +1 -89
  70. package/dist/src/versuch.js +1 -250
  71. package/dist/src/vorspann.js +1 -146
  72. package/dist/src/wartung/vektoren-verdichten.js +1 -200
  73. package/dist/src/werkzeug-nutzung.js +1 -72
  74. package/dist/src/wertbeitrag.js +1 -73
  75. package/dist/src/wirkungsspur.js +1 -0
  76. package/glama.json +1 -1
  77. package/package.json +8 -7
  78. package/server.json +3 -3
  79. package/dist/index.d.ts +0 -1
  80. package/dist/index.js.map +0 -1
  81. package/dist/packages/telegram-notify/client.d.ts +0 -19
  82. package/dist/packages/telegram-notify/client.js.map +0 -1
  83. package/dist/src/ambient-cli.d.ts +0 -101
  84. package/dist/src/ambient-cli.js.map +0 -1
  85. package/dist/src/ambient-deps.d.ts +0 -26
  86. package/dist/src/ambient-deps.js.map +0 -1
  87. package/dist/src/ambient-hooks.d.ts +0 -137
  88. package/dist/src/ambient-hooks.js.map +0 -1
  89. package/dist/src/ambient-ledger.d.ts +0 -19
  90. package/dist/src/ambient-ledger.js.map +0 -1
  91. package/dist/src/ambient-memory.d.ts +0 -12
  92. package/dist/src/ambient-memory.js.map +0 -1
  93. package/dist/src/ambient-recall.d.ts +0 -127
  94. package/dist/src/ambient-recall.js.map +0 -1
  95. package/dist/src/aussetzer.d.ts +0 -67
  96. package/dist/src/aussetzer.js.map +0 -1
  97. package/dist/src/auth.d.ts +0 -43
  98. package/dist/src/auth.js.map +0 -1
  99. package/dist/src/autor-abzeichen.d.ts +0 -41
  100. package/dist/src/autor-abzeichen.js.map +0 -1
  101. package/dist/src/autor.d.ts +0 -101
  102. package/dist/src/autor.js.map +0 -1
  103. package/dist/src/bauabdruck-daten.generiert.json +0 -5
  104. package/dist/src/bauabdruck.d.ts +0 -38
  105. package/dist/src/bauabdruck.js.map +0 -1
  106. package/dist/src/bedeutung.d.ts +0 -168
  107. package/dist/src/bedeutung.js.map +0 -1
  108. package/dist/src/bench/cachly-bench.d.ts +0 -61
  109. package/dist/src/bench/cachly-bench.js.map +0 -1
  110. package/dist/src/bench/external-corpus.d.ts +0 -44
  111. package/dist/src/bench/external-corpus.js.map +0 -1
  112. package/dist/src/bench/fixtures.d.ts +0 -37
  113. package/dist/src/bench/fixtures.js.map +0 -1
  114. package/dist/src/brain-export.d.ts +0 -64
  115. package/dist/src/brain-export.js.map +0 -1
  116. package/dist/src/brain-watch-hook.d.ts +0 -21
  117. package/dist/src/brain-watch-hook.js.map +0 -1
  118. package/dist/src/cachly-url.d.ts +0 -68
  119. package/dist/src/cachly-url.js.map +0 -1
  120. package/dist/src/ckg.d.ts +0 -54
  121. package/dist/src/ckg.js.map +0 -1
  122. package/dist/src/cls-hook.d.ts +0 -15
  123. package/dist/src/cls-hook.js.map +0 -1
  124. package/dist/src/confidence.d.ts +0 -19
  125. package/dist/src/confidence.js.map +0 -1
  126. package/dist/src/credentials.d.ts +0 -37
  127. package/dist/src/credentials.js.map +0 -1
  128. package/dist/src/deutsch.d.ts +0 -98
  129. package/dist/src/deutsch.js.map +0 -1
  130. package/dist/src/doctor.d.ts +0 -47
  131. package/dist/src/doctor.js.map +0 -1
  132. package/dist/src/editor.d.ts +0 -9
  133. package/dist/src/editor.js.map +0 -1
  134. package/dist/src/eingaenge-nachruesten.d.ts +0 -41
  135. package/dist/src/eingaenge-nachruesten.js.map +0 -1
  136. package/dist/src/eingaenge.d.ts +0 -135
  137. package/dist/src/eingaenge.js.map +0 -1
  138. package/dist/src/embeddings.d.ts +0 -48
  139. package/dist/src/embeddings.js.map +0 -1
  140. package/dist/src/first-contact.d.ts +0 -56
  141. package/dist/src/first-contact.js.map +0 -1
  142. package/dist/src/first-recall-proof.d.ts +0 -19
  143. package/dist/src/first-recall-proof.js.map +0 -1
  144. package/dist/src/funnel-milestones.d.ts +0 -5
  145. package/dist/src/funnel-milestones.js.map +0 -1
  146. package/dist/src/geliefert.d.ts +0 -63
  147. package/dist/src/geliefert.js.map +0 -1
  148. package/dist/src/handlers/advanced.d.ts +0 -6
  149. package/dist/src/handlers/advanced.js.map +0 -1
  150. package/dist/src/handlers/brain.d.ts +0 -41
  151. package/dist/src/handlers/brain.js.map +0 -1
  152. package/dist/src/handlers/cache.d.ts +0 -6
  153. package/dist/src/handlers/cache.js.map +0 -1
  154. package/dist/src/handlers/context.d.ts +0 -6
  155. package/dist/src/handlers/context.js.map +0 -1
  156. package/dist/src/handlers/fedbrain.d.ts +0 -18
  157. package/dist/src/handlers/fedbrain.js.map +0 -1
  158. package/dist/src/handlers/instances.d.ts +0 -33
  159. package/dist/src/handlers/instances.js.map +0 -1
  160. package/dist/src/handlers/roadmap.d.ts +0 -6
  161. package/dist/src/handlers/roadmap.js.map +0 -1
  162. package/dist/src/handlers/share.d.ts +0 -8
  163. package/dist/src/handlers/share.js.map +0 -1
  164. package/dist/src/handlers/syndicate.d.ts +0 -6
  165. package/dist/src/handlers/syndicate.js.map +0 -1
  166. package/dist/src/handlers/team.d.ts +0 -45
  167. package/dist/src/handlers/team.js.map +0 -1
  168. package/dist/src/handlers/viz.d.ts +0 -6
  169. package/dist/src/handlers/viz.js.map +0 -1
  170. package/dist/src/index.d.ts +0 -93
  171. package/dist/src/index.js.map +0 -1
  172. package/dist/src/kostprobe.d.ts +0 -25
  173. package/dist/src/kostprobe.js.map +0 -1
  174. package/dist/src/lesson-preview.d.ts +0 -81
  175. package/dist/src/lesson-preview.js.map +0 -1
  176. package/dist/src/namespace.d.ts +0 -20
  177. package/dist/src/namespace.js.map +0 -1
  178. package/dist/src/notifier.d.ts +0 -5
  179. package/dist/src/notifier.js.map +0 -1
  180. package/dist/src/rangfolge.d.ts +0 -169
  181. package/dist/src/rangfolge.js.map +0 -1
  182. package/dist/src/raumkorrektur.d.ts +0 -100
  183. package/dist/src/raumkorrektur.js.map +0 -1
  184. package/dist/src/recall-tiefe.d.ts +0 -48
  185. package/dist/src/recall-tiefe.js.map +0 -1
  186. package/dist/src/rerank.d.ts +0 -48
  187. package/dist/src/rerank.js.map +0 -1
  188. package/dist/src/search.d.ts +0 -153
  189. package/dist/src/search.js.map +0 -1
  190. package/dist/src/seltenheitsbestand.d.ts +0 -53
  191. package/dist/src/seltenheitsbestand.js.map +0 -1
  192. package/dist/src/speicherlage.d.ts +0 -51
  193. package/dist/src/speicherlage.js.map +0 -1
  194. package/dist/src/spuren.d.ts +0 -97
  195. package/dist/src/spuren.js.map +0 -1
  196. package/dist/src/starter-corpus.d.ts +0 -28
  197. package/dist/src/starter-corpus.js.map +0 -1
  198. package/dist/src/telemetry-types.d.ts +0 -87
  199. package/dist/src/telemetry-types.js.map +0 -1
  200. package/dist/src/tools.d.ts +0 -2933
  201. package/dist/src/tools.js.map +0 -1
  202. package/dist/src/toolspecs.d.ts +0 -43
  203. package/dist/src/toolspecs.js.map +0 -1
  204. package/dist/src/upgrade-nudge.d.ts +0 -15
  205. package/dist/src/upgrade-nudge.js.map +0 -1
  206. package/dist/src/utils.d.ts +0 -34
  207. package/dist/src/utils.js.map +0 -1
  208. package/dist/src/versuch.d.ts +0 -179
  209. package/dist/src/versuch.js.map +0 -1
  210. package/dist/src/vorspann.d.ts +0 -73
  211. package/dist/src/vorspann.js.map +0 -1
  212. package/dist/src/wartung/vektoren-verdichten.d.ts +0 -50
  213. package/dist/src/wartung/vektoren-verdichten.js.map +0 -1
  214. package/dist/src/werkzeug-nutzung.d.ts +0 -62
  215. package/dist/src/werkzeug-nutzung.js.map +0 -1
  216. package/dist/src/wertbeitrag.d.ts +0 -57
  217. package/dist/src/wertbeitrag.js.map +0 -1
@@ -1,92 +1 @@
1
- /**
2
- * Die Seltenheit der Wörter im Bestand — einmal gelesen, dann stehend.
3
- *
4
- * ── Warum es das gibt ───────────────────────────────────────────────────────
5
- *
6
- * `bewerteTopf` (src/rangfolge.ts) gewichtet die Seltenheits-Deckung mit 1,3 —
7
- * dem höchsten Gewicht von allen. Sie zu rechnen verlangt die Wortstatistik
8
- * über den GANZEN Bestand, nicht nur über die Kandidaten.
9
- *
10
- * Diese Statistik bei jeder Frage neu aufzubauen wäre genau der Fehler, den
11
- * der Wortabgleich heute macht: gemessen am 19.08.2026 baut er seinen Index
12
- * bei JEDER Frage neu, 1,6 ms je Lektion — bei 2000 Lektionen 3,2 Sekunden,
13
- * womit das 3-Sekunden-Budget der automatischen Einblendung reißt.
14
- *
15
- * Also dasselbe Muster wie `Vektorbestand`: einmal laden, eine Minute lang
16
- * gültig, danach nachladen. Ein voller Lesevorgang je Minute statt einer je
17
- * Frage.
18
- *
19
- * ── Was hier NICHT passiert ─────────────────────────────────────────────────
20
- *
21
- * Es wird keine zweite Zerlegung gebaut. `inhaltsWoerter` und `grobStamm`
22
- * kommen aus rangfolge.ts — dieselben Funktionen, die auch der Sortierer
23
- * benutzt. Zwei Zerlegungen desselben Textes wären zwei Wahrheiten, und die
24
- * Deckung würde gegen eine Statistik gerechnet, die anders zählt als sie.
25
- */
26
- import { Seltenheit } from './rangfolge.js';
27
- const LEKTION_PRAEFIX = 'cachly:lesson:best:';
28
- /** Der Text einer Lektion, so wie ihn auch der Messstand bildet. */
29
- export function lektionsText(l) {
30
- const s = (v) => (typeof v === 'string' ? v : '');
31
- return [s(l.topic), s(l.what_worked), s(l.what_failed)].filter(Boolean).join(' ');
32
- }
33
- export class Seltenheitsbestand {
34
- frischeMs;
35
- seltenheit = null;
36
- texte = new Map();
37
- geladen = 0;
38
- constructor(frischeMs = 60_000) {
39
- this.frischeMs = frischeMs;
40
- }
41
- get groesse() { return this.texte.size; }
42
- /** Der Wortschatz einer Lektion, oder ein leerer Text, wenn sie fehlt. */
43
- textVon(topic) { return this.texte.get(topic) ?? ''; }
44
- /**
45
- * Alle Themen des Bestands.
46
- *
47
- * Wird für die Vorauswahl gebraucht: sie muss über ALLE Lektionen laufen,
48
- * nicht nur über die, die zufällig einen bestimmten Vektor haben. Genau
49
- * daran ist der erste Verdrahtungsversuch am 20.08.2026 gescheitert — die
50
- * Vorauswahl lief nur über die 399 Lektionen mit Fehlertext, und die
51
- * restlichen 108 konnten nicht mehr gefunden werden (Trefferlage 90 % auf
52
- * 70 % gefallen).
53
- */
54
- themen() { return this.texte.keys(); }
55
- /** Die Statistik selbst. `null`, solange nie geladen wurde. */
56
- get statistik() { return this.seltenheit; }
57
- async aktualisiere(redis, jetzt = Date.now()) {
58
- if (this.seltenheit && jetzt - this.geladen < this.frischeMs)
59
- return;
60
- const schluessel = [];
61
- let cursor = '0';
62
- do {
63
- const [next, gefunden] = await redis.scan(cursor, 'MATCH', `${LEKTION_PRAEFIX}*`, 'COUNT', 500);
64
- cursor = next;
65
- schluessel.push(...gefunden);
66
- } while (cursor !== '0');
67
- if (schluessel.length === 0)
68
- return; // Lieber die alte Statistik als gar keine.
69
- const texte = new Map();
70
- for (let i = 0; i < schluessel.length; i += 100) {
71
- const block = schluessel.slice(i, i + 100);
72
- const werte = await redis.mget(...block);
73
- for (const [j, roh] of werte.entries()) {
74
- if (!roh)
75
- continue;
76
- try {
77
- const o = JSON.parse(roh);
78
- const topic = typeof o.topic === 'string' && o.topic
79
- ? o.topic
80
- : block[j].slice(LEKTION_PRAEFIX.length);
81
- if (topic)
82
- texte.set(topic, lektionsText(o));
83
- }
84
- catch { /* eine kaputte Zeile ist ein Thema fuer doctor, nicht fuer den Recall */ }
85
- }
86
- }
87
- this.texte = texte;
88
- this.seltenheit = new Seltenheit([...texte.values()]);
89
- this.geladen = jetzt;
90
- }
91
- }
92
- //# sourceMappingURL=seltenheitsbestand.js.map
1
+ import{Seltenheit as p}from"./rangfolge.js";const f="cachly:lesson:best:";function w(n){const t=s=>typeof s=="string"?s:"";return[t(n.topic),t(n.what_worked),t(n.what_failed)].filter(Boolean).join(" ")}class d{frischeMs;seltenheit=null;texte=new Map;geladen=0;constructor(t=6e4){this.frischeMs=t}get groesse(){return this.texte.size}textVon(t){return this.texte.get(t)??""}themen(){return this.texte.keys()}get statistik(){return this.seltenheit}async aktualisiere(t,s=Date.now()){if(this.seltenheit&&s-this.geladen<this.frischeMs)return;const i=[];let c="0";do{const[e,o]=await t.scan(c,"MATCH",`${f}*`,"COUNT",500);c=e,i.push(...o)}while(c!=="0");if(i.length===0)return;const h=new Map;for(let e=0;e<i.length;e+=100){const o=i.slice(e,e+100),u=await t.mget(...o);for(const[g,l]of u.entries())if(l)try{const r=JSON.parse(l),a=typeof r.topic=="string"&&r.topic?r.topic:o[g].slice(f.length);a&&h.set(a,w(r))}catch{}}this.texte=h,this.seltenheit=new p([...h.values()]),this.geladen=s}}export{d as Seltenheitsbestand,w as lektionsText};
@@ -1,84 +1 @@
1
- /**
2
- * Was tut der Speicher WIRKLICH — nicht, was für ihn vorgesehen war.
3
- *
4
- * ── Warum es das gibt ───────────────────────────────────────────────────────
5
- *
6
- * Am 20.08.2026 stand ein Bestand bei 23,6 MB von 25 MB Tarifgrenze und lief
7
- * dabei auf der Räumungsregel `allkeys-lru`. Diese Regel löscht bei Platzmangel
8
- * die am längsten ungenutzte Lektion — ohne Meldung, ohne Fehler, ohne Spur.
9
- * Genau die alten, selten gebrauchten Lektionen sind aber oft die wertvollen.
10
- *
11
- * Das Ärgerliche daran: der Code war seit April richtig. `evictionPolicy` gibt
12
- * für jeden Tarif `volatile-lru` zurück, und ein Test bewacht das seither. Die
13
- * laufende Instanz hatte trotzdem `allkeys-lru`, weil ein Container den
14
- * Startbefehl behält, mit dem er erzeugt wurde. Eine Regeländerung im Code
15
- * erreicht bestehende Instanzen NICHT.
16
- *
17
- * Ein Test beweist die Absicht. Diese Prüfung misst den Zustand. Das ist nicht
18
- * dieselbe Frage, und die zweite hat monatelang niemand gestellt.
19
- *
20
- * ── Warum "nicht gemessen" ein eigenes Urteil ist ──────────────────────────
21
- *
22
- * `CONFIG GET` ist auf manchen verwalteten Speichern gesperrt. Wer das als
23
- * "in Ordnung" verbucht, baut genau den Fehler wieder ein: Stille als grün.
24
- * Deshalb hat diese Prüfung drei Ausgänge, nicht zwei — gut, Hinweis, und
25
- * "konnte nicht nachsehen".
26
- */
27
- /** Anteil der Belegung, 0 bis 1. `null`, wenn es keine Grenze gibt oder nichts ablesbar ist. */
28
- export function anteil(l) {
29
- if (l.benutzt === null || l.grenze === null || l.grenze <= 0)
30
- return null;
31
- return l.benutzt / l.grenze;
32
- }
33
- const mb = (b) => `${(b / 1024 / 1024).toFixed(1)} MB`;
34
- /**
35
- * Das Urteil über eine Speicherlage.
36
- *
37
- * Die Reihenfolge ist Absicht: die stille Löschung steht vor der Füllung. Eine
38
- * halbvolle Instanz, die still löscht, ist gefährlicher als eine volle, die
39
- * laut scheitert.
40
- */
41
- export function beurteileSpeicher(l) {
42
- const aus = [];
43
- if (l.richtlinie === null) {
44
- aus.push({
45
- art: 'ungemessen',
46
- text: 'Raeumungsregel nicht ablesbar (CONFIG GET gesperrt) — unbekannt, ob dieser Speicher bei Platzmangel still loescht.',
47
- });
48
- }
49
- else if (l.richtlinie.startsWith('allkeys')) {
50
- aus.push({
51
- art: 'fehler',
52
- text: `Raeumungsregel ist \`${l.richtlinie}\`: bei Platzmangel wird die am laengsten ungenutzte Lektion GELOESCHT, ohne Meldung. Ein Gedaechtnis darf nicht raeumen wie ein Zwischenspeicher. Richtig waere \`volatile-lru\` (raeumt nur, was ohnehin ablaeuft) oder \`noeviction\` (scheitert laut).`,
53
- });
54
- }
55
- else if (l.richtlinie === 'volatile-lru' || l.richtlinie === 'noeviction') {
56
- aus.push({ art: 'gut', text: `Raeumungsregel \`${l.richtlinie}\` — Lektionen ohne Ablaufdatum sind sicher.` });
57
- }
58
- else {
59
- aus.push({ art: 'hinweis', text: `Raeumungsregel \`${l.richtlinie}\` — ungeprueft fuer diesen Zweck.` });
60
- }
61
- const a = anteil(l);
62
- if (l.benutzt === null) {
63
- aus.push({ art: 'ungemessen', text: 'Belegung nicht ablesbar.' });
64
- }
65
- else if (a === null) {
66
- aus.push({ art: 'hinweis', text: `${mb(l.benutzt)} belegt, keine Obergrenze gesetzt — dieser Speicher waechst, bis der Rechner voll ist.` });
67
- }
68
- else if (a >= 0.9) {
69
- aus.push({ art: 'fehler', text: `${mb(l.benutzt)} von ${mb(l.grenze)} belegt (${Math.round(a * 100)} %). Die naechsten Lektionen scheitern bald.` });
70
- }
71
- else if (a >= 0.75) {
72
- aus.push({ art: 'hinweis', text: `${mb(l.benutzt)} von ${mb(l.grenze)} belegt (${Math.round(a * 100)} %).` });
73
- }
74
- else {
75
- aus.push({ art: 'gut', text: `${mb(l.benutzt)} von ${mb(l.grenze)} belegt (${Math.round(a * 100)} %).` });
76
- }
77
- return aus;
78
- }
79
- /** Eine Zahl aus einem INFO-Block, z. B. `used_memory`. `null`, wenn sie fehlt. */
80
- export function zahlAusInfo(info, name) {
81
- const t = new RegExp(`^${name}:(\\d+)`, 'm').exec(info);
82
- return t ? Number(t[1]) : null;
83
- }
84
- //# sourceMappingURL=speicherlage.js.map
1
+ function r(e){return e.benutzt===null||e.grenze===null||e.grenze<=0?null:e.benutzt/e.grenze}const i=e=>`${(e/1024/1024).toFixed(1)} MB`;function u(e){const t=[];e.richtlinie===null?t.push({art:"ungemessen",text:"Raeumungsregel nicht ablesbar (CONFIG GET gesperrt) \u2014 unbekannt, ob dieser Speicher bei Platzmangel still loescht."}):e.richtlinie.startsWith("allkeys")?t.push({art:"fehler",text:`Raeumungsregel ist \`${e.richtlinie}\`: bei Platzmangel wird die am laengsten ungenutzte Lektion GELOESCHT, ohne Meldung. Ein Gedaechtnis darf nicht raeumen wie ein Zwischenspeicher. Richtig waere \`volatile-lru\` (raeumt nur, was ohnehin ablaeuft) oder \`noeviction\` (scheitert laut).`}):e.richtlinie==="volatile-lru"||e.richtlinie==="noeviction"?t.push({art:"gut",text:`Raeumungsregel \`${e.richtlinie}\` \u2014 Lektionen ohne Ablaufdatum sind sicher.`}):t.push({art:"hinweis",text:`Raeumungsregel \`${e.richtlinie}\` \u2014 ungeprueft fuer diesen Zweck.`});const n=r(e);return e.benutzt===null?t.push({art:"ungemessen",text:"Belegung nicht ablesbar."}):n===null?t.push({art:"hinweis",text:`${i(e.benutzt)} belegt, keine Obergrenze gesetzt \u2014 dieser Speicher waechst, bis der Rechner voll ist.`}):n>=.9?t.push({art:"fehler",text:`${i(e.benutzt)} von ${i(e.grenze)} belegt (${Math.round(n*100)} %). Die naechsten Lektionen scheitern bald.`}):n>=.75?t.push({art:"hinweis",text:`${i(e.benutzt)} von ${i(e.grenze)} belegt (${Math.round(n*100)} %).`}):t.push({art:"gut",text:`${i(e.benutzt)} von ${i(e.grenze)} belegt (${Math.round(n*100)} %).`}),t}function s(e,t){const n=new RegExp(`^${t}:(\\d+)`,"m").exec(e);return n?Number(n[1]):null}export{r as anteil,u as beurteileSpeicher,s as zahlAusInfo};
@@ -1,150 +1 @@
1
- /**
2
- * Trampelpfade: das System lernt die Fragen, mit denen man es wirklich sucht.
3
- *
4
- * ── Der Gedanke ─────────────────────────────────────────────────────────────
5
- *
6
- * Ein Immunsystem hält Andockstellen vorrätig — und nach jeder überstandenen
7
- * Infektion bleiben Gedächtniszellen zurück, die genau diesen Erreger beim
8
- * nächsten Mal sofort greifen. Die Andockstellen sind gebaut (`eingaenge.ts`,
9
- * die Fehlertexte). Das hier sind die Gedächtniszellen.
10
- *
11
- * Wenn eine Frage eine Lektion findet, ist diese Frage ein bewiesener Weg zu
12
- * ihr. Sie wird als eigener Eingang gespeichert — beim nächsten Mal ist der
13
- * Weg breiter.
14
- *
15
- * ── Warum erst beim ZWEITEN Mal ─────────────────────────────────────────────
16
- *
17
- * Der Bauplan wollte den Eingang speichern, sobald eine Lektion „benutzt oder
18
- * bestätigt" wurde. Dieses Signal gibt es nicht: der Server sieht, was er
19
- * ausgeliefert hat, nicht was jemand damit gemacht hat. Es zu erfinden wäre
20
- * eine Zahl ohne Deckung.
21
- *
22
- * Also das, was ein Trampelpfad wirklich ist: **Wiederholung.** Ein einzelnes
23
- * Durchqueren macht keinen Weg. Führt dieselbe Frage ZWEIMAL zu derselben
24
- * Lektion, ist sie ein Pfad — und braucht dafür keine Bestätigung von außen,
25
- * sondern nur Geduld.
26
- *
27
- * ── Was das kann, und was ausdrücklich nicht ────────────────────────────────
28
- *
29
- * ES HILFT: einer Frage, die die Lektion heute auf Platz 3 findet, morgen auf
30
- * Platz 1. Genau das ist der gemessene Engpass — 37 richtige Antworten liegen
31
- * im Topf und werden nicht gezeigt (`.agent/cachly/tor0-tor1-ergebnis.md`).
32
- *
33
- * ES HILFT NICHT: einer Frage, die die Lektion gar nicht findet. Die wird nie
34
- * aufgezeichnet, weil sie nie ankam. Dieser blinde Fleck ist der Grund, warum
35
- * die Fehlertext-Eingänge daneben bestehen bleiben — sie wirken ohne Nutzung.
36
- */
37
- import { packe } from './bedeutung.js';
38
- import { EINGANG_PRAEFIX } from './eingaenge.js';
39
- /** Wo die noch unbewiesenen Spuren liegen: Frage → wie oft sie hierher führte. */
40
- export const SPUR_PRAEFIX = 'cachly:lesson:spur:';
41
- /**
42
- * Wo die bewiesenen Pfade liegen — als eigener Hash, NICHT im Eingangs-Hash.
43
- *
44
- * Grund: `schreibeEingaenge` löscht seinen Hash vor jedem Schreiben, damit die
45
- * Fehlertexte einer alten Fassung nicht neben denen der neuen stehen bleiben.
46
- * Lägen die gelernten Fragen dort, würde jedes erneute Lernen der Lektion die
47
- * gesammelte Erfahrung wegwerfen — ein Gedächtnis, das beim Dazulernen
48
- * vergisst.
49
- */
50
- export const PFAD_PRAEFIX = 'cachly:lesson:pfad:';
51
- /** Ab wie vielen Malen eine Frage als Pfad gilt. Einmal ist Zufall. */
52
- export const PFAD_SCHWELLE = 2;
53
- /** Höchstens so viele gelernte Fragen je Lektion. Der schwächste weicht. */
54
- export const PFAD_KAPPE = 8;
55
- /** Nur Fragen dieser Länge werden aufgezeichnet. */
56
- const MIN_LAENGE = 8;
57
- const MAX_LAENGE = 200;
58
- /**
59
- * Zwei Fragen, die sich nur in Zeichensetzung und Grossschreibung
60
- * unterscheiden, sind derselbe Weg.
61
- *
62
- * Bewusst KEIN Stammformen-Verfahren: am 19.08.2026 gemessen kostete
63
- * Stammbildung drei Punkte Findequote. Hier geht es ausserdem um Gleichheit,
64
- * nicht um Ähnlichkeit — wer „docker startet nicht" und „Docker startet
65
- * nicht!" trennt, zählt zweimal halb statt einmal ganz.
66
- */
67
- export function spurSchluessel(frage) {
68
- return frage
69
- .toLowerCase()
70
- .replace(/[^\p{L}\p{N}\s]/gu, ' ')
71
- .replace(/\s+/g, ' ')
72
- .trim()
73
- .slice(0, MAX_LAENGE);
74
- }
75
- /** Taugt diese Frage überhaupt als Pfad? */
76
- export function taugtAlsSpur(frage) {
77
- const k = spurSchluessel(frage);
78
- // Eine Frage aus einem einzigen Wort ist kein Weg, sondern ein Stichwort —
79
- // sie würde jede Lektion an sich ziehen, die dieses Wort enthält.
80
- return k.length >= MIN_LAENGE && k.split(' ').length >= 2;
81
- }
82
- /**
83
- * Welche Fragen sollen ihre Kappe überleben?
84
- *
85
- * Absteigend nach Häufigkeit; bei Gleichstand gewinnt die kürzere. Eine kurze
86
- * Frage, die genauso oft hierher führte, ist die allgemeinere — sie fängt mehr
87
- * Formulierungen als ihre lange Schwester.
88
- */
89
- export function behalte(pfade, kappe = PFAD_KAPPE) {
90
- return pfade
91
- .slice()
92
- .sort((a, b) => b.anzahl - a.anzahl || a.frage.length - b.frage.length)
93
- .slice(0, kappe);
94
- }
95
- /**
96
- * Zeichnet auf, dass diese Frage zu diesen Lektionen geführt hat, und macht
97
- * aus einer Spur einen Pfad, sobald sie sich wiederholt.
98
- *
99
- * Bewusst KEIN await beim Aufrufer nötig: wer sucht, soll nicht warten, bis
100
- * das Gedächtnis nachgeführt ist. Fällt es aus, ist die Suche trotzdem
101
- * beantwortet — der Pfad entsteht dann eben beim nächsten Mal.
102
- *
103
- * @returns wie viele Fragen zu Pfaden befördert wurden
104
- */
105
- export async function spurLegen(redis, frage, themen, einbetten) {
106
- if (!taugtAlsSpur(frage) || themen.length === 0)
107
- return 0;
108
- const schluessel = spurSchluessel(frage);
109
- let befoerdert = 0;
110
- for (const topic of themen) {
111
- const spurKey = `${SPUR_PRAEFIX}${topic}`;
112
- const pfadKey = `${PFAD_PRAEFIX}${topic}`;
113
- // Schon ein Pfad? Dann nur mitzaehlen, nicht noch einmal einbetten.
114
- const istPfad = await redis.hexists(pfadKey, schluessel);
115
- const anzahl = await redis.hincrby(spurKey, schluessel, 1);
116
- if (istPfad || anzahl < PFAD_SCHWELLE)
117
- continue;
118
- // Eingebettet wird die FRAGE, wiedererkannt wird der Schluessel.
119
- //
120
- // Zwei verschiedene Aufgaben: der Schluessel muss "Docker startet nicht!"
121
- // und "docker startet nicht" als denselben Weg erkennen — dafuer ist er
122
- // kleingeschrieben und ohne Zeichensetzung. Fuer die Bedeutung ist genau
123
- // das ein Verlust: im Deutschen traegt die Grossschreibung, ob "Sein" ein
124
- // Hauptwort ist. Also wird der Originalwortlaut eingebettet.
125
- const v = await einbetten(frage.trim().slice(0, MAX_LAENGE));
126
- if (!v?.length)
127
- continue;
128
- await redis.hset(pfadKey, schluessel, packe(v));
129
- befoerdert++;
130
- // Kappe durchsetzen: der am seltensten begangene Pfad weicht.
131
- const alle = await redis.hkeys(pfadKey);
132
- if (alle.length > PFAD_KAPPE) {
133
- const zaehler = await redis.hgetall(spurKey);
134
- const mitAnzahl = alle.map((f) => ({ frage: f, anzahl: Number(zaehler[f] ?? 0) }));
135
- const bleiben = new Set(behalte(mitAnzahl).map((x) => x.frage));
136
- const raus = alle.filter((f) => !bleiben.has(f));
137
- if (raus.length)
138
- await redis.hdel(pfadKey, ...raus);
139
- }
140
- }
141
- return befoerdert;
142
- }
143
- /**
144
- * Was `Eingangsbestand` laden muss: beide Hashes.
145
- *
146
- * Steht hier und nicht in eingaenge.ts, damit die Reihenfolge der Module
147
- * eindeutig bleibt — spuren kennt eingaenge, nicht umgekehrt.
148
- */
149
- export const EINGANGS_PRAEFIXE = [EINGANG_PRAEFIX, PFAD_PRAEFIX];
150
- //# sourceMappingURL=spuren.js.map
1
+ import{packe as _}from"./bedeutung.js";import{EINGANG_PRAEFIX as y}from"./eingaenge.js";const F="cachly:lesson:spur:",f="cachly:lesson:pfad:",I=2,g=8,L=8,A=200;function E(t){return t.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu," ").replace(/\s+/g," ").trim().slice(0,A)}function z(t){const e=E(t);return e.length>=L&&e.split(" ").length>=2}function G(t,e=g){return t.slice().sort((o,s)=>s.anzahl-o.anzahl||o.frage.length-s.frage.length).slice(0,e)}async function R(t,e,o,s){if(!z(e)||o.length===0)return 0;const c=E(e);let r=0;for(const i of o){const p=`${F}${i}`,a=`${f}${i}`,P=await t.hexists(a,c),x=await t.hincrby(p,c,1);if(P||x<I)continue;const h=await s(e.trim().slice(0,A));if(!h?.length)continue;await t.hset(a,c,_(h)),r++;const l=await t.hkeys(a);if(l.length>g){const m=await t.hgetall(p),w=l.map(n=>({frage:n,anzahl:Number(m[n]??0)})),N=new Set(G(w).map(n=>n.frage)),u=l.filter(n=>!N.has(n));u.length&&await t.hdel(a,...u)}}return r}const X=[y,f];export{X as EINGANGS_PRAEFIXE,g as PFAD_KAPPE,f as PFAD_PRAEFIX,I as PFAD_SCHWELLE,F as SPUR_PRAEFIX,G as behalte,R as spurLegen,E as spurSchluessel,z as taugtAlsSpur};
@@ -1,165 +1 @@
1
- /**
2
- * Curated starter corpus — universal, high-value engineering lessons.
3
- *
4
- * Loaded on demand via `brain_seed_starter` (or offered in the empty-brain
5
- * session_start welcome). The goal is to drop **time-to-first-recall** below
6
- * two minutes: a brand-new Brain (fresh repo, shallow clone, no fix-commits in
7
- * git history) would otherwise return nothing on the user's first query.
8
- *
9
- * Every lesson here is:
10
- * - stack-agnostic or broadly applicable (no project-specific paths)
11
- * - a real, common failure mode with a proven fix
12
- * - free of secrets / PII
13
- * - tagged `source: 'starter'` so it can be identified, filtered, or removed
14
- *
15
- * These ship inside the package — no network call needed to seed.
16
- */
17
- export const STARTER_CORPUS = [
18
- {
19
- topic: 'docker:layer-cache',
20
- outcome: 'success',
21
- what_worked: 'Copy package manifests (package.json/lock, go.mod, requirements.txt) and install deps BEFORE copying the rest of the source. Dependency layers then stay cached across code-only changes.',
22
- what_failed: 'Build re-downloads all dependencies on every code change because `COPY . .` came before the install step, busting the cache.',
23
- ctx: 'Slow Docker builds in CI — every commit reinstalls dependencies even when only app code changed.',
24
- tags: ['docker', 'ci', 'build', 'cache', 'performance'],
25
- confidence: 0.9,
26
- },
27
- {
28
- topic: 'git:force-push-safety',
29
- outcome: 'success',
30
- what_worked: 'Use `git push --force-with-lease` instead of `--force`. It refuses to overwrite if the remote moved since your last fetch, protecting teammates\' commits.',
31
- what_failed: 'A plain `git push --force` silently clobbered a colleague\'s commits that had landed after the last local fetch.',
32
- ctx: 'Rebasing a shared feature branch and force-pushing the result.',
33
- tags: ['git', 'rebase', 'collaboration', 'safety'],
34
- confidence: 0.92,
35
- },
36
- {
37
- topic: 'ci:flaky-tests-timing',
38
- outcome: 'success',
39
- what_worked: 'Pin time and randomness: use fake/frozen timers (e.g. vi.useFakeTimers, freezegun) and a fixed RNG seed. Replace arbitrary sleeps with explicit awaits on a condition.',
40
- what_failed: 'Tests passed locally but failed ~10% of the time in CI due to real wall-clock timing and unseeded random data.',
41
- ctx: 'Intermittent CI failures that disappear on re-run — classic flaky test.',
42
- tags: ['ci', 'testing', 'flaky', 'timers', 'determinism'],
43
- confidence: 0.85,
44
- },
45
- {
46
- topic: 'node:esm-cjs-interop',
47
- outcome: 'success',
48
- what_worked: 'Set `"type": "module"` in package.json for ESM, use explicit `.js` extensions in relative imports, and `import { createRequire }` if you must load a CJS-only module.',
49
- what_failed: '"ReferenceError: exports is not defined" / "Cannot use import statement outside a module" after mixing ESM and CommonJS.',
50
- ctx: 'Migrating a Node project to ES modules or adding an ESM-only dependency.',
51
- tags: ['node', 'esm', 'commonjs', 'modules', 'typescript'],
52
- confidence: 0.85,
53
- },
54
- {
55
- topic: 'jwt:clock-skew',
56
- outcome: 'success',
57
- what_worked: 'Allow a small leeway (30–60s) when validating `exp`/`nbf` claims, and keep server clocks synced with NTP. Most JWT libraries accept a `clockTolerance` option.',
58
- what_failed: 'Valid tokens were rejected as expired because the auth server and API server clocks differed by a few seconds.',
59
- ctx: 'Intermittent 401s right around token expiry across multiple services.',
60
- tags: ['jwt', 'auth', 'clock', 'security', 'tokens'],
61
- confidence: 0.88,
62
- },
63
- {
64
- topic: 'postgres:migration-lock',
65
- outcome: 'success',
66
- what_worked: 'Set a short `lock_timeout` before DDL and add indexes with `CREATE INDEX CONCURRENTLY`. This avoids a migration blocking on a long-held table lock and stalling the whole deploy.',
67
- what_failed: 'A migration hung indefinitely waiting for an ACCESS EXCLUSIVE lock while a long-running query held the table, blocking the deploy.',
68
- ctx: 'Production deploy froze during a schema migration under live traffic.',
69
- tags: ['postgres', 'database', 'migration', 'deploy', 'locking'],
70
- confidence: 0.87,
71
- },
72
- {
73
- topic: 'redis:eviction-policy',
74
- outcome: 'success',
75
- what_worked: 'Set `maxmemory` and an explicit `maxmemory-policy` (e.g. `allkeys-lru` for a cache, `noeviction` for a datastore). Always set TTLs on cache keys.',
76
- what_failed: 'Redis silently evicted keys (or OOM-errored on writes) because no maxmemory policy was configured and keys never expired.',
77
- ctx: 'Cache hit-rate cratered / writes started failing as Redis filled up.',
78
- tags: ['redis', 'cache', 'memory', 'eviction', 'ttl'],
79
- confidence: 0.86,
80
- },
81
- {
82
- topic: 'k8s:oom-limits',
83
- outcome: 'success',
84
- what_worked: 'Set both memory `requests` and `limits` on every container. For JVM/Node, also cap the runtime heap below the container limit so the GC reclaims before the kernel OOM-kills.',
85
- what_failed: 'Pods were OOMKilled (exit 137) and restarted in a loop because no memory limit was set and the node was overcommitted.',
86
- ctx: 'Pod restarting repeatedly with OOMKilled status in kubectl describe.',
87
- tags: ['kubernetes', 'oom', 'memory', 'limits', 'infra'],
88
- confidence: 0.85,
89
- },
90
- {
91
- topic: 'cors:preflight',
92
- outcome: 'success',
93
- what_worked: 'Handle the OPTIONS preflight explicitly and return the right Access-Control-Allow-{Origin,Methods,Headers}. For credentialed requests, echo a specific origin (never `*`) and set Allow-Credentials: true.',
94
- what_failed: 'Browser blocked requests with "No \'Access-Control-Allow-Origin\' header" — the server never answered the preflight OPTIONS request.',
95
- ctx: 'Frontend on a different origin gets CORS errors only in the browser (curl works fine).',
96
- tags: ['cors', 'http', 'api', 'browser', 'preflight'],
97
- confidence: 0.84,
98
- },
99
- {
100
- topic: 'env:dotenv-precedence',
101
- outcome: 'success',
102
- what_worked: 'Know the precedence: real environment variables (and Docker `-e`/compose `environment`) override a `.env` file. Most loaders will NOT overwrite an already-set var. Audit with a startup log of effective config.',
103
- what_failed: 'A value in `.env` was silently ignored in the container because an environment variable of the same name was already set by Docker.',
104
- ctx: 'Config works locally but the container picks up the wrong value.',
105
- tags: ['env', 'dotenv', 'docker', 'config'],
106
- confidence: 0.83,
107
- },
108
- {
109
- topic: 'async:unhandled-rejection',
110
- outcome: 'success',
111
- what_worked: 'Await or `.catch()` every promise. Add a process-level `unhandledRejection` handler that logs and exits non-zero, so a dropped rejection is loud, not silent.',
112
- what_failed: 'A fire-and-forget promise rejected, the error vanished, and the process kept running in a broken state with no log.',
113
- ctx: 'Mysterious missing data / silent failures with no stack trace in a Node service.',
114
- tags: ['async', 'node', 'promises', 'error-handling'],
115
- confidence: 0.84,
116
- },
117
- {
118
- topic: 'sql:n-plus-one',
119
- outcome: 'success',
120
- what_worked: 'Eager-load related rows in one query (JOIN or the ORM\'s include/preload/select_related) instead of looping and querying per row. Verify with query logging or an APM trace.',
121
- what_failed: 'An endpoint issued one query per item in a list (N+1), making latency scale linearly with result count.',
122
- ctx: 'List endpoint gets slow as data grows; DB shows a flood of near-identical small queries.',
123
- tags: ['sql', 'database', 'orm', 'performance', 'n+1'],
124
- confidence: 0.86,
125
- },
126
- {
127
- topic: 'http:retry-idempotency',
128
- outcome: 'success',
129
- what_worked: 'Only auto-retry idempotent requests (GET/PUT/DELETE) or POSTs guarded by an idempotency key. Use exponential backoff with jitter and a cap on attempts.',
130
- what_failed: 'A retried POST created duplicate records because the first request actually succeeded but the response was lost.',
131
- ctx: 'Duplicate charges / duplicate rows after adding naive retry logic to an HTTP client.',
132
- tags: ['http', 'retry', 'idempotency', 'reliability', 'backoff'],
133
- confidence: 0.85,
134
- },
135
- {
136
- topic: 'cache:stampede',
137
- outcome: 'success',
138
- what_worked: 'Prevent thundering-herd recomputation on cache expiry with a short lock (single-flight) or early-recompute-with-jitter so only one request rebuilds the value while others serve the stale one.',
139
- what_failed: 'When a hot cache key expired, hundreds of concurrent requests all missed and hammered the database simultaneously.',
140
- ctx: 'Periodic DB load spikes that line up exactly with cache TTL expiry.',
141
- tags: ['cache', 'stampede', 'performance', 'concurrency', 'redis'],
142
- confidence: 0.83,
143
- },
144
- {
145
- topic: 'security:no-secrets-in-logs',
146
- outcome: 'success',
147
- what_worked: 'Redact tokens, passwords, and full auth headers before logging. Log a token\'s prefix + length, never the value. Add a log scrubber/filter so it cannot regress.',
148
- what_failed: 'A bearer token was written to application logs and ended up in the log aggregator, where it was searchable by anyone with log access.',
149
- ctx: 'Security review found credentials in centralized logs.',
150
- tags: ['security', 'logging', 'secrets', 'pii', 'compliance'],
151
- confidence: 0.9,
152
- },
153
- {
154
- topic: 'tls:cert-expiry',
155
- outcome: 'success',
156
- what_worked: 'Automate renewal (ACME/cert-manager) and alert at least 14 days before expiry. Monitor the leaf AND intermediate chain — clients fail if the chain is incomplete even when the leaf is valid.',
157
- what_failed: 'A production outage hit when a TLS certificate silently expired over a weekend with no alerting in place.',
158
- ctx: 'Sudden "certificate has expired" errors from clients; site unreachable over HTTPS.',
159
- tags: ['tls', 'ssl', 'certificates', 'monitoring', 'infra'],
160
- confidence: 0.88,
161
- },
162
- ];
163
- /** Stable count for changelog / docs. */
164
- export const STARTER_CORPUS_SIZE = STARTER_CORPUS.length;
165
- //# sourceMappingURL=starter-corpus.js.map
1
+ const e=[{topic:"docker:layer-cache",outcome:"success",what_worked:"Copy package manifests (package.json/lock, go.mod, requirements.txt) and install deps BEFORE copying the rest of the source. Dependency layers then stay cached across code-only changes.",what_failed:"Build re-downloads all dependencies on every code change because `COPY . .` came before the install step, busting the cache.",ctx:"Slow Docker builds in CI \u2014 every commit reinstalls dependencies even when only app code changed.",tags:["docker","ci","build","cache","performance"],confidence:.9},{topic:"git:force-push-safety",outcome:"success",what_worked:"Use `git push --force-with-lease` instead of `--force`. It refuses to overwrite if the remote moved since your last fetch, protecting teammates' commits.",what_failed:"A plain `git push --force` silently clobbered a colleague's commits that had landed after the last local fetch.",ctx:"Rebasing a shared feature branch and force-pushing the result.",tags:["git","rebase","collaboration","safety"],confidence:.92},{topic:"ci:flaky-tests-timing",outcome:"success",what_worked:"Pin time and randomness: use fake/frozen timers (e.g. vi.useFakeTimers, freezegun) and a fixed RNG seed. Replace arbitrary sleeps with explicit awaits on a condition.",what_failed:"Tests passed locally but failed ~10% of the time in CI due to real wall-clock timing and unseeded random data.",ctx:"Intermittent CI failures that disappear on re-run \u2014 classic flaky test.",tags:["ci","testing","flaky","timers","determinism"],confidence:.85},{topic:"node:esm-cjs-interop",outcome:"success",what_worked:'Set `"type": "module"` in package.json for ESM, use explicit `.js` extensions in relative imports, and `import { createRequire }` if you must load a CJS-only module.',what_failed:'"ReferenceError: exports is not defined" / "Cannot use import statement outside a module" after mixing ESM and CommonJS.',ctx:"Migrating a Node project to ES modules or adding an ESM-only dependency.",tags:["node","esm","commonjs","modules","typescript"],confidence:.85},{topic:"jwt:clock-skew",outcome:"success",what_worked:"Allow a small leeway (30\u201360s) when validating `exp`/`nbf` claims, and keep server clocks synced with NTP. Most JWT libraries accept a `clockTolerance` option.",what_failed:"Valid tokens were rejected as expired because the auth server and API server clocks differed by a few seconds.",ctx:"Intermittent 401s right around token expiry across multiple services.",tags:["jwt","auth","clock","security","tokens"],confidence:.88},{topic:"postgres:migration-lock",outcome:"success",what_worked:"Set a short `lock_timeout` before DDL and add indexes with `CREATE INDEX CONCURRENTLY`. This avoids a migration blocking on a long-held table lock and stalling the whole deploy.",what_failed:"A migration hung indefinitely waiting for an ACCESS EXCLUSIVE lock while a long-running query held the table, blocking the deploy.",ctx:"Production deploy froze during a schema migration under live traffic.",tags:["postgres","database","migration","deploy","locking"],confidence:.87},{topic:"redis:eviction-policy",outcome:"success",what_worked:"Set `maxmemory` and an explicit `maxmemory-policy` (e.g. `allkeys-lru` for a cache, `noeviction` for a datastore). Always set TTLs on cache keys.",what_failed:"Redis silently evicted keys (or OOM-errored on writes) because no maxmemory policy was configured and keys never expired.",ctx:"Cache hit-rate cratered / writes started failing as Redis filled up.",tags:["redis","cache","memory","eviction","ttl"],confidence:.86},{topic:"k8s:oom-limits",outcome:"success",what_worked:"Set both memory `requests` and `limits` on every container. For JVM/Node, also cap the runtime heap below the container limit so the GC reclaims before the kernel OOM-kills.",what_failed:"Pods were OOMKilled (exit 137) and restarted in a loop because no memory limit was set and the node was overcommitted.",ctx:"Pod restarting repeatedly with OOMKilled status in kubectl describe.",tags:["kubernetes","oom","memory","limits","infra"],confidence:.85},{topic:"cors:preflight",outcome:"success",what_worked:"Handle the OPTIONS preflight explicitly and return the right Access-Control-Allow-{Origin,Methods,Headers}. For credentialed requests, echo a specific origin (never `*`) and set Allow-Credentials: true.",what_failed:`Browser blocked requests with "No 'Access-Control-Allow-Origin' header" \u2014 the server never answered the preflight OPTIONS request.`,ctx:"Frontend on a different origin gets CORS errors only in the browser (curl works fine).",tags:["cors","http","api","browser","preflight"],confidence:.84},{topic:"env:dotenv-precedence",outcome:"success",what_worked:"Know the precedence: real environment variables (and Docker `-e`/compose `environment`) override a `.env` file. Most loaders will NOT overwrite an already-set var. Audit with a startup log of effective config.",what_failed:"A value in `.env` was silently ignored in the container because an environment variable of the same name was already set by Docker.",ctx:"Config works locally but the container picks up the wrong value.",tags:["env","dotenv","docker","config"],confidence:.83},{topic:"async:unhandled-rejection",outcome:"success",what_worked:"Await or `.catch()` every promise. Add a process-level `unhandledRejection` handler that logs and exits non-zero, so a dropped rejection is loud, not silent.",what_failed:"A fire-and-forget promise rejected, the error vanished, and the process kept running in a broken state with no log.",ctx:"Mysterious missing data / silent failures with no stack trace in a Node service.",tags:["async","node","promises","error-handling"],confidence:.84},{topic:"sql:n-plus-one",outcome:"success",what_worked:"Eager-load related rows in one query (JOIN or the ORM's include/preload/select_related) instead of looping and querying per row. Verify with query logging or an APM trace.",what_failed:"An endpoint issued one query per item in a list (N+1), making latency scale linearly with result count.",ctx:"List endpoint gets slow as data grows; DB shows a flood of near-identical small queries.",tags:["sql","database","orm","performance","n+1"],confidence:.86},{topic:"http:retry-idempotency",outcome:"success",what_worked:"Only auto-retry idempotent requests (GET/PUT/DELETE) or POSTs guarded by an idempotency key. Use exponential backoff with jitter and a cap on attempts.",what_failed:"A retried POST created duplicate records because the first request actually succeeded but the response was lost.",ctx:"Duplicate charges / duplicate rows after adding naive retry logic to an HTTP client.",tags:["http","retry","idempotency","reliability","backoff"],confidence:.85},{topic:"cache:stampede",outcome:"success",what_worked:"Prevent thundering-herd recomputation on cache expiry with a short lock (single-flight) or early-recompute-with-jitter so only one request rebuilds the value while others serve the stale one.",what_failed:"When a hot cache key expired, hundreds of concurrent requests all missed and hammered the database simultaneously.",ctx:"Periodic DB load spikes that line up exactly with cache TTL expiry.",tags:["cache","stampede","performance","concurrency","redis"],confidence:.83},{topic:"security:no-secrets-in-logs",outcome:"success",what_worked:"Redact tokens, passwords, and full auth headers before logging. Log a token's prefix + length, never the value. Add a log scrubber/filter so it cannot regress.",what_failed:"A bearer token was written to application logs and ended up in the log aggregator, where it was searchable by anyone with log access.",ctx:"Security review found credentials in centralized logs.",tags:["security","logging","secrets","pii","compliance"],confidence:.9},{topic:"tls:cert-expiry",outcome:"success",what_worked:"Automate renewal (ACME/cert-manager) and alert at least 14 days before expiry. Monitor the leaf AND intermediate chain \u2014 clients fail if the chain is incomplete even when the leaf is valid.",what_failed:"A production outage hit when a TLS certificate silently expired over a weekend with no alerting in place.",ctx:'Sudden "certificate has expired" errors from clients; site unreachable over HTTPS.',tags:["tls","ssl","certificates","monitoring","infra"],confidence:.88}],t=e.length;export{e as STARTER_CORPUS,t as STARTER_CORPUS_SIZE};
@@ -1,13 +0,0 @@
1
- /**
2
- * Canonical types for the cachly telemetry event stream.
3
- *
4
- * These types form the contract between:
5
- * - cachly-mcp (emitter) → POST /api/v1/telemetry/mcp
6
- * - cachly API (receiver) → resolves api_key → {org_id, user_id}, queues enriched event
7
- * - cachly-insights ingest (consumer) ← reads enriched events from the resolved queue
8
- *
9
- * The ingest worker MUST NOT see raw JWTs or api_keys. Resolution happens
10
- * exclusively inside the cachly API trust boundary before events reach the queue.
11
- */
12
- export {};
13
- //# sourceMappingURL=telemetry-types.js.map