# Dispatch substrate: three-tier prompt strategy + v2-ready telemetry

Prompt construction is a per-workflow choice across three tiers — `static` / `assembled` (default) / `meta-prompted`. The substrate is plain text with `$VAR` substitution; the leverage is in the resolver, which does deterministic context selection from `dispatches.jsonl`, `patterns.yaml`, `prompts/examples/`, and frontmatter, wrapping optional sections so empty values omit headers. Tier 3 (`meta-prompted`) spends a small extra LLM call on a cheaper meta-model to compose the worker prompt for quality-sensitive dispatches. Self-improving prompts (an agent that mines telemetry and rewrites templates) is deferred to v2, but v1 captures every byte v2 will consume so retrofit is unnecessary: rich `dispatches.jsonl` schema, blob storage for full prompt + meta-prompt + artifacts, template SHAs, A/B variant slot, outcome evaluator hook, quality-signal back-propagation, and a reserved `fw orchestrator improve` CLI namespace.

This decision is two halves bound together. The tiers without rich telemetry strands the v2 loop. The telemetry without tiers has nothing to compare. Treating them as separate decisions would lock in one half before the other was specified.

## Considered Options

- **Plain `$VAR` substrate only, no tier framing** — what the agent first proposed. Rejected: collapses the question of "where does the framework put effort to make prompts good" into a syntax decision and gives no place to wire in stochastic generation. Self-confirming framing.
- **Jinja2 with full conditionals** — flexible, mature templating. Rejected: zero failures in the 1500+ task corpus traced to missing template conditionals; existing prompt files already use prose-embedded branching successfully; adds a templating language operators must learn for ~5% of cases the resolver can handle natively.
- **Stochastic / LLM-generated prompts as default (Tier 3 always)** — every dispatch goes through a meta-prompt step. Rejected: cost creep, latency, debug complexity (now there's a meta-failure mode + a worker-failure mode), reproducibility loss for "rerun this task with the same prompt," and most workflows don't need it. Right answer is per-workflow opt-in, not global default.
- **Deterministic only, defer all stochastic generation to v2** — what the agent's penultimate position said. Rejected after user pushback: prompt quality drives outcome quality is the load-bearing premise; spending tokens on prompt construction is a high-leverage lever; deferring it past v1 is a quality choice dressed up as architectural rigor. Three tiers with `meta-prompted` available in v1 (opt-in) is the honest cut.
- **Build the v2 self-improvement loop in v1** — most ambitious option. Rejected: requires telemetry that hasn't accumulated yet; would ship a learner with nothing to learn from. The substrate-then-loop split is bootstrap order, not architectural compromise.
- **Defer self-improvement to v2 without v2-readiness commitments** — agent's earlier position. Rejected after user challenge: v2 can only learn from data v1 captured; if v1 ships without rich `dispatches.jsonl` / blob storage / template SHAs / variants / outcome hook / back-propagation, v2 needs a painful retrofit. Wiring it in from the beginning costs a few schema fields and one CLI stub now; not wiring it costs a v2 migration later.

## Consequences

- **Workflow schema gains four optional fields**: `prompt_strategy`, `meta_model`, `meta_template`, `outcome_evaluator`, `variants`. All optional with sensible defaults. Existing single-tier workflows work unchanged.
- **The resolver becomes a non-trivial component**, not a `sed` loop. It reads dispatch history, matches healing patterns, picks variants, runs meta-prompts, records SHAs, captures blobs. This is the highest-complexity addition v1 ships — it warrants its own implementation task with its own ACs.
- **`dispatches.jsonl` row size grows**: ~30 fields vs the originally-sketched ~13. Inline rows stay small (most fields are short strings or bools); large blobs (full prompt text, meta-prompt, artifacts) go to `.context/dispatch-blobs/<YYYY-MM>/<dispatch-id>/` per the existing `fw bus` pattern (T-1063).
- **Template versioning depends on git**. Workflows and templates live in repo-tracked files; resolver records `git rev-parse HEAD:<path>` at dispatch time. Uncommitted edits get an mtime-hash fallback flagged in the record so v2 can filter.
- **Quality-signal back-propagation crosses task boundaries.** When a task transitions to `work-completed` or `issues` AFTER a dispatch ran for it, the resolver writes back `task_completion_outcome` into the relevant `dispatches.jsonl` rows. This couples task lifecycle (Agent's slice 1) to dispatch telemetry (Agent's slice 3) — the Agent already sees both.
- **`outcome_evaluator` is an extension point operators can opt into.** Default evaluator is built-in: did `## Verification` pass + are all `### Agent` ACs ticked. Custom evaluators are shell scripts that emit JSON. v2 can ship richer default evaluators without breaking existing workflows.
- **`fw orchestrator improve` is a reserved CLI namespace in v1**, exiting with "v2: not yet implemented; data is being captured." This is intentional pre-commitment — operators see the path and the namespace can't be claimed by an unrelated feature.
- **A/B variants are operator-driven in v1.** No automated variant generation. If an operator wants to test prompt phrasing, they edit the workflow file and add `variants:`. v2 can automate this once telemetry shows it's worth automating.
- **Telemetry-comparability is preserved across tiers.** Outcome aggregation ("do build dispatches succeed at rate X?") works identically for static, assembled, and meta-prompted. Prompt-level A/B requires reading blobs, which is v2 work — but the data is captured.
