Summary
In flowsh-cli 0.4.0 and 0.4.1, agent steps with expandPrompt: true generate a placeholder substitution line that silently does nothing. Variables like ${ISSUE_NUMBER} are never replaced in the prompt string sent to the agent, so the agent receives the literal text ${ISSUE_NUMBER} instead of the actual value.
The bug was fixed in 0.4.2 — this issue documents the root cause and the correct fix for reference, and flags that harnesses generated with the affected versions must be regenerated.
Root Cause
The code generator in versions 0.4.0–0.4.1 emitted:
prompt="${prompt//"${ISSUE_NUMBER}"/"$ISSUE_NUMBER"}"
Why this is a no-op
The prompt is captured via a single-quoted heredoc (<<'PROMPT_EOF'), which means ${ISSUE_NUMBER} is stored as the literal 7-character sequence in the prompt variable — it is never expanded by bash at capture time.
The substitution then uses "${ISSUE_NUMBER}" as the search pattern. Inside double quotes, ${ISSUE_NUMBER} is expanded by bash before the // operator runs, so bash replaces the pattern ${ISSUE_NUMBER} with the current value of the variable (e.g. 42). The operator ends up searching for 42 in a string containing the literal text ${ISSUE_NUMBER} — no match, no replacement.
Minimal reproduction:
ISSUE_NUMBER=42
# Broken pattern (0.4.0 / 0.4.1)
prompt='Fix issue #${ISSUE_NUMBER} now'
prompt="${prompt//"${ISSUE_NUMBER}"/"$ISSUE_NUMBER"}"
echo "$prompt" # → Fix issue #${ISSUE_NUMBER} now (unchanged!)
# Correct pattern (0.4.2+)
_p='${ISSUE_NUMBER}'; prompt="${prompt//"$_p"/"$ISSUE_NUMBER"}"
echo "$prompt" # → Fix issue #42 now
The Fix (already in 0.4.2+)
Using an intermediate variable with a single-quoted assignment forces bash to treat the search string as a literal:
_p='${ISSUE_NUMBER}'; prompt="${prompt//"$_p"/"$ISSUE_NUMBER"}"
_p='$ISSUE_NUMBER'; prompt="${prompt//"$_p"/"$ISSUE_NUMBER"}"
The second line handles bare $ISSUE_NUMBER references (without braces) for completeness.
Why this is safe
_p is assigned via single quotes — no variable expansion, no code execution.
"$_p" in ${prompt//"$_p"/...} is a bash parameter expansion, not eval. It performs a literal string search; special characters in _p are not interpreted as a pattern.
- The replacement side
"$ISSUE_NUMBER" expands the value normally. If the value contains /, \, or other characters, bash parameter expansion handles them safely — no shell injection is possible because no subprocess or eval is involved.
This pattern is secure for all valid bash variable values.
Impact on Existing Harnesses
Any harness generated with 0.4.0 or 0.4.1 using expandPrompt: true will send unresolved placeholders to the agent. The failure is silent — the harness runs without errors, but the agent prompt contains literal ${VAR_NAME} text instead of the intended values.
Required action: Regenerate affected harnesses with flowsh-cli >= 0.4.2:
uvx flowsh-cli@latest your-workflow.yml --force
Suggestion: Add a CHANGELOG entry or migration note
Since the broken pattern produces no runtime error, users who pinned to 0.4.0 or 0.4.1 may not notice the silent failure. A clear note in the changelog or README migration section would help.
Summary
In flowsh-cli 0.4.0 and 0.4.1, agent steps with
expandPrompt: truegenerate a placeholder substitution line that silently does nothing. Variables like${ISSUE_NUMBER}are never replaced in the prompt string sent to the agent, so the agent receives the literal text${ISSUE_NUMBER}instead of the actual value.The bug was fixed in 0.4.2 — this issue documents the root cause and the correct fix for reference, and flags that harnesses generated with the affected versions must be regenerated.
Root Cause
The code generator in versions 0.4.0–0.4.1 emitted:
prompt="${prompt//"${ISSUE_NUMBER}"/"$ISSUE_NUMBER"}"Why this is a no-op
The prompt is captured via a single-quoted heredoc (
<<'PROMPT_EOF'), which means${ISSUE_NUMBER}is stored as the literal 7-character sequence in thepromptvariable — it is never expanded by bash at capture time.The substitution then uses
"${ISSUE_NUMBER}"as the search pattern. Inside double quotes,${ISSUE_NUMBER}is expanded by bash before the//operator runs, so bash replaces the pattern${ISSUE_NUMBER}with the current value of the variable (e.g.42). The operator ends up searching for42in a string containing the literal text${ISSUE_NUMBER}— no match, no replacement.Minimal reproduction:
The Fix (already in 0.4.2+)
Using an intermediate variable with a single-quoted assignment forces bash to treat the search string as a literal:
The second line handles bare
$ISSUE_NUMBERreferences (without braces) for completeness.Why this is safe
_pis assigned via single quotes — no variable expansion, no code execution."$_p"in${prompt//"$_p"/...}is a bash parameter expansion, noteval. It performs a literal string search; special characters in_pare not interpreted as a pattern."$ISSUE_NUMBER"expands the value normally. If the value contains/,\, or other characters, bash parameter expansion handles them safely — no shell injection is possible because no subprocess orevalis involved.This pattern is secure for all valid bash variable values.
Impact on Existing Harnesses
Any harness generated with 0.4.0 or 0.4.1 using
expandPrompt: truewill send unresolved placeholders to the agent. The failure is silent — the harness runs without errors, but the agent prompt contains literal${VAR_NAME}text instead of the intended values.Required action: Regenerate affected harnesses with
flowsh-cli >= 0.4.2:Suggestion: Add a CHANGELOG entry or migration note
Since the broken pattern produces no runtime error, users who pinned to 0.4.0 or 0.4.1 may not notice the silent failure. A clear note in the changelog or README migration section would help.