Commit Graph
7 Commits
Author SHA1 Message Date
arcodangeandClaude Opus 5 3b6c93404e feat(erp): FAC011 — la part différée du cycle M3 n'avait jamais été facturée
3 000 USD manquants, découverts en assemblant le dossier client complet. La
cartographie des cycles ne laisse pas de doute : M1, M2 et M4 ont chacun leur
part fixe ET leur part différée ; M3 n'avait que sa part fixe (FAC008, réglée le
20/07).

La facture pro forma PR2607-0001, remise au client en juillet, annonçait
pourtant l'émission de cette part différée pour le 24/08/2026 — soit le jour
même. C'est la date retenue : la numérotation reste chronologique au sens de
l'article 289 du CGI, et l'échéance reste au 23/10/2026, trois mois après la fin
du cycle M3. Le retard est écrit dans la note de la facture plutôt que masqué
par une date d'émission rétroactive, qui elle romprait la chronologie.

LE JUGE A POSÉ LA BONNE QUESTION. Il demandait si le différé de trois mois court
depuis l'émission ou depuis la fin du cycle — les deux lectures ne divergent que
pour M3, dont la facture est tardive : 23/10 contre 24/11. La pro forma tranche
en toutes lettres et dans ses deux versions : « émise le 24/08/2026, à échéance
du 23/10/2026 », et « paiement différé à 3 mois DE LA PRESTATION ». Retenir une
autre date reviendrait à s'écarter d'une annonce déjà faite au client. Preuve en
02b-preuve-echeance.txt.

CE QUI A ÉTÉ RETIRÉ DU CHANGE-SET EN COURS DE ROUTE. Une première version
ajoutait la clause de pénalités L.441-10 à FAC001, FAC002 et FAC003, qui en sont
dépourvues. L'opérateur a précisé le circuit réel : pendant la phase d'audit
(janvier-février 2026), c'est WISE qui a émis les factures, en reprenant les
identifiants internes de Dolibarr. Ces trois-là ONT donc été transmises au
client. Modifier leur note aujourd'hui ferait diverger le registre interne du
document que le client détient — l'inverse du but recherché. Le défaut de
mention est réel mais historique, sur des factures réglées : consigné, pas
réécrit.

Depuis avril 2026 en revanche, KissMetrics vire le montant sur le compte Wise
sans recevoir aucune facture. C'est ce qui a permis de reprendre FAC004, FAC006
et FAC009 plus tôt dans la journée, et c'est le dossier du 24/08 qui porte ces
factures au client pour la première fois.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-24 14:23:58 +02:00
arcodange 58705fda56 feat(erp): cycle M4 KissMetrics, et les deux comptes bancaires ramenés au centime (#96)
Co-authored-by: Gabriel Radureau <[email protected]>
2026-08-24 13:13:32 +02:00
arcodange 480888937f feat(erp): indemnité d'occupation janv→juil 2026 (1 483,23 €) — paiements divers, sans tiers (#89)
Co-authored-by: Gabriel Radureau <[email protected]>
2026-08-13 21:09:10 +02:00
arcodangeandClaude Opus 5 1cba032512 fix(security): production read agent is now actually read-only
Migration applied to production, in the only order that does not break the
promote flow:

1. Created `ai_agent_prod_prod_write` (id=5) with the narrow `prod-write` scope —
   invoices, payments, and document submission (needed by builddoc to regenerate
   a modified invoice's PDF). Verified functionally: reads pass, DELETE on an
   invoice returns 403.
2. Repointed the promote pipeline at that user's key. It no longer borrows the
   read skills' credential; if the key is absent it dies with the provisioning
   command rather than silently falling back.
3. Revoked 12 write/delete rights from `ai_agent` (id=3), the credential every
   read skill holds: create/modify on customer AND supplier invoices,
   thirdparties, contacts, thirdparty payment details, proposals, exports,
   accounting links — and delete on proposals, events, and GED documents.

Verified after: invoices, thirdparties, contacts, products, proposals, supplier
invoices and bank accounts all still read; creating an invoice returns
`403 Forbidden: Insuffisant rights`. The documented posture and the real one
finally agree.

scopes.ts corrected against the live instance: 262 is NOT "créer/modifier les
produits" as the first catalogue guessed but the `voir_tous` ACL extension — a
READ right the skills depend on (without it, list endpoints return empty arrays
instead of 403). Revoking it would have silently blinded every read skill. This
is why the audit reads labels off /user/perms.php rather than trusting ids in
code. The READ_ONLY baseline is now the audited read surface (35 rights), not a
guess.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
2026-08-09 19:33:00 +02:00
arcodangeandClaude Opus 5 a2cafc0d6b feat(harness): gated promote pipeline — rehearse, judge, human gate, apply, judge
The discipline (ADR-0003, the promote flow, the operating rules) was written
down and still depended on whoever was driving choosing to follow it. On
2026-07-25 an agent session wrote five documents into the production ledger
through direct API calls, bypassing the promote flow entirely — a correct result
reached by a path nobody could audit. A rule an operator can skip is a
recommendation.

The five stages are now chained by artefacts on disk. Each refuses to run until
the previous produced its file, and the file says what it needs to hear:
rehearse (sandbox, host-guarded) -> judge --pre -> gate (human) -> apply
(prod) -> judge --post. The gate binds to a manifest digest, so approving a
change-set approves THAT change-set.

An op is defined ONCE, as an API call, and replayed on the sandbox then on
production — because the first design described each write twice (a sandbox
script input and a prod API body) and the pre-gate judge immediately caught them
diverging: the rehearsal was creating a EUR invoice with no due date while
production would have received a USD one at 60 days. Two descriptions of the
same write are two things that can disagree.

Judges are context-free, cross-family per the PRD qa-strategy rule, and
advisory: a BLOCK still lets the operator approve, and the override is recorded
with their name. Blocking authority stays with the human gate and the host
guards — an LLM verdict never silently starts or stops a production write.

Verified end to end against the real 24/08 change-set (M3 deferred, USD 3,000):
- pre-gate judge (Mistral) returned BLOCK twice, correctly — first on the
  sandbox/prod divergence, then on a duplicate left by a repeated rehearsal;
- apply refuses after a rejected gate;
- apply refuses without ARCO_PROD_CONFIRM;
- editing an amount after approval invalidates the gate on digest mismatch.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
2026-07-26 08:06:45 +02:00
arcodangeandClaude Fable 5 ceb4321224 chore(fleet): erp#63 evidence — verifier parity + builder bench transcripts
- runs/2026-07-18/: the 8 sha256-pinned verifier transcripts (4 runtimes ×
  2 tests), blind-judging verdicts (2 independent judges per cell, unanimous),
  the erp#56 builder-bench journal + prompt + caps, and the evidence README
  with the parity table.
- run-verifier.sh: mistral runtime drops the tool-filter flag (--enabled-tools
  with a no-match pattern hangs vibe 2.21.0); plain -p with --max-turns 1.

Verdicts: Mistral (vibe -p, mistral-medium-3.5) and Ornith 35B (hermes MLX)
reach verdict parity with the Claude baseline on both tests → admitted to
verifier duty. Qwen2.5-7B-4bit fails both → the honest small-model floor.
Builder bench: erp#56 completed by the Mistral runtime, 0 code corrections,
261 s, acceptance run clean (0 bank-UNKNOWN) → merged as PR #68.

Closes #63 (with the paired factory qa-strategy PR).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
2026-07-18 19:56:55 +02:00
arcodangeandClaude Fable 5 f2a60817e2 feat(fleet): multi-runtime harness — verifier tests + capped builder shell
The harness layer (builder sessions, cold verifiers, evidence flow) gets a
committable home, per the PRD model-fleet § harness portability and erp#63:

- fleet/harness/verifier/: the two canonical verifier tests (locate-test,
  cold-reader backlog audit) with pinned inputs, verbatim prompts, ground
  truth and pass rules — judged context-free, never self-graded.
- fleet/harness/bin/run-verifier.sh: runs a test against any OpenAI-style
  local endpoint (Ornith/MLX) or vibe -p (Mistral); emits sha256-pinned
  JSON transcripts.
- fleet/harness/bin/vibe-builder.sh: the bounded shell for scoped builders
  and recurring tasks — refuses the trunk (linked-worktree guard), hard
  --max-turns/--max-price caps, full JSON journal per run.
- fleet/README.md layout + AGENTS.md Fleet section updated in the same
  change (same-change freshness rule).

Part of erp#63 (harness portability spike, D2).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
2026-07-18 18:52:53 +02:00