Escape the provision command for its shell context in agent prompts
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 71
- Forks
- 64
- Avg merge
- 15h 38m
- Merged PRs (30d)
- 66
Description
Context
Raised while reviewing #220, which fixes the YAML half of this problem:
the provision command is now rendered into a block scalar, so a command
containing ": " no longer breaks the workflow document.
The same command is also interpolated raw into a shell string, and that
half is untouched.
Problem
{{PROVISION_CMD}} is substituted into the agent prompt inside a
double-quoted shell argument:
claude_args: |
--append-system-prompt "This OVERRIDES ... provisioned the environment ('{{PROVISION_CMD}}'), and you run with ..."
A provision command containing a double quote closes that argument early.
Reproduced on a clean checkout:
facility init --yes --provision='docker compose up -d && echo "db: ready"'
renders, in .github/workflows/facility-crew.yml:
--append-system-prompt "This OVERRIDES ... provisioned the environment ('docker compose up -d && echo "db: ready"'), and you run with full byp...
The " before db: terminates the string. The rest of the system prompt —
including the security clauses about treating issue text as untrusted data and
never pushing to protected branches — is no longer part of the argument.
Affected sites, all rendering the same variable:
packages/cli/templates/workflows/facility-crew.yml(builder and architect lanes)packages/cli/templates/workflows/facility-codex.ymlpackages/cli/templates/workflows/facility-doctor.ymlpackages/cli/templates/workflows/facility-address-review.ymlpackages/cli/templates/prompts/architect.md,builder.md
This is pre-existing and was not introduced by #220. It is worth tracking now
because #220 makes it more reachable: a command containing ": " previously
produced an unparseable workflow that failed loudly and never ran, so this
truncation was masked. Those commands now produce a workflow that parses and
runs.
Proposed change
Escape the command for its shell context at render time rather than
interpolating it raw — a PROVISION_PROMPT variable alongside the existing
PROVISION_RUN, so each interpolation site gets a value already correct for
where it lands. Prompt text is documentation of what ran, so escaping (or a
conservative quoted form) is enough; it does not need to stay executable.
Why not in #220
#220 is scoped to the YAML scalar context of the run: key. This is a
different context (shell, inside a block scalar that already parses), needs a
second rendering variable, and touches templates and prompt files that PR does
not. Fixing it there would change what the PR is about.
Acceptance criteria
-
facility init --provision='docker compose up -d && echo "db: ready"'renders a prompt whose--append-system-promptargument contains the whole system prompt, security clauses included. - A test renders the workflows with a quote-bearing provision command and asserts the prompt argument is intact — alongside the parse test added in #220.
- The same holds for
.github/facility/architect.mdandbuilder.md.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing how PROVISION_RUN is rendered into the affected workflow templates and prompt files: packages/cli/templates/workflows/facility-crew.yml, facility-codex.yml, facility-doctor.yml, facility-address-review.yml, and the architect.md and builder.md prompts. Run or extend the quote-bearing render test alongside the parse test from #220. Done means the full system prompt, including security clauses, remains in the shell argument for every listed output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, shell, typescript
- Domain
- ci-cd, cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100