← Choice Health strong-typing-quality-report.md raw .md

Strong Slot Typing — Quality & Testing Report

For: Fable 5 design review Scope: schema-0.2 strong slot typing (remote-control design §2.2) + the codex-review fixes Date: 2026-07-02 Branch/commits: voice-capability-hierarchymain2513a7d4, c6871ce3, cc84fa6a, 8d991170 (+ design docs 10ff8b52, a2d6d991)


1. What shipped

The slot_types facility was extended (not replaced) to make collect slots strongly typed, enforced at compile time (riffc L0-10) and runtime (validators):

2. Codex findings → fixes → evidence

Codex reviewed the design + first slice and found real gaps. All slice-level findings are closed with tests:

# Sev Finding Fix Test evidence
1 HIGH runtime ignored unified type:{type: phone} accepted garbage resolve via effective_semantic_type at all 3 validation sites test_unified_type_enforced_at_runtime, test_unified_and_longform_agree_at_runtime
2 MED {type: phone, semantic_type: email} silently resolved by precedence reject conflicting semantics at load test_conflicting_semantics_rejected (3 forms)
3 HIGH enum declared but not enforced at runtime enum_match membership check in validate_slot_value test_enum_accepts_and_canonicalizes (5), test_enum_rejects_out_of_domain (5), test_enum_rejects_injection_before_membership
7 HIGH channel-bind unsound (design) resolved by Fable 5 → §3.1 device-pairing (OD-R6) design doc
8 MED L0-11 undefined field-voice-prompt (design) resolved → canonize reask (OD-R7) design doc

Design findings #7/#8 are in Fable 5's court (recorded as OD-R6/OD-R7 §9). Surface-lane findings #4 (GoalSegment target_slots), #5 (enum option metadata), #6 (untyped-degrade) are assigned to the parallel surface session with the iter_slots(flow) directive.

3. Acceptance A5 coverage

A5: riffc rejects a surface button naming a nonexistent token, a form field with an untyped slot, and a screen-only state with no voice path.

4. Test inventory

Suite Tests Focus
test_slot_types_schema02.py 16 vocabulary, validation, unified-type + enum runtime, L0-10
test_slot_typing_adversarial.py 53 adversarial: every semantic via type:; enum alias/case/whitespace/injection/collision; conflicts in every form; runtime enforcement per semantic; widget override; date; L0-10 synthetic flows
test_typed_slots_across_flows.py 157 cross-fleet: every typed slot resolves to an implemented type + validates type-correctly
test_slot_type_ratchet.py 2 exact ratchet — no untyped behavioral slot silently added
test_riffc_golden.py / test_riffc_all_flows.py 3 + 60 anchor census/checks locked; whole-corpus classification

Adversarial highlights (the "under pressure" evidence): enum rejects an injection payload ("drain\x00; DROP TABLE") via the shape check before membership; alias collisions resolve deterministically by declaration order; conflicting type:/semantic_type: rejected; {type: phone} and {semantic_type: phone} proven byte-identical at runtime.

5. Regression discipline — every remaining failure is pre-existing

The full -k "validator or slot" suite has 11 failures + 1 error. Every one was verified failing on clean HEAD (41792be4, before any typing work) via isolated git worktree runs — pizza/scheduling/offer/fsm-debug scenario tests unrelated to typing. This slice:

Method note: each suspected regression was reproduced on a clean checkout before attribution — no failure was assumed mine or pre-existing without proof.

6. Honest caveats / open items

7. Verdict

Strong typing is real end-to-end: declared at load, enforced at compile (L0-10) and runtime (unified type: + enum membership), covered by 228 passing typing tests (schema02 16 + adversarial 53 + cross-fleet 157 + ratchet 2) including a 53-case adversarial suite, with a proven-zero-regression, net-positive impact on the corpus.