# Sibyla — state

**Updated:** 2026-08-28 · **Phase:** **S0 closed (8/8)**; **S1 closed 2026-08-20**; **S2 is open**. `S2-6`–`S2-13` are complete: `S2-12` landed in `!160` and `S2-13` in `!161`, with `S2-14`'s spine but not yet its metric. **`S2-14` is the next implementation item, and it is blocked on a decision rather than on code** — see `O13`. Runtime baseline **`!162`** (merge `248c52a`); `!158`–`!162` all merged 2026-08-27 with green pipelines. This does not claim local `main`/upstream synchronization. **A Worker-only schema-pinned maintenance cutover plus documental-agent profile rollout was deployed and verified under O14/O16; there was no general `main` deployment, live migration, ERP activation, EntryCode/LGCode issuance, or live-tenant operation.** · **Plan:** `docs/V6.md` · **Backlog:** `docs/project-todo-v6.md`

One page. Updated **in place**, never appended to. If this file passes two pages it is being used
as a diary and needs cutting — that is the first sign the v5 habit has returned.

## The nine steps

The loop v6 exists to make work (`V6.md` §3). Filled in by **S0-4** from its **final, successful run on 2026-08-18**: the exact pinned **GD-1** bytes
(`docs/golden-documents.md`) submitted through `/api/channel-intake/v1` with the verified dedicated channel-intake client, against isolated PostgreSQL and an
isolated Local scratch storage root. That run supersedes the **2026-08-10 preliminary run**, which admitted no document and is history rather than state.
**works** · **broken**, with what was unresolved · **missing**, meaning no such code exists · **not reached**, meaning the step was never given an input, so
its code is neither proven nor disproven.

| # | Step | Status |
|---|---|---|
| 1 | A document arrives — email · WhatsApp · Mattermost · web upload | **works** — 201 on register, 200 on same-idempotency-key replay with `replayed=true`, and 200 on upload and on status. The sender mapping was **pre-existing and enabled**; none was created, enabled or edited |
| 2 | It is recognised — is this a document, whose, what type | **broken** — recognised as an Invoice, but the internal company, the counterparty and the direction were all left **unresolved** |
| 3 | It is read — agent extracts, deterministic code validates | **works** — the Hermes extraction job reported **Succeeded on attempt 1**; the response passed strict contract validation and was persisted as one revision with two lines. The deterministic gates **executed and returned false**, raising warning `LINE_SIGN_AMBIGUOUS` and routing the document to review. Executed, not passed |
| 4 | It is classified — counterparty resolved, lines mapped to accounts | **broken** — cataloging ran, but direction and counterparty stayed unresolved, and the July `DocumentLine` shape carries **no account-mapping surface** to map lines onto |
| 5 | It is persisted — DOCLOG + FDCHDR + FDCDTL, audited | **missing** — no DOCLOG/FDCHDR/FDCDTL writer exists anywhere. The application persistence and the audit writes did work |
| 6 | Uncertainty is surfaced — flags raised, human reviews the doubtful | **works** — the document reached `AwaitingReview`/`NeedsReview` on the false gates, with the warning and a fingerprint-incomplete audit entry recorded. **No human decision was performed** |
| 7 | The human's answer is learned — correction updates the reference layer | **missing** — no correction-learning write-back exists |
| 8 | It is pushed — Cegid izibizi, idempotent, PDF attached | **not reached** — outbound **business integrations** were **deliberately disabled** for the run (Cegid, Microsoft Graph and the financial push paths off), so no external **business-integration** job, commit, operation or call was attempted and the code is neither proven nor disproven. What did occur was **OIDC discovery and token acquisition against the configured Identity authority, for authentication to the Sibyla API** — no token, client id or value is recorded |
| 9 | It is filed — original stored, non-fiscal archived | **works for fiscal GD-1** — the exact original was stored immutably and rehashed to match. The **non-fiscal archive branch was not applicable** to GD-1 and was not invoked |

**Measured, 2026-08-18.** The run exercised the **installed artifact `a8d0a4bab7b2f93920ad29819d442e01c04dd374`**, which is **ancestral to `main`**: this is
evidence about that artifact and is **not a demonstration of the current `main` runtime**, and `main`'s governed staged migrations were **not** bypassed to
obtain it. Storage was an **isolated Local scratch root** and the database an **isolated PostgreSQL** instance — neither shared nor live. Intake used the
dedicated channel-intake client verified earlier the same day against a **pre-existing enabled sender mapping**: **no live write, and no mapping created,
enabled or edited**. **Cleanup verified after the run:** the disposable resources and the sensitive snapshots were removed; the temporary listeners, the
container and the temporary directory are **absent**; the live Worker remains **Running** under `.\GottSibylaDocumental`; and the original GD-1 file in the
read-only prototype is **unchanged**. No field values, identifiers or sender identity are reproduced here.

**The 2026-08-10 preliminary run, for contrast — superseded, not current state.** Three hosts started under the `Development` EF InMemory fallback with
`/health/ready` **`Degraded`**, no PostgreSQL migration applied, and no document admitted, which is why every downstream step then read *not reached*. Its
durable measurement stands: `scripts/run-p11a-disposable-tests.ps1` starts a throwaway PostgreSQL and the 61-test FDR schema suite passes **61/61** against
it — a suite excluded from `dotnet test` by a csproj default filter, so the schema had never been exercised by a pipeline.

**What S1 and S2 must change.** Nothing observed reverses V6-D1 — the July spine was recovered and carried GD-1 from channel intake through
extraction to review routing and immutable storage. That is the spine running, not all nine steps: the broken, missing and not-reached findings in
the table above stand exactly as recorded. S1 and S2's real work is what steps 2, 4, 5 and 7 name:
re-pointing cataloging onto DOCLOG/FDCHDR/FDCDTL, resolving internal company, counterparty and direction, giving lines an account-mapping surface, and the
correction write-back. Per-host configuration stays as it is: the committed `Sibyla:StorageRoot` defaults are empty and each host sets `Sibyla__StorageRoot`;
left blank, `LocalDocumentObjectStore` resolves `{ContentRoot}\devStorage` **per host project**, not at the repository root. Local is Development-only.
**S2 does not need a new intake route:** `/api/channel-intake/v1` exists under the `ChannelIntakeWrite` policy, delegates to `IDocumentUploadService`, and
GD-1 has now been carried through it end to end.

## Where the code stands

The **July stack** is the spine: upload, Hermes extraction, cataloging, review UI, Cegid izibizi client, Moloni adapter, PostgreSQL job engine. MR `!59`
merged substantial application code on **2026-08-15**. In the last recorded three-host check, all hosts used the `Development` InMemory fallback;
PostgreSQL migration application on those hosts was unexercised and readiness was `Degraded`.

The **FDR tables** are owned by the EF migration chain. S1.5 Phase B removed the duplicate P11a ENTMST, renamed the live `BusinessEntities` table to `ENTMST`,
retargeted its children to the UUID key, and retained the initial `P11aSchemaSql` only as historical migration payload. The reference-data seeder now writes the
post-collapse shape. The **document** tables (DOCLOG/FDCHDR/FDCDTL) still have no live writer: the July pipeline persists to `Documents`, `DocumentLines`,
`FileAssets` and `ExtractionRevisions`. That bridge remains S2.

Since MR `!59`, merges `!62`–`!115` landed 2026-08-16/20 on `main`, every one on a green MR
head pipeline, runtime merges also on a green post-merge `main` pipeline, each with a fresh
adversarial review recorded as MR comments and fixed forward. **The full record of every merge
— description, SHAs, pipelines, review and disposition — lives on its merge request and in the
docs-record merges in this file's git history**; this file keeps the map and the current
baseline only:

| MRs | What |
|---|---|
| `!62` | S1-3a item-master consolidation (migration `20260815142000`) |
| `!63` `!64` | S1-9a module shell + routes · S1-9b `<ReferenceGrid>` pattern |
| `!65` `!66` `!69` | S1-9c code lists: ITMCLS · MNGACC · COCACC (read-only) |
| `!70`–`!72` | S1-6a: DOCTYP presentation data, routing service, `DocumentTypeSetting` drop + read-only DOCTYP catalogue |
| `!74` `!79` `!82` `!84` `!86` `!89` `!91` `!93` `!96` `!97` `!98` | S1-9d Entity 360, slices 1–11 — all nine tabs; governed M-D4 writes for Identity, Tax identifiers, Roles, Aliases, Banking, Items; read-only Documents, Balances, Audit |
| `!100` `!101` `!102` | S1-9c remainder: EXCRAT + missing-rates panel · ITMALS (first `GlobalOrActiveCompany`) · ENTALS (read-only) |
| `!104` `!105` | S1-9h first cut: DOCEFL read catalogue · S1-9g slice 1: governed DOCTYP presentation write (LabelPt/LabelEn/SortOrder) |
| `!107` | S1-9i: Companies entity half onto the governed identity write |
| `!109` `!110` `!112` | S1-9e: ITMMST item master · entity-item matrix + classification queue · entity-banking catalogue |
| `!113` | S1-9f: SNC chart-of-accounts tree |
| docs-only | `!67` `!68` `!73` `!75`–`!78` `!80` `!81` `!83` `!85` `!87` `!88` `!90` `!92` `!94` `!95` `!99` `!103` `!106` `!108` `!111` `!114` `!115` — no runtime change |

**The runtime-baseline chain.** Exactly one merge is *the* current runtime baseline at any moment: the GitLab `main` API reported **`!153`** as of 2026-08-25 (source `bc5d94a7882db5be9bd3f0b5a807ee65415a9a2d` → merge `4167f7e67da02f9527a3433908396d49580c9d29`). This is remote API evidence, not a claim that local `main` or an upstream-tracking ref is synchronized. The entries below record the chain that led to it, each having been the baseline until the next runtime merge superseded it — they are history, not competing claims.

**Baseline at 2026-08-20 10:35:** `!113` — source `cf444ed1278ee2691c7d9d6052b5b854bfb7fc8a` →
merge `904b434a367d3a140a8c07da10b311f0139b27ff`, merged 2026-08-20T10:35:36.673Z; MR pipeline
**2775760116** and post-merge `main` pipeline **2775800133** succeeded. The CI-minutes quota
ran out earlier that day (`ci_quota_exceeded`, `!110`'s post-merge **2775612809**), was topped
up the same day, and that pipeline was retried green. **One stop-list merge exists in this
repository:** `!72`'s `DocumentTypeSetting` drop, merged 2026-08-18T09:46:15.85Z on green
pipeline **2768548294** — the measured merge action is the only approval record; no verbatim
approval text exists and none is to be reconstructed.

**`!117`** (*the governed DOCTYP offer toggle, `S1-9g` g2*; source
`3d8f1cea45382f5cd65ad3dd921291c5ebedf469` → merge `639dd65e5eb04c574d7b4fa56b11b4ff6ff9f306`,
merged 2026-08-20T11:37:27.151Z) superseded `!113` as the baseline: administrators offer or withdraw a document type at intake on the same governed
write path as `!105` — offering fails closed without the full presentation, on an inactive row,
or when an already-offered sibling of the same DocumentType carries divergent presentation
(routing would turn ambiguous for every consumer); withdrawal takes a typed confirmation
enforced server-side, with the dialog stating the per-row semantics and the in-flight
consequence; every change audits before/after in the same transaction. The slice's stop-list
assessment is in its MR: it writes only `DOCTYP.IsActive` in the application's own database —
no live tenant is configured, no routing column is touched. **The first slice under the CI
economy:** the fresh adversarial review ran **pre-push** (verdict ACCEPT-WITH-FIXES, all five
should-fixes folded in before the single push), so the MR cost one head pipeline —
**2775927583** — plus post-merge `main` pipeline **2775965673**, both green.

**`!119`** (*teach the source parser Oman*; source `a7c8c630d0a62e859db7a122c7e9e0b65ee446b1`
→ merge `29a05bcf18e55c6ffa16d36c32b3a3520acbeae9`, merged 2026-08-20T12:53:49.882Z) superseded `!117`: a four-line change — the parser's country dictionary gains
Oman/OM for the source's new Omani counterparty, the known-country theory pins both forms, and
the unknown-country rejection sentinel moves to "XQ" (ISO user-assigned range, so it can never
rot into a real code). Pre-push review verdict **ACCEPT with no findings** — every downstream
country validator is shape-only. MR pipeline **2776140303** and post-merge `main` pipeline
**2776181542** succeeded; PartyCollapseContract 38/38 and P11aDatabase 61/61 ran locally for
the Infrastructure change.

Two more fixes followed the demonstration's findings the same day. **`!121`** (*repair the
double-encoded dashes*; merged on green pipelines) replaced nine mojibake em-dashes committed
into `Suppliers.razor` — the "â€”" the Roles tab showed — and widened the page-contract
mojibake pin to the generic double-encoded prefix so no future variant reaches a
demonstration. **`!122`** (*materialize the primary tax identifier from seed evidence*; source
`58ecd44efc12477a428796c1ad421b8464f8dddc` → merge `1b4600da817ee7826b16f0191c539e2c324b2755`,
merged 2026-08-20T14:51:21.760Z): migration `20260820141922` restores the `!82` invariant on
rebuilt databases — the FiscalNo scalar regains its 1:N primary identifier, materialized from
the seed evidence's canonical values, inserts-only, merged parties excluded, human-corrected
rows surviving `Down`; MR pipeline **2776510104** and post-merge **2776567880** succeeded.
**Applying it to the demo database surfaced real data: the current source carries two genuine
duplicate-fiscal groups** — `EC000001`+`EC000093`+`EC000095` share one fiscal identifier and
`EC000097`+`EC000098` another (not repeated-digit placeholders) — and the migration's first
cut failed closed on them, holding every clean party back. Miguel decided **skip-and-report**
(O6, 2026-08-20), delivered as **`!124`** (*skip-and-report collisions in the tax-identifier
materialization*; source `97c7be82e89ca0419c45537184fad7384b1b5296` → merge
`19f7e8df2ef7d1d52d04d956fc56ebac44b9adec`, merged 2026-08-20T16:45:13.852Z), which superseded `!122`: the same migration edited in place — safe because it was applied nowhere
durable — now skips source-internal duplicate groups **whole** (never choosing a winner),
skips a candidate whose identity an existing identifier already claims, reports skips as a
PostgreSQL `WARNING` naming the entity codes (visible in psql/Npgsql notice logging; the EF
CLI prints no notices), and **always materializes the clean parties** — the fiscal-identifier
policy's live-data-first stance. Only the **merge** branch of O6 unblocks a replay for the
skipped parties; a legitimacy call needs its own schema decision, since the fiscal-identity
unique keys forbid two owners. The pre-push review's four fixes were folded before the single
push (among them a test seeding the exact duplicate shape that blocked the demo database, with
the WARNING pinned through a notice listener); MR pipeline **2776839210** and post-merge
**2776884680** succeeded. Applied to the demo database the same day: **110 identifiers
materialized, the 5 O6-group members skipped and reported**, and the Tax Identifiers tab shows
data — CTT included.

**S2 opened the same day.** **`!127`** (*governed enablement for runtime DOCLOG code
issuance, S2 slice 1*; source `8d0a075c94b14e9c662889e66628d3dc0a50a290` → merge
`c484b2e2a9e1d4cfc9233873dcb90cc378c3ed81`, merged 2026-08-20T18:10:50.666Z) superseded `!124` and opened S2: writing DOCLOG from the `DocumentCatalogingService` bridge needs runtime
LG-code issuance, which P1-1a ships deliberately disabled — **Miguel authorized issuance in
the bridge on 2026-08-20** (stop-list act) — and migration `20260820173747` installs the
machinery while **enabling nothing by itself**: `EnableS2DoclogRuntimeIssuance(role)` is
operator-invoked once per environment (S1.5 grant-function precedent), requires the S1-8
high-water reservation first and an active RuntimePrincipal, flips only the DOCLOG bucket,
grants the allocator authority, and appends to an append-only audit; the registry trigger
gains exactly one arm (RuntimeEnabled-only UPDATE on `CodeSequenceRegistry` under a dedicated
GUC); Down refuses while any LG code issued since the first enablement exists (time-based
attribution). The doc-comments state the accepted breadth (the allocator grant is
bucket-global; every other governed bucket refuses as disabled; enabling more buckets is its
own stop-list act) and the accepted S1-8 interaction (an exact high-water replay after
enablement refuses — reserve first, enable after). Pre-push review ACCEPT-WITH-FIXES, four
should-fixes folded before the single push; MR pipeline **2777040575** and post-merge
**2777078784** succeeded. Applied to the demo database (machinery only — issuance stays off
until an operator enables it). **Host-only finding, independent of the slice:** the
current-source byte-equal reseed proof (`S15PartyCurrentSourceRecoveryTests`, pre-Phase-B
target) **fails with today's source** — two consecutive seeds of the current source no longer
snapshot byte-equal. To re-check when Miguel's O6 source correction lands, before the
requested seed replay.

**S2 slice 2 — the registry lifecycle contract (`!129`, merged 2026-08-21; branch
`s2/registry-lifecycle-contract`).** The pre-writer audit of 2026-08-20 found the DOCLOG writer
blocked by a contradiction between the backlog, the P1-1a schema and the intake lifecycle — not by
authorization: the LG natural key `(Filename, EntryCode)` cannot be issued before the EntryCode for
PostFiscal, DOCLOG demands a final disposition while cataloging runs before routing, and the
state-carrying FKs (NO ACTION) made every governed transition fail once a registry row existed —
no test covered that order. Slice 2 fixes the contract instead of writing around it: migration
`20260820235016` makes the state-carrying FKs `ON UPDATE CASCADE` with guard triggers on the
mirrored columns; `TransitionDocumentDisposition` gains two registry-aware refusals (no
`RestoreForReview` once DOCLOG exists; posted evidence — EntryCode binding, FDCHDR, official bank
evidence — freezes a discard with a named reason); `CommitDocumentRegistry` (SECURITY DEFINER, own
authority, company/correlation GUCs, lower-cased SHA-256, append-only command audit) and
`EnableS2RegistryCommit(role)` (operator-invoked after the `!127` enablement, audited) are
installed, enabling nothing by themselves. `RegistryCommitService` is the application side —
called after validation/routing, **never from `ApplyExtractionAsync`** — failing fast on a
malformed request and committing DOCLOG (+ DOCARC for ArchiveOnly/ReferenceOnly; + FDCHDR/FDCDTL
for PostFiscal with the EntryCode issued first) in one idempotent, fail-closed transaction.
**Decisions fixed:** DOCLOG is born only on a stable Posted/ReferenceOnly disposition (Review and
unresolved stay intake-only; intake discards stay restorable and purgeable); one Document ↔ one
DOCLOG (replays and reprocessing return the existing code and keep the committing revision);
`Filename` is the governed registry filename, `SourceFilename` the upload name. **Open, recorded
in the backlog:** the canonical-filename policy (S6 archive naming or the bridge) and EntryCode
month-bucket provisioning (S2-4 remainder — the commit refuses with the allocator's own error
meanwhile). Pre-push adversarial review: ten findings folded before the single push (identity
columns frozen under the cascade, counterparty code name verified as the entity's `fdr.code_name`,
route-aware replay, `IsActive` in the DOCTYP match, an advisory lock on the governed filename, the
disposition-command window closed behind the commit, `Lines`/`DateDoc` null logic, error mapping,
`DocumentId` indexes, a versioned EntryCode key). Verified locally before the single push: default suite and the PostgreSQL
`S2RegistryLifecycleContractDatabaseTests` on the disposable Latest target. Source `35a6650` →
merge `59b61bd` (2026-08-21T00:48:59Z); MR pipeline **2778141409** succeeded (3/3 jobs, one push);
post-merge **2778165438** succeeded. **Applied to the demo database the same day** (machinery
only — `20260820235016` at Latest, cascade verified, zero DOCLOG, nothing enabled).

