Skip to content

feat(repo): repo fetch --json, validate and budget --out, validate --fail-on-warning - #150

Merged
napetrov merged 2 commits into
intel:mainfrom
vchamarthi:feat/repo-cli-output-parity
Oct 21, 2026
Merged

napetrov merged 2 commits into
intel:mainfrom
vchamarthi:feat/repo-cli-output-parity

Conversation

@vchamarthi

@vchamarthi vchamarthi commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Three repo commands lacked options their siblings already have, so a script or CI job had to parse stdout to use them.

  • repo fetch --json prints {"sha", "git_dir"} instead of a tab-separated line.
  • repo validate --out FILE and repo budget --out FILE write the full report as JSON, as repo scan and repo inspect do.
  • repo validate --fail-on-warning exits 1 on a warning, as repo budget --fail-on-warning does.

Changes

  • dokimi/dokimi/commands/repo.py: the four options above; a write failure for --out prints cannot write <path> and exits 1, as scan does.
  • dokimi/docs/repo-evaluation-contract.md: the command synopsis lists the new options.
  • Tests in tests/test_repo_manifest.py and tests/test_repo_budget.py; one changelog fragment.

Risk

Low. All four options are additive. Default output and exit codes of fetch, validate and budget are unchanged. No persisted format changes. The contract doc is also edited by several open PRs (#107, #113, #114, #115, #116, #120, #137), so expect a trivial rebase on the synopsis lines.

Testing

On Linux (Python 3.12): pytest tests/test_repo_manifest.py tests/test_repo_budget.py tests/test_docs_code_refs.py passes (235 tests); ruff check . and mypy dokimi are clean. The full pytest run is left to CI.

Checklist

  • Tests added/updated and pytest passes (touched files and docs refs locally; full run in CI)
  • ruff, mypy, and schema checks pass (no schema change)
  • Docs updated (or N/A): contract synopsis updated
  • No ad-hoc run artifacts committed
  • New files carry the SPDX license header (or are exempt in .github/.licenserc.yaml): the only new file is a changelog fragment, which is exempt

…te --fail-on-warning

Bring the repo commands in line with each other. fetch prints {sha, git_dir}
as JSON with --json. validate and budget write their full report to a file
with --out, as scan and inspect do. validate exits 1 on a warning with
--fail-on-warning, as budget does. Default output and exit codes are unchanged.

Signed-off-by: vchamarthi <123653452+vchamarthi@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Both new persisted report formats need registered versioned schemas and schema-aware artifact writes.

1 open issue
What changed in this PR

Adds output and warning-gate options to repository evaluation commands while preserving defaults.

Changes:

  • Adds repo fetch --json.
  • Adds --out to validation and budget commands, plus validation’s --fail-on-warning.
  • Updates tests, documentation, and changelog.
File Description
dokimi/​tests/​test_repo_manifest.py Tests fetch JSON and validation options.
dokimi/​tests/​test_repo_budget.py Tests budget file output and write failures.
dokimi/​dokimi/​commands/​repo.py Implements and registers the new options.
dokimi/​docs/​repo-evaluation-contract.md Updates command usage examples.
dokimi/​changelog.d/​20261021_130000_vchamarthi_repo-cli-output-parity.md Documents the added options.

Review effort: Balanced

Comment thread dokimi/dokimi/commands/repo.py Outdated

if args.out:
try:
Path(args.out).write_text(json.dumps(report.to_dict(), indent=2) + "\n", encoding="utf-8")
@codecov-commenter

codecov-commenter commented Oct 21, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.40%. Comparing base (9ad5506) to head (6267044).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #150      +/-   ##
==========================================
+ Coverage   91.38%   91.40%   +0.02%     
==========================================
  Files         216      216              
  Lines       26722    26738      +16     
  Branches     4373     4376       +3     
==========================================
+ Hits        24419    24441      +22     
+ Misses       1637     1633       -4     
+ Partials      666      664       -2     
Files with missing lines Coverage Δ
dokimi/dokimi/commands/repo.py 96.34% <100.00%> (+0.90%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vchamarthi

Copy link
Copy Markdown
Contributor Author

@exai-bot /review

@exai-bot exai-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

AI-generated review of 9ee05ee33d58, 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.

The change adds repo fetch --json, --out for repo validate and repo budget, and repo validate --fail-on-warning. All four are additive and the defaults are unchanged. I found no correctness bugs. The exit-code logic, error handling for --out write failures, and the tests (including the open_source monkeypatch and GitTree(git_dir, sha) signature) check out against the code. The one issue is that the new --out files are unversioned, unlike scan and inspect.

1 finding is on the changed lines, as comments below.

For a human reviewer

  • Decide whether validate/budget --out files should be versioned artifacts like scan/inspect, or plain JSON.

Comment thread dokimi/dokimi/commands/repo.py Outdated
report.notes.append("task bases were not checked: the source has no git history")

if args.out:
try:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor (plausible, maintainability): --out writes unstamped JSON, unlike scan/inspect which the docs say it matches

repo scan and repo inspect write --out through save_artifact(kind, ...). That call stamps the file with a schema version, and --json output is also stamped. The new validate --out and budget --out call Path.write_text(json.dumps(...)) directly, so the file has no schema/version stamp. The changelog and PR text say it works "as repo scan and repo inspect do", which is only partly true. A script that reads these files cannot tell the format version. Because the shape is not registered, it can change later without any compatibility check. The same write block is also duplicated in both commands. If an unversioned dump is intended, say so in the help text and docs. Otherwise, register artifact kinds for the validate report and the budget inventory.

Suggested fix:

Add artifact kinds (e.g. repo_validation, repo_budget) with schemas and use save_artifact, or document that these files are plain unversioned JSON.

Copilot AI balanced review requested due to automatic review settings October 21, 2026 19:43

@napetrov napetrov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additive, defaults unchanged, --out written before the exit so a failing validate still leaves its report. Good.

Pushed 6267044: the two new raw --out writes go through one _write_json helper instead of two copies of the try/except. (scan/inspect keep save_artifact, since they're schema-stamped.)

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes are narrowly scoped, preserve defaults, and include focused regression tests with no unresolved findings.

1 open issue

Review effort: Balanced

@napetrov
napetrov merged commit 7c1e7d0 into intel:main Oct 21, 2026
22 checks passed
napetrov added a commit to napetrov/dokimi that referenced this pull request Oct 22, 2026
…r raise

Main grew four baselined or near-cap items and added three functions over
complexity 10 before the gate landed: test_repo_environment.py 1369 -> 1371
(intel#147), manifest._check_task 21 -> 22 (intel#113), ci_local.run 28 -> 29 (intel#146),
cmd_repo_validate 10 -> 11 (intel#150), cli_surface._value 17 (intel#88),
research_register.check 19 and main 15 (intel#139). Each entry names its PR.
--update after the seed lowers nothing. Now 15 files and 98 functions.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
antonwolfy pushed a commit that referenced this pull request Oct 22, 2026
* ci: no-growth ratchet for file length and function complexity

A first-party .py file over 800 lines (1000 under tests/) or a function
over cyclomatic complexity 10 (ruff's C901 count, computed with ast so the
test job needs no ruff) now fails tests/test_growth_ratchet.py unless
scripts/growth_baseline.json records it. A recorded value is exact: the
code may shrink but not grow, and a shrunk, gone or back-under-cap entry
must be lowered or removed (--update does that, never raising). An entry
raised or added relative to the base branch needs a rationale of at most
300 characters.

The baseline holds the 14 files and 81 functions over the caps today.
`check_growth.py --report --markdown` adds the totals to the static job's
step summary, non-blocking.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(ci_local): pass resolved base ref to growth check via DOKIMI_GROWTH_BASE

ci_local.py resolves the base ref to handle non-origin remotes, but did not pass
it to the pytest environment. This caused the growth check to use the wrong
baseline or skip the rationale check if the baseline was missing, allowing
misleading local CI passes when using --remote with a non-origin remote.

Pass the runner's resolved base_ref as DOKIMI_GROWTH_BASE environment variable
to the subprocess steps. Add a regression test that verifies the check correctly
uses a non-origin remote's baseline.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* ci(growth): baseline evaluate_novelty at 26, as #72 left it on main

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* feat(ci-local): pass resolved base_ref as DOKIMI_GROWTH_BASE env var

ci_local.py now passes the resolved base reference to workflow steps as
DOKIMI_GROWTH_BASE, allowing check_growth.py to use it without requiring
--base argument when ci_local is used to run workflows locally.

Adds test to verify the env var is passed to all subprocess steps.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix: restore the files f105136 reverted by mistake

f105136 was built on a stale tree and deleted the #72 and #84 changes
from this branch. Bring every file back to 6c4cc20; only the
test_ci_local.py addition of f105136 stays.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(growth): a raised entry needs a new rationale; test loop/try else and match guards

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(ci_local, check_growth): propagate DOKIMI_GROWTH_BASE to isolated jobs and guard TryStar

Two fixes for growth ratchet compatibility:

1. Isolated jobs (package-smoke) did not receive DOKIMI_GROWTH_BASE from base_env,
causing the growth check to compare against the wrong baseline. Now included in env.

2. ast.TryStar is only available on Python 3.11+ (introduced with except*). Guarded
with hasattr() so the script remains compatible with Python 3.10.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(ci_local, check_growth): cover isolated-job env and drop dead TryStar guard

Add a regression test for DOKIMI_GROWTH_BASE reaching the isolated
package-smoke job, and a try-star complexity case. ast.TryStar always
exists on the supported Python (>=3.11), so the hasattr guard is removed.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* refactor: split functions over the complexity cap

Extract helpers from cmd_answers_generate (runtime config, question loading,
output path) and from the import-architecture test (import targets, owner
module, Tarjan component pop, spawn-import aliases) so each is under the cap.
cmd_answers_generate is back under its cap, so its baseline entry is removed.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* test(answers): cover the helpers answers generate was split into

The refactor moved config loading, question loading and output-path choice
into helpers that the existing tests never reach, leaving 12 changed lines
uncovered (diff-cover gate: 61%, needs 80%). The new tests cover the
missing-, empty-, invalid- and non-mapping config cases, the question load
error, the output-path precedence, and the command end to end over fake
Answerer and documentation-source clients.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* ci(growth): take the #101 growth into the baseline; changelog fragment

Main's #101 grew dokimi/novelty/bundle.py to 1016 lines and
evaluate_novelty to complexity 29 after the baseline was cut, so the
ratchet failed on code this PR does not touch. Raise both entries with a
rationale, as the #72 entry already does.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(growth): compare rationale against the fork point, not the base tip

The rationale check read the baseline at the tip of origin/<base>. Once main
lowers an entry, every branch behind it, and a re-run CI merge commit, was
told it raised that entry. Read it at git merge-base HEAD <ref> instead.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>

* test(growth): pin the C901 count and guards that no test reached

Eleven single-line mutants of check_growth.py passed the whole suite: defs in
except/case bodies, async for, nested async defs, class bodies, `(_ as z)`,
duplicate names, GITHUB_BASE_REF, cli.py, dot dirs, non-int entries and the
rationale strip. Expected counts come from ruff C901 at max-complexity 0.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>

* test(growth,answers): pin the match-case counts, the subdirectory baseline read, and the top_k default

Three review gaps with no failing test: a decision inside a case body and a refutable
as-pattern last case in the complexity count; load_base_baseline when the project sits
in a subdirectory of the git root (the ./ prefix); and the answers command's top_k
default from retrieval.top_k when the flag is unset.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* test(answers): make the flag row differ from config and default; fix growth comments

The flag row used top_k=3, which is also the built-in default, so a
command ignoring --top-k still passed (mutant: if True:). Use 5 with a
config of 7. Correct the test and function counts in check_growth.py
comments and drop the unused _product_config assignment in answers.py.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* ci(growth): --seed mode, reseed baseline after merging main, document --update after rebase

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* fix(growth): the --seed rationale does not explain a raise against a baselined base

After this lands, `--seed` on a branch that grew llm.py wrote the entry at
the new size with "pre-existing when the gate was introduced", and the gate
passed. The rationale check now treats that text as missing, so only the
one-time seeding (base with no baseline) can use it.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>

* ci(growth): reseed the baseline after the merge of main (main has no baseline)

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* ci(growth): seed the baseline after merging main, with a rationale per raise

Main grew four baselined or near-cap items and added three functions over
complexity 10 before the gate landed: test_repo_environment.py 1369 -> 1371
(#147), manifest._check_task 21 -> 22 (#113), ci_local.run 28 -> 29 (#146),
cmd_repo_validate 10 -> 11 (#150), cli_surface._value 17 (#88),
research_register.check 19 and main 15 (#139). Each entry names its PR.
--update after the seed lowers nothing. Now 15 files and 98 functions.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

* ci(growth): re-seed the baseline after merging main again (#73, #115)

#73 grew test_judge_validity.py 1423 -> 2235, test_judge_reliability.py
1505 -> 1695, model_compare.py 1296 -> 1297, cmd_eval_judge_validity
25 -> 29, and took degrade.build_pairs (17) and
judge_sequential.run_sequential (12) over the cap. #115 grew
l0 _build_names 14 -> 15 and shrank _cmake (now under the cap, entry
dropped) and Scan.resolve_path (20 -> 19). Each raise names its PR.
Now 15 files and 99 functions.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>

---------

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
Co-authored-by: Alexander Rybkin <alexander.rybkin@intel.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.

5 participants