Lesson 185: Mock Audit Rubric JSON Semver Drift Block on Calendar Re-Export (2026)

Direct answer: Lesson 181 exports ICS holds from mock_audit_rubric_v1.json. Lesson 185 adds a semver gate: if the committed rubric JSON changes dimensions, weights, or failure-mode tags without bumping rubric_version, the calendar re-export job refuses to run and publish stays blocked until holds are regenerated with matching version pins.

Lesson hero for mock audit rubric JSON semver drift block on calendar re-export

Why this matters now (2026 rubric drift on booked holds)

Teams already hit this in Q4 2026 planning:

  • Panel books January T-14 rehearsal from ICS exported in October.
  • Engineering edits mock_audit_rubric_v1.json (adds dimension, reweights) without semver bump.
  • Calendar UIDs look unchanged—scribe runs tabletop with new rubric, attendance receipt still references old event description weights.
  • Lesson 172 scoring rejects rows; Lesson 183 CSV export empty; leadership blames “calendar bug.”

The failure is version skew, not scheduling. This lesson makes skew mechanical.

Lesson objectives

You will implement:

  • mock_audit_rubric_registry with immutable rubric_version rows
  • cert_window_calendar.rubric_version pin on every hold
  • forbid_calendar_reexport_without_semver_bump job guard
  • rubric_semver_drift_open publish-gate extension
  • Re-export procedure paired with Lesson 177 dictionary migration phases

Prerequisites

  • Lesson 181 — ICS export + stable ics_uid
  • Lesson 177 — dictionary semver migration pattern (dual-write discipline)
  • Lesson 184 — clear room conflicts before re-export
  • Lesson 172 — scoring uses rubric dimensions from registry

mock_audit_rubric_registry table

CREATE TABLE mock_audit_rubric_registry (
  rubric_version     TEXT PRIMARY KEY,
  rubric_sha256      CHAR(64) NOT NULL,
  effective_at_utc   TIMESTAMPTZ NOT NULL,
  changelog          TEXT NOT NULL,
  retired_at_utc     TIMESTAMPTZ
);

ALTER TABLE cert_window_calendar
  ADD COLUMN rubric_version TEXT NOT NULL DEFAULT '1.0.0'
    REFERENCES mock_audit_rubric_registry (rubric_version);

On every commit to governance/mock_audit_rubric_v1.json:

  1. Compute SHA-256 of normalized JSON (sorted keys, LF endings).
  2. If hash differs from active registry row → require new rubric_version (semver).
  3. Insert registry row before any calendar re-export.

Semver rules (rubric JSON)

Change class Bump Example
Typo in changelog only patch 1.0.01.0.1 README note
Add dimension, reweight, new failure_mode minor 1.0.11.1.0 New Lesson 173 column
Remove dimension or change pass_rule major 1.1.02.0.0 Panel contract break

Forbidden: edit weights in place while rubric_version stays 1.0.0.

Calendar re-export guard

def reexport_calendar(cert_window_id: str) -> None:
    active = load_committed_rubric_json()
    registry = query_one(
        "SELECT rubric_version, rubric_sha256 FROM mock_audit_rubric_registry "
        "WHERE retired_at_utc IS NULL ORDER BY effective_at_utc DESC LIMIT 1"
    )
    if sha256(active) != registry.rubric_sha256:
        raise RubricSemverDrift(
            "Committed rubric hash differs from registry. Bump rubric_version first."
    )
    pinned = query(
        "SELECT DISTINCT rubric_version FROM cert_window_calendar WHERE cert_window_id = %s",
        [cert_window_id],
    )
    if len(pinned) != 1 or pinned[0] != registry.rubric_version:
        raise RubricSemverDrift(
            "Calendar holds pin a different rubric_version. Re-export required."
    )
    run_lesson_181_exporter(cert_window_id, rubric_version=registry.rubric_version)

Publish-gate extension

