Memory Audit Diagnostics via DEBUG Log Stream - #12767
Conversation
Code Review SummaryStatus: 3 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (1 file changed since last review)
Resolved since the last review: the digest parse-error append (line 305) now routes the raw completion through Fix these issues in Kilo Cloud Previous Review Summary (commit 2d64473)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 2d64473)Status: 4 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (6 files)
Notes: the Reviewed by claude-opus-5 · Input: 30 · Output: 4.3K · Cached: 613.3K Review guidance: REVIEW.md from base branch |
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Issue
Fixes # — (no reported issue; related to #12674, #12675 and #12748)
Context
Memory-capture diagnostics have been invisible on
mainsince28d015f8fe("fix(memory): refine CLI and extension experience" #12422 ) stubbedMemoryAudit.audit()into a no-op. The file-writing machinery it replaced was never called anywhere (record()had zero callers;readChanges/readDecisionsare re-exported but unused), so no audit.log was ever produced — parse failures were silent.Currently, when memory consolidation fails with JSON parse errors, there is no way to debug why the failure occurred. This makes it impossible to understand what model output triggered the failure or whether the schema needs adjustment.
Captured evidence of why this matters (DEBUG run, 2026-08-01): both digest and typed consolidation fell back with
Invalid JSON response statusCode=200. The provider returned a valid JSON completion, but the client received the same JSON with an SSEdata: [DONE]terminator appended (..."cost":"0"}data: [DONE]\n\n), which the non-streaming AI SDK path cannot parse →InvalidJSONResponseError→ memory capture falls back silently. The full response was never visible in the log because the error-path append briefs the reason to 160 chars (MemoryShared.brief), whilefull=is only attached on theparse_errorappends (seetmp/drafts/attachments/streaming-pr-followup-9router-evidence/9router-evidence-data-done-suffix.txtandtmp/drafts/attachments/streaming-pr-followup-9router-evidence/devlog-memory-error-2026-08-01.txt).This PR restores visibility by routing the diagnostics through the standard DEBUG log stream (consistent with how the rest of the CLI logs) instead of reviving the dead audit.log file mechanism.
Implementation
MemoryAudit.audit()— the single choke point every capture decision funnels through (append/decidecallers in capture/state/tool/operations/indexer) — now emitsMemoryLog.debug("memory audit", input)instead of a no-op. All call sites are unchanged.MemoryLog.debug/setDebugseam ineffect/log.ts(mirrors the existingwarn/setWarn), wired to the CLI logger inruntime.ts— so output lands in the standard rotatingdata/logstream, gated by the normal log level.memory.appendsites (digest + consolidate) now includefull=<raw model output>so the exact failing text is captured, not just the error brief.record(), the zodLogschema, andMemoryFsparsing. Nothing that was reachable was dropped.KILO_MEMORY_DEBUGenv gate and audit.log file concept — one gate, the standard log level.Attachments
devlog-memory-error-2026-08-01.txt
9router-evidence-data-done-suffix.txt
devlog-memory-after-fix-2026-08-01.txt
How to Test
Manual/local verification
bun testinpackages/kilo-memory: 169 pass (5 new routing tests inaudit.test.ts).bun run typecheckinpackages/kilo-memoryandpackages/opencode: clean.Reviewer test steps
data/log/dev.log): entriesmemory auditwithparse_error+full=<raw text>should appear.KILO_LOG_LEVEL=DEBUG(or--logLevel DEBUG) — nothing logged at default INFO.Blocked checks and substitute verification
Bottom line
Full model/9router responses (
full=) are logged at DEBUG — the most verbose tier and the dev default. To keep default runs minimal-noise while still allowing full-picture debugging of transport-level parse failures (e.g. thedata: [DONE]corruption above), a TRACE level below DEBUG would let us gate raw full-response emission behind an explicit opt-in. Proposal for a follow-up: addTRACEto the log level schema (core/src/util/log.tsLevel enum +levelPriority,opencode/src/kilocode/log.tsinit literal,index.tsCLI choices) and emitfull=payloads at TRACE instead of DEBUG. This PR intentionally keeps DEBUG parity and does not add the level.