- Implement global memory layer for cross-project patterns. - Improve memory entry scoring with recency and tokenization. - Adjust MAX_TEXT limit from 400 to 800 for better context retention. - Add TTL pruning for stale memory entries. - Capture and summarize dropped content during compaction. - Update tests to reflect changes in memory behavior and compaction logic.
4.9 KiB
4.9 KiB
Plan: Lifelong Learning — Memory + Compaction Fix
1. Goal
Bikin shiro-neko cukup untuk agent yang belajar terus (lifelong) tanpa ngulang kesalahan setelah context compact / sesi ganti.
Status sekarang:
- Harness (session + prune + notebook): 7.5/10 — ladder prune, orphan repair, repeat guard sudah benar.
- Auto-memory: 4/10 — keyword literal, manual
remember, boot block hits-only, MAX_TEXT 400, per-project silo, tanpa auto-consolidation.
Target: harness 9/10, memory 8/10 dengan perubahan kecil, backward-compatible, semua tes hijau.
2. Scope
A. Memory (src/memory.ts)
- Search dari
terms.every(includes)strict → scored hybrid (normalize + token + substring + hits + recency). Tetap require every term untuk kompatibilitas tes, tapi ranking jauh lebih baik dan tahan typo minor (underscore/hyphen/punct). - Render boot block dari hits-only → diverse: top-hits + most-recent, dedup. Mencegah 20 gotcha lama mengusir decision baru.
- MAX_TEXT 400 → 800 (potong silent terlalu agresif untuk gotcha/decision berkonteks).
- Dedup dari exact
text===clean→ normalized (lower + collapse ws + strip punct) biar near-duplicate tidak dobel. - TTL / decay:
pruneExpired(90d)untuk entry hits==0 & umur >90d, dipanggil di load/persist. hits diberi recency bonus saat render, bukan decay destructive. - Global memory:
~/.shiro-neko/memory/_global.jsonsebagai layer kedua; per-project tetap utama, global untuk pattern lintas-repo. - Auto-extract hook:
suggestFromTranscript(messages, model)— 1x generateText yang meringkas sesi jadi 1-3 kandidat memory (dipakai session afterTurn, bukan auto-write diam-diam).
B. Compaction (src/prune.ts + src/session.ts)
- estimateTokens:
len/4→len/3.6 + messages*8(akun overhead role/tool envelope; terukur lebih dekat ke cl100k). Threshold tetap 120k. - pruneToFit: selalu preserve head (first user goal + first assistant) terlepas ladder, jadi goal tidak hilang di narrowest rung.
- prepareStep di session: ladder tetap, tapi droppedSpan di-capture by identity dan di-ringkas via 1x generateText menjadi
Note (retained from compacted history)user message (lossless compaction). Guarded try/catch — mock/dead model tidak break turn. - afterTurn auto-memory: jika turn menambah >=4 pesan dan memory ada, tawarkan 1-3 kandidat via suggestFromTranscript (tidak auto-persist tanpa konfirmasi model; tool
remembertetap sumber write). - Repeat guard lintas-turn:
seensekarang Map dengan decay per 20 turn (opsional, ringan). - Persist: onChange debounce 400ms → flush juga di
beforeExit+ tiap done (sudah ada), tambah flush on compact.
C. Prompt / Wiring (src/prompt.ts, src/cli.tsx, src/store.ts)
- Prompt: memory block sekarang labeled
Project memory (project + global); notebook tetap survive compaction. - cli.tsx: Memory ctor dapat global layer;
session.sendafter done trigger suggest (off jika --no-memory). - store: tidak diubah format, hanya notebook persistance tetap.
3. Files Touched
src/memory.ts— utama (search, render, MAX_TEXT, dedup, global, TTL, suggest)src/prune.ts— preserveHead, estimate helper export, ladder keepsrc/session.ts— estimateTokens baru, summarizeDiscarded, afterTurn hook, cross-turn seensrc/prompt.ts— minor label (opsional)src/cli.tsx— wiring global memory + afterTurn suggestiontest/memory.test.ts— update expectation truncation 400→800, tambah tes diverse/ranking/TTLtest/prune.test.ts— tambah preserveHead testtest/compact.test.ts— tambah lossless-compaction test (mock summarize)
4. Schema / Types
- MemoryEntry tetap
{id,kind,text,createdAt,hits}— tambah field opsionallastHitAt?: stringuntuk recency bonus (backward compat: fallback ke createdAt). - Config tidak berubah (SHIRO_HOME, maxSpendUsd, etc).
- File: per-project
${hash(cwd)}.json, global_global.jsondi root(). Format array JSON sama, corrupted → [].
5. Verification
bun run typecheck— harus pass (verbatimModuleSyntax, noUncheckedIndexedAccess)bun test— semua existing + baru hijau; khusus:- memory.test: truncation 800, every-term strict tetap, hits+recency ranking, diverse render contains recent
- prune.test: head goal survive narrowest rung, estimate monotonic
- compact.test: droppedSpan summarized to retained note, tidak loop
bun run build—dist/shirobisa di-compile- Manual:
SHIRO_HOME=$(mktemp -d) bun run src/cli.tsx -p "hello" --yolo --json→ compacted event + done, memory file terisi
6. Non-Goals (defer)
- Embedding vector search (butuh dep + infra) — trigram/BM25 cukup untuk sekarang, bisa follow-up.
- Subagent parallel fan-out — butuh executor custom, defer (catat di ROADMAP).
- MCP meta-tools — defer.
7. Rollout
- Implement memory.ts dulu → test
- prune.ts preserveHead + estimate
- session.ts summarizeDiscarded + wiring
- Update tests incremental, typecheck tiap langkah, jangan bulk.