Repository navigation
fix(novelty): skill shorten and analyze refuse an unusable --cache-dir up front (#701) - #766
Open
antonwolfy wants to merge 5 commits into
Open
antonwolfy wants to merge 5 commits into
antonwolfy wants to merge 5 commits into
Conversation
…r up front (intel#701) A --cache-dir naming a regular file (or whose parent is one) let FileExistsError escape RetentionOracle._store on the first adjudication, after the run had begun paying for calls. Both commands now check the flag through one helper, usable_cache_dir, before any client is built: a regular file, a path below one, and an unwritable directory exit 2 with an InputError that names --cache-dir and the path. A directory that exists, or one that does not exist yet, is taken as before. RetentionOracle._store is unchanged. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
|
✅ OpenCodeReview: Review complete: 0 finding(s) across 2 selected item(s). CI at Review details
|
exai-bot
reviewed
Nov 14, 2026
…front (intel#701) Settles the review point on `usable_cache_dir`: `Path.exists()` follows symlinks, so the walk skipped a dangling `cache -> missing` link and accepted the writable directory above it, and `RetentionOracle._store` then failed on `mkdir`. The walk now stops at a symlink, so the `is_dir()` check refuses the link itself, or a path below it, with exit 2 before any call. A test covers the direct link and a child path; the changelog fragment names the case. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #766 +/- ##
=======================================
Coverage 95.72% 95.72%
=======================================
Files 415 415
Lines 55363 55384 +21
Branches 9516 9520 +4
=======================================
+ Hits 52994 53015 +21
Misses 1466 1466
Partials 903 903
🚀 New features to boost your workflow:
|
exai-bot
reviewed
Nov 14, 2026
…s refused with exit 2 (intel#701) Review point: `usable_cache_dir` called `exists()` and `is_dir()` unguarded, and on Python before 3.14 those raise PermissionError for a path below a directory without search permission, so `cli.main` printed a traceback and exited 5 instead of 2. The inspection now converts an OSError into an InputError naming the flag and the path. A test builds an ancestor with mode 0600 and checks the refusal. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
…n every Python (intel#701) Settles the codecov concern on novelty_run.py lines 50 and 52: the except OSError branch of usable_cache_dir only runs where is_dir() raises PermissionError (Python < 3.14, not as root), so the existing chmod test left it uncovered on other runners. The new test makes is_dir() raise PermissionError and checks the refusal names the flag, the path and the inspected directory. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
Add a case for an existing --cache-dir of mode 0600 (no search permission) that must be refused as not writable; dropping os.X_OK from usable_cache_dir left the suite green. The changelog fragment named FileExistsError for every unusable case; it is raised only for a regular file, the rest are other OSErrors. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
Contributor
|
Pushed 1 commit to
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#701:
skill shortenandskill novelty analyzeend in a traceback when--cache-diris not a usable directory. Onmain,skill shorten --artifact text:rows.md --atoms atoms.json --model o --max-usd 0.05 --cache-dir cache, wherecacheis an existing regular file, builds the model client, pays for the first retention adjudication and then dies withFileExistsError: [Errno 17] File exists: '.../cache'fromRetentionOracle._store(path.parent.mkdir(...)), before any verdict is kept; with no cap it is the same.analyzeshares the oracle and fails the same way.The fix takes the issue's first option: validate
--cache-dirup front and exit 2 with anInputErrorthat names the flag and the path, before any client is built. The second option (catchOSErrorin_storeand warn once) does not stop a run from paying for adjudications it cannot keep, so it is not taken.--cache-dirmainFileExistsErrortraceback after the first paid callError: --cache-dir <path> is not a directory; pass a directory the retention verdicts can be stored in, no call made--cache-dir <path> has <file> above it, which is not a directory; ...OSErrortraceback on the first store (mkdirover the link)--cache-dir <path> is not a directory; ...(orhas <link> above it ...)OSErrortraceback on the first store (mkdir/write_textunguarded)--cache-dir <path>: <dir> is not writable; ...PermissionErrortraceback from the check itself on Python before 3.14--cache-dir <path>: cannot inspect <dir> (...); ...(on 3.14,exists()reads it as missing and the unwritable-directory refusal applies)Closes #701
The same cause in the
repocommands' clone cache is tracked in #765.Changes
usable_cache_dirindokimi/dokimi/commands/novelty_run.py: the one check, returning thePath(orNonewhen the flag is unset) or raisingInputError; anOSErrorfrom inspecting the path (an ancestor without search permission) becomes anInputErrornaming the flag and path.cmd_novelty_analyze(commands/novelty.py) calls it before the run estimate and any client;score_candidates(commands/novelty_atoms_file.py, reached byskill shorten) calls it before building the oracle's client.tests/test_novelty_cache_dir_usable.py: the helper against a regular file, a child of a file, a dangling symlink and a child of one, a directory, a missing child of a directory, and an unwritable directory (skipped as root);skill shorten(with and without--max-usd) andskill novelty analyzedriven with a regular file as--cache-dirassert exit 2, the path in the message and that no client was built.Risk
A
--cache-dirthat was always going to crash on the first store is now refused before the run starts, with exit 2 instead of a traceback. A directory that exists and is writable, and one that does not exist yet, behave as before. The check reads the filesystem once (exists,is_dir,os.access); a disk that fills mid-run still raises fromRetentionOracle._store, unchanged.Testing
On a Linux review host, at
8295fb3(onmain7137604):make ci-local: 31 passed, 2 failed, 14 skipped; the two failures areInstall gitleaks(the download returned exit 22) andScan commits(exit 127, gitleaks not installed), so no commit scan ran here; the skips are steps that need docker, micromamba, semgrep, the fuzz expression, the deploy and matrix jobs, and the pinned Claude Code install. 20451 tests passed, 19 skipped.test_usable_cache_dir_names_the_flag_when_inspecting_the_path_raisesmakesis_dir()raisePermissionErrorand checks theInputErrornames--cache-dir, the path and the inspected directory; with theexcept OSErrornarrowed toFileNotFoundErrorit fails (together with the chmod-based test), so the refusal branch is covered also where Python 3.14 or root hides the error.usable_cache_diron a path below a directory of mode 0600 raisedPermissionErrorbefore the fix and raisesInputErrornow; with thetry/except OSErrorremoved,test_usable_cache_dir_refuses_a_path_below_a_directory_it_cannot_searchfails (8 other tests pass).usable_cache_dironcache -> missing-target(andcache/child) now raisesInputError; with the walk'snot probe.is_symlink()condition removed,test_usable_cache_dir_refuses_a_dangling_symlink_and_a_child_of_onefails.main's code (the helper name givenmain's value, a plainPath(raw)), six of the seven tests fail on their assertions (the one that accepts a directory and a missing child passes, as it should); here all seven pass.test_usable_cache_dir_accepts_unset_a_directory_and_a_missing_child,..._refuses_a_child_of_a_regular_file,..._refuses_an_unwritable_directory_and_a_child_of_one); theos.accesscheck removed (..._refuses_an_unwritable_directory_and_a_child_of_one); theis_dircheck removed (..._refuses_a_regular_file_naming_the_flag_and_path,..._refuses_a_child_of_a_regular_file, both shorten cases and the analyze test);analyzenot calling the helper (test_analyze_refuses_a_cache_dir_that_is_a_file_before_any_call);score_candidatesnot calling it (bothtest_shorten_refuses_...cases).fix/partial-status-guardsonmain7137604:pytest -n auto20449 passed, 19 skipped,mypyclean,ruff checkclean.Revert
A plain revert restores the traceback on an unusable
--cache-dir. Nothing is stored.Checklist
pytestpassesruff,mypy, and schema checks passAGENTS.md.github/.licenserc.yaml)