Skip to content

Worktree-isolated sessions refuse compound and variable-path commands that cannot be shown not to be git #5673

Closed

Description

@kyle-sexton

Problem

In worktree-isolated sessions, read-only shell commands are refused when the guard cannot prove
they are not git operations on another checkout. During the Building with Claude Sonnet 5.5
digest run (2026-09-29), six subagents reported refusals of compound commands and of commands
whose paths contain github (the ghq root is ~/repos/github.com/...). On 2026-09-30 the main
session saw the same shape: sed -n ... $F with F set to a scratchpad file was refused with
"this command runs sed with a value computed at runtime ... so what it runs cannot be shown not
to be git".

Each refusal costs a retry: rewrite as single commands, inline the literal path, or switch to
the Read tool.

What to find out

  • Which layer issues each refusal: this repo's guardrails hooks or the Claude Code harness's
    worktree isolation. The 2026-09-30 message names no plugin.
  • Whether the github-path refusals are a false positive on the ghq path layout.
  • Whether this is by design (some may be), and if so, whether skill and agent briefs should tell
    workers the accepted command shapes up front.

Done when

The source of each refusal class is identified and either fixed (if this repo's) or documented as
expected, with the accepted command shapes written where workers read them.

Related

Parent effort: linked from its tracking issue. Prior work on the same refusal family (all closed):
#4537, #1619, #1691.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 1, 2026
  2. kyle-sexton commented on Oct 4, 2026

    @kyle-sexton
    MemberAuthor

    This was generated by AI during triage.

    Triage: human-gated, needs a decision

    Routing reason: one open placement decision (where workers read the accepted command shapes) plus one refusal class whose layer is not yet identified. Neither can be settled by an agent alone.

    What triage established

    • Layer, for the git-shaped refusals: the refusal texts quoted in the body ("cannot be shown not to be git", "computed at runtime") appear nowhere in this repository's hooks. They come from Claude Code's built-in worktree isolation, which the upstream worktrees page documents as four checks, the last being a command shape whose text cannot show that any git it runs stays inside the worktree.
    • The eval-word class is resolved here: Worktree-isolated sessions refuse claude plugin eval (guard reads 'eval' as shell eval) #5696 identified it as the same built-in guard, and docs(evals): stop and hand off when a worktree session refuses plugin eval #5739 documented it in /evals:plugin-eval (stop, hand the user the exact command, read the result back). That discharges the eval part of this item's done-when; Worktree-isolated sessions refuse claude plugin eval (guard reads 'eval' as shell eval) #5696 stays open only as the upstream watch.
    • Possible regression or stale record: this repo's records say Claude Code 2.1.257 stopped refusing $VAR reads that never touch git. The 2026-09-30 refusal of sed -n ... $F (a scratchpad file, no git) contradicts that. Either the record is stale or the harness regressed.
      Basis: verified, plugins/playbooks/skills/skill-authoring/reference/precompute-context.md:98 and plugins/source-control/skills/worktree/reference/gather-block.md:23.
    • Path-shaped refusals (github in the path): not reproduced from this repository's hooks. A user-scope hook outside this repository is a candidate layer; operator to confirm.
    • Existing coverage of accepted shapes is scoped to skill pre-compute blocks (the worktree gather-block reference and the skill-authoring pre-compute spoke), plus roughly 30 per-skill notes. Nothing tells a subagent or a body-time Bash call the accepted shapes up front.

    Open question for the operator: where should the accepted command shapes for body-time and subagent Bash live?

    1. Recommended: one shared reference that subagent briefs and the orchestration guidance point to, so the per-skill notes can shrink to a pointer. Basis: judgment, from the six subagent refusals the body reports (observed-stumble evidence for a standing instruction).
    2. Extend the existing pre-compute references to cover body-time Bash too.
    3. Document as expected only, with no worker-facing instruction.

    Also confirm whether the path-shaped refusals come from a user-scope hook, which would put that half outside this repository.

    Agent Brief

    Type: Task
    Summary: Identify the source of each worktree-isolation refusal class and give workers the accepted command shapes up front.

    Current behavior:
    In worktree-isolated sessions, compound commands, commands carrying a $ expansion, and commands whose paths contain github are refused. Each refusal costs a retry. Guidance on accepted shapes exists only for skill pre-compute blocks and in scattered per-skill notes.

    Desired behavior:
    Each refusal class is attributed to its layer (built-in isolation guard, this repository's hooks, or a user-scope hook). Classes owned by this repository are fixed; the rest are documented as expected. Workers find the accepted shapes where the operator's chosen placement puts them, before their first Bash call.

    Key interfaces:

    • The built-in worktree-isolation command-shape check, and this repository's recorded claim about which $ expansions it accepts.
    • Subagent and orchestration briefs, the surface workers read.

    Acceptance criteria:

    • Each refusal class in the body (compound, $ expansion without git, github path) names its layer with a probe or a cited source.
    • The $VAR-without-git record is either re-verified on the current Claude Code release or corrected.
    • The accepted command shapes are written at the placement the operator chose, and the per-skill notes point to it rather than restate it.

    Out of scope:

  3. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 4, 2026
  4. kyle-sexton commented on Oct 13, 2026

    @kyle-sexton
    MemberAuthor

    Decision recorded. The owner approved applying independently verified recommendations on 2026-10-12.

    Worktree-isolated sessions refuse compound commands, $-expanded paths and some github-path commands from Claude Code's built-in isolation guard, costing a retry each. Triage attributed the git-shaped refusals to the built-in guard; the open decision is where workers read the accepted command shapes, and PR #5738 drafted exactly that before being closed for ownership reasons only.

    Verification notes:

    • Q2's basis covers this machine only, and the digest run used another machine. Two things mitigate this: ~/.claude/hooks and settings come from chezmoi (modify_settings.json), so they are likely shared across machines, and parent-contract.md:701-704 records the built-in guard refusing a path ending in 'git', which is the same word-match shape.

    Verified by an independent fresh-context check (confirmed, risk low): gh issue view 5673 (body + triage 2026-10-04; no owner decision); gh pr view 5738 (CLOSED 2026-10-02, closed only for session ownership; review comments found nothing blocking; files incl. gather-block.md, precompute-context.md, session-flow/reference/gather.md); origin/main plugins/discovery/reference/parent-contract.md:699-708 (pointer to worktrees#how-claude-code-enforces-isolation); origin/main plugins/playbooks/skills/skill-authoring/reference/precompute-context.md:124-132 (2.1.257/2.1.259 record); origin/main plugins/source-control/skills/worktree/reference/gather-block.md:18-28; https://code.claude.com/docs/en/worktrees.md fetched 2026-10-12: four checks incl. command shape, applies to subagents and background

    Admission to an agent lane stays with the work-class rules and owner ratification.

  5. added theissue type on Oct 15, 2026
  6. removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 17, 2026
  7. kyle-sexton commented on Oct 17, 2026

    @kyle-sexton
    MemberAuthor

    Admitted in owner wave 1.

  8. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 17, 2026
  9. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 18, 2026
  10. kyle-sexton commented on Oct 18, 2026

    @kyle-sexton
    MemberAuthor

    This was generated by AI during triage.

    Triage after #7805 merged: one decided item left

    What #7805 finished (merged 2026-10-17, 72a22ae): the owner record. On main (e59e0be) /source-control:worktree holds "Accepted command shapes for body-time and subagent Bash" (in its gather-block reference): the accepted shape, the three refusal classes with their layer and basis, and the unsettled $VAR question with a recheck trigger. plugins/discovery/reference/parent-contract.md and the skill-authoring pre-compute reference now point at it. That meets the body's done-when for identifying each refusal's source and documenting it as expected.

    What remains. The 2026-10-13 decision says worker briefs and per-skill notes point to that one heading. Only two files reference it today (git grep -l 'Accepted command shapes' origin/main -- plugins), while 57 skill and agent bodies mention worktree isolation. The notes among them that restate accepted shapes have not been re-pointed.

    The $VAR probe is recorded as unsettled with a recheck trigger; it is not part of this item's remaining work.

    Triage: briefed, delegable (Task, priority: medium, work-class: scoped).

    Agent Brief

    Type: Task
    Summary: Re-point per-skill and per-agent notes that restate worktree-isolated Bash command shapes at the owner heading.

    Current behavior: /source-control:worktree now owns the accepted command shapes for worktree-isolated Bash, but many skill and agent bodies still carry their own notes on which shapes the isolation guard accepts or refuses.

    Desired behavior: Every skill or agent note that restates accepted or refused command shapes for worktree-isolated Bash is replaced by a pointer to /source-control:worktree, "Accepted command shapes for body-time and subagent Bash", keeping any skill-specific fact the owner heading does not hold. Notes that only mention worktree isolation without restating shapes stay as they are. Pointers name the skill by /plugin:skill, never by path.

    Key interfaces:

    • /source-control:worktree owner heading: the single source; read, not edited, except to add a shape a note held that the heading lacks.

    Acceptance criteria:

    • A list of every skill and agent body checked, each marked re-pointed, kept (with reason), or not restating.
    • No re-pointed note restates a shape the owner heading holds.
    • Each changed plugin gets its version bump and changelog entry or fragment.
    • /skill-quality:check passes on every changed skill.

    Out of scope:

    • Probing the $VAR question.
    • Changing which shapes the owner heading accepts.
  11. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 18, 2026
  12. changed the issue type fromtoon Oct 18, 2026
  13. changed the issue type fromtoon Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions