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

Hand this to the coding agent on the **development machine**, working in
`D:\fileStorage\repos\GOTT.Sibyla`. It is written to be pasted as the opening message of a
fresh session.

> ## Read this first — you may be on a stale checkout
>
> The v5.0 planning documents this assignment depends on were authored on a **different
> machine** and reach you only through GitLab (`origin`:
> `gottsolutions.dev/sibyla/GOTT.Sibyla`, branch `feature/document-type-settings`).
>
> **Before anything else: `git fetch && git status`, then open `docs/project-todo.md` and
> check two things —** line 1 must read `# Sibyla Project TODO — Development Plan v5.0`,
> and there must be a `## Decisions Taken for v5.0` section listing **D1 through D9**.
>
> If line 1 says **v4.0**, or the decisions section is missing, **stop and report it.** Do
> not proceed. The v4.0 backlog contradicts this prompt on the points that matter most —
> it has DOCRQE as a recomputed live view, `MNGAPL` instead of `MNGACC`, `DOCTYPE` instead
> of `DOCTYP`, 79 items instead of 133, no flag-governance or queue phases, and Layer 5
> parked in Phase 2. Working from it would produce a schema that has to be thrown away.

---

## Context

You are working in the **GOTT.Sibyla** repository (`D:\fileStorage\repos\GOTT.Sibyla`),
on branch `feature/document-type-settings`. This is a .NET 10 solution (API, Blazor Web,
Worker, Domain, Infrastructure, Tests) that acts as the production harness for a fiscal
document processing system.

The roadmap was reissued on **2026-08-03 as Development Plan v5.0**. Read these first,
in this order, before doing anything:

1. `docs/project-todo.md` — the v5.0 execution backlog. This is the authority. 14 phases
   (P1-0…P1-13), 133 items, 1 done.
2. `docs/project-evolution.html` — current state, the three v5.0 decisions, open risks.
3. [`docs/2026-08-03 Sibyla_Organigrama_Fluxo_v13.svg`](<2026-08-03 Sibyla_Organigrama_Fluxo_v13.svg>) — the information-flow diagram.
4. `docs/project-todo-v4.md` — the superseded v4.0 backlog, kept for diff purposes only.
   Do not execute from it.

**Where v5.0 came from.** The domain model is proven first in a separate Python
prototype — the *Fiscal Document Registry* (FDR), built by Luís Nascimento in a folder
outside this repo. v5.0 merges that prototype's Stage 8–10 work into this backlog.
Items marked `[S]` in the backlog have a **working reference implementation** in the
prototype: your job on those is to port behaviour that is already proven, not to
redesign it. When the backlog and your instincts disagree on an `[S]` item, the backlog
wins — it is describing something that already runs and has a control record behind it.

**You can read the prototype directly — see the section below.** You do **not** have write
access to it and should not ask for any. Read it rather than guessing, and never
reimplement an `[S]` item from first principles when a proven implementation is sitting
there.

## The prototype repository — read-only reference

`git@gitlab.com:gottsolutions.dev/sibyla/invoice-skill-build.git`, branch `main`.

Clone it **beside** the Sibyla repo, never inside it. It is a reference you read, not a
dependency you build against.

**Four rules, all load-bearing:**

1. **Read-only. Never push, never open a merge request, never commit.** Luís owns this
   repository and works in it daily — the most recent commit is 2026-08-04 11:34, carrying
   the identity fixes this prompt depends on. A write from you would collide with live work.
2. **Pin to a commit and record it.** Check out a specific SHA and write it into your design
   documents as the version you ported from. The prototype moves during the day; a floating
   `main` means the specification shifts underneath your schema mid-design. When something
   looks contradictory, first check whether your pin is simply older than the fix.
3. **It contains real financial data.** 3,071 tracked files, and the data is *committed*,
   not gitignored — real IBANs, fiscal numbers, salaries, bank statements and invoice PDFs
   for Gott and Itoorer. Treat it as confidential: do not copy data into the Sibyla repo, do
   not paste values into commits, issues or logs, and **synthesize your test fixtures**
   rather than lifting real rows.
4. **Port the behaviour, not the Python.** The .NET application is the production harness,
   not a transliteration of scripts. Extract the rules, the invariants and the test cases,
   then design them properly for a database and a job system. A script that reads a JSON
   file and rewrites it is solving a problem you do not have.

**Where to look, by backlog phase:**

| Phase | Read |
|---|---|
| P1-0 / P1-1 code issuance | `Scripts/add_row_codes.py`, `Scripts/verify_code_identity_stability.py`, `entity_utils.generated_source_index()`, `Scripts/build_bnkmov.py` |
| P1-1 validation service | `Scripts/validate_registry.py` — the explicit port target |
| P1-3 production skill | `SKILL.md`, `Specs/Lessons/lessons-learned.md` (~190 KB of corpus knowledge), `Specs/Lessons/known-limitations.md` |
| P1-4 pipeline and gates | `Scripts/process_new_documents.py`, `Specs/computed-fields.md`, `Specs/Data Schema/schema.md` |
| P1-5 flag governance | `Scripts/build_docflg.py`, `Scripts/add_flag_evaluation.py`, `Editor/Data/flag_evaluation.json` |
| P1-6 queues | `Scripts/build_docrqe.py`, `Scripts/build_recrev.py`, `Scripts/sanitize_docrqe_stale_items.py` |
| P1-7 apply engine | `Scripts/apply_review_decisions.py` |
| P1-11 reconciliation | `Scripts/match_bnkmov_*.py`, `Scripts/sanitize_ineligible_matches.py`, `Scripts/sanitize_own_account_transfers.py`, `Scripts/build_bnkmat.py` |
| Governance | `Specs/Engagement Rules/` — 13 binding documents the .NET system must honour |
| Why anything is the way it is | `Backups/Control Log.md` and `Specs/Roadmap/Roadmap.md` |

The Control Log is worth more than it looks. When a rule seems arbitrary it usually has an
entry explaining which specific failure produced it — and reading that is how you avoid
designing the failure back in. Several entries are corrections of Luís's own earlier
conclusions; those are the most valuable ones.

## Working mode

**Propose first, build on approval.** For this assignment:

- Produce the deliverables as **drafts** in `docs/`.
- Maintain a running list of open questions that need a human decision, separated into
  "needs Miguel" and "needs Luís (FDR side)". **As of 2026-08-04 that list starts empty** —
  every decision this assignment depends on is taken. If you find yourself adding to it,
  check first whether D4–D7 or the identity section below already answers it.
- **Do not** write EF Core migrations, modify the database schema, or start P1-1. The
  plan gates migration work behind a P1-0 sign-off (backlog P1-0, final item).
- **Do not** modify anything under `src/` except where a specific item below says so.
- Commit to the current branch with focused commits; do not merge to `main`.

Stop and ask when you hit a decision the backlog marks as needing a user or accountant
input. There will be several — P1-0 is mostly decisions.

## Your assignment: P1-0 — Contract and Schema Design Freeze

Work the P1-0 checklist in `docs/project-todo.md`. Deliverables:

1. **`sibyla.claude-extraction.v1` contract spec** — classification (docClass,
   documentType, originClass, failure category), parties as printed with fiscal numbers,
   fiscal header/line fields, basic non-fiscal metadata, `readingMode`, per-field
   confidence, the five warning codes, optional operator comment, and strict validation
   rules applied *before* persistence.
2. **Discard / Purge lifecycle design.** Reviewer Discard is soft (excluded everywhere,
   bytes and audit retained); authorized-role Purge deletes bytes and leaves an audit
   tombstone with metadata + SHA-256. Never automatic; never available for anything that
   reached a fiscal or archive table. A retained hash auto-discards byte-identical
   resubmissions at Information level. **This design is also the mechanism Luís needs
   on the FDR side — write it so it is usable from there too. Note his constraint: DOCLOG
   carries a never-delete rule, and a soft discard that retains evidence is exactly what a
   blanket delete would have destroyed.**
3. **Full schema mapping**, FDR layers 1–5 plus the Layer 6 ground-truth slice, to
   PostgreSQL. Use the corrected roster in the backlog. Note especially:
   `MNGACC` (not `MNGAPL`), `DOCTYP` (not `DOCTYPE`), and the presence of `COCACC`
   and `DOCFLG`, all of which the v4.0 plan had wrong or missing.
4. **Permanent-code issuance design** — database-backed sequences per bucket, collisions
   raise rather than silently picking a winner, codes are never reassigned. **The natural
   keys are already settled and proven — see the identity section below and port them.**
5. **DocClass / DocumentType taxonomy** seeded as `DOCTYP` rows.
6. **Nextcloud business-copy layout** per class; decide the Legal sub-path.
7. **Grandfathering model**, built to decision D7 below: enforcement is prospective against
   each instance's own `DetectedAt`, never the import date. Without this, importing 1,153
   headers raises a blocking flag on most of them.
8. **`RelatedParty` flag on ENTMST** (or an equivalent item classification) so intercompany
   funding is identified by rule rather than ignored by note.
9. **"User and AI Roles and Responsibilities" policy** — a superseding policy that sits
   above the capture, entry, and reconciliation procedures. A full draft exists on the
   FDR side; ask for it rather than writing one from scratch. Its operative clause for
   you: the review queues are **exception-and-learning surfaces, not mandatory work
   queues** — which shapes the P1-9 UI later.
10. **History import — already decided (D4).** Full 2026 history as opening balances plus
    the complete reference layer; 2025 out. Your job is the mapping and the validation, not
    the decision.

## The identity model — CLOSED, port it rather than deriving it

This was the one part of P1-0 with a dependency outside the repository. **It is resolved.**
Luís closed all three code-identity defects on 3–4 Aug and proved each. Your job is to port
the keys, not to re-derive them.

1. **Bank-generated P/F/O documents key on the movement's natural key.** `BMCode` had
   `SourceFile` in its key — a field the pipeline deliberately *rewrites in place* so
   BNKCHK's `(BankAccount, SourceFile)` join survives an archive rename. Two keys for one
   thing, one of them moving. `SourceFile` is now excluded, and the generated-document
   scripts anchor on a `SourceKey` carried by all 426 rows. Two details that only appeared
   under test and that you must preserve: seven payroll documents aggregate a whole pay run
   and hold a **comma-joined list** of up to 15 BMCodes, so a single-code reader fails to
   anchor exactly the documents where a wrong duplicate would be largest; and the occurrence
   tiebreaker must be **recomputed, not dropped**, because a real BCP statement lists two
   byte-identical lines on one day and merging them causes *under*-generation.
   *Proof on file: all 1,960 BMCodes renumbered and every SourceFile changed — 426 of 426
   re-anchored, 0 duplicates. Under the old rule, 0 of 426 and EUR 639,943.78 regenerated.*
2. **DOCLOG keys on `(Filename, EntryCode)`.** LGCode was re-keyed on that pair, 512 fresh
   codes issued from max+1, and DOCFLG's 509 references migrated in the same transaction.
   **1,475 rows now carry 1,475 distinct LGCodes**, so LGCode *is* the per-row identity and
   **no `DocLogId` is required** — drop that idea if you find it in older text.
3. **PAYCODE / RCVCODE derive from the fiscal document plus payment sequence, and are
   proven stable.** `verify_code_identity_stability.py` runs every pass: it shuffles the
   rows, blanks every code, reassigns from the ledger alone and requires that not one code
   moves. Result: 0 of 481 PAYCODEs, 0 of 245 RCVCODEs, 0 of 119 EntityCodes, 0 of 1,475
   LGCodes and 0 of 1,960 BMCodes. **Port that test too** — an order-preserving check would
   have gone green while the defect was live, which is exactly what happened before. Read
   `Scripts/verify_code_identity_stability.py` rather than reconstructing it from this
   description.

Write P1-1's uniqueness check against these keys. The naive version — "no permanent code
may appear against more than one EntryCode" — would reject internally consistent data and
must not be implemented.

**Do not propose deleting residual DOCLOG rows.** That was proposed once and would have
destroyed evidence: of the rows originally flagged, most were honest audit traces of
superseded generations, some were future-dated schedule rows correctly removed, and 27
concealed a real EUR 142,835.50 gap — six months of 2026 payroll with no FDCHDR row at all,
matched to a ledger reference so the cash reconciled while the entry layer was empty. That
lesson is now decision D6 and a control you implement in P1-11.

## Decisions already taken — do not reopen these

All six were settled on 2026-08-04 and are recorded as D4–D9 in `docs/project-todo.md`.

- **D4 — history import.** Full 2026 as opening balances plus the complete reference layer;
  2025 stays out under the scope rule. Scope: DOCLOG 1,475 · FDCHDR 1,153 · FDCDTL 1,190.
  Accepted consequence: the Toorist related-party position cannot close across years yet.
- **D5 — `Reference Only` is a first-class document state.** Captured, archived and
  searchable, but issued **no EntryCode by design**, so it cannot reach FDCHDR, PAYCTR,
  ENTBLC, the matchers or aging even by accident. Classified by rule EF0000045 (Information,
  Non-Blocking), distinct from "routed to FailureTable" — these processed fine and were
  *chosen* not to be posted. Retain the full payload so a later round can post one without
  re-reading the PDF. Not folded into Discard: discard means junk, these are evidence.
- **D6 — "reconciled is not recorded" gets its own BNKMAT match status**
  (`Matched — ledger reference, no entry`), **excluded from the reconciliation percentage**.
  Chosen over a flag on an otherwise-`Matched` row: a separate status makes the movement
  impossible to count as clean *by construction*, where a flag relies on whoever reads the
  metric remembering to filter. Satisfy the match-type governance rule when you add it —
  control logic, tolerance, required evidence, test case. This is the failure mode that hid
  six months of payroll.
- **D7 — grandfathering.** Import each DOCFLG instance with its `DetectedAt` and apply
  prospective enforcement against that, not the import date. 29 instances are open carrying
  a blocking level (detected 31 Jul – 2 Aug; 25 still point at live records). They stay
  visible and audited, and do not block.
- **D8 — `ItemClass` is frozen at Decision / Status / Annotation.** A closed enumeration.
  Model it as such, not as an extensible lookup. Every detector you build must declare which
  of the three it emits and must fit one of them; a fourth class later is a migration, and
  that friction is intended — it is what stops a phantom backlog re-forming.
- **D9 — recurring payment-control imports are additive, keyed by period.** Each import
  declares its period and appends; re-importing a period replaces **only** that period.
  Idempotent by construction, and history survives. The prototype hardcodes one filename and
  PAYDTL reads only from it, so the next period's file currently has no ingestion path —
  build the convention, do not inherit the hardcode.

## Non-negotiables

These come from the v5.0 Definition of Done. Treat them as invariants:

- Claude reads and proposes; only deterministic .NET code decides, persists, and executes
  side effects, after validation and approval.
- A recorded decision survives a full pipeline rerun. Queue state is **persisted, never
  recomputed** — DOCRQE is a persisted table with permanent ReviewIDs, not a live view.
  If you find v4.0-era text describing it as a recomputed view, that text is superseded.
- **An item is only Open if a human decision could change something.** The queue carries an
  `ItemClass` of Decision / Status / Annotation; only Decision items are ever Open, and a
  finding the pipeline resolves is CLOSED with evidence rather than annotated and left
  open. Without this the prototype's queue read as 2,616 open against 9 decided; with it,
  164 open of 180 Decision-class. Do not port the queue without it.
- **Before adding a detector, state which `ItemClass` it emits.** A detector that cannot
  say whether its output is a Decision, a Status or an Annotation does not yet know what
  it is for.
- **"% worked" is reported on the Decision denominator only.** A percentage across a whole
  file measures a register, not a backlog.
- A rejected proposal is never re-proposed by any matcher, on any subsequent run.
- New rules do not retroactively block imported history.
- A wrong-but-plausible value is worse than an honest blank. Missing rates, identifiers,
  or evidence fail closed to review; nothing is estimated to fill a gap.
- Human-origin 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 no warnings; `dotnet test
  tests\Sibyla.Tests\Sibyla.Tests.csproj` passes with no failures.

## Repository hygiene

This repository has a history of incidental churn under `docs/` — line-ending and sync
noise unrelated to any feature work. If `git status` shows modified files you did not
touch, **leave them alone**. Stage only files you deliberately changed, by explicit path;
never `git add docs` or `git add -A`.

Push to `feature/document-type-settings` only. Do not merge to `main`, and do not rebase or
force-push a branch that another machine is also writing to — the planning documents arrive
on this branch from elsewhere.

The prototype clone lives **outside** this repository. Never add it as a submodule, never
commit any part of it here, and never let a real IBAN, fiscal number, salary or bank
reference from it reach a file in this repo.

There is no `AGENTS.md` in this repository. As part of this assignment, create one
capturing: the v5.0 plan pointer, the three decisions, the `[S]` marker convention, the
non-negotiables above, and the build/test commands — so a future session inherits this
context without re-reading everything.

## Definition of done for this assignment

- Every P1-0 checklist item is either drafted in `docs/` or explicitly listed as blocked
  on a named human decision.
- The contract spec and schema mapping are complete enough to review — not sketches.
- The LGCode definition question is answered with a recommendation and the P1-1
  validation check is restated to match.
- `AGENTS.md` exists.
- The prototype commit SHA you ported from is recorded in the design documents.
- A single summary document lists what was decided, what is open, and who owns each open
  item (Miguel or Luís).
- Nothing under `src/` changed; no migrations written; P1-1 not started.

Report back with that summary rather than proceeding to P1-1.
