docs(prd): agent catalog — task→(prompt+model+orchestrator) matrix + agent-facing file syntax

New agent-catalog.md leaf answering three operator directions:
(1) the document surface agents read is now specified — AGENTS.md
orientation maps, SKILL.md with trigger-carrying descriptions
(Use-when/SKIP-for), atom.yaml registry contracts, thin prompt.md
files (no business rules in prompts — rules live in profile files
and validators), schema'd fiscal.yaml/calendar.yaml with
effective_from dates, [AGENT]/[HUMAN] runbooks, env-var-indirected
.mcp.json; same-change freshness rule extended to the fleet.
(2) hermes's telegram-gateway confirmed as THE human channel when
available (cluster-served cards, email fallback; D1 operator-endorsed).
(3) the categorization to prove: seven agent classes (incl. the
LLM-free deterministic controller) and a T01-T17 assignment matrix
with per-row proof gates and statuses (proven / to-prove / not-built),
re-scored monthly from run journals (fallback rate >20% = wrong cell).
New D8 (fleet code home, leaning erp fleet/).

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-11 15:09:28 +02:00
co-authored by Claude Fable 5
parent 5430e5f3ac
commit 8e4186dbeb
4 changed files with 82 additions and 4 deletions
+2
View File
@@ -114,6 +114,7 @@ flowchart TB
- **[Task inventory](task-inventory.md)** — the enumerated tasks (T01T17 + backlog), each with trigger, mode opératoire, guardrails, current tooling, and target autonomy. *This is the functional requirement set.*
- **[Agent architecture](agent-architecture.md)** — atom contracts, pipeline shape, write safety, security model (least-privilege ephemeral ERP credentials), prompt-injection defenses, runtimes/scheduling, and the human channel.
- **[Model fleet](model-fleet.md)** — the four tiers, routing policy, structured-output enforcement, availability model, degraded modes, and cost envelope.
- **[Agent catalog](agent-catalog.md)** — the concrete assignment task → (prompt + model + orchestrator) with a proof status per row, the seven agent classes, and the syntax of every file agents read (`AGENTS.md`, `SKILL.md`, atom registry, prompts, fiscal profile).
- **[Challenges](challenges.md)** — the twelve identified risks and their mitigation strategies (the technical "second temps" of this PRD).
- **[Compliance](compliance.md)** — the French bookkeeping obligations (inaltérabilité, FEC, piste d'audit fiable, numbering, retention) mapped to fleet mechanisms; the production ledger grammar and its linter; the sandbox-vs-production operating posture.
- **[POC plan](poc-plan.md)** — feasibility proofs as real implementations, ordered, with exit criteria.
@@ -166,6 +167,7 @@ Golden datasets built from real history (mails, invoices, filed declarations), a
| [Task inventory](task-inventory.md) | T01T16 + backlog: trigger, mode opératoire, guardrails, current tooling, target autonomy per task. | 🟡 In design |
| [Agent architecture](agent-architecture.md) | Atom contracts, pipeline shape, write safety, security, injection defenses, runtimes, human channel. | 🟡 In design |
| [Model fleet](model-fleet.md) | Four tiers, routing policy, structured outputs, availability, degraded modes, cost. | 🟡 In design |
| [Agent catalog](agent-catalog.md) | Task → (prompt + model + orchestrator) matrix with proof statuses; agent classes; agent-facing file syntax. | 🟡 In design |
| [Challenges](challenges.md) | Twelve risks with mitigation strategies and residual ownership. | 🟡 In design |
| [Compliance](compliance.md) | Bookkeeping obligations → mechanisms; ledger grammar + linter; sandbox-vs-prod posture; Dolibarr verifications. | 🟡 In design |
| [POC plan](poc-plan.md) | Ordered feasibility proofs with exit criteria and challenge coverage. | 🟡 In design |
@@ -31,7 +31,7 @@ Every atom is registered in a versioned YAML registry (git) with:
| `model_policy` | Preferred tier, fallbacks, escalation rule ([model fleet](model-fleet.md)). |
| `eval_ref` | Golden set + scoring script for this atom. |
The registry is the source of truth for what the fleet may do; an atom absent from the registry does not run.
The registry is the source of truth for what the fleet may do; an atom absent from the registry does not run. File layout, prompt syntax, and the full agent-facing document surface (`AGENTS.md`, `SKILL.md`, `atom.yaml`, `prompt.md`, profile files) are specified in the [agent catalog](agent-catalog.md#the-document-surface-agents-read).
## The pipeline shape
@@ -149,6 +149,8 @@ Inbound documents are adversarial by default — an invoice PDF or a mail body c
## Human channel
The channel is **hermes's telegram-gateway whenever it is available** (operator direction, 2026-07): the gateway runs on the cluster, so digests and approval cards are served 24/7 without depending on the laptop being awake — the M4-side hermes runtime consumes the same gateway for its own jobs. When the gateway is down, the fleet keeps queueing, the digest falls back to plain email, and the [degraded-modes table](model-fleet.md#degraded-modes) applies.
- **One daily digest** (Telegram, morning): items awaiting approval, quarantined items, aging unresolved work, heartbeat summary, upcoming deadlines (D-30/D-7/D-1). An empty day still sends "all green" — silence must be distinguishable from failure.
- **Approval cards**: one decision per card (approve / edit / reject-with-reason); rejection reasons are first-class data feeding golden sets.
- **Escape hatch**: every automated lane has a documented manual runbook fallback (the fleet augments the operator; it never becomes the only way to run the company).
@@ -170,12 +172,13 @@ To be settled by POC evidence, each closing with a short ADR:
| # | Decision | Options (leaning) |
| --- | --- | --- |
| D1 | Work queue | telegram-gateway's planned Postgres durable queue (**leaning** — already roadmapped, transactional, one less system) vs. flat files in git vs. Redis |
| D1 | Work queue | telegram-gateway's planned Postgres durable queue (**leaning, operator-endorsed 2026-07** — already roadmapped, transactional, one less system) vs. flat files in git vs. Redis |
| D2 | Orchestration runtime | Claude Agent SDK headless for cluster-triggered jobs + **hermes** for M4-side lanes (**leaning** — hermes already runs skills + cron there) vs. bespoke TS orchestrator (erp `test/` Deno codebase) vs. pure CronJobs + scripts |
| D3 | KM monthly invoice firing | enable Dolibarr template auto-fire (`frequency>0`) vs. agent-fired via sandbox+promote (**leaning** — keeps the gate + mention audit in-line) |
| D4 | PA — e-invoicing platform (*plateforme agréée*, ex-PDP) | **Leaning: Qonto** (operator direction, 2026-07 — the capital-deposit bank, DGFiP-registered PA, e-invoicing included in every plan, and the fleet's richest existing API integration); POC-6 validates reception + API pull before the ADR — **must close before 2026-09-01** ([C12](challenges.md#c12--e-invoicing-reform-unknowns)) |
| D5 | OCR provider for scanned docs | Mistral OCR (EU cloud) vs. local vision model on M4 vs. Tesseract baseline |
| D6 | Pi inference serving | llama.cpp server vs. Ollama on arm64, resource limits, node pinning ([C5](challenges.md#c5--slm-capability-ceiling-on-pi-hardware)) |
| D7 | Cluster↔vault access | git clone/pull of the SecondBrain remote (**leaning** — the Gitea remote exists, offline-friendly, reviewable) vs. tunneled Obsidian REST API (M4-only today) vs. keeping vault access M4-exclusive |
| D8 | Fleet code home | erp repo `fleet/` next to the skills (**leaning** — the atoms are ERP-domain today; revisit into a dedicated repo when a second domain joins) vs. dedicated fleet repo vs. scattered per existing repo |
D4D6 close with their mapped POCs ([POC-6](poc-plan.md#poc-6--e-invoicing-readiness-spike), [POC-5](poc-plan.md#poc-5--model-routing-bench), [POC-2](poc-plan.md#poc-2--pi-sentinel)); D1D2 are settled while building phase 3's standing fleet (the queue and scheduler *are* its skeleton); D3 lands with phase 4's money loops; D7 closes when the first cluster-side atom needs vault context (phase 3 at the earliest).
D4D6 close with their mapped POCs ([POC-6](poc-plan.md#poc-6--e-invoicing-readiness-spike), [POC-5](poc-plan.md#poc-5--model-routing-bench), [POC-2](poc-plan.md#poc-2--pi-sentinel)); D1D2 are settled while building phase 3's standing fleet (the queue and scheduler *are* its skeleton); D3 lands with phase 4's money loops; D7 closes when the first cluster-side atom needs vault context (phase 3 at the earliest); D8 rides POC-1 — the first atoms need their home on day one.
+73
View File
@@ -0,0 +1,73 @@
[vibe](../../README.md) > [PRD](../README.md) > [AI back-office](README.md) > **Agent catalog**
# Agent catalog — who does what, with which brain, under which conductor
> **Status:** In design (assignments are hypotheses until proven)
> **Last Updated:** 2026-07-11
> **Up:** [AI back-office hub](README.md)
> **Related:** [Task inventory](task-inventory.md) · [Model fleet](model-fleet.md) · [Agent architecture](agent-architecture.md) · [QA strategy](qa-strategy.md)
An "agent" here is the concrete triple **prompt + model + orchestrator** bound to a task. This page names the classes, assigns every task, states how each assignment gets *proven* (éprouvé), and fixes the syntax of the document surface agents read to do the work. Honesty first: several agents are deliberately **LLM-free** — a cron-driven script with validators is the best "agent" for deterministic work, and the prompt column says so.
## Agent classes
Seven prompt skeletons; every atom's prompt extends exactly one. Skeletons live with the fleet code (`fleet/classes/<class>.md` — see [D8](agent-architecture.md#open-decisions)).
| Class | Prompt skeleton (the invariant part) | Model policy | Orchestrator | Serves |
| --- | --- | --- | --- | --- |
| **Sentinel** | closed-set classification, schema-constrained output, refuse below threshold | Pi SLM (GBNF) → M4/Mistral fallback | k3s CronJob → queue | T01, deadline detection |
| **Extractor** | document → JSON Schema, zero tools, dual independent run, never "fix" arithmetic | M4 local ∥ Mistral (agreement), Claude escalation | queue workers (cluster leg + hermes leg) | T02, T16 |
| **ERP scribe** | manifest assembly over the write skills, [ledger grammar](compliance.md#the-ledger-grammar-production) honored, predicted-delta before card | Claude (Agent SDK headless) | gateway handler → gate → promote | T03, T04-create, T05, T08-ambiguous |
| **Deterministic controller** | — (no prompt: scripts + validators + linter) | — | k3s CronJobs | T07, T08-matched, T11, T13, T14 |
| **Analyst-writer** | narrative strictly over verified figures; cite from ERP/journals only; no advice | Claude, or M4 for local prose | crons → digest | T06 drafts, T09, T10 narrative, T15 exceptions |
| **Researcher** | sourced-claims-only (official domains), effective dates mandatory, output = diff proposal | Claude + web | quarterly / event-driven | T12 |
| **Knowledge archivist** | vault conventions: append-only, idempotent frontmatter, PARA filing hints | per vault doctrine (Ornith/Mistral/Claude) | hermes cron + per-run hooks | T17 |
## Assignment matrix
Status legend: ✅ proven in operation · 🧪 built or designed, **to prove** (à éprouver) · ⬜ not built. Where a task splits (deterministic core + LLM edge), both appear.
| Task | Class | Prompt / code | Model | Orchestrator | Proof gate | Status |
| --- | --- | --- | --- | --- | --- | --- |
| [T01](task-inventory.md#t01--mailbox-triage--routing) | Sentinel | `fleet/atoms/mail-classify/` | Pi Qwen3-class 1.74B, GBNF | k3s CronJob (30 min) | [POC-2](poc-plan.md#poc-2--pi-sentinel) ≥ 95 % on 200 labeled mails | 🧪 |
| [T02](task-inventory.md#t02--supplier-invoice-extraction) | Extractor ×2 | `fleet/atoms/invoice-extract/` | M4 structured ∥ Mistral JSON; Claude escalation | queue workers | [POC-1](poc-plan.md#poc-1--supplier-invoice-end-to-end)+[POC-5](poc-plan.md#poc-5--model-routing-bench) ≥ 98 % critical fields | 🧪 |
| [T03](task-inventory.md#t03--supplier-invoice-recording) | ERP scribe | `dolibarr-sandbox-write` + `fleet/atoms/invoice-record/` | Claude headless | gateway → gate → promote | POC-1 10-invoice exit gate | 🧪 (write skills ✅, loop ⬜) |
| [T04](task-inventory.md#t04--thirdparty-creation--completeness) | Controller + scribe | `dolibarr-thirdparty-completeness` (audit, no LLM); creation rides T03 | — / Claude | monthly CronJob / with T03 | audit: live now; creation: POC-1 | ✅ audit · 🧪 creation |
| [T05](task-inventory.md#t05--client-invoice-issuance) | ERP scribe + auditor | `dolibarr-recurring-templates` + `dolibarr-invoice-audit` + fire atom | Claude | monthly cron (1st) + card | first agent-fired invoice == manual twin ([D3](agent-architecture.md#open-decisions)) | ⬜ |
| [T06](task-inventory.md#t06--receivables-watch--dunning) | Analyst-writer | `fleet/atoms/dunning-draft/` (+ T17 retrieval for tone/history) | Claude | weekly cron → card | N consecutive drafts approved unedited | ⬜ |
| [T07](task-inventory.md#t07--bank-reconciliation) | Controller | `arcodange-bank-reco` (`bank-match.sh`) | **— no LLM** | weekly CronJob | fixture-proven; standing zero-delta invariant | ✅ skill · 🧪 standing |
| [T08](task-inventory.md#t08--payment-recording) | Controller + scribe | `payment-record.sh` manifests from matched movements | — matched; Claude ambiguous | queue → gate → promote | [POC-3](poc-plan.md#poc-3--reconciliation--payment-recording) one clean month | 🧪 |
| [T09](task-inventory.md#t09--cash-position--runway) | Analyst-writer | balances workflow + `fleet/atoms/cash-report/` | figures deterministic; M4 prose | monthly CronJob + hermes leg | figures == live bank APIs, every run | 🧪 |
| [T10](task-inventory.md#t10--tva-preparation) | Controller + analyst | `dolibarr-tva-summary` + narrative atom | — figures; Claude narrative | calendar-triggered (T11) | [POC-4](poc-plan.md#poc-4--tva-dry-run) €-parity vs filed | 🧪 (skills ✅) |
| [T11](task-inventory.md#t11--compliance-calendar--reminders) | Controller | calendar file + `fleet/atoms/deadline-remind/` | **— no LLM** (parsing upstream in T01/T12) | daily k3s cron → gateway | synthetic-calendar firing test | ⬜ |
| [T12](task-inventory.md#t12--regulatory-watch) | Researcher | `fleet/atoms/reg-watch/` | Claude + web | quarterly + event | every claim sourced + PR review | 🧪 (method proven authoring this PRD) |
| [T13](task-inventory.md#t13--erp-snapshot--drift-detection) | Controller | `dolibarr-data-snapshot` | **— no LLM** | daily CronJob + around writes | drift alert fires on seeded change | ✅ skill · 🧪 cron+alert |
| [T14](task-inventory.md#t14--backup--restore-verification) | Controller | `ops/backup` + freshness watchdog | **— no LLM** | daily CronJob (live) + monthly drill | restore drill green monthly | ✅ backup/restore · 🧪 watchdog+drill cadence |
| [T15](task-inventory.md#t15--monthly-coherence-audit) | Composer + analyst | skill composition + exception narrative | — checks; Claude narrative | monthly CronJob → digest | first pack matches a manual cohort review | ⬜ |
| [T16](task-inventory.md#t16--document-filing--retention) | Extractor | `fleet/atoms/doc-file/` | M4 local | per-document queue | document golden set | ⬜ |
| [T17](task-inventory.md#t17--knowledge-capture--retrieval-second-brain) | Knowledge archivist | `sb.py` + hermes `second-brain` skill + capture atom | vault doctrine (Ornith/Mistral/Claude) | hermes cron (live) + per-run hooks | deposits idempotent over re-runs; retrieval dated | ✅ vault side · 🧪 fleet side |
## Proving protocol — how a 🧪 becomes a ✅
The matrix is a set of falsifiable hypotheses, not documentation:
1. **Tier choice** is proven by [POC-5](poc-plan.md#poc-5--model-routing-bench)'s bench (accuracy × latency × cost on the golden set) and recorded into the atom's `model_policy` — if the Pi can't hold T01's bar, the matrix cell changes, not the bar.
2. **Loop viability** is proven by the owning POC's exit criterion; autonomy then follows the [promotion gates](qa-strategy.md#autonomy-promotion-gates).
3. **In operation, the matrix is re-scored from run journals**: every escalation and tier fallback is journaled, so the monthly ops review reads which tier *actually* served each task. A cell whose fallback rate exceeds ~20 % is wrong and gets reassigned.
4. A ✅ is revocable: incident → demotion → the cell reverts to 🧪 with the same path back.
## The document surface agents read
What an agent knows about this system, it learns from files. Their syntax is part of the architecture:
| File | Read by | Lives at | Syntax rules |
| --- | --- | --- | --- |
| `AGENTS.md` | every agent, session start | each repo root | Orientation map: what the repo is, operating rules, pointers — the factory `AGENTS.md` is the canon (diagram + tables + hard rules). The **erp repo's must gain a Fleet section**: environment rules, ledger-grammar pointer, registry location. Keep it short; link, don't inline. |
| `SKILL.md` | Claude Code (auto-discovery), hermes (snapshot) | `.claude/skills/<name>/`, `~/.hermes/skills/<domain>/<name>/` | YAML frontmatter `name` + `description`; the description **carries the triggers**: capability summary + explicit *"Use when…"* and *"SKIP for…"* clauses (the proven `dolibarr-*` pattern). Body = numbered workflows; executables under `scripts/`; secrets in mode-600 gitignored `.env`. |
| `atom.yaml` (registry) | orchestrators, humans, CI | `fleet/atoms/<atom>/` | The [contract fields](agent-architecture.md#atom-contract): I/O JSON Schemas, invariants, `side_effect_class`, idempotency key, earned autonomy + eval evidence link, `model_policy`. Folder name = atom name = registry name — the `<app>` join-key discipline applied to atoms. |
| `prompt.md` | the model, at runtime | next to `atom.yaml` | ≤ ~40 lines: role (1 line), task, output = *reference to the schema* (never a prose re-description), refusal/escalation clause. **No business rules in prompts** — rules live in the fiscal profile and validators (code); prompts stay thin, versioned, diff-reviewable. Extends one class skeleton (`fleet/classes/`). |
| `fiscal.yaml` + `calendar.yaml` | fiscal atoms, T11 | `fleet/profile/` | Schema'd YAML; **every rule carries an `effective_from`** (and `effective_until` when known); mutations arrive as PRs (T12 proposes, human merges). |
| Runbooks | humans + agents | factory `vibe/runbooks/` | House rule: every step marked `[AGENT]` (safe, delegable) or `[HUMAN]` (prod-mutating, approval-bound) — the same markers as the [task inventory](task-inventory.md). |
| `.mcp.json` | agents needing MCP tools (vault, ERP) | repo/vault roots | Servers declared with **env-var indirection for keys** (`${OBSIDIAN_API_KEY}` pattern) — never literals. |
Cross-cutting rules: **English** for all agent-facing files (house language policy); **write descriptions for retrieval** — agents discover skills by their description text, so triggers belong there, not in the body; **same-change freshness** — a change to an atom that leaves its `SKILL.md`/`atom.yaml`/`prompt.md` stale is an incomplete change (the guidebook-maintenance rule extended to the fleet); **one capability per file**; frontmatter over prose for anything a machine parses.
+1 -1
View File
@@ -7,7 +7,7 @@
> **Up:** [AI back-office hub](README.md)
> **Related:** [Agent architecture](agent-architecture.md) · [Model fleet](model-fleet.md) · [QA strategy](qa-strategy.md)
Every recurring admin/accounting task, with its mode opératoire. Steps carry the runbook markers: **[AGENT]** = safe for an agent at the stated autonomy, **[HUMAN]** = stays human (approval, signature, or money). "Today" names the existing tooling (skills live in the [erp repo](https://gitea.arcodange.lab/arcodange-org/erp) under `.claude/skills/`, wrapped by `bin/arcodange`). Autonomy levels are defined in the [hub](README.md#the-autonomy-ladder).
Every recurring admin/accounting task, with its mode opératoire. Steps carry the runbook markers: **[AGENT]** = safe for an agent at the stated autonomy, **[HUMAN]** = stays human (approval, signature, or money). "Today" names the existing tooling (skills live in the [erp repo](https://gitea.arcodange.lab/arcodange-org/erp) under `.claude/skills/`, wrapped by `bin/arcodange`). Autonomy levels are defined in the [hub](README.md#the-autonomy-ladder). The concrete agent bound to each task — prompt, model, orchestrator, and its proof status — is assigned in the [agent catalog](agent-catalog.md#assignment-matrix).
## Overview