feat(agent-isolation): name the blocked command and its directory on the touch overlay - #1318
Merged
Merged
Conversation
…the touch overlay The overlay said a key was waiting and nothing about what for. That is enough when one thing is signing, and not enough the rest of the time: an agent session and a terminal can both be blocked on the same key, several worktrees of one repository look alike from the outside, and a touch given to the wrong one is not recoverable — the key fires its OTP slot into whatever has focus. The window now carries two more lines, the command and the directory it runs in. `arm` takes them from the hook payload (`.cwd`, the command it already parses), `wrap` from its own `$PWD` and argv, since the wrapper is the command's process while the hook only runs beside it. They go in a per-owner file under `context/`, keyed like the registration and swept with it, rather than into the watcher's environment. That is what makes the ride-along case right: a second command arming into a session that is already watched returns before it would spawn anything, so the text has to reach the running watcher through something it can re-read — and the window should name the command actually blocked, not the one that started the watcher. A separate directory from `owners/` because `_sweep_owners` reads every entry there as a registration. A password in a URL is masked before it is recorded: `git push https://user:token@host/repo` is a documented git spelling, and this is a full-screen window raised at an unpredictable moment. Nothing else is scrubbed and the docs say so. The command is flattened to one line and capped at 400 characters on disk — an agent's `git commit -F -` heredoc carries newlines, and a two-line file cannot hold those. The windows elide again for their own width, keeping the head of a command and the tail of a path. `elide` and `context` are duplicated across the GTK and Aqua windows, which are standalone scripts run by whichever interpreter has the toolkit and import nothing. A test compares the two copies so they cannot drift. Generated-by: Claude Opus 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
git push https://user:token@host/repo) is masked before it is recorded; nothing else is, and the docs say so, because this is a full-screen window raised at an unpredictable moment.Type of change
.claude/skills/<name>/) — eval fixtures updated belowtools/<system>/*.md)tools/*/withpyproject.toml) —tools/agent-isolationdocs/,README.md,CONTRIBUTING.md)projects/_template/)prek, workflows, validators)How it works
armtakes the two values from the hook payload (.cwd, plus the command it already parses);wraptakes them from its own$PWDand argv, since the wrapper is the command's process while the hook only runs beside it.They go into a per-owner file under
context/, keyed like the registration and swept with it — not into the watcher's environment. That is what makes the ride-along case correct: a second command arming into an already-watched session returns before it would spawn anything, so the text has to reach the running watcher through something it can re-read, and the window should name the command actually blocked rather than the one that started the watcher.context/is a separate directory fromowners/because_sweep_ownersreads every entry there as a registration.The command is flattened to one line and capped at 400 characters on disk (an agent's
git commit -F -heredoc carries newlines, and a two-line file cannot hold those). The windows elide again for their own width, keeping the head of a command and the tail of a path.Test plan
prek run --all-filespasses (32 hooks, exit 0).uv run --directory tools/agent-isolation --project . python -m pytest— 90 passed, 7 skipped (all pre-existing environmental skips: no gi, no Tk 8.6, sandboxedpgrep/unix-socket).armandwraprecord, the ride-along refresh under one watcher, cleanup on disarm and on sweep of a dead owner, one-line flattening, the length cap, and the URL-password masking.Tk()aborts,_gui_availablereturns 1), so the rendered layout is unconfirmed — the logic feeding it is covered by the tests above. Worth a reviewer with a hardware key eyeballing one real commit.RFC-AI-0004 compliance
context/inside the existingmagpie-gpg-touchruntime directory.Linked issues
None.
Notes for reviewers (optional)
elideandcontextare duplicated across the GTK and Aqua windows. Those are standalone scripts run by whichever interpreter happens to have the toolkit, and they import nothing — the package ships tests only, by design. A test compares the two copies withastso they cannot drift; extracting them to a shared module would mean asys.pathhack in both, which seemed the worse trade.//user:secret@in a URL is the one secret shape that routinely rides in an argv this script matches. I did not try to write a general redactor — a partial one invites trust it cannot earn, so the docs state the limit instead.tools/spec-loop/.last-syncis 6 commits behindmain; I updated the affected spec by hand rather than bumping the marker, since I have not verified the other five commits' specs.🤖 Generated with Claude Code