Skip to main content
강홍재/ James
← Work
MVP2026 · Founder · Product · Engineer· Started(First Commit date)

DocuStory

An analysis engine that turns Korean real-estate documents into risk signals.

  • Python
  • FastAPI
  • PDF
  • Real Estate

Setup

Context

An experiment to make risk judgement separable into "rules" so the same document yields the same score, regardless of who's reading it.

Build

QA considerations
  • Same document, always the same score - with now pinned to FIXED_NOW, does the result exactly match the stored golden?
  • Does the rule catalog cover the real registry risk signals (mortgage, seizure, provisional seizure) without missing them?
  • Was the tradeoff decided - a missed risk (false negative) vs over-flagging (false positive)?
  • Are 말소 (cancellation) detection (strike line + text cue) and amount/date normalization robust across varied PDF layouts?
  • For scans with no text layer it explicitly refuses (PARSER_OCR_NOT_IMPLEMENTED), and limits that couldn't be verified are surfaced as PARSER_*/ANALYZER_* warnings, rather than silently returning a wrong answer
  • Contract schemas across the six repos (ParsedDocument, Rule, AnalysisResult, etc.) are meta-validated by each repo's test_contract and platform's test_openapi so contract and implementation can't drift
  • Rule-catalog integrity, packaging, and deterministic-ordering tests keep the weighted score (warning 15, danger 40, cap 100) reproducible regardless of evaluation order

Outcome

Metrics

Currently in external validation. Architecture, rule catalog, and implementation details will be published once validation lands.

Process (planning → build)

The same template from problem and hypothesis through scope, spec (SSOT), build, the QA gate, and release - how this was planned and driven.

Problem & hypothesis

A Korean real-estate registry (등기부등본) PDF carries risk signals - mortgages, seizures, provisional seizures - that an ordinary reader cannot reliably decode. The core hypothesis: separating risk judgement into declarative rules makes it regression-testable, so the same document must always yield the same score.

Skills · Problem framing · hypothesis

Scope & priority

Kickoff fixed the scope to the thinnest e2e slice - "one registry PDF → 갑구/을구 extraction → mortgage/seizure detection → a one-line Korean risk summary" (`_roundtable/brief.md`, the agenda doc every repo's CLAUDE.md points to). Registry-only and text-layer-first were core (the parser explicitly rejects image OCR with `PARSER_OCR_NOT_IMPLEMENTED`), while auth, financial/contract document types, and real cloud deploy were deferred.

Skills · Scoping · prioritization

Spec-first (SSOT)

The SSOT was the R2-frozen contract doc (`_roundtable/output/00-r2-decisions.md`) plus per-repo `contracts/*.schema.json` (ParsedDocument, Rule, RuleEvalResult, AnalysisResult, SampleManifest), each owned by exactly one repo. The build then advanced slice by slice, using each repo's `NEXT_BUILD.md` as the plan for the next slice, and allowed schema changes only as backward-compatible extensions - keeping `schema_version` at 0.1.0 across many slices.

Skills · Spec · documentation

Build & iteration

The build split into six repos (samples → parser/rules → analyzer → platform → infra) wired by in-process imports. parser does pdfplumber text extraction plus 갑구/을구 cell mapping, 말소 (cancellation) detection via both a visual strike line and a text cue, and amount/date normalization; rules is a declarative 7-rule JSON catalog with a deterministic evaluator; analyzer computes risk_level, a weighted score (warning 15, danger 40, cap 100), and the Korean summary; platform is a FastAPI POST/GET surface with a CLI and SQLite persistence.

Skills · Execution · delivery

Verification (QA gate)

The QA lens drove verification. analyzer golden tests inject a fixed `now` (FIXED_NOW = 2026-06-05T12:00Z) and assert the produced AnalysisResult exactly matches the stored golden, directly gating the "same document → same score" hypothesis, while platform e2e runs the real parser/rules/analyzer against real sample PDFs and asserts exact risk_level, rule IDs, score, and summary text (e.g. danger_003 sums to 190 contributions and caps to 100 across 6 findings). Under that sit contract-schema meta-validation in every repo (each `test_contract`, platform `test_openapi`, infra manifest schema) plus rule-catalog integrity, packaging, and deterministic-ordering tests, and unverified limits are surfaced honestly through `PARSER_*`/`ANALYZER_*` warnings.

Skills · Quality · risk

Release

It runs via a dev compose and a prod compose (multi-stage, non-root user, healthcheck, named-volume Docker), exposing `POST /v1/documents:analyze` + `GET /v1/documents/{document_id}` plus a single/batch CLI, with SQLite as the default store. It is still MVP - the samples are synthetic PDFs (`gen_synthetic_pdf.py`), so accuracy against real registries is the remaining gate, with auth, an external DB, CI/CD, and a cloud-deploy blueprint left as follow-ups.

Skills · Release

Tech stack
  • Python
  • FastAPI