You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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 LS→WR 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 LS→WR 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 RVandEV 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 noSP-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-104 — LS → 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 → LS → N) and med-074 (arm → N → WR).
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).
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.
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 probenotes/assets/202607241000-ls-wr-association-probe.py. That review asked four questions of the suite — theLS→WRlevel 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
LS→WRlevel 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
lrp-rli-ca-010concurrentWRlevel ~LS+ age + hearing + non-verbal ability, per wavekey_findings.json, nopsense.ca-001is the nearest registered model but mutually adjusts for five other same-wave skills, which answers a different conditional questionlrp-rli-ca-011concurrentca-010, plus same-waveNWca-001excludes flooredNWas a predictor by design, so no registered model carries thislrp-rli-gf-012gain_factorsTRgains withskill_symbols = ("R", "E")gf-009carries 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 gaplrp-rli-gf-013gain_factorsTEgains withskill_symbols = ("TR", "R", "E")gf-010carries onlyTR; the review findsRVandEVboth matter for taught-expressive gains (+0.28 and +0.31, both P ≈ 0.98)lrp-rli-mech-102mechanismRW → NW— phonological memory → nonword decodingmech-090(from #311) already fitsRW → WRat +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 isHS, its other parents beingAand latentGAlrp-rli-mech-103mechanismSP → NW— speech production → nonword decodingSPis a DAG parent of bothLSandNW(SP -> { TE EV LS PA NW }) and a consistent review discriminator (+0.19 to +0.28 across waves), yet there is noSP-exposure mechanism model anywhere in the suiteNote that
gf-1NNis already the treated-only-companion convention (gf-101isgf-001's companion), which is why the taught-vocabulary additions takegf-012/gf-013rather thangf-109/gf-110. All proposed ids were checked free against the module tree, but confirm againstdefinitions.MODEL_REGISTRY/docs/models/registry-counts.jsonat build time as #404 requires.Both
mech-102andmech-103should uselinear_mechanism=Truerather than an HSGP curve:NWis 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 tomech-072).Tier 2 — existing factories, harder to interpret
lrp-rli-mech-104—LS → WRmoderated byRW(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 > 0would 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:erbtois a covariate rather than aMEASURESsymbol, so it takesmoderator_is_covariate=True, the pathmech-073/mech-173already use for age.This model has an interpretive advantage over #404's pair that is worth stating explicitly in its report prose.
BandNare DAG-descendants ofL, which is why #404 has to reportbeta_mechas a controlled-direct effect at fixed moderator andgamma_intas effect-modification by a downstream skill.RWis not a descendant ofL— under the committed DAGRW's children are{ TE EV TR RV PA NW PS }, which does not includeLS, andRWis not an ancestor ofLSeither. SoL × RW → Wis 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 (plusL × B → Wand 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 modelThe 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 itsLS→NminusLS→Wdifference 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: extendbuild_joint_model(currently an ITT-suite construction overITT_OUTCOMES) to a levels/concurrent design, or add a two-outcome variant ofbuild_concurrent_model. Given the review's Q1/Q2 are per-wave levels models, the concurrent route is the closer fit; thecorr_factorfamily's LKJ handling is the obvious reference, noting the repo's own gotcha that PyMC 6.1'sLKJCorrreturns the Cholesky factor rather than the correlation matrix.Tier 3 (2) — a floor-tolerant second mediator leg
build_two_mediator_modelcurrently requires an autoregressive baseline per mediator leg ({mE}_pre_logit) and hard-codes the first leg toL. Nonword reading is post-only and ~72 % floored at t1, so it cannot supply one — which is why the chainedLS → NW → WRdecomposition (med-081) was specced and then withdrawn at build time, as recorded innotes/202607172330-tier1-decoding-specificity-spec.md§6. The DAG designatesNWthe 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 modelsmed-086(arm →LS→N) andmed-074(arm →N→WR).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_offfloorlikelihood the ITT and gain-factor families already carry forPandN, 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. Unblockingmed-081is the deliverable; the second leg'smL != "L"restriction can stay in place.Sequencing — one cheap probe change first
Before
mech-102/mech-103are specced, change the review probe soRWandSPenter 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 tonotes/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
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.notes/202607172345-design-lessons-for-future-studies.mdalready records.notes/202607171215-findings-skill-thresholds.mdalready swept six exposures and found onlyLShas 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
RW/SPentered same-wave in the discriminator partials; note updated if the conclusion moves.ca-010,ca-011,gf-012,gf-013,mech-102,mech-103), each aSPEC = ModelSpec(...)+fit(), registered indefinitions.MODEL_REGISTRY, withregistry-counts.jsonregenerated (python scripts/check_statistical_documentation.py --write).mech-104plus a no-interaction companion for the PSIS-LOO contrast, following themech-072/mech-172convention; 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.docs/models/{model_id}/reusing_results_concurrent/_results_factors/_results_mechanism;docs/models/README.mdfamily tables updated.{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.build_two_mediator_model;med-081built, fitted and reported on an off-floor risk-difference scale.--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 spellcheckpass.Related
Companion to #404 (
L×B → WandL×N → Wjoint-readiness interactions — this issue defers the descendant-moderator cell to it) and #405 (TR → L/TE → L). Builds on #311 (which producedmech-090, theRW → WRmodel), #312 / #314 (which created theconcurrentfamily), and the 2026-07-10 DAG revision adopted in #251.