You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
name: strict-prompt-template-engine
description: Render WORKFLOW.md prompt bodies with a Liquid-compatible engine configured to fail on unknown variables and filters, preventing silently corrupted agent prompts.
status: backlog
estimated_complexity: low
blast_radius: contained
Use strict template for prompts
Executive Summary
WORKFLOW.md (#65) introduces user-authored prompt templates. If the rendering engine silently turns {{ issue.titel }} into an empty string, the agent receives a malformed prompt and burns turns on garbage input. Symphony (SPEC §5.4) requires a Liquid-compatible engine configured strictly: unknown variables and unknown filters MUST fail rendering. This issue lands the same contract for ShipCode so configuration typos surface immediately, not three minutes into a wasted agent run.
Problem Statement
Today's pipeline prompt is a hardcoded template literal in packages/pipeline/src/pipeline.ts:148. Once #65 ships and that string moves to a user-edited WORKFLOW.md, the rendering layer becomes the place where typos die — silently or loudly. Default-permissive rendering produces silent failures: agents see an empty {{ issue.titel }} and proceed. We want loud failures: render error → fail the attempt with a clear message.
Goals
Pick a Liquid-compatible renderer with strict modes available (liquidjs is the obvious candidate).
Configure both strictVariables: true and strictFilters: true.
Surface render failures as a typed error in pipeline state so the UI can show the offending template line.
Provide a small set of input objects (issue, attempt, phase) consumed by templates.
Not adding custom filters in this issue beyond what the engine ships with.
Not building a template editor UI.
User Stories with Acceptance Criteria
Story 1: Typo fails immediately
As a user who typed {{ issue.titel }}, I see a clear error before any agent runs.
Acceptance: pipeline state transitions to template_render_error with the variable name; no agent process is spawned for that attempt.
Story 2: Valid template renders unchanged
As a user with a correct template, I see the rendered prompt sent to the agent.
Acceptance: rendered output equals the expected interpolation; no warnings logged.
Story 3: Unknown filter fails
As a user who wrote {{ issue.title | uppercas }}, I see a render error naming the filter.
Acceptance: error message includes uppercas; attempt does not proceed.
Functional Requirements
Renderer module at packages/pipeline/src/template-renderer.ts exporting renderTemplate(source: string, ctx: TemplateContext): string and a typed TemplateRenderError.
Inputs available to templates: issue (number, title, body, labels, state), attempt (number, prior_failure_reason?), phase (plan|review|execute|verify).
Render failures throw TemplateRenderError carrying the original engine error message and source line if available.
Pipeline catches the error, records template_render_error on the attempt, and surfaces it via the standard pipeline-event emitter.
No silent fallbacks — never substitute empty string for a missing variable.
Non-Functional Requirements
Render of a 10KB template completes in under 50ms.
Engine choice must be MIT/Apache-compatible.
No template eval may execute filesystem or network operations.
Success Criteria
A unit test rendering {{ issue.titel }} against a valid issue object throws TemplateRenderError.
A unit test rendering {{ issue.title | uppercas }} throws with the filter name in the message.
A pipeline-level test confirms the failed render does not spawn an agent process.
A unit test rendering a known-good template returns the expected string.
name: strict-prompt-template-engine
description: Render WORKFLOW.md prompt bodies with a Liquid-compatible engine configured to fail on unknown variables and filters, preventing silently corrupted agent prompts.
status: backlog
estimated_complexity: low
blast_radius: contained
Use strict template for prompts
Executive Summary
WORKFLOW.md (#65) introduces user-authored prompt templates. If the rendering engine silently turns
{{ issue.titel }}into an empty string, the agent receives a malformed prompt and burns turns on garbage input. Symphony (SPEC §5.4) requires a Liquid-compatible engine configured strictly: unknown variables and unknown filters MUST fail rendering. This issue lands the same contract for ShipCode so configuration typos surface immediately, not three minutes into a wasted agent run.Problem Statement
Today's pipeline prompt is a hardcoded template literal in
packages/pipeline/src/pipeline.ts:148. Once #65 ships and that string moves to a user-edited WORKFLOW.md, the rendering layer becomes the place where typos die — silently or loudly. Default-permissive rendering produces silent failures: agents see an empty{{ issue.titel }}and proceed. We want loud failures: render error → fail the attempt with a clear message.Goals
liquidjsis the obvious candidate).strictVariables: trueandstrictFilters: true.issue,attempt,phase) consumed by templates.Non-Goals
User Stories with Acceptance Criteria
Story 1: Typo fails immediately
{{ issue.titel }}, I see a clear error before any agent runs.template_render_errorwith the variable name; no agent process is spawned for that attempt.Story 2: Valid template renders unchanged
Story 3: Unknown filter fails
{{ issue.title | uppercas }}, I see a render error naming the filter.uppercas; attempt does not proceed.Functional Requirements
packages/pipeline/src/template-renderer.tsexportingrenderTemplate(source: string, ctx: TemplateContext): stringand a typedTemplateRenderError.issue(number, title, body, labels, state),attempt(number, prior_failure_reason?),phase(plan|review|execute|verify).TemplateRenderErrorcarrying the original engine error message and source line if available.template_render_erroron the attempt, and surfaces it via the standard pipeline-event emitter.Non-Functional Requirements
Success Criteria
{{ issue.titel }}against a validissueobject throwsTemplateRenderError.{{ issue.title | uppercas }}throws with the filter name in the message.Out of Scope
Dependencies
Verification Plan
issue.labels[0].name).Risks & Open Questions
liquidjsmay have surprising quirks around whitespace control; document the chosen settings.dry-runCLI command that just renders the template against a sample issue, for users to debug locally?