Time Impact Analysis (TIA) — prospective fragnet insertion
into a pre-impact baseline schedule. Supports two modes.
**Single-base mode** (legacy): supply ``baseline_xer_path`` or
``baseline_xer_content``. All fragnets are inserted into the
same shared baseline XER and impact is measured against that
shared baseline. The result carries a
``single_base_disclosure`` warning explaining this is an AACE
29R-03 §3.7 simplification — acceptable when all events share
a single baseline window, but not strict MIP 3.7 Multiple
Base.
**Multi-base mode** (AACE 29R-03 MIP 3.7 Multiple Base):
supply ``per_event_bases`` — a dict keyed by each fragnet's
``id``, with each value a dict containing EITHER
``xer_path`` OR ``xer_content`` for that event's
pre-event contemporaneous baseline. Each fragnet is inserted
into its OWN base, impact is measured against THAT base's
pre-event finish, and the result carries
``per_event_methodology``, ``per_event_base_count``, and
``per_event_bases_used`` (sha256-truncated content hashes for
audit reproducibility). The cumulative-impact figure carries
``cumulative_caveat`` because the sum of events measured
against different bases is NOT a valid joint impact.
Exactly ONE of {baseline_xer_path, baseline_xer_content,
per_event_bases} must be supplied. Multi-base mode errors out
(returning ``{"error": ...}``) if any fragnet id is missing
from ``per_event_bases``.
Use this tool when modeling delay impact prospectively (e.g.
quantifying RFI / change-order delay before settlement). For
retrospective windows analysis after the fact, use
``forensic_windows_analysis`` (MIP 3.3 windows).
Args:
baseline_xer_path: server-side pre-impact baseline XER
(single-base mode).
baseline_xer_content: full text of pre-impact baseline XER
(single-base mode, hosted/remote use).
per_event_bases: dict {fragnet_id: {"xer_path": "..."}
OR {"xer_content": "<full XER text>"}}
for AACE MIP 3.7 Multiple Base mode.
Example::
{
"F1": {"xer_path": "/tmp/bl_pre_F1.xer"},
"F2": {"xer_content": "<XER text>"},
}
fragnets: list of fragnet dicts. Each must have:
- 'id', 'name', 'liability' (responsible party)
- 'activities': list of {code, name, duration_days,
calendar_id?}
- 'ties': list of {pred, succ, type, lag_days?}
Optional: 'description'.
output_dir: output dir for TIA_Report.txt + CSV (tempdir if "").
project_name: optional override.
Returns:
{
"report": path to TIA_Report.txt,
"impacts_csv": path to TIA_Impact_Details.csv,
"baseline": {"project_finish", "critical_count", ...},
"per_fragnet": [{fragnet_id, name, liability,
completion_before, completion_after,
impact_days, impact_working_days,
affected_activities, status, error}, ...],
"cumulative_days": int (sum of per-fragnet impacts),
"per_event_methodology": str (canonical label),
"per_event_base_count": int (count of unique base XERs),
"per_event_bases_used": {fragnet_id: sha256_hash8} (multi-base only),
"single_base_disclosure": str (single-base only),
"cumulative_caveat": str (multi-base only),
}