**S2 slice 3 — `S2-4` EntryCode month-bucket provisioning (`!130`, merged 2026-08-21; branch
`s2/entrycode-bucket-provisioning`).** P1-1a created EntryCode month sequences only through the
one-shot `BootstrapEntryCodeSequence`, so the first fiscal commit of every new month refused.
Migration `20260821005452` installs `ProvisionEntryCodeBucket(prefix, year, month)` — returns an
existing bucket freely, otherwise requires its own authority and the company context, serializes
under the entry-bootstrap lock, starts **above every code already known for the month** (ledger,
FDCHDR, bindings, DOCLOG — the S1-8 high-water discipline), registers the sequence enabled, and
audits append-only — plus `EnableS2EntryCodeProvisioning(role)` (operator-invoked after the
registry-commit enablement; unattended bucket creation is a stop-list act performed once,
explicitly). `AllocateEntryCode` gains exactly one arm — a missing month is provisioned first when the
session role holds the authority, inside the database contract for every caller — so a new month
never stalls posting once the role is enabled; without it the allocator
still refuses a missing month by its own error. Down is guarded (refuses once any bucket was
provisioned at runtime — provisioning history is never made untruthful). Pre-push review folded:
the DB-side placement (replacing a C# savepoint), per-bucket lock, 40001 on a concurrent snapshot
race, NULL guard, `RejectAppendOnlyMutationFn` reuse, guarded Down. Source `0157d05` → merge
`898d3bb` (2026-08-21T01:55:38Z); MR pipeline **2778235658** succeeded (3/3, one push);
post-merge **2778251415** succeeded. **Applied to the demo database the same day** (`20260821005452` at
Latest, functions present, zero buckets — nothing enabled).
**Canonical filename accepted 2026-08-21:** `{date}_{CompanyCode}_{DTCode}_{sha256[0..16)}.{ext}`
— date = document date if extracted else capture date; unique at birth by content hash; depends
only on immutable capture facts; the human-friendly archive name stays in `ArchiveNameLedger`
(S6). Implemented by the S2-3 wiring slice.

**S2 slice 4 — `S2-3` non-fiscal wiring (`!131`, merged 2026-08-21; branch
`s2/routing-registry-wiring`).** The first path from a routed document to the registry:
`DocumentRegistryBridge` projects an ArchiveOnly/ReferenceOnly document onto the record from
immutable capture facts (canonical filename via `RegistryFilenamePolicy` with the **capture
date** — the extracted document date is correctable and therefore cannot sit in a permanent
identity — the original asset's hash/size/name, the intake channel, the DOCTYP rule, the
counterparty only with its `fdr.code_name` identity) and commits through
`RegistryCommitService`. Two triggers, both after routing is stable: the extraction handler when
the document is auto-classified with every gate passed and the company resolved (the proof that
already queues a PostFiscal integration), and the review service on a human confirmation.
Success → `ArchivePending` (new transitions from Extracting/AwaitingReview; S6 files next);
governed refusal → `NeedsAttention` with the refusal's own code and message; audited as
`document.registry_committed`. PostFiscal remains deliberately unbridged; its later classification,
FX and validation prerequisites through `S2-11` are delivered. Verified:
handler unit tests with a fake bridge (commit,
refusal, no-proof stays in review), the policy's tests, and the bridge end to end on the
disposable Latest target (DOCLOG + DOCARC under the canonical name, replay, counterparty
omitted without an identity, fiscal route refused without throwing). Pre-push review folded: confirmed
duplicates are ignored, not committed; environmental refusals (role not enabled, company not a
registry company) keep the document reviewable and audit `document.registry_commit_unavailable`
— only a governed refusal of the document goes to `NeedsAttention`; pending integration jobs are
cancelled on commit; predicate on `DocumentTypeRoute`; one applier for both triggers; the human
path has its own tests (`DocumentReviewServiceRegistryTests`). Source `456d56d` → merge `5642b98`
(2026-08-21T02:19:37Z); MR pipeline **2778261892** succeeded (3/3, one push); post-merge
**2778286083**. No migration in this slice; the demo database stays at `20260821005452`.

**S2 slice 5 — `S2-5` intake capture evidence and the governed intake discard (`!133`, merged
2026-08-21; branch `s2/intake-capture-discard`).** Decided with Miguel in two rounds the same
day: byte-identity is **per company, decided at the moment the company is known** (the F1
global unique hash index becomes unique on `(InternalCompanyEntityId, OriginalContentHashSha256)`;
a capture registered without a company is checked globally at intake and re-decided when
cataloging or review assigns the company); an intake discard is a real **`Discarded`** status
mirroring the governed disposition; a byte-identical resubmission is **registered, linked on its
own `ResubmissionOfDocumentId`, released from the per-company identity and auto-discarded as
evidence** (never restored; never a semantic duplicate, so purge stays possible); audit now; the
corresponding target-owned DOCEFL Annotation is now `EF0000065` (see the S2-11 closeout below). The first cut of the slice had put the per-company rule on the index
alone and the link on `DuplicateOfDocumentId`; the pre-push review showed that channel captures
(company-null) would collide later and that the link froze purge — hence the second decision
round and the redesign. Migration `20260821085010` installs `RecordIntakeCapture` (the P1-1a
capture evidence purge requires, written from the asset row, shared per company/hash/length),
`DiscardIntakeCapture` (governed `Discarded` + mirrored status, audited kind), `EnableS2IntakeCapture(role)`,
the link and the index, and teaches `TransitionDocumentDisposition` that a resubmission is not
restored. Application: `IntakeCaptureService` + `IntakeResubmissionResolver` through the shared
`GovernedCommandScope`; the registration service is transactional, records evidence at intake
and registers-links-discards a known resubmission; the extraction handler and the review service
resolve byte-identity when they set the company, record evidence before a NOT_A_DOCUMENT discard,
and route a detected-but-undiscardable resubmission to attention; API/Web/channel keep their
contract. Second pre-push review round folded: a partial unique index keeps company-unknown
captures race-safe; every intake discard releases the row hash (the detector and the resolver agree
on what is live); a detected-but-undiscardable resubmission keeps its link as a hard stop and is
discarded on the next resolve once enabled; the entity merge re-homes documents through the resolver;
ReadyForIntegration may be discarded; discarded documents leave the review predicates and item
sightings; a channel rollback deletes a discarded capture's object; the registration service detaches
only its own entries. **Enables nothing by itself.** Verified: unit tests (state machine,
registration and resubmission with a fake governed service, the resolver's cases including the
pending-link retry, handler `unsupported` both ways, per-company uniqueness in the upload service)
and `S2IntakeCaptureDatabaseTests` on Latest (Unavailable without enablement, evidence shared per
company, discard + restore, a resubmission not restored, purge request possible because the
evidence exists, Down guard). Source `4031961` + `4188875` (the S13a Down lock test paused on the
first `CREATE INDEX` of the whole chain; it now pauses only on its own) → merge `cc19b32`
(2026-08-21T09:52:28Z); MR pipeline **2779162676** succeeded (3/3; the first head pipeline
**2779046693** failed on that test, twice); post-merge **2779215102**. **Applied to the demo
database the same day** (`20260821085010` at Latest: three functions, three hash indexes, zero
captures recorded — nothing enabled).

**Stage 11 source alignment (`!135`, merged 2026-08-21; branch `s2/stage11-source-alignment`).**
Miguel fast-forwarded the `invoice-skill-build` working tree from the Aug-6 pin `b917685` — what the
parser shapes, the FdrSource tests and the demo database's reference layer were built against — to
Stage 11 (`4ea2e67`, 2026-08-21) and asked that the retired duplicate-fiscal entities not be
imported, that the other Stage 11 changes be assessed, and that the data be reseeded. Assessment:
the current source broke five strict parser shapes before retirement mattered — `sncacc.json` is the
full SNC chart (518 → 3,509 rows) with five fiscal-year annex members, `productmaster.json` and
`entity_products.json` carry `SNCSource`, `flag_evaluation.json` carries `Relevancy` and twelve
new rules (`EF0000053`–`EF0000064`) with `Document Archive`, `Accountant` and ITMMST/ITMCLS
targets — **only `EF0000057`–`EF0000060` are item-master rules**, the other eight targeting DOCLOG,
BNKMOV or ENTMST (corrected 2026-08-22 against the pin) —, `permanent_code_ledger.json` lists twelve more source-owned buckets beside the governed
seven, `itemclass_taxonomy.json` re-issued its CLCodes (now ledgered), and `document_type_rules.json`
coded `Bank Statement` as `DT000020` with a blank DocClass (the shape the existing authorization
fingerprint already named). Data: 5 entities retired (`EC000093`/`EC000095` the Gott brands on
`EC000001`'s NIF; `EC000094` unresolved vendor; `EC000107`/`EC000108` fiscal-less legacy rows),
3 deleted (`EC000045`, `EC000087`, `EC000088`), 3 new (`EC000120`–`EC000122`), `EC000097`/`EC000098`
now distinct Cyprus fiscal numbers (O6's second group dissolved at the source), 123 of 395 items
retired as tombstones (zero references, three chained successors), 24 new aliases, 28 new
exchange-rate months, the ENTITM authorized orphan resolved. The slice: tombstones are validated
like live rows in source order, keep their codes reserved, are disposed (`RetiredInSourceTombstone`)
and may not be referenced by any child file; a row an earlier seed placed under a tombstoned item
code is left to the target (`IsActive` is target-owned by the replay contract) and reported as
Skipped; annex members are declared, gated uniformly and not persisted; `Relevancy` is governed and
not persisted (no DOCEFL column — a decision, not a default); the rule vocabulary widens with
migration `20260821103837_S2Stage11RuleVocabulary` (DOCEFL/DOCFLG CHECKs dropped and re-added by
name, Down restores verbatim) and `docs/p1-0-vocabularies.md` is re-measured; the ledger admits the
source-owned buckets without reserving them; re-issued ITMCLS codes already fail closed on an
already-seeded database through the alternate-key preflight (now covered by a test). Pre-push
review (10 findings + 2 addenda) folded before the single push. Verified: parser suites; disposable
`FdrStage11SeederDatabaseTests` + post-collapse replay contract + rule/ledger seeder suites
(120/120); FdrSource parse/tamper tests against the Stage 11 directory; MR pipeline
**2779467574** and post-merge **2779519327**.

**The three findings that slice left open were closed the same day — Miguel's instruction, 2026-08-21:
rebuild the demo from Stage 11 and solve the rest.**

**(1) The demo was rebuilt from Stage 11** — a replay was impossible by design (the post-collapse
resolver matches and never creates, so the entity delta failed closed at `post-collapse party
identity resolution is not exact` before any write: the S2-6 gap, larger). The demo held zero
documents; the previous database is kept at
`D:\fileStorage\SibylaBackups\demo\sibyla_demo_pre_stage11_20260821.dump`. Repeatable sequence:
migrate to `20260812100000_S15PartyDataBackfill` → runtime principal, pre-collapse parties, company
registry → seed → S15 backfill → **reconciliation 112/112** → DOCTYP presentation migration → the
four missing cutover tuples → Latest → replay the complete seed (idempotent). Result: **112 parties,
all 112 carrying a primary tax identifier — O6 has nothing left to skip**, the source's own
retirements having dissolved both duplicate-fiscal groups. CTT (`EC000007`) Active and capturable,
three items, all SNC-mapped. Full Stage 11 reference layer: SNCACC **3 509** (was 518), ITMMST **272**
live (123 tombstones not imported), ENTITM 349, EXCRAT 75, DOCTYP 23, and **DOCEFL 64 rules / 93
targets — the flag catalogue on the demo for the first time** (was 0). Documents 0. **A stated
Phase-B cut of two entities remains**, each refused by a different gate: `EC000050` (fiscal without
country — S1.5-2 source identity preflight; its 2026-08-20 "Oman" correction is *not* in Stage 11,
which says "Varies (anonymized)") and `EC000109` (no fiscal — S1.5-4 merged-party completeness).
That was the open S2-6/S2-7 boundary at the time; `!141` now covers both shapes without claiming a
live migration or issuance.

**(2) The related-party kinds were re-bound by pair (`!137`).** Stage 11 moved Banks/Financing to
`CL000008` and Revenue/Intercompany to `CL000026`, reusing the old codes for other classes — a fresh
database would have bound `ENTMST.RelatedPartyKind` to the wrong classes silently. The codes and
**the (Class, Subclass) pair each is bound to** now live in one Domain type that the CHECK, the
Entity360 contract, `BusinessEntityService`, the UI labels and the page-contract test all derive
from, so the next renumbering fails a test instead of needing a grep. Migration `20260821114744`
remaps existing kinds and refuses any contradicting taxonomy — the pair under another code (an
Aug-6-numbered database: **re-key ITMCLS first, by decision**), the code under another pair, or the
target absent while a party still carries the outgoing one; `Down` mirrors it. The seeder refuses a
source taxonomy that moves either pair. No party ever carried a kind (demo: 0).

**(3) The three host-only proofs now prove what they claim (`!137`).** Each failed on a harness
condition, not the code under test: the byte-equality proof compared snapshots holding two
wall-clock columns (`ENTMSTSeedManifest."SeededAt"`, `DOCTYP."EffectiveFrom"`) the synthetic path
already normalizes — each is now asserted to hold one distinct value before normalization, and an
inequality names the differing projections instead of a bare boolean; the live DOCTYP proof asserted
a first insert into a table the reset had already seeded; the lossless/idempotent proof ran the whole
source through Phase B, which refuses the two shapes above — it now applies that cut, states it, and
**bounds it**, so a regression admitting nothing can no longer pass green. Stage 11 source: 8/8.

**Stage 11 documentation closeout (`!140`, merged 2026-08-23).** Source
`f0483610f81bfb5ec3f62d9161ad5c1354347ad4` → merge
`fe98b2764670d5a433d1e1e5588817e714ebc629`; pipeline **2783312130** succeeded. This preserved the
Stage 11 vocabulary and flow decisions as documentation and changed no runtime behaviour.

**Entity resolution (`!141`, `S2-6`, merged 2026-08-23).** Source
`4719d4181bfa6f034d41f333d768d2954dd60b97` → merge
`847cb79057052c9e2f767193acc3484515788c28`; MR pipeline **2783312334** and `main` pipeline
**2783365430** succeeded. Deterministic resolution is NIF → company-scoped/global alias → normalized
name, with every outcome recorded in a trusted append-only `MatchDecision`. Unmatched evidence can
emit governed provisional ENTMST and CodeLedger state only through deny-by-default authorities;
source deltas carry revision/lineage, including governed replay and merge-chain handling. `M-D11`
now resolves RelatedParty/Kind by the exact `(Class, Subclass)` pair. Human-owned corrections win;
replay, canonical merge chains, advisory locking and `ReadCommitted` transaction behaviour are
covered, including the `EC000050` and `EC000109` shapes. Miguel explicitly authorized the permanent
ENTMST merge/emission path before `!141` merged. This is merge and pipeline evidence only: **none of
deployment, live migration, live issuance or FdrSource host proof is claimed or verified by this
closeout**; the explicit FdrSource mapping remains absent locally. `M-D9` destructive re-keying was
not built because it is conditional on a non-rebuildable affected database; `M-D10` Relevancy and
`M-D12` exact ITMMST constraints were later implemented by the `S2-11` framework in `!149`.

**Counterparty own-company gate (`!143`, `S2-7`, merged 2026-08-24).** Final source
`0e18457e40953ed031a5d159549e7a483065b9c9` → merge
`335a23ada4454241528c9d0071f8727fb7ad552d`. A counterparty cannot equal the selected company or
carry an active `InternalCompany` role. Forbidden evidence is evaluated strictly in
NIF → alias → name order through canonical merge chains. Unknown direction does not mutate state
or issue identity; explicit human/upload identity, origin and confidence are preserved.
Bidirectional PostgreSQL triggers share advisory serialization with application preflight, and
migration `Down` is guarded. The first MR pipeline **2783866496** failed only because a database
test fixture assumed a third baseline entity; it was fixed forward with a deterministic dedicated
fixture. Final MR pipeline **2783891036** and post-merge `main` pipeline **2783915643** succeeded.
Exact-candidate local evidence: build **0 warnings / 0 errors**; default **1904/1904**; changed
PostgreSQL **146/146**; Party **38/38**; P11a **61/61**; migration database **5/5**; review
**0 Critical / 0 High / 0 Medium**. This is merge and pipeline evidence only: **none of deployment,
live migration or live issuance is claimed or verified by this closeout**. At that closeout,
`S2-8` was next.

**Verified S2-9/S2-10/S2-11 closeout (2026-08-25).** `S2-9` is complete for deterministic EXCRAT cataloging resolution only, with no PostFiscal wiring:
`!147`, source `42800a68e962d35feb37c4a415250d243bb7f281` → merge `d216f0adf4a2f59edafd355e6fcface8904a4dca`; MR pipeline **2787051255** and post-merge `main`
pipeline **2787092890** succeeded. `S2-10` is complete for its authoritative backlog scope — VAT-splitting and date-validation gates: `!148`, source
`ccee284341097cbe26b8e643cb99ba8f8f0d12a3` → merge `7fe4c70e8899426932289088569c29c037138fca`; MR pipeline **2787103414** and post-merge `main`
pipeline **2787139680** succeeded.

`S2-11` is **complete**. Framework MR `!149` delivered the governed evaluator, exact Relevancy and
subject domains, and `EF0000057`; item-detector MR `!151` (source
`abc066ff1063b9710926303d613161eb5038f34b` → merge
`aafbca4afec8ade1e43d847613fa8fa83209743f`; final pipeline **2787689712** succeeded) added
`EF0000058` taxonomy mismatch, per-member FK-faithful `EF0000059` normalized-duplicate instances
with group evidence, `EF0000060` for both SNC sources blank, and authoritative same-document
resolution for `EF0000057`–`EF0000060` while preserving human-terminal and cross-document state.

Closure MR `!153` merged source `bc5d94a7882db5be9bd3f0b5a807ee65415a9a2d` as
`4167f7e67da02f9527a3433908396d49580c9d29` at 2026-08-25T16:34:27.226Z, with parents
`cca363a96b041ef2bf5f5919bd400a583e18f707` and
`bc5d94a7882db5be9bd3f0b5a807ee65415a9a2d`; the GitLab `main` API reported exactly that merge.
MR pipeline **2789667930** and post-merge `main` pipeline **2789745778** succeeded. It delivered
target-owned permanent `EF0000065` as a terminal **Resolved · Non-Blocking · Consultive ·
Annotation** on `DOCUMENT`, with exact provenance, permanent delete/rename guards and irreversible
`Down`; structural same-company capture-and-discard evidence with original/current locks; and
replay plus caller-state atomicity in both known-company and later-resolution paths. Ordinary
`EvaluateCurrentDOCEFL` recognizes it separately as structural support without item evaluation.
**No other Status/Annotation mapping is required in Phase 1.** Final measured local gates: build
**0 warnings / 0 errors**; default **2020/2020**; EF pending-model clean; full disposable
PostgreSQL `FdrDatabase` **463/463**; focused S2 **11/11**, S13a **22/22**, rule seeder + CLI
**20/20**, exact predecessor **8/8**; final adversarial review **Findings: none**. **`S2-12` is
next.** This remote API, merge, pipeline and local-test evidence does not claim local
`main`/upstream synchronization. **No deployment, live migration, ERP activation, EntryCode/LGCode
issuance or live-tenant operation was performed or verified.**

## Stage 12–13

**The source moved twice on 2026-08-25/26** — Stage 11 `4ea2e67` → Stage 12 `d551734` → Stage 13
`f2c73b7`. `Editor/Data` is unmoved by Stage 12's artifact reorganisation, so the parser's source
directory is unaffected; what each move broke was strict *shapes*, and each break hid the next.
Measured against Stage 11: DOCEFL 64 → 66, ITMCLS 51 → 54 (`CL000009` Dividends/Shareholders
retired, `CL000053`–`CL000056` added), ITMMST 395 → 397, ENTITM 350 → 354, ENTMST 119 → 120. ENTMST
gained `ExpectedRcvVal` and both item files gained `CostCentreSource`; none is consumed.

**`S2-11` was recorded complete while it could not work.** `!153` wrote the `S2-5` cross-capture
resubmission rule into DOCEFL from its own migration, marked `Imported=false` with an `'authored'`
provenance marker, under **`EF0000065`** — a code the source had already issued to a different rule
(customer invoicing cadence, ENTMST, Periodic Review). One rule, two owners, and a governed literal
invented against `S2-11`'s own closeout: *"No EFCode or ItemClass was invented."* Miguel authored
the real rule in the source as **`EF0000066`**. It was not theoretical: seeding the live source
failed closed at *"DOCEFL row 64: the activation fields are owned by ActivateDOCEFLRule after insert
and differ from the source"* — row 64 being `EF0000065`. The guard worked; what it reported was an
identity collision. Nothing durable had applied the migrations (the demo went down before they
existed), so `!157` corrected them in place on the `!124` precedent.

**Removing the native `INSERT` exposed a contradiction it had been hiding.** The seeder writes rules
with `ItemClass` and `EnforcementStartsAt` NULL; `GovernDOCEFLRule`, the only governed way to
classify one, *forbids* an enforcement date for any class other than `Decision`; `ActivateDOCEFLRule`
updates `WHERE NOT "Active"` and so cannot touch a rule the source seeds active — yet
`CK_DOCFLG_DeterministicEvidence` required `EnforcementStartsAtSnapshot` unconditionally. **No DOCFLG
instance for an `Annotation` rule could ever be written.** `!153` never met it because it INSERTed
its rule with a hard-coded date `GovernDOCEFLRule` would have refused. The constraint now mirrors
that policy — required exactly when `ItemClass='Decision'` — and a test drives seeder-shape →
governed classification → detector end to end.

**A parser regression from `!141` was found and fixed (`!155`).** `S2-6` made `RelatedParty` required
on every live entity row, on the written premise that live rows always carry it. Measured: the source
writes the member **only where it is true** — 3 of 120 rows — so the parser rejected every ordinary
party at `entities.json` **row 0**, identically against Stage 11. **No pipeline could see it:**
`Category=FdrSource` needs the confidential source directory and appears in **none** of the three CI
jobs, which is the systemic finding behind most of this section. The shape is now pinned in the
default suite instead.

**Stage 13 broke two more shapes, and the ledger gate stopped being an enumeration.**
`CostCentreSource` is declared on both item files; `AUDCHK`, `DPRCHK`, `DQLCHK`, `QUACHK` and
`WRKFLW` join the ledger on the `ENTPAY` terms. Refusing the whole ledger over a bucket outside a
hardcoded roster cost one repository change per source release, and Miguel confirms the workflow
catalogues are still under construction with more expected; what is enforced instead, and
unconditionally, is that every governed bucket is present and every bucket holds a well-formed
binding map.

**The related-party kinds became data.** `CK_ENTMST_RelatedPartyKind_FundingOnly` was generated from a
constant naming two codes, so admitting a third — `Shareholders / Transfers`, `CL000054`, which
`EC000121` now cites — was a deployment. ENTMST references a `RelatedPartyKindCatalogue`, which
references ITMCLS by one composite key on `(CLCode, Class, Subclass)` so a code and a pair cannot
describe different rows. Measuring rather than reasoning found that P11a's own
`FK_ENTMST_RelatedPartyKind`, carrying no `ON UPDATE` clause, blocked the very renumbering the design
exists to survive; it is redundant under the catalogue and was replaced by it.

Adversarial review then found the slice broken in the two ways that matter most, both from one
cause: the catalogue was filled *after* the party delta had already resolved and written every
party. A fresh database migrated to `Latest` therefore reached the delta with an empty catalogue and
refused every related party, and an upgraded one — whose ITMCLS predates `Shareholders / Transfers`
— was filled with two kinds by the migration and, because the bootstrap ran only on an empty
catalogue, could never admit the third. The second is the live database's own upgrade path. The
taxonomy and its catalogue are seeded before the parties now, with the item-class preflight hoisted
alongside so it still reads pre-write state, and the bootstrap is idempotent. The stated cost:
deleting one of the three bootstrap kinds no longer sticks. Every other kind stays a governed INSERT
that no replay touches. Both defects were measured failing before their fixes, not argued.

**Not done, and not claimed:** the page option lists are still fixed markup, so a kind admitted by
INSERT is accepted, resolved and rendered but does not appear in the dropdown without a release.

## S2-12, the golden set, and what running it found

**`S2-12` — `blocking_open_instances()` (`!160`).** `DOCFLG."BlockingLevel"` names the action an
instance stops, so the gate is per action and each command declares which actions it performs. Open
is `Open` or `InReview`; grandfathered instances do not gate, as `D7` decided. An unrecognised
action **refuses**: `= ANY(NULL)` is NULL, so a mistyped action would otherwise let every caller
through. Enforcement sits on a trigger on `FDCDTL` rather than inside `CommitDocumentRegistry` — a
check in the writer is one every future writer must remember. Stated plainly: the disposition-side
gate cannot fire today, because `DOCUMENT` rows are constrained non-blocking and the commit calls
the transition before the `DOCLOG` row exists.

Adversarial review caught the replacement body forked from `S2RegistryLifecycleContract`, which
reads like the live definition but is one migration behind `S2IntakeCapture`; the fork silently
dropped the byte-identical-resubmission guard, and the existing test for that guard passed either
way. **Replacing a SQL function restates its whole body and nothing diffs it**, so the test that
found it asks the live `pg_proc` rather than the file.

**`S2-13` — the April golden set (`!161`).** Twenty documents chosen by measurement from the 112 the
prototype holds under `Gott/*/202604`. Six of the month's seven `Duplicate_` files are byte-identical
to an original and the seventh is not; both pairs are in, because a hash resolves one and only
`(ProviderCodeName, InvoiceNo)` resolves the other.

**What running it found on day one.** Two documents came back `UNREADABLE_AFTER_VISION` and were
first written up here as unprocessable — a conclusion about the documents drawn from a statement by
the reader, and wrong. A scanned page filtered `[/FlateDecode, /DCTDecode]` yielded **no page image
at all**, so the agent was handed a PDF it could not rasterize. Swept across the whole prototype:
of 867 PDFs, 19 depend on the visual fallback and **9 of the 12 that could not be read now can**.
Three still fail — two are scans sliced into image strips (one has 71), one is vector-only — and
both need composition or rendering, not a loosened guard.

**The warning catalogue (`!162`).** Four runs on identical bytes produced **26 distinct codes for
roughly 8 conditions**; a cancelled sale with no accounting value was named nine ways, two differing
only by `NO_` versus `NON_`. The vocabulary was closed on paper in P1-0 and never enforced — the
validator checked uppercase snake case and no more. It is closed now, with
`UNCATALOGUED_CONDITION` as the escape, following the pattern P1-0 already decided for
`identifierType`. **Enforcement is off by default**: the agent's instructions do not carry the
catalogue yet, and turning it on first would refuse every document with a cancelled sale.

## Open

| Id | What | Owner |
|---|---|---|
| **O5** | Restricted-identity validation on the target host. A **production** gate, not a development gate — nothing in S0–S6 waits on it. **Prerequisites measured on the host 2026-08-28** and written up in `docs/deployment/o5-prerequisites-2026-08-28.md`; no probe was run, because the F0 rule is that an Administrator running one satisfies nothing. Ready: the host is confirmed as the target (`EC2AMAZ-NTPJCNO`, Windows Server 2025 Datacenter), the four fixtures verify byte-for-byte against their manifest, `SecretManagement` is installed, and both helper executables are present and reachable by the account that runs them. **Three items are unmet and two of them are decisions, not provisioning.** `Add-NetFirewallDynamicKeywordAddress` does not exist on this firewall build, so `provision-egress.ps1 -Mechanism FqdnRule` throws and `LoopbackProxy` is forced — a path needing a loopback forward proxy that is not installed and that the scripts deliberately do not install, so D-O5-6 item 3 cannot close inside the runbook's 40–50 minute estimate. **And the design has diverged from the deployment:** `D-O5-1` is "Two identities, not one" precisely so the firewall can express per-SID egress — zero network for the PDF helper, Anthropic-only for the agent — but what runs is one identity, `GottSibylaDocumental`, with the Worker as a Windows service and both helpers as its child processes inheriting the same token. Item 3 is therefore not a test that fails but one that cannot be written. Either the deployment splits to match `D-O5-1`, or `D-O5-1` is revised to one identity and the guarantee item 3 exists to give must come from elsewhere or be dropped. The deployment itself is sound — `C:\SibylaApps\Documental-agent` grants `Modify` only to `GottSibylaDocumental`, machine-wide, nothing to `Users`. Third item: no secret vault is registered, so the two passwords cannot be stored — interactive, operator-only. The runbook's requirement for branch `feature/p1-2-o5-prep` was stale and is corrected: everything is on `main` | **Miguel** |
| **S4-B1** | izibizi certificate + key ring on the host — **provisioned 2026-07-21 and reconfirmed live 2026-08-22; not outstanding.** Verified on the machine: `Cegid:Enabled` **false**; `KeyRingPath` `D:\SibylaData\Keys\Cegid`; the configured thumbprint matches a `LocalMachine\My` certificate `CN=GOTT Sibyla Cegid Data Protection` with `HasPrivateKey` true, expiring 2031-07-21; the key ring exists with **1** `key-*.xml`; key-ring ACL = SYSTEM/Administrators FullControl + the three live runtime identities (`.\GottSibylaDocumental`, `IIS APPPOOL\Sibyla.Api`, `IIS APPPOOL\Sibyla.Web`) Modify; private CNG key ACL = those three Read, SYSTEM/Administrators FullControl; `.pfx` backup present under `D:\fileStorage\SibylaBackups\CegidSecretProtection` with ACL SYSTEM/Administrators only. **One named closeout remains: no `key-*.xml` backup exists under that backup root** — back the live key-ring XML up before disaster recovery is called complete. **Do not reprovision.** Detail in `docs/deployment/izibizi-b1-verification.md` | **Miguel** |
| **S4-B2** | izibizi endpoint, client id, client secret — **the credentials are already set, contrary to what the docs said, but B2 is not operationally closed.** Live database aggregate (no secret, ciphertext, identifier or record value reproduced): **1** `CegidCompanyConnection`, **disabled**; client id present; protected secret present; **all 3 endpoints HTTPS**; 1 fiscal-year mapping; configuration **not validated**; **no successful last test**; latest test **2026-08-11T12:34:52Z failed** `cegid_fiscal_year_2026_rejected`. Outstanding: a successful save/reload/test. **Do not enable or call Cegid** | **Luís** |
| **O7** | `EC000121` (Factor Matriz, `PT509428428`) carried `RelatedPartyKind` `"Financing / Intercompany"` — a pair ITMCLS never held, since `Financing` is a Subclass under `Banks` and not a Class — so the live-source seed failed closed at `ResolveRelatedPartyKinds`. It had done so since Stage 11, masked until `!155` fixed the row-0 parser failure ahead of it. **Corrected at the source 2026-08-26 to `"Shareholders / Transfers"`** (`CL000054`), which is the pair its own ENTITM already carries. **Closed by the related-party kind catalogue**, which admits it as data; before that, a third kind was a deployment | **closed** |
| **O8** | `recrev.json` and `recrev-MFNT-LPT.json` were **truncated mid-string** from `4fa9e28`, blocking the vocabulary annex generator, which declares RECREV a source. **Regenerated at `ce9b834` and larger than before** — `recrev.json` 490 KB → 2.1 MB, 1 451 records; all 69 source JSON files now parse. Not merely un-truncated: the originals were an interrupted write, not a good file cut short | **closed** |
| **O9** | **The demo database contradicts the source on related parties.** All 112 parties carry `RelatedParty = false` and no kind, while the source marks three as related with their kinds — so `M-D11`'s pair resolution has never run against demo data, and the `EC000121` failure only ever appeared when seeding the source into a disposable database. Separately, `EC000038` Itoorer is `Role: Company` in the ENTMST scalar but has **no** `InternalCompany` row in the authoritative `EntityRoleAssignments` and no `CompanyRegistry` entry; by `S1.5-7` the child table is the authority, so the two disagree and nothing arbitrates. Measured on the demo 2026-08-26, read-only | **Miguel** |
| **O10** | **`Category=FdrSource` runs in no CI job.** It needs the confidential prototype directory, so the only place it runs is a local script someone remembers to invoke. Every source-shape defect this week lived in that blind spot — the `!141` `RelatedParty` regression, `ENTPAY`, `DOCUMENT`, the `EF0000065` collision, and both Stage 13 shapes — and each was found by hand, not by a pipeline. Mitigation so far is per-defect: each shape is pinned by a synthetic case in the default suite. The standing question is whether that is enough, or whether the source readings need a CI path of their own | **Miguel** |
| **O11** | **The disposable script's seeder-CLI phase cannot succeed.** `run-fdr-seeder-disposable-tests.ps1` runs `Category=FdrSource` and then the `Sibyla.ReferenceDataSeeder` CLI against the same connection string — but those fixtures drop the runner database at teardown, so the CLI fails `3D000 invalid_catalog_name` every time. It became visible only on 2026-08-27, when the phases before it finally passed; every earlier run failed sooner, so the phase has been dead for an unknown length of time and no CLI validation has actually been performed. Not a code defect — the CLI itself is exercised green by `FdrSeederCliProcessTests`. Fixing it means the script must prepare a database between the two phases | **Miguel** |
| **O12** | **The disposable harness seeds before it migrates, so the ordinary upgrade path was never covered.** `FdrDisposableDatabaseSetup.RecreateAsync` migrates to the pre-Phase-B target, establishes synthetic prerequisites, and only then migrates to `Latest` — the reverse of production, which migrates a populated database and seeds afterwards. Its synthetic ITMCLS also carries none of the governed related-party pairs, so `RelatedPartyKindCatalogue` ended every test empty and no test ever seeded a related party: the table's shape was proven, the path through it never was. That blind spot hid two defects in `!158` until adversarial review — a fresh database migrated to `Latest` refused every related party, and an upgraded one could never admit a kind its taxonomy gained later. Both are now pinned by `S2RelatedPartyKindCatalogueDatabaseTests`, each measured failing without its own fix. The general question stands: which other invariants are proven only in seed-then-migrate order | **Miguel** |
| **O13** | **The same bytes do not produce the same extraction.** Four golden-set runs on identical pinned bytes: eleven of twenty-one documents differ. Conditions appear and vanish — GD-18 flagged in three runs and clean in the fourth, GD-3's status `ok`/`needs_attention`/`ok`/`ok` — and line counts move on ordinary invoices, GD-5 returning 3 then 6, 6, 6. GD-10/GD-11, the pair that exists so the duplicate detector can compare one invoice captured twice, returned 2,2,2,1 and 2,1,2,1: that comparison is over noise. The agent's own instructions already require the opposite — *"given the same readable input and instruction version, preserve the same output structure, field interpretation, and warning codes"* — so this is a stated requirement unmet, not an unstated expectation disappointed. **`S2-14`'s pass rate cannot be defined until this is answered**, and the answer belongs with whoever owns the agent | **Miguel** |
| **O14** | **The warning catalogue operational rollout is complete — 2026-08-28.** `!162` closed the vocabulary and left enforcement off, because enabling it against a `2.3` agent would refuse the extraction of every document with a cancelled sale or a duplicate copy. The repository copy carries the closed list, the escape rule and a checkable stability requirement at `sibyla-documental/2.4`. A second gap surfaced on 2026-08-27: the catalogue was assembled only from what four April runs emitted, so three codes the instructions **mandate** were absent from it — `UNTRUSTED_INSTRUCTION_IGNORED`, `PT_FISCAL_QR_PARTIAL` and `PT_FISCAL_QR_CONFLICT`. Enforcement would have refused the exact response switchover acceptance item 4 exists to prove correct. This was closed Sibyla-side with a test that reads the instruction document instead of restating its codes, because a copy drifts as silently as the omission did. `!170` candidate `54038697e10b488ae59789cc9a3e83de0ebb23d1` (merge `1b8cd55cf34f3092a390a735aa497d605d06721f`) added the frozen exact 20-code catalogue with default-off; it was deployed, then `ExtractionResponse__EnforceWarningCatalogue` was separately set `true`. Live `ProductVersion` is `1.0.0+54038697e10b488ae59789cc9a3e83de0ebb23d1`; a byte-equal live-DLL probe accepted all three prior synthetic agent responses and rejected `CALLER_INJECTED_CODE`. Item 12 passed only for the synthetic fixture; **O13 stays open and is not resolved.** | **closed 2026-08-28** |
| **O15** | **The party `identifierType` vocabulary was written without the countries this system processes.** P1-0 closed it to `VAT`, `NIF`, `EORI`, `PassportNumber`, `NationalID`, `Other`, case-sensitive, and the validator checked only its length. **Measured on the live database 2026-08-28**, the register holds `NIF` 33, `VAT` 9, `CNPJ` 4, `SYNTHETIC` 4, `VAT_OSS` 2, and the extraction revisions add `NIPC` twice and `EU_VAT` once. **The first reading of this was wrong and is corrected here:** `NIPC`, `CNPJ` and `CPF` are not coined synonyms — they are real national schemes, and P1-0 simply has no home for them. What the data shows instead is `NIF`, a Portuguese term, doing duty as a generic label: an Irish `NIF` of six digits and a United States `NIF` of twelve. Only `EU_VAT` is genuinely coined, on a row whose number is an ordinary Irish VAT. **Why the type must survive rather than collapse to `Other`:** every one of these schemes occupies the same `FiscalNo` field, so `identifierType` is the only thing saying which digits these are — it is part of the `EntityResolutionService` key alongside country and normalized value, and it is what decides whether a check-digit validation applies. `TaxIdentifierNormalizer.IsValid` knows only the Portuguese nine-digit check for `NIF`/`VAT` and the Irish `VAT` format; `NIPC`, `CNPJ` and `CPF` fall through to a bare `Length is >= 4 and <= 32`. Checked by hand, all four live `CNPJ`s and both `NIPC`s carry correct check digits — the gap is latent, not realised. **`PartyIdentifierTypeCatalogue` therefore widens rather than closes**, which is P1-0's own governed migration taken once and in the open rather than a silent enum widening, and it holds **two sets**: what an extraction may declare, and what the register may store. `SYNTHETIC` is in the second only — it records that the issuing country has no fiscal number and the Portuguese system requires one, so the register minted a value; nothing on a document says that, and the live extraction revisions never carry it. `EnforcePartyIdentifierCatalogue` is **off by default**: the instructions never list the vocabulary, naming only `UNKNOWN`. **What remains:** `IsValid` must learn the `CNPJ` and `CPF` check digits and treat `NIPC` as `NIF` for `PT`, which changes a governed path and belongs in its own change; the instructions must carry the list, which is an instruction-version bump and should ride the next one; and the mislabelled `IE`/`US` `NIF` rows and the three extraction rows are data corrections owned by Miguel. **The `US` row also exposes a normalizer defect:** `TaxIdentifierNormalizer.Normalize` strips a leading prefix only when it equals the `CountryCode`, so `"EIN 82-3412842"` under country `US` keeps its scheme name and normalises to `EIN823412842`, which matches nothing — the same mechanism that leaves `IE4276970QH` whole on the extraction row whose country says `US`. The scheme name belongs in `identifierType`, which is what widening the vocabulary to `EIN`/`TIN` now allows. **And the `IE` six-digit value is a question, not a mislabel:** Irish tax references are seven digits plus a letter, so `626569` on `Itoorer IE Ltd` looks like a CRO company-registration number, which is not a fiscal identifier and arguably does not belong in `EntityTaxIdentifiers` at all. `countryCode` was examined and is **not** the same work — `EU` on the `VAT_OSS` rows is a region occupying the country slot, accepted deliberately | open |
| **O16** | **The instruction-version cutover fails closed in both directions, and the window that survives it is temporary.** `ExtractionResponseValidator` compared `instructionVersion` against a single literal and the agent echoes whatever version its installed profile carries, so installing `sibyla-documental/2.4` on the target host while the Worker demanded `2.3` rejected **every** extraction, and moving the Worker first rejected every extraction too. A rejected response is a failed attempt: at `Job.MaxAttempts` (8) the document is `DeadLettered` and needs recovering by hand, so a mismatch is not a pause. **Decision taken 2026-08-28:** a temporary window — `AcceptedInstructions` holds `2.4` and `2.3`, the Worker asks for `2.4`, and `PreviousInstructions` leaves the set once a fresh `documental-agent` process has been proved to declare `2.4` (switchover acceptance item 10). **The window does not make the order free.** Until the new Worker is running, the binary doing the validating is the old one and has no window at all, so **the Worker moves first and the `2.4` profile is installed afterwards** — a gate, not a preference. Because `main` cannot be deployed (see the 35 pending migrations and `S15PartyCollapsePhaseB` below), the change was also cherry-picked onto the commit the running binaries were built from: branch `maintenance/deployed-2026-08-10`, whose name records that base commit and **not** any operational state. `!167` is integrated there. The reviewed and CI-tested candidate is `f60c699e24a27387693c15c0a25b45a3091e3a5c`; the branch head is the merge commit `4f77c217543b24b0e7a3033500fbf42d43f2db99`. Their trees are identical (`509f2753fff3c6e9c8a1d7741f52921e8b0cd666`), but `ProductVersion` embeds the **commit** SHA, so publish was deliberately pinned to `f60c699` — otherwise the binary on the host would identify itself with a merge commit nobody reviewed. **Cutover closed 2026-08-28.** The initial dual-window Worker candidate `f60c699e24a27387693c15c0a25b45a3091e3a5c` was published and deployed first. Persistent documental-agent instructions came from `main` `docs/hermes-documental-agent-instructions.md` at `sibyla-documental/2.4`, not the old maintenance copy, and a fresh process under the effective `GottSibylaDocumental` account declared `2.4`. `!169` candidate `c0e41a2a81572d18e2d288bfd5650c0619107f85` closed `2.3` acceptance and was deployed; the `!170` catalogue candidate and separate enforcement setting are recorded under O14. Deployed `Domain` contains `2.4` and not `2.3`. The database remains at **22 migrations**, latest `20260806200000_P11bPieceCGovernedCommands`; there was no schema change. The first restart exposed an expired dedicated-service-account password; automatic rollback restored the old Worker, the dedicated local account was set `PasswordNeverExpires`, and the subsequent deploys succeeded. Sanitized evidence: `D:\fileStorage\SibylaBackups\DeploymentEvidence\GOTT-Sibyla-documental-2.4-cutover-20260828T123044Z.json`, SHA-256 `4FD006BE8B05539A3C563A13E02404B0753D8CCC7E056A59048D14BC5D63F5DE`. That evidence records `configuration_backup` commit `2d65292964be6ea63dcf5f5a8d3a20ca53e80a0c`, remote verification as true, byte-equal instruction hashes, catalogue environment-name presence, and the account enabled and `PasswordNeverExpires` policy flags; it therefore evidence-backs the SibylaMem preservation of the `2.4` instructions byte-for-byte, the new environment-variable name, and the account policy state. General `main` deployment remains blocked by 35 migrations and `S15PartyCollapsePhaseB`. | **closed 2026-08-28** |

## S0 progress

**S0 is closed — all eight items**, with their detail in the backlog and not repeated here: **S0-1** V6-O1 decided · **S0-2** P1-1b closed, Scopes 1–8
revoked · **S0-3** the nine migration files on `main`, green · **S0-6** process corpus archived, `docs/*.md` 86 → 26 · **S0-7** izibizi prerequisites owned ·
**S0-8** GitLab CI on merge requests and branch pushes. The last two closed 2026-08-18:

- `[x]` **S0-4** **closed 2026-08-18.** GD-1 (`docs/golden-documents.md`) was carried through the stack: the exact pinned bytes submitted to
  `/api/channel-intake/v1` with the verified dedicated channel-intake client, against a pre-existing enabled sender mapping, isolated PostgreSQL and an
  isolated Local scratch storage root, on installed artifact `a8d0a4bab7b2f93920ad29819d442e01c04dd374`. Outbound **business** integrations were deliberately
  disabled — Cegid, Microsoft Graph and the financial push paths — so no external business-integration job, commit, operation or call occurred. **OIDC
  discovery and token acquisition did occur**, as authentication to the Sibyla API for the intake submission; no token, client id or value is recorded. No
  live write and no mapping edit occurred. The persisted and negative side-effect postconditions were checked and the disposable resources cleaned up. The
  nine steps above are marked from that run — four **works**, two **broken**, two **missing**, one **not reached** — and breakage stays a valid finding.
  The earlier 2026-08-10 run was preliminary and is superseded.
- `[x]` **S0-5** **closed 2026-08-18** — this file, with the nine steps marked from that run and the preliminary run kept distinct from it.

## S1 progress

**Every buildable `S1-9` piece is delivered** (map in the merge table above): seeding, `S1-3a`,
`S1-6a`, all six `S1-9c` descriptor screens, all eleven `S1-9d` Entity 360 slices with the
governed M-D4 write pattern, the three `S1-9e` slices, the `S1-9f` SNC tree, `S1-9i`, the
`S1-9h` read catalogue and the `S1-9g` presentation write. DOCTYP's unmatched label rows stay
target-owned and fillable through `!105`; the seeder writes none of them. **Remaining in S1**,
per `docs/s1-gated-editors-proposal.md`: `g2` (IsActive offer toggle — normal flow, assessed in
its MR), `g3` (blocked on **O-1**, Luís), the DOCEFL editor (**formally deferred to S2**;
**O-4** stays Miguel's) — and the exit. `S1-9g` g2 — the governed offer toggle — shipped 2026-08-20 (`!117`, record above), leaving
only g3 (on **O-1**) and the S2-deferred DOCEFL editor among the remainders.

**The "CTT" exit was demonstrated and S1 is closed — 2026-08-20.** Miguel ran the session at
14:45 against the demo database: searched CTT, opened the real `EC000007` row, walked all nine
tabs. Identity, Items (three rows, all SNC-mapped) and Balances carried data; Aliases and
Banking showed honestly empty (the source carries none for CTT). The session's two findings
were fixed the same day — the Roles-tab mojibake (`!121`) and the empty Tax Identifiers tab
(`!122` + `!124`) — after which **Miguel revalidated that CTT shows its NIF on the Tax
Identifiers tab and validated the exit with screenshots as the record**. Date, person and
evidence are exactly these. **Demo preparation, measured 2026-08-20.** The first pass
surfaced `EC000050`/`EC000094` (fiscal without country); the source was corrected the same day
(`EC000050` → Oman, `EC000094` removed), which needed `!119` (record below) because the parser
did not know Oman. The rebuilt demo database then reached **Latest through the full S1.5
sequence with the real source**: pre-collapse seed, S1.5-3 backfill and reconciliation
**115/115 complete**, Phase B, the DOCTYP cutover (four missing cutover tuples inserted the way
the disposable harness does), and every migration through `20260820065333` (later
`20260820141922` via `!124`, record above). **The seeder replay on Latest is idempotent — a
second run reported `unchanged` across all fourteen tables.** The **real CTT row**:
`EC000007`, CodeName `CTT`, Active and capturable, with three ENTITM items all mapped to SNC
accounts.

**Two findings from the preparation, recorded for S2:**
- **Fiscal-identifier policy (stated 2026-08-20):** newly created entities and documents must
  carry a FiscalNo prefixed with the ISO2 country code; **pre-existing entities from working
  ERPs (Moloni, Primavera, Sage, …) are taken verbatim** — including without a fiscal
  identifier — because live systems cannot be rewritten. `S2-6` implemented the resolution and
  governed creation portion in `!141`; `S2-7` delivered the remaining own-company gate in `!143`.
- **Post-collapse ingestion gap:** the seeder's post-collapse party resolver matches existing
  parties only and **creates none**, and the historical Phase B gate required a fiscal on every
  entity — so source entities added after the collapse without a fiscal (`EC000107`–`EC000109`,
  legacy per the policy above) currently have **no automated ingestion path**, and a seeder
  replay against the official database would fail party resolution with today's source. The
  demo database therefore carries the collapse-era cut (those three excluded, plus one ENTBNK
  row referencing them — reported, never silent). The governed ingestion path for source deltas
  landed with `S2-6` in `!141`; the own-company gate landed with `S2-7` in `!143`.

**S1.5 is complete through `S1.5-8`.** Cumulative MR `!59` merged source `394fbbd` to `main` as `60ffb46` on 2026-08-15: Phase B collapsed the party master;
the phase-0 contract replay had an empty diff; the 61-test `P11aDatabase` suite now runs against migrations; S1.5-7 closed as the compatibility realization
using the authoritative `EntityRoleAssignments` child with `InternalCompany`, ENTMST scalar `Role='Company'`, and party reads on merged ENTMST; and the
reference-data seeder resolves and replays the post-collapse shape. The explicit counterparty-not-own-company enforcement was delivered by S2-7 in `!143`. Pipeline
**2762302842** succeeded: Debug and Release builds each reported 0 warnings and 0 errors; default 1183/1183, `PartyCollapseContract` 38/38,
`P11aDatabase` 61/61 and PostgreSQL 17 `FdrDatabase` 189/189 passed with zero failures or skips.

## How work proceeds

Not restated here — this file is state, and process lives in `AGENTS.md` ("How work proceeds") and
`V6.md` §2: pipeline green → merge, adversarial pass as comments rather than a gate, fix forward,
the four-item stop list, and the runtime gates that are features rather than process.

## Watch

`PROJECT-STATE.md` grew 128 KB → 148 KB and `p1-1b-status.md` 476 KB → 484 KB **after** v6 was
merged. Both are now in `docs/archive/` and frozen. If this file starts growing the same way, the
problem was never the files.

Two regression signals, both measurable from git: a phase that produces more governance words than
code lines, and this file passing one page. If a defect gets through, tighten **verification** —
more golden documents (`docs/golden-documents.md`), contract tests at the ERP boundary — never add approval steps. Conceding
that is how v5 happened.
