Projets · spécification

Pas de pass sans mesure : AI Architect Spec, suivi dans son code

Une spécification qui se lit bien et décrit un système que personne ne peut construire est pire que pas de spécification. Ce serveur est fait pour attraper ce cas avant qu’il n’atteigne le code : il contrôle que chaque symbole existe, que chaque critère d’acceptation remonte à une exigence, et qu’aucune affirmation de performance ne passe sans mesure — de façon déterministe, sans modèle dans la boucle de contrôle.13 C’est un réducteur plutôt qu’un agent : il émet des actions que votre hôte exécute, et il ne téléphone jamais pour obtenir un verdict.2

Tourneun processus Node sur l’entrée et la sortie standard, exposant 17 outils sous trois profils67
Formeun réducteur sans état : état et résultat en entrée, état suivant et une action en sortie2
Chaîne20 étapes, dont 11 produisent la spécification et 9 sont sur demande derrière une porte humaine9
Contrôles73 fonctions de règle déterministes sans modèle, et une taxonomie à cinq verdicts au-dessus1416
Refuseun rapport où tout passe, et toute affirmation de performance marquée PASS16
Ne garde rienl’état d’exécution est en mémoire seulement, et ne survit pas à un redémarrage11
Pièce 01 · la forme

Un réducteur qui émet des actions, et n’appelle aucun modèle

Le choix d’architecture intéressant est ce que ce serveur refuse de faire. Il ne rédige pas vos sections et ne les juge pas. Il calcule l’état suivant et remet à l’hôte une action à exécuter, ce qui fait tourner la même chaîne contre n’importe quel runtime d’agent plutôt que contre celui d’un seul fournisseur.52 Il n’écrit aucun fichier source et ne pousse aucune branche ; les neuf fichiers de sortie sont écrits par l’hôte.25

Dix-sept outils sont enregistrés, et trois profils décident lesquels un hôte donné voit : tout, tout moins cinq diagnostics internes refusés à l’appel, ou seulement les deux validateurs pour un hôte qui ne veut que le vérificateur.67 L’ordre n’est pas indicatif. Le serveur l’énonce dans le message envoyé à la connexion, et le mode de défaillance est nommé : appeler les outils dans le désordre ne lève pas d’erreur, cela laisse l’exécution dans un mauvais état.8

L’hôte Claude Code, ou tout client MCP stdio il exécute les actions ; le serveur, jamais UN PROCESSUS NODE · STDIO un réducteur sans état step(state, result?) → next_state, action « It runs on your machine, and it never phones home for a verdict. » 17 OUTILS, TROIS PROFILS full · tout agent · 5 outils internes refusés à l’appel verifier · les deux validateurs seulement CE QUE L’HÔTE EXÉCUTE spawn_subagents brouillons de sections et verdicts de juges reviennent par là, jamais d’un Aucun modèle dans la boucle « No tool calls an LLM », donc la même chaîne tourne contre n’importe quel runtime d’agent, pas celui d’un seul SORTANT, LES SIENNES un serveur de mémoire un serveur de graphe de code délai de connexion 10 000 ms SUR DISQUE, OPTIONNEL ~/.prd-gen/evidence.db ~/.prd-gen/reliability.db l’état d’exécution n’est pas là stdio L’ORDRE EST LE PRODUIT « The tools are a strongly ordered pipeline: start_pipeline then submit_action_result until done; calling them out of order does not error, it leaves the run in a wrong state. » La boucle de génération et l’étape de vérification sont séparées, et le serveur le dit à la connexion.
Deux connexions sortent, et ce sont les siennes. Le serveur ouvre des clients stdio vers un serveur de mémoire et un serveur de graphe de code, sous un délai de connexion de dix secondes que le fichier étiquette heuristique provisoire plutôt que mesure.13 Tout le reste reste local : deux fichiers SQLite optionnels sous votre répertoire personnel, et aucun appel réseau pour un verdict.2
Pièce 02 · la chaîne

Vingt étapes, et les neuf qu’il faut demander

Onze étapes produisent la spécification, du premier bandeau au contrôle préalable, à la détection de contexte, à l’analyse d’entrée, à une porte de faisabilité, à la clarification, au budget, à la génération de sections, à celle des tickets, à l’export et à un auto-contrôle.9 Neuf autres portent la même exécution jusqu’à l’implémentation, aux tests, à la revue et à une pull request — et elles sont sur demande, derrière une porte qu’un humain ouvre. Le marqueur terminal n’est pas une étape, distinction qui ne compte que jusqu’au jour où quelqu’un compte mal les étapes.9

Au cœur de la génération de section se trouve la boucle qui fait le travail : rappel depuis la mémoire, brouillon par un agent lancé, validation déterministe, réessai. Le budget de réessai est de trois, et le fichier qui le définit dit ce qu’est ce trois : un ancrage provisoire en attente d’une étude d’ablation, remplaçable à l’exécution par une valeur calibrée.10 C’est une petite honnêteté au grand effet, car elle indique au lecteur quels nombres portent le système et lesquels sont des placeholders.

11 ÉTAPES · OBLIGATOIRES · LA SPÉCIFICATION banner → preflight → context_detection → input_analysis → feasibility_gate → clarification → budget → section_generation → jira_generation → file_export → self_check 9 ÉTAPES · SUR DEMANDE, DERRIÈRE UNE PORTE HUMAINE · L’IMPLÉMENTATION implementation_gate → pre_impl_grounding → implementation → post_impl_verification → testing → review → pr_gate → pr_creation → finalize DANS UNE SECTION rappel depuis la mémoire → brouillon par un agent lancé → validation déterministe → réessai, au plus 3 tentatives MAX_ATTEMPTS = 3 POURQUOI TROIS, HONNÊTEMENT La constante est étiquetée dans son fichier comme un ancrage provisoire, en attente d’une étude d’ablation nommée mais absente de l’arbre. Une valeur calibrée peut être injectée à l’exécution : le 3 est un défaut, pas une loi. CE QUE L’HÔTE ÉCRIT, PAS LE SERVEUR neuf fichiers à l’export : six principaux, trois compagnons « This server only emits spawn_subagents actions — it never edits source files or pushes branches itself. » complete est le marqueur terminal, pas une étape la porte qu’un humain ouvre
C’est l’hôte qui écrit. Neuf fichiers atterrissent à l’export, six principaux et trois compagnons, et le serveur émet une action plutôt que de toucher au disque.25 La même frontière explique pourquoi la chaîne peut être pilotée par un tout autre hôte : rien dans le réducteur ne dépend de qui exécute l’action qu’il rend.5
Pièce 03 · la vérification

Ce qu’elle prouve, et ce qu’elle refuse de feindre

La couche déterministe, ce sont soixante-treize fonctions de règle sur vingt-quatre fichiers, de l’analyse pure sans modèle, ce qui rend son verdict identique sur chaque hôte et en intégration continue.14 Ce qui compte plus que le compte, c’est la phrase que le serveur envoie à son sujet : un rapport qui passe établit la conformité structurelle à ces règles, et dans le même souffle énonce qu’il n’établit ni l’exactitude factuelle, ni la faisabilité, ni la correction sémantique.15 Il dit aussi franchement qu’il ne juge pas la prose.26

Au-dessus siège la couche de jugement, et elle est bâtie autour d’un refus. La taxonomie compte cinq verdicts, une affirmation de performance ne peut pas recevoir un simple pass, et un rapport où tout passe est rejeté d’emblée.16 Un panel unanime sur cinq verdicts ou plus est signalé comme suspect plutôt que cru,17 et la moitié du vote pondéré par la confiance force un échec.18 Les juges sont tenus pour faillibles par conception, ce que le dossier d’assurance énonce comme une limite et non comme une qualité.24

DÉTERMINISTE · AUCUN MODÈLE DANS LA BOUCLE 73 fonctions de règle sur 24 fichiers analyse et expressions régulières pures, donc le même verdict revient sur chaque hôte et en intégration continue Exemple, verbatim : « FR table contains Story Points column — SP belongs only in Implementation Roadmap » JUGÉ · CINQ VERDICTS, DONT UN REFUSÉ PASS · SPEC-COMPLETE · NEEDS-RUNTIME · INCONCLUSIVE · FAIL « A report with 100% PASS verdicts is REJECTED. NFR claims (latency, throughput, storage) MUST NOT receive PASS. » Un panel unanime sur cinq verdicts ou plus est signalé ; la moitié du vote pondéré force un échec. CE QU’UN RAPPORT QUI PASSE ÉTABLIT « structural conformance to those rules » et, dans la même phrase, ce qu’il n’établit pas : « it does not establish factual accuracy, implementation feasibility, or semantic correctness. » CE QUE PERSONNE N’A FAIT, SELON LE DOSSIER D’ASSURANCE aucune vérification formelle · aucune revue adverse aucun second relecteur : il y a un seul mainteneur rien sur les modèles : les verdicts de juges sont tenus pour faillibles Un diagnostic échappe à cette discipline : le contrôle de santé rend toujours un statut littéral « ok », jamais dérivé des trois booléens qu’il calcule. Un appelant qui ne lit que ce champ ne voit pas un composant dégradé ; il doit lire les booléens lui-même.
Un diagnostic ne tient pas la ligne. Le contrôle de santé rend toujours un « ok » littéral, jamais dérivé des trois booléens qu’il calcule, de sorte qu’un appelant qui ne lit que ce champ ne peut pas distinguer un composant dégradé d’un composant sain.19 C’est une petite incohérence dans une base par ailleurs soigneuse sur exactement ce point, et il vaut mieux la connaître avant d’y brancher une alerte.
Pièce 04 · l’état et les nombres

Rien ne survit à un redémarrage, et les nombres disent lesquels sont lesquels

Une exécution vit dans une seule table en mémoire et nulle part ailleurs. Le fichier dit pourquoi — le serveur est par session, donc une table convient à un hôte — et nomme l’échange qui changerait cela.11 La conséquence mérite d’être dite franchement : redémarrer le processus perd toute exécution en cours, et ce qui survit, ce sont les fichiers déjà écrits par l’hôte plus les deux bases optionnelles. Les runs terminaux sont évincés après trente minutes ou au-delà de soixante-quatre ; les runs en cours ne le sont jamais.12

Deux chemins de dérogation existent et tous deux sont explicites. Une porte calibrée peut être retenue hors promotion même quand elle passe son seuil,20 et une comparaison sur partition scellée refuse de tourner sans reconnaissance du sceau, la raison étant portée par le message d’erreur lui-même.21 Côté mesure, un run de calibration est daté et complet — et porte ses deux propres drapeaux disant qu’il diverge au-delà de la tolérance et qu’il devrait être recalculé.22 Chaque plafond de performance autour de lui est étiqueté heuristique provisoire dans le fichier qui le définit.23

ÉTAT D’EXÉCUTION · EN MÉMOIRE SEULEMENT « a single in-memory map is correct for one host » Redémarrer le processus perd toute exécution en cours. Survivent : les fichiers déjà écrits par l’hôte, et les deux bases optionnelles. TTL 30 min · au plus 64 runs · ≈12,8 Mo les runs en cours ne sont jamais évincés DEUX FAÇONS DE PASSER OUTRE UN RÉSULTAT hold_provisional retient une porte calibrée hors promotion même quand elle passe son seuil SEAL_VERIFIED une comparaison sur partition scellée refuse de tourner sans reconnaissance explicite du sceau MESURÉ, ET AUTO-SIGNALÉ Un run de calibration daté : 1 050 tentatives, 500 événements, taux 0,476 avec intervalle à 95 %. Le fichier porte ses deux propres drapeaux : diverges_beyond_tolerance: true recompute_recommended: true Une mesure qui plaide contre elle-même. CHOISI, ET ÉTIQUETÉ COMME TEL Budget de réessai 3, plafond d’itérations 100, plafond d’horloge 500 ms, plafond d’échecs de section 5 : chacun porte les mots « provisional heuristic » ou « provisional anchor » dans le fichier qui le définit. Le dépôt étiquette ses suppositions au lieu de les habiller. ET UN NOMBRE QUE CE DOSSIER N’A PAS PU TRANCHER Le nombre de tests publié est 1506. Le comptage statique des sites d’appel dans l’arbre à cette révision donne 1 061 sur 98 fichiers ; l’écart tient à des cas développés à l’exécution, que seule l’exécution de la suite peut trancher. Le chiffre est rapporté ici comme non vérifié, pas repris.
Une mesure qui plaide contre elle-même est la chose la plus forte de cette page. Le fichier de calibration porte à la fois son résultat et les deux drapeaux disant que ce résultat ne doit pas encore être cru.22 La plupart des projets publient le nombre et laissent tomber les drapeaux.

Un nombre que ce dossier ne reprend pas

Le nombre de tests publié est 1506, et il apparaît à plusieurs endroits visibles. Le comptage statique des sites d’appel dans l’arbre à cette révision donne 1 061 sur 98 fichiers de test. L’écart tient presque certainement à des cas développés à l’exécution, que seule l’exécution de la suite peut trancher, et le dépôt contrôle bien cette affirmation en intégration continue contre un run réel. Elle est rapportée ici comme non vérifiable depuis la seule source plutôt que reprise comme un fait, ce qui est le standard que le projet applique lui-même à une affirmation de latence.3 L’honnêteté du projet sur l’énergie mérite d’être citée pour la même raison : il ne publie aucun chiffre de carbone, parce qu’il ne mesure aucun joule et que le travail évité est un argument de conception, pas une mesure.4

