Todo Fase 6 final: hapus flake.lock (artefak era Rust/Nix, tidak ada flake.nix
lagi, deploy.yml sudah bun build --compile + scp binary). Verifikasi wire-shape
lama selesai: settings.json (api_keys/provider/model/review_*) diload true di
headless + TUI real agent. Gate: tsc 0 error, bun test 70 pass, TUI render.
review_enabled (default TRUE) selama ini no-op: tampil di TUI settings
overlay ("Review: true"), bisa di-toggle via command, TAPI spawn_background_review
tidak pernah dipanggil & Origin::Reviewer tidak pernah dikonstruksi. User
melihat "Review: true" padahal auto-review setelah edit tak pernah jalan.
Sekarang feature yang sudah dibangun penuh (subagent/auto/engine.rs: git diff
-> LLM review -> auto-fix HIGH/MEDIUM) di-wire:
- daemon/handler.rs: trigger setelah run_turn bila review_enabled; capture
flag+creds SEBELUM api_key/provider_cfg di-move ke LlmClient.
- tui/turn.rs: sama, gated by state.settings.flags.review_enabled.
- ws/lib.rs: channel minimal tanpa settings -> review nyala tiap prompt
(konsisten dgn default ON).
Aman: review fire-and-forget (tokio::spawn), get_git_diff skip bila no-change,
no-op bila bukan git repo (auto/engine). Creds dipakai = creds ter-resolve yg
sama dgn komposisi turn.
Verifikasi: check/clippy/fmt/test workspace hijau (0 error/warning/fail).
Sebelumnya SemanticSearch/ListSymbols/RebuildIndex menahan SYMBOL_INDEX
Mutex selama full `rebuild` (walk seluruh workspace, bisa detikan) +
selama search. Di main loop yang menjalankan read-only tools paralel,
semantic_search/list_symbols lain jadi BLOCK selama rebuild.
Refactor:
- Global berubah Mutex<Option<SymbolIndex>> -> OnceLock<Mutex<HashMap<
workspace, SymbolIndex>>> — index per-workspace, jadi pencarian workspace B
tidak mungkin bocor simbol stale dari A (workspace-awareness kini struktural,
bukan hanya via needs_rebuild).
- ensure_symbol_index(workspace, force): rebuild dijalankan DI LUAR lock
(mutex hanya dicek/insert/lookup singkat), lalu hasilnya di-swap-in di bawah
short lock. Search/list/rebuild-report tak lagi memblock thread lain selama
walk I/O. Per-workspace key menghilangkan race lintas-workspace dari skema
swap tunggal.
- Test +1 (test_ensure_symbol_index_per_workspace_isolation): verifikasi dua
workspace punya index independen, rebuild A tidak menimpa B.
Verifikasi: check/clippy -D warnings/fmt clean; test infra 64 (0 gagal).
SymbolIndex global sudah melacak workspace_path tapi SemanticSearch dan
ListSymbols Cuma rebuild saat index kosong (is_empty). Akibat: setelah
mengindeks workspace A, mencari di workspace B diam-diam mengembalikan
simbol STALE dari A — menyesatkan coding agent (referensikan simbol yang
tidak ada di repo aktif).
Fix:
- Tambah SymbolIndex::needs_rebuild(workspace) — true bila index kosong
ATAU workspace diminta beda dari yang ter-cache.
- Pakai di 2 call site (SemanticSearch::run, ListSymbols::run) menggantikan
is_empty(), jadi pindah workspace otomatis trigger rebuild.
- test: +1 (test_needs_rebuild_workspace_aware — verifikasi flip workspace
memicu rebuild bolak-balik A -> B -> A).
Catatan (bukan bug, dilaporkan): mutex SYMBOL_INDEX masih dipegang selama
full rebuild di run() — bottleneck saat semantic_search dipanggil paralel;
perbaikan butuh restrukturisasi double-checked rebuild, tak diubah di sini.
Verifikasi: check/clippy -D warnings/fmt clean; test infra 63 (0 gagal).
synth_consensus selama ini Cuma concatenate output node lalu dilabeli
"Consensus" — tidak ada sintesis. Kini:
- Resolve kredensial LLM (provider/model/base_url/api_key) dari Store,
sumber yang sama dgn execute_cycle.
- Kirim prompt sintesis ke model: minta distilasi node outputs jadi satu
laporan konsensus berisi AGREEMENTS / CONFLICTS / KEY FINDINGS /
RECOMMENDATION.
- Graceful fallback ke summary concatenation bila panggilan LLM gagal /
output kosong, supaya sintesis konsensus tidak pernah merusak siklus
hive-mind (konsisten dgn filosofi isolated-errors utk node).
- Batasi output per-node (MAX_NODE_OUTPUT_CHARS=4000, char-safe via
truncate_chars) agar prompt tetap bounded.
- test: +2 (truncation char-safe pada output besar multi-byte; concat
summary memuat semua node id).
Verifikasi: cargo check/clippy -D warnings/fmt clean; test infra 62 (0
gagal). Disk root sudah di-cargo clean (free 43.7GB, turun 98% -> 63%).
Hasil audit round 4 (workflow/hive_mind + memory + semantic_search).
- fix(memory): recall.search selama ini TIDAK pernah dipakai — tool
mengiklankan keyword search di skema tapi run() cuma list semua nama.
Kini search benar-benar memfilter (cocok di name/description/content,
case-insensitive), + output 'No memories match' bila kosong.
- fix(memory): ToolCtxBuilder tidak punya setter memory_dir dan tak ada
call-site yang mengisinya — remember/recall/forget memakai PathBuf kosong
dan menulis memory ke CWD (bukan lokasi persisten). Tambah setter
memory_dir + worktrees_dir, dan helper resolve_memory_dir() yang fallback
ke Store::new().memory_dir bila ctx.memory_dir kosong; dipakai di ketiga
tool memory.
- refactor(workflow): hapus LlmClient dummy di WorkflowRun (dibuat dengan
API key kosong + model default + base_url default lalu tak pernah dipakai
— execute_workflow menerimanya sebagai _llm_client). Kini execute_workflow
tak ambil parameter tak terpakai; LLM asli tetap lewat execute_primitive
yang resolve kredensial dengan benar.
- test: +2 (recall search memfilter; resolve_memory_dir fallback/eksplisit).
Catatan audit yang dilaporkan (belum difix): synth_consensus hanya
menggabungkan output (label Consensus menyesatkan, bukan sintesis LLM), dan
semantic_search memegang Mutex index global saat full rebuild (bottleneck
saat paralel) + index tidak workspace-aware.
PENTING (infra): disk root 100% saat kerja. Saya bebaskan ~4.6G dari /tmp +
cache aman (sekai*, verify-z, bun/npm cache). target/debug di repo = 38G —
rampah, perlu cargo clean + rebuild (jangan dibiarkan).
Hasil audit alur AI agent round 3 (fokus correctness & latent crash).
- fix(subagent): engine.rs sebelumnya mengeksekusi tool lalu push
ChatMessage::tool hasil TANPA mendahuluinya dengan pesan assistant yang
mendeklarasikan tool_calls → history malformed ([..., tool, tool,
assistant(text)]). Kontrak OpenAI/Anthropic mensyaratkan pesan assistant
(berisi tool_calls) sebelum hasil tool. Kini push response_msg
(assistant + tool_calls + content) sebelum eksekusi, dan hapus push
assistant content-only di akhir (agar tidak duplikat). Loop utama sudah
benar; subagent kini selaras.
- fix(utils): &content[..1500] / &content[..1000] di build_rich_context
dan &diff[..5000] di auto/engine.rs bisa panic saat indeks byte jatuh di
tengah karakter multi-byte UTF-8 (emoji/CJK/panah). Tambah helper
truncate_chars() yang memotong per karakter (char-safe) dan pakai di
3 titik tersebut.
- test: +4 unit test truncate_chars (ASCII, potong, multibyte no-panic,
emoji).
Catatan audit: subagent/auto (auto-review) & build_rich_context adalah dead
code (spawn_background_review & build_rich_context tidak pernah dipanggil).
Auto-review jangan diaktifkan asal (parser format teks rapuh + tanpa
verifikasi pasca-fix) — dilaporkan, bukan dicolokkan.