#!/usr/bin/env python3
"""Generate and validate the 3,000-line round-2 coding-agent prompt dataset."""

from __future__ import annotations

import json
import random
import re
from collections import Counter
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "round2_prompts.jsonl"

LABEL_COUNTS = {
    "writing": 30,
    "review": 29,
    "refactor": 29,
    "quickFix": 25,
    "frontendImpl": 22,
    "planning": 22,
    "debugging": 18,
    "backendImpl": 9,
}
SLICE_COUNTS = {
    "core": 58,
    "boundary": 52,
    "pasted-context": 50,
    "mixed": 24,
    "vague-eval": 16,
}
LABELS = list(LABEL_COUNTS)
LOCALES = ["es", "de", "fr", "pt", "zh", "ja"]

# Each row is a deliberately unique 3-domain / 2-register / confusion-pair combination.
BATCHES = [
    (("checkout", "inventory", "fraud"), ("incident-room", "staff-note"), ("refactor", "quickFix")),
    (("telemetry", "exports", "retention"), ("ticket", "design-chat"), ("review", "writing")),
    (("accessibility", "routing", "localization"), ("pairing", "product-brief"), ("writing", "backendImpl")),
    (("identity", "sessions", "permissions"), ("support-escalation", "code-review"), ("review", "debugging")),
    (("media", "transcoding", "storage"), ("architecture-note", "slack-thread"), ("planning", "refactor")),
    (("billing", "invoicing", "tax"), ("bug-report", "release-brief"), ("refactor", "quickFix")),
    (("search", "ranking", "indexing"), ("on-call-handoff", "pull-request"), ("review", "writing")),
    (("messaging", "presence", "notifications"), ("customer-ticket", "engineering-note"), ("writing", "backendImpl")),
    (("maps", "geocoding", "offline-sync"), ("standup", "failure-analysis"), ("review", "debugging")),
    (("analytics", "experiments", "consent"), ("roadmap-brief", "pairing-chat"), ("planning", "refactor")),
    (("scheduling", "calendars", "timezones"), ("maintenance-ticket", "team-chat"), ("refactor", "quickFix")),
    (("devices", "firmware", "provisioning"), ("qa-report", "api-note"), ("review", "writing")),
    (("education", "grading", "rosters"), ("spec-comment", "support-thread"), ("writing", "backendImpl")),
    (("health-data", "sync", "privacy"), ("postmortem", "review-comment"), ("review", "debugging")),
    (("deployments", "feature-flags", "rollbacks"), ("migration-brief", "dev-chat"), ("planning", "refactor")),
]

SECONDARIES = {
    "writing": ["review", "backendImpl"],
    "review": ["writing", "debugging"],
    "refactor": ["quickFix", "planning"],
    "quickFix": ["refactor", "debugging"],
    "frontendImpl": ["writing", "review"],
    "planning": ["refactor", "writing"],
    "debugging": ["review", "quickFix"],
    "backendImpl": ["writing", "review"],
}

TERSE = {
    "writing": "document the edge cases",
    "review": "any hidden risks here?",
    "refactor": "consolidate the duplicate branches",
    "quickFix": "rename the stale flag",
    "frontendImpl": "wire up keyboard navigation",
    "planning": "map the migration sequence",
    "debugging": "why are retries looping?",
    "backendImpl": "expose the health endpoint",
}

MEDIUM = {
    "writing": "needs a concise maintainer note covering its contract, failure modes, and one realistic usage example.",
    "review": "changed in yesterday's branch; inspect the behavior and call out correctness, security, or compatibility risks with concrete references.",
    "refactor": "has three nearly identical control paths. Reshape them around one shared abstraction without changing public behavior.",
    "quickFix": "uses the old option name in one branch. Make the smallest safe correction and keep the surrounding structure intact.",
    "frontendImpl": "is still a static shell. Connect loading, empty, error, and success states while preserving the existing component conventions.",
    "planning": "must move behind the new contract next quarter. Lay out sequencing, dependencies, rollback points, and verification milestones.",
    "debugging": "occasionally stalls after a retry. Trace the likely execution path, identify the cause, and prove it with a focused regression test.",
    "backendImpl": "needs a production-ready endpoint with validation, authorization, idempotency, structured errors, and focused integration coverage.",
}

LONG = {
    "writing": "The team keeps learning its behavior from scattered comments and old tickets, and new maintainers are making incompatible assumptions. Produce a practical guide that states the contract, walks through a normal request, describes retry and cancellation semantics, and includes one troubleshooting example. Keep it close to the code, distinguish guarantees from current implementation details, mention privacy implications, and avoid promising behavior the tests do not establish. Finish with a short checklist someone can use before changing the module.",
    "review": "This is about to ship behind a gradual rollout, but the change crosses validation, caching, and asynchronous cleanup. Read the relevant code as a whole and assess whether the new behavior is correct under retries, concurrent callers, stale data, and partial failure. Point to exact files or branches for every concern, separate blocking defects from optional improvements, and note any missing tests. Also check compatibility with existing callers and whether logs could expose sensitive values. Do not edit anything; return a prioritized assessment with a brief rationale.",
    "refactor": "Over time this module accumulated several paths that normalize the same input, choose a policy, and emit nearly identical results. Rework it so those decisions live in one obvious place while public types, error messages, and observable ordering remain stable. Prefer small named helpers over a new framework, preserve metrics and cancellation behavior, and keep the diff reviewable. Add characterization coverage where behavior is implicit, remove dead branches only when the tests prove they are unreachable, and leave a short note explaining the resulting ownership boundaries.",
    "quickFix": "A narrow regression appeared after the last option rename: one fallback path still reads the deprecated field and silently chooses the wrong default. Patch only that path, preserve the current API and surrounding control flow, and add a focused test that fails before the correction. Please avoid opportunistic cleanup, dependency changes, or broad formatting churn. Check both an explicitly supplied value and the absent-value case, then report the exact files touched and why the change cannot affect callers that already use the new field.",
    "frontendImpl": "The product shell exists, but the interaction is incomplete and keyboard users cannot finish the flow. Connect the view to the existing data hook, render distinct loading, empty, failure, and populated states, and keep focus stable when results refresh. The layout must work at narrow mobile widths and at two hundred percent zoom, use the established design tokens, and announce validation errors accessibly. Preserve deep links and browser back behavior. Add component tests for keyboard navigation and the retry action without replacing the repository's current state-management pattern.",
    "planning": "This area has to migrate without interrupting active users, and several consumers still rely on undocumented ordering. Draft an execution path that begins with discovery and characterization, identifies dependency owners, introduces compatibility seams, and ends with removal of the old route. Include checkpoints for observability, load testing, privacy review, staged rollout, and rollback. Call out assumptions that need confirmation, propose how to measure success, and divide the work into reviewable increments. No code changes yet; the result should let the team estimate risk and assign follow-up tickets.",
    "debugging": "Intermittent failures are appearing only when a request is retried while an earlier attempt is completing, and the existing logs disagree about which attempt owns the final state. Follow the data and control flow from entry point through persistence and cleanup, form a specific hypothesis, and test it rather than masking the symptom. Check timer cancellation, shared mutable state, idempotency keys, and error translation. Once the cause is established, add the smallest regression test that reproduces it and describe the evidence connecting the failure to the responsible branch.",
    "backendImpl": "The client contract is approved and now needs a complete server path. Introduce the endpoint using existing routing and service conventions, validate identifiers and bounded pagination, enforce tenant-scoped authorization, and make repeated submissions idempotent. Persist through the current repository layer, return the documented structured errors, and emit metrics without logging user content. Cover success, malformed input, forbidden access, duplicate requests, and storage failure in integration tests. Keep schema changes backward compatible and include a safe rollout note if a migration or feature flag is required.",
}

