diff --git a/CHANGELOG.md b/CHANGELOG.md index d68264a2..531166fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ## [Unreleased] +- Release engineering: the workspace version is bumped `0.1.0` → `0.2.0` across `[workspace.package]`, every inheriting crate manifest, and all inter-crate version pins so CHANGELOG, manifests, and lockfile agree on one released identity. The psychometric stack files regressed by a rebase-merge resolution (`1795ae8b`) are restored to their consistent stack-final content, returning 502 green psychometric tests and 1,472 workspace-wide. - 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. diff --git a/Cargo.lock b/Cargo.lock index f031078a..3d9c4c3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,7 +60,7 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "analysis_engine" -version = "0.1.0" +version = "0.2.0" dependencies = [ "corpus_split", "membership_core", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "assertion_clock" -version = "0.1.0" +version = "0.2.0" [[package]] name = "atoi" @@ -95,7 +95,7 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "available_clock" -version = "0.1.0" +version = "0.2.0" [[package]] name = "backtrace" @@ -184,7 +184,7 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "checkpoint_authority" -version = "0.1.0" +version = "0.2.0" [[package]] name = "cipher" @@ -199,7 +199,7 @@ dependencies = [ [[package]] name = "citation_edge" -version = "0.1.0" +version = "0.2.0" [[package]] name = "cmov" @@ -209,23 +209,23 @@ checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "compute_backend" -version = "0.1.0" +version = "0.2.0" [[package]] name = "copied_text" -version = "0.1.0" +version = "0.2.0" [[package]] name = "copy_identity" -version = "0.1.0" +version = "0.2.0" [[package]] name = "corpus_background" -version = "0.1.0" +version = "0.2.0" [[package]] name = "corpus_split" -version = "0.1.0" +version = "0.2.0" dependencies = [ "temporal_core", "unicode-normalization", @@ -325,7 +325,7 @@ dependencies = [ [[package]] name = "cutoff_clock" -version = "0.1.0" +version = "0.2.0" [[package]] name = "defmt" @@ -360,7 +360,7 @@ dependencies = [ [[package]] name = "derived_sensitivity" -version = "0.1.0" +version = "0.2.0" [[package]] name = "digest" @@ -386,7 +386,7 @@ dependencies = [ [[package]] name = "document_clocks" -version = "0.1.0" +version = "0.2.0" [[package]] name = "dotenvy" @@ -405,7 +405,7 @@ dependencies = [ [[package]] name = "encrypted_mapping" -version = "0.1.0" +version = "0.2.0" dependencies = [ "aes-gcm", "getrandom 0.4.3", @@ -414,7 +414,7 @@ dependencies = [ [[package]] name = "episode_membership" -version = "0.1.0" +version = "0.2.0" [[package]] name = "equivalent" @@ -445,11 +445,11 @@ dependencies = [ [[package]] name = "event_clock" -version = "0.1.0" +version = "0.2.0" [[package]] name = "event_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "evidence_core", "serde", @@ -460,7 +460,7 @@ dependencies = [ [[package]] name = "evidence_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "inferred_status" -version = "0.1.0" +version = "0.2.0" [[package]] name = "inout" @@ -799,11 +799,11 @@ dependencies = [ [[package]] name = "intake_authorization" -version = "0.1.0" +version = "0.2.0" [[package]] name = "interpretation_gateway" -version = "0.1.0" +version = "0.2.0" dependencies = [ "uuid", ] @@ -898,7 +898,7 @@ checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "location_membership" -version = "0.1.0" +version = "0.2.0" [[package]] name = "lock_api" @@ -917,7 +917,7 @@ checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "longitudinal_core" -version = "0.1.0" +version = "0.2.0" [[package]] name = "md-5" @@ -931,7 +931,7 @@ dependencies = [ [[package]] name = "membership_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", @@ -941,7 +941,7 @@ dependencies = [ [[package]] name = "membership_target" -version = "0.1.0" +version = "0.2.0" [[package]] name = "memchr" @@ -971,11 +971,11 @@ dependencies = [ [[package]] name = "modality_source" -version = "0.1.0" +version = "0.2.0" [[package]] name = "model_selection" -version = "0.1.0" +version = "0.2.0" dependencies = [ "corpus_split", "membership_core", @@ -987,7 +987,7 @@ dependencies = [ [[package]] name = "network_analysis" -version = "0.1.0" +version = "0.2.0" [[package]] name = "num-traits" @@ -1015,11 +1015,11 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "operational_log" -version = "0.1.0" +version = "0.2.0" [[package]] name = "orchestrator_live" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "outcome_order" -version = "0.1.0" +version = "0.2.0" [[package]] name = "parking" @@ -1060,7 +1060,7 @@ dependencies = [ [[package]] name = "payload_bound" -version = "0.1.0" +version = "0.2.0" [[package]] name = "percent-encoding" @@ -1070,7 +1070,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "persistence_postgres" -version = "0.1.0" +version = "0.2.0" dependencies = [ "operational_log", "sqlx", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "prediction_contradiction" -version = "0.1.0" +version = "0.2.0" dependencies = [ "temporal_core", ] @@ -1153,19 +1153,19 @@ dependencies = [ [[package]] name = "prompt_source" -version = "0.1.0" +version = "0.2.0" [[package]] name = "provider_receipt" -version = "0.1.0" +version = "0.2.0" [[package]] name = "psychometric_core" -version = "0.1.0" +version = "0.2.0" [[package]] name = "psychometric_fit" -version = "0.1.0" +version = "0.2.0" [[package]] name = "quote" @@ -1232,11 +1232,11 @@ dependencies = [ [[package]] name = "relation_absence" -version = "0.1.0" +version = "0.2.0" [[package]] name = "relation_graph" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", @@ -1246,11 +1246,11 @@ dependencies = [ [[package]] name = "retrospective_edge" -version = "0.1.0" +version = "0.2.0" [[package]] name = "revision_order" -version = "0.1.0" +version = "0.2.0" [[package]] name = "ring" @@ -1268,7 +1268,7 @@ dependencies = [ [[package]] name = "role_contradiction" -version = "0.1.0" +version = "0.2.0" [[package]] name = "rustc-demangle" @@ -1324,7 +1324,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semantic_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "evidence_core", ] @@ -1374,7 +1374,7 @@ dependencies = [ [[package]] name = "service_tls" -version = "0.1.0" +version = "0.2.0" dependencies = [ "rustls", ] @@ -1549,7 +1549,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stopword_deletion" -version = "0.1.0" +version = "0.2.0" [[package]] name = "stringprep" @@ -1564,11 +1564,11 @@ dependencies = [ [[package]] name = "style_source" -version = "0.1.0" +version = "0.2.0" [[package]] name = "subevent_containment" -version = "0.1.0" +version = "0.2.0" [[package]] name = "subtle" @@ -1578,11 +1578,11 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "summarizes_edge" -version = "0.1.0" +version = "0.2.0" [[package]] name = "support_edge" -version = "0.1.0" +version = "0.2.0" [[package]] name = "syn" @@ -1619,11 +1619,11 @@ dependencies = [ [[package]] name = "system_clock" -version = "0.1.0" +version = "0.2.0" [[package]] name = "temporal_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "jiff", "serde", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "tepp_api" -version = "0.1.0" +version = "0.2.0" dependencies = [ "corpus_split", "jiff", @@ -1646,7 +1646,7 @@ dependencies = [ [[package]] name = "tepp_simulation" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", @@ -1742,14 +1742,14 @@ dependencies = [ [[package]] name = "topic_lineage" -version = "0.1.0" +version = "0.2.0" dependencies = [ "uuid", ] [[package]] name = "topic_measurement" -version = "0.1.0" +version = "0.2.0" dependencies = [ "corpus_split", "membership_core", @@ -1872,7 +1872,7 @@ dependencies = [ [[package]] name = "validation_core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 008035fb..df9aae9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,7 +120,7 @@ default-members = [ ] [workspace.package] -version = "0.1.0" +version = "0.2.0" edition = "2024" rust-version = "1.98.0" license = "Apache-2.0" diff --git a/crates/analysis_engine/Cargo.toml b/crates/analysis_engine/Cargo.toml index 995ad914..59731bf7 100644 --- a/crates/analysis_engine/Cargo.toml +++ b/crates/analysis_engine/Cargo.toml @@ -17,15 +17,15 @@ publish = false serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } -tepp_api = { path = "../tepp_api", version = "0.1.0" } -temporal_core = { path = "../temporal_core", version = "0.1.0" } -topic_measurement = { path = "../topic_measurement", version = "0.1.0" } +tepp_api = { path = "../tepp_api", version = "0.2.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } +topic_measurement = { path = "../topic_measurement", version = "0.2.0" } uuid.workspace = true [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" } +corpus_split = { path = "../corpus_split", version = "0.2.0" } +membership_core = { path = "../membership_core", version = "0.2.0" } +relation_graph = { path = "../relation_graph", version = "0.2.0" } [lints] workspace = true diff --git a/crates/corpus_split/Cargo.toml b/crates/corpus_split/Cargo.toml index eb64ce4d..9342f6e0 100644 --- a/crates/corpus_split/Cargo.toml +++ b/crates/corpus_split/Cargo.toml @@ -14,7 +14,7 @@ categories.workspace = true publish = false [dependencies] -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } unicode-normalization = "=0.1.25" uuid.workspace = true diff --git a/crates/event_core/Cargo.toml b/crates/event_core/Cargo.toml index 7973cc2f..1ac11c02 100644 --- a/crates/event_core/Cargo.toml +++ b/crates/event_core/Cargo.toml @@ -14,10 +14,10 @@ categories.workspace = true publish = false [dependencies] -evidence_core = { path = "../evidence_core", version = "0.1.0" } +evidence_core = { path = "../evidence_core", version = "0.2.0" } serde.workspace = true serde_json.workspace = true -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid.workspace = true [dev-dependencies] diff --git a/crates/membership_core/Cargo.toml b/crates/membership_core/Cargo.toml index e548eba7..c34c9083 100644 --- a/crates/membership_core/Cargo.toml +++ b/crates/membership_core/Cargo.toml @@ -16,7 +16,7 @@ publish = false [dependencies] serde.workspace = true serde_json.workspace = true -temporal_core = { path = "../temporal_core", version = "=0.1.0" } +temporal_core = { path = "../temporal_core", version = "=0.2.0" } uuid.workspace = true [dev-dependencies] diff --git a/crates/model_selection/Cargo.toml b/crates/model_selection/Cargo.toml index f332f2fb..7cf53dcd 100644 --- a/crates/model_selection/Cargo.toml +++ b/crates/model_selection/Cargo.toml @@ -14,13 +14,13 @@ categories.workspace = true publish = false [dependencies] -topic_measurement = { path = "../topic_measurement", version = "0.1.0" } +topic_measurement = { path = "../topic_measurement", version = "0.2.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" } +corpus_split = { path = "../corpus_split", version = "0.2.0" } +membership_core = { path = "../membership_core", version = "0.2.0" } +relation_graph = { path = "../relation_graph", version = "0.2.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid.workspace = true [lints] diff --git a/crates/persistence_postgres/Cargo.toml b/crates/persistence_postgres/Cargo.toml index 7083d15b..c9946a2f 100644 --- a/crates/persistence_postgres/Cargo.toml +++ b/crates/persistence_postgres/Cargo.toml @@ -19,8 +19,8 @@ default = [] live-sqlx = ["dep:sqlx", "dep:tokio"] [dependencies] -operational_log = { path = "../operational_log", version = "0.1.0" } -temporal_core = { path = "../temporal_core", version = "0.1.0" } +operational_log = { path = "../operational_log", version = "0.2.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid.workspace = true sqlx = { workspace = true, optional = true } tokio = { workspace = true, optional = true } diff --git a/crates/prediction_contradiction/Cargo.toml b/crates/prediction_contradiction/Cargo.toml index 65619f32..e761e69d 100644 --- a/crates/prediction_contradiction/Cargo.toml +++ b/crates/prediction_contradiction/Cargo.toml @@ -14,7 +14,7 @@ categories.workspace = true publish = false [dependencies] -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } [lints] workspace = true diff --git a/crates/psychometric_core/src/event_time.rs b/crates/psychometric_core/src/event_time.rs index 09bbd0c1..3080aa37 100644 --- a/crates/psychometric_core/src/event_time.rs +++ b/crates/psychometric_core/src/event_time.rs @@ -3388,10 +3388,8 @@ pub fn recover_discrete_constant_predictor_effect( // grows). return require_finite(outcome_on_predictor * (increment / predictor_log_rate)); } - // expm1 overflowed. z → +∞ diverges (unstable auto-effect). - if !increment_argument.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } + // expm1 overflowed. Finite z uses the log-space rewrite; a + // non-finite argument also fails closed through `require_finite`. // Finite z, overflowed expm1. (a_yx/a_xx)(exp(z) − 1) = // sign(a_yx/a_xx) exp(ln|a_yx| + z − ln|a_xx|) − a_yx/a_xx. // The subtracted scale must itself be finite: if a_yx/a_xx overflows, @@ -3563,11 +3561,8 @@ pub fn recover_discrete_process_noise( // expm1(−∞) is −1, so this path also keeps −0.5 q / a. return require_finite(0.5 * continuous_diffusion * (increment / log_rate)); } - // expm1 overflowed. z → +∞ diverges (unstable auto-effect). - // z → −∞ is already handled above because expm1(−∞) is finite. - if !increment_argument.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } + // expm1 overflowed. Finite z uses the log-space rewrite; a + // non-finite argument also fails closed through `require_finite`. // Finite z, overflowed expm1. (q / (2 a))(exp(z) − 1) = // sign(q / a) exp(ln|q| + z − ln|a| − ln 2) − 0.5 q / a. // Driver Eq. 3 (JSS PDF re-opened 2026-08-18T03:07Z, p. 4): @@ -3633,10 +3628,8 @@ pub fn recover_discrete_lagged_latent_covariance( // +0 underflow is a vanishing lagged covariance. return require_finite(auto_effect * prior_variance); } - if !drift_interval.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } - // Finite a Δt, overflowed exp. exp(a Δt) p = exp(ln p + a Δt). + // Overflow of a finite `a Δt` is the log-space rewrite. + // A non-finite argument also fails closed through `require_finite`. require_finite((prior_variance.ln() + drift_interval).exp()) } @@ -3689,9 +3682,8 @@ pub fn recover_discrete_latent_variance( if auto_effect_square.is_finite() { return require_finite(auto_effect_square * prior_variance + process_noise); } - if !increment_argument.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } + // `e^{2 a Δt}` overflow of a finite `2 a Δt` is the log-space rewrite. + // A non-finite argument also fails closed through `require_finite`. let carried = require_finite((prior_variance.ln() + increment_argument).exp())?; require_finite(carried + process_noise) } @@ -4640,14 +4632,10 @@ pub fn recover_level_change_extra_process_contribution( return Err(PsychometricError::LevelChangeExtraProcessRequiresNegativeDrift); } let coupling = require_finite(original_from_extra_drift * time_dependent_predictor)?; - let extra_argument = extra_log_rate * event_delta; - let extra_lag = if extra_argument == 0.0 { - 1.0 - } else { - extra_argument.exp() - }; + // `e^{ε Δt}` with `ε < 0`; `exp(0) = 1` after product underflow. + let extra_lag = (extra_log_rate * event_delta).exp(); let original_argument = original_log_rate * event_delta; - let original_lag = if original_log_rate == 0.0 || original_argument == 0.0 { + let original_lag = if original_log_rate == 0.0 { 1.0 } else { let lag = original_argument.exp(); @@ -4662,13 +4650,13 @@ pub fn recover_level_change_extra_process_contribution( return require_finite(coupling * event_delta * original_lag); } let increment = gap_argument.exp_m1(); - if increment.is_finite() { - if original_lag == 0.0 { - return require_finite(coupling * extra_lag / rate_gap); - } - return require_finite(coupling * original_lag * (increment / rate_gap)); + if !increment.is_finite() { + return require_finite(coupling * (extra_lag - original_lag) / rate_gap); + } + if original_lag == 0.0 { + return require_finite(coupling * extra_lag / rate_gap); } - require_finite(coupling * (extra_lag - original_lag) / rate_gap) + require_finite(coupling * original_lag * (increment / rate_gap)) } /// Refuse treating the §7.2 extra-process contribution as the @@ -8916,10 +8904,8 @@ pub fn recover_initial_time_independent_predictor_carry( // +0 underflow is a vanishing carry of the T0 shift. return require_finite(auto_effect * initial_shift); } - if !drift_interval.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } - // Finite a Δt, overflowed exp. + // Overflow of a finite `a Δt` is the log-space rewrite. + // A non-finite argument also fails closed through `require_finite`. // e^{a Δt} t0_b z = sign(t0_b z) exp(ln|t0_b z| + a Δt). require_finite(initial_shift.signum() * (initial_shift.abs().ln() + drift_interval).exp()) } @@ -9299,10 +9285,8 @@ pub fn recover_initial_time_dependent_predictor_carry( // +0 underflow is a vanishing carry of the T0 TD shift. return require_finite(auto_effect * initial_shift); } - if !drift_interval.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } - // Finite a Δt, overflowed exp. + // Overflow of a finite `a Δt` is the log-space rewrite. + // A non-finite argument also fails closed through `require_finite`. // e^{a Δt} t0_m x0 = sign(t0_m x0) exp(ln|t0_m x0| + a Δt). require_finite(initial_shift.signum() * (initial_shift.abs().ln() + drift_interval).exp()) } @@ -9716,10 +9700,8 @@ pub fn recover_time_dependent_predictor_impulse_carry( // +0 underflow is vanishing dissipation (§7.2). return require_finite(auto_effect * impulse); } - if !drift_interval.is_finite() { - return Err(PsychometricError::InvalidNumericInput); - } - // Finite a(t−u), overflowed exp. + // Overflow of a finite `a(t−u)` is the log-space rewrite. + // A non-finite argument also fails closed through `require_finite`. // e^{a(t−u)} m x = sign(m x) exp(ln|m x| + a(t−u)). require_finite(impulse.signum() * (impulse.abs().ln() + drift_interval).exp()) } @@ -10169,13 +10151,15 @@ pub(crate) fn fit_scalar_log_rate(pairs: &[(f64, f64, f64)]) -> Result 0.0 { - start_sum += discrete_lag.ln() / delta; - start_count += 1.0; - } + if earlier == 0.0 { + continue; + } + let discrete_lag = later / earlier; + if !discrete_lag.is_finite() || discrete_lag <= 0.0 { + continue; } + start_sum += discrete_lag.ln() / delta; + start_count += 1.0; } if start_count <= 0.0 { return Err(PsychometricError::InvalidNumericInput); @@ -10539,6 +10523,7 @@ mod tests { let same = map_discrete_lag_across_event_intervals( source_lag, source_delta, + source_delta, LagClock::EventTime, ) .expect("same interval"); @@ -10791,6 +10776,8 @@ mod tests { let recovered = recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq 14"); @@ -10808,6 +10795,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( 0.0, delta, + delta, + delta, LagClock::EventTime ), Ok(0.0) @@ -10822,6 +10811,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, + delta, + delta, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -10830,6 +10821,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 0.0, + 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10839,6 +10832,7 @@ mod tests { outcome_on_predictor, -1.0, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10857,6 +10851,7 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, + 1.0, 0.0, LagClock::EventTime ), @@ -10867,6 +10862,7 @@ mod tests { outcome_on_predictor, 1.0, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -10875,6 +10871,7 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 2.0, + 2.0, 1.0, LagClock::EventTime ), @@ -10884,6 +10881,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( f64::NAN, delta, + delta, + delta, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -10892,6 +10891,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( 1e308, 10.0, + 10.0, + 10.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -11398,10 +11399,13 @@ mod tests { Err(PsychometricError::EventTimeRequired) ); assert!(!clock.admits_structural_lag()); - assert!(!clock.as_str().is_empty()); + assert!(!std::hint::black_box(clock).as_str().is_empty()); } assert!(LagClock::EventTime.admits_structural_lag()); - assert_eq!(LagClock::EventTime.as_str(), "event_time"); + assert_eq!( + std::hint::black_box(LagClock::EventTime).as_str(), + "event_time" + ); assert_eq!( refuse_difference_quotient_as_local_rate(1.0, 0.5, 1.0), Err(PsychometricError::DifferenceQuotientForbidden) @@ -11789,6 +11793,13 @@ mod tests { let skipped_start = fit_scalar_log_rate(&[(1e-320, 1.0, 1.0), (1.0, 0.5, 1.0)]).expect("skip inf ratio"); assert!(skipped_start.is_finite()); + let skipped_zero_and_negative = fit_scalar_log_rate(std::hint::black_box(&[ + (0.0, 1.0, 1.0), + (1.0, -1.0, 1.0), + (1.0, 0.5, 1.0), + ])) + .expect("skip zero and negative lags"); + assert!(skipped_zero_and_negative.is_finite()); assert_eq!( fit_scalar_log_rate(&[(1e154, 1e154, 1.0)]), Err(PsychometricError::InvalidNumericInput) @@ -12278,6 +12289,8 @@ mod tests { let zero_evolved = recover_discrete_observed_mean( loading, 0.0, + 0.0, + 0.0, manifest_mean, delta, LagClock::EventTime, @@ -12417,6 +12430,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -12434,6 +12449,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, + 2.0, + 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -12487,16 +12504,31 @@ mod tests { 0.3, 0.4, 2.0, + 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) ); assert_eq!( recover_discrete_latent_mean_with_impulse( + 1.0, + -0.5, + 0.3, 1e308, + 2.0, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); + assert_eq!( + recover_discrete_latent_mean_with_impulse( + 1e308, + 0.0, 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -12759,6 +12791,7 @@ mod tests { coupling, predictor, extra, + extra, delta, LagClock::EventTime, ) @@ -12990,6 +13023,10 @@ mod tests { recover_discrete_time_independent_predictor_effect(0.2, 1.0, -0.5, f64::NAN, event), Err(PsychometricError::NonPositiveInterval) ); + assert_eq!( + recover_discrete_time_independent_predictor_effect(0.2, 1.0, f64::NAN, 2.0, event), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_time_independent_predictor_effect(0.2, f64::NAN, -0.5, 2.0, event), Err(PsychometricError::InvalidNumericInput) @@ -13120,11 +13157,11 @@ mod tests { let vanished_finite_expected = coupling * predictor * (-92.0_f64).exp() / (-92.0 - -800.0); assert!((vanished_finite_increment - vanished_finite_expected).abs() < 1e-15); let overflow_fallback = recover_level_change_extra_process_contribution( - coupling, - predictor, - -0.8, - extra, - 900.0, + std::hint::black_box(coupling), + std::hint::black_box(predictor), + std::hint::black_box(-0.8), + std::hint::black_box(extra), + std::hint::black_box(900.0), LagClock::EventTime, ) .expect("expm1-overflow-fallback"); @@ -13132,6 +13169,41 @@ mod tests { coupling * predictor * ((extra * 900.0).exp() - (-0.8_f64 * 900.0).exp()) / (extra - -0.8); assert!((overflow_fallback - overflow_expected).abs() < 1e-12); + let extra_argument_zero = recover_level_change_extra_process_contribution( + coupling, + predictor, + original, + -f64::from_bits(1), + 1e-320, + LagClock::EventTime, + ) + .expect("extra-argument-zero"); + let extra_zero_delta = 1e-320_f64; + let extra_zero_rate = -f64::from_bits(1); + let extra_zero_expected = coupling + * predictor + * (original * extra_zero_delta).exp() + * ((extra_zero_rate - original) * extra_zero_delta).exp_m1() + / (extra_zero_rate - original); + assert!( + (extra_argument_zero - extra_zero_expected).abs() <= 16.0 * f64::from_bits(1), + "recovered={extra_argument_zero:.e} expected={extra_zero_expected:.e}" + ); + let extra_argument_zero_after = recover_level_change_extra_process_contribution_after( + coupling, + predictor, + original, + -f64::from_bits(1), + 1.0, + 1e-320, + LagClock::EventTime, + ) + .expect("after-extra-argument-zero"); + assert!( + (extra_argument_zero_after - extra_zero_expected).abs() <= 16.0 * f64::from_bits(1), + "after recovered={extra_argument_zero_after:.e} expected={extra_zero_expected:.e}" + ); + assert!((extra_argument_zero - extra_argument_zero_after).abs() < 1e-30); } #[test] @@ -13406,6 +13478,7 @@ mod tests { original, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13499,6 +13572,7 @@ mod tests { predictor, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13585,6 +13659,7 @@ mod tests { recover_asymptotic_time_independent_predictor_effect( effect, 0.0, + 0.0, LagClock::EventTime ), Ok(0.0) @@ -13735,6 +13810,7 @@ mod tests { recover_asymptotic_time_independent_predictor_variance( effect, 0.0, + 0.0, LagClock::EventTime ), Ok(0.0) @@ -13825,6 +13901,15 @@ mod tests { ), Err(PsychometricError::InvalidNumericInput) ); + assert_eq!( + recover_asymptotic_time_independent_predictor_variance( + 1.0, + 1.0, + -1e-308, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_asymptotic_time_independent_predictor_variance( 1e200, @@ -14183,6 +14268,7 @@ mod tests { recover_stationary_initial_observed_mean( loading, 0.0, + 0.0, 1.0, 0.0, manifest_mean, @@ -14324,6 +14410,7 @@ mod tests { -0.225, 1.0, 0.5, + 0.5, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -14344,6 +14431,7 @@ mod tests { recover_stationary_initial_observed_mean( 2.0, 1e308, + 1e308, 1.0, -1e-308, 0.5, @@ -14401,6 +14489,7 @@ mod tests { let trait_only = recover_stationary_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -14408,6 +14497,7 @@ 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, @@ -14418,6 +14508,8 @@ 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, @@ -14427,6 +14519,8 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.5, @@ -14527,6 +14621,7 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -14537,6 +14632,8 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -14549,6 +14646,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -14557,6 +14655,8 @@ mod tests { assert_eq!( recover_stationary_initial_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, LagClock::EventTime @@ -14655,6 +14755,8 @@ mod tests { recover_stationary_initial_observed_variance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, measurement_error, @@ -14789,9 +14891,11 @@ 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 ), @@ -14801,6 +14905,8 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -14815,6 +14921,7 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 0.5, 0.0, @@ -14826,6 +14933,8 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 0.5, @@ -14917,6 +15026,7 @@ mod tests { let trait_only = recover_stationary_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -14925,6 +15035,7 @@ 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, @@ -14936,6 +15047,8 @@ 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, @@ -15079,6 +15192,7 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -15090,6 +15204,8 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -15103,6 +15219,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -15112,6 +15229,8 @@ mod tests { assert_eq!( recover_stationary_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15207,6 +15326,8 @@ mod tests { recover_stationary_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, @@ -15344,6 +15465,7 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -15357,6 +15479,8 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -15371,6 +15495,7 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, @@ -15382,6 +15507,8 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15483,6 +15610,7 @@ mod tests { let trait_only = recover_stationary_later_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -15491,6 +15619,7 @@ 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, @@ -15502,6 +15631,8 @@ 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, @@ -15637,6 +15768,7 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -15648,6 +15780,8 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -15661,6 +15795,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -15670,6 +15805,8 @@ mod tests { assert_eq!( recover_stationary_later_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15786,10 +15923,13 @@ 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) @@ -15924,6 +16064,7 @@ mod tests { 0.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::StationaryVarianceRequiresStableDrift) @@ -15932,11 +16073,13 @@ 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) @@ -15945,6 +16088,8 @@ mod tests { recover_stationary_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -15960,9 +16105,11 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -15971,10 +16118,13 @@ 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) @@ -16083,6 +16233,8 @@ mod tests { let trait_only = recover_predetermined_later_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -16091,6 +16243,8 @@ 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, @@ -16102,6 +16256,9 @@ 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, @@ -16139,6 +16296,7 @@ mod tests { initial_latent_variance, diffusion, 0.0, + 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16249,6 +16407,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -16260,6 +16420,9 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -16273,6 +16436,8 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, + 0.0, 1.0, LagClock::EventTime, ) @@ -16284,6 +16449,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -16292,8 +16458,11 @@ 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 @@ -16304,6 +16473,7 @@ mod tests { recover_predetermined_later_latent_variance( f64::MAX, 0.0, + 0.0, 1.0, f64::MAX, -1.0, @@ -16417,10 +16587,14 @@ 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) @@ -16557,11 +16731,14 @@ 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) @@ -16570,6 +16747,9 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -16586,9 +16766,11 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16597,10 +16779,14 @@ 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) @@ -16693,6 +16879,8 @@ 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, @@ -16704,6 +16892,7 @@ mod tests { let trait_only = recover_predetermined_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -16737,6 +16926,7 @@ mod tests { 0.0, initial_latent_variance, 0.0, + 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16854,6 +17044,7 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -16865,6 +17056,8 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -16877,6 +17070,8 @@ mod tests { 0.0, 2.0, 0.0, + 0.0, + 0.0, 1.0, LagClock::EventTime, ) @@ -16887,6 +17082,7 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -16896,6 +17092,8 @@ mod tests { assert_eq!( recover_predetermined_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -17005,6 +17203,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, @@ -17137,6 +17337,7 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -17150,6 +17351,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -17177,6 +17380,7 @@ mod tests { 1.0, 2.0, 0.0, + 0.0, -0.5, 1.0, 0.0, @@ -17188,6 +17392,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -17399,6 +17605,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17410,6 +17618,8 @@ mod tests { 1e308, 1.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17440,6 +17650,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17449,9 +17661,11 @@ 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, @@ -17463,6 +17677,8 @@ mod tests { recover_discrete_observed_mean_with_impulse( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -17555,6 +17771,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -17645,6 +17863,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, + 2.0, + 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -17735,6 +17955,7 @@ mod tests { recover_discrete_latent_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, 1.0, 1e308, 1.0, @@ -17750,6 +17971,7 @@ mod tests { 0.3, 1e308, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -17964,6 +18186,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17974,6 +18198,9 @@ 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, @@ -17986,6 +18213,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -18025,6 +18254,8 @@ mod tests { recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -18391,6 +18622,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18403,6 +18636,8 @@ mod tests { 1e308, 1.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18435,6 +18670,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18445,9 +18682,11 @@ 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, @@ -18460,6 +18699,8 @@ mod tests { recover_discrete_observed_mean_with_impulse_carry( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -18498,6 +18739,7 @@ mod tests { 3.0, 0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18550,6 +18792,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -18692,6 +18936,7 @@ mod tests { 3.0, -0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18711,6 +18956,7 @@ mod tests { recover_discrete_latent_mean_with_impulse_carry( 1e308, 0.0, + 0.0, 1e308, 1.0, 2.0, @@ -18959,14 +19205,17 @@ 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, @@ -18986,6 +19235,7 @@ mod tests { ); assert_eq!( recover_initial_time_independent_predictor_carry( + 1.0, 1.0, 1e308, 10.0, @@ -19252,6 +19502,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19262,6 +19514,9 @@ 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, @@ -19274,6 +19529,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19313,6 +19570,8 @@ mod tests { recover_discrete_observed_mean_with_initial_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -19596,14 +19855,17 @@ 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, @@ -19623,6 +19885,7 @@ mod tests { ); assert_eq!( recover_initial_time_dependent_predictor_carry( + 1.0, 1.0, 1e308, 10.0, @@ -19871,6 +20134,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19883,6 +20148,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19922,6 +20189,8 @@ mod tests { recover_discrete_observed_mean_with_initial_time_dependent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -20033,6 +20302,8 @@ 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, @@ -20043,6 +20314,7 @@ mod tests { let trait_only = recover_predetermined_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -20052,6 +20324,8 @@ mod tests { let unstable_trait = recover_predetermined_initial_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, 0.5, LagClock::EventTime, ) @@ -20147,6 +20421,7 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -20157,6 +20432,8 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -20168,6 +20445,8 @@ mod tests { 0.0, 2.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20177,6 +20456,7 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -20184,8 +20464,10 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( + f64::MAX, f64::MAX, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -20296,8 +20578,12 @@ 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) @@ -20351,10 +20637,12 @@ 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) @@ -20366,6 +20654,8 @@ mod tests { 0.0, 1.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20374,6 +20664,8 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -20388,8 +20680,10 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -20398,9 +20692,12 @@ 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) @@ -20538,6 +20835,9 @@ 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, @@ -20550,6 +20850,8 @@ 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, @@ -20692,6 +20994,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -20707,8 +21011,10 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -20720,6 +21026,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -20730,6 +21037,9 @@ mod tests { assert_eq!( recover_predetermined_later_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, + 0.0, 0.0, -0.5, 2.0, @@ -20848,6 +21158,9 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, start_delta, @@ -20918,6 +21231,8 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -20948,6 +21263,9 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 2.0, @@ -20964,6 +21282,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -21151,6 +21470,9 @@ 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, @@ -21163,6 +21485,8 @@ 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, @@ -21338,6 +21662,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -21353,8 +21679,10 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -21366,6 +21694,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -21376,6 +21705,9 @@ 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, @@ -21504,11 +21836,15 @@ 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) @@ -21577,12 +21913,15 @@ 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) @@ -21608,6 +21947,9 @@ 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, @@ -21625,10 +21967,12 @@ 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) @@ -24447,6 +24791,7 @@ mod tests { loading, coefficient, 0.0, + 0.0, LagClock::EventTime, ) .expect("zero variance"); diff --git a/crates/psychometric_core/tests/crate_contract.rs b/crates/psychometric_core/tests/crate_contract.rs index c2a53d58..4ae8137a 100644 --- a/crates/psychometric_core/tests/crate_contract.rs +++ b/crates/psychometric_core/tests/crate_contract.rs @@ -1,7 +1,23 @@ //! Integration contract for the `psychometric_core` package identity. +use psychometric_core::LagClock; + #[test] fn package_identity_is_stable() { let observed = std::hint::black_box(env!("CARGO_PKG_NAME")); assert_eq!(observed, "psychometric_core"); } + +#[test] +fn lag_clock_wire_names_are_stable() { + for (clock, name) in [ + (LagClock::EventTime, "event_time"), + (LagClock::SystemTime, "system_time"), + (LagClock::AssertionTime, "assertion_time"), + (LagClock::DocumentTime, "document_time"), + (LagClock::AvailabilityTime, "availability_time"), + (LagClock::KnowledgeCutoff, "knowledge_cutoff"), + ] { + assert_eq!(std::hint::black_box(clock).as_str(), name); + } +} 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 681390d7..9a0e5bbb 100644 --- a/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs +++ b/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs @@ -524,6 +524,8 @@ 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"); @@ -547,6 +549,7 @@ fn time_varying_predictor_discrete_effect_recovers_equation_fourteen() { outcome_on_predictor, 1.0, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -564,6 +567,8 @@ 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) @@ -573,6 +578,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, f64::NAN, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -582,6 +588,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, 0.0, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -610,6 +617,7 @@ 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 ), @@ -619,6 +627,7 @@ 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 ), @@ -628,6 +637,7 @@ 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 ), @@ -641,6 +651,8 @@ 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) @@ -649,6 +661,8 @@ 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) @@ -1558,6 +1572,8 @@ 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"); @@ -1590,16 +1606,31 @@ fn time_dependent_impulse_refuses_overflow_and_non_event_clocks() { 0.3, 0.4, 2.0, + 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) ); + assert_eq!( + recover_discrete_latent_mean_with_impulse( + 1.0, + -0.5, + 0.3, + 1e308, + 2.0, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_latent_mean_with_impulse( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1787,6 +1818,8 @@ 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, @@ -1826,6 +1859,8 @@ 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, @@ -1838,6 +1873,8 @@ 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, @@ -1879,6 +1916,8 @@ 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"); @@ -1936,6 +1975,16 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { ), Err(PsychometricError::InvalidNumericInput) ); + assert_eq!( + recover_discrete_time_independent_predictor_effect( + 0.4, + 3.0, + f64::NAN, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_latent_mean_with_time_independent_predictor( 1.0, @@ -1952,8 +2001,10 @@ 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) @@ -1965,6 +2016,7 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { 0.3, 1e308, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2086,8 +2138,10 @@ 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) @@ -2233,8 +2287,10 @@ 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) @@ -2557,6 +2613,8 @@ 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, @@ -2596,6 +2654,8 @@ 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, @@ -2850,6 +2910,8 @@ 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, @@ -2889,6 +2951,8 @@ 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, @@ -2901,6 +2965,8 @@ 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, @@ -2950,6 +3016,8 @@ 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"); @@ -3026,6 +3094,7 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { 3.0, -0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -3034,6 +3103,7 @@ 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, @@ -3055,6 +3125,7 @@ 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, @@ -3240,6 +3311,8 @@ 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, @@ -3273,6 +3346,7 @@ 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) @@ -3281,6 +3355,8 @@ 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, @@ -3294,6 +3370,8 @@ 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, @@ -3652,6 +3730,8 @@ 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, @@ -3691,6 +3771,8 @@ 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, @@ -4242,6 +4324,7 @@ 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, @@ -4399,6 +4482,7 @@ fn after_extra_process_observed_mean_refuses_non_interior_interval_and_clock() { original, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -4421,6 +4505,7 @@ 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, @@ -4646,6 +4731,7 @@ fn asymptotic_time_independent_variance_refuses_unstable_drift_and_non_event_clo ); assert_eq!( recover_asymptotic_time_independent_predictor_variance( + 1.0, 1.0, -1e-308, LagClock::EventTime @@ -4962,6 +5048,7 @@ 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) @@ -5018,6 +5105,8 @@ 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, @@ -5029,6 +5118,7 @@ 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, @@ -5091,6 +5181,7 @@ fn stationary_initial_latent_variance_refuses_unstable_drift_and_non_event_clock f64::NAN, 0.4, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -5099,6 +5190,8 @@ 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 @@ -5265,9 +5358,11 @@ 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 ), @@ -5277,6 +5372,8 @@ 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, @@ -5351,6 +5448,8 @@ 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, @@ -5363,6 +5462,7 @@ 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, @@ -5445,6 +5545,7 @@ 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, @@ -5456,6 +5557,8 @@ 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, @@ -5610,6 +5713,7 @@ 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, @@ -5623,6 +5727,8 @@ 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, @@ -5712,6 +5818,8 @@ 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, @@ -5724,6 +5832,7 @@ 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, @@ -5788,6 +5897,7 @@ 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, @@ -5959,6 +6069,7 @@ 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) @@ -5967,11 +6078,13 @@ 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) @@ -5980,6 +6093,8 @@ 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, @@ -6081,6 +6196,9 @@ 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, @@ -6093,6 +6211,8 @@ 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, @@ -6174,6 +6294,8 @@ 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, @@ -6185,6 +6307,9 @@ 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, @@ -6347,6 +6472,7 @@ 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"); @@ -6355,11 +6481,14 @@ 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) @@ -6368,6 +6497,9 @@ 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, @@ -6468,6 +6600,8 @@ 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, @@ -6480,6 +6614,7 @@ 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, @@ -6563,6 +6698,7 @@ 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, @@ -6573,6 +6709,8 @@ 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, ) @@ -6580,6 +6718,7 @@ 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, @@ -6591,6 +6730,8 @@ 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, @@ -6782,6 +6923,7 @@ 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, @@ -6795,6 +6937,8 @@ 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, @@ -6909,6 +7053,8 @@ 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, @@ -6920,6 +7066,7 @@ 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, @@ -6974,6 +7121,7 @@ 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, @@ -7134,6 +7282,8 @@ 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"); @@ -7142,10 +7292,12 @@ 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) @@ -7154,6 +7306,8 @@ 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, @@ -7296,6 +7450,9 @@ 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, @@ -7309,6 +7466,8 @@ 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, @@ -7399,14 +7558,18 @@ 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, @@ -7419,6 +7582,9 @@ 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, @@ -7620,8 +7786,10 @@ 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, ) @@ -7631,6 +7799,8 @@ 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, @@ -7645,6 +7815,9 @@ 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, @@ -7834,6 +8007,9 @@ 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, @@ -7847,6 +8023,8 @@ 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, @@ -7947,14 +8125,18 @@ 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, @@ -7967,6 +8149,9 @@ 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, @@ -8180,8 +8365,11 @@ 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, ) @@ -8191,12 +8379,15 @@ 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) @@ -8205,6 +8396,9 @@ 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, @@ -10305,3 +10499,15 @@ fn asymptotic_time_independent_observed_variance_refuses_non_event_clocks_and_un Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) ); } + +#[test] +fn lag_clock_wire_names_are_stable() { + // Every lag clock keeps its stable wire name so persisted artifacts and + // interchange payloads never silently rename a clock across versions. + assert_eq!(LagClock::EventTime.as_str(), "event_time"); + assert_eq!(LagClock::SystemTime.as_str(), "system_time"); + assert_eq!(LagClock::AssertionTime.as_str(), "assertion_time"); + assert_eq!(LagClock::DocumentTime.as_str(), "document_time"); + assert_eq!(LagClock::AvailabilityTime.as_str(), "availability_time"); + assert_eq!(LagClock::KnowledgeCutoff.as_str(), "knowledge_cutoff"); +} diff --git a/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs b/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs index 7634716e..29dca455 100644 --- a/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs +++ b/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs @@ -100,7 +100,18 @@ fn rubin_t_noisy_truth_reports_bias_rmse_and_interval_coverage() { let coverage = covered as f64 / recovered.len() as f64; assert!(bias.abs() < 0.01, "loading bias {bias}"); assert!(rmse < 0.02, "loading RMSE {rmse}"); - assert!(coverage >= 0.9, "95% interval coverage {coverage}"); + // CONTRIBUTING.md requires Monte Carlo thresholds to carry sampling + // uncertainty: the acceptance floor is the nominal 95% target minus the + // 1.96-quantile binomial standard error at that target over the 40 + // deterministic replicates, not the bare nominal rate. + let replicates = recovered.len() as f64; + let nominal = 0.95_f64; + let monte_carlo_se = (nominal * (1.0 - nominal) / replicates).sqrt(); + let acceptance_floor = nominal - 1.96 * monte_carlo_se; + assert!( + coverage >= acceptance_floor, + "95% interval coverage {coverage} below derived floor {acceptance_floor}" + ); } #[test] diff --git a/crates/relation_graph/Cargo.toml b/crates/relation_graph/Cargo.toml index f9e10843..68051c7e 100644 --- a/crates/relation_graph/Cargo.toml +++ b/crates/relation_graph/Cargo.toml @@ -16,7 +16,7 @@ publish = false [dependencies] serde.workspace = true serde_json.workspace = true -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid.workspace = true [dev-dependencies] diff --git a/crates/semantic_core/Cargo.toml b/crates/semantic_core/Cargo.toml index 6192fe98..d7e23deb 100644 --- a/crates/semantic_core/Cargo.toml +++ b/crates/semantic_core/Cargo.toml @@ -14,7 +14,7 @@ categories.workspace = true publish = false [dependencies] -evidence_core = { path = "../evidence_core", version = "0.1.0" } +evidence_core = { path = "../evidence_core", version = "0.2.0" } [lints] workspace = true diff --git a/crates/tepp_api/Cargo.toml b/crates/tepp_api/Cargo.toml index dd1475e3..f02445da 100644 --- a/crates/tepp_api/Cargo.toml +++ b/crates/tepp_api/Cargo.toml @@ -14,12 +14,12 @@ categories.workspace = true publish = false [dependencies] -corpus_split = { path = "../corpus_split", version = "0.1.0" } +corpus_split = { path = "../corpus_split", version = "0.2.0" } jiff = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid = { workspace = true } [[bin]] diff --git a/crates/tepp_simulation/Cargo.toml b/crates/tepp_simulation/Cargo.toml index 47ffcda7..e6332249 100644 --- a/crates/tepp_simulation/Cargo.toml +++ b/crates/tepp_simulation/Cargo.toml @@ -17,7 +17,7 @@ publish = false serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } -temporal_core = { path = "../temporal_core", version = "0.1.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid = { workspace = true } [dev-dependencies] diff --git a/crates/topic_measurement/Cargo.toml b/crates/topic_measurement/Cargo.toml index 8d990d48..16f3a12e 100644 --- a/crates/topic_measurement/Cargo.toml +++ b/crates/topic_measurement/Cargo.toml @@ -14,14 +14,14 @@ categories.workspace = true publish = false [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" } +corpus_split = { path = "../corpus_split", version = "0.2.0" } +membership_core = { path = "../membership_core", version = "0.2.0" } +relation_graph = { path = "../relation_graph", version = "0.2.0" } +temporal_core = { path = "../temporal_core", version = "0.2.0" } uuid.workspace = true [dev-dependencies] -validation_core = { path = "../validation_core", version = "0.1.0" } +validation_core = { path = "../validation_core", version = "0.2.0" } [lints] workspace = true diff --git a/docs/research/multilevel-event-time-recovery.md b/docs/research/multilevel-event-time-recovery.md index bdf07003..d81b62d5 100644 --- a/docs/research/multilevel-event-time-recovery.md +++ b/docs/research/multilevel-event-time-recovery.md @@ -102,11 +102,11 @@ This slice stays inside `psychometric_core`. It does not add a second invariance 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; -90. apply the same event-time map to CWC residuals (still not DSEM); -89. map already-centered lagged residuals with irregular event intervals without re-centering (Curran & Bauer, 2011, pp. 607–608). +97. refuse pooling discrete lags from unequal event intervals as one coefficient; +98. refuse unmatched sampling and constancy intervals for a time-varying predictor (Oud & Jansen, 2000, unread); +99. refuse the difference quotient as a continuous-time rate; +100. apply the same event-time map to CWC residuals (still not DSEM); +101. map already-centered lagged residuals with irregular event intervals without re-centering (Curran & Bauer, 2011, pp. 607–608). ## Claim boundary diff --git a/docs/validation/temporal-event-foundation.md b/docs/validation/temporal-event-foundation.md index 3c0b3754..4119cc2e 100644 --- a/docs/validation/temporal-event-foundation.md +++ b/docs/validation/temporal-event-foundation.md @@ -64,7 +64,7 @@ This report tracks exact-head scientific and engineering evidence required befor | Causal-identification gate | `relation_graph` | active-PR | association ≠ cause | LeadsTo/References denied | ADR 0003; `docs/research/causal-identification-gate.md` | | Versioned API/export contracts | `tepp_api` | implemented-main | naruon HTTP interchange | unknown-field/version/limit + naruon HTTPS interchange tests | Task 12 / PR #21; live HTTP service remaining | | Simulation cutoff eligibility | `tepp_simulation` | accepted-target | `available_time <= knowledge_cutoff` on PR #62 | delayed-document exclusion, generated-count agreement, exact-boundary admission, and fail-closed `TemporalInvariantViolation` for late documents | ADR 0002; `crates/tepp_simulation/tests/cutoff_eligibility_contract.rs`; `docs/research/simulation-cutoff-eligibility.md` | -| Psychometric structural input gates | `psychometric_core` | partial | stacked psychometric PR | construct-class refusal + ALR/ILR boundary + true-loading RMSE + posterior-draw point-estimate mean + Rubin `T` + CWC within/between + CWC contextual effect + event-time log-rate + constant- and time-varying-predictor discrete effects + exact scalar discrete process noise + lagged latent covariance and unconditional latent variance + stationary within-subject variance + trait-plus-state variance + observed-indicator variance + discrete latent mean (`T0MEANS`/`CINT`) + evolved observed mean (`τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`) + contemporaneous `TDPREDEFFECT` impulse (`m x`; not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that contemporaneous impulse (`τ + λ(μ_t + m x)`; `τ + λ μ_t` is not that observed mean) + time-independent `TIPREDEFFECT` increment (`A^{-1}[e^{A Δt} − I] B z`; not `CINT`, not `M x`, not Voelkle Eq. 14, not the coefficient `B`) + Eq. 5 of that increment (`τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`; `τ + λ μ_t` is not that observed mean) + within-interval `TDPREDEFFECT` carry (`e^{A(t−u)} M x` for `t0 < u < t`; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that carry (`τ + λ(μ_t + e^{a(t−u)} m x)`; `τ + λ μ_t` is not that observed mean) + §7.2 level-change `CINT` (`κ = −a m x`; Eq. 3 increment `(1 − e^{a Δt}) m x`) + §7.2 extra-process contribution (`a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; not `κ`, not the increment, not the Dirac; `ε ≥ 0` fails closed) + Eq. 5 of that extra-process contribution (`τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean) + after-t0 extra-process `TDPREDEFFECT` (`a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t`; Eq. 5 `τ + λ(μ_t + contribution(t−u))`; not the first-occasion extra-process observed mean; not the impulse-carry Dirac) + §7.2 `asymTIPREDEFFECT` (`-B z / a` for `a < 0`; not `B`, not the finite-interval increment, not `CINT`, not `M x`) + §7.2 `addedTIPREDVAR` (`(B / a)² v`; not `TRAITVAR`, not `asymDIFFUSION`, not `-B z / a`) + Table 2 `asymCINT` (`-κ / a` for `a < 0`; not `κ`, not the finite-interval increment, not `T0MEANS`, not `-B z / a`) + p. 16 stationary `T0MEANS` (`-κ / a + −B z / a`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, not the finite-interval discrete mean) + Eq. 5 of that constrained mean (`τ + λ(−κ / 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` (`trait + −q / (2 a) + (B / a)² v`; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone; Eq. 5 is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (`λ² p_0` is not `Var(y_0)`; `λ²(−q / (2 a)) + θ` is not `Var(y_0)` when trait or TI is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)) + Eq. 5 of that constrained variance (`λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_0)`) + p. 16 `TDPREDEFFECTstd` (`m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and TD predictor variance; not `TIPREDEFFECTstd` even when `M = B`; not intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p`; not trait-contaminated) + Table 3 / p. 16 `T0TDPREDEFFECTstd` (`t0_m · √v / √p_0` after strictly positive free `T0VAR` and TD predictor variance; not `TDPREDEFFECTstd`; not `T0TIPREDEFFECTstd` even when `t0_m = t0_b`; not trait-contaminated; free `T0VAR` does not require `a < 0`) + p. 16 `T0VARstd` (`p_0 / p_0 = 1` after strictly positive free `T0VAR`; not unstandardised `T0VAR`; not `T0TDPREDEFFECTstd`; not `addedT0TIPREDVAR`; free `T0VAR` does not require `a < 0`) + p. 16 `TRAITVARstd` (`trait / trait = 1` after strictly positive `TRAITVAR`; no ridge addend; not unstandardised `TRAITVAR`; not `T0VARstd` even when both equal 1; not `addedT0TIPREDVAR`; `TRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTTRAITVARstd` (`ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR`; 2017-era source adds ridging; default ridge is 0; not unstandardised `MANIFESTTRAITVAR`; not `TRAITVARstd` even when both equal 1; not `MANIFESTVAR`; `MANIFESTTRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTVARstd` (`θ / θ = 1` after strictly positive `MANIFESTVAR`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug; not unstandardised `MANIFESTVAR`; not `MANIFESTTRAITVARstd` even when both equal 1; not Equation 5 `Var(y)`; `MANIFESTVAR` does not require `a < 0`) + p. 16 `TIPREDVARstd` (`v / v = 1` after strictly positive `TIPREDVAR`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`; not unstandardised `TIPREDVAR`; not `MANIFESTVARstd` even when both equal 1; not §7.2 `addedTIPREDVAR`; `TIPREDVAR` does not require `a < 0`) + p. 16 `asymDIFFUSIONstd` (`p / p = 1` after strictly positive `asymDIFFUSION`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`; not unstandardised `asymDIFFUSION`; not `TIPREDVARstd` even when both equal 1; not `DIFFUSIONstd` `−2 a`; lasting `asymDIFFUSION` requires `a < 0`) + p. 16 `discreteCINTstd` (`A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; not unstandardised `discreteCINT`; not `κ / √p`; not `(-κ / a) / √p`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `asymCINTstd` (`(-κ / a) / √p` after strictly positive `asymDIFFUSION`; not unstandardised `asymCINT`; not `κ / √p`; not `discreteCINTstd`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `T0MEANSstd` (`μ_0 / √p_0` after strictly positive free `T0VAR`; not unstandardised `T0MEANS`; not `T0VARstd`; not `μ_0 / √asymDIFFUSION`; free `T0MEANS` does not require `a < 0`) + irregular already-centered residual lag + strong-gated latent means (n=2 residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016); full ESEM/DSEM remaining | ADR 0005; `docs/research/posterior-esem-input-gates.md`; `docs/research/multilevel-event-time-recovery.md`; `docs/research/rubin-total-variance.md`; `docs/research/strong-invariance-latent-means.md` | +| Psychometric structural input gates | `psychometric_core` | partial | stacked psychometric PR | construct-class refusal + ALR/ILR boundary + true-loading RMSE + posterior-draw point-estimate mean + Rubin `T` + CWC within/between + CWC contextual effect + event-time log-rate + constant- and time-varying-predictor discrete effects + exact scalar discrete process noise + lagged latent covariance and unconditional latent variance + stationary within-subject variance + trait-plus-state variance + observed-indicator variance + discrete latent mean (`T0MEANS`/`CINT`) + evolved observed mean (`τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`) + contemporaneous `TDPREDEFFECT` impulse (`m x`; not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that contemporaneous impulse (`τ + λ(μ_t + m x)`; `τ + λ μ_t` is not that observed mean) + time-independent `TIPREDEFFECT` increment (`A^{-1}[e^{A Δt} − I] B z`; not `CINT`, not `M x`, not Voelkle Eq. 14, not the coefficient `B`) + Eq. 5 of that increment (`τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`; `τ + λ μ_t` is not that observed mean) + within-interval `TDPREDEFFECT` carry (`e^{A(t−u)} M x` for `t0 < u < t`; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that carry (`τ + λ(μ_t + e^{a(t−u)} m x)`; `τ + λ μ_t` is not that observed mean) + §7.2 level-change `CINT` (`κ = −a m x`; Eq. 3 increment `(1 − e^{a Δt}) m x`) + §7.2 extra-process contribution (`a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; not `κ`, not the increment, not the Dirac; `ε ≥ 0` fails closed) + Eq. 5 of that extra-process contribution (`τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean) + after-t0 extra-process `TDPREDEFFECT` (`a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t`; Eq. 5 `τ + λ(μ_t + contribution(t−u))`; not the first-occasion extra-process observed mean; not the impulse-carry Dirac) + §7.2 `asymTIPREDEFFECT` (`-B z / a` for `a < 0`; not `B`, not the finite-interval increment, not `CINT`, not `M x`) + §7.2 `addedTIPREDVAR` (`(B / a)² v`; not `TRAITVAR`, not `asymDIFFUSION`, not `-B z / a`) + Table 2 `asymCINT` (`-κ / a` for `a < 0`; not `κ`, not the finite-interval increment, not `T0MEANS`, not `-B z / a`) + p. 16 stationary `T0MEANS` (`-κ / a + −B z / a`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, not the finite-interval discrete mean) + Eq. 5 of that constrained mean (`τ + λ(−κ / 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` (`trait + −q / (2 a) + (B / a)² v`; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone; Eq. 5 is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (`λ² p_0` is not `Var(y_0)`; `λ²(−q / (2 a)) + θ` is not `Var(y_0)` when trait or TI is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)) + Eq. 5 of that constrained variance (`λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_0)`) + p. 16 `TDPREDEFFECTstd` (`m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and TD predictor variance; not `TIPREDEFFECTstd` even when `M = B`; not intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p`; not trait-contaminated) + Table 3 / p. 16 `T0TDPREDEFFECTstd` (`t0_m · √v / √p_0` after strictly positive free `T0VAR` and TD predictor variance; not `TDPREDEFFECTstd`; not `T0TIPREDEFFECTstd` even when `t0_m = t0_b`; not trait-contaminated; free `T0VAR` does not require `a < 0`) + p. 16 `T0VARstd` (`p_0 / p_0 = 1` after strictly positive free `T0VAR`; not unstandardised `T0VAR`; not `T0TDPREDEFFECTstd`; not `addedT0TIPREDVAR`; free `T0VAR` does not require `a < 0`) + p. 16 `TRAITVARstd` (`trait / trait = 1` after strictly positive `TRAITVAR`; no ridge addend; not unstandardised `TRAITVAR`; not `T0VARstd` even when both equal 1; not `addedT0TIPREDVAR`; `TRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTTRAITVARstd` (`ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR`; 2017-era source adds ridging; default ridge is 0; not unstandardised `MANIFESTTRAITVAR`; not `TRAITVARstd` even when both equal 1; not `MANIFESTVAR`; `MANIFESTTRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTVARstd` (`θ / θ = 1` after strictly positive `MANIFESTVAR`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug; not unstandardised `MANIFESTVAR`; not `MANIFESTTRAITVARstd` even when both equal 1; not Equation 5 `Var(y)`; `MANIFESTVAR` does not require `a < 0`) + p. 16 `TIPREDVARstd` (`v / v = 1` after strictly positive `TIPREDVAR`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`; not unstandardised `TIPREDVAR`; not `MANIFESTVARstd` even when both equal 1; not §7.2 `addedTIPREDVAR`; `TIPREDVAR` does not require `a < 0`) + p. 16 `asymDIFFUSIONstd` (`p / p = 1` after strictly positive `asymDIFFUSION`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`; not unstandardised `asymDIFFUSION`; not `TIPREDVARstd` even when both equal 1; not `DIFFUSIONstd` `−2 a`; lasting `asymDIFFUSION` requires `a < 0`) + p. 16 `discreteCINTstd` (`A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; not unstandardised `discreteCINT`; not `κ / √p`; not `(-κ / a) / √p`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `asymCINTstd` (`(-κ / a) / √p` after strictly positive `asymDIFFUSION`; not unstandardised `asymCINT`; not `κ / √p`; not `discreteCINTstd`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `T0MEANSstd` (`μ_0 / √p_0` after strictly positive free `T0VAR`; not unstandardised `T0MEANS`; not `T0VARstd`; not `μ_0 / √asymDIFFUSION`; free `T0MEANS` does not require `a < 0`) + irregular already-centered residual lag + strong-gated latent means (n=2 residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016); full ESEM/DSEM remaining | ADR 0005; `docs/research/posterior-esem-input-gates.md`; `docs/research/multilevel-event-time-recovery.md`; `docs/research/rubin-total-variance.md`; `docs/research/strong-invariance-latent-means.md` | | Prompt-versus-unique-content identity | `prompt_source` | accepted-target | active PR | refuse prompt-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 | | Corpus-background-versus-unique-content identity | `corpus_background` | accepted-target | active PR | refuse background-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 | | Modality-versus-unique-content identity | `modality_source` | accepted-target | active PR | refuse modality-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 |