Rex Automaton
All posts
Operations & Admin AutomationSeptember 23, 20269 min read

BC CRT Small Claims: How We Automated Evidence for Theology Academy

Case study: we built an AI-backed evidence workflow for a BC CRT small-claims dispute at Theology Academy. It assembles timelines, hashes artifacts, and drafts point-by-point replies.

By Jacky Lei

We built and shipped an AI-backed evidence workflow for a BC Civil Resolution Tribunal small-claims dispute involving Theology Academy. The system ingests artifacts across email, videos, logs and contracts, hashes and indexes them, builds a defensible timeline, and drafts point-by-point replies that map to the contract scope and acceptance terms.

Dispute-evidence automation is the process of collecting, verifying, organizing, and summarizing case artifacts into a defensible package with minimal manual effort.

The problem it solves

Most small-claims disputes are not won on rhetoric. They turn on documentation quality: what was agreed, what was delivered, and when. For Theology Academy, artifacts were spread across multiple inboxes, meeting transcripts, Make.com logs with short retention, and a contract with unclear refund/termination language. Manually assembling a chain-of-custody timeline and a numbered evidence pack would take days and risk omissions.

TaskManual approachAutomated workflow
Collect artifactsSearch multiple inboxes and drives, download files piecemealSingle intake folder with auto-ingest and file hashes written to a manifest
Prove integrityRely on file dates and screenshotsCompute SHA-256 per file, store manifest, lock timestamps
Build timelineHand-write dates from emails and notesAuto-extract dates, normalize timezones, render a single event log
Map to contractSkim SOW and meeting notes, hope to matchClause-to-evidence linking and a reply template that cites exhibits
Draft rebuttalStart from a blank doc each timeAI drafts a point-by-point response with inline exhibit references
Package for CRTStitch PDFs by handOne-click export: index + exhibits in numbered order

How the automation works

The architecture centers on a defensible pipeline: one evidence inbox, immutable hashing and manifests, a normalized timeline, and a drafting stage that never invents facts. We keep model outputs gated by human approval before anything is filed.

  • Evidence intake: A dedicated Drive folder and inbox rule catch all dispute-relevant artifacts. A watcher writes filename, SHA-256, size, and first-seen timestamp to a manifest.
  • Chain of custody: We preserve originals and generate read-only exports for emails, transcripts, and logs. Edits create new versions with new hashes.
  • Timeline builder: Filenames and headers are parsed for dates, then normalized to one timezone and sorted. Events are de-duplicated and labeled.
  • Contract mapper: A scope matrix links SOW clauses to acceptance checkpoints and delivery proofs.
  • AI reply drafting: The model converts the scope matrix and timeline into a numbered, point-by-point reply that cites exhibits and never fabricates values. A human reviews and edits.

BC CRT dispute evidence workflow: evidence intake feeds a hashed manifest, the Evidence Engine builds a timeline and contract map, then a drafting stage produces a point-by-point reply and an indexed CRT package

Step-by-step: how to build it

1) Set up a single evidence inbox and intake folder

Create a dedicated email label and a Drive folder for the dispute. Forward or move all artifacts here. A small daemon writes a manifest row per file.

# evidence_intake.py
import hashlib, json, os, time
from pathlib import Path
 
INTAKE = Path("./evidence_intake")
MANIFEST = Path("./manifest.jsonl")
 
def sha256sum(p: Path) -> str:
    h = hashlib.sha256()
    with p.open('rb') as f:
        for chunk in iter(lambda: f.read(1024 * 1024), b''):
            h.update(chunk)
    return h.hexdigest()
 
def scan_once():
    rows = []
    for p in INTAKE.rglob("*"):
        if p.is_file():
            rows.append({
                "path": str(p.relative_to(INTAKE)),
                "hash": sha256sum(p),
                "bytes": p.stat().st_size,
                "first_seen": int(time.time())
            })
    with MANIFEST.open('a', encoding='utf-8') as out:
        for r in rows:
            out.write(json.dumps(r) + "\n")
 