Add to Lesson 171 allow-list:

  • rubric_semver_drift_open — active holds’ rubric_version ≠ registry head, or committed JSON hash mismatch.

Blocks publish until:

  1. Registry row inserted for new semver.
  2. Lesson 181 re-export completes with same ICS UIDs (Lesson 181 rule).
  3. GOVERNANCE_REHEARSAL_README.md changelog line added.

Pairing with Lesson 177 dictionary migration

Run rubric semver bumps in the same change window as dictionary minor migrations when both touch panel scoring:

Phase Dictionary (177) Rubric (185)
prepare Freeze exports Freeze calendar re-export
dual_write Dual column names Optional: hold description lists both versions
cutover Switch exporters Re-export ICS with new rubric_version
rollback Revert dictionary semver Retire rubric registry row; re-export prior semver

Never cutover dictionary while calendar still pins old rubric_version.

Re-export procedure (after semver bump)

Step Owner Action
1 Governance owner Bump rubric_version + insert registry row
2 Engineering Verify Lesson 184 conflicts = 0
3 Scribe Run guarded re-export job
4 Panel lead Confirm ICS descriptions show new version in subject line
5 Governance owner Clear rubric_semver_drift_open gate

ICS subject template:

[mock-audit v1.1.0] Q1 2027 Meta T-14 Rehearsal

Evidence artifact

release-evidence/05-operations/RUBRIC_SEMVER_YYYYMMDD.json:

{
  "schema": "rubric_semver_export_v1",
  "from_version": "1.0.0",
  "to_version": "1.1.0",
  "rubric_sha256": "…",
  "cert_window_id": "q1_2027_meta",
  "ics_uid_count": 4,
  "reexport_at_utc": "2026-10-12T16:00:00Z"
}

Common mistakes

  • Hand-editing ICS descriptions without registry row.
  • Minor weight tweak without semver—breaks Lesson 172 muscle memory.
  • New ics_uid on re-export when only semver bumped—breaks Lesson 182 receipts.
  • Running re-export while Lesson 184 conflicts open.
  • Dictionary migration cutover without rubric re-export.

Troubleshooting

Symptom Likely cause Fix
Job raises RubricSemverDrift JSON changed, version not bumped Insert registry + bump semver
Gate stuck after re-export Holds still old version column UPDATE pins or full re-export
Panel sees mixed weights Description not updated Re-export with version in subject
Scoring allow-list rejects tags New failure_mode without minor bump Bump rubric + re-export

Verification checklist

  • [ ] Hash change without version bump fails CI
  • [ ] Registry row required before re-export succeeds
  • [ ] All holds share one rubric_version per window
  • [ ] Publish gate fires on deliberate drift test
  • [ ] ICS UIDs stable across semver re-export

Mini exercise (20 minutes)

  1. Copy mock_audit_rubric_v1.json; change one weight_percent by 1.
  2. Write expected CI failure message.
  3. Bump minor semver; draft registry INSERT.
  4. List one Lesson 177 phase that must align.

Continuity

  • Lesson 181 — exporter implementation; UID stability rules unchanged.
  • Lesson 177 — dictionary semver sibling discipline.
  • Lesson 184 — run before re-export.
  • Next: Lesson 186 — regional panel roster across time zones.
  • Guide: Unity mock-audit rubric preflight chapter pairs Q3 intake tabletop.

FAQ

Can we use calendar sequence numbers instead of semver?
No. Panel and SQL tooling key off rubric_version string in registry.

Patch bump for typo in dimension name?
Yes if scoring allow-list unchanged; still re-export ICS so descriptions match.

Major bump mid-window?
Allowed with leadership ack; reschedule T-3 if panel already trained on prior weights.

Does this replace git tags?
No—registry is operational truth for gates; git tags are optional metadata.


Booked rehearsals are contracts. If the rubric changes, the version must change—and the calendar must say so before anyone walks into the room.