Skip to content

feat(repo): process metrics in result.json, manifest process_metrics, grade optional for dokimi: graders - #157

Open
napetrov wants to merge 3 commits into
intel:mainfrom
napetrov:d4-process-metrics
Open

napetrov wants to merge 3 commits into
intel:mainfrom
napetrov:d4-process-metrics

Conversation

@napetrov

Copy link
Copy Markdown
Contributor

Part of #41 (step D4).

Summary

 run_cell
   convert(trace) -> events.jsonl
+  run_process_metrics(events, guidance.globs, manifest.process_metrics)
   run_entry("grade") -> grade
-  result.json {agent, grade}
+  result.json {agent, process, grade}
# result.json
process: {tool_calls: 10, commands: 4, failed_commands: 1, denied_commands: 1,
          guidance_read: [AGENTS.md, src/AGENTS.md], counters: {bazel_cmds: 2, icpx_missing: 1}}
# repo-eval.yaml
process_metrics:
  bazel_cmds: '\bbazel(?:isk)?\b'                             # command text (default)
  icpx_missing: {regex: "icpx is not found", match: output}   # text | output | any
  • New dokimi/repos/process_metrics.py; counts all events (parent and subagents). failed_commands = rc not 0/null; denied commands still count for counters (the agent asked for them), as in oneDAL's metrics.py.
  • repo validate refuses a regex that does not compile, a bad match, a bad name; process_metrics needs a runnable manifest.
  • entry_points.grade no longer schema-required (widening, v1 in place); check_repo requires it only when some task's grader does not start with dokimi:, and names those tasks. Generic, so it holds whether or not feat(repos): built-in review graders dokimi:review_seeds and dokimi:review_replay #120 lands first.
  • Task host: blocks were already validated by repo validate (feat(repo): task host requirements, unsupported instead of a false pass (#41 D3) #112); added a test that pins it.
  • Contract: §2 manifest rules, §4.1 result.json process table. Nothing in §3/§5/§8.

Evidence

Merge Danger

Door: two-way

Additive key in result.json; schema widened only.

Blast Radius: small

Readers of result.json that reject unknown keys would see process; none in-tree.

Checklist

  • DCO sign-off
  • scriv fragment
  • contract doc updated
  • pytest, ruff, mypy pass

🤖 Generated with Claude Code

… grade optional for dokimi: graders

result.json gains `process`, counted by the framework from events.jsonl:
tool_calls, commands, failed_commands, denied_commands and guidance_read
(read paths the guidance globs match). The manifest's process_metrics
maps a name to a regex over command text, output or both; repo validate
refuses a regex that does not compile. entry_points.grade is required
only when some task's grader is not a built-in dokimi: one.

Part of intel#41 (step D4).

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

codecov-commenter commented Oct 22, 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.55%. Comparing base (a44b3d0) to head (3c8a0cc).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #157      +/-   ##
==========================================
+ Coverage   91.54%   91.55%   +0.01%     
==========================================
  Files         222      223       +1     
  Lines       27369    27423      +54     
  Branches     4505     4510       +5     
==========================================
+ Hits        25054    25108      +54     
  Misses       1644     1644              
  Partials      671      671              
Files with missing lines Coverage Δ
dokimi/dokimi/repos/manifest.py 94.50% <100.00%> (+0.31%) ⬆️
dokimi/dokimi/repos/process_metrics.py 100.00% <100.00%> (ø)
dokimi/dokimi/repos/runner.py 93.86% <100.00%> (+0.14%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@antonwolfy antonwolfy 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.

Review at 343f7ac. The process-metrics code is clean and the counting rules match the contract. Two things are worth fixing before merge: the optional grade entry point has no runtime behind it at this head, and the one runner test cannot tell a working guidance_read / counters wiring from a broken one.

What I ran, on a Linux review host at 343f7ac:

  • make ci-local: 25 passed, 1 failed, 6 skipped. 6,731 tests, changed-line coverage passes. The failure is pip-audit on virtualenv 21.14.7 (CVE-2026-113722) from the existing locks, fixed on main by #152.
  • A reproduction of the first finding through repo run with the container runner faked.
  • A mutation run: 48 mutants of process_metrics.py, manifest.py and runner.py against the three test files that cover them; 18 survive, 17 of them real gaps (the second finding).

Checked, no issues

  • Schema: dropping required: ["grade"] only widens repo_manifest.v1; process_metrics is validated by both the schema and parse_counter.
  • Counting rules: failed_commands ignores rc null, denied commands still reach the counters, bad regex / bad match / bad name are refused with the metric named.
  • Offline: the new tests need no network or Docker.

return report


def grade_problems(manifest: RepoManifest, tasks: list[TaskSummary]) -> list[str]:

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.

A manifest without entry_points.grade and with only dokimi: graders passes repo validate, then every cell of repo run fails as a grader failure.

grade_problems returns [] for such a manifest, but nothing at this head runs a dokimi: grader. run_cell still calls run_entry(ctx, "grade", ...) (runner.py:216), and run_entry raises when the entry point is missing (grading.py:107). grep -rn 'dokimi:' dokimi/dokimi --include=*.py finds only the new BUILTIN_GRADER_PREFIX.

Reproduction: take the test_repo_run.py fixture, remove entry_points.grade, change the task graders to dokimi:calc, and run repo run --task fix_add. The cell's result.json grade is:

{"pass": null, "rc": 125, "status": "grader_failure", "success": false,
 "reasons": ["grade run failed: the manifest declares no `grade` entry point"]}

The description says the rule holds whether or not #120 lands first. It holds for validate, but not for run: a repository can pass validation and then pay for agent runs that all fail grading.

Suggestion: land this after the PR that adds the built-in grader dispatch, or keep grade required until then. If the PR stays as it is, add a test that runs a cell with a dokimi: grader and no grade entry point, so the gap is visible. The contract text at repo-evaluation-contract.md:197 also describes a built-in grader that does not exist at this head.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Resolved by merging intel/main (d9c92f4), which brings the #120 built-in grader dispatch: run_entry runs a dokimi: grader without entry_points.grade, so no runner change is needed. Pinned in 3c8a0cc by test_a_cell_graded_by_a_builtin_grader_needs_no_grade_entry_point (repo run on a manifest with no entry points, cell status graded).

assert result["grade"]["status"] == "graded" and result["grade"]["success"] is True
assert result["agent"]["cost_usd"] == 0.01 and result["agent"]["num_turns"] == 3
assert result["model_resolved"] == "m-1"
assert result["process"] == {"tool_calls": 1, "commands": 0, "failed_commands": 0, "denied_commands": 0,

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.

The runner test cannot tell a working guidance_read / counters wiring from a broken one.

The fixture manifest has no counters and its trace reads no guidance file, so the assertion expects "guidance_read": [] and "counters": {}. run_process_metrics (runner.py:236) is therefore unpinned.

Mutation check: each of these passes test_repo_process_metrics.py, test_repo_manifest.py and test_repo_run.py (194 tests):

  • is_guidance as lambda path: False, and as lambda path: True;
  • globs = ();
  • ctx.manifest.process_metrics replaced by {};
  • process = {} in place of None for an unreadable trace.

Three smaller gaps in test_repo_process_metrics.py also survive:

  • match: any that searches only the text (x_anywhere, line 58, already matches both commands by text, so the output half is never needed);
  • counters run over all events instead of command events, since no non-command event in the fixture carries text or output;
  • failed_commands counting only rc == 1 or rc > 0, since no test uses another non-zero rc.

Suggestion: give the fixture manifest one process_metrics entry and one guidance glob, add a trace that reads a matching file, and assert non-empty guidance_read and counters in result.json. Make x_anywhere match only the output. Add a read event with a text field, an rc of -9, and a trace that fails to convert (process is None).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added in 3c8a0cc: the fixture manifest has process_metrics (text and output counters) and the guidance glob; test_process_metrics_reach_result_json asserts non-empty guidance_read and counters in result.json, and test_an_unreadable_trace_leaves_process_null_and_still_grades covers process: null. Unit tests: test_any_matches_the_output_when_the_text_does_not, test_counters_search_command_events_only, test_failed_commands_counts_every_non_zero_rc (rc 2, -9, 137). I did not re-run the mutation set.

… cell without a grade entry point

The runner fixture now has process_metrics and a guidance glob, with a trace
that reads a guidance file and runs a failing command; a null process for an
unreadable trace is covered. Process-metric unit tests gain output-only
'any' matches, command-only counting and non-1 rc values.

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

This branch has not been deployed

No deployments
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.

3 participants