{
    "name": "batch-compress",
    "description": "Batch compression: 4 large text turns compressed as two separate ranges in a single compress call, producing 2 blocks. Validates the batch/multi-range path of the compress tool.",
    "turns": [
        {
            "respond": "text",
            "userText": "Explain the caching layer.",
            "text": "The caching layer sits between the application and the database to reduce latency and load. We use Redis (cluster mode) as the primary cache. The cache client is initialized at src/cache/client.ts:24 with connection pooling (10 connections per node) and a command timeout of 200ms. The core read-through helper at src/cache/read-through.ts:18 implements the canonical pattern: on a cache key miss it falls back to the database, writes the result back with a TTL, and returns; on a Redis error it degrades gracefully to the database rather than failing the request (circuit breaker at src/cache/circuit-breaker.ts:40, opens after 5 failures in 10s, half-opens after 30s). Cache keys are namespaced as svc:{service}:{entity}:{id} and constructed at src/cache/keys.ts:12. TTLs are entity-specific: user profiles 5 minutes (src/cache/ttl.ts:14), product catalog 60 minutes (src/cache/ttl.ts:22), session data 24 hours (src/cache/ttl.ts:30). Cache invalidation is event-driven: when the database writes an entity, it publishes to the cache-invalidation Redis pub/sub channel; subscribers delete the stale key. The publisher lives at src/cache/invalidate.ts:28, the subscriber at src/cache/subscriber.ts:33. Stampede protection prevents thundering-herd rebuilds when a hot key expires: a per-key mutex (SETNX with TTL) at src/cache/stampede.ts:19 ensures only one request rebuilds the value while others wait. Negative caching stores empty-result sentinels for 30s to avoid repeated DB probes for nonexistent keys (src/cache/negative.ts:16). Cache hit ratio is instrumented at src/cache/metrics.ts:24 and exported to Prometheus as cache_hit_ratio{service,entity}; the SLO is >92% for the product catalog. The warmup job preloads hot keys on deploy via src/cache/warmup.ts:50."
        },
        {
            "respond": "text",
            "userText": "Continue with cache consistency and failure modes.",
            "text": "Cache consistency is the hardest part of a two-tier (cache + DB) system. We guarantee eventual consistency via write-through for critical entities and cache-aside with TTL expiry for the rest. Write-through is implemented at src/cache/write-through.ts:22: the service writes to the DB and the cache in a single logical operation, with a compensating delete on cache-write failure (logged but not fatal). Read-your-writes consistency for the originating user is achieved by pinning to the primary DB replica for 5 seconds after a write (src/db/session-pinning.ts:30). The main failure modes and mitigations: (1) cache crash — circuit breaker opens, traffic falls through to DB, autoscaler absorbs the spike (src/cache/circuit-breaker.ts:40); (2) stale reads after a write missed by invalidation — a periodic reconciliation job at src/cache/reconcile.ts:44 re-checks random keys against the DB every 60s and evicts mismatches; (3) hot-key overload — when a single key sees >10k QPS we shard it into N sub-keys (src/cache/shard.ts:28) so load spreads across nodes; (4) big-value eviction — values over 1MB are chunked at src/cache/chunk.ts:18 to avoid Redis memory fragmentation; (5) cold-start after deploy — the warmup job (src/cache/warmup.ts:50) preloads the top 1000 keys from a daily snapshot. Distributed locking with Redlock (src/cache/redlock.ts:36) serializes competitive updates across nodes with a 10s auto-release. The observability dashboard (src/cache/dashboard.ts:60) plots hit ratio, latency p50/p99, error rate, and circuit-breaker state. A full cache flush is a privileged, audited operation wired behind a feature flag at src/admin/cache-flush.ts:25; it is never automated."
        },
        {
            "respond": "text",
            "userText": "Now explain the logging infrastructure.",
            "text": "The logging infrastructure uses structured JSON logs shipped to OpenSearch via Fluent Bit. Each service emits logs through the shared logger at src/log/logger.ts:20, which wraps pino with a fixed schema: timestamp (ISO 8601 UTC), level, service, instanceId, requestId (propagated via the x-request-id header, parsed at src/middleware/request-id.ts:14), userId (added after auth at src/middleware/auth-context.ts:40), and the message plus arbitrary structured fields. Log levels: fatal, error, warn, info, debug, trace; the default is info and is configurable via LOG_LEVEL (src/log/config.ts:16). Sampling reduces volume: debug logs are sampled at 1/100 in production (src/log/sampler.ts:22). Sensitive fields (password, token, apiKey, ssn) are redacted by a recursive scrubber at src/log/redact.ts:18 using an allowlist-denylist merge. Request-scoped context (the current user, the trace span) is propagated with AsyncLocalStorage at src/log/context.ts:28 so every log line within a request is enriched without threading arguments. The Fluent Bit DaemonSet on each Kubernetes node tails the log files (src/log/rotate.ts:30 rotates at 100MB / keeps 5) and forwards to OpenSearch; the index template at deploy/opensearch/index-template.json maps requestId as a keyword for fast correlation. Distributed tracing uses OpenTelemetry: spans are created at src/trace/span.ts:24 around every external call, exported via OTLP to Jaeger at src/trace/exporter.ts:18. Metrics (counters, histograms) use prom-client at src/metrics/client.ts:20 and are scraped at /metrics (src/routes/metrics.ts:12). The alerting rules in deploy/alerts.yaml fire on: error rate >1% over 5m, p99 latency >2s, log volume drop (pipeline breakage). Log retention is 30 days hot, 90 days warm, 2 years cold (S3), per the policy at src/log/retention.ts:14."
        },
        {
            "respond": "text",
            "userText": "Continue with observability and alerting.",
            "text": "Observability spans logs, metrics, and traces, correlated by the shared requestId/traceId. The three pillars are joined in the operations dashboard at deploy/grafana/dashboards/ops.json. Alerting is defined as code (deploy/alerts.yaml) and evaluated by Prometheus; a critical alert pages the on-call engineer via PagerDuty within 60 seconds (src/alerts/pagerduty.ts:26). Alert taxonomy: (1) availability — SLO burn rate exceeds 14.4x over 1h (deploy/alerts.yaml:18), (2) latency — p99 > 2s for 5m (deploy/alerts.yaml:34), (3) error — 5xx ratio > 1% for 5m (deploy/alerts.yaml:50), (4) saturation — CPU > 80% or memory > 90% for 10m (deploy/alerts.yaml:66), (5) correctness — a canary check fails (src/alerts/canary.ts:40 runs synthetic transactions every 60s). Every alert includes a runbook link in its annotations (deploy/runbooks/) so the on-call engineer knows the remediation. Dead-letter handling: failed async jobs are written to a DLQ with full context at src/queue/dlq.ts:30 and retried with exponential backoff (src/queue/retry.ts:22, base 1s, factor 2, max 5min, 12 attempts). Health checks: liveness at /healthz (src/routes/health.ts:14, process alive), readiness at /readyz (src/routes/health.ts:28, can serve traffic, checks DB + cache + queue connectivity). The deploy pipeline gates on the canary: a rollout proceeds only if the canary's error rate stays below 0.1% for 10 minutes (src/deploy/canary-gate.ts:50). Incident postmortems are stored in docs/incidents/ and linked from the dashboard (src/alerts/postmortem-link.ts:18)."
        },
        {
            "respond": "compress",
            "ranges": [
                {
                    "topic": "Caching Layer & Consistency",
                    "range": [0, 1],
                    "summary": "## Caching Layer (Redis cluster)\n- Client src/cache/client.ts:24 (pool 10/node, 200ms timeout). Read-through src/cache/read-through.ts:18 (miss→DB→writeback). Circuit breaker src/cache/circuit-breaker.ts:40 (open after 5/10s, half-open 30s).\n- Keys svc:{service}:{entity}:{id} src/cache/keys.ts:12. TTLs src/cache/ttl.ts:14,22,30 (profiles 5m, catalog 60m, session 24h).\n- Invalidation: event-driven pub/sub — publisher src/cache/invalidate.ts:28, subscriber src/cache/subscriber.ts:33.\n- Stampede guard (SETNX mutex) src/cache/stampede.ts:19. Negative cache (empty sentinel 30s) src/cache/negative.ts:16. Hit-ratio SLO >92%, metrics src/cache/metrics.ts:24. Warmup src/cache/warmup.ts:50.\n\n## Consistency & Failure Modes\n- Write-through src/cache/write-through.ts:22 (compensating delete on cache fail). Read-your-writes: pin to primary 5s post-write src/db/session-pinning.ts:30.\n- Reconciliation src/cache/reconcile.ts:44 (random-key recheck 60s). Hot-key sharding src/cache/shard.ts:28. Big-value chunking src/cache/chunk.ts:18. Cold-start warmup src/cache/warmup.ts:50.\n- Redlock src/cache/redlock.ts:36 (10s auto-release). Dashboard src/cache/dashboard.ts:60. Flush is privileged+audited src/admin/cache-flush.ts:25."
                },
                {
                    "topic": "Logging & Observability",
                    "range": [2, 3],
                    "summary": "## Logging (pino JSON → Fluent Bit → OpenSearch)\n- Logger src/log/logger.ts:20; schema {ts,level,service,instanceId,requestId(x-request-id parsed src/middleware/request-id.ts:14),userId src/middleware/auth-context.ts:40}. Levels via LOG_LEVEL src/log/config.ts:16. Debug sampled 1/100 src/log/sampler.ts:22.\n- Redaction (password/token/apiKey/ssn) src/log/redact.ts:18. AsyncLocalStorage context src/log/context.ts:28. Rotate 100MB/5 src/log/rotate.ts:30. OTel tracing: spans src/trace/span.ts:24, OTLP→Jaeger src/trace/exporter.ts:18. Metrics prom-client src/metrics/client.ts:20, /metrics src/routes/metrics.ts:12.\n- Retention 30d hot/90d warm/2y cold(S3) src/log/retention.ts:14.\n\n## Observability & Alerting\n- Dashboard deploy/grafana/dashboards/ops.json (logs+metrics+traces joined by requestId/traceId).\n- Alerts deploy/alerts.yaml: SLO burn 14.4x/1h (:18), p99>2s/5m (:34), 5xx>1%/5m (:50), CPU/mem (:66), canary src/alerts/canary.ts:40 every 60s. PagerDuty 60s src/alerts/pagerduty.ts:26. Runbooks deploy/runbooks/.\n- DLQ src/queue/dlq.ts:30; retry backoff src/queue/retry.ts:22 (1s,factor2,max5min,12x). Health /healthz src/routes/health.ts:14, /readyz :28. Canary-gated deploy src/deploy/canary-gate.ts:50 (err<0.1%/10min). Postmortems docs/incidents/."
                }
            ]
        },
        {
            "respond": "text",
            "text": "Batch compression complete. Two summary blocks created.",
            "auto": true
        }
    ],
    "verify": {
        "blockCount": 2,
        "activeBlockCount": 2,
        "minCompressedCount": 1
    }
}
