Repository navigation
Conversation
Add built-in harness_profile.v1 files codex, codex-review, copilot and copilot-review, so repo run and repo reach can compare guidance arms under codex exec, codex exec review --commit HEAD, copilot -p and Copilot's /review agent, not only Claude Code. - trace: codex-json and copilot-json convert the CLIs' JSON event streams to events.jsonl (cli_traces.py); Codex read events come from shell commands that only print files. - native_prompt: a profile may run the harness's own prompt; reach refuses it. - answer_format: codex-review appends a findings block parsed from Codex's review text (answers.py), so review graders read it unchanged. - bin_companions: helper files mounted beside the executable (Codex's codex-code-mode-host, without which no tool call runs in the container). - repo reach now writes the profile's config_files, as repo run does. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #116 +/- ##
==========================================
+ Coverage 93.50% 93.53% +0.02%
==========================================
Files 273 276 +3
Lines 35569 36153 +584
Branches 6040 6174 +134
==========================================
+ Hits 33260 33814 +554
- Misses 1492 1509 +17
- Partials 817 830 +13
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
Trace conversion can distort evaluation results, and reach configuration produces invalid JSON on Windows.
4 open issues
What changed in this PR
Adds Codex and Copilot CLI harnesses so repository evaluations can compare guidance across agents, including native review modes.
Changes:
- Adds four harness profiles and optional profile settings.
- Converts CLI traces and native review answers into evaluation artifacts.
- Applies profile configuration during reach probes, with tests and documentation.
| File | Description |
|---|---|
| dokimi/tests/test_repo_reach.py | Tests reach configuration generation. |
| dokimi/tests/test_repo_cli_harnesses.py | Tests profiles, converters, and runner integration. |
| dokimi/dokimi/schemas/harness_profile.v1.json | Adds optional harness capabilities. |
| dokimi/dokimi/repos/runner.py | Mounts companion binaries and converts answers. |
| dokimi/dokimi/repos/reach.py | Writes configuration and rejects native prompts. |
| dokimi/dokimi/repos/profiles/copilot.yaml | Adds Copilot execution profile. |
| dokimi/dokimi/repos/profiles/copilot-review.yaml | Adds Copilot review profile. |
| dokimi/dokimi/repos/profiles/codex.yaml | Adds Codex execution profile. |
| dokimi/dokimi/repos/profiles/codex-review.yaml | Adds Codex native review profile. |
| dokimi/dokimi/repos/harness_profile.py | Parses and validates new settings. |
| dokimi/dokimi/repos/events.py | Dispatches new trace formats. |
| dokimi/dokimi/repos/cli_traces.py | Normalizes Codex and Copilot events. |
| dokimi/dokimi/repos/answers.py | Converts native review findings. |
| dokimi/docs/repo-evaluation-contract.md | Documents profiles and evaluation behavior. |
| dokimi/docs/architecture.md | Describes new modules and harnesses. |
| dokimi/changelog.d/20261019_050000_nikolay.a.petrov_codex_copilot_profiles.md | Records harness additions and reach fix. |
Review effort: Balanced
…d, cd commands, and incomplete commands On Windows, str(Path) contains backslashes that produce invalid JSON escape sequences when inserted into configuration files. Use Path.as_posix() for both config_dir and support_dir to ensure forward slashes. shell_reads() now splits only on unquoted shell operators (&&, ||, ;, newline), preserving quoted arguments like sed -n '1p;2p'. Previously, it split all semicolons regardless of quoting context, breaking multi-range sed commands. Track directory changes from cd commands in shell scripts so subsequent file reads are resolved to the correct path. For example, 'cd sub && cat AGENTS.md' now correctly reports reading 'sub/AGENTS.md'. Preserve incomplete commands (item.started without item.completed) in Codex JSON traces. When an agent times out mid-command, record the command with rc: null per contract §4.1, instead of losing it entirely. Correlate started and completed items by command text to update rc on completion. Add regression tests for all three fixes. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Create tests/__init__.py and normalize test module imports to use explicit 'tests.' prefix. This resolves the mypy error where artifact_fixtures was found under two module names. All imports of test fixtures now consistently use the 'tests.' prefix (repo_eval_fixture, artifact_fixtures, test_process). Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Fix remaining imports from conftest, test_novelty_analyze, and test_repo_reach to use explicit 'tests.' prefix for consistency now that tests is a proper package. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Fix remaining import from test_novelty_gate in test_novelty_items.py to use explicit 'tests.' prefix for consistency. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
There was a problem hiding this comment.
🟡 Changes recommended
Overlapping identical Codex commands produce incorrect trace events used by graders.
7 open issues
Track overlapping identical commands by item ID · New Fix remaining sibling imports after converting tests to a package Remove duplicate event annotation Correlate command events by item ID Normalize expected paths in Windows test Compose and normalize relative command paths Resolve reads relative to the execution directory
Review effort: Balanced
…ay uv.lock Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 27911d6. The profiles, schema widening and mounting logic hold up, but the trace converters have several wrong-result cases, and the Codex findings parser is fragile. Four things are worth fixing before merge; the inline comments have the inputs and outputs.
What I ran, on a Linux review host at 27911d6:
make ci-local: 19 passed, 0 failed, 4 skipped (docker/semgrep/jobs that do not run on a PR); changed-line coverage gate passes.- Reproductions for the code findings, with no model or network calls.
- A mutation run over the new tests: 36 of 83 mutants of
cli_traces.pypass the suite; two of the severity-mapping mutants inanswers.pypass too.
I agree with Copilot that Codex commands are matched by text, not item.id; it still holds (two overlapping make build items give rc [None, 0, 1]).
Checked, no issues
- Schema: the
harness_profile.v1.jsonchange only widens thetraceenum and adds optional keys, so no version bump is needed;schema_compatpasses against the base;bin_companionsnames reject..and/. - Docs: flags, keys, section numbers and the profile table match the code; the changelog fragment is present; no
tests/__init__.pyoruv.lockremains after the reverts. - Mounts and reach: a missing companion fails with a clear error, a symlinked
--binfinds the companion beside the real file, andrepo reachrefusesnative_promptprofiles before--dry-run.
`cat 'a 2>/dev/null b'` reads the file named `a 2>/dev/null b`; the harmless-redirect pattern now runs on the unquoted text, as the stderr file redirect already did. Thread: PRRT_kwDOVBg7g86x2UDw Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…oses the directory `builtin cd "$D"; cat AGENTS.md` kept the starting directory and recorded AGENTS.md. The computed-command branch now skips the same prefixes as a literal command before it checks for a directory builtin. Thread: PRRT_kwDOVBg7g86x2UDx Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
A `view` that completes with success=false, and a bash call that is one part naming one file and exits non-zero, now drop their read events, as the Codex converter does. A compound command keeps its reads. Thread: PRRT_kwDOVBg7g86x2UD3 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Replacing a companion such as codex-code-mode-host kept the same id, so repo run could reuse a cell made with the old helper. execution_record hashes each companion beside the resolved executable, where harness_mounts takes it from. Thread: PRRT_kwDOVBg7g86x2UD6 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
`config_files: {".": ...}` passed the schema and then raised
IsADirectoryError from write_config, a traceback in repo reach and repo
run. The name pattern now excludes . and .., so the profile is refused
with a ProfileError before anything is written.
Thread: PRRT_kwDOVBg7g86x2UD-
Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
scripts/check_comment_blocks.py (from main) caps a comment block at two lines and covers YAML. The rationale stays in the contract's §9 profile table and routing paragraph; the comments keep the constraint and point there. Thread: PRRT_kwDOVBg7g86x0azJ Thread: PRRT_kwDOVBg7g86x0azM Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
The harness test file passed the 1000-line growth cap (scripts/check_growth.py, from main). The traces section moves whole, unchanged. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…tripped `cat \" 2>&1 "z"` was masked as if \" opened a quoted string, so the fd dup stayed in the command and was recorded as a read of `2>&1`. Backslash escapes are now masked before quotes are matched. Thread: PRRT_kwDOVBg7g86x2UDw Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…gests Thread: PRRT_kwDOVBg7g86x2UD6 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…schema Tightening the name pattern of harness_profile.v1 in place fails schema_compat against main, which already ships v1. The schema is back as it was, and parse_profile refuses the two names with a ProfileError. Thread: PRRT_kwDOVBg7g86x2UD- Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…iles are Thread: PRRT_kwDOVBg7g86x0azJ Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
80736ee to
aa9922b
Compare
…com/napetrov/dokimi into HEAD Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com> # Conflicts: # dokimi/dokimi/repos/answers.py # dokimi/dokimi/repos/profiles/codex-review.yaml # dokimi/dokimi/repos/profiles/codex.yaml # dokimi/dokimi/repos/profiles/copilot-review.yaml # dokimi/dokimi/repos/profiles/copilot.yaml # dokimi/tests/test_repo_cli_harnesses.py # dokimi/tests/test_repo_cli_pins.py
Thread: PRRT_kwDOVBg7g86x21H4 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…e body-split test Thread: PRRT_kwDOVBg7g86x21H4 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
|
This review has no body text, and each of its inline threads has its own answer in the thread, so nothing in the review itself needs a change. |
|
This review has no body text, and each of its inline threads has its own answer in the thread, so nothing in the review itself needs a change. |
|
Both inline comments of this review (comment blocks in the profiles) are fixed in 902d3d6 and answered in their threads. |
|
(a) Waiting on a decision before I change this: an agent run can have an earlier message with a |
|
This review has no body text, and its inline thread has its own answer in the thread, so nothing in the review itself needs a change. |
| `prompt_suffix`), the agent never sees the task prompt, and `repo reach` | ||
| refuses the profile. Use such a profile only on tasks whose grader reads what | ||
| it answers, which `answer_format` provides. | ||
| - `answer_format` converts the final answer before grading. `codex-review` |
There was a problem hiding this comment.
The answer_format text says codex-review appends a findings block, but convert_answer (repos/answers.py) leaves the answer unchanged in three cases: the run failed, the answer is empty, or the text has more [Pn] markers than parsed findings (format drift). It also sets severity to null for a priority outside P0–P3. A reader can't tell from the doc that a missing block means "no review" or "drifted format", not a clean review. A clean review gets []. Add one sentence covering these cases.


