Skip to content

Template Format

Templates are markdown files with YAML frontmatter that define reusable prompt sections for wu:brief. The template system enables customization of agent prompts without modifying core LumenFlow code.

Templates live in .lumenflow/templates/spawn-prompt/:

.lumenflow/
  templates/
    manifest.yaml          # Assembly order configuration
    spawn-prompt/
      methodology/
        tdd-directive.md
        test-after-directive.md
      architecture/
        hexagonal-directive.md
      tdd-directive.md     # Compatibility fallback
      documentation-directive.md
      visual-directive.md
      structured-content-directive.md
      verification-requirements.md
      skills-selection.md
      design-context-ui.md
      effort-scaling.md
      constraints.md       # Always included last
      lane-guidance/       # Lane-specific templates
        operations.md
        framework.md
        content.md

Every template has two parts: YAML frontmatter and markdown content.

---
id: my-template
name: My Template
required: false
order: 100
---

## Template Content

Your markdown content here.
---
id: tdd-directive
name: TDD Directive
required: false
order: 10
tokens: [WU_ID, LANE]
condition: "type !== 'documentation'"
---

## TDD Directive for {WU_ID}

Working in lane: {LANE}

Your markdown content with token placeholders...

| Field | Type | Required | Description | | ----------- | -------- | -------- | --------------------------------------------------- | | id | string | Yes | Unique identifier matching manifest entry | | name | string | Yes | Human-readable name for debugging | | required | boolean | Yes | If true, assembly fails when template is missing | | order | number | Yes | Assembly position (lower numbers appear first) | | tokens | string[] | No | Token names used in this template | | condition | string | No | Expression that must be true for template inclusion |

The id must match an entry in manifest.yaml. It’s used to:

  • Look up the template during assembly
  • Apply client-specific overrides (matching by id)
  • Reference templates in error messages

Templates are sorted by order before assembly. Use these ranges:

| Range | Purpose | Examples | | ------- | ------------------------------------ | --------------------------------------------- | | 10-20 | Type and verification directives | tdd-directive, verification-requirements | | 50-70 | Skills, craft, and context | skills-selection, mandatory-agents | | 100-140 | Agent guidance and completion format | effort-scaling, completion-format | | 200-300 | Operational guidance | bug-discovery, quick-fix-commands | | 300-310 | Recovery and worktree | worktree-recovery, worktree-path-guidance | | 400-500 | Lane-specific guidance | lane-guidance-operations | | 820-850 | Action and completion checks | action-unclaimed, self-review | | 900+ | Constraints (always last) | constraints |

When required: true:

  • Template must exist for assembly to succeed
  • Missing template throws an error with the expected path
  • Use for critical sections like constraints

When required: false:

  • Template is optional
  • Missing template is silently skipped
  • Use for type-specific or conditional content

Lists token names that appear in the template content:

tokens: [WU_ID, LANE, WORKTREE_PATH]

This field is informational (documents which tokens the template uses) but token replacement happens automatically for all known tokens regardless of this field.

A JavaScript-like expression evaluated against the WU context. Template is included only when the condition evaluates to true.

See Condition Syntax for details.

Tokens are placeholders in template content that get replaced with actual values during assembly.

Use curly braces with uppercase names:

Working on {WU_ID} in lane {LANE}.
Navigate to: {WORKTREE_PATH}

| Token | Description | Example Value | | ------------------------------ | ----------------------------------------- | ---------------------------------- | | {WU_ID} | Work Unit identifier | WU-1234 | | {LANE} | Full lane name | Framework: Core | | {TYPE} | WU type | feature, bug, documentation | | {TITLE} | WU title | Add template loader | | {DESCRIPTION} | WU description | Implement the template system... | | {WORKTREE_PATH} | Path to worktree (if claimed) | worktrees/framework-core-wu-1234 | | {WORK_DOMAIN} | Classified work domain | ui, backend, docs | | {WORK_TEST_METHODOLOGY_HINT} | Classifier-driven methodology hint | smoke-test, structured-content | | {REQUIRED_VERIFICATION} | Rendered required verification text block | 1. Run ... |

Template:

## Action

Claim this WU before starting:

\`\`\`bash
pnpm wu:claim --id {WU_ID} --lane "{LANE}"
cd {WORKTREE_PATH}
\`\`\`

Output (after replacement):

## Action

Claim this WU before starting:

\`\`\`bash
pnpm wu:claim --id WU-1234 --lane "Framework: Core"
cd worktrees/framework-core-wu-1234
\`\`\`

Conditions control whether a template is included in the assembled prompt.

| Operator | Syntax | Description | | ---------- | ------------------- | ----------------------- | | Equality | field === 'value' | Exact match | | Inequality | field !== 'value' | Not equal | | Truthy | field | Field exists and truthy | | AND | expr1 && expr2 | Both must be true | | OR | expr1 \|\| expr2 | Either can be true |

Conditions use lowercase aliases of token values:

| Variable | Maps To | Example Values | | -------------------------- | --------------------------------- | -------------------------------------------- | | type | {TYPE} | feature, bug, documentation | | lane | {LANE} | Framework: Core | | wuId | {WU_ID} | WU-1234 | | title | {TITLE} | Add template loader | | description | {DESCRIPTION} | Full description text | | worktreePath | {WORKTREE_PATH} | Path or undefined | | laneParent | Extracted | Framework, Content, Operations | | policy.testing | Resolved policy | tdd, test-after, none | | policy.architecture | Resolved policy | hexagonal, layered, none | | work.domain | {WORK_DOMAIN} | ui, backend, docs, infra, mixed | | work.testMethodologyHint | {WORK_TEST_METHODOLOGY_HINT} | smoke-test, structured-content | | hasRequiredVerification | Derived from WU test requirements | truthy when any required verification exists | | tests.hasUnit | Derived from WU test paths | truthy when unit paths are declared | | tests.hasE2E | Derived from WU test paths | truthy when E2E paths are declared | | tests.hasManual | Derived from WU test paths | truthy when manual checks are declared |

Type-based inclusion:

# Include for features and bugs, exclude for docs
condition: "type !== 'documentation'"

# Include only for documentation WUs
condition: "type === 'documentation' || type === 'docs'"

Lane-based inclusion:

# Include only for Framework lanes
condition: "laneParent === 'Framework'"

# Include for Operations or Framework
condition: "laneParent === 'Operations' || laneParent === 'Framework'"

Truthy checks:

# Include only when worktree exists
condition: 'worktreePath'

Policy-based inclusion:

# Include only when TDD methodology is active
condition: "policy.testing === 'tdd'"

# Include for test-after methodology
condition: "policy.testing === 'test-after'"

Work-classification inclusion:

# Include only for UI-classified work
condition: "work.domain === 'ui'"

# Include only for structured-content work
condition: "work.testMethodologyHint === 'structured-content'"

# Include only when the WU spec declares required verification
condition: 'hasRequiredVerification'

Combined conditions:

# Feature in Framework lane
condition: "type === 'feature' && laneParent === 'Framework'"

When wu:brief runs, templates are assembled in this order:

  1. Load manifest from .lumenflow/templates/manifest.yaml
  2. Load templates from spawn-prompt/ directory
  3. Resolve client alias (for example claude-code -> claude, codex-cli -> codex)
  4. Apply client overrides (e.g., templates.claude/spawn-prompt/)
  5. Sort by order field (ascending)
  6. Evaluate conditions for each template against the WU context
  7. Replace tokens in included templates
  8. Concatenate with double newlines between sections

Client-specific templates take priority:

.lumenflow/
  templates/
    spawn-prompt/
      skills-selection.md     # Base template (order 50)
  templates.claude/
    spawn-prompt/
      skills-selection.md     # Claude override (same id, replaces base)
  templates.cursor/
    spawn-prompt/
      skills-selection.md     # Cursor override (same id)

When running wu:brief --id WU-XXX --client <client>:

  1. Load base skills-selection.md
  2. Resolve alias (claude-code -> claude)
  3. Override with templates.claude/spawn-prompt/skills-selection.md
  4. Other client directories are ignored

| Client Flag (--client) | Alias | Override Directory | | ------------------------ | -------- | --------------------- | | claude-code | claude | templates.claude/ | | codex-cli | codex | templates.codex/ | | gemini-cli | gemini | templates.gemini/ | | cursor | cursor | templates.cursor/ | | windsurf | windsurf | templates.windsurf/ |

Error: Required template 'constraints' is missing.
Expected at: spawn-prompt/constraints.md

Fix: Create the template at the expected path or mark it required: false in the manifest.

Error: Template spawn-prompt/my-template.md: 'id' field is required in frontmatter

Fix: Add the missing frontmatter field.

Error: manifest.yaml: Template entry 'my-template' is missing required fields: order

Fix: Add the missing field to the manifest entry.

  • One concern per template - Keep templates focused
  • Use conditions - Avoid including irrelevant content
  • Document tokens - List tokens in frontmatter even though optional
  • Leave order gaps - Use increments of 10 for flexibility
  • File names: Lowercase with hyphens (tdd-directive.md)
  • Template IDs: Match file name without extension (tdd-directive)
  • Subdirectories: Use for related groups (lane-guidance/)
# Type directives (mutually exclusive)
- id: tdd-directive
  order: 10
  condition: "type !== 'documentation'"

- id: documentation-directive
  order: 10
  condition: "type === 'documentation'"

# Common sections (always included)
- id: skills-selection
  order: 50

# Constraints (always last)
- id: constraints
  order: 1000

LUMENFLOW.md is fully managed by LumenFlow and force-synced on every upgrade. To add project-specific workflow additions without losing them on upgrade, create LUMENFLOW.local.md in the project root.

  • Agents read LUMENFLOW.local.md after LUMENFLOW.md when present.
  • init and upgrade never touch LUMENFLOW.local.md.
  • If a user-modified LUMENFLOW.md is detected on the first force-sync, the CLI backs up the custom content to LUMENFLOW.local.md automatically.

This is separate from the template system above — templates customize wu:brief prompts, while LUMENFLOW.local.md customizes the workflow documentation that agents read at startup.

docs:sync also refreshes the default agent-facing workflow docs that ship with the CLI. The bundled LUMENFLOW.md and wu-sizing-guide.md stay intentionally compact so agents get operational rules without carrying the full reference manual in every prompt.

Files such as AGENTS.md, CLAUDE.md, .cursor/rules/lumenflow.md, and .windsurf/rules/lumenflow.md use LumenFlow marker blocks. On sync, LumenFlow replaces the managed block and preserves user content outside it. If older syncs or manual edits left duplicate or nested LumenFlow blocks, rerunning docs:sync collapses them back to one managed region.