Causal Assumptions and Abstention Boundary
Date: 2026-04-07 Scope: AR-first causal / intervention layer Related doctrine:architecture-doctrine-2026-04-08.md
This note is the repo-grounded boundary for what the current system can honestly claim today. It is not a mathematical proof of causality. It is the operational contract that the code currently approximates.
What The System Assumes
The current intervention stack assumes:- Temporal order matters. Predictions and interventions should be evaluated on point-in-time object state, not future outcomes leaked back into the past.
- Tenant scope is real. Every causal artifact must be interpreted inside one tenant boundary.
- The object graph is the source of state. The ledger and object graph define what the model saw at decision time.
- Learned intervention effects are only trustworthy inside observed support. If the action/object combination is thinly supported, the system should soften or abstain rather than pretend certainty.
- Drift and out-of-distribution signals matter. A learned result that looks off-distribution should not be treated as a clean counterfactual.
Where The Code Enforces This Today
services/ml-sidecar/src/training.py- Probability-model training now requires resolved
decision_epochsrows with frozenfeature_snapshotdata. Legacy rows without point-in-time snapshots are rejected instead of being rebuilt from current object state.
- Probability-model training now requires resolved
services/ml-sidecar/src/server.py- The cached probability-model path, release replay scoring, and drift/distribution baselines now consume normalized decision-epoch examples instead of current
world_objectssnapshots. - The live uplift shadow path now calls the DR-first
/uplift/predict/v2endpoint, and weekly retraining now calls/uplift/train/v2instead of the legacy T-learner endpoints.
- The cached probability-model path, release replay scoring, and drift/distribution baselines now consume normalized decision-epoch examples instead of current
services/ml-sidecar/src/db.py- Intervention training rows now hydrate object state from
world_object_versionsas ofaction_at, and fail closed when no point-in-time version exists.
- Intervention training rows now hydrate object state from
services/ml-sidecar/src/training.py- Intervention-effect models now build features with
action_atas the reference time instead ofobserved_at, which avoids encoding post-action time drift into training features.
- Intervention-effect models now build features with
src/world-model/ensemble.tspredict()now rejects invalid V2 responses, falls back when the sidecar reports drift or out-of-distribution input, and requires an approvedworld_model_releasesrow plus an approved promotion-quality report before it accepts a learned V2 prediction.estimateIntervention()prefers explicit sidecar intervention models only when causal-quality evidence is approved; otherwise it falls back to learned priors or heuristic effects.estimateIntervention()now downgrades toproceed_with_cautionwhen the approved causal support is thin.
src/eval/autonomy-enforcer.ts- Elevated-autonomy promotion now treats observational-only treatment-quality evidence as insufficient authority, even when a legacy treatment report still says
approved/eligible.
- Elevated-autonomy promotion now treats observational-only treatment-quality evidence as insufficient authority, even when a legacy treatment report still says
src/api/world-runtime-routes.ts- Learned-model release gating now treats observational-only treatment-quality evidence as insufficient for release approval during
/v1/world/reestimate.
- Learned-model release gating now treats observational-only treatment-quality evidence as insufficient for release approval during
src/eval/rollout-gates.ts- Rollout-gate evidence snapshots now record whether treatment-quality evidence was observational-only or causal-grade so the audit trail does not hide that distinction.
src/core/uncertainty.ts- The uncertainty profile already marks drift and OOD as abstention-relevant signals.
src/eval/shadow-scorecard.ts- Calibration and shadow-scoring are tracked as evaluation signals, not as a proof of causal identification.
src/eval/evaluation-reports.tstreatment_qualitynow prefers propensity-aware comparisons fromaction_decision_loglinked to resolveddecision_epochs, and stampsdecision_epoch_ope_v1only when that evidence is actually available.- When those logged propensities/outcomes are missing or too weak, the report falls back to observational comparisons but remains
candidate/insufficient_evidenceinstead of granting causal-grade eligibility.
Where The Code Does Not Fully Enforce It
- There is no formal written ignorability, positivity, SUTVA, or consistency proof in the codebase.
- There is no general unmeasured-confounder check such as an E-value or sensitivity analysis gate on the live inference path.
- Support / overlap is not a hard abstention gate everywhere. The current boundary is conservative, but it is still a policy approximation.
- The treatment-quality report path is now OPE-backed when decision-log coverage exists, but it is still weaker than a full DR / refutation-backed evaluation stack.
- Many tenants may still have sparse or missing linked decision-log outcomes, which means the report will stay observational-only and ineligible until that logging surface matures.
- Confidence intervals are only as good as the upstream model and the promotion gates behind it. A valid interval is not the same thing as a valid causal identification strategy.
Current Abstention Boundary
The system currently fails closed or softens when:- the sidecar returns a malformed V2 payload;
- the V2 payload is marked drifted or out-of-distribution;
- the learned model lacks an approved
world_model_releasesrow; - the learned release lacks an approved promotion-quality artifact;
- intervention support is thin enough that the system should only recommend
proceed_with_caution. - the treatment-quality report is observational-only, in which case it cannot promote autonomy or approve learned-model release.
- the treatment-quality report lacks enough linked propensity-weighted evidence, in which case it stays
candidateeven if observational deltas look good.
Practical Reading
The honest public claim today is:Nooterra uses a governed, tenant-scoped world model to rank actions and estimate intervention effects under uncertainty, with fail-closed fallbacks when the learned path is not sufficiently supported.The stronger claim, that the system has fully validated causal identification under all deployment conditions, is not yet warranted by the code.