v1.7.1 — Closed-Loop Hardening: warm-up, PDB, env gates, dynamic Behavior Protocol
Note
Historical audit snapshot. This release belongs to the v1.0–v1.12 line that
shipped during the post-audit remediation sprint (2026-04-15 → 2026-04-29).
Per docs/RELEASING.md
these tags are immutable historical snapshots; the active public release line
is now v0.x
hardening, with v1.0.0 reserved for the first verified GKE+EKS cloud E2E rollout.
See CHANGELOG.md for the reclassification rationale.
Release date: 2026-04-24
This is a hardening release for v1.7.0 (closed-loop monitoring).
Seven focused commits close operational gaps that prevented the closed
loop from being production-grade:
- Model warm-up + readiness gating (D-23, D-24)
- PodDisruptionBudget + Rego v1 policies (D-27)
- Champion/Challenger in Argo Rollouts (G-02b)
- Rollback skill + /rollback workflow (G-05)
- Environment promotion gates dev→staging→prod (D-26, ADR-011)
- Dynamic Behavior Protocol via mcp-prometheus (ADR-010)
- Documentation consolidation (this file + CHANGELOG)
No breaking data changes. No migration required for existing services
EXCEPT environment-promotion adoption (documented below).
Highlights
Model warm-up + probe split (D-23, D-24)
Problem: the first inference after pod start took 300–800 ms while
scikit-learn/XGBoost lazily initialized the SHAP explainer. Under a
rolling deploy, pods became Ready on /health while they were still
cold — and the HPA happily sent production traffic their way.
Fix:
app/fastapi_app.py::warm_up_model()forces a dummypredict_proba
pass AND builds the SHAPKernelExplaineronce during FastAPI
lifespanbefore_warmed_up=True/readyreturns 503 until warm-up completes (separate from/health)- K8s manifests split:
livenessProbe→/health,readinessProbe→
/ready, newstartupProbe→/healthwithfailureThreshold: 24 - The Argo Rollout canary now waits on
/readybefore routing traffic
PodDisruptionBudget (D-27)
Problem: a single kubectl drain on a node with all replicas evicted
the entire service.
Fix:
templates/k8s/base/pdb.yaml—minAvailable: 1templates/k8s/base/hpa.yaml—minReplicas: 2(PDB with minAvailable=1
cannot tolerate voluntary disruption on 1-replica services)templates/tests/infra/policies/closed_loop.rego— enforces presence- valid selector + explicit annotation escape hatch for
minAvailable: 0
- valid selector + explicit annotation escape hatch for
Argo Rollouts C/C (G-02b)
Problem: the Champion/Challenger statistical gate (McNemar + bootstrap
ΔAUC, shipped in v1.7.0) ran ONLY offline in retrain-service.yml. The
K8s canary only checked HTTP error rate and latency.
Fix:
templates/k8s/base/analysistemplate-champion-challenger.yaml
ships TWO AnalysisTemplates:{service}-cc-online— 4 proxy metrics during canary: prediction
log error rate, error-rate vs stable, score-distribution shift,
p95 latency. Auto-rollback on failure.{service}-cc-post-deploy— 3 real business metrics from
performance_monitor CronJob. Manual trigger or scheduled. Does
NOT auto-rollback (post-deploy rollback is STOP-class).
Three-layer C/C architecture is now complete:
OFFLINE → champion_challenger.py + retrain-service.yml
ONLINE → {service}-cc-online during canary
POST-DEPLOY → {service}-cc-post-deploy after labels arrive
Rollback skill + /rollback workflow (G-05)
The most critical on-call skill had no dedicated flow. release-checklist
mentioned "rollback plan" but no runbook existed.
New:
.windsurf/skills/rollback/SKILL.md— 7-step STOP-class procedure:
triage → identify revision →argo rollouts abort/undo→ MLflow
registry revert → silence alerts → verify → audit issue.windsurf/workflows/rollback.md— /rollback slash command with
15-min triage budget, 5-business-day RCA follow-up
Environment promotion gates (D-26, ADR-011)
Problem: deploy-gcp.yml and deploy-aws.yml were tag-triggered into
a single flat production-{cloud} environment. No staging validation;
no required-reviewer gates.
Fix:
templates/cicd/deploy-common.yml— reusableworkflow_callcentralizing
build/auth/apply/smoke-test logictemplates/cicd/deploy-{gcp,aws}.ymlrewritten as 4-job chain:
build → deploy-dev → deploy-staging → deploy-prod- 6 GitHub Environments to configure (gcp/aws × dev/staging/prod) with
explicit reviewer and wait_timer rules docs/environment-promotion.md— operator setup guide with migration
steps for pre-v1.7.1 services
Dynamic Behavior Protocol via mcp-prometheus (ADR-010)
Problem: AGENTS.md's AUTO/CONSULT/STOP mapping was static. A deploy to
staging that is CONSULT at 10am Tuesday should NOT be CONSULT when a P1
incident is active, drift is severe, the error budget is exhausted, it
is 17:45 Friday, or a rollback happened < 6h ago.
Fix:
templates/common_utils/risk_context.py— 200-line helper with a
frozenRiskContextdataclass,escalate(base_mode)applying the
ADR-010 table (AUTO→CONSULT→STOP, sticky STOP), 60s cache,
fallback to ops/*.json local files when mcp-prometheus is unavailablemcp-prometheuspromoted to CORE MCP in AGENTS.md (same tier as
github/kubectl/terraform).windsurf/rules/01-mlops-conventions.md— Dynamic Behavior Protocol
section with the table and five signalsdocs/decisions/ADR-010-dynamic-behavior-protocol.md— the trade-off
analysis, including why we rejected a file-only stub
New ADRs
- ADR-010 — Dynamic Behavior Protocol via mcp-prometheus
- ADR-011 — Environment Promotion Gates (dev→staging→prod)
New anti-patterns (D-23..D-27)
| ID | Description |
|---|---|
| D-23 | Liveness and readiness probes share a path |
| D-24 | SHAP explainer rebuilt per request |
| D-25 | Pod killed mid-request on deploy / scale-down |
| D-26 | Deploys go directly to prod without staging validation |
| D-27 | Deployment without PodDisruptionBudget |
Full corrective actions in AGENTS.md anti-pattern table.
New files
templates/common_utils/risk_context.py+ unit teststemplates/k8s/base/pdb.yamltemplates/k8s/base/analysistemplate-champion-challenger.yamltemplates/cicd/deploy-common.ymltemplates/tests/infra/policies/closed_loop.rego.windsurf/skills/rollback/SKILL.md.windsurf/workflows/rollback.mddocs/environment-promotion.mddocs/decisions/ADR-010-dynamic-behavior-protocol.mddocs/decisions/ADR-011-environment-promotion-gates.mdreleases/v1.7.1.md(this file)
Changed files
templates/service/app/fastapi_app.py—warm_up_model()functiontemplates/service/app/main.py—/readyendpoint, lifespan warm-uptemplates/k8s/base/deployment.yaml+argo-rollout.yaml— probe
split,terminationGracePeriodSeconds, startupProbetemplates/k8s/base/hpa.yaml—minReplicas: 2templates/k8s/base/kustomization.yaml— 2 new resources registeredtemplates/cicd/deploy-gcp.yml+deploy-aws.yml— 4-job chaintemplates/tests/infra/policies/kubernetes.rego— converted to Rego v1AGENTS.md— D-23..D-27 added, mcp-prometheus core MCP, rollback skill.windsurf/rules/01-mlops-conventions.md— 6 invariants, dynamic table.windsurf/rules/02-kubernetes.md— graceful shutdown, PDB sections.windsurf/rules/05-github-actions.md— D-26 enforcement, reusable workflowsCHANGELOG.md— this release
Test counts
- Unit tests: 75 passing (up from 56 in v1.7.0)
test_risk_context.py: 19 new tests
- Rego policies: now parse cleanly on conftest v0.46+
Migration guide (v1.7.0 → v1.7.1)
1. Enable warm-up (service-level)
Update app/fastapi_app.py and app/main.py to the new lifespan
pattern. See diff in commit A1.
2. Add PodDisruptionBudget
Copy templates/k8s/base/pdb.yaml into your service's k8s/base. Add
to kustomization.yaml. Bump HPA minReplicas: 2.
3. Adopt environment promotion
- Create 6 Environments in repo Settings (
gcp-dev,gcp-staging,
gcp-production,aws-dev,aws-staging,aws-production) - Set
required_reviewers,wait_timer,deployment_branchesper
the table indocs/environment-promotion.md - Replace
deploy-{gcp,aws}.ymlwith the new 4-job chain - Add
k8s/overlays/{cloud}-{env}/kustomizations - Remove the old flat
production-{cloud}environments AFTER first
successful pipeline
4. Install mcp-prometheus (optional)
Not required for the template to work, but unlocks the Dynamic Behavior
Protocol. Add the mcp-prometheus block shown in AGENTS.md §MCP
Integrations to your ~/.codeium/windsurf/mcp_config.json.
Related documentation
- AGENTS.md — full invariant + mode protocol reference
docs/environment-promotion.md— operator setup for env gatesdocs/decisions/ADR-010— dynamic Behavior Protocoldocs/decisions/ADR-011— environment promotion gates.windsurf/skills/rollback/SKILL.md— emergency revert runbook