Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bff1c3f
fix(repo): Claude Code Bash reads count as reads; bash= reach scenario
antonwolfy Nov 2, 2026
862dc49
fix(repo): a cd in a job or pipeline does not move the Bash shell
antonwolfy Nov 2, 2026
8f2b8de
fix(repo): settle Claude Code Bash reads once the trace ends
antonwolfy Nov 2, 2026
aa0c86f
fix(repo): a refused or failed read is no read in reach or skill use
antonwolfy Nov 2, 2026
d0bb1ab
fix(repo): shell-quote the probe path in the bash= reach prompt
antonwolfy Nov 2, 2026
261b310
test(repo): POSIX paths in the fake Bash commands of the bash= tests
antonwolfy Nov 2, 2026
8be264e
fix(repo): a brace group's separators do not end the list around it
antonwolfy Nov 2, 2026
444aec9
fix(repo): a computed cd in a job or a pipeline moves no Bash shell
antonwolfy Nov 2, 2026
f05363f
fix(repo): one moved Bash shell for the parent and its subagents
antonwolfy Nov 2, 2026
fe82755
fix(repo): a refused Skill call is no use of the skill
antonwolfy Nov 2, 2026
0e16f14
fix(repo): a failed cd-then-read command is no read
antonwolfy Nov 2, 2026
58920c4
fix(repo): a refused Bash read after a cd stays, denied
antonwolfy Nov 2, 2026
ff48bb1
fix(repo): eval, source and time cd move the Bash shell too
antonwolfy Nov 2, 2026
61a34a3
docs(repo): tool_calls counts kept shell reads, denied ones too
antonwolfy Nov 2, 2026
6d06087
fix(repo): a failed Skill call is no use of the skill
antonwolfy Nov 2, 2026
3a5eabf
fix(repo): a cd $(...) in a pipeline moves no Bash shell
antonwolfy Nov 2, 2026
13f858b
fix(repo): a failed time cd-then-read command is no read
antonwolfy Nov 2, 2026
8ce0a93
fix(repo): follow a brace group past the $( ) and groups in it
antonwolfy Nov 2, 2026
3467d96
fix(repo): a directory builtin in a job or a pipe keeps the directory
antonwolfy Nov 2, 2026
e60774d
fix(repo): a failed read naming two files keeps the one it knows
antonwolfy Nov 2, 2026
9515e0b
fix(repo): a builtin in a job or a pipe leaves a later || its directory
antonwolfy Nov 2, 2026
7ba6c6a
fix(repo): a quoted or escaped directory builtin name is the builtin
antonwolfy Nov 2, 2026
e61e812
fix(repo): a directory builtin the parser does not follow moves it
antonwolfy Nov 2, 2026
33634a8
fix(repo): only the command word can name a directory builtin
antonwolfy Nov 3, 2026
1e5ccd7
refactor(repo): move a shell command's word helpers to shell_words
antonwolfy Nov 3, 2026
f7f4f65
fix(repo): time is the keyword only as the first unquoted word
antonwolfy Nov 3, 2026
ba846db
fix(repo): a brace group holding one read is that read
antonwolfy Nov 3, 2026
87ba817
fix(repo): a refused relative read after a move has no path
antonwolfy Nov 3, 2026
226a04c
feat(repo): count the shell reads at a directory not known
antonwolfy Nov 3, 2026
c51f68a
test(repo): pin a failed cd continued over a line as no read
antonwolfy Nov 3, 2026
b52a3e1
fix(repo): a hidden group's reads are not counted as unknown
antonwolfy Nov 3, 2026
75d06d4
Merge main into feat/claude-bash-reads
antonwolfy Nov 3, 2026
8b08665
docs(repo): reviewing.md says which shell reads guidance_read counts
antonwolfy Nov 3, 2026
4597bc3
Merge main into feat/claude-bash-reads
antonwolfy Nov 3, 2026
77a3bdd
fix(repo): repo report and compare show process:unknown_reads
antonwolfy Nov 3, 2026
b6ce65f
fix(repo): time with assignments, nested case, braces on a case part
antonwolfy Nov 3, 2026
7434efd
fix(repo): a failed one-file read adds nothing to unknown_reads
antonwolfy Nov 3, 2026
92c790d
fix(repo): a leading redirection is not a cd's command word
antonwolfy Nov 3, 2026
e8c06f0
fix(repo): a redirection before a prefix's options hides no cd
antonwolfy Nov 3, 2026
31d8499
Merge main into feat/claude-bash-reads
antonwolfy Nov 4, 2026
2f5dfd3
docs(repo): first_useful.steps counts a Claude Bash read as one more …
antonwolfy Nov 4, 2026
21e0690
fix(repo): the bash= probe may run only the cat it names
xaleryb Nov 4, 2026
4ed00e4
Merge main into feat/claude-bash-reads
xaleryb Nov 4, 2026
5aab99f
refactor(repo): keep repo.py and test_repo_useful.py under the growth…
xaleryb Nov 4, 2026
1751a05
fix(repo): a negated printer is no read
xaleryb Nov 4, 2026
e4e5711
fix(repo): a negated read adds nothing to unknown_reads
antonwolfy Nov 4, 2026
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,12 @@
<!--
Copyright (C) 2026 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->

