Repository navigation
feat(repo): stamp and schema-check repo budget JSON as repo_budget.v1 - #205
Conversation
`repo budget --json` carried no schema field, unlike `repo scan` (repo_readiness.v1), `repo inspect` (repo_environment.v1) and `repo reach` (guidance_reach.v1), so nobody gating CI on the JSON could detect a shape change. This settles that non-blocking review point on intel#71. Add schemas/repo_budget.v1.json for the payload `budget()` returns, register it in artifacts.SCHEMA_VERSIONS, stamp the `--json` output, and write `--out` through save_artifact as the sibling commands do (it now creates missing parent directories and validates before writing). Add the schema fixture, tests, and name the schema in the contract and architecture docs. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
|
@exai-bot /review |
exai-bot
left a comment
There was a problem hiding this comment.
Note
AI-generated review of 5571756e718c, 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, 8 of 94 turns, 0.5 of 48 minutes, 161k in / 3k out tokens.
This PR adds a repo_budget.v1 schema and registers it. repo budget --json now prints a stamped payload, and --out writes through save_artifact, as repo scan and repo inspect do. The schema matches what budget() emits: I checked the kind/when values, the top-level keys and the overlap rounding against repos/budget.py. The fixture and tests cover the new contract well. I found only minor edge-case issues.
2 findings are on the changed lines, as comments below.
| _write_json(args.out, payload) | ||
| try: | ||
| save_artifact("repo_budget", payload, Path(args.out)) | ||
| except OSError as exc: |
There was a problem hiding this comment.
Minor (confirmed, correctness): A schema-invalid payload under --out escapes as a traceback
- Problem: only
OSErroris caught.save_artifactraisesArtifactValidationError, aValueError, when the payload fails the schema. That includes a futurekindorwhenvalue that nobody added to the schema. - Effect: the user gets a raw traceback and not the
✗ ...message with exit 1. The changelog says--out"refuses a payload that does not match the schema", but the refusal arrives as a crash. - Context:
repo scanandrepo inspectdo the same, so this follows existing practice.--jsonwithout--outnever validates the payload.
Suggested fix:
Catch (OSError, ArtifactValidationError) in the --out block, print ✗ ... to stderr and exit 1.
There was a problem hiding this comment.
Left as is, on purpose:
- A payload that fails the schema means
budget()produced a shape the schema doesn't know. That's a dokimi bug, not a user error. repo scan --outandrepo inspect --outraise the same way, and a handler onlybudgethad would make the three differ.
The changelog's "refuses a payload that does not match the schema" did read like a handled error, so c8a141b changes it to "validates the payload against the schema before writing".
| payload = budget(tree, profile.guidance_names, profile.import_max_depth) | ||
| if args.out: | ||
| _write_json(args.out, payload) | ||
| try: |
There was a problem hiding this comment.
Nit (confirmed, style): --out file no longer ends with a newline
The old _write_json appended "\n". save_artifact writes json.dumps(...) with no trailing newline. This only matters to tools or diffs that expect a final newline.
There was a problem hiding this comment.
True. It's what save_artifact writes for every artifact (repo scan --out, repo inspect --out and the rest), so this stays consistent with them rather than becoming a special case.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #205 +/- ##
==========================================
+ Coverage 91.78% 91.97% +0.19%
==========================================
Files 223 223
Lines 27623 27714 +91
Branches 4549 4553 +4
==========================================
+ Hits 25354 25491 +137
+ Misses 1606 1574 -32
+ Partials 663 649 -14
🚀 New features to boost your workflow:
|
vchamarthi
left a comment
There was a problem hiding this comment.
No blockers, not approving yet: CI at the head is not green (0 failing, 14 pending).
CI is still running at this head (20 checks pending, 2 passing); no defects found in the change. The schema's required keys, kind/when enums and overlap range match what budget() returns at dokimi/repos/budget.py:117-169, and the CLI wiring matches cmd_repo_inspect (save_artifact on --out, stamp on --json).
CI at send time: 0 failing, 14 pending.
exai-bot
left a comment
There was a problem hiding this comment.
Note
AI-generated review of 5571756e718c, 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, 5 of 80 turns, 0.3 of 40 minutes, 117k in / 2k out tokens.
Re-review of 5571756e718c: nothing new.
…scan does Review of intel#205 (exai-bot): "refuses a payload that does not match the schema" read like a handled user error. A payload that fails the schema is a bug in `budget()`, and `--out` raises on it as `repo scan --out` and `repo inspect --out` do; the entry now says it validates. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
napetrov
left a comment
There was a problem hiding this comment.
Reuse of save_artifact/stamp matches repo scan, good. The summary says the schema is closed like repo_readiness/repo_environment, but only the top level has additionalProperties: false; the item objects in entries and duplicate_skills (and totals) accept extra keys. Suggest closing those too so a shape change is caught at every level.
Review of intel#205 (napetrov): only the top level had `additionalProperties: false`, so an entry, `totals` or a `duplicate_skills` pair could gain a key and still validate, and a CI gate on the JSON would miss that shape change. `budget()` writes exactly `{path, kind, when, chars}`, the four `when` totals and `{a, b, overlap}` (the real-output fixture has no other key), so all three are closed now. The sibling schemas close only their top level; this one is new, so it can start strict. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
Summary
Follow-up to the review of #71 (point 3).
repo budget --jsoncarried no schema stamp, whilerepo scan,repo inspectandrepo reachstamp theirs. A CI gate on the JSON could not tell when its shape changed.Changes
repo_budget.v1(dokimi/schemas/repo_budget.v1.json), registered inartifacts.SCHEMA_VERSIONS. It is closed at every level: the top level, as inrepo_readinessandrepo_environment, and also each entry,totalsand eachduplicate_skillspair, sincebudget()writes exactly those keys. It requires:tree;entries:{path, kind, when, chars}, wherekindandwhenare the valuesbudget()emits;totals: perwhen;skills;duplicate_skills:{a, b, overlap}, withoverlapin [0, 1];mcp_servers,warnings.--jsonand--out:--jsonprints the payload stamped withschema_version;--outwrites throughsave_artifact, asrepo scan --outdoes, so the file is validated and stamped, and a missing parent directory is created. A path that cannot be written still exits 1 withcannot write.tests/fixtures/artifacts/, the real output on a populated toy tree, whichschema_compatneeds;architecture.mdname the schema.Risk
--jsonoutput gains one key,schema_version. Nothing else in the payload changes.--outinto a directory that does not exist used to fail; it now creates it. The existing test that relied on that failure now uses a parent that is a file.kindorwhenvalue later needs a widening edit to the schema, whichschema_compatallows.Testing
On a Linux review host, at
f6c71e9(onmain506f7ba):make ci-local: 29 passed, 0 failed, 7 skipped (the Docker catalog smoke,test-latest, thecli-surfacepackaging step, conda-forge-deps without micromamba, docsdeploy, the pip-audit report, semgrep). 7,398 tests passed, 1 skipped; changed-line coverage 100% of 9 lines.tests/test_repo_budget_schema.py(19 cases): the--jsonoutput and the--outfile are the same valid stamped artifact; an empty tree is valid; a payload missing any required field, with a badkind,when,charsoroverlap, or with an extra key at the top, in an entry, intotalsor in a pair, is rejected. Dropping the stamp fails 4 of them; droppingwarningsfromrequiredfails 1; reopening any one nested object fails its case.main92d92d3 (test(llm): pin provider-call budgets for judge, panel, answer and validation paths #170, tests only) before opening; with the ten follow-up branches merged together, the full suite (7,447 passed, 1 skipped), the growth check,mypyandruffpass.f959a6f:make ci-local29 passed, 0 failed, 7 skipped; 7,427 tests passed, 1 skipped; changed-line coverage 100% of 9 lines.Checklist
pytestpassesruff,mypy, and schema checks pass.github/.licenserc.yaml)