Skip to content

Build the letter-sound → word-reading follow-ups: minimal-adjustment concurrent models, RW/SP → NW mechanisms, L×RW moderation, a joint {W, N} fit and a floor-tolerant mediator leg #421

Description

@frankbuckley

Note

Drafted by a LLM-based AI tool (Claude Code/Opus 4.8).

Formalises the models identified by the letter-sound → word-reading associational review recorded in notes/202607241000-findings-letter-sounds-word-reading-association.md (pending commit) and its reproducible probe notes/assets/202607241000-ls-wr-association-probe.py. That review asked four questions of the suite — the LSWR level association adjusted for age/hearing/non-verbal ability, whether it survives holding nonword reading fixed, what distinguishes children with good letter sounds but poor word reading, and how vocabulary relates to word learning — and answered them with 62 exploratory scratch fits (max R-hat 1.000, min bulk ESS 1 618, zero divergences) that deliberately bypass the production convergence gate. This issue promotes the parts worth keeping and closes the genuine suite gaps the review exposed. Everything below is an adjusted association, latent-general-ability-confounded, never causal — the only randomisation-licensed effect in the study remains the ITT arm.

What the review found that motivates each build

The LSWR level association is large and, strikingly, untouched by the adjustment: +0.63 / +1.01 / +0.71 / +0.81 logit per +1 SD at t1–t4 (P ≈ 1.000 throughout), against matched unadjusted slopes of +0.63 / +0.99 / +0.76 / +0.83. Age, hearing and non-verbal ability together explain none of it — block design is a weak adjuster (P reaches 0.97 only at t4) and hearing is flat. Holding nonword reading fixed attenuates the slope by a fifth to a third but leaves it decisively positive (P = 1.000 at every wave). Among children alike on letter sounds, the sharpest discriminators of word reading are nonword reading and nonword repetition (the phonological short-term-memory component of the word-repetition task, d ≈ −1.2 in the t4 subgroup split), with speech production and oral language moderate and non-verbal ability flat (d = +0.06, medians identical). Vocabulary predicts learning new spoken words strongly (broad receptive vocabulary → taught-receptive gains +0.38, 89% CrI +0.18 to +0.58, P = 0.999) but learning to read words only weakly (+0.16 / +0.11, intervals straddling zero) — and that contrast is unchanged whether or not letter sounds are held fixed.

Tier 1 — existing factories, no new pipeline code

