garrytan/gstack · error · Error
TASKS_SECTION_EMIT requires one of ${[...VALID_PHASES].join(
Error message
TASKS_SECTION_EMIT requires one of ${[...VALID_PHASES].join(', ')} — got ${phase} What it means
generateTasksSectionEmit() in scripts/resolvers/tasks-section.ts:17 requires the phase argument to be one of VALID_PHASES: 'ceo-review', 'design-review', 'eng-review', 'devex-review'. Any other value (or missing value) throws. The phase names are kebab-case.
Source
Thrown at scripts/resolvers/tasks-section.ts:17
/**
* Resolvers for the Implementation Tasks emission (#1454).
*
* {{TASKS_SECTION_EMIT:<phase>}} — per-skill task emission + JSONL write
* {{TASKS_SECTION_AGGREGATE}} — autoplan aggregation across all phases
*
* Schema for the JSONL artifact lives in scripts/task-emission-schema.ts.
*/
import type { TemplateContext, ResolverFn } from './types';
const VALID_PHASES = new Set(['ceo-review', 'design-review', 'eng-review', 'devex-review']);
export const generateTasksSectionEmit: ResolverFn = (_ctx: TemplateContext, args?: string[]) => {
const phase = args?.[0];
if (!phase || !VALID_PHASES.has(phase)) {
throw new Error(`TASKS_SECTION_EMIT requires one of ${[...VALID_PHASES].join(', ')} — got ${phase}`);
}
return `## Implementation Tasks
Before closing this review, synthesize the findings above into a flat list of
build-actionable tasks. Each task derives from a specific finding — no padding.
Emit the markdown section AND write a JSONL artifact that \`/autoplan\` can
aggregate across phases.
### Markdown section (always emit)
\`\`\`markdown
## Implementation Tasks
Synthesized from this review's findings. Each task derives from a specific
finding above. Run with Claude Code or Codex; checkbox as you ship.
- [ ] **T1 (P1, human: ~2h / CC: ~15min)** — <component> — <imperative title>
- Surfaced by: <section name> — <specific finding text or line reference>View on GitHub (pinned to 94993f7401)
Solutions
- Use exactly one of the four phase strings in kebab-case
- If you intentionally added a new phase, extend the VALID_PHASES set first
Example fix
<!-- before -->
{{TASKS_SECTION_EMIT:ceo_review}}
<!-- after -->
{{TASKS_SECTION_EMIT:ceo-review}} Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_PHASES = new Set(['ceo-review', 'design-review', 'eng-review', 'devex-review']);
if (phase && !VALID_PHASES.has(phase)) {
throw new Error(`phase must be one of: ${[...VALID_PHASES].join(', ')}`);
} Type guard
const VALID_PHASES = new Set(['ceo-review', 'design-review', 'eng-review', 'devex-review']); const isTaskPhase = (p: string): boolean => VALID_PHASES.has(p);
Prevention
- Reference the VALID_PHASES constant when extending rather than string literals
- Keep phase names kebab-case to match the existing convention
- Update VALID_PHASES before referencing a new phase in any .tmpl
When it happens
Trigger: Passing a phase outside the set. Typo like `ceo_review` (underscore) or `ceoReview` (camelCase). Adding a new review phase without updating VALID_PHASES.
Common situations: Extending the autoplan review sequence with a new phase. Copying from documentation using a different naming convention.
Related errors
- Unknown placeholder {{${resolverName}}} in ${relTmplPath}
- Unresolved placeholders in ${relTmplPath}: ${remaining.join(
- {{INVOKE_SKILL}} requires a skill name, e.g. {{INVOKE_SKILL:
- {{LEARNINGS_SEARCH:query=...}} value must match ${QUERY_SAFE
- Invalid preamble-tier: ${tier} in ${ctx.tmplPath}. Must be 1
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/b71cdbf3ce07eff0.
Report an issue: GitHub.