Worktree command guard refuses pipeline agents' os-sdlc-subagent-stop calls #1096
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#1096
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
In a worktree-isolated session the PreToolUse command guard refuses commands it cannot verify as staying inside the worktree. It refuses the pipeline agents'
os-sdlc-subagent-stopcalls, so a gated agent cannot submit its handoff and the Runner records a placeholder as a pass.Observed
During implementation 61 the change-auditor ran
os-sdlc-subagent-stop --json <multi-kilobyte payload>. The guard refused it four times. The agent then submitted a placeholder handoff. The Runner recorded dispatch 527 as verdict pass with an empty items list. Downstream nodes would have run on no audit. The orchestrator abandoned run 61 and reopened as run 62. The guard also refused the orchestrator'spython3 -I - <<'EOF'heredocs and onecat > file <<'EOF'write.Reproduce
Run it in a worktree-isolated session.
Approach
Boot::Inputs.subagent_stopaccepts--json-file PATHbeside--jsonand stdin. The agent writes the handoff to a file and submits a short command. The guard allows everyos-sdlc-*bin regardless of argument length, because these bins never run git.Required work:
Boot::Inputs.subagent_stopreads the handoff from--json-file PATH— check: presentjson-fileinplugins/os-sdlc/lib/os_sdlc/boot/inputs.rbos-sdlc-subagent-stop --json-file PATH, never a placeholder — check: present--json-fileinplugins/os-sdlc/agents/*.mdOrchestrator work: allowlist the
os-sdlc-*bins in the worktree PreToolUse guard in plugin os (plugins/os/skills/worktree/SKILL.mddescribes it).Acceptance criteria
os-sdlc-subagent-stop --json-file PATH, then the Runner records the full handoff.os-sdlc-*command in a worktree session, when its arguments exceed the guard's complexity limit, then the guard does not refuse it.--json-filerather than a placeholder.Owner sketch
Boot::Inputs.subagent_stopreads--json-file. The worktree guard in plugin os holds theos-sdlc-*allowlist.Origin
Resolution
Done: Mechanism: the os-sdlc-subagent-stop --json command is refused by the worktree guard or harness, and the agent improvises. Occurrences: #848 "Pipeline agents without Write cannot submit a handoff that contains the word git from a worktree session"; #854 "Handoff stop refused by the worktree guard when its text contains git".
Evidence: #848 adds #844 impl 9 dispatch 75: read-only agents (contract-auditor, change-auditor, behavior-verifier, reviewer, test-reviewer, seam-designer) have no Write tool to move the handoff into a file. #854 adds #852 impl 16 dispatch 128: three forms (--json, cd && --json, heredoc) refused because the JSON named a git command.
Follow-ups: none
Occurrence: Worktree command filter refuses runtime-variable operands and long quoted text, so pipeline agents submit stub handoffs.
Seen: change-auditor dispatch 895 in implementation 113 (ticket 1234) recorded only a stub handoff (summary: x, verdict: fail) after the filter refused its stop command; the run escalated and was rerouted. The ticket-skeptic agent for this very occurrence could not run its backlog search: every Bash call was refused ("working directory resolved to the shared checkout"). Posting this comment with --body inline was refused too ("cannot be shown not to be git"); it went through --body-file.
Run: session 9feaee0d-e0ed-4f5a-85b4-db1166f8539a, implementations 113 and 114.
Adds: the refusal fires on any $VAR path operand (sed, cat), on long quoted text in a plain command, and on subagents whose cwd resolves to the main checkout, not only on the stop command. Workaround used: a prompt note on every dispatch to spell out literal paths and write handoff YAML with the Write tool.
Occurrence: Keep a subagent-stop handoff from being refused by the worktree guard
Seen: plugins/os-sdlc/agents/behavior-verifier.md:49 (stop command form)
Run: implementation 134 (#1266), dispatch 1146, session 4f3f95ea-3c6f-4d23-a0ea-e349d6ab02a5
Adds: The Runner stayed at await_completion with no stall, so the run waited without a signal. Workaround that worked: SendMessage to the same agent asking it to resend single-quoted JSON with no dollar sign, backticks, =>, <, >, or pipe characters in the content.
Occurrence: Worktree guard false positive refuses os-sdlc-subagent-stop when inline handoff YAML contains "git merge-base"
Seen: worktree PreToolUse guard; refusal text "cannot be shown not to be git"
Run: dispatch 1394, implementation 161 (session eb98cdcd-6783-46a0-b7df-cf18a8fe2a56, 2026-10-25)
Adds: a different trigger text (the words "git merge-base" inside the handoff YAML). Writing the YAML to a file and passing it worked. Effect: a green programmer dispatch could not submit its handoff.
Occurrence: Worktree guard blocks os-sdlc-subagent-stop with a JSON payload, so Bash-only pipeline agents cannot submit their handoff
Seen: the worktree-isolation PreToolUse Bash guard, behavior-verifier dispatch 1625, implementation 184, ticket #1404
Run: session 47f54f99-e35c-4567-a3e6-581fecf54dc3
Adds: the agent tried four forms with no "git" substring in any payload (--json, reworded --json, heredoc to a file, stdin from the missing file); all but the last were refused. This disproves the "git substring" reading in handoff 2026-10-27-1540. The orchestrator relayed the unchanged payload from a file written with the Write tool via stdin, which the Runner accepted. The guard also refused the orchestrator's own multi-line os-backlog comment body in this worktree. Same fault as #1415.