Clean Slate Eligibility Explorer — Hawaii

A proof of concept for Hawaii's Clean Slate effort. Pick an initiating agency below and see, record by record, which are eligible to be sealed — and why. All records shown are synthetic.

1 · IDENTIFY eligible records→ 2 · Notify agencies→ 3 · Update (seal) records

This page runs a set of plain eligibility rules over synthetic criminal records and shows which ones could be sealed automatically. Every decision comes with a reason, so you can follow the logic.

Clean Slate is started by one initiating agency. Different agencies keep different records, so the explorer lets you choose which agency is running the check and watch the results from that agency's own data. Switching agencies can change an answer — because a rule can only be applied when the agency actually holds the piece of information it needs.

This is the Identify step — the first of Clean Slate's three steps (Identify, Notify, Update). It shows eligible records can be found programmatically from data the agencies already have.

0
Eligible
0
Not eligible
0
Cannot determine
✓checking…

The rules you've dialed in

Show as

This rewrites itself as you change the controls above — it always states the exact rules currently in force. Every rule is a policy choice made to demonstrate feasibility, not a recommendation for Hawaii.

A look under the hood

Each agency's software reads its own records and applies the same rules. Some fields are structured; a records repository keeps the charge and sentence as free text that has to be read out — including the imposed sentence the waiting-period clock can use. The snippet shows the reading step and the shared rules.

reading the free text (statute, grade, and the imposed sentence) def parse_statute(text): # "…(HRS 708-0832)…" -> "708-832" m = re.search(r'HRS\s*§?\s*(\d{3}[A-Z]?)-0*(\d+)', text, re.I) return "%s-%s" % (m.group(1), m.group(2)) if m else None value, unit = parse_imposed_sentence(sentence_text) # "3 YEAR(S)…" -> (3, "year") the same eligibility rules, applied by whichever agency is running the check if disp in non_conviction_dispositions: # (1) non-conviction return ELIGIBLE # eligible right away if disp == "" and charges_filed != "yes": # repository arrest, no case filed return ELIGIBLE if today >= arrest + sol[grade] else NOT_ELIGIBLE if grade not in eligible_grades: # (2) grade must be eligible return NOT_ELIGIBLE if exclude_violent and code in crimes_of_violence: # (3a) optional carve-out return NOT_ELIGIBLE if exclude_sex and code in sex_offenses: # (3b) independent carve-out return NOT_ELIGIBLE if sentence == LIFE: # (4) life term — no end date return NOT_ELIGIBLE cl = clear_date(charge, model) # (5) waiting period: disposition (+ imposed sentence) + time return ELIGIBLE if today >= cl else NOT_ELIGIBLE

Highlighted lines are the shared rules; the lines above them are the reading step the free-text records need. Full source: the engine scripts for each agency.