Baseline change control, explained for developers
If you've ever been asked to build tooling for a large engineering project, you'll hear the phrase "change control" within a day. It sounds like bureaucracy. It's actually a version-control system for a project's promises, and the concepts map neatly onto things developers already know.
The baseline is your tagged release
A project baseline is the approved version of three things: scope (what will be built), cost (the budget) and schedule (when). Once approved, it's frozen, like a tagged release. Progress is measured against it, and nobody edits it directly.
| Git concept | Project controls equivalent |
|---|---|
| Tagged release | Approved baseline |
| Pull request | Change request |
| Code review | Impact assessment |
| Maintainers approving a merge | Change control board |
| Merge to main | Baseline update |
| Direct push to production | Unapproved change (the thing everyone fears) |
The lifecycle of a change
1-Raise. Someone identifies a change: a design revision, a scope addition, a supplier delay.
2-Assess. The impact is estimated on cost, schedule, risk and interfaces with other work packages.
3-Decide. A change board approves, rejects or defers it within its delegated authority.
4-Implement. Only after approval does the baseline update and the work proceed.
5-Record. Everything lands in a change register, so the history of why the baseline moved is auditable. The discipline matters because on a large project, untracked change is how budgets drift without anyone being able to explain why. People who run this process, often titled change control manager on nuclear and infrastructure programmes, spend much of their time on step 2: making sure impact assessments are honest and complete before a decision is made.
A minimal data model Here's a simple representation of a change register entry and a function that reports how far the current forecast has moved from the original baseline. from dataclasses import dataclass from enum import Enum
class Status(Enum): RAISED = "raised" ASSESSED = "assessed" APPROVED = "approved" REJECTED = "rejected"
@dataclass class ChangeRequest: ref: str description: str cost_impact: float # currency units, + = increase schedule_impact_days: int status: Status
def baseline_position(original_budget, original_days, changes): approved = [c for c in changes if c.status == Status.APPROVED] pending = [c for c in changes if c.status in (Status.RAISED, Status.ASSESSED)] return { "current_budget": original_budget + sum(c.cost_impact for c in approved), "current_days": original_days + sum(c.schedule_impact_days for c in approved), "exposure_cost": sum(c.cost_impact for c in pending), "exposure_days": sum(c.schedule_impact_days for c in pending), }
changes = [ ChangeRequest("CR-001", "Additional drainage run", 120_000, 10, Status.APPROVED), ChangeRequest("CR-002", "Revised valve specification", 45_000, 0, Status.ASSESSED), ChangeRequest("CR-003", "Redundant cable tray", -15_000, -2, Status.REJECTED), ]
print(baseline_position(5_000_000, 400, changes))
{'current_budget': 5120000, 'current_days': 410,
'exposure_cost': 45000, 'exposure_days': 0}
The figures are illustrative. The useful idea is the split between approved changes, which move the baseline, and pending ones, which are exposure. Reporting only the first hides risk; reporting them together blurs what has actually been agreed.
Things that trip up developers new to this domain
- Never overwrite the baseline. Store each approved baseline as a new version so you can always compare against the original.
- Changes interact. Two changes that each add five days may not add ten if they sit on parallel paths of the schedule. Real schedule impact needs the scheduling tool, not a sum.
- Authority limits are data. Who can approve what value of change is usually defined by role and threshold. Model it explicitly.
- Audit trail is a feature, not a log. Users will need to answer "why did this number move in March?" months later.
Wrapping up
If you understand why teams protect main, you already understand why projects protect their baseline. The vocabulary is different; the instinct is the same.
Comments
Join the discussionNo comments yet. Be the first to comment.