Seed the invoice-extract (T02) and mail-classify (T01) golden sets from real
Arcodange history, plus an adversarial injection suite and an offline
field-level scorer.
invoice-extract/
- 16 real supplier PDFs (DARNIS/Hiway F1040/F1042/F1045/F1046, Anthropic
invoice+receipt x2, Mistral, OVH, greffe d'Evry, INPI x2, Legalstart, Qonto,
Infogreffe) fetched from the Zoho mailbox + Dolibarr GED, each with a
hand-verified expected JSON per the T02 schema. Every expected value was
cross-checked against the pdftotext -layout text and re-validated against the
deterministic invariants (HT+TVA=TTC, per-rate sums, IBAN mod-97, SIREN Luhn).
- inputs/ carries both the source PDF and its {source_sha256, mime, text} pair.
- 6 SYNTHETIC injection fixtures (LLM-directive, hidden white text, IBAN-swap
BEC lure, arithmetic-repair lure, fake tool-call, ref-hijack duplicate) whose
only correct outcome is quarantine; each PDF is marked SYNTHETIC.
- score.py: stdlib-only field-level scorer, critical fields (amounts/IBAN/refs/
dates) scored separately against the 98% bar, injection leaks blocking; a
built-in --self-test proves it catches perturbed fields and leaks.
- manifest.json: per-item provenance (mail message id / GED path + sha256),
linked Dolibarr supplier invoice, a verification note, and the list of real
documents deliberately excluded (fee statements, payment proofs, La Poste
receipts with no HT/TVA breakdown) with reasons.
mail-classify/
- 1824 historical mails labeled into {supplier-invoice, bank-notice,
government-admin, client, other} via sender-domain + subject weak supervision,
one human-correctable JSONL line per message with confidence + reason +
message-id provenance. manifest.json records the pull method and distribution.
Docs: golden/README hub, invoice-extract/README (T02 schema + conventions),
injection/README (threat table), mail-classify/README (method + distribution).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
fleet/ — the atom registry
The fleet is Arcodange's AI back-office: narrow agents ("atoms") that operate the Dolibarr ERP's daily admin & accounting under the AI back-office PRD. This directory is the registry — the versioned source of truth for what the fleet may do. An atom absent from the registry does not run. Contract semantics come from the PRD atom contract; file syntax from the PRD document surface.
What an atom is
One narrow capability (classify, extract, validate, record, reconcile, report, remind) with a strict I/O contract and deterministic validators around it. The LLM proposes, code disposes: formats, arithmetic, checksums, dedupe and referential integrity are enforced by validators, and a model output that fails validation is quarantined, never auto-corrected. Workflows are compositions of atoms with explicit gates — never one prompt that "does the accounting".
Each atom lives in fleet/atoms/<atom>/:
| File | Role |
|---|---|
atom.yaml |
the registry entry — the contract (schema below) |
prompt.md |
thin runtime prompt, ≤ ~40 lines, extends exactly one class skeleton; no business rules (rules live in fleet/profile/ and in validators) |
scripts/ |
the deterministic implementation: runners, validators, scoring hooks |
Folder name = atom name = registry name — the house <app> join-key discipline
applied to atoms.
Layout
fleet/
├── README.md # this file: registry doc + atom.yaml schema
├── classes/ # the 7 prompt skeletons (PRD agent catalog)
│ ├── sentinel.md
│ ├── extractor.md
│ ├── erp-scribe.md
│ ├── deterministic-controller.md # no-LLM by design
│ ├── analyst-writer.md
│ ├── researcher.md
│ └── knowledge-archivist.md
├── atoms/
│ └── invoice-extract/ # T02 — the worked example (contract only; implementation = erp#40)
│ ├── atom.yaml
│ ├── prompt.md
│ └── scripts/
├── golden/ # per-atom golden sets — land with erp#39
└── profile/ # fiscal.yaml + calendar.yaml + ADC register — land with erp#54
atom.yaml — the contract, field by field
Per the PRD atom contract:
| Field | Meaning |
|---|---|
name, version |
Identity. Folder name = name. version bumps on any behavioral change (prompt, model, validator) — a bump re-triggers the atom's golden-set evals. |
input_schema / output_schema |
JSON Schema for the atom's I/O; enforced at runtime (constrained decoding where the model tier supports it). |
invariants |
Deterministic post-conditions checked by code after every run (e.g. HT + TVA == TTC ± 0.01). A failed invariant quarantines the output — refuse, never repair. |
side_effect_class |
read · draft · write-sandbox · write-prod · outbound — drives which gates and credentials apply, per the PRD environment posture table. |
idempotency_key |
How a replay is recognized (e.g. supplier + ref_supplier + TTC) — a second run with the same key must be a no-op. |
autonomy |
The earned level (A0–A3 on the autonomy ladder) + a pointer to the eval evidence that justifies it. |
model_policy |
Preferred tier, fallbacks, escalation rule, per the PRD model fleet; closed per-atom by routing-bench evidence (erp#45 for the first atoms). |
eval_ref |
Where the golden set + scoring script live (fleet/golden/<atom>/). |
Two registry conveniences beyond the PRD contract fields bind the entry to the rest
of the surface: class (which fleet/classes/<class>.md skeleton the prompt
extends) and task (the PRD task-inventory
id the atom serves).
The worked example is atoms/invoice-extract/atom.yaml
(T02) — contract only; its implementation is
erp#40.
How an atom graduates
Autonomy is earned per atom, never assumed. The levels (A0 manual → A1 prepare
→ A2 rehearse + gate → A3 autonomous + audit) are defined on the PRD
autonomy ladder;
promotion and demotion are mechanical, per the PRD
autonomy promotion gates
(golden-set evals, unedited-approval streaks, incident demotion — the bars live
there, not here). The earned level and its evidence are recorded in the atom's
autonomy field: a promotion is a PR that changes that field with the evidence
linked, verified per the QA strategy's independent-verification rule.
Conventions
- English for all agent-facing files (house language policy).
- Same-change freshness: a change to an atom that leaves its
atom.yaml/prompt.mdstale is an incomplete change. - One capability per file; YAML/frontmatter over prose for anything a machine parses.
- Environment rules (trunk hygiene, read-only prod, sandbox-first writes, promote
gate) are the repo-wide ones:
AGENTS.mdoperating rules +dolibarr-sandbox-writeSKILL.md.