# Developer agent prompt — Sibyla v5.0, assignment P1-1a

Hand this to the coding agent on the **development machine**, working in
`D:\fileStorage\repos\GOTT.Sibyla`, branch `feature/p1-0d-follow-up`. It is written
to be pasted as the opening message of a fresh session.

---

> ## Read this first — this assignment deliberately opens a gated phase
>
> **Read `docs/PROJECT-STATE.md` first — it is the only source of project state, and no other
> document may be quoted as status.**
>
> **P1-0 was accepted and fully closed on 2026-08-05.** Its named C9/C11/C12/C15 carve-out was
> closed by P1-0d after P1-0c was superseded; none of those corrections is open and P1-0c must not
> be rerun. This historical assignment now runs only as P1-1a under the current phase state.
>
> **All C1–C19 are decided and applied. Nothing is blocked on Luís Nascimento.** If you read a
> marker, a title or a status report suggesting otherwise, it is stale: report it, do not act on
> it and do not repeat it in your own status document.
>
> **The authorization covers exactly this:** write the schema and the validation service,
> exercise them against a **disposable** database, and prove them with **synthetic**
> fixtures.
>
> **It does not cover:** applying a migration to any shared or persistent database,
> importing Luís's live reference data, importing the 2026 history, merging to `main`, or
> claiming P1-1 acceptance. Those stay behind the sign-off. If you find yourself about to
> do one of them, stop and report instead.
>
> This split has a name in this assignment: **P1-1a** is what you may do now, **P1-1b** is
> what waits. Do not silently widen P1-1a. A gate that erodes quietly is worse than no gate.

---

> ## Precedence — read before you open any draft
>
> A structured review of the P1-0 drafts against the pinned prototype (2026-08-04) found **19
> blocking defects**, ten of them proven to fail on counted rows at import. The decisions are
> recorded in **`docs/p1-0-corrections.md` (C1–C19)** and **`docs/p1-0-vocabularies.md`**.
>
> **Both of those documents OVERRIDE the six P1-0 drafts wherever they disagree.** P1-0b's original
> pass was partial, but P1-0d subsequently closed C9, C11, C12 and C15 with governed seed rows and
> provenance, and P1-0e closed their nullability follow-up. If you still read a draft
> statement that contradicts a C-entry, the C-entry wins — do not "reconcile" them yourself and do
> not implement the draft version.
>
> **`docs/p1-0-a-group-decisions.md` is also normative and sits between the C-entries and the
> drafts.** It decides the seven group-A residual items (A1–A7), settles C3's open half, and rules
> that the fifteen group-B items go into this same migration train. It was written specifically to
> unblock this assignment: without it, A1, A3, A4, A5, A6 and A7 each require you to invent a
> column, a key or a constraint. **Read it before the schema mapping.**
>
> `docs/p1-0-vocabularies.md` is **normative and generated from the pin**. Every CHECK constraint,
> enum and domain derives from it. Never transcribe a literal from a draft: transcribing literals by
> hand is how nine of the nineteen defects were created.
>
> If `docs/p1-0-corrections.md` does not exist in your checkout, **stop and report it** — you are on
> a stale branch and everything below assumes it.
>
> **Closed decisions, not deferred blockers.** The seven triage group-A items (A1–A7) and C3's
> formerly open half are closed by `docs/p1-0-a-group-decisions.md`. Implement every one exactly as
> decided there; do not reopen them, stop for a new decision, or substitute a different design.
> `docs/p1-0-residual-triage.md` preserves the earlier defect history and is not current state.

---

## Context

You are working in the **GOTT.Sibyla** repository — a .NET 10 solution (API, Blazor Web,
Worker, Domain, Infrastructure, Tests) that is the production harness for a fiscal document
processing system. The domain model is proven first in a separate Python prototype, the
*Fiscal Document Registry* (FDR), built by Luís Nascimento.

Read these first, in this order:

1. `docs/PROJECT-STATE.md` — the sole authority for current project state.
2. `AGENTS.md` — the v5.0 instructions this repository binds every session to.
3. `docs/project-todo.md` — the v5.0 execution backlog only, not an authority for current state.
   Confirm line 1 reads `Development Plan v5.0` and its live header says `rev. 4`. If either check
   fails, stop and report the stale checkout.
4. **The six P1-0 design freeze drafts** — these are your specification and they did not
   exist when P1-1 was written:
   - `docs/p1-0-design-freeze-summary.md` — start here; 19 decisions and a checklist
   - `docs/p1-0-schema-mapping.md` — the field-level mapping you are implementing
   - `docs/p1-0-codes-taxonomy-archive.md` — code issuance, sequences, DOCTYP seed
   - `docs/p1-0-claude-extraction-contract.md` — the contract the schema must receive
   - `docs/p1-0-discard-purge-lifecycle.md` — Discard/Purge state machine
   - `docs/p1-0-user-ai-roles-responsibilities-policy.md` — the superseding policy
5. **The normative decision documents that sit above the drafts** — `docs/p1-0-corrections.md`
   (C1–C19), `docs/p1-0-a-group-decisions.md` (A1–A7, C3, group B), `docs/p1-0-signoff.md` (S1–S4),
   `docs/p1-0-b1-decision.md` (B1), `docs/p1-0-c20-authored-rows.md` (the three authored seed rows
   and the A3 identity decision), and `docs/p1-0-vocabularies.md` (generated, normative for every
   literal). **`docs/p1-0-c20-authored-rows.md` is the one most likely to be missed and it is
   normative** — the next section is its implementation index.
6. `docs/2026-08-04 Sibyla_Organigrama_Fluxo_v14.svg` — the information-flow diagram,
   redrawn against the freeze. **Do not use the v13 file**; it is kept only because the
   cross-check record cites it, and nine of its labels are superseded.
7. `docs/project-evolution.html` — project history, risks, and next steps; it yields to
   `docs/PROJECT-STATE.md` for current state.

**Where the two sources disagree, the P1-0 drafts win.** The P1-1 backlog section was
written before the freeze and still carries superseded text — see the next section. The
backlog is the authority on *what* to do; the drafts are the authority on *how it is keyed*.

## Three places the backlog is stale — correct them, do not implement them

This is the single most important section of this prompt. All three would produce work that
has to be thrown away.

1. **The code-uniqueness item still offers `DocLogId` as a live option.** It reads "If
   LGCode remains a capture identifier, the constraint is `(LGCode ↔ Filename)` 1:1 and
   DOCLOG carries a separate per-row `DocLogId`." That question is **closed**. LGCode *is*
   the permanent DOCLOG row identity, keyed on **`(Filename, EntryCode)`**, and **no
   `DocLogId` is added**. Implement the check as a **`(Filename, EntryCode)` ↔ LGCode
   bijection**. The naive "no permanent code may appear against more than one EntryCode"
   test is wrong under this model and would reject internally consistent data — it is
   explicitly prohibited.
2. **The orphan-DOCLOG check must not become a delete.** Add the check; report what it
   finds. Do **not** propose removing rows. That was proposed once: of the rows flagged,
   most were honest audit traces of superseded generations, some were future-dated schedule
   rows, and 27 concealed a real **EUR 142,835.50** gap — six months of 2026 payroll with no
   FDCHDR row at all. A blanket delete would have destroyed the only surviving trace.
3. **The roster in the backlog is the corrected one, but check it against the mapping
   draft, not against memory.** `MNGACC` not `MNGAPL`; `DOCTYP` not `DOCTYPE`; `COCACC` and
   `DOCFLG` present; DOCRQE is a persisted table, never a view.

If you find a fourth contradiction, **report it rather than resolving it yourself** — a
contradiction between the backlog and a frozen draft is a signal that one of them is wrong,
and that is a human call.

---

## Step 0 — repository hygiene prerequisite (completed)

At assignment time the working tree showed **268 files modified with 87,768 insertions and 87,768
deletions** from CRLF churn and had no `.gitattributes`. That historical prerequisite is complete:
the repository now has an LF policy commit followed by a dedicated empty renormalization commit.

- Do not repeat or amend either line-ending commit.
- Keep `.gitattributes` in force (`*.svg` is text; `*.pdf`, `*.png`, `*.xlsx` are binary).
- Verify that `git status` contains only the intended P1-1 work before continuing.

The work below may start once that clean-scope check passes.

---

## What P1-0d and P1-0e added — implement these exactly

This prompt predates both assignments. Everything below is **decided, in the drafts, and easy to
implement from the older text by accident**. Read it before you open the schema mapping; if any of
it contradicts an older paragraph in this prompt, this section wins.

**One of these is a removal, and a removal is the one an implementer never notices:**

- **`MatchGroupID` has NO CodeLedger bucket.** A3 was resolved by measurement: `build_bnkrec.py`
  derives `MatchGroupID` per run from `(MatchStatus, BMCode)` or `(MatchStatus, MatchedRef)`, so it
  is a **run-scoped grouping label with no permanent identity**. Its bucket was **removed from
  P1-1a's ledger scope**. Do not create it because an older draft or diagram lists it. Record it as
  non-permanent, never quotable as stable identity, and keep it out of every key.
- **`BRCode` keeps its bucket** and its permanent alternate key is
  `(Company, BMCode, EntryCode, FindingDiscriminator)` with `NULLS NOT DISTINCT`. `BRCode` itself is
  non-null unique and binds restrictively to the single surviving `BNKREC` bucket through a
  generated constant and composite FK. **Issuance is P1-1b** — create the column, the constraint and
  the bucket; do not implement generation.

**DOCEFL and BNKMAT nullability is now specified, and it is not the older all-NOT-NULL shape:**

- DOCEFL permits NULL on `FlagCategory`, `RiskFactor`, `AutoReviewable`, `Summary`, `FlowDimension`,
  `PolicyReference`, `RequiredAction`, `AutoActionAllowed`, `ReviewOwnerRole`, `ReviewPriority`,
  `BlockingLevel`, `ResolutionEvidenceRequired`, `EffectiveFrom` and `EnforcementStartsAt`, in
  addition to the three already nullable. **A NULL automation boolean grants no authority** — model
  that as denial, never as a default-true.
- The DOCEFL identity constraint is `UNIQUE NULLS NOT DISTINCT (FlagReasonCategory, FlowDimension)`.
  PostgreSQL's default `NULLS DISTINCT` would silently stop enforcing it the moment `FlowDimension`
  is NULL. **Write the modifier explicitly; do not rely on the default.**
- Add the named **`RequireRunnableActiveDecisionDOCEFL`** CHECK: an *active* `Decision` detector must
  have non-NULL `FlagCategory`, `ReviewOwnerRole`, `ReviewPriority`, `BlockingLevel` and
  `EnforcementStartsAt`. Add the authenticated, company-scoped, audited **`ActivateDOCEFLRule`**
  command that supplies all five in one operation and **refuses a partial activation**.
- BNKMAT permits NULL on `ReconciliationType`, `AutoProposeAllowed`, `AutoCloseAllowed`,
  `MaxDateWindowDays` and `ToleranceAmount`. `RequiresReview` stays NOT NULL.

**The three authored rows exist and are normative — but you do not seed them:**

