# P1-0 — controlled vocabulary annex

**Normative.** Generated from the pinned prototype at `9359c67` (re-confirmed at `6146004`), with
the DOCEFL domains regenerated by O8-D1 from immutable P1-1b pin
`b91768513fc638381fbde91f0b576b08220a98f6`, not transcribed by hand. Where a P1-0 draft declares
a literal that disagrees with this table, **this table wins** and the draft is corrected. Any value
the team decides to normalize instead becomes an explicit listed exception with a migration note —
never a silent rewrite.

Regenerate this file from the pin rather than editing it. Counts are as at the pin; re-measure.

## Pinned domains

| Table | Field | Distinct | Pinned values (verbatim) |
|---|---|---:|---|
| DOCLOG | Source | 3 | `BNK` (547) · `FDR` (817) · `MET` (111) |
| DOCLOG | CaptureQuality | 3 | `Accepted` (6) · `Rejected` (42) · `Review Required` (2) · *blank on 1425* |
| DOCLOG | DocumentType | 10 | `Cancelled Invoice` (10) · `Credit Note` (15) · `Duplicate` (93) · `Financing` (125) · `Invoice` (606) · `Invoice-Receipt` (198) · `NoDocMov` (366) · `Payment Notice` (3) · `Payroll` (56) · `Wrong Document Type` (3) |
| DOCLOG | OriginClass | 2 | `External` (1200) · `Internal` (275) |
| DOCTYP | DocClass | 2 | `Payables` (12) · `Receivable` (7) |
| DOCTYP | OriginClass | 2 | `External` (11) · `Internal` (8) |
| DOCTYP | Treatment | 2 | `Exclude` (6) · `Include` (13) |
| DOCEFL | BlockingLevel | 5 | `Block Classification` (5) · `Block Document` (1) · `Block Financial Entry` (8) · `Block Reconciliation` (4) · `Non-Blocking` (34) |
| DOCEFL | FlagCategory | 4 | `High Risk` (11) · `Information` (17) · `Low Risk` (13) · `Medium Risk` (11) |
| DOCEFL | ReviewPriority | 6 | `Before Posting` (16) · `High` (1) · `Immediate` (4) · `Informational` (17) · `Periodic Review` (12) · `Routine` (2) |
| DOCEFL | ReviewOwnerRole | 4 | `AI` (26) · `Finance Reviewer` (19) · `Master-Data Reviewer` (4) · `Process Owner` (3) |
| DOCEFL | AutoActionAllowed | 3 | `No` (25) · `Yes` (26) · `Yes (provided all Entity Entry Flow requirements are verified)` (1) |
| DOCEFL | AutoReviewable | 2 | `No` (24) · `Yes` (28) |
| DOCEFL | Active | 1 | `Yes` (52) |
| DOCEFL | ResolutionEvidenceRequired | 36 | *free-text / high-cardinality — not a controlled domain* |
| DOCEFL | FlowDimension | 4 | `Bank Reconciliation` (8) · `Document Entry` (1) · `Document Registry` (28) · `Entity Item Classification` (15) |
| DOCEFL | AppliesToTable | 12 | `BNKMOV` (8) · `BNKMOV; FDCHDR; BNKREC` (1) · `DOCLOG` (10) · `DOCLOG; DOCFAI` (1) · `DOCLOG; FDCHDR` (11) · `DOCLOG; FDCHDR; BNKMOV` (1) · `DOCLOG; FDCHDR; FDCDTL` (2) · `DOCLOG; FDCHDR; PAYCTR` (1) · `ENTMST` (11) · `ENTMST; ENTALS` (4) · `FDCHDR` (1) · `FDCHDR; ENTMST` (1) |
| DOCFLG | Status | 4 | `Open` (149) · `Resolved` (1497) · `Superseded` (204) · `Waived` (861) |
| DOCFLG | BlockingLevel | 4 | `Block Classification` (62) · `Block Financial Entry` (158) · `Block Reconciliation` (116) · `Non-Blocking` (2375) |
| DOCFLG | ReviewPriority | 4 | `Before Posting` (325) · `Immediate` (13) · `Informational` (1293) · `Periodic Review` (1080) |
| DOCFLG | ReviewOwnerRole | 4 | `AI` (1439) · `Finance Reviewer` (1174) · `Master-Data Reviewer` (61) · `Process Owner` (37) |
| DOCFLG | RelatedRecordType | 3 | `BNKMOV` (1167) · `DOCLOG` (1362) · `ENTMST` (182) |
| DOCFLG | DetectedBy | 4 | `build_docflg.py` (273) · `build_docflg.py (Stage 10 Round 4 reconciliation detector)` (1167) · `build_docflg.py (Stage 9 Round 1 backfill)` (1255) · `fix_stage9_round2_entity_fiscalno_migration.py` (16) |
| DOCRQE | ItemClass | 3 | `Annotation` (1310) · `Decision` (64) · `Status` (1294) |
| DOCRQE | Status | 4 | `Applied` (12) · `Open` (41) · `Recorded` (1965) · `Superseded` (650) |
| DOCRQE | Priority | 5 | `Critical` (14) · `High` (63) · `Information` (2) · `Low` (1088) · `Normal` (1501) |
| DOCRQE | UserDecision | 2 | `Accept` (9) · `Accept with Changes` (3) · *blank on 2656* |
| DOCRQE | SourceRecordType | 14 | `BNKMOV` (74) · `BNKREC` (70) · `DOCFLG` (48) · `DOCLOG` (23) · `ENTBLC` (202) · `ENTITM` (11) · `ENTMST` (100) · `FDCDTL` (391) · `FDCHDR` (655) · `ITMMST` (2) · `PAYCTR` (497) · `PAYDTL` (91) · `RCVCTR` (359) · `RCVDTL` (145) |
| RECREV | Status | 3 | `Applied` (909) · `Open` (154) · `Superseded` (138) |
| RECREV | Priority | 4 | `Critical` (112) · `High` (401) · `Low` (387) · `Normal` (301) |
| RECREV | UserDecision | 2 | `Accept` (871) · `Accept with Changes` (38) · *blank on 292* |
| BNKMAT | MatchType | 11 | `Auto-Created Document - Many-to-One` (1) · `Auto-Created Document - One-to-One` (1) · `Counterparty Balance Settlement` (1) · `Exact Document Match` (1) · `FX-Tolerant Document Match` (1) · `FX-Tolerant Multi-Document Match` (1) · `Internal Transfer` (1) · `Multiple Movements to One Document` (1) · `One Movement to Multiple Documents` (1) · `Payment Gateway Payout Reconciliation` (1) · `Time-Windowed Multiple Movements to One Document` (1) |
| BNKREC | MatchType | 12 | `Internal` (179) · `Matched` (694) · `Matched (FIFO inferred)` (16) · `Matched (FX-tolerant)` (1) · `Matched (approx)` (9) · `Matched (balance netted)` (150) · `Matched (payment control ground truth)` (31) · `Matched (payout reconciliation)` (80) · `Matched (period aggregate)` (8) · `Matched (receivable control ground truth)` (7) · `Matched (review decision)` (32) · `Unmatched` (865) |
| BNKMOV | Classified | 1 | `True` (1960) |
| BNKMOV | Currency | 2 | `EUR` (1939) · `USD` (21) |

## What this table changes

1. **`Non-Blocking` is hyphenated.** Every CHECK constraint and the blocking predicate in the drafts
   use `NonBlocking`. Against pinned data every such predicate is false — total enforcement failure
   from one character.
2. **`DOCFLG.Status` has a fourth terminal state, `Waived`, on 861 rows — 32% of all instances.** No
   draft mentions it. It is a real business act (someone dispensed with a flag) and it is not rare.
   Decided: add it to the lifecycle as a terminal state alongside `Resolved` and `Superseded`, with
   its own waiver evidence and authority. Mapping it onto `Resolved` would erase an audit
   distinction on a third of the table.
3. **`RECREV` has no `Recorded` status and no `ItemClass` field.** The Roles policy asserts
   "Status and Annotation items are retained as `Recorded`" over RECREV. That sentence is
   inapplicable twice over.
4. **`DOCTYP.DocClass` is `Receivable`, singular.** The drafts declare `Receivables`.
5. **Severity is not one vocabulary, it is three.** `DOCRQE.Priority` is
   Critical/High/Normal/Low/Information. The table-derived governed
   `DOCEFL.ReviewPriority` set has six exact literals: `Before Posting`, `High`, `Immediate`,
   `Informational`, `Periodic Review`, and `Routine`; `DOCFLG.ReviewPriority` contains the
   four-literal subset shown in the generated table. This is a *when* ladder, not a severity ladder.
   The v5.0 backlog declares a third vocabulary. They must not be modelled as one column type.
   O9-D4 reconciles the accepted schema artifact to this normative table: the earlier five-literal
   CHECK omitted `Routine` because it was derived from formerly defective explanatory prose. The
   replacement CHECK is exactly the six literals above, with no translation and no vocabulary
   change; its implementation belongs to the additive P1-1b corrective migration and is not part
   of this records amendment.
6. **`DOCEFL.AutoActionAllowed` holds conditional free text** —
   `Yes (provided all Entity Entry Flow requirements are verified)` — in a column the drafts treat as
   boolean. Same defect class as `DOCTYP.FiscalEligible`; both need a separate condition field.
7. **`DOCEFL.AppliesToTable` holds semicolon-joined multi-values** (`DOCLOG; FDCHDR`,
   `DOCLOG; FDCHDR; FDCDTL`). The drafts explicitly forbid multi-valued cells for `DOCTYP.OriginClass`
   and did not notice the same shape here. It needs the same one-row-per-pair expansion.
8. **`BNKREC.MatchType` and `BNKMAT.MatchType` are disjoint vocabularies.** BNKMAT governs 11 named
   match types (`Exact Document Match`, `Internal Transfer`, …); BNKREC records 12 different strings
   (`Matched (FIFO inferred)`, `Matched (balance netted)`, `Unmatched`, …). The mapping draft gives
   BNKREC both a free-text `MatchType` and an FK to BNKMAT with no consistency rule. They are
   measuring different things and need different column names before either is constrained.
9. **Two columns are single-valued today** — `DOCEFL.Active` (`Yes` ×52) and `BNKMOV.Classified`
   (`True` ×1960). Neither has an observed negative case, so neither has a tested false branch.
10. **`DOCLOG.CaptureQuality` is blank on 1,425 of 1,475 rows** while the mapping declares it
    non-nullable.

## How to use it

- Derive every `CHECK` constraint and every enum/domain from this file, generated, not hand-written.
- The import validates against it and fails closed on an unlisted value — an unknown literal is a
  finding, not a row to coerce.
- Regenerate on each new prototype pin and diff. A new literal appearing between pins is exactly the
  signal the freeze exists to catch.

## Annex history

- **2026-08-05 — initial generated annex:** pinned prototype domains established the normative
  literal source. The `DOCEFL.ReviewPriority` table was authoritative, but explanatory prose
  mistakenly named only five literals and omitted `Routine`.
- **2026-08-06 — O8-D1 regeneration:** DOCEFL domains were regenerated from immutable pin
  `b91768513fc638381fbde91f0b576b08220a98f6`; the table measured the same exact six-literal set:
  `Before Posting`, `High`, `Immediate`, `Informational`, `Periodic Review`, `Routine`.
- **2026-08-06 — O9-D4 reconciliation:** the prose/table defect is recorded as history and the
  accepted five-literal CHECK is identified as the defective artifact. The governed decision is to
  replace it with the table-derived six-literal set. This is CHECK completion, not an annex or
  source-vocabulary change; the two pinned `Routine` rows will import verbatim after the corrective
  migration is implemented.
