At 2026-08-18 14:37:22, a decision engine approved a limit increase. Today, exposure is higher, another facility exists, DPD was corrected, identity resolution changed and behavioural PD runs on version 5. None of that proves what the engine knew at 14:37:22.
DPD known then · PD v4≠TODAYmerged identity · three facilities
restated DPD · PD v5
Decision time is the anchor for every layer
Define Td as the exact decision timestamp. Current state is not historical state even when the borrower did nothing: mappings, correction knowledge, reducers and feature logic can all change.
Identity uses the resolution information known by Td. Relationships include only co-borrower, guarantor and facility links valid and known then. Facility state contains drawn, limit, undrawn, arrears, DPD and status under the historical reducer version. Exposure composes only those known facilities and edges.
Known state replays the decision; restated state explains corrected history
A late payment, identity merge or co-borrower correction can change what is now believed economically true. Historical replay must still use the values, relationships and versions that were available to production. Corrected state belongs in a separately labelled comparison.
A feature must have been available—not merely effective
A feature can summarise data through 13:00 but become available only at 14:00. A 13:30 decision cannot consume it. Effective time describes the world; availability time describes the institution’s knowledge.
type PointInTimeFeature<T> = {
value: T;
effectiveAsOf: Date;
availableAsOf: Date;
calculatedAt: Date;
featureVersion: string;
};A latest-value-only feature store cannot reproduce decisions. Historical online and offline retrieval must agree for the same available event set and feature definition:
The decision manifest binds state, versions and outcome
type DecisionManifest = {
decisionId: string;
decisionTime: Date;
partyId: string;
identityResolutionVersion: string;
relationshipStateVersion: string;
facilityStateRefs: string[];
featureSnapshotId: string;
modelVersion: string;
policyVersion: string;
configurationVersion: string;
decisionEngineBuild: string;
outcome: string;
};{
"decisionEngineBuild": "2026.08.18.3",
"identityVersion": "identity-v7",
"customerProjectionVersion": "customer-state-v4",
"featureSetVersion": "behavioural-features-v11",
"modelVersion": "pd-v5.2",
"policyVersion": "limit-strategy-v9"
}Choose immutable payloads, versioned references or a deliberate hybrid
| Pattern | Strength | Cost / condition |
|---|---|---|
| Full input snapshot | Straightforward replay and strong audit evidence | Storage, sensitive-data duplication and schema evolution |
| Reference manifest | Lower duplication and centralised state | Every referenced historical version must remain immutable and queryable |
| Hybrid | Critical scalars plus references to larger state | Requires a clear boundary and referential integrity |
Store Hash(InputPayload) to verify equality, never as a replacement for preserved inputs. Minimise PII through canonical references and controlled encrypted snapshots. Retention follows audit, validation and product obligations; do not delete lineage while decisions can still be challenged.
Historical joins use both valid time and system time
SELECT ...
FROM decisions d
JOIN party_relationship_history r
ON r.party_id = d.party_id
AND r.valid_from <= d.decision_time
AND (r.valid_to IS NULL OR r.valid_to > d.decision_time)
AND r.system_from <= d.decision_time
AND (r.system_to IS NULL OR r.system_to > d.decision_time);Valid time selects the relationship economically applicable at Td; system time prevents later corrections from leaking backward. Dialects differ, but a join to the current customer master is never an equivalent substitute.
For performance, reconstruct from a temporal snapshot plus later available events. The snapshot must declare effective horizon, knowledge horizon and reducer version. A snapshot labelled only “as of date” is ambiguous.
Replay executes the original decision function with the original context
async function replayDecision(
manifest: DecisionManifest
): Promise<DecisionResult> {
const state = await reconstructCustomerKnownState(manifest);
const features = await featureStore.loadSnapshot(
manifest.featureSnapshotId
);
const model = await modelRegistry.load(manifest.modelVersion);
const policy = await policyRegistry.load(manifest.policyVersion);
return runDecision({ state, features, model, policy });
}The sketch omits configuration and runtime wiring for readability. Production replay must preserve deterministic rule order and the strategy graph—not just which rules fired. External bureau or SaaS responses require an immutable response ID, received time and schema version; today’s endpoint cannot recreate yesterday’s response.
Historical replay and counterfactual replay answer different questions
Original known state + features + model + policy. Goal: reproduce the actual outcome.
Change corrected state, model, policy or freshness. Goal: ask what would have happened.
Change one component at a time where possible. Hold state, features and policy constant to isolate a model change; hold model and policy constant to quantify a late-data incident.
State, feature, model and policy effects can interact; do not pretend their attribution is always additively separable. Preserve the actual decision as immutable evidence.
Corrected historical data can create hindsight leakage
| Leakage | Mechanism | Control |
|---|---|---|
| Payment correction | Warehouse backdates a later-known payment to economic date | Filter by availability time |
| Identity leakage | Later merge consolidates old exposure | Use identity mapping known at scoring |
| Relationship leakage | Later co-borrower edge changes historical obligations | Use bitemporal relationship state |
| Policy leakage | Today’s strategy reclassifies old decisions | Retain original policy and label counterfactuals |
| Training-serving skew | Code, freshness, nulls or mappings differ online/offline | Compare identical state and feature versions |
Engineering explainability traces the input state, not only the model score
type DecisionTrace = {
decisionId: string;
inputManifest: DecisionManifest;
modelScore?: number;
ruleHits: string[];
finalOutcome: string;
};A feature-importance explanation is incomplete if the value itself cannot be traced to its source, time and definition. Record rule hits without exposing sensitive rule text, plus the deterministic strategy version and evaluation sequence.
Freshness and fallback are part of the historical policy path
{
"exposureEffectiveAsOf": "2026-08-18T14:35:00Z",
"dpdEffectiveAsOf": "2026-08-18T14:30:00Z",
"behaviouralPdCalculatedAt": "2026-08-18T06:00:00Z"
}If an input is stale, retain the stale condition, the fallback or review branch used and that fallback’s configuration version. Hiding staleness makes a decision look reproducible while omitting why the engine followed a different path.
Preserve only runtime details that can change output
Exact replay may require the engine build, model artefact, policy graph, feature-definition code, schemas and material dependency versions. For a non-deterministic component, preserve the seed, model snapshot and input/output record; deterministic core credit logic remains preferable where appropriate.
Current-state caches can serve live traffic, but an expired cache cannot be the historical system. Use durable temporal stores, indexed snapshots and tail replay. Optimised replay and full event reconstruction must agree.
A golden decision fixture makes reproducibility executable
| Layer | Fixture state |
|---|---|
| Party | P1 under identity resolution v7 |
| Facilities | F1 term loan; F2 revolving line |
| Events | Known payments and limit changes through T |
| Relationships | P1 primary borrower under relationship v4 |
| Features | Immutable behavioural feature snapshot v11 |
| Execution | PD model v5.2; limit policy v9; engine build 2026.08.18.3 |
| Expected | Exact customer inputs, score, rule path and approved limit outcome |
The fixture is broader than a single event stream: it fixes identity, relationships, state, features and execution versions together. A controlled golden portfolio should also cover a joint borrower, late payment, identity correction, stale feature and fallback path.
Test inputs and outcome—matching decisions can hide compensating bugs
| Test | Expected proof |
|---|---|
| Replay equality | Replayed deterministic outcome equals stored outcome |
| State equality | Every critical reconstructed input equals the stored snapshot or hash |
| Identity version | Using current mapping creates a visible mismatch |
| Late payment | Known replay stays fixed; restated counterfactual may change |
| Relationship correction | Later co-borrower never enters original replay |
| Feature availability | Corrected offline feature is rejected when unavailable at T |
| Policy version | Original policy reproduces; new policy is labelled counterfactual |
| Build version | Engine-code changes remain distinguishable from model changes |
| Missing input | No silent substitution with today’s value |
| Replay implementation | Snapshot+tail equals full event reconstruction |
Classify legacy evidence as exact, reconstructed with assumptions or unreproducible. Never fake precision when lineage is incomplete. Run fixed replay cases in CI after feature, state-engine, identity and policy-engine changes; only reviewed differences pass.
Reproducibility is a production control, not a one-off audit
No universal thresholds apply. A replay diff should show decision ID, stored and replayed outcomes, changed inputs, changed versions and reason. If a previously reproducible sample fails after an infrastructure release, investigate before trusting new historical analysis.
The Entimema architecture turns historical decisions into reproducible evidence
- Anchor decision time
- Resolve identity at T
- Resolve relationships at T
- Reconstruct facility state
- Derive exposure and DPD
- Load available features
- Load execution versions
- Execute
- Compare stored decision
- Explain differences
A Decision Replay & Lineage Agent can assemble evidence without rewriting history
A controlled agent can reconstruct historical customer state, resolve identity and relationship versions, retrieve known financial state and exact feature snapshots, identify model/policy/configuration versions, replay decisions, compare known and restated outcomes, detect hindsight leakage and surface missing lineage.
Decision Automation
Version decision state, strategies, fallbacks and rule paths.
Credit Risk
Financial Data
Preserve bitemporal identity, relationships, events and feature lineage.
Continue with Handling Joint Borrowers and Connected Exposures, Building a Golden Customer Record, Why Customer ID Is Not Enough, Customer, Facility, Account and Exposure, Event Time vs Processing Time vs Posting Time, Building a Reliable DPD Engine, The Single Customer View Is Usually a Fiction and Credit Decision Engine Architecture. A time-respecting feature store, event-driven risk architecture and model/policy replay remain future research directions—not fabricated routes.