if __name__ == "__main__":
    INTAKE.mkdir(parents=True, exist_ok=True)
    scan_once()

Gotcha: keep this write-once. Edits create a new copy in an Updates subfolder so the original hash remains intact.

2) Normalize emails and meeting transcripts into PDFs

Export emails and transcripts to PDFs to avoid mutable web views. Store the source message IDs alongside the file so you can trace back if needed.

# example ops script
mkdir -p exports/emails exports/transcripts
# Use your mail client or a script to export .eml -> .pdf and transcripts -> .pdf
# Record a simple CSV map: pdf_path,source_id,source_system

Key point: never edit the exported PDFs. If redaction is needed, save a redacted copy and keep both with distinct hashes.

3) Build a unified timeline from filenames and headers

Pull dates from filenames, email headers, and document metadata, then normalize to one timezone.

# timeline.py
import csv, json, re
from datetime import datetime
from zoneinfo import ZoneInfo
 
TZ = ZoneInfo("America/Vancouver")
DATE_RE = re.compile(r"(20\d{2}-\d{2}-\d{2})[ T_]?([0-2]\d:[0-5]\d)?")
 
sources = []
with open("manifest.jsonl", encoding='utf-8') as f:
    for line in f:
        row = json.loads(line)
        m = DATE_RE.search(row["path"]) or None
        dt = None
        if m:
            date = m.group(1)
            time_s = m.group(2) or "00:00"
            dt = datetime.fromisoformat(f"{date}T{time_s}").replace(tzinfo=TZ)
        sources.append({
            "when": dt.isoformat() if dt else None,
            "artifact": row["path"],
            "hash": row["hash"]
        })
 
# Write a sorted timeline CSV
with open("timeline.csv", "w", newline='', encoding='utf-8') as out:
    w = csv.writer(out)
    w.writerow(["when", "artifact", "hash"])
    for e in sorted([s for s in sources if s["when"]], key=lambda x: x["when"]):
        w.writerow([e["when"], e["artifact"], e["hash"]])

Tip: where filenames do not contain dates, maintain a small sidecar CSV keyed by artifact path with the authoritative timestamp.

4) Map SOW clauses to evidence checkpoints

Create a scope matrix that links each deliverable or clause to its acceptance evidence. This is the backbone for a point-by-point reply.

# scope_matrix.yaml
project: Theology Academy
clauses:
  - id: C1
    text: "Implementation window: 8, 10 weeks; revenue share 60/40."
    evidence:
      - "exports/emails/2025-07-14-kickoff.pdf"
      - "exports/transcripts/2025-08-21-status-call.pdf"
  - id: C2
    text: "Two staged invoices; final due upon completion as specified."
    evidence:
      - "exports/emails/2025-10-03-invoice-2-issued.pdf"
      - "exports/emails/2025-10-17-receipt-logged.pdf"
notes:
  - "No refund clause present in executed agreement. Termination required mutual written consent."

Guardrail: do not rely on auto-transcribed meeting summaries for legal positions. Always verify key statements against the original audio or a vetted transcript.

5) Draft a point-by-point rebuttal with exhibit citations

Use a model to draft a structured reply that mirrors the claimant's numbered allegations. Keep hard facts as variables and force exhibit references.

# rebuttal_prompt.py
allegations = [
  {"num": 1, "claim": "The platform was not delivered."},
  {"num": 2, "claim": "Final payment was requested prematurely."}
]
 
scope = open("scope_matrix.yaml", encoding='utf-8').read()
 
def draft_reply(allegations, scope):
    system = (
      "You draft factual small-claims replies. Cite exhibits as [Exhibit N]. "
      "Never invent dates or amounts. If evidence is absent, state 'No exhibit on file'."
    )
    user = f"Allegations: {allegations}\n\nScope and evidence map:\n{scope}"
    # Call your model here. Pseudocode for clarity:
    reply = """
1. Regarding delivery: Exhibit 3 shows the live deployment on 2026-08-09. The timeline lists 39,222 records ingested [Exhibit 3].
2. Regarding payment timing: The executed agreement contains no refund clause. Invoice 2 was issued post-milestone as per C2 [Exhibit 5].
"""
    return reply
 
