01A score is bound to its frame
The tuple (dataset × scorer × judge × harness) version is part of a score's identity. Cross-frame comparison is a rejected operation, not a discouraged one.
ADR-0121 views, in reading order. Every view ships three ways: an HTML page, an SVG that re-opens in diagrams.net fully editable, and draw.io source.
The system that decides whether the next version of a consumer AI assistant reaches its 40 million users. Read it in seven acts: what sits inside the boundary, who it serves and what they get to do, how it is put together, what it stores, what happens when a candidate is evaluated, how it is operated, and why it is safe. One rule runs through every view — a score is permanently bound to the frame that produced it, and two scores from different frames are never compared.
A score is a fact about a comparison frame, not about a model. Two scores from different frames are never compared — the incumbent is re-scored instead.
Every week, a team ships a new version of an AI assistant to 40 million people. A new base model, a rewritten system prompt, a changed tool definition, a different retrieval configuration — each one a bet that the assistant got better, and each one capable of making it quietly worse for a cohort nobody checked. The question the organisation needs answered is narrow and hard: is this candidate better than what users have today, and where is it worse? Answering it requires measuring open-ended quality at a volume no human team can reach, which forces a model into the role of judge; and it requires those measurements to stay comparable for years, across corrections to the corpus, clarifications to the rubric, and upgrades to the judge itself. The second requirement is the one that is usually lost. A platform that loses it does not fail loudly — it keeps producing confident numbers that mean nothing, indefinitely, without ever erroring.
A candidate is a fully pinned configuration, identified by its digest. A run is planned against a comparison frame — dataset version, scorer version, judge version, harness version — resolved before any inference is bought. A harness fans out across GKE, generating outputs with tools executed in a kernel-isolated sandbox that has no route to production, and stores a full trace for every generation. A separate scoring stage reads those traces: deterministic checks, a pinned and calibrated model judge evaluating both orderings of every pair, and a sampled human audit. Scores are appended to BigQuery as immutable facts, each stamped with its frame. The gate engine compares candidate against incumbent within a single frame, per declared slice, with an interval on every delta, and returns PASS, BLOCK or INSUFFICIENT_EVIDENCE to a deployment pipeline that will not release without an affirmative pass. Exposure is staged — shadow, canary, progressive rollout — with online guardrails armed to roll back automatically, and production failures flow back into targeted regression sets so that every incident becomes a permanent test.
The tuple (dataset × scorer × judge × harness) version is part of a score's identity. Cross-frame comparison is a rejected operation, not a discouraged one.
ADR-01The incumbent is re-scored in the new frame; its old number is never reinterpreted. Gating is suspended until that completes, and the cost is a budgeted line.
ADR-02A dataset correction publishes a new version; a score correction supersedes rather than updates. This is what makes a three-year-old number interpretable.
ADR-03Model, prompt, tools, retrieval index, decoding and safety filter together. Scoring the model alone confounds a prompt edit with a model upgrade.
ADR-05Traces are stored, so a rubric clarification costs a scoring pass rather than a full generation sweep — and a blocked engineer can read what actually happened.
ADR-06Pinned version, continuous drift detection against a fixed calibration set, and a published agreement threshold below which it may observe but not block.
ADR-08INSUFFICIENT_EVIDENCE is a distinct verdict. An incomplete run, an unavailable judge or an unevaluated gated slice stops the release.
ADR-11Safety, latency and cost block regardless of quality gain, and safety guardrails have no waiver path in code.
ADR-13A pipeline that cannot reach the gate does not release. The property lives where an outage of the platform cannot reach it.
ADR-14It executes text a model wrote, against tools, at volume. Kernel isolation, denied egress and a hard in-harness cost ceiling follow from that classification.
ADR-18An evaluation platform outlives the models it was built to judge, because its output is the historical record an organisation uses to know whether it is getting better. These are the properties that should survive a change of model, of cloud, and of the people who built it.
ADR-01 depends on nothing about BigQuery, Google Cloud, or any judge. It is a statement about what a measurement means, and it survives replacing every component underneath it. It is also the property a future team would most easily discard without noticing, which is why it is enforced by a rejected query rather than a convention.
The main cost of the design is re-scoring the incumbent on every frame change. Inference costs fall and caching improves; the discipline therefore becomes easier to sustain over time rather than harder, which is the right direction for a rule that must not be broken.
Admissibility lives on the scorer row, not in a policy document. A future team swapping in a judge nobody has calibrated finds it cannot block, without anyone having to remember why.
Suites, slices and thresholds will all churn. The distinction between 'worse' and 'unknown' will not, and any future gate built on this platform inherits it for free.
As agents gain more tools and more autonomy, treating model output as untrusted input moves from prudent to obvious. This decision will read as unremarkable long before it stops mattering.
The erasure-versus-immutability gap in ADR-17 is written down rather than hidden. A future team facing tighter obligations can make a different trade knowingly, which is not possible when a compromise was made silently.
Every number here is a stated assumption from the requirement, chosen to be argued with rather than believed. The right-hand column names the view where the mechanism that meets it is drawn.
| Quality | Target | How it is met | View |
|---|---|---|---|
| Gate decision availability | ≥ 99.9% monthly, in release windows | Control plane across two zones; the verdict API is the only synchronous obligation, and fail-closed lives in the pipeline's contract rather than here. | 16 |
| Smoke tier latency | ≤ 8 min p95, 400 examples | A small subset of the gating suite on the same execution pool at interactive priority — the only tier a human waits on. | 04 |
| Gate suite latency | ≤ 90 min p95, ≤ 150 min p99 | 6,500 examples × 3 generations fanned across 0-600 harness pods, each example independently retryable. | 12 |
| Full regression sweep | ≤ 6 h p95, 42,000 examples | Same pool at lower priority, on Spot capacity with checkpointed resume. | 16 |
| Re-baseline window | ≤ 12 h across all gating suites | Queued ahead of candidate runs on a frame change, so a rubric edit lands inside one working day. | 15 |
| Throughput | 1,200 generations/min steady, 4× burst for 30 min | Pub/Sub work items against an autoscaling node pool, rate-limited against shared serving quota. | 13 |
| Slice query latency | ≤ 3 s p95 over 12 months of scores | BigQuery partitioned by run and clustered by slice; ~55 M rows/year. | 18 |
| Judge agreement | ≥ 0.75 κ to gate; < 0.65 κ inadmissible | Calibration against ≥ 1,200 human labels per rubric, stored on the scorer row and read by the gate engine. | 14 |
| Detection power | 2 pp regression at ≥ 90% power, α = 0.05 | The requirement that sets the 6,500-example suite size, evaluated as a paired comparison against the incumbent. | 12 |
| False-block rate | ≤ 5% of candidates | 34 declared gate-bearing slices rather than every measurable cohort, with human adjudication on every block. | 14 |
| Reproducibility | ± 0.5 pp on ≥ 99% of re-runs | Stored (candidate, frame) re-runs against immutable artefacts; bounded by the tombstone case in ADR-17. | 11 |
| Rollback latency | ≤ 5 min p99 from guardrail breach | Continuous guardrail evaluation against serving telemetry, emitting a rollback trigger without waiting for analysis. | 19 |
| Cost per gate run | ≤ $340 fully loaded; judge ≤ 55% | In-harness ceiling that halts the run, plus per-team monthly budgets enforced at admission. | 18 |
| Evaluation spend | ≤ 2.5% of production inference spend | Suite cost reported against measured offline-online correlation, so an unproductive suite is a visible retirement candidate. | 18 |
| Verdict retention | 7 years, immutable | Append-only verdict records in BigQuery with no update or delete path; traces for blocking runs held 3 years. | 10 |
| Recovery | Scores RPO 0 / RTO ≤ 4 h; run state RPO ≤ 5 min | Managed multi-region stores; in-flight runs resume from checkpoint rather than restarting. | 16 |
Four of this architecture's claims are cheap to test and expensive to be wrong about. A prototype that proves these can be built on; one that skips them is a demonstration of running a benchmark, which is the easy half.
| Risk | If it lands | Response |
|---|---|---|
| Re-baselining proves unaffordable | If a frame change costs more than modelled, teams will avoid changing rubrics and datasets — and a corpus nobody improves is the slow version of the problem the frame rule exists to solve. | Measure re-baseline cost in the prototype. The mitigation is score caching for scorer-only changes (ADR-16), which requires the temperature-zero question to be settled. |
| Gating at temperature zero mis-measures production | The cache, and much of the cost model, assumes gating suites can run deterministically. If deterministic runs do not represent live behaviour, the largest cost lever disappears. | Compare deterministic and stochastic runs of the same candidate across all gate-bearing slices before committing to the cache. |
| Judge agreement is lower than assumed | If no available judge reaches 0.75 κ on the rubrics that matter, the gate has no automated blocking authority and human capacity becomes the binding constraint immediately. | Measure κ first, on the real rubrics. The fallback is narrower rubrics with higher agreement, plus deterministic scorers carrying more of the gating load. |
| False blocks erode trust in the gate | A gate people route around is worse than no gate, because it carries authority it no longer earns. The 34-slice set and the 5% target are modelled, not measured. | Track false-block rate from the first week and treat a breach as a policy defect. Reducing the gate-bearing slice set is the available lever. |
| The erasure gap widens | ADR-17 accepts that a tombstoned example makes a verdict not fully reproducible. Tightening obligations could make tombstoning insufficient and force retroactive corpus changes. | Track what fraction of gating examples are production-derived. If it is small, migrating gating suites to synthesised or licensed material removes the conflict rather than managing it. |
Eighteen decisions make up this architecture. Everything else across the twenty-one views is convention, sizing or consequence. Each record states the forcing question, the context that makes it hard, what was decided, how it is realised on Google Cloud, the options weighed, what the choice buys and costs, the conditions that would flip it, why it should still be right in ten years, and the lesson that transfers beyond this platform.
Status of this document. This is a design, not a report on a running system. The rates, latencies, volumes, retentions and thresholds are the requirement's stated assumptions for a consumer AI assistant — 40 million monthly active users, 25 release candidates per week, 18 suites over 42,000 examples — invented to be defensible and arguable rather than absent. They are to be replaced by measured telemetry before build, and four of them in particular are the first numbers real data should overturn: the 0.75 κ judge-admissibility threshold, the 2 percentage-point detectable regression that sets the 6,500-example suite size, the 5% false-block rate, and the assumption that judge inference is no more than 55% of run cost.
What a score is a fact about, and why two numbers may not be placed side by side.
ADR-01A score is bound to a comparison frame, and cross-frame comparison is a rejected operation ADR-02A frame change re-scores the incumbent rather than reinterpreting its stored number ADR-03Datasets are immutable, versioned artefacts; a correction publishes a new version ADR-04Scores are append-only facts; a correction supersedes rather than updatesThe subject of an evaluation, and the corpus it is evaluated against.
ADR-05The evaluation subject is the full pinned configuration, not the model ADR-06Generation and scoring are separate stages joined by a stored trace ADR-07Three dataset classes: a frozen golden set, a rolling set, and targeted regression setsUsing a model to score a model, without pretending the ruler is fixed.
ADR-08The judge is pinned to an explicit version and monitored for silent drift ADR-09A judge may block a release only above a published agreement threshold ADR-10Known judge pathologies are countered structurally, not by prompt wordingHow evidence becomes a verdict, and what happens when there is not enough of it.
ADR-11The verdict is three-valued: PASS, BLOCK and INSUFFICIENT_EVIDENCE ADR-12Gates are evaluated per slice against a declared gate-bearing set ADR-13Guardrail gates block regardless of quality gain, and safety guardrails are never waivable ADR-14Fail closed is a property of the pipeline's contract, not of the platform's availabilityThe proxy, the truth, and how each earns its authority.
ADR-15Offline gates entry to exposure; online guardrails gate rollout and trigger rollback ADR-16Suites justify themselves by predicting online outcomes, and cached scores must not assert false determinismUser data under an immutable corpus, and running generated code at volume without an unbounded bill.
ADR-17Production examples are redacted at admission, and erasure is a tombstone with bounded reproducibility ADR-18The harness is an untrusted workload, and every run carries a hard cost ceilingEvery capability and what it is realised with, the origin of that choice, the alternative that was weighed, and the record that argues it. The requirement stays vendor-neutral throughout; this table is where the architecture commits to Google Cloud.
| Capability | Choice | Origin | Credible alternative | Why this one | Record |
|---|---|---|---|---|---|
| Score store | BigQuery, EU multi-region, partitioned by run and clustered by slice | Google Cloud | ClickHouse on GKE with object storage | The dominant query is a per-slice comparison across tens of millions of frame-bound rows with a 3-second p95 target; a columnar warehouse with no cluster to operate wins on both the query shape and the operational burden. | ADR-01 |
| Dataset, trace and artefact store | Cloud Storage, dual-region, object versioning on, in a separate project | Google Cloud | A content-addressed store built on a filesystem | Immutability and retention are enforced by the platform rather than by application code, and project separation puts the corpus outside every execution-plane identity's reach. | ADR-03 |
| Run, candidate and frame state | Cloud SQL for PostgreSQL, HA, point-in-time recovery | Google Cloud | Spanner | Single-region transactional state at modest volume with an RPO of 5 minutes; Spanner's global consistency buys nothing here and costs materially more. | ADR-02 |
| Execution fan-out | GKE node pool on Spot capacity with an on-demand floor | Google Cloud | Cloud Run jobs, or Batch | 0-600 pods with checkpointed resume makes re-baselining a natural fit for interruptible capacity, while the on-demand floor protects gate runs inside a release window. | ADR-06 |
| Work distribution and events | Pub/Sub, six topics | Google Cloud | Cloud Tasks, or a queue on Redis | Independently retryable per-example work items with at-least-once delivery, and the same spine carries verdict and drift events to consumers. | ADR-06 |
| Candidate inference | Vertex AI endpoints, pinned model versions | Google Cloud | Direct provider APIs for everything | The primary in-house model is served here already; pinning is first-class and quota is manageable against production serving. | ADR-05 |
| Judge inference | External provider API, pinned version, behind an egress allowlist | Third party | A self-hosted open-weight judge | Judge quality currently justifies the dependency; ADR-08 exists precisely because that dependency cannot be trusted to stay fixed, and ADR-18 keeps the egress path narrow. | ADR-08 |
| Tool sandbox | gVisor-isolated pods, egress denied, side-effect-free tool stubs | Open source on Google Cloud | Plain containers with network policy | The workload executes model-generated tool calls at volume; kernel-level isolation is proportionate to running untrusted generated code. | ADR-18 |
| Score cache | Memorystore, keyed by candidate, example and frame | Google Cloud | No cache | The single largest cost lever, admitted only for deterministic candidates — a cached score for a stochastic candidate asserts a determinism it does not have. | ADR-16 |
| Redaction at admission | Sensitive Data Protection, versioned inspection templates | Google Cloud | A bespoke redaction service | Production-derived examples must be de-identified before anything is durable, and the redaction version is recorded so the treatment applied to an example is itself auditable. | ADR-17 |
| Data perimeter | VPC Service Controls around the corpus, label and trace projects | Google Cloud | IAM alone | IAM governs who may call; a service perimeter governs where data may go, which is the control that survives a leaked service-account key. | ADR-18 |
| Workload identity | Workload Identity Federation, short-lived tokens only | Google Cloud | Service account keys | There is no long-lived credential anywhere in the policy path, so a gate change cannot be made by anything holding an old secret. | ADR-14 |
| Policy source of truth | Git repository with enforced two-person review | Open source | A policy table in Cloud SQL | A gate is a production control; it must be reviewable, diffable and impossible to edit in place, which a database row is not. | ADR-14 |
| Platform CI/CD | Cloud Build to Artifact Registry with signed images | Google Cloud | GitHub Actions with Workload Identity Federation | Keeps the build identity inside the same trust domain as the perimeter, and the synthetic regressed candidate runs as a release gate on the platform itself. | ADR-13 |
| Observability | OpenTelemetry into Cloud Monitoring, quality signals into BigQuery | Open source on Google Cloud | A self-hosted Prometheus and Grafana stack | Operational signals and measurement-quality signals have different shapes: one is time series, the other is a statistic over scores, and each goes where it belongs. | ADR-08 |
Is a score a property of a candidate, or a property of a candidate measured a particular way?
When the dataset, rubric, judge or harness changes, what happens to the baseline the next candidate will be compared against?
When an example is found to be wrong — a bad reference answer, a mislabelled slice — is it fixed in place or superseded?
When a score turns out to be wrong, is the row updated or is a new row written?
What exactly is being scored when the platform says a candidate improved?
Does a scorer run inline with the model call, or against stored outputs?
Should the gating corpus be a stable benchmark or a live sample of what users are actually asking?
Which model scores the outputs, and what happens when the provider changes it underneath the pin?
How good does a model judge have to be before it is allowed to stop a release?
How are position bias, verbosity bias and self-preference handled?
What does the platform return when a run did not finish, or finished with too many harness errors to trust?
How does the platform gate on cohorts without blocking most neutral releases by chance?
Can a large enough improvement in helpfulness justify a small regression in safety, latency or cost?
What happens to releases when the evaluation platform is unavailable during a release window?
Does online evidence stop a release, or only observe one?
How does the platform know a suite is worth running, and when may a score be reused rather than recomputed?
How can dataset versions be immutable while a user retains the right to have their data erased?
How should a system that executes model-generated tool calls thousands of times an hour be contained, and what stops a misconfigured run spending without limit?
The terms this package uses in a specific way, and what each one is doing in the architecture.
| Package | What it is | What it does here | Considered instead |
|---|---|---|---|
| Comparison frame | The tuple (dataset version × scorer version × judge version × harness version) under which a score was produced. | Part of a score's identity. Two scores from different frames may not be compared, which is the architecture's defining rule. | Treating these as metadata, which makes the rule advisory and therefore absent. |
| Release candidate | A fully pinned configuration: model, prompt, tools, retrieval index, decoding parameters, safety filter. | The subject of every score, so that a quality change is attributable to a specific change. | Attributing scores to a model version, which confounds a prompt edit with a model upgrade. |
| Incumbent | The candidate currently serving production traffic. | The baseline every gate compares against, maintained by the deployment pipeline and re-scored on every frame change. | An absolute threshold, which answers 'is this good enough' rather than 'is this better'. |
| Re-baseline | Re-scoring the incumbent in a newly registered frame. | The budgeted, recurring cost of changing any measurement axis. Gating is suspended until it completes. | Carrying the old score forward, which is the forbidden cross-frame comparison by another route. |
| Gate-bearing slice | A declared subset of the corpus — language, task type, cohort, safety category — on which a regression blocks. | Declared in advance so the multiple-comparisons cost is bounded and known rather than discovered. | Gating every slice, which produces a false block on most neutral releases. |
| Guardrail gate | A gate that blocks regardless of any quality improvement: safety violation rate, benign refusal rate, latency, cost, tool-call errors. | Prevents a candidate that is wittier and less safe from being scored as better. Safety guardrails have no waiver path. | Folding safety into the aggregate quality score, where a large enough gain can outvote it. |
| INSUFFICIENT_EVIDENCE | A verdict distinct from BLOCK, returned when a run did not complete, a judge was unavailable, or the harness error rate exceeded budget. | Keeps absence of evidence from being read as a pass. The pipeline treats it as a stop. | A two-valued verdict, under which an incomplete run either blocks wrongly or passes dangerously. |
| Harness error | A failure of the evaluation machinery — sandbox timeout, provider 5xx, expired credential — as opposed to a wrong answer from the model. | Classified separately and excluded from scoring, because scoring infrastructure failures as model failures corrupts every number in the run. | Counting any non-success as a model failure, which makes a flaky dependency look like a regression. |
| Contamination canary | A subset of examples never published in any form. | A published-versus-canary score gap reveals that a candidate has seen the golden set, which otherwise looks like a large genuine improvement. | Trusting that a training corpus excluded the benchmark, which is unverifiable from outside. |
| Judge admissibility | Whether a judge's measured agreement with human labels is high enough for it to block a release. | Stored on the scorer row and read by the gate, so authority is data rather than convention. | Using a judge because it is available, which grants unearned authority to an uncalibrated instrument. |
| Confound register | A record of changes — UI, traffic mix, infrastructure — that overlapped a candidate's exposure window. | Lets the platform refuse to attribute an online movement to a candidate, rather than guessing under pressure. | Attributing every online change to the most recent model release, which is how the wrong thing gets rolled back. |
| Tombstone | Removal of an example's content while retaining its identity, slice labels and derived scores. | The erasure path under an immutable corpus. It preserves aggregate comparability and bounds full reproducibility. | Deleting the example, which silently changes every score computed from it. |
svg/<view>.svg or drawio/<view>.drawio in draw.io Desktop or at app.diagrams.net to edit. The SVG carries the diagram inside it, so it is both the picture and the source. This folder is self-contained — copy it whole and every link still resolves.