diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b03adb92..9117220dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ## [Unreleased] +- Restored protected-main gate integrity after the consolidation merges: hourly-scheduler prompt-contract tests now assert the gap-baseline-derived task contract (Gap ID naming, no invented weights) instead of stale increment-specific tokens, the operator-gap register inventory matches the live 33-PR queue, `evidence_core::image_unit` non-image/empty-subtype refusals and `load_union_branch_totals` valid-record accumulation have exact coverage, and the README crate fence plus duplicate registry entries stay deduped. +- Branch-coverage diagnostics on the post-consolidation head exposed two uncovered outcomes in `evidence_core::image_unit` (`is_image_media_type_token` non-image prefix and empty-subtype refusals), one uncovered authored line (the strip-prefix refusal), and lost valid-record coverage for `load_union_branch_totals`; exact red-to-green cases now cover the non-image/empty-subtype data URIs and per-coordinate True/False accumulation. - Repaired post-consolidation merge fallout that left protected `main` red: restored the lost `return True` in the `check_coverage.py` match-guard branch, removed the shadowed duplicate `load_union_branch_totals` and `_is_multiline_match_guard` definitions plus duplicate workspace-crate entries (`episode_membership`, `analysis_engine`) from the contract tuple and Cargo member arrays, split two union-fused four-tuples back into `(variant, message)` pairs in the `event_core` error table, repaired the fused `identity_recovery_rate` body in `episode_membership::window`, deduplicated the checked-arithmetic eligible-count block in `analysis_engine`, fixed four-argument `unit()` test call sites, rebalanced the README crate-list fence around all 54 unique crates, and deduplicated the `location_membership`/`validation_core`/`tepp_api` architecture-table rows. Also documents private `PLAUSIBLE_IMAGE_MEDIA_TYPES` so `cargo doc -D warnings` passes. - Branch coverage JSON now unique-folds `files[].branches` True/False counts across instantiations. Nightly totals on #49 head `1e3e2eb` reported `event_time.rs` 505/506 while every unique site had both arms taken (253 sites × 2 instantiations). Summary-only reports without branch arrays still fail closed on totals. The 100% contract is unique production arms, matching the LCOV authored-line gate. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. - `psychometric_core` maps overflowing `expm1(a Δt)` / `expm1(2 a Δt)` in `recover_discrete_constant_predictor_effect` and `recover_discrete_process_noise` through the log-space rewrite without a redundant `if !argument.is_finite()` after overflow. Local crate llvm-cov on #49 head `559e7b399473ee90ba3234677dd9ef7f05f7fd2e` was 509/510: the same LLVM `exp`/`expm1` finite-argument proof as L768/L5040. Existing rewrite (`a = 800` / `a = 400`) and overflow (`a = 1e308`) tests remain the contract. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. diff --git a/crates/evidence_core/src/image_unit.rs b/crates/evidence_core/src/image_unit.rs index a35588b1e..5be9884a7 100644 --- a/crates/evidence_core/src/image_unit.rs +++ b/crates/evidence_core/src/image_unit.rs @@ -215,6 +215,20 @@ mod tests { ); } + #[test] + fn non_image_and_empty_subtype_data_uris_are_not_lexical_images() { + // A non-image media type exercises the strip-prefix refusal arm. + assert_eq!( + refuse_base64_image_as_lexical_text("data:text/plain;base64,AAAA"), + Ok(()) + ); + // An empty image subtype exercises the empty-subtype refusal arm. + assert_eq!( + refuse_base64_image_as_lexical_text("data:image/;base64,AAAA"), + Ok(()) + ); + } + #[test] fn common_raster_media_types_are_accepted() { let text = "a data:image/png;base64,AAAA b data:image/jpeg;base64,BBBB \ diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 2267bc030..5fa3e527a 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -2,6 +2,13 @@ **Status:** Live delivery baseline **Product:** Temporal Event Psychometrics Platform (TEPP) +**Snapshot:** 2026-08-25T04:24:53Z +**Protected-main evidence:** `0e7479c96c080036deed14a5925bb0ca715fa524` (full SHA fetched live before every mutation) | Signal | Snapshot evidence | Delivery implication | +|---|---:|---| +| Protected-main SHA | `5c8599442e85…` (2026-08-25T02:12Z, merge of #215) | All as-built claims are bounded to this commit. | +| Workspace members | 48 unique Rust crates | The repository is modular, but the approved target still lacks complete semantic, estimator, compute, psychometric, event-intelligence, network, interpretation, artifact, and visual product boundaries. | +| Open pull requests | **33** | The consolidation program drained all main-conflicting slices; the residual queue is 31 stacked drafts plus two non-draft slices and the coverage repairs in flight. | +| Draft pull requests | **31** | Most queued work is not independently review-ready; the psychometric recovery stack dominates. | **Snapshot:** 2026-08-25T02:30:00Z **Protected-main evidence:** `abbd89874b0087ae0645c7a5c493557a1be8c2d5` (full SHA fetched live before every mutation) **Workspace version on protected main:** `0.1.0` @@ -89,40 +96,15 @@ including the psychometric recovery stack and non-psychometric drafts. ## Snapshot open pull-request evidence The following exact-head register was fetched live from GitHub at -2026-08-25T02:22:37Z. Review decisions, required Checks, and mergeability remain +2026-08-25T04:24:53Z. Review decisions, required Checks, and mergeability remain volatile; the live GitHub API supersedes this snapshot. `draft=false` is not approval, mergeability, or a passing-check claim. Re-read the full SHA, current review decision, required Checks, and branch rules immediately before every mutation. | PR | Exact current head | Draft | Base | Title | |---:|---|:---:|---|---| -| #48 | `c3951af34a0bc81d272395d1e1e455d0b910f385` | false | main | feat(topic): logistic-normal ALR coordinates with true-parameter RMSE | -| #49 | `7b53b2f43b3d40933e97f597037628bd72990d34` | false | main | feat(psychometric): posterior ESEM input gates with true-parameter RMSE | -| #58 | `14febe9f343c2cd1c9891ae7f1907359c5669fc1` | false | main | feat(evidence): keep embedded image URIs as positional non-lexical units | -| #62 | `fe29d2a409e2018690793d83d04e860b35a90b4f` | false | main | feat(simulation): exclude delayed documents before they are available | -| #63 | `f2cbf34fcd4465490938c4eaa2e1653dd48aa21c` | false | main | feat(corpus): refuse TF-IDF and BM25 as inferential weights | -| #65 | `3fd7b39fc71af621ff0c5df0a830ec6a5473c492` | false | main | feat(event): score first-story detections with FAR and miss rates | -| #66 | `07fdb0246a7c21f5621990f454b58052426f6c9d` | false | main | feat(event): score TDT mention links with precision and recall | -| #74 | `0ce7e6a923282d3533cf3b8c0592d5df244049f8` | true | main | feat(temporal): keep predicted Allen assertions hypothetical | -| #75 | `90cc8b6d4848e4c7718dd4bea74c1aaaab6f3685` | true | main | feat(method): model template sources without inferential weights | -| #76 | `ccffcab50ff2f1d8c0e6ee80269d0f7ee0075368` | true | main | feat(event): score TDT topic detections without promoting clusters | -| #79 | `166e37c2cb540a575c690c813a21123a13d86376` | true | main | feat(privacy): bind authorization grants to one processing purpose | -| #80 | `9539417f223bc6067f21e701986a49b7d3a37aba` | true | main | feat(temporal): space longitudinal lags on event time | -| #81 | `a7769d37ad1f950547f00e05ce2c03e5a2843b43` | true | main | feat(privacy): bind tenant roles to system-time lifetimes | -| #82 | `774a01bc63600c0c4703114bb01467fd65e57077` | true | main | feat(privacy): export identity maps only under re-identification purpose | -| #83 | `18200b674cb29d84ab66853f50e1b5dc38096279` | true | main | docs(evidence): define language-agnostic semantic spans | -| #84 | `e0ef1f869c46aa20969ce083f9ca31d622c31bb4` | true | main | feat(invariance): replay shared-meaning gate on current main | -| #86 | `47f6216aec217f15a6274d889bc507e59821096f` | true | main | feat(privacy): replay privileged-access decisions without source identity | -| #92 | `192e1eab459ea1c7e155d9fafe60d1b5912025f2` | true | main | feat(orchestrator): serve interpretation POSTs on a loopback HTTP listener | -| #95 | `3c42b3b09e9a0501d7c7a1a42a322e58cba39165` | true | main | feat(privacy): refuse blanket-masked scientific field grants | -| #129 | `8981696f58892a1ace9baeb6224ac55b436b8110` | true | main | feat(membership): refuse customer-competitor overlap | -| #132 | `fe73209ea3407f0c8cd62fbf10ecea844ac15e50` | true | main | feat(relation): refuse unobserved pairs as no-relationship | -| #134 | `7f4a5df9fd18be203c995f59f1e734f69eba56f9` | true | main | feat(psychometric): refuse unidentified association as causal language | -| #136 | `7825c778f39bb8d1ab9f6fe18c227559f8e78fee` | true | main | feat(relation): refuse translation edges as state transitions | -| #142 | `7ca6035c5d8b7c9a7761a0c5f26d1de4215c334b` | true | main | feat(evidence): refuse untrusted payloads as estimator authority | -| #146 | `aac43e83d8567696aeaa504e2d88b6314aedfb68` | false | main | feat(membership): refuse episode membership outside the episode | -| #147 | `08c427f76098adcd5226d1e141d208896bfe58f8` | true | main | feat(method): refuse section boilerplate as unique content | -| #157 | `5d1492cc46f2acef7d0875c81f72c05e745e44ae` | false | main | feat(api): publish completed analysis-run result contract | +| #92 | `56fadb1d99be2478f86c7dd493d9240f4f7af349` | false | main | feat(orchestrator): serve interpretation POSTs on a loopback HTTP listener | +| #132 | `426c2d38e8d46914b3d6743aa616bd3383481715` | false | main | feat(relation): refuse unobserved pairs as no-relationship | | #181 | `96e8d1c21924124d144f6273893eda8ac6b41b2d` | true | agent/psychometric-posterior-esem-input | feat(psychometric): recover Driver later-occasion variance of predetermined T0VAR | | #182 | `ee999e1ed23327a75d9cf4eb09a4652561f07cab` | true | agent/psychometric-predetermined-later-t0var | feat(psychometric): recover Driver lagged covariance of predetermined T0VAR | | #183 | `c10097be0f6f4ff8dd8e6db21dce8818630fe17f` | true | agent/psychometric-predetermined-lagged-t0var | feat(psychometric): recover Driver first-occasion variance of predetermined T0VAR | @@ -154,7 +136,6 @@ Checks, and branch rules immediately before every mutation. | #213 | `d32c069c5653434302dc2507e272ff916cb7b16a` | true | agent/psychometric-standardised-asymptotic-diffusion | feat(psychometric): recover Driver p.16 discreteCINTstd after positive p | | #216 | `91903db726f1da6b398e0a32c5a401126598154f` | true | agent/psychometric-standardised-discrete-intercept | feat(psychometric): recover Driver p.16 asymCINTstd after positive p | | #218 | `19279547f5a8622d9584d95822ec36ae3830beeb` | true | agent/psychometric-standardised-asymptotic-intercept | feat(psychometric): recover Driver p.16 T0MEANSstd after positive T0VAR | -| #219 | `6cf0d87f0bb8e57e2cbfef190dc364fcc3867dd7` | false | main | test(persistence): cover uppercase-label and scanner edge branches | Review decisions, required Checks, and mergeability remain volatile; re-read them immediately before every mutation. This snapshot is not merge authorization diff --git a/tests/quality/test_check_coverage.py b/tests/quality/test_check_coverage.py index ec25ee15f..cecbeb65b 100644 --- a/tests/quality/test_check_coverage.py +++ b/tests/quality/test_check_coverage.py @@ -342,6 +342,39 @@ def test_full_branch_reports_fail_closed_on_malformed_records(self) -> None: with self.assertRaisesRegex(ValueError, message): coverage_contract.load_union_branch_totals(files) + def test_union_branch_totals_accumulate_valid_records(self) -> None: + """Valid records accumulate True/False counts per unique coordinate.""" + + files = [ + { + "filename": "src/live.rs", + "branches": [[10, 4, 10, 12, 3, 0, 0, 0, 4]], + }, + { + # A second instrumented copy of the same coordinate unions its + # outcomes with the first copy instead of double-counting. + "filename": "src/live.rs", + "branches": [[10, 4, 10, 12, 0, 2, 0, 0, 4]], + }, + { + # An empty branches array exercises the loop-exhaustion arc. + "filename": "src/idle.rs", + "branches": [], + }, + { + "filename": "src/other.rs", + "branches": [[20, 8, 20, 16, 1, 1, 0, 0, 4]], + }, + ] + self.assertEqual( + coverage_contract.load_union_branch_totals(files), + {"count": 4, "covered": 4}, + ) + self.assertEqual( + coverage_contract.load_union_branch_totals([]), + {"count": 0, "covered": 0}, + ) + def test_lcov_authored_line_totals_and_incomplete_detection(self) -> None: """LCOV counts unique authored source lines and exposes zero-hit lines.""" diff --git a/tests/quality/test_hourly_nim_product_development.py b/tests/quality/test_hourly_nim_product_development.py index 96335487a..afe24e1e1 100644 --- a/tests/quality/test_hourly_nim_product_development.py +++ b/tests/quality/test_hourly_nim_product_development.py @@ -168,7 +168,10 @@ def test_hourly_prompt_and_verifier_keep_commercial_quality_gates(self) -> None: normalized = " ".join(text.casefold().split()) for token in ( "buyer-visible", - "exactly one bounded pull request", + "product-technical-gap-baseline.md", + "gap id", + "never invent weights", + "exactly one bounded increment", "standalone", "modular MSA", "ContextualWisdomLab/.github", @@ -193,9 +196,6 @@ def test_hourly_prompt_and_verifier_keep_commercial_quality_gates(self) -> None: "Do not release", "Do not deploy", "Rust", - "audit_event", - "try_record", - "OperationalLogRecord::new", ): self.assertIn(token.casefold(), normalized)