Skip to content

Repository files navigation

Citework

Investment-committee memos with a paper trail. The model extracts. Python does the math. You approve before a sentence is written.

tests Python 3.12 License: MIT Anthropic Streamlit

Citework turns a folder of deal documents into a one-page credit memo a committee can actually trust: every reported figure carries a verbatim quote, every ratio is Decimal arithmetic in Python, and a human gate sits between extraction and prose.

A shipped example — a fictional mid-market software LBO — is already in the repo:

Python, not the model
Net debt at close $48.0M
Forward leverage 30.0x
LTM leverage N/M (EBITDA is negative)
NRR excluding concentrated expansion 97.8%

Full memo: output/memo.txt. Evidence: output/numbers.md.

Key numbers from the sample memo

Why this exists

Language models will invent a 4x leverage multiple if you let them do the arithmetic. Citework does not:

  • Closed world. Documents are the only source of truth. Outside knowledge is forbidden. File text is untrusted data, never instructions.
  • Quotes, then math. Python checks that each quote appears in the named file (whitespace folded, paraphrases fail, 2 inside $52M does not count). Then Python computes net debt, leverage, ARR multiple, and NRR.
  • A real gate. Assumptions, conflicts, gaps, at most three questions, and the verified numbers are on the table before the second call writes the memo.
flowchart LR
  docs[docs txt pack]
  step1[Extract]
  py[Verify quotes and Decimal math]
  gate[Human gate]
  step2[Write prose]
  out[memo numbers report]
  ui[Streamlit review]
  docs --> step1 --> py --> gate --> step2 --> out
  out --> ui
Loading

Quickstart

python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -m unittest discover -v
python run.py --offline --yes
python -m streamlit run app.py

--offline replays the captured model responses already in output/raw/. No API key, no network.

For a live run, copy .env.example to .env, set ANTHROPIC_API_KEY, then:

python run.py          # pauses at the gate
python run.py --yes    # approve without prompting

A live run is two calls, typically under a minute. The Streamlit app is artifact-first: opening it does not call the model. A live button exists; it is not the default.

Sample pack

docs/ is a fictional data room for Redwood Software Inc. — CIM excerpt, banker-call notes, internal financials. Drop a different folder of .txt files in and the same pipeline runs. There is no deal-specific logic in the production modules.

Design, in one page

The long version is ARCHITECTURE.md. The short version:

  1. Step 1 extracts named figures with source + quote. It does no arithmetic.
  2. verify.py traces every quote. calculations.py derives every ratio in Decimal. A non-positive denominator is N/M, never a negative multiple.
  3. output/numbers.md is written before you approve.
  4. Step 2 is handed the numbers block, not the raw documents, so the prose cannot invent a multiple the table disagrees with.
  5. report.json is the structured contract. memo.txt is pasteable plain text (450–650 words, no markdown). Both come from one object.

Layout

citework/
├── run.py              CLI: extract → verify → compute → gate → write
├── analysis.py         Anthropic structured output (two calls)
├── verify.py           Quote traceability
├── calculations.py     Decimal math, N/M guards
├── render.py           One-page memo + numbers.md
├── app.py              Streamlit review UI
├── schema.json         Output contract
├── docs/               Sample data room
├── output/             Frozen demo artifacts
└── tests/              Offline suite (~70 tests)

License

MIT. See LICENSE.

About

Grounded investment-committee memos: the model extracts, Python does the math, you approve before prose exists.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages