P2 from the 2026-07-03 review (docs/reviews/2026-07-03-rules-layer-review.md, PR #19).
engine/attributes.ts documents that a mis-transcribed chart cell "throws at import time — so bad data can never reach the app", but the schema never validates that each effect's byValue covers the full minValueForBonus..maxTabulatedValue range (16–30), nor that each attribute code appears only once. A missing row validates fine and effectBonus's ?? 0 (attributes.ts:41) silently converts the transcription hole into a +0 bonus.
Current shipped content is complete (verified cell-for-cell against printed p.281), so this is a latent gap that will bite on the next transcription pass (#12, #14).
Fix: add a schema refine enforcing full byValue coverage and unique attribute codes; consider making effectBonus throw on a missing key instead of ?? 0.
P2 from the 2026-07-03 review (
docs/reviews/2026-07-03-rules-layer-review.md, PR #19).engine/attributes.tsdocuments that a mis-transcribed chart cell "throws at import time — so bad data can never reach the app", but the schema never validates that each effect'sbyValuecovers the fullminValueForBonus..maxTabulatedValuerange (16–30), nor that each attribute code appears only once. A missing row validates fine andeffectBonus's?? 0(attributes.ts:41) silently converts the transcription hole into a +0 bonus.Current shipped content is complete (verified cell-for-cell against printed p.281), so this is a latent gap that will bite on the next transcription pass (#12, #14).
Fix: add a schema refine enforcing full byValue coverage and unique attribute codes; consider making
effectBonusthrow on a missing key instead of?? 0.