Skip to content

Phase 4/6 prescribe a command-substitution heredoc form some harness classifiers reject outright #91

Description

@dmccoystephenson

What happened

Phase 4 step 5 (self-review post) and Phase 6 (commit) prescribe the "$(cat <<'EOF' ... EOF)" command-substitution form:

gh pr comment <number> --body "$(cat <<'EOF'
...
EOF
)"

and

git commit -m "$(cat <<'EOF'
...
EOF
)"

In at least one downstream harness (a gardener tend headless dispatch of the medieval-factions-dev-loop skill, generated from this template), this exact invocation is rejected outright by the Bash tool's static command classifier with Contains command_substitution — it never reaches the shell. Two related rejections were observed in the same session: grep -rn "a\|b" <path> was rejected with Contains simple_expansion (the \| alternation), and both git diff origin/main...HEAD --stat and an awk one-liner containing || came back as This command requires approval — a hard block in a headless run with no human available to approve.

Why it matters

This is template-wide: every generated dev-loop skill inherits these exact snippets in Phase 4 step 5 and Phase 6, including the phase whose output is the loop's main audit artifact (the self-review comment). An agent that follows the prescribed form literally, rather than improvising a workaround, fails to post its self-review or its commit at all.

Workaround that worked

Write the body with the Write tool to a scratch path inside the working directory, then pass it by file — --body-file / -F avoid command substitution entirely and preserve the multi-line formatting the heredoc was protecting:

gh pr comment <number> --body-file /path/in/workdir/selfreview.md
gh issue create --title "..." --body-file /path/in/workdir/issue.md
git commit -F /path/in/workdir/commitmsg.txt

Suggested instruction text

Replace the "$(cat <<'EOF' ... EOF)" snippets in Phase 4 step 5 and Phase 6 with the --body-file / -F form above, and add a line near the existing scratch-file-handling rule (create-dev-loop.md:259):

Avoid command substitution in Bash tool calls. Some harnesses' command classifiers reject $(...) outright, so a prescribed --body "$(cat <<'EOF' ... EOF)" can fail before reaching the shell. Compose long bodies with the Write tool to a scratch file inside the working directory and pass --body-file (gh) or -F (git commit). Likewise prefer separate grep invocations over \| alternation, which some classifiers flag as an expansion.

Also observed (not filed separately — mention if useful)

gh pr comment failed twice with transient HTTP/2 transport errors (http2: client conn could not be established, then unexpected EOF) before succeeding on a third attempt. Nothing in Edge cases mentions retrying a transient gh network failure; an agent treating the first failure as terminal would silently drop its self-review. A one-line "retry transient gh network errors once or twice before treating them as blocked" in Edge cases would cover it.


Originally filed against dmccoystephenson/medieval-factions-dev-loop#24 and routed upstream per that skill's template-rule policy — this is a harness/template-wide gap, not Medieval-Factions-specific.

Metadata

Metadata

Assignees

No one assigned

    Labels

    template-ruleShould be promoted into create-dev-loop.md

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions