DEV Community

Cover image for The date string that invented $725 in a synthetic margin report
Mike Riggs
Mike Riggs

Posted on

The date string that invented $725 in a synthetic margin report

Summer Bug Smash: Clear the Lineup 🐛🛹

This is a submission for DEV's Summer Bug Smash: Clear the Lineup, powered by Sentry.

Project Overview

I built LeakLens Control Room to keep AI away from the financial math. Python calculates every dollar. The optional model explains the evidence. A human decides whether to act.

LeakLens is a live, functional restaurant margin-review application built with Python, SQLite, HTML, CSS, and JavaScript. It uses synthetic data in the public demo. The optional application narrative provider defaults to GPT-5.6, but every rate, threshold, ranking, and dollar scenario comes from deterministic code.

Then a date string proved that deterministic code can still lie. I had let a raw CSV field decide which operating day counted as "current."

Bug Fix or Performance Improvement

The symptom

LeakLens groups channel metrics by date, sorts those dates, and analyzes the last one against prior days. That works when every input is canonical ISO data such as 2026-07-09.

The loader only checked that the date field was not blank. This input slipped through:

metrics = [
    DailyMetric("2026-7-9", "direct", 500, 250, 0, 0, 125),
    DailyMetric("2026-07-10", "direct", 1000, 50, 0, 0, 250),
]
Enter fullscreen mode Exit fullscreen mode

July 10 is later than July 9. Python's string ordering sees something else:

sorted(["2026-07-10", "2026-7-9"])
# ['2026-07-10', '2026-7-9']
Enter fullscreen mode Exit fullscreen mode

LeakLens selected the final string, 2026-7-9, as the current day. That mistake spread through the report:

expected current date: 2026-07-10
actual current date:   2026-7-9
actual gross sales:    500.00
sales-loss scenario:  500.00
discount scenario:    225.00
Enter fullscreen mode Exit fullscreen mode

The input had not shown a current sales collapse or discount leak. The analyzer compared the days backward and produced $725 of false scenario impact from synthetic data.

For a restaurant operator, this is worse than a visible crash. A crash asks for attention. A plausible financial report can send someone to audit the wrong promotion, question the wrong manager, or change a schedule that was working.

The root cause

The old analyzer stored the stripped CSV value directly:

metric = DailyMetric(
    date=row["date"].strip(),
    # financial fields omitted
)
Enter fullscreen mode Exit fullscreen mode

Later, it grouped and sorted the strings:

grouped[metric.date].append(metric)
dates = sorted(grouped)
current_date = dates[-1]
Enter fullscreen mode Exit fullscreen mode

The portfolio loader had the same path. Direct callers could also construct DailyMetric with any nonempty string.

I considered normalizing loose values such as 2026-7-9 into 2026-07-09. I rejected that approach. This system produces financial decision support, and silently guessing an input format creates another trust problem. The documented contract already says YYYY-MM-DD. Invalid or ambiguous data should stop before analysis.

Code

I wrote the failure first

Before changing production code, I added regression tests for four missing boundaries:

  1. A direct DailyMetric rejects a noncanonical date.
  2. A direct DailyMetric rejects an impossible date such as 2026-02-30.
  3. The single-store CSV loader reports an invalid date with the CSV line number.
  4. The portfolio loader does the same.

I also kept chronological tests for canonical dates in both analysis paths.

The focused suite failed four times on the original implementation:

FAIL: test_direct_metrics_reject_noncanonical_or_impossible_dates
      (bad_date='2026-7-2')
FAIL: test_direct_metrics_reject_noncanonical_or_impossible_dates
      (bad_date='2026-02-30')
FAIL: test_loader_reports_invalid_dates_with_line_context
FAIL: test_portfolio_loader_reports_invalid_dates_with_line_context
Ran 12 tests in 0.023s
FAILED (failures=4)
Enter fullscreen mode Exit fullscreen mode

That RED stage showed that the tests caught the observed bug rather than merely agreeing with the eventual implementation.

The fix

The final change puts the date invariant at the object boundary:

from datetime import date as Date

_CANONICAL_DATE = re.compile(r"\d{4}-\d{2}-\d{2}\Z")

@dataclass(frozen=True)
class DailyMetric:
    date: str
    # financial fields omitted

    def __post_init__(self) -> None:
        if not isinstance(self.date, str) or not _CANONICAL_DATE.fullmatch(self.date):
            raise ValueError("date must use YYYY-MM-DD")
        try:
            parsed = Date.fromisoformat(self.date)
        except ValueError as exc:
            raise ValueError("date must use YYYY-MM-DD") from exc
        if parsed.isoformat() != self.date:
            raise ValueError("date must use YYYY-MM-DD")
Enter fullscreen mode Exit fullscreen mode

The regex enforces the written shape. Date.fromisoformat proves the calendar date exists. The final round trip makes the canonical form explicit.

Both CSV loaders now separate numeric parsing from object construction. A broken amount still reports Invalid numeric value on CSV line N. A broken date reports Invalid date on CSV line N. The fix did not trade one misleading error for another.

The original reproduction now stops immediately:

ValueError: date must use YYYY-MM-DD
Enter fullscreen mode Exit fullscreen mode

The analyzer produces no report from malformed input, so the false scenario never reaches an operator.

My Improvements

Verification

The focused date and portfolio suite passes:

Ran 12 tests in 0.023s
OK
Enter fullscreen mode Exit fullscreen mode

The complete suite also passes:

Ran 28 tests in 0.073s
OK
Enter fullscreen mode Exit fullscreen mode

The change is public in LeakLens pull request #1, now merged into main at commit 7f98e05.

The live demo still uses synthetic data and deterministic financial calculations. It does not connect to a POS or execute restaurant changes.

How AI helped, and where it stopped

The LeakLens application defaults to GPT-5.6 for its optional narrative provider. Separately, GPT-5.5 through Codex performed the read-only bug audit and found the malformed-date path by probing beyond the existing tests. I reproduced the finding independently and constrained the repair to test-driven date validation. Codex implemented the narrow patch after the tests failed. Claude Opus through Claude Code on a Max subscription then reviewed the uncommitted diff in read-only Plan mode and returned READY FOR COMMIT.

The models did not choose the operating policy, publish the code, or decide that malformed financial data should be rejected rather than guessed. I made those calls and verified every command and result before merging.

Keeping a model away from arithmetic is useful, but it is not enough. Every boundary feeding deterministic code needs a contract strong enough to fail loudly before a tidy report makes bad data look trustworthy.

Top comments (0)