Measured, not asserted

Does obfuscation break contract time and liquidated damages?

An extension of contract time is a union of the calendar days on which excusable delay occurred, not the sum of the delay events' durations. Two excusable events that overlap extend the contract by the days they jointly cover, because a day already granted cannot be granted twice. This test made the engine add instead, and every delay event stayed genuine, every classification stayed correct, every record was used exactly once -- and $28,800.00 of the owner's remedy disappeared behind a review that passed and read better than the correct one.

Adding is the wrong operation, and nothing about the records says so

Contract time is a date arithmetic problem with one subtlety. When the contractor is entitled to more time, you do not add up the durations of the delay events; you work out which calendar days were actually affected and count those. If a differing site condition runs for twenty-two days and an owner-directed change runs for fourteen, and they overlap for nine, the contractor is entitled to twenty-seven days, not thirty-six. The nine overlapping days have already been granted once.

The fixture is a $24,000,000.00 building on a 480-calendar-day contract with liquidated damages at $3,200.00 per calendar day. Five delay events are on the record. A differing site condition runs days 120-141 and an owner-directed change runs days 133-146, overlapping for nine days. Abnormal weather runs days 300-308. A subcontractor default runs days 300-316 and is not excusable, so it buys nothing. A concurrent delay runs days 402-407.

The union of the excusable days is 27 plus 9 plus 6, which is 42. The adjusted completion date is day 522, substantial completion was certified on day 548, the project is 26 days late, and $83,200.00 of liquidated damages is assessed.

Add the four excusable durations instead and you get 51. That answer is arithmetically sound. It uses every record exactly once. It accounts for every event submitted. It is simply the wrong operation, and it is always at least as generous to the contractor as the right one.

Protection on its own moved nothing

Five areas, five presets, twenty-five comparisons, every one byte-identical to the unprotected run, under a guard that runs each original twice and refuses to compare anything against a fixture that will not reproduce itself.

Everything below required member renaming aimed at a name the installed contract-time engine also reads.

Both sides of the boundary reach the same wrong answer

Renaming the option that names the overlap policy reverts it to the library's default of summing, and the assessment reads extension=51days/sum adjusted-completion=531 late=17days assessed=$54400.00 => LIQUIDATED DAMAGES ASSESSED.

Renaming the field that carries each event's start day instead produces the identical money. Without a readable calendar window there are no intervals to merge, so the engine falls back to adding: $54400.00 again, from the other side of the boundary, by a completely different route.

$28,800.00 of the owner's contractual remedy is gone in both. And the verdict does not change: liquidated damages are assessed, so the mechanism is visibly working. All four excusable events are named on the output and every one of them is a real delay the contractor genuinely suffered. Nothing is undefined, nothing is NaN, no figure is implausible.

The configuration screen keeps telling you the policy is correct

The two routes differ in one respect and it is not the money. Renaming the option is honest about itself: the configuration line reads overlap-policy=sum(each excusable event extends the contract by its own duration). Somebody reviewing the settings would see it.

Renaming the record field does not. The configuration line still reads overlap-policy=union(a calendar day already granted is not granted twice). The policy is present, correct, and reported as in force. It is being applied to a calendar the engine cannot read, so it silently degrades to the operation it was chosen to avoid. The only tell anywhere in the output is the phrase [no readable calendar window], tucked inside a display field.

"Is the overlap policy configured correctly?" returns a true answer to the wrong question. The policy is configured correctly. It did not run.

The review rule passes, and the failing arm reads better than the correct one

The contract's own review rule is a sensible one: every delay event must have been considered, and the extension granted must not exceed the total delay claimed. It passed in both arms, and what it printed is the part worth staring at.

The correct run prints checked by time-check(5 event(s) reviewed, 42d granted of 51d claimed). The failing runs print checked by time-check(5 event(s) reviewed, 51d granted of 51d claimed).

Fifty-one of fifty-one looks like a complete, tidy, fully reconciled grant. Forty-two of fifty-one looks like something was disallowed and might need explaining. A reviewer scanning a project log for anomalies would stop on the correct line and skim past the wrong one. The check is not merely blind to this failure -- it certifies it, and it does so more convincingly than it certifies the truth.

