Repository navigation
Conversation
…tion verdict With no adjudicator, an ambiguous-band atom was memoized and written to the disk cache as absent. The key names no oracle, so a later LLM run replayed it as a final cache verdict and never adjudicated. The placeholder is now neither memoized nor stored, and the cache version moves to v5 so old entries are not read. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues require changes before approval.
No open issues 🎉
What changed in this PR
0 new findings; nothing to fix.
This PR addresses the retention-cache issue in #687 by preventing lexical-only placeholder answers from being reused as final verdicts in later adjudicated runs.
Changes:
- Return ambiguous-band placeholders without memoizing or storing them.
- Bump the retention cache to v5 so older entries are not reused.
- Add regression coverage and document the cache behavior and upgrade impact.
| File | Description |
|---|---|
dokimi/tests/test_novelty_silent_defaults.py |
Adds a regression test for lexical-only followed by adjudicated runs. |
dokimi/dokimi/novelty/retention.py |
Skips caching placeholders and advances the cache version to v5. |
dokimi/docs/skill-novelty.md |
Explains v5 invalidation and legacy placeholder entries. |
dokimi/docs/skill-novelty-walkthrough.md |
Clarifies that ambiguous lexical-only answers are not cached. |
dokimi/changelog.d/20261113_120000_napetrov_fsm687-retention.md |
Records the fix and cache upgrade impact. |
Review effort: Balanced
|
✅ OpenCodeReview: Review complete: 0 finding(s) across 5 selected item(s). CI at Review details
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #692 +/- ##
=======================================
Coverage 95.71% 95.72%
=======================================
Files 415 415
Lines 55346 55349 +3
Branches 9514 9515 +1
=======================================
+ Hits 52977 52982 +5
+ Misses 1466 1465 -1
+ Partials 903 902 -1
🚀 New features to boost your workflow:
|
vlad-perevezentsev
left a comment
There was a problem hiding this comment.
Review at 061436a. The fix is right for the direction it targets: a --lexical-only band answer is no longer memoized or stored, and the v5 bump drops the old placeholders. The reverse direction (a lexical-only run reading stored LLM verdicts) and a test for the v4 entries are in the line comments.
What I ran, at 061436a:
make ci-local --offline: 18,932 passed, 0 failed, 72 skipped; all checks pass.- A repro: an adjudicated run stores
contradictedfor a band pair; a--lexical-onlyoracle on the same--cache-dirthen returnscontradicted(methodcache), andabsentwith an empty cache. With the one-line change in the line comment it returnsabsent, and the novelty tests (1,632) pass.
Checked, no issues
- Stats: the new branch still counts the decision and no escalation, so
escalation_ratestays 0 for a lexical-only run. - The full cache bump: a stored entry has no method, so a placeholder
absentcannot be told apart from an adjudicated one; dropping all v4 entries is the safe choice, and the docs say the first run pays again. - Docs and changelog: both pages and the
Fixedfragment match the code; the new test fails on the base (the lexical run writes a file there).
vchamarthi
left a comment
There was a problem hiding this comment.
Reviewed head 061436a. Nothing new to fix; 2 threads from vlad-perevezentsev are still open. Stops a --lexical-only run from storing its ambiguous-band placeholder and moves the cache to v5; on the head the new test and the v5 bump hold for the input they cover. Two open threads still stand: a lexical-only run still reads adjudicated cache entries, and no test pins the v5 bump.
Verified
- Placeholder not stored:
test_a_lexical_only_run_does_not_store_a_placeholder_for_a_later_llm_runpasses on the head and pins that a lexical-only ambiguous answer writes no cache file and a later adjudicated run asks the model. - Placeholder test on main: The same test fails on main, where the lexical-only run writes a cache file.
- Placeholder test strength: Storing the lexical-only placeholder in the memo and on disk makes the test fail on the assertion that the cache directory is empty.
- V4 entries on disk: A v4 entry holding
absentforalpha beta gamma delta/alpha beta epsilon zetais not read on the head: the adjudicator answersretained, methodllm. - Low band boundary: A lexical score of exactly 0.25 on the head gives
absentwith methodlexicaland writes one cache file, as on main. - Lexical-only stats: A lexical-only ambiguous answer on the head counts one decision and no escalation, so
escalation_ratestays 0. - Merge: The PR merges onto current main with no conflict.
- Full test run: The full test run with main merged in shows no new failure; its three failing tests also fail on main.
Open threads from other reviewers:
- still holds on this head: #692 (comment):
--lexical-onlywith a--cache-dirholding an adjudicatedcontradictedforalpha beta epsilon zetaagainstalpha beta gamma deltastill returnscontradicted(methodcache) on the head, whereabsentis expected. - still holds on this head: #692 (comment): Changing
_CACHE_VERSIONfromretention-cache-v5toretention-cache-v4still passes all 96 cases intests/test_novelty_silent_defaults.py.
Follow-up, not blocking:
dokimi/dokimi/novelty/retention.py:106: Withcontradictedstored underalpha beta gamma delta/alpha beta epsilon zetaby an adjudicated run, a client-less oracle on the same--cache-dirreturnscontradicted(methodcache); expectedabsent(methodlexical) (main has it too).
An adjudicated run stores its verdict under the same key a --lexical-only run computes, so a shared --cache-dir made lexical output depend on the cache (contradicted/cache instead of absent/lexical). A lexical oracle gains nothing from the disk cache, so it skips the load. Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
Reverting _CACHE_VERSION to v4 passed the suite, so placeholders a --lexical-only run left on disk could be replayed again unnoticed. Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
|
xaleryb
left a comment
There was a problem hiding this comment.
Re-checked on 1179367 merged with main: a lexical-only run no longer replays an adjudicated verdict from a shared cache dir, an adjudicated oracle still replays the cache with no model call, and a stored v4 placeholder is re-adjudicated; the full suite, ruff, mypy, bandit, docs check --strict and the growth and comment-block checks pass, and CI is green.
antonwolfy
left a comment
There was a problem hiding this comment.
LGTM. The fix is right in both directions: a --lexical-only ambiguous-band answer is neither memoized nor stored, and a lexical oracle no longer reads the disk cache, so its output does not depend on what an adjudicated run left in --cache-dir. One nit inline.
What I ran, on a Linux review host at d19d9df:
make ci-local: 30 passed, 14 skipped, 19,954 tests, changed-line coverage passes. The two gitleaks steps did not run because the scanner download failed; GitHub's own check scans the PR- Mutation run on
retention.py: 11 mutants against the new tests andtests/test_novelty*.py. Storing the placeholder, removing or inverting theself.client is not Noneguard on the load, reverting_CACHE_VERSIONto v4, and changing the placeholder's verdict, method or escalation count each fail the suite. Three survive: thedecisionsincrement (nit inline), the placeholder'sscore, and memoizing the placeholder, which changes nothing observable because the memo is per oracle andclientis fixed at construction.
Checked, no issues
- Pins: the three new tests cover lexical-then-adjudicated, adjudicated-then-lexical (with a check that an adjudicated oracle still replays with no model call), and a stored v4 placeholder being re-adjudicated.
- Docs:
skill-novelty.md,skill-novelty-walkthrough.mdand the changelog fragment match the code; no other text names v4 or says a lexical-only run reads the cache. - Callers:
analyze.pyandshorten.pyonly use.verdict(...).retained, so nothing depends on lexical results being memoized. - Commits: every non-merge commit has a
Signed-off-by.
Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
antonwolfy
left a comment
There was a problem hiding this comment.
LGTM. I pushed a commit per nit, up to beb9eda, which fix the nit from my review:
beb9eda:dokimi/tests/test_novelty_silent_defaults.py:369: after the lexicalverdictcall, assertlexical.stats()["decisions"] == 1; deletingself.decisions += 1now fails the test.
make ci-local at beb9eda: 29 passed, 3 failed (host), 14 skipped; 19952 tests passed, 2 setup timeouts that pass on rerun.
|
I approved this at
|
…tention-cache-key Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
|
Re: review by vlad-perevezentsev
|
Part of #687 (novelty retention cache, High).
Summary
Evidence
test_a_lexical_only_run_does_not_store_a_placeholder_for_a_later_llm_runfails on intel/main: a later adjudicated run replays the placeholder as a finalcacheverdict.make ci-local: every step passes excepttest / Run testsontests/test_process.py::test_sighup_kills_the_live_groups_too, a timeout under box load that passes when run alone (1 passed).Merge Danger
Door: two-way
Cache version bumped to v5: entries already on disk under v4 are not read; they can be deleted.
Blast Radius: low