diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ca620c..ca81311c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ### Added +- Live `docs/product-technical-gap-baseline.md` mapping operator-visible gaps to + protected-main maturity, exact current PR/issue state, stacked delivery order, + and closure evidence; placeholder-only issues #161 and #162 were closed as + queue hygiene. The documentation validator requires a dated UTC snapshot, a + 40-character protected-main SHA, an exact-head inventory matching the declared + open-PR count, and operator-gap closure evidence, and it rejects affirmative + queued-Checks-as-implemented-main claims even when wrapped across a line + break, and it rejects an unrelated `not` in the same span (`queued Checks are + not required; this PR is implemented-main`). Only never/do not/does not/ + cannot/must not plus promote/treat/make/mean counts as a promotion denial. - `checkpoint_authority` estimator gate: a model checkpoint remains an untrusted run artifact until identity, canonical `SHA-256`, and model-run provenance validate, and it cannot replace the CPU `f64` estimator or promote a scientific claim; recovered roles match known truth at a higher computed rate than collapsing every artifact to the estimator (ADR 0001/0014). - `persistence_postgres` retention/deletion/legal-hold (migration `0007`): policy rows, legal holds that block completed deletion, evidence tombstones without raw-source restore, analysis exclusion only for `logical_revocation`/`identity_tombstone` (not `cache_export_removal`), and deletion requests bound to the cited retention policy's tenant/class/purpose. - `event_core` now requires and retains `EventEvidenceLayer::PromotedTransition` when constructing an `EventInstance`; every other layer is rejected at the promotion boundary, and TDT story classification uses a caller-owned hash set for expected constant-time membership checks. @@ -79,6 +89,14 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ### Changed +- Refreshed the live gap-baseline inventory to the 2026-08-24T05:41:54Z GitHub + snapshot (118 open PRs / 48 drafts / 12 issues; protected-main + `c45be17a9dbce95ef81cee230e9d128abc7160ac`), binding each operator-gap current + head SHA to that exact-head register, including #201 `6afd650667e1` (RFC 5646 + cited once; first GAP-005 slice, not implemented-main), stacked drafts + #202–#204, and #164 `ff2e645b1785` as the predecessor register head. Duplicate + PR #179 remains closed. Stacked-merged heads and queued Checks are not + implemented-main. - Clarified ADR 0001 so it owns Rust-first numerical/reference-backend authority while ADR 0011 owns cross-service MSA/service authority. - Clarified ADR 0006 so it owns GPU/VRAM and model-credential boundaries; ADR 0010 now owns LLM orchestration policy and ADR 0015 owns autonomous repository-write/review/merge authority. - Expanded ADR 0002–0005 and 0009–0011 with explicit implementation maturity, alternatives, failure/recovery, compatibility/migration, verification, and rollback/supersession boundaries where they were previously implicit. diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index d16a2050..9e7952e3 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -5,6 +5,7 @@ TEPP's approved PRD v0.4 and implementation plan are the primary product baselin | Area | Canonical document | |---|---| | Approved product requirements | [`docs/product/prd-v0.4-approved.md`](docs/product/prd-v0.4-approved.md) | +| Live product and technical gap baseline | [`docs/product-technical-gap-baseline.md`](docs/product-technical-gap-baseline.md) | | Whole-conversation documentation fitness | [`docs/DOCUMENTATION_ASSESSMENT.md`](docs/DOCUMENTATION_ASSESSMENT.md) | | Technical requirements | [`docs/TRD.md`](docs/TRD.md) | | Architecture | [`ARCHITECTURE.md`](ARCHITECTURE.md) | diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md new file mode 100644 index 00000000..c7112e04 --- /dev/null +++ b/docs/product-technical-gap-baseline.md @@ -0,0 +1,378 @@ +# Product and Technical Gap Baseline + +**Status:** Live delivery baseline +**Product:** Temporal Event Psychometrics Platform (TEPP) +**Snapshot:** 2026-08-24T05:41:54Z +**Protected-main evidence:** `c45be17a9dbce95ef81cee230e9d128abc7160ac` +**Workspace version on protected main:** `0.1.0` +**Canonical gap-baseline authority:** [PR #164](https://github.com/ContextualWisdomLab/TEPP/pull/164). Duplicate [PR #179](https://github.com/ContextualWisdomLab/TEPP/pull/179) was closed at 2026-08-23T12:39:22Z and is not a second protected-main register. + +## Purpose + +This document is the executable operator-gap register for TEPP. It separates: + +- capabilities an operator can use from protected `main`; +- bounded work that exists only on open pull requests; +- product-completion issues with measurable acceptance evidence; and +- release claims that remain prohibited. + +A planning document, local test, queued check, predecessor-head result, LLM +judgment, or mergeable branch does not make a capability shipped. Re-read live +GitHub state before any customer, release, certification, or valuation claim. + +## Snapshot facts + +| Signal | Snapshot evidence | Delivery implication | +|---|---:|---| +| Protected-main SHA | `c45be17a9dbce95ef81cee230e9d128abc7160ac` | All as-built claims are bounded to this commit. | +| Workspace members | 10 Rust crates | The foundation is modular, but the approved target contains additional semantic, estimator, compute, psychometric, event-intelligence, network, interpretation, artifact, and visual boundaries. | +| Open pull requests | **118** | The queue is itself a release blocker and requires consolidation. | +| Draft pull requests | **48** | Most queued work is not independently review-ready. | +| Non-draft pull requests | **70** | A non-draft state is not a qualifying review or required-check result. | +| Open product issues | **12** | Issue #156 plus the product-completion program #166–#176. | +| Duplicate gap-baseline PRs | **#164** (authority); **#179** closed as superseded | Only one live register remains; queued Checks on #164 are not protected-main evidence. | +| Current package version | `0.1.0` | No supported product release is established by the repository version alone. | + +The pull-request counts come from the live GitHub search at this snapshot. The +full exact-head classification is owned by +[issue #175](https://github.com/ContextualWisdomLab/TEPP/issues/175); this file +keeps the operator-level summary while the exact-head register below records the +current 118-row volatile queue. Passing or queued Checks on an open PR never +promote that PR to implemented-main. + +## Current open pull-request evidence + +The following exact-head register was fetched from the live GitHub pull-request +API at the snapshot above. `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 | +|---:|---|:---:|---|---| +| #213 | `ad25389642aff6300c17cd852e39cc5c9a9c8c09` | true | agent/psychometric-standardised-asymptotic-diffusion | feat(psychometric): recover Driver p.16 discreteCINTstd after positive p | +| #212 | `267cd1828f279a0c2514b45ff2c815b06619849b` | true | agent/psychometric-standardised-time-independent-predictor-variance | feat(psychometric): recover Driver p.16 asymDIFFUSIONstd after positive asymDIFFUSION | +| #211 | `cc281b57af46b0f6af497a33b837e20954d44428` | true | agent/psychometric-standardised-manifest-variance | feat(psychometric): recover Driver p.16 TIPREDVARstd after positive TIPREDVAR | +| #210 | `22202c57c0818d3efb28438e95bdde5d0e7143b0` | true | agent/psychometric-standardised-manifest-trait-variance | feat(psychometric): recover Driver p.16 MANIFESTVARstd after positive Θ | +| #209 | `5e3ef38256f42ce09a934eb0f3893e02a40ad6b7` | true | agent/psychometric-added-initial-tdpred-var | feat(psychometric): recover Eq. 5 of analog addedT0TIPREDVAR extra observed TD variance | +| #208 | `adcd68a582725130c046239753290d6cb5f3b8b7` | true | agent/psychometric-standardised-trait-variance | feat(psychometric): recover Driver p.16 MANIFESTTRAITVARstd after positive Ψ_τ | +| #207 | `5dd0c01549c93fa05f57df5658058244c7b675e4` | true | agent/psychometric-standardised-initial-latent-variance | feat(psychometric): recover Driver p.16 TRAITVARstd after positive TRAITVAR | +| #206 | `dcb339f3e2e5ac2dd2dda9b61b5d2c9b811c7636` | true | agent/psychometric-standardised-initial-tdpred-std | feat(psychometric): recover analog of addedT0TIPREDVAR for first-occasion TD extra | +| #205 | `db60fe4eb47abf1efb793ccef37597689d11d09a` | true | agent/psychometric-standardised-initial-tdpred-std | feat(psychometric): recover Driver p.16 T0VARstd after positive T0VAR | +| #204 | `ac757e5e4f3651cad98fa88d5a44db570eb1c3cf` | true | agent/psychometric-standardised-continuous-tdpred-effect | feat(psychometric): recover Driver Table 3 T0TDPREDEFFECTstd after positive T0VAR | +| #203 | `e5a63d0c7ffac91e9945f6c483152a0bdf267525` | true | agent/psychometric-asymptotic-tipred-observed-variance | feat(psychometric): recover Driver 2017-era addedTIPREDVARstd after addedTIPREDVAR | +| #202 | `2d2d3efe5fd2f742a335e071f22fc1738c51ab27` | true | agent/psychometric-asymptotic-tipred-observed-variance | feat(psychometric): recover Driver p.16 TDPREDEFFECTstd after positive variances | +| #201 | `57be20fc361aa0a812b0ed4e0eaffc70680d7123` | false | main | feat(semantic): bind exact spans as units; refuse language as identity | +| #200 | `8f429471e2b249e76c9b722eaf2443518b666c98` | true | agent/psychometric-initial-tipred-observed-variance | feat(psychometric): recover Driver Eq. 5 of addedTIPREDVAR extra observed TI variance | +| #199 | `7a476ed3c39e4ba14c9c51f5cbbafc33310979d2` | true | agent/psychometric-added-t0-tipred-var | feat(psychometric): recover Driver Eq. 5 of addedT0TIPREDVAR extra observed TI variance | +| #198 | `52a9b4ceb26bdd89e6e49c56fb473d96c68ca352` | true | agent/psychometric-standardised-initial-tipred-effect | feat(psychometric): recover Driver 2017-era addedT0TIPREDVAR after T0TIPREDEFFECT | +| #197 | `a19ea1ecba3d773470f12ed4dbbeb8a01b987f26` | true | agent/psychometric-standardised-initial-tipred-effect | feat(psychometric): recover Driver Table 3 T0TDPREDEFFECTstd after positive T0VAR | +| #196 | `1cb91b43002765bf5b855be51e55cb29db41a599` | true | agent/psychometric-standardised-continuous-tipred-effect | feat(psychometric): recover Driver Table 3 T0TIPREDEFFECTstd after positive T0VAR | +| #195 | `cf275b25611953bd405550f96df257c77df01751` | true | agent/psychometric-standardised-continuous-tipred-effect | feat(psychometric): recover Driver p.16 CINTstd after positive asymDIFFUSION | +| #194 | `471b115e891be11fb41eb75a5cc3073258ab0f34` | true | agent/psychometric-standardised-asymptotic-tipred-effect | feat(psychometric): recover Driver p.16 TIPREDEFFECTstd after positive variances | +| #193 | `6235a3fc6fd6899f85f74aed71053bd50529c34c` | true | agent/psychometric-standardised-asymptotic-tipred-effect | feat(psychometric): recover Driver p.16 finite-interval TIPREDEFFECTstd after positive variances | +| #192 | `1690c7b65693cf27c8f1730150d67084594aef07` | true | agent/psychometric-standardised-continuous-drift | feat(psychometric): recover Driver p.16 asymTIPREDEFFECTstd after positive variances | +| #190 | `adb0bc6f2a1b0684eb9242bcb0d6cddd1ff09ae3` | true | agent/psychometric-standardised-continuous-diffusion | feat(psychometric): recover Driver p.16 DRIFTstd after positive asymDIFFUSION | +| #189 | `0836c359fab7878084ac3a711920550eb6cacb0d` | true | agent/psychometric-standardised-discrete-diffusion | feat(psychometric): recover Driver p.16 DIFFUSIONstd after positive asymDIFFUSION | +| #188 | `444304d2d702cceb47cd4fdf695ba630d7e7c83a` | true | agent/psychometric-standardised-discrete-drift | feat(psychometric): recover Driver p.16 discreteDIFFUSIONstd after positive asymDIFFUSION | +| #187 | `6afd048d1a78bd7e1f68555182ec6a1f0db9ea8c` | true | agent/psychometric-predetermined-later-start-later-t0var | feat(psychometric): recover Driver p.16 discreteDRIFTstd after positive asymDIFFUSION | +| #185 | `69ffec6425863b2842094ff1b1d6c07d8eee6b5b` | true | agent/psychometric-predetermined-later-lagged-t0var | feat(psychometric): recover Driver later-start later-occasion variance of predetermined T0VAR | +| #184 | `6b93147e668ff414240f3ea94997f2937c0817f1` | true | agent/psychometric-predetermined-initial-t0var | feat(psychometric): recover Driver later-start lagged covariance of predetermined T0VAR | +| #183 | `c10097be0f6f4ff8dd8e6db21dce8818630fe17f` | true | agent/psychometric-predetermined-lagged-t0var | feat(psychometric): recover Driver first-occasion variance of predetermined T0VAR | +| #182 | `7e203976fe4b768fdb4ee6c11126ac7e9ab1c4b8` | true | agent/psychometric-predetermined-later-t0var | feat(psychometric): recover Driver lagged covariance of predetermined T0VAR | +| #181 | `96e8d1c21924124d144f6273893eda8ac6b41b2d` | true | agent/psychometric-posterior-esem-input | feat(psychometric): recover Driver later-occasion variance of predetermined T0VAR | +| #180 | `60e936b43740c238d9a4083b529a3d0a12265c12` | false | main | fix(transport): hide raw provider exception details | +| #177 | `580d45206536bf2f7deba327ffafb96a69ba7260` | false | main | fix(workflow): pin scheduler budget hardening | +| #165 | `34083c3f5d6637cf1665a29dac45fbf67a74d5dd` | false | main | feat: route hourly product agents through contextual orchestrator | +| #164 | `d9d55513f5ddcc1d89139d4ba940fb8261d33b4b` | false | main | docs: define TEPP product completion and technical gap baseline | +| #157 | `340087494b0a9653aede4eeb4bd27049e051222d` | false | main | feat(api): publish completed analysis-run result contract | +| #155 | `2071a9c0090a24cd6583147f69c89020cda006ed` | false | main | feat(api): admit LineageWeave as a modular analysis-run consumer | +| #154 | `a7a1bdf96a6759f11aed9284b73319ed94b82fd2` | false | main | ci(rust): refresh branch coverage compiler baseline | +| #153 | `e7c871bc2f5e6023002ceeea30217130561842e1` | false | main | feat(membership): refuse location as entity identity or language | +| #152 | `70a6c6608e39df757417b2674f0acf27aa09b612` | false | main | feat(method): refuse prompt boilerplate as unique content | +| #151 | `f87c812415280681c4243117fbd1302b204e4f68` | false | main | feat(method): refuse corpus-background wording as unique content | +| #150 | `f9110e0eec68d823778a433c4ccab3a1beca46f5` | false | main | feat(method): refuse non-lexical modality as unique content | +| #149 | `6077b9ce7f0961a3e287c4e8afe0faa5a0638b2e` | false | main | feat(method): refuse copied-text residue as unique content | +| #148 | `4c0612fe717a40cebfb9ba1e31daaa7317607c9f` | false | main | feat(method): refuse house-voice style as unique content | +| #147 | `08c427f76098adcd5226d1e141d208896bfe58f8` | true | main | feat(method): refuse section boilerplate as unique content | +| #146 | `5419b0f76a737faf65d6b0c848c83f2f1336e326` | false | main | feat(membership): refuse episode membership outside the episode | +| #145 | `696d56c5816815e22181a03c57a822f974d41706` | false | main | feat(method): refuse default stopword deletion of report language | +| #143 | `7d533c6198492f748303869f0795fac5c8764b50` | false | main | feat(relation): refuse a template copy as the source identity | +| #142 | `7ca6035c5d8b7c9a7761a0c5f26d1de4215c334b` | true | main | feat(evidence): refuse untrusted payloads as estimator authority | +| #141 | `d558a4b4b3518f4ae09fde6ac828602bb007cdec` | false | main | feat(privacy): refuse untrusted intake without a grant | +| #140 | `4feb427f6f895ebb53a151ae7c8483f69a3890f0` | false | main | feat(estimator): refuse a checkpoint as the CPU f64 estimator | +| #139 | `43ebbda0d35f9bf227c5764d53d429fff0f08c8c` | false | main | feat(relation): refuse a summary as the source identity | +| #138 | `f06879da364e3149aa2caf51158de60926d9846f` | false | main | feat(relation): refuse reverse input-process-outcome event time | +| #137 | `c8b3d494df100e57aab7fdbcdc58a798c874e6c0` | false | main | feat(relation): refuse retrospective reporting as a transition | +| #136 | `7825c778f39bb8d1ab9f6fe18c227559f8e78fee` | true | main | feat(relation): refuse translation edges as state transitions | +| #135 | `1576e7fe5f03eb1a678060091115dfc927518d49` | false | main | feat(evidence): refuse untrusted payloads without identity and bounds | +| #134 | `7f4a5df9fd18be203c995f59f1e734f69eba56f9` | true | main | feat(psychometric): refuse unidentified association as causal language | +| #133 | `dbe1c1f6f1e27403ee6301f3de220fff1f2d8b40` | false | main | feat(relation): refuse inferred status as observed evidence | +| #132 | `fe73209ea3407f0c8cd62fbf10ecea844ac15e50` | true | main | feat(relation): refuse unobserved pairs as no-relationship | +| #131 | `02c04db787ed6fc443102875740d97b7d2e2cbcc` | false | main | feat(membership): refuse collapsing targets into entity or project | +| #130 | `6f963c8527986c8290aff94ae898991adf03e4d6` | false | main | feat(relation): refuse support edges as state transitions | +| #129 | `8981696f58892a1ace9baeb6224ac55b436b8110` | true | main | feat(membership): refuse customer-competitor overlap | +| #128 | `30ff215365a18ccef7b22e03912c293532b8f7bc` | false | main | feat(temporal): refuse other clocks as system time | +| #127 | `bd34a2dda405fab264147f68daa2059dd61c30ca` | false | main | feat(temporal): refuse other clocks as event time | +| #126 | `28f7ed69785da71c38439c4241a132ab391a5c6f` | false | main | feat(temporal): refuse other clocks as assertion time | +| #125 | `c225f353f27647268d44a9e8156412a1b9de9fc2` | false | main | feat(temporal): refuse event, system, and available time as cutoff | +| #124 | `e89b90ce8d2792cb3f1fd61ad7dbd12556855df2` | false | main | feat(temporal): refuse event and system time as availability | +| #123 | `78e41907ff95067a8755e3ceb41de5f32299ba6e` | false | main | feat(temporal): refuse document rows that omit assertion or document time | +| #122 | `38542fd41196394587e024c7e824c840dcafb32c` | false | main | feat(temporal): refuse later revisions with earlier system time | +| #121 | `93f6aa5e28761e69f14093d2e341799219f867c6` | false | main | feat(privacy): seal identity mappings with purpose-bound HMAC | +| #120 | `34c4c119608b2aa46c84e9bef2b47711740ff9de` | false | main | feat(relation): refuse citation edges as state transitions | +| #119 | `47ab763d49b14ab1ba31f4828ad6e3fda274c007` | false | main | feat(psychometric): recover ESEM loadings and refuse reverse DSEM lags | +| #118 | `b8f4582f65852b0ac5ba9149de9d5d7783b1c282` | false | main | feat(event): refuse subevents that escape the parent interval | +| #117 | `8a5a3fa6d38703e6b83b03ad64959dd01c8f263d` | false | main | feat(membership): recover nested ICC and refuse cross-classified collapse | +| #116 | `08d557c2f772e92543e71d27ac41a108fe64a8bb` | false | main | docs(adr): wire verified method papers into temporal and psychometric ADRs | +| #115 | `2dbc0fd1d7200100a72990c01008e50ad5f9e641` | false | main | fix(quality): refuse inverted coverage-authority PR sentences | +| #114 | `df734d71293bf5bbdd10d28430c15626cdb1220e` | false | main | feat(privacy): record provider field codes without source text | +| #113 | `bd800fc62a7cb59339177e34baf3237d6897fce7` | false | main | feat(persistence): fail-closed entity and project target SQL | +| #110 | `4517b3f00d56d08a5a9bf47e6b7a681537765127` | false | main | feat(api): export corpus-split leakage-audit manifests | +| #106 | `60aef093e4f89638b896864342aa28d3a2d3ece7` | false | main | fix(privacy): inspect audit_event inserts through try_record | +| #100 | `b2a885b9b5418c79d5e828d64291c878f5ae5477` | false | main | test(tls): recover bind decisions from the live policy | +| #99 | `c4ed064c9e931f1772992526969fb4ae5fcd4537` | false | main | feat(persistence): persist exact text_segment byte spans without 0007 | +| #95 | `3c42b3b09e9a0501d7c7a1a42a322e58cba39165` | true | main | feat(privacy): refuse blanket-masked scientific field grants | +| #92 | `192e1eab459ea1c7e155d9fafe60d1b5912025f2` | true | main | feat(orchestrator): serve interpretation POSTs on a loopback HTTP listener | +| #91 | `808ae6690b35bb58f2152d74c7978e90de6b86a0` | false | main | feat(privacy): inherit source sensitivity onto derived artifacts | +| #86 | `47f6216aec217f15a6274d889bc507e59821096f` | true | main | feat(privacy): replay privileged-access decisions without source identity | +| #85 | `1ebb40644bb479ed8703f6df1b351f3e19d5fe13` | false | main | feat(event): score CHRONOS occurrence forecasts with a Brier rule | +| #84 | `e0ef1f869c46aa20969ce083f9ca31d622c31bb4` | true | main | feat(invariance): replay shared-meaning gate on current main | +| #83 | `18200b674cb29d84ab66853f50e1b5dc38096279` | true | main | docs(evidence): define language-agnostic semantic spans | +| #82 | `774a01bc63600c0c4703114bb01467fd65e57077` | true | main | feat(privacy): export identity maps only under re-identification purpose | +| #81 | `a7769d37ad1f950547f00e05ce2c03e5a2843b43` | true | main | feat(privacy): bind tenant roles to system-time lifetimes | +| #80 | `9539417f223bc6067f21e701986a49b7d3a37aba` | true | main | feat(temporal): space longitudinal lags on event time | +| #79 | `166e37c2cb540a575c690c813a21123a13d86376` | true | main | feat(privacy): bind authorization grants to one processing purpose | +| #78 | `b64c6799708ac1f6ac7c84e07fe3ae50750434e1` | false | main | feat(longitudinal): keep unit means out of within-unit change | +| #76 | `ccffcab50ff2f1d8c0e6ee80269d0f7ee0075368` | true | main | feat(event): score TDT topic detections without promoting clusters | +| #75 | `90cc8b6d4848e4c7718dd4bea74c1aaaab6f3685` | true | main | feat(method): model template sources without inferential weights | +| #74 | `0ce7e6a923282d3533cf3b8c0592d5df244049f8` | true | main | feat(temporal): keep predicted Allen assertions hypothetical | +| #73 | `11cc811a10b80a49e8a8ed6bc60fba3d5c753d28` | false | main | feat(topic): keep one identity across dormancy and reactivation | +| #72 | `899656968cc9f68a3d8fc55dddc4fd257fb27050` | false | main | feat(event): score TDT story segments with WindowDiff and Pk | +| #71 | `2588f38281b97fa03f552634d307e8b4c908899d` | false | main | feat(network): refuse raw simplex Euclidean cluster geometry | +| #70 | `7a1f33aa68c1c9be9e9da7ac7f7dadb1092ff9e4` | false | main | feat(event): score CHRONOS schema slots with precision and recall | +| #69 | `8e4a3ca9cc80f0f4e3bccf712fe6a725bfb1365e` | false | main | feat(interpretation): keep LLM claims hypothetical and evidence-cited | +| #68 | `6a98c812ef8e621e1bc1c46a615296b39f0bae33` | false | main | feat(event): score TDT tracks with pair precision and switch rate | +| #67 | `45b272d2498ecff128d75621c88c1e7d6eb1400b` | false | main | feat(model): statistical Pareto K gates refuse LLM numerical authority | +| #66 | `380be3f33f798cc8648a9dc9f24b85011f9e0468` | false | main | feat(event): score TDT mention links with precision and recall | +| #65 | `74351f398d67df590019049ab85a7f649495b860` | false | main | feat(event): score first-story detections with FAR and miss rates | +| #64 | `c11adce997d4f3e462f50711211af9f051e747b0` | false | main | feat(event): score mention confidence with a known-truth Brier rule | +| #63 | `0735ca67abcf5c6c2fd591a52d29067e5f16215a` | false | main | feat(corpus): refuse TF-IDF and BM25 as inferential weights | +| #62 | `0446878c69fdd63809826d61bb90e2be1b105227` | false | main | feat(simulation): exclude delayed documents before they are available | +| #61 | `c7f094cf17b5d0be0aa9270b2d397da4d2db851d` | false | main | feat(temporal): refuse uncertain availability past knowledge cutoff | +| #60 | `40ede67614599ba21495fea024d4493d3af9fbb3` | false | main | feat(relation): refuse association and precedence as causation | +| #59 | `b47efdc3cfdcec61f69c4219c49519a160bd5549` | false | main | feat(corpus): treat NFC/NFD bodies as split leakage | +| #58 | `431561a6c422660c618f82a241e5a4b320653378` | false | main | feat(evidence): keep embedded image URIs as positional non-lexical units | +| #57 | `b76e38393e932873ec2aed682ab539ee61828537` | false | main | feat(validation): exact-head claim promotion gates | +| #51 | `1801501c4d7c5be720d24aba954280fbc9068612` | false | main | feat(compute): VRAM budget types with CPU f64 fallback | +| #50 | `d4cd08341e8dca8475542cf9f3b46a1f5bae5ea3` | false | main | feat(event): refuse TDT/CHRONOS outputs as state transitions | +| #49 | `dd6cf43e5edfe1d9a7e344cac5352bfb55480e8a` | false | main | feat(psychometric): posterior ESEM input gates with true-parameter RMSE | +| #48 | `6110d3660607ba46b312b4d76f048f1bcc4f3bc5` | false | main | feat(topic): logistic-normal ALR coordinates with true-parameter RMSE | + +The exact-head register, counts, and protected-main SHA were fetched from the live GitHub REST API at `2026-08-24T05:41:54Z`. Review decisions, required Checks, and mergeability remain volatile; re-read them immediately before every mutation. This snapshot is not merge authorization and does not treat queued or passing Checks as shipped protected-main behavior. + +## Authority and derivation + +| Concern | Canonical authority | Constraint | +|---|---|---| +| Product outcomes | [`docs/product/prd-v0.4-approved.md`](product/prd-v0.4-approved.md) | Defines the release product, users, visual surfaces, scientific claims, and eight delivery phases. | +| Technical/runtime requirements | [`docs/TRD.md`](TRD.md) | Requires independently usable Rust boundaries, CPU `f64` authority, temporal eligibility, realistic validation, and warning-free release evidence. | +| Architecture and service boundaries | [`ARCHITECTURE.md`](../ARCHITECTURE.md), [`docs/UML.md`](UML.md), [`docs/API_CONTRACT.md`](API_CONTRACT.md) | Separates evidence, measurement, compute, psychometrics, event intelligence, interpretation, artifacts, and visual analytics. | +| Data authority | [`docs/ERD.md`](ERD.md), [`docs/TRACEABILITY.md`](TRACEABILITY.md), [`docs/adr/0013-bitemporal-persistence-reproducibility-and-split-authority.md`](adr/0013-bitemporal-persistence-reproducibility-and-split-authority.md) | Requires normalized persistence, six-clock eligibility, relation-aware splits, immutable provenance, and reproducible artifacts. | +| Scientific claim promotion | [`docs/adr/0014-scientific-claim-promotion-and-release-evidence.md`](adr/0014-scientific-claim-promotion-and-release-evidence.md), [`docs/TEST_STRATEGY.md`](TEST_STRATEGY.md) | Requires production-code recovery, uncertainty, parity, exact-head checks, and independent review before promotion. | +| LLM authority | [`docs/adr/0010-adaptive-llm-orchestration.md`](adr/0010-adaptive-llm-orchestration.md), [`docs/LLM_ORCHESTRATION.md`](LLM_ORCHESTRATION.md) | LLMs may propose and verify interpretations; deterministic/statistical gates remain authoritative. | +| Privacy/security/assurance | [`docs/PRIVACY_DATA_GOVERNANCE.md`](PRIVACY_DATA_GOVERNANCE.md), [`SECURITY.md`](../SECURITY.md), [`docs/THREAT_MODEL.md`](THREAT_MODEL.md), [`docs/COMPLIANCE_READINESS.md`](COMPLIANCE_READINESS.md) | Preserves legitimate PII utility through purpose-bound access while prohibiting credential/source leakage and unsupported certification claims. | +| Research | [`docs/research/standards-and-literature.md`](research/standards-and-literature.md) | Method and standards claims require current authoritative sources and APA 7 traceability. | +| Live delivery | [open PRs](https://github.com/ContextualWisdomLab/TEPP/pulls?q=is%3Apr+is%3Aopen), [open issues](https://github.com/ContextualWisdomLab/TEPP/issues?q=is%3Aissue+is%3Aopen) | Live GitHub state supersedes this time-stamped queue snapshot. | + +## Protected-main as-built baseline + +Protected `main` contains the following workspace boundaries: + +```text +evidence_core +temporal_core +event_core +relation_graph +membership_core +persistence_postgres +corpus_split +tepp_simulation +validation_core +tepp_api +``` + +The traceability ledger records meaningful protected-main implementation in +immutable evidence, six clocks and interval reasoning, forward transitions, +event mention/instance separation, weighted multiple membership, cutoff-safe +splits, validation metrics, simulations, PostgreSQL slices, versioned API/export +contracts, orchestration routing, privacy authorization, and release-evidence +generation. + +Protected `main` does **not** yet establish the complete approved product. In +particular, it does not contain the full multilingual semantic pipeline, a +shared-latent temporal topic estimator, a production longitudinal ESEM/DSEM +estimator, a calibrated TDT/CHRONOS workflow, a posterior network estimator, +real accelerator kernels, a production interpretation gateway, the coordinated +visual workspace, or a supported multi-tenant release. + +## Operator-gap register + +| ID | Operator-visible gap | Maturity | Delivery status | Protected-main authority | Current delivery authority | Current head SHA | Closure evidence | +|---|---|---|---|---|---|---|---| +| GAP-001 | Submission can produce a durable accepted receipt, but protected `main` lacks the separate deterministic terminal-result lifecycle. | `active-PR` | landing vehicle | `c45be17` (accepted receipt only) | [#156](https://github.com/ContextualWisdomLab/TEPP/issues/156) / [PR #157](https://github.com/ContextualWisdomLab/TEPP/pull/157) | `340087494b0a` | Exact request/result/snapshot/cutoff/model/profile binding, typed terminal failures, deterministic retrieval, current-head checks, and qualifying review. Cutoff-safe execution from closed stacked PR #178 is on this head only and is not implemented-main. | +| GAP-002 | LineageWeave and other modular consumers cannot yet rely on the complete protected-main HTTP evidence/result boundary. | `active-PR` | landing vehicle | `c45be17` (loopback naruon listener from merged PR #107; versioned API contracts) | [#155](https://github.com/ContextualWisdomLab/TEPP/pull/155) | `2071a9c0090a` | Merge the live consumer contract after exact-head review/Checks. Closed stacked PRs #158 and #159 were folded into this head; they are not protected-main evidence. | +| GAP-003A | Immutable evidence cannot yet be submitted to a durable validation run that produces operator-usable scientific acceptance evidence. | `accepted-target` | product-completion | `c45be17` (validation metrics are library-level only) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | Compose/CLI/API execution must bind immutable evidence, cutoffs, model configuration, validation metrics, and reproducibility manifests to one idempotent run. | +| GAP-003B | Scientific result artifacts cannot yet be persisted, restarted, and recovered as one supported operator workflow. | `accepted-target` | product-completion | `c45be17` (persistence contracts lack E2E recovery) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | Durable storage, migration/rollback, restart/recovery, artifact digest verification, and terminal retrieval must pass against a real Compose deployment. | +| GAP-003C | The persistence slice classifies concurrent-write SQLSTATEs, but has no measured hot-partition detection, routing, or mitigation for tenant/result workloads. | `accepted-target` | product-completion | `c45be17` (conflict classification only; no measured partition control) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | `—` (issue program; no current implementation PR) | A real Compose/PostgreSQL workload identifies hot keys and partition skew, applies bounded tenant/time or result routing without weakening 3NF or temporal authority, and proves conflict rate, latency, recovery, and migration/rollback behavior under load. | +| GAP-004 | The central shared-latent temporal/relational topic estimator is absent. | `accepted-target` | product vertical | `c45be17` (no production estimator) | [#167](https://github.com/ContextualWisdomLab/TEPP/issues/167) / [PR #48](https://github.com/ContextualWisdomLab/TEPP/pull/48) | `6110d3660607` | Rust CPU `f64` fitting, sparse bounded parallelism, posterior artifacts, convergence, true-parameter RMSE/bias/coverage, and real candidate-K fitting. | +| GAP-005 | Real multilingual documents are not yet transformed into validated exact-span semantic units and versioned shared concepts. | `accepted-target` | product vertical | `c45be17` (evidence spans exist without full semantic pipeline) | [#168](https://github.com/ContextualWisdomLab/TEPP/issues/168) / [PR #201](https://github.com/ContextualWisdomLab/TEPP/pull/201) | `57be20fc361a` | Span-grounded units on #201 are a first slice only (not concept alignment, not invariance, not implemented-main). Closure still requires Unicode/layout/language-tailored processing, unknown-concept review, multilingual calibration/invariance, image-position evidence, and prompt-injection tests. | +| GAP-006 | Posterior topic measurements cannot yet be fitted through a complete cross-classified longitudinal ESEM/DSEM engine. | `accepted-target` | product vertical | `c45be17` (temporal and membership primitives only) | [#169](https://github.com/ContextualWisdomLab/TEPP/issues/169) / [PR #119](https://github.com/ContextualWisdomLab/TEPP/pull/119) | `47ab763d49b1` | Plausible-value/joint uncertainty, invariance, irregular event time, within/between separation, multiple membership, true-parameter recovery, and causal-claim refusal. | +| GAP-007 | TDT detection/tracking and CHRONOS schema/forecast/temporal reasoning remain isolated bounded gates rather than one calibrated product workflow. | `accepted-target` | product vertical | `c45be17` (event/time primitives only) | [#170](https://github.com/ContextualWisdomLab/TEPP/issues/170) / [PR #70](https://github.com/ContextualWisdomLab/TEPP/pull/70) | `7a1f33aa68c1` | Span-grounded mentions, calibrated TDT metrics, schema/forecast hypothesis states, interval consistency, known-truth recovery, persistence, and exports. | +| GAP-008 | GPU support is policy-only; no production estimator kernel has real hardware parity or declared VRAM evidence. | `accepted-target` | product vertical | `c45be17` (VRAM policy only) | [#171](https://github.com/ContextualWisdomLab/TEPP/issues/171) / [PR #51](https://github.com/ContextualWisdomLab/TEPP/pull/51) | `1801501c4d7c` | Real CUDA/portable backend execution, CPU parity, streamed memory, bounded OOM/fallback, hardware profiles, telemetry, and no skipped-support claim. | +| GAP-009 | Topic association and cluster outputs lack posterior-valid estimation, uncertainty, edge stability, and consensus communities. | `accepted-target` | product vertical | `c45be17` (network primitives only) | [#172](https://github.com/ContextualWisdomLab/TEPP/issues/172) / [PR #71](https://github.com/ContextualWisdomLab/TEPP/pull/71) | `2588f38281b9` | Valid log-ratio coordinates, interval/stability-bearing edges, repeated Leiden consensus, known-truth network/cluster recovery, and reproducible exports. | +| GAP-010 | Operators lack coordinated accessible visual analytics and exact-value export workflows. | `accepted-target` | product vertical | `c45be17` (no visual workspace) | [#173](https://github.com/ContextualWisdomLab/TEPP/issues/173) | `—` (Figma work not started) | Real Figma File ID in ADR, Storybook/design tokens, ten PRD views, exact-value tables, accessible interaction/print/PDF states, provenance, and source-consistent exports. | +| GAP-011 | TEPP is not yet an operable multi-tenant service or supported release. | `accepted-target` | product vertical | `c45be17` (library contracts only) | [#174](https://github.com/ContextualWisdomLab/TEPP/issues/174) | `—` (issue program; no current implementation PR) | Durable queue/storage, OIDC/RLS/purpose controls, OpenTelemetry/SLOs, load/recovery, migrations, signed release/SBOM/provenance, assurance evidence, and support policy. | +| GAP-012 | The 118-PR queue obscures authority, repeatedly stales exact-head evidence, and fragments product boundaries. | `partial` | release blocker | `c45be17` (protected-main truth) | [#175](https://github.com/ContextualWisdomLab/TEPP/issues/175) | `—` (live queue program) | Every PR classified; unique landing vehicles; compatible slices folded; superseded work closed with provenance; scheduler prioritizes consolidation; queue reaches zero before GA. | +| GAP-013 | Evidence-grounded LLM interpretation is routed but not executed and validated as a production interpreter/verifier port. | `partial` | active integration | `c45be17` (routing and refusal contracts only) | [#176](https://github.com/ContextualWisdomLab/TEPP/issues/176), [PR #69](https://github.com/ContextualWisdomLab/TEPP/pull/69), [PR #165](https://github.com/ContextualWisdomLab/TEPP/pull/165) | `8e4a3ca9cc80` / `34083c3f5d66` | Contextual-orchestrator execution, evidence citations, verifier refusals, comparable-budget ablations, provider eligibility/fallback, abstention, live/offline contract tests, and no numerical-authority escalation. | +| GAP-014 | README/TRD and some PR descriptions lag protected-main and live queue reality. | `partial` | documentation drift | `c45be17` (documentation is not fully synchronized) | [#175](https://github.com/ContextualWisdomLab/TEPP/issues/175) | `—` (queue-consolidation work) | Reconcile README, TRD, traceability, ADR maturity, CHANGELOG, preferred-merge declarations, and exact protected-main evidence. | +| GAP-015 | There was no canonical live product/operator-gap register tied to documentation validation. | `active-PR` | landing vehicle | `c45be17` (no live gap register) | [PR #164](https://github.com/ContextualWisdomLab/TEPP/pull/164) (authority); closed [PR #179](https://github.com/ContextualWisdomLab/TEPP/pull/179) is not a second register | `d9d55513f5dd` | Merge this document and its validator/map/quality-test integration after exact-head checks and independent review. Passing Checks on #164 are not implemented-main. | +| GAP-016 | Hourly PR maintenance used an older central scheduler revision whose per-repository sweep budgets could amplify the queued review workload. | `active-PR` | operability hardening | `c45be17` (caller pin before central budget hardening) | [PR #177](https://github.com/ContextualWisdomLab/TEPP/pull/177) | `580d45206536` | The change pins a verified central revision immutably; closure still requires exact-head hosted Checks, resolved threads, and independent review. | +| GAP-017 | Accepted analysis runs have a terminal DTO, and cutoff-safe execution exists only on the #157 head after stacked PR #178 merged into that branch. | `active-PR` | product vertical | `c45be17` (accepted receipt only) | [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) / [PR #157](https://github.com/ContextualWisdomLab/TEPP/pull/157) | `340087494b0a` | Exact availability cutoff, snapshot binding, multiple-membership preservation, digest integrity, redacted no-eligible failure, and realistic end-to-end tests on protected main. Closed stacked PR #178 is not implemented-main. | + +## Product-completion issue register + +| Issue | Product vertical | Depends on / constrains | +|---:|---|---| +| [#156](https://github.com/ContextualWisdomLab/TEPP/issues/156) | Completed analysis-run result contract | Must land before consumers can call accepted work a measurement result. | +| [#166](https://github.com/ContextualWisdomLab/TEPP/issues/166) | Executable end-to-end analysis run, recovery, and hot-partition readiness | Integrates all scientific/service verticals; cannot substitute placeholders or hide write skew behind an unmeasured queue. | +| [#167](https://github.com/ContextualWisdomLab/TEPP/issues/167) | Shared-latent temporal topic CPU estimator | Numerical foundation for K selection, networks, psychometrics, interpretation, and product E2E. | +| [#168](https://github.com/ContextualWisdomLab/TEPP/issues/168) | Multilingual semantic units and concept dictionary | Supplies validated span-grounded estimator evidence. | +| [#169](https://github.com/ContextualWisdomLab/TEPP/issues/169) | Multilevel longitudinal ESEM/DSEM | Consumes posterior topic coordinates and membership/time contracts. | +| [#170](https://github.com/ContextualWisdomLab/TEPP/issues/170) | TDT/CHRONOS event intelligence | Consumes evidence/time/event contracts and supplies calibrated event artifacts. | +| [#171](https://github.com/ContextualWisdomLab/TEPP/issues/171) | Real GPU compute and parity | Accelerates production estimators only after CPU authority is stable. | +| [#172](https://github.com/ContextualWisdomLab/TEPP/issues/172) | Posterior network and consensus clustering | Depends on a real fitted topic posterior. | +| [#173](https://github.com/ContextualWisdomLab/TEPP/issues/173) | Accessible visual analytics and exports | Starts after stable API/artifact contracts; requires Figma and Storybook evidence. | +| [#174](https://github.com/ContextualWisdomLab/TEPP/issues/174) | Commercial deployment/release/support | Wraps a scientifically complete product without weakening gates. | +| [#175](https://github.com/ContextualWisdomLab/TEPP/issues/175) | PR queue and delivery consolidation | Immediate release-system priority; prevents further unbounded fragmentation. | +| [#176](https://github.com/ContextualWisdomLab/TEPP/issues/176) | Contextual-orchestrator interpreter/verifier | Consumes validated artifacts and cannot promote scientific truth. | + +## Priority pull-request queue + +This table is intentionally non-exhaustive. Issue #175 owns the full exact-head +inventory and classification. The pull request's live page is authoritative +because its head can change after this file is committed. + +| PR | Current delivery role | Required next action | +|---:|---|---| +| [#164](https://github.com/ContextualWisdomLab/TEPP/pull/164) | Canonical product/technical gap baseline | Re-run exact-head documentation/repository checks and obtain independent review. | +| [#179](https://github.com/ContextualWisdomLab/TEPP/pull/179) | Duplicate gap-baseline snapshot | Closed as superseded at 2026-08-23T12:39:22Z; do not reopen as a second register. | +| [#177](https://github.com/ContextualWisdomLab/TEPP/pull/177) | Central scheduler budget-hardening pin | Re-run exact-head Checks and obtain independent review before relying on the hourly caller. | +| [#165](https://github.com/ContextualWisdomLab/TEPP/pull/165) | Hourly agent routing through contextual-orchestrator | Ensure queue-consolidation policy from #175 prevents unrelated micro-PR growth. | +| [#157](https://github.com/ContextualWisdomLab/TEPP/pull/157) | Terminal result contract for #156, including folded cutoff-safe execution from closed #178 | Complete exact-head review/check gates; keep #156 open until protected-main verification. | +| [#155](https://github.com/ContextualWisdomLab/TEPP/pull/155) | Modular LineageWeave consumer parent, including folded #158/#159 | Obtain independent review; passing Checks are not implemented-main. | +| [#180](https://github.com/ContextualWisdomLab/TEPP/pull/180) | Hide raw provider exception details | Review/check gates; do not weaken fail-closed provider handling. | +| [#201](https://github.com/ContextualWisdomLab/TEPP/pull/201) | First ADR 0020 / #168 span-grounded semantic-unit slice | Complete exact-head Checks and independent review; not concept alignment and not implemented-main. | +| [#153](https://github.com/ContextualWisdomLab/TEPP/pull/153) | Refuse location as entity identity or language | Independent review after exact-head membership tests. | +| [#48](https://github.com/ContextualWisdomLab/TEPP/pull/48) | Logistic-normal/ILR coordinate slice, including folded stacked #191 TRSL lineage artifacts | Fold into the estimator landing plan; coordinates and lineage artifacts are not candidate-K fitting. | +| [#51](https://github.com/ContextualWisdomLab/TEPP/pull/51) | VRAM budget/fallback policy types | Resolve requested changes; connect only to a real production kernel under #171. | +| [#67](https://github.com/ContextualWisdomLab/TEPP/pull/67) | Model-selection gates | Rebase/merge only with an explicit path to real candidate fitting under #167. | +| [#69](https://github.com/ContextualWisdomLab/TEPP/pull/69) | Interpretation grounding/refusal metrics | Fold into the product interpreter/verifier under #176. | +| [#71](https://github.com/ContextualWisdomLab/TEPP/pull/71) | Compositional geometry/network pair metrics | Fold into the network estimator under #172. | +| [#119](https://github.com/ContextualWisdomLab/TEPP/pull/119) | Bounded loading/lag recovery slice | Consolidate into the psychometric engine under #169. | +| [#181](https://github.com/ContextualWisdomLab/TEPP/pull/181)–[#190](https://github.com/ContextualWisdomLab/TEPP/pull/190), [#192](https://github.com/ContextualWisdomLab/TEPP/pull/192)–[#204](https://github.com/ContextualWisdomLab/TEPP/pull/204) | Draft stacked psychometric T0VAR/drift/standardised recoveries | Keep stacked; do not promote drafts or predecessor heads as protected-main. Closed stacked #191 landed on #48 only. | + +## Delivery sequence + +The dependency-aware product order is: + +1. **Consolidate delivery authority:** #175 and PR #164. +2. **Finish live result/consumer contracts:** #156/#157 and #155 (loopback PR #107 is already implemented-main; closed stacked #158/#159/#178 are not). +3. **Build validated multilingual evidence:** #168. +4. **Build the CPU topic estimator:** #167. +5. **Build event intelligence and posterior networks:** #170 and #172. +6. **Build the posterior-aware longitudinal psychometric engine:** #169. +7. **Accelerate real kernels with parity:** #171. +8. **Complete the durable end-to-end run:** #166. +9. **Execute and validate interpretation:** #176. +10. **Design and implement the operator workspace:** #173. +11. **Productionize and release:** #174. + +Stacking is appropriate where public contracts make dependencies explicit. +Stacking is not a reason to leave multiple unexplained implementation authorities +or stale draft predecessors open. + +## Definition of product complete + +TEPP is not complete until one released version proves all of the following on +the same protected source lineage: + +- a documented user can install, authenticate, ingest, run, inspect, export, and + recover the product without repository-internal intervention; +- immutable source evidence, six clocks, relation/membership structure, cutoff, + splits, model/config, backend, seeds, and artifacts are reproducible; +- the shared-latent topic estimator and longitudinal psychometric model recover + declared known truth with pre-registered RMSE, bias, coverage, convergence, + calibration, and error-rate gates; +- declared language profiles have span/concept/alignment/invariance evidence; +- event intelligence, topic networks, and clusters have known-truth and + uncertainty/stability evidence; +- accelerator claims use real hardware and match the CPU scientific reference; +- LLM interpretation cites allowed evidence, rejects unsupported claims, and + abstains when evidence or policy is insufficient; +- every visual value has an accessible exact-value and provenance path; +- tenant, purpose, identity, retention, security, migration, backup/restore, + observability, capacity, rollback, SBOM, provenance, and support evidence pass; +- production statement coverage, branch coverage, and public documentation are + 100% for shipped TEPP code; +- current-head CI, security, supply-chain, scientific, and independent review + gates pass with no unresolved release blocker; +- version, CHANGELOG, signed artifacts, and release notes match the protected + source and make no unsupported certification, causality, language, GPU, or + valuation claim; +- the release-blocking PR and issue queues are zero. + +A `200억 달러` bar remains a prioritization heuristic. It is not a valuation +result and cannot replace operator adoption, predictive/construct validity, +operational reliability, proprietary advantage, revenue, retention, or +independent diligence evidence. + +## Architecture, data, and assurance constraints + +- Rust owns production mathematical and psychometric arithmetic. +- CPU `f64` is the numerical reference; parallelism is bounded and GPU work must + prove real-hardware parity. +- Event, assertion, document, system, availability, and knowledge-cutoff clocks + remain distinct. +- Cross-classified and weighted multiple membership prevents atomistic + pseudo-replication. +- Topic proportions remain compositional; valid latent/log-ratio coordinates + feed ESEM and network analysis. +- Database objects use descriptive two-or-more-word `snake_case`, third-normal + form where applicable, explicit tenant/temporal/provenance authority. Hot + partition readiness is a separate acceptance gate: measure skew first, then + mitigate it without denormalizing authority tables or changing temporal + semantics. +- Documents, web/search results, connector data, and LLM output are untrusted. +- Purpose-bound access and protected identity mappings preserve PII utility + without broadcasting or blanket masking. +- External products integrate through versioned API/event/artifact contracts, + never direct application-table access. +- CSAP/SOC 2/ISO/NIST alignment is readiness evidence, not certification. +- Every method/standard decision updates APA 7 traceability and source-to-test + traceability in the same reviewed change. + +## Refresh rule + +Refresh this file when any of the following changes materially: + +- protected-main SHA or package version; +- open PR/draft/issue counts; +- a priority PR head/base/review/check/merge state; +- an issue or operator-gap acceptance boundary; +- a capability's implementation maturity; +- the dependency/landing order; +- a release, deprecation, replacement, Figma file, or standards/research basis. + +Keep this file operator-oriented. Store the volatile per-PR classification in the +artifact required by issue #175, and link it here. Never rewrite an active-PR +capability as protected-main before merge and exact-head verification. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..f0e4c8af --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[tool.pytest.ini_options] +pythonpath = ["."] +testpaths = ["tests"] diff --git a/scripts/validate_documentation.py b/scripts/validate_documentation.py index c0603c4d..d687a475 100644 --- a/scripts/validate_documentation.py +++ b/scripts/validate_documentation.py @@ -8,6 +8,7 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[1] +PRODUCT_TECHNICAL_GAP_BASELINE = "docs/product-technical-gap-baseline.md" REQUIRED_FILES = ( "DOCUMENTATION.md", @@ -41,6 +42,7 @@ "docs/adr/0015-autonomous-development-review-and-merge-authority.md", "docs/adr/0016-tdt-chronos-event-intelligence-boundary.md", "docs/product/prd-v0.4-approved.md", + PRODUCT_TECHNICAL_GAP_BASELINE, "docs/roadmaps/2026-08-05-tepp-delivery-roadmap.md", "docs/superpowers/plans/2026-08-05-temporal-event-foundation.md", "docs/research/standards-and-literature.md", @@ -58,6 +60,34 @@ MARKDOWN_LINK = re.compile( r'(?[^)\s]+)(?:\s+"[^"]*")?\)' ) +PROTECTED_MAIN_SHA = re.compile( + r"\*\*Protected-main evidence:\*\*\s*`(?P[0-9a-f]{40})`" +) +SNAPSHOT_STAMP = re.compile( + r"\*\*Snapshot:\*\*\s*(?P\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)" +) +INVENTORY_ROW = re.compile( + r"^\|\s*#(?P\d+)\s*\|\s*`(?P[0-9a-f]{40})`\s*\|\s*" + r"(?Ptrue|false)\s*\|", + re.MULTILINE, +) +OPEN_PR_COUNT = re.compile( + r"\|\s*Open pull requests\s*\|\s*\*\*(?P\d+)\*\*" +) +QUEUED_CHECKS_AS_SHIPPED = re.compile( + r"queued Checks.{0,80}implemented-main", + re.IGNORECASE | re.DOTALL, +) +QUEUED_CHECKS_NEGATED_VERB = re.compile( + r"\b(?Pnever|not|cannot|must\s+not|do\s+not|does\s+not)\b" + r"[a-z\s]{0,12}\b" + r"(?Ppromot\w+|treat\w*|make\w*|mean\w*|constitut\w+|represent\w*)", + re.IGNORECASE, +) +QUEUED_CHECKS_ADVERSATIVE = re.compile( + r"\b(?:but|however|yet|although|though)\b", re.IGNORECASE +) +QUEUED_CHECKS_SENTENCE_BREAK = re.compile(r"[.;!?\n]") ADR_TABLE_ROW = re.compile(r"^\|\s*\[(?P\d{4})\]", re.MULTILINE) ADR_FILE_NAME = re.compile(r"^(?P\d{4})-[a-z0-9-]+\.md$") ADR_DECISION_STATUS = re.compile( @@ -79,6 +109,7 @@ CANONICAL_LINKS = ( "docs/product/prd-v0.4-approved.md", + PRODUCT_TECHNICAL_GAP_BASELINE, "docs/DOCUMENTATION_ASSESSMENT.md", "docs/TRD.md", "ARCHITECTURE.md", @@ -111,18 +142,18 @@ def markdown_files() -> list[Path]: return sorted(path for path in ROOT.rglob("*.md") if ".git" not in path.parts) -def validate_required_files() -> None: +def validate_required_files(root: Path = ROOT) -> None: """Require the approved governance, product, and technical documentation baseline.""" - missing = [path for path in REQUIRED_FILES if not (ROOT / path).is_file()] + missing = [path for path in REQUIRED_FILES if not (root / path).is_file()] if missing: raise AssertionError(f"missing required documentation: {missing}") -def validate_documentation_map() -> None: +def validate_documentation_map(root: Path = ROOT) -> None: """Require cross-cutting canonical documents to be discoverable from the root map.""" - documentation = (ROOT / "DOCUMENTATION.md").read_text(encoding="utf-8") + documentation = (root / "DOCUMENTATION.md").read_text(encoding="utf-8") link_targets = { match.group("target") for match in MARKDOWN_LINK.finditer(documentation) } @@ -133,6 +164,66 @@ def validate_documentation_map() -> None: ) +def _promotion_is_denied(text: str, claim: re.Match[str]) -> bool: + """Return whether the sentence around ``claim`` negates its promotion. + + A sentence denies the claim only when a negation cue directly governs a + promotion verb within that same sentence and no adversative conjunction + separates that pair from the ``implemented-main`` assertion. This accepts + honest wordings such as "does not treat queued Checks as implemented-main" + while refusing sentences where an unrelated negation coexists with an + affirmative maturity claim after "but". + """ + + sentence_start = 0 + for boundary in QUEUED_CHECKS_SENTENCE_BREAK.finditer(text, 0, claim.start()): + sentence_start = boundary.end() + window_end = claim.end() + for cue in QUEUED_CHECKS_NEGATED_VERB.finditer(text, sentence_start, window_end): + if QUEUED_CHECKS_ADVERSATIVE.search(text, cue.end(), window_end) is None: + return True + return False + + +def validate_product_technical_gap_baseline(root: Path = ROOT) -> None: + """Require a dated live gap register that does not promote queued Checks.""" + + path = root / PRODUCT_TECHNICAL_GAP_BASELINE + if not path.is_file(): + raise AssertionError( + f"missing required documentation: ['{PRODUCT_TECHNICAL_GAP_BASELINE}']" + ) + text = path.read_text(encoding="utf-8") + failures: list[str] = [] + if SNAPSHOT_STAMP.search(text) is None: + failures.append("gap baseline lacks a dated UTC snapshot stamp") + if PROTECTED_MAIN_SHA.search(text) is None: + failures.append("gap baseline lacks a 40-character protected-main SHA") + if "Closure evidence" not in text: + failures.append("gap baseline lacks operator-gap closure evidence") + if "Exact current head" not in text: + failures.append("gap baseline lacks an exact-head open-PR inventory") + if any( + not _promotion_is_denied(text, match) + for match in QUEUED_CHECKS_AS_SHIPPED.finditer(text) + ): + failures.append("gap baseline treats queued Checks as implemented-main") + inventory = list(INVENTORY_ROW.finditer(text)) + if not inventory: + failures.append("gap baseline open-PR inventory has no exact-head rows") + count_match = OPEN_PR_COUNT.search(text) + if count_match is None: + failures.append("gap baseline lacks an open pull-request count") + elif count_match.group("count") != str(len(inventory)): + failures.append( + "gap baseline open-PR count " + f"{count_match.group('count')} does not match inventory " + f"{len(inventory)}" + ) + if failures: + raise AssertionError("\n".join(failures)) + + def validate_adr_graph() -> None: """Require every numbered ADR to be indexed and carry unambiguous authority metadata.""" @@ -235,6 +326,7 @@ def main() -> None: validate_required_files() validate_documentation_map() + validate_product_technical_gap_baseline() validate_adr_graph() validate_markdown() validate_workflows() diff --git a/tests/quality/test_product_technical_gap_baseline.py b/tests/quality/test_product_technical_gap_baseline.py new file mode 100644 index 00000000..a6542153 --- /dev/null +++ b/tests/quality/test_product_technical_gap_baseline.py @@ -0,0 +1,237 @@ +"""Contracts for the live product/technical gap baseline.""" + +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from scripts import validate_documentation as docs + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[2] +BASELINE_PATH = docs.PRODUCT_TECHNICAL_GAP_BASELINE +VALID_SHA = "c45be17a9dbce95ef81cee230e9d128abc7160ac" +VALID_HEAD = "a" * 40 + + +def valid_baseline(*, count: int = 1, extra: str = "") -> str: + """Return a structurally valid gap-baseline document.""" + + return ( + "# Product and Technical Gap Baseline\n\n" + "**Snapshot:** 2026-08-23T12:27:12Z\n" + f"**Protected-main evidence:** `{VALID_SHA}`\n\n" + "## Snapshot facts\n\n" + "| Signal | Snapshot evidence | Delivery implication |\n" + "|---|---:|---|\n" + f"| Open pull requests | **{count}** | Queue only. |\n\n" + "## Current open pull-request evidence\n\n" + "| PR | Exact current head | Draft | Base | Title |\n" + "|---:|---|:---:|---|---|\n" + f"| #164 | `{VALID_HEAD}` | false | main | docs |\n\n" + "## Operator-gap register\n\n" + "| ID | Closure evidence |\n" + "|---|---|\n" + "| GAP-015 | Merge after independent review. |\n" + f"{extra}" + ) + + +class ProductTechnicalGapBaselineTests(unittest.TestCase): + """Require the baseline to be mapped, dated, and honest about queued Checks.""" + + def test_baseline_is_required_and_mapped(self) -> None: + """The canonical map and required-file set both name the live register.""" + + self.assertIn(BASELINE_PATH, docs.REQUIRED_FILES) + self.assertIn(BASELINE_PATH, docs.CANONICAL_LINKS) + documentation = (REPOSITORY_ROOT / "DOCUMENTATION.md").read_text( + encoding="utf-8" + ) + self.assertIn(f"]({BASELINE_PATH})", documentation) + + def test_live_repository_baseline_is_structurally_valid(self) -> None: + """The committed register carries a dated SHA-bound inventory.""" + + docs.validate_required_files(REPOSITORY_ROOT) + docs.validate_documentation_map(REPOSITORY_ROOT) + docs.validate_product_technical_gap_baseline(REPOSITORY_ROOT) + + def test_missing_baseline_fails_required_files_and_structure(self) -> None: + """A tree that omits the register fails both required-file and structure checks.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + with self.assertRaisesRegex(AssertionError, BASELINE_PATH): + docs.validate_required_files(root) + with self.assertRaisesRegex(AssertionError, BASELINE_PATH): + docs.validate_product_technical_gap_baseline(root) + + def test_map_without_baseline_link_fails(self) -> None: + """The documentation map must discover the register by markdown link.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + (root / "DOCUMENTATION.md").write_text( + "[PRD](docs/product/prd-v0.4-approved.md)\n", + encoding="utf-8", + ) + with self.assertRaisesRegex(AssertionError, BASELINE_PATH): + docs.validate_documentation_map(root) + + def test_valid_fixture_passes_structure_validator(self) -> None: + """A dated exact-head register with matching count is accepted.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text(valid_baseline(), encoding="utf-8") + docs.validate_product_technical_gap_baseline(root) + + def test_missing_snapshot_sha_closure_or_inventory_fails(self) -> None: + """Structure validation refuses an undated or uninventoried register.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text("# Empty gap register\n", encoding="utf-8") + with self.assertRaisesRegex(AssertionError, "dated UTC snapshot"): + docs.validate_product_technical_gap_baseline(root) + with self.assertRaisesRegex(AssertionError, "protected-main SHA"): + docs.validate_product_technical_gap_baseline(root) + with self.assertRaisesRegex(AssertionError, "closure evidence"): + docs.validate_product_technical_gap_baseline(root) + with self.assertRaisesRegex(AssertionError, "exact-head"): + docs.validate_product_technical_gap_baseline(root) + + def test_inventory_count_mismatch_fails(self) -> None: + """Declared open-PR count must match exact-head inventory rows.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text(valid_baseline(count=94), encoding="utf-8") + with self.assertRaisesRegex(AssertionError, "does not match inventory"): + docs.validate_product_technical_gap_baseline(root) + + def test_queued_checks_as_implemented_main_fails(self) -> None: + """Queued Checks must not be promoted to protected-main maturity.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra="\nqueued Checks on this PR are implemented-main.\n" + ), + encoding="utf-8", + ) + with self.assertRaisesRegex( + AssertionError, "queued Checks as implemented-main" + ): + docs.validate_product_technical_gap_baseline(root) + + def test_negated_queued_checks_wording_is_accepted(self) -> None: + """Correct one-line negation must not be treated as a promotion claim.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra=( + "\nPassing or queued Checks on an open PR never " + "promote that PR to implemented-main.\n" + ) + ), + encoding="utf-8", + ) + docs.validate_product_technical_gap_baseline(root) + + def test_wrapped_queued_checks_promotion_still_fails(self) -> None: + """A wrapped affirmative claim must not evade the promotion guard.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra="\nqueued Checks on this PR are\nimplemented-main.\n" + ), + encoding="utf-8", + ) + with self.assertRaisesRegex( + AssertionError, "queued Checks as implemented-main" + ): + docs.validate_product_technical_gap_baseline(root) + + def test_unrelated_negation_does_not_license_implemented_main(self) -> None: + """A `not` that does not deny promotion must not pass the guard.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra=( + "\nqueued Checks are not required; " + "this PR is implemented-main.\n" + ) + ), + encoding="utf-8", + ) + with self.assertRaisesRegex( + AssertionError, "queued Checks as implemented-main" + ): + docs.validate_product_technical_gap_baseline(root) + + def test_leading_negation_before_queued_checks_is_accepted(self) -> None: + """Negation placed before the phrase still denies promotion honestly.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra=( + "\nThe register does not treat queued Checks " + "as implemented-main.\n" + ) + ), + encoding="utf-8", + ) + docs.validate_product_technical_gap_baseline(root) + + def test_adversative_severed_negation_still_fails(self) -> None: + """An unrelated negated clause cannot license a later maturity claim.""" + + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / BASELINE_PATH + path.parent.mkdir(parents=True) + path.write_text( + valid_baseline( + extra=( + "\nqueued Checks never make noise, but " + "this PR is implemented-main.\n" + ) + ), + encoding="utf-8", + ) + with self.assertRaisesRegex( + AssertionError, "queued Checks as implemented-main" + ): + docs.validate_product_technical_gap_baseline(root) + + +if __name__ == "__main__": # pragma: no cover + unittest.main()