diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 46e61d05..1505c7da 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -33,7 +33,7 @@ flowchart LR | `concept_dictionary` | versioned multilingual concept alignment and unknown-concept review | | `topic_measurement` | shared-latent temporal/relational topic estimation and uncertainty | | `compute_backend` | CPU `f64`, fixed-pool multithreading, CUDA/WGPU, sparse streaming, VRAM budgeting | -| `model_selection` | candidate K, predictive fit, coherence, exclusivity, stability, alignment, fairness, blinded LLM review | +| `model_selection` | fitted candidate-K scoring from the CPU reference, predictive fit, coherence, exclusivity, stability, alignment, fairness, blinded LLM review | | `psychometric_core` | posterior-plausible-value ESEM, longitudinal invariance, DSEM, continuous-time paths | | `event_intelligence` | TDT segmentation/link/detection/first-story/tracking and CHRONOS schema reasoning | | `network_analysis` | log-ratio topic correlation, conditional networks, uncertainty, Leiden consensus clusters | @@ -107,13 +107,17 @@ boundaries above remain the target modular MSA architecture. | `network_analysis` | compositional cluster-pair gates; raw simplex is not Euclidean | | `interpretation_gateway` | evidence-bounded LLM interpretations; not estimators or observed facts | | `orchestrator_live` | loopback interpretation HTTP/1.1 listener | -| `model_selection` | statistical/Pareto candidate-`K` gates; LLM votes are not numerical authority | +| `model_selection` | fitted candidate-`K` scoring from the CPU `f64` reference plus statistical/Pareto gates; LLM votes are not numerical authority | | `checkpoint_authority` | a model checkpoint is not the CPU `f64` estimator | | `compute_backend` | VRAM-budgeted streamed planning, executable OOM retry plans, and a compensated CPU `f64` reference | | `episode_membership` | episode membership cannot escape the episode event-time interval | | `membership_target` | language, episode, template, department, and opportunity-pool targets cannot collapse into entity or project | -| `topic_measurement` | logistic-normal ALR and sequential Egozcue ILR topic coordinates | +| `topic_measurement` | logistic-normal ALR/ILR coordinates and the CPU `f64` TRSL-TM reference estimator | | `analysis_engine` | bounded cutoff-safe temporal evidence readiness execution and digest-bound terminal artifacts | +| `psychometric_core` | posterior-aware structural input gates, CWC within/between OLS plus the contextual effect, event-time log-rate, unequal-interval discrete-lag remapping, constant-predictor discrete effect, time-varying-predictor discrete effect (Eq. 14), exact scalar discrete process noise (Driver et al., 2017, Eq. 3), lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; `asymDIFFUSION`), trait-plus-state variance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise), observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5; Table 2 `MANIFESTVAR` is `Θ`, not `Var(y)`; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; `Θ` does not enter lagged observed covariance; observed-indicator mean is `τ + λ μ`; `MANIFESTMEANS` is not `E(y)`; `CINT` is not `MANIFESTMEANS`; discrete latent mean is `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ`; `T0MEANS` is not `μ_t`; `CINT` is not the discrete increment; evolved observed mean is `τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`; contemporaneous `TDPREDEFFECT` impulse is `m x`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that contemporaneous impulse is `τ + λ(μ_t + m x)`, and `τ + λ μ_t` is not that observed mean; time-independent `TIPREDEFFECT` increment is `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, not `M x`, not Voelkle Eq. 14, and not the coefficient `B`; Eq. 5 of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`; within-interval `TDPREDEFFECT` carry is `e^{A(t−u)} M x` for `t0 < u < t`, not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that carried observed mean when `u ≠ t`; first-occasion `T0TIPREDEFFECT` shift is `t0_b z` and Eq. 3 first-summand carry is `e^{A Δt} t0_b z` (`T0TIPREDEFFECT` is not `TIPREDEFFECT` `B`; `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`; `e^{A Δt} t0_b z` is not `t0_b z`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_b z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean), first-occasion `T0TDPREDEFFECT` shift is `t0_m x0` and Eq. 3 first-summand carry is `e^{A Δt} t0_m x0` (`T0TDPREDEFFECT` is not `TDPREDEFFECT` `M`; `t0_m x0` is not `M x`; `e^{A Δt} t0_m x0` is not `t0_m x0`; `e^{A Δt} t0_m x0` is not `e^{A(t−u)} M x` for `t0 < u < t`; `t0_m x0` is not `t0_b z`; an impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_m x0)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean; `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean; §7.2 level-change `CINT` is `κ = −a m x` with `a < 0` so `−κ / a = m x` (`−a m x` is not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`, and not the extra near-zero-drift latent process also named in §7.2; Eq. 3 of that setting is `(1 − e^{a Δt}) m x`, which is not `m x`, not `κ`, and not `TIPREDEFFECT`; §7.2 extra-process contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (`ε = a` is `a_{ηξ} x Δt e^{a Δt}`; identification `TDPREDEFFECT` on the extra process is 1; printed extra `DRIFT` is `−0.000001`; not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`; `ε ≥ 0` fails closed; Eq. 5 of that contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; the extra process has `LAMBDA` 0 and is not an observed indicator; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; the contribution is not `E(y_t)`; the evolved-plus-contribution latent mean is not `E(y_t)`; after-t0 extra-process `TDPREDEFFECT` is `a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t` while `μ_t` uses `Δt`; Eq. 5 of that after-t0 contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)`; the first-occasion extra-process observed mean is not that observed mean when `u ≠ t0`; `e^{a(t−u)} m x` is a Dirac on the original process, not this `DRIFT` drive; §7.2 `asymTIPREDEFFECT` is `-B z / a` for `a < 0` (`-B z / a` is not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; §7.2 `addedTIPREDVAR` is `(B / a)² v`, not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`; Table 2 `asymCINT` is `-κ / a` for `a < 0` and is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; p. 16 stationary `T0MEANS` is `-κ / a + −B z / a` and is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean; Eq. 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`; stationary `T0VAR` is `trait + −q / (2 a) + (B / a)² v` (not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`); lagged stationary `T0VAR` is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (trait and `addedTIPREDVAR` do not decay; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map; Eq. 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`; `Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance); later-occasion stationary `T0VAR` is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt`; `Q_Δt` is not that later map; Eq. 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`; lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not `Var(y_t)`; the later-occasion latent variance is not `Var(y_t)`))), irregular already-centered residual lag, Rubin `T` on OLS loadings, and strong-gated latent means (two-observation residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016) | +| `validation_core` | RMSE, bias, coverage, graph, and Monte Carlo metrics | +| `tepp_api` | versioned DTO, schema, and export contracts | +| `psychometric_core` | posterior-aware structural input gates, CWC within/between OLS plus the contextual effect, event-time log-rate, unequal-interval discrete-lag remapping, constant-predictor discrete effect, time-varying-predictor discrete effect (Eq. 14), exact scalar discrete process noise (Driver et al., 2017, Eq. 3), lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; `asymDIFFUSION`), trait-plus-state variance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise), observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5; Table 2 `MANIFESTVAR` is `Θ`, not `Var(y)`; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; `Θ` does not enter lagged observed covariance; observed-indicator mean is `τ + λ μ`; `MANIFESTMEANS` is not `E(y)`; `CINT` is not `MANIFESTMEANS`; discrete latent mean is `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ`; `T0MEANS` is not `μ_t`; `CINT` is not the discrete increment; evolved observed mean is `τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`; contemporaneous `TDPREDEFFECT` impulse is `m x`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that contemporaneous impulse is `τ + λ(μ_t + m x)`, and `τ + λ μ_t` is not that observed mean; time-independent `TIPREDEFFECT` increment is `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, not `M x`, not Voelkle Eq. 14, and not the coefficient `B`; Eq. 5 of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`; within-interval `TDPREDEFFECT` carry is `e^{A(t−u)} M x` for `t0 < u < t`, not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that carried observed mean when `u ≠ t`; first-occasion `T0TIPREDEFFECT` shift is `t0_b z` and Eq. 3 first-summand carry is `e^{A Δt} t0_b z` (`T0TIPREDEFFECT` is not `TIPREDEFFECT` `B`; `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`; `e^{A Δt} t0_b z` is not `t0_b z`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_b z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean), first-occasion `T0TDPREDEFFECT` shift is `t0_m x0` and Eq. 3 first-summand carry is `e^{A Δt} t0_m x0` (`T0TDPREDEFFECT` is not `TDPREDEFFECT` `M`; `t0_m x0` is not `M x`; `e^{A Δt} t0_m x0` is not `t0_m x0`; `e^{A Δt} t0_m x0` is not `e^{A(t−u)} M x` for `t0 < u < t`; `t0_m x0` is not `t0_b z`; an impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_m x0)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean; `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean; §7.2 level-change `CINT` is `κ = −a m x` with `a < 0` so `−κ / a = m x` (`−a m x` is not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`, and not the extra near-zero-drift latent process also named in §7.2; Eq. 3 of that setting is `(1 − e^{a Δt}) m x`, which is not `m x`, not `κ`, and not `TIPREDEFFECT`; §7.2 extra-process contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (`ε = a` is `a_{ηξ} x Δt e^{a Δt}`; identification `TDPREDEFFECT` on the extra process is 1; printed extra `DRIFT` is `−0.000001`; not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`; `ε ≥ 0` fails closed; Eq. 5 of that contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; the extra process has `LAMBDA` 0 and is not an observed indicator; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; the contribution is not `E(y_t)`; the evolved-plus-contribution latent mean is not `E(y_t)`; after-t0 extra-process `TDPREDEFFECT` is `a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t` while `μ_t` uses `Δt`; Eq. 5 of that after-t0 contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)`; the first-occasion extra-process observed mean is not that observed mean when `u ≠ t0`; `e^{a(t−u)} m x` is a Dirac on the original process, not this `DRIFT` drive; §7.2 `asymTIPREDEFFECT` is `-B z / a` for `a < 0` (`-B z / a` is not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; §7.2 `addedTIPREDVAR` is `(B / a)² v`, not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`; Table 2 `asymCINT` is `-κ / a` for `a < 0` and is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; p. 16 stationary `T0MEANS` is `-κ / a + −B z / a` and is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean; Eq. 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`; stationary `T0VAR` is `trait + −q / (2 a) + (B / a)² v` (not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`); lagged stationary `T0VAR` is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (trait and `addedTIPREDVAR` do not decay; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map; Eq. 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`; `Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance); later-occasion stationary `T0VAR` is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt`; `Q_Δt` is not that later map; Eq. 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`; lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not `Var(y_t)`; the later-occasion latent variance is not `Var(y_t)`); predetermined later-occasion `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_t)`; the predetermined later-occasion latent variance is not `Var(y_t)`; stationary later observed variance is not that observed variance when `p_0` is free); predetermined lagged `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map; Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`; `MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free; the predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`; free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map; Eq. 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the §7.1 trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; `TRAITVAR` is not the standardisation variance; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`; `MANIFESTMEANSstd` is `τ / √θ` after strictly positive `MANIFESTVAR`; unstandardised `MANIFESTMEANS` is not `MANIFESTMEANSstd`; `MANIFESTVARstd` is not `MANIFESTMEANSstd`; `τ / √(λ² Var(η) + θ)` is not `MANIFESTMEANSstd`;))))), irregular already-centered residual lag, Rubin `T` on OLS loadings, and strong-gated latent means (two-observation residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016) | | `psychometric_core` | posterior-aware structural input gates, CWC within/between OLS plus the contextual effect, event-time log-rate, unequal-interval discrete-lag remapping, constant-predictor discrete effect, time-varying-predictor discrete effect (Eq. 14), exact scalar discrete process noise (Driver et al., 2017, Eq. 3), lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; `asymDIFFUSION`), trait-plus-state variance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise), observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5; Table 2 `MANIFESTVAR` is `Θ`, not `Var(y)`; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; `Θ` does not enter lagged observed covariance; observed-indicator mean is `τ + λ μ`; `MANIFESTMEANS` is not `E(y)`; `CINT` is not `MANIFESTMEANS`; discrete latent mean is `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ`; `T0MEANS` is not `μ_t`; `CINT` is not the discrete increment; evolved observed mean is `τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`; contemporaneous `TDPREDEFFECT` impulse is `m x`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that contemporaneous impulse is `τ + λ(μ_t + m x)`, and `τ + λ μ_t` is not that observed mean; time-independent `TIPREDEFFECT` increment is `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, not `M x`, not Voelkle Eq. 14, and not the coefficient `B`; Eq. 5 of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`; within-interval `TDPREDEFFECT` carry is `e^{A(t−u)} M x` for `t0 < u < t`, not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that carried observed mean when `u ≠ t`; first-occasion `T0TIPREDEFFECT` shift is `t0_b z` and Eq. 3 first-summand carry is `e^{A Δt} t0_b z` (`T0TIPREDEFFECT` is not `TIPREDEFFECT` `B`; `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`; `e^{A Δt} t0_b z` is not `t0_b z`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_b z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean), first-occasion `T0TDPREDEFFECT` shift is `t0_m x0` and Eq. 3 first-summand carry is `e^{A Δt} t0_m x0` (`T0TDPREDEFFECT` is not `TDPREDEFFECT` `M`; `t0_m x0` is not `M x`; `e^{A Δt} t0_m x0` is not `t0_m x0`; `e^{A Δt} t0_m x0` is not `e^{A(t−u)} M x` for `t0 < u < t`; `t0_m x0` is not `t0_b z`; an impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`; Eq. 5 of that carry is `τ + λ(μ_t + e^{a Δt} t0_m x0)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean; `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean; §7.2 level-change `CINT` is `κ = −a m x` with `a < 0` so `−κ / a = m x` (`−a m x` is not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`, and not the extra near-zero-drift latent process also named in §7.2; Eq. 3 of that setting is `(1 − e^{a Δt}) m x`, which is not `m x`, not `κ`, and not `TIPREDEFFECT`; §7.2 extra-process contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (`ε = a` is `a_{ηξ} x Δt e^{a Δt}`; identification `TDPREDEFFECT` on the extra process is 1; printed extra `DRIFT` is `−0.000001`; not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`; `ε ≥ 0` fails closed; Eq. 5 of that contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; the extra process has `LAMBDA` 0 and is not an observed indicator; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; the contribution is not `E(y_t)`; the evolved-plus-contribution latent mean is not `E(y_t)`; after-t0 extra-process `TDPREDEFFECT` is `a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t` while `μ_t` uses `Δt`; Eq. 5 of that after-t0 contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)`; the first-occasion extra-process observed mean is not that observed mean when `u ≠ t0`; `e^{a(t−u)} m x` is a Dirac on the original process, not this `DRIFT` drive; §7.2 `asymTIPREDEFFECT` is `-B z / a` for `a < 0` (`-B z / a` is not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; §7.2 `addedTIPREDVAR` is `(B / a)² v`, not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`; Table 2 `asymCINT` is `-κ / a` for `a < 0` and is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; p. 16 stationary `T0MEANS` is `-κ / a + −B z / a` and is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean; Eq. 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`; stationary `T0VAR` is `trait + −q / (2 a) + (B / a)² v` (not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`); lagged stationary `T0VAR` is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (trait and `addedTIPREDVAR` do not decay; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map; Eq. 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`; `Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance); later-occasion stationary `T0VAR` is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt`; `Q_Δt` is not that later map; Eq. 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`; lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not `Var(y_t)`; the later-occasion latent variance is not `Var(y_t)`); predetermined later-occasion `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_t)`; the predetermined later-occasion latent variance is not `Var(y_t)`; stationary later observed variance is not that observed variance when `p_0` is free); predetermined lagged `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map; Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`; `MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free; the predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`; free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map; Eq. 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the §7.1 trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; `TRAITVAR` is not the standardisation variance; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`;))))), irregular already-centered residual lag, Rubin `T` on OLS loadings, and strong-gated latent means (two-observation residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016) | diff --git a/CHANGELOG.md b/CHANGELOG.md index 3235eff3..96fe2919 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ## [Unreleased] +- Restored protected-main gate integrity after the consolidation merges: hourly-scheduler prompt-contract tests now assert the gap-baseline-derived task contract (Gap ID naming, no invented weights) instead of stale increment-specific tokens, the operator-gap register inventory matches the live 33-PR queue, `evidence_core::image_unit` non-image/empty-subtype refusals and `load_union_branch_totals` valid-record accumulation have exact coverage, and the README crate fence plus duplicate registry entries stay deduped. +- Branch-coverage diagnostics on the post-consolidation head exposed two uncovered outcomes in `evidence_core::image_unit` (`is_image_media_type_token` non-image prefix and empty-subtype refusals), one uncovered authored line (the strip-prefix refusal), and lost valid-record coverage for `load_union_branch_totals`; exact red-to-green cases now cover the non-image/empty-subtype data URIs and per-coordinate True/False accumulation. +- Repaired post-consolidation merge fallout that left protected `main` red: restored the lost `return True` in the `check_coverage.py` match-guard branch, removed the shadowed duplicate `load_union_branch_totals` and `_is_multiline_match_guard` definitions plus duplicate workspace-crate entries (`episode_membership`, `analysis_engine`) from the contract tuple and Cargo member arrays, split two union-fused four-tuples back into `(variant, message)` pairs in the `event_core` error table, repaired the fused `identity_recovery_rate` body in `episode_membership::window`, deduplicated the checked-arithmetic eligible-count block in `analysis_engine`, fixed four-argument `unit()` test call sites, rebalanced the README crate-list fence around all 54 unique crates, and deduplicated the `location_membership`/`validation_core`/`tepp_api` architecture-table rows. Also documents private `PLAUSIBLE_IMAGE_MEDIA_TYPES` so `cargo doc -D warnings` passes. +- Branch coverage JSON now unique-folds `files[].branches` True/False counts across instantiations. Nightly totals on #49 head `1e3e2eb` reported `event_time.rs` 505/506 while every unique site had both arms taken (253 sites × 2 instantiations). Summary-only reports without branch arrays still fail closed on totals. The 100% contract is unique production arms, matching the LCOV authored-line gate. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` maps overflowing `expm1(a Δt)` / `expm1(2 a Δt)` in `recover_discrete_constant_predictor_effect` and `recover_discrete_process_noise` through the log-space rewrite without a redundant `if !argument.is_finite()` after overflow. Local crate llvm-cov on #49 head `559e7b399473ee90ba3234677dd9ef7f05f7fd2e` was 509/510: the same LLVM `exp`/`expm1` finite-argument proof as L768/L5040. Existing rewrite (`a = 800` / `a = 400`) and overflow (`a = 1e308`) tests remain the contract. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` maps overflowing `e^{a Δt}` / `e^{a(t−u)}` through the log-space rewrite without redundant `if !argument.is_finite()` after `exp` overflow on lagged covariance, T0 TI/TD carry, and impulse carry. Nightly branch coverage on #49 head `7e669babcc54408dd8407bbac56be0f304fa99e5` was 1713/1714: LLVM counted `event_time.rs` L5040 True and treated the finite-argument overflow False as uncovered after proving `exp` of a finite argument is finite, which binary64 overflow falsifies. `fit_scalar_log_rate` now also skips a zero earlier residual and a negative lag while still recovering from a valid pair. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` maps overflowing `e^{2 a Δt}` in `recover_discrete_latent_variance` through the log-space rewrite `(ln p + 2 a Δt).exp()` without a redundant `if !2 a Δt.is_finite()` after `exp` overflow. Nightly branch coverage on #49 head `e301e9706c0bd671ccad533063fb624cc568d0b3` was 1715/1716: LLVM counted `event_time.rs` L768 True and treated the finite-argument overflow False as uncovered after proving `exp` of a finite argument is finite, which binary64 overflow falsifies. Existing rewrite (`p = 1e-308`, `a = 400`, `Δt = 1`) and overflow (`a = 1e308`) tests remain the contract. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` executes the later `|| !log_rate.is_finite()` operand on `recover_discrete_time_independent_predictor_effect` from both the lib tests and the multilevel integration crate. Nightly branch coverage on #49 head `90b08bbe82cbe7776365a6c04df38857dfe5e53c` was 1714/1716: both True arms at `event_time.rs` L2480 were unhit because fail-closed tests supplied a non-finite `TIPREDEFFECT` or predictor before `a`. Direct `a = NaN` now takes those arms. `LagClock::as_str` is called through `black_box` so the outlined instantiation is not const-folded away. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` evaluates the Driver, Oud, and Voelkle (2017, §7.2) extra-process lag as `e^{ε Δt}` even when `ε Δt` underflows to `0` (`exp(0) = 1`). Nightly branch coverage on #49 head `22b8e68813ad59a9a91689bacfa4cf033dfad158` was 1718/1720: LLVM deleted `if extra_argument == 0.0` / `original_argument == 0.0` True after proving `ε < 0` and `Δt > 0` imply a nonzero product, which binary64 underflow falsifies. The public map now uses `exp` directly; `original_log_rate == 0` remains the Brownian `e^{0} = 1` path. Recovery tests assert the §7.2 identity `a_{ηξ} x e^{a Δt}(e^{(ε−a)Δt} − 1)/(ε − a)` on `(-min_subnormal) * 1e-320`. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. +- `psychometric_core` recovers the Driver, Oud, and Voelkle (2017, p. 16 `MANIFESTMEANSstd`; Table 2, p. 12; footnote 4; Eq. 5, p. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-25T05:04Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) scalar standardised manifest mean. Page 16 prints standardised matrices with the suffix `std` when appropriate. Footnote 4 standardises using only the relevant variance, not the total. Table 2 names `MANIFESTMEANS` `τ` the `n.manifest × 1` matrix of manifest means. Table 2 names `MANIFESTVAR` `Θ` the residual covariance of the indicators. The relevant variance for that named measurement intercept is residual `MANIFESTVAR` `θ`, not total observed `Var(y) = λ² Var(η) + θ`, matching `MANIFESTVARstd`. The 2017-era `summary.ctsemFit.R` forms unstandardised `MANIFESTMEANS` as `mxEval(MANIFESTMEANS, mxobj, compute=TRUE)`. That source does not form a `MANIFESTMEANSstd` matrix; the scalar map here is the footnote 4 standardisation of that named intercept: `τ / √θ`. Form strictly positive `θ` first, then divide `τ` by `√θ`. A zero mean is exactly zero. Unstandardised `MANIFESTMEANS` is defined for a zero residual; standardised `MANIFESTMEANS` is not. Zero `θ` has no positive SD and fails closed. Manifest means are an event-time measurement quantity, so a non-event clock fails closed. `MANIFESTMEANS` does not require stable `a < 0`. `MANIFESTVARstd` `θ / θ = 1` recovers the same number when `τ = √θ` and remains a distinct named quantity. `τ / √(λ² Var(η) + θ)` uses total observed variance and is not this residual map. The 2017-era source assigns `dimnames(MANIFESTMEANS)` to `list(manifestNames, manifestNames)` on an `n.manifest × 1` matrix; that assignment is a source bug and is not this map. `T0MEANSstd` `μ_0 / √p_0` recovers the same number when `τ = μ_0` and `θ = p_0` and remains a distinct named quantity. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. Meredith (1993) remains unread (Unpaywall 2026-08-25T05:04Z: `is_oa: false`, 0 locations; title *Measurement Invariance, Factor Analysis and Factorial Invariance*). Mislevy (1991, *Psychometrika, 56*, 177–196) remains unread (Unpaywall 2026-08-25T05:04Z: `is_oa: false`, 0 locations; title *Randomization-Based Inference about Latent Variables from Complex Samples*). - `network_analysis` posterior edge estimation now carries exact two-sided Fisher z-transform p-values against `rho = 0` (erfc evaluated by an all-positive confluent series plus the Laplace continued fraction, locked to libm reference values at 1e-13 relative tolerance), percentile-bootstrap credible intervals and selection fractions over posterior draws, Benjamini–Hochberg step-up admission on those exact p-values instead of the complement of a thresholded fraction, an explicit fail-closed `edge_drop_probability` parameter for consensus co-assignment resampling (replacing a hardcoded 0.1), and honest per-replicate stability admission; the greedy partition helper is renamed to state that it makes no modularity-optimization claim. APA 7 entries added: Benjamini & Hochberg (1995), Efron (1979), Fisher (1921), Hennig (2007), Monti (2003). - Restored protected-main gate integrity after the consolidation merges: hourly-scheduler prompt-contract tests now assert the gap-baseline-derived task contract (Gap ID naming, no invented weights) instead of stale increment-specific tokens, the operator-gap register inventory matches the live 33-PR queue, `evidence_core::image_unit` non-image/empty-subtype refusals and `load_union_branch_totals` valid-record accumulation have exact coverage, and the README crate fence plus duplicate registry entries stay deduped. - Branch-coverage diagnostics on the post-consolidation head exposed two uncovered outcomes in `evidence_core::image_unit` (`is_image_media_type_token` non-image prefix and empty-subtype refusals), one uncovered authored line (the strip-prefix refusal), and lost valid-record coverage for `load_union_branch_totals`; exact red-to-green cases now cover the non-image/empty-subtype data URIs and per-coordinate True/False accumulation. @@ -103,6 +113,7 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang - `psychometric_core` posterior-aware structural input gates: construct classification, refusal of raw-proportion Pearson/OLS, explicit ALR-versus-ILR geometry boundaries, CPU `f64` OLS recovery, posterior-draw loading point-estimate averaging without Rubin uncertainty claims, invariance-gated latent-mean comparison, and causal-heuristic refusal (ADR 0005 first production slice; no new migration). ### Added +- `model_selection` fitted candidate-`K` scoring: each candidate is fitted with the CPU `f64` TRSL-TM reference, scored from the actual in-sample mixture log-likelihood and Schwarz's (1978) `ℓ − (p ln N)/2` penalty, then passed through the existing Pareto gate. A typed non-convergence, non-finite, or invalid-input failure is a failed candidate, not a fabricated diagnostic. LLM-vote-only `K` remains non-authoritative. TF-IDF, BM25, stopword-deletion, and LLM labels are refused as inferential coordinates. Known two-topic counts select `K=2` over `K=3` with selected-`K` RMSE `0` across seed replications. This is not GPU execution, full Bayesian sampling, or topic birth/split/merge (ADR 0012; issue #167 remaining slice). - `relation_absence` identity gate: unobserved relation pairs cannot become evidence of no relationship; recovered observed/inferred/unobserved statuses match known truth at a higher computed rate than collapsing every status to observed (ADR 0003). - `orchestrator_live` loopback HTTP/1.1 listener: `POST /v1/interpretation-runs` binds loopback only, replays matching idempotency keys, and refuses non-loopback binds, table-access hosts, review/Copilot/GitHub credentials, and scientific-authority promotion. Accepted output is always hypothetical. Not TLS termination or model execution (ADR 0010; ADR 0011). - `role_contradiction` identity gate: customer and competitor cannot occupy the same group; recovered commercial-role labels match known truth at a higher computed rate than collapsing every role to customer (ADR 0003). diff --git a/CLAUDE.md b/CLAUDE.md index 18a067b6..55c2c776 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,7 +15,7 @@ Read and follow `AGENTS.md` before changing this repository. The repository-wide - Do not remove repeated report language with global stopword lists or use TF-IDF/BM25 as inferential weights. Model template, section, copied-text, style, modality, and corpus-background sources explicitly. - Do not treat raw topic proportions as ordinary Euclidean indicators. Use logistic-normal coordinates or valid log-ratio coordinates and propagate posterior uncertainty into ESEM/DSEM. - Do not treat metric/weak invariance as a latent-mean license. Strong (equal loading and intercept) or strict is required; `#84` `metric` licenses shared metric meaning only. Putnick and Bornstein (2016, PMC5145197 opened 2026-08-19T22:15Z) require scalar invariance before latent-mean comparison; residual invariance is not a prerequisite. Two-observation series have no residual degrees of freedom (`ordinary_least_squares_fit` returns residual variance `0`) and cap at strong/scalar; they still license means. This is two-group OLS, not MGCFA. Meredith (1993) names remain unread labels. -- Do not use the difference quotient as a continuous-time rate. The scalar map is `a = ln(φ) / Δt` on event time. Discrete lags from unequal event intervals are not one coefficient; remap them through that log-rate. Binary64 `exp(a Δt) = 0` is not a discrete lag. A constant predictor's discrete effect is Voelkle et al. (2012, Eq. 12), evaluated as `a_yx (expm1(z) / a_xx)` with `z = a_xx Δt` so a finite result is not lost when `z` overflows to `-∞` or when `a_yx Δt` overflows. When `expm1(z)` overflows at a finite `z`, rewrite in log space; a zero continuous effect is exactly zero; an overflowing `a_yx/a_xx` rewrite term fails closed. The first-order product is the underflow limit of that equation, not the general constant-predictor discrete effect. A time-varying predictor whose sampling interval equals its constancy interval uses Voelkle et al. (2012, Eq. 14): `b* = a_yx Δt`. Unmatched intervals fail closed (Oud & Jansen, 2000, unread). Discrete process noise is Driver et al. (2017, Eq. 3): `Q_Δt = 0.5 q (expm1(z) / a)` with `z = 2 (a Δt)` and `q = G G⊤ ≥ 0`; do not form `2 a` first; `a = 0` and `z → 0` recover `q Δt`; a zero diffusion is exactly zero; an overflowing rewrite scale `0.5 q / a` fails closed; this is not a Kalman filter. `Q_Δt` is `cov(η_t | η_{t-1})`, not `Var(η_t)`. The lagged covariance is `exp(a Δt) p` and the unconditional variance is `exp(2 a Δt) p + Q_Δt` (Driver et al., 2017, Eq. 3–4, pp. 4–5; JSS has no numbered §2.2). A zero diffusion whose `2 (a Δt)` overflows to `+∞` is not a finite `Var(η_t)`. The stationary within-subject variance is the `Δt → ∞` limit of Eq. 4: `-q / (2 a)` for stable `a < 0` (JSS p. 16 `asymDIFFUSION`; §4.3). When `2 a` is finite, form `q / -(2 a)` so `q / a` overflow does not lose a finite result (`q = MAX`, `a = -0.75` → `MAX / 1.5`). When `2 a` overflows, form `(q / a) * -0.5`. Do not form `0.5 q` first (`q = from_bits(1)` underflows). `a ≥ 0` has no finite stationary variance. Finite-interval `Q_Δt` is not that limit. Trait-plus-state variance is `trait + state` and lagged covariance is `trait + exp(a Δt) p` (Driver et al., 2017, §4.3, p. 9). Trait variance is not process noise and not `asymDIFFUSION`. Evolving the summed variance as if it were all state is not that map. This is not RI-CLPM. Observed-indicator variance is `λ² Var(η) + θ` when `MANIFESTTRAITVAR` is zero and `λ² Var(η) + θ + ψ` otherwise (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12). Lagged observed covariance is `λ² cov(η_t, η_{t-1}) + ψ`; `MANIFESTVAR` does not enter. Observed-indicator mean is `τ + λ μ` (Driver et al., 2017, Eq. 5; Table 2, p. 12). `MANIFESTMEANS` is `τ`, not `E(y)`. `E(η)` is not `E(y)`. `CINT` is not `MANIFESTMEANS`. `T0MEANS` is not `E(y)`. The discrete latent mean is `μ_t = exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ` (Driver et al., 2017, Eq. 3, p. 4; Table 2, p. 12). `T0MEANS` is not `μ_t`. `CINT` is not that discrete increment. A zero drift is `κ Δt`. Underflow of `exp(a Δt)` to `+0` drops the carried `T0MEANS` and keeps `−κ / a`. The evolved observed mean is `τ + λ μ_t` (Driver et al., 2017, Eq. 5 of that Eq. 3 map). The first-occasion map `τ + λ μ_0` is not `E(y_t)`. `μ_t` is not `E(y_t)`. The contemporaneous time-dependent predictor impulse is `m x` (Driver et al., 2017, Eq. 3 fourth summand; Table 2 `TDPREDEFFECT` is `M`). Form `μ_t` first, then add `m x`. `TDPREDEFFECT` is not `CINT`. `M x` is not `A^{-1}[e^{A Δt} − I] B z` and is not Voelkle et al. (2012, Eq. 14). The §7.2 level-change form is not that impulse. The observed mean of that contemporaneous impulse is `τ + λ(μ_t + m x)` (Driver et al., 2017, Eq. 5 of the Eq. 3 fourth-summand composition). The evolved map `τ + λ μ_t` is not that observed mean. The carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`. The evolved-plus-impulse latent mean is not `E(y_t)`. The time-independent predictor increment is `A^{-1}[e^{A Δt} − I] B z` (Driver et al., 2017, Eq. 3 second summand; Table 2 `TIPREDEFFECT` is `B`). Form `B z` first, then the discrete intercept map. A zero drift is `B z Δt`. `TIPREDEFFECT` is `B`, not that discrete increment. `A^{-1}[e^{A Δt} − I] B z` is not `CINT`, not `M x`, and not Voelkle et al. (2012, Eq. 14). The observed mean of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` (Driver et al., 2017, Eq. 5 of the Eq. 3 printed addend after the `T0MEANS` carry and the `CINT` increment). The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`. The evolved-plus-increment latent mean is not `E(y_t)`. The within-interval time-dependent impulse carry is `e^{A(t−u)} M x` for `t0 < u < t` (Driver et al., 2017, Eq. 1–2 Green-function integral of Eq. 2; §7.2 dissipation). Form `m x` first, then `e^{a(t−u)} m x`. A zero drift is `m x` with no dissipation. Underflow of `e^{a(t−u)}` to `+0` is vanishing dissipation and is kept. `e^{A(t−u)} M x` is not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle et al. (2012, Eq. 14). An impulse at `u = t` is the contemporaneous map. An impulse at `u ≤ t0` is already in `η(t0)`. The observed mean of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)` (Driver et al., 2017, Eq. 5 of the Eq. 1–2 carried latent mean). The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean when `u ≠ t`. `MANIFESTMEANS` is not `E(y_t)`. The carried latent mean is not `E(y_t)`. The first-occasion time-independent predictor shift is `t0_b z` (Driver et al., 2017, Table 3 `T0TIPREDEFFECT`; Eq. 3 first summand). Form `t0_b z` first, then `e^{a Δt} t0_b z`. Form `μ_t` first, then add that carry. A zero drift is `t0_b z`. Underflow of `e^{a Δt}` to `+0` is a vanishing carry of the first-occasion shift and is kept. `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. `e^{A Δt} t0_b z` is not `t0_b z`. `T0TIPREDEFFECT` is the coefficient, not the shift. The observed mean of that first-occasion carry is `τ + λ(μ_t + e^{a Δt} t0_b z)` (Driver et al., 2017, Eq. 5 of the Table 3 / Eq. 3 first-summand composition). The evolved map `τ + λ μ_t` is not that observed mean. The process-increment map `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t0`. The evolved-plus-carry latent mean is not `E(y_t)`. The first-occasion time-dependent predictor shift is `t0_m x0` (Driver et al., 2017, Table 3 `T0TDPREDEFFECT`; Eq. 3 first summand; JSS PDF re-opened 2026-08-20T19:10Z). Form `t0_m x0` first, then `e^{a Δt} t0_m x0`. Form `μ_t` first, then add that carry. A zero drift is `t0_m x0`. Underflow of `e^{a Δt}` to `+0` is a vanishing carry of the first-occasion shift and is kept. `t0_m x0` is not `M x`, not `e^{A(t−u)} M x` for `t0 < u < t`, not `t0_b z`, not `A^{-1}[e^{A Δt} − I] B z`, and not `CINT`. `e^{A Δt} t0_m x0` is not `t0_m x0`. `T0TDPREDEFFECT` is the coefficient, not the shift. An impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`. The observed mean of that first-occasion TD carry is `τ + λ(μ_t + e^{a Δt} t0_m x0)` (Driver et al., 2017, Eq. 5 of the Table 3 / Eq. 3 first-summand TD composition; JSS PDF re-opened 2026-08-20T19:07Z). The evolved map `τ + λ μ_t` is not that observed mean. The process-increment map `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t0`. The first-occasion TI map `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean. The evolved-plus-carry latent mean is not `E(y_t)`. The lasting level-change `CINT` is `κ = −a m x` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF re-opened 2026-08-20T19:45Z). Form `m x` first, then multiply by `−a`. Stable `a < 0` is required so `−κ / a = m x` is an equilibrium offset. `a ≥ 0` cannot hold a new process mean. `−a m x` is not the dissipating Dirac `m x`, not a free `CINT`, and not `A^{-1}[e^{A Δt} − I] B z`. The extra near-zero-drift latent process also named in §7.2 is a different specification and is not this `CINT` setting. Equation 3 maps that intercept as `(1 − e^{a Δt}) m x` (JSS PDF re-opened 2026-08-20T19:50Z). Form the level-change `CINT` first, then the discrete intercept map. Underflow of `e^{a Δt}` to `+0` keeps `m x`. `(1 − e^{a Δt}) m x` is not `m x`, not `κ`, and not `A^{-1}[e^{A Δt} − I] B z`. The printed §7.2 lasting level change is an extra near-zero-drift latent process (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-20T23:10Z). `T0MEANS`, `CINT`, `T0VAR`, `DIFFUSION`, and `TRAITVAR` of that process are fixed to 0; `TDPREDEFFECT` on it is fixed to 1; its `DRIFT` diagonal is very close to 0 (printed example `−0.000001`; precisely 0 causes computational problems); the original process is driven by the `DRIFT` coupling `a_{ηξ}`. After a unit identification impulse the scalar contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (`ε = a` is `a_{ηξ} x Δt e^{a Δt}`). Form `a_{ηξ} x` first. A zero coupling or zero predictor is exactly zero. `ε ≥ 0` fails closed. That contribution is not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`. The observed mean of that extra-process contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` (Driver et al., 2017, Eq. 5 of that §7.2 contribution; JSS PDF re-opened 2026-08-21T06:12Z). The extra process has `LAMBDA` 0 and is not an observed indicator. Original indicators load on the original process after the `DRIFT` coupling. The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The contribution is not `E(y_t)`. The evolved-plus-contribution latent mean is not `E(y_t)`. `T0TDPREDEFFECT` on the extra process begins at `t = 0` and uses `Δt = t − t0` for both the original-process evolution and the extra drive. `TDPREDEFFECT` after `t0` uses `t − u` with `t0 < u < t` for the extra drive while `μ_t` still uses `Δt`. The observed mean of that after-t0 extra-process contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a))` (Driver et al., 2017, Eq. 5 of that §7.2 after-t0 contribution; JSS PDF re-opened 2026-08-21T06:32Z). The first-occasion extra-process observed mean is not that observed mean when `u ≠ t0`. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is a Dirac on the original process and is not that `DRIFT` drive. An impulse at `u = t0` or `u = t` is not interior. The asymptotic time-independent predictor effect is `-B z / a` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF opened 2026-08-21T13:08Z). Form `B z` first, then divide by `-a`. Stable `a < 0` is required. `a ≥ 0` cannot hold a finite process-mean change. `-B z / a` is not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. The asymptotic time-independent predictor variance is `(B / a)² v` (Driver et al., 2017, §7.2, pp. 20–21 `addedTIPREDVAR`). Form the unit asymptotic effect first, then square, then multiply by `v`. `(B / a)² v` is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`. The asymptotic continuous intercept is `-κ / a` (Driver et al., 2017, Table 2, p. 12 `asymCINT`; Eq. 3 as `Δt → ∞`; JSS PDF opened 2026-08-21T16:13Z). Form `κ` first, then divide by `-a`. Stable `a < 0` is required. `-κ / a` is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`. The p. 16 stationary `T0MEANS` constraint is `-κ / a + −B z / a`. Form the intercept contribution first, then include the TI extra effect, then add. That constrained first-occasion mean is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean. Equation 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)` (Driver et al., 2017, §4.3, pp. 9–10; Eq. 5, p. 5; JSS PDF re-opened 2026-08-21T20:07Z). Form the stationary latent mean first, then `τ + λ` of that mean. `τ + λ μ_0` for free `T0MEANS` is not that composition. `τ + λ(−κ / a)` is not that composition when `B z ≠ 0`. `τ + λ μ_t` is not that composition. `MANIFESTMEANS` is not `E(y_0)`. The constrained latent mean is not `E(y_0)`. The p. 16 constrained first-occasion variance `trait + −q / (2 a) + (B / a)² v` is not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`). The lagged covariance of that constrained process is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T19:13Z). Trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Contemporaneous `T0VAR` is not that lagged map. Decaying the constrained total as if it were all state is not that lagged map. Equation 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`. `Θ` does not enter. Contemporaneous `Var(y_0)` is not that lagged observed covariance. The lagged latent covariance is not that observed covariance. The later-occasion variance of that constrained process is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T23:12Z). Trait and `addedTIPREDVAR` do not enter `Q_Δt`. Under stationarity that composition equals contemporaneous `T0VAR`. Evolving the constrained total as if it were all state is not that later map. The lagged covariance omits `Q_Δt` and is not that later map. `Q_Δt` is not that later map. Equation 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`. The lagged observed covariance omits `Q_Δt` and `θ`. `MANIFESTVAR` is not `Var(y_t)`. The later-occasion latent variance is not `Var(y_t)`. The later-occasion variance of §4.3 predetermined `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T05:12Z). Trait and `addedTIPREDVAR` do not enter `Q_Δt`. Free `T0VAR` `p_0` is not that later map. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. Stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map. As `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not `Var(y_t)`. The predetermined later-occasion latent variance is not `Var(y_t)`. Stationary later observed variance is not that observed variance when `p_0` is free. The lagged covariance of §4.3 predetermined `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T09:04Z). Trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Free `T0VAR` `p_0` is not that lagged map. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. Stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map. Later-occasion variance includes `Q_Δt` and is not that lagged map. As `Δt → ∞` with stable `a < 0` the state term vanishes. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. Equation 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`. `MANIFESTVAR` does not enter. The predetermined lagged latent covariance is not that observed covariance. Predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance. Stationary lagged observed covariance is not that observed covariance when `p_0` is free. The predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`. Free `p_0` is not that map. Stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free. Lagged covariance decays the state and is not that map. Later-occasion variance includes `Q_Δt` and is not that map. Equation 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not that first-occasion observed variance. The predetermined first-occasion latent variance is not that observed variance. Stationary first-occasion observed variance is not that observed variance when `p_0` is free. Predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance. Later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z). First-occasion lagged omits `e^{a s} Q_u`. Later-occasion variance does not lag. Stationary lagged uses `−q / (2 a)`. Decaying the later total is not that map. Equation 5 of that later-start lagged covariance is `λ²` of it plus `ψ`. Independent `ε_t` does not enter. First-occasion lagged observed omits `e^{a s} Q_u`. Predetermined later observed variance includes `Q_u` and `θ` and is not that later-start lagged observed covariance. Later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z). Later-occasion variance at `u` omits `Q_s`. Later-start lagged covariance omits `Q_s`. Stationary later uses `−q / (2 a)`. Evolving the later total as if it were all state is not that map. Ignoring `startoffset` omits `e^{2 a s} Q_u`. Equation 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`. `MANIFESTVAR` is not that observed variance. Page 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; footnote 4; §7.1; JSS PDF re-opened 2026-08-23T11:40Z). Unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`. The §7.1 trait-plus-state autocorrelation `(trait + e^{a Δt} p + added) / (trait + p + added)` uses `TRAITVAR` and is not `discreteDRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:06Z). Unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`. The continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`. `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z). Unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`. The discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`. `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z). Unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`. The discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`. `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z). Unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`. `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z). Unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`. The asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`. `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 / Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z). The affected variance is free first-occasion `T0VAR`, not `asymDIFFUSION`. Unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`. `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`. `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. 2017-era `addedT0TIPREDVAR` is `t0_b² v` after a first-occasion time-independent predictor (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z). Form `t0_b` first, then square, then multiply by `v`. A zero coefficient or zero predictor variance is exactly zero. Free `T0TIPREDEFFECT` does not require `a < 0`. `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map. `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance. Free `T0VAR` is not this extra TI variance. `TRAITVAR` is not this extra TI variance. Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z). Form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. `t0_b² v` is the latent extra, not the observed extra. `λ² p_0 + θ` is first-occasion observed variance, not this extra. `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra. `MANIFESTVAR` `θ` is not this extra. Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v` (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12; §7.2, pp. 20–21; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:23Z). Form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. Lasting asymptotic extra requires `a < 0`. `(B / a)² v` is the latent extra, not the observed extra. `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra. `λ² p + θ` is stationary observed variance, not this extra. `MANIFESTVAR` `θ` is not this extra. Page 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance. Unstandardised `M` is not `TDPREDEFFECTstd`. `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`. intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`. `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`. Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance. Unstandardised `t0_m` is not `T0TDPREDEFFECTstd`. `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`. `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`. `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`. Free `T0VAR` does not require `a < 0`. Page 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; the default ridge is 0). Unstandardised `T0VAR` is not `T0VARstd`. `T0TDPREDEFFECTstd` is not `T0VARstd`. `addedT0TIPREDVAR` is not `T0VARstd`. Page 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend). Unstandardised `TRAITVAR` is not `TRAITVARstd`. `T0VARstd` is not `TRAITVARstd` even when both equal 1. `addedT0TIPREDVAR` is not `TRAITVARstd`. Page 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0). Unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`. `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1. `MANIFESTVAR` is not `MANIFESTTRAITVARstd`. Page 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug). Unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`. `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1. Equation 5 `Var(y)` is not `MANIFESTVARstd`. Page 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`). Unstandardised `TIPREDVAR` is not `TIPREDVARstd`. `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1. Section 7.2 `addedTIPREDVAR` is not `TIPREDVARstd`. Page 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`). Unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`. `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1. `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`. Page 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`. Unstandardised `discreteCINT` is not `discreteCINTstd`. `κ / √p` is not `discreteCINTstd`. `(-κ / a) / √p` is not `discreteCINTstd`. `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`. Unstandardised `asymCINT` is not `asymCINTstd`. `κ / √p` is not `asymCINTstd`. `discreteCINTstd` is not `asymCINTstd`. `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`. Unstandardised `T0MEANS` is not `T0MEANSstd`. `T0VARstd` is not `T0MEANSstd`. `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`. Evolving from that stationary start with `CINT` and `TIPREDEFFECT` stays at the stationary mean. Equation 1 is the latent SDE, not the measurement model. Form `(λ p) λ` then add `θ`, then add `ψ`. `MANIFESTVAR` is `Θ`, not `Var(y)`. `MANIFESTTRAITVAR` is `Ψ_τ`, not `Θ`. `TRAITVAR` is latent and scaled by `λ²`. `Var(η)` is not `Var(y)`. +- Do not use the difference quotient as a continuous-time rate. The scalar map is `a = ln(φ) / Δt` on event time. Discrete lags from unequal event intervals are not one coefficient; remap them through that log-rate. Binary64 `exp(a Δt) = 0` is not a discrete lag. A constant predictor's discrete effect is Voelkle et al. (2012, Eq. 12), evaluated as `a_yx (expm1(z) / a_xx)` with `z = a_xx Δt` so a finite result is not lost when `z` overflows to `-∞` or when `a_yx Δt` overflows. When `expm1(z)` overflows at a finite `z`, rewrite in log space; a zero continuous effect is exactly zero; an overflowing `a_yx/a_xx` rewrite term fails closed. The first-order product is the underflow limit of that equation, not the general constant-predictor discrete effect. A time-varying predictor whose sampling interval equals its constancy interval uses Voelkle et al. (2012, Eq. 14): `b* = a_yx Δt`. Unmatched intervals fail closed (Oud & Jansen, 2000, unread). Discrete process noise is Driver et al. (2017, Eq. 3): `Q_Δt = 0.5 q (expm1(z) / a)` with `z = 2 (a Δt)` and `q = G G⊤ ≥ 0`; do not form `2 a` first; `a = 0` and `z → 0` recover `q Δt`; a zero diffusion is exactly zero; an overflowing rewrite scale `0.5 q / a` fails closed; this is not a Kalman filter. `Q_Δt` is `cov(η_t | η_{t-1})`, not `Var(η_t)`. The lagged covariance is `exp(a Δt) p` and the unconditional variance is `exp(2 a Δt) p + Q_Δt` (Driver et al., 2017, Eq. 3–4, pp. 4–5; JSS has no numbered §2.2). A zero diffusion whose `2 (a Δt)` overflows to `+∞` is not a finite `Var(η_t)`. The stationary within-subject variance is the `Δt → ∞` limit of Eq. 4: `-q / (2 a)` for stable `a < 0` (JSS p. 16 `asymDIFFUSION`; §4.3). When `2 a` is finite, form `q / -(2 a)` so `q / a` overflow does not lose a finite result (`q = MAX`, `a = -0.75` → `MAX / 1.5`). When `2 a` overflows, form `(q / a) * -0.5`. Do not form `0.5 q` first (`q = from_bits(1)` underflows). `a ≥ 0` has no finite stationary variance. Finite-interval `Q_Δt` is not that limit. Trait-plus-state variance is `trait + state` and lagged covariance is `trait + exp(a Δt) p` (Driver et al., 2017, §4.3, p. 9). Trait variance is not process noise and not `asymDIFFUSION`. Evolving the summed variance as if it were all state is not that map. This is not RI-CLPM. Observed-indicator variance is `λ² Var(η) + θ` when `MANIFESTTRAITVAR` is zero and `λ² Var(η) + θ + ψ` otherwise (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12). Lagged observed covariance is `λ² cov(η_t, η_{t-1}) + ψ`; `MANIFESTVAR` does not enter. Observed-indicator mean is `τ + λ μ` (Driver et al., 2017, Eq. 5; Table 2, p. 12). `MANIFESTMEANS` is `τ`, not `E(y)`. `E(η)` is not `E(y)`. `CINT` is not `MANIFESTMEANS`. `T0MEANS` is not `E(y)`. The discrete latent mean is `μ_t = exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ` (Driver et al., 2017, Eq. 3, p. 4; Table 2, p. 12). `T0MEANS` is not `μ_t`. `CINT` is not that discrete increment. A zero drift is `κ Δt`. Underflow of `exp(a Δt)` to `+0` drops the carried `T0MEANS` and keeps `−κ / a`. The evolved observed mean is `τ + λ μ_t` (Driver et al., 2017, Eq. 5 of that Eq. 3 map). The first-occasion map `τ + λ μ_0` is not `E(y_t)`. `μ_t` is not `E(y_t)`. The contemporaneous time-dependent predictor impulse is `m x` (Driver et al., 2017, Eq. 3 fourth summand; Table 2 `TDPREDEFFECT` is `M`). Form `μ_t` first, then add `m x`. `TDPREDEFFECT` is not `CINT`. `M x` is not `A^{-1}[e^{A Δt} − I] B z` and is not Voelkle et al. (2012, Eq. 14). The §7.2 level-change form is not that impulse. The observed mean of that contemporaneous impulse is `τ + λ(μ_t + m x)` (Driver et al., 2017, Eq. 5 of the Eq. 3 fourth-summand composition). The evolved map `τ + λ μ_t` is not that observed mean. The carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`. The evolved-plus-impulse latent mean is not `E(y_t)`. The time-independent predictor increment is `A^{-1}[e^{A Δt} − I] B z` (Driver et al., 2017, Eq. 3 second summand; Table 2 `TIPREDEFFECT` is `B`). Form `B z` first, then the discrete intercept map. A zero drift is `B z Δt`. `TIPREDEFFECT` is `B`, not that discrete increment. `A^{-1}[e^{A Δt} − I] B z` is not `CINT`, not `M x`, and not Voelkle et al. (2012, Eq. 14). The observed mean of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` (Driver et al., 2017, Eq. 5 of the Eq. 3 printed addend after the `T0MEANS` carry and the `CINT` increment). The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`. The evolved-plus-increment latent mean is not `E(y_t)`. The within-interval time-dependent impulse carry is `e^{A(t−u)} M x` for `t0 < u < t` (Driver et al., 2017, Eq. 1–2 Green-function integral of Eq. 2; §7.2 dissipation). Form `m x` first, then `e^{a(t−u)} m x`. A zero drift is `m x` with no dissipation. Underflow of `e^{a(t−u)}` to `+0` is vanishing dissipation and is kept. `e^{A(t−u)} M x` is not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle et al. (2012, Eq. 14). An impulse at `u = t` is the contemporaneous map. An impulse at `u ≤ t0` is already in `η(t0)`. The observed mean of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)` (Driver et al., 2017, Eq. 5 of the Eq. 1–2 carried latent mean). The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean when `u ≠ t`. `MANIFESTMEANS` is not `E(y_t)`. The carried latent mean is not `E(y_t)`. The first-occasion time-independent predictor shift is `t0_b z` (Driver et al., 2017, Table 3 `T0TIPREDEFFECT`; Eq. 3 first summand). Form `t0_b z` first, then `e^{a Δt} t0_b z`. Form `μ_t` first, then add that carry. A zero drift is `t0_b z`. Underflow of `e^{a Δt}` to `+0` is a vanishing carry of the first-occasion shift and is kept. `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. `e^{A Δt} t0_b z` is not `t0_b z`. `T0TIPREDEFFECT` is the coefficient, not the shift. The observed mean of that first-occasion carry is `τ + λ(μ_t + e^{a Δt} t0_b z)` (Driver et al., 2017, Eq. 5 of the Table 3 / Eq. 3 first-summand composition). The evolved map `τ + λ μ_t` is not that observed mean. The process-increment map `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t0`. The evolved-plus-carry latent mean is not `E(y_t)`. The first-occasion time-dependent predictor shift is `t0_m x0` (Driver et al., 2017, Table 3 `T0TDPREDEFFECT`; Eq. 3 first summand; JSS PDF re-opened 2026-08-20T19:10Z). Form `t0_m x0` first, then `e^{a Δt} t0_m x0`. Form `μ_t` first, then add that carry. A zero drift is `t0_m x0`. Underflow of `e^{a Δt}` to `+0` is a vanishing carry of the first-occasion shift and is kept. `t0_m x0` is not `M x`, not `e^{A(t−u)} M x` for `t0 < u < t`, not `t0_b z`, not `A^{-1}[e^{A Δt} − I] B z`, and not `CINT`. `e^{A Δt} t0_m x0` is not `t0_m x0`. `T0TDPREDEFFECT` is the coefficient, not the shift. An impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`. The observed mean of that first-occasion TD carry is `τ + λ(μ_t + e^{a Δt} t0_m x0)` (Driver et al., 2017, Eq. 5 of the Table 3 / Eq. 3 first-summand TD composition; JSS PDF re-opened 2026-08-20T19:07Z). The evolved map `τ + λ μ_t` is not that observed mean. The process-increment map `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t0`. The first-occasion TI map `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean. The evolved-plus-carry latent mean is not `E(y_t)`. The lasting level-change `CINT` is `κ = −a m x` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF re-opened 2026-08-20T19:45Z). Form `m x` first, then multiply by `−a`. Stable `a < 0` is required so `−κ / a = m x` is an equilibrium offset. `a ≥ 0` cannot hold a new process mean. `−a m x` is not the dissipating Dirac `m x`, not a free `CINT`, and not `A^{-1}[e^{A Δt} − I] B z`. The extra near-zero-drift latent process also named in §7.2 is a different specification and is not this `CINT` setting. Equation 3 maps that intercept as `(1 − e^{a Δt}) m x` (JSS PDF re-opened 2026-08-20T19:50Z). Form the level-change `CINT` first, then the discrete intercept map. Underflow of `e^{a Δt}` to `+0` keeps `m x`. `(1 − e^{a Δt}) m x` is not `m x`, not `κ`, and not `A^{-1}[e^{A Δt} − I] B z`. The printed §7.2 lasting level change is an extra near-zero-drift latent process (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-20T23:10Z). `T0MEANS`, `CINT`, `T0VAR`, `DIFFUSION`, and `TRAITVAR` of that process are fixed to 0; `TDPREDEFFECT` on it is fixed to 1; its `DRIFT` diagonal is very close to 0 (printed example `−0.000001`; precisely 0 causes computational problems); the original process is driven by the `DRIFT` coupling `a_{ηξ}`. After a unit identification impulse the scalar contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (`ε = a` is `a_{ηξ} x Δt e^{a Δt}`). Form `a_{ηξ} x` first. A zero coupling or zero predictor is exactly zero. `ε ≥ 0` fails closed. That contribution is not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`. The observed mean of that extra-process contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` (Driver et al., 2017, Eq. 5 of that §7.2 contribution; JSS PDF re-opened 2026-08-21T06:12Z). The extra process has `LAMBDA` 0 and is not an observed indicator. Original indicators load on the original process after the `DRIFT` coupling. The evolved map `τ + λ μ_t` is not that observed mean. The contemporaneous map `τ + λ(μ_t + m x)` is not that observed mean. The contribution is not `E(y_t)`. The evolved-plus-contribution latent mean is not `E(y_t)`. `T0TDPREDEFFECT` on the extra process begins at `t = 0` and uses `Δt = t − t0` for both the original-process evolution and the extra drive. `TDPREDEFFECT` after `t0` uses `t − u` with `t0 < u < t` for the extra drive while `μ_t` still uses `Δt`. The observed mean of that after-t0 extra-process contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a))` (Driver et al., 2017, Eq. 5 of that §7.2 after-t0 contribution; JSS PDF re-opened 2026-08-21T06:32Z). The first-occasion extra-process observed mean is not that observed mean when `u ≠ t0`. The impulse-carry map `τ + λ(μ_t + e^{a(t−u)} m x)` is a Dirac on the original process and is not that `DRIFT` drive. An impulse at `u = t0` or `u = t` is not interior. The asymptotic time-independent predictor effect is `-B z / a` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF opened 2026-08-21T13:08Z). Form `B z` first, then divide by `-a`. Stable `a < 0` is required. `a ≥ 0` cannot hold a finite process-mean change. `-B z / a` is not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. The asymptotic time-independent predictor variance is `(B / a)² v` (Driver et al., 2017, §7.2, pp. 20–21 `addedTIPREDVAR`). Form the unit asymptotic effect first, then square, then multiply by `v`. `(B / a)² v` is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`. The asymptotic continuous intercept is `-κ / a` (Driver et al., 2017, Table 2, p. 12 `asymCINT`; Eq. 3 as `Δt → ∞`; JSS PDF opened 2026-08-21T16:13Z). Form `κ` first, then divide by `-a`. Stable `a < 0` is required. `-κ / a` is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`. The p. 16 stationary `T0MEANS` constraint is `-κ / a + −B z / a`. Form the intercept contribution first, then include the TI extra effect, then add. That constrained first-occasion mean is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean. Equation 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)` (Driver et al., 2017, §4.3, pp. 9–10; Eq. 5, p. 5; JSS PDF re-opened 2026-08-21T20:07Z). Form the stationary latent mean first, then `τ + λ` of that mean. `τ + λ μ_0` for free `T0MEANS` is not that composition. `τ + λ(−κ / a)` is not that composition when `B z ≠ 0`. `τ + λ μ_t` is not that composition. `MANIFESTMEANS` is not `E(y_0)`. The constrained latent mean is not `E(y_0)`. The p. 16 constrained first-occasion variance `trait + −q / (2 a) + (B / a)² v` is not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`). The lagged covariance of that constrained process is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T19:13Z). Trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Contemporaneous `T0VAR` is not that lagged map. Decaying the constrained total as if it were all state is not that lagged map. Equation 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`. `Θ` does not enter. Contemporaneous `Var(y_0)` is not that lagged observed covariance. The lagged latent covariance is not that observed covariance. The later-occasion variance of that constrained process is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T23:12Z). Trait and `addedTIPREDVAR` do not enter `Q_Δt`. Under stationarity that composition equals contemporaneous `T0VAR`. Evolving the constrained total as if it were all state is not that later map. The lagged covariance omits `Q_Δt` and is not that later map. `Q_Δt` is not that later map. Equation 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`. The lagged observed covariance omits `Q_Δt` and `θ`. `MANIFESTVAR` is not `Var(y_t)`. The later-occasion latent variance is not `Var(y_t)`. The later-occasion variance of §4.3 predetermined `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T05:12Z). Trait and `addedTIPREDVAR` do not enter `Q_Δt`. Free `T0VAR` `p_0` is not that later map. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. Stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map. As `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not `Var(y_t)`. The predetermined later-occasion latent variance is not `Var(y_t)`. Stationary later observed variance is not that observed variance when `p_0` is free. The lagged covariance of §4.3 predetermined `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T09:04Z). Trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Free `T0VAR` `p_0` is not that lagged map. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. Stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map. Later-occasion variance includes `Q_Δt` and is not that lagged map. As `Δt → ∞` with stable `a < 0` the state term vanishes. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. Equation 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`. `MANIFESTVAR` does not enter. The predetermined lagged latent covariance is not that observed covariance. Predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance. Stationary lagged observed covariance is not that observed covariance when `p_0` is free. The predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`. Free `p_0` is not that map. Stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free. Lagged covariance decays the state and is not that map. Later-occasion variance includes `Q_Δt` and is not that map. Equation 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not that first-occasion observed variance. The predetermined first-occasion latent variance is not that observed variance. Stationary first-occasion observed variance is not that observed variance when `p_0` is free. Predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance. Later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z). First-occasion lagged omits `e^{a s} Q_u`. Later-occasion variance does not lag. Stationary lagged uses `−q / (2 a)`. Decaying the later total is not that map. Equation 5 of that later-start lagged covariance is `λ²` of it plus `ψ`. Independent `ε_t` does not enter. First-occasion lagged observed omits `e^{a s} Q_u`. Predetermined later observed variance includes `Q_u` and `θ` and is not that later-start lagged observed covariance. Later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z). Later-occasion variance at `u` omits `Q_s`. Later-start lagged covariance omits `Q_s`. Stationary later uses `−q / (2 a)`. Evolving the later total as if it were all state is not that map. Ignoring `startoffset` omits `e^{2 a s} Q_u`. Equation 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`. `MANIFESTVAR` is not that observed variance. Page 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; footnote 4; §7.1; JSS PDF re-opened 2026-08-23T11:40Z). Unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`. The §7.1 trait-plus-state autocorrelation `(trait + e^{a Δt} p + added) / (trait + p + added)` uses `TRAITVAR` and is not `discreteDRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:06Z). Unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`. The continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`. `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z). Unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`. The discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`. `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z). Unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`. The discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`. `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z). Unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`. `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z). Unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`. The asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`. `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 / Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z). The affected variance is free first-occasion `T0VAR`, not `asymDIFFUSION`. Unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`. `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`. `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. 2017-era `addedT0TIPREDVAR` is `t0_b² v` after a first-occasion time-independent predictor (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z). Form `t0_b` first, then square, then multiply by `v`. A zero coefficient or zero predictor variance is exactly zero. Free `T0TIPREDEFFECT` does not require `a < 0`. `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map. `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance. Free `T0VAR` is not this extra TI variance. `TRAITVAR` is not this extra TI variance. Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z). Form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. `t0_b² v` is the latent extra, not the observed extra. `λ² p_0 + θ` is first-occasion observed variance, not this extra. `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra. `MANIFESTVAR` `θ` is not this extra. Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v` (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12; §7.2, pp. 20–21; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:23Z). Form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. Lasting asymptotic extra requires `a < 0`. `(B / a)² v` is the latent extra, not the observed extra. `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra. `λ² p + θ` is stationary observed variance, not this extra. `MANIFESTVAR` `θ` is not this extra. Page 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance. Unstandardised `M` is not `TDPREDEFFECTstd`. `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`. intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`. `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`. Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance. Unstandardised `t0_m` is not `T0TDPREDEFFECTstd`. `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`. `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`. `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`. Free `T0VAR` does not require `a < 0`. Page 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; the default ridge is 0). Unstandardised `T0VAR` is not `T0VARstd`. `T0TDPREDEFFECTstd` is not `T0VARstd`. `addedT0TIPREDVAR` is not `T0VARstd`. Page 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend). Unstandardised `TRAITVAR` is not `TRAITVARstd`. `T0VARstd` is not `TRAITVARstd` even when both equal 1. `addedT0TIPREDVAR` is not `TRAITVARstd`. Page 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0). Unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`. `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1. `MANIFESTVAR` is not `MANIFESTTRAITVARstd`. Page 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug). Unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`. `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1. Equation 5 `Var(y)` is not `MANIFESTVARstd`. Page 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`). Unstandardised `TIPREDVAR` is not `TIPREDVARstd`. `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1. Section 7.2 `addedTIPREDVAR` is not `TIPREDVARstd`. Page 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`). Unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`. `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1. `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`. Page 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`. Unstandardised `discreteCINT` is not `discreteCINTstd`. `κ / √p` is not `discreteCINTstd`. `(-κ / a) / √p` is not `discreteCINTstd`. `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`. Unstandardised `asymCINT` is not `asymCINTstd`. `κ / √p` is not `asymCINTstd`. `discreteCINTstd` is not `asymCINTstd`. `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`. Unstandardised `T0MEANS` is not `T0MEANSstd`. `T0VARstd` is not `T0MEANSstd`. `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`. Page 16 `MANIFESTMEANSstd` is `τ / √θ` after strictly positive `MANIFESTVAR`. Unstandardised `MANIFESTMEANS` is not `MANIFESTMEANSstd`. `MANIFESTVARstd` is not `MANIFESTMEANSstd`. `τ / √(λ² Var(η) + θ)` is not `MANIFESTMEANSstd`. Evolving from that stationary start with `CINT` and `TIPREDEFFECT` stays at the stationary mean. Equation 1 is the latent SDE, not the measurement model. Form `(λ p) λ` then add `θ`, then add `ψ`. `MANIFESTVAR` is `Θ`, not `Var(y)`. `MANIFESTTRAITVAR` is `Ψ_τ`, not `Θ`. `TRAITVAR` is latent and scaled by `λ²`. `Var(η)` is not `Var(y)`. - Separate cluster means before within-unit lag. CWC plus an event-time lag is not DSEM. Subtracting the person-specific mean from a raw autoregressive series does not isolate the lagged within-person effect (Curran & Bauer, 2011, pp. 607–608); already-centered residuals with irregular event intervals use the exact scalar map. - Do not treat the CWC cluster-mean coefficient as the between-cluster effect. It is the contextual effect `between − within` (Enders & Tofighi, 2007, Table 2, pp. 124–127). - Never use future-available evidence in historical model fits. diff --git a/Cargo.lock b/Cargo.lock index b000f155..f031078a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -976,6 +976,14 @@ version = "0.1.0" [[package]] name = "model_selection" version = "0.1.0" +dependencies = [ + "corpus_split", + "membership_core", + "relation_graph", + "temporal_core", + "topic_measurement", + "uuid", +] [[package]] name = "network_analysis" diff --git a/crates/model_selection/Cargo.toml b/crates/model_selection/Cargo.toml index ae636952..f332f2fb 100644 --- a/crates/model_selection/Cargo.toml +++ b/crates/model_selection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "model_selection" -description = "Statistical and Pareto candidate-K gates that refuse LLM numerical authority." +description = "Fitted candidate-K scoring and Pareto gates that refuse LLM numerical authority." version.workspace = true edition.workspace = true rust-version.workspace = true @@ -13,5 +13,15 @@ keywords.workspace = true categories.workspace = true publish = false +[dependencies] +topic_measurement = { path = "../topic_measurement", version = "0.1.0" } + +[dev-dependencies] +corpus_split = { path = "../corpus_split", version = "0.1.0" } +membership_core = { path = "../membership_core", version = "0.1.0" } +relation_graph = { path = "../relation_graph", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.1.0" } +uuid.workspace = true + [lints] workspace = true diff --git a/crates/model_selection/src/error.rs b/crates/model_selection/src/error.rs index 9c34391e..46002a16 100644 --- a/crates/model_selection/src/error.rs +++ b/crates/model_selection/src/error.rs @@ -14,6 +14,10 @@ pub enum ModelSelectionError { EmptyCandidateSet, /// An LLM vote was asked to define the numerical optimum. LlmVoteIsNotStatisticalAuthority, + /// TF-IDF, BM25, stopword deletion, or LLM labels were offered as coordinates. + LexicalWeightForbidden, + /// Every fitted candidate failed to converge or produced a typed numeric failure. + NoSuccessfulFit, } impl fmt::Display for ModelSelectionError { @@ -23,6 +27,8 @@ impl fmt::Display for ModelSelectionError { Self::InvalidDiagnostic => "invalid model-selection diagnostic", Self::EmptyCandidateSet => "empty model-selection candidate set", Self::LlmVoteIsNotStatisticalAuthority => "llm vote is not statistical authority", + Self::LexicalWeightForbidden => "lexical inferential weights are forbidden", + Self::NoSuccessfulFit => "no fitted candidate produced a finite diagnostic", }; formatter.write_str(message) } @@ -53,6 +59,14 @@ mod tests { ModelSelectionError::LlmVoteIsNotStatisticalAuthority, "llm vote is not statistical authority", ), + ( + ModelSelectionError::LexicalWeightForbidden, + "lexical inferential weights are forbidden", + ), + ( + ModelSelectionError::NoSuccessfulFit, + "no fitted candidate produced a finite diagnostic", + ), ] { assert_eq!(error.to_string(), message); } diff --git a/crates/model_selection/src/fitted.rs b/crates/model_selection/src/fitted.rs new file mode 100644 index 00000000..59673a99 --- /dev/null +++ b/crates/model_selection/src/fitted.rs @@ -0,0 +1,425 @@ +//! Fit each candidate `K` and score it from the actual reference model. + +use std::collections::BTreeSet; + +use topic_measurement::{ + ReferenceTopicInput, ReferenceTopicModel, ReferenceTopicModelConfig, fit_reference_topic_model, + refuse_lexical_inferential_weight, +}; + +use crate::{ModelCandidate, ModelSelectionError, select_candidate_k}; + +/// ADR 0012 `σ²` prior variance. Identical to `topic_measurement` reference. +const DEFAULT_PRIOR_VARIANCE: f64 = 1.0; +/// ADR 0012 network penalty `λ`. Identical to `topic_measurement` reference. +const DEFAULT_RELATION_STRENGTH: f64 = 0.25; +/// ADR 0012 coefficient ridge `ρ`. Identical to `topic_measurement` reference. +const DEFAULT_RIDGE: f64 = 0.01; +/// Smoothed multinomial `β` floor. Identical to `topic_measurement` reference. +const DEFAULT_TOPIC_SMOOTHING: f64 = 0.05; +/// Bounded GEM step. Identical to `topic_measurement` reference. +const DEFAULT_STEP_SIZE: f64 = 0.2; + +/// Seeds, iteration budget, and candidate topic counts for fitted selection. +#[derive(Clone, Debug, PartialEq)] +pub struct FittedCandidateKConfig { + candidate_topic_counts: Vec, + seeds: Vec, + maximum_iterations: usize, + tolerance: f64, + prior_variance: f64, + relation_strength: f64, + ridge: f64, + topic_smoothing: f64, + step_size: f64, +} + +impl FittedCandidateKConfig { + /// Construct a fitted-selection configuration with ADR-owned defaults. + /// + /// # Errors + /// + /// Returns [`ModelSelectionError::EmptyCandidateSet`] when no candidate + /// `K` is supplied, [`ModelSelectionError::NonPositiveCandidateK`] when any + /// candidate is less than two, or + /// [`ModelSelectionError::InvalidDiagnostic`] when candidates are + /// duplicated or the seed/iteration/tolerance contract fails. + pub fn new( + candidate_topic_counts: Vec, + seeds: Vec, + maximum_iterations: usize, + tolerance: f64, + ) -> Result { + let value = Self { + candidate_topic_counts, + seeds, + maximum_iterations, + tolerance, + prior_variance: DEFAULT_PRIOR_VARIANCE, + relation_strength: DEFAULT_RELATION_STRENGTH, + ridge: DEFAULT_RIDGE, + topic_smoothing: DEFAULT_TOPIC_SMOOTHING, + step_size: DEFAULT_STEP_SIZE, + }; + value.validate()?; + Ok(value) + } + + /// Replace numerical hyperparameters while retaining candidate `K` and seeds. + /// + /// # Errors + /// + /// Returns [`ModelSelectionError::InvalidDiagnostic`] for any non-finite or + /// non-positive value, except `relation_strength` and `ridge`, which may be + /// exactly zero for a declared ablation. + pub fn with_hyperparameters( + mut self, + prior_variance: f64, + relation_strength: f64, + ridge: f64, + topic_smoothing: f64, + step_size: f64, + ) -> Result { + self.prior_variance = prior_variance; + self.relation_strength = relation_strength; + self.ridge = ridge; + self.topic_smoothing = topic_smoothing; + self.step_size = step_size; + self.validate()?; + Ok(self) + } + + /// Return the candidate topic counts in caller order. + #[must_use] + pub fn candidate_topic_counts(&self) -> &[u32] { + &self.candidate_topic_counts + } + + /// Return the estimator initialization seeds. + #[must_use] + pub fn seeds(&self) -> &[u64] { + &self.seeds + } + + /// Return the per-seed iteration budget. + #[must_use] + pub const fn maximum_iterations(&self) -> usize { + self.maximum_iterations + } + + /// Return the relative-objective convergence tolerance. + #[must_use] + pub const fn tolerance(&self) -> f64 { + self.tolerance + } + + fn validate(&self) -> Result<(), ModelSelectionError> { + if self.candidate_topic_counts.is_empty() { + return Err(ModelSelectionError::EmptyCandidateSet); + } + let mut seen = BTreeSet::new(); + for &candidate_k in &self.candidate_topic_counts { + if candidate_k < 2 { + return Err(ModelSelectionError::NonPositiveCandidateK); + } + if !seen.insert(candidate_k) { + return Err(ModelSelectionError::InvalidDiagnostic); + } + } + if self.seeds.is_empty() + || self.maximum_iterations < 2 + || !self.tolerance.is_finite() + || self.tolerance <= 0.0 + || !self.prior_variance.is_finite() + || self.prior_variance <= 0.0 + || !self.relation_strength.is_finite() + || self.relation_strength < 0.0 + || !self.ridge.is_finite() + || self.ridge < 0.0 + || !self.topic_smoothing.is_finite() + || self.topic_smoothing <= 0.0 + || !self.step_size.is_finite() + || self.step_size <= 0.0 + { + return Err(ModelSelectionError::InvalidDiagnostic); + } + Ok(()) + } +} + +/// Build a statistically supported candidate from one actual fitted model. +/// +/// The first diagnostic is Schwarz's (1978) large-sample maximizer +/// `ℓ − (p ln N)/2` from the fitted `θ` and `β`. Complexity is the free +/// parameter count `p`. A failed or non-finite diagnostic is returned as a +/// typed error; it is never replaced with a fabricated likelihood. +/// +/// # Errors +/// +/// Returns [`ModelSelectionError::NonPositiveCandidateK`] when `candidate_k` +/// is less than two, or [`ModelSelectionError::InvalidDiagnostic`] when the +/// fitted dimensions, likelihood, or parameter count are unusable. +pub fn statistical_candidate_from_fit( + input: &ReferenceTopicInput, + candidate_k: u32, + model: &ReferenceTopicModel, +) -> Result { + let log_likelihood = input + .in_sample_log_likelihood(model) + .map_err(|_| ModelSelectionError::InvalidDiagnostic)?; + let tokens = input + .token_count() + .map_err(|_| ModelSelectionError::InvalidDiagnostic)?; + let parameters = free_parameter_count(model)?; + let log_tokens = tokens.ln(); + if log_tokens < 0.0 { + return Err(ModelSelectionError::InvalidDiagnostic); + } + let penalty = parameters * log_tokens; + let score = log_likelihood - 0.5 * penalty; + ModelCandidate::statistical(candidate_k, score, parameters) +} + +/// Fit each candidate `K` and select the admissible statistical topic count. +/// +/// Each candidate is fitted with [`fit_reference_topic_model`]. A typed +/// `DidNotConverge`, `NonFiniteEstimate`, or `InvalidModelInput` is a failed +/// candidate, not a fabricated diagnostic. LLM-vote-only values may be +/// supplied as recommenders; they cannot win without a successful statistical +/// fit. TF-IDF, BM25, stopword-deletion, and LLM labels are refused as +/// inferential coordinates. +/// +/// This wiring does not claim GPU execution, full Bayesian sampling, or topic +/// birth/split/merge. +/// +/// # Errors +/// +/// Returns a typed model-selection failure when the method is lexical, the +/// configuration is invalid, every fit fails, or only LLM votes remain. +pub fn select_fitted_candidate_k( + input: &ReferenceTopicInput, + config: &FittedCandidateKConfig, + method_name: &str, + llm_votes: &[u32], +) -> Result { + refuse_nonstatistical_method(method_name)?; + let mut candidates = Vec::new(); + for &candidate_k in config.candidate_topic_counts() { + #[allow(clippy::cast_possible_truncation)] + let topic_count = candidate_k as usize; + let fit_config = ReferenceTopicModelConfig::new( + topic_count, + config.seeds().to_vec(), + config.maximum_iterations(), + config.tolerance(), + ) + .and_then(|value| { + value.with_hyperparameters( + config.prior_variance, + config.relation_strength, + config.ridge, + config.topic_smoothing, + config.step_size, + ) + }) + .map_err(|_| ModelSelectionError::InvalidDiagnostic)?; + if let Ok(model) = fit_reference_topic_model(input, &fit_config) { + candidates.push(statistical_candidate_from_fit(input, candidate_k, &model)?); + } + } + for &vote in llm_votes { + candidates.push(ModelCandidate::llm_vote_only(vote)?); + } + if candidates.is_empty() { + return Err(ModelSelectionError::NoSuccessfulFit); + } + select_candidate_k(&candidates) +} + +fn refuse_nonstatistical_method(method: &str) -> Result<(), ModelSelectionError> { + refuse_lexical_inferential_weight(method) + .map_err(|_| ModelSelectionError::LexicalWeightForbidden)?; + let folded: String = method + .chars() + .filter(char::is_ascii_alphanumeric) + .flat_map(char::to_lowercase) + .collect(); + if matches!( + folded.as_str(), + "stopword" + | "stopwords" + | "stopworddeletion" + | "llm" + | "llmlabel" + | "llmlabels" + | "llmvote" + | "llmvoteonly" + ) { + return Err(ModelSelectionError::LexicalWeightForbidden); + } + Ok(()) +} + +fn free_parameter_count(model: &ReferenceTopicModel) -> Result { + let topic_count = model.document_topic_proportions.first().map_or(0, Vec::len); + let vocabulary = model.topic_term_probabilities.first().map_or(0, Vec::len); + let documents = model.document_topic_proportions.len(); + let features = model.prevalence_coefficients.len(); + if topic_count < 2 + || vocabulary < 2 + || documents < 2 + || model.topic_term_probabilities.len() != topic_count + || model + .topic_term_probabilities + .iter() + .any(|row| row.len() != vocabulary) + || model + .document_topic_proportions + .iter() + .any(|row| row.len() != topic_count) + || model + .prevalence_coefficients + .iter() + .any(|row| row.len() != topic_count - 1) + { + return Err(ModelSelectionError::InvalidDiagnostic); + } + Ok(topic_count as f64 * (vocabulary - 1) as f64 + + (documents as f64 + features as f64) * (topic_count - 1) as f64) +} + +#[cfg(test)] +mod tests { + use super::{FittedCandidateKConfig, free_parameter_count, refuse_nonstatistical_method}; + use crate::ModelSelectionError; + use topic_measurement::{PrevalenceFeature, ReferenceTopicModel}; + + fn model( + topic_term_probabilities: Vec>, + document_topic_proportions: Vec>, + prevalence_coefficients: Vec>, + ) -> ReferenceTopicModel { + ReferenceTopicModel { + seed: 1, + iterations: 4, + objective: -1.0, + topic_term_probabilities, + document_topic_proportions, + document_coordinate_variances: Vec::new(), + prevalence_coefficients, + prevalence_features: vec![PrevalenceFeature::Intercept], + sequence_edges: Vec::new(), + connected_post_count: 0, + lineage_count: 0, + } + } + + #[test] + fn configuration_accessors_and_method_gate_cover_local_branches() { + let config = + FittedCandidateKConfig::new(vec![2, 3], vec![7, 11], 20, 1e-5).expect("config"); + assert_eq!(config.candidate_topic_counts(), &[2, 3]); + assert_eq!(config.seeds(), &[7, 11]); + assert_eq!(config.maximum_iterations(), 20); + assert!((config.tolerance() - 1e-5).abs() < f64::EPSILON); + refuse_nonstatistical_method("trsl_tm_reference").expect("allowed"); + refuse_nonstatistical_method("logistic_normal").expect("allowed"); + for method in [ + "tfidf", + "bm25", + "keyword", + "stopword", + "stopwords", + "stopworddeletion", + "llm", + "llmlabel", + "llm-labels", + "llm_vote", + "llm_vote_only", + ] { + assert_eq!( + refuse_nonstatistical_method(method), + Err(ModelSelectionError::LexicalWeightForbidden) + ); + } + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![1], 10, 1e-6) + .expect("base") + .with_hyperparameters(1.0, 0.0, 0.0, 0.05, 0.2) + .expect("zero ablation") + .seeds() + .len(), + 1 + ); + } + + #[test] + fn free_parameter_count_refuses_dimension_mismatch() { + let valid = model( + vec![vec![0.7, 0.3], vec![0.2, 0.8]], + vec![vec![0.9, 0.1], vec![0.1, 0.9]], + vec![vec![0.0]], + ); + assert!((free_parameter_count(&valid).expect("p") - 5.0).abs() < f64::EPSILON); + assert_eq!( + free_parameter_count(&model(Vec::new(), Vec::new(), Vec::new())), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.5, 0.5]], + vec![vec![0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![0.5, 0.5]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![1.0], vec![1.0]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![1.0, 0.0]], + vec![vec![1.0], vec![1.0]], + vec![vec![]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![0.5, 0.5], vec![0.5, 0.5, 0.0]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.5, 0.5], vec![0.5, 0.5, 0.0]], + vec![vec![0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + free_parameter_count(&model( + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.0, 0.0]] + )), + Err(ModelSelectionError::InvalidDiagnostic) + ); + } +} diff --git a/crates/model_selection/src/lib.rs b/crates/model_selection/src/lib.rs index 599829af..dbc67c8d 100644 --- a/crates/model_selection/src/lib.rs +++ b/crates/model_selection/src/lib.rs @@ -4,18 +4,27 @@ #![allow(clippy::cast_precision_loss)] //! Statistical and Pareto candidate-`K` gates for TRSL-TM model selection. //! -//! Model selection uses held-out log-likelihood and complexity before any -//! blinded LLM review. An LLM vote may recommend among statistically -//! admissible candidates but never defines the numerical optimum (ADR 0012). +//! Model selection fits each candidate `K` with the CPU `f64` reference +//! estimator and scores the actual mixture likelihood and parameter count +//! before any blinded LLM review. An LLM vote may recommend among +//! statistically admissible candidates but never defines the numerical +//! optimum (ADR 0012). mod candidate; mod error; +mod fitted; mod gate; /// One candidate `K` with statistical or LLM-only support. pub use candidate::ModelCandidate; /// Fail-closed model-selection errors. pub use error::ModelSelectionError; +/// Seeds, iteration budget, and candidate topic counts for fitted selection. +pub use fitted::FittedCandidateKConfig; +/// Fit each candidate `K` and select from the actual statistical diagnostics. +pub use fitted::select_fitted_candidate_k; +/// Build a statistical candidate from one actual fitted model. +pub use fitted::statistical_candidate_from_fit; /// Select the admissible candidate `K` from a Pareto-filtered statistical front. pub use gate::select_candidate_k; /// RMSE of selected `K` replications against known truth. diff --git a/crates/model_selection/tests/fitted_candidate_k_contract.rs b/crates/model_selection/tests/fitted_candidate_k_contract.rs new file mode 100644 index 00000000..1b8e3638 --- /dev/null +++ b/crates/model_selection/tests/fitted_candidate_k_contract.rs @@ -0,0 +1,400 @@ +//! Fitted candidate-`K` scoring uses real TRSL-TM reference fits. + +use corpus_split::{CorpusDocument, CorpusSnapshot}; +use membership_core::{ + GroupId, MemberId, MembershipAssignment, MembershipNetwork, MembershipRole, MembershipWeight, +}; +use model_selection::{ + FittedCandidateKConfig, ModelSelectionError, select_fitted_candidate_k, + selected_k_root_mean_square_error, statistical_candidate_from_fit, +}; +use relation_graph::{ + RelationEdge, RelationEndpointId, RelationEvidenceStatus, RelationGraph, RelationKind, +}; +use temporal_core::{ + AvailableTime, EventTime, KnowledgeCutoff, TemporalBoundary, TemporalInterval, + TemporalPrecision, +}; +use topic_measurement::{ReferenceTopicInput, ReferenceTopicModel, SparseMatrix}; +use uuid::Uuid; + +fn event_time(day: u8) -> EventTime { + EventTime::parse_rfc3339(&format!("2026-01-{day:02}T00:00:00Z")).expect("event time") +} + +fn relation(source: Uuid, target: Uuid, source_day: u8, target_day: u8) -> RelationEdge { + let interval = |day| { + TemporalInterval::bounded( + TemporalBoundary::Included(event_time(day)), + TemporalBoundary::Included( + EventTime::parse_rfc3339(&format!("2026-01-{day:02}T12:00:00Z")) + .expect("interval end"), + ), + TemporalPrecision::Second, + ) + .expect("bounded interval") + }; + RelationEdge::new( + RelationKind::TransitionsTo, + RelationEndpointId::from_uuid(source), + RelationEndpointId::from_uuid(target), + RelationEvidenceStatus::Observed, + interval(source_day), + interval(target_day), + ) + .expect("forward relation") +} + +fn separated_topic_input() -> ReferenceTopicInput { + let document_ids: Vec<_> = (1_u128..=6).map(Uuid::from_u128).collect(); + let times: Vec<_> = (1_u8..=6).map(event_time).collect(); + let available = AvailableTime::parse_rfc3339("2026-01-10T00:00:00Z").expect("available"); + let cutoff = KnowledgeCutoff::parse_rfc3339("2026-02-01T00:00:00Z").expect("cutoff"); + let mut snapshot = CorpusSnapshot::new(); + for id in &document_ids { + snapshot + .insert_if_eligible(CorpusDocument::new(*id, available), &cutoff) + .expect("eligible"); + } + + let organization = GroupId::from_uuid(Uuid::from_u128(100)); + let projects = [ + GroupId::from_uuid(Uuid::from_u128(101)), + GroupId::from_uuid(Uuid::from_u128(102)), + ]; + let validity_start = event_time(1); + let validity_end = event_time(9); + let mut memberships = MembershipNetwork::new(); + for (index, id) in document_ids.iter().enumerate() { + let member = MemberId::from_uuid(*id); + memberships + .insert( + MembershipAssignment::new( + member, + organization, + MembershipRole::Organization, + MembershipWeight::full().expect("full"), + validity_start, + validity_end, + ) + .expect("organization membership"), + ) + .expect("insert organization"); + memberships + .insert( + MembershipAssignment::new( + member, + projects[usize::from(index >= 3)], + MembershipRole::Project, + MembershipWeight::new(0.75).expect("partial"), + validity_start, + validity_end, + ) + .expect("project membership"), + ) + .expect("insert project"); + } + + let mut relations = RelationGraph::new(); + for (source, target, source_day, target_day) in [ + (0, 1, 1, 2), + (1, 2, 2, 3), + (2, 3, 3, 4), + (3, 4, 4, 5), + (4, 5, 5, 6), + ] { + relations + .insert(relation( + document_ids[source], + document_ids[target], + source_day, + target_day, + )) + .expect("insert relation"); + } + + let counts = SparseMatrix::from_csr( + 6, + 4, + vec![0, 2, 4, 6, 8, 10, 12], + vec![0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3], + vec![ + 90.0, 10.0, 85.0, 15.0, 80.0, 20.0, 10.0, 90.0, 15.0, 85.0, 20.0, 80.0, + ], + ) + .expect("counts"); + ReferenceTopicInput::new( + &snapshot, + document_ids, + &counts, + ×, + None, + &memberships, + &relations, + ) + .expect("validated input") +} + +fn two_document_input(term_values: [f64; 4]) -> ReferenceTopicInput { + let document_ids = vec![Uuid::from_u128(1), Uuid::from_u128(2)]; + let times = vec![event_time(1), event_time(2)]; + let available = AvailableTime::parse_rfc3339("2026-01-10T00:00:00Z").expect("available"); + let cutoff = KnowledgeCutoff::parse_rfc3339("2026-02-01T00:00:00Z").expect("cutoff"); + let mut snapshot = CorpusSnapshot::new(); + for id in &document_ids { + snapshot + .insert_if_eligible(CorpusDocument::new(*id, available), &cutoff) + .expect("eligible"); + } + let mut memberships = MembershipNetwork::new(); + memberships + .insert( + MembershipAssignment::new( + MemberId::from_uuid(document_ids[0]), + GroupId::from_uuid(Uuid::from_u128(100)), + MembershipRole::Organization, + MembershipWeight::full().expect("full"), + event_time(1), + event_time(9), + ) + .expect("membership"), + ) + .expect("insert"); + memberships + .insert( + MembershipAssignment::new( + MemberId::from_uuid(document_ids[1]), + GroupId::from_uuid(Uuid::from_u128(100)), + MembershipRole::Organization, + MembershipWeight::full().expect("full"), + event_time(1), + event_time(9), + ) + .expect("membership"), + ) + .expect("insert"); + let mut relations = RelationGraph::new(); + relations + .insert(relation(document_ids[0], document_ids[1], 1, 2)) + .expect("relation"); + let counts = + SparseMatrix::from_csr(2, 2, vec![0, 2, 4], vec![0, 1, 0, 1], term_values.to_vec()) + .expect("counts"); + ReferenceTopicInput::new( + &snapshot, + document_ids, + &counts, + ×, + None, + &memberships, + &relations, + ) + .expect("two-document input") +} + +fn recovery_config(seeds: Vec) -> FittedCandidateKConfig { + FittedCandidateKConfig::new(vec![2, 3], seeds, 2_000, 1e-5) + .expect("candidate configuration") + .with_hyperparameters(1.0, 0.5, 0.01, 0.05, 0.2) + .expect("hyperparameters") +} + +#[test] +fn fitted_diagnostics_select_true_k_over_overspecified_and_llm_only() { + let input = separated_topic_input(); + let config = recovery_config(vec![7, 11, 19]); + let selected = select_fitted_candidate_k(&input, &config, "trsl_tm_reference", &[3]) + .expect("fitted statistical selection"); + assert_eq!(selected, 2); +} + +#[test] +fn selected_k_rmse_on_fitted_replications_recovers_true_k() { + let input = separated_topic_input(); + let selected: Vec = [vec![7, 11, 19], vec![3, 5, 13], vec![17, 23, 29]] + .into_iter() + .map(|seeds| { + select_fitted_candidate_k( + &input, + &recovery_config(seeds), + "tepp_topic_measurement", + &[3], + ) + .expect("replication") + }) + .collect(); + assert_eq!(selected, vec![2, 2, 2]); + let rmse = selected_k_root_mean_square_error(&selected, 2).expect("selected-K RMSE"); + assert!(rmse.abs() < f64::EPSILON); +} + +#[test] +fn failed_and_non_finite_fits_fail_closed() { + let input = separated_topic_input(); + let exhausted = FittedCandidateKConfig::new(vec![2], vec![1], 2, 1e-12).expect("exhausted"); + assert_eq!( + select_fitted_candidate_k(&input, &exhausted, "trsl_tm_reference", &[]), + Err(ModelSelectionError::NoSuccessfulFit) + ); + + let oversized = FittedCandidateKConfig::new(vec![5], vec![1], 10, 1e-6).expect("K > V"); + assert_eq!( + select_fitted_candidate_k(&input, &oversized, "trsl_tm_reference", &[]), + Err(ModelSelectionError::NoSuccessfulFit) + ); + + let unstable = FittedCandidateKConfig::new(vec![2], vec![1], 10, 1e-6) + .expect("unstable") + .with_hyperparameters(1.0, 0.5, 0.01, 0.05, f64::MAX) + .expect("finite-declared step"); + assert_eq!( + select_fitted_candidate_k(&input, &unstable, "trsl_tm_reference", &[]), + Err(ModelSelectionError::NoSuccessfulFit) + ); + + let only_failed_plus_llm = + FittedCandidateKConfig::new(vec![5], vec![1], 10, 1e-6).expect("failed statistical"); + assert_eq!( + select_fitted_candidate_k(&input, &only_failed_plus_llm, "trsl_tm_reference", &[3]), + Err(ModelSelectionError::LlmVoteIsNotStatisticalAuthority) + ); +} + +#[test] +fn lexical_and_llm_label_methods_are_refused() { + let input = separated_topic_input(); + let config = FittedCandidateKConfig::new(vec![2], vec![1], 10, 1e-6).expect("config"); + for method in [ + "tf-idf", + "tfidf", + "BM25", + "bm25", + "keyword", + "stopword-deletion", + "stopword", + "stopwords", + "llm-label", + "llm-labels", + "llm", + "llm_vote", + "llm_vote_only", + "", + ] { + assert_eq!( + select_fitted_candidate_k(&input, &config, method, &[]), + Err(ModelSelectionError::LexicalWeightForbidden) + ); + } +} + +#[test] +fn invalid_fitted_configuration_fails_closed() { + assert_eq!( + FittedCandidateKConfig::new(vec![], vec![1], 10, 1e-6), + Err(ModelSelectionError::EmptyCandidateSet) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![1], vec![1], 10, 1e-6), + Err(ModelSelectionError::NonPositiveCandidateK) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2, 2], vec![1], 10, 1e-6), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![], 10, 1e-6), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![1], 1, 1e-6), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![1], 10, f64::NAN), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![1], 10, 0.0), + Err(ModelSelectionError::InvalidDiagnostic) + ); + assert_eq!( + FittedCandidateKConfig::new(vec![2], vec![1], 10, f64::INFINITY), + Err(ModelSelectionError::InvalidDiagnostic) + ); + let base = FittedCandidateKConfig::new(vec![2], vec![1], 10, 1e-6).expect("base"); + for values in [ + (f64::NAN, 0.5, 0.01, 0.05, 0.2), + (f64::INFINITY, 0.5, 0.01, 0.05, 0.2), + (0.0, 0.5, 0.01, 0.05, 0.2), + (1.0, f64::NAN, 0.01, 0.05, 0.2), + (1.0, f64::INFINITY, 0.01, 0.05, 0.2), + (1.0, -1.0, 0.01, 0.05, 0.2), + (1.0, 0.5, f64::NAN, 0.05, 0.2), + (1.0, 0.5, f64::INFINITY, 0.05, 0.2), + (1.0, 0.5, -1.0, 0.05, 0.2), + (1.0, 0.5, 0.01, f64::NAN, 0.2), + (1.0, 0.5, 0.01, f64::INFINITY, 0.2), + (1.0, 0.5, 0.01, 0.0, 0.2), + (1.0, 0.5, 0.01, 0.05, f64::NAN), + (1.0, 0.5, 0.01, 0.05, f64::INFINITY), + (1.0, 0.5, 0.01, 0.05, 0.0), + ] { + assert_eq!( + base.clone() + .with_hyperparameters(values.0, values.1, values.2, values.3, values.4), + Err(ModelSelectionError::InvalidDiagnostic) + ); + } + assert_eq!( + select_fitted_candidate_k(&separated_topic_input(), &base, "trsl_tm_reference", &[1]), + Err(ModelSelectionError::NonPositiveCandidateK) + ); +} + +#[test] +fn statistical_candidate_from_fit_refuses_unusable_diagnostics() { + let input = separated_topic_input(); + let matching = ReferenceTopicModel { + seed: 1, + iterations: 4, + objective: -1.0, + topic_term_probabilities: vec![vec![0.25; 4]; 2], + document_topic_proportions: vec![vec![0.5, 0.5]; 6], + document_coordinate_variances: vec![vec![0.1]; 6], + prevalence_coefficients: vec![vec![0.0]; 5], + prevalence_features: Vec::new(), + sequence_edges: Vec::new(), + connected_post_count: 0, + lineage_count: 0, + }; + assert!(statistical_candidate_from_fit(&input, 2, &matching).is_ok()); + assert_eq!( + statistical_candidate_from_fit(&input, 1, &matching), + Err(ModelSelectionError::NonPositiveCandidateK) + ); + let mut short = matching.clone(); + short.document_topic_proportions.pop(); + assert_eq!( + statistical_candidate_from_fit(&input, 2, &short), + Err(ModelSelectionError::InvalidDiagnostic) + ); + + let tiny = two_document_input([0.2, 0.2, 0.2, 0.2]); + let tiny_model = ReferenceTopicModel { + seed: 1, + iterations: 4, + objective: -1.0, + topic_term_probabilities: vec![vec![0.5, 0.5], vec![0.5, 0.5]], + document_topic_proportions: vec![vec![0.5, 0.5], vec![0.5, 0.5]], + document_coordinate_variances: vec![vec![0.1], vec![0.1]], + prevalence_coefficients: vec![vec![0.0]; 3], + prevalence_features: Vec::new(), + sequence_edges: Vec::new(), + connected_post_count: 0, + lineage_count: 0, + }; + assert_eq!( + statistical_candidate_from_fit(&tiny, 2, &tiny_model), + Err(ModelSelectionError::InvalidDiagnostic) + ); +} diff --git a/crates/psychometric_core/src/error.rs b/crates/psychometric_core/src/error.rs index 5f723b42..ee59f19d 100644 --- a/crates/psychometric_core/src/error.rs +++ b/crates/psychometric_core/src/error.rs @@ -1099,6 +1099,27 @@ pub enum PsychometricError { /// mean using free `T0VAR`, not process-dynamics /// `asymDIFFUSION`. WithinSubjectScaledInitialLatentMeanIsNotStandardisedInitialLatentMean, + /// Driver p. 16 `MANIFESTMEANSstd` was requested with a + /// non-positive residual. Footnote 4 standardisation of the + /// 2017-era `MANIFESTMEANS` vector requires strictly positive + /// `MANIFESTVAR`. + StandardisedManifestMeanRequiresPositiveManifestVariance, + /// Driver Table 2 unstandardised `MANIFESTMEANS` `τ` was treated + /// as `MANIFESTMEANSstd`. Unstandardised measurement intercept + /// is defined for a zero residual; standardised `MANIFESTMEANS` + /// is not. + UnstandardisedManifestMeanIsNotStandardisedManifestMean, + /// Driver p. 16 `MANIFESTVARstd` was treated as p. 16 + /// `MANIFESTMEANSstd`. Equal numbers when `τ = √θ` are still + /// distinct named quantities. `MANIFESTVARstd` is the + /// correlation form of residual `MANIFESTVAR`; + /// `MANIFESTMEANSstd` is the measurement intercept. + StandardisedManifestVarianceIsNotStandardisedManifestMean, + /// Driver Eq. 5 `τ / √(λ² Var(η) + θ)` was treated as + /// `MANIFESTMEANSstd`. Footnote 4 standardises the named + /// intercept using residual `MANIFESTVAR`, not total observed + /// variance. + ObservedScaledManifestMeanIsNotStandardisedManifestMean, } impl fmt::Display for PsychometricError { @@ -1896,6 +1917,18 @@ impl fmt::Display for PsychometricError { Self::WithinSubjectScaledInitialLatentMeanIsNotStandardisedInitialLatentMean => { "within-subject scaled initial latent mean is not standardised initial latent mean" } + Self::StandardisedManifestMeanRequiresPositiveManifestVariance => { + "standardised manifest mean requires strictly positive measurement error" + } + Self::UnstandardisedManifestMeanIsNotStandardisedManifestMean => { + "unstandardised manifest mean is not standardised manifest mean" + } + Self::StandardisedManifestVarianceIsNotStandardisedManifestMean => { + "standardised manifest variance is not standardised manifest mean" + } + Self::ObservedScaledManifestMeanIsNotStandardisedManifestMean => { + "observed scaled manifest mean is not standardised manifest mean" + } }; formatter.write_str(message) } @@ -3275,4 +3308,25 @@ mod tests { "within-subject scaled initial latent mean is not standardised initial latent mean" ); } + + #[test] + fn standardised_manifest_mean_boundary_messages_are_stable() { + assert_eq!( + PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance.to_string(), + "standardised manifest mean requires strictly positive measurement error" + ); + assert_eq!( + PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean.to_string(), + "unstandardised manifest mean is not standardised manifest mean" + ); + assert_eq!( + PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean + .to_string(), + "standardised manifest variance is not standardised manifest mean" + ); + assert_eq!( + PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean.to_string(), + "observed scaled manifest mean is not standardised manifest mean" + ); + } } diff --git a/crates/psychometric_core/src/event_time.rs b/crates/psychometric_core/src/event_time.rs index 5e7c4cbf..09bbd0c1 100644 --- a/crates/psychometric_core/src/event_time.rs +++ b/crates/psychometric_core/src/event_time.rs @@ -336,7 +336,15 @@ //! 2026-08-24T22:30Z). Unstandardised `T0MEANS` is not //! `T0MEANSstd`. `T0VARstd` is not `T0MEANSstd` even when both //! equal 1. `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`. Free -//! `T0MEANS` does not require `a < 0`. The JSS article +//! `T0MEANS` does not require `a < 0`. Page 16 +//! `MANIFESTMEANSstd` is `τ / √θ` after strictly positive +//! `MANIFESTVAR` (2017-era `summary.ctsemFit.R` forms +//! unstandardised `MANIFESTMEANS` and does not form +//! `MANIFESTMEANSstd`; JSS PDF re-opened 2026-08-25T05:04Z). +//! Unstandardised `MANIFESTMEANS` is not `MANIFESTMEANSstd`. +//! `MANIFESTVARstd` is not `MANIFESTMEANSstd` even when both +//! equal 1. `τ / √(λ² Var(η) + θ)` is not `MANIFESTMEANSstd`. +//! `MANIFESTMEANS` does not require `a < 0`. The JSS article //! has no numbered §2.2 (2.1 is Continuous time and SEM; §3 follows). //! The difference quotient `(x(t+Δt) − x(t)) / Δt` (their //! Eqs. 3–4) is refused. This is not DSEM and not a matrix `expm`. @@ -2879,6 +2887,132 @@ pub fn refuse_within_subject_scaled_initial_latent_mean_as_standardised_initial_ Err(PsychometricError::WithinSubjectScaledInitialLatentMeanIsNotStandardisedInitialLatentMean) } +/// Exact scalar p. 16 `MANIFESTMEANSstd` after strictly positive +/// `MANIFESTVAR`. +/// +/// Driver, Oud, and Voelkle (2017, Table 2, p. 12; p. 16; footnote +/// 4; Eq. 5, p. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF +/// re-opened 2026-08-25T05:04Z from +/// ) +/// name `MANIFESTMEANS` `τ` the `n.manifest × 1` matrix of manifest +/// means. Table 2 names `MANIFESTVAR` `Θ` the residual covariance +/// of the indicators (measurement error). Page 16 prints +/// standardised matrices with the suffix `std` when appropriate. +/// Footnote 4: standardisations use only the relevant variance, not +/// the total. The relevant variance for that named measurement +/// intercept is residual `MANIFESTVAR` `θ`, not total observed +/// `Var(y) = λ² Var(η) + θ`, matching `MANIFESTVARstd`. The +/// 2017-era `summary.ctsemFit.R` forms unstandardised +/// `MANIFESTMEANS` as `mxEval(MANIFESTMEANS, mxobj, compute=TRUE)`. +/// That source does not form a `MANIFESTMEANSstd` matrix; the +/// scalar map here is the footnote 4 standardisation of that named +/// intercept: `τ / √θ`. Form strictly positive `θ` first, then +/// divide `τ` by `√θ`. A zero mean is exactly zero. +/// Unstandardised `MANIFESTMEANS` is defined for a zero residual; +/// standardised `MANIFESTMEANS` is not. Zero `θ` has no positive +/// SD and fails closed. Manifest means are an event-time +/// measurement quantity, so a non-event clock fails closed. +/// `MANIFESTMEANS` does not require stable `a < 0`. +/// `MANIFESTVARstd` `θ / θ = 1` recovers the same number when +/// `τ = √θ` and remains a distinct named quantity. +/// `τ / √(λ² Var(η) + θ)` uses total observed variance and is not +/// this residual map. The 2017-era source assigns +/// `dimnames(MANIFESTMEANS)` to `list(manifestNames, manifestNames)` +/// on an `n.manifest × 1` matrix; that assignment is a source bug +/// and is not this map. `T0MEANSstd` `μ_0 / √p_0` recovers the +/// same number when `τ = μ_0` and `θ = p_0` and remains a distinct +/// named quantity. This is not a Kalman filter, not a matrix +/// `expm`, not DSEM, and not ctsem estimation. +/// +/// # Errors +/// +/// Returns [`PsychometricError::EventTimeRequired`] for any +/// non-event clock, +/// [`PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance`] +/// when `MANIFESTVAR` is zero, and +/// [`PsychometricError::InvalidNumericInput`] when the mean is +/// non-finite, the residual is non-finite or negative, or the +/// mapped ratio overflows. Negative means remain valid signed +/// locations. +pub fn recover_standardised_manifest_mean( + manifest_mean: f64, + measurement_error: f64, + clock: LagClock, +) -> Result { + if !clock.admits_structural_lag() { + return Err(PsychometricError::EventTimeRequired); + } + if !measurement_error.is_finite() || measurement_error < 0.0 { + return Err(PsychometricError::InvalidNumericInput); + } + if measurement_error == 0.0 { + return Err(PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance); + } + let mean = require_finite(manifest_mean)?; + if mean == 0.0 { + return Ok(0.0); + } + let residual_sd = measurement_error.sqrt(); + require_finite(mean / residual_sd) +} + +/// Refuse treating unstandardised `MANIFESTMEANS` as p. 16 +/// `MANIFESTMEANSstd`. +/// +/// Free `MANIFESTMEANS` `τ` is defined for a zero residual. +/// Footnote 4 `MANIFESTMEANSstd` requires strictly positive `θ`. +/// Equal numbers when `θ = 1` are still distinct named quantities. +/// +/// # Errors +/// +/// Always returns +/// [`PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean`]. +pub fn refuse_unstandardised_manifest_mean_as_standardised_manifest_mean( + unstandardised_manifest_mean: f64, + standardised_manifest_mean: f64, +) -> Result { + let _ = (unstandardised_manifest_mean, standardised_manifest_mean); + Err(PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean) +} + +/// Refuse treating p. 16 `MANIFESTVARstd` as p. 16 +/// `MANIFESTMEANSstd`. +/// +/// Both scalar maps equal 1 when `τ = √θ`. `MANIFESTVARstd` is +/// the correlation form of residual `MANIFESTVAR`. +/// `MANIFESTMEANSstd` is the measurement intercept. Equal numbers +/// remain distinct named quantities. +/// +/// # Errors +/// +/// Always returns +/// [`PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean`]. +pub fn refuse_standardised_manifest_variance_as_standardised_manifest_mean( + standardised_manifest_variance: f64, + standardised_manifest_mean: f64, +) -> Result { + let _ = (standardised_manifest_variance, standardised_manifest_mean); + Err(PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean) +} + +/// Refuse treating `τ / √(λ² Var(η) + θ)` as p. 16 +/// `MANIFESTMEANSstd`. +/// +/// Footnote 4 measurement-intercept standardisation uses residual +/// `MANIFESTVAR`, not total observed `Var(y)`. +/// +/// # Errors +/// +/// Always returns +/// [`PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean`]. +pub fn refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean( + observed_scaled_mean: f64, + standardised_manifest_mean: f64, +) -> Result { + let _ = (observed_scaled_mean, standardised_manifest_mean); + Err(PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean) +} + /// Exact scalar 2017-era `addedT0TIPREDVAR` after a first-occasion /// time-independent predictor. /// @@ -10135,7 +10269,8 @@ mod tests { recover_standardised_initial_latent_mean, recover_standardised_initial_latent_variance, recover_standardised_initial_time_dependent_predictor_effect, recover_standardised_initial_time_independent_predictor_effect, - recover_standardised_manifest_trait_variance, recover_standardised_manifest_variance, + recover_standardised_manifest_mean, recover_standardised_manifest_trait_variance, + recover_standardised_manifest_variance, recover_standardised_time_independent_predictor_variance, recover_standardised_trait_variance, recover_stationary_initial_latent_mean, recover_stationary_initial_latent_variance, recover_stationary_initial_observed_mean, @@ -10238,6 +10373,7 @@ mod tests { refuse_measurement_error_as_standardised_manifest_trait_variance, refuse_measurement_error_as_stationary_lagged_observed_covariance, refuse_measurement_error_as_stationary_later_observed_variance, + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean, refuse_observed_variance_as_standardised_manifest_variance, refuse_pooled_discrete_lag_across_unequal_intervals, refuse_predetermined_initial_latent_variance_as_initial_latent_variance, @@ -10292,6 +10428,7 @@ mod tests { refuse_standardised_initial_time_dependent_effect_as_standardised_initial_latent_variance, refuse_standardised_initial_time_independent_effect_as_standardised_initial_time_dependent_effect, refuse_standardised_manifest_trait_variance_as_standardised_manifest_variance, + refuse_standardised_manifest_variance_as_standardised_manifest_mean, refuse_standardised_manifest_variance_as_standardised_time_independent_predictor_variance, refuse_standardised_time_independent_predictor_variance_as_standardised_asymptotic_diffusion, refuse_standardised_trait_variance_as_standardised_manifest_trait_variance, @@ -10363,6 +10500,7 @@ mod tests { refuse_unstandardised_initial_latent_variance_as_standardised_initial_latent_variance, refuse_unstandardised_initial_time_dependent_effect_as_standardised_initial_time_dependent_effect, refuse_unstandardised_initial_time_independent_effect_as_standardised_initial_time_independent_effect, + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean, refuse_unstandardised_manifest_trait_variance_as_standardised_manifest_trait_variance, refuse_unstandardised_manifest_variance_as_standardised_manifest_variance, refuse_unstandardised_time_independent_predictor_variance_as_standardised_time_independent_predictor_variance, @@ -10401,7 +10539,6 @@ mod tests { let same = map_discrete_lag_across_event_intervals( source_lag, source_delta, - source_delta, LagClock::EventTime, ) .expect("same interval"); @@ -10654,8 +10791,6 @@ mod tests { let recovered = recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq 14"); @@ -10673,8 +10808,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( 0.0, delta, - delta, - delta, LagClock::EventTime ), Ok(0.0) @@ -10689,8 +10822,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, - delta, - delta, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -10699,8 +10830,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 0.0, - 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10710,7 +10839,6 @@ mod tests { outcome_on_predictor, -1.0, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10729,7 +10857,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, - 1.0, 0.0, LagClock::EventTime ), @@ -10740,7 +10867,6 @@ mod tests { outcome_on_predictor, 1.0, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -10749,7 +10875,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 2.0, - 2.0, 1.0, LagClock::EventTime ), @@ -10759,8 +10884,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( f64::NAN, delta, - delta, - delta, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -10769,8 +10892,6 @@ mod tests { recover_discrete_time_varying_predictor_effect( 1e308, 10.0, - 10.0, - 10.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -12157,8 +12278,6 @@ mod tests { let zero_evolved = recover_discrete_observed_mean( loading, 0.0, - 0.0, - 0.0, manifest_mean, delta, LagClock::EventTime, @@ -12298,8 +12417,6 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -12317,8 +12434,6 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, - 2.0, - 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -12372,7 +12487,6 @@ mod tests { 0.3, 0.4, 2.0, - 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -12381,10 +12495,8 @@ mod tests { recover_discrete_latent_mean_with_impulse( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -12647,7 +12759,6 @@ mod tests { coupling, predictor, extra, - extra, delta, LagClock::EventTime, ) @@ -13295,7 +13406,6 @@ mod tests { original, extra, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13389,7 +13499,6 @@ mod tests { predictor, extra, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13476,7 +13585,6 @@ mod tests { recover_asymptotic_time_independent_predictor_effect( effect, 0.0, - 0.0, LagClock::EventTime ), Ok(0.0) @@ -13627,7 +13735,6 @@ mod tests { recover_asymptotic_time_independent_predictor_variance( effect, 0.0, - 0.0, LagClock::EventTime ), Ok(0.0) @@ -14076,7 +14183,6 @@ mod tests { recover_stationary_initial_observed_mean( loading, 0.0, - 0.0, 1.0, 0.0, manifest_mean, @@ -14218,7 +14324,6 @@ mod tests { -0.225, 1.0, 0.5, - 0.5, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -14239,7 +14344,6 @@ mod tests { recover_stationary_initial_observed_mean( 2.0, 1e308, - 1e308, 1.0, -1e-308, 0.5, @@ -14297,7 +14401,6 @@ mod tests { let trait_only = recover_stationary_initial_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -14305,7 +14408,6 @@ mod tests { .expect("trait-only"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_initial_latent_variance( - 0.0, 0.0, printed_effect, predictor_variance, @@ -14316,8 +14418,6 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_initial_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -14327,8 +14427,6 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, 0.5, @@ -14429,7 +14527,6 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( - 0.0, 0.0, -0.225, 1.0, @@ -14440,8 +14537,6 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -14454,7 +14549,6 @@ mod tests { f64::NAN, 0.4, 0.0, - 0.0, -0.5, LagClock::EventTime ), @@ -14462,10 +14556,8 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( - f64::MAX, f64::MAX, 0.0, - 0.0, -0.5, LagClock::EventTime ), @@ -14563,8 +14655,6 @@ mod tests { recover_stationary_initial_observed_variance( loading, 0.0, - 0.0, - 0.0, 1.0, 0.0, measurement_error, @@ -14699,11 +14789,9 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, - 0.5, 0.0, LagClock::EventTime ), @@ -14713,8 +14801,6 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 0.5, @@ -14729,7 +14815,6 @@ mod tests { 1.0, 0.4, 0.0, - 0.0, -0.5, 0.5, 0.0, @@ -14741,8 +14826,6 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 0.5, @@ -14834,7 +14917,6 @@ mod tests { let trait_only = recover_stationary_lagged_latent_covariance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -14843,7 +14925,6 @@ mod tests { .expect("trait-only lagged"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_lagged_latent_covariance( - 0.0, 0.0, printed_effect, predictor_variance, @@ -14855,8 +14936,6 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -15000,7 +15079,6 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, 0.0, -0.225, 1.0, @@ -15012,8 +15090,6 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -15027,7 +15103,6 @@ mod tests { f64::NAN, 0.4, 0.0, - 0.0, -0.5, 1.0, LagClock::EventTime @@ -15037,8 +15112,6 @@ mod tests { assert_eq!( recover_stationary_lagged_latent_covariance( f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, @@ -15134,8 +15207,6 @@ mod tests { recover_stationary_lagged_observed_covariance( loading, 0.0, - 0.0, - 0.0, 1.0, 0.0, event_delta, @@ -15273,7 +15344,6 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -15287,8 +15357,6 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -15303,7 +15371,6 @@ mod tests { 1.0, 0.4, 0.0, - 0.0, -0.5, 1.0, 0.0, @@ -15315,8 +15382,6 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, @@ -15418,7 +15483,6 @@ mod tests { let trait_only = recover_stationary_later_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -15427,7 +15491,6 @@ mod tests { .expect("trait-only later"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_later_latent_variance( - 0.0, 0.0, printed_effect, predictor_variance, @@ -15439,8 +15502,6 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_later_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -15576,7 +15637,6 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( - 0.0, 0.0, -0.225, 1.0, @@ -15588,8 +15648,6 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -15603,7 +15661,6 @@ mod tests { f64::NAN, 0.4, 0.0, - 0.0, -0.5, 1.0, LagClock::EventTime @@ -15613,8 +15670,6 @@ mod tests { assert_eq!( recover_stationary_later_latent_variance( f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, @@ -15731,13 +15786,10 @@ mod tests { recover_stationary_later_observed_variance( loading, 0.0, - 0.0, - 0.0, 1.0, 0.0, event_delta, 0.0, - 0.0, LagClock::EventTime, ), Ok(0.0) @@ -15872,7 +15924,6 @@ mod tests { 0.0, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::StationaryVarianceRequiresStableDrift) @@ -15881,13 +15932,11 @@ mod tests { recover_stationary_later_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -15896,8 +15945,6 @@ mod tests { recover_stationary_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -15913,11 +15960,9 @@ mod tests { 1.0, 0.4, 0.0, - 0.0, -0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -15926,13 +15971,10 @@ mod tests { recover_stationary_later_observed_variance( 2.0, f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16041,8 +16083,6 @@ mod tests { let trait_only = recover_predetermined_later_latent_variance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -16051,8 +16091,6 @@ mod tests { .expect("trait-only predetermined later"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_predetermined_later_latent_variance( - 0.0, - 0.0, 0.0, printed_effect, predictor_variance, @@ -16064,9 +16102,6 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -16104,7 +16139,6 @@ mod tests { initial_latent_variance, diffusion, 0.0, - 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16215,8 +16249,6 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -16228,9 +16260,6 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -16244,8 +16273,6 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, - 0.0, 1.0, LagClock::EventTime, ) @@ -16257,7 +16284,6 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 1.0, LagClock::EventTime @@ -16266,11 +16292,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( - f64::MAX, f64::MAX, 0.0, - 0.0, - 0.0, -0.5, 1.0, LagClock::EventTime @@ -16281,7 +16304,6 @@ mod tests { recover_predetermined_later_latent_variance( f64::MAX, 0.0, - 0.0, 1.0, f64::MAX, -1.0, @@ -16395,14 +16417,10 @@ mod tests { recover_predetermined_later_observed_variance( loading, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, event_delta, 0.0, - 0.0, LagClock::EventTime, ), Ok(0.0) @@ -16539,14 +16557,11 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -16555,9 +16570,6 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -16574,11 +16586,9 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16587,14 +16597,10 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, f64::MAX, - f64::MAX, - 0.0, - 0.0, 0.0, -0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16687,8 +16693,6 @@ mod tests { assert!((recovered - initial_latent_variance).abs() > 1e-3); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -16700,7 +16704,6 @@ mod tests { let trait_only = recover_predetermined_lagged_latent_covariance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -16734,7 +16737,6 @@ mod tests { 0.0, initial_latent_variance, 0.0, - 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16852,7 +16854,6 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, 0.0, -0.225, 1.0, @@ -16864,8 +16865,6 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -16878,8 +16877,6 @@ mod tests { 0.0, 2.0, 0.0, - 0.0, - 0.0, 1.0, LagClock::EventTime, ) @@ -16890,7 +16887,6 @@ mod tests { f64::NAN, 2.0, 0.0, - 0.0, -0.5, 1.0, LagClock::EventTime @@ -16900,8 +16896,6 @@ mod tests { assert_eq!( recover_predetermined_lagged_latent_covariance( f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, @@ -17011,8 +17005,6 @@ mod tests { recover_predetermined_lagged_observed_covariance( loading, 0.0, - 0.0, - 0.0, 1.0, 0.0, event_delta, @@ -17145,7 +17137,6 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -17159,8 +17150,6 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -17188,7 +17177,6 @@ mod tests { 1.0, 2.0, 0.0, - 0.0, -0.5, 1.0, 0.0, @@ -17200,8 +17188,6 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 1.0, @@ -17413,8 +17399,6 @@ mod tests { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -17426,8 +17410,6 @@ mod tests { 1e308, 1.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -17458,8 +17440,6 @@ mod tests { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -17469,11 +17449,9 @@ mod tests { ); assert_eq!( recover_discrete_observed_mean_with_impulse( - 1.0, 1.0, 710.0, 0.0, - 0.0, 3.0, 0.5, 1.0, @@ -17485,8 +17463,6 @@ mod tests { recover_discrete_observed_mean_with_impulse( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -17579,8 +17555,6 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -17671,8 +17645,6 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, - 2.0, - 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -17763,7 +17735,6 @@ mod tests { recover_discrete_latent_mean_with_time_independent_predictor( 1e308, 0.0, - 0.0, 1.0, 1e308, 1.0, @@ -17779,7 +17750,6 @@ mod tests { 0.3, 1e308, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -17994,8 +17964,6 @@ mod tests { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -18006,9 +17974,6 @@ mod tests { let finite_loaded = recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, - 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -18021,8 +17986,6 @@ mod tests { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -18062,8 +18025,6 @@ mod tests { recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -18430,8 +18391,6 @@ mod tests { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 2.0, @@ -18444,8 +18403,6 @@ mod tests { 1e308, 1.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 2.0, @@ -18478,8 +18435,6 @@ mod tests { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 2.0, @@ -18490,11 +18445,9 @@ mod tests { ); assert_eq!( recover_discrete_observed_mean_with_impulse_carry( - 1.0, 1.0, 710.0, 0.0, - 0.0, 3.0, 0.5, 1.0, @@ -18507,8 +18460,6 @@ mod tests { recover_discrete_observed_mean_with_impulse_carry( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -18547,7 +18498,6 @@ mod tests { 3.0, 0.5, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18600,8 +18550,6 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -18744,7 +18692,6 @@ mod tests { 3.0, -0.5, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18764,7 +18711,6 @@ mod tests { recover_discrete_latent_mean_with_impulse_carry( 1e308, 0.0, - 0.0, 1e308, 1.0, 2.0, @@ -19013,17 +18959,14 @@ mod tests { recover_discrete_latent_mean_with_initial_time_independent_predictor( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) ); assert_eq!( recover_initial_time_independent_predictor_carry( - 1.0, 1.0, f64::INFINITY, 1.0, @@ -19043,7 +18986,6 @@ mod tests { ); assert_eq!( recover_initial_time_independent_predictor_carry( - 1.0, 1.0, 1e308, 10.0, @@ -19310,8 +19252,6 @@ mod tests { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -19322,9 +19262,6 @@ mod tests { let finite_loaded = recover_discrete_observed_mean_with_initial_time_independent_predictor( 1e308, 0.0, - 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -19337,8 +19274,6 @@ mod tests { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -19378,8 +19313,6 @@ mod tests { recover_discrete_observed_mean_with_initial_time_independent_predictor( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -19663,17 +19596,14 @@ mod tests { recover_discrete_latent_mean_with_initial_time_dependent_predictor( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) ); assert_eq!( recover_initial_time_dependent_predictor_carry( - 1.0, 1.0, f64::INFINITY, 1.0, @@ -19693,7 +19623,6 @@ mod tests { ); assert_eq!( recover_initial_time_dependent_predictor_carry( - 1.0, 1.0, 1e308, 10.0, @@ -19942,8 +19871,6 @@ mod tests { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -19956,8 +19883,6 @@ mod tests { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -19997,8 +19922,6 @@ mod tests { recover_discrete_observed_mean_with_initial_time_dependent_predictor( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -20110,8 +20033,6 @@ mod tests { assert!((near_later - recovered).abs() < 1e-9); assert_eq!( recover_predetermined_initial_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -20122,7 +20043,6 @@ mod tests { let trait_only = recover_predetermined_initial_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -20132,8 +20052,6 @@ mod tests { let unstable_trait = recover_predetermined_initial_latent_variance( trait_variance, 0.0, - 0.0, - 0.0, 0.5, LagClock::EventTime, ) @@ -20229,7 +20147,6 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( - 0.0, 0.0, -0.225, 1.0, @@ -20240,8 +20157,6 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -20253,8 +20168,6 @@ mod tests { 0.0, 2.0, 0.0, - 0.0, - 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20264,7 +20177,6 @@ mod tests { f64::NAN, 2.0, 0.0, - 0.0, -0.5, LagClock::EventTime ), @@ -20273,8 +20185,6 @@ mod tests { assert_eq!( recover_predetermined_initial_latent_variance( f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, LagClock::EventTime @@ -20386,12 +20296,8 @@ mod tests { recover_predetermined_initial_observed_variance( loading, 0.0, - 0.0, - 0.0, 1.0, 0.0, - 0.0, - 0.0, LagClock::EventTime, ), Ok(0.0) @@ -20445,12 +20351,10 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -20462,8 +20366,6 @@ mod tests { 0.0, 1.0, 0.0, - 0.0, - 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20472,8 +20374,6 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 0.5, @@ -20488,10 +20388,8 @@ mod tests { f64::NAN, 2.0, 0.0, - 0.0, -0.5, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -20500,12 +20398,9 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -20643,9 +20538,6 @@ mod tests { assert!((near_later - later).abs() < 1e-9); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -20658,8 +20550,6 @@ mod tests { let trait_only = recover_predetermined_later_lagged_latent_covariance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, start_delta, @@ -20802,8 +20692,6 @@ mod tests { ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -20819,10 +20707,8 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -20834,7 +20720,6 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 2.0, 1.0, @@ -20844,11 +20729,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - f64::MAX, f64::MAX, 0.0, - 0.0, - 0.0, -0.5, 2.0, 1.0, @@ -20966,9 +20848,6 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( loading, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, start_delta, @@ -21039,8 +20918,6 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -21071,9 +20948,6 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 2.0, @@ -21090,7 +20964,6 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 2.0, 1.0, @@ -21278,9 +21151,6 @@ mod tests { assert!((near_first - later_over_s).abs() < 1e-9); assert_eq!( recover_predetermined_later_start_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -21293,8 +21163,6 @@ mod tests { let trait_only = recover_predetermined_later_start_later_latent_variance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, start_delta, @@ -21470,8 +21338,6 @@ mod tests { ); assert_eq!( recover_predetermined_later_start_later_latent_variance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -21487,10 +21353,8 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -21502,7 +21366,6 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 2.0, 1.0, @@ -21513,9 +21376,6 @@ mod tests { assert_eq!( recover_predetermined_later_start_later_latent_variance( f64::MAX, - f64::MAX, - 0.0, - 0.0, 0.0, -0.5, 2.0, @@ -21644,15 +21504,11 @@ mod tests { recover_predetermined_later_start_later_observed_variance( loading, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, start_delta, lag_delta, 0.0, - 0.0, LagClock::EventTime, ), Ok(0.0) @@ -21721,15 +21577,12 @@ mod tests { recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, 2.0, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -21755,9 +21608,6 @@ mod tests { recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 2.0, @@ -21775,12 +21625,10 @@ mod tests { 2.0, 0.4, 0.0, - 0.0, -0.5, 2.0, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -23899,6 +23747,94 @@ mod tests { ); } + #[test] + fn standardised_manifest_mean_recovers_driver_page_sixteen_after_positive_theta() { + // Driver et al. (2017, p. 16 MANIFESTMEANSstd; Table 2; footnote 4; + // 2017-era summary.ctsemFit.R MANIFESTMEANS): form strictly + // positive MANIFESTVAR θ, then τ / √θ. Relevant variance + // is θ, not λ² Var(η) + θ. + let mean = 0.8_f64; + let measurement_error = 1.6_f64; + let recovered = + recover_standardised_manifest_mean(mean, measurement_error, LagClock::EventTime) + .expect("MANIFESTMEANSstd"); + let expected = mean / measurement_error.sqrt(); + assert!((recovered - expected).abs() < 1e-15); + let larger_theta = recover_standardised_manifest_mean(mean, 6.4, LagClock::EventTime) + .expect("MANIFESTMEANSstd θ=6.4"); + assert!((larger_theta - recovered).abs() > 1e-3); + assert!(larger_theta.abs() < recovered.abs()); + let unit = recover_standardised_manifest_mean( + measurement_error.sqrt(), + measurement_error, + LagClock::EventTime, + ) + .expect("MANIFESTMEANSstd τ=√θ"); + let variance_std = + recover_standardised_manifest_variance(measurement_error, LagClock::EventTime) + .expect("MANIFESTVARstd"); + assert!((unit - variance_std).abs() < 1e-15); + let loading = 1.2_f64; + let latent_variance = 0.9_f64; + let observed = loading * loading * latent_variance + measurement_error; + let observed_scaled = mean / observed.sqrt(); + assert!((observed_scaled - recovered).abs() > 1e-3); + let matching_t0 = + recover_standardised_initial_latent_mean(mean, measurement_error, LagClock::EventTime) + .expect("T0MEANSstd same numbers"); + assert!((matching_t0 - recovered).abs() < 1e-15); + let zero = recover_standardised_manifest_mean(0.0, measurement_error, LagClock::EventTime) + .expect("zero MANIFESTMEANS"); + assert_eq!(zero.to_bits(), 0.0_f64.to_bits()); + let negative = + recover_standardised_manifest_mean(-mean, measurement_error, LagClock::EventTime) + .expect("negative signed MANIFESTMEANSstd"); + assert!((negative + expected).abs() < 1e-15); + assert_eq!( + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean(mean, recovered), + Err(PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean) + ); + assert_eq!( + refuse_standardised_manifest_variance_as_standardised_manifest_mean(variance_std, unit), + Err(PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean) + ); + assert_eq!( + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean( + observed_scaled, + recovered + ), + Err(PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean) + ); + } + + #[test] + fn standardised_manifest_mean_fails_closed_when_unstandardised_is_defined() { + assert_eq!( + recover_standardised_manifest_mean(0.8, 0.0, LagClock::EventTime), + Err(PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance) + ); + assert_eq!( + recover_standardised_manifest_mean(0.8, 1.6, LagClock::SystemTime), + Err(PsychometricError::EventTimeRequired) + ); + assert_eq!( + recover_standardised_manifest_mean(0.8, -1.6, LagClock::EventTime), + Err(PsychometricError::InvalidNumericInput) + ); + assert_eq!( + recover_standardised_manifest_mean(f64::NAN, 1.6, LagClock::EventTime), + Err(PsychometricError::InvalidNumericInput) + ); + assert_eq!( + recover_standardised_manifest_mean(0.8, f64::INFINITY, LagClock::EventTime), + Err(PsychometricError::InvalidNumericInput) + ); + assert_eq!( + recover_standardised_manifest_mean(f64::MAX, 1e-4, LagClock::EventTime), + Err(PsychometricError::InvalidNumericInput) + ); + } + #[test] fn standardised_initial_time_independent_effect_recovers_driver_table_three_after_positive_variances() { @@ -24511,7 +24447,6 @@ mod tests { loading, coefficient, 0.0, - 0.0, LagClock::EventTime, ) .expect("zero variance"); diff --git a/crates/psychometric_core/src/lib.rs b/crates/psychometric_core/src/lib.rs index be356c51..f6004523 100644 --- a/crates/psychometric_core/src/lib.rs +++ b/crates/psychometric_core/src/lib.rs @@ -592,6 +592,21 @@ //! number when `μ_0 = √p_0` and remains a distinct named //! quantity; `μ_0 / √asymDIFFUSION` uses process-dynamics //! variance and is not this map), +//! recovers the Driver p. 16 `MANIFESTMEANSstd` as +//! `τ / √θ` after forming strictly +//! positive `MANIFESTVAR` (JSS PDF re-opened 2026-08-25T05:04Z; +//! p. 16; footnote 4; Table 2; Eq. 5; 2017-era +//! `summary.ctsemFit.R` forms unstandardised `MANIFESTMEANS` +//! as `mxEval(MANIFESTMEANS, mxobj, compute=TRUE)`; that +//! source does not form a `MANIFESTMEANSstd` matrix; the scalar map +//! is the footnote 4 standardisation of that named measurement +//! intercept; unstandardised `MANIFESTMEANS` is defined for a zero +//! residual and is not `MANIFESTMEANSstd`; zero `θ` +//! fails closed; a non-event clock fails closed; `MANIFESTMEANS` +//! does not require `a < 0`; `MANIFESTVARstd` recovers the same +//! number when `τ = √θ` and remains a distinct named +//! quantity; `τ / √(λ² Var(η) + θ)` uses total observed +//! variance and is not this map), //! and refuses //! latent-mean comparison below strong invariance. @@ -784,6 +799,8 @@ pub use event_time::recover_standardised_initial_latent_variance; pub use event_time::recover_standardised_initial_time_dependent_predictor_effect; /// Exact scalar Table 3 / p. 16 `T0TIPREDEFFECTstd` `t0_b · √v / √p_0` after strictly positive free `T0VAR` and `v`. pub use event_time::recover_standardised_initial_time_independent_predictor_effect; +/// Exact scalar p. 16 `MANIFESTMEANSstd` `τ / √θ` after strictly positive `MANIFESTVAR`. +pub use event_time::recover_standardised_manifest_mean; /// Exact scalar p. 16 `MANIFESTTRAITVARstd` `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR`. pub use event_time::recover_standardised_manifest_trait_variance; /// Exact scalar p. 16 `MANIFESTVARstd` `θ / θ = 1` after strictly positive `MANIFESTVAR`. @@ -1014,6 +1031,8 @@ pub use event_time::refuse_measurement_error_as_standardised_manifest_trait_vari pub use event_time::refuse_measurement_error_as_stationary_lagged_observed_covariance; /// Refuse treating `MANIFESTVAR` as Eq. 5 of later-occasion §4.3 stationary `T0VAR`. pub use event_time::refuse_measurement_error_as_stationary_later_observed_variance; +/// Refuse treating `τ / √(λ² Var(η) + θ)` as p. 16 `MANIFESTMEANSstd`. +pub use event_time::refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean; /// Refuse treating Driver Eq. 5 `Var(y)` as p. 16 `MANIFESTVARstd`. pub use event_time::refuse_observed_variance_as_standardised_manifest_variance; /// Refuse pooling discrete lags from unequal event intervals. @@ -1122,6 +1141,8 @@ pub use event_time::refuse_standardised_initial_time_dependent_effect_as_standar pub use event_time::refuse_standardised_initial_time_independent_effect_as_standardised_initial_time_dependent_effect; /// Refuse treating p. 16 `MANIFESTTRAITVARstd` as p. 16 `MANIFESTVARstd`. pub use event_time::refuse_standardised_manifest_trait_variance_as_standardised_manifest_variance; +/// Refuse treating p. 16 `MANIFESTVARstd` as p. 16 `MANIFESTMEANSstd`. +pub use event_time::refuse_standardised_manifest_variance_as_standardised_manifest_mean; /// Refuse treating p. 16 `MANIFESTVARstd` as p. 16 `TIPREDVARstd`. pub use event_time::refuse_standardised_manifest_variance_as_standardised_time_independent_predictor_variance; /// Refuse treating p. 16 `TIPREDVARstd` as p. 16 `asymDIFFUSIONstd`. @@ -1266,6 +1287,8 @@ pub use event_time::refuse_unstandardised_initial_latent_variance_as_standardise pub use event_time::refuse_unstandardised_initial_time_dependent_effect_as_standardised_initial_time_dependent_effect; /// Refuse treating unstandardised `T0TIPREDEFFECT` `t0_b` as Table 3 / p. 16 `T0TIPREDEFFECTstd`. pub use event_time::refuse_unstandardised_initial_time_independent_effect_as_standardised_initial_time_independent_effect; +/// Refuse treating unstandardised `MANIFESTMEANS` as p. 16 `MANIFESTMEANSstd`. +pub use event_time::refuse_unstandardised_manifest_mean_as_standardised_manifest_mean; /// Refuse treating unstandardised `MANIFESTTRAITVAR` as p. 16 `MANIFESTTRAITVARstd`. pub use event_time::refuse_unstandardised_manifest_trait_variance_as_standardised_manifest_trait_variance; /// Refuse treating unstandardised `MANIFESTVAR` as p. 16 `MANIFESTVARstd`. diff --git a/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs b/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs index 8a03c23d..681390d7 100644 --- a/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs +++ b/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs @@ -56,7 +56,8 @@ use psychometric_core::{ recover_standardised_initial_latent_variance, recover_standardised_initial_time_dependent_predictor_effect, recover_standardised_initial_time_independent_predictor_effect, - recover_standardised_manifest_trait_variance, recover_standardised_manifest_variance, + recover_standardised_manifest_mean, recover_standardised_manifest_trait_variance, + recover_standardised_manifest_variance, recover_standardised_time_independent_predictor_variance, recover_standardised_trait_variance, recover_stationary_initial_latent_mean, recover_stationary_initial_latent_variance, recover_stationary_initial_observed_mean, recover_stationary_initial_observed_variance, @@ -155,6 +156,7 @@ use psychometric_core::{ refuse_measurement_error_as_standardised_manifest_trait_variance, refuse_measurement_error_as_stationary_lagged_observed_covariance, refuse_measurement_error_as_stationary_later_observed_variance, + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean, refuse_observed_variance_as_standardised_manifest_variance, refuse_pooled_discrete_lag_across_unequal_intervals, refuse_predetermined_initial_latent_variance_as_initial_latent_variance, @@ -209,6 +211,7 @@ use psychometric_core::{ refuse_standardised_initial_time_dependent_effect_as_standardised_initial_latent_variance, refuse_standardised_initial_time_independent_effect_as_standardised_initial_time_dependent_effect, refuse_standardised_manifest_trait_variance_as_standardised_manifest_variance, + refuse_standardised_manifest_variance_as_standardised_manifest_mean, refuse_standardised_manifest_variance_as_standardised_time_independent_predictor_variance, refuse_standardised_time_independent_predictor_variance_as_standardised_asymptotic_diffusion, refuse_standardised_trait_variance_as_standardised_manifest_trait_variance, @@ -280,6 +283,7 @@ use psychometric_core::{ refuse_unstandardised_initial_latent_variance_as_standardised_initial_latent_variance, refuse_unstandardised_initial_time_dependent_effect_as_standardised_initial_time_dependent_effect, refuse_unstandardised_initial_time_independent_effect_as_standardised_initial_time_independent_effect, + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean, refuse_unstandardised_manifest_trait_variance_as_standardised_manifest_trait_variance, refuse_unstandardised_manifest_variance_as_standardised_manifest_variance, refuse_unstandardised_time_independent_predictor_variance_as_standardised_time_independent_predictor_variance, @@ -520,8 +524,6 @@ fn time_varying_predictor_discrete_effect_recovers_equation_fourteen() { let recovered = recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq 14"); @@ -545,7 +547,6 @@ fn time_varying_predictor_discrete_effect_recovers_equation_fourteen() { outcome_on_predictor, 1.0, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -563,8 +564,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, - 1.0, - 1.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -574,7 +573,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, f64::NAN, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -584,7 +582,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, 0.0, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -613,7 +610,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, - 1.0, f64::NAN, LagClock::EventTime ), @@ -623,7 +619,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, - 1.0, 0.0, LagClock::EventTime ), @@ -633,7 +628,6 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 2.0, - 2.0, 1.0, LagClock::EventTime ), @@ -647,8 +641,6 @@ fn time_varying_predictor_equation_fourteen_numeric_inputs_fail_closed() { recover_discrete_time_varying_predictor_effect( f64::NAN, 1.0, - 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -657,8 +649,6 @@ fn time_varying_predictor_equation_fourteen_numeric_inputs_fail_closed() { recover_discrete_time_varying_predictor_effect( 1e308, 10.0, - 10.0, - 10.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1568,8 +1558,6 @@ fn time_dependent_impulse_recovers_driver_equation_three_fourth_summand() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -1602,7 +1590,6 @@ fn time_dependent_impulse_refuses_overflow_and_non_event_clocks() { 0.3, 0.4, 2.0, - 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -1611,10 +1598,8 @@ fn time_dependent_impulse_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_impulse( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1802,8 +1787,6 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -1843,8 +1826,6 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { recover_discrete_observed_mean_with_impulse( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -1857,8 +1838,6 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -1900,8 +1879,6 @@ fn time_independent_predictor_recovers_driver_equation_three_second_summand() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -1975,10 +1952,8 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_time_independent_predictor( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1990,7 +1965,6 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { 0.3, 1e308, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2112,10 +2086,8 @@ fn initial_time_independent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_initial_time_independent_predictor( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2261,10 +2233,8 @@ fn initial_time_dependent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_initial_time_dependent_predictor( 1e308, 0.0, - 0.0, 1e308, 1.0, - 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2587,8 +2557,6 @@ fn discrete_observed_mean_with_initial_time_independent_predictor_refuses_overfl 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -2628,8 +2596,6 @@ fn discrete_observed_mean_with_initial_time_independent_predictor_refuses_overfl 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -2884,8 +2850,6 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -2925,8 +2889,6 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -2939,8 +2901,6 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -2990,8 +2950,6 @@ fn time_dependent_impulse_carry_recovers_driver_equation_one_two_dissipation() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, - delta, - delta, LagClock::EventTime, ) .expect("eq14"); @@ -3068,7 +3026,6 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { 3.0, -0.5, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -3077,7 +3034,6 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_impulse_carry( 1e308, 0.0, - 0.0, 1e308, 1.0, 2.0, @@ -3099,7 +3055,6 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { ); assert_eq!( recover_time_dependent_predictor_impulse_carry( - 1.0, 1.0, 1_000.0, 2.0, @@ -3285,8 +3240,6 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 2.0, @@ -3320,7 +3273,6 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 3.0, 0.5, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -3329,8 +3281,6 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc recover_discrete_observed_mean_with_impulse_carry( 1e308, 0.0, - 0.0, - 0.0, 1e308, 1.0, 0.0, @@ -3344,8 +3294,6 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 2.0, @@ -3704,8 +3652,6 @@ fn discrete_observed_mean_with_initial_time_dependent_predictor_refuses_overflow 1e308, 2.0, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -3745,8 +3691,6 @@ fn discrete_observed_mean_with_initial_time_dependent_predictor_refuses_overflow 1e308, 1e-308, 0.0, - 0.0, - 0.0, 3.0, 0.0, 1.0, @@ -4044,6 +3988,16 @@ fn extra_process_contribution_refuses_nonnegative_extra_drift_clock_and_overflow ), Ok(0.0) ); + let overflow_fallback = recover_level_change_extra_process_contribution( + 0.4, + 3.0, + -0.8, + -0.000_001, + 900.0, + LagClock::EventTime, + ) + .expect("expm1-overflow-fallback"); + assert!(overflow_fallback.is_finite()); let finite_exp_m1_overflow = recover_level_change_extra_process_contribution( 0.4, 3.0, @@ -4288,7 +4242,6 @@ fn extra_process_observed_mean_refuses_clock_nonpositive_interval_and_nonnegativ recover_discrete_latent_mean_with_extra_process( 1e308, 0.0, - 0.0, 1e308, 1.0, extra, @@ -4446,7 +4399,6 @@ fn after_extra_process_observed_mean_refuses_non_interior_interval_and_clock() { original, extra, 2.0, - 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -4469,7 +4421,6 @@ fn after_extra_process_observed_mean_refuses_non_interior_interval_and_clock() { ); assert_eq!( recover_discrete_observed_mean_with_extra_process_after( - 0.0, 0.0, original, 0.0, @@ -4693,6 +4644,14 @@ fn asymptotic_time_independent_variance_refuses_unstable_drift_and_non_event_clo recover_asymptotic_time_independent_predictor_variance(0.0, 1.0, 0.0, LagClock::EventTime), Ok(0.0) ); + assert_eq!( + recover_asymptotic_time_independent_predictor_variance( + 1.0, + -1e-308, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_asymptotic_time_independent_predictor_variance( f64::MAX, @@ -5003,7 +4962,6 @@ fn stationary_initial_observed_mean_refuses_unstable_drift_and_non_event_clocks( -0.225, 1.0, 0.5, - 0.5, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -5060,8 +5018,6 @@ fn stationary_initial_latent_variance_recovers_driver_section_four_point_three() assert!(rmse(&[recovered], &[2.838]) > error); assert_eq!( recover_stationary_initial_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, log_rate, @@ -5073,7 +5029,6 @@ fn stationary_initial_latent_variance_recovers_driver_section_four_point_three() recover_stationary_initial_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -5136,7 +5091,6 @@ fn stationary_initial_latent_variance_refuses_unstable_drift_and_non_event_clock f64::NAN, 0.4, 0.0, - 0.0, -0.5, LagClock::EventTime ), @@ -5145,8 +5099,6 @@ fn stationary_initial_latent_variance_refuses_unstable_drift_and_non_event_clock assert_eq!( recover_stationary_initial_latent_variance( f64::MAX, - f64::MAX, - 0.0, 0.0, -0.5, LagClock::EventTime @@ -5313,11 +5265,9 @@ fn stationary_initial_observed_variance_refuses_unstable_drift_and_non_event_clo recover_stationary_initial_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, - 0.5, 0.0, LagClock::EventTime ), @@ -5327,8 +5277,6 @@ fn stationary_initial_observed_variance_refuses_unstable_drift_and_non_event_clo recover_stationary_initial_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 0.5, @@ -5403,8 +5351,6 @@ fn stationary_lagged_latent_covariance_recovers_driver_section_four_point_three( assert!(rmse(&[recovered], &[trait_plus_state]) > error); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, - 0.0, 0.0, predictor_variance, log_rate, @@ -5417,7 +5363,6 @@ fn stationary_lagged_latent_covariance_recovers_driver_section_four_point_three( recover_stationary_lagged_latent_covariance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -5500,7 +5445,6 @@ fn stationary_lagged_latent_covariance_refuses_unstable_drift_and_non_event_cloc ); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, 0.0, -0.225, 1.0, @@ -5512,8 +5456,6 @@ fn stationary_lagged_latent_covariance_refuses_unstable_drift_and_non_event_cloc ); assert_eq!( recover_stationary_lagged_latent_covariance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -5668,7 +5610,6 @@ fn stationary_lagged_observed_covariance_refuses_unstable_drift_and_non_event_cl recover_stationary_lagged_observed_covariance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -5682,8 +5623,6 @@ fn stationary_lagged_observed_covariance_refuses_unstable_drift_and_non_event_cl recover_stationary_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -5773,8 +5712,6 @@ fn stationary_later_latent_variance_recovers_driver_section_four_point_three() { assert!(rmse(&[recovered], &[process_noise]) > error); assert_eq!( recover_stationary_later_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, log_rate, @@ -5787,7 +5724,6 @@ fn stationary_later_latent_variance_recovers_driver_section_four_point_three() { recover_stationary_later_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -5852,7 +5788,6 @@ fn stationary_later_latent_variance_refuses_unstable_drift_and_non_event_clocks( ); assert_eq!( recover_stationary_later_latent_variance( - 0.0, 0.0, -0.225, 1.0, @@ -6024,7 +5959,6 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock 0.0, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::StationaryVarianceRequiresStableDrift) @@ -6033,13 +5967,11 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock recover_stationary_later_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -6048,8 +5980,6 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock recover_stationary_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -6151,9 +6081,6 @@ fn predetermined_later_latent_variance_recovers_driver_section_four_point_three( assert!(rmse(&[from_stationary_start], &[stationary_later]) < 1e-12); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, log_rate, @@ -6166,8 +6093,6 @@ fn predetermined_later_latent_variance_recovers_driver_section_four_point_three( recover_predetermined_later_latent_variance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -6249,8 +6174,6 @@ fn predetermined_later_latent_variance_refuses_non_event_clocks_and_keeps_growin assert!((growing - 2.4).abs() < 1e-12); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -6262,9 +6185,6 @@ fn predetermined_later_latent_variance_refuses_non_event_clocks_and_keeps_growin ); assert_eq!( recover_predetermined_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -6427,7 +6347,6 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow 0.0, 1.0, 0.0, - 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -6436,14 +6355,11 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow recover_predetermined_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -6452,9 +6368,6 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow recover_predetermined_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -6555,8 +6468,6 @@ fn predetermined_lagged_latent_covariance_recovers_driver_section_four_point_thr assert!(rmse(&[from_stationary_start], &[stationary_lagged]) < 1e-12); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -6569,7 +6480,6 @@ fn predetermined_lagged_latent_covariance_recovers_driver_section_four_point_thr recover_predetermined_lagged_latent_covariance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, event_delta, @@ -6653,7 +6563,6 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro 0.0, 2.0, 0.0, - 0.0, 0.5, 1.0, LagClock::EventTime, @@ -6664,8 +6573,6 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro 0.0, 2.0, 0.0, - 0.0, - 0.0, 1.0, LagClock::EventTime, ) @@ -6673,7 +6580,6 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro assert!((brownian - 2.0).abs() < 1e-12); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, 0.0, -0.225, 1.0, @@ -6685,8 +6591,6 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro ); assert_eq!( recover_predetermined_lagged_latent_covariance( - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -6878,7 +6782,6 @@ fn predetermined_lagged_observed_covariance_refuses_non_event_clocks_and_keeps_g recover_predetermined_lagged_observed_covariance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -6892,8 +6795,6 @@ fn predetermined_lagged_observed_covariance_refuses_non_event_clocks_and_keeps_g recover_predetermined_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 1.0, @@ -7008,8 +6909,6 @@ fn predetermined_initial_latent_variance_recovers_driver_section_four_point_thre assert!(rmse(&[near_later], &[recovered]) < 1e-9); assert_eq!( recover_predetermined_initial_latent_variance( - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -7021,7 +6920,6 @@ fn predetermined_initial_latent_variance_recovers_driver_section_four_point_thre recover_predetermined_initial_latent_variance( trait_variance, 0.0, - 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -7076,7 +6974,6 @@ fn predetermined_initial_latent_variance_refuses_non_event_clocks_and_keeps_unst assert!((brownian - 2.0).abs() < 1e-12); assert_eq!( recover_predetermined_initial_latent_variance( - 0.0, 0.0, -0.225, 1.0, @@ -7237,8 +7134,6 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un 0.0, 1.0, 0.0, - 0.0, - 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -7247,12 +7142,10 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un recover_predetermined_initial_observed_variance( 2.0, 0.0, - 0.0, -0.225, 1.0, 0.5, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -7261,8 +7154,6 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un recover_predetermined_initial_observed_variance( 2.0, 0.0, - 0.0, - 0.0, 1.0, 0.0, 0.5, @@ -7405,9 +7296,6 @@ fn predetermined_later_lagged_latent_covariance_recovers_driver_section_four_poi assert!(rmse(&[near_later], &[later]) < 1e-9); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -7421,8 +7309,6 @@ fn predetermined_later_lagged_latent_covariance_recovers_driver_section_four_poi recover_predetermined_later_lagged_latent_covariance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, start_delta, @@ -7513,18 +7399,14 @@ fn predetermined_later_lagged_latent_covariance_refuses_non_event_clocks_and_kee 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, LagClock::EventTime, ) .expect("growing a>0"); assert!(growing.is_finite() && growing > 2.0); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -7537,9 +7419,6 @@ fn predetermined_later_lagged_latent_covariance_refuses_non_event_clocks_and_kee ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( - 0.0, - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -7741,10 +7620,8 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, 0.0, LagClock::EventTime, ) @@ -7754,8 +7631,6 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, @@ -7770,9 +7645,6 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 2.0, @@ -7962,9 +7834,6 @@ fn predetermined_later_start_later_latent_variance_recovers_driver_section_four_ assert!(rmse(&[near_first], &[later_over_s]) < 1e-9); assert_eq!( recover_predetermined_later_start_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, predictor_variance, 0.0, @@ -7978,8 +7847,6 @@ fn predetermined_later_start_later_latent_variance_recovers_driver_section_four_ recover_predetermined_later_start_later_latent_variance( trait_variance, 0.0, - 0.0, - 0.0, predictor_variance, 0.0, start_delta, @@ -8080,18 +7947,14 @@ fn predetermined_later_start_later_latent_variance_refuses_non_event_clocks_and_ 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, LagClock::EventTime, ) .expect("growing a>0"); assert!(growing.is_finite() && growing > 2.0); assert_eq!( recover_predetermined_later_start_later_latent_variance( - 0.0, - 0.0, 0.0, -0.225, 1.0, @@ -8104,9 +7967,6 @@ fn predetermined_later_start_later_latent_variance_refuses_non_event_clocks_and_ ); assert_eq!( recover_predetermined_later_start_later_latent_variance( - 0.0, - 0.0, - 0.0, 0.0, 1.0, 0.0, @@ -8320,11 +8180,8 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an 2.0, 0.4, 0.0, - 0.0, 0.5, 1.0, - 1.0, - 0.0, 0.0, LagClock::EventTime, ) @@ -8334,15 +8191,12 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, -0.225, 1.0, 0.5, 2.0, 1.0, 0.0, - 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -8351,9 +8205,6 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, - 0.0, - 0.0, - 0.0, 1.0, 0.0, 2.0, @@ -9996,6 +9847,83 @@ fn standardised_initial_latent_mean_refuses_non_event_clocks_and_does_not_keep_z ); } +#[test] +fn standardised_manifest_mean_recovers_driver_page_sixteen_after_positive_manifestvar() { + let mean = 0.8_f64; + let measurement_error = 1.6_f64; + let recovered = + recover_standardised_manifest_mean(mean, measurement_error, LagClock::EventTime) + .expect("MANIFESTMEANSstd"); + let expected = mean / measurement_error.sqrt(); + assert!((recovered - expected).abs() < 1e-15); + let recovered_error = (recovered - expected).abs(); + let negative = + recover_standardised_manifest_mean(-mean, measurement_error, LagClock::EventTime) + .expect("negative signed MANIFESTMEANSstd"); + assert!((negative + expected).abs() < 1e-15); + let unstd_rmse = (mean - expected).abs(); + assert!( + recovered_error < unstd_rmse, + "Driver et al. (2017, p. 16): unstandardised MANIFESTMEANS RMSE {unstd_rmse} must exceed MANIFESTMEANSstd RMSE {recovered_error}" + ); + let variance_std = + recover_standardised_manifest_variance(measurement_error, LagClock::EventTime) + .expect("MANIFESTVARstd"); + let unit = recover_standardised_manifest_mean( + measurement_error.sqrt(), + measurement_error, + LagClock::EventTime, + ) + .expect("MANIFESTMEANSstd τ=√θ"); + assert!((unit - variance_std).abs() < 1e-15); + let loading = 1.2_f64; + let latent_variance = 0.9_f64; + let observed = loading * loading * latent_variance + measurement_error; + let observed_scaled = mean / observed.sqrt(); + let observed_rmse = (observed_scaled - expected).abs(); + assert!( + recovered_error < observed_rmse, + "Driver et al. (2017, p. 16): τ / √(λ² Var(η) + θ) RMSE {observed_rmse} must exceed MANIFESTMEANSstd RMSE {recovered_error}" + ); + let larger = recover_standardised_manifest_mean(mean, 6.4, LagClock::EventTime) + .expect("MANIFESTMEANSstd θ=6.4"); + assert!((larger - recovered).abs() > 1e-3); + let zero = recover_standardised_manifest_mean(0.0, measurement_error, LagClock::EventTime) + .expect("zero MANIFESTMEANS"); + assert_eq!(zero.to_bits(), 0.0_f64.to_bits()); + let matching_t0 = + recover_standardised_initial_latent_mean(mean, measurement_error, LagClock::EventTime) + .expect("T0MEANSstd same numbers"); + assert!((matching_t0 - recovered).abs() < 1e-15); + assert_eq!( + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean(mean, recovered), + Err(PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean) + ); + assert_eq!( + refuse_standardised_manifest_variance_as_standardised_manifest_mean(variance_std, unit), + Err(PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean) + ); + assert_eq!( + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean( + observed_scaled, + recovered + ), + Err(PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean) + ); +} + +#[test] +fn standardised_manifest_mean_refuses_non_event_clocks_and_does_not_keep_zero_residual() { + assert_eq!( + recover_standardised_manifest_mean(0.8, 1.6, LagClock::SystemTime), + Err(PsychometricError::EventTimeRequired) + ); + assert_eq!( + recover_standardised_manifest_mean(0.8, 0.0, LagClock::EventTime), + Err(PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance) + ); +} + #[test] fn standardised_initial_time_independent_effect_recovers_driver_table_three_footnote_four() { let initial_variance = 1.6_f64; diff --git a/crates/psychometric_core/tests/scientific_claim_boundary_contract.rs b/crates/psychometric_core/tests/scientific_claim_boundary_contract.rs index f246619b..ded2e96c 100644 --- a/crates/psychometric_core/tests/scientific_claim_boundary_contract.rs +++ b/crates/psychometric_core/tests/scientific_claim_boundary_contract.rs @@ -52,7 +52,8 @@ use psychometric_core::{ recover_standardised_initial_latent_variance, recover_standardised_initial_time_dependent_predictor_effect, recover_standardised_initial_time_independent_predictor_effect, - recover_standardised_manifest_trait_variance, recover_standardised_manifest_variance, + recover_standardised_manifest_mean, recover_standardised_manifest_trait_variance, + recover_standardised_manifest_variance, recover_standardised_time_independent_predictor_variance, recover_standardised_trait_variance, recover_stationary_initial_latent_mean, recover_stationary_initial_latent_variance, recover_stationary_initial_observed_mean, recover_stationary_initial_observed_variance, @@ -151,6 +152,7 @@ use psychometric_core::{ refuse_measurement_error_as_standardised_manifest_trait_variance, refuse_measurement_error_as_stationary_lagged_observed_covariance, refuse_measurement_error_as_stationary_later_observed_variance, + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean, refuse_observed_variance_as_standardised_manifest_variance, refuse_predetermined_initial_latent_variance_as_initial_latent_variance, refuse_predetermined_initial_latent_variance_as_lagged_latent_covariance, @@ -204,6 +206,7 @@ use psychometric_core::{ refuse_standardised_initial_time_dependent_effect_as_standardised_initial_latent_variance, refuse_standardised_initial_time_independent_effect_as_standardised_initial_time_dependent_effect, refuse_standardised_manifest_trait_variance_as_standardised_manifest_variance, + refuse_standardised_manifest_variance_as_standardised_manifest_mean, refuse_standardised_manifest_variance_as_standardised_time_independent_predictor_variance, refuse_standardised_time_independent_predictor_variance_as_standardised_asymptotic_diffusion, refuse_standardised_trait_variance_as_standardised_manifest_trait_variance, @@ -274,6 +277,7 @@ use psychometric_core::{ refuse_unstandardised_initial_latent_variance_as_standardised_initial_latent_variance, refuse_unstandardised_initial_time_dependent_effect_as_standardised_initial_time_dependent_effect, refuse_unstandardised_initial_time_independent_effect_as_standardised_initial_time_independent_effect, + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean, refuse_unstandardised_manifest_trait_variance_as_standardised_manifest_trait_variance, refuse_unstandardised_manifest_variance_as_standardised_manifest_variance, refuse_unstandardised_time_independent_predictor_variance_as_standardised_time_independent_predictor_variance, @@ -5785,6 +5789,85 @@ fn standardised_initial_latent_mean_is_not_unstandardised_or_t0varstd() { ); } +#[allow(clippy::too_many_lines)] +#[test] +fn standardised_manifest_mean_is_not_unstandardised_or_manifestvarstd() { + let mean = 0.8_f64; + let measurement_error = 1.6_f64; + let recovered = + recover_standardised_manifest_mean(mean, measurement_error, LagClock::EventTime) + .expect("MANIFESTMEANSstd"); + let expected = mean / measurement_error.sqrt(); + assert!( + (recovered - expected).abs() < 1e-15, + "Driver et al. (2017, p. 16 / footnote 4): MANIFESTMEANSstd is τ / √θ" + ); + let variance_std = + recover_standardised_manifest_variance(measurement_error, LagClock::EventTime) + .expect("MANIFESTVARstd"); + let unit = recover_standardised_manifest_mean( + measurement_error.sqrt(), + measurement_error, + LagClock::EventTime, + ) + .expect("MANIFESTMEANSstd τ=√θ"); + assert!( + (unit - variance_std).abs() < 1e-15, + "Driver et al. (2017, p. 16): equal 1 with MANIFESTVARstd remains a distinct named quantity" + ); + let loading = 1.2_f64; + let latent_variance = 0.9_f64; + let observed = loading * loading * latent_variance + measurement_error; + let observed_scaled = mean / observed.sqrt(); + assert!( + (observed_scaled - recovered).abs() > 1e-3, + "Driver et al. (2017, p. 16): τ / √(λ² Var(η) + θ) is not MANIFESTMEANSstd" + ); + let larger = recover_standardised_manifest_mean(mean, 6.4, LagClock::EventTime) + .expect("MANIFESTMEANSstd θ=6.4"); + assert!((larger - recovered).abs() > 1e-3); + let zero = recover_standardised_manifest_mean(0.0, measurement_error, LagClock::EventTime) + .expect("zero MANIFESTMEANS"); + assert_eq!(zero.to_bits(), 0.0_f64.to_bits()); + let matching_t0 = + recover_standardised_initial_latent_mean(mean, measurement_error, LagClock::EventTime) + .expect("T0MEANSstd same numbers"); + assert!( + (matching_t0 - recovered).abs() < 1e-15, + "Driver et al. (2017, p. 16): equal numbers with T0MEANSstd remain distinct named quantities" + ); + assert_eq!( + recover_standardised_manifest_mean(mean, 0.0, LagClock::EventTime), + Err( + psychometric_core::PsychometricError::StandardisedManifestMeanRequiresPositiveManifestVariance + ) + ); + assert_eq!( + recover_standardised_manifest_mean(mean, measurement_error, LagClock::SystemTime), + Err(psychometric_core::PsychometricError::EventTimeRequired) + ); + assert_eq!( + refuse_unstandardised_manifest_mean_as_standardised_manifest_mean(mean, recovered), + Err( + psychometric_core::PsychometricError::UnstandardisedManifestMeanIsNotStandardisedManifestMean + ) + ); + assert_eq!( + refuse_standardised_manifest_variance_as_standardised_manifest_mean(variance_std, unit), + Err( + psychometric_core::PsychometricError::StandardisedManifestVarianceIsNotStandardisedManifestMean + ) + ); + assert_eq!( + refuse_observed_scaled_manifest_mean_as_standardised_manifest_mean( + observed_scaled, recovered + ), + Err( + psychometric_core::PsychometricError::ObservedScaledManifestMeanIsNotStandardisedManifestMean + ) + ); +} + #[allow(clippy::too_many_lines)] #[test] fn standardised_initial_time_independent_effect_is_not_unstandardised_or_trait_contaminated() { diff --git a/crates/topic_measurement/src/reference.rs b/crates/topic_measurement/src/reference.rs index ec5f223c..7d375395 100644 --- a/crates/topic_measurement/src/reference.rs +++ b/crates/topic_measurement/src/reference.rs @@ -127,6 +127,83 @@ impl ReferenceTopicInput { pub fn features(&self) -> &[PrevalenceFeature] { &self.features } + + /// Return the total token count used as the BIC sample size `N`. + /// + /// # Errors + /// + /// Returns [`TopicMeasurementError::InvalidModelInput`] when the counts are + /// empty, non-positive, or non-finite. + pub fn token_count(&self) -> Result { + let mut total = 0.0_f64; + for row in &self.term_rows { + for &(_, count) in row { + if !count.is_finite() || count < 0.0 { + return Err(TopicMeasurementError::InvalidModelInput); + } + total += count; + } + } + if total.is_finite() && total > 0.0 { + Ok(total) + } else { + Err(TopicMeasurementError::InvalidModelInput) + } + } + + /// In-sample mixture log-likelihood of a fitted model on these counts. + /// + /// This is the first term of the ADR 0012 MAP objective, + /// `Σ C_dv log(Σ_k θ_dk β_kv)`, evaluated on the fitted `θ` and `β`. It is + /// not the penalized objective and not a held-out split. + /// + /// # Errors + /// + /// Returns [`TopicMeasurementError::InvalidModelInput`] when the fitted + /// dimensions do not match this input, or + /// [`TopicMeasurementError::NonFiniteEstimate`] when a mixture probability + /// is not a finite positive value. + pub fn in_sample_log_likelihood( + &self, + model: &ReferenceTopicModel, + ) -> Result { + let topic_count = model.topic_term_probabilities.len(); + if topic_count < 2 + || model.document_topic_proportions.len() != self.document_ids.len() + || model + .topic_term_probabilities + .iter() + .any(|row| row.len() != self.vocabulary_size) + || model + .document_topic_proportions + .iter() + .any(|row| row.len() != topic_count) + { + return Err(TopicMeasurementError::InvalidModelInput); + } + let mut log_likelihood = 0.0_f64; + for (document, terms) in self.term_rows.iter().enumerate() { + let theta = &model.document_topic_proportions[document]; + for &(term, count) in terms { + if term >= self.vocabulary_size { + return Err(TopicMeasurementError::InvalidModelInput); + } + let probability = (0..topic_count) + .map(|topic| theta[topic] * model.topic_term_probabilities[topic][term]) + .sum::(); + let log_probability = probability.ln(); + if !log_probability.is_finite() { + return Err(TopicMeasurementError::NonFiniteEstimate); + } + log_likelihood += count * log_probability; + } + } + if log_likelihood.is_finite() { + Ok(log_likelihood) + } else { + Err(TopicMeasurementError::NonFiniteEstimate) + } + } } fn build_design( @@ -752,9 +829,9 @@ fn next_unit(state: &mut u64) -> f64 { #[cfg(test)] mod tests { use super::{ - FitState, PrevalenceFeature, ReferenceTopicInput, ReferenceTopicModelConfig, argmax, - bounded_count, build_result, dot, expectation, next_unit, normalize, objective, - require_finite, standardize_event_time, + FitState, PrevalenceFeature, ReferenceTopicInput, ReferenceTopicModel, + ReferenceTopicModelConfig, argmax, bounded_count, build_result, dot, expectation, + next_unit, normalize, objective, require_finite, standardize_event_time, }; use crate::TopicMeasurementError; use temporal_core::EventTime; @@ -874,4 +951,123 @@ mod tests { Err(TopicMeasurementError::InvalidModelInput) ); } + + fn scoring_input( + term_rows: Vec>, + vocabulary_size: usize, + ) -> ReferenceTopicInput { + ReferenceTopicInput { + document_ids: vec![Uuid::from_u128(1), Uuid::from_u128(2)], + term_rows, + vocabulary_size, + design: vec![vec![1.0], vec![1.0]], + features: vec![PrevalenceFeature::Intercept], + transition_pairs: vec![(0, 1)], + } + } + + fn scoring_model( + topic_term_probabilities: Vec>, + document_topic_proportions: Vec>, + ) -> ReferenceTopicModel { + ReferenceTopicModel { + seed: 1, + iterations: 4, + objective: -1.0, + topic_term_probabilities, + document_topic_proportions, + document_coordinate_variances: vec![vec![0.1], vec![0.1]], + prevalence_coefficients: vec![vec![0.0]], + prevalence_features: vec![PrevalenceFeature::Intercept], + sequence_edges: Vec::new(), + connected_post_count: 0, + lineage_count: 0, + } + } + + #[test] + fn in_sample_likelihood_and_token_count_fail_closed() { + let input = scoring_input(vec![vec![(0, 1.0)], vec![(1, 2.0)]], 2); + assert!((input.token_count().expect("tokens") - 3.0).abs() < f64::EPSILON); + let model = scoring_model( + vec![vec![0.9, 0.1], vec![0.1, 0.9]], + vec![vec![0.8, 0.2], vec![0.2, 0.8]], + ); + assert!( + input + .in_sample_log_likelihood(&model) + .expect("ll") + .is_finite() + ); + + assert_eq!( + scoring_input(vec![vec![]], 2).token_count(), + Err(TopicMeasurementError::InvalidModelInput) + ); + assert_eq!( + scoring_input(vec![vec![(0, 0.0)], vec![(1, 0.0)]], 2).token_count(), + Err(TopicMeasurementError::InvalidModelInput) + ); + assert_eq!( + scoring_input(vec![vec![(0, f64::NAN)], vec![(1, 1.0)]], 2).token_count(), + Err(TopicMeasurementError::InvalidModelInput) + ); + assert_eq!( + scoring_input(vec![vec![(0, -1.0)], vec![(1, 1.0)]], 2).token_count(), + Err(TopicMeasurementError::InvalidModelInput) + ); + assert_eq!( + scoring_input(vec![vec![(0, f64::MAX)], vec![(1, f64::MAX)]], 2).token_count(), + Err(TopicMeasurementError::InvalidModelInput) + ); + + let short_docs = scoring_model(vec![vec![0.5, 0.5], vec![0.5, 0.5]], vec![vec![0.5, 0.5]]); + assert_eq!( + input.in_sample_log_likelihood(&short_docs), + Err(TopicMeasurementError::InvalidModelInput) + ); + let one_topic = scoring_model(vec![vec![1.0, 0.0]], vec![vec![1.0], vec![1.0]]); + assert_eq!( + input.in_sample_log_likelihood(&one_topic), + Err(TopicMeasurementError::InvalidModelInput) + ); + let wide_beta = scoring_model( + vec![vec![0.5, 0.5, 0.0], vec![0.5, 0.5, 0.0]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + ); + assert_eq!( + input.in_sample_log_likelihood(&wide_beta), + Err(TopicMeasurementError::InvalidModelInput) + ); + let wide_theta = scoring_model( + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.5, 0.5, 0.0], vec![0.5, 0.5, 0.0]], + ); + assert_eq!( + input.in_sample_log_likelihood(&wide_theta), + Err(TopicMeasurementError::InvalidModelInput) + ); + let out_of_range = scoring_input(vec![vec![(3, 1.0)], vec![(0, 1.0)]], 2); + let matching = scoring_model( + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + ); + assert_eq!( + out_of_range.in_sample_log_likelihood(&matching), + Err(TopicMeasurementError::InvalidModelInput) + ); + let zero_beta = scoring_model( + vec![vec![0.0, 0.0], vec![0.0, 0.0]], + vec![vec![0.5, 0.5], vec![0.5, 0.5]], + ); + assert_eq!( + input.in_sample_log_likelihood(&zero_beta), + Err(TopicMeasurementError::NonFiniteEstimate) + ); + let overflow_counts = scoring_input(vec![vec![(0, f64::MAX)], vec![(1, f64::MAX)]], 2); + assert_eq!( + overflow_counts.in_sample_log_likelihood(&matching), + Err(TopicMeasurementError::NonFiniteEstimate) + ); + } } diff --git a/crates/topic_measurement/tests/reference_estimator_contract.rs b/crates/topic_measurement/tests/reference_estimator_contract.rs index 2aa6de87..8fb3e1e3 100644 --- a/crates/topic_measurement/tests/reference_estimator_contract.rs +++ b/crates/topic_measurement/tests/reference_estimator_contract.rs @@ -188,6 +188,13 @@ fn separated_topics_recover_and_emit_predecessor_successor_counts() { .expect("rmse") .min(root_mean_square_error(&truth_b, &recovered).expect("label-swapped rmse")); assert!(rmse < 0.25, "known-truth topic RMSE {rmse} exceeded 0.25"); + + let log_likelihood = input + .in_sample_log_likelihood(&result) + .expect("in-sample mixture log-likelihood"); + assert!(log_likelihood.is_finite()); + let tokens = input.token_count().expect("token count"); + assert!((tokens - 600.0).abs() < f64::EPSILON); } #[test] diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 6bb9ca78..8709f7f6 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -60,7 +60,7 @@ The full APA 7th standards/literature register remains `docs/research/standards- | executable cutoff-safe analysis runs | ADR 0012/0022; temporal research; API terminal-result contract | `analysis_engine` availability cutoff, snapshot binding, multiple-membership aggregation, digest-bound readiness artifact, and `tepp.trsl_topic_lineage.v1` execution through `topic_measurement`; synthetic recovery plus tamper/non-convergence tests and exact coverage on the active product branch | active-PR | | immutable split/run/reproducibility manifests | ADR 0013; ERD | `tepp_api` reproducibility manifest contract on protected main; `persistence_postgres` append-only SQL insert/lookup for `reproducibility_manifest`, `corpus_split_manifest`, `model_run`, and `model_artifact` (migration `0003`); full physical ERD constraints remaining | partial | | multilingual shared latent semantic space | PRD; ADR 0004; ADR 0020 | `semantic_core` span-grounded units (active-PR); concept dictionary and shared latent estimator remaining | active-PR | -| TRSL-TM temporal/relational topic posterior and backend compatibility | ADR 0012; ADR 0004 | `topic_measurement` stable ALR/ILR coordinates and bounded CPU `f64` reference estimator on the active product branch; calibrated posterior promotion, method effects, persistence, and accelerated backends remaining | partial | +| TRSL-TM temporal/relational topic posterior and backend compatibility | ADR 0012; ADR 0004 | `topic_measurement` stable ALR/ILR coordinates and bounded CPU `f64` reference estimator on protected main; `model_selection` fitted candidate-`K` scoring on this PR; calibrated posterior promotion, method effects, persistence, and accelerated backends remaining | partial | | global P0 topic identity with activity/dormancy/reactivation | ADR 0012 | `topic_lineage` activity/dormancy/reactivation identity on the active product branch; birth/split/merge remain later extensions | partial | | no default stopword deletion / no TF-IDF-BM25 inferential weighting | ADR 0004/0012; PRD/TRD | `topic_measurement::refuse_lexical_inferential_weight` on the active PR; preprocessing pipeline remaining | partial | | TRSL-TM temporal/relational topic posterior and backend compatibility | ADR 0012; ADR 0004 | future `topic_measurement` | accepted-target | @@ -74,9 +74,9 @@ The full APA 7th standards/literature register remains `docs/research/standards- | report template/section/copied/style/modality method effects | ADR 0004/0012; PRD/TRD | simulation truth factors implemented; `modality_source` modality-versus-unique-content identity on the active PR; estimator-side method model remains future | partial | | report template/section/copied/style/modality method effects | ADR 0004/0012; PRD/TRD | simulation truth factors implemented; `corpus_background` background-versus-unique-content identity on the active PR; estimator-side method model remains future | partial | | report template/section/copied/style/modality method effects | ADR 0004/0012; PRD/TRD | simulation truth factors implemented; `prompt_source` prompt-versus-unique-content identity on the active PR; estimator-side method model remains future | partial | -| candidate K statistical/Pareto gates | ADR 0012; research | `model_selection` statistical/Pareto `K` gate on the active PR; candidate blinding, blinded LLM review, and backend comparison remain accepted-target | active-PR | +| candidate K statistical/Pareto gates | ADR 0012; research | `model_selection` fits each candidate `K` with the CPU `f64` reference and scores the actual mixture likelihood plus Schwarz's (1978) `ℓ − (p ln N)/2` penalty before the Pareto gate; candidate blinding, blinded LLM review, GPU, and backend comparison remain accepted-target | active-PR | | compositional topic correlation / stable clustering | ADR 0005/0012; research | future `network_analysis` | accepted-target | -| posterior ESEM / longitudinal invariance / DSEM | ADR 0005 | `psychometric_core` construct/input gates, true-loading OLS recovery, posterior-draw point-estimate averaging, Rubin `T` on draw-level OLS loadings, CWC within/between OLS plus the contextual effect, event-time log-rate, constant- and time-varying-predictor discrete effects (Voelkle Eqs. 12 and 14), exact scalar discrete process noise (Driver et al., 2017, Eq. 3), lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; `asymDIFFUSION`), trait-plus-state variance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise), observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5; Table 2 `MANIFESTVAR` is `Θ`, not `Var(y)`; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; `Θ` does not enter lagged observed covariance; observed-indicator mean is `τ + λ μ`; `MANIFESTMEANS` is not `E(y)`; `CINT` is not `MANIFESTMEANS`; discrete latent mean is `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ`; `T0MEANS` is not `μ_t`; evolved observed mean is `τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`; contemporaneous `TDPREDEFFECT` impulse is `m x`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that contemporaneous impulse is `τ + λ(μ_t + m x)`, and `τ + λ μ_t` is not that observed mean; time-independent `TIPREDEFFECT` increment is `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, not `M x`, not Voelkle Eq. 14, and not the coefficient `B`; Eq. 5 of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`; within-interval `TDPREDEFFECT` carry is `e^{A(t−u)} M x` for `t0 < u < t`, not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that carried observed mean when `u ≠ t`; §7.2 level-change `CINT` is `κ = −a m x` (`a < 0`; not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`; Eq. 3 of that setting is `(1 − e^{a Δt}) m x`); §7.2 extra-process contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, not the dissipating Dirac; `ε ≥ 0` fails closed; Eq. 5 of that contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean; after-t0 extra-process `TDPREDEFFECT` uses `t − u` with `t0 < u < t` while `μ_t` uses `Δt`; that after-t0 observed mean is not the first-occasion extra-process observed mean; §7.2 `asymTIPREDEFFECT` is `-B z / a` for `a < 0` and is not `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; §7.2 `addedTIPREDVAR` is `(B / a)² v` and is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`; Table 2 `asymCINT` is `-κ / a` for `a < 0` and is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; p. 16 stationary `T0MEANS` is `-κ / a + −B z / a` and is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean; Eq. 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`; stationary `T0VAR` is `trait + −q / (2 a) + (B / a)² v` (not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)); lagged stationary `T0VAR` is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (trait and `addedTIPREDVAR` do not decay; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map; Eq. 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`; `Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance); later-occasion stationary `T0VAR` is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt`; `Q_Δt` is not that later map; Eq. 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`; lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not `Var(y_t)`; the later-occasion latent variance is not `Var(y_t)`); predetermined later-occasion `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_t)`; the predetermined later-occasion latent variance is not `Var(y_t)`; stationary later observed variance is not that observed variance when `p_0` is free); predetermined lagged `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map; Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`; `MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free; the predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`; free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map; Eq. 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the §7.1 trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`;))))), irregular already-centered residual lag, and strong/strict-gated latent means on the stacked psychometric PR (two-observation residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016, PMC5145197 opened 2026-08-19T22:15Z); full ESEM/DSEM remaining | partial | +| posterior ESEM / longitudinal invariance / DSEM | ADR 0005 | `psychometric_core` construct/input gates, true-loading OLS recovery, posterior-draw point-estimate averaging, Rubin `T` on draw-level OLS loadings, CWC within/between OLS plus the contextual effect, event-time log-rate, constant- and time-varying-predictor discrete effects (Voelkle Eqs. 12 and 14), exact scalar discrete process noise (Driver et al., 2017, Eq. 3), lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; `asymDIFFUSION`), trait-plus-state variance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise), observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5; Table 2 `MANIFESTVAR` is `Θ`, not `Var(y)`; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; `Θ` does not enter lagged observed covariance; observed-indicator mean is `τ + λ μ`; `MANIFESTMEANS` is not `E(y)`; `CINT` is not `MANIFESTMEANS`; discrete latent mean is `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ`; `T0MEANS` is not `μ_t`; evolved observed mean is `τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`; contemporaneous `TDPREDEFFECT` impulse is `m x`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that contemporaneous impulse is `τ + λ(μ_t + m x)`, and `τ + λ μ_t` is not that observed mean; time-independent `TIPREDEFFECT` increment is `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, not `M x`, not Voelkle Eq. 14, and not the coefficient `B`; Eq. 5 of that increment is `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`; within-interval `TDPREDEFFECT` carry is `e^{A(t−u)} M x` for `t0 < u < t`, not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; Eq. 5 of that carry is `τ + λ(μ_t + e^{a(t−u)} m x)`, and `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that carried observed mean when `u ≠ t`; §7.2 level-change `CINT` is `κ = −a m x` (`a < 0`; not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`; Eq. 3 of that setting is `(1 − e^{a Δt}) m x`); §7.2 extra-process contribution is `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, not the dissipating Dirac; `ε ≥ 0` fails closed; Eq. 5 of that contribution is `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean; after-t0 extra-process `TDPREDEFFECT` uses `t − u` with `t0 < u < t` while `μ_t` uses `Δt`; that after-t0 observed mean is not the first-occasion extra-process observed mean; §7.2 `asymTIPREDEFFECT` is `-B z / a` for `a < 0` and is not `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; §7.2 `addedTIPREDVAR` is `(B / a)² v` and is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`; Table 2 `asymCINT` is `-κ / a` for `a < 0` and is not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; p. 16 stationary `T0MEANS` is `-κ / a + −B z / a` and is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean; Eq. 5 of that constrained mean is `τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`; stationary `T0VAR` is `trait + −q / (2 a) + (B / a)² v` (not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)); lagged stationary `T0VAR` is `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (trait and `addedTIPREDVAR` do not decay; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map; Eq. 5 of that lagged covariance is `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ`; `Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance); later-occasion stationary `T0VAR` is `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt`; `Q_Δt` is not that later map; Eq. 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ`; lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not `Var(y_t)`; the later-occasion latent variance is not `Var(y_t)`); predetermined later-occasion `T0VAR` is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_t)`; the predetermined later-occasion latent variance is not `Var(y_t)`; stationary later observed variance is not that observed variance when `p_0` is free); predetermined lagged `T0VAR` is `trait + e^{a Δt} p_0 + (B / a)² v` (free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map; Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`; `MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free; the predetermined first-occasion variance of §4.3 predetermined `T0VAR` is `trait + p_0 + (B / a)² v`; free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map; Eq. 5 of that predetermined first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the §7.1 trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`; `MANIFESTMEANSstd` is `τ / √θ` after strictly positive `MANIFESTVAR`; unstandardised `MANIFESTMEANS` is not `MANIFESTMEANSstd`; `MANIFESTVARstd` is not `MANIFESTMEANSstd`; `τ / √(λ² Var(η) + θ)` is not `MANIFESTMEANSstd`;))))), irregular already-centered residual lag, and strong/strict-gated latent means on the stacked psychometric PR (two-observation residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016, PMC5145197 opened 2026-08-19T22:15Z); full ESEM/DSEM remaining | partial | | CPU bounded multithreading + GPU/VRAM streaming/parity | ADR 0001/0006 | future `compute_backend` | accepted-target | | CPU bounded multithreading + GPU/VRAM streaming/parity | ADR 0001/0006 | future `compute_backend` | accepted-target | | TDT detection/tracking vs CHRONOS schema/prediction/temporal consistency | ADR 0016; PRD/research | `event_core` TDT link precision/recall on the active PR; remaining TDT/CHRONOS stack and any future `event_intelligence` crate remain accepted-target | active-PR | diff --git a/docs/adr/0005-posterior-esem-dsem.md b/docs/adr/0005-posterior-esem-dsem.md index c6434b2b..549807c1 100644 --- a/docs/adr/0005-posterior-esem-dsem.md +++ b/docs/adr/0005-posterior-esem-dsem.md @@ -1,6 +1,7 @@ # ADR 0005 — Posterior-aware ESEM/DSEM and structural interpretation **Decision status:** Accepted +**Implementation maturity:** partial — construct classification, valid log-ratio/logistic-normal indicator gates, CPU `f64` OLS and posterior-draw loading point-estimate averaging, Rubin `T_m = Ū_m + (1+1/m) B_m` on draw-level OLS loadings, cluster-mean within/between OLS with the CWC contextual effect and Kish ESS WLS, event-time discrete lag-1 and exact scalar local log-rate, exact scalar forward map and unequal-interval remapping, exact scalar discrete effect of a constant predictor, first-order discrete effect of a time-varying predictor with matched sampling and constancy intervals (Voelkle et al., 2012, Eq. 14), exact scalar discrete process noise (Driver, Oud, & Voelkle, 2017, Eq. 3), exact scalar lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), exact scalar stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; §4.3; p. 16 `asymDIFFUSION`), exact scalar trait-plus-state variance and lagged covariance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise and not `asymDIFFUSION`), exact scalar observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12; `λ² Var(η) + θ` when `MANIFESTTRAITVAR` is zero, else `λ² Var(η) + θ + ψ`; lagged `λ² cov(η_t, η_{t-1}) + ψ`; `MANIFESTVAR` is `Θ`, not `Var(y)`; `Θ` does not enter lagged observed covariance; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; observed-indicator mean is `τ + λ μ` (`MANIFESTMEANS` is `τ`, not `E(y)`; `CINT` is not `MANIFESTMEANS`; `T0MEANS` is not `E(y)`; Equation 1 is the SDE; not a Kalman filter), exact scalar discrete latent mean `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ` (Driver et al., 2017, Eq. 3; `T0MEANS` is not `μ_t`; `CINT` is not the discrete increment), exact scalar evolved observed-indicator mean `τ + λ μ_t` (Driver et al., 2017, Eq. 5 of that Eq. 3 map; the first-occasion map `τ + λ μ_0` is not `E(y_t)`), exact scalar contemporaneous `TDPREDEFFECT` impulse `m x` (Driver et al., 2017, Eq. 3 fourth summand; Table 2 `TDPREDEFFECT` is `M`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; the §7.2 level-change form is not that impulse), exact scalar observed mean of that contemporaneous impulse `τ + λ(μ_t + m x)` (Driver et al., 2017, Eq. 5 of that Eq. 3 composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`), exact scalar time-independent `TIPREDEFFECT` increment `A^{-1}[e^{A Δt} − I] B z` (Driver et al., 2017, Eq. 3 second summand; Table 2 `TIPREDEFFECT` is `B`, not `κ`, not `M`, and not Voelkle Eq. 14; `B` is not that discrete increment), exact scalar observed mean of that increment `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` (Driver et al., 2017, Eq. 5 of that Eq. 3 printed addend after the `T0MEANS` carry and the `CINT` increment; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`), exact scalar within-interval `TDPREDEFFECT` carry `e^{A(t−u)} M x` for `t0 < u < t` (Driver et al., 2017, Eq. 1–2 Green-function integral of Eq. 2; §7.2 dissipation; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14), exact scalar observed mean of that carry `τ + λ(μ_t + e^{a(t−u)} m x)` (Driver et al., 2017, Eq. 5 of that carried latent mean; `τ + λ μ_t` is not that observed mean), exact scalar first-occasion `T0TIPREDEFFECT` shift `t0_b z` and Eq. 3 first-summand carry `e^{A Δt} t0_b z` (Driver et al., 2017, Table 3, p. 13; Eq. 3, p. 5; `T0TIPREDEFFECT` is not `TIPREDEFFECT` `B`; `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`; `e^{A Δt} t0_b z` is not `t0_b z`), exact scalar observed mean of that first-occasion carry `τ + λ(μ_t + e^{a Δt} t0_b z)` (Driver et al., 2017, Eq. 5 of that Table 3 / Eq. 3 first-summand composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean), exact scalar first-occasion `T0TDPREDEFFECT` shift `t0_m x0` and Eq. 3 first-summand carry `e^{A Δt} t0_m x0` (Driver et al., 2017, Table 3, p. 13; Eq. 3, p. 5; JSS PDF re-opened 2026-08-20T19:10Z; `T0TDPREDEFFECT` is not `TDPREDEFFECT` `M`; `t0_m x0` is not `M x`; `e^{A Δt} t0_m x0` is not `t0_m x0`; `e^{A Δt} t0_m x0` is not `e^{A(t−u)} M x` for `t0 < u < t`; `t0_m x0` is not `t0_b z`; an impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`), exact scalar observed mean of that first-occasion TD carry `τ + λ(μ_t + e^{a Δt} t0_m x0)` (Driver et al., 2017, Eq. 5 of that Table 3 / Eq. 3 first-summand TD composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean; `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean), exact scalar §7.2 level-change `CINT` `κ = −a m x` (Driver et al., 2017, §7.2, pp. 20–21; `a < 0` so `−κ / a = m x`; not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`, and not the extra near-zero-drift latent process also named in §7.2), exact scalar Eq. 3 increment of that setting `(1 − e^{a Δt}) m x` (not `m x`, not `κ`, and not `TIPREDEFFECT`), exact scalar §7.2 extra near-zero-drift latent process contribution `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-20T23:10Z; identification `TDPREDEFFECT` on the extra process is 1; extra `DRIFT` printed as `−0.000001`; precisely 0 causes computational problems; `ε = a` is `a_{ηξ} x Δt e^{a Δt}`; not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`; `ε ≥ 0` fails closed), exact scalar observed mean of that extra-process contribution `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` (Driver et al., 2017, Eq. 5, p. 5; §7.2, pp. 22–23; JSS PDF re-opened 2026-08-21T06:12Z; the extra process has `LAMBDA` 0 and is not an observed indicator; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; the contribution is not `E(y_t)`; the evolved-plus-contribution latent mean is not `E(y_t)`), exact scalar after-t0 extra-process contribution `a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t` and Eq. 5 observed mean `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a))` (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-21T06:32Z; `T0TDPREDEFFECT` uses `Δt` for both the evolution and the extra drive; `TDPREDEFFECT` after `t0` uses `t − u`; `e^{a(t−u)} m x` is a Dirac on the original process, not this `DRIFT` drive), exact scalar §7.2 `asymTIPREDEFFECT` `-B z / a` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF opened 2026-08-21T13:08Z; expected total change in process means given a time-independent predictor; `a < 0`; not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; `a ≥ 0` fails closed), exact scalar §7.2 `addedTIPREDVAR` `(B / a)² v` (Driver et al., 2017, §7.2, pp. 20–21; stable between-subject variance accounted for by a time-independent predictor; not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`), exact scalar Table 2 `asymCINT` `-κ / a` (Driver et al., 2017, Table 2, p. 12; Eq. 3 as `Δt → ∞`; `a < 0`; not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; `a ≥ 0` fails closed), exact scalar p. 16 stationary `T0MEANS` `-κ / a + −B z / a` (Driver et al., 2017, p. 16; constrained first-occasion mean using `T0MEANSbase` / `T0MEANSfree`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean), exact scalar Eq. 5 of that constrained mean `τ + λ(−κ / a + −B z / a)` (Driver et al., 2017, §4.3, pp. 9–10; Eq. 5, p. 5; JSS PDF re-opened 2026-08-21T20:07Z; form the stationary latent mean first, then `τ + λ` of that mean; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`), exact scalar §4.3 / p. 16 stationary `T0VAR` `trait + −q / (2 a) + (B / a)² v` (Driver et al., 2017, §4.3, pp. 9–10; p. 16; JSS PDF re-opened 2026-08-22T03:07Z; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`), exact scalar lagged covariance of that constrained process `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T19:13Z; trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map), exact scalar Eq. 5 of that lagged covariance `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ` (`Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance), exact scalar later-occasion variance of that constrained process `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T23:12Z; trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt` and is not that later map; `Q_Δt` is not that later map), exact scalar Eq. 5 of that later-occasion variance `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ` (the lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not that later observed variance; the later-occasion latent variance is not that observed variance)), exact scalar later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T05:12Z; trait and `addedTIPREDVAR` do not enter `Q_Δt`; free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; as `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`; as `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`; nonzero diffusion with `a ≥ 0` is a growing process and is kept. Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ` (`MANIFESTVAR` is not that later observed variance; the predetermined later-occasion latent variance is not that observed variance; stationary later observed variance is not that observed variance when `p_0` is free)), exact scalar lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a Δt} p_0 + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T09:04Z; trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`; free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map. Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ` (`MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free)), exact scalar first-occasion variance of §4.3 predetermined `T0VAR` `trait + p_0 + (B / a)² v` (free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map), exact scalar Eq. 5 of that predetermined first-occasion variance `λ²(trait + p_0 + (B / a)² v) + θ + ψ` (`MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; footnote 4; §7.1; JSS PDF re-opened 2026-08-23T11:40Z; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:06Z; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`; `MANIFESTMEANSstd` is `τ / √θ` after strictly positive `MANIFESTVAR`; unstandardised `MANIFESTMEANS` is not `MANIFESTMEANSstd`; `MANIFESTVARstd` is not `MANIFESTMEANSstd`; `τ / √(λ² Var(η) + θ)` is not `MANIFESTMEANSstd`;))))), CWC-then-event-time residual lag, irregular already-centered residual log-rate, and strong/strict-gated two-group OLS latent-mean difference are implemented on the stacked psychometric PR and are not implemented-main until exact-head checks, review, and protected-main integration complete; full ESEM/set-ESEM, formative composites, DSEM, and matrix continuous-time dynamics remain accepted-target **Implementation maturity:** partial — construct classification, valid log-ratio/logistic-normal indicator gates, CPU `f64` OLS and posterior-draw loading point-estimate averaging, Rubin `T_m = Ū_m + (1+1/m) B_m` on draw-level OLS loadings, cluster-mean within/between OLS with the CWC contextual effect and Kish ESS WLS, event-time discrete lag-1 and exact scalar local log-rate, exact scalar forward map and unequal-interval remapping, exact scalar discrete effect of a constant predictor, first-order discrete effect of a time-varying predictor with matched sampling and constancy intervals (Voelkle et al., 2012, Eq. 14), exact scalar discrete process noise (Driver, Oud, & Voelkle, 2017, Eq. 3), exact scalar lagged latent covariance and unconditional latent variance (Driver et al., 2017, Eq. 3–4), exact scalar stationary within-subject variance (Driver et al., 2017, Eq. 4 as `Δt → ∞`; §4.3; p. 16 `asymDIFFUSION`), exact scalar trait-plus-state variance and lagged covariance (Driver et al., 2017, §4.3 `TRAITVAR`; not process noise and not `asymDIFFUSION`), exact scalar observed-indicator variance and lagged observed covariance (Driver et al., 2017, Eq. 5, p. 5; Table 2, p. 12; `λ² Var(η) + θ` when `MANIFESTTRAITVAR` is zero, else `λ² Var(η) + θ + ψ`; lagged `λ² cov(η_t, η_{t-1}) + ψ`; `MANIFESTVAR` is `Θ`, not `Var(y)`; `Θ` does not enter lagged observed covariance; `MANIFESTTRAITVAR` is not `MANIFESTVAR`; observed-indicator mean is `τ + λ μ` (`MANIFESTMEANS` is `τ`, not `E(y)`; `CINT` is not `MANIFESTMEANS`; `T0MEANS` is not `E(y)`; Equation 1 is the SDE; not a Kalman filter), exact scalar discrete latent mean `exp(a Δt) μ_0 + (exp(a Δt) − 1)/a κ` (Driver et al., 2017, Eq. 3; `T0MEANS` is not `μ_t`; `CINT` is not the discrete increment), exact scalar evolved observed-indicator mean `τ + λ μ_t` (Driver et al., 2017, Eq. 5 of that Eq. 3 map; the first-occasion map `τ + λ μ_0` is not `E(y_t)`), exact scalar contemporaneous `TDPREDEFFECT` impulse `m x` (Driver et al., 2017, Eq. 3 fourth summand; Table 2 `TDPREDEFFECT` is `M`, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14; the §7.2 level-change form is not that impulse), exact scalar observed mean of that contemporaneous impulse `τ + λ(μ_t + m x)` (Driver et al., 2017, Eq. 5 of that Eq. 3 composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`), exact scalar time-independent `TIPREDEFFECT` increment `A^{-1}[e^{A Δt} − I] B z` (Driver et al., 2017, Eq. 3 second summand; Table 2 `TIPREDEFFECT` is `B`, not `κ`, not `M`, and not Voelkle Eq. 14; `B` is not that discrete increment), exact scalar observed mean of that increment `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` (Driver et al., 2017, Eq. 5 of that Eq. 3 printed addend after the `T0MEANS` carry and the `CINT` increment; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; `τ + λ(μ_t + e^{a(t−u)} m x)` is not that observed mean when `u ≠ t`), exact scalar within-interval `TDPREDEFFECT` carry `e^{A(t−u)} M x` for `t0 < u < t` (Driver et al., 2017, Eq. 1–2 Green-function integral of Eq. 2; §7.2 dissipation; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle Eq. 14), exact scalar observed mean of that carry `τ + λ(μ_t + e^{a(t−u)} m x)` (Driver et al., 2017, Eq. 5 of that carried latent mean; `τ + λ μ_t` is not that observed mean), exact scalar first-occasion `T0TIPREDEFFECT` shift `t0_b z` and Eq. 3 first-summand carry `e^{A Δt} t0_b z` (Driver et al., 2017, Table 3, p. 13; Eq. 3, p. 5; `T0TIPREDEFFECT` is not `TIPREDEFFECT` `B`; `t0_b z` is not `A^{-1}[e^{A Δt} − I] B z`; `e^{A Δt} t0_b z` is not `t0_b z`), exact scalar observed mean of that first-occasion carry `τ + λ(μ_t + e^{a Δt} t0_b z)` (Driver et al., 2017, Eq. 5 of that Table 3 / Eq. 3 first-summand composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean), exact scalar first-occasion `T0TDPREDEFFECT` shift `t0_m x0` and Eq. 3 first-summand carry `e^{A Δt} t0_m x0` (Driver et al., 2017, Table 3, p. 13; Eq. 3, p. 5; JSS PDF re-opened 2026-08-20T19:10Z; `T0TDPREDEFFECT` is not `TDPREDEFFECT` `M`; `t0_m x0` is not `M x`; `e^{A Δt} t0_m x0` is not `t0_m x0`; `e^{A Δt} t0_m x0` is not `e^{A(t−u)} M x` for `t0 < u < t`; `t0_m x0` is not `t0_b z`; an impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`), exact scalar observed mean of that first-occasion TD carry `τ + λ(μ_t + e^{a Δt} t0_m x0)` (Driver et al., 2017, Eq. 5 of that Table 3 / Eq. 3 first-summand TD composition; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that observed mean; `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that observed mean), exact scalar §7.2 level-change `CINT` `κ = −a m x` (Driver et al., 2017, §7.2, pp. 20–21; `a < 0` so `−κ / a = m x`; not the dissipating Dirac, not a free `CINT`, not `TIPREDEFFECT`, and not the extra near-zero-drift latent process also named in §7.2), exact scalar Eq. 3 increment of that setting `(1 − e^{a Δt}) m x` (not `m x`, not `κ`, and not `TIPREDEFFECT`), exact scalar §7.2 extra near-zero-drift latent process contribution `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-20T23:10Z; identification `TDPREDEFFECT` on the extra process is 1; extra `DRIFT` printed as `−0.000001`; precisely 0 causes computational problems; `ε = a` is `a_{ηξ} x Δt e^{a Δt}`; not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`; `ε ≥ 0` fails closed), exact scalar observed mean of that extra-process contribution `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` (Driver et al., 2017, Eq. 5, p. 5; §7.2, pp. 22–23; JSS PDF re-opened 2026-08-21T06:12Z; the extra process has `LAMBDA` 0 and is not an observed indicator; `τ + λ μ_t` is not that observed mean; `τ + λ(μ_t + m x)` is not that observed mean; the contribution is not `E(y_t)`; the evolved-plus-contribution latent mean is not `E(y_t)`), exact scalar after-t0 extra-process contribution `a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t` and Eq. 5 observed mean `τ + λ(μ_t + a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a))` (Driver et al., 2017, §7.2, pp. 22–23; JSS PDF re-opened 2026-08-21T06:32Z; `T0TDPREDEFFECT` uses `Δt` for both the evolution and the extra drive; `TDPREDEFFECT` after `t0` uses `t − u`; `e^{a(t−u)} m x` is a Dirac on the original process, not this `DRIFT` drive), exact scalar §7.2 `asymTIPREDEFFECT` `-B z / a` (Driver et al., 2017, §7.2, pp. 20–21; JSS PDF opened 2026-08-21T13:08Z; expected total change in process means given a time-independent predictor; `a < 0`; not the coefficient `B`, not `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`; `a ≥ 0` fails closed), exact scalar §7.2 `addedTIPREDVAR` `(B / a)² v` (Driver et al., 2017, §7.2, pp. 20–21; stable between-subject variance accounted for by a time-independent predictor; not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`), exact scalar Table 2 `asymCINT` `-κ / a` (Driver et al., 2017, Table 2, p. 12; Eq. 3 as `Δt → ∞`; `a < 0`; not `κ`, not `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`; `a ≥ 0` fails closed), exact scalar p. 16 stationary `T0MEANS` `-κ / a + −B z / a` (Driver et al., 2017, p. 16; constrained first-occasion mean using `T0MEANSbase` / `T0MEANSfree`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean), exact scalar Eq. 5 of that constrained mean `τ + λ(−κ / a + −B z / a)` (Driver et al., 2017, §4.3, pp. 9–10; Eq. 5, p. 5; JSS PDF re-opened 2026-08-21T20:07Z; form the stationary latent mean first, then `τ + λ` of that mean; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`), exact scalar §4.3 / p. 16 stationary `T0VAR` `trait + −q / (2 a) + (B / a)² v` (Driver et al., 2017, §4.3, pp. 9–10; p. 16; JSS PDF re-opened 2026-08-22T03:07Z; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Eq. 5 of that constrained variance is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (JSS PDF re-opened 2026-08-22T03:20Z; form the stationary latent variance first, then `λ² p + θ + ψ`; `λ² p_0` is not that observed variance; `λ²(−q / (2 a)) + θ` is not that observed variance when `TRAITVAR` or `addedTIPREDVAR` is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`), exact scalar lagged covariance of that constrained process `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T19:13Z; trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`; contemporaneous `T0VAR` is not that lagged map; decaying the constrained total as if it were all state is not that lagged map), exact scalar Eq. 5 of that lagged covariance `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ` (`Θ` does not enter; contemporaneous `Var(y_0)` is not that lagged observed covariance; the lagged latent covariance is not that observed covariance), exact scalar later-occasion variance of that constrained process `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 / p. 16 `T0VAR`; JSS PDF re-opened 2026-08-22T23:12Z; trait and `addedTIPREDVAR` do not enter `Q_Δt`; under stationarity that composition equals contemporaneous `T0VAR`; evolving the constrained total as if it were all state is not that later map; the lagged covariance omits `Q_Δt` and is not that later map; `Q_Δt` is not that later map), exact scalar Eq. 5 of that later-occasion variance `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ` (the lagged observed covariance omits `Q_Δt` and `θ`; `MANIFESTVAR` is not that later observed variance; the later-occasion latent variance is not that observed variance)), exact scalar later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T05:12Z; trait and `addedTIPREDVAR` do not enter `Q_Δt`; free `T0VAR` `p_0` is not that later map; setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map; stationary later variance uses `−q / (2 a)` in place of `p_0` and is not that later map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that later map; as `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`; as `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`; nonzero diffusion with `a ≥ 0` is a growing process and is kept. Eq. 5 of that predetermined later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ` (`MANIFESTVAR` is not that later observed variance; the predetermined later-occasion latent variance is not that observed variance; stationary later observed variance is not that observed variance when `p_0` is free)), exact scalar lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a Δt} p_0 + (B / a)² v` (Driver et al., 2017, Eq. 3–4 of §4.3 predetermined first occasion; JSS PDF re-opened 2026-08-23T09:04Z; trait and `addedTIPREDVAR` do not decay with `e^{a Δt}`; free `T0VAR` `p_0` is not that lagged map; setting `p_0 = −q / (2 a)` recovers the stationary lagged map; stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not that lagged map when `p_0` is free; evolving `trait + p_0 + (B / a)² v` as if it were all state is not that lagged map; later-occasion variance includes `Q_Δt` and is not that lagged map. Eq. 5 of that predetermined lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ` (`MANIFESTVAR` does not enter; the predetermined lagged latent covariance is not that observed covariance; predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance; stationary lagged observed covariance is not that observed covariance when `p_0` is free)), exact scalar first-occasion variance of §4.3 predetermined `T0VAR` `trait + p_0 + (B / a)² v` (free `p_0` is not that map; stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not that map when `p_0` is free; lagged covariance decays the state and is not that map; later-occasion variance includes `Q_Δt` and is not that map), exact scalar Eq. 5 of that predetermined first-occasion variance `λ²(trait + p_0 + (B / a)² v) + θ + ψ` (`MANIFESTVAR` is not that first-occasion observed variance; the predetermined first-occasion latent variance is not that observed variance; stationary first-occasion observed variance is not that observed variance when `p_0` is free; predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance; later-start lagged covariance of predetermined `T0VAR` is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 4; JSS PDF re-opened 2026-08-23T10:27Z; first-occasion lagged omits `e^{a s} Q_u`; later-occasion variance does not lag; stationary lagged uses `−q / (2 a)`; decaying the later total is not that map; Eq. 5 of that later-start lagged covariance is `λ²` of it plus `ψ`; `Θ` does not enter; first-occasion lagged observed omits `e^{a s} Q_u`; later observed variance includes `Q_u` and `θ`; later-start later-occasion variance of predetermined `T0VAR` is `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` (Driver et al., 2017, §4.3 `startoffset`; Eq. 3–4 Chapman–Kolmogorov `Q_{u+s} = e^{2 a s} Q_u + Q_s`; JSS PDF re-opened 2026-08-23T11:05Z; later-occasion variance at `u` omits `Q_s`; later-start lagged covariance omits `Q_s`; stationary later uses `−q / (2 a)`; evolving the later total as if it were all state is not that map; ignoring `startoffset` omits `e^{2 a s} Q_u`; Eq. 5 of that later-start later-occasion variance is `λ²` of it plus `θ + ψ`; `MANIFESTVAR` is not that observed variance; p. 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; footnote 4; §7.1; JSS PDF re-opened 2026-08-23T11:40Z; unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`; the trait-plus-state autocorrelation uses `TRAITVAR` and is not `discreteDRIFTstd`; p. 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:06Z; unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`; the continuous standardisation `−2 a` is not `discreteDIFFUSIONstd`; `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DIFFUSIONstd` is `q / (−q / (2 a)) = −2 a` after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 4; footnote 4; JSS PDF re-opened 2026-08-23T13:20Z; unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`; the discrete standardisation `Q_Δt / (−q / (2 a))` depends on `Δt` and is not `DIFFUSIONstd`; `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`; `TRAITVAR` is not the standardisation variance; p. 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (Driver et al., 2017, p. 16; Eq. 1; footnote 4; JSS PDF re-opened 2026-08-23T13:28Z); unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`; the discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`; `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T14:25Z; unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`; `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); p. 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (Driver et al., 2017, p. 16; §7.2; footnote 4; JSS PDF re-opened 2026-08-23T16:21Z; unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`; the asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`; the finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`; `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); Table 3 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (Driver et al., 2017, Table 3, p. 13; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T17:20Z; the affected variance is free `T0VAR`, not `asymDIFFUSION`; unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`; `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` is the continuous coefficient and is not `T0TIPREDEFFECTstd`; `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`; `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`; `TRAITVAR` is not the standardisation variance); 2017-era `addedT0TIPREDVAR` is `t0_b² v` (Driver et al., 2017, Table 3, p. 13; p. 16; §7.2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T18:20Z; `T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`; form `t0_b` first, then square, then multiply by `v`; a zero coefficient or zero predictor variance is exactly zero; free `T0TIPREDEFFECT` does not require `a < 0`; `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map; `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance; free `T0VAR` is not this extra TI variance; `TRAITVAR` is not this extra TI variance; Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v` (Driver et al., 2017, Eq. 5, p. 5; Table 3, p. 13; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-23T19:10Z; form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; `t0_b² v` is the latent extra, not the observed extra; `λ² p_0 + θ` is first-occasion observed variance, not this extra; `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra; `MANIFESTVAR` `θ` is not this extra; Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`; form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`; a zero loading or zero extra is exactly zero; lasting asymptotic extra requires `a < 0`; `(B / a)² v` is the latent extra, not the observed extra; `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra; `λ² p + θ` is stationary observed variance, not this extra; `MANIFESTVAR` `θ` is not this extra; p. 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and strictly positive time-dependent predictor variance; unstandardised `M` is not `TDPREDEFFECTstd`; `TIPREDEFFECTstd` is not `TDPREDEFFECTstd` even when `M = B`; intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p` is not `TDPREDEFFECTstd`; `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`; Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` and strictly positive TD predictor variance; unstandardised `t0_m` is not `T0TDPREDEFFECTstd`; `TDPREDEFFECTstd` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`; `T0TIPREDEFFECTstd` is not `T0TDPREDEFFECTstd` even when `t0_m = t0_b`; `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`; free `T0VAR` does not require `a < 0`; p. 16 `T0VARstd` is `p_0 / p_0 = 1` after strictly positive free `T0VAR` (`solve(sqrt(diag(T0VAR))) %&% T0VAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; default ridge is 0); unstandardised `T0VAR` is not `T0VARstd`; `T0TDPREDEFFECTstd` is not `T0VARstd`; `addedT0TIPREDVAR` is not `T0VARstd`; p. 16 `TRAITVARstd` is `trait / trait = 1` after strictly positive `TRAITVAR` (`solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; no ridge addend); unstandardised `TRAITVAR` is not `TRAITVARstd`; `T0VARstd` is not `TRAITVARstd` even when both equal 1; `addedT0TIPREDVAR` is not `TRAITVARstd`; p. 16 `MANIFESTTRAITVARstd` is `ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR` (`solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0); unstandardised `MANIFESTTRAITVAR` is not `MANIFESTTRAITVARstd`; `TRAITVARstd` is not `MANIFESTTRAITVARstd` even when both equal 1; `MANIFESTVAR` is not `MANIFESTTRAITVARstd`; p. 16 `MANIFESTVARstd` is `θ / θ = 1` after strictly positive `MANIFESTVAR` (`solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug); unstandardised `MANIFESTVAR` is not `MANIFESTVARstd`; `MANIFESTTRAITVARstd` is not `MANIFESTVARstd` even when both equal 1; Equation 5 `Var(y)` is not `MANIFESTVARstd`; p. 16 `TIPREDVARstd` is `v / v = 1` after strictly positive `TIPREDVAR` (`solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`); unstandardised `TIPREDVAR` is not `TIPREDVARstd`; `MANIFESTVARstd` is not `TIPREDVARstd` even when both equal 1; §7.2 `addedTIPREDVAR` is not `TIPREDVARstd`; p. 16 `asymDIFFUSIONstd` is `p / p = 1` after strictly positive `asymDIFFUSION` (`solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION`; OpenMx `%&%` is `t(A) %*% B %*% A`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`); unstandardised `asymDIFFUSION` is not `asymDIFFUSIONstd`; `TIPREDVARstd` is not `asymDIFFUSIONstd` even when both equal 1; `DIFFUSIONstd` `−2 a` is not `asymDIFFUSIONstd`; p. 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; unstandardised `discreteCINT` is not `discreteCINTstd`; `κ / √p` is not `discreteCINTstd`; `(-κ / a) / √p` is not `discreteCINTstd`; `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION`; unstandardised `asymCINT` is not `asymCINTstd`; `κ / √p` is not `asymCINTstd`; `discreteCINTstd` is not `asymCINTstd`; `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR`; unstandardised `T0MEANS` is not `T0MEANSstd`; `T0VARstd` is not `T0MEANSstd`; `μ_0 / √asymDIFFUSION` is not `T0MEANSstd`;))))), CWC-then-event-time residual lag, irregular already-centered residual log-rate, and strong/strict-gated two-group OLS latent-mean difference are implemented on the consolidation vehicle PR `integration/psychometric-standardisation` (folding draft stack #181–#218) and are not implemented-main until exact-head checks, review, and protected-main integration complete; full ESEM/set-ESEM, formative composites, DSEM, and matrix continuous-time dynamics remain accepted-target **Date:** 2026-08-05 **Supersedes:** None. ADR 0012 governs upstream topic measurement/network coordinates; this ADR governs higher-order psychometric structure and longitudinal interpretation. diff --git a/docs/adr/0012-temporal-relational-shared-latent-topic-measurement.md b/docs/adr/0012-temporal-relational-shared-latent-topic-measurement.md index d824ceb8..f0d7603e 100644 --- a/docs/adr/0012-temporal-relational-shared-latent-topic-measurement.md +++ b/docs/adr/0012-temporal-relational-shared-latent-topic-measurement.md @@ -1,30 +1,8 @@ # ADR 0012 — Temporal Relational Shared-Latent Topic Measurement -**Decision status:** Accepted -**Implementation maturity:** partial — bounded identity, recovery, temporal lineage, network geometry, model-selection, preprocessing, method-effect, and modality gates are implemented across the foundation crates; the TRSL-TM estimator, global topic identity, method effects, and backend interchange remain accepted-target. -**Implementation maturity:** partial — logistic-normal ALR/ILR coordinates, lexical-weight refusal, statistical/Pareto candidate-`K` gates, stable active/dormant/reactivated topic identity, and the bounded CPU `f64` reference estimator are implemented on the active product branch; `corpus_background`, `topic_lineage`, `network_analysis`, `model_selection`, `stopword_deletion`, `style_source`, `copied_text`, and `modality_source` implement bounded identity and recovery gates implemented-main; method effects, calibrated posterior acceptance, accelerated backends, and backend interchange remain accepted-target until implemented and protected-main integrated -**Implementation maturity:** partial — `corpus_background`, `topic_lineage`, `network_analysis`, `model_selection`, `stopword_deletion`, `style_source`, `copied_text`, and `modality_source` implement bounded identity and recovery gates; the TRSL-TM estimator, method effects, global topic identity, and backend interchange remain accepted-target. -**Date:** 2026-08-24 -**Decision status:** Accepted -**Implementation maturity:** partial — the prompt-source, corpus-background, modality-source, copied-text, style-source, and default-stopword-deletion identity gates plus `topic_lineage` single-identity persistence across dormancy/reactivation are implemented-main; `network_analysis` cluster-pair scoring and `model_selection` candidate-K gates remain on their open PRs; the TRSL-TM estimator, global topic identity, method-effect model, and backend interchange remain accepted-target. -**Date:** 2026-08-12 -**Decision status:** Accepted -**Implementation maturity:** accepted-target — prompt-versus-unique-content identity in `prompt_source` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — corpus-background-versus-unique-content identity in `corpus_background` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — modality-versus-unique-content identity in `modality_source` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — copied-versus-unique-content identity in `copied_text` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — style-versus-unique-content identity in `style_source` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** partial — default stopword-deletion refusal is `stopword_deletion` on the active PR; topic estimator, global topic identity, method-effect model, and TF-IDF/BM25 inferential-weight refusal remain accepted-target -**Implementation maturity:** active-PR — `topic_lineage` keeps one P0 identity across active/dormant/reactivated states; remaining TRSL-TM estimator, method effects, and backend interchange remain accepted-target -**Implementation maturity:** active-PR — `network_analysis` refuses raw-simplex Euclidean geometry and scores cluster pair precision/recall; remaining TRSL-TM estimator, global topic identity, method effects, and backend interchange remain accepted-target -**Implementation maturity:** active-PR — `model_selection` statistical/Pareto candidate-`K` gates and known-`K` RMSE live in the new crate; remaining TRSL-TM estimator, global topic identity, method effects, and backend interchange remain accepted-target -**Implementation maturity:** partial — default stopword-deletion refusal is `stopword_deletion` on the active PR; topic estimator, global topic identity, method-effect model, and TF-IDF/BM25 inferential-weight refusal remain accepted-target -**Implementation maturity:** accepted-target — style-versus-unique-content identity in `style_source` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — modality-versus-unique-content identity in `modality_source` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — corpus-background-versus-unique-content identity in `corpus_background` on the active PR; estimator-side method model remains accepted-target -**Implementation maturity:** accepted-target — prompt-versus-unique-content identity in `prompt_source` on the active PR; estimator-side method model remains accepted-target -**Date:** 2026-08-12 **Date:** 2026-08-24 +**Decision status:** Accepted +**Implementation maturity:** partial — coordinates and the CPU `f64` reference estimator are implemented-main; fitted candidate-`K` scoring is this PR; method effects and GPU remain accepted-target. **Supersedes:** None; refines ADR 0004 and ADR 0005 without replacing their multilingual and psychometric authorities. ## Context diff --git a/docs/adr/README.md b/docs/adr/README.md index 04d4b23f..b5efd463 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -17,7 +17,7 @@ Read [`ADR_POLICY.md`](ADR_POLICY.md) first. **Decision status and implementatio | [0009](0009-purpose-bound-pii-governance.md) | Purpose-bound PII governance without blanket masking | Accepted | partial | Opaque analytical IDs, purpose grants, provider minimization, retention, and encrypted mapping are covered; deployment evidence and persistent access storage remain target work. | | [0010](0010-adaptive-llm-orchestration.md) | Adaptive LLM orchestration and test-time compute | Accepted | partial | Direct/verify/committee routing and ablation contracts exist; live provider execution and production calibration remain target work. | | [0011](0011-standalone-modular-msa-boundary.md) | Standalone operation and modular CWL MSA boundary | Accepted | partial | Versioned service boundaries and credential separation are authoritative; production TLS and live ports remain target work. | -| [0012](0012-temporal-relational-shared-latent-topic-measurement.md) | Temporal relational shared-latent topic measurement | Accepted | partial | Method-source and stopword identity slices are active; estimator, backend, global topic identity, and candidate-K completion remain target work. | +| [0012](0012-temporal-relational-shared-latent-topic-measurement.md) | Temporal relational shared-latent topic measurement | Accepted | partial | Coordinates and the CPU `f64` reference estimator are implemented-main; fitted candidate-`K` scoring is this PR; method effects and GPU remain accepted-target. | | [0013](0013-bitemporal-persistence-reproducibility-and-split-authority.md) | Bitemporal persistence, reproducibility, and split authority | Accepted | partial | Migration, tenant, append-only, interval, and live SQL contracts are present; physical ERD and recovery depth remain target work. | | [0014](0014-scientific-claim-promotion-and-release-evidence.md) | Scientific claim promotion and release evidence | Accepted | partial | Exact-head promotion authority and repository evidence exist; the complete release bundle remains target work. | | [0015](0015-autonomous-development-review-and-merge-authority.md) | Autonomous development, review, and merge authority separation | Accepted | active-PR | Proposal, deterministic verification, publication, independent review, and merge/release authority remain separate. | @@ -93,7 +93,7 @@ Read [`ADR_POLICY.md`](ADR_POLICY.md) first. **Decision status and implementatio | [0009](0009-purpose-bound-pii-governance.md) | Purpose-bound PII governance without blanket masking | Accepted | partial | Persistence retention/deletion/legal-hold (`0007`) and provider-payload minimization implemented-main; deployment evidence remains accepted-target. | | [0010](0010-adaptive-llm-orchestration.md) | Adaptive LLM orchestration and test-time compute | Accepted | partial | `tepp_api` router/ablation/orchestrator binding implemented-main; live NIM execution and production ablation evidence remain accepted-target. | | [0011](0011-standalone-modular-msa-boundary.md) | Standalone operation and modular CWL MSA boundary | Accepted | partial | Owns cross-service persistence/credential/API authority; no direct cross-service application-table coupling. | -| [0012](0012-temporal-relational-shared-latent-topic-measurement.md) | Temporal Relational Shared-Latent Topic Measurement (TRSL-TM) | Accepted | partial | Logistic-normal ALR/ILR, lexical-weight refusal, statistical/Pareto candidate-`K` gates, and active/dormant/reactivated identity are on the active product branch; the estimator, method effects, and backend interchange remain accepted-target. | +| [0012](0012-temporal-relational-shared-latent-topic-measurement.md) | Temporal Relational Shared-Latent Topic Measurement (TRSL-TM) | Accepted | partial | Coordinates and the CPU `f64` reference estimator are implemented-main; fitted candidate-`K` scoring is this PR; method effects and GPU remain accepted-target. | | [0013](0013-bitemporal-persistence-reproducibility-and-split-authority.md) | Bitemporal persistence, reproducibility manifests, and relation-aware split authority | Accepted | partial | Owns PostgreSQL adapter semantics, immutable run/split manifests, leakage-safe partitions, and recovery identity; optional `live-sqlx` `PgPool`, live PG CI, tenant RLS, and `0006` membership implemented-main; `0007` retention/deletion/legal-hold on the active PR; remaining physical ERD/backup accepted-target. | | [0014](0014-scientific-claim-promotion-and-release-evidence.md) | Scientific claim promotion and release evidence authority | Accepted | partial | Separates design, implementation, scientific/product claim, and release authority; repository SBOM/provenance generator implemented; checkpoint-versus-estimator refusal is `checkpoint_authority` on the active PR; full release bundle remaining. | | [0015](0015-autonomous-development-review-and-merge-authority.md) | Autonomous development, review, and merge authority separation | Accepted | active-PR | Separates model proposal, deterministic verification, publication, independent review, and merge/release authority. | diff --git a/docs/doctoring/fitted-candidate-k.md b/docs/doctoring/fitted-candidate-k.md new file mode 100644 index 00000000..8e22c237 --- /dev/null +++ b/docs/doctoring/fitted-candidate-k.md @@ -0,0 +1,38 @@ +# Fitted candidate-K scoring (doctoring) + +## Claim boundary + +`select_fitted_candidate_k` fits each caller-supplied candidate `K` with the +CPU `f64` TRSL-TM reference and scores the actual in-sample mixture +log-likelihood. It does not run GPU inference, full Bayesian sampling, or +topic birth/split/merge, and it does not close issue #167. + +## Numeric constants + +| Constant | Value | Provenance | +|---|---|---| +| prior variance `σ²` | `1.0` | Identical copy of `topic_measurement` `DEFAULT_PRIOR_VARIANCE`; ADR 0012 names `σ²` in the MAP objective | +| relation strength `λ` | `0.25` | Identical copy of `topic_measurement` `DEFAULT_RELATION_STRENGTH`; ADR 0012 names `λ` in `R(Θ,G)` | +| ridge `ρ` | `0.01` | Identical copy of `topic_measurement` `DEFAULT_RIDGE`; ADR 0012 names `ρ` on `(Γ,u)` | +| topic smoothing | `0.05` | Identical copy of `topic_measurement` `DEFAULT_TOPIC_SMOOTHING` for the smoothed multinomial `β` update | +| GEM step | `0.2` | Identical copy of `topic_measurement` `DEFAULT_STEP_SIZE` | +| Schwarz penalty | `ℓ − (p ln N)/2` | Schwarz (1978, p. 461) maximizer `log M_j − (1/2) k_j log n` | + +These copies are not a second heuristic set. A value that diverged from the +`topic_measurement` reference would be a defect. + +## Primary sources + +Schwarz, G. (1978). Estimating the dimension of a model. *The Annals of +Statistics, 6*(2), 461–464. https://doi.org/10.1214/aos/1176344136 +(Project Euclid PDF opened 2026-08-25T06:08Z from +https://projecteuclid.org/journalArticle/Download?urlId=10.1214%2Faos%2F1176344136) + +Roberts, M. E., Stewart, B. M., Tingley, D., Lucas, C., Leder-Luis, J., +Gadarian, S. K., Albertson, B., & Rand, D. G. (2014). Structural topic models +for open-ended survey responses. *American Journal of Political Science, +58*(4), 1064–1082. https://doi.org/10.1111/ajps.12103 + +Roberts, M. E., Stewart, B. M., & Tingley, D. (2019). stm: An R package for +structural topic models. *Journal of Statistical Software, 91*(2), 1–40. +https://doi.org/10.18637/jss.v091.i02 diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 5fa3e527..c870b156 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -199,7 +199,7 @@ visual workspace, or a supported multi-tenant release. | GAP-003A | Immutable evidence cannot yet be submitted to a durable validation run that produces operator-usable scientific acceptance evidence. | `accepted-target` | product-completion | `e65cd66` (validation metrics are library-level only) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | Compose/CLI/API execution must bind immutable evidence, cutoffs, model configuration, validation metrics, and reproducibility manifests to one idempotent run. | | GAP-003B | Scientific result artifacts cannot yet be persisted, restarted, and recovered as one supported operator workflow. | `accepted-target` | product-completion | `e65cd66` (persistence contracts lack E2E recovery) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | Durable storage, migration/rollback, restart/recovery, artifact digest verification, and terminal retrieval must pass against a real Compose deployment. | | GAP-003C | The persistence slice classifies concurrent-write SQLSTATEs, but has no measured hot-partition detection, routing, or mitigation for tenant/result workloads. | `accepted-target` | product-completion | `e65cd66` (conflict classification only; no measured partition control) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | A real Compose/PostgreSQL workload identifies hot keys and partition skew, applies bounded tenant/time or result routing without weakening 3NF or temporal authority, and proves conflict rate, latency, recovery, and migration/rollback behavior under load. | -| GAP-004 | The central shared-latent temporal/relational topic estimator is absent. | `accepted-target` | product vertical | `e65cd66` (no production estimator) | [#167](https://github.com/ContextualWisdomLab/TEPP/issues/167) / [PR #48](https://github.com/ContextualWisdomLab/TEPP/pull/48) | `6110d3660607` | Rust CPU `f64` fitting, sparse bounded parallelism, posterior artifacts, convergence, true-parameter RMSE/bias/coverage, and real candidate-K fitting. | +| GAP-004 | The central shared-latent temporal/relational topic estimator is absent. | `partial` | product vertical | CPU `f64` reference plus fitted candidate-`K` scoring | [#167](https://github.com/ContextualWisdomLab/TEPP/issues/167) | this PR | GPU, method effects, full Bayesian sampling, and topic birth/split/merge remain. This is not full #167 closure. | | GAP-005 | Real multilingual documents are not yet transformed into validated exact-span semantic units and versioned shared concepts. | `partial` | product vertical | `e65cd66` (semantic_core exact-span units and language-profile validation are implemented-main as the first slice) | [#168](https://github.com/ContextualWisdomLab/TEPP/issues/168) / [PR #201](https://github.com/ContextualWisdomLab/TEPP/pull/201) (merged) | `—` | Closure still requires concept alignment, Unicode/layout/language-tailored processing, unknown-concept review, multilingual calibration/invariance, image-position evidence, and prompt-injection tests. | | GAP-006 | Posterior topic measurements cannot yet be fitted through a complete cross-classified longitudinal ESEM/DSEM engine. | `accepted-target` | product vertical | `e65cd66` (temporal and membership primitives only) | [#169](https://github.com/ContextualWisdomLab/TEPP/issues/169) / [PR #119](https://github.com/ContextualWisdomLab/TEPP/pull/119) | `47ab763d49b1` | Plausible-value/joint uncertainty, invariance, irregular event time, within/between separation, multiple membership, true-parameter recovery, and causal-claim refusal. | | GAP-007 | TDT detection/tracking and CHRONOS schema/forecast/temporal reasoning remain isolated bounded gates rather than one calibrated product workflow. | `accepted-target` | product vertical | `e65cd66` (event/time primitives only) | [#170](https://github.com/ContextualWisdomLab/TEPP/issues/170) / [PR #70](https://github.com/ContextualWisdomLab/TEPP/pull/70) | `7a1f33aa68c1` | Span-grounded mentions, calibrated TDT metrics, schema/forecast hypothesis states, interval consistency, known-truth recovery, persistence, and exports. | diff --git a/docs/research/model-selection-pareto-gates.md b/docs/research/model-selection-pareto-gates.md index f7da5c82..1dc0c884 100644 --- a/docs/research/model-selection-pareto-gates.md +++ b/docs/research/model-selection-pareto-gates.md @@ -8,9 +8,13 @@ complexity) and not Pareto-dominated on those two objectives. An LLM vote may later recommend among admissible candidates. It cannot itself define the numerical optimum or bypass diagnostics (ADR 0012). -This slice does not fit a topic model, choose a neural architecture, or claim a -unique true `K` for every corpus. Known-truth recovery reports computed RMSE of -the selected `K` against the generating `K`. +`select_fitted_candidate_k` now fits each candidate with the CPU `f64` TRSL-TM +reference and builds `ModelCandidate::statistical` from the actual in-sample +mixture log-likelihood and Schwarz's (1978) large-sample penalty. A typed +non-convergence, non-finite, or invalid-input failure is a failed candidate, +not a fabricated diagnostic. This slice does not choose a neural architecture, +run GPU inference, or claim a unique true `K` for every corpus. Known-truth +recovery reports computed RMSE of the selected `K` against the generating `K`. ## Authority @@ -19,17 +23,30 @@ the selected `K` against the generating `K`. - `docs/adr/0012-temporal-relational-shared-latent-topic-measurement.md` — model selection uses statistical/recovery/stability/alignment/fairness gates and a Pareto-style comparison before any future blinded LLM review; the LLM - never defines the numerical optimum. + never defines the numerical optimum. The fitted path copies the ADR-owned + v1 reference hyperparameters from `topic_measurement` + (`σ² = 1.0`, `λ = 0.25`, `ρ = 0.01`, topic-smoothing `0.05`, GEM step + `0.2`). Those values are not a second heuristic set. ### Supporting model-selection literature -Akaike (1974) and Burnham and Anderson (2002) provide background for -likelihood-and-complexity comparison of fitted candidates. Deb et al. (2002) -provides background for non-dominated (Pareto) filtering when two objectives -are compared simultaneously. Those sources do not by themselves validate the -exact TEPP thresholds, acceptance criteria, or orchestration boundary; ADR -0012 is normative for this repository. They do **not** authorize an LLM vote as -a statistical estimator. +Schwarz (1978) is the primary source for the candidate score +`ℓ − (p ln N)/2`. The printed large-sample Bayes procedure chooses the model +that maximizes `log M_j − (1/2) k_j log n` (Schwarz, 1978, p. 461; Project +Euclid PDF opened 2026-08-25T06:08Z from +https://projecteuclid.org/journalArticle/Download?urlId=10.1214%2Faos%2F1176344136). +`N` is the total token mass. `p` is the free-parameter count +`K(V−1) + (D+F)(K−1)`. `N < 1` makes `ln N` negative and fails closed. This +is the maximizer form, not a second invented weight. Akaike (1974) and +Burnham and Anderson (2002) remain background for likelihood-and-complexity +comparison. Deb et al. (2002) remains background for non-dominated (Pareto) +filtering. Those sources do not by themselves validate the TEPP acceptance +criteria or orchestration boundary; ADR 0012 is normative for this +repository. They do **not** authorize an LLM vote as a statistical estimator. + +Roberts et al. (2014, 2019) remain the STM-family authority for the +reference estimator itself. They do not license a different numeric +hyperparameter set than the ADR 0012 / `topic_measurement` copies. Akaike, H. (1974). A new look at the statistical model identification. *IEEE Transactions on Automatic Control, 19*(6), 716–723. @@ -41,3 +58,15 @@ inference: A practical information-theoretic approach* (2nd ed.). Springer. Deb, K., Pratap, A., Agarwal, S., & Meyarivan, T. (2002). A fast and elitist multiobjective genetic algorithm: NSGA-II. *IEEE Transactions on Evolutionary Computation, 6*(2), 182–197. https://doi.org/10.1109/4235.996017 + +Roberts, M. E., Stewart, B. M., Tingley, D., Lucas, C., Leder-Luis, J., +Gadarian, S. K., Albertson, B., & Rand, D. G. (2014). Structural topic models +for open-ended survey responses. *American Journal of Political Science, +58*(4), 1064–1082. https://doi.org/10.1111/ajps.12103 + +Roberts, M. E., Stewart, B. M., & Tingley, D. (2019). stm: An R package for +structural topic models. *Journal of Statistical Software, 91*(2), 1–40. +https://doi.org/10.18637/jss.v091.i02 + +Schwarz, G. (1978). Estimating the dimension of a model. *The Annals of +Statistics, 6*(2), 461–464. https://doi.org/10.1214/aos/1176344136 diff --git a/docs/research/multilevel-event-time-recovery.md b/docs/research/multilevel-event-time-recovery.md index 7a384b2d..bdf07003 100644 --- a/docs/research/multilevel-event-time-recovery.md +++ b/docs/research/multilevel-event-time-recovery.md @@ -100,6 +100,8 @@ This slice stays inside `psychometric_core`. It does not add a second invariance 94. refuse treating unstandardised `asymCINT` as `asymCINTstd`, refuse treating `κ / √p` as `asymCINTstd`, and refuse treating `discreteCINTstd` as `asymCINTstd`; 95. recover the exact scalar p. 16 `T0MEANSstd` as `μ_0 / √p_0` after forming strictly positive free `T0VAR` `p_0` (Driver et al., 2017, p. 16; footnote 4; Table 2, p. 12; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-24T22:30Z; the 2017-era source forms unstandardised `T0MEANS` as `OpenMx::mxEval(T0MEANS, mxobj, compute=TRUE)`; that source does not form a `T0MEANSstd` matrix; a zero mean is exactly zero; `p_0 = 0` fails closed; a non-event clock fails closed; free `T0MEANS` does not require `a < 0`); 96. refuse treating unstandardised `T0MEANS` as `T0MEANSstd`, refuse treating `T0VARstd` as `T0MEANSstd` even when both equal 1, and refuse treating `μ_0 / √asymDIFFUSION` as `T0MEANSstd`; +97. recover the exact scalar p. 16 `MANIFESTMEANSstd` as `τ / √θ` after forming strictly positive `MANIFESTVAR` `θ` (Driver et al., 2017, p. 16; footnote 4; Table 2, p. 12; Eq. 5, p. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-25T05:04Z; the 2017-era source forms unstandardised `MANIFESTMEANS` as `mxEval(MANIFESTMEANS, mxobj, compute=TRUE)`; that source does not form a `MANIFESTMEANSstd` matrix; the 2017-era `dimnames` assignment to `list(manifestNames, manifestNames)` on an `n.manifest × 1` matrix is a source bug; a zero mean is exactly zero; `θ = 0` fails closed; a non-event clock fails closed; `MANIFESTMEANS` does not require `a < 0`); +98. refuse treating unstandardised `MANIFESTMEANS` as `MANIFESTMEANSstd`, refuse treating `MANIFESTVARstd` as `MANIFESTMEANSstd` even when both equal 1, and refuse treating `τ / √(λ² Var(η) + θ)` as `MANIFESTMEANSstd`; 87. refuse pooling discrete lags from unequal event intervals as one coefficient; 88. refuse unmatched sampling and constancy intervals for a time-varying predictor (Oud & Jansen, 2000, unread); 89. refuse the difference quotient as a continuous-time rate; @@ -108,7 +110,7 @@ This slice stays inside `psychometric_core`. It does not add a second invariance ## Claim boundary -This is two-level OLS and a noiseless scalar continuous-time map. It is not DSEM, not RI-CLPM, not a random-effects sampler, not a Kalman filter, and not a matrix `expm` implementation. The CWC cluster-mean coefficient is the **contextual** effect, not the between-cluster effect. Discrete lags from different event intervals are not one coefficient. Equation 14 is not Equation 12. Discrete process noise \(Q_{\Delta t}\) is not the continuous diffusion \(GG^{\top}\). \(Q_{\Delta t}\) is the conditional residual variance, not \(\operatorname{Var}(\eta_{t})\). Finite-interval \(Q_{\Delta t}\) is not the stationary within-subject variance. Trait variance is not process noise and not the stationary within-subject variance. Measurement-error variance is not the observed-indicator variance. Latent variance is not the observed-indicator variance. Manifest means are not the observed-indicator mean. The latent mean is not the observed-indicator mean. The continuous intercept is not the manifest mean. The first-occasion latent mean is not the evolved latent mean. The continuous intercept is not the discrete mean increment. The first-occasion observed mean is not the evolved observed mean. The contemporaneous `TDPREDEFFECT` impulse is not the continuous intercept, not the time-independent discrete effect, and not Voelkle et al. (2012, Eq. 14). The time-independent `TIPREDEFFECT` increment is not the continuous intercept, not the contemporaneous impulse, not Voelkle et al. (2012, Eq. 14), and not the coefficient `B`. The within-interval `TDPREDEFFECT` carry `e^{A(t−u)} M x` for `t0 < u < t` is not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle et al. (2012, Eq. 14). The evolved observed mean `τ + λ μ_t` is not the contemporaneous-impulse observed mean `τ + λ(μ_t + m x)`. The contemporaneous composition `τ + λ(μ_t + m x)` is not the impulse-carry observed mean `τ + λ(μ_t + e^{a(t−u)} m x)` when `u ≠ t`. The evolved observed mean `τ + λ μ_t` is not the impulse-carry observed mean. The carried latent mean is not `E(y_t)`. The evolved-plus-impulse latent mean is not `E(y_t)`. The evolved observed mean `τ + λ μ_t` is not the time-independent-predictor observed mean `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`. The contemporaneous composition `τ + λ(μ_t + m x)` is not that time-independent-predictor observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that time-independent-predictor observed mean when `u ≠ t`. The evolved-plus-increment latent mean is not `E(y_t)`. The Table 3 first-occasion `T0TIPREDEFFECT` shift `t0_b z` is not the Eq. 3 process increment `A^{-1}[e^{A Δt} − I] B z`, not `κ`, and not `M x`. The Eq. 3 first-summand carry `e^{A Δt} t0_b z` is not `t0_b z` and is not that process increment. `T0TIPREDEFFECT` is the coefficient, not the first-occasion shift. The evolved observed mean `τ + λ μ_t` is not the first-occasion TI-predictor observed mean `τ + λ(μ_t + e^{a Δt} t0_b z)`. The process-increment composition `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that first-occasion observed mean. The contemporaneous composition `τ + λ(μ_t + m x)` is not that first-occasion observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that first-occasion observed mean when `u ≠ t0`. The evolved-plus-T0TIPRED latent mean is not `E(y_t)`. The Table 3 first-occasion `T0TDPREDEFFECT` shift `t0_m x0` is not `M x`, not `e^{A(t−u)} M x` for `t0 < u < t`, not `t0_b z`, not `A^{-1}[e^{A Δt} − I] B z`, and not `κ`. The Eq. 3 first-summand carry `e^{A Δt} t0_m x0` is not `t0_m x0` and is not that within-interval impulse carry. `T0TDPREDEFFECT` is the coefficient, not the first-occasion shift. An impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`. The evolved observed mean `τ + λ μ_t` is not the first-occasion TD-predictor observed mean `τ + λ(μ_t + e^{a Δt} t0_m x0)`. The process-increment composition `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that first-occasion TD observed mean. The contemporaneous composition `τ + λ(μ_t + m x)` is not that first-occasion TD observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that first-occasion TD observed mean when `u ≠ t0`. The first-occasion TI composition `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that first-occasion TD observed mean. Same numbers as `T0TIPREDEFFECT` yield the same product; Table 3 names a different matrix. The evolved-plus-T0TDPRED latent mean is not `E(y_t)`. The §7.2 level-change `CINT` `κ = −a m x` is not the dissipating Dirac `m x`, not a free `CINT`, and not `A^{-1}[e^{A Δt} − I] B z`. Lasting level change via that `CINT` setting requires `a < 0`. The extra near-zero-drift latent process also named in §7.2 is a different specification and is not that `CINT` setting. The Eq. 3 increment of that setting `(1 − e^{a Δt}) m x` is not the dissipating Dirac `m x`, not `κ`, and not `A^{-1}[e^{A Δt} − I] B z`. Underflow of `e^{a Δt}` to `+0` keeps the equilibrium offset `m x`. The §7.2 extra-process contribution `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` is not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`. Lasting level change via that extra process requires `ε < 0`. Precisely `ε = 0` causes computational problems in the printed specification. The extra-process observed mean `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` is not `τ + λ μ_t`, not `τ + λ(μ_t + m x)`, not the contribution, and not the evolved-plus-contribution latent mean. The extra process has `LAMBDA` 0 and is not an observed indicator. `T0TDPREDEFFECT` on the extra process uses `Δt = t − t0` for both the original-process evolution and the extra drive. `TDPREDEFFECT` after `t0` uses `t − u` with `t0 < u < t` for the extra drive while `μ_t` still uses `Δt`. The after-t0 extra-process observed mean is not the first-occasion extra-process observed mean when `u ≠ t0`. The impulse-carry `e^{a(t−u)} m x` is a Dirac on the original process and is not that `DRIFT` drive. The §7.2 `asymTIPREDEFFECT` `-B z / a` is the expected total change in process means given a time-independent predictor. It is not the coefficient `B`, not the finite-interval increment `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. Lasting asymptotic change via that map requires `a < 0`. The §7.2 `addedTIPREDVAR` `(B / a)² v` is the stable between-subject variance accounted for by that predictor. It is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`. Table 2 `asymCINT` `-κ / a` is the intercept contribution to the stationary process mean. It is not `κ`, not the finite-interval increment `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`. Lasting asymptotic intercept change via that map requires `a < 0`. Page 16 notes that a `T0MEANS` stationarity constraint includes time-independent predictors; that composition is not this intercept-only map. The p. 16 constrained first-occasion mean `-κ / a + −B z / a` is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean. Equation 5 of that constrained mean `τ + λ(−κ / a + −B z / a)` is not `τ + λ μ_0`, not `τ + λ(−κ / a)` when `B z ≠ 0`, not `τ + λ μ_t`, not `MANIFESTMEANS`, and not the constrained latent mean. The p. 16 constrained first-occasion variance `trait + −q / (2 a) + (B / a)² v` is not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Equation 5 of that constrained variance `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` is not `λ² p_0 + θ`, not `λ²(−q / (2 a)) + θ` when `TRAITVAR` or `addedTIPREDVAR` is nonzero, not `λ² Var(η_t) + θ` when the first occasion is constrained, not `MANIFESTVAR`, and not the constrained latent variance. The lagged covariance of that constrained process `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` is not contemporaneous `T0VAR`, not `e^{a Δt}` of the constrained total, and not `trait + e^{a Δt} p` when `addedTIPREDVAR` is nonzero. Trait variance and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Equation 5 of that lagged covariance `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ` is not `θ`, not contemporaneous `Var(y_0)`, and not the lagged latent covariance. Independent measurement error does not enter lagged observed covariance. The later-occasion variance of that constrained process `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` equals contemporaneous `T0VAR` under stationarity and is not the lagged covariance, not `e^{2 a Δt}` of the constrained total plus `Q_Δt`, and not `Q_Δt` alone. Trait variance and `addedTIPREDVAR` do not enter `Q_Δt`. Equation 5 of that later-occasion variance `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ` is not `θ`, not lagged `cov(y_t, y_{t-1})`, and not the later-occasion latent variance. The later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` is not stationary later-occasion variance when `p_0` is free, not `e^{2 a Δt}` of `trait + p_0 + (B / a)² v` plus `Q_Δt`, and not free `p_0`. Trait variance and `addedTIPREDVAR` do not enter `Q_Δt`. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. As `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that predetermined later-occasion variance `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ` is not `θ`, not the predetermined later-occasion latent variance, and not stationary later-occasion observed variance when `p_0` is free. The lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a Δt} p_0 + (B / a)² v` is not stationary lagged covariance when `p_0` is free, not later-occasion variance, not `e^{a Δt}` of `trait + p_0 + (B / a)² v`, and not free `p_0`. Trait variance and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. As `Δt → ∞` with stable `a < 0` the state term vanishes. A zero-diffusion carry with `a ≥ 0` is `e^{a Δt} p_0` and is kept. Equation 5 of that predetermined lagged covariance `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ` is not `θ`, not the predetermined lagged latent covariance, not predetermined later observed variance, and not stationary lagged observed covariance when `p_0` is free. Independent measurement error does not enter lagged observed covariance. The first-occasion variance of §4.3 predetermined `T0VAR` `trait + p_0 + (B / a)² v` is not stationary first-occasion variance when `p_0` is free, not free `p_0`, not lagged covariance, and not later-occasion variance. Trait variance and `addedTIPREDVAR` do not decay and do not enter `Q_Δt`. Setting `p_0 = −q / (2 a)` recovers the stationary first-occasion map. As `Δt → 0+` the lagged and later maps approach this composition. Trait-only variance does not require a stable drift. Equation 5 of that predetermined first-occasion variance `λ²(trait + p_0 + (B / a)² v) + θ + ψ` is not `θ`, not the predetermined first-occasion latent variance, not stationary first-occasion observed variance, and not predetermined later observed variance when `p_0` is free. The later-start lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` is not first-occasion lagged covariance when `u > 0`, not later-occasion variance, not stationary lagged covariance when `p_0` is free, and not `e^{a s}` of the later total. Trait variance and `addedTIPREDVAR` do not decay with `e^{a s}`. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. As `u → 0+` the composition approaches first-occasion lagged covariance. As `s → 0+` the composition approaches later-occasion variance at `u`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that later-start lagged covariance `λ²(trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v) + ψ` is not `θ`, not the later-start lagged latent covariance, not first-occasion lagged observed covariance, not predetermined later observed variance, and not stationary lagged observed covariance when `p_0` is free. Independent measurement error does not enter lagged observed covariance. The later-start later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` is not later-occasion variance at `u` when `s > 0`, not later-start lagged covariance, not stationary later-occasion variance when `p_0` is free, not `e^{2 a s}` of the later total plus `Q_s`, and not later-occasion variance over the lag interval alone when `u > 0`. Trait variance and `addedTIPREDVAR` do not enter `Q_s`. Chapman–Kolmogorov writes `Q_{u+s} = e^{2 a s} Q_u + Q_s`. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. As `u → 0+` the composition approaches later-occasion variance over `s`. As `s → 0+` the composition approaches later-occasion variance at `u`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that later-start later-occasion variance `λ²(trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v) + θ + ψ` is not `θ`, not the later-start later-occasion latent variance, not predetermined later observed variance, not later-start lagged observed covariance, and not stationary later-occasion observed variance when `p_0` is free. Page 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise `DRIFT` using only within-subject variance, not the total). Unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`. The §7.1 trait-plus-state autocorrelation `(trait + e^{a Δt} p + added) / (trait + p + added)` uses `TRAITVAR` and is not `discreteDRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise process noise using only within-subject variance, not the total). Unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`. The continuous standardisation `q / (−q / (2 a)) = −2 a` is not `discreteDIFFUSIONstd`. `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DIFFUSIONstd` is `q / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise process noise using only within-subject variance, not the total). Unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`. The discrete standardisation `Q_Δt / (−q / (2 a)) = 1 − exp(2 a Δt)` depends on the event interval and is not `DIFFUSIONstd`. `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise `DRIFT` using only within-subject variance, not the total). Unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`. The discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`. `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is `asymDIFFUSION`). Unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`. `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is `asymDIFFUSION`). Unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`. The asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`. `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Table 3 / p. 16 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` uses `asymDIFFUSION` and is not `T0TIPREDEFFECTstd`. `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`. `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. 2017-era `addedT0TIPREDVAR` is `t0_b² v` (`T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`). A zero coefficient or zero predictor variance is exactly zero. Free `T0TIPREDEFFECT` does not require `a < 0`. `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map. `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance. Free `T0VAR` is not this extra TI variance. `TRAITVAR` is not this extra TI variance. Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v`. Form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. `t0_b² v` is the latent extra, not the observed extra. `λ² p_0 + θ` is first-occasion observed variance, not this extra. `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra. `MANIFESTVAR` `θ` is not this extra. Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`. Form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. Lasting asymptotic extra requires `a < 0`. `(B / a)² v` is the latent extra, not the observed extra. `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra. `λ² p + θ` is stationary observed variance, not this extra. `MANIFESTVAR` `θ` is not this extra. Page 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive time-dependent predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is the TD predictor; the affected variance is `asymDIFFUSION`). Unstandardised `M` is defined for a zero coefficient and for zero predictor variance and is not `TDPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √p` is a different named matrix even when `M = B`. The finite-interval intercept-style standardisation `A^{-1}[e^{A Δt} − I] M · √v / √p` depends on the event interval and is not `TDPREDEFFECTstd`. `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive time-dependent predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is the TD predictor, not `TIPREDVAR`; the affected variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `t0_m` is defined for a zero coefficient and for zero predictor variance and is not `T0TDPREDEFFECTstd`. `TDPREDEFFECTstd` `m · √v / √(-q / (2 a))` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`. `T0TIPREDEFFECTstd` `t0_b · √v / √p_0` is a different named matrix even when `t0_m = t0_b`. `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Free `T0VAR` does not require `a < 0`. Page 16 `T0VARstd` is the correlation form `solve(sqrt(diag(T0VAR))) %&% T0VAR` after strictly positive free `T0VAR` `p_0` (2017-era `summary.ctsemFit.R`; OpenMx `%&%` is `t(A) %*% B %*% A`; the default ridge is 0; the scalar map is `p_0 / p_0 = 1`). Unstandardised `T0VAR` is defined for a zero first-occasion variance and is not `T0VARstd`. Zero `p_0` fails closed. Distinct positive `p_0` recover the same 1. `T0TDPREDEFFECTstd` `t0_m · √v / √p_0` depends on `p_0` and is not `T0VARstd`. `addedT0TIPREDVAR` `t0_b² v` is extra TI variance, not this correlation. `TRAITVAR` is not the standardisation variance. Page 16 `TRAITVARstd` is the correlation form `solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR` after strictly positive `TRAITVAR` (2017-era `summary.ctsemFit.R` forms it only when `TRAITVAR != 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `T0VARstd` there is no ridge addend; the scalar map is `trait / trait = 1`). Unstandardised `TRAITVAR` is defined for a zero trait and is not `TRAITVARstd`. Zero `TRAITVAR` fails closed. Distinct positive `trait` recover the same 1. `T0VARstd` `p_0 / p_0 = 1` recovers the same number and remains a distinct named quantity. `addedT0TIPREDVAR` `t0_b² v` is extra TI variance, not this correlation. `TRAITVAR` does not require `a < 0`. Page 16 `MANIFESTTRAITVARstd` is the correlation form `solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR` after strictly positive `MANIFESTTRAITVAR` (2017-era `summary.ctsemFit.R` forms it only when `MANIFESTTRAITVAR != 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; the scalar map is `ψ / ψ = 1`). Unstandardised `MANIFESTTRAITVAR` is defined for a zero trait and is not `MANIFESTTRAITVARstd`. Zero `MANIFESTTRAITVAR` fails closed. Distinct positive `ψ` recover the same 1. `TRAITVARstd` `trait / trait = 1` recovers the same number and remains a distinct named quantity. `MANIFESTVAR` `θ` is measurement error, not this correlation. `MANIFESTTRAITVAR` does not require `a < 0`. Page 16 `MANIFESTVARstd` is the correlation form `solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR` after strictly positive `MANIFESTVAR` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; the 2017-era `dimnames` assignment to `latentNames` is a source bug; the scalar map is `θ / θ = 1`). Unstandardised `MANIFESTVAR` is defined for a zero residual and is not `MANIFESTVARstd`. Zero `MANIFESTVAR` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `θ` recover the same 1. `MANIFESTTRAITVARstd` `ψ / ψ = 1` recovers the same number and remains a distinct named quantity. Equation 5 `λ² Var(η) + θ` is `Var(y)`, not this correlation. `MANIFESTVAR` does not require `a < 0`. Page 16 `TIPREDVARstd` is the correlation form `solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR` after strictly positive `TIPREDVAR` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE` and `n.TIpred > 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; `dimnames` are `TIpredNames`; the scalar map is `v / v = 1`). Unstandardised `TIPREDVAR` is defined for a zero predictor and is not `TIPREDVARstd`. Zero `TIPREDVAR` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `v` recover the same 1. `MANIFESTVARstd` `θ / θ = 1` recovers the same number and remains a distinct named quantity. Section 7.2 `addedTIPREDVAR` `(B / a)² v` is extra process variance, not this correlation. `TIPREDVAR` does not require `a < 0`. Page 16 `asymDIFFUSIONstd` is the correlation form `solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE`; OpenMx `%&%` is `t(A) %*% B %*% A`; the 2017-era source adds ridging; the default ridge is 0; `dimnames` are `latentNames`; the scalar map is `p / p = 1`). Unstandardised `asymDIFFUSION` is defined for a zero process and is not `asymDIFFUSIONstd`. Zero `q` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `p` recover the same 1. `TIPREDVARstd` `v / v = 1` recovers the same number and remains a distinct named quantity. `DIFFUSIONstd` `q / p = −2 a` is the continuous-diffusion ratio, not this correlation. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms unstandardised `discreteCINT` whenever `verbose = TRUE` as `solve(DRIFT) %*% (discreteDRIFT − I) %*% CINT`; that source does not form a `discreteCINTstd` matrix; the scalar map is the footnote 4 standardisation of that named discrete intercept). Unstandardised `discreteCINT` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteCINTstd`. Zero `q` has no positive process SD and fails closed. `κ / √p` does not depend on `Δt` and is not this finite-interval map. `(-κ / a) / √p` is the standardised asymptotic intercept and is not this map. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms unstandardised `asymCINT` whenever `verbose = TRUE` as `-solve(DRIFT) %*% CINT`; that source does not form an `asymCINTstd` matrix; the scalar map is the footnote 4 standardisation of that named asymptotic intercept). Unstandardised `asymCINT` is defined for a zero process and is not `asymCINTstd`. Zero `q` has no positive process SD and fails closed. `κ / √p` is the continuous intercept standardisation and is not this total-change map. `A^{-1}[e^{A Δt} − I] κ / √p` depends on the event interval and is not this `Δt → ∞` map. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR` `p_0` (2017-era `summary.ctsemFit.R` forms unstandardised `T0MEANS` and does not form a `T0MEANSstd` matrix; the scalar map is the footnote 4 standardisation of that named first-occasion mean; relevant variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `T0MEANS` is defined for a zero first-occasion variance and is not `T0MEANSstd`. Zero `p_0` has no positive SD and fails closed. `T0VARstd` `p_0 / p_0 = 1` recovers the same number when `μ_0 = √p_0` and remains a distinct named quantity. `μ_0 / √asymDIFFUSION` uses process-dynamics variance and is not this first-occasion map. Free `T0MEANS` does not require `a < 0`. +This is two-level OLS and a noiseless scalar continuous-time map. It is not DSEM, not RI-CLPM, not a random-effects sampler, not a Kalman filter, and not a matrix `expm` implementation. The CWC cluster-mean coefficient is the **contextual** effect, not the between-cluster effect. Discrete lags from different event intervals are not one coefficient. Equation 14 is not Equation 12. Discrete process noise \(Q_{\Delta t}\) is not the continuous diffusion \(GG^{\top}\). \(Q_{\Delta t}\) is the conditional residual variance, not \(\operatorname{Var}(\eta_{t})\). Finite-interval \(Q_{\Delta t}\) is not the stationary within-subject variance. Trait variance is not process noise and not the stationary within-subject variance. Measurement-error variance is not the observed-indicator variance. Latent variance is not the observed-indicator variance. Manifest means are not the observed-indicator mean. The latent mean is not the observed-indicator mean. The continuous intercept is not the manifest mean. The first-occasion latent mean is not the evolved latent mean. The continuous intercept is not the discrete mean increment. The first-occasion observed mean is not the evolved observed mean. The contemporaneous `TDPREDEFFECT` impulse is not the continuous intercept, not the time-independent discrete effect, and not Voelkle et al. (2012, Eq. 14). The time-independent `TIPREDEFFECT` increment is not the continuous intercept, not the contemporaneous impulse, not Voelkle et al. (2012, Eq. 14), and not the coefficient `B`. The within-interval `TDPREDEFFECT` carry `e^{A(t−u)} M x` for `t0 < u < t` is not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, and not Voelkle et al. (2012, Eq. 14). The evolved observed mean `τ + λ μ_t` is not the contemporaneous-impulse observed mean `τ + λ(μ_t + m x)`. The contemporaneous composition `τ + λ(μ_t + m x)` is not the impulse-carry observed mean `τ + λ(μ_t + e^{a(t−u)} m x)` when `u ≠ t`. The evolved observed mean `τ + λ μ_t` is not the impulse-carry observed mean. The carried latent mean is not `E(y_t)`. The evolved-plus-impulse latent mean is not `E(y_t)`. The evolved observed mean `τ + λ μ_t` is not the time-independent-predictor observed mean `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`. The contemporaneous composition `τ + λ(μ_t + m x)` is not that time-independent-predictor observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that time-independent-predictor observed mean when `u ≠ t`. The evolved-plus-increment latent mean is not `E(y_t)`. The Table 3 first-occasion `T0TIPREDEFFECT` shift `t0_b z` is not the Eq. 3 process increment `A^{-1}[e^{A Δt} − I] B z`, not `κ`, and not `M x`. The Eq. 3 first-summand carry `e^{A Δt} t0_b z` is not `t0_b z` and is not that process increment. `T0TIPREDEFFECT` is the coefficient, not the first-occasion shift. The evolved observed mean `τ + λ μ_t` is not the first-occasion TI-predictor observed mean `τ + λ(μ_t + e^{a Δt} t0_b z)`. The process-increment composition `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that first-occasion observed mean. The contemporaneous composition `τ + λ(μ_t + m x)` is not that first-occasion observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that first-occasion observed mean when `u ≠ t0`. The evolved-plus-T0TIPRED latent mean is not `E(y_t)`. The Table 3 first-occasion `T0TDPREDEFFECT` shift `t0_m x0` is not `M x`, not `e^{A(t−u)} M x` for `t0 < u < t`, not `t0_b z`, not `A^{-1}[e^{A Δt} − I] B z`, and not `κ`. The Eq. 3 first-summand carry `e^{A Δt} t0_m x0` is not `t0_m x0` and is not that within-interval impulse carry. `T0TDPREDEFFECT` is the coefficient, not the first-occasion shift. An impulse at `u ≤ t0` that used `M` is already in `η(t0)` as `TDPREDEFFECT`, not as `T0TDPREDEFFECT`. The evolved observed mean `τ + λ μ_t` is not the first-occasion TD-predictor observed mean `τ + λ(μ_t + e^{a Δt} t0_m x0)`. The process-increment composition `τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)` is not that first-occasion TD observed mean. The contemporaneous composition `τ + λ(μ_t + m x)` is not that first-occasion TD observed mean. The impulse-carry composition `τ + λ(μ_t + e^{a(t−u)} m x)` is not that first-occasion TD observed mean when `u ≠ t0`. The first-occasion TI composition `τ + λ(μ_t + e^{a Δt} t0_b z)` is not that first-occasion TD observed mean. Same numbers as `T0TIPREDEFFECT` yield the same product; Table 3 names a different matrix. The evolved-plus-T0TDPRED latent mean is not `E(y_t)`. The §7.2 level-change `CINT` `κ = −a m x` is not the dissipating Dirac `m x`, not a free `CINT`, and not `A^{-1}[e^{A Δt} − I] B z`. Lasting level change via that `CINT` setting requires `a < 0`. The extra near-zero-drift latent process also named in §7.2 is a different specification and is not that `CINT` setting. The Eq. 3 increment of that setting `(1 − e^{a Δt}) m x` is not the dissipating Dirac `m x`, not `κ`, and not `A^{-1}[e^{A Δt} − I] B z`. Underflow of `e^{a Δt}` to `+0` keeps the equilibrium offset `m x`. The §7.2 extra-process contribution `a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)` is not `κ = −a m x`, not `(1 − e^{a Δt}) m x`, and not the dissipating Dirac `m x`. Lasting level change via that extra process requires `ε < 0`. Precisely `ε = 0` causes computational problems in the printed specification. The extra-process observed mean `τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))` is not `τ + λ μ_t`, not `τ + λ(μ_t + m x)`, not the contribution, and not the evolved-plus-contribution latent mean. The extra process has `LAMBDA` 0 and is not an observed indicator. `T0TDPREDEFFECT` on the extra process uses `Δt = t − t0` for both the original-process evolution and the extra drive. `TDPREDEFFECT` after `t0` uses `t − u` with `t0 < u < t` for the extra drive while `μ_t` still uses `Δt`. The after-t0 extra-process observed mean is not the first-occasion extra-process observed mean when `u ≠ t0`. The impulse-carry `e^{a(t−u)} m x` is a Dirac on the original process and is not that `DRIFT` drive. The §7.2 `asymTIPREDEFFECT` `-B z / a` is the expected total change in process means given a time-independent predictor. It is not the coefficient `B`, not the finite-interval increment `A^{-1}[e^{A Δt} − I] B z`, not `CINT`, and not `M x`. Lasting asymptotic change via that map requires `a < 0`. The §7.2 `addedTIPREDVAR` `(B / a)² v` is the stable between-subject variance accounted for by that predictor. It is not `TRAITVAR`, not `asymDIFFUSION`, and not `-B z / a`. Table 2 `asymCINT` `-κ / a` is the intercept contribution to the stationary process mean. It is not `κ`, not the finite-interval increment `A^{-1}[e^{A Δt} − I] κ`, not `T0MEANS`, and not `-B z / a`. Lasting asymptotic intercept change via that map requires `a < 0`. Page 16 notes that a `T0MEANS` stationarity constraint includes time-independent predictors; that composition is not this intercept-only map. The p. 16 constrained first-occasion mean `-κ / a + −B z / a` is not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, and not the finite-interval discrete latent mean. Equation 5 of that constrained mean `τ + λ(−κ / a + −B z / a)` is not `τ + λ μ_0`, not `τ + λ(−κ / a)` when `B z ≠ 0`, not `τ + λ μ_t`, not `MANIFESTMEANS`, and not the constrained latent mean. The p. 16 constrained first-occasion variance `trait + −q / (2 a) + (B / a)² v` is not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone, and not the finite-interval discrete latent variance. Equation 5 of that constrained variance `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` is not `λ² p_0 + θ`, not `λ²(−q / (2 a)) + θ` when `TRAITVAR` or `addedTIPREDVAR` is nonzero, not `λ² Var(η_t) + θ` when the first occasion is constrained, not `MANIFESTVAR`, and not the constrained latent variance. The lagged covariance of that constrained process `trait + e^{a Δt}(−q / (2 a)) + (B / a)² v` is not contemporaneous `T0VAR`, not `e^{a Δt}` of the constrained total, and not `trait + e^{a Δt} p` when `addedTIPREDVAR` is nonzero. Trait variance and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Equation 5 of that lagged covariance `λ²(trait + e^{a Δt}(−q / (2 a)) + (B / a)² v) + ψ` is not `θ`, not contemporaneous `Var(y_0)`, and not the lagged latent covariance. Independent measurement error does not enter lagged observed covariance. The later-occasion variance of that constrained process `trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v` equals contemporaneous `T0VAR` under stationarity and is not the lagged covariance, not `e^{2 a Δt}` of the constrained total plus `Q_Δt`, and not `Q_Δt` alone. Trait variance and `addedTIPREDVAR` do not enter `Q_Δt`. Equation 5 of that later-occasion variance `λ²(trait + e^{2 a Δt}(−q / (2 a)) + Q_Δt + (B / a)² v) + θ + ψ` is not `θ`, not lagged `cov(y_t, y_{t-1})`, and not the later-occasion latent variance. The later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` is not stationary later-occasion variance when `p_0` is free, not `e^{2 a Δt}` of `trait + p_0 + (B / a)² v` plus `Q_Δt`, and not free `p_0`. Trait variance and `addedTIPREDVAR` do not enter `Q_Δt`. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. As `Δt → ∞` with stable `a < 0` the composition approaches contemporaneous stationary `T0VAR`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that predetermined later-occasion variance `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ` is not `θ`, not the predetermined later-occasion latent variance, and not stationary later-occasion observed variance when `p_0` is free. The lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a Δt} p_0 + (B / a)² v` is not stationary lagged covariance when `p_0` is free, not later-occasion variance, not `e^{a Δt}` of `trait + p_0 + (B / a)² v`, and not free `p_0`. Trait variance and `addedTIPREDVAR` do not decay with `e^{a Δt}`. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. As `Δt → ∞` with stable `a < 0` the state term vanishes. A zero-diffusion carry with `a ≥ 0` is `e^{a Δt} p_0` and is kept. Equation 5 of that predetermined lagged covariance `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ` is not `θ`, not the predetermined lagged latent covariance, not predetermined later observed variance, and not stationary lagged observed covariance when `p_0` is free. Independent measurement error does not enter lagged observed covariance. The first-occasion variance of §4.3 predetermined `T0VAR` `trait + p_0 + (B / a)² v` is not stationary first-occasion variance when `p_0` is free, not free `p_0`, not lagged covariance, and not later-occasion variance. Trait variance and `addedTIPREDVAR` do not decay and do not enter `Q_Δt`. Setting `p_0 = −q / (2 a)` recovers the stationary first-occasion map. As `Δt → 0+` the lagged and later maps approach this composition. Trait-only variance does not require a stable drift. Equation 5 of that predetermined first-occasion variance `λ²(trait + p_0 + (B / a)² v) + θ + ψ` is not `θ`, not the predetermined first-occasion latent variance, not stationary first-occasion observed variance, and not predetermined later observed variance when `p_0` is free. The later-start lagged covariance of §4.3 predetermined `T0VAR` `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v` is not first-occasion lagged covariance when `u > 0`, not later-occasion variance, not stationary lagged covariance when `p_0` is free, and not `e^{a s}` of the later total. Trait variance and `addedTIPREDVAR` do not decay with `e^{a s}`. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. As `u → 0+` the composition approaches first-occasion lagged covariance. As `s → 0+` the composition approaches later-occasion variance at `u`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that later-start lagged covariance `λ²(trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v) + ψ` is not `θ`, not the later-start lagged latent covariance, not first-occasion lagged observed covariance, not predetermined later observed variance, and not stationary lagged observed covariance when `p_0` is free. Independent measurement error does not enter lagged observed covariance. The later-start later-occasion variance of §4.3 predetermined `T0VAR` `trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v` is not later-occasion variance at `u` when `s > 0`, not later-start lagged covariance, not stationary later-occasion variance when `p_0` is free, not `e^{2 a s}` of the later total plus `Q_s`, and not later-occasion variance over the lag interval alone when `u > 0`. Trait variance and `addedTIPREDVAR` do not enter `Q_s`. Chapman–Kolmogorov writes `Q_{u+s} = e^{2 a s} Q_u + Q_s`. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. As `u → 0+` the composition approaches later-occasion variance over `s`. As `s → 0+` the composition approaches later-occasion variance at `u`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Equation 5 of that later-start later-occasion variance `λ²(trait + e^{2 a s}(e^{2 a u} p_0 + Q_u) + Q_s + (B / a)² v) + θ + ψ` is not `θ`, not the later-start later-occasion latent variance, not predetermined later observed variance, not later-start lagged observed covariance, and not stationary later-occasion observed variance when `p_0` is free. Page 16 `discreteDRIFTstd` is `e^{a Δt}` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise `DRIFT` using only within-subject variance, not the total). Unstandardised `e^{a Δt}` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDRIFTstd`. The §7.1 trait-plus-state autocorrelation `(trait + e^{a Δt} p + added) / (trait + p + added)` uses `TRAITVAR` and is not `discreteDRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `discreteDIFFUSIONstd` is `Q_Δt / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise process noise using only within-subject variance, not the total). Unstandardised `Q_Δt` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteDIFFUSIONstd`. The continuous standardisation `q / (−q / (2 a)) = −2 a` is not `discreteDIFFUSIONstd`. `Q_Δt / (trait + p + added)` uses `TRAITVAR` and is not `discreteDIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DIFFUSIONstd` is `q / (−q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise process noise using only within-subject variance, not the total). Unstandardised `q` is defined for growing `a ≥ 0` and for zero diffusion and is not `DIFFUSIONstd`. The discrete standardisation `Q_Δt / (−q / (2 a)) = 1 − exp(2 a Δt)` depends on the event interval and is not `DIFFUSIONstd`. `q / (trait + p + added)` uses `TRAITVAR` and is not `DIFFUSIONstd`. `TRAITVAR` is not the standardisation variance. Page 16 `DRIFTstd` is the continuous auto-effect after strictly positive `asymDIFFUSION` `-q / (2 a)` (footnote 4: standardise `DRIFT` using only within-subject variance, not the total). Unstandardised `a` is defined for growing `a ≥ 0` and for zero diffusion and is not `DRIFTstd`. The discrete standardisation `e^{a Δt}` depends on the event interval and is not `DRIFTstd`. `a p / (trait + p + added)` uses `TRAITVAR` and is not `DRIFTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `asymTIPREDEFFECTstd` is `(-B / a) · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is `asymDIFFUSION`). Unstandardised `-B / a` is defined for a zero coefficient and for zero predictor variance and is not `asymTIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `asymTIPREDEFFECTstd`. `(-B / a) · √v / √(trait + p + added)` uses `TRAITVAR` and is not `asymTIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Page 16 `TIPREDEFFECTstd` is `B · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is `asymDIFFUSION`). Unstandardised `B` is defined for a zero coefficient and for zero predictor variance and is not `TIPREDEFFECTstd`. The asymptotic standardisation `(-B / a) · √v / √p` is the total change and is not `TIPREDEFFECTstd`. The finite-interval standardisation `A^{-1}[e^{A Δt} − I] B · √v / √p` depends on the event interval and is not `TIPREDEFFECTstd`. `B · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Table 3 / p. 16 `T0TIPREDEFFECTstd` is `t0_b · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is `TIPREDVAR`; the affected variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `t0_b` is defined for a zero coefficient and for zero predictor variance and is not `T0TIPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √(-q / (2 a))` uses `asymDIFFUSION` and is not `T0TIPREDEFFECTstd`. `asymTIPREDEFFECTstd` `(-B / a) · √v / √p` is the total change and is not `T0TIPREDEFFECTstd`. `t0_b · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TIPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. 2017-era `addedT0TIPREDVAR` is `t0_b² v` (`T0TIPREDEFFECT %*% TIPREDVAR %*% t(T0TIPREDEFFECT)` immediately after `T0TIPREDEFFECTstd`). A zero coefficient or zero predictor variance is exactly zero. Free `T0TIPREDEFFECT` does not require `a < 0`. `(B / a)² v` is `addedTIPREDVAR` and is not this first-occasion map. `t0_b · √v / √p_0` is `T0TIPREDEFFECTstd` and is not this variance. Free `T0VAR` is not this extra TI variance. `TRAITVAR` is not this extra TI variance. Equation 5 of 2017-era `addedT0TIPREDVAR` is `λ² t0_b² v`. Form `t0_b² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. `t0_b² v` is the latent extra, not the observed extra. `λ² p_0 + θ` is first-occasion observed variance, not this extra. `λ² (B / a)² v` is Eq. 5 of `addedTIPREDVAR`, not this first-occasion observed extra. `MANIFESTVAR` `θ` is not this extra. Equation 5 of §7.2 `addedTIPREDVAR` is `λ² (B / a)² v`. Form `(B / a)² v` first, then `(λ extra) λ` with `θ = 0`. A zero loading or zero extra is exactly zero. Lasting asymptotic extra requires `a < 0`. `(B / a)² v` is the latent extra, not the observed extra. `λ² t0_b² v` is first-occasion extra observed TI variance, not this extra. `λ² p + θ` is stationary observed variance, not this extra. `MANIFESTVAR` `θ` is not this extra. Page 16 `TDPREDEFFECTstd` is `m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` `-q / (2 a)` and strictly positive time-dependent predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is the TD predictor; the affected variance is `asymDIFFUSION`). Unstandardised `M` is defined for a zero coefficient and for zero predictor variance and is not `TDPREDEFFECTstd`. `TIPREDEFFECTstd` `B · √v / √p` is a different named matrix even when `M = B`. The finite-interval intercept-style standardisation `A^{-1}[e^{A Δt} − I] M · √v / √p` depends on the event interval and is not `TDPREDEFFECTstd`. `m · √v / √(trait + p + added)` uses `TRAITVAR` and is not `TDPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Table 3 / p. 16 `T0TDPREDEFFECTstd` is `t0_m · √v / √p_0` after strictly positive free `T0VAR` `p_0` and strictly positive time-dependent predictor variance `v` (footnote 4: standardise using only the relevant variance, not the total; the affecting variance is the TD predictor, not `TIPREDVAR`; the affected variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `t0_m` is defined for a zero coefficient and for zero predictor variance and is not `T0TDPREDEFFECTstd`. `TDPREDEFFECTstd` `m · √v / √(-q / (2 a))` uses `asymDIFFUSION` and is not `T0TDPREDEFFECTstd`. `T0TIPREDEFFECTstd` `t0_b · √v / √p_0` is a different named matrix even when `t0_m = t0_b`. `t0_m · √v / √(trait + p_0 + added)` uses `TRAITVAR` and is not `T0TDPREDEFFECTstd`. `TRAITVAR` is not the standardisation variance. Free `T0VAR` does not require `a < 0`. Page 16 `T0VARstd` is the correlation form `solve(sqrt(diag(T0VAR))) %&% T0VAR` after strictly positive free `T0VAR` `p_0` (2017-era `summary.ctsemFit.R`; OpenMx `%&%` is `t(A) %*% B %*% A`; the default ridge is 0; the scalar map is `p_0 / p_0 = 1`). Unstandardised `T0VAR` is defined for a zero first-occasion variance and is not `T0VARstd`. Zero `p_0` fails closed. Distinct positive `p_0` recover the same 1. `T0TDPREDEFFECTstd` `t0_m · √v / √p_0` depends on `p_0` and is not `T0VARstd`. `addedT0TIPREDVAR` `t0_b² v` is extra TI variance, not this correlation. `TRAITVAR` is not the standardisation variance. Page 16 `TRAITVARstd` is the correlation form `solve(sqrt(diag(TRAITVAR))) %&% TRAITVAR` after strictly positive `TRAITVAR` (2017-era `summary.ctsemFit.R` forms it only when `TRAITVAR != 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `T0VARstd` there is no ridge addend; the scalar map is `trait / trait = 1`). Unstandardised `TRAITVAR` is defined for a zero trait and is not `TRAITVARstd`. Zero `TRAITVAR` fails closed. Distinct positive `trait` recover the same 1. `T0VARstd` `p_0 / p_0 = 1` recovers the same number and remains a distinct named quantity. `addedT0TIPREDVAR` `t0_b² v` is extra TI variance, not this correlation. `TRAITVAR` does not require `a < 0`. Page 16 `MANIFESTTRAITVARstd` is the correlation form `solve(sqrt(diag(MANIFESTTRAITVAR))) %&% MANIFESTTRAITVAR` after strictly positive `MANIFESTTRAITVAR` (2017-era `summary.ctsemFit.R` forms it only when `MANIFESTTRAITVAR != 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; the scalar map is `ψ / ψ = 1`). Unstandardised `MANIFESTTRAITVAR` is defined for a zero trait and is not `MANIFESTTRAITVARstd`. Zero `MANIFESTTRAITVAR` fails closed. Distinct positive `ψ` recover the same 1. `TRAITVARstd` `trait / trait = 1` recovers the same number and remains a distinct named quantity. `MANIFESTVAR` `θ` is measurement error, not this correlation. `MANIFESTTRAITVAR` does not require `a < 0`. Page 16 `MANIFESTVARstd` is the correlation form `solve(sqrt(diag(MANIFESTVAR))) %&% MANIFESTVAR` after strictly positive `MANIFESTVAR` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; the 2017-era `dimnames` assignment to `latentNames` is a source bug; the scalar map is `θ / θ = 1`). Unstandardised `MANIFESTVAR` is defined for a zero residual and is not `MANIFESTVARstd`. Zero `MANIFESTVAR` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `θ` recover the same 1. `MANIFESTTRAITVARstd` `ψ / ψ = 1` recovers the same number and remains a distinct named quantity. Equation 5 `λ² Var(η) + θ` is `Var(y)`, not this correlation. `MANIFESTVAR` does not require `a < 0`. Page 16 `TIPREDVARstd` is the correlation form `solve(sqrt(diag(TIPREDVAR))) %&% TIPREDVAR` after strictly positive `TIPREDVAR` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE` and `n.TIpred > 0`; OpenMx `%&%` is `t(A) %*% B %*% A`; unlike `TRAITVARstd` the 2017-era source adds ridging; the default ridge is 0; `dimnames` are `TIpredNames`; the scalar map is `v / v = 1`). Unstandardised `TIPREDVAR` is defined for a zero predictor and is not `TIPREDVARstd`. Zero `TIPREDVAR` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `v` recover the same 1. `MANIFESTVARstd` `θ / θ = 1` recovers the same number and remains a distinct named quantity. Section 7.2 `addedTIPREDVAR` `(B / a)² v` is extra process variance, not this correlation. `TIPREDVAR` does not require `a < 0`. Page 16 `asymDIFFUSIONstd` is the correlation form `solve(sqrt(diag(asymDIFFUSION))) %&% asymDIFFUSION` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms it whenever `verbose = TRUE`; OpenMx `%&%` is `t(A) %*% B %*% A`; the 2017-era source adds ridging; the default ridge is 0; `dimnames` are `latentNames`; the scalar map is `p / p = 1`). Unstandardised `asymDIFFUSION` is defined for a zero process and is not `asymDIFFUSIONstd`. Zero `q` makes `solve(sqrt(0))` fail and fails closed. Distinct positive `p` recover the same 1. `TIPREDVARstd` `v / v = 1` recovers the same number and remains a distinct named quantity. `DIFFUSIONstd` `q / p = −2 a` is the continuous-diffusion ratio, not this correlation. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `discreteCINTstd` is `A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms unstandardised `discreteCINT` whenever `verbose = TRUE` as `solve(DRIFT) %*% (discreteDRIFT − I) %*% CINT`; that source does not form a `discreteCINTstd` matrix; the scalar map is the footnote 4 standardisation of that named discrete intercept). Unstandardised `discreteCINT` is defined for growing `a ≥ 0` and for zero diffusion and is not `discreteCINTstd`. Zero `q` has no positive process SD and fails closed. `κ / √p` does not depend on `Δt` and is not this finite-interval map. `(-κ / a) / √p` is the standardised asymptotic intercept and is not this map. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `asymCINTstd` is `(-κ / a) / √p` after strictly positive `asymDIFFUSION` `-q / (2 a)` (2017-era `summary.ctsemFit.R` forms unstandardised `asymCINT` whenever `verbose = TRUE` as `-solve(DRIFT) %*% CINT`; that source does not form an `asymCINTstd` matrix; the scalar map is the footnote 4 standardisation of that named asymptotic intercept). Unstandardised `asymCINT` is defined for a zero process and is not `asymCINTstd`. Zero `q` has no positive process SD and fails closed. `κ / √p` is the continuous intercept standardisation and is not this total-change map. `A^{-1}[e^{A Δt} − I] κ / √p` depends on the event interval and is not this `Δt → ∞` map. Lasting `asymDIFFUSION` requires `a < 0`. Page 16 `T0MEANSstd` is `μ_0 / √p_0` after strictly positive free `T0VAR` `p_0` (2017-era `summary.ctsemFit.R` forms unstandardised `T0MEANS` and does not form a `T0MEANSstd` matrix; the scalar map is the footnote 4 standardisation of that named first-occasion mean; relevant variance is free `T0VAR`, not `asymDIFFUSION`). Unstandardised `T0MEANS` is defined for a zero first-occasion variance and is not `T0MEANSstd`. Zero `p_0` has no positive SD and fails closed. `T0VARstd` `p_0 / p_0 = 1` recovers the same number when `μ_0 = √p_0` and remains a distinct named quantity. `μ_0 / √asymDIFFUSION` uses process-dynamics variance and is not this first-occasion map. Free `T0MEANS` does not require `a < 0`. Page 16 `MANIFESTMEANSstd` is `τ / √θ` after strictly positive `MANIFESTVAR` `θ` (2017-era `summary.ctsemFit.R` forms unstandardised `MANIFESTMEANS` and does not form a `MANIFESTMEANSstd` matrix; the scalar map is the footnote 4 standardisation of that named measurement intercept; relevant variance is residual `MANIFESTVAR`, not total observed `Var(y)`). Unstandardised `MANIFESTMEANS` is defined for a zero residual and is not `MANIFESTMEANSstd`. Zero `θ` has no positive SD and fails closed. `MANIFESTVARstd` `θ / θ = 1` recovers the same number when `τ = √θ` and remains a distinct named quantity. `τ / √(λ² Var(η) + θ)` uses total observed variance and is not this residual map. `MANIFESTMEANS` does not require `a < 0`. ## Authoritative sources @@ -178,6 +180,7 @@ The Voelkle et al. (2012) ZORA accepted manuscript was re-opened 2026-08-18T21:0 - **CWC-then-lag.** Sample cluster means are removed first. Consecutive within residuals are then fitted by least squares to \(r_{t+\Delta t}\approx\exp(a\Delta t)\,r_{t}\) on event time. Same-sign pair-wise logs initialize the scalar Newton step. Sign-flipping \(T=2\) CWC pairs have no real logarithm and fail closed. Curran and Bauer (2011, pp. 607–608) show that this person-mean subtraction on a raw autoregressive series does **not** isolate the lagged within-person effect; the helper therefore does not claim to recover the raw-process drift. - **Already-centered irregular residual.** The caller supplies lagged within residuals. The mean of \(a=\ln(r_{t+\Delta t}/r_t)/\Delta t\) is the exact scalar map. Intervals may be irregular. The helper does not center again. This is not DSEM. - **Standardised initial latent mean.** Driver et al. (2017, Table 2, p. 12; p. 16; footnote 4; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-24T22:30Z): Table 2 names `T0MEANS` the latent process means at the first time point `T0`. Footnote 4 standardises using only the relevant variance, not the total. The first-occasion relevant variance is free `T0VAR` `p_0`, not `asymDIFFUSION`. The 2017-era source forms unstandardised `T0MEANS` and does not form `T0MEANSstd`. The scalar map is `μ_0/√p_0`. Form strictly positive `p_0` first, then divide. A zero mean is exactly zero. Zero `p_0` has no positive SD and fails closed. `T0` is an event-time occasion. Free `T0MEANS` does not require `a<0`. `T0VARstd` is not this map even when both equal 1. `μ_0/√asymDIFFUSION` is not this map. An overflowing quotient fails closed. This is not a Kalman filter and not ctsem estimation. +- **Standardised manifest mean.** Driver et al. (2017, Table 2, p. 12; p. 16; footnote 4; Eq. 5, p. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-25T05:04Z): Table 2 names `MANIFESTMEANS` `τ` the matrix of manifest means. Footnote 4 standardises using only the relevant variance, not the total. The relevant variance is residual `MANIFESTVAR` `θ`, not total observed `Var(y)`. The 2017-era source forms unstandardised `MANIFESTMEANS` and does not form `MANIFESTMEANSstd`. The scalar map is `τ/√θ`. Form strictly positive `θ` first, then divide. A zero mean is exactly zero. Zero `θ` has no positive SD and fails closed. Manifest means are event-time measurement quantities. `MANIFESTMEANS` does not require `a<0`. `MANIFESTVARstd` is not this map even when both equal 1. `τ/√(λ²Var(η)+θ)` is not this map. The 2017-era `dimnames` assignment on an `n.manifest × 1` matrix is a source bug and is not this map. An overflowing quotient fails closed. This is not a Kalman filter and not ctsem estimation. ## Verification @@ -252,3 +255,4 @@ The Voelkle et al. (2012) ZORA accepted manuscript was re-opened 2026-08-18T21:0 - Driver et al. (2017, p. 16 `discreteCINTstd`; footnote 4; Eq. 3; Table 2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-24T05:20Z) recovers the scalar standardised discrete intercept \(A^{-1}[e^{A\Delta t}-I]\kappa/\sqrt{p}\) at machine-scale RMSE after strictly positive `asymDIFFUSION` \(-q/(2a)\), and that RMSE is smaller than treating unstandardised `discreteCINT`, \(\kappa/\sqrt{p}\), or \((-\kappa/a)/\sqrt{p}\) as `discreteCINTstd`; a later event interval changes the result; a zero intercept is exactly zero; `q = 0` fails closed; a non-event clock fails closed; a non-positive event interval fails closed; \(a\ge 0\) fails closed. - Driver et al. (2017, p. 16 `asymCINTstd`; footnote 4; Eq. 3; Table 2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-24T09:05Z) recovers the scalar standardised asymptotic intercept \((-\kappa/a)/\sqrt{p}\) at machine-scale RMSE after strictly positive `asymDIFFUSION` \(-q/(2a)\), and that RMSE is smaller than treating unstandardised `asymCINT`, \(\kappa/\sqrt{p}\), or `discreteCINTstd` as `asymCINTstd`; a later event interval changes `discreteCINTstd` and not this map; a zero intercept is exactly zero; `q = 0` fails closed; a non-event clock fails closed; \(a\ge 0\) fails closed. - Driver et al. (2017, p. 16 `T0MEANSstd`; footnote 4; Table 2; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-24T22:30Z) recovers the scalar standardised initial latent mean \(\mu_0/\sqrt{p_0}\) at machine-scale RMSE after strictly positive free `T0VAR` \(p_0\), and that RMSE is smaller than treating unstandardised `T0MEANS` or \(\mu_0/\sqrt{\mathrm{asymDIFFUSION}}\) as `T0MEANSstd`; a larger positive \(p_0\) yields a smaller \(|\mathrm{std}|\); a zero mean is exactly zero; equal 1 with `T0VARstd` when \(\mu_0=\sqrt{p_0}\) remains a distinct named quantity; \(p_0=0\) fails closed; a non-event clock fails closed; free `T0MEANS` does not require \(a<0\). +- Driver et al. (2017, p. 16 `MANIFESTMEANSstd`; footnote 4; Table 2; Eq. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-25T05:04Z) recovers the scalar standardised manifest mean \(\tau/\sqrt{\theta}\) at machine-scale RMSE after strictly positive `MANIFESTVAR` \(\theta\), and that RMSE is smaller than treating unstandardised `MANIFESTMEANS` or \(\tau/\sqrt{\lambda^{2}\mathrm{Var}(\eta)+\theta}\) as `MANIFESTMEANSstd`; a larger positive \(\theta\) yields a smaller \(|\mathrm{std}|\); a zero mean is exactly zero; equal 1 with `MANIFESTVARstd` when \(\tau=\sqrt{\theta}\) remains a distinct named quantity; equal numbers with `T0MEANSstd` when \(\tau=\mu_0\) and \(\theta=p_0\) remain distinct named quantities; \(\theta=0\) fails closed; a non-event clock fails closed; `MANIFESTMEANS` does not require \(a<0\). diff --git a/docs/research/standards-and-literature.md b/docs/research/standards-and-literature.md index f1761730..cdff5d0e 100644 --- a/docs/research/standards-and-literature.md +++ b/docs/research/standards-and-literature.md @@ -124,11 +124,13 @@ Yang, X., Zhao, H., Phung, D., Buntine, W., & Du, L. (2025). LLM reading tea lea Akaike, H. (1974). A new look at the statistical model identification. *IEEE Transactions on Automatic Control, 19*(6), 716–723. https://doi.org/10.1109/TAC.1974.1100705 +Schwarz, G. (1978). Estimating the dimension of a model. *The Annals of Statistics, 6*(2), 461–464. https://doi.org/10.1214/aos/1176344136 + Burnham, K. P., & Anderson, D. R. (2002). *Model selection and multimodel inference: A practical information-theoretic approach* (2nd ed.). Springer. Deb, K., Pratap, A., Agarwal, S., Meyarivan, T. (2002). A fast and elitist multiobjective genetic algorithm: NSGA-II. *IEEE Transactions on Evolutionary Computation, 6*(2), 182–197. https://doi.org/10.1109/4235.996017 -LLM evaluation complements but never replaces predictive, posterior, stability, alignment, fairness, recovery, and human-validation evidence. The current `model_selection` crate performs statistical/Pareto gating; candidate blinding and blinded LLM review remain accepted-target extensions and are not executed by this crate. Pareto-filtered held-out log-likelihood and complexity admit a candidate `K`; an LLM vote cannot define the numerical optimum. `interpretation_gateway` records judgments as hypothetical proposals that must cite evidence spans and cannot become estimator results or observed facts. +LLM evaluation complements but never replaces predictive, posterior, stability, alignment, fairness, recovery, and human-validation evidence. The current `model_selection` crate fits each candidate `K` with the CPU `f64` reference and applies statistical/Pareto gating to those fitted diagnostics; candidate blinding and blinded LLM review remain accepted-target extensions and are not executed by this crate. Pareto-filtered in-sample mixture log-likelihood and Schwarz (1978) complexity `ℓ − (p ln N)/2` admit a candidate `K`; an LLM vote cannot define the numerical optimum. The fitted path copies the ADR 0012 / `topic_measurement` reference hyperparameters rather than inventing a second set. `interpretation_gateway` records judgments as hypothetical proposals that must cite evidence spans and cannot become estimator results or observed facts. ## Compositional data, correlation, and clusters