The Four-Gate Delivery Validation Pipeline
Every failure class this track documented — the bot that never traded, the broken deploy config, the silent write failure, the gradual drift — has a corresponding gate. This capstone shows how all four compose into a single, non-bypassable delivery validation pipeline.
Every lesson in this track documented a real failure. A bot with 340 tests that never placed a trade. A service with green dashboards whose every write was silently discarded. A broken deploy that reached users because there was no smoke gate. And — from the companion quantitative-scoring track — a calibrator with dead components that no unit test caught.
Each failure had a specific gap: a validation axis that was absent. Each gap has a corresponding gate. This lesson shows how the four gates compose into a single pipeline.
The Four Axes
The track established that code integrity and operational validity are orthogonal. The four-gate pipeline makes this concrete by separating validation into four distinct axes, each measured at a different moment:
| Gate | Axis | Moment | Catches |
|---|---|---|---|
| A | Code correctness | Pre-merge | Logic bugs, type errors, coverage gaps |
| B | Deployed surface | Post-deploy | Broken config, missing env vars, dead endpoints |
| C | Write path | Post-cutover | Silent write failures, broken DB connections |
| D | Output liveness | Continuous | Long-term silence, gradual drift |
No single gate covers all four axes. A system that only runs Gate A has the Agent Framework failure class. A system with Gates A and B but not C has the silent-write-failure class. A system with A, B, and C but not D has the gradual-drift class. Closing all four is the definition of operationally valid.
Composing the Pipeline
The four gates are independent tools. Composing them into a pipeline means deciding three things: ordering, gating behavior, and failure reporting.
Ordering is natural: A runs before a PR merges (pre-merge CI), B runs immediately after each deploy, C runs as a post-deploy integration check, and D runs continuously as a cron. The pipeline script handles B, C, and D in sequence; A is handled by the merge gate CI workflow.
Gating behavior means deciding what a failure in one gate means for the subsequent gates. The natural rule: Gate B failure blocks Gate C. If the service isn't responding to HTTP, a write probe would fail for the same reason and provide no additional information. Gate A failure does not block B, C, or D in the deploy script — they measure different axes.
Failure reporting means making each gate's failure loud and unambiguous. The validate.sh from the BuildChallenge runs each gate in a subshell and fails fast by design — (gate_fn) || { echo "GATE … FAILED"; exit 1; } — so the first failing gate aborts the deploy with a labeled message rather than letting a later step run against a broken surface. This is the gating contract in code: Gate B failing stops Gate C, because a write probe against an unreachable service would only fail for the same reason.
#!/usr/bin/env bash
set -euo pipefail
# Deploy the new version
deploy_to_staging
# Gate B: Smoke (blocks Gate C on failure)
(gate_b_smoke) || { echo "GATE B FAILED — skipping write probe"; exit 1; }
# Gate C: Write probe
(gate_c_write_probe) || { echo "GATE C FAILED — write path broken"; exit 1; }
echo "Deploy gates passed. Promoting to production."
promote_to_production
# Gate D: Liveness (cron — not in this script, runs separately)
The Failure Classes This Closes
The matrix makes the closure explicit. The Agent Framework failure (the “The 340-Test Bot That Never Traded” lesson) was missing Gate D — the liveness monitor that would have paged when the silence reached 48 hours. The silent write failure class (the previous lesson) is caught by Gate C. The broken deploy class (the “Post-Deploy Smoke Tests” lesson) is caught by Gate B. Each gate was designed to address a real incident.
Gate D: The Continuous Gate
Gates A, B, and C are event-driven — they fire at specific moments in the deployment lifecycle. Gate D is different. It runs as a scheduled check, fires an alert when the staleness threshold is crossed, and resets when the next real output arrives.
# liveness_check.py — called by Gate D cron
import sys
import argparse
from staleness import alert_if_stale # built in the lesson 286 BuildChallenge
parser = argparse.ArgumentParser()
parser.add_argument("db_path")
parser.add_argument("--threshold-hours", type=float, required=True)
args = parser.parse_args()
result = alert_if_stale(args.db_path, threshold_hours=args.threshold_hours)
print(result["message"])
sys.exit(1 if result["stale"] else 0)
The critical distinction is that Gate D catches the failure class that all three acute gates miss: a service that deploys cleanly (B passes), has a working write path (C passes), and has good test coverage (A passes) — but stops producing output two days after the deploy because a downstream data source went stale and no one noticed. Gate D catches this because it measures outcome, not process.
Making the Pipeline Non-Bypassable
A pipeline that can be skipped is not a gate. Three practices make it non-bypassable:
1. Wire it into the deploy script, not just the documentation. set -euo pipefail in the deploy script means a non-zero exit from any gate aborts the deploy. It is not a suggestion.
2. Treat red gates as P0s. A failing smoke is not "we'll fix it in the next sprint." The rollout is blocked. The deploy is reverted. The failure is diagnosed. This is the cultural discipline, not the technical one.
3. Make the liveness alert page someone. An alert that goes to a Slack channel where it is routinely ignored is not Gate D — it is theater. Route the staleness alert to a real on-call rotation. The Agent Framework bot was silent for weeks. No one knew because no one was paged.
The Track Closes Here
This lesson closes the delivery-validation track. The arc:
- The “The 340-Test Bot That Never Traded” lesson: The failure case — a well-tested system that never produced output.
- The “Last Real Trade as a Metric” lesson: The liveness metric — hours since last real output as a first-class observable.
- The “Operational Validation Checklist” lesson: The operational validation checklist — what "done" actually requires.
- The “Post-Deploy Smoke Tests” lesson: The smoke suite — a 30-second gate on the real deployed surface.
- The previous lesson: The write-path probe — the one check that cannot be faked by a healthy read path.
- The “The Four-Gate Delivery Validation Pipeline” lesson: This lesson — composing the four gates the previous lessons built into a single non-bypassable pipeline.
The cultural correction is simple to state and hard to maintain: shipping is not done until the running system produces its intended outcome. The four-gate pipeline makes that statement operational.