> ## 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.

# The 146-document registry

> One record per document type, generated from the ontology, shared by the Clerk, the Typewriter, the renderer and the SOP corpus.

# The 146-document registry

## What it guarantees

Every document type GreatBook knows about has exactly **one** record, describing what it is, how to recognise it, what to extract from it, and what it does to the books.

That record is **generated from the ontology assets**, not hand-maintained.
Four independent consumers read the same file, so none of them can hold a different opinion about what a supplier invoice is.

## The shape of it

**146 records**, split by category:

| Category      | Count | What it is                                                   |
| ------------- | ----- | ------------------------------------------------------------ |
| `transaction` | 48    | events that move value: invoices, receipts, payments         |
| `evidence`    | 40    | supporting proof: bank statements, delivery notes, contracts |
| `master`      | 38    | reference data: suppliers, items, cost centres               |
| `adjustment`  | 20    | corrections and reclassifications                            |

Each record carries:

| Field                                                      | What it is for                                                 |
| ---------------------------------------------------------- | -------------------------------------------------------------- |
| `id`, `idx`, `name_en`, `name_vn`                          | identity, in both working languages                            |
| `definition`                                               | the one-line self-description, including the accounting effect |
| `category`, `role`, `ontology_role`                        | where it sits in the ontology                                  |
| `target_model`, `target_table`, `schema_key`, `schema_ref` | the pointer into the shared JSON Schema                        |
| `related_docs`                                             | the document chain it belongs to                               |
| `required_masters`                                         | which reference data has to resolve before it is complete      |
| `classification_cues`                                      | the tokens that identify it, in English **and** Vietnamese     |
| `accounting_effect`                                        | what it does to the books                                      |
| `source_tier`, `automatable`, `frequency`, `entity`        | operational metadata                                           |
| `extract_fields`                                           | the fields the extractor is asked for                          |

## One record, in full

```json theme={null}
{
  "id": "supplier_vat_invoice",
  "idx": 24,
  "name_en": "Supplier VAT invoice",
  "name_vn": "hoá đơn GTGT đầu vào",
  "definition": "#24 · hoá đơn GTGT đầu vào · CREATES AP + 133 -> purchase_bill + bill_line",
  "category": "transaction",
  "target_model": "purchase_bill",
  "schema_ref": "worthstate_models.schema.json#/documents/SupplierVatInvoiceDoc",
  "related_docs": ["purchase_order", "goods_receipt_note", "e_invoice"],
  "required_masters": ["supplier", "item", "cost_centre", "tax_code"],
  "classification_cues": ["gtgt", "hoá đơn", "input VAT", "8%", "10%",
                          "supplier tax code", "invoice serial"],
  "accounting_effect": "creates_ap",
  "extract_fields": ["doc_no", "doc_date", "supplier_name", "supplier_tax_code",
                     "invoice_serial", "currency", "lines",
                     "amount_pretax", "vat_amount", "total_amount", "po_refs"]
}
```

Two things to notice.

The `worthstate_models.schema.json` value is a legacy source filename emitted by the current generator, not a product or service name.

**The classification cues are bilingual.**
Vietnamese source documents say *hoá đơn GTGT đầu vào*, not "supplier VAT invoice", and a registry that only carried English tokens would classify by luck.

**The definition states the accounting effect inline.**
`CREATES AP + 133` is a claim the [posting rules](/greatbook/agents/bookkeeper) then have to honour, and a mismatch between what a document type says it does and what the posting produces is a real defect - it is exactly how the missing input-VAT split was found.

## The accounting effect

The field that connects a document to the books.

| Effect                                                                                     | Documents | What it means                                |
| ------------------------------------------------------------------------------------------ | --------- | -------------------------------------------- |
| `none`                                                                                     | 71        | evidence and reference data. Nothing posts   |
| `creates_ap`                                                                               | 4         | a payable: `Cr 2000` and an obligation opens |
| `creates_ar`, `creates_ar_commitment`, `reduces_ar`, `settles_ar`, `adjusts_ar_allocation` | 6         | the receivable side                          |
| `creates_payroll`                                                                          | 2         | the payroll accrual                          |
| `creates_withholding`                                                                      | 2         | foreign-contractor tax                       |
| `creates_provision`, `creates_customer_deposit`, `creates_sample_cost`                     | 5         | the remaining posting shapes                 |

