Repository navigation
feat(call-agent): optional cwd and permission-mode for sandboxed runs - #5
Conversation
…nd-permission-mode-rebased
main cut the 0.1.1 release while this branch was open. The automatic merge folded this branch's changelog entry into the 0.1.1 section, which would have claimed the feature shipped in a release it is not in; moved back under a fresh Unreleased heading above 0.1.1, with the installer entry left in 0.1.1 where it belongs.
|
Updated for the One thing the automatic merge got wrong, corrected by hand: it folded this branch's changelog entry into the Versions now match Separate pre-existing issue, not touched here: on 73 tests pass on the merged content, and the consuming runner's gate re-probed green against it: |
Summary
Two optional keyword-only arguments on
call_agent, threaded throughfan_outanddeliver.run:cwd— runs theclaudesubprocess in that directory, validated to exist first so anunusable path raises
AgentErrorbefore any process starts. Insidefan_outthat surfaces asthe unit's
_errorrow instead of taking the batch down.permission_mode— passed toclaude --permission-mode. The accepted modes stay the CLI'svocabulary, not the runner's, so a mode the CLI adds later needs no release here. Flag name was
read from real
claude --helpoutput, not assumed.A campaign confines its worker, advisor and grader alike, so an escalation cannot step outside
the sandbox its worker ran in.
Why
A consumer's eval runner replays recorded prompts, some of them action-shaped ("ship it"). It must
run them confined to a throwaway fixture directory under a restrictive permission mode. It could
not, so it refuses to run replay mode at all and nightly evals are blocked on this package. Verified
against this branch — the consumer's gate flips on its own with no change on its side:
(It returns
(False, 'driver exposes no workdir or permission-mode parameter…')againstmain.)Backward compatibility
Both default to
None; omitting them changes nothing. No--permission-modein the argv, and nocwd=keyword on thesubprocess.runcall at all — not evencwd=None. That is enforced byconstruction: the pre-existing test stub is
def fake_run(cmd, capture_output, text, timeout)andwould
TypeErroron an unconditionalcwd=. Injectedcall=functions keep their four-positionalsignature.
Supersedes #3
#3 was refused by the merge wrapper on a genuine stale base —
mainmoved ahead with the installerPR, which also edits
CHANGELOG.mdandREADME.md. Rebasing in place needs a force-push, which isblocked in this environment, so the commit is re-pushed on a fresh branch.
Two changes made while resolving, both toward this repo's stated convention:
## Unreleasedalongside the installer entry, perCONTRIBUTING.md("Add your entry under an## Unreleasedheading"). feat(call-agent): optional cwd and permission-mode for sandboxed runs #3 had created a## 0.2.0heading.
pyproject.tomland__version__stay at0.1.0. Theinstaller PR did not bump either, so this repo bumps at release time, not per PR. Consumers can
pin to the merge commit until a release is cut.
Test plan
python3 -m pytest -q→ 73 passed0.2.0string remains inpyproject.tomlor the packagemain(6002f84); CHANGELOG conflict resolved by keeping both entries