Skip to content

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

Closed

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.


drafted by Claude on behalf of Daniel Stephenson

Activity

  1. added a commit that references this issue on Aug 3, 2026
    2596f9b
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

    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