diff --git a/.codegraph/.gitignore b/.codegraph/.gitignore new file mode 100644 index 00000000..d20c0fe4 --- /dev/null +++ b/.codegraph/.gitignore @@ -0,0 +1,5 @@ +# CodeGraph data files — local to each machine, not for committing. +# Ignore everything in .codegraph/ except this file itself, so transient +# files (the database, daemon.pid, sockets, logs) never show up in git. +* +!.gitignore diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ffe514db..6dbf2cf6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -53,7 +53,7 @@ boundaries above remain the target modular MSA architecture. |---|---| | `evidence_core` | immutable evidence domain primitives | | `temporal_core` | typed clocks, intervals, and temporal reasoning | -| `event_core` | event instances, mentions, roles, and provenance | +| `event_core` | event instances, mentions, roles, provenance, and CHRONOS occurrence-prediction calibration | | `relation_graph` | typed relations and forward-transition validation | | `membership_core` | time-varying cross-classified multiple membership | | `persistence_postgres` | PostgreSQL repositories and migrations | diff --git a/CHANGELOG.md b/CHANGELOG.md index 36c2e8dd..ee73e79f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang ### Added +- `event_core` CHRONOS occurrence-prediction calibration: forecasts stay hypothetical, refuse promotion to event instances, and recover a computed Brier score against later-observed occurrence truth, with empty or mismatched streams failing closed. - `tepp_api` naruon live loopback HTTP/1.1 listener: `serve_one` installs a read/write deadline, requires a loopback `Host`, refuses `Transfer-Encoding` and NIM/proxy credential headers, parses `knowledge_cutoff` as RFC 3339 and refuses a future cutoff, keys analysis-run idempotency by tenant plus key, and proves both analysis-run and export POSTs over a real `TcpStream`. Not a production TLS/`$PORT` service (ADR 0011). - `tepp_api` adaptive orchestration router (ADR 0010): versioned `direct`/`verify`/`committee`/`conductor`/`abstain` selection from CPU `f64` risk, ambiguity, evidence, and token-budget inputs; recorded stages, recursion, decomposition, access lists, and role-specific reasoning effort; fail-closed document-controlled policy/access/credentials; LLM plans remain proposals under deterministic statistical authority; comparable-budget ablation requires a direct baseline; credential-free contextual-orchestrator binding. Live NIM HTTP remains accepted-target. - `tepp_api` purpose-bound provider-payload minimization: time-bounded `PurposeGrant` evaluation, fail-closed expired/not-yet-valid/inverted/cross-tenant/impossible-calendar denial, semantic UTC calendar validation, refusal to copy identity mappings into model-provider payloads or ordinary logs, preservation of opaque analytical identifiers and membership roles (no blanket PII mask), a separately authorized scientific re-identification path, and an internally bound FIPS 180-4 SHA-256 audit digest appended through `ReidentificationAuditSink` before disclosure. diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 3f094947..7b1dea83 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -33,6 +33,7 @@ TEPP's approved PRD v0.4 and implementation plan are the primary product baselin | Hourly NIM product-development operations | [`docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md`](docs/operations/HOURLY_NIM_PRODUCT_DEVELOPMENT.md) | | Actions workflow fleet audit | [`docs/operations/ACTIONS_WORKFLOW_FLEET.md`](docs/operations/ACTIONS_WORKFLOW_FLEET.md) | | Actions fleet research doctoring | [`docs/research/actions-workflow-fleet.md`](docs/research/actions-workflow-fleet.md) | +| CHRONOS prediction-calibration doctoring | [`docs/research/chronos-prediction-calibration.md`](docs/research/chronos-prediction-calibration.md) | | Retention/deletion/legal-hold doctoring | [`docs/research/retention-deletion-legal-hold.md`](docs/research/retention-deletion-legal-hold.md) | | Provider-payload minimization doctoring | [`docs/research/provider-payload-minimization.md`](docs/research/provider-payload-minimization.md) | | Adaptive orchestration router doctoring | [`docs/research/adaptive-orchestration-router.md`](docs/research/adaptive-orchestration-router.md) | diff --git a/crates/event_core/src/error.rs b/crates/event_core/src/error.rs index 6c795fef..8bdc9eb1 100644 --- a/crates/event_core/src/error.rs +++ b/crates/event_core/src/error.rs @@ -20,6 +20,10 @@ pub enum EventError { UnsupportedWireVersion, /// An unknown event-role name was supplied. UnknownEventRole, + /// A CHRONOS occurrence prediction was treated as an event instance. + PredictionIsNotEventInstance, + /// An unknown occurrence-truth label was supplied. + UnknownOccurrenceTruth, } impl fmt::Display for EventError { @@ -32,6 +36,8 @@ impl fmt::Display for EventError { Self::InvalidWirePayload => "invalid event wire payload", Self::UnsupportedWireVersion => "unsupported event wire version", Self::UnknownEventRole => "unknown event role", + Self::PredictionIsNotEventInstance => "CHRONOS prediction is not an event instance", + Self::UnknownOccurrenceTruth => "unknown occurrence truth label", }; formatter.write_str(message) } @@ -65,6 +71,14 @@ mod tests { "unsupported event wire version", ), (EventError::UnknownEventRole, "unknown event role"), + ( + EventError::PredictionIsNotEventInstance, + "CHRONOS prediction is not an event instance", + ), + ( + EventError::UnknownOccurrenceTruth, + "unknown occurrence truth label", + ), ] { assert_eq!(error.to_string(), message); } diff --git a/crates/event_core/src/lib.rs b/crates/event_core/src/lib.rs index 25fd1022..b392b0e5 100644 --- a/crates/event_core/src/lib.rs +++ b/crates/event_core/src/lib.rs @@ -4,13 +4,15 @@ //! //! TEPP separates **fallible event mentions** grounded in evidence from //! **versioned event instances** used for temporal state, multilevel membership, -//! and scientific estimation. Mentions never silently become instances. +//! and scientific estimation. Mentions and CHRONOS occurrence forecasts never +//! silently become instances. mod confidence; mod error; mod identifier; mod instance; mod mention; +mod prediction; mod registry; mod role; @@ -30,6 +32,16 @@ pub use instance::EventInstance; pub use instance::refuse_mention_as_instance; /// Fallible textual event mention. pub use mention::EventMention; +/// One CHRONOS occurrence forecast that remains hypothetical. +pub use prediction::ChronosOccurrenceForecast; +/// Opaque CHRONOS occurrence-prediction identity. +pub use prediction::ChronosPredictionId; +/// Later-observed occurrence truth for a CHRONOS forecast. +pub use prediction::OccurrenceTruth; +/// Mean squared error of CHRONOS occurrence forecasts against later truth. +pub use prediction::chronos_prediction_brier_score; +/// Explicit refusal to treat a CHRONOS prediction as an event instance. +pub use prediction::refuse_prediction_as_instance; /// In-memory registry separating mentions from instances. pub use registry::EventRegistry; /// Typed event role kind. diff --git a/crates/event_core/src/prediction.rs b/crates/event_core/src/prediction.rs new file mode 100644 index 00000000..d40191aa --- /dev/null +++ b/crates/event_core/src/prediction.rs @@ -0,0 +1,207 @@ +//! CHRONOS occurrence forecasts stay hypothetical until later evidence. + +use crate::{EventConfidence, EventError, EventInstanceId}; + +/// Opaque CHRONOS occurrence-prediction identity. +/// +/// A forecast is hypothesized future or schema-completion evidence. It is +/// never a promoted event instance. +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ChronosPredictionId(u32); + +impl ChronosPredictionId { + /// Reconstruct a prediction identity from a raw fixture or estimator label. + #[must_use] + pub const fn from_raw(raw: u32) -> Self { + Self(raw) + } + + /// Return the raw prediction label. + #[must_use] + pub const fn raw(self) -> u32 { + self.0 + } +} + +/// Later-observed occurrence truth for a CHRONOS forecast. +/// +/// Truth is recovered from later evidence. It does not rewrite the forecast +/// into an event instance. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum OccurrenceTruth { + /// Later evidence established that the predicted event occurred. + Occurred, + /// Later evidence established that the predicted event did not occur. + DidNotOccur, +} + +impl OccurrenceTruth { + /// Return the stable wire label name. + #[must_use] + pub const fn wire_name(self) -> &'static str { + match self { + Self::Occurred => "occurred", + Self::DidNotOccur => "did_not_occur", + } + } + + /// Parse a stable wire occurrence-truth label. + /// + /// # Errors + /// + /// Returns [`EventError::UnknownOccurrenceTruth`] for unrecognized names. + pub fn from_wire_name(name: &str) -> Result { + match name { + "occurred" => Ok(Self::Occurred), + "did_not_occur" => Ok(Self::DidNotOccur), + _ => Err(EventError::UnknownOccurrenceTruth), + } + } + + /// Return whether later evidence established occurrence. + #[must_use] + pub const fn occurred(self) -> bool { + matches!(self, Self::Occurred) + } + + /// Return the binary probability target used for Brier scoring. + /// + /// Occurred truth is `1.0`; non-occurrence is `0.0`. + #[must_use] + pub const fn as_probability_target(self) -> f64 { + match self { + Self::Occurred => 1.0, + Self::DidNotOccur => 0.0, + } + } +} + +/// One CHRONOS occurrence forecast that remains hypothetical. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct ChronosOccurrenceForecast { + prediction_id: ChronosPredictionId, + probability: EventConfidence, +} + +impl ChronosOccurrenceForecast { + /// Bind a prediction identity to an occurrence probability. + #[must_use] + pub const fn new(prediction_id: ChronosPredictionId, probability: EventConfidence) -> Self { + Self { + prediction_id, + probability, + } + } + + /// Return the prediction identity. + #[must_use] + pub const fn prediction_id(self) -> ChronosPredictionId { + self.prediction_id + } + + /// Return the hypothesized occurrence probability. + #[must_use] + pub const fn probability(self) -> EventConfidence { + self.probability + } +} + +/// Explicit refusal to treat a CHRONOS occurrence prediction as an event instance. +/// +/// # Errors +/// +/// Always returns [`EventError::PredictionIsNotEventInstance`]. +pub fn refuse_prediction_as_instance( + _prediction: ChronosPredictionId, +) -> Result { + Err(EventError::PredictionIsNotEventInstance) +} + +/// Mean squared error of CHRONOS occurrence probabilities against later truth. +/// +/// # Errors +/// +/// Returns [`EventError::InvalidWirePayload`] when the slices are empty or +/// have unequal length. +pub fn chronos_prediction_brier_score( + forecasts: &[ChronosOccurrenceForecast], + outcomes: &[OccurrenceTruth], +) -> Result { + if forecasts.is_empty() || forecasts.len() != outcomes.len() { + return Err(EventError::InvalidWirePayload); + } + let mut square_sum = 0.0_f64; + for (forecast, outcome) in forecasts.iter().zip(outcomes) { + let residual = forecast.probability().value() - outcome.as_probability_target(); + square_sum += residual * residual; + } + mean_square(square_sum, forecasts.len()) +} + +fn mean_square(square_sum: f64, count: usize) -> Result { + let n = u32::try_from(count).map_err(|_| EventError::InvalidWirePayload)?; + if n == 0 { + return Err(EventError::InvalidWirePayload); + } + Ok(square_sum / f64::from(n)) +} + +#[cfg(test)] +mod tests { + use super::{ + ChronosOccurrenceForecast, ChronosPredictionId, OccurrenceTruth, + chronos_prediction_brier_score, refuse_prediction_as_instance, + }; + use crate::{EventConfidence, EventError}; + + #[test] + fn prediction_helpers_cover_local_branches() { + let prediction = ChronosPredictionId::from_raw(9); + assert_eq!(prediction.raw(), 9); + assert_eq!( + refuse_prediction_as_instance(prediction), + Err(EventError::PredictionIsNotEventInstance) + ); + assert_eq!(OccurrenceTruth::Occurred.wire_name(), "occurred"); + assert_eq!(OccurrenceTruth::DidNotOccur.wire_name(), "did_not_occur"); + assert_eq!( + OccurrenceTruth::from_wire_name("occurred").expect("parse"), + OccurrenceTruth::Occurred + ); + assert_eq!( + OccurrenceTruth::from_wire_name("did_not_occur").expect("parse"), + OccurrenceTruth::DidNotOccur + ); + assert_eq!( + OccurrenceTruth::from_wire_name("maybe"), + Err(EventError::UnknownOccurrenceTruth) + ); + assert!(OccurrenceTruth::Occurred.occurred()); + assert!(!OccurrenceTruth::DidNotOccur.occurred()); + assert!((OccurrenceTruth::Occurred.as_probability_target() - 1.0).abs() < f64::EPSILON); + assert!((OccurrenceTruth::DidNotOccur.as_probability_target() - 0.0).abs() < f64::EPSILON); + + let forecast = ChronosOccurrenceForecast::new( + prediction, + EventConfidence::new(0.25).expect("probability"), + ); + assert_eq!(forecast.prediction_id(), prediction); + assert!((forecast.probability().value() - 0.25).abs() < f64::EPSILON); + let miss = chronos_prediction_brier_score(&[forecast], &[OccurrenceTruth::Occurred]) + .expect("miss"); + assert!((miss - 0.5625).abs() < 1e-15); + assert_eq!( + chronos_prediction_brier_score(&[], &[OccurrenceTruth::Occurred]), + Err(EventError::InvalidWirePayload) + ); + assert_eq!( + super::mean_square(0.0, 0), + Err(EventError::InvalidWirePayload) + ); + assert_eq!( + super::mean_square(1.0, usize::MAX), + Err(EventError::InvalidWirePayload) + ); + assert!((super::mean_square(1.0, 2).expect("half") - 0.5).abs() < f64::EPSILON); + } +} diff --git a/crates/event_core/tests/prediction_calibration_contract.rs b/crates/event_core/tests/prediction_calibration_contract.rs new file mode 100644 index 00000000..fde98e1c --- /dev/null +++ b/crates/event_core/tests/prediction_calibration_contract.rs @@ -0,0 +1,59 @@ +//! CHRONOS occurrence forecasts stay hypothetical and recover Brier scores. + +use event_core::{ + ChronosOccurrenceForecast, ChronosPredictionId, EventConfidence, EventError, OccurrenceTruth, + chronos_prediction_brier_score, refuse_prediction_as_instance, +}; + +fn forecast(raw: u32, probability: f64) -> ChronosOccurrenceForecast { + ChronosOccurrenceForecast::new( + ChronosPredictionId::from_raw(raw), + EventConfidence::new(probability).expect("probability"), + ) +} + +#[test] +fn chronos_prediction_cannot_be_cast_to_an_instance() { + let prediction = ChronosPredictionId::from_raw(7); + assert_eq!( + refuse_prediction_as_instance(prediction), + Err(EventError::PredictionIsNotEventInstance) + ); +} + +#[test] +fn perfect_occurrence_forecasts_recover_zero_brier() { + let forecasts = [forecast(1, 1.0), forecast(2, 0.0), forecast(3, 1.0)]; + let outcomes = [ + OccurrenceTruth::Occurred, + OccurrenceTruth::DidNotOccur, + OccurrenceTruth::Occurred, + ]; + let score = chronos_prediction_brier_score(&forecasts, &outcomes).expect("brier"); + assert!(score.abs() < 1e-15, "perfect Brier {score}"); +} + +#[test] +fn calibrated_forecasts_beat_overconfident_always_occur_and_mismatches_fail_closed() { + let calibrated = [forecast(1, 0.8), forecast(2, 0.2), forecast(3, 0.7)]; + let overconfident = [forecast(1, 1.0), forecast(2, 1.0), forecast(3, 1.0)]; + let outcomes = [ + OccurrenceTruth::Occurred, + OccurrenceTruth::DidNotOccur, + OccurrenceTruth::Occurred, + ]; + let calibrated_brier = chronos_prediction_brier_score(&calibrated, &outcomes).expect("cal"); + let naive_brier = chronos_prediction_brier_score(&overconfident, &outcomes).expect("naive"); + assert!( + calibrated_brier < naive_brier, + "calibrated Brier {calibrated_brier} must be below always-occur Brier {naive_brier}" + ); + assert_eq!( + chronos_prediction_brier_score(&calibrated, &[OccurrenceTruth::Occurred]), + Err(EventError::InvalidWirePayload) + ); + assert_eq!( + chronos_prediction_brier_score(&[], &[]), + Err(EventError::InvalidWirePayload) + ); +} diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index a3e674cf..a6d8721a 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -1,7 +1,7 @@ # TEPP Requirements, Research, and Evidence Traceability **Status:** Accepted cross-cutting traceability baseline -**Last reviewed:** 2026-08-13 +**Last reviewed:** 2026-08-20 The full APA 7th standards/literature register remains `docs/research/standards-and-literature.md`. This matrix links durable requirements to their owning decisions and implementation/evidence maturity without duplicating the bibliography. @@ -30,7 +30,7 @@ The full APA 7th standards/literature register remains `docs/research/standards- | compositional topic correlation / stable clustering | ADR 0005/0012; research | future `network_analysis` | accepted-target | | posterior ESEM / longitudinal invariance / DSEM | ADR 0005 | future `psychometric_core` | accepted-target | | CPU bounded multithreading + GPU/VRAM streaming/parity | ADR 0001/0006 | future `compute_backend` | accepted-target | -| TDT detection/tracking vs CHRONOS schema/prediction/temporal consistency | ADR 0016; PRD/research | future `event_intelligence` | accepted-target | +| TDT detection/tracking vs CHRONOS schema/prediction/temporal consistency | ADR 0016; PRD/research | `event_core` occurrence-prediction Brier calibration on the active PR; remaining detection/schema/temporal-consistency stack future | active-PR | | evidence-bounded LLM interpretation | ADR 0010/0012; PRD | `tepp_api` router plus future `interpretation_gateway` | partial | | adaptive direct/verify/committee/conductor test-time compute | ADR 0010; `docs/LLM_ORCHESTRATION.md` | `tepp_api::route_orchestration` + ablation record on the active PR; live contextual-orchestrator execution remaining | partial | | purpose-bound PII handling without blanket masking | ADR 0009; `docs/PRIVACY_DATA_GOVERNANCE.md` | `tepp_api` export authorization plus provider-payload minimization / elevated re-identification implemented-main; persistence retention/deletion remaining | partial | diff --git a/docs/adr/0011-standalone-modular-msa-boundary.md b/docs/adr/0011-standalone-modular-msa-boundary.md index d545ee23..04181fb3 100644 --- a/docs/adr/0011-standalone-modular-msa-boundary.md +++ b/docs/adr/0011-standalone-modular-msa-boundary.md @@ -1,7 +1,7 @@ # ADR 0011 — Standalone operation and modular CWL MSA boundary **Decision status:** Accepted -**Implementation maturity:** partial — Rust crates are independently usable; naruon HTTP interchange and loopback live listener (`POST /v1/analysis-runs` and `/v1/exports`, fail-closed table-access, NIM/proxy headers, RFC 3339 cutoff, stream deadline) are on the active PR (not implemented-main); production TLS/`$PORT` and remaining persistence integrations remain accepted-target +**Implementation maturity:** partial — Rust crates are independently usable; naruon HTTP interchange and loopback live listener (`POST /v1/analysis-runs` and `/v1/exports`, fail-closed table-access, NIM/proxy headers, RFC 3339 cutoff, stream deadline) are on the active PR (not implemented-main); production TLS/`$PORT` and remaining persistence integrations remain accepted-target **Date:** 2026-08-10 **Supersedes:** The broad cross-service ownership wording in ADR 0001. ADR 0001 remains authoritative for Rust-first numerical architecture. diff --git a/docs/adr/0016-tdt-chronos-event-intelligence-boundary.md b/docs/adr/0016-tdt-chronos-event-intelligence-boundary.md index b85ee0b4..d874fbf6 100644 --- a/docs/adr/0016-tdt-chronos-event-intelligence-boundary.md +++ b/docs/adr/0016-tdt-chronos-event-intelligence-boundary.md @@ -1,7 +1,7 @@ # ADR 0016 — TDT, CHRONOS, and Event Ontology intelligence boundary **Decision status:** Accepted -**Implementation maturity:** accepted-target +**Implementation maturity:** active-PR — `event_core` scores CHRONOS occurrence forecasts with a Brier rule and refuses to promote them as instances; remaining TDT detection, schema extraction, and temporal-consistency reasoning remain accepted-target **Date:** 2026-08-12 **Supersedes:** None; complements ADR 0002 temporal semantics and ADR 0003 event ontology/membership. diff --git a/docs/adr/README.md b/docs/adr/README.md index 258eb7f3..081fa8db 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -21,7 +21,7 @@ Read [`ADR_POLICY.md`](ADR_POLICY.md) first. **Decision status and implementatio | [0013](0013-bitemporal-persistence-reproducibility-and-split-authority.md) | Bitemporal persistence, reproducibility manifests, and relation-aware split authority | Accepted | partial | Owns PostgreSQL adapter semantics, immutable run/split manifests, leakage-safe partitions, and recovery identity; optional `live-sqlx` `PgPool`, live PG CI, tenant RLS, and `0006` membership implemented-main; `0007` retention/deletion/legal-hold on the active PR; remaining physical ERD/backup accepted-target. | | [0014](0014-scientific-claim-promotion-and-release-evidence.md) | Scientific claim promotion and release evidence authority | Accepted | partial | Separates design, implementation, scientific/product claim, and release authority; repository SBOM/provenance generator implemented, full release bundle remaining. | | [0015](0015-autonomous-development-review-and-merge-authority.md) | Autonomous development, review, and merge authority separation | Accepted | active-PR | Separates model proposal, deterministic verification, publication, independent review, and merge/release authority. | -| [0016](0016-tdt-chronos-event-intelligence-boundary.md) | TDT, CHRONOS, and Event Ontology intelligence boundary | Accepted | accepted-target | Separates observed evidence, detection/tracking, prediction/schema inference, temporal consistency, and promoted transition authority. | +| [0016](0016-tdt-chronos-event-intelligence-boundary.md) | TDT, CHRONOS, and Event Ontology intelligence boundary | Accepted | active-PR | Occurrence-prediction Brier calibration and fail-closed instance refusal on the active PR; remaining TDT detection/schema/temporal-consistency stack is accepted-target. | ## Decision ownership summary diff --git a/docs/connectors/naruon-artifact-consumer.md b/docs/connectors/naruon-artifact-consumer.md index 2e4f4d6c..5fe0424c 100644 --- a/docs/connectors/naruon-artifact-consumer.md +++ b/docs/connectors/naruon-artifact-consumer.md @@ -1,6 +1,6 @@ # naruon modular consumer contract for TEPP artifacts -**Status:** Partial — versioned DTO, HTTP interchange, and loopback live listener on the active PR; production TLS/`$PORT` remaining +**Status:** Partial — versioned DTO, HTTP interchange, and loopback live listener on the active PR; production TLS/`$PORT` remaining **Last reviewed:** 2026-08-16 ## Boundary diff --git a/docs/research/chronos-prediction-calibration.md b/docs/research/chronos-prediction-calibration.md new file mode 100644 index 00000000..ca0a7662 --- /dev/null +++ b/docs/research/chronos-prediction-calibration.md @@ -0,0 +1,30 @@ +# CHRONOS occurrence-prediction calibration + +## Scope + +This note doctors the `event_core` contract for CHRONOS-style occurrence forecasts: + +1. a forecast is hypothesized future or schema-completion evidence, not a promoted event instance; +2. `chronos_prediction_brier_score` is the mean squared error of occurrence probabilities against later-observed binary truth; +3. empty or length-mismatched streams fail closed. + +No database migration is allocated. Mention-confidence scoring, TDT detection, schema-slot extraction, and temporal-consistency reasoning remain separate slices. + +## Authoritative sources + +Anagnostopoulos, E., Batsakis, S., & Petrakis, E. G. M. (2013). CHRONOS: A reasoning engine for qualitative temporal information in OWL. *Procedia Computer Science, 22*, 70–77. https://doi.org/10.1016/j.procs.2013.09.082 + +Brier, G. W. (1950). Verification of forecasts expressed in terms of probability. *Monthly Weather Review, 78*(1), 1–3. https://doi.org/10.1175/1520-0493(1950)078<0001:VOFEIT>2.0.CO;2 + +Gneiting, T., & Raftery, A. E. (2007). Strictly proper scoring rules, prediction, and estimation. *Journal of the American Statistical Association, 102*(477), 359–378. https://doi.org/10.1198/016214506000001437 + +## Application + +CHRONOS-style reasoning may propose next-event or schema-completion candidates (Anagnostopoulos et al., 2013). ADR 0016 keeps those candidates hypothetical until later evidence supports them. Brier (1950) defines the mean squared error of a probability forecast, and Gneiting and Raftery (2007) treat that score as strictly proper, so a forecast that is certain when the event later occurs and impossible when it does not is uniquely optimal. TEPP therefore scores CHRONOS occurrence probabilities against later-observed truth and refuses to cast a prediction as an event instance (Brier, 1950; Gneiting & Raftery, 2007). + +## Verification + +- forecasts `(1,0,1)` against outcomes `(occurred, did_not_occur, occurred)` recover Brier `0`; +- calibrated probabilities beat an always-occur predictor on mixed later truth; +- empty and mismatched streams return `InvalidWirePayload`; +- `refuse_prediction_as_instance` always returns `PredictionIsNotEventInstance`. diff --git a/docs/research/standards-and-literature.md b/docs/research/standards-and-literature.md index 28e62d5c..e6416ce8 100644 --- a/docs/research/standards-and-literature.md +++ b/docs/research/standards-and-literature.md @@ -66,7 +66,11 @@ Allan, J. (Ed.). (2002). *Topic detection and tracking: Event-based information Anagnostopoulos, E., Batsakis, S., & Petrakis, E. G. M. (2013). CHRONOS: A reasoning engine for qualitative temporal information in OWL. *Procedia Computer Science, 22*, 70–77. https://doi.org/10.1016/j.procs.2013.09.082 -TEPP uses interval and partial-order reasoning, bitemporal availability, leakage-safe cutoffs, TDT segmentation/link/detection/first-story/tracking tasks, and separate neural/symbolic event-schema and temporal-consistency layers. +Brier, G. W. (1950). Verification of forecasts expressed in terms of probability. *Monthly Weather Review, 78*(1), 1–3. https://doi.org/10.1175/1520-0493(1950)078<0001:VOFEIT>2.0.CO;2 + +Gneiting, T., & Raftery, A. E. (2007). Strictly proper scoring rules, prediction, and estimation. *Journal of the American Statistical Association, 102*(477), 359–378. https://doi.org/10.1198/016214506000001437 + +TEPP uses interval and partial-order reasoning, bitemporal availability, leakage-safe cutoffs, TDT segmentation/link/detection/first-story/tracking tasks, and separate neural/symbolic event-schema and temporal-consistency layers. CHRONOS occurrence forecasts remain hypothetical and are scored with the Brier mean squared error against later-observed truth (Brier, 1950; Gneiting & Raftery, 2007). ## Unicode, language tags, and multilingual structure diff --git a/docs/validation/temporal-event-foundation.md b/docs/validation/temporal-event-foundation.md index aae1a06e..c9f5ea3b 100644 --- a/docs/validation/temporal-event-foundation.md +++ b/docs/validation/temporal-event-foundation.md @@ -15,7 +15,8 @@ This report tracks exact-head scientific and engineering evidence required befor | Immutable evidence + spans | `evidence_core` | implemented-main | — | unit + wire + coverage | Task 2 | | Six-clock temporal | `temporal_core` | implemented-main | — | unit + wire | Task 3 / PR #8 | | Allen path-consistency | `temporal_core` | implemented-main | — | unit + budget tests | Task 4 / PR #9 | -| Event mention/instance | `event_core` | partial | — | unit + fail-closed promotion | Task 5 / PR #13 | +| Event mention/instance | `event_core` | partial | CHRONOS prediction calibration | unit + fail-closed promotion | Task 5 / PR #13 | +| CHRONOS occurrence-prediction calibration | `event_core` | accepted-target | active PR | Brier vs later-observed truth; refuse prediction-as-instance | ADR 0016; `docs/research/chronos-prediction-calibration.md` | | Multiple membership | `membership_core` | partial | — | unit + ESS weights | Task 7 / PR #12 + #25 | | Forward transition DAG | `relation_graph` | implemented-main | — | unit + cycle rejection | Task 6 / PR #14 | | Bitemporal persistence + live SQL port | `persistence_postgres` | partial | backup/restore integrity | migration contracts + recording transport + optional PgPool + live CI + tenant RLS + `0005`/`0006` + event relation/mention/instance + source-artifact + audit-event + concurrent-write (#37–#43 implemented-main) + restore integrity probes (active PR) | Task 8 / PR #16 + #23 + #26 + #27 + #29 + #30–#43 + restore integrity |