`EF0000000` (C11 sentinel, `Annotation`, `Non-Blocking`, the FK target for `FL0002653`, `FL0002654`,
`FL0002655`, `FL0002661`), `EF0000053` (C12 Monthly-gap, `ItemClass=Decision`, **seeds
`Active=No`** and can only be activated through the command above) and `BT000012` (D6,
`RequiresReview=Yes`, `RequiresFDCHDR=No`, excluded from the reconciliation numerator). **Seeding is
P1-1b, and that has not changed just because the rows now exist.** Your job is that the schema can
hold them: build the migration so all three would insert without a placeholder literal, and prove it
with synthetic fixtures shaped like them. **Historical-result correction:** accepted P1-1a was
implemented and tested before O8, so its synthetic authored-row fixture and tests still use the old
Monthly-gap code `EF0000046`; they do not prove `EF0000053`. Preserve that accepted P1-1a history
and keep its migration immutable. Before P1-1b seeds the O8-authorized row, P1-1b must update or
replace that synthetic fixture and its tests from `EF0000046` to `EF0000053`, then prove the same
inactive-row/nullability contract against the current code. **A migration that forces a `'N/A'`,
an `'Unknown'`, an empty string or a zero into one of those columns has failed this assignment**,
no matter what else it does.

**Seed rows that now exist and are still not yours to import:** the 19 DOCTYP tuples, the 52 DOCEFL
rows and the two ITMCLS `CLCode`s are transcribed into the drafts with per-field `extracted`
provenance and blob SHAs. They are specification, not an invitation. Importing them is P1-1b.

**One thing the new nullability costs you, and it is yours to catch:** the 52 imported DOCEFL rules
all carry values in columns that are now nullable, so the schema can no longer reject an import that
silently drops one. **Add a seed/import completeness assertion to the validation service** — every
imported DOCEFL rule must carry the fields its source row carried — and report it as a failure, not
a warning. Do not solve this by reverting a column to NOT NULL.

---

## P1-1a — what you may do now

### 1. The migration train (written, not deployed)

Add EF Core migrations for the FDR layer 1–5 tables, `DOCARC`, the code sequences, and the
export-run ledger, implementing `docs/p1-0-schema-mapping.md` field by field **as corrected by
`docs/p1-0-corrections.md`**. Retire the superseded financial schema in the same train.

**The corrections that change this task most** — read the C-entries, this list is an index, not a
substitute:

- **C1** — bank-generated FDCHDR needs a `FdcHdrBankMovement` junction table plus a `SourceKeyHash`
  generated column. The draft's scalar `SourceKey` FK resolves 0 of 7 aggregate payroll documents.
- **C2** — ENTITM stores `CodeName`; the rendered `EntityCode` is a derived export. The draft's
  "import must reject an EC code" rule is inverted and would reject 100% of rendered rows.
- **C3** — `EnforcementStartsAt` is seeded to the Sibyla go-live timestamp, **not** from DOCEFL
  `EffectiveFrom`. Seeding from `EffectiveFrom` makes 29 blocking flags fire on day one.
- **C4** — every literal comes from `docs/p1-0-vocabularies.md`. `Non-Blocking` is hyphenated;
  `DOCFLG.Status` includes `Waived` (861 rows); `DOCTYP.DocClass` is `Receivable`, singular.
- **C6** — the DOCRQE constraint is the openness invariant only. The draft's `Recorded` requirement
  fails on 639 rows.
- **C7** — `SourceTextHash` keeps the pinned `md5-12` algorithm plus a `HashAlgorithm` discriminator.
  Recomputing it reopens 2,562 terminal instances.
- **C9** — DOCTYP coverage applies to captured documents only (`Source <> 'BNK'`). Add
  `Duplicate | External`. `Invoice-Receipt` keeps its hyphen.
- **C10** — `PaymentSequence` lives on PAYDTL/RCVDTL, never on the PAYCTR/RCVCTR header.
- **C12** — there is no OFDGAP table. Gap detection is a DOCEFL rule emitting findings.
- **A1 (group-A decisions)** — `CounterpartyCodeName`, a stored `char(1)` `FlowType`, and a
  generated `NormalizedDocumentID` with a `DocumentIdNormalizationVersion` discriminator **in the
  unique index**. Normalization is uppercase then strip non-`[A-Z0-9]`. Never compare across
  versions — same rule as C7's `HashAlgorithm`.
- **A4 / A6 / A7 (group-A decisions)** — RECREV stores `ProposedMatchBTCode` FK to `BNKMAT(BTCode)`;
  `ImportBatch` gets an identity PK plus the retained `unique (Id, CompanyCode)`; `FailureCategory`
  is deleted and `Category` is the field.
- **C3 as decided** — `EnforcementStartsAt` is seeded to the Sibyla go-live timestamp and is
  **immutable after import or first use**, enforced by a named reject trigger. There is no
  recompute path and no recompute audit table. Persisted `IsGrandfathered` verdicts are never
  rewritten; a rule correction is a new DOCEFL rule version.
- **All fifteen Group B items are in scope for this train.** B1 is closed: each capture owns its
  own unshared byte object, even when content hashes match; `RetainedContentHash` is only a
  duplicate-detection index and never a storage pointer. Implement no sharing or reference
  counting, and do not wait for confirmation before implementing the capture-scoped tombstone path.
- **C13** — the FL natural key is
  `(EFCode, RelatedRecordType, RelatedRecordID, SourceTextHash, DetectedAt)`. The draft's key
  collides on 78 rows. FL is **not** sequential — 141 gaps exist at the pin.

Constraints that come straight from the freeze and are easy to get wrong:

- **Keep it as ONE squashable migration until sign-off.** If Luís's review changes the
  mapping, you **delete and regenerate** it. Do not stack a fix-up migration on top of a
  migration that was never applied anywhere — that permanently bakes a mistake into the
  train for no benefit.
- **Sequences are non-cycling, and allocation is not naive.** `INSERT … ON CONFLICT DO
  NOTHING RETURNING`, and on loss, a **new-statement winner read followed by a full-key
  comparison**. `nextval()` is intentionally non-transactional: rollbacks, crashes and
  concurrency losers leave gaps, and **those gaps are never reused**. Runtime `setval` /
  `RESTART` is forbidden; preserved imports initialize unused sequences **once**, under
  exclusive bootstrap locks.
- **A collision raises. It never silently picks a winner.**
- **The parked `Integration*` ledger keeps its existing non-null restrictive
  `Document`/`ExtractionRevision` FKs.** Do not repoint historical integration records.
  FDCHDR distinguishes four evidence anchors without fabricating any: native extracted
  Document+ExtractionRevision, authenticated ManualEntryEvidence, deterministic bank
  `SourceKey`, or imported `ImportEvidenceRow`.
- **Company scope is relationally closed** through controlled `CompanyRegistry` codes
  resolved from authenticated context. Composite FKs must reject cross-company links on
  FDCHDR, bank, reconciliation, PAY/RCV, manual, Document and import-evidence rows. The
  pinned `Company` / `CompanyCode` spellings survive as *export* fields only.
- **The current global unique Document hash index is NOT replaced in this train.** Retained
  content hashes become canonical `(company, hash, length)` rows with many capture-event
  links, and byte-identical captures stay distinct — but the index swap is a reviewed later
  migration. Leave it.
- **`DOCARC.DocumentDate` is nullable**, and a missing date routes to review without
  becoming archive-eligible. Enforce that in the model, not only in code.
- **`ItemClass` is a closed enum** (Decision / Status / Annotation) — model it as closed,
  not as an extensible lookup table.
- **`ReferenceOnly` is first-class and has no EntryCode.** The schema must make it
  structurally impossible for a Reference Only row to reach FDCHDR, PAYCTR, ENTBLC, aging or
  the matchers — not merely unlikely.
- **DOCTYP expands one row per `(DocumentType, OriginClass)`.** A multi-valued Allowed
  OriginClass cell is not one row with a list in it.

Apply it **only** to a throwaway local database or a test container you create and destroy.
Nothing shared. Nothing that survives the session.

### 2. The validation service

Port `Scripts/validate_registry.py` from the prototype. Read the script; do not
reconstruct it from the backlog summary. Checks required:

- unique DOCLOG filenames
- no `(CodeName, DocumentID)` collisions on payables
- header ↔ detail within 2 cents; no zero-line rows
- every CodeName resolves to ENTMST with a non-blank FiscalNo
- every `(Period, Currency)` in use has an EXCRAT row
- every DOCLOG row has a DocumentType
- Flag ↔ FlagCategory both-or-neither
- every `(DocumentType, OriginClass)` **on a captured document (`Source <> 'BNK'`)** has a DOCTYP
  rule and matches its Treatment — see C9; the universal form fails on 547 bank-generated rows
- synthetic-FiscalNo count reported as a **warning**, not a failure

Plus the two new ones:

- **orphan DOCLOG** — an EntryCode resolving to no document in either FDCHDR or the
  bank-generated document set. Report only.
- **code uniqueness** — the `(Filename, EntryCode)` ↔ LGCode bijection described above.

### 3. Port the identity-stability test

`Scripts/verify_code_identity_stability.py` shuffles the rows, blanks every code, reassigns
from the ledger alone, and requires that **not one code moves**. Port it as a .NET test.

This one matters more than it looks: **an order-preserving check would have gone green while
the defect was live** — that is exactly what happened before. Read the script.

### 4. Synthetic fixtures

Build the fixture set yourself. **Never lift real rows from the prototype**: it contains
real IBANs, fiscal numbers, salaries and bank statements for Gott and Itoorer. No real value
reaches this repository, a commit message, a log line or a test file.

Cover at minimum: the seven payroll documents that carry a **comma-joined list of up to 15
BMCodes** (a single-code reader fails to anchor exactly where a wrong duplicate would be
largest), and the **two byte-identical statement lines on one day** that make the occurrence
tiebreaker load-bearing — merging them causes *under*-generation.

---

## P1-1b — blocked, do not start

Report these as blocked rather than attempting them:

- importing Luís's live reference data from `Invoice Skill Build/Editor/Data/*.json`
  (ENTMST, ENTALS, ITMMST, ITMALS, ENTITM, ITMCLS, MNGACC, SNCACC, COCACC, EXCRAT, DOCTYP,
  DOCEFL, DOCFLG instances, and `user_observations.json`)
- the D4 2026 history import (DOCLOG 1,475 · FDCHDR 1,153 · FDCDTL 1,190 as at 2026-08-04 —
  re-measure, do not quote)
- applying the migration to any shared or persistent environment
- the P1-1 acceptance criterion — "seeded database reproduces the FDR reference sheets
  exactly through the P1-12 renderer" — which is unreachable without the seed
- any change to the P1-0 drafts themselves

The reason is the same for all of them: they depend on Luís's review of the schema/key
mapping against the pinned prototype, and doing them now would mean redoing them.

---

## The prototype — read-only reference

`git@gitlab.com:gottsolutions.dev/sibyla/invoice-skill-build.git`, branch `main`. Clone it
**beside** this repository, never inside it.

1. **Read-only. Never push, never open a merge request, never commit.** Luís works in it
   daily.
2. **Pin to a SHA and record it** in your work. P1-0 pinned `9359c67c4ef0101218d7e0ffff1986114ba5cc7a`
   — use the same pin unless you have a reason not to, and say so if you change it. A
   floating `main` means the specification shifts under your schema mid-design.
3. **It contains real financial data, committed rather than gitignored.** Treat it as
   confidential.
4. **Port the behaviour, not the Python.** A script that reads a JSON file and rewrites it
   is solving a problem you do not have.

Read for this assignment: `Scripts/validate_registry.py`,
`Scripts/verify_code_identity_stability.py`, `Scripts/add_row_codes.py`,
`Scripts/build_bnkmov.py`, `entity_utils.generated_source_index()`,
`Specs/Data Schema/schema.md`, and `Backups/Control Log.md` — the Control Log is worth more
than it looks, because when a rule seems arbitrary it usually has an entry explaining which
specific failure produced it.

---

## Non-negotiables

From the v5.0 Definition of Done. Invariants, not preferences:

- Claude reads and proposes; only authenticated deterministic .NET code validates, decides,
  persists, issues identity and executes side effects.
- Strict deterministic validation is **atomic and precedes every extraction-derived
  projection**. Intake `Document` and `ExtractionAttempt` may persist first.
- A malformed payload creates **no ExtractionRevision and no DOCLOG** — ExtractionAttempt
  plus attempt-keyed DOCFAI/Decision review with a NULL LGCode. A schema-valid
  `NOT_A_DOCUMENT` is a **different thing** and takes the normal ExtractionRevision →
  DOCLOG/LGCode → DOCFAI → Decision route.
- A recorded decision survives a full pipeline rerun. Queue state is persisted, never
  recomputed.
- Only Decision items are ever Open. `% worked` is reported on the Decision denominator only.
- A rejected proposal is never re-proposed by any matcher, on any run.
- New rules do not retroactively block imported history — grandfathering derives from each
  instance's own `DetectedAt` against `EnforcementStartsAt`, never the import date.
- DOCFLG is the enforcement authority and blocks the affected action **before it runs**.
  Queues display and decide; they do not enforce.
- A wrong-but-plausible value is worse than an honest blank. Missing rates, identifiers or
  evidence fail closed to review.
- Human classifications and corrections are never overwritten by automation.
- A metric that improves because a check was removed is a regression, not progress.
- `dotnet build GOTT.Sibyla.slnx` passes with **zero warnings**;
  `dotnet test tests\Sibyla.Tests\Sibyla.Tests.csproj` passes with zero failures.

## Repository hygiene

- Stage only files you deliberately changed, **by explicit path**. Never `git add -A`,
  never `git add docs`.
- Focused commits on `feature/p1-0d-follow-up`. **Do not merge to `main`**, do not
  rebase or force-push — the planning documents arrive on this branch from another machine.
- The prototype clone lives outside this repository. Never a submodule, never committed
  here.

---

## Definition of done for this assignment

- The completed `.gitattributes` policy and dedicated empty renormalization commit remain intact;
  `git status` is clean except for this assignment's intended work.
- The migration train exists as a single regeneratable migration, applied only to a
  disposable database, and implements the schema mapping draft field by field **as corrected by
  C1–C19**.
- The validation service passes clean on synthetic fixtures, including the orphan-DOCLOG
  check and the `(Filename, EntryCode)` ↔ LGCode bijection.
- The identity-stability test is ported and green.
- **No `MatchGroupID` CodeLedger bucket exists.** `BRCode` is non-null unique with the
  `(Company, BMCode, EntryCode, FindingDiscriminator) NULLS NOT DISTINCT` alternate key, bound to the
  single surviving BNKREC bucket; no issuance is implemented.
- DOCEFL and BNKMAT carry the P1-0e nullability exactly, the DOCEFL unique constraint states
  `NULLS NOT DISTINCT`, and `RequireRunnableActiveDecisionDOCEFL` plus `ActivateDOCEFLRule` exist and
  refuse partial activation.
- At P1-1a acceptance, the synthetic fixture proves `EF0000000`, the then-current
  `EF0000046` Monthly-gap row (inactive), and `BT000012` all insert with no placeholder literal in
  any column. O8 later re-authorizes Monthly-gap as `EF0000053`; P1-1b must update or replace that
  fixture and its tests before seeding, without editing the accepted P1-1a migration.
- The validation service includes the DOCEFL seed/import completeness assertion.
- Sequence allocation is proven concurrent-safe by test: rollback, crash and concurrency
  losers leave gaps, and no gap is ever reused.
- No real prototype value appears anywhere in this repository.
- A short `docs/p1-1a-status.md` recording: the prototype SHA you read, every place the
  backlog contradicted a P1-0 draft and how you resolved it, **every C-entry you applied and any you
  could not**, and the exact list of P1-1b items left blocked and why.
- **Nothing from the P1-1b list was started.** No shared database was touched. No live
  reference data was imported.

Report back with that status document. Do not proceed to P1-1b, and do not treat P1-1 as
accepted — acceptance needs the seed, and the seed needs the sign-off.