Proposed id Family Estimand Why
lrp-rli-ca-010 concurrent WR level ~ LS + age + hearing + non-verbal ability, per wave The review's headline currently exists only as a scratch fit: no gate, no report, no key_findings.json, no psense. ca-001 is the nearest registered model but mutually adjusts for five other same-wave skills, which answers a different conditional question
lrp-rli-ca-011 concurrent as ca-010, plus same-wave NW The "does it survive holding decoding fixed" decomposition. ca-001 excludes floored NW as a predictor by design, so no registered model carries this
lrp-rli-gf-012 gain_factors TR gains with skill_symbols = ("R", "E") gf-009 carries no skill terms at all, yet broad receptive vocabulary is the single clearest predictor of taught-word learning anywhere in the review (+0.38, P = 0.999). A live gap
lrp-rli-gf-013 gain_factors TE gains with skill_symbols = ("TR", "R", "E") gf-010 carries only TR; the review finds RV and EV both matter for taught-expressive gains (+0.28 and +0.31, both P ≈ 0.98)
lrp-rli-mech-102 mechanism RW → NW — phonological memory → nonword decoding mech-090 (from #311) already fits RW → WR at +0.10 logit per +1 SD (89% +0.00 to +0.20, P = 0.952), so the discriminator is registered on the word-reading side. Nothing tests whether phonological memory feeds the alphabetic route specifically, which is what the nonword-repetition result points at. mech-090's adjustment set transfers unchanged: RW's only measured parent is HS, its other parents being A and latent GA
lrp-rli-mech-103 mechanism SP → NW — speech production → nonword decoding SP is a DAG parent of both LS and NW (SP -> { TE EV LS PA NW }) and a consistent review discriminator (+0.19 to +0.28 across waves), yet there is no SP-exposure mechanism model anywhere in the suite

Note that gf-1NN is already the treated-only-companion convention (gf-101 is gf-001's companion), which is why the taught-vocabulary additions take gf-012/gf-013 rather than gf-109/gf-110. All proposed ids were checked free against the module tree, but confirm against definitions.MODEL_REGISTRY / docs/models/registry-counts.json at build time as #404 requires.

Both mech-102 and mech-103 should use linear_mechanism=True rather than an HSGP curve: NW is a 6-item outcome floored at zero for 72 / 64 / 52 / 40 % of children at t1–t4, where a nonparametric dose-response is not identifiable (the same reasoning already applied to mech-072).

Tier 2 — existing factories, harder to interpret

lrp-rli-mech-104LS → WR moderated by RW (phonological memory). This is the direct, uncertainty-quantified version of the review's third question, which currently rests on a 15-vs-15 descriptive subgroup split plus one-at-a-time partial associations. gamma_int > 0 would mean letter sounds convert to word reading more strongly for children with better phonological memory — precisely the hypothesis the discriminator analysis suggests. No new factory code is needed: erbto is a covariate rather than a MEASURES symbol, so it takes moderator_is_covariate=True, the path mech-073 / mech-173 already use for age.

This model has an interpretive advantage over #404's pair that is worth stating explicitly in its report prose. B and N are DAG-descendants of L, which is why #404 has to report beta_mech as a controlled-direct effect at fixed moderator and gamma_int as effect-modification by a downstream skill. RW is not a descendant of L — under the committed DAG RW's children are { TE EV TR RV PA NW PS }, which does not include LS, and RW is not an ancestor of LS either. So L × RW → W is a clean moderation by an exogenous-ish trait, free of #404's estimand caveat, and it should be built alongside #404 rather than folded into it.

Explicitly not proposed here: L × N → W. The review independently suggested it, but #404 already specifies exactly that model (plus L × B → W and their no-interaction companions). Nothing is added by duplicating it — this issue defers to #404 for the descendant-moderator cell, and the two issues should be read as one family.

Tier 3 (1) — a joint {WR, NW} levels model

The review's "does the letter-sound association survive holding decoding fixed" answer reports a share retained (0.97 / 0.74 / 0.80 / 0.66 across t1–t4) computed by pairing draws from two separate fits under a working-independence assumption. That is a product-of-marginals sensitivity, not an identified posterior contrast — the two fits share children, so the true joint posterior has a cross-outcome covariance the calculation ignores. The identical limitation is already documented on the Tier-1 convergent–discriminant Δ in notes/202607172358-findings-decoding-specificity.md, which flags its LS→N minus LS→W difference as a sensitivity for the same reason.

Two notes now depend on this one piece of machinery, which makes it the highest-value build in this issue despite needing new code. A joint {W, N} fit — sharing children, with an LKJ residual correlation between the two outcomes — would make both quantities identified contrasts computable from a single posterior. Implementation options: extend build_joint_model (currently an ITT-suite construction over ITT_OUTCOMES) to a levels/concurrent design, or add a two-outcome variant of build_concurrent_model. Given the review's Q1/Q2 are per-wave levels models, the concurrent route is the closer fit; the corr_factor family's LKJ handling is the obvious reference, noting the repo's own gotcha that PyMC 6.1's LKJCorr returns the Cholesky factor rather than the correlation matrix.

Tier 3 (2) — a floor-tolerant second mediator leg

build_two_mediator_model currently requires an autoregressive baseline per mediator leg ({mE}_pre_logit) and hard-codes the first leg to L. Nonword reading is post-only and ~72 % floored at t1, so it cannot supply one — which is why the chained LS → NW → WR decomposition (med-081) was specced and then withdrawn at build time, as recorded in notes/202607172330-tier1-decoding-specificity-spec.md §6. The DAG designates NW the code route between phonics knowledge and word reading (LS -> NW -> WR), so this is the suite's missing within-model test of its own central mechanism; it is currently triangulated only indirectly from the arm-anchored g-formula models med-086 (arm → LSN) and med-074 (arm → NWR).

The fix is a post-only / off-floor second mediator leg: a Bernoulli leg on the off-the-floor-at-post indicator, reusing the bernoulli_offfloor likelihood the ITT and gain-factor families already carry for P and N, so the leg needs no fabricated baseline. The decomposition would then report the indirect effect on an off-floor risk-difference scale rather than an items scale, which must be stated in the report prose. Unblocking med-081 is the deliverable; the second leg's mL != "L" restriction can stay in place.

Sequencing — one cheap probe change first

Before mech-102 / mech-103 are specced, change the review probe so RW and SP enter the discriminator analysis as same-wave values rather than t1 baselines broadcast across waves. The probe currently enters those two as t1 baselines competing against same-wave skill measures, and that timing asymmetry plausibly explains why both collapse in the joint fit while holding up one at a time. It is a one-line change to notes/assets/202607241000-ls-wr-association-probe.py, not a new model, and it may change how strongly the two mechanism models are motivated.

Explicitly out of scope

  • A mixture / latent-class model for the sight-word subgroup. By the continuous LS-conditional residual there are about two such children at t4 (one of them a clean case: 34 words read on 17 letter sounds with 0/6 nonwords, letter sounds falling t1→t4). Mixture models need orders of magnitude more; this stays a case series for the team to review qualitatively.
  • An item-level LSK measurement model to separate a genuine readiness threshold from the 32-item ceiling. Blocked by data, not modelling — there is no item-level data, as notes/202607172345-design-lessons-for-future-studies.md already records.
  • Further GP knee models. notes/202607171215-findings-skill-thresholds.md already swept six exposures and found only LS has a resolved knee; the review then showed that even that knee is confounded with the instrument ceiling (zero of 26 children in the bottom half of word reading reach 28 letter sounds, against 19 of 25 in the top half, while word reading spans 12–62 words in the same band). Another knee model cannot break that tie.

Acceptance criteria

  • Probe change: RW/SP entered same-wave in the discriminator partials; note updated if the conclusion moves.
  • Tier 1: six new modules (ca-010, ca-011, gf-012, gf-013, mech-102, mech-103), each a SPEC = ModelSpec(...) + fit(), registered in definitions.MODEL_REGISTRY, with registry-counts.json regenerated (python scripts/check_statistical_documentation.py --write).
  • Tier 2: mech-104 plus a no-interaction companion for the PSIS-LOO contrast, following the mech-072/mech-172 convention; report prose states the non-descendant-moderator advantage over Build L×B→W and L×N→W joint-readiness interaction models (is the letter-sound → word-reading conversion moderated by blending / nonword decoding?) #404.
  • Thin report templates under docs/models/{model_id}/ reusing _results_concurrent / _results_factors / _results_mechanism; docs/models/README.md family tables updated.
  • Tier 3 (1): joint {W, N} levels factory + model; the share-retained and the Tier-1 Δ both re-reported as identified contrasts, and the two findings notes updated to drop the working-independence caveat.
  • Tier 3 (2): off-floor second mediator leg in build_two_mediator_model; med-081 built, fitted and reported on an off-floor risk-difference scale.
  • All fits pass the convergence gate under --config reporting (R-hat ≤ 1.01, ESS ≥ 400, BFMI ≥ 0.3, 0 divergences); every coefficient reported as median + inner 50 % + outer 89 % credible interval + P(>0), with the adjusted-association caveat.
  • ruff check src/, npm run format:check, npm run spellcheck pass.

Related

Companion to #404 (L×B → W and L×N → W joint-readiness interactions — this issue defers the descendant-moderator cell to it) and #405 (TR → L / TE → L). Builds on #311 (which produced mech-090, the RW → WR model), #312 / #314 (which created the concurrent family), and the 2026-07-10 DAG revision adopted in #251.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions