Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/docs-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- "**/*.json"
- ".github/workflows/**"
- "scripts/validate_documentation.py"
- "tests/quality/test_validate_documentation.py"
push:
branches:
- main
Expand All @@ -15,6 +16,7 @@ on:
- "**/*.json"
- ".github/workflows/**"
- "scripts/validate_documentation.py"
- "tests/quality/test_validate_documentation.py"
workflow_dispatch:

permissions:
Expand Down
6 changes: 3 additions & 3 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ boundaries above remain the target modular MSA architecture.
| `tepp_simulation` | known-truth temporal/event data generation |
| `validation_core` | RMSE, bias, coverage, graph, and Monte Carlo metrics |
| `tepp_api` | versioned DTO, schema, and export contracts |
| `prediction_contradiction` | Allen promotion gate: `before`/`after` stay contradictory; `meets`/`met_by` stay unsupported; coverage is required before unmatched predicted mass may be authorized for promotion |

No crate exposes placeholder production behavior in Task 1. This prevents an
empty façade from becoming a de facto public API before its invariants and tests
exist.
Foundation crates expose only tested contracts. Empty façades are not public
APIs.

## Immutable evidence boundary

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang

### Added

- `prediction_contradiction` promotion gate: `temporal_core` Allen classification refuses `before`/`after` as contradiction and `meets`/`met_by` as unsupported adjacency; `refuse_promotion` and `require_observed_coverage` refuse partial overlap that leaves unmatched predicted mass; `refuse_contradiction_or_adjacency` is the weaker contradiction/adjacency filter only; evidence available after the knowledge cutoff is ineligible. Label agreement is not RMSE recovery (ADR 0002, ADR 0016). Canonical docs name the crate, not a pull-request number, as the landable authority; `scripts/validate_documentation.py` fail-closes on `landable coverage gate is PR #N` including drafts #93, #94, #97, #101, #102, #104, #108, #109, and #111. The hourly queue lock also fail-closes when those drafts are omitted from Keep-unmerged sentences or when naruon live HTTP is pointed away from PR #107.
- `persistence_postgres` backup/restore integrity: restored snapshots stay unusable until tenant, canonical `SHA-256`, knowledge-cutoff eligibility, temporal window order, and append-only triggers revalidate; SQL probes raise `restore integrity failed` (ADR 0013).
- `persistence_postgres` concurrent document-write stress: atomic revise `DO` block that requires exactly one open `system_to` close, SQLSTATE mapping onto `ConcurrentWriteConflict` / `DuplicateDocumentRecord`, and live multi-session insert/revise/append-only proofs. No new migration number.
- `tepp_api` naruon HTTP interchange: versioned `https` POST contracts for analysis-run create and modular export authorization that refuse table-access URLs, review/Copilot credential headers, reserved standard-header redefinition, principal-only export idempotency keys, and lexical inference claims (ADR 0011).
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = [
"crates/tepp_simulation",
"crates/validation_core",
"crates/tepp_api",
"crates/prediction_contradiction",
]
default-members = [
"crates/evidence_core",
Expand All @@ -23,6 +24,7 @@ default-members = [
"crates/tepp_simulation",
"crates/validation_core",
"crates/tepp_api",
"crates/prediction_contradiction",
]

[workspace.package]
Expand Down
2 changes: 1 addition & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ The documentation graph is **design-sufficient** when a reviewer can reconstruct

It is **protected-main-sufficient** only after the canonical documents are integrated on protected `main`, remain semantically current with live code, and their required exact-head documentation/security/review gates pass. An active documentation PR can therefore be design-sufficient while the protected branch remains documentation-insufficient.

At the time of this review, immutable evidence records/exact spans, the Rust workspace quality foundation, and typed six-clock values/uncertain intervals (PR #8) are implemented-main. PR #9 is the active-PR that replays Task 4 Allen interval algebra and bounded path-consistency reasoner work onto that protected-main temporal foundation. Superseded PRs #5 and #6 remain historical lineage only. Event ontology, PostgreSQL persistence, shared-latent topic estimation, GPU kernels, TDT/CHRONOS intelligence, longitudinal ESEM/DSEM, visual analytics, production HTTP services, and deployment assurance remain later accepted-target or deployment-owned work.
At the time of this review, immutable evidence records/exact spans, the Rust workspace quality foundation, typed six-clock values/uncertain intervals (PR #8), Allen interval algebra and bounded path-consistency (PR #9), event ontology/membership, and PostgreSQL persistence through restore-integrity probes are implemented-main. The active-PR coverage gate in `prediction_contradiction` requires observed Allen coverage (`during`, `starts`, `finishes`, or `equals`) before unmatched predicted mass may be authorized for promotion; `refuse_promotion` is that authority and is not a contradiction-only filter. Coverage may authorize promotion; it does not convert a forecast into observed fact. Drafts #93, #94, #97, #101, #102, #104, #108, #109, and #111 are superseded non-landable lineage. Remaining TDT/CHRONOS tasks, shared-latent topic estimation, GPU kernels, longitudinal ESEM/DSEM, visual analytics, production HTTP services, and deployment assurance stay accepted-target or deployment-owned.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ implemented in Rust.

## Current implementation state

This branch establishes the Task 1 Rust workspace and quality-gate foundation.
The ten bounded crates compile independently but intentionally expose no
placeholder production APIs. Domain behavior begins in Task 2 with immutable
evidence identifiers and source records.
This branch keeps the Rust workspace quality foundation and the bounded
foundation crates. Domain crates expose only tested contracts: immutable
evidence, six-clock temporal values, event mentions/instances, relations,
membership, persistence, splits, simulation, validation, API DTOs, and the
predicted-versus-observed promotion gate.

```text
crates/evidence_core
Expand All @@ -22,6 +23,7 @@ crates/corpus_split
crates/tepp_simulation
crates/validation_core
crates/tepp_api
crates/prediction_contradiction
```

## Local verification
Expand Down
20 changes: 20 additions & 0 deletions crates/prediction_contradiction/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "prediction_contradiction"
description = "Predicted intervals stay hypothetical unless later evidence covers them."
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
readme.workspace = true
keywords.workspace = true
categories.workspace = true
publish = false

[dependencies]
temporal_core = { path = "../temporal_core", version = "0.1.0" }

[lints]
workspace = true
82 changes: 82 additions & 0 deletions crates/prediction_contradiction/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! Fail-closed prediction-contradiction errors.

use std::fmt;

/// A fail-closed prediction-contradiction error.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum PredictionContradictionError {
/// Predicted and observed event-time intervals are Allen `before` or `after`.
PredictionContradictsObservation,
/// Predicted and observed intervals are adjacent and do not overlap in their interiors.
PredictionLacksOverlappingSupport,
/// Observed evidence overlaps the prediction but does not cover it.
PredictionNotCoveredByObservation,
/// Observed evidence became available after the analysis knowledge cutoff.
EvidenceAfterCutoff,
/// An interval is not a closed proper Allen input.
InvalidIntervalPayload,
/// An agreement-rate comparison used empty or length-mismatched slices.
AgreementSliceMismatch,
}

impl fmt::Display for PredictionContradictionError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match self {
Self::PredictionContradictsObservation => {
"predicted interval contradicts observed evidence"
}
Self::PredictionLacksOverlappingSupport => {
"predicted interval is adjacent to observation without overlapping support"
}
Self::PredictionNotCoveredByObservation => {
"observed evidence does not cover the predicted interval"
}
Self::EvidenceAfterCutoff => {
"observed evidence is available after the knowledge cutoff"
}
Self::InvalidIntervalPayload => "invalid prediction-contradiction payload",
Self::AgreementSliceMismatch => "agreement slices are empty or length-mismatched",
};
formatter.write_str(message)
}
}

impl std::error::Error for PredictionContradictionError {}

#[cfg(test)]
mod tests {
use super::PredictionContradictionError;

#[test]
fn error_messages_are_stable() {
for (error, message) in [
(
PredictionContradictionError::PredictionContradictsObservation,
"predicted interval contradicts observed evidence",
),
(
PredictionContradictionError::PredictionLacksOverlappingSupport,
"predicted interval is adjacent to observation without overlapping support",
),
(
PredictionContradictionError::PredictionNotCoveredByObservation,
"observed evidence does not cover the predicted interval",
),
(
PredictionContradictionError::EvidenceAfterCutoff,
"observed evidence is available after the knowledge cutoff",
),
(
PredictionContradictionError::InvalidIntervalPayload,
"invalid prediction-contradiction payload",
),
(
PredictionContradictionError::AgreementSliceMismatch,
"agreement slices are empty or length-mismatched",
),
] {
assert_eq!(error.to_string(), message);
}
}
}
Loading
Loading