LOCAL_ACTION = {
    "es": {
        "writing": "deja una guía breve con contrato, fallos y un ejemplo real",
        "review": "revisa el cambio y señala riesgos concretos sin tocar el código",
        "refactor": "reordena estas rutas duplicadas sin cambiar el comportamiento público",
        "quickFix": "corrige solo la rama equivocada y añade una prueba enfocada",
        "frontendImpl": "conecta los estados de carga, vacío, error y éxito con accesibilidad",
        "planning": "propón una secuencia con dependencias, métricas y rollback",
        "debugging": "averigua por qué se repite el intento y demuéstralo con una prueba",
        "backendImpl": "completa el endpoint con validación, auth e idempotency",
    },
    "de": {
        "writing": "erstelle eine knappe Maintainer-Doku mit Vertrag, Fehlerfällen und Beispiel",
        "review": "prüfe die Änderung auf konkrete Risiken, ohne Dateien zu ändern",
        "refactor": "führe die doppelten Pfade zusammen, ohne externes Verhalten zu ändern",
        "quickFix": "korrigiere nur den falschen Zweig und ergänze einen gezielten Test",
        "frontendImpl": "verbinde Loading-, Empty-, Error- und Success-State barrierefrei",
        "planning": "skizziere Reihenfolge, Abhängigkeiten, Messpunkte und Rollback",
        "debugging": "finde die Ursache der Retry-Schleife und belege sie mit einem Test",
        "backendImpl": "vervollständige den Endpoint mit Validierung, Auth und Idempotency",
    },
    "fr": {
        "writing": "rédige une note mainteneur avec contrat, erreurs et exemple concret",
        "review": "examine ce changement et relève les risques précis sans modifier le code",
        "refactor": "regroupe les chemins dupliqués sans changer le comportement public",
        "quickFix": "corrige uniquement la branche fautive avec un test ciblé",
        "frontendImpl": "branche les états loading, empty, error et success de façon accessible",
        "planning": "propose un ordre, les dépendances, les métriques et le rollback",
        "debugging": "trouve la cause de la boucle de retry et prouve-la par un test",
        "backendImpl": "termine l'endpoint avec validation, auth et idempotency",
    },
    "pt": {
        "writing": "prepare uma nota curta com contrato, falhas e exemplo real",
        "review": "avalie a mudança e aponte riscos concretos sem editar o código",
        "refactor": "una os caminhos duplicados sem alterar o comportamento público",
        "quickFix": "corrija somente o ramo errado e acrescente um teste focado",
        "frontendImpl": "ligue os estados loading, empty, error e success com acessibilidade",
        "planning": "desenhe sequência, dependências, métricas e rollback",
        "debugging": "descubra a causa do retry infinito e comprove com um teste",
        "backendImpl": "complete o endpoint com validação, auth e idempotency",
    },
    "zh": {
        "writing": "请整理一份简短维护文档，包含契约、失败场景和真实示例",
        "review": "请检查这次改动的具体风险，不要修改代码",
        "refactor": "合并重复路径，但保持公开行为完全不变",
        "quickFix": "只修正错误分支，并补一个针对性测试",
        "frontendImpl": "接好 loading、empty、error 和 success 状态，并保证无障碍体验",
        "planning": "给出迁移顺序、依赖、观测指标和 rollback 方案",
        "debugging": "查明 retry 循环的根因，并用回归测试证明",
        "backendImpl": "完成 endpoint，包括 validation、auth 和 idempotency",
    },
    "ja": {
        "writing": "契約、失敗例、実例を含む短い保守向けドキュメントを残して",
        "review": "コードは変更せず、この差分の具体的なリスクを確認して",
        "refactor": "外部挙動を変えずに重複した経路を一つにまとめて",
        "quickFix": "誤った分岐だけ直し、focused test を追加して",
        "frontendImpl": "loading、empty、error、success を接続し accessibility も守って",
        "planning": "移行順序、依存関係、metrics、rollback を整理して",
        "debugging": "retry loop の根本原因を特定し regression test で証明して",
        "backendImpl": "validation、auth、idempotency を含む endpoint を完成させて",
    },
}

COMPACT = {
    "en": {"writing": "document contract", "review": "assess risks", "refactor": "merge duplicate branches",
           "quickFix": "patch stale flag", "frontendImpl": "wire accessible UI", "planning": "sequence migration",
           "debugging": "trace retry loop", "backendImpl": "finish authenticated endpoint"},
    "es": {"writing": "documenta contrato", "review": "evalúa riesgos", "refactor": "consolida ramas",
           "quickFix": "corrige flag", "frontendImpl": "conecta UI", "planning": "ordena migración",
           "debugging": "rastrea retry loop", "backendImpl": "termina endpoint autenticado"},
    "de": {"writing": "Vertrag dokumentieren", "review": "Risiken prüfen", "refactor": "Zweige bündeln",
           "quickFix": "Flag korrigieren", "frontendImpl": "UI anbinden", "planning": "Migration ordnen",
           "debugging": "Retry-Schleife finden", "backendImpl": "Auth-Endpoint bauen"},
    "fr": {"writing": "documente contrat", "review": "évalue risques", "refactor": "regroupe branches",
           "quickFix": "corrige flag", "frontendImpl": "branche UI", "planning": "ordonne migration",
           "debugging": "trace retry-loop", "backendImpl": "termine endpoint"},
    "pt": {"writing": "documente contrato", "review": "avalie riscos", "refactor": "una ramos",
           "quickFix": "corrija flag", "frontendImpl": "ligue UI", "planning": "ordene migração",
           "debugging": "rastreie retry-loop", "backendImpl": "termine endpoint"},
    "zh": {"writing": "记录 API 契约", "review": "检查具体风险", "refactor": "合并重复分支",
           "quickFix": "修正旧 flag", "frontendImpl": "接好无障碍 UI", "planning": "安排迁移顺序",
           "debugging": "追踪 retry loop", "backendImpl": "完成鉴权 endpoint"},
    "ja": {"writing": "API 契約を文書化", "review": "具体的なリスクを確認", "refactor": "重複分岐を統合",
           "quickFix": "古い flag を修正", "frontendImpl": "accessible UI を接続", "planning": "移行順序を整理",
           "debugging": "retry loop を追跡", "backendImpl": "認証付き endpoint を完成"},
}


