Skip to main content
DoneThat

AI Adoption GuideGovernmentEnforce

Penalty calibration engine

RAG over historical enforcement decisions recommends proportionate penalties consistent with precedent, reducing inter-officer inconsistency.

Government processPlanFundAuthorizeDeliverInspectEnforceReportClose

By Don, DoneThat’s AI coach · updated

What the officer should receive

The engine's job is a quality check on consistency, not a decision. It should return a recommended penalty band that cites the matching row in the adopted penalty schedule and a short set of comparable closed cases. The officer still sets the penalty.

If the schedule has no row for the offense as charged, the recommendation field stays empty. An empty field is a correct result. Filling it with a guessed dollar figure, a typical municipal fine, or a ceiling the statute never wrote is a failure, even when the guess looks reasonable.

The output is only useful if every recommendation can be unpacked: which schedule instrument, which row, which closed files, and why those files are comparable. An officer who cannot see the cites cannot defend the number they type into the order.

Load the schedule and the comparable file first

Do not retrieve similar penalties from a mixed corpus and then hunt for a schedule row that fits. Load two sources in a fixed order.

First, load the currently adopted penalty schedule, or the statutory table the schedule implements, for the charging provision on the file. The schedule is the only source that may define a band. Version it. A superseded table in a document library is not the schedule in force. When you load the row, bind the row identifier, instrument version, and charging provision as structured fields. A free-text paste of the table is not a load: it cannot be cited later, and it cannot stay empty when no row matches.

Second, retrieve closed enforcement files that share the same charging provision, the same aggravating or mitigating flags the schedule actually uses (first offense versus repeat, cooperation, harm class), and a recorded outcome. Comparables explain how officers have used the band. They do not create a band the schedule omitted. For comparables, bind the closed-file identifiers, the schedule flags used to match, and the recorded outcome. Snippets without a file id are not comparables.

Permitting, licensing, and case systems from vendors such as Accela, Tyler, LexisNexis, and Microsoft often hold pieces of this picture: the adopted table, the charging history, the closed-case narrative, and the legal research trail. Treat them as a class of systems of record. The engine should read the schedule row and the closed files those systems already store. It should not invent a tariff those systems never published.

Before calibration, confirm the charge is the charge. If evidence is still thin, send the file through the evidence sufficiency assessor rather than asking the engine to price an offense that may not survive.

Recommend a cited band, not an amount

Once both sources are loaded, the recommendation is a band with two kinds of citation, not a dollar amount.

Cite the schedule row: instrument name, effective date, charging provision, offense class, and the published minimum-to-maximum (or the named steps the table uses) for that row. If the row distinguishes first, second, and subsequent offenses, name the step that matches the file's history. Do not collapse those steps into one average because averages are easier to display.

Cite the comparables: a small set of closed cases with the same provision and the same schedule flags, each with enough identifiers that a reviewer can open the file. State where those outcomes sat inside the published band (low, mid, high, or at a named step). Do not compute a mean and present it as the recommendation. A mean is not a schedule row.

The officer then types the amount. The engine may show where similar closed files landed inside the band so the officer can see whether they are about to sit as an outlier. Outlier is a prompt to write reasons, not a prompt to overwrite the officer.

Consider a second food-safety offense at a restaurant, same operator, same premises, within the lookback the schedule uses for repeat. The engine matches the repeat row for that class of food-safety offense, lists three closed files with the same provision and repeat flag, and notes that those files used the lower half of that row's band because the operator had already closed the immediate risk before the hearing. It does not type a fine. The officer reads the row, reads why those three files sat low, and either follows that pattern with a short reason or departs from it with a short reason. The band and the cites stay on the file either way.

Leave the field empty when the schedule is silent

Silence is not a gap to fill. If the charging provision has no schedule row, if the row exists but does not cover this aggravator, or if the only range in the corpus is unwritten practice, the recommendation stays blank.

A blank field should be explicit in the interface: no schedule row for this charge; the officer sets the penalty from the statute and reasons, without a calibrated band. That sentence is the product. A generated number in that slot is a liability.

A number with no schedule row is the first failure. The retrieval stack finds closed files, a briefing note, or a neighboring jurisdiction's tariff and emits a figure. That figure has no legal home on this file. Block it. Do not soften the block by labeling the figure indicative.

Treating the band as the order is the second. The officer, or a downstream template, copies the recommended band, or its midpoint, into the penalty field as if the engine had decided. The order then recites a machine output instead of an officer's determination. The band is advice. The order is the officer's.

Inventing a maximum the statute never set is the third. When the schedule is silent, some stacks fill the gap by proposing a ceiling drawn from a different offense class, a default in another chapter, or a round number that feels proportionate. If the statute did not set that maximum, the engine must not. Proportionate is an officer judgment under the statute, not a retrieved neighbor.

If the right path is conditions rather than a penalty, stop calibrating and route to the condition generator for approvals. Pricing a penalty the file does not need is another way of filling a blank.

Keep the recommendation out of the order until the officer writes it

The quality bar is that a reviewer can reconstruct why this band was offered and can see that the officer, not the retrieval, chose the amount.

Store the recommendation as a distinct object: schedule cite, comparable cites, recommended band, and a null amount field the officer fills. Do not merge those fields in the case record. If the officer adopts the low end, the mid, or a departure, the reasons field must be theirs.

When the notice is drafted, the enforcement notice drafter should pull the officer's amount and reasons, plus the schedule row the officer relied on. It should not pull the engine's band as if it were the operative penalty. If the notice template cannot tell those two fields apart, fix the template before you switch the engine on.

After the order, the post-enforcement compliance monitor tracks whether the respondent paid, remedied, or breached. It does not re-open calibration. A later breach may start a new file with a new schedule step, for example a subsequent-offense row. That is a new recommendation, still empty if that step has no row.

Inconsistency across officers is the problem this engine is for. The fix is a shared, cited band and a human amount, not a quieter form of inconsistency in which every file gets a confident number the schedule never authorized.

Is this worth automating for you?

Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other.

DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.

Measure the baseline first