### Changed

- **A Claude Code `Bash` call that prints a file is a read, as a Codex or Copilot shell command is** — the `claude-stream-json` converter now gives a `read` event, before the `command` event, for each file a Bash command only prints (a bare `cat`, `head`, `tail`, `nl` or `sed -n`, after any `cd` in the same command: `cd benchmarks; cat AGENTS.md` reads `benchmarks/AGENTS.md`). So `result.json` `process.guidance_read` now counts guidance printed through Bash, where it counted only the Read tool before, and means the same for the three harnesses; `tool_calls` counts the new read events too, a `cat` of an installed skill's `SKILL.md` counts the skill as used, and a `cat` of a file a `patch:` arm added counts in `uptake.reads`. A command that is one read of one file and fails (`cat AGENTS.md` where there is none), alone, in a brace group (`{ cat AGENTS.md; }`) or after a `cd` (`cd sub && cat AGENTS.md`, `time cd`, `command cd`, `builtin cd` or `X=1 cd` too, which Codex and Copilot commands counted as a read before), gives no read, but one naming two files keeps its reads for all three, even when only one of them is known (`cd -; cat missing.md /ws/AGENTS.md`, whose read Codex and Copilot commands dropped before); a refused one gives denied reads; a pipe, `grep` or `rg` gives none, nor does a negated read (`! cat AGENTS.md`), whose exit says nothing of the file. Claude Code keeps the shell's directory between Bash calls, so after a call that ran a `cd`, `pushd`, or an `eval`, `source` or `.` (which may run a `cd`) in that shell (not in a subshell, pipeline or background job: `cd sub &` moves nothing, nor does a refused call), later relative reads are not recorded (absolute ones are), the parent's and every subagent's alike, since a subagent may share the parent's shell. For all three harnesses, a backgrounded or piped `cd`, `pushd`, `eval`, `source` or `.` no longer loses the directory for the rest of its command, a later `||` branch included (`source env.sh & cat AGENTS.md` and `source env.sh & false || cat AGENTS.md` read `AGENTS.md`), a `cd` inside `$( )`, backticks or `( ... )` no longer moves the shell (`(true; cd sub); cat AGENTS.md` reads `AGENTS.md`), a brace group is followed through the `$( )` or nested groups in it (`{ cd $(pwd); } | cat` moves nothing), and a directory builtin whose name is quoted or escaped is that builtin (`"source" "$ENV"` and `\cd "$D"` lose the directory, and `"cd" sub && cat AGENTS.md` that fails gives no read), and a command the parser does not fully follow whose command word, after `builtin`, `command` or `time` and their options (and assignments after `time`: `time X=1 cd sub` runs the `cd` in the shell), names a directory builtin (`X="a b" cd "$D"`, `time -p cd sub`, `command -p cd sub`, `builtin -- cd sub`; not `time git add .` or `command -v cd`) counts as moving the shell, as does one in a `case` arm, while a `time` after an assignment or quoted or escaped (`X=1 time cd sub`, `\time cd sub`) runs /usr/bin/time and moves nothing. In `repo reach`, a Bash read of a guidance file now makes it `fetched`. A read that was refused or failed, by any tool (the Read tool's too, before this change), no longer makes a file `fetched` in `repo reach` or its receipt's `states.accessed` true, nor counts a skill whose `SKILL.md` it named as used; nor does a refused or failed `Skill` tool call (a Claude Code `Skill` event now carries `rc`, `1` when the call failed), and a failed read of a file a `patch:` arm added no longer counts in `uptake.reads`; the event stays in `events.jsonl`; a refused relative Bash read after a move stays with no `path`, since which file it named is not known. `first_useful.steps` counts events, so a Claude Code run that prints a file through Bash before its first useful result shows one step more than before (`cat AGENTS.md`, then a passing `pytest`: 3, was 2), and `issued_s` is unchanged; `repo compare` pairs steps with batches run before this change on that basis. `docs/repo-evaluation-contract.md` §4.1, §7 and §7.1 say so.

