SANDSCOPE / DATA

Everything here is invented. Here is all of it.

There is no real company behind SANDSCOPE. The services, the documents, the incidents and the metrics were all authored for this project. That is stated on every other surface in one sentence — this page is the inventory behind the sentence, because a claim of “synthetic” that cannot be inspected is just a claim.

No document, service or question below was written by a language model. The estate topology is hand-authored; the telemetry and incidents are generated from a seed, so any run can be reproduced exactly rather than described.

19
Documents
87 passages
19
Services
27 dependencies
8
Fault patterns
each with a runbook
715
Labelled questions
55% answerable
5,759
Words of corpus
hand-written

The document library

This is the entire world the agent can reason from. 19 documents, 5,759 words, split into 87 passages — every citation the system emits points at one of these. It is deliberately small: a corpus you can read in an afternoon is one where you can verify the agent’s answers yourself.

KindDocumentTitleWordsPassages
Architecturearch-deployment-and-change-flowDeployment topology and change flow2755
Architecturearch-estate-overviewEstate overview and dependency topology2454
Postmortempm-2026-04-pricing-config-rolloutPricing rounding change applied to all regions at once2906
Postmortempm-2026-05-orders-db-saturationCheckout unavailable for 34 minutes — orders-db pool exhaustion3195
Postmortempm-2026-06-sessions-cache-flushLatency spike after sessions-cache key prefix change2835
Postmortempm-2026-07-fraud-scoring-restart-loopfraud-scoring restart loop masked a memory leak for nine days3215
Policypol-change-managementChange management and rollback1923
Policypol-change-risk-classificationChange risk classification3614
Policypol-data-freshnessData freshness commitments1753
Policypol-incident-severityIncident severity and paging policy2563
Runbookrb-cache-stampedeCache stampede on sessions-cache3555
Runbookrb-change-rollbackRolling back a production change2834
Runbookrb-database-connection-poolConnection pool exhaustion on orders-db3875
Runbookrb-memory-pressureHeap growth and collection pauses3704
Runbookrb-query-amplificationQuery amplification after deploy2985
Runbookrb-search-shard-imbalanceSearch shard imbalance on catalog-search3065
Runbookrb-stream-consumer-lagConsumer group lag on events-bus3365
Runbookrb-timeout-and-retrySynchronous timeout cascade3835
Runbookrb-tls-certificateTLS certificate expiry at the edge3246

What the corpus deliberately does NOT cover

The most load-bearing file in the dataset is a list of things it leaves out. Without verified gaps, “correct refusal” cannot be measured at all — every refusal would count as a mistake, and the refusal threshold could be set to zero without any test noticing.

Twelve topics are absent outright: disk exhaustion, DNS failures, data retention, on-call rotas, disaster recovery, feature flags and more. Six more are the harder case — partially covered, where retrieval happily returns adjacent material. A weak system answers those from context that is about something else.

A system that answers any row in that table has failed, and the failure is specifically the one this product exists to prevent.

The gap list also carries a correction, kept visible: one entry claimed the corpus couldn’t say who approves an emergency change. It can. The evidence gate scored it answerable, the author had marked it unanswerable, and the author was wrong. It is recorded rather than quietly deleted, because a gap list is itself a claim about the corpus.

read the full gap list →

The invented company

19 services across 4 criticality tiers, owned by 8 teams, wired together by 27 real dependencies. The topology is authored, not generated — a randomly wired graph produces plausible names and an implausible shape, and incident causality is only interesting when the topology is.

Tier 0 is on the customer’s critical path right now. Tier 3 can be down for an hour before anyone outside the owning team notices.

ServiceTierRuntimeOwning team
edge-gatewaytier 0go1.23Platform Edge
checkout-apitier 0java21Commerce
payments-gatewaytier 0java21Payments
identity-servicetier 0go1.23Identity
catalog-apitier 0node20Commerce
order-orchestratortier 1java21Commerce
inventory-servicetier 1go1.23Supply
pricing-enginetier 1rust1.82Commerce
fraud-scoringtier 1python3.12Risk
notification-servicetier 1node20Growth
search-indexertier 2python3.12Commerce
recommendation-servicetier 2python3.12Growth
config-servicetier 2go1.23Platform Edge
orders-dbtier 0postgres16Data Platform
sessions-cachetier 0redis7Data Platform
events-bustier 1kafka3.8Data Platform
catalog-searchtier 2opensearch2Data Platform
analytics-etltier 3python3.12Data Platform
reporting-batchtier 3python3.12Data Platform

The things that go wrong

8 fault patterns, each describing a real failure mode, the metrics that identify it, and the runbook that covers it. An incident is generated by choosing a pattern and a service that can actually exhibit it — the root service moves first, and services in its blast radius move later, attenuated by distance in the dependency graph. That time ordering is the diagnostic signal the agent has to reason from.

sev 1Connection pool exhaustionrb-database-connection-pool

Callers hold connections longer than the pool can recycle them. Wait time climbs first, available connections reach zero, and every upstream caller then times out together.

db.pool.wait_ms · db.pool.available · db.active_connections

sev 2Cache stampede after mass evictionrb-cache-stampede

A mass eviction empties the working set, every request misses at once, and the traffic that the cache was absorbing lands on the origin in a single wave.

cache.hit_ratio · cache.evictions_per_s · cache.memory_used_ratio

sev 2Consumer group lag growthrb-stream-consumer-lag

Consumers fall behind producers. Nothing errors, so alerting on error rate sees a healthy system while downstream data quietly goes stale.

stream.consumer.lag · stream.consumer.throughput

sev 2Heap growth with escalating pause timerb-memory-pressure

Resident memory climbs monotonically across a deploy window. Collection pauses lengthen as the heap fills, and the process is eventually restarted by the platform, which resets the graph and hides the trend.

process.memory.rss_mb · runtime.gc.pause_ms · process.restarts

sev 1Synchronous timeout cascaderb-timeout-and-retry

One slow synchronous dependency occupies caller threads until the caller itself runs out. Retries multiply the load on the already-slow dependency, so the system degrades faster the harder it tries to recover.

http.client.timeout_rate · http.client.p99_ms

sev 1TLS certificate expiryrb-tls-certificate

A certificate reaches its expiry. Failure is total and instant at the moment of expiry rather than gradual, which is what distinguishes it from a capacity problem on the same graph.

tls.handshake_failures_per_s · tls.certificate_days_remaining

sev 2Query amplification after deployrb-query-amplification

Request volume is unchanged but query volume is not. A change replaced a batched read with a per-item read, so cost scales with result size rather than with traffic.

db.queries_per_request · db.query_rate

sev 3Search shard imbalancerb-search-shard-imbalance

Documents concentrate on one shard. Mean latency stays acceptable and the tail does not, so a dashboard built on averages shows nothing wrong.

search.query.p99_ms · search.shard.max_docs_ratio

The 715 questions

Every threshold in the refusal gate is set against these. 396 have an answer in the corpus and 319 deliberately do not — and the label is true by construction rather than assigned by a person or a model. An answerable question is generated FROM the passage that answers it, so the passage is the answer. An unanswerable one is generated from a topic whose absence is verified against the corpus text at generation time.

That matters because the alternative is labelling by hand, which produces a set that measures the labeller’s judgement. It has already gone wrong once here — see the correction in the gap list above.

214unanswerableproperty documented for another entity

The sharpest trick in the set. Takes a property the corpus documents for ONE service and asks it of a different service. Retrieval happily returns the passage about the wrong service, so a weak system answers confidently with a real number that is about something else.

what is the connection pool ceiling for events-bus

152answerablesymptom from fault signal

Takes a real metric from a fault pattern and asks about it the way an on-call engineer would. Answerable because the runbook for that fault is in the corpus.

cache.evictions_per_s is climbing on sessions-cache, what is happening

127answerablequestion from any section heading

Turns a heading in a document into the question that heading answers. Answerable by construction — the section IS the answer.

what are the environments

93answerablesection from runbook heading

The same idea narrowed to runbooks, where headings are procedural steps.

what was the impact of pricing rounding change applied to all regions at once

86unanswerableentity cannot exhibit this fault

Asks about a fault a given service physically cannot have — a memory-leak metric on a gateway that does not run that way. Plausible-sounding, ungrounded.

what is the expected process.memory.rss_mb baseline on edge-gateway

24answerablepolicy value lookup

Asks for a specific number a policy states — a severity level, an escalation timer. The hardest answerable kind, because a near-miss reads as correct.

what severity is a tier 0 service being unavailable

19unanswerabletopic absent from corpus

Topics deliberately left out of the corpus entirely, listed in GAPS.md. Absence is VERIFIED against the text, not assumed.

the disk is full on the host, what should I do