@cachly-dev/mcp-server 0.10.223 → 0.10.225
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/src/abstention.js +2 -2
- package/dist/src/autor.js +1 -1
- package/dist/src/doppel-kandidat.js +1 -1
- package/dist/src/entscheidung-ableiten.js +1 -1
- package/dist/src/ersetzung-vorschlag.js +1 -1
- package/dist/src/handlers/advanced.js +1 -1
- package/dist/src/handlers/brain.js +64 -65
- package/dist/src/handlers/team.js +1 -1
- package/dist/src/projektdateien.js +10 -4
- package/dist/src/rangfolge.js +1 -1
- package/dist/src/search.js +1 -1
- package/dist/src/sitzungs-kosten.js +1 -1
- package/dist/src/uninstall.js +4 -4
- package/dist/src/upgrade-nudge.js +1 -1
- package/dist/src/vorspann.js +1 -1
- package/dist/src/wirkungsspur.js +1 -1
- package/glama.json +1 -1
- package/hooks/cachly-ambient-einblendung.mjs +9 -9
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -64,13 +64,20 @@ move is refused with a message.
|
|
|
64
64
|
npx @cachly-dev/mcp-server@latest autopilot
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
`autopilot` finds the editors you use and writes the MCP config for each. It
|
|
67
|
+
`autopilot` finds the editors you use and writes the MCP config for each. It also writes
|
|
68
|
+
the rule file each editor reads in every chat (`CLAUDE.md`, `AGENTS.md`,
|
|
69
|
+
`.cursor/rules/cachly.mdc`, `.github/copilot-instructions.md`, `.windsurfrules`,
|
|
70
|
+
`.clinerules`; `GEMINI.md`, `.junie/guidelines.md` and `.continue/rules/cachly.md` where
|
|
71
|
+
you use Gemini CLI, Junie or Continue), which tells your AI to check its memory before a task. It adds a git
|
|
68
72
|
hook that learns from your commits and fills your Brain from your git history. You sign
|
|
69
73
|
in once in the browser (a device code, no password, no credit card), so the Brain
|
|
70
74
|
belongs to your own account from the start. Restart your editor afterwards.
|
|
71
75
|
|
|
72
76
|
You can also add the server by hand (see [Manual Setup](#manual-setup)). Without a key,
|
|
73
|
-
the first tool call creates the same test Brain as in Claude Code.
|
|
77
|
+
the first tool call creates the same test Brain as in Claude Code. Without a rule file,
|
|
78
|
+
Claude Code still starts each task with `smart_recall`, because the server's instructions
|
|
79
|
+
ask for it. Gemini CLI also passes them on. Some editors do not (Cline, Continue and Zed,
|
|
80
|
+
for example); there, the rule file from `autopilot` is what makes your AI use its memory.
|
|
74
81
|
|
|
75
82
|
> **Already inside Claude, Cursor or Copilot?** Paste this to your AI:
|
|
76
83
|
> ```
|
package/dist/src/abstention.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{CKG_BELEG_SCHWELLE as
|
|
2
|
-
`)}const
|
|
1
|
+
import{CKG_BELEG_SCHWELLE as d,SINN_BELEG_SCHWELLE as f,WORT_BELEG_SCHWELLE as l}from"./rangfolge-stellschrauben.js";const s=e=>typeof e=="number"&&Number.isFinite(e)?e:0;function g(e,t={}){return s(e.wortBelege)>=(t.woerter??l)||s(e.semScore)>=(t.naehe??f)||s(e.ckgScore)>=(t.kante??d)}function E(e,t={}){let o=0,n=0,r=!1,a=0;for(const i of e){const c=s(i.wortBelege),h=s(i.semScore);c>o&&(o=c),h>n&&(n=h),g(i,t)&&(r=!0,a++)}return{schweigen:e.length===0||!r,besteWortBelege:o,besteNaehe:n,geprueft:e.length,belegte:a}}const u="No matches found";function w(e,t={}){if(e.geprueft===0)return`\u{1F50D} **${u}** \u2014 there is no lesson for this question yet.`;const o=t.woerter??l,n=t.naehe??f;return[`\u{1F50D} **${u}.**`,"",`${e.geprueft} candidates checked, none confirmed \u2014 the best contained ${e.besteWortBelege} of the searched words (needed: ${o}), highest semantic similarity ${e.besteNaehe.toFixed(2)} (needed: ${n.toFixed(2)}).`,"They are deliberately NOT shown: a weak match looks like a strong one, and the difference matters.","",'_If the answer should be in the Brain anyway, ask with other words \u2014 or use `recall_best_solution(topic="\u2026")` if you know the topic._'].join(`
|
|
2
|
+
`)}const b=5;function N(e){const t=e.filter(r=>Number.isFinite(r)&&r>=0);if(t.length===0)return null;const o=Math.min(...t),n=Math.max(...t);return o<b?null:t.length===1?`The backed match has not been confirmed for ${n} days.`:o===n?`The backed matches have not been confirmed for ${n} days.`:`The backed matches have not been confirmed for ${o}\u2013${n} days.`}export{b as ALTER_NENNEN_AB_TAGEN,u as SCHWEIGEN_MARKE,w as abstentionSatz,N as alterssatzFuerBelegte,E as beurteileTreffer,g as istBelegt};
|
package/dist/src/autor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execFileSync as c}from"node:child_process";const
|
|
1
|
+
import{execFileSync as c}from"node:child_process";const m=e=>t=>{try{return t.startsWith("-")?"":c("git",["config",t],{cwd:e,encoding:"utf-8",stdio:"pipe",timeout:1500,windowsHide:!0}).trim()}catch{return""}};function r(e){const t=(e??"").trim();return t?(t.split(/[\s.]+/)[0]??"").toLowerCase().replace(/[^a-z0-9_-]/g,"").slice(0,32):""}const a=new Set(["-","anonym","anonymous","none","kein","off"]);function g(e){const t=(e.uebergeben??"").trim().toLowerCase();if(a.has(t))return{autor:"",quelle:"anonym"};const n=(e.umgebung??"").trim().toLowerCase();if(a.has(n))return{autor:"",quelle:"anonym"};const o=r(e.uebergeben??"");if(o)return{autor:o,quelle:"uebergeben"};const u=r(e.umgebung??"");if(u)return{autor:u,quelle:"umgebung"};const i=r(e.git("user.name"));if(i)return{autor:i,quelle:"git-name"};const l=e.git("user.email"),s=r((l??"").split("@")[0]??"");return s?{autor:s,quelle:"git-mail"}:{autor:"",quelle:"unbekannt"}}const h="coauthor";function b(e){const t=(e??"").trim().toLowerCase();return!t||t==="off"||t==="false"||t==="0"||t==="none"?"":r(t)}function p(e,t){return e?!t||t===e?e:`${e}+${t}`:""}function d(e){return(e??"").split("+")[0]??""}function w(e){return e.autor||e.quelle==="anonym"?null:'\u{1F464} **No author found** \u2014 neither `author`, nor `CACHLY_AUTHOR`, nor `git config user.name`. Without an author this lesson does not count as team knowledge: `brain_who_knows` finds nobody and reuse across people stays uncounted. A `git config user.name "Your Name"` in the project is enough for all future lessons.'}export{h as COAUTHOR_PREF_KEY,w as autorHinweis,b as coautorAus,m as echterGitLeser,g as ermittleAutor,p as mitCoautor,r as normalisiere,d as nurMensch};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{kosinus as x}from"./bedeutung.js";import{DOPPEL_SCHWELLE as
|
|
1
|
+
import{kosinus as x}from"./bedeutung.js";import{DOPPEL_SCHWELLE as _}from"./rangfolge-stellschrauben.js";const f="cachly:doppel:kandidaten",k=40,y=14,D=30,L=90*86400,T=1500,O=6,E=864e5,d=t=>typeof t.what_worked=="string"?t.what_worked.trim().length:0;function g(t,e,n,o=_){return t.topic===e.topic||!(n>=o)||d(t)<k||d(e)<k?!1:!(t.ersetzt===e.topic||t.ersetzt_durch===e.topic||e.ersetzt===t.topic||e.ersetzt_durch===t.topic)}function A(t,e){let n=null;for(const o of e)g(t,o.lektion,o.naehe)&&(!n||o.naehe>n.naehe)&&(n={topic:o.lektion.topic,naehe:o.naehe});return n}function m(t){if(!t)return null;try{const e=JSON.parse(t);return e&&typeof e=="object"?e:null}catch{return null}}const P=t=>Math.round(t*1e3)/1e3;async function z(t,e,n,o,i=new Date){try{await o.aktualisiere(t);const r=o.aehnlichste(n,O+1).filter(s=>s.topic!==e.topic&&s.naehe>=_);let a=null;if(r.length>0){const s=await t.mget(...r.map(h=>`cachly:lesson:best:${h.topic}`)),u=r.flatMap((h,S)=>{const w=m(s[S]);return w?[{lektion:{...w,topic:h.topic},naehe:h.naehe}]:[]});a=A(e,u)}const p=await t.hgetall(f),c=Object.entries(p).filter(([s,u])=>s===e.topic||i.getTime()-Date.parse(String(m(u)?.am??""))>D*E||!m(u)).map(([s])=>s);if(c.length>0&&await t.hdel(f,...c),!a)return null;const l={neu:e.topic,alt:a.topic,naehe:P(a.naehe),am:i.toISOString()};return await t.hset(f,e.topic,JSON.stringify({alt:l.alt,naehe:l.naehe,am:l.am})),await t.expire(f,L),l}catch{return null}}async function I(t,e=T){let n;const o=new Promise(i=>{n=setTimeout(()=>i(null),e),n.unref?.()});try{return await Promise.race([t,o])}finally{n&&clearTimeout(n)}}function M(t,e=""){return!t||e.includes(`\`${t.alt}\``)?"":`\u267B\uFE0F Says almost the same as \`${t.alt}\` (similarity ${t.naehe.toFixed(2)}). If this is the newer version: write the same lesson again with \`ersetzt="${t.alt}"\` and \`grund\`. If it is a separate matter: nothing to do.`}async function H(t,e,n=new Date){try{const o=await t.hgetall(f),i=new Map(e.map(a=>[a.topic,a])),r=[];for(const[a,p]of Object.entries(o)){const c=m(p);if(!c||typeof c.alt!="string")continue;const l=String(c.am??"");if(!(n.getTime()-Date.parse(l)<=y*E))continue;const s=i.get(a),u=i.get(c.alt),h=Number(c.naehe);!s||!u||!g(s,u,h)||r.push({neu:a,alt:c.alt,naehe:h,am:l})}return r.sort((a,p)=>p.naehe-a.naehe)}catch{return[]}}function $(t){const e=[];for(let n=0;n<t.length;n++)for(let o=n+1;o<t.length;o++){const i=t[n],r=t[o],a=x(i.vektor,r.vektor);if(!g(i.lektion,r.lektion,a))continue;const p=String(i.lektion.ts??"")>=String(r.lektion.ts??""),[c,l]=p?[i.lektion,r.lektion]:[r.lektion,i.lektion];e.push({neu:c.topic,alt:l.topic,naehe:P(a)})}return e.sort((n,o)=>o.naehe-n.naehe)}export{y as DOPPEL_BRIEFING_TAGE,D as DOPPEL_HALTEN_TAGE,k as DOPPEL_MINDEST_TEXT,f as DOPPEL_SCHLUESSEL,L as DOPPEL_TTL_S,T as DOPPEL_WARTE_MS,M as doppelHinweis,$ as doppelPaare,H as leseDoppelKandidaten,I as mitFrist,z as pruefeDoppelung,A as waehleDoppelKandidat,g as zaehltAlsDoppelung};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const t=[/(?:bewusst|ausdruecklich|explizit)?\s*(?:haben wir uns|wir haben uns|ich habe mich|hat sich)?\s*entschieden gegen\s+([^,.;—\n]{3,80})(?:\s*[,—]\s*(?:weil|da|grund:?)\s+([^.;\n]{3,200}))?/i,/(?:bewusst|ausdruecklich|explizit)\s+gegen\s+([^,.;—\n]{3,80}?)\s+entschieden(?:\s*[,—]\s*(?:weil|da|grund:?)\s+([^.;\n]{3,200}))?/i,/decided against\s+(.{3,80}?)\s+because\s+([^.;\n]{3,200})/i,/decided against\s+([^,.;\n]{3,80})/i];function
|
|
1
|
+
const t=[/(?:bewusst|ausdruecklich|explizit)?\s*(?:haben wir uns|wir haben uns|ich habe mich|hat sich)?\s*entschieden gegen\s+([^,.;—\n]{3,80})(?:\s*[,—]\s*(?:weil|da|grund:?)\s+([^.;\n]{3,200}))?/i,/(?:bewusst|ausdruecklich|explizit)\s+gegen\s+([^,.;—\n]{3,80}?)\s+entschieden(?:\s*[,—]\s*(?:weil|da|grund:?)\s+([^.;\n]{3,200}))?/i,/decided against\s+(.{3,80}?)\s+because\s+([^.;\n]{3,200})/i,/decided against\s+([^,.;\n]{3,80})/i];function c(e){for(const i of t){const n=i.exec(e);if(!n)continue;const s=n[1].trim().replace(/\s+/g," ");if(!/^\d|^(mittag|abend|morgen|ende|anfang)\b/i.test(s))return{gegen:s,grund:n[2]?n[2].trim().replace(/\s+/g," "):null}}return null}function r(e){return`\u2696\uFE0F **Deliberately decided AGAINST ${e.gegen}**${e.grund?` \u2014 reason: ${e.grund}`:""}. Do not soften this without a NEW reason.`}export{r as entscheidungsZeile,c as leiteEntscheidungAb};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{inhaltsWoerter as
|
|
1
|
+
import{inhaltsWoerter as f,grobStamm as h}from"./rangfolge.js";const u=/\b(nicht mehr|doch nicht|stattdessen|statt dessen|in wahrheit|widerlegt|war falsch|stimmt nicht|korrektur|korrigiert|entgegen|no longer|instead|actually|turned out|wrong|superseded)\b/i;function l(e){return new Set([...f(e)].map(h))}function d(e,n){if(e.size===0||n.size===0)return 0;let i=0;for(const r of e)n.has(r)&&i++;return i/(e.size+n.size-i)}function g(e,n){const i=l(e.replace(/[:\-_/.]+/g," ")),r=l(n.replace(/[:\-_/.]+/g," "));if(i.size===0||r.size===0)return 0;let s=0;for(const t of i)r.has(t)&&s++;return s/Math.min(i.size,r.size)}function m(e,n,i){const r=n.match(u);if(!r)return null;const s=l(n);let t=null;for(const o of i){if(o.topic===e)continue;const c=g(e,o.topic),a=d(s,l(o.what_worked??""));c>=.5?(!t||c>t.wert)&&(t={topic:o.topic,grund:`topic similarity ${(100*c).toFixed(0)} %`,wert:c}):a>=.3&&(!t||a>t.wert)&&(t={topic:o.topic,grund:`text overlap ${(100*a).toFixed(0)} %`,wert:a})}return t?`\u{1F501} This sounds like a correction of \`${t.topic}\` ("${r[0]}" + ${t.grund}). If so: write the same lesson again with \`ersetzt="${t.topic}"\` \u2014 then recall hides the old version instead of still serving it as current. If not: nothing to do.`:null}export{m as schlageErsetzungVor,g as themenNaehe};
|
|
@@ -3,7 +3,7 @@ import{ckgSlug as j}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}fr
|
|
|
3
3
|
`)}case"causal_trace":{const{instance_id:l,problem:g,max_depth:$=5,tags:m=[]}=S,w=await W(l,L,`\u{1F50D} **Causal Trace: "${g}"**
|
|
4
4
|
|
|
5
5
|
No matching lessons found in brain.`);if(w)return w;const d=await M(l),u=g.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(o=>o.length>2),_={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},c=[];try{for(const o of u.slice(0,4)){const a=await d.smembers(`cachly:ckg:idx:from:${j(o)}`),r=await d.smembers(`cachly:ckg:idx:to:${j(o)}`),p=[],n=d.scanStream({match:`cachly:ckg:node:*${o}*`,count:50});await new Promise((e,s)=>{n.on("data",i=>p.push(...i)),n.on("end",e),n.on("error",s)});for(const e of p.slice(0,10)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.smembers(`cachly:ckg:idx:from:${i.id}`);for(const T of D.slice(0,20)){const R=await d.get(T);if(!R)continue;const C=x(R,null);if(!C||C.edgeType!=="fixes"&&C.edgeType!=="requires")continue;const I=await d.get(`cachly:lesson:best:${C.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),E=I?x(I,null)??void 0:void 0;c.push({conceptId:i.id,edge:C,lesson:E&&B(E)?E:void 0})}}for(const e of[...a,...r].slice(0,20)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.get(`cachly:lesson:best:${i.from}`),T=D?x(D,null)??void 0:void 0;c.push({conceptId:i.from,edge:i,lesson:T&&B(T)?T:void 0})}}}catch{}const y=new Set,f=c.filter(o=>{const a=`${o.edge.from}:${o.edge.edgeType}:${o.edge.to}`;return y.has(a)?!1:(y.add(a),!0)}).sort((o,a)=>a.edge.confidence-o.edge.confidence).slice(0,$);let k=0;const b=[];do{const[o,a]=await d.scan(k,"MATCH","cachly:lesson:best:*","COUNT",200);k=parseInt(o),b.push(...a)}while(k!==0);const h=[];for(const o of b){const a=await d.get(o);if(a){const r=x(a,null);if(!r||!B(r)||m.length>0&&!(r.tags??[]).some(e=>m.includes(e)))continue;const p=[r.topic,r.what_failed??"",r.what_worked??"",r.context??""].join(" ").toLowerCase(),n=u.reduce((e,s)=>e+(p.includes(s)?1:0),0);n>0&&h.push({score:n,lesson:r,key:o})}}h.sort((o,a)=>a.score-o.score);const v=h.slice(0,$);if(v.length===0&&f.length===0)return[`\u{1F50D} **Causal Trace: "${g}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${l}",`,` topic = "fix:${u[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${g}",`,")","```"].join(`
|
|
6
|
-
`);const t=[`\u{1F50D} **Causal Trace: "${g}"**`,""];if(f.length>0){t.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const o of f){const a=Math.round(o.edge.confidence*100),r="\u2593".repeat(Math.round(a/10))+"\u2591".repeat(10-Math.round(a/10));t.push(` ${o.edge.from} **\u2192[${o.edge.edgeType}]\u2192** ${o.edge.to}`),t.push(` ${r} ${a}% confidence (${o.edge.successes}/${o.edge.trials} confirmed)`),o.lesson?.what_worked&&t.push(` \u2705 Fix: ${o.lesson.what_worked.slice(0,150)}`),t.push("")}}if(v.length>0){t.push(f.length>0?`### \u{1F4DA} Text Search (${v.length} related lessons)`:`Found **${v.length}** related lessons. Reconstructed causal chain:`,"");const o=v.filter(p=>p.lesson.outcome!=="success"),a=v.filter(p=>p.lesson.outcome==="success");o.length>0&&(t.push("**Root causes & failure chain:**"),o.forEach((p,n)=>{const e=p.lesson,s=_[e.severity??"minor"]??"\u{1F7E1}";t.push(`${n===0?" Root:":" \u2192 :"} ${s} \`${e.topic}\``),e.what_failed&&t.push(` \u21B3 ${e.what_failed.slice(0,120)}`)}),t.push("")),a.length>0&&(t.push("**Solutions that worked before:**"),a.forEach((p,n)=>{const e=p.lesson,s=new Date(e.ts).toLocaleDateString("de-DE");t.push(` ${n+1}. \u2705 \`${e.topic}\` \u2014 ${s} \xB7
|
|
6
|
+
`);const t=[`\u{1F50D} **Causal Trace: "${g}"**`,""];if(f.length>0){t.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const o of f){const a=Math.round(o.edge.confidence*100),r="\u2593".repeat(Math.round(a/10))+"\u2591".repeat(10-Math.round(a/10));t.push(` ${o.edge.from} **\u2192[${o.edge.edgeType}]\u2192** ${o.edge.to}`),t.push(` ${r} ${a}% confidence (${o.edge.successes}/${o.edge.trials} confirmed)`),o.lesson?.what_worked&&t.push(` \u2705 Fix: ${o.lesson.what_worked.slice(0,150)}`),t.push("")}}if(v.length>0){t.push(f.length>0?`### \u{1F4DA} Text Search (${v.length} related lessons)`:`Found **${v.length}** related lessons. Reconstructed causal chain:`,"");const o=v.filter(p=>p.lesson.outcome!=="success"),a=v.filter(p=>p.lesson.outcome==="success");o.length>0&&(t.push("**Root causes & failure chain:**"),o.forEach((p,n)=>{const e=p.lesson,s=_[e.severity??"minor"]??"\u{1F7E1}";t.push(`${n===0?" Root:":" \u2192 :"} ${s} \`${e.topic}\``),e.what_failed&&t.push(` \u21B3 ${e.what_failed.slice(0,120)}`)}),t.push("")),a.length>0&&(t.push("**Solutions that worked before:**"),a.forEach((p,n)=>{const e=p.lesson,s=new Date(e.ts).toLocaleDateString("de-DE");t.push(` ${n+1}. \u2705 \`${e.topic}\` \u2014 ${s} \xB7 in ${e.recall_count??0} answers`),e.what_worked&&t.push(` ${e.what_worked.slice(0,200)}`)}),t.push(""));const r=a[0]?.lesson;if(r?.what_worked){t.push("**\u26A1 Most likely fix:**"),t.push("```"),t.push(r.what_worked.slice(0,500)),t.push("```"),t.push("");const p=F(r)?P(r,"trace"):0;p>0&&d.incrbyfloat(`cachly:stats:time_saved_mins:${l}`,p).catch(()=>{})}}return t.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${u[0]??"issue"}", outcome="success", ...)\``),f.length>0&&t.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${u[0]??"fix"}")\``),t.join(`
|
|
7
7
|
`)}case"knowledge_decay":{let f=function(t){const o=Math.round(t/10);return"\u2588".repeat(o)+"\u2591".repeat(10-o)+` ${t}%`};const{instance_id:l,min_age_days:g=0,show_top:$=20}=S,m=await M(l),w=Date.now(),d=g*864e5;let u=0;const _=[];do{const[t,o]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(t),_.push(...o)}while(u!==0);const c=[];for(const t of _){const o=await m.get(t);if(o){const a=x(o,null);if(!a)continue;const r=w-new Date(a.ts).getTime();if(r<d)continue;const p=Math.floor(r/864e5),n=a.recall_count??0,e=Math.max(0,p-7),s=Math.max(5,100-e),i=Math.min(50,n*5),D=a.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,s+i+D));c.push({topic:a.topic,confidence:T,age_days:p,recalls:n,outcome:a.outcome})}}c.sort((t,o)=>t.confidence-o.confidence);const y=c.slice(0,$),k=c.length>0?Math.round(c.reduce((t,o)=>t+o.confidence,0)/c.length):0,b=c.filter(t=>t.confidence<30).length,h=c.filter(t=>t.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${c.length} lessons`,"",`Average confidence: **${f(k)}**`,`\u{1F534} Critical (<30%): ${b} \u{1F7E2} Healthy (\u226570%): ${h}`,"","Lowest confidence lessons (fix these first):","",...y.map((t,o)=>`${(o+1).toString().padStart(2)}. \`${t.topic}\`
|
|
8
8
|
${f(t.confidence)} \xB7 ${t.age_days}d old \xB7 ${t.recalls} recalls \xB7 ${t.outcome}`),"",c.length>$?`\u2026 and ${c.length-$} more lessons`:"","",b>0?`\u26A0\uFE0F ${b} lessons are critically stale. Validate them and re-run \`learn_from_attempts\` with updated findings.`:"\u2705 Brain confidence is healthy overall.","","\u{1F4A1} Run `memory_consolidate` to prune stale entries \xB7 `causal_trace` to find root causes."].filter(t=>t!=="").join(`
|
|
9
9
|
`)}case"autopilot":{const{instance_id:l,editor:g="claude",project_name:$="this project",style:m="full"}=S,w=z({editor:String(g),project_name:String($)},"die Anweisungsdatei (CLAUDE.md)");if(!w.ok)return w.meldung;const d=(b,h)=>b.replace(/[\p{C}\s]+/gu," ").trim().slice(0,h),u=d(w.felder.editor,30)||"claude",_=d(w.felder.project_name,80)||"this project",c=`## Cachly AI Brain \u2014 Autopilot
|