Lesson 99: Annual Escalation Policy Version Bump and Migration Runbook - Evolving lesson78_* Schemas Without Orphan Hashes
Direct answer: An annual escalation policy version bump is a semver-tagged change set ([email protected]) plus a migration runbook that freezes in-flight Lesson 92–98 trains, backfills new columns, recomputes dependent hashes (dry_run_evidence_hash, kill_switch_evidence_hash, attestation_evidence_hash, Lesson 98 digest_evidence_hash), and records schema_migration_id on every touched row so auditors see lineage, not magic.

What this lesson solves
Schema drift is how governance dies quietly. This runbook makes column adds as serious as database migrations: freeze, transform, verify, sign.
Prerequisites: Write access to CSV stores, a staging copy of Lesson 97 zips, and a change advisory slot. Expected time: about one hundred minutes including a tabletop on a breaking column rename.
What you will build
lesson78_annual_escalation_policy_version_bump_policy.md(contract below)lesson78_schema_migration_runbook.csv(one row per migration attempt, including rollbacks)- A
policy semvertag in everylesson78_*filename or frontmatter block your tooling reads
Step 1 - Define migration gate classes
| gate | fail signal | posture |
|---|---|---|
| M1 – Active send window | external send scheduled during transform | block migration or route sends through legacy reader |
| M2 – Partial backfill | nullable new columns without default policy | stop; define default_for_legacy_rows |
| M3 – Hash break | recomputed hash differs but schema_migration_id missing |
fail audit |
| M4 – Digest desync | Lesson 98 slide still cites old manifest_sha256 |
re-issue digest row |
Step 2 - Author lesson78_annual_escalation_policy_version_bump_policy.md
Minimum sections:
- Purpose – evolve
lesson78_*contracts once per year unless emergency patch; emergency usesPATCHwith thirty-day sunset. - Semver rules –
MAJOR= renamed or removed columns;MINOR= additive nullable columns;PATCH= documentation-only if hashes unchanged. - Freeze window – default seventy-two hours with no new Lesson 95 overrides except P0 incidents logged under
emergency_migration_flag=true. - Backfill – deterministic scripts checked into version control; no hand edits in prod CSVs.
- Hash recompute order – Lesson 92 → 93 → 94 → 95 → 96 → 97 → 98 dependencies; re-run in topological order.
- Rollback – keep prior CSV snapshot tarball addressable by
migration_id; practice restore quarterly.
Step 3 - Author lesson78_schema_migration_runbook.csv
| column | purpose |
|---|---|
migration_id |
stable id |
from_semver / to_semver |
policy versions |
freeze_start_utc / freeze_end_utc |
communication window |
scripts_git_sha |
automation pointer |
rows_touched_count |
integer |
hash_recompute_job_id |
orchestration id |
m1_m4_gate_status |
pass / fail |
signer_engineering_id |
owner |
signer_governance_id |
second owner |
migration_evidence_hash |
sha256 over manifest + logs |
Step 4 - Execute migration (55 minutes dry-run)
- Snapshot all Lesson 92–98 CSVs and Lesson 97 zips; hash tarball.
- Announce freeze with
freeze_end_utcand P0 exception path. - Run transforms in staging; diff row counts and key hashes.
- Apply prod during lowest-traffic window; stream logs to immutable store.
- Recompute downstream hashes; open a fresh Lesson 97 attestation stub if quarter boundary crossed.
- Sign
migration_evidence_hash.
Step 5 - Tabletop - “we only renamed a column”
Renaming dry_run_id_ref without a MAJOR bump and compatibility view breaks partner automation. Outcome: M3 failure; ship compatibility shim for two releases.
Pro tips
- Dual-write period – for
MAJOR, run old and new column writers in parallel for one sprint if partners lag. - Feature flags – gate new hash fields behind
policy_semver >= xin CI validators. - Docs – update lesson markdown examples the same day; stale docs are a control failure.
Troubleshooting
| symptom | likely cause | fix |
|---|---|---|
| Rows explode after join | one-to-many merge mistake | revert snapshot; fix script |
| Attestation zip rejects | manifest not regenerated | rebuild manifest after migration |
| Board digest unchanged | forgot Lesson 98 refresh | open new digest_id |
Common mistakes
- Migrating Friday 4 p.m. without freeze comms.
- Letting analytics drop columns they think are unused—hashes depend on them.
- Skipping Lesson 94 recompute because holds were empty.
FAQ
Do we migrate Lessons 89–91 too?
Yes when their exports feed Lesson 92 inputs; include them in the same migration_id or declare explicit version pins.
What if only docs change?
PATCH only if byte-identical CSV outputs; otherwise bump MINOR.
Who approves MAJOR?
Engineering lead + governance lead + legal on column removals affecting disclosures.
Lesson recap
A schema bump without a runbook is a silent recall on your evidence chain. Version everything that touches a hash.
Next lesson teaser
Next: Lesson 100: Fiscal-Year Escalation Governance Closure Checklist seals the year—quarterly Lesson 97 zips, Lesson 98 digests, Lesson 99 migration, zero stuck verification rows, dual-signed fiscal_closure_evidence_hash, next-year charter.
Related learning
- Lesson 98: Board-Ready Escalation Lineage Digest
- Lesson 97: Quarterly Escalation Governance Attestation Export
- How to Score Forecast Calibration Drift Before Release Gates for Live-Ops Teams (2026)
Treat semver as API compatibility, not marketing labels.