1README.md:20 :20-21 — « Catch a hallucinated spec before it becomes code… deterministically, with no model in the checking loop. »
2README.md:49 :49 — « The server is a stateless reducer… It runs on your machine, and it never phones home for a verdict. »
3README.md:43 :43 — « The verdict taxonomy *refuses* to pass a latency, throughput, fps or storage claim — it returns SPEC-COMPLETE or NEEDS-RUNTIME instead of a confident guess. »
4README.md:57 :57 — « we publish no energy or CO₂ figure: this repository measures no joules, and avoided rework is a design argument rather than a measurement. »
5README.md:368 :368 — « No tool calls an LLM — section drafts and judge verdicts come back via the host's spawn_subagents action so the same pipeline runs against any agent runtime. »
6packages/mcp-server/src/index.ts:56 :56 — dix-sept outils : cinq diagnostics, deux de validation, deux de preuve, huit de chaîne, vérification et budget
7packages/mcp-server/src/tool-profiles.ts:43 :43-57 — les cinq outils internes que le profil agent refuse à l’appel, et les deux que le profil verifier expose
8packages/mcp-server/src/tool-profiles.ts:126 :126-129 — l’ordre d’appel que le serveur envoie à l’hôte à la connexion : budget, démarrage, état, soumission, répétés jusqu’à la fin ; la vérification est une étape séparée
9packages/orchestration/src/types/state/pipeline-step.ts:3 :3-93 — les vingt étapes, avec complete comme marqueur terminal et non comme étape
10packages/orchestration/src/handlers/section-generation-constants.ts:26 :26 — trois tentatives par section, étiquetées en :18-25 comme un ancrage provisoire en attente d’une étude d’ablation, avec une valeur calibrée injectable à l’exécution
11packages/orchestration/src/run-store.ts:4 :4-6 — « The MCP server is per-session, so a single in-memory map is correct for one host. If we ever need multi-host or persistent runs, swap this for a SQLite-backed store. »
12packages/orchestration/src/run-store.ts:68 :68 et :86-94 — trente minutes de durée de vie, au plus soixante-quatre runs, environ 12,8 Mo résidents ; :13 énonce que les runs en cours ne sont jamais évincés
13packages/ecosystem-adapters/src/transport/stdio-mcp-client.ts:36 :36 — un délai de connexion de dix secondes sur les connexions sortantes du serveur, étiqueté heuristique provisoire
14packages/validation/src/hard-output-rules/rules/sp-rules.ts:47 :47 — l’une des soixante-treize fonctions de règle, et la phrase exacte qu’elle émet : « FR table contains Story Points column — SP belongs only in Implementation Roadmap »
15packages/mcp-server/src/tool-profiles.ts:152 :152-155 — ce qu’un rapport qui passe établit, « structural conformance to those rules », et dans la même phrase ce qu’il n’établit pas : « it does not establish factual accuracy, implementation feasibility, or semantic correctness. »
16packages/core/src/domain/verdict.ts:14 :14-15 — « A report with 100% PASS verdicts is REJECTED. NFR claims (latency, throughput, storage) MUST NOT receive PASS. » ; :17-23 énumère les cinq verdicts
17packages/verification/src/orchestrator.ts:375 :375-378 — un panel unanime sur cinq verdicts ou plus est signalé. La même règle est implémentée une seconde fois dans core/src/domain/verdict.ts:38-44, et les deux ne sont pas reliées
18packages/verification/src/consensus.ts:139 :139 — la moitié du vote pondéré par la confiance force un échec
19packages/mcp-server/src/index.ts:199 :193-208 — le contrôle de santé rend un « ok » littéral, jamais dérivé des trois booléens qu’il calcule, de sorte qu’un appelant qui ne lit que ce champ ne voit pas un composant dégradé
20packages/benchmark/src/calibrated-gates-loader.ts:51 :51-58 et :107-109 — une porte calibrée marquée hold_provisional est retenue hors promotion même quand elle passe son seuil
21packages/benchmark/calibration/paired-bootstrap.ts:184 :184-188 — une comparaison sur partition scellée refuse de tourner sans reconnaissance du sceau : « precondition violated — verifyHeldoutPartitionSeal must be called before invoking this function. »
22packages/benchmark/calibration/data/event-rate-K50.json:16 :1-18 — un run de calibration daté, 1 050 tentatives et 500 événements, taux 0,476 avec un intervalle de Clopper-Pearson, portant ses propres drapeaux diverges_beyond_tolerance et recompute_recommended
23packages/benchmark/src/pipeline-kpis.ts:360 :360, :369, :377 — les plafonds d’itérations, d’horloge murale et d’échecs de section, chacun étiqueté « provisional heuristic » dans le fichier qui le définit
24docs/ASSURANCE-CASE.md:118 :118-126 — aucune vérification formelle, aucune revue adverse, aucun second relecteur avec un seul mainteneur, et rien d’établi sur les modèles eux-mêmes
25README.md:561 :561 — « This server only emits spawn_subagents actions — it never edits source files or pushes branches itself. »
26README.md:562 :562 — « It does not validate prose quality. »