### Added

- **`process.unknown_reads` in `result.json`** — the relative shell reads a trace made at a directory the converter could not follow (after `source .venv/bin/activate`, `cd -`, or a `cd` in an earlier Claude Code Bash call), which give no `read` event, for Claude Code, Codex and Copilot alike; `0` when there are none. A `guidance_read` of `[]` with `unknown_reads` above 0 means not known, not none read. `repo report` and `repo compare` show it as `process:unknown_reads`, after `process:guidance_read`. `docs/repo-evaluation-contract.md` §4.1 says so.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!--
Copyright (C) 2026 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->

### Added

- **A `bash=<dir>` reach scenario** — `repo reach --scenarios bash` runs, for each guidance directory, a scenario started at the root with the profile's new `bash` tool mode (`claude-code`: `--tools Bash`) that tells the agent to `cat <dir>/REACH_PROBE.txt` (the path shell-quoted, so a space or `;` in a directory name stays one operand) and then list tokens: it shows whether a shell read of a nested file loads that directory's guidance, as `read=<dir>` shows for the Read tool. The default stays `root,cwd,read`, so a probe costs no more unless asked; `--dry-run` lists the bash scenarios and `--only bash=<dir>` picks one. A profile without a `bash` tool mode (`codex`, `copilot`) asked for `--scenarios bash` is a usage error (exit 2) naming the profile. `harness_profile.v1` accepts an optional `bash` key under `tools` (not under `delegation.none`, so `repo run --tools bash --delegation none` is refused); the receipt treats a `bash=<dir>` run as it does `read=<dir>`. The scenario runs a shell on the host, with the harness's credentials and network, so `claude-code`'s `bash` mode adds a PreToolUse hook that blocks every Bash call but the exact `cat` that `repo reach` names in `DOKIMI_REACH_COMMAND`, and blocks every call when the hook itself fails: a `CLAUDE.md` in the probed repository cannot make the probe run anything else.
6 changes: 5 additions & 1 deletion dokimi/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,11 @@ next release.
`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; `dokimi/repos/cli_traces.py` holds the Codex and
Copilot JSON converters, and `dokimi/repos/answers.py` the `answer_format`
Copilot JSON converters and the parser of the files a shell command prints
(`dokimi/repos/shell_split.py` splits the command into its parts, and
`dokimi/repos/shell_words.py` finds a part's command word and the
directory builtins it runs),
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
Expand Down
Loading
Loading