Skip to content
Merged
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
1 change: 1 addition & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"allowWrite": [
".",
"~/GitHub/bess-manager",
"~/.claude/jobs",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Root-cause check: the PR description says claude agents --json reads the session list from ~/.claude/jobs, but the fix adds the path to filesystem.allowWrite, not allowRead. This repo's own CLAUDE.md (unchanged by this PR, line ~510) documents that reads and writes are governed separately: "There is no allow-within-deny primitive for writes (reads have one, which is why allowRead differs)". Given the doc's own repeated lesson that sandbox-knob guesses are frequently wrong unless grounded in the actual error text (see the podman example a few lines below, where filesystem.allowRead was tried and disproved for a different symptom), and given the PR explicitly could not verify this fix in-session, is there a captured error message showing this is a write denial rather than a read denial? If not, allowRead looks like the more consistent knob for a stated read operation.

"~/Library/Caches/ms-playwright",
"~/.cache/ms-playwright",
"~/.npm"
Expand Down
32 changes: 32 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,38 @@ redundant:
one from outside. `verify-sandbox.sh` skips its symlink check outside a
linked worktree rather than reporting a PASS that proves nothing.

- **`filesystem.allowWrite: "~/.claude/jobs"`** — `claude agents --json` reads
the session list from there, and a sandboxed call does not fail, it silently
**TRUNCATES**. Measured in one session, seconds apart: **sandboxed returns 1
agent, unsandboxed returns 14, of which 7 are live sessions sitting in
worktrees.** All seven read as dead.

That is not cosmetic. `backlog-rhythm.sh` keys `resume_implementation` off
"worktree on disk, no live session", so with a truncated listing it told the
maintainer to re-enter a worktree a live session was actively working — a
second session on one branch, against commits the advice itself calls the
only copy. `implement-issue` Step 0 reads the same list before touching a
resumed branch, and both skills already carry a warning to run it
unsandboxed. This makes the warning unnecessary rather than merely repeated.

**An under-count, not an error, is the dangerous shape**: nothing about a
short list looks wrong, so the wrong answer is acted on with full confidence.

**`allowWrite`, not `allowRead`, and that is measured rather than assumed** —
the obvious objection is that `claude agents --json` only *reads* the list.
Two probes in a sandboxed session settle it:

```
ls ~/.claude/jobs -> 16 entries # read: ALLOWED
touch ~/.claude/jobs/.probe -> Operation not permitted # write: DENIED
```

Reads were never blocked; the read policy denies only `~/.claude/ide`.
Enumeration needs to WRITE, and a dropped entry rather than an error is what
produces the truncation. Same lesson as the podman entry below, where
`filesystem.allowRead` was tried and disproved: read the actual error instead
of reasoning about what ought to be blocked.

- **`filesystem.allowWrite`: the two user-level caches `worktree-setup.sh`
writes** — `~/Library/Caches/ms-playwright` (plus its Linux spelling
`~/.cache/ms-playwright`) and `~/.npm`. Setup runs `npm install` when a
Expand Down
Loading