def words(text: str) -> int:
    return len(re.findall(r"\S+", text))


def opener(batch: int, line: int, domain: str) -> str:
    """A varied artifact, stakeholder, circumstance, or noun-phrase opener."""
    stem = re.sub(r"[^A-Za-z0-9]", "", domain.title())
    ident = f"B{batch + 1:02d}L{line + 1:03d}"
    styles = (
        f"src/{domain}/{ident.lower()}.ts",
        f"{stem}Worker ({ident})",
        f"[{stem[:4].upper()}-{batch + 1}{line + 101}]",
        f"Support noticed the {domain} worker ({ident})",
        f"QA isolated a failure in {domain} ({ident})",
        f"PM flagged the {domain} handoff ({ident})",
        f"SRE saw {domain} retries spike ({ident})",
        f"Design called out the {domain} flow ({ident})",
        f"Security questioned the {domain} guard ({ident})",
        f"During failover, the {domain} path ({ident})",
        f"After deploy {ident}, the {domain} module",
        f"Whenever retries overlap, the {domain} path ({ident})",
        f"Our {domain} worker ({ident})",
        f"This {domain} module ({ident})",
        f"Yesterday's {domain} rollout ({ident})",
        f"A {domain} incident report ({ident})",
        f"The {domain} branch ({ident})",
        f"One {domain} caller ({ident})",
        f"Somehow the {domain} path ({ident})",
        f"Oddly, the {domain} worker ({ident})",
        f"Heads-up: the {domain} module ({ident})",
        f"Sorry, the {domain} branch ({ident})",
        f"Customer report {ident} mentions the {domain} flow",
        f"On-call traced the {domain} failure ({ident})",
        f"tools/{domain}/{ident.lower()}.go",
    )
    return styles[line % len(styles)]


def short_opener(batch: int, line: int, domain: str) -> str:
    stem = re.sub(r"[^A-Za-z0-9]", "", domain.title())
    return f"{stem}CaseB{batch + 1:02d}L{line + 1:03d}"


def localized(action_label: str, lang: str, suffix: str = "") -> str:
    action = LOCAL_ACTION[lang][action_label]
    connectors = {
        "es": " Contexto técnico:", "de": " Technischer Kontext:",
        "fr": " Contexte technique :", "pt": " Contexto técnico:",
        "zh": " 技术上下文：", "ja": " 技術的な前提:",
    }
    return f"{action}.{connectors[lang]} {suffix}" if suffix else f"{action}."


def terse_prompt(op: str, label: str, lang: str) -> str:
    return f"{op}: {COMPACT[lang][label]}"


def medium_prompt(op: str, label: str, lang: str, domain: str, register: str) -> str:
    if lang == "en":
        sentence = MEDIUM[label][0].upper() + MEDIUM[label][1:]
        shapes = (
            f"{op}. {sentence}",
            f"{op}: {MEDIUM[label]}",
            f"{op}. From the {register}: {MEDIUM[label]}",
        )
        return shapes[len(op) % len(shapes)]
    detail = f"{domain} module; keep existing API, tests, metrics, and error semantics stable"
    return f"{op}: {localized(label, lang, detail)}"


def long_prompt(op: str, label: str, lang: str, domains: tuple[str, ...], registers: tuple[str, ...]) -> str:
    context = LONG[label]
    tail = (
        f"The immediate context is the {domains[0]} path, but verify its interactions with "
        f"{domains[1]} and {domains[2]}. The request originated in a {registers[0]} and should "
        f"be understandable to someone reading it later from a {registers[1]}."
    )
    if lang == "en":
        return f"{op}. {context} {tail}"
    return f"{op}: {localized(label, lang, context + ' ' + tail)}"


