Skip to content

fix(tools): MemoryReviewer --dry-run builds the prompts and stops - #2109

Open
pai-scaffolde wants to merge 1 commit into
danielmiessler:mainfrom
pai-scaffolde:fix/i-reviewer-dry-run-no-inference
Open

fix(tools): MemoryReviewer --dry-run builds the prompts and stops#2109
pai-scaffolde wants to merge 1 commit into
danielmiessler:mainfrom
pai-scaffolde:fix/i-reviewer-dry-run-no-inference

Conversation

@pai-scaffolde

Copy link
Copy Markdown

Reproduced on a fresh LifeOS 7.40.4 install (macOS, Claude Code in the Claude desktop app); the fix was applied to that install and run there before filing. Fixes #2073 (the shape suggested there is the one taken).

Observed

bun LIFEOS/TOOLS/MemoryReviewer.ts review --dry-run called the model, created MEMORY/OBSERVABILITY/reviewer-runs/<runId>/ and appended a row to reviewer-runs.jsonl, while the file's own header (line 28) promises "extract + prompt, no inference".

Root cause

review() threads dryRun into exactly one place, dispatchItems(). Everything upstream of that — writeRunDebug(), inference() (twice on a parse retry), logRunSummary() — runs unconditionally. Those two artifacts are what CortexHealth.reviewerEvidence() grades: a run directory newer than the latest ledger row is treated as an orphaned run and, past the grace window, reported timed-out; every dry run also inflates the reviewer denominators MemoryFixesCheck/MemoryInsights/MemoryStatus read.

Fix (behavior, so the header becomes true)

review() returns right after the prompts are built when dryRun is set: no inference, no run directory, no ledger row. The result carries dry_run: true and prompt_chars (system/user sizes) alongside transcript and exchanges, so the operator sees what would have been sent. dispatchItems() keeps its own dryRun option (the smoke test uses it); review() no longer passes it since a dry run never reaches dispatch. The header line is unchanged because it now describes the code.

How tested

bun MemoryReviewer.ts test (the tool's existing self-test), run under a temp HOME with the USER/MEMORY symlink layout, gains five checks: dry run returns ok with dry_run, inference_duration_ms === 0 and no dispatch_summary, run-dir count unchanged, ledger row count unchanged, prompt sizes reported.

upstream file + the new checks (negative control):  dry-run: no run directory written — 1 → 2 ✗ ; no ledger row written — 1 → 2 ✗
patched:                                              all five dry-run checks ✓

The remaining self-test checks are unchanged before and after. Transpiles. On the live install: review --dry-run leaves the run-dir and ledger counts unchanged, and Cortex health reports ok.

🤖 Generated with Claude Code

The header documents `review --dry-run` as "extract + prompt, no
inference", but the flag only reached dispatchItems(): review() still
called the model (twice on a parse retry), created a
MEMORY/OBSERVABILITY/reviewer-runs/<runId>/ directory and appended a row
to reviewer-runs.jsonl. CortexHealth reads both artifacts as evidence of
a real run — a run directory newer than the latest ledger row grades as
"timed-out" — so the command meant to be safe could move memory health
and inflate every reviewer denominator.

Return right after the prompts are built: no inference, no run
directory, no ledger row. The result carries dry_run:true and the
prompt sizes so the operator sees what would have been sent. dispatchItems
keeps its own dryRun option (used by the smoke test); review() no longer
passes it since that path is never reached on a dry run. The smoke test
now asserts a dry run leaves run-dir and ledger counts unchanged.

Public issue danielmiessler#2073.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MemoryReviewer --dry-run calls the model and writes to the health ledger, while its own header promises "no inference"

1 participant