# F0 Spike Results

Updated: 2026-07-15

This document records the current evidence and go/no-go decision for every external
F0 acceptance spike in Sibyla Implementation Plan v3.2. A `NO-GO` result blocks F1
financial or document-processing work that depends on that proof; it does not
invalidate the completed repository foundation.

## Repository foundation

| Check | Evidence | Result |
|---|---|---|
| .NET 10 build | All eight projects, including the PostgreSQL and Graph acceptance runners, build with zero warnings | GO |
| Rebaselined tests | 30 tests pass | GO |
| API host smoke test | Development API returned `Healthy` from `/health/live` | GO |
| Worker host smoke test | Development Worker remained running with all configured job lanes | GO |
| EF migration alignment | `migrations has-pending-model-changes` reports no changes | GO |
| Initial PostgreSQL script | Migration script generated successfully in `artifacts/f0-schema.sql` | GO |
| Audit immutability | DbContext test plus successful UPDATE/DELETE rejection by the PostgreSQL append-only trigger | GO |
| Job lifecycle | Automated tests plus PostgreSQL concurrency, process-kill recovery, retry, and dead-letter proof | GO |

## PostgreSQL job crash and concurrency

**Current result: GO — passed against the dedicated local PostgreSQL database on
2026-07-13.**

The reproducible runner in `tests/Sibyla.PostgresSpike` executed against
`localhost:55432/sibyla_f0` using the non-superuser, non-`CREATEDB` role `gott`.
It proved that:

- the reviewed F0 migration applies successfully;
- the database trigger rejects both UPDATE and DELETE against `AuditEvents`;
- 16 simultaneous claimants receive 16 distinct jobs through `FOR UPDATE SKIP LOCKED`;
- retry reaches `DeadLettered` exactly at `MaxAttempts` with the expected attempt history;
- stored document, original asset metadata, first job, and audit events roll back together after a real unique-constraint failure;
- killing a separate claimant process leaves its durable lease in place;
- after lease expiry another worker reclaims the same job with a new token, records the killed attempt as `LeaseExpired`, and completes a second audited attempt.

Re-run the proof with:

```powershell
dotnet run --project tests\Sibyla.PostgresSpike\Sibyla.PostgresSpike.csproj
```

## Microsoft Graph workbook write

**Current result: GO — passed against the isolated workbook copy on 2026-07-14.**

An isolated copy named `Sibyla_F0_GraphSpike_20260713_203724.xlsx` was created for
the acceptance test. The Graph runner refuses the original item ID and requires
the isolated-copy filename prefix before it can write. The v3.2 implementation now
includes delegated MSAL authentication, a CurrentUser-DPAPI token cache, persistent
workbook sessions, schema fingerprint validation, `MST_ID` reconciliation, and
bounded 429/503/504 handling. Automated tests cover the retry, ambiguous-write,
idempotency, and fail-closed branches.

The dedicated public-client registration issued a delegated `Files.ReadWrite.All`
token for `sibyla@gottsolutions.net`. Initialization created the CurrentUser-DPAPI
cache, verified the target filename, opened a persistent workbook session, added
the dedicated `MST_ID` column to the copy, and stored this 24-column Table2 schema
fingerprint:

`B49477CD62F73CCC098FD5885E26F44D3DA76D86D3CFF7DEE4351B043F750196`

A separate process silently acquired the token from the protected cache, opened a
new persistent session, validated the fingerprint, and added
`MST_ID=SIBYLA-F0-685f3aab4d994f24bf7bdde40e9865f1`. Repeating delivery with the
same identifier produced no duplicate row.

Automated response tests prove that 429 and 503 respect `Retry-After`, idempotent
504 responses can be retried, non-idempotent 504 responses are treated as
ambiguous, and an ambiguous write is reconciled by `MST_ID` before any decision to
retry. A separate test proves schema mismatch fails closed before a write.

Re-run initialization and the fresh-process proof with:

```powershell
dotnet run --project tests\Sibyla.GraphSpike\Sibyla.GraphSpike.csproj -- --initialize
dotnet run --project tests\Sibyla.GraphSpike\Sibyla.GraphSpike.csproj
```

## Restricted Hermes `documental-agent` profile

**Current result: GO — canonical target-host acceptance passed after reboot on
2026-07-15.**

The target host is `EC2AMAZ-NTPJCNO`, running Hermes Agent v0.18.2
(`2026.7.7.2`, upstream `2d0f2185`). The canonical profile is named
`documental-agent`. It runs under `EC2AMAZ-NTPJCNO\GottSibylaDocumental` with
`HERMES_HOME=C:\SibylaApps\Documental-agent` and an isolated Python/Hermes runtime.

The versioned extraction, prompt-injection, and remote-handoff instructions are in
`docs/hermes-documental-agent-instructions.md`. They may be transported by
`orquestrador`, but must be installed persistently in the remote `documental-agent`
profile. Windows ACLs, profile tool restrictions, and the service account remain
external security controls.

The authoritative request is `sibyla-documental-acceptance/1.2-ws2025`. The
post-reboot canonical run `20260715T115019Z-ff717f71` passed under the restricted
identity with task logon type `Password` and run level `Limited`. Identity, profile
resolution, instruction hash, legacy-instruction absence, tool policy, filesystem
and credential isolation, benign extraction, malicious-document prompt injection,
concurrency `2`, and timeout cleanup all passed. The temporary task was removed and
this F0 evidence file remained unchanged.

Canonical target-host report:
`C:\SibylaApps\Documental-agent\evidence\canonical-acceptance-1.2-20260715T115019Z-ff717f71\report.json`.

## Reboot without interactive login

**Current result: GO — restricted runtime acceptance passed after a real target-host
reboot on 2026-07-15.**

The canonical task started without interactive login, ran as the restricted account,
returned task result `0`, and removed its temporary task. Full API, Web, Worker,
PostgreSQL, and gateway startup checks remain part of deployment acceptance rather
than a blocker for beginning F1 implementation.

## F0 gate

The repository foundation, PostgreSQL spike, delegated Graph workbook spike,
restricted Hermes runtime, prompt-injection isolation, concurrency, timeout cleanup,
and post-reboot execution are accepted. **F0 is GO.**