def boundary_prompt(op: str, label: str, lang: str, long: bool,
                    domains: tuple[str, ...], registers: tuple[str, ...],
                    pair: tuple[str, str]) -> str:
    # The request stays actionable while sitting close to a common intent boundary.
    pair_note = {
        ("refactor", "quickFix"): "Keep the change narrow; the question is whether the tiny restructure is necessary for the correction.",
        ("review", "writing"): "The useful output should distinguish an assessment of the artifact from prose intended for future readers.",
        ("writing", "backendImpl"): "Treat the API contract as documentation unless executable server behavior is explicitly requested.",
        ("review", "debugging"): "Separate understanding suspicious behavior from proving that an actual defect exists.",
        ("planning", "refactor"): "The boundary is whether to propose a safer structure or perform that restructuring now.",
    }[pair]
    if long:
        base = f"{LONG[label]} {pair_note} The affected areas are {', '.join(domains)}, and the tone should fit a {registers[0]}."
        if lang == "en":
            return f"{op}. This raises an awkward scope question. {base}"
        return f"{op}: {localized(label, lang, base)}"
    boundary_medium = {
        "writing": "The code works, but its contract is opaque. Describe what callers may rely on; do not turn the note into a feature patch.",
        "review": "Tell me what this branch does and whether its assumptions are safe; only report defects that the code actually supports.",
        "refactor": "Rename the misleading helper and move its repeated guard beside the caller, preserving every observable result.",
        "quickFix": "One local name hides the real unit. Correct that small mismatch without redesigning the surrounding module.",
        "frontendImpl": "The mock already defines the interaction. Complete only the missing focus and error states, then note any design ambiguity.",
        "planning": "Describe how to split this oversized module safely, with characterization steps and stopping points; leave the files untouched.",
        "debugging": "Why does this branch skip the cache sometimes? Determine whether it is intentional before proposing any correction.",
        "backendImpl": "The API page promises idempotent creation. Wire that documented behavior into the existing handler and cover duplicate requests.",
    }[label]
    if lang == "en":
        return f"{op}: {boundary_medium}"
    return f"{op}: {localized(label, lang, boundary_medium)}"


def mixed_prompt(op: str, primary: str, secondary: str, lang: str, long: bool,
                 domains: tuple[str, ...], registers: tuple[str, ...]) -> str:
    if long:
        base = (
            f"{LONG[primary]} After completing that main task, also handle this separate need: {LONG[secondary]} "
            f"Keep the two deliverables visibly distinct so the {registers[0]} can act on the first while the "
            f"{registers[1]} preserves the second. Check interactions across {', '.join(domains)}."
        )
    else:
        base = f"{MEDIUM[primary]} Separately, it {MEDIUM[secondary]}"
    if lang == "en":
        return f"{op}: {base}"
    return f"{op}: {localized(primary, lang, base)}"


