Waiting
Something sat in one state longer than the standard allows.
A lead unworked past the response window.
Finding where an operation stops matching the process everyone thinks is happening.
A method for any operation that records events. It reconstructs what actually happened from the records a business already keeps, then reports only what the evidence supports. Its first implementation runs on dealership CRM data.
Both gears turn. The trouble is where they meet.
Most operational problems aren't obvious failures. The software works, the automation runs, the report gets generated, and people follow the process. Something still gets lost between them.
Those gaps are hard to see because they sit between parts that each look fine on their own. The Diagnostic tests one question: can the event data a business already records expose those gaps reliably enough to produce a finding a manager can check?
It doesn't report what the process diagram says should happen. It reports what happened, the evidence behind it, and what the data can't establish.
Every finding names one of four causes. None of them is specific to cars: any operation with handoffs has all four.
Something sat in one state longer than the standard allows.
A lead unworked past the response window.
Responsibility existed in theory, but no one owns it in the record.
A lead assigned to someone who left.
The process kept going, but an exception dropped out of sight of the people meant to act on it.
A lead closed as lost that nobody ever spoke to.
Several records or paths stand for what should be one thing.
The same customer arriving from two sites.
One lead from a synthetic dealership export, shown exactly as each stage of the pipeline produced it. The customer details are invented. It plays on its own until you pick a stage.
The store exports its CRM's lead activity: one row per event. Nothing new is installed and no new source of truth is invented. This lead came in from Cars.com at 9:39 on a Tuesday morning.
| LeadID | Customer | Phone | Source | AssignedTo | ActivityType | Timestamp | |
|---|---|---|---|---|---|---|---|
| L100329 | Gregory Tucker | 817.488.4795 | susan11@example.org | Cars.com | B. Walsh | New Internet Lead | 09/15/2026 09:39 AM |
| L100329 | Gregory Tucker | 817.488.4795 | susan11@example.org | Cars.com | B. Walsh | Auto-Reply | 09/15/2026 09:39 AM |
| L100329 | Gregory Tucker | 817.488.4795 | susan11@example.org | Cars.com | B. Walsh | Lead Assigned | 09/15/2026 09:40 AM |
The full synthetic export: 4,227 activity rows across 703 leads, with duplicates, missing timestamps, departed owners and silent losses planted on purpose so the pipeline can be checked against a known answer.
Customer fields are replaced with a salted hash before any analysis, using a salt set for each engagement. The same customer always gets the same hash within a run, so duplicates can still be found. An entity-recognition model scrubs names and numbers out of free-text notes, and if it can't run, the stage stops instead of passing notes through.
| LeadID | Customer | Source | AssignedTo | ActivityType | Timestamp |
|---|---|---|---|---|---|
| L100329 | Gregory Tucker · 817… · susan11@… CUST-1A95366377 | Cars.com | B. Walsh | New Internet Lead | 09/15/2026 09:39 AM |
| L100329 | CUST-1A95366377 | Cars.com | B. Walsh | Auto-Reply | 09/15/2026 09:39 AM |
| L100329 | CUST-1A95366377 | Cars.com | B. Walsh | Lead Assigned | 09/15/2026 09:40 AM |
The redaction log records counts only, never the values it removed.
Every CRM names the same events differently. A mapping file translates each raw label into a common event, and the rows become a clean event log: what happened, when, to which case, and by whom.
A label the map doesn't know is refused, not guessed. In this run 3 rows had unmapped labels and 137 had unusable timestamps. All 140 went to a data-quality list instead of disappearing.
| case_id | activity | timestamp | resource |
|---|---|---|---|
| L100329 | New Internet Lead → Lead Received | 2026-09-15 09:39 | B. Walsh |
| L100329 | Auto-Reply → Auto Response | 2026-09-15 09:39 | B. Walsh |
| L100329 | Lead Assigned → Lead Assigned | 2026-09-15 09:40 | B. Walsh |
Changing CRMs means writing a new mapping file. The analysis code doesn't change.
A lead being created isn't interesting by itself. Neither is an assignment. The information is in the relationship between events, and in what never followed them.
Time is measured in the store's business hours, so a lead that arrives after close starts aging at the next opening.
Every rule belongs to the dealer: store hours, what counts as working a lead, how long a lead may wait. They live in a versioned file, and any rule still on a suggested value is printed in the report.
Two checks fail for this lead. The pipeline only measures. Naming the cause is an analyst's call, recorded with its evidence.
The lead lands on the next morning's exception list, routed to the person who can fix it. The list carries lead IDs, not customer details. The store looks the lead up in its own CRM.
Across the whole store, patterns like this one become findings, which have to pass the finding contract below before they reach a report.
Untouched 99.3 business hours. Owner not on active staff list.
→ Sales manager: assign an ownerIn this synthetic run the classifier recovered every planted case it was built to find. A test checks that on every change.
Each boundary exists so one kind of change can't break another.
Changing how a CRM names an activity means editing a mapping file, not rewriting the analysis.
Changing an operating standard is a versioned config change. It never rewrites the historical evidence.
The report layer can't make a weak finding stronger by writing more confident prose.
A finding is a structured record, not a paragraph, and missing evidence makes it weaker, never louder. Switch the evidence on and off to see how the rules respond. This is a simplified version of the schema the pipeline enforces.
A clean result is only reported as clean when coverage is established. Otherwise the report says there wasn't enough evidence to know.
The happy path is the easy part. These are the cases the code actually handles.
A preflight check runs before any analysis and answers READY or NOT READY. Anything short of a pass, including a check it couldn't run, means not ready. Known missing periods mark the result incomplete, so a clean result is never reported over a gap.
An unknown label is refused, not guessed, and logged as a data-quality item. The preflight blocks until every raw label has a meaning in the mapping file.
Matching leads are grouped into one opportunity, so the same customer isn't counted twice. Known gap: matching is exact today (same name and phone). Real exports format phones differently, and fuzzy matching isn't built yet.
Every owner is checked against the store's staff list. A blank owner or someone no longer active makes the lead unowned, and it's routed to the sales manager to reassign.
A lead with no usable received time goes to the data-quality list, not the findings. Events dated before the lead arrived, or in the future, are flagged the same way. Nothing is silently dropped.
Findings from different methods are only merged when a person declares the link, and only within the same workflow. Nothing is merged because it looks similar.
Analyst notes can add evidence but can never create a finding or change a pipeline fact. If one tries, the run fails and writes nothing. Every sentence in the report is traced back to its source, and a headline can't contain numbers, so it can't disagree with the counts.
It doesn't go there. The repository and its automated tests only ever see synthetic data. Real exports stay in the store's own isolated environment under a data agreement.
1,000automated tests, all passing. The number matters less than what they protect.
Dealerships are the first implementation, not the definition. Every business has its own systems and its own standards, so every engagement starts by mapping one and declaring the other. The rest of the method is the same everywhere.
Every engagement includes both steps, dealerships too. The mappings and rules written so far are for a dealership CRM.
Tickets that wait past the response standard, or sit with a technician who's off the schedule.
Referrals received but never scheduled, or entered twice from fax and portal.
Demo requests assigned to a rep who left, with nobody noticing them go quiet.
Examples of where the same method would apply. None of them has been run.
Engineering evidence isn't the same as proof in a live operation. Both steps are listed.
Export to morning list and finding report, checked against a dataset where the right answer is known.
The next real test: whether the same system survives a real export's inconsistencies and produces findings the business can check for itself.
The problem, the assumption, the system, and what comes next.