fix: restore mempalace compress after stats rename (#159)#162
fix: restore mempalace compress after stats rename (#159)#162mvalentsev wants to merge 2 commits intoMemPalace:developfrom
Conversation
PR Review: fix: restore mempalace compress after stats rename (#159)Executive Summary
Affected Areas: Business Impact: Flow Changes: The summary section switches from char-based accumulation (re-estimating tokens at the end) to direct token-estimate accumulation. Output format and stored metadata are functionally identical. Ratings
PR Health
Key Changes Verified1. Stats Key Alignment (Correct)All old → new key mappings match what
2. Accumulator Simplification (Improvement)Before: Accumulated chars, then re-estimated tokens via After: Directly sums per-drawer token estimates. Avoids O(n) memory allocation for the summary string, and stays consistent with per-drawer output. 3. Stored Metadata (Correct)
4. Other Callers
Issues FoundNone. This is a clean, well-scoped bug fix. Created by Octocode MCP https://octocode.ai 🔍🐙 |
5212c4c to
eef9b6f
Compare
eef9b6f to
085423e
Compare
web3guru888
left a comment
There was a problem hiding this comment.
Review: fix: restore mempalace compress after stats rename (#159)
This is the most thorough of the three PRs fixing the cmd_compress KeyError regression introduced when #147 renamed Dialect.compression_stats() keys. Here's my analysis comparing all three approaches.
Background: Three PRs, One Bug
Three PRs address the same KeyError: 'compressed_chars' crash in cmd_compress:
- #162 (this PR, @mvalentsev) — comprehensive fix with token accumulator refactor
- #569 (@arnoldwender) — minimal key-swap only, adds a live
Dialectintegration test - #588 (@helhindi) — minimal key-swap only, updates test mocks only
All three correctly replace the four stale keys (compressed_chars → summary_chars, original_tokens → original_tokens_est, compressed_tokens → summary_tokens_est, ratio → size_ratio). The crash fix itself is identical in all three.
What #162 Does Better
Fixes a second, pre-existing bug. The summary line at the end of cmd_compress was accumulating total_original and total_compressed from character counts (original_chars, summary_chars), then passing those char totals to Dialect.count_tokens(\"x\" * total_original) to compute token estimates. But count_tokens is word-based — a long string of repeated x characters is one "word", so the summary always printed Total: 1t -> 1t (1.0x) regardless of actual workload. This is a genuine silent correctness bug that #569 and #588 both miss entirely.
The fix — renaming accumulators to total_orig_tokens / total_comp_tokens and summing original_tokens_est / summary_tokens_est from per-drawer stats — is semantically correct and self-consistent with the per-drawer output lines. This is the right approach.
Backward-compatible metadata keys. The PR is explicit that comp_meta["compression_ratio"] and comp_meta["original_tokens"] keep their old names even though the values now come from the renamed stats fields. This is a thoughtful choice — downstream consumers reading the mempalace_compressed collection won't break.
Issues and Suggestions
Missing test coverage — acknowledged by the author. The cmd_compress path has zero unit tests. #569 adds an integration test (test_compression_stats_keys_match_dialect) that calls the real Dialect class and asserts the key set. That test would immediately catch regressions like the one in #147. I'd strongly suggest cherry-picking or adapting that test for this PR, or filing a follow-up issue to track it. Shipping a fix without a regression guard leaves the door open for #147-style renames to slip through again.
Summary ratio computation. After the accumulator fix, the summary ratio is computed as total_orig_tokens / total_comp_tokens. This will ZeroDivisionError if total_comp_tokens is 0 (e.g., all drawers compressed to empty strings). Worth guarding: ratio = total_orig_tokens / total_comp_tokens if total_comp_tokens else 0.
Pre-existing test failures flagged — the author notes test_stats and test_count_tokens in test_dialect.py are already failing from #147 and are addressed in #150. Good disclosure; just confirming this PR doesn't touch those and won't make them worse.
Diff Quality
The cli.py changes are clean. The accumulator rename from total_original/total_compressed to total_orig_tokens/total_comp_tokens improves readability — it's now obvious what unit is being tracked. The f-string split across two lines is also fine for 88-char line limits.
Comparison Verdict
| Criterion | #162 (this PR) | #569 | #588 |
|---|---|---|---|
| Fixes KeyError crash | ✅ | ✅ | ✅ |
| Fixes broken summary totals | ✅ | ❌ | ❌ |
| Backward-compat metadata keys | ✅ explicit | ✅ implicit | ✅ implicit |
| Adds regression test | ❌ | ✅ integration test | ❌ |
| Test mock updates | ✅ | ✅ | ✅ |
Recommendation: Merge #162 and close #569 and #588 as superseded — but only after adding a regression guard for the zero-division edge case and ideally pulling in the integration test from #569. #162 is the only one that actually improves the correctness of the feature beyond just not crashing.
Overall
APPROVE with minor suggestions. The core fix is correct, the accumulator refactor is genuinely better, and the backward-compatibility note on metadata keys shows careful thinking. Add a guard for the zero-division edge case and a regression test before merge.
Reviewed by MemPalace-AGI — autonomous research system with perfect memory
|
Clean fix. All four stale key references are updated consistently ( The summary simplification is a nice bonus — the old code was converting token estimates back to a character count and then re-running On the One minor observation: LGTM otherwise. |
The honest-stats rename in PR MemPalace#147 changed the keys returned by Dialect.compression_stats() (ratio -> size_ratio, compressed_chars -> summary_chars, original_tokens / compressed_tokens -> original_tokens_est / summary_tokens_est). cmd_compress still reads the old names, so mempalace compress throws KeyError on the first drawer it touches and the feature is effectively dead. Also fix the summary line at the bottom of cmd_compress. It called count_tokens("x" * total_original), but count_tokens is word-based (max(1, int(len(text.split()) * 1.3))), and a string of repeated xs is a single "word", so both totals were always 1. Accumulate the per-drawer estimates during the main loop instead, and use a token-based ratio so the summary line is self-consistent with the per-drawer dry-run output. The storage metadata key names on the compressed collection (compression_ratio, original_tokens) stay the same for compatibility with anything already reading them. Only the source of the values is updated. Fixes MemPalace#159 (points 1 and 2)
The new test_cmd_compress_dry_run and test_cmd_compress_stores_results tests (added upstream after this branch diverged) mock compression_stats() with the old key names. Update the mocks to use the post-MemPalace#147 keys (original_tokens_est, summary_tokens_est, size_ratio, summary_chars) so they match what the fixed cmd_compress actually reads.
085423e to
9cc1bcf
Compare
|
The |
|
Closing -- #569 and #609 on develop together cover all three fixes this PR addressed: the stats key alignment, the backward-compat metadata key preservation, and the token summary bug. One minor note for anyone touching the compress path later: the merged #609 estimates summary tokens via |
What does this PR do?
Fixes points 1 and 2 from #159.
mempalace compresswas dead after #147 renamed theDialect.compression_stats()keys:ratiobecamesize_ratiocompressed_charsbecamesummary_charsoriginal_tokens/compressed_tokensbecameoriginal_tokens_est/summary_tokens_estcmd_compressstill read all four old names, so the first drawer it touched raisedKeyError: 'compressed_chars'and the whole command crashed before writing anything.While in there, the summary line at the bottom of
cmd_compresswas also wrong in a subtler way. It tried to turn the char totals into token totals by callingDialect.count_tokens("x" * total_original).count_tokensis word-based (max(1, int(len(text.split()) * 1.3))), and a long string of repeatedxs is a single "word", so both totals were always1and the user sawTotal: 1t -> 1t (1.0x compression)regardless of the actual workload. The fix accumulates the per-draweroriginal_tokens_est/summary_tokens_estduring the main loop and uses a token-based ratio so the summary is self-consistent with the per-drawer dry-run line.The storage metadata keys on the
mempalace_compressedcollection (compression_ratio,original_tokens) keep their old names so anything already reading them still works. Only the source of the values is updated.How to test
Checklist
ruff check .,ruff format --check .)pytest tests/test_miner.py tests/test_config.py tests/test_normalize.py tests/test_version_consistency.py -q- 21 passed)Notes on testing scope
There are no unit tests for
cmd_compresstoday and adding one would need a fake ChromaDB collection fixture that the repo does not have yet. The fix is verified end to end via the dry-run and real-compress walkthroughs above. Can follow up with a CLI test harness in a separate PR if useful.Unrelated:
tests/test_dialect.pyhas two pre-existing failing assertions from the same PR #147 rename (test_stats/test_count_tokens). Those are addressed in #150 and are not touched here to keep this PR focused.