The rule cannot do otherwise. It was written to catch an extension that is too large relative to what was claimed, and a sum is never larger than the sum it is compared against. Switching the rule off entirely, or replacing it with the library's builtin, produces exactly the same $54,400.00. It was contributing nothing to remove.

What the loud arms look like, for contrast

Renaming the list of excusable categories, or the field on each event that carries its category, grants nothing at all: extension=0d late=68days assessed=$217600.00. That is an over-assessment of $134,400.00 against a contractor with a documented differing site condition, and it is disputed the day the certificate arrives.

Renaming the delay durations themselves refused before assessment. Renaming the contract duration or the certified completion date refused as well. That contrast has now held for seventeen consecutive failure shapes in this series: losing a value fails closed and loud, losing what a value means fails open and quiet.

Two smaller arms round it out. Renaming the daily rate produces assessed=$0.00 still reported as LIQUIDATED DAMAGES ASSESSED -- an assessment of nothing, described as an assessment. Renaming the event identifiers leaves the $83,200.00 exactly right and prints granted=[undefined undefined undefined undefined]: the correct sum, with no record of which delays earned it. A contractor challenging an extension challenges a specific event, and that is the field that went.

What to do about it

Assert the relation, not the population. Every mitigation this series has validated -- completeness over records, conservation over totals, reconciliation against the far side -- is defined over items, and every one of them passes here. What is wrong is not any item but the operation taken across them. Assert that the extension equals the number of distinct calendar days covered, and name the first and last day of each granted window.

Test with an overlap in the fixture. If every delay event in your test data is disjoint, the union and the sum are the same number and this entire class of defect is invisible to your test suite by construction. One overlapping pair is enough.

Make an unreadable calendar window an error rather than a fallback. An engine that cannot date an event should refuse to grant time for it, not quietly switch to adding durations. That is worth doing regardless of obfuscation, because a dropped column in a schedule import produces the same silent fallback.

And report which operation ran, not which one is configured. The record-field arm above is the sharpest illustration in this pass of a distinction that keeps recurring: a control's telemetry must say that it ran, not that it exists. Those two sentences are one line apart in an options object, and only one of them is evidence.

Teams working to IEC 62443-style process requirements will find the framing familiar -- the standard cares about what your process demonstrably did, and a configuration screen is a statement of intent rather than a record of execution.

Frequently asked questions

Did obfuscation change any liquidated damages assessment on its own?

No. Five areas ran through five presets and every protected output was byte-identical to the unprotected run. Every failure here required member renaming aimed at a name the installed contract-time engine also reads.

What is the difference between a union and a sum of delay days?

An extension is the count of distinct calendar days on which excusable delay occurred. Two excusable events overlapping by nine days extend the contract by the days they jointly cover, not by their durations added together. A day already granted cannot be granted twice.

What did the failure actually cost?

The extension went from 42 days to 51, the adjusted completion date from day 522 to day 531, the project from 26 days late to 17, and the assessment from $83,200.00 to $54,400.00. Every delay event stayed genuine and every one was counted exactly once.

Would the configuration screen have shown the problem?

Only for one of the two routes. Renaming the overlap option makes the configuration line read 'sum'. Renaming the field that dates each event leaves it reading 'union', correctly, while the engine falls back to adding because it cannot read the calendar.

Did the contract's own review rule catch it?

No. It passed, and it read better in the failing arm than in the correct one: '51d granted of 51d claimed' looks complete, where the correct '42d granted of 51d claimed' looks like something was disallowed. The rule checks that an extension is not larger than what was claimed, and a sum never is.

Which arms failed loudly?

Losing the excusable categories, or the category on each event, granted nothing and assessed $217,600.00 instead of $83,200.00 -- an over-assessment a contractor disputes on sight. Losing the delay durations, the contract duration or the completion date refused outright.

What is the cheapest test that would have caught this?

Assess one known project end to end, with at least one overlapping pair of excusable delays in the fixture, and assert the extension in days and the assessment to the cent. If every delay in your test data is disjoint, the union and the sum agree and the defect is invisible by construction.

Related reading