Narration Ready

Why probabilistic risk?

A deterministic schedule says "this project finishes on 12 Dec 2027." A probabilistic schedule says "this project has an 80% chance of finishing by 28 Jan 2028." The difference matters more than it looks — and is the difference between defensible forecasting and optimistic guessing.

Lesson 1.1

Deterministic vs Probabilistic

Project teams traditionally produce a single forecast — one finish date, one budget number, one performance figure. This is deterministic. It feels confident because it's a single answer, but it conceals the variability that every project actually contains.

Probabilistic risk analysis runs the project model thousands of times under different "what-if" combinations of risk events firing, durations varying, and costs fluctuating. The output is a distribution: P50 (50% confidence), P80 (80% confidence), P90, and so on. Each is a meaningful answer to a different question.

Single forecast vs distribution
Deterministic
"12 Dec 2027"
One number
(false confidence)
Probabilistic
distribution
P50: 22 Dec
P80: 28 Jan
P90: 14 Feb
Mental model Deterministic = "the answer". Probabilistic = "the range, the shape of the range, and which risks drive the tail."
Lesson 1.2

The Monte Carlo idea

Monte Carlo simulation is brutally simple. For each of (say) 10,000 iterations:

  1. For every risk in the register, roll a die against its probability to decide if it fires this iteration.
  2. If it fires, sample a value from its three-point estimate using the chosen distribution shape (BetaPert by default).
  3. Sum the sampled values across all firing risks to get this iteration's total schedule delta, cost delta, and performance loss.
  4. Store the totals. Repeat 9,999 more times.

You end up with three arrays of 10,000 numbers each. Sort them, take the value at the 80th percentile — that's your P80. Take the value at the 50th — that's P50. The histogram of these arrays is the probability distribution of project outcomes.

Concrete trace — one iteration
1Risk A (40% prob, 5-12-30d): die roll = 0.32 → fires. Sample = 18d.
2Risk B (15% prob): die roll = 0.41 → doesn't fire.
3Risk C (60% prob, 2-8-15d): die roll = 0.18 → fires. Sample = 9d.
4This iteration's schedule delta = 18 + 9 = 27 days.
After 10,000 iterations the engine has 10,000 such numbers. P80 = sort them, take position 8,000. P50 = position 5,000.
10,000-iteration Monte Carlo histogram building up
+0d P50 ≈ +18d P80 ≈ +47d P90 ≈ +68d +120d

Each bar grows from the bottom as iterations land in that bucket. Right-skewed shape with a long tail — typical for project risk. P50 (median) is the centre of mass; P80/P90 sit in the right tail because that is where the painful outcomes accumulate.

Per-iteration cycle (highlighted step rotates through)
1
Roll die against each risk probability
2
Sample three-point distribution for firing risks
3
Apply add/replace logic to working durations
4
CPM forward-pass through network
5
Store schedule, cost, perf totals

This 5-step cycle runs 10,000 times per simulation. Each pass produces one observation. The cycle completes in milliseconds — the whole 10k-iteration run finishes in 1-3 seconds depending on schedule complexity.

Lesson 1.3

QSRA, QCRA, QPRA — three dimensions

Risk Intelligence runs all three simulations in parallel, each iteration produces three totals:

QSRA
Schedule Risk
Days delta from planned finish. CPM forward-pass per iteration when activities are linked.
QCRA
Cost Risk
Currency delta from baseline budget. Single accumulator per iteration.
QPRA
Performance Risk
% loss against 100% nominal. Compounds via the configurable perfMode (mult / add / max).

Why all three matter together

Project performance is not just "did we finish on time" or "did we spend the budget." Performance KPIs capture quality, safety, technical objectives, resource adequacy — the dimensions a client actually cares about. A project that finished early but with 40% performance loss is a failure that schedule-only analysis would miss.

Risk Intelligence's KPI framework lets you define per-project quality, safety, deliverable acceptance, and similar dimensions and run them through the same Monte Carlo machine.

Lesson 1.4

The remaining-only philosophy

This is the single most important conceptual point in the platform, and it differs from how some traditional Monte Carlo tools work. The engine simulates from the data date forward, using the remaining work on every activity. Original (target) durations are not used by the engine.

An in-progress activity
27d done
63d remaining
Original target: 90d. The done portion (27d) is immutable — risk cannot affect it. The simulation runs only against the 63d remaining.

This matters because risks fundamentally model future uncertainty. A risk event firing in iteration 4,247 can't go back in time and add days to work already completed. Treating the activity as if it has 90 days of "at-risk" duration over-states the exposure and produces phantom risk against work that's already in the bank.

What changes practically

  • P80 schedule numbers will typically be lower than legacy tools that use original duration, on schedules with significant in-progress portions.
  • For not-started activities, the philosophy makes no difference (remaining = original).
  • For completed activities (remaining = 0), any risk mistakenly linked contributes nothing.
Module 06 deep dive The remaining philosophy interacts heavily with the Add/Replace apply-mode. Module 05 and 06 work through the engine math step by step. If you skip ahead, read those before changing engine settings in production.

The Workbench tour

The platform's workbench is organised into 11 functional tabs plus three sidebars (Activities, Issue Modeling, Help). Each tab is a workflow stage. Knowing where to look first saves real time on real projects.

Lesson 2.1

The 11 tabs at a glance

Top tab bar (workbench)
Overview
Schedule
Risks
Uncertainty
QSRA
QCRA
QPRA
Confidence
Sensitivity
Insights
Report
app.dharaniholdings.com/platform
Dharani Risk Intelligence · UAE-Oman Rail Link · Package I2 · E2310 💾 Save 📁 Projects Chinni Aarna
Overview Schedule Risks Uncert. QSRA QCRA QPRA Conf. Sens. Insights Report
Baseline (from XER · data date 2026-03-15)
Sched finish 12 Dec 27
Planned budget €42.8M
Performance nominal 100%
Schedule P80
+47d
forecast ≈ 28 Jan 28
Cost P80
+€2.85M
forecast ≈ €45.65M
Performance P80
-7.2%
retained ≈ 92.8%
Recommended Actions
R-014 Ground conditions drives 31% of schedule variance. Mitigation potential 13d. → Open risk
①Header & tabs
②Baseline strip
③KPI tiles
④Recommended Actions
▶ Run Simulation
Scenario
Focus dimension
P-value
P80
Iterations
Distribution
⑤Run controls
⑥Scenario & focus
1Header & tabs — top strip with project name + 11 tabs. Save / Projects / sign-out on the right.
2Baseline strip — pulls from XER PROJECT record (scd_end_date) and BOQ. Reference for interpreting all P-value tiles below.
3KPI tiles — P80 schedule / cost / performance. Each tile shows the delta and the forecast (baseline + delta).
4Recommended Actions — gold card that names the dominant driver and the next mitigation step.
5Run controls — right sidebar with Scenario, Focus, P-value slider, Iterations, Distribution. Collapsible.
6Sampling & engine knobs — distribution + sampling method + mitigation effectiveness slider below.
TabWhat it's forWhen to use
OverviewHeadline P50/P80/P90 + recommended actionsFirst stop after a run; client-facing summary
ScheduleActivity table with CPM, float, critical pathAnchor risks to activities; verify import
RisksFull risk register with edit dialogsAdd/edit/review every risk individually
UncertaintyAleatory uncertainty — per-activity duration bandsCapture estimating uncertainty separate from discrete risk events
QSRA / QCRA / QPRADimension-specific Monte Carlo dashboardsDeep dive on schedule / cost / performance
ConfidencePer-activity P50/P80 finish datesNegotiating contract milestones with the client
SensitivityTornado / driver analysis"Which risks drive the tail" — Spearman correlations
InsightsGenerated narrative findingsTalking points; report copy
ReportMulti-section deliverable for exportPDF / Word / Excel publication
Lesson 2.2