print(draft_reply(allegations, scope))

Gate it: human review and edits are required before filing. The draft is a starting point, not the filing.

6) Export an indexed CRT evidence package

Produce a single index with exhibit numbers, then output a zip or a binder PDF with a contents page that references each file's hash for integrity.

# Contents
 
- Exhibit 1: Executed Agreement (sha256: 9b6e...)
- Exhibit 2: Kickoff Email 2025-07-14 (sha256: 1c42...)
- Exhibit 3: Deployment Screenshot 2026-08-09 (sha256: d0aa...)
- Exhibit 4: Timeline CSV (sha256: 0f77...)
- Exhibit 5: Invoice 2 and Receipt (sha256: 77ab...)

Where it gets complicated

  • Short log retention: Some automation tools purge run logs quickly. If a scenario was writing directly to a third-party system, set up a watcher to export logs before the window closes or your audit trail will have holes.
  • Transcript misattribution: Auto-transcription can mislabel speakers. For meeting evidence, cite the original audio with timestamps and a vetted transcript, not the auto-summary.
  • Contract language gaps: If there is no refund clause and termination requires mutual consent, your evidence must reflect the executed agreement verbatim. Capture a contract manifest and highlight the operative sections rather than paraphrasing.
  • Multi-mailbox confusion: When multiple senders are involved, preserve message IDs and the account of origin. Your timeline should attribute each event to a specific mailbox.
  • Versioning discipline: Redactions and edits must create new files and new hashes. Never overwrite an artifact that has already been hashed and referenced as an exhibit.

What this actually changes

For Theology Academy, the live system produced a defensible, indexed evidence pack and a reply that mapped each allegation to a clause and an exhibit. That shifted the burden from debating feelings about completeness to reviewing concrete deliverables against the executed terms and timeline. The structural value is durable: every future dispute follows the same intake, hashing, timeline, and drafting path.

A technical integrity note: NIST guidance treats SHA-256 as providing approximately 128 bits of collision resistance, which is suitable for integrity checks in this context. See NIST SP 800-107r1 for details: https://csrc.nist.gov/pubs/sp/800/107/r1/final

Frequently asked questions

Can this work if I did not start collecting evidence from day one?

Yes. Start now. Ingest what you have, hash it, and build a timeline from today backward. Note any gaps explicitly. A clear record from the moment you become aware of a dispute is better than a retroactive reconstruction without a manifest.

Do I need an AI model, or can this be done with templates?

The hashing, manifests, and timeline do not require AI. The model helps produce a clean, numbered reply that mirrors the allegations and cites exhibits consistently. We keep a human review step before anything is filed.

What about sensitive information in transcripts and emails?

Keep originals immutable. Generate redacted copies for filing and store both with distinct hashes and a small redaction log. Do not edit an exhibit in place once its hash appears in your contents index.

Will this replace my lawyer?

No. It reduces the manual assembly your team or counsel must do, and it standardizes how evidence is packaged. Counsel still reviews strategy, legal sufficiency, and filing format. The automation handles collection, integrity, and first-draft structure.

How long does it take to set up?

The intake, manifest, and timeline can be stood up in days. Contract mapping depends on the complexity of your SOW. The drafting template is fast to tune once your scope matrix exists. We ran this in parallel with normal operations and kept filing gates human-approved.

If you are facing a dispute or want to standardize delivery-risk evidence before there is a dispute, we have run this in production and can adapt it to your stack. See our service scope at /services#document-automation, read our related post on contract scopes /blog/ai-automation-agency-contract-sow-checklist-2026, and when you are ready /book.

Want us to build this for you?

Nine questions, about 90 seconds. You see the hours it is costing you, then pick a time. No pitch.

Get your free assessment

Related reading