Skip to content

bug: expandPrompt placeholder substitution is a no-op in flowsh-cli 0.4.0 and 0.4.1 #38

Description

@tbrandenburg

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions