Lesson 192: Mock Audit Rubric Emergency Dimension Weight Hotfix Without Invalidating Lesson 185 Pins (2026)
Direct answer: When Gamescom-adjacent Q3 2026 partner feedback demands a single-dimension weight nudge inside an active cert window, do not edit mock_audit_rubric_v1.json in place. Open a rubric_weight_hotfix_request, dual-write weights that still sum to 100, mint a hotfix semver row (1.2.0-hotfix.1) distinct from a major bump, re-pin future holds only, and fail-close publish on rubric_hotfix_pending until ICS re-export completes.

Why this matters now (Q3 2026 mid-window partner nudges)
Q3 2026 intake windows overlap Gamescom-adjacent reviews and autumn Deck verification. Partners sometimes ask:
“Increase telemetry_readiness from 12 → 15 points and reduce documentation_clarity by 3—same seven dimensions, no new failure modes.”
Teams that mutate weights without semver trigger Lesson 185 rubric_semver_drift_open and block all calendar re-exports. Teams that major-bump to 2.0.0 invalidate booked T-14 holds still pinned to 1.2.0.
This lesson adds a hotfix lane: rebalance weights without breaking pins on already-completed rehearsals.
Lesson objectives
You will implement:
rubric_weight_hotfix_requestworkflow table + signer ack- Dual-write weights on registry (
active+pending_hotfixJSON) - Hotfix semver pattern (
{base}-hotfix.{n}) separate from minor/major rubric_hotfix_pendingpublish gate until re-export finishes- Re-export scope limited to not-yet-completed
cert_window_calendarrows
Prerequisites
- Lesson 185 — semver drift block on calendar re-export
- Lesson 181 — ICS export +
rubric_versioncolumn - Lesson 172 — seven dimensions, weights sum 100
- Lesson 177 — dictionary dual-write pattern (reuse discipline)
rubric_weight_hotfix_request table
CREATE TABLE rubric_weight_hotfix_request (
hotfix_request_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
cert_window_id TEXT NOT NULL,
base_rubric_version TEXT NOT NULL REFERENCES mock_audit_rubric_registry (rubric_version),
hotfix_rubric_version TEXT NOT NULL,
dimension_id TEXT NOT NULL,
delta_points INT NOT NULL CHECK (delta_points BETWEEN -20 AND 20),
donor_dimension_id TEXT NOT NULL,
partner_ticket_ref TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'draft'
CHECK (status IN ('draft','approved','applied','rejected')),
approver_signer_id TEXT,
applied_at_utc TIMESTAMPTZ,
CHECK (dimension_id <> donor_dimension_id)
);
Policy: delta_points must be offset by opposite delta on donor_dimension_id so total weight stays 100.
Dual-write weights (sum = 100)
{
"schema": "mock_audit_rubric_v1",
"rubric_version": "1.2.0-hotfix.1",
"dimensions": [
{ "id": "telemetry_readiness", "weight": 15 },
{ "id": "documentation_clarity", "weight": 9 }
],
"weight_sum_check": 100
}
Job steps:
- Copy active registry row
1.2.0→ working hotfix JSON. - Apply approved deltas only on named dimensions.
- Assert
SUM(weight) = 100in SQL and in CI. - Insert registry row
1.2.0-hotfix.1with new SHA-256. - Leave completed
mock_audit_logrows pinned to1.2.0(no retroactive rescoring).
Hotfix semver lane (distinct from Lesson 185 bumps)
| Lane | When | Example |
|---|---|---|
| patch | Changelog typo only | 1.2.0 → 1.2.1 |
| minor | New dimension / failure mode | 1.2.0 → 1.3.0 |
| major | Remove dimension / pass rule change | 1.2.0 → 2.0.0 |
| hotfix | Weight rebalance only, same dimension set | 1.2.0 → 1.2.0-hotfix.1 |
Forbidden: reuse 1.2.0 SHA after weight edit (Lesson 185 blocks re-export).
Apply workflow
| Step | Owner | Action |
|---|---|---|
| 1 | Partner liaison | File rubric_weight_hotfix_request with ticket ref |
| 2 | Governance owner | Approve; verify donor dimension exists |
| 3 | Engineering | Insert mock_audit_rubric_registry hotfix row |
| 4 | Engineering | Set rubric_hotfix_pending = true on cert window |
| 5 | Engineering | Re-export ICS for scheduled holds only (Lesson 181) |
| 6 | Scribe | Announce hotfix in tabletop opener—completed logs stay on old version |
| 7 | Engineering | Clear pending after re-export SHA pinned |
def apply_weight_hotfix(req_id: UUID) -> None:
req = load_request(req_id)
assert req.status == "approved"
hotfix_json = build_hotfix_json(req)
assert sum_weights(hotfix_json) == 100
insert_registry_row(req.hotfix_rubric_version, sha256(hotfix_json))
mark_window_hotfix_pending(req.cert_window_id)
reexport_ics_for_scheduled_holds_only(req.cert_window_id, req.hotfix_rubric_version)
Publish gate: rubric_hotfix_pending
-- block_reason = 'rubric_hotfix_pending'
WHEN EXISTS (
SELECT 1 FROM cert_window_calendar c
WHERE c.cert_window_id = :active_window
AND c.hotfix_pending = true
);
Clears when:
- All future holds show
rubric_version = hotfix version ICS_REEXPORT_RECEIPT.jsonSHA pinned- No
rubric_semver_drift_openfrom Lesson 185
Pairs with panel_roster_gap_open (Lesson 191)—resolve hotfix before quorum crosswalk sign-off.
Common mistakes
- Hotfixing weights and adding a failure mode tag—use minor bump instead.
- Rescoring last week’s
mock_audit_logto hotfix version—breaks audit trail. - Re-exporting completed UIDs—partners see duplicate calendar noise.
- Donor dimension delta wrong sign—sum ≠ 100, CI fails at 2 a.m.
- Skipping partner ticket ref—intake replay rejects “silent” weight changes.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
rubric_semver_drift_open |
Edited JSON without registry row | Insert hotfix semver row first |
rubric_hotfix_pending stuck |
ICS job not scoped to scheduled | Finish re-export receipt |
| Panel argues weights mid-tabletop | Hotfix applied mid-session | Apply only between rehearsals |
| Lesson 186 roster mismatch | Re-export changed UID text | Keep ics_uid stable; update DESCRIPTION only |
| Sum 99 or 101 | Rounding on three-way split | Integer math in SQL generator |
Verification checklist
- [ ] Approved hotfix with
+3/-3keepsweight_sum_check = 100 - [ ] Registry contains both
1.2.0and1.2.0-hotfix.1rows - [ ] Completed attendance still references
1.2.0in receipt metadata - [ ] Scheduled T-3 hold shows hotfix version after re-export
- [ ] Gate
rubric_hotfix_pendingclears after receipt pin
Mini exercise (20 minutes)
- Export rubric
1.2.0with weights summing to 100. - Draft hotfix:
telemetry_readiness +2,documentation_clarity -2. - Insert
1.2.0-hotfix.1registry row. - Run re-export for one scheduled hold only.
- Confirm completed mock log unchanged; scheduled hold description updated.
Continuity
- Lesson 185 — semver drift block you must not trip.
- Lesson 181 — ICS re-export mechanics.
- Lesson 172 — dimension IDs and scoring view.
- Lesson 191 — quorum crosswalk after hotfix settles.
- Next: Lesson 193 — Q1 2027 rehearsal completion rollup.
- Resource: Q3 2026 submission intake mock-audit packet templates — cert-window context.
FAQ
Can we stack two hotfixes?
Yes—1.2.0-hotfix.2 from 1.2.0-hotfix.1 base only if partner approves; never chain off completed logs.
Is hotfix a patch semver?
No. Patches are typo-only. Hotfix is an explicit weight-rebalance lane.
Do we notify partners?
Attach partner_ticket_ref to ICS_REEXPORT_RECEIPT.json and the hotfix request row.
What if Gamescom feedback needs a new dimension?
Use minor bump (1.2.0 → 1.3.0) and full Lesson 185 re-export—not this hotfix lane.
Q3 2026 partners accept mid-window tuning when booked holds stay honest and completed scores stay immutable. Use the hotfix lane, keep weights at 100, and clear rubric_hotfix_pending before the next publish tuple promotes.