Lesson 195: Partner-Sanitized Rehearsal Score Letter Export Without Raw mock_audit_log Rows (2026)

Direct answer: Lesson 193 exports rehearsal_completion_v1.json. Lesson 195 projects that JSON—and dimension rollups only from Lesson 172 scoring—into a partner-safe PARTNER_SCORE_LETTER.md. Raw mock_audit_log rows, signer emails, internal ticket IDs, and panel notes never leave the redaction boundary. Publish blocks on partner_letter_draft_open until legal approves the template and the export passes an allow-list scan.

Lesson hero for partner-sanitized rehearsal score letter export

Why this matters now (Q4 2026 partner readbacks)

Q4 2026 partner templates changed again:

  • Attachments with raw mock_audit_log CSV and signer email columns now trigger yellow-flag on readback—not because scores were wrong, but because PII crossed the partner boundary.
  • Partners want dimension summaries and phase completion proof from Lesson 193, not SQL dumps.
  • Lesson 194 intake folders explicitly exclude raw logs; this lesson is the sanitized letter that belongs beside rehearsal_completion_v1.json.
  • Lesson 170 FAQ tone rules apply to every sentence partners quote back to executives.

Lesson objectives

You will implement:

  • View partner_score_letter_redacted_v1
  • Allow-listed column contract (no PII, no raw log IDs)
  • Markdown template PARTNER_SCORE_LETTER.md
  • Export job export_partner_score_letter_v1
  • Publish gate partner_letter_draft_open
  • Receipt PARTNER_SCORE_LETTER_RECEIPT.json

Prerequisites

  • Lesson 193rehearsal_completion_v1.json, rehearsal_completion_incomplete clear
  • Lesson 172 — seven-dimension rubric labels and weights
  • Lesson 170 — FAQ-bound readback tone for letter prose
  • Lesson 194 — optional; letter ships inside intake folder when ready

Allow-listed export fields

Field Source Partner-safe
cert_window_id rollup JSON Yes
completion_score_percent Lesson 193 Yes
phase (t_minus_14, t_minus_3) rollup JSON Yes
pass_bit per phase rollup JSON Yes
weighted_score per phase rollup JSON Yes (aggregate only)
dimension_id (1–7) rubric rollup Yes
dimension_label rubric Yes
dimension_score_percent aggregated Yes
structural_red_flag (bool) rubric Yes
rubric_version rollup JSON Yes

Forbidden in partner lane (fail export):

  • signer_email, panelist_email, scribe_email
  • mock_audit_log_id, attendance_id, internal_ticket_id
  • Free-text panel_notes, deficiency_detail, raw CSV paths
  • Any column matching %_email or %_hash except public bundle_sha256 on manifests

partner_score_letter_redacted_v1 (view)

CREATE VIEW partner_score_letter_redacted_v1 AS
SELECT
  r.cert_window_id,
  r.completion_score_percent,
  p.rehearsal_phase,
  p.pass_bit,
  p.weighted_score,
  p.rubric_version,
  d.dimension_id,
  d.dimension_label,
  d.dimension_score_percent,
  d.structural_red_flag
FROM rehearsal_completion_export_staging r
JOIN rehearsal_completion_phases_staging p
  ON p.cert_window_id = r.cert_window_id
JOIN mock_audit_dimension_rollup_staging d
  ON d.cert_window_id = r.cert_window_id
  AND d.rehearsal_phase = p.rehearsal_phase
WHERE r.export_schema = 'rehearsal_completion_v1';

Staging rule: ETL loads from rehearsal_completion_v1.json only—never SELECT * FROM mock_audit_log.

PARTNER_SCORE_LETTER.md template

# Rehearsal completion summary — {{cert_window_id}}

**Planning window:** Q1 2027 intake rehearsal  
**Exported:** {{exported_at_utc}}  
**Completion score:** {{completion_score_percent}}%

## Phase results

| Phase | Pass | Weighted score | Rubric |
|-------|------|----------------|--------|
| T-14 | {{t14_pass}} | {{t14_score}} | {{t14_rubric}} |
| T-3  | {{t3_pass}}  | {{t3_score}}  | {{t3_rubric}}  |

## Dimension summary (no raw panel notes)

| # | Dimension | Score % | Structural red |
|---|-----------|---------|----------------|
{{#each dimensions}}
| {{dimension_id}} | {{dimension_label}} | {{dimension_score_percent}} | {{structural_red_flag}} |
{{/each}}

## Partner-facing statement

Both required rehearsal phases completed with scored logs. Dimension summaries above are aggregated; raw audit rows are not included per 2026 partner readback policy.

**Questions:** Reply via your governance channel referencing `cert_window_id` only.

Render with FAQ-bound tone checks from Lesson 170 (no blame language, no internal codenames).

Export job

FORBIDDEN_SUBSTRINGS = ("@", "mock_audit_log_id", "signer_", "panel_notes")

def export_partner_score_letter(cert_window_id: str, out_dir: Path) -> Path:
    rows = query_view("partner_score_letter_redacted_v1", cert_window_id)
    md = render_partner_letter_template(rows)
    for bad in FORBIDDEN_SUBSTRINGS:
        if bad in md:
            raise RedactionError(f"forbidden token in letter: {bad}")
    path = out_dir / "PARTNER_SCORE_LETTER.md"
    path.write_text(md, encoding="utf-8")
    receipt = {
        "schema": "partner_score_letter_receipt_v1",
        "cert_window_id": cert_window_id,
        "sha256": sha256_file(path),
        "allow_list_version": "2026-q4-partner-v1",
        "raw_log_rows_included": False,
    }
    write_json(out_dir / "PARTNER_SCORE_LETTER_RECEIPT.json", receipt)
    return path

Publish gate partner_letter_draft_open

Pipeline sets partner_letter_draft_open when any of:

Condition Block reason
Legal has not approved template version letter_template_unapproved
Allow-list scan finds @ in output pii_email_detected
rehearsal_completion_incomplete still open rollup_not_passing
Export references raw CSV path string raw_csv_reference
raw_log_rows_included true in receipt raw_logs_flagged

Clear gate only after legal sign-off row in partner_letter_template_approval and successful allow-list scan.

Ninety-second preflight

  • [ ] rehearsal_completion_v1.json shows "pass": true
  • [ ] View query returns zero email columns
  • [ ] PARTNER_SCORE_LETTER.md has no @ and no mock_audit_log_id
  • [ ] Seven dimension rows present (or documented waiver)
  • [ ] PARTNER_SCORE_LETTER_RECEIPT.json shows raw_log_rows_included: false
  • [ ] partner_letter_draft_open clears on dry-run publish

Troubleshooting

Symptom Fix
Partner asks for “the CSV” Resend letter + rehearsal_completion_v1.json; cite 2026 redaction policy
Dimension scores missing Refresh mock_audit_dimension_rollup_staging from scored logs inside warehouse only
Legal blocks template Bump allow_list_version; re-approve FAQ tone
Yellow-flag on email in footer Strip mailto links from template

Mini exercise (25 minutes)

  1. Load fixture rehearsal_completion_v1.json with passing phases.
  2. Run export; grep letter for @ (expect no matches).
  3. Inject signer_email into staging—confirm export raises RedactionError.
  4. Attach letter to Lesson 194 intake folder dry-run.
  5. Pin receipt JSON.

Continuity

  • Lesson 193 — rollup source.
  • Lesson 172 — dimension labels.
  • Lesson 170 — prose tone.
  • Lesson 194 — intake folder sibling (no raw logs).
  • Next: Lesson 196 — dashboard slice fails closed when rollup incomplete.

FAQ

Can partners receive hashed signer IDs?
No—use cert_window_id and phase pass bits only unless counsel approves a new allow-list version.

Do we attach dimension deficiency tickets?
Not in the partner letter lane; internal tickets stay in ops tools.

What if T-3 pass_bit is false?
Letter still exports with honest fail summary; partner_letter_draft_open may remain until remediation—do not hide gaps.

How does this relate to Lesson 199?
Attestation bundles the letter receipt with Lessons 194–198 green gates.


Q4 2026 partners trust short, redacted letters backed by rehearsal_completion_v1.json—not spreadsheets that leak who sat in the panel and which internal ticket IDs were debated.