…tes (v0.4.3)
Reading the v0.4.2 output, found the domain enum value leaking into
prose at 4 distinct sites:
1. **Ml** (uni technical-depth heading) — capitalizeFirst('ml') →
"Ml" instead of "ML" / "Machine Learning"
2. "2 ml projects in Python" (uni technical-depth sentence body) —
raw enum 'ml' interpolated
3. "An active ml project built primarily in Python" (uni per-project
intro) — same raw 'ml' leak
4. "A ml project in Python." (case-studies overview fallback when
description is null) — same root cause
Fix: two new exported maps in @portfoliocraft/core:
DOMAIN_DISPLAY — lowercase mid-sentence: 'machine-learning', 'DevOps'
DOMAIN_TITLE — Title Case heading: 'Machine Learning', 'DevOps'
Used at all 4 prose sites + tightened TechnicalDepthEntry.domain
schema from z.string() to the existing Domain enum so renderers can
safely index without runtime fallback. Builder always emitted enum
values; schema was looser than the data.
Removed the now-dead capitalizeFirst helper in summary-uni.ts.
Pattern recorded for future renderer work: when a prose-rendering bug
appears in one site, audit the WHOLE module for sibling sites that
share the shape. v0.4.0 → v0.4.3 has been a chain of catch-up because
each patch was localized. v0.4.3's fix is centralised so the next
"an X" or "title-case domain" need never reopens.
Summary
Reading the v0.4.2 dogfood output found 4 sites where the `Domain` enum value was leaking directly into prose:
All same root cause: raw enum values (`ml`, `devops`) were being interpolated into rendered text. Fixed at the source with two new exported maps in `@portfoliocraft/core`:
Used at all 4 prose sites + tightened `TechnicalDepthEntry.domain` schema from `z.string()` to the existing `Domain` enum so renderers can safely index without runtime fallback.
Pattern recorded
This is the third v0.4.x patch where reading the rendered output found bugs the unit tests, lint, and CodeQL gates all missed. They were structurally correct; just embarrassing to read.
Process gate going forward: when a prose-rendering bug appears in one site, audit the whole renderer module for sibling sites. v0.4.0 → v0.4.3 has been a chain of catch-up because each patch was localized. v0.4.3 closes the audit by centralizing.
Test plan