Repository navigation
fix(cli): tools preference and catalog exit with a message on bad input or output - #239
vchamarthi wants to merge 23 commits into
Conversation
Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
… be written Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
… written Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
….json is not UTF-8 or unreadable Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
3 open issues
What changed in this PR
Improves CLI error handling for tools preference, catalog trigger-set, and catalog scan by turning file read/write OS + decode failures into clean one-line messages with a non-zero exit, and adds regression tests for these cases.
Changes:
- Add guarded read/write paths for groups files, manifests, and
--out/--items-outoutputs with clear error messages. - Refactor
catalog trigger-setoutput writing into a helper that handles unwritable destinations. - Add/extend tests covering non-UTF-8 inputs and unwritable output paths; update complexity baseline.
| File | Description |
|---|---|
| dokimi/tests/test_tools_preference_items_out.py | New tests for tools preference --items-out unwritable path behavior. |
| dokimi/tests/test_tool_preference.py | Adds coverage for non-UTF-8 --groups input in tools preference. |
| dokimi/tests/test_skill_selection.py | Adds coverage for catalog trigger-set unwritable --out. |
| dokimi/tests/test_catalog_command.py | Adds coverage for non-UTF-8/unreadable manifests in catalog scan. |
| dokimi/scripts/growth_baseline.json | Updates complexity budget for the refactor in cmd_catalog_trigger_set. |
| dokimi/dokimi/external/catalog.py | Converts manifest read/decode errors into user-friendly ValueErrors. |
| dokimi/dokimi/commands/tools.py | Adds _write_items and improves --groups error reporting. |
| dokimi/dokimi/commands/catalog.py | Adds _write_trigger_set with clean error reporting on write failures. |
| dokimi/changelog.d/20261025_120000_vchamarthi_cli-input-tools-catalog.md | Changelog entry describing the improved CLI error behavior. |
Review effort: Lite
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #239 +/- ##
==========================================
+ Coverage 92.76% 92.78% +0.02%
==========================================
Files 256 256
Lines 32414 32498 +84
Branches 5421 5426 +5
==========================================
+ Hits 30068 30153 +85
+ Misses 1561 1559 -2
- Partials 785 786 +1
🚀 New features to boost your workflow:
|
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 192057b. The fix does what it says for the cases it names: non-UTF-8 --groups, unwritable --items-out and --out, unreadable or non-UTF-8 manifests all exit with a one-line message. The problems are on the paths right next to them, which still end in a traceback, and in one test that does not pin the widened except. I'd fix these before merge.
What I ran, on a Linux review host at 192057b:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code findings, offline.
- Mutation runs: with
external/catalog.pyorcommands/catalog.pyreverted to the base, the new catalog tests fail (4 and 3 tests). Seven of eight mutations of thetoolscode and tests are caught; the survivor is the first inline test comment ontest_tool_preference.py.
Not anchored inline:
tools preference --out-jsonis still unguarded, and it is written after all the model calls.tools.py:139callssave_artifact("tool_preference", data, args.out_json). With--out-json blocker/o.json, whereblockeris a regular file, the command ends in aFileExistsErrortraceback after the paid calls have run.--items-outis now checked before any spend, so this is the remaining unguarded output. This predates the PR, but the PR title and changelog saytools preferenceexits with a message on an unwritable output. Suggestion: guard it the same way as_write_items, or check the parent of--out-jsonbefore the calls.
Checked, no issues
except ValueErrorintools.py: Copilot's point on the broadValueErrordoes not apply:tp.GroupsErroris aValueErrorsubclass, and I found no input that makesload_groupsraise anotherValueError(wrong types for ids, names and vendors all becomeGroupsError). The only otherValueErrorin the module is raised frombuild_items, outside thetry.- Callers of the manifest readers:
read_skill_manifestandread_task_manifestare called only from the two scan helpers, and both catchValueError. --outfailures: a directory, a file as parent, a symlink loop and a dangling symlink all give the one-line message forreachandskill-creator, and forquestionsapart from the empty path below.- Repo rules: the changelog fragment passes the fragment check, and the growth baseline entry (16 to 15) is correct per
check_growth.py. No schema or docs pages are touched.
Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
antonwolfy
left a comment
There was a problem hiding this comment.
I pushed a commit per nit, up to 8940627, which fix the two nits from my review:
766eae4:dokimi/dokimi/commands/catalog.py:140: the docstring now ends "when it cannot be written."8940627:dokimi/tests/test_skill_selection.py:485: thematch=pattern wraps the path inre.escape(str(out));import rewas already there.
Left as is:
dokimi/dokimi/commands/tools.py:139: the unguarded--out-jsonis not labelledNit:orNon-blocking:, and guarding it would change behaviour, so it stays with the author.
make ci-local at 8940627: 29 passed, 0 failed, 7 skipped.
Not approving yet. Still open: the five risks from my review.
|
@exai-bot /review |
|
@vchamarthi I did not start this: 4 requests are already waiting for a worker. Ask again in a few minutes. |
…ut-json and empty --out read_task_manifest raises ValueError naming suites.json when the top level, suites or a suite's tasks have the wrong type. tools preference --groups rejects a non-object document and catches only JSON, UTF-8, OS and groups errors. --out-json and an empty trigger-set --out exit 1 with a message instead of a traceback. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
|
@exai-bot /review |
exai-bot
left a comment
There was a problem hiding this comment.
Note
AI-generated review of 0f9bfd9e68a6, requested by @vchamarthi, using the default review skill. It can be wrong: verify a finding before acting on it. React with a thumbs up or down on a finding to tell the bot whether it helped.
Model us.anthropic.claude-sonnet-5-5, effort default, 7 of 93 turns, 0.4 of 48 minutes, 141k in / 2k out tokens.
The change wraps the reads and writes of tools preference, catalog trigger-set and catalog scan so OS and decode errors exit with a one-line message. It also validates the shape of suites.json and of the groups document. The changes look correct and the tests cover the new paths. I found one minor problem with the message wording. I could not run the tests here because pytest isn't installed in the container.
1 finding is on the changed lines, as comments below.
Not verified
I did not run the new tests. I also did not check that make ci-local, including the growth baseline drop from 16 to 15 for cmd_catalog_trigger_set, is green.
…le --out ArtifactValidationError subclasses ValueError, so a schema failure was reported as 'cannot write --out'. It now exits with 'questions set rejected', and the write-failure message stays for path errors. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
exai-bot
left a comment
There was a problem hiding this comment.
Note
AI-generated review of 5d1c627fe3d8, requested by @vchamarthi, using the default review skill. It can be wrong: verify a finding before acting on it. React with a thumbs up or down on a finding to tell the bot whether it helped.
Model us.anthropic.claude-sonnet-5-5, effort default, 7 of 93 turns, 0.5 of 48 minutes, 121k in / 3k out tokens.
Re-review of 5d1c627fe3d8: 1 new finding.
1 finding is on the changed lines, as comments below.
napetrov
left a comment
There was a problem hiding this comment.
Review at 5d1c627f.
Summary. All earlier findings (antonwolfy, Copilot, exai-bot round 1) are addressed in 0f9bfd9 / 766eae4 / 8940627 / 5d1c627: wrong-shape suites.json and --groups, the narrowed except with a test that pins it, --out "", and the schema-rejection message. I found nothing new on the changed lines and pushed no commits.
Open items
- Minor, design choice for the author (not a small fix, so left as is):
tools preferenceonly discovers an unwritable--out-jsonin_save_result, after the paid probe run, so the results are lost (exai-bot attools.py:149, also mentioned by antonwolfy as left to the author). A cheap pre-flight (e.g.parent.mkdir+ open-for-append check beforerun_probe) would avoid paying for a run that cannot be saved. Pre-existing behaviour; the PR adds the clean message but not the early check. OK as a follow-up.
Test evidence (Linux, uv run)
ruff check dokimi tests: clean.test_catalog_command.py test_skill_selection.py test_tool_preference.py test_tools_preference_items_out.py: 147 passed.
Verdict from my side: ready; the --out-json pre-flight can be a follow-up.
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 5d1c627. The five risks from my earlier review are fixed, and the tests for them fail when each fix is reverted. Two inputs next to the fixed ones still end in a traceback. I'd fix both before merge.
What I ran, on a Linux review host at 5d1c627:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code findings, offline.
- Mutation runs: reverting each of the
catalogfixes (15 mutations) and each of thetoolsfixes (10 mutations) makes a new test fail.
@napetrov's and @exai-bot's question on checking --out-json before the paid run waits for the author. The command now exits with a message, but the results are still lost when the path is unwritable.
Checked, no issues
- Re-indented loop:
read_task_manifestreturns the same entries as the base for a mixed valid fixture, andgit diff -wshows only the new_manifest_taskscall. - Narrowed
exceptintools.py:--groupsas a directory, a BOM, an empty file and wrong types incues,system,twins,idandnameall exit with--groups <path>: .... --outintrigger-set: a directory, a file as parent,.,/and a 5000-character name exit with a message naming--outin all three formats.- Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
…ON, and an empty --out-json load_groups iterates groups only when it is a list, so a null value is reported by the schema check. The groups file read also catches RecursionError and ValueError. _save_result catches ValueError next to OSError and reports a schema rejection as a rejected artifact. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 53e5e33. Both fixes from my last review hold: "groups": null and --out-json "" now exit with a message. Two things are worth fixing before merge: the same deep-nesting input that was fixed for --groups still ends in a traceback in the manifest readers, and the new tool_preference artifact rejected branch has no test.
What I ran, on a Linux review host at 53e5e33:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code findings, offline.
- Mutation runs: dropping the
ArtifactValidationErrorbranch in_save_resultleavestest_tool_preference.pyandtest_tools_preference_items_out.pygreen (77 passed). Reverting thegroups: null, deep-nesting and huge-int fixes makes the new parametrized cases fail.
@napetrov's and @exai-bot's question on checking --out-json before the paid run still waits for the author. The command now exits with a message, but the results are still lost when the path is unwritable.
Checked, no issues
--groups: about 50 inputs (nested wrong types, BOM, UTF-16, empty file, NaN, a directory, a missing path, a 5000-character path, 6000-digit ints,[and{"a":nested deeply) all exit with--groups <path>: ....--out-json: an empty path, a directory, a file as parent and.all exit 1 withError: cannot write <path>: ....--outintrigger-set: three formats against 19 odd paths (directory, file as parent, empty, symlink loop,/dev/null/x, 300-character name) give a one-line message, never a traceback.- Re-indented loop:
git diff -wshows only the new_manifest_taskscall in the loop header. - Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
napetrov
left a comment
There was a problem hiding this comment.
Delta review of 5d1c627f..53e5e33b.
New commit 53e5e33 (null groups, deep/huge JSON in --groups, empty --out-json, schema rejection reported separately from an unwritable path): reads correct; ArtifactValidationError is caught before the broader ValueError, so the two messages stay distinct. Nothing new from me, no commits pushed.
Still open (unchanged, follow-up OK): --out-json is only checked after the paid probe run.
Evidence: ruff check dokimi tests clean; test_tool_preference.py test_tools_preference_items_out.py 77 passed; CI 20/20 green at 53e5e33.
…with a message A deeply nested skills.yaml or suites.json raised RecursionError and a task name longer than the filesystem allows raised OSError from is_task_dir. Both now produce the invalid-manifest error or a failed catalog entry. Also cover the tool_preference artifact rejected branch with a test. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 6c4295c. Both fixes from my last review hold: a deeply nested skills.yaml or suites.json now exits with an invalid ... at <path> message, and the tool_preference artifact rejected branch has a test that fails when the clause is removed. Two risks remain on the neighbouring catalog paths, which still end in a traceback. Both predate the PR, but the changelog says a bad manifest exits with a message.
What I ran, on a Linux review host at 6c4295c:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code findings, offline.
- Mutation runs: reverting the
RecursionErrorcatch forskills.yaml, the one forsuites.json, and theOSErrorhandler aroundis_task_dirmakes exactly one new test fail each. Removing theexcept ArtifactValidationErrorclause in_save_resultmakes the newtoolstest fail withcannot write.
Not anchored inline (outside this diff):
- A malformed
SKILL.mdunder--catalogstill ends in a traceback incatalog trigger-set.discover_skills(catalog_root)atcommands/catalog.py:171runs outside anytry. With--catalogholdinga/SKILL.mdand a validb/SKILL.md, and--questions q.json=b --out o.json: bytes\xff\xfegiveUnicodeDecodeError: 'utf-8' codec can't decode byte 0xff; frontmattername: [or a YAML list givesValueError: Skill 'a' (...) is missing a 'description' in its frontmatter; frontmatter of[repeated 100000 times givesRecursionError;a/SKILL.mdas a directory givesIsADirectoryError. All exit 1 and write no--out.catalog scanreports the same inputs per row, so the two commands disagree. Suggestion: wrap the call intry/except (OSError, ValueError, RecursionError)and raiseSystemExit(f"--catalog {catalog_root}: {exc}"), with a parametrized test for a non-UTF-8 and a missing-descriptionSKILL.md. catalog scan --kind taskswithout asuites.jsonstill ends in a traceback on a task directory with noinstruction.md.discover_tasks(tasks_root)atexternal/catalog.py:273is unguarded, unlike the manifest branch below it. Withevaluation/harbor/tasks/t/task.tomlpresent, noinstruction.mdand nosuites.json,catalog scan --root <dir> --kind tasksexits withFileNotFoundError: Task has no instruction.md: .../tasks/t. The same task listed insuites.jsongives a failed row. Suggestion: catch(OSError, ValueError)arounddiscover_tasks, raiseValueError(f"cannot read tasks at {tasks_root}: {exc}")(whichcommands/catalog.pyalready turns into a message), and add a test with a task directory holding onlytask.toml.
@napetrov's and @exai-bot's question on checking --out-json before the paid run still waits for the author. The command exits with a message, but the results are still lost when the path is unwritable.
Checked, no issues
- Over-long task name: with the tasks directory present, a 300-character
track: executablename gives a failed entry (cannot inspect task directory ...: File name too long) in text and JSON, exit 1. A 255-character name is skipped, exit 0. - Deep nesting:
[repeated 200000 times inskills.yaml(--kind skillsandall) and insuites.json(--kind tasksandall) exits with the invalid-manifest message. - Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
…irectory without instruction.md catalog trigger-set now reports an unreadable or malformed SKILL.md under --catalog, and catalog scan --kind tasks without suites.json reports a task directory missing instruction.md, instead of a traceback. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 61cdeb2. Both fixes from my last review hold: catalog trigger-set exits with a message on a malformed SKILL.md, and catalog scan --kind tasks does the same on a task directory without instruction.md. A sibling path in catalog scan still ends in a traceback for the nested-frontmatter input the new code handles, and the new tests do not pin two of the five new exception types. There is also one wording nit.
What I ran, on a Linux review host at 61cdeb2:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code findings, offline.
- Mutation runs: reverting either call site makes the matching new test fail. Dropping
RecursionErrorfrom the_discover_catalog_skillstuple, orOSError(aSKILL.mdthat is a directory), leaves the 23 tests intest_catalog_command.pygreen.
Not anchored inline:
- Nit: the task-directory error is prefixed
suites.json:when nosuites.jsonexists._scan_tasks(commands/catalog.py:105, outside this diff) wraps everyValueErrorfromread_task_manifestassuites.json: {exc}. The new_discover_tasks_checkedruns only in the branch where the manifest is absent. A task directory holding onlytask.tomlgivessuites.json: cannot read tasks at <root>/evaluation/harbor/tasks: Task has no instruction.md: <root>/evaluation/harbor/tasks/t. Suggestion: drop thesuites.json:prefix, since theinvalid suites.json at <path>messages already name the file.
@napetrov's and @exai-bot's question on checking --out-json before the paid run waits for the author.
Checked, no issues
trigger-set --catalog: aSKILL.mdthat is a directory, a symlink loop, mode 0, a list frontmatter and a 100000-deep frontmatter all exit 1 with--catalog <root>: ....read_task_manifestsuccess path: hoistingfoundout of the comprehension leaves a good task plus an empty skills directory printing the sameokrow.- Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
catalog scan --kind skills now lists a SKILL.md whose frontmatter nests too deeply for the YAML parser as an error row, instead of ending in a traceback. The strict frontmatter check used by the validator reports the same case as a frontmatter-parse error. Tests cover a SKILL.md that is a directory, one that is not UTF-8, and one with deeply nested frontmatter, for both scan and trigger-set. The task directory test also covers an unparsable task.toml, which raises ValueError. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
tools preference checks --out-json before the first model call, so a path that cannot be written (a file used as a parent directory, or a directory) exits 2 with a message instead of after a paid run. Missing parent directories are created, and the probe file is removed when the path did not exist before. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 263ccde. Both fixes from my last review hold: a deeply nested SKILL.md is now an error row in catalog scan, the new tests pin each added exception, and the suites.json: prefix is gone from the task-directory message. One thing is worth fixing before merge: the new --out-json pre-flight in tools preference does not match what the real save does.
What I ran, on a Linux review host at 263ccde:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). The changed-line coverage check passed.- Reproductions for the code finding, offline.
- Mutation runs: dropping
RecursionErrorfromexternal/catalog.py, fromexternal/validate.pyor fromcommands/catalog.pymakes exactly one new test fail each.
Checked, no issues
- Prefix removal: no test or doc still expects
suites.json:in front of the task-directory error. - Deep
SKILL.md:catalog scan --kind skillsonname:followed by 100000[prints anERROR:row plus afrontmatter-parsefinding, exits 1, and the other skills still scan. - Pre-flight order:
--dry-runand a missing--modelexit before the check, and a missing target file is removed again. - Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
The out-json check now creates and removes a temp file beside the path the save writes to, instead of opening the target itself. A read-only existing file in a writable directory is accepted, a dangling symlink creates nothing at its target, and a symlink into a missing directory is refused before any probe call. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
The --out-json probe now matches the save in the cases I tried, and make ci-local is green. One thing is worth fixing before merge: the tests do not pin the new probe.
What I ran, on a Linux review host at ad114ec:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). 8,264 tests; changed-line coverage 97%.- Reproductions for the probe against the real save, offline.
- Mutation runs: 8 mutants of
_check_out_json_writable; 3 are caught (no_write_target, nois_dircheck, nomkdir) and 5 pass the full suite (no probe, probingtarget.parent,is_dirontarget, noValueErrorin theexcept, and a changed temp prefix). The first three are in the inline comment; theValueErrorone needs an embedded NUL byte in the path, which a shell cannot pass, and the prefix one is cosmetic.
Checked, no issues
- Probe against save: a read-only file in a writable directory, a symlink to one, a dangling symlink, a symlink into a missing directory, a symlink loop, a directory target and an empty path give the same accept or reject in the check and in
save_artifact. A dangling symlink leaves no file at its target, and no.tmpfile is left behind. - Call order:
_check_out_json_writableruns after--dry-runand the--modelcheck and before the first probe call. - Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
…argets Three tests cover a writable file in a read-only directory, a symlink whose target sits in a read-only directory, and a symlink to a directory. Each refuses with exit 2 before any probe call. The read-only cases skip on Windows and when the process can write through chmod 0555 (root). Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
test_tool_preference.py passed the 1000-line growth cap, so the out-json pre-flight tests move to test_tool_preference_out_json.py. The tests are unchanged apart from the moved location and an unused import. Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 41466dd. The three tests from my last review are in, and they kill the probe mutants I named (no probe, target.parent, no is_dir on the resolved path). One nit inline: the probe's temp name is shorter than the save's, so a very long file name passes the pre-flight and the save then fails after the paid calls.
What I ran, on a Linux review host at 41466dd:
make ci-local: 29 passed, 0 failed, 7 skipped (docker, network and other-Python legs). 8,267 tests; changed-line coverage 97%.- Reproduction for the code finding, offline.
- Mutation runs: of 7 mutants of
_check_out_json_writable, 6 are caught (no probe,target.parent, nomkdir, nois_dircheck,open(..., 'ab')probe, no_write_target). DroppingValueErrorfrom theexceptpasses the suite; it needs an embedded NUL byte in the path, which a shell cannot pass, so I did not raise it.
Checked, no issues
- Probe against save: a read-only file, a symlink into a read-only directory, a dangling symlink, a symlink loop (as file and as parent), a trailing slash, an empty path and a
0555directory give the same accept or reject in the check and insave_artifact, and the probe leaves no file behind. - Call order: the check runs after
--dry-runand the--modelcheck, and before the first model call. - Repo rules: the changelog fragment and the growth baseline (16 to 15) pass; no schema or docs pages are touched.
Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
antonwolfy
left a comment
There was a problem hiding this comment.
I pushed a commit per nit, up to 8f04440, which fix the nit from my review:
8f04440:dokimi/dokimi/commands/tools.py:129: the probe now creates<name>.<pid>.<thread id>.tmp, the save's temp name, and a new test pins a 240-character file name to exit 2.
make ci-local at 8f04440: 29 passed, 0 failed, 7 skipped.
GitHub CI has not run on these commits: the branch conflicts with main, and Actions runs no workflow on a conflicting PR. CI will check them once main is merged in.
Not approving until CI passes at this head.
Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com> # Conflicts: # dokimi/scripts/growth_baseline.json
The manifest branch (_skill_entry) caught only OSError and ValueError around load_skill, so a deeply nested frontmatter ended catalog scan in a RecursionError traceback; the no-manifest branch already caught it. Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
`data.get("suites") or []` turned {}, 0, false and "" into an empty list
before the shape check, so such a manifest scanned as 0 declared, rc 0.
Only null or a missing key now means empty, as in skills.yaml.
Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
|
antonwolfy
left a comment
There was a problem hiding this comment.
LGTM. Both new commits are right: a SKILL.md that is too deeply nested and is listed in skills.yaml is now an error row, and suites.json rejects {}, 0 and {"tasks": {}} while null or a missing key still reads as empty. No new findings. @xaleryb left one choice to you: whether to turn RecursionError into ValueError once, in load_skill.
What I ran, on Linux at 3d29187:
make ci-local: 26 passed, 2 failed, 7 skipped; 8,722 tests; the changed-line coverage check passed. The two failures are the gitleaks install and scan steps, which could not download the gitleaks binary (curl: (22) ... 504); not caused by this PR.- Mutation runs on the new tests: dropping
RecursionErrorfrom_skill_entry, restoringor []forsuitesor fortasks, and removing eitherNoneto[]mapping each make at least one new test fail.
Checked, no issues
- Delta:
catalog scan --kind skillson askills.yamlthat lists aSKILL.mdwith[repeated 100000 times in the frontmatter prints anERROR:row, exits 1, and the other skills still scan. - Repo rules: the changelog fragment is present, the growth baseline entry (16 to 15) passes, and no schema is touched.
…talog-skills Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>


Summary
tools preference,catalog trigger-setandcatalog scanread a groups file and skill manifests and write--outand--items-outwithout handling OS or decode errors, so a bad file or path ends in a traceback.Changes
Each affected read or write now reports the path and reason in a one-line message and exits. One commit per command.
Risk
Error paths only.
Testing
make ci-local(offline), Python 3.13: everything passes exceptmypy(1 error) and the 10 tests that also fail onmain(process, sandbox, container probes; macOS). Load-flaky tests pass alone.Checklist
pytestpasses (apart from the 10 pre-existing failures)ruff,mypy, and schema checks pass (mypy: the one pre-existing error).github/.licenserc.yaml)