Home / Platform / Deterministic compliance engine
Core component · Implemented

The rules that decide before anything is asked of a model.

The compliance engine is the first gate every billing line passes through. It accepts a typed payload, applies versioned rules that a person can read, recalculates the affected values, and returns a structured result. It reaches no conclusion it cannot attribute to a named rule — and it never approves anything.

Component
DeterministicComplianceEngineSingle exported class, one public method
Entry point
evaluatePayload()RawBillingPayload → ProcessedOutput
Rule families
TwoProhibited overhead · semantic vagueness
Model involvement
NoneDeterministic throughout; may only request review
Element 01

What the engine is allowed to see

The engine accepts exactly five fields. There is no client record, no matter history, no timekeeper file, and no prior invoice. This is deliberate: a rule that cannot reach outside its payload produces the same answer every time it is given the same input, which is what makes the result reproducible in an audit.

RawBillingPayload — the complete input surface
FieldTypeWhat it carries and why the engine needs it
line_item_idstringThe identity of the billing line. Carried through untouched so a finding can be traced back to the exact source row in the original file.
timekeeper_rolestringThe role that recorded the time. Present in the contract and available to rules; the two rules shipped today do not branch on it.
hourly_rate_usdnumberThe rate applied to the line. Used only as a multiplier — the engine never questions or alters the rate itself.
hours_loggednumberThe hours as submitted. This is the figure a deduction reduces, and the baseline every calculation compares against.
raw_narrative_textstringThe free-text description of the work. Every rule in both families reads this field and nothing else.
Why this matters to a reviewer Because the input is closed, any two runs over the same invoice produce identical findings. A disagreement about an adjustment becomes a disagreement about a rule — which can be resolved by reading the rule — rather than a disagreement about a system's mood.
Input contractTypeScript
export interface RawBillingPayload {
  line_item_id: string;
  timekeeper_role: string;
  hourly_rate_usd: number;
  hours_logged: number;
  raw_narrative_text: string;
}

export interface RuleViolation {
  rule_id: string;
  description: string;
  action: 'STRIP_AND_RECALCULATE'
        | 'FLAG_FOR_AI_CONSENSUS_REWRITE';
}
Element 02 · Rule family A

Prohibited administrative overhead

The first family answers a question with an objectively correct answer: does this narrative describe work the guidelines say cannot be billed at all? Printing, photocopying and scanning are administrative overhead under a common Outside Counsel Guideline. No interpretation is required to recognise them, so no interpretation is invited.

OCG-04-NO-PRINTING

Administrative overhead is not billable

The engine holds a map of prohibited terms. If the narrative contains any of them, the rule fires once per matching term.

printphotocopyscan
STRIP_AND_RECALCULATE
CONSEQUENCE

A flat half-hour deduction

Each match reduces billable hours by a fixed 0.5, floored at zero so a line can never go negative. The deduction is a policy constant, not an estimate of how long the printing actually took.

adjustedHours = max(0, hours − 0.5)
DETERMINISTIC
CONSEQUENCE

The offending clause is removed

A regular expression removes the clause containing the term, bounded by the nearest comma, period or semicolon, leaving the remaining narrative intact for the next stage.

[^,.;]*\bkeyword\b[^,.;]*[,.;]?
DETERMINISTIC
The flat deduction is a policy decision, and it is visible Half an hour is what the rule asserts administrative bloat is worth on a line — it is not measured. Two consequences follow, and both are intentional in a deterministic system: the same narrative always yields the same deduction, and a narrative containing several prohibited terms is deducted several times. Section 8 shows exactly when that compounds.
Element 03 · Rule family B

Semantic vagueness — where the engine stops

The second family answers a different kind of question: is this narrative specific enough for a client to understand what they paid for? That question has no mechanical answer. “Research” may be perfectly adequate on one line and unacceptably thin on another, and only the surrounding context decides.

So the engine does not decide. It records that a judgment is required, sets a flag, and stops. No hours are deducted and no money moves when this family fires.

OCG-11-BLOCK-VAGUE-RESEARCH

Narrative lacks specificity

Terms that describe a category of work rather than the work itself are escalated for semantic review.

researchreviewfile prep
FLAG_FOR_AI_CONSENSUS_REWRITE
CONSEQUENCE

A flag, not a finding

needs_ai_consensus becomes true. The orchestrator reads that flag and routes the line onward. The engine has expressed no opinion about whether the line is acceptable.