The largest bucket by far is `none`.
That is the right shape: most documents in a business are evidence, and treating them as postable is how a book fills with entries nobody asked for.

## Line items come from the document, not the table

Seventeen document types carry a `lines` array.

The line shape is derived from the ontology's own `lines: {type: array, items: {$ref: LineItem}}`, **not** from a `line_table` field on the record.
No record has a `line_table`, so anything built on it is dead code - and something was, which is why every bill once extracted `lines: []`.

Lines ride their own state key through the graph, never inside the flat field map, so validation can present them back under the schema's own property name before the shape check.

## Four consumers, one file

```mermaid theme={null}
flowchart LR
  ONT["ontology assets<br/>worthstate_models.schema.json"] -->|"generated by<br/>gen_doc_registry.py"| REG["doc_registry.json<br/>146 records"]
  REG --> CLERK["Clerk<br/>classify · extract · validate"]
  REG --> TW["Typewriter<br/>the catalog it proposes from"]
  REG --> SOP["local SOP index<br/>per-doc-type intake rulebooks"]
  ONT --> RND["renderer<br/>the 146 layouts"]
```

* **The [Clerk](/greatbook/agents/clerk)** classifies against the cues, loads the record, and extracts the declared fields against the referenced schema.
* **The [Typewriter](/greatbook/agents/typewriter)** proposes documents from the same catalog, so a proposal opens in the builder as a document the Clerk will recognise.
* **The [SOP corpus](/greatbook/agents/sops)** generates its per-document-type intake rulebooks from the registry, so an agent's playbook cannot describe a document type that does not exist.
* **The [renderer](/greatbook/capabilities/composition-and-rendering)** reads the same schema, and its Docker build **asserts at build time** that the schema parses and carries at least 146 types.

That build-time assertion is a small thing that prevents a specific bad day: a schema file missing from an image works in development and 500s in the container.

## Regenerate, do not hand-edit

The registry is generated from the ontology.
Editing it by hand produces a file that the next regeneration silently overwrites, and in the meantime an agent is working from a description of a document that does not match its schema.

```bash theme={null}
python -m agents.common.gen_doc_registry
```

## Where it is enforced

| Concern                               | Code                                                              |
| ------------------------------------- | ----------------------------------------------------------------- |
| the registry itself                   | `langgraph_chat/agents/common/doc_registry.json`                  |
| the generator                         | `langgraph_chat/agents/common/gen_doc_registry.py`                |
| the loader, and the schema resolution | `langgraph_chat/agents/common/kb.py`                              |
| the shared JSON Schema                | `langgraph_chat/data_entry/kb/data/worthstate_models.schema.json` |
| the Typewriter's view of it           | `langgraph_chat/agents/typewriter/catalog.py`                     |

<Note>
  The records wrap under the top-level key `documents`.
  The loader also tolerates a development stub shape and a bare list, which exists because a mismatch there once broke graph loading in a way that looked like a model failure rather than a file-format one.
</Note>

## The test that would fail if it broke

`langgraph_chat/agents/tests/test_integration.py` loads the **real** registry, builds the dependencies and compiles the graph.
That is the guard against a file-shape regression reaching production disguised as something else.

The renderer's build-time assertion is the other end of it, and the renderer suite includes a gate that renders all 146 types.

## What goes wrong without it

Two copies of the document catalog is the failure.
The Clerk classifies a type the renderer cannot lay out, or the Typewriter proposes fields the builder's validator rejects, and **each side looks correct on its own**.

That is the hardest class of defect to diagnose, because there is no wrong line of code - only two files that used to agree.

## Related

* [The Clerk](/greatbook/agents/clerk) - classification and extraction against the registry
* [The Typewriter](/greatbook/agents/typewriter) - composing from the same catalog
* [Composition and the render seam](/greatbook/capabilities/composition-and-rendering) - the renderer's half
* [The SOP store](/greatbook/agents/sops) - the rulebooks generated from it