Summary
repo runandrepo reachhad one built-in harness, Claude Code. This adds the Codex CLI and the Copilot CLI, including each CLI's own review mode, so the same task can be compared across guidance arms × harness × model.harness_profile.v1is widened in place with three optional keys:Things that only show up when running the real CLIs:
codex review --commitrefuses a prompt.codex-code-mode-hostbeside its binary, so a single-file mount leaves it with no tools.--available-toolslist leaves every tool on, sononenames a tool that doesn't exist.--binhas to name the native binary.Not here: hosted PR reviewers (Copilot code review,
@codex review, CodeRabbit). They are not CLIs and need a separate PR-replay adapter.Evidence
Before:
repo run --harness codexfails withno harness profile 'codex' (built-in: claude-code). A profile with a Codex provider inconfig_filesprobed viarepo reachhitwss://api.openai.comwith a 401, because reach never wrote the file.After: live runs on oneDAL
review_seeded_fc(forkdev/agent-evalsc4e2667f5, imageagent-benchmark/onedal:a28e8a6c33a7, gpt-6-luna through a LiteLLM proxy,guidance:raw, 1 rep):The first codex-review run, without
bin_companions, answered "the repository command tool failed to start" and got recall 0.0.Live
repo reachon oneDAL main 7f6d9f86 (3 scenarios, gpt-6-luna):Both CLIs load AGENTS.md from the git root down to cwd, and reading a file in a subtree does not pull in that subtree's AGENTS.md. In
read=Codex skipped the read, because the reach ask says "use the Read tool" and Codex has no tool by that name. Rewording the ask is left for a follow-up: it would change Claude's recorded ask too.Tests:
tests/test_repo_cli_harnesses.py(29 tests) covers:shell_reads, including pipes, redirects andsed -i;codex_review_findings;repo runcell that grades a native review answer;bin_companionsmounted, or a stop before any agent runs.test_repo_reach.pyadds a test that a profile'sconfig_filesreach the probe.make ci-local: every row passes excepttest. There, every PR-touched test passes, but 1–3 unrelated tests fail at random, a different one each run:test_processPopen ResourceWarning,test_container_agent"AF_UNIX path too long". This happens under 224 xdist workers on a shared box.pytest -n 32gives 5208 passed, 2 skipped. Those two files alone: 149 passed.Merge Danger
Door: two-way
New profiles and optional schema keys only. Profiles that already exist are left as they were.
schema_compatpasses against the base.Blast Radius:
repo reachEvery reach run now writes the profile's
config_files. Forclaude-codethat adds the no-background hooksettings.jsonto each scenario's config dir. Reach scenarios run with toolsnone/read, so the Bash hook never fires. Onlyrepo run/repo reachread the new keys.🤖 Generated with Claude Code