The right sidebar: Analysis Controls

The right edge of the workbench has a collapsible sidebar with the simulation controls. Click the small tab to collapse it for full-width viewing of dashboards. Key controls:

  • Run Simulation — fires the Monte Carlo engine. Auto-run can be toggled in Settings → General.
  • Scenario — Pre-mitigation, Post-mitigation, or Uncertainty-only.
  • Focus dimension — Schedule / Cost / Performance — drives which P-value is the headline KPI.
  • P-value slider — 50 to 95. Default is 80 (industry-standard confidence target).
  • Iterations — 1,000 to 100,000. Default 5,000. Convergence banner advises if more are needed.
  • Sampling method — Monte Carlo (random) or Latin Hypercube (stratified, fewer iterations needed).
  • Distribution — BetaPert (default), Triangular, Uniform, Normal, LogNormal, Beta, Trigen, Discrete, Bitriangular, Two-point, Point.
  • Mitigation effectiveness — slider for the Post scenario, scales risk impacts.
Lesson 2.3

Roles & permissions

The platform uses Firebase custom claims for role-based access. Roles are assigned by your administrator and govern what you can do:

Member
Read-only on most data. Can save private analyses to their own account. Cannot edit shared projects.
Operator
Full edit access to projects within their organisation. Can create / modify risks, run simulations, generate reports. Standard analyst role.
Admin
Operator + can manage users within their organisation. Can edit organisation settings, categories, KPI templates.
Superuser
Cross-organisation access. Reserved for Dharani Holdings staff. Can access Anthropic-internal diagnostics and operational dashboards.
Lesson 2.4

Loading data — file formats

Drop any combination onto the workspace:

  • Primavera P6 XER — full schedule with TASK, TASKPRED, TASKRSRC, RSRC, UMEASURE tables. Activities, relationships, resource assignments, units-of-measure all populate.
  • Excel risk register — .xlsx / .xls. Multi-sheet workbook with the platform's 20-column Schedule sheet (see Module 12 for round-trip).
  • CSV / TSV — flat risk register. Schema auto-detection picks up ID, Description, Probability, three-point impacts, Category, Owner, etc.
  • JSON — full project archive (re-import an exported project).
  • PDF / Word / PowerPoint — unstructured documents. Parser extracts candidate risks for review; you confirm before they enter the register.
Workflow gate After upload, the platform always shows the Workflow choice modal before running anything. You pick: Auto-detect & run (trusted register), Review pending risks (manual triage), or Use only schedule (no risk register yet). No silent auto-run on import.

Risk Register basics

The risk register is the heart of the platform. Each row is a discrete risk event with a probability of firing and a three-point impact estimate. Understanding the data model makes every downstream feature easier to use.

Lesson 3.1

Anatomy of a risk record

Risk row in the register table
R-014 Unexpected ground conditions in earthworks HIGH P × I = 0.40 × 35 = 14.0

Every risk record carries these fields:

  • ID — unique identifier (R-001, R-002... or user-defined)
  • Description — clear, specific risk statement (avoid generic "schedule risk" — describe the actual event)
  • Category — risk category for grouping (Design, Procurement, Construction, Commissioning, External)
  • Owner — person accountable for managing this risk
  • Probability — 0–100% chance of firing during the project
  • Three-point impacts — Min / Most Likely / Max for each dimension (Schedule days, Cost currency, Performance % loss)
  • Per-KPI estimates — if you've defined custom KPIs, three-point per KPI overrides the legacy single "performance %"
  • Activity links — risks linked to one or more activities anchor the impact spatially in the schedule
  • Response strategy — Avoid / Reduce / Transfer / Accept
  • Source citation — where this risk came from (workshop, SME interview, lessons learned)
  • Apply-mode override — per-risk Add/Replace setting (see Module 05)
Lesson 3.2

Probability × Impact

Two independent quantities. Probability is "how likely is this event to occur at all during the project life." Impact is "if it does occur, how bad is it." The product P × I gives you the expected value — useful for sorting but never a substitute for the full Monte Carlo run.

Why P × I alone misleads
RiskProbabilityImpact (ML)P×IWhy ranking by P×I is wrong
A50%20d10Stable, predictable, fires routinely
B5%200d10Same P×I but the tail risk is catastrophic — drives P95 even though P50 doesn't see it
Risk B contributes to the worst-case scenarios disproportionately. Monte Carlo + Sensitivity analysis catches this; expected value alone does not.
Lesson 3.3

Risk categories

Categories enable grouping in tornado charts, sensitivity analysis, and reports. Default categories on a new project:

Design
Procurement
Construction
Commissioning
External / Force Majeure
Regulatory

Add custom categories via Settings → Categories. The tornado view supports a "by category" tornado-mode to roll up sensitivity to the category level.

Lesson 3.4

Risk vs Uncertainty — two registers

The platform distinguishes two types of variability:

Risks
Discrete events with a probability of firing.
Example: "Permit delay" — might happen (40% chance), might not. If it does, 5-15-30 day impact.
Each iteration includes a die-roll against probability.
Uncertainties
Continuous estimating bands per activity, always active.
Example: "Earthworks duration estimate is 90d ± 20%". Always varies, never "doesn't happen".
Captures inherent estimating uncertainty separate from discrete events.

Use both. A complete model has a risk register for things-that-might-happen and an uncertainty register for things-that-have-uncertain-magnitude-regardless. The QSRA / QCRA / QPRA tabs let you scenario-toggle between Pre (risks active), Post (mitigated risks), or Uncertainty-only (just the bands, no risk events).

Activity linkage & context

Linking a risk to one or more activities anchors the impact in time and space. The CPM forward-pass uses the linkage to propagate risk effects through the precedence network. The activity context block makes your estimates calibrated.

Lesson 4.1

Why link risks to activities

An unlinked risk is a project-level overlay — sampled days are added to the bottom-line schedule, not routed through any specific activity. This is fine for high-level risks ("strategic alignment shift") but loses precision for activity-specific risks.

A linked risk is routed through the CPM network. If the risk fires in a given iteration:

  • The sampled time impact extends the linked activity's working duration in that iteration.
  • The CPM forward-pass recomputes early start and early finish dates downstream.
  • If the activity is on the critical path, the entire project shifts. If not, the activity may consume float silently — until it doesn't, and the path becomes critical.
  • The PRA convention: each linked activity receives the full sampled impact. Multiple links = multiple parallel effects.
Linked vs unlinked schedule impact routing
Risk fires (linked)
sampled = 20d
workingDurations[A]
+= 20d
CPM forward-pass
Project finish
extended
Risk fires (unlinked)
sampled = 20d
sched += 20d
(project overlay)
Project finish
extended
Both routes shift the project finish, but only the linked path participates in CPM — float erosion, path-criticality changes, and per-activity confidence forecasts only exist for linked risks.
Lesson 4.2

The activity picker in the risk dialog

Add Risk / Edit Risk — activity linkage section
Link to Activity (optional)
A-4010 · 2025-07-23 → 2025-10-21 · 90d orig · 63d rem ×

Type-ahead search resolves on code or name. Click a result to add it as a chip. Click the × on a chip to unlink. Multiple chips = multiple linked activities (the risk's impact applies to each).

The chip's tooltip shows the activity's start/finish dates and duration. For in-progress activities, both original and remaining are displayed in the chip text.

Lesson 4.3

The activity context block

Once you link one or more activities, the dialog renders a context panel directly below the chip area. This is the platform's calibration aid — it shows you the actual schedule footprint so your three-point estimates are grounded in reality.

Activity context block — single activity linked
Linked activity — A-4010 Earthworks and foundations
Duration
63d remaining of 90d original
Cost
595k remaining of 850k original
Performance-relevant resources assigned
Earthworks Crew crew-hr
Qty 2240 / 3200 Cost 595k / 850k

The panel auto-aggregates if multiple activities are linked (heading becomes "Linked activities (N) — aggregated"). Resources shown are filtered to those ticked as performance-relevant in Settings → Performance → Resources.

Lesson 4.4

Inline baseline strips above three-point inputs

Each impact section (Schedule, Cost, Performance) now carries a thin strip directly above the Min/ML/Max inputs. This is the operative reference for your estimate.

Schedule Impact section with baseline strip
Schedule Impact (days) · Three-point estimate
Remaining duration (engine baseline): 63d → Add: remaining + sample; Replace: sample becomes new remaining
Optimistic (Min)
Most Likely
Pessimistic (Max)
Full Edit Risk Parameters dialog — top to bottom

The screenshot below shows every section of the risk dialog when a risk is linked to one activity. Note the apply-mode dropdown at the top, the activity context block in the middle, and the differently-styled baseline strips above each impact section (accent for schedule + cost, muted N/A for performance).

Edit Risk Parameters — R-014 Ground conditions
Impact application mode (how sampled values relate to the linked activity baseline)
Add: sample is the extra work — 63d remaining + 20d sample → simulation uses 83d. Replace: sample IS the new remaining — engine derives delta.
Link to Activity
A-4010 · 90d orig · 63d rem ×
Linked activity — A-4010 Earthworks and foundations
Duration
63d remaining of 90d orig
Cost
595k remaining of 850k
Performance-relevant resources
Earthworks Crew crew-hr 2240/3200 · 595k/850k
Schedule Impact (days) · Three-point
Remaining duration: 63d
Min
Most Likely
Max
Cost Impact · Three-point
Remaining cost: 595k
Min
ML
Max
Performance Impact (% loss) · Three-point
Apply-mode N/A Sample is % loss against 100% nominal. Compounds via global perfMode.
Min
ML
Max
Performance Impact section — informational variant
Performance Impact (% loss) · Three-point estimate
Apply-mode N/A Sample is the % loss against 100% nominal. Multiple risks compound via the global performance mode (mult / add / max) — the per-risk Add/Replace toggle has no effect on performance.
Min
Most Likely
Max
Visual hierarchy Accent-coloured strips (Schedule, Cost) are operative — the apply-mode toggle changes how the sample relates to them. The muted-grey strip with the APPLY-MODE N/A pill on Performance is informational — the toggle doesn't affect performance.
Lesson 4.5

Multi-activity linkage and aggregation

When a risk is linked to multiple activities, both the engine and the dialog handle aggregation:

  • In the engine — each linked activity independently receives the full sampled impact (PRA convention). If the sampled value is 20d and there are 3 links, each activity's working duration gains 20d in that iteration. The CPM forward-pass then determines which activity drives the project finish.
  • In the dialog baseline display — durations and costs are summed across linked activities. The strip shows the totals (e.g. "Total remaining: 187d across 3 activities").
  • Replace mode with multi-link — each linked activity's working duration is set independently to the sampled value, so each gets sample - this_activity's_remaining as its delta. Multiple replace-mode risks on overlapping activities accumulate deltas (additive engine consequence — slightly more pessimistic than pure replace; usually conservative).

Apply-mode: Add vs Replace

The single most consequential simulation control after distribution choice. Add mode treats the sampled value as a delta on top of remaining work. Replace mode treats it as the new remaining work entirely. Choose deliberately — it changes the engine math.

Lesson 5.1

The two modes — concept

An activity with 63d remaining work, risk sampled at 20d

ADD mode — sample is the extra work on top of remaining

27d done
63d remaining
+20d added
Working duration for CPM: 63 + 20 = 83d

REPLACE mode — sample IS the new remaining work; risk sampled at 70d

27d done
70d new remaining (replaces 63d)
Working duration for CPM: 70d (engine internally computes delta = 70 - 63 = +7)

The visual point: add mode lengthens the activity by the sampled amount. Replace mode resets the activity's remaining duration to the sampled amount, regardless of what was there before.

Watch the two modes apply (loops every 4 seconds)
Add mode — extra orange bar appears after the remaining work
27d done
63d remaining
+20d
Replace mode — the entire remaining segment is replaced
27d done
63d remaining
70d new remaining

The completed 27d portion never changes — it is burned and immutable. Add mode extends the remaining segment; Replace mode swaps it out entirely for the sampled value.

Lesson 5.2

Worked example — Add mode

Earthworks activity with weather risk — ADD mode
1Activity: A-4010 Earthworks, 90d original, 63d remaining at data date.
2Risk linked: "Adverse weather during rainy season", probability 50%, three-point 5-15-30 days.
3Mode: Add (default; inherits global)
4Iteration 2,847: die roll = 0.32 → fires. Sample from BetaPert(5,15,30) = 18 days.
5Engine: workingDurations[A-4010] starts at 63. After risk: 63 + 18 = 81. CPM forward-pass uses 81d for this activity in this iteration.
Mental model: "Weather adds 18 more days of work to the 63 still needed." Result: 81d of remaining work in this iteration.
Same activity, same risk, but multiple risks firing in one iteration — ADD mode
1Iteration 5,612: two risks fire on A-4010:
2Risk W (weather): sample = 12d
3Risk G (ground conditions): sample = 25d
4Engine: workingDurations[A-4010] = 63 + 12 + 25 = 100d. Both deltas accumulate.
In Add mode, deltas always accumulate. Two risks firing on the same activity both extend it. This is correct — if weather adds 12 days AND ground conditions add 25 days, the activity is delayed by both.
Lesson 5.3

Worked example — Replace mode

Specialist contractor risk — REPLACE mode
1Activity: A-5020 Specialist welding, 45d original, 30d remaining at data date.
2Risk linked: "Contractor switches mid-job to less-experienced team", probability 25%, three-point 50-60-90 days.
3Why Replace: the three-point estimates the new total duration if the risk fires, not the additional time. The team change resets how long the remaining work takes — it's no longer "30 days + extra".
4Mode: Replace (per-risk override; global default unchanged)
5Iteration 8,103: die roll = 0.19 → fires. Sample from BetaPert(50,60,90) = 65 days.
6Engine: workingDurations[A-5020] starts at 30. Replace formula: 30 + (65 - 30) = 65d. Engine derives the delta of +35d automatically.
Mental model: "If the contractor change happens, the remaining work takes 65 days regardless of what it was before." Result: 65d in this iteration.
Multi-risk subtlety If two replace-mode risks fire on the same activity in the same iteration, the engine adds both deltas. So if Risk A replaces 30d→65d (delta +35) and Risk B replaces 30d→80d (delta +50), the result is 30 + 35 + 50 = 115d, which is more pessimistic than either pure-replace alone. This is a known additive-engine consequence — for risk modelling it's conservative which is usually safer than the alternative.
Lesson 5.4

The per-risk override + the global setting

Apply-mode is configurable at two levels:

Global default — Settings → Advanced
Drives behaviour for all risks that don't have a per-risk override. Saved with project state.
Per-risk override — top of risk dialog
Overrides global for this risk only. Empty value = inherit global.

When to use which

  • Default Add globally — most projects, most risks. Standard Monte Carlo PRA convention.
  • Per-risk Replace when an individual risk fundamentally re-bases the activity, not just adds to it. Examples: "Permit forces a complete redesign approach" (the activity is now a different activity), "Site access change makes the work much faster" (opportunity risk).
  • Global Replace — rare, but useful for sensitivity testing ("if I treat all my estimates as the new totals, what's the P80?").
Settings — Advanced
General Categories People Thresholds Performance Advanced
Default risk impact application mode
Simulation runs entirely on activity remaining duration / cost — original (target) is not used by the engine. Add: 63d + 20d = 83d. Replace: 70d sample replaces 63d remaining.
Scope: schedule + cost only. Performance compounds via the performance mode below.
PHASE 13
Seed:
Performance compounding mode

Settings → Advanced panel showing the global apply-mode dropdown introduced in Phase 13.

Lesson 5.5

Scope: schedule and cost only

The apply-mode dropdown has no effect on the Performance dimension. Performance is structurally different:

  • Performance is measured as percentage loss against 100% nominal, not as an absolute number.
  • The sampled value IS already a delta (% reduction), not a candidate "new total".
  • There's no XER-derived "remaining performance baseline" the way duration and cost have. Performance baselines are KPI definitions, not schedule data.
  • Add and Replace would produce identical results for performance — sample - 0 = sample.

The dialog's performance baseline indicator carries an APPLY-MODE N/A badge to make this explicit. The explainer says: "Multiple risks compound via the global performance mode (mult / add / max) — the per-risk Add/Replace toggle has no effect on performance."

In summary Apply-mode is a Schedule + Cost lever. Performance is handled by the perfMode setting in Settings → Advanced, which controls how multiple risk losses combine across iterations (mult = compounding, add = sum capped at 100%, max = take the worst).

The remaining-only philosophy

The engine operates on remaining work, never on original target durations. This is a fundamental design choice that affects how every result is interpreted. Take this module seriously — it's the difference between defensible numbers and inflated ones.

Lesson 6.1

The core principle

Risks model future uncertainty. They can only affect work that has not yet happened. Work already completed is in the past, immutable, not subject to perturbation.

Activity state spectrum
Not Started
90d remaining
Remaining = Original. No work done yet. Risk applies to the full duration.
In Progress (30%)
27d
63d remaining
Remaining = 63d. The completed 27d is locked. Risk applies only to the 63d.
Completed
90d done
Remaining = 0. Even if risk is linked, contributes 0 to working duration.
Lesson 6.2

Why this matters — concrete comparison

Consider the same in-progress activity (90d original, 63d remaining), same risk (sample = 80d), with two different engine designs:

ScenarioOld (original-based engine)New (remaining-based engine)
Add mode, sample 20d workingDur = 90 + 20 = 110d
Over-states: counts the 27d already done
workingDur = 63 + 20 = 83d
Correct: only 83d of work still needs to happen
Replace mode, sample 80d workingDur = 80d (set directly)
Credits back the 27d burned! Activity duration < what's already been done.
workingDur = 63 + (80 - 63) = 80d worth of remaining work + 27 already done = 107d total elapsed
Correct: 27d burned + 80d new remaining = 107d total elapsed

The replace-mode case is where the old approach went badly wrong. A pure "set the activity to 80d" treatment doesn't make physical sense for an in-progress activity — you can't un-burn the 27d already in the bank. The remaining-based engine handles this correctly by treating sample as the new remaining, then letting the engine derive the right delta.

Lesson 6.3

Engine internals — how it's implemented

Inside simulate(), the platform precomputes two structures from App.activities:

// Precomputed once per simulation run (outside iteration loop)
const _remainDurByIdx = new Float64Array(network.acts.length);
for (let i = 0; i < network.acts.length; i++) {
  const a = network.acts[i];
  // Trust explicit 0 for completed activities; fall back only when missing
  _remainDurByIdx[i] = (a.remainDrtnDays != null)
    ? a.remainDrtnDays
    : (network.baseDuration[i] || 0);
}

// Per-risk baseline for replace-mode delta
const riskBaselines = risks.map(risk => {
  let baseSched = 0, baseCost = 0;
  String(risk.activityId || '').split(/[;,]/).forEach(code => {
    const a = App.activityIndex[code];
    if (!a) return;
    baseSched += (a.remainDrtnDays != null) ? a.remainDrtnDays : (a.origDrtnDays || a.drtnDays || 0);
    baseCost  += (a.remainCost     != null) ? a.remainCost     : (a.origCost     || 0);
  });
  return { baseSched, baseCost, mode: risk.applyMode || globalMode };
});

Then per iteration, workingDurations is reset from _remainDurByIdx (not network.baseDuration):

// Per-iteration reset — start from REMAINING, not original
workingDurations.set(_remainDurByIdx);

// Per-risk handling in inner loop
const inc = _replaceLinked
  ? (schedSample - _remainDurByIdx[links[li]])  // Replace: delta against remaining
  : schedSample;                                // Add: just the sample
workingDurations[links[li]] += inc;

// Cost — same pattern
cost += _replaceCost ? (costSample - _rb.baseCost) : costSample;
Lesson 6.4

What changes practically

If you previously ran the same XER through a legacy build, expect these differences in the new (current) build:

  • P80 schedule numbers may be lower on schedules with significant in-progress portions. The engine isn't double-counting burned time.
  • Per-activity Confidence dates are sharper — early finish dates reflect remaining-from-data-date, not from project start.
  • Replace-mode behaviour on in-progress activities is now correct — sample becomes the new remaining, not the new total elapsed.
  • Completed activities (remain = 0) contribute zero to the CPM working durations, even when linked to risks. (You shouldn't link risks to completed activities, but if you do, they're a no-op.)
Reporting note Per-activity Confidence forecasts are now expressed relative to the data date. The Overview baseline strip continues to anchor on the schedule's scheduled finish date — so the P80 forecast ("forecast finish ≈ 28 Jan 2028") is the data date + P80 days, not the project start + P80 days.
Lesson 6.5

Same philosophy for cost

Cost dimension follows identical logic. The cost variable per iteration is a "delta over project baseline cost" — it represents additional cost beyond the planned remaining cost.

  • _rb.baseCost is the sum of remaining costs of linked activities (from XER TASKRSRC remain_cost field, or backfilled from import).
  • Add mode: cost += costSample — extra cost added to the project overrun.
  • Replace mode: cost += (costSample - _rb.baseCost) — if sample is below remaining baseline, this can be negative (an opportunity / savings).

For a 100k-remaining-cost activity with a 30k replace-mode sample: cost += (30 - 100) = -70k. The project's cost forecast drops by 70k for that iteration, reflecting that the new remaining cost is lower than the planned remaining. Replace mode handles opportunity risks correctly.

Lesson 6.6

Performance under the philosophy

Performance handling is consistent with the philosophy because:

  • Each risk's sampled performance value IS a % loss — it's always relative.
  • The loss conceptually applies to remaining work (which is the only work the simulation horizon covers).
  • There's no need for an explicit "remaining performance baseline" because percentage loss is dimensionless.
  • The perfMode setting (mult / add / max) controls how multiple losses compound. Default is multiplicative: retention = (1 - loss1) × (1 - loss2) × ...

Add/replace toggle is therefore N/A for performance — and the dialog says so explicitly. Module 5 covered the scope; Module 7 deep-dives the KPI framework.

KPIs & Resources

Performance risk needs measurable indicators. The KPI framework lets you define what "performance" means for this project — on-time delivery, safety incidents, quality acceptance, resource utilisation, anything dimensional. Resources are first-class KPIs.

Lesson 7.1

Defining KPIs

Settings → Performance has the KPI table. Each KPI carries these attributes:

name
Display name, e.g. "On-time delivery", "Safety incident rate"
unit
UOM badge shown in tables (%, incidents, crew-hr, kWh)
measurement
absolute / percentage / ratio — how the KPI is quantified
direction
higher_is_better or lower_is_better — drives "loss" interpretation
weight
0..1, contribution to weighted overall performance score
isPrimary
Flagged as the project's headline KPI — shown gold in tornado, separately highlighted
Lesson 7.2

Per-KPI three-point estimates in the risk dialog

Once KPIs are defined, the risk dialog renders a grid where you enter Min/ML/Max per KPI. This replaces the single legacy "performance %" field.

Per-KPI grid in the risk dialog
KPIMin lossML lossMax loss
On-time delivery primary2512
Quality acceptance138
Safety incident rate013
Earthworks Crew resource0515

Resources also appear in this grid (Phase 9 unification — "Resources ARE KPIs"). Tick a resource as performance-relevant in Settings → Performance → Resources, and it appears here for per-risk three-point input.

Lesson 7.3

Resources from the schedule

When you load a Primavera XER, the parser reads the RSRC table (resource catalog) and TASKRSRC table (assignments). Each resource carries:

  • Name + Code — from rsrc_name + rsrc_short_name
  • Type — Labour, Material, Non-Labour
  • UOM — from the UMEASURE table (units like crew-hr, m³, tonnes, kWh)
  • targetQty / remainQty — aggregated from TASKRSRC target_qty / remain_qty across all assignments
  • targetCost / remainCost — aggregated from TASKRSRC target_cost / remain_cost
  • targetDurDays / remainDurDays — aggregated duration across assignments
  • selectedForPerf — user-controlled tick; only ticked resources surface as performance KPIs
Resources panel (Settings → Performance)
From schedule (5 resources detected)
NameUOMQty (remain / total)Cost (remain / total)
Earthworks Crewcrew-hr2240 / 3200595k / 850k
Concrete Plant180 / 400120k / 240k
Light Vehicleshr820 / 120012k / 18k
Specialist Welderscrew-day30 / 2008k / 60k
Generic Labourhr450 / 180014k / 55k
Lesson 7.4

Why tick a resource as performance-relevant

Three things happen when a resource is ticked (selectedForPerf = true):

  1. It appears in the per-KPI grid of every risk dialog. You can enter three-point % loss estimates against it.
  2. The engine includes it in the per-KPI simulation pass (_simulateKpisOnly), producing per-resource P50/P80/P90 numbers.
  3. If amplification is configured (Module 8), the engine multiplies impacts against this resource based on its consumption ratio.

Not every resource needs ticking. Tick only the ones that meaningfully drive project performance — typically the critical-path resources, scarce specialist resources, or anything that's near its capacity ceiling.

Lesson 7.5

The per-KPI driver tornado

After a simulation, the QPRA dashboard shows a per-KPI driver tornado — the top risks ranked by Spearman rank correlation with each KPI's iteration outcome. This tells you "if you mitigate this one risk, which KPI shifts most".

Drivers are computed independently per KPI, so the same risk might be a high driver for one KPI and low for another. This is the value of the unified framework: a single risk register feeds into multiple KPI-specific dashboards.

Custom resources & amplification

Beyond resources auto-imported from the schedule, you can define custom resources for any performance-relevant consumable. When resources approach their consumption ceiling, the amplification engine increases the impact of risks affecting them — capturing real-world fragility.

Lesson 8.1

Custom resources — what and when

XER schedules don't always contain every resource the project cares about. Some examples that warrant a custom resource:

  • Specialist crews not modelled in the schedule (e.g. permits team, design review board)
  • Environmental constraints (e.g. allowable noise hours, water-extraction permit volume)
  • Capital constraints (e.g. drawdown limits, working capital)
  • Stakeholder bandwidth (e.g. owner review hours, regulator engagement days)
Add Custom Resource dialog
Resource name
Unit
Capacity (max per period)
Original quantity (total)
Remaining quantity

Sanity-clamping on save: remainQty is bounded between 0 and targetQty. If you enter values outside this range, the platform clamps them silently.

Lesson 8.2

The amplification concept

Real-world intuition: a project that's already consumed 90% of its specialist welding crew is more exposed to further perturbation than one at 30% consumed. Less buffer, fewer alternatives, more cascading impact.

Consumption ratio drives amplification
consumed_ratio
= (target - remain) / target
below threshold
(default 0.8)
multiplier = 1.0
(no amp)
consumed_ratio = 0.85
above threshold
multiplier = 1.125
(amplification)
Lesson 8.3

The amplification math

Settings → Performance has two knobs:

  • Resource consumption amplification (resourceAmp) — 0 to 2, default 0 (off)
  • Amplification threshold (resourceAmpThreshold) — 0.5 to 0.95, default 0.8
function _resourceConsumptionMultiplier(metric) {
  if (metric.kind !== 'resource') return 1;
  const r = metric.resource;
  const orig = r.targetQty || 0;
  const remain = r.remainQty != null ? r.remainQty : orig;
  if (orig <= 0) return 1;
  const ratio = (orig - remain) / orig;
  const amp = App.settings.resourceAmp || 0;
  const threshold = App.settings.resourceAmpThreshold || 0.8;
  if (ratio <= threshold || amp <= 0) return 1;
  const excess = (ratio - threshold) / (1 - threshold);
  return 1 + amp * excess;
}

In words: at exactly the threshold, multiplier = 1. At 100% consumed, multiplier = 1 + resourceAmp. Linear in between.

Lesson 8.4

Worked example

Specialist Welding Crew amplification
1Custom resource: "Specialist Welding Crew", Original Qty 200 crew-day, Remaining Qty 30.
2Settings: resourceAmp = 0.5, threshold = 0.8.
3Consumption ratio: (200 - 30) / 200 = 0.85.
4Excess: (0.85 - 0.8) / (1 - 0.8) = 0.25.
5Multiplier: 1 + 0.5 × 0.25 = 1.125.
6Effect: Any risk impacting this resource has its sampled performance loss multiplied by 1.125. Sampled 10% loss → 11.25%.
In a project where the welding crew is 85% consumed and you have a 0.5 amp factor, every welding-related risk hits 12.5% harder. The QPRA dashboard reflects this in higher P80 for welding-related KPIs.
Lesson 8.5

When to use amplification

  • Late-stage projects with significant resource consumption — set resourceAmp > 0 to capture fragility.
  • Greenfield projects — leave at 0 (default). Nothing's consumed yet.
  • Stress-testing — set amp = 1.0 or 2.0 to model "what if our specialist resources are near their limit by month X."
  • Threshold tuning — 0.8 (80% consumed = stressed) is the default. Lower it (e.g. 0.6) for projects where you want amplification to kick in earlier.
Amplification + replace mode Amplification multiplies the sampled performance loss. It interacts with replace mode independently — replace mode determines what the new total is, amplification scales the perf loss for the KPI. The two layers are orthogonal but applied in sequence.

Schedule tab & CPM

The Schedule tab is your activity table. The CPM forward-pass runs against this table every simulation iteration. Understanding what's stored and what's computed clarifies why P80 numbers move the way they do.

Lesson 9.1

What lives in App.activities

{
  task_id: 'T12345', code: 'A-4010', name: 'Earthworks and foundations',
  wbs_id: '1.3.2', type: 'Task', status: 'Active',
  // Duration fields
  drtnDays: 90,           // target/planned (legacy)
  origDrtnDays: 90,       // from XER target_drtn_hr_cnt
  remainDrtnDays: 63,     // from XER remain_drtn_hr_cnt — USED BY ENGINE
  pctComplete: 30,
  // Schedule dates
  startISO: '2025-07-23', endISO: '2025-10-21',
  // Float & criticality
  tfDays: 0, ffDays: 0, isCritical: true,
  // Cost (aggregated from TASKRSRC)
  origCost: 850000, remainCost: 595000,
  // Per-resource assignment breakdown
  assignments: [{ rsrc_id: 5, targetQty: 3200, remainQty: 2240, targetCost: 850000, remainCost: 595000 }],
}
Lesson 9.2

CPM forward-pass — the engine's heartbeat

Every simulation iteration:

  1. Reset workingDurations to per-activity remaining (_remainDurByIdx)
  2. Sample each risk; add sampled value (Add mode) or compute delta (Replace mode) to each linked activity's working duration
  3. Run _cpmForwardPass(network, workingDurations, workES, workEF) — Kahn's topological sort + forward-pass honouring FS/SS/FF/SF lag
  4. Compute cpmDelta = iterFinish - baselineCpmFinish for this iteration's schedule contribution

All four relationship types and lag values are honoured — from the XER's TASKPRED table or from Excel round-trip via _rebuildTaskRelationshipsFromImport.

CPM forward-pass walks the network in topological order
A-1010
Design
30d
A-1020
Engineering
90d
A-4010
Earthworks
63d
A-5030
Handover
45d
Finish

Each node lights up gold as the forward-pass arrives. ES = max(predecessor EF + lag). EF = ES + working duration. Critical-path activities (no float) are highlighted red. This walk repeats every iteration with the perturbed durations from that iteration's risk samples.

Lesson 9.3

Critical path identification

The Schedule tab can be filtered to "critical only" — activities with TF below the criticality threshold (default 1 day). Use this filter to identify candidate activities for risk linkage.

Best practice Risks on critical-path activities affect the project finish directly. Risks on near-critical activities (TF < 5d) consume float and may push activities onto the critical path. The Sensitivity tornado surfaces these patterns.

Simulation engine internals

Under the hood, the engine is disciplined JavaScript. Understanding the per-iteration loop lets you reason about edge cases, choose iteration counts intelligently, and interpret results with confidence.

Lesson 10.1

The simulate() function — high level

function simulate(risks, scenario) {
  // 1. Pre-compute (once per simulation)
  const network = _buildCPMNetwork();
  const riskActIdx = _buildRiskActivityMap(risks, network);
  const riskBaselines = risks.map(...);          // remaining-based
  const _remainDurByIdx = ...;                  // per-slot remaining
  
  // 2. Per-iteration loop (N = iterations)
  for (let it = 0; it < N; it++) {
    let sched = 0, cost = 0;
    workingDurations.set(_remainDurByIdx);
    
    for (let r = 0; r < risks.length; r++) {
      if (probSamples[r][it] > risk.effProb) continue;  // gate
      const schedSample = sampleDist(impSamples[r][it], min, ml, max, distTime);
      
      if (links.length > 0) {
        for (let li = 0; li < links.length; li++) {
          const inc = _replaceLinked
            ? (schedSample - _remainDurByIdx[links[li]])
            : schedSample;
          workingDurations[links[li]] += inc;
        }
      } else sched += schedSample;
      
      cost += _replaceCost ? (costSample - _rb.baseCost) : costSample;
      perfRetention *= Math.max(0, 1 - perfSample / 100);
    }
    
    const iterFinish = _cpmForwardPass(network, workingDurations, workES, workEF);
    schedTotals[it] = Math.max(0, iterFinish - baselineCpmFinish) + sched;
    costTotals[it] = cost;
    perfLosses[it] = (1 - perfRetention) * 100;
  }
  
  return processResults(schedTotals, costTotals, perfLosses, ...);
}
Lesson 10.2

Sampling — Monte Carlo vs Latin Hypercube

  • Monte Carlo (default) — Independent uniform draws. Robust, well-understood. Needs more iterations to converge (5,000–10,000 typical).
  • Latin Hypercube — Stratified sampling. Converges with fewer iterations (2,000–5,000). Slightly biased estimator for far-tail percentiles (P95+) on heavily correlated inputs.
Sensitivity tornado — Spearman rank correlation driving the P80
R-014 Ground conditions
ρ = 0.74
R-023 Permit delay
ρ = 0.58
R-007 Weather (rainy)
ρ = 0.43
R-031 Vendor lead time
ρ = 0.31
R-019 Specialist labour
ρ = 0.19

Each bar draws over 2.5 seconds with a 0.2s stagger between rows. Bars rank by Spearman correlation between a risk's per-iteration sample and the iteration's total outcome. Top of the tornado = the highest-impact risk to mitigate next.

Lesson 10.3

Convergence and reproducibility

After every run, the engine computes the relative standard error (RSE) of the schedule mean: RSE = (σ / √N) / μ. The Convergence slider sets the target (default 1%); when exceeded, an amber banner recommends N' = N × (RSE / target)².

Reproducibility: enable Seed Lock in Settings → Engine. The locked seed is captured in archive snapshots, the Run Log sheet, and report cover pages. Two analysts with the same locked seed get bit-identical results.

Lesson 10.4

Scenarios — Pre / Post / Uncertainty

  • Pre-mitigation — every risk uses raw probability and impact. The "untouched" view.
  • Post-mitigation — every risk uses postProb / postImp (or scaled by mitEffect). Models project after planned mitigation.
  • Uncertainty-only — no risk events fire; only activity-level uncertainty bands. Models inherent estimating noise.

Distributions & sampling

Eleven distribution shapes. Choose deliberately — shape drives the tail behaviour, and the tail is what your P90 and P95 come from.

Lesson 11.1

The eleven shapes

BetaPert (default)
Smooth bell, weighted toward ML. Industry standard for project risk; reflects expert judgment well.
Triangular
Three points form a triangle. Wider tails than BetaPert. Use when ML is genuinely uncertain.
Uniform
Flat between Min and Max, ignores ML. Use when no preferred value.
Normal
Bell-shaped, symmetric, infinite tails. Doesn't fit skewed distributions.
LogNormal
Right-skewed (heavy upper tail). Good for cost overruns and duration extensions.
Beta
Bounded shape with shape parameters from lambdaShape config. Flexible but harder to tune.
Trigen
Triangular with explicit confidence levels (trigenLo, trigenHi). Useful when "Min" means "10th percentile".
Bitriangular
Symmetric two-sided triangular. Used for unbiased uncertainty bands.
Two-point
50% chance of Min, 50% chance of Max. Discrete binary outcome.
Point
Single deterministic value — ML always returned.
Discrete
Custom discrete probability mass (advanced — defined per risk via JSON).
Lesson 11.2

Distribution choice guide

ScenarioRecommended shapeWhy
Standard schedule riskBetaPertIndustry standard; ML weighting realistic
Cost overrunLogNormal or BetaPertRight-skewed tails capture catastrophic overruns
"Anywhere between 5 and 30 days"UniformNo preferred value
"Will succeed or fail, no middle"Two-pointDiscrete binary outcome
Activity estimating uncertaintyTriangular or BitriangularWider tails for estimation noise
Confidence-bounded estimateTrigen (trigenLo=10, trigenHi=90)Honest about what "Min" means
Lesson 11.3

Correlation groups

Risks in the same correlation group sample their probability die-rolls together. Pooling three 50%-probability risks into one group → in any iteration either all three fire or none do.

Effect: increases variance of the sum (heavier right tail). Use when risks share a root cause — e.g. three weather-related risks driven by the same monsoon timing.

Practical use Pooling previously independent risks produces a heavier right tail. Expect P80 to rise, P50 roughly unchanged. The detailed PDF methodology section reports active groups and pooled risk counts.

Excel template round-trip

Take a P6 XER, export to Excel, edit offline, re-import — the relationship graph and resource assignments rebuild from the workbook alone. The 20-column Schedule sheet is the single source of truth.

Lesson 12.1

The 20 columns

#ColumnNotes
1-2Activity Code* / Activity Name*Required
3-5WBS / Type / StatusCategorisation
6-7Start Date / Finish DateISO format preferred
8-9Original / Remaining Duration (days)Engine uses remaining
10% Complete0-100
11-13Total Float / Free Float / Critical (Y/N)Slack & criticality
14-15Original / Remaining CostFrom TASKRSRC aggregation
16Resource QuantitySum of qty assignments
17PredecessorsA-1020 (FS,0d); A-1030 (SS,5d)
18SuccessorsA-1100 (FS,0d)
19ResourcesEarthworks Crew (3200 crew-hr, 850000)
20SourceFile / template origin

Template and export workbook use the SAME 20 columns — single source-of-truth header (SCHEDULE_SHEET_HEADERS).

Lesson 12.2

Predecessor / Successor format

A-1020 (FS,0d); A-1030 (SS,5d); A-1040 (FF,-2d)
  • Types: FS Finish-to-Start, SS Start-to-Start, FF Finish-to-Finish, SF Start-to-Finish
  • Lag: in days; negative = lead
  • Parser is tolerant: (FS, 0d), (FS,0d), (FS 0d), and A-1020 alone (defaults FS,0d) all work
Lesson 12.3

Resource format

Earthworks Crew (3200 crew-hr, 850000); Concrete Plant (400 hr, 240000)
  • Format: <name> (<qty> <uom>, <cost>)
  • Multiple assignments separated by semicolons
  • On first import, remaining defaults to target (no consumption recorded). Refine via the resource editor afterward.
Lesson 12.4

Round-trip flow

Full round-trip cycle
Load XER
Export to Excel
Edit offline
Drop .xlsx back
Re-build complete
On re-import, _rebuildTaskRelationshipsFromImport() parses Pred/Succ strings into App.taskRelationships. _rebuildAssignmentsFromImport() parses Resources into App.resources + activity assignments. _syncScheduleResources() mirrors into App.performance.resources.fromSchedule.

Filename pattern: <project_name>_Risk_Intelligence.xlsx for export, <project_name>_Risk_Intelligence_Template.xlsx for the empty template. Project name normalised (non-alphanumeric → underscore).

Reports & exports

Excel, PDF, and Word formats each have their purpose. Pick the right deliverable for the audience.

Lesson 13.1

The Excel workbook

SheetContent
CoverProject metadata, run parameters, seed, iteration count
Risk RegisterFull register with probabilities, three-point estimates, owners
Confidence LevelsP10/P25/P50/P75/P80/P90/P95 across all three dimensions
SensitivitySpearman rank correlations per risk, per dimension
Schedule20-column Schedule sheet — same as template
Performance KPIsPer-KPI P50/P80/P90/Mean + driver risks per KPI
InsightsAuto-generated narrative findings
Issue Register / ClaimsMaterialised issues, claims tracker
Run Log / Audit TrailEvery run + every meaningful edit
Lesson 13.2

PDF reports

  • Standard PDF — on-screen Report tab printed as PDF. Quick; methodology summary, top drivers, recommendations. Use for internal review.
  • Detailed PDF — formal multi-page report: cover, executive summary, methodology with reproducibility statement, risk matrix, sensitivity drivers, per-risk appendix, per-KPI breakdown. Use for client deliverables and dispute panels.
Lesson 13.3

Word export

The Word format wraps the Report tab's HTML in a Microsoft Word-compatible structure (Word-HTML with xmlns:o/w/Mso). Opens cleanly in Word for native editing — useful when the report needs annotation or further drafting.

Filename: <project_name>_Risk_Intelligence.doc

Lesson 13.4

The Report tab structure

  1. Executive Summary — three KPI tiles (P80 sched / cost / perf) + headline recommendations
  2. Methodology — iteration count, sampling method, distribution choice, seed status
  3. Per-Dimension Analysis — QSRA, QCRA, QPRA
  4. 3a · Performance KPI Breakdown — per-KPI P50/P80/P90 table
  5. 3b · Top Driver Risks per KPI — Spearman-ranked drivers for each KPI
  6. Scenario Comparison — Pre vs Post deltas, mitigation effectiveness
  7. 4b · Section — additional dimensional analysis
  8. Risk Register Appendix + Sensitivity Drivers

Best practices & glossary

Distilled lessons from actual engagements. The patterns that produce defensible analyses and the pitfalls that produce contested ones.

Lesson 14.1

Workshop facilitation patterns

  • Capture the source citation for every risk. "Workshop 2026-04-12 · SME interview with K. Patel" is defensible; a blank source field is a vulnerability in a claim.
  • Calibrate against the activity context. Use the remaining-duration baseline strip as your reality check. If you're entering 60d ML for an activity with 30d remaining, that's a replace-mode call, not an add.
  • Don't conflate uncertainty with risk. Activity-level estimating uncertainty (Uncertainty register) is separate from discrete risk events (Risk register).
  • Iterate on the apply-mode call. Default Add. Switch to Replace when the three-point estimates the new total, not additional time. Document reasoning in the Description.
Lesson 14.2

Calibrating three-point estimates

  • Min ≠ absolute lowest. The 10th–15th percentile. Use optimistic-but-plausible.
  • ML = the most likely if everything goes as expected.
  • Max ≠ apocalyptic. The 85th–90th percentile. Worst plausible given current info.
  • Width check: Min and Max too close → BetaPert near-deterministic. Widen if the team has uncertainty.
  • Skew check: Max − ML > 4 × (ML − Min) → heavily right-skewed. Consider LogNormal.
Lesson 14.3

When Add, when Replace

  • Use Replace when the three-point estimates the new total: contractor change, permit-driven redesign, fundamentally different execution approach.
  • Stay Add when the three-point estimates additional impact: weather delays, scope additions, defect rework.
  • Document the call in the risk description. Future reviewers should understand why this specific risk is in Replace mode.
  • Don't mix without reason. Categorical consistency makes the rationale clear in audit.
Rule of thumb If you can't explain in one sentence why this specific risk needs Replace mode, leave it on Add. Replace is the exception, not the default.
Lesson 14.4

Audit trail discipline

  • Every override, sign-off, deletion, and material edit is logged automatically with timestamp + user.
  • Use the Source / Citation field for traceability — workshop date, SME name, document reference.
  • Use Review and Approve sign-offs (Settings → Categories → Reviewers) to capture two-eye gates on risk register edits.
  • Archive snapshots at every major engagement milestone — "Pre-mitigation review", "Post-Apr workshop", "Final submission". The archive history acts as your audit trail.
  • Export the Audit Trail CSV (Settings → Audit) at engagement close.
Lesson 14.5

Common pitfalls

PitfallSymptomFix
Single P50 used as forecastStakeholders treat P50 as "the answer"Always quote P80 alongside; explain confidence semantics
Risks linked to completed activitiesNo engine effect (remain = 0)Move risks to currently-active activities, or unlink
Mixing original and remaining mental modelsNumbers don't match analyst intuitionRe-read Module 06; the engine uses remaining everywhere
Too few iterationsConvergence banner amberBump to recommended N; or use Latin Hypercube
Replace mode on add-style estimatesP80 collapses oddlyAudit the per-risk applyMode column; reset to inherit
Forgetting to tick resourcesPer-KPI driver tornado empty for resourcesSettings → Performance → Resources → tick what matters
Lesson 14.6

Master glossary

P-value (P50, P80, P90)
Confidence percentile from the Monte Carlo distribution. P80 = 80% probability the actual outcome is at or below this value.
QSRA / QCRA / QPRA
Quantitative Schedule / Cost / Performance Risk Analysis. The three dimensions the platform simulates.
CPM
Critical Path Method. Forward-pass through the precedence network determines the earliest finish date.
SRA
Schedule Risk Analysis. The PRA / Pertmaster convention where each linked activity receives the full sampled impact.
BetaPert
Default distribution. Bell-shaped, weighted toward ML. Industry standard for project risk.
Apply-mode
Add (sample is delta on remaining) vs Replace (sample is new remaining total). Set globally and per-risk.
Remaining
The work still to do on an activity at the data date. The engine operates exclusively on remaining, never original.
Replace-mode delta
For linked replace risks: delta = sample − remaining. The engine adds delta to working duration, which lands the activity at the sampled value.
Spearman correlation
Rank correlation between a risk's sampled value and the iteration's outcome. Used for tornado / driver analysis.
Float erosion
When a non-critical activity consumes its total float due to risk impacts, it may become critical in some iterations.
Correlation group
A pool of risks that fire together (correlated probability die-rolls). Increases right-tail variance.
Convergence (RSE)
Relative Standard Error. Target 1% by default. Below target = trust the result; above = run more iterations.
Seed lock
Fixed random seed for reproducibility. Two analysts with same seed get identical results.
perfMode
How multiple performance losses combine across risks. Multiplicative (default), Additive (capped at 100%), or Max.
Amplification
Multiplier applied to risk impacts when affected resources exceed a consumption threshold. Captures fragility of stretched resources.
PRA / Pertmaster convention
When a risk is linked to multiple activities, each activity receives the FULL sampled impact (not divided). Mirrors industry tools.
Lesson 14.7

Filename conventions

ExportFilename
Excel workbook<project_name>_Risk_Intelligence.xlsx
Excel template<project_name>_Risk_Intelligence_Template.xlsx
Word document<project_name>_Risk_Intelligence.doc
PDF (standard / detailed)Browser print-to-PDF naming
JSON project archive<project_name>_archive.json

Project name is normalised: non-alphanumeric characters become underscores. "ACME / Phase 2 Construction" becomes ACME_Phase_2_Construction.

Lesson 14.8

Where to go from here

  • Try a real XER end-to-end: load → review activities → link risks → run engine → publish report. The platform's intuition is hard to build without hands-on iteration.
  • Read the Help tab in the app. It mirrors this training course plus has FAQ entries that capture answers to common engagement questions.
  • Build a personal library of risk-source citations you trust. Workshop minutes, SME interview notes, lessons-learned databases. Reference these in the Source / Citation field consistently across projects.
  • Pair-review. Every claim-package level analysis should have a second analyst review the register, distribution choices, apply-mode calls, and per-KPI estimates. The audit trail will capture the review.
  • Iterate the methodology. Capture your own engagement-specific patterns. Keep them in a project README so the next analyst on the same engagement has continuity.
Course complete You've covered every major feature, the engine internals, the philosophy, and the practical patterns. The platform is now a tool you can wield with full understanding — not a black box producing numbers. Welcome to operator level.