needs_ai_consensus: true
NO FINANCIAL EFFECT
This is the architectural boundary of the whole product Everything a rule can settle is settled here, cheaply and repeatably. Everything requiring interpretation is isolated and handed onward under controls — and even then, consensus produces evidence, never approval. Authority to change a dollar remains with a named person. See how controlled consensus works →
Element 04

The arithmetic, in full

Four numbers, three multiplications, one subtraction. The engine performs no other financial operation. Below is the documented worked example, executed step by step exactly as the code executes it.

1

Submitted line. Senior Associate, 4.5 hours at $650/hour. Narrative mentions both research and printing.

4.5 h
2

Original value. hours_logged × hourly_rate_usd — the baseline everything is measured against.

$2,925.00
3

OCG-04 fires on print. One match, one flat deduction of 0.5 hours.

−0.5 h
4

Adjusted hours. max(0, 4.5 − 0.5)

4.0 h
5

Adjusted value. adjusted_hours × hourly_rate_usd. The rate is untouched.

$2,600.00
6

OCG-11 fires on research. Flag set, no hours deducted, no effect on either value.

±$0.00
=

Calculated adjustment. original_value − adjusted_value

$325.00
The calculationevaluatePayload()
const originalValue =
  payload.hours_logged * payload.hourly_rate_usd;

const adjustedValue =
  adjustedHours * payload.hourly_rate_usd;

const leakagePrevented =
  originalValue - adjustedValue;
A note on the field name The output field is called revenue_leakage_prevented_usd. It is a calculated figure: the arithmetic difference the rules produced. It is not realised savings, and it is not payable-amount guidance, until an authorised reviewer establishes a disposition on the line. The demonstration and the investor material both report proposed and authorised adjustments separately for exactly this reason.
Element 05

What comes back, and who consumes it

Every field in the result exists because something downstream needs it. Original values are retained alongside adjusted ones so that no comparison requires re-reading the source file, and every finding keeps its rule identifier so an adjustment can always be attributed.

ProcessedOutput — the complete return surface
FieldTypeMeaningConsumed by
original_hoursnumberHours as submitted, preserved unchanged.Audit comparison
adjusted_hoursnumberHours after all deterministic deductions, floored at zero.Resulting invoice
original_value_usdnumberSubmitted hours × rate.Audit comparison
adjusted_value_usdnumberAdjusted hours × the same untouched rate.Resulting invoice
revenue_leakage_prevented_usdnumberThe arithmetic difference between the two values above. Calculated, not realised.Reporting · reviewer context
violations_detectedRuleViolation[]Every finding, each carrying its rule identifier, human-readable description and action.Audit trail · reviewer display
needs_ai_consensusbooleanWhether any finding requires semantic review the engine will not perform.Orchestrator routing
sanitized_narrative_basestringThe narrative with prohibited clauses removed and punctuation tidied — the starting text for any downstream rewrite.Consensus wrapper
Nothing in this contract says “approved” There is no approval field, because the engine has no authority to grant one. It reports what rules found and what the arithmetic produced. Disposition is established later, by a person, and recorded separately.
Element 06

Order of operations — and why it is not arbitrary

The two rule families run in sequence, not in parallel, and the sequence changes the result. Administrative rules run first and modify the working text. Vagueness rules then run against the already-stripped narrative, not against the original.

Execution sequencesimplified
// Phase 1 — administrative overhead
for (const [keyword, description] of forbiddenKeywords) {
  if (textBuffer.toLowerCase().includes(keyword)) {
    violations.push({ /* OCG-04 */ });
    adjustedHours = Math.max(0, adjustedHours - 0.5);
    textBuffer = textBuffer.replace(regex, '').trim();
  }
}

// Phase 2 — runs against the MODIFIED buffer
for (const vagueWord of vagueKeywords) {
  if (textBuffer.toLowerCase().includes(vagueWord)) {
    violations.push({ /* OCG-11 */ });
    needsAiConsensus = true;
  }
}
The practical effect If a vague term sits inside a clause that phase 1 removes, phase 2 never sees it — and the line is not escalated. Consider “Photocopy of research memoranda for the file.” Phase 1 matches photocopy and removes the entire clause up to the period. By the time phase 2 runs, research no longer exists in the buffer. The line takes its 0.5-hour deduction and clears with needs_ai_consensus: false — never flagged for semantic review.
Whether that is correct is a policy question, not a bug An argument exists both ways: the removed clause is no longer being billed, so arguably needs no rewrite. The point is that the behaviour is knowable — you can read the order, predict the outcome, and configure it deliberately. Load the Order effect preset in the next section to watch it happen.
Element 07

