Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Added

- **Codex CLI and Copilot CLI harness profiles for `repo run` and `repo reach`** — `--harness codex`, `codex-review`, `copilot` and `copilot-review` run oneDAL-style repository tasks under `codex exec`, Codex's native review mode (`codex exec review --commit HEAD`), `copilot -p` and `copilot -p` with a `/review`-prefixed prompt, so guidance arms can be compared per harness, not only under Claude Code. Their JSON traces convert to `events.jsonl` (`trace: codex-json`, `copilot-json`). A profile can now run the harness's own prompt (`native_prompt`) and convert its answer before grading (`answer_format: codex-review` appends a findings block parsed from Codex's review text); `repo reach` refuses a `native_prompt` profile. `bin_companions` mounts the helper files an executable needs beside it (Codex's `codex-code-mode-host`).

### Fixed

- **`repo reach` writes the profile's `config_files`** — only `repo run` wrote them, so a profile whose endpoint or hooks live in a config file (a Codex `config.toml` naming a provider) probed a different setup than it ran.
10 changes: 7 additions & 3 deletions dokimi/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,10 @@ next release.
it can see. A file comes back `loaded`, `truncated` (one token — the file was
cut), `fetched` (seen only after the agent read it), `not_loaded`, or `error`
(no usable answer). Harness behaviour is data, not code:
`dokimi/repos/profiles/claude-code.yaml` is a `harness_profile.v1`
file and any other harness is another YAML.
`dokimi/repos/profiles/` holds `harness_profile.v1` files for Claude
Code, the Codex CLI (`codex`, and its native review mode `codex-review`) and
the Copilot CLI (`copilot`, and `copilot-review`, a `/review`-prefixed prompt variant of it); any
other harness is another YAML.
- `dokimi/repos/budget.py` — `repo budget`: what the tree puts into an
agent's context when it starts at the root, in characters, with no LLM call.
Root CLAUDE.md files and their `@` imports, the root AGENTS.md files and their `@` imports, and
Expand All @@ -312,7 +314,9 @@ next release.
- `dokimi/repos/bases.py` — checks that need every task base: each
`base` must resolve, and the guidance globs are evaluated at each base.
- `dokimi/repos/events.py` — converts a harness trace to the
`events.jsonl` run trace.
`events.jsonl` run trace; `dokimi/repos/cli_traces.py` holds the Codex and
Copilot JSON converters, and `dokimi/repos/answers.py` the `answer_format`
conversions that turn a native review answer into a findings block.
- `dokimi/repos/l0/` — `repo scan` (L0): checks the links, paths,
identifiers, commands and build labels the guidance names against the same
tree (`repo_readiness.v1`), with no LLM call.
Expand Down
9 changes: 5 additions & 4 deletions dokimi/docs/preparing-a-repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,11 @@ effect. Targets skipped because a `CLAUDE.md` already exists are listed as
`bridge_skipped` in `meta.json`; `repo report` does not show them.

Loading changes between versions. Run `dokimi repo reach` for the harness and
version you use instead of relying on this table. Only the `claude-code` profile is
built in; for Codex or Copilot, pass a `harness_profile.v1` file with `--harness`
version you use instead of relying on this table. The `claude-code`, `codex`,
`codex-review`, `copilot` and `copilot-review` profiles are built in; for another
harness, pass a `harness_profile.v1` file with `--harness`
Comment on lines +216 to +218

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

documentation · low
Must-fix: This reach-probe guidance lists codex-review alongside the supported profiles without noting that repo reach --harness codex-review always fails: the profile sets native_prompt: true, and probe_files() rejects native-prompt profiles. Add the exception here and direct users to --harness codex for the probe, as the checklist later in this document already does.

([contract](repo-evaluation-contract.md)). Tool-use counts need a trace the profile
can convert, which today means `claude-stream-json`; a `text` trace gives no
can convert, which today means `claude-stream-json`, `codex-json` or `copilot-json`; a `text` trace gives no
events, turns or cost, so for such a harness `repo reach` can report a file as
loaded but never as fetched by the agent. For Claude Code it requires the `claude`
CLI, credentials and a mandatory `--model` flag; `repo --help` notes it costs one
Expand Down Expand Up @@ -281,5 +282,5 @@ Treat each item above as a hypothesis for your repository.
- C/C++: `compile_commands.json` covers every build variant; indexes are prebuilt if you offer navigation tools.
- Recurring review rules, curated, are in the review prompt (§6); `AGENTS.md` placement is not measured yet.
- A `CLAUDE.md` containing `@AGENTS.md` sits next to each `AGENTS.md` (§7).
- `dokimi repo reach` (only `claude-code` is built in; others need a `harness_profile.v1` file) confirms each harness you use loads the files you rely on.
- `dokimi repo reach` (`claude-code`, `codex`, `copilot` and `copilot-review` are built in; `codex-review` runs its own prompt and is refused; others need a `harness_profile.v1` file) confirms each harness you use loads the files you rely on.
- Each change was compared against the baseline on current models.
80 changes: 70 additions & 10 deletions dokimi/docs/repo-evaluation-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ SPDX-License-Identifier: Apache-2.0
> Slice S3 adds harness profiles (§6) and the reach probe (§7):
>
> ```bash
> python cli.py repo reach <source> --manifest <path> --model <id> [--harness claude-code]
> python cli.py repo reach <source> --manifest <path> --model <id> [--harness claude-code|codex|copilot|copilot-review|<profile.yaml>]
> [--bin <cli>] [--scenarios root,cwd,read] [--only <scenario>] [--dry-run]
> ```
>
Expand Down Expand Up @@ -417,8 +417,11 @@ reads the upstream base (`base_sha`) and the workspace start commit
`cache_read_tokens`, `cache_write_tokens`) over the same scope as `cost_usd`.
`usage_scope` is `tree` when they include subagents and helper models (Claude
Code's `modelUsage`), `main` when the harness reported the parent's only, and
`null` when it reported none. `subagent_calls` counts the parent's and
subagents' `Agent`/`Task` calls; `null` when the harness wrote no result record.
`null` when it reported none. Codex counts `cached_input_tokens` inside its
`input_tokens`; the converter moves them to `cache_read_tokens`, so
`input_tokens` is the uncached part in every cell that reports tokens, as with
Claude. `subagent_calls` counts the parent's and subagents' `Agent`/`Task`
calls; `null` when the harness wrote no result record.
`first_prompt_tokens` is what the first main-thread model call was sent
(`input + cache_creation + cache_read` tokens of that call, counted once per
message id, as `context trace` reads it): everything start-up loaded plus the
Expand Down Expand Up @@ -855,7 +858,7 @@ env_allow: [PATH, HOME, AWS_REGION, AWS_BEARER_TOKEN_BEDROCK, ANTHROPIC_API_KEY,
env_set: {CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: "1", DISABLE_AUTOUPDATER: "1"}
egress: ["bedrock-runtime.*.amazonaws.com", "api.anthropic.com"] # the only hosts the agent container reaches (§2)
endpoint_env: ANTHROPIC_BASE_URL # used by payload capture, if set
trace: claude-stream-json # converter to events.jsonl; or: text
trace: claude-stream-json # converter to events.jsonl; or: codex-json, copilot-json, text
guidance: # DECLARED; verified by the reach probe, never trusted
names: [CLAUDE.md, CLAUDE.local.md, AGENTS.md]
resolution: ancestors-of-cwd + lazy-on-subtree-access
Expand Down Expand Up @@ -904,8 +907,58 @@ args_if_present: # argv added after the "{tools}" element wh
Fix or remove the file in the task base; `--tools read` or `none` do not
pass it, so `repo run` does not check it there.

Profiles for other harnesses (Codex, Gemini CLI, Copilot CLI, Cursor agent,
Aider, OpenCode, in-house agents) follow the same shape. Their `guidance`
- `trace` names the converter of the harness's stdout to `events.jsonl`:
`claude-stream-json`, `codex-json` (`codex exec --json`), `copilot-json`
(`copilot -p --output-format json`) or `text` (stdout is the answer, no
events). Codex has no read tool, so its `read` events come from shell
commands that only print files (`cat`, `head`, `tail`, `sed -n`, `nl`).
Neither Codex nor Copilot reports a cost: `cost_usd` is `null` and a batch
budget counts each cell's cap.
- `bin_companions` names files the executable starts from its own directory.
`repo run` mounts the executable alone at `/eval/harness/<name>`, so each
companion is mounted read-only beside it, from the directory of the file
`--bin` resolves to (a symlink is followed); a missing one
stops the run before any agent starts. Codex 0.160 needs
`codex-code-mode-host`: every tool call goes through it.
- `repo reach` writes `config_files` into each scenario's config directory as
`repo run` does, with `{config_dir}` and `{support_dir}` as host paths.
- `native_prompt: true` marks a harness that runs its own built-in prompt, such
as a native review mode. `invoke` then passes no `{prompt}` (and there is no
`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`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

documentation · low
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.

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.

Fixed in 8ad1cb7: the contract now says a missing findings block means no review rather than a clean one, and that a priority outside P0-P3 gets severity null.

Comment thread
antonwolfy marked this conversation as resolved.
Resolved
keeps Codex's review text and appends a ```` ```json ```` block of findings
`{file, line, end_line, severity, priority, rule, message}` parsed from its
`- [P1] title — path:12-14` lines (a failed run, an empty answer or a `[Pn]`
header that does not parse gets no block, so no block means no review, not a clean one; a priority outside P0–P3 gets `severity` null): `file` relative to the workspace,
`severity` `blocker` (P0), `major` (P1) or `minor` (P2, P3), `rule` the title
and `message` the body.

Built-in profiles besides `claude-code`:

| profile | runs | trace | notes |
|---|---|---|---|
| `codex` | `codex exec --json … -- {prompt}` | `codex-json` | `CODEX_HOME` is the per-run config dir; no turn or spend flag, the timeout bounds a run; `none`/`read` get Codex's read-only sandbox, which needs unprivileged user namespaces |
| `codex-review` | `codex exec review --commit HEAD --json` | `codex-json` | `native_prompt`, `answer_format: codex-review`; review tasks only (the change under review is HEAD) |
| `copilot` | `copilot --prompt={prompt} --output-format json --allow-all-tools …` | `copilot-json` | `COPILOT_HOME` per run; a GitHub token as `COPILOT_GITHUB_TOKEN` (`GH_TOKEN` and `GITHUB_TOKEN` are not forwarded: Copilot leaves them readable by the agent's commands), or BYOK through the `COPILOT_PROVIDER_*` variables; `none` names a tool that does not exist, because an empty `--available-tools` leaves every tool on |
| `copilot-review` | as `copilot`, with the prompt `/review {prompt}` | `copilot-json` | a prompt variant of `copilot`, not Copilot's review agent: under `-p`, `/review` reaches the model as plain text, with the same system prompt and tools; the task prompt still asks for its answer format |

npm installs `codex` and `copilot` as Node launchers. A run mounts one file as
the harness, so `--bin` names the native binary the launcher starts
(`@openai/codex-<platform>/vendor/<triple>/bin/codex`,
`@github/copilot-<platform>/copilot`). To route a CLI to another endpoint,
copy its profile: for Copilot, set the `COPILOT_PROVIDER_*` variables (and
`COPILOT_OFFLINE=true` to skip GitHub sign-in); for Codex, add a `config.toml`
under `config_files` that defines a `model_providers` entry with the endpoint's
`base_url`, `wire_api = "responses"` and `env_key = "CODEX_API_KEY"` (the variable that
holds its key; without it Codex sends no `Authorization` header) and selects it with `model_provider`.
Add the endpoint's host to `egress` in both cases. The hosted pull-request
reviewers (Copilot code review, `@codex review`, CodeRabbit) are not CLIs and
have no profile.

Profiles for other harnesses (Gemini CLI, Cursor agent, Aider, OpenCode,
in-house agents) follow the same shape. Their `guidance`
blocks start as the vendor's documented behaviour and are corrected by the
reach probe. Loading changes between versions of one harness, so
reach results are keyed by version.
Expand Down Expand Up @@ -975,7 +1028,12 @@ per scenario).
- `class` is one of:
- `loaded`: both tokens reported;
- `truncated`: one token reported;
- `fetched`: reported only after the agent read the file with a tool;
- `fetched`: reported only after the agent read the file with a tool. For the
Codex and Copilot profiles a shell read counts only as a bare `cat`, `head`,
`tail`, `nl` or `sed -n`; for Codex, a command that is one such read of one
file and exits non-zero is not a read (the exit code of `cat a missing` does
not say which file failed, so both stay reads). A read through a pipe, `grep`
or `rg` is not seen, so such a file can be classed `loaded`;
- `not_loaded`;
- `error`: the scenario produced no usable answer: no answer, a non-zero
exit, or an error result.
Expand Down Expand Up @@ -1308,9 +1366,10 @@ python cli.py repo compare repo-runs/replay --baseline guidance:none --metric re
under `none`) and an
`id` hashing the profile's name, `invoke`, tool arguments, `env_set`,
`env_allow`, `config_dir_env`, `config_files`, `prompt_suffix`, `egress`,
`bridge`, the SHA-256 of the harness executable (`--bin`) and harness version.
`bridge`, `answer_format`, the SHA-256 of the harness executable (`--bin`),
the SHA-256 of each `bin_companions` file and harness version.
A rerun whose `id` differs (another `--tools`, a `--delegation` that changes the tool arguments, profile,
harness binary or harness version, or an edited `invoke`, `env_set`, `env_allow`, `config_dir_env`, `config_files`, `prompt_suffix`, `egress` or `bridge`) is refused before any agent starts, and
harness binary or harness version, or an edited `invoke`, `env_set`, `env_allow`, `config_dir_env`, `config_files`, `prompt_suffix`, `egress`, `bridge` or `answer_format`) is refused before any agent starts, and
`--force` or another `--batch` runs it. `--force` replaces the cells of the
run's plan only: if the batch dir holds finished cells outside that plan
whose `id` differs from this run's (e.g. `--reps 2`, then `--reps 1
Expand All @@ -1325,7 +1384,8 @@ python cli.py repo compare repo-runs/replay --baseline guidance:none --metric re
names a `dokimi:` grader (or a task directory that cannot be read) also stays on the built-in graders' sources.
- The agent's container mounts the workspace, the per-run `home`, `config` and
scratch directories (each `image.env` value under `{run_dir}/`), the caches,
the harness executable (`--bin`, read-only at `/eval/harness`) and the
the harness executable (`--bin`, read-only at `/eval/harness`, with its
`bin_companions` beside it, §6) and the
framework's helper scripts (read-only at `/eval/support`). Before a batch,
the harness must report its version inside the image, and a probe container
with the same mounts must see neither `/eval/content` nor `/eval/source`, no
Expand Down
Loading
Loading