Ike Lim← All projects

Case Study

Code Council

Regulatory change, propagated - a LegalTech pipeline built as the sole engineer in a team of three at SMU LIT Hackathon 2026.

Sep 2026

PythonFastAPISQLiteSQLModelAPSchedulerBM25LLMNext.jsReactTailwind CSS

The problem

The hackathon theme was "Designing a Sustainable and Resilient LegalTech": how might legal teams build tools that are resilient to regulatory change, not just responsive to it? Law firms run on template clauses, playbooks and advisories that silently assume the rules stay still - the moment an amendment lands, every document that encoded the old rule becomes a liability, and nobody knows which ones they are.

Alert services already exist, but they all stop at a notification. The lawyer still has to find the affected documents, read them, decide how each is affected, draft the amendment and tell everyone who relies on it. I built Code Council with two law-student teammates to close that gap between alert and amended document.

Code Council dashboard listing open tasks raised by parliamentary items
The landing dashboard - tasks raised by regulatory change

The approach

Every contract (PDF or DOCX) is split into individually addressed clauses, written to a plain-markdown vault and tagged with legal concepts to form a graph. Stable anchors such as warehouse-lease#7-2 survive re-ingestion, so proposals and edits made months ago still point at the right text.

A scheduler scrapes Singapore's parliamentary record every day at 07:00 SGT. Each new item passes a cheap retrieval gate - BM25 over clause text plus concept-tag overlap, keeping the top five candidate clauses - because judging every item against every clause with an LLM is neither affordable nor fast. Only the survivors go to an LLM judge, which returns whether the clause is impacted, the severity, a written rationale and suggested replacement text.

Documents page grouping the firm's contracts by practice sector with clause counts and versions
The firm's documents, grouped by practice sector

Understanding the impact

The judge's suggestion is rendered as a word-level redline against the clause as it stands today, alongside the rationale for why it was flagged - so a lawyer reviews a specific, explained change rather than a raw alert.

Clause-level redline showing deleted and inserted words with the reason the clause was flagged
Word-level redlines with the reason each clause was flagged

Propagating the fix

A human approves every change - the system proposes, it never amends on its own. Approval rewrites the clause in the vault, bumps the document version, records an immutable edit holding the before-text, and notifies every lawyer linked to that document.

Inbox of notifications telling lawyers which document clauses were updated
Approved changes fan out to every linked lawyer

Design decisions

The markdown vault, not the database, is the source of truth for content - Obsidian opens it, git diff reads it, and a lawyer can edit it with no software at all. SQLite holds only state, relations and workflow.

Nothing has to leave the firm: the LLM sits behind a provider interface with an on-prem Ollama option, so swapping models is one config line. The parliamentary feed is the first source, not the only one - everything downstream runs on normalised items. And a full daily run replays end to end with the network unplugged, which is how the live demo was guaranteed to work on stage.

The outcome

On the demo corpus, the running system ingested 10 documents across 4 practice sectors - 509 addressed clauses and 125 legal concepts with 942 clause-concept links. From 168 parliamentary items in a single sitting, the gate and judge produced 2 tasks, 3 document reviews and 7 clause-level redlines, routed to 4 lawyers across 20 document links. The backend ships with 125 passing tests.

Affected documents for a task, each listing the clauses flagged for amendment
Documents affected by a single regulatory change

Learnings

Being the only engineer on a team with two law students meant translating legal workflow into system design on a hackathon clock. The biggest lesson was where to spend the model: cheap lexical and structural filtering does the elimination, and the LLM is reserved for the judgment that actually needs it.