The Accountant
🟡 Deployed source; agent flow unexercised end to end for this documentation cut. It owns the period close and the statutory reports, and it is the only agent that produces journal-entry proposals without being able to post them.The shape
Three capabilities
The close checklist
The close checklist
Five steps, in the order a human closes a period in:
period, integrity, unposted, close_list, statutory.It orchestrates existing oracles rather than reinventing them.
Step 2 calls the Auditor’s own sweep; step 4 calls the backend’s Close checksum oracle.
The two checks that genuinely belong here are the ones living between the agents: is the period open, and are approved documents still unposted.Any step that cannot run is INCONCLUSIVE, and an inconclusive report is never ready_to_close.Full detail: Fiscal periods and closing.Adjusting entries · eight kinds, no guesses
Adjusting entries · eight kinds, no guesses
Built from a deterministic rule table, the accountant’s counterpart to the Bookkeeper’s posting rules and held to the same three commitments.
An unknown kind, or one missing a parameter its rule requires, raises
UnmappedAdjustmentError.
There is no fallback anywhere in the table, and the suspense accounts are refused outright even when a caller names one explicitly:refusing to post to suspense account 6900 - an adjustment that cannot be coded to a real account is a human’s decision, not a suspense dumpThe account codes are duplicated here as constants rather than read from the database, deliberately: the rule must be decidable offline, and the ledger engine independently verifies that every account exists and is active before it posts. So a stale constant fails loudly at the writer rather than silently booking somewhere plausible.A business reversal is not an adjustment kind. It goes through the separate typed reversal boundary, and the Accountant cannot invoke that write path.
Statutory reporting
Statutory reporting
Trial balance, P&L, balance sheet and the Circular-200 projection, all built from one posted-lines base so they cannot disagree.Full detail: Statutory reporting.
Wave D/F: period-end assurance
Wave D completes the explicitclose_gated assurance family and its server-owned monthly job.
The family reads the phase metadata from the generated Close inventory rather than keeping a second list of codes, so the three KETCHUYEN-* checks and DEPR-COVERAGE join the sweep through the same authority.
The routine full sweep still excludes close_gated because its subject must be a finished period.
A question naming a close-gated control resolves one exact closed period; the monthly job uses a bounded last_closed backlog scan so a missed run cannot permanently skip an unverified closed period.
No closed period, a named open/unknown period, or a control that cannot run is inconclusive, never a vacuous pass.
Findings are scoped to their fiscal period, so a clean August run cannot resolve a still-real July finding.
Wave F adds DEPR-COVERAGE as one of those close-gated controls.
For the selected period, every positive-cost asset already in service and still inside its useful-life month window needs its own depreciation charge posted inside that period.
A future or fully depreciated asset is outside the population; a positive-cost asset with no in-service date makes coverage inconclusive and is named rather than dropped.
FX-revaluation coverage remains deferred until the realized-FX and rate workflow can support it honestly.
Accounting Desk read surfaces
The Accountant workspace is not only a chat answer. Its Accounting Desk exposes Close, Analysis, Allocations, Costing and Adjustments as authenticated read surfaces with exact decimal strings, pagination, event/journal links and explicit empty, partial and error states. An adjustment or close calculation is backed by an immutablejournal_workpapers source record.
The workpaper links to the exact journal event and entries, and Transactions links back to the workpaper; a descriptive source label alone is not resolved lineage.
These read surfaces do not release or post an adjustment.
How it reaches the book: it does not
posting_gate.py is the only seam out, and it hands the proposal to the Bookkeeper’s graph, where it stops at that graph’s existing human gate.
The accountant proposes; a human approves; the single writer posts. No step of that can be skipped from here, because there is no code in this package that writes.An adjustment has no staging row to re-read, so its trusted record is the payload signed where it is staged, inside the server process that built it. The lines, the amounts, the entry date, the GL source lineage and the proposing agent are all fixed before the run ever pauses. See the posting mandate. Separation of duties still applies: the checker must be named, and may not be the proposing agent.
Idempotency by construction
Every proposal carries a stable source id derived from(kind, period, subject):
Read-only elsewhere
The Accountant shares the Auditor’s read-only channel, so the database rejects a write regardless of what any node asks for. A static import check asserts that no accountant module can reach a writer. That test is the control; without it, the guarantee lasts until the next import.The release path, stated plainly
A staged adjustment uses the stable adjustment-keyed approve/reject path. Both decisions require a named non-agent human, approval refuses the proposing agent as checker, and the decision is bound to the exact adjustment source. Only a resulting journal entry establishes that an approved proposal posted; rejection is stored as a durable decision. That same release path is now registered as two typed staged-workspace outcomes. The approve/reject adapters accept only the stableADJ-* source and its exact workpaper content hash, revalidate the current gate, then call the existing canonical decision service.
Approval cannot substitute journal lines and reports success only from the immutable entry; rejection requires a written reason and retains its close-run decision evidence.
The public OAuth/MCP ingress and release source are current at registry 1.14.1.
Real ChatGPT and Claude identity, scope, discovery, fallback, confirmation and safety exercises remain open.
Worked cases
acct-close-checklist-completeness
acct-close-checklist-completeness
All five steps must appear.
Completeness matters because a checklist that silently drops a step reads exactly like a checklist that passed it.
acct-close-checklist-blockers-reported
acct-close-checklist-blockers-reported
Two independent real conditions are seeded: a document a human approved that is not in the books, and a credit to the AP control with no matching bill in the sub-ledger.The verdict is read back from the period row’s own status, not from what the answer claims.
acct-adjusting-entry-routes-through-gate
acct-adjusting-entry-routes-through-gate
The governance case, and the reason the Accountant is riskier than the Auditor: it proposes journal entries.The proposal is routed through the real Bookkeeper graph, proven paused at the gate, with the ledger empty.
And
MakerIsCheckerError when the proposing agent tries to be its own checker.acct-adjusting-entry-unmapped-raises
acct-adjusting-entry-unmapped-raises
The same anti-suspense guardrail as the Bookkeeper’s.
No fallback, ever.
Where it is enforced
Related
- Fiscal periods and closing - the checklist in full
- The Close checksums - step 4’s oracle
- The Bookkeeper - where an adjustment actually posts
- Closing a period - the same flow, from a user’s chair