Sheet02 / 08
Redline · pre-load checkThe check
Rev A2026-10-22
StatusBRC-28BLOCK

The check, Rules

Rules

The ten rules, each with its SQL twin and UAT scenario.

BLOCK means the loader rejects or corrupts the row. REVIEW means the row loads, and a person decides. Each rule exists twice, in TypeScript and in SQL. A unit test runs both on the same tables and fails on any difference.

UAT plan: 20 scenarios, 0 passed
R1

Gate sequence integrity

BLOCK

Every program needs every gate in the catalog, in order. A missing or reversed gate breaks stage-gate reporting from the first load.

Findings, BRC-28
1
All programs
2
TypeScript
R1.run(ctx: CheckContext): Finding[]
Run R1 in the SQL bench
Generated UAT scenarios

UAT-R1-P Given a program with gate G4 missing, or gate G3 dated on or before gate G2. When the check runs. Then one BLOCK finding per missing gate and per out-of-order gate pair, with the gate template as the proposed fix.

UAT-R1-N Given a record which meets the gate sequence integrity rule in full. When the check runs. Then no R1 finding appears for the record.

R2

Dependency logic

BLOCK

A successor which starts before its predecessor finishes makes the critical path meaningless. A loop stops any scheduler from computing dates.

Findings, BRC-28
2
All programs
6
TypeScript
R2.run(ctx: CheckContext): Finding[]
Run R2 in the SQL bench
Generated UAT scenarios

UAT-R2-P Given a finish-to-start dependency whose successor starts before predecessor finish plus lag, or three activities linked in a loop. When the check runs. Then one BLOCK finding per broken dependency and one per activity inside the loop.

UAT-R2-N Given a record which meets the dependency logic rule in full. When the check runs. Then no R2 finding appears for the record.

R3

Working calendar

REVIEW

A milestone on a weekend or holiday usually means the legacy tool stored calendar days. The row loads, but the date needs a decision.

Findings, BRC-28
1
All programs
4
TypeScript
R3.run(ctx: CheckContext): Finding[]
Run R3 in the SQL bench
Generated UAT scenarios

UAT-R3-P Given a milestone dated on a Saturday. When the check runs. Then one REVIEW finding with a proposed shift to the next working day.

UAT-R3-N Given a record which meets the working calendar rule in full. When the check runs. Then no R3 finding appears for the record.

R4

Key reconciliation

BLOCK

Resource codes and cost centers must exist in the master lists. An unknown key either fails the load or lands hours on nobody.

Findings, BRC-28
1
All programs
3
TypeScript
R4.run(ctx: CheckContext): Finding[]
Run R4 in the SQL bench
Generated UAT scenarios

UAT-R4-P Given an assignment with resource code RES-0O7, which is not in the resource master. When the check runs. Then one BLOCK finding with the closest master code shown as a proposal, never applied automatically.

UAT-R4-N Given a record which meets the key reconciliation rule in full. When the check runs. Then no R4 finding appears for the record.

R5

Naming variants

REVIEW

One milestone spelled four ways splits every report which groups by name. The alias table maps each spelling to one canonical name.

Findings, BRC-28
1
All programs
3
TypeScript
R5.run(ctx: CheckContext): Finding[]
Run R5 in the SQL bench
Generated UAT scenarios

UAT-R5-P Given a milestone named "S.O.P." where the canonical name is "Start of production". When the check runs. Then one REVIEW finding proposing the rename to the canonical name.

UAT-R5-N Given a record which meets the naming variants rule in full. When the check runs. Then no R5 finding appears for the record.

R6

Over-allocation

REVIEW

Assigned hours above capacity in a month mean the plan relies on time nobody has. The plan loads, and resource planning decides what moves.

Findings, BRC-28
1
All programs
3
TypeScript
R6.run(ctx: CheckContext): Finding[]
Run R6 in the SQL bench
Generated UAT scenarios

UAT-R6-P Given resource RES-011 assigned 140 percent of capacity in 2027-05. When the check runs. Then one REVIEW finding naming the resource, the period, assigned hours, and capacity.

UAT-R6-N Given a record which meets the over-allocation rule in full. When the check runs. Then no R6 finding appears for the record.

R7

Baseline drift

REVIEW

A current date far from the approved baseline with no change record is an unapproved slip. The PMO decides whether to re-baseline or log the change.

Findings, BRC-28
1
All programs
3
TypeScript
R7.run(ctx: CheckContext): Finding[]
Run R7 in the SQL bench
Generated UAT scenarios

UAT-R7-P Given a milestone 24 days from its baseline with no change record. When the check runs. Then one REVIEW finding with the drift in days and a request for a change record.

UAT-R7-N Given a record which meets the baseline drift rule in full. When the check runs. Then no R7 finding appears for the record.

R8

Financial rollup

BLOCK

A parent budget must equal the sum of its children, in the program currency. Otherwise portfolio totals disagree with program totals on day one.

Findings, BRC-28
1
All programs
3
TypeScript
R8.run(ctx: CheckContext): Finding[]
Run R8 in the SQL bench
Generated UAT scenarios

UAT-R8-P Given a WBS parent whose budget differs from the sum of its children by 25,000. When the check runs. Then one BLOCK finding showing the parent budget, the children total, and the difference.

UAT-R8-N Given a record which meets the financial rollup rule in full. When the check runs. Then no R8 finding appears for the record.

R9

Orphans

BLOCK

An activity without a parent WBS node has no cost owner and drops out of every rollup. The loader rejects the row or parks the activity outside the structure.

Findings, BRC-28
1
All programs
2
TypeScript
R9.run(ctx: CheckContext): Finding[]
Run R9 in the SQL bench
Generated UAT scenarios

UAT-R9-P Given an activity pointing to WBS BRC-W99, which does not exist. When the check runs. Then one BLOCK finding naming the activity and the missing WBS node.

UAT-R9-N Given a record which meets the orphans rule in full. When the check runs. Then no R9 finding appears for the record.

R10

Required fields for load

BLOCK

A required field left empty either fails the row or, worse, loads with a default nobody chose. The mapping table marks which fields the loader needs.

Findings, BRC-28
1
All programs
2
TypeScript
R10.run(ctx: CheckContext): Finding[]
Run R10 in the SQL bench
Generated UAT scenarios

UAT-R10-P Given a milestone row with an empty owner, where owner is marked required in the mapping. When the check runs. Then one BLOCK finding naming the row and the empty field.

UAT-R10-N Given a record which meets the required fields for load rule in full. When the check runs. Then no R10 finding appears for the record.

Sheet index

  1. 01CoverWho built Redline, what the check does, and where to start.
  2. 02The checkThe working tool: programs, rules, trace, ledger, gate, SQL bench, drift.2 of 3 blockedBLOCK
  3. 03Case studyContext, observations, solution, measurement plan, and limits.
  4. 04Readiness auditPrioritized findings with evidence, printable.
  5. 05WorkbookSix guided exercises on the sample data.
  6. 06First 90 daysSix two-week sprints with stories and acceptance criteria.
  7. 07FitRequirement to evidence map, with the gaps stated plainly.
  8. 08SystemTokens, components, motion spec, and how to adapt the set.
  9. ATTAttachmentsResume, cover letter, sample data, and session exports.

Arrow keys move. Enter opens. Esc closes.