How an engagement runs
The pipeline is four skills invoked in order against one folder. Nothing is hidden in a database: the folder holds the source documents, the deliverables, and the notes.
1 — Create the engagement
In the dashboard's intake view, pick personal or business, name the client, and drop in their documents. That writesclients/<slug>/ with a client.json and the files beside it. Each type shows its own collection checklist — W-2s and transcripts for individuals, 941s and merchant statements for entities — because a document missing here becomes a Phase 1 flag later.
2 — Run the phases
Each skill reads the folder and writes its deliverable back into it:
| Command | Writes |
|---|---|
/accounting-intake clients/<slug>/ | financial-profile-<slug>.md |
/accounting-verify-data clients/<slug>/ | phase1-data-verification-report.md |
/accounting-verify-compliance clients/<slug>/ | phase2-compliance-report.md |
/accounting-tax-strategy clients/<slug>/ | phase3-tax-strategy-report.md |
3 — Read the state
The dashboard parses those deliverables on every request. It never caches a status: refresh and you are looking at what is on disk right now.
The status contract
Each check section carries one machine-readable line, so the UI never has to guess what a paragraph meant:
## CHECK 3 — CLASSIFICATION ACCURACY
**Status:** FLAG — 14 transactions need reclassification before filingPASS, FLAG, FAIL, or SKIPPED leads; the human detail follows. Two rules make the display trustworthy: prose that cannot be parsed resolves to flag, never pass, and a section with no status line at all is reported as unrecorded — the phase then shows as "written", not "verified".
Deliverables are the API
Because state derives from markdown, a phase can be re-run, hand-edited, or produced by a human accountant, and the dashboard reflects it identically. There is no sync step and nothing to migrate — deleting a report removes that phase from the UI.
Running it
git clone git@github.com:cemarsh/accounting.git
cd accounting/web
npm install
npm run dev # dashboard + engagement API on localhost
npm run serve # build, then serve the same thing from dist/The local server binds loopback and refuses any other interface unless you explicitly override it. That is deliberate — see Security.