> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vinmake.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Where the business logic lives

> The dividing line: agent judgment is editable knowledge with no deploy; rules with ledger consequences are code with a deploy, a test and a review.

# Where the business logic lives

Every AI-driven system has to answer one question: **which rules can a business user change, and which ones need an engineer?**

Answering it badly in either direction is expensive.
Too much in code and the system is unusable without a deploy for every business decision.
Too much in editable knowledge and somebody changes the books through a text box.

GreatBook draws the line at **ledger consequences**.

## The line

<CardGroup cols={2}>
  <Card title="SOP · editable knowledge, no deploy" icon="book">
    Agent **judgment**.
    How the Clerk classifies the 146 document types.
    What counts as a supplier bill.
    How an agent interprets a document before proposing anything.

    Soft, natural-language, retrieved at run time.
  </Card>

  <Card title="Code · deploy required" icon="code">
    Rules with **ledger consequences**.
    The double-entry.
    The sub-ledger writes.
    The Close checksums.
    The hash chain.

    Hard, deterministic, gated.
  </Card>
</CardGroup>

The test is not "is this a business rule".
Almost everything here is a business rule.

The test is: **does getting this wrong change the books?**

## Worked example

> *"Open an AP obligation when you credit AP control."*

That reads like an operating procedure.
It is **code**.

Getting it wrong leaves the control account carrying a balance the sub-ledger cannot explain, which fails a Close checksum and makes every aging report unreliable.
That is a ledger consequence, so the rule lives in the [single obligation writer](/greatbook/capabilities/subledgers/settlement), with a regression test, behind a pull request.

Compare:

> *"A bill from a laundry service is a service invoice, not a consumables invoice."*

That is **judgment**.
Getting it wrong routes a document to the wrong reviewer and produces a proposal a human declines at a gate.
No ledger consequence, because a gate stands between it and the books.

So it is an SOP, editable without a deploy.

## How to change each

<AccordionGroup>
  <Accordion title="To change accounting behaviour">
    Whether an obligation opens, which account is used, how the due date, party or currency derive.

    Edit the engine code, add a regression test, and ship it as **a code change, through the review pipeline, to a deploy**.

    This is **intentionally not** a business-user edit, because it changes the books.
  </Accordion>

  <Accordion title="To change agent judgment">
    What the Bookkeeper recognises.
    How an agent reads a document before proposing.

    Edit the SOP. No code deploy.

    With one caveat that matters: a rulebook **generated from code** is regenerated when the code changes, so it is not a free-text field.
    See [the SOP store](/greatbook/agents/sops).
  </Accordion>
</AccordionGroup>

## There is no data-driven posting-rules layer today, on purpose

<Warning>
  A search over the backend for any posting-rules, account-map or obligation-config **table** returns nothing.
  The double-entry rules are hard-coded in the engine, deliberately, for integrity: the hash chain and the Close checksums both assume the rules were the rules at the time of posting.

  If you later want this tunable without a deploy, that is **net-new work**: it means building a posting-rules configuration layer that the engine reads, with its own versioning, its own audit trail and its own answer to "which version of the rules posted this entry".
  It does not exist yet, and this documentation does not imply that it does.
</Warning>

That last sentence is the honest part.
"Configurable posting rules" is a feature every accounting product eventually wants, and describing the current design as if it already had one would be the easiest kind of documentation lie to tell.

## Why the boundary holds in practice

Three properties keep judgment from leaking into ledger consequences:

| Property                                                                  | Effect                                                                                                                                                                            |
| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **The knowledge store can only pick, never invent.**                      | A retrieved answer is used to choose among **real** account codes. It cannot mint one and cannot suppress the hard error                                                          |
| **The static table is the floor.**                                        | When the store is unreachable - its normal degraded mode - the deterministic table alone decides, and an uncovered record still raises                                            |
| **Source-specific human control stands between judgment and the ledger.** | A document proposal crosses intake and posting review; an Accountant workpaper uses its stable adjustment-keyed release, requiring a named non-agent human who did not propose it |

So the worst case for a wrong SOP is a proposal a human declines.
The worst case for a wrong posting rule is an immutable entry that has to be reversed.

Those are different magnitudes, and the line is drawn exactly there.

## Quick reference

| Concern                                          | Where                                                       |
| ------------------------------------------------ | ----------------------------------------------------------- |
| the Bookkeeper agent: decides and gates the post | `langgraph_chat/agents/bookkeeper/`                         |
| the posting gate and maker-checker               | `agents/accountant/posting_gate.py`, `agents/common/sod.py` |
| the ledger posting entry point                   | `backend/app/services/ledger_service.py`                    |
| the AP/AR obligation writers                     | `backend/app/logics/finance/settlement.py`, `costing.py`    |
| the failing reconciliation checksum              | `close_checks.ap_control_tie`                               |
| the live Close runner                            | `backend/tools/live_acceptance.py`                          |
| the SOP corpus                                   | `agents/common/sops.py`                                     |

## Related

* [The SOP store](/greatbook/agents/sops) - how the editable half is kept from drifting
* [The Bookkeeper](/greatbook/agents/bookkeeper) - where the two halves meet
* [Settlement, rails and the AP/AR spine](/greatbook/capabilities/subledgers/settlement) - the worked example, in full
* [Guardrails and refusals](/greatbook/agents/guardrails) - the other structural boundary
