StatusCompleted
PriorityMedium
Has UIYes
Sourcerich

Legacy System Documentation

A pipeline that reverse-engineers a legacy Oracle telecom billing system — schemas, PL/SQL, batches, scripts, adapters, and 20 years of scattered Word docs — into one navigable, cross-linked knowledge base.

01 — THE PROBLEM

I was handed a legacy Oracle BRM 7.3 billing platform with basically no living documentation: 300+ tables, PL/SQL packages, Java batch jobs, shell crontabs, SOAP adapters, and a pile of Word documents from years of change requests, all disconnected from each other. Nobody could answer “what touches this table” or “what does this business process actually call under the hood” without grepping through code or asking whoever happened to remember. That’s not a rare situation — it’s the default state of any billing, ERP, or core-banking system that’s been alive for a decade-plus. The knowledge that explains why the system behaves the way it does lives in people’s heads and in a drawer of stale specs, and it evaporates every time someone leaves. Any team running a system like this is one departure away from having no map at all.

02 — THE APPROACH

The pipeline runs in explicit stages, no orchestrator, each stage a script you invoke by hand: DDL to DBML (per-table schema files enriched against a source Excel data model), PL/SQL to DBML for every package/procedure/function, then a Claude CLI enrichment pass that writes semantic descriptions into each artifact’s front matter — what a procedure does, what it reads and writes, its transaction behavior. Word documents get converted to Markdown in two passes: first a literal word-for-word extraction with tables and image placeholders, then a second pass where Claude describes each extracted image and drops the description back under its placeholder. Everything gets ingested into a SQLite knowledge graph — one spine table for every object (tables, procedures, batches, scripts, adapters, documents, business-process steps) plus a relation table for edges like CALLS, READS_FROM, WRITES_TO, IMPLEMENTS_PROCESS. That one graph answers “what does this contain” and “what implements this process” with the same query regardless of object kind, and every claim in it carries provenance back to the exact source file and line range, so you can prove where a fact came from.

The output isn’t just data — it’s a static HTML site you can actually click through: a DB Objects browser, a Components browser (adapters, services, batch jobs, scripts, reports), and a Business Processes browser organized into 17 macro-areas (rating, billing/invoicing, customer structure, financial reporting, renewals, credit/suspension, payments, reconciliation, provisioning, and more), drilling down through 75 processes and 154 steps, each one cross-linked to the DB objects and components that implement it. There’s a searchable glossary, a synonyms page for terminology drift across documents, and auto-generated SVG “impact view” diagrams that show any object’s 1-hop neighborhood — what calls it, what it calls, what breaks if you touch it. Everything is rebuildable from source artifacts on disk; the HTML and the graph are disposable projections, never hand-edited.

03 — WHAT I LEARNED

The graph design that actually held up was treating every kind of object — a table, a PL/SQL procedure, a batch job, a Word document, a process step — as one row in a single entity spine with kind-specific detail tables joined onto it. That’s what let one query answer “what does this contain” whether the parent is a package or a business process, without a growing pile of kind-specific joins. The other lesson was to make the knowledge graph strictly a derived index and never the source of truth: the DBML, Markdown, and YAML files on disk are authoritative and human/tool-editable, the SQLite DB is rebuilt from them and can be thrown away. That distinction is what makes “renamed, edited, or removed” safe to handle as upsert-and-withdraw instead of ad hoc deletes — nothing is ever silently lost, old claims get withdrawn with a timestamp and the run that superseded them, so you can always answer “what did we believe about this before, and when did that change.”

04 — WHERE THIS COULD GO

This is the general shape of “modernize without rewriting”: before anyone touches a legacy core system — billing, claims processing, core banking, an ERP — you need an accurate, current map of what depends on what, or every change is a guess. The same three-layer pattern (structural extraction → LLM semantic enrichment → a typed graph with provenance) generalizes past telecom billing to any org sitting on a system nobody fully understands anymore: mainframe COBOL, an old SAP instance, a homegrown claims engine. At team scale the win isn’t just having docs, it’s having docs a new hire or an outside vendor can actually navigate instead of shadowing the one person who’s been there since the system was built — and having impact analysis that’s a graph query instead of a week of grepping and Slack archaeology before anyone dares touch a shared table.

05 — TAKEAWAY

The unglamorous problem — nobody knows what’s actually in the legacy system anymore — is exactly the kind of thing LLM-assisted extraction is good at, as long as you keep the graph as a disposable, provenance-tracked index over authoritative files rather than letting it become the thing people trust blindly.

Text summarized and optimized using Anthropic’s models and reviewed by a human.