def pasted_material(batch: int, line: int, op: str, domains: tuple[str, ...], kind: int) -> str:
    d0, d1, d2 = domains
    rid = f"req-{batch + 1:02d}-{line + 1:03d}"
    if kind % 5 == 0:
        return f"""{op}
Captured pasted CI failure:
$ pnpm test --filter {d0}-integration -- --runInBand
RUN v3.8.2 /workspace/apps/{d0}
stdout | reconcile preserves an existing reservation
[{rid}] seed tenant=acme actor=user-17 region=eu-west-1
[{rid}] POST /v2/{d0} idempotency-key=case-441 attempt=1
[{rid}] repository.insert status=committed version=18 elapsed=43ms
[{rid}] response status=201 body.id=obj-81 cache=miss
stdout | reconcile preserves an existing reservation
[{rid}] POST /v2/{d0} idempotency-key=case-441 attempt=2
[{rid}] repository.lookup status=not_found replica=reader-2 lag=87ms
[{rid}] repository.insert status=conflict code=unique_violation elapsed=12ms
[{rid}] error.translate input=unique_violation output=internal_error
FAIL test/integration/reconcile.spec.ts > retries > preserves an existing reservation
AssertionError: expected 500 to equal 200
  at test/integration/reconcile.spec.ts:184:31
  at async withTenant (test/support/tenant.ts:47:5)
Expected: 200
Received: 500
UnhandledPromiseRejection: Error: metric scope closed before retry counter flushed
  at MetricsScope.increment (src/metrics/scope.ts:92:13)
  at finalizeAttempt (src/{d0}/reconcile.ts:211:9)
Test Files 1 failed | 37 passed (38)
Tests 1 failed | 286 passed (287)
Duration 18.42s"""
    if kind % 5 == 1:
        return f"""{op}
Captured production log tail:
2026-07-29T18:42:11.083Z INFO  gateway request_started request_id={rid} route=/{d0}/sync tenant=t-42 attempt=1
2026-07-29T18:42:11.091Z DEBUG auth policy_resolved request_id={rid} subject=u-19 scopes={d0}:write,{d1}:read
2026-07-29T18:42:11.112Z INFO  {d1} snapshot_loaded request_id={rid} version=902 items=148 source=replica
2026-07-29T18:42:11.130Z WARN  {d2} lease_expiring request_id={rid} remaining_ms=34 owner=worker-7
2026-07-29T18:42:11.151Z ERROR {d0} commit_failed request_id={rid} code=deadline_exceeded retryable=true elapsed_ms=68
2026-07-29T18:42:11.152Z INFO  gateway retry_scheduled request_id={rid} delay_ms=25 attempt=2
2026-07-29T18:42:11.179Z INFO  {d0} request_resumed request_id={rid} lease=lease-887
2026-07-29T18:42:11.184Z WARN  {d2} lease_owner_changed request_id={rid} previous=worker-7 current=worker-3
2026-07-29T18:42:11.207Z INFO  {d0} commit_ok request_id={rid} version=903 writes=6
2026-07-29T18:42:11.209Z ERROR cleanup release_rejected request_id={rid} reason=owner_mismatch expected=worker-7 actual=worker-3
2026-07-29T18:42:11.211Z INFO  gateway response_sent request_id={rid} status=200 elapsed_ms=128
2026-07-29T18:42:11.214Z ERROR worker unhandled_exception request_id={rid} type=LeaseOwnershipError
2026-07-29T18:42:11.215Z WARN  queue message_requeued request_id={rid} delivery_count=4 visibility_timeout_s=30
2026-07-29T18:42:41.226Z INFO  gateway request_started request_id={rid}-replay route=/{d0}/sync tenant=t-42 attempt=1
Dashboard note: successful responses increased while queue depth and duplicate-write alarms rose together."""
    if kind % 5 == 2:
        return f"""{op}
Captured proposed patch:
diff --git a/src/{d0}/resolver.ts b/src/{d0}/resolver.ts
index 8c281aa..1af644e 100644
--- a/src/{d0}/resolver.ts
+++ b/src/{d0}/resolver.ts
@@ -42,18 +42,34 @@ export async function resolve(input: Input, ctx: Context) {{
-  const cached = await ctx.cache.get(input.key)
-  if (cached) return JSON.parse(cached)
-  const record = await ctx.{d1}.load(input.key)
-  return normalize(record)
+  const state = await readState(input, ctx)
+  if (state.kind === 'hit') return state.value
+  if (state.kind === 'missing' && input.allowEmpty) return EMPTY_RESULT
+  return normalize(await ctx.{d1}.load(input.key))
 }}
+
+async function readState(input: Input, ctx: Context): Promise<State> {{
+  try {{
+    const raw = await ctx.cache.get(input.key)
+    if (raw == null) return {{ kind: 'missing' }}
+    ctx.metrics.increment('{d0}.cache.hit', 1, {{ key: input.key }})
+    return {{ kind: 'hit', value: JSON.parse(raw) }}
+  }} catch (error) {{
+    ctx.logger.warn('cache read failed', {{ input, error }})
+    return {{ kind: 'missing' }}
+  }}
+}}
diff --git a/test/{d0}/resolver.spec.ts b/test/{d0}/resolver.spec.ts
index f042d19..4d71d90 100644
--- a/test/{d0}/resolver.spec.ts
+++ b/test/{d0}/resolver.spec.ts
@@ -88,6 +88,10 @@ describe('resolve', () => {{
+  it('returns empty when cache misses and allowEmpty is true', async () => {{
+    expect(await resolve(input({{ allowEmpty: true }}), ctx())).toEqual(EMPTY_RESULT)
+  }})
 }})
PR description: centralize cache handling, tolerate malformed entries, and reduce calls to {d1}. No schema or API changes intended. The {d2} consumer is not covered by this test fixture."""
    if kind % 5 == 3:
        return f"""{op}
Captured ticket excerpt:
Title: Make {d0} reconciliation safe during regional failover
Owner: Platform Foundations
Target: 2026-Q3 maintenance window
Background:
Customers can keep editing while traffic moves between regions. The current worker reads {d1} from a local replica, obtains a ninety-second lease, writes normalized rows, and publishes a {d2} event. During the June exercise, replica lag exceeded the lease renewal threshold. Two workers then published different versions for the same logical operation.
Acceptance notes:
- Existing mobile clients must not receive a new required field.
- A repeated operation with the same key returns the first committed result.
- Operators can identify the winning attempt without user content in logs.
- Rollout begins with internal tenants, then one percent, ten percent, and full traffic.
- The old worker remains available for rollback for seven days.
Known constraints:
- Table rewrites longer than thirty seconds are not approved.
- The queue offers at-least-once delivery and may reorder messages.
- Analytics currently treats every published event as a unique operation.
- Security wants tenant authorization checked before idempotency lookup.
Open questions:
Who owns cleanup after rollback? Can the event schema gain an optional attempt identifier? Which dashboard is authoritative when the database and queue disagree?
Comment from QA: Please include a deterministic failover test; sleeps made the earlier suite flaky."""
    return f"""{op}
Captured request and trace capture:
POST /api/v3/{d0}/reconcile?dry_run=false HTTP/1.1
Host: api.internal.example
Content-Type: application/json
Idempotency-Key: idem-{batch + 1}-{line + 101}
X-Tenant: tenant-42
X-Request-Id: {rid}

{{"source":"{d1}","mode":"merge","items":[{{"id":"a-17","version":8}},{{"id":"b-04","version":3}}],"notify":true}}

HTTP/1.1 202 Accepted
Content-Type: application/json
Retry-After: 2

{{"job_id":"job-882","state":"queued","links":{{"status":"/api/v3/jobs/job-882"}}}}

GET /api/v3/jobs/job-882 HTTP/1.1
X-Tenant: tenant-42
X-Request-Id: {rid}-poll-1

HTTP/1.1 200 OK
{{"job_id":"job-882","state":"complete","result":{{"merged":2,"skipped":0}},"warnings":[]}}

Trace spans:
gateway.receive              0.0ms   3.8ms status=202
auth.authorize               0.7ms   1.2ms decision=allow
queue.publish                2.1ms   1.4ms partition=11 offset=8041
worker.consume             206.4ms  48.2ms delivery=1
{d1}.read                  211.1ms  17.7ms rows=2 replica=true
{d0}.write                 229.8ms  20.9ms rows=2 transaction=tx-71
{d2}.publish               251.4ms   3.1ms event_id=evt-55
job.complete               254.9ms   0.8ms
Customer report: polling sometimes returns complete, but a second notification arrives roughly thirty seconds later with the same event identifier and a different attempt number."""


def pasted_prompt(batch: int, line: int, op: str, label: str, lang: str,
                  domains: tuple[str, ...], registers: tuple[str, ...]) -> str:
    material = pasted_material(batch, line, op, domains, line)
    asks = {
        "writing": "Turn this material into a concise maintainer-facing note that states the observed contract, operational warning signs, and a reproducible example; do not invent guarantees.",
        "review": "Assess the pasted artifact for correctness, security, compatibility, and test gaps. Cite the exact lines that support each finding and do not edit the repository.",
        "refactor": "Reshape the responsible code so duplicated decisions have one owner while behavior, ordering, metrics, and public errors stay stable; add characterization coverage first.",
        "quickFix": "Make the smallest safe correction supported by this evidence, add one focused regression test, and avoid unrelated cleanup or dependency changes.",
        "frontendImpl": "Complete the affected interface, including loading, empty, error, retry, focus, and narrow-screen behavior, using the existing hooks and design tokens.",
        "planning": "Produce a staged execution plan with owners, dependencies, observability, compatibility checks, rollout gates, and an explicit rollback path; make no code changes yet.",
        "debugging": "Trace the conflicting attempts to a specific cause, test the hypothesis, and show how a deterministic regression case reproduces the failure before proposing a patch.",
        "backendImpl": "Complete the server behavior implied here with tenant authorization, validation, idempotency, structured errors, metrics, and integration coverage for retries and partial failure.",
    }
    ask = asks[label]
    if lang != "en":
        ask = localized(label, lang, ask)
    return f"{material}\n\nRequest: {ask}"


def vague_prompt(op: str, label: str, lang: str) -> str:
    vague = {
        "writing": "make this easier to follow",
        "review": "does this seem safe?",
        "refactor": "could this be cleaner?",
        "quickFix": "tidy this small thing",
        "frontendImpl": "make this screen feel finished",
        "planning": "what should happen next?",
        "debugging": "why does this feel flaky?",
        "backendImpl": "make this API work",
    }[label]
    if lang == "en":
        return f"{op}: {vague}"
    return terse_prompt(op, label, lang)


def build_batch(batch_index: int) -> list[dict]:
    domains, registers, pair = BATCHES[batch_index]
    rng = random.Random(730_000 + batch_index)

    slices = [s for s, count in SLICE_COUNTS.items() for _ in range(count)]
    rng.shuffle(slices)
    nonvague_labels = [label for label, count in LABEL_COUNTS.items() for _ in range(count)]
    rng.shuffle(nonvague_labels)
    label_iter = iter(nonvague_labels)
    labels = [next(label_iter) if s != "vague-eval" else LABELS[(i + batch_index) % len(LABELS)]
              for i, s in enumerate(slices)]

    # Every pasted entry is long. Pick exactly 30 additional long entries and 44
    # non-vague terse entries; all 16 vague entries are terse, giving exactly 60.
    eligible = [i for i, s in enumerate(slices) if s not in ("pasted-context", "vague-eval")]
    rng.shuffle(eligible)
    long_extra = set(eligible[:30])
    terse_candidates = [i for i in eligible if i not in long_extra]
    rng.shuffle(terse_candidates)
    terse_indices = set(terse_candidates[:44]) | {i for i, s in enumerate(slices) if s == "vague-eval"}

    # Sixteen non-English lines, spread across all six requested languages and shapes.
    shape_buckets = [
        [i for i in range(200) if i in terse_indices],
        [i for i in range(200) if slices[i] == "pasted-context"],
        [i for i in range(200) if i not in terse_indices and slices[i] != "pasted-context"],
    ]
    chosen_lang_indices: list[int] = []
    for bucket, take in zip(shape_buckets, (4, 6, 6)):
        rng.shuffle(bucket)
        chosen_lang_indices.extend(bucket[:take])
    rng.shuffle(chosen_lang_indices)
    lang_at = {idx: LOCALES[n % len(LOCALES)] for n, idx in enumerate(chosen_lang_indices)}

    secondary_rotation = Counter()
    rows: list[dict] = []
    for line, (slice_name, label) in enumerate(zip(slices, labels)):
        lang = lang_at.get(line, "en")
        domain = domains[line % 3]
        op = opener(batch_index, line, domain)
        if line in terse_indices:
            op = short_opener(batch_index, line, domain)
        is_long = slice_name == "pasted-context" or line in long_extra
        secondary = None

        if slice_name == "pasted-context":
            prompt = pasted_prompt(batch_index, line, op, label, lang, domains, registers)
        elif slice_name == "vague-eval":
            prompt = vague_prompt(op, label, lang)
        elif slice_name == "mixed":
            choices = SECONDARIES[label]
            secondary = choices[secondary_rotation[label] % len(choices)]
            secondary_rotation[label] += 1
            if line in terse_indices:
                # Two real asks in fewer than eight whitespace-delimited words.
                compact = f"{COMPACT[lang][label]}; {COMPACT[lang][secondary]}"
                prompt = f"{op}: {compact}"
            else:
                prompt = mixed_prompt(op, label, secondary, lang, is_long, domains, registers)
        elif line in terse_indices:
            prompt = terse_prompt(op, label, lang)
        elif slice_name == "boundary":
            prompt = boundary_prompt(op, label, lang, is_long, domains, registers, pair)
        elif is_long:
            prompt = long_prompt(op, label, lang, domains, registers)
        else:
            prompt = medium_prompt(op, label, lang, domain, registers[line % 2])

        rows.append({
            "prompt": prompt,
            "purpose": label,
            "secondary": secondary,
            "mixed": slice_name == "mixed",
            "difficulty": "easy" if line in terse_indices else ("hard" if is_long else "medium"),
            "slice": slice_name,
            "lang": lang,
        })
    return rows


def validate_batch(rows: list[dict], batch_index: int) -> None:
    assert len(rows) == 200
    assert Counter(r["slice"] for r in rows) == Counter(SLICE_COUNTS), (batch_index, Counter(r["slice"] for r in rows))
    nonvague = [r for r in rows if r["slice"] != "vague-eval"]
    assert Counter(r["purpose"] for r in nonvague) == Counter(LABEL_COUNTS)
    assert sum(r["mixed"] for r in rows) == 24
    assert all((r["secondary"] is not None) == r["mixed"] for r in rows)
    assert all(r["slice"] == "mixed" for r in rows if r["mixed"])
    assert sum(words(r["prompt"]) < 8 for r in rows) >= 60
    assert sum(words(r["prompt"]) > 60 for r in rows) >= 80
    assert 14 <= sum(r["lang"] != "en" for r in rows) <= 18
    assert set(r["lang"] for r in rows if r["lang"] != "en") == set(LOCALES)
    pasted_materials = [r["prompt"].split("\n\nRequest:", 1)[0]
                        for r in rows if r["slice"] == "pasted-context"]
    assert all(100 <= words(material) <= 400 for material in pasted_materials)
    assert all(set(r) == {"prompt", "purpose", "secondary", "mixed", "difficulty", "slice", "lang"} for r in rows)

    # No opening token more than twice in any sliding 50-line window.
    opening = [r["prompt"].split()[0].lower() for r in rows]
    for start in range(151):
        counts = Counter(opening[start:start + 50])
        assert max(counts.values()) <= 2, (batch_index, start, counts.most_common(3))


def main() -> None:
    all_rows: list[dict] = []
    for batch_index in range(15):
        rows = build_batch(batch_index)
        validate_batch(rows, batch_index)
        all_rows.extend(rows)
    assert len(all_rows) == 3000
    assert len({r["prompt"] for r in all_rows}) == 3000
    OUT.write_text("".join(json.dumps(row, ensure_ascii=False, separators=(",", ":")) + "\n" for row in all_rows), encoding="utf-8")
    print(OUT)


if __name__ == "__main__":
    main()