Run the engine yourself

This is the rule logic described above, ported faithfully to the browser — the same keyword maps, the same 0.5-hour constant, the same strip expression, the same order. Change any field and the result recalculates immediately. Nothing is transmitted; everything runs on this page.

Deterministic evaluator · live
— 0 findings
original_hours—
adjusted_hours—
original_value_usd—
adjusted_value_usd—
calculated adjustment—
needs_ai_consensus—
    Narrative as submitted — struck = administrative match, marked = vagueness match
    sanitized_narrative_base — what the next stage receives
    Inspect the full ProcessedOutput contract
    
                
    Suggested sequence Start with the documented example and confirm $2,925 → $2,600. Switch to Multiple admin terms to watch three matches compound into a 1.5-hour deduction. Then open False positive and read what the engine does to a deposition of Dr. Scanlon.
    Element 08

    Documented boundaries of the current implementation

    The following behaviours are present in the implementation as supplied. They are published here because a reviewer will find them in ten minutes, and because a system that claims determinism has to be willing to state precisely what it currently does. Each is reproducible in the evaluator above.

    B-1 · Detection and removal disagree

    A deduction can fire while the text is left intact

    Detection uses a substring test, but removal requires a whole-word match. Inflected forms are therefore detected and deducted, yet never stripped — so sanitized_narrative_base can still contain the clause the output implies was removed.

    "printed and collated binders"
    includes("print")  → true   → −0.5 h
    /\bprint\b/        → no match → text unchanged
    B-2 · Unbounded substring matching

    Ordinary legal language triggers deductions

    Because matching is not word-bounded, any word containing a prohibited term matches. A deposition of a witness named Scanlon and a reference to blueprint specifications each register as administrative overhead.

    "deposition of Dr. Scanlon"     → "scan"  → −0.5 h
    "the blueprint specifications"  → "print" → −0.5 h
    Result: 3.0 h → 2.0 h, $900 deducted
    B-3 · Repeated deduction, one rule

    Several terms compound into several deductions

    The loop fires once per prohibited term present, each time deducting a further 0.5 hours and each time appending a violation carrying the same rule identifier — so a reviewer sees OCG-04 listed more than once for a single line.

    "Printed pleadings; scan of correspondence"
    → 2 × OCG-04 → −1.0 h
    → violations_detected.length === 2
    B-4 · Rules are compiled in

    Keywords and the deduction constant are literals

    The keyword maps and the 0.5-hour figure are declared inside the class. Per-client Outside Counsel Guidelines, rule versioning, effective dates and exception handling are not yet externalised — changing a rule currently means changing code.

    private forbiddenKeywords = new Map([...]);
    private vagueKeywords = ['research', ...];
    adjustedHours - 0.5
    Why these are tractable Every item above is a property of the rule layer, not of the architecture. Word-boundary matching, a per-rule deduction policy, one finding per rule, and externalised versioned configuration are each a contained change to a component that already has a defined input, a defined output, and no hidden state. The separation of settled questions from interpretive ones — the part that is difficult to retrofit — is already in place.
    Element 09

    What this component is, and what it is not

    DRE addresses outside-counsel billing and Outside Counsel Guidelines review for corporate legal departments. The compliance engine occupies one clearly bounded position inside that scope.

    It does

    • Resolve objective guideline questions deterministically
    • Recalculate hours and values from explicit rules
    • Preserve original values beside adjusted ones
    • Attribute every finding to a named rule identifier
    • Identify lines requiring semantic review
    • Produce the sanitised text the next stage starts from

    It does not

    • Approve, reject or authorise any line
    • Call a model or depend on one
    • Interpret whether a narrative is adequate
    • Question or alter an hourly rate
    • Read client, matter or timekeeper records
    • Write to any downstream financial system
    Product scope DRE is a legal-billing review platform. It is not a matter-management, document-management, CRM, timekeeping or trust-accounting system. Medical, HIPAA and academic applications are outside the current product scope.
    Responsive system visual

    Deterministic billing compliance engine

    The live HTML and CSS rendering reflows for desktop, tablet, and mobile. The preserved source artwork is available for printing and circulation.