fix: mend the guard, the suite, and the validator #208

Merged
claudiomaradonna merged 4 commits from fix/review-defects into main 2026-11-10 09:57:30 +01:00
Collaborator

Why

A review of the source on 2026-11-10 reproduced three defects on main.
An agent that edits a file in a submodule, in the worktree of its own
change, was refused by the main-checkout guard and told to open a
worktree it was already in, so a project with submodules could change
them only around the file-editing tools. A maintainer whose Git
configuration signs commits had every fixture commit of
bash tests/verify-agent-config.sh signed with their key, and in an
agent session, where Claude Code's sandbox blocks the signing agent, saw
22 of the suite's areas stop. And a repository whose
.agents/scripts/run-sandboxed.sh was missing or had lost its
executable mode passed the validator, though the run-sandboxed skill
calls the script directly.

Set aside: refusing a submodule's files everywhere with a reason of
their own, which keeps them out of the editing tools; turning off
signing in each fixture, which leaves the machine's other settings in
play; and checking the script in every repository, which would fail one
that dropped the skill.

What changed

The guard judges a submodule's file by the worktree of its outermost
superproject: the edit passes in a linked worktree and in a main
checkout off its main branch, and is refused in a main checkout on its
main branch or nested in another repository, where the refusal now names
the file by its path in the superproject. A member clone in an umbrella
is judged as before.

The suite runs Git without the machine's global and system
configuration, so its result no longer depends on who runs it.

The validator checks run-sandboxed.sh as it checks the hooks, tracked,
present, and executable with Git mode 100755, in the source and in a
repository that keeps the run-sandboxed skill.

How to verify

The guard, from an empty directory, with <checkout> this branch's
checkout:

git init -q -b main lib && git -C lib commit -q --allow-empty -m lib
git init -q -b main app && git -C app commit -q --allow-empty -m app
git -C app -c protocol.file.allow=always submodule --quiet add ../lib vendor/lib
git -C app commit -qm submodule
git -C app worktree add -q -b feat/x .worktrees/feat/x main
git -C app/.worktrees/feat/x -c protocol.file.allow=always submodule --quiet update --init
for dir in app/.worktrees/feat/x app; do
  printf '{"tool_name":"Edit","cwd":"%s","tool_input":{"file_path":"vendor/lib/f.c"}}' "$PWD/$dir" |
    <checkout>/.agents/hooks/main-checkout-guard.sh; echo "exit $?"
done

The worktree's edit prints exit 0, and the main checkout's is refused
with "vendor/lib/f.c is in the main checkout … on its main branch main"
and exit 2; main refuses both.

The suite: with a file holding [commit] gpgsign = true and
[gpg] program = false,
GIT_CONFIG_GLOBAL=<file> bash tests/verify-agent-config.sh ends with
its line "all … agent configuration tests passed"; on main its areas
stop with "gpg failed to sign the data".

The validator:
git update-index --chmod=-x .agents/scripts/run-sandboxed.sh, then
scripts/verify-agent-config.sh prints "run-sandboxed.sh must be
tracked, present, and executable, with Git mode 100755" and exits 1,
where main reports the source valid; --chmod=+x restores it.

The six checks of docs/MAINTENANCE.md pass on the tip, the suite with
no test skipped; the six new submodule tests and the three new validator
tests fail on main, and the two pins pass there. Not tried: Codex and
OpenCode at run time.

Considerations

A file in a submodule beneath a submodule whose path ends in a newline
is refused everywhere, since the guard cannot resolve its superproject.

A reviewer's finding that the pin of the refusal in a main checkout and
the test of the refusal's new text send the same event is set aside: the
pin passes on main and on the tip, and the second test fails on
main.

## Why A review of the source on 2026-11-10 reproduced three defects on `main`. An agent that edits a file in a submodule, in the worktree of its own change, was refused by the main-checkout guard and told to open a worktree it was already in, so a project with submodules could change them only around the file-editing tools. A maintainer whose Git configuration signs commits had every fixture commit of `bash tests/verify-agent-config.sh` signed with their key, and in an agent session, where Claude Code's sandbox blocks the signing agent, saw 22 of the suite's areas stop. And a repository whose `.agents/scripts/run-sandboxed.sh` was missing or had lost its executable mode passed the validator, though the `run-sandboxed` skill calls the script directly. Set aside: refusing a submodule's files everywhere with a reason of their own, which keeps them out of the editing tools; turning off signing in each fixture, which leaves the machine's other settings in play; and checking the script in every repository, which would fail one that dropped the skill. ## What changed The guard judges a submodule's file by the worktree of its outermost superproject: the edit passes in a linked worktree and in a main checkout off its main branch, and is refused in a main checkout on its main branch or nested in another repository, where the refusal now names the file by its path in the superproject. A member clone in an umbrella is judged as before. The suite runs Git without the machine's global and system configuration, so its result no longer depends on who runs it. The validator checks `run-sandboxed.sh` as it checks the hooks, tracked, present, and executable with Git mode 100755, in the source and in a repository that keeps the `run-sandboxed` skill. ## How to verify The guard, from an empty directory, with `<checkout>` this branch's checkout: ```bash git init -q -b main lib && git -C lib commit -q --allow-empty -m lib git init -q -b main app && git -C app commit -q --allow-empty -m app git -C app -c protocol.file.allow=always submodule --quiet add ../lib vendor/lib git -C app commit -qm submodule git -C app worktree add -q -b feat/x .worktrees/feat/x main git -C app/.worktrees/feat/x -c protocol.file.allow=always submodule --quiet update --init for dir in app/.worktrees/feat/x app; do printf '{"tool_name":"Edit","cwd":"%s","tool_input":{"file_path":"vendor/lib/f.c"}}' "$PWD/$dir" | <checkout>/.agents/hooks/main-checkout-guard.sh; echo "exit $?" done ``` The worktree's edit prints `exit 0`, and the main checkout's is refused with "vendor/lib/f.c is in the main checkout … on its main branch main" and `exit 2`; `main` refuses both. The suite: with a file holding `[commit] gpgsign = true` and `[gpg] program = false`, `GIT_CONFIG_GLOBAL=<file> bash tests/verify-agent-config.sh` ends with its line "all … agent configuration tests passed"; on `main` its areas stop with "gpg failed to sign the data". The validator: `git update-index --chmod=-x .agents/scripts/run-sandboxed.sh`, then `scripts/verify-agent-config.sh` prints "run-sandboxed.sh must be tracked, present, and executable, with Git mode 100755" and exits 1, where `main` reports the source valid; `--chmod=+x` restores it. The six checks of `docs/MAINTENANCE.md` pass on the tip, the suite with no test skipped; the six new submodule tests and the three new validator tests fail on `main`, and the two pins pass there. Not tried: Codex and OpenCode at run time. ## Considerations A file in a submodule beneath a submodule whose path ends in a newline is refused everywhere, since the guard cannot resolve its superproject. A reviewer's finding that the pin of the refusal in a main checkout and the test of the refusal's new text send the same event is set aside: the pin passes on `main` and on the tip, and the second test fails on `main`.
No test guards the refusal of an edit in a submodule of a main
checkout on its main branch, which the fix for submodules in linked
worktrees keeps.
The fixtures' commits read the machine's Git configuration, so one
that signs commits had each signed with the user's key, and 22 areas
stopped where the signing could not run, as inside Claude Code's
sandbox. The library now runs Git without the global and system
configuration, as evals/run.sh and run-sandboxed.sh do.
The guard took a submodule's checkout for a clone nested in another
repository, as an umbrella's member is, and refused each edit of its
files, in the change's own linked worktree too, advising a worktree
the agent was already in. A submodule is part of the worktree that
holds it, so the worktree of its outermost superproject now decides,
and the refusal names the file by its path there.
fix(validator): check the sandbox script's mode
All checks were successful
Maintenance / checks (pull_request) Successful in 4m21s
Maintenance / checks (push) Successful in 4m3s
13e818100f
The run-sandboxed skill calls .agents/scripts/run-sandboxed.sh
directly, the one form Claude Code's settings run outside its sandbox,
so a checkout that loses the script or its executable mode fails every
sandboxed run while the validator passed. The validator now checks the
script as it checks the hooks, in the source and wherever a repository
keeps the skill.
claudiomaradonna deleted branch fix/review-defects 2026-11-10 09:57:34 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/agent-foundry!208
No description provided.