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

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

> **P1-0d is complete and is not reopened.** Its rows, its provenance markers, its A3 measurement
> and its governance text all stand and were independently re-verified on 2026-08-05: the 45 DOCEFL
> rows re-parse to 45 unique EFCodes with no gap in `EF0000001`–`EF0000045`, all 19 DTCodes and both
> ITMCLS `CLCode`s check out against their stated blobs, the A2 register is exhaustive, and the
> commit touched documentation only. **This assignment closes what that verification found, and
> nothing else.**

---

> ## Read this first — state, and where to get it
>
> **`docs/PROJECT-STATE.md` is the only source of project state.** Read it before this prompt's
> context and before any draft. Everything else in the repository is a record of a moment.
>
> - **C1–C19, A1–A7, C3, D1–D9, group-B scope, S1–S4, B1 and A3 are all decided.** Do not reopen one.
> - **P1-0 is accepted and closed.** Nothing here reopens it; every item below is a defect in how a
>   closed decision is written down, not a new decision about the design.
> - **Only O5 is open on the whole project.** Do not report anything else as a blocker, and never
>   write "pending", "unconfirmed" or "awaiting Luís" into a draft.

---

## Why this assignment exists

P1-0d did the hard part correctly: it replaced an all-or-nothing source gate with per-field
provenance, and it left **34 fields explicitly `absent`** rather than inventing plausible values.
That was the right call and it is not being undone.

But `absent` means *blank*, and **blank has to be legal somewhere**. Verification found that it is
not. **This is the one item that matters, and it has a deadline: P1-1a is writing the migration
train now.** If it emits the declarations as written, the three rows P1-0d authored cannot be
inserted, and the failure surfaces at seed time in P1-1b — six weeks after the decision that caused
it, which is exactly the failure mode this project keeps paying for.

---

## Deliverable 1 · Reconcile `absent` with nullability — the only urgent item

`docs/p1-0-schema-mapping.md` declares DOCEFL with **only three nullable columns**
(`DetectionPattern`, `AppliesToField`, `AutoActionCondition`) and BNKMAT with **one**
(`FlagReviewNotes`). Against those declarations, the three authored rows are blank in columns that
are not allowed to be blank:

| Row | Fields `absent` | Of which the declaration forbids NULL |
|---|---:|---:|
| `EF0000000` (C11 sentinel) | 16 | **13** — `FlagCategory`, `RiskFactor`, `AutoReviewable`, `Summary`, `FlowDimension`, `PolicyReference`, `RequiredAction`, `AutoActionAllowed`, `ReviewOwnerRole`, `ReviewPriority`, `ResolutionEvidenceRequired`, `EffectiveFrom`, `EnforcementStartsAt` |
| `EF0000053` (C12 Monthly-gap) | 12 | **11** — the same list minus `Summary`/`RequiredAction`/`ResolutionEvidenceRequired`, plus `BlockingLevel` |
| `BT000012` (D6 BNKMAT) | 6 | **6** — `ReconciliationType`, `AutoProposeAllowed`, `AutoCloseAllowed`, `RequiresReview`, `MaxDateWindowDays`, `ToleranceAmount` |

**Thirty columns. Decide each one, and record the decision in the schema mapping next to the column
declaration — not only in a status report.** There are exactly three legitimate outcomes per column,
and you pick one:

1. **The column becomes nullable**, because a rule that describes the *absence* of a rule genuinely
   has no value there and never will. Write `NULL` into the declaration and say in one line why the
   column is optional *for every row*, not just for the sentinel.
2. **The column stays non-nullable and the row supplies a value**, because the field is in fact
   structurally implied and P1-0d was over-cautious. Then it is `authored` with a same-cell
   justification, exactly as `Active` and `RuleVersion` already are — and
   `docs/p1-0-c20-authored-rows.md` is updated so the two documents cannot drift.
3. **The column stays non-nullable and the row is not seeded in P1-1a**, because the value depends
   on an activation decision nobody has taken. Then say *when* the row is created, by which command,
   and what supplies the field — and note it for P1-1b.

**Do not resolve this by inventing a sentinel literal** — no `'N/A'`, no `'Unknown'`, no empty
string standing in for NULL, no `0` risk factor, no epoch timestamp. A fake value that satisfies a
constraint is worse than an honest nullable column, and it is the exact failure the `absent` marker
was created to prevent.

Two specific cases you must not skip:

- **`DOCEFL` unique `(FlagReasonCategory, FlowDimension)`.** If `FlowDimension` becomes nullable,
  PostgreSQL's default `NULLS DISTINCT` means this constraint stops binding for every row that has
  no dimension. State `NULLS NOT DISTINCT`, or change the constraint, or explain why unenforced is
  correct here. Do not leave it implicit.
- **`EF0000053` is `Active=Yes` with no `BlockingLevel`, `ReviewOwnerRole`, `ReviewPriority` or
  `FlagCategory`.** An active detector with no owner, no priority and no blocking level is governed
  but not runnable: DOCFLG instances it raises cannot be routed. Either those four are structurally
  implied by C12 and route 2 applies, or the row ships `Active=No` and is activated by the same
  governed command that supplies `EnforcementStartsAt`. **Say which, in the schema mapping.**

---

## Deliverable 2 · Two stale statements

- **`docs/p1-0-schema-mapping.md`, "Group-B placement":** *"B1 remains Miguel's separate byte-scope
  confirmation and is not decided here."* **B1 was closed on 2026-08-05** by
  `docs/p1-0-b1-decision.md`, and `PROJECT-STATE.md` §2.2 records it. Replace the sentence with the
  decision: byte storage is per capture, `RetainedContentHash` is a duplicate-detection index and
  never a storage pointer, reference counting is not implemented, purge is capture-scoped storage
  hygiene and not erasure. **Then grep the whole `docs/` tree for any other sentence that describes
  a closed item as open, and report what you find even if you fix it.**
- **Patch artifacts.** A literal `+` from a diff leaked into two markdown headings and renders as
  body text: `docs/p1-0-codes-taxonomy-archive.md` line 167 (`+### Extracted pinned DOCTYP rows`)
  and `docs/p1-0-schema-mapping.md` line 233 (`+#### Extracted 45-row DOCEFL base seed`). Remove
  both leading `+`. Check for others with a line-start scan; do not hand-inspect only these two.

---

## Deliverable 3 · Line-ending hygiene, before it contaminates a commit

The repository has **no `.gitattributes`**. Files are committed with LF and checked out on Windows
with CRLF, so a working clone reports **272 files modified and roughly 89,000 changed lines that
contain no content change at all** — `git diff --ignore-all-space` is empty against them. The next
person who commits from a Windows clone buries a real change inside that noise.

Add a `.gitattributes` at the repository root that normalizes text to LF in the index (`* text=auto
eol=lf`) with the obvious binary exclusions for `*.pdf`, `*.png`, `*.svg` if you treat SVG as text
decide it explicitly, and `*.ps1`/`*.cmd` if the toolchain needs CRLF on disk. **Then run
`git add --renormalize .` and commit that renormalization as its own commit, touching nothing
else**, so the noise commit is separable in history from any content commit.

This is the one place you may touch paths outside `docs/` — and only for renormalization. **You
still may not change the content of any file under `src/`, `tests/` or `migrations/`.** Verify with
`git diff --ignore-all-space HEAD~1` on your renormalization commit: it must come back empty.

There is also a stale zero-byte `.git/index.lock` in the user's clone at `C:\WIP\GOTT.Sibyla`. That
is not yours to fix from the dev machine; **name it in your status report** so the user deletes it.

---

## Deliverable 4 · Close the loop

- Update **`docs/p1-0-c20-authored-rows.md`** for every field that moved from `absent` to
  `authored`, keeping the same-cell justification format. A field that stays `absent` keeps its
  evidence line unchanged.
- Update **`docs/PROJECT-STATE.md`**: add a changelog row for P1-0e, and state in §3 that
  **P1-1a's DOCEFL and BNKMAT column nullability is now specified** and what it is. O5 stays the
  only open item unless deliverable 1 route 3 creates a genuinely new one — if it does, add it to
  the §2 table with who closes it.
- Write **`docs/p1-0e-status.md`**: the thirty-column decision table with the route taken for each,
  the constraint decision, the `EF0000053` activation decision, the list of stale statements found
  by the grep, and the exact paths changed. **The line to read first is the thirty-column table.**

---

## What you may not do

- Reopen P1-0d's extractions, its A3 measurement, or any C/A/S/D/B decision.
- Invent a placeholder literal to satisfy a NOT NULL constraint.
- Change content under `src/`, `tests/` or `migrations/` — renormalization only, and only in its own
  commit.
- Write, apply or plan a migration. P1-1a owns the train; you are specifying its inputs.
- Touch the prototype repository in any way.
- Write "pending", "unconfirmed" or "awaiting Luís" anywhere.
- Merge to `main`.

## When to stop and report — scoped to the deliverable, never global

Stop **the affected deliverable only**, finish the others, and report:

- A column's nullability cannot be decided without a decision nobody has taken. Name the column, say
  what the decision is, and route it — do not stall the other twenty-nine.
- The renormalization commit shows a non-empty `--ignore-all-space` diff, meaning something other
  than line endings changed. Stop that deliverable immediately and report it.

## Definition of done

- All thirty columns are decided, each recorded next to its declaration in
  `docs/p1-0-schema-mapping.md`, with `docs/p1-0-c20-authored-rows.md` in agreement.
- The `(FlagReasonCategory, FlowDimension)` uniqueness question and the `EF0000053` activation
  question are answered in the mapping.
- No document in `docs/` describes B1 — or any other closed item — as open.
- No markdown heading begins with a stray `+`.
- `.gitattributes` exists; the renormalization is its own commit; `git diff --ignore-all-space` on
  that commit is empty.
- `docs/PROJECT-STATE.md` reflects reality and `docs/p1-0e-status.md` exists.
- `dotnet build GOTT.Sibyla.slnx` still passes. If the sandbox cannot reach `api.nuget.org`
  (`NU1301`), say so and run it on the host; a network failure is not a build failure.
