agent-doc-system 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/EVALS.md CHANGED
@@ -387,3 +387,127 @@ Each was fixed in the engine, not by relaxing a threshold.
387
387
  weight a long constraint file against a short ref.
388
388
  - Scenarios touch one or two files. A change spanning twenty files is not
389
389
  measured.
390
+
391
+ ## Executable agent-task campaigns
392
+
393
+ `node evals/agent/run.mjs --list` lists a bootstrap corpus of 30 pinned fixtures
394
+ (10 coding-task families, three fixture variants per family). This is a synthetic
395
+ pilot corpus, not a benchmark of 30 independent production incidents. Development
396
+ and holdout families are disjoint. Fixture content hashes live in
397
+ `evals/agent/tasks/pins.json`; changes require deliberately updating those pins.
398
+ Each attempt creates and commits a fresh temporary repository. Validation runs
399
+ after the driver exits, outside the task repository, against executable behavior
400
+ and input-preservation requirements. Neither the validator nor its cases are
401
+ included in the model prompt. A driver saying it succeeded does not pass a task.
402
+
403
+ Campaigns are opt-in. No model request is made by the regular deterministic
404
+ routing evaluation or test suite. Example configuration:
405
+
406
+ ```json
407
+ {
408
+ "driver": ["node", "/absolute/path/to/evals/agent/codex-driver.mjs"],
409
+ "model": "your-configured-model",
410
+ "modelVersion": "record-the-model-version-and-driver-version",
411
+ "repeats": 3,
412
+ "split": "development",
413
+ "tasks": ["money-1"],
414
+ "budget": {
415
+ "timeoutMs": 120000,
416
+ "maxTokens": 16000,
417
+ "maxToolCalls": 40,
418
+ "maxCostUsd": null,
419
+ "maxOutputBytes": 1048576
420
+ },
421
+ "conditions": {
422
+ "baseline": {"contextCommands": []},
423
+ "reference": {"contextCommands": [
424
+ ["node", "{agentdoc}", "compile"],
425
+ ["node", "{agentdoc}", "query", "service/src/logic.mjs"]
426
+ ]},
427
+ "candidate": {"contextCommands": [
428
+ ["node", "{agentdoc}", "prepare", "--request", "request.json"]
429
+ ]}
430
+ }
431
+ }
432
+ ```
433
+
434
+ Run `node evals/agent/run.mjs --config campaign.json --out report.json`.
435
+ The runner records the declared model/version, driver file hashes, fixture pins,
436
+ conditions, repeats, validation results, usage, runtime and infrastructure errors.
437
+ It does not resolve a provider's model alias to an immutable model build; the
438
+ chosen driver must pin and report its actual deployment for that guarantee.
439
+ Model prompts, editing tools and execution permissions should otherwise remain
440
+ identical across conditions. Context-command outputs are included in the model
441
+ prompt and must be counted in input usage. The built-in Codex adapter uses the
442
+ user's existing configured provider and model without switching either.
443
+
444
+ ### Driver protocol and limits
445
+
446
+ The runner starts an argv array without a shell. The driver receives one JSON
447
+ line on stdin with protocol `agentdoc.eval.driver/v1`, the temporary workspace,
448
+ public task, condition, context and budgets. It writes JSON lines on stdout:
449
+
450
+ ```json
451
+ {"type":"usage","usage":{"inputTokens":100,"outputTokens":20,"toolCalls":2,"costUsd":0.01}}
452
+ {"type":"result","completed":true}
453
+ ```
454
+
455
+ Usage events are cumulative and nondecreasing. Optional `trace` events can carry
456
+ diagnostics. Missing usage, malformed events, a failed driver or failed context
457
+ command is an infrastructure error. Wrong behavior is a task failure. Both stay
458
+ in the report and denominator; neither is silently dropped. Reports with unknown
459
+ cost retain `null` cost rather than treating it as zero.
460
+
461
+ Wall time and output limits terminate the process group on POSIX, including its
462
+ children. Token, tool and dollar limits terminate when usage events report a
463
+ limit exceeded. They cannot prevent an unreported request from being charged:
464
+ a driver must reserve/enforce provider request budgets before making calls for
465
+ a hard spend guarantee. The Codex adapter receives token usage at turn boundaries
466
+ and does not expose dollar cost, so use `maxCostUsd: null` with that adapter.
467
+ For a driver reporting dollars, `maxCampaignCostUsd` additionally reserves each
468
+ attempt's maximum before launch and stops when costs are unmeasured.
469
+
470
+ Temporary repositories isolate task files and cleanup; they are not an OS
471
+ security sandbox. Driver execution permissions and common tool restrictions
472
+ belong to the driver/runtime. The optional Codex adapter requests workspace-write
473
+ execution. Untrusted third-party task code requires an external container or
474
+ sandbox, including for validation.
475
+
476
+ ### Candidate selection
477
+
478
+ `selectCandidate(reference, candidate)` requires paired holdout outcomes and
479
+ identical fixture hashes. It rejects infrastructure errors and declared critical
480
+ errors. It groups variants and repetitions by family and uses a conservative
481
+ 95% bounded-variable interval on the paired success-rate difference. A tiny pilot
482
+ cannot establish a 2-point noninferiority margin, even with identical outcomes.
483
+ Adoption additionally requires measured cost per success to improve by at least
484
+ 20%; unknown cost cannot support adoption. All attempts, including failures,
485
+ contribute to total cost. This selector evaluates supplied candidates; it never
486
+ changes truth, edits thresholds, publishes code or starts a paid campaign itself.
487
+ Use development tasks to propose variants, holdout tasks to select them, and a
488
+ separate final test set before making production performance claims.
489
+
490
+ `node evals/agent/optimize.mjs optimization.json report.json` runs a bounded offline
491
+ search. Its configuration contains `campaign` (the runner configuration),
492
+ `reference`, named `variants` (context-command settings), `maxCandidates` (1–20),
493
+ and `maxTotalCostUsd`. The nested campaign must have a measured per-attempt dollar
494
+ cap. An optional `proposer` argv receives public development tasks and the allowed
495
+ variant definitions, and returns `{"variants":["variant-name"]}`. Only declared
496
+ variants can be proposed. The optimizer compares them on development tasks, then
497
+ runs the selected candidate and reference on holdout tasks and applies the
498
+ conservative selection gate. Unknown costs stop the search; the total dollar
499
+ limit is shared across the two stages. Proposal-provider costs are outside the
500
+ runner's usage stream and must be budgeted by that provider driver separately.
501
+ The optimizer never edits the implementation, adjusts thresholds or publishes a
502
+ candidate. The bootstrap corpus is too small to establish a 2-point margin;
503
+ normal pilot output is therefore `inconclusive`, not an adoption claim.
504
+
505
+ A real-model functional smoke is recorded in
506
+ [`evals/agent/results/smoke-gpt-6.1-sol.json`](../evals/agent/results/smoke-gpt-6.1-sol.json).
507
+ On one synthetic development task with one repetition, the independent validator
508
+ accepted the reference and candidate patches and rejected the baseline patch's
509
+ per-unit decimal rounding. This verifies the runner/model/validator integration;
510
+ it establishes neither a general success-rate difference nor a cost improvement.
511
+ The configured model was `gpt-6.1-sol` through local Codex CLI 0.167.2. Dollar cost
512
+ was unavailable, and the run used the development worktree rather than an
513
+ immutable released revision. Larger pinned holdout campaigns remain necessary.
@@ -0,0 +1,310 @@
1
+ # AgentDoc — plan d’implémentation pour un outil destiné aux agents IA
2
+
3
+ ## 1. Résultat visé
4
+
5
+ Transformer AgentDoc en moteur de contexte opérationnel : un agent décrit une tâche, reçoit les connaissances nécessaires pour agir, approfondit les points utiles et actualise son contexte après les modifications.
6
+
7
+ L’objectif principal est de réduire le **coût total d’une tâche correctement terminée**, sous contrainte de fiabilité. Le coût inclut les appels au modèle, les outils, les vérifications, les reprises et les échecs. La longueur d’une réponse et la vitesse d’une requête sont des mesures intermédiaires.
8
+
9
+ Public cible : agents de développement et systèmes qui pilotent leurs sessions. Le protocole, les erreurs et les sorties sont conçus pour leur utilisation directe. Les documents humains servent à maintenir le projet ; ils ne constituent pas l’interface de travail obligatoire de l’agent.
10
+
11
+ Ce document décrit la cible et ses critères. La version 1.5.0 implémente le protocole, le cache conservateur, les API de session, les expériences de symboles et le runner d’évaluation. Le suivi ci-dessous distingue les fonctionnalités disponibles des résultats empiriques restant à établir.
12
+
13
+ ## 2. Point de départ et invariants
14
+
15
+ État constaté lors de l’audit de la version locale 1.4.0 :
16
+
17
+ - Les 30 scénarios déterministes retrouvent les 101 faits attendus. Ils n’évaluent pas la résolution d’une tâche par un modèle.
18
+ - Les 422 tests passent avec la signature Git désactivée pour l’exécution. Les dépôts temporaires héritent sinon de la configuration de signature de la machine.
19
+ - Le rendu Markdown par défaut ne transmet pas toutes les garanties de l’objet interne. Reproductions : une vérification affichée sur quatre sans avertissement sur la fixture Rust ; un conflit affiché sur quatre sans avertissement sur Koda, avec des budgets explicites de un.
20
+ - `query` et `impact` recompilent chacun le dépôt. Des lectures, parsings et constructions d’index sont répétés.
21
+ - Les budgets portent sur des nombres d’éléments ; certaines surfaces, dont les engagements de revue globaux, restent non bornées.
22
+
23
+ Préserver pendant toute la migration :
24
+
25
+ 1. La distinction entre faits déclarés, dérivés et observés, avec leur provenance.
26
+ 2. Les conflits et les inconnues explicites. Une absence de résultat n’est pas une preuve d’absence.
27
+ 3. La reproductibilité du graphe et la validation stricte des schémas.
28
+ 4. La détection des entrées modifiées, ajoutées, supprimées ou nouvellement résolues.
29
+ 5. Les règles de secret, de chemin, de propriété et de validité des observations.
30
+ 6. La distinction entre une vérification recommandée, exécutée, réussie et encore valide.
31
+
32
+ La compilation complète reste la référence de correction. Aucun résultat de performance ne justifie une perte silencieuse d’information critique.
33
+
34
+ ## 3. Décisions d’architecture
35
+
36
+ ### Interface principale
37
+
38
+ Ajouter trois opérations, d’abord exposées en CLI avec JSON sur stdin/stdout et diagnostics sur stderr :
39
+
40
+ | Opération | Entrée | Résultat |
41
+ |---|---|---|
42
+ | `prepare` | tâche, chemins ou diff, intention, budget | paquet de travail sur un instantané explicite |
43
+ | `expand` | référence de paquet, éléments ou continuation | connaissances supplémentaires du même instantané |
44
+ | `refresh` | paquet précédent et état courant du dépôt | changements de connaissances et obligations invalidées |
45
+
46
+ Le CLI appelle une interface JavaScript commune. Un transport MCP pourra l’exposer ensuite sans reproduire sa logique. Aucun serveur permanent n’est requis pour la première livraison.
47
+
48
+ `prepare` rassemble résolution, impact, contraintes, preuves et sélection des vérifications sur un seul instantané. Les intentions initiales sont `implement`, `change-contract`, `debug-runtime` et `review`. Elles modifient les priorités de présentation ; elles ne permettent pas, à elles seules, d’exclure une obligation.
49
+
50
+ ### Paquet de travail
51
+
52
+ Créer un schéma de paquet indépendant du schéma du graphe, versionné `agentdoc.dev/context/v1` et fermé aux champs inconnus. Il comprend :
53
+
54
+ - `snapshot` : empreinte des entrées, versions des extracteurs et schémas ; le commit seul ne suffit pas pour un arbre modifié ;
55
+ - `task` et `scope` : demande normalisée, sujets résolus, portée effective ;
56
+ - `coverage` : capacités d’analyse disponibles, chemins non couverts, résultats partiels et ambiguïtés ;
57
+ - `requirements`, `conflicts`, `facts` : connaissances utiles et leur statut d’autorité ;
58
+ - `evidence` : références adressables, empreintes et localisateurs ;
59
+ - `checks` : vérifications sélectionnées, justification, portée et contexte d’exécution ;
60
+ - `budget`, `omitted`, `continuation` : consommation, omissions explicites et moyen de poursuivre.
61
+
62
+ Séparer l’incomplétude due au budget, une analyse non prise en charge et un conflit non résolu. Un paquet complet signifie complet dans la portée et les capacités annoncées, jamais connaissance exhaustive du dépôt.
63
+
64
+ ### Frontières internes
65
+
66
+ | Module cible | Responsabilité | Base existante |
67
+ |---|---|---|
68
+ | `core/context/` | préparation, sélection, sérialisation et approfondissement | `query.mjs`, `impact.mjs`, `dependents.mjs` |
69
+ | `core/snapshot.mjs` | accès cohérent aux entrées et identité de l’instantané | `fsx.mjs`, `compile.mjs` |
70
+ | `core/cache/` | résultats intermédiaires et invalidation | suivi des lectures, probes et listings |
71
+ | `core/session/` | références livrées, versions et deltas | nouveau |
72
+ | `evals/agent/` | exécution des tâches et comparaison des variantes | nouveau, distinct du routage déterministe |
73
+
74
+ Introduire ces modules avec leurs premiers usages. Éviter une extraction massive préalable de fonctions ou une seconde implémentation des règles d’autorité.
75
+
76
+ ## 4. Lots d’implémentation
77
+
78
+ ### Lot 0 — rendre la mesure reproductible
79
+
80
+ **Dépendance :** aucune.
81
+
82
+ **Travaux**
83
+
84
+ - Désactiver la signature des commits dans les dépôts de test et les utilitaires qui les créent, sans changer la configuration Git de l’utilisateur. Conserver des cas explicites pour les règles Git que le produit doit réellement respecter.
85
+ - Recenser les autres créations de dépôts qui contournent `tests/helpers.mjs` et appliquer la même isolation.
86
+ - Ajouter une instrumentation opt-in : durée par étape, octets lus, lectures physiques, parsings, reconstructions d’index, taille sérialisée et mémoire du processus.
87
+ - Émettre cette télémétrie hors du graphe et hors du contexte envoyé au modèle. Les horodatages et mesures de machine ne doivent pas casser le déterminisme.
88
+ - Enregistrer une référence sur les fixtures et les dépôts publics déjà épinglés, avec matériel, versions, nombre de répétitions et état froid/chaud.
89
+
90
+ **Fichiers :** `tests/helpers.mjs`, créateurs de fixtures, `core/fsx.mjs`, `core/compile.mjs`, `scripts/bench/run.mjs`, `docs/BENCHMARK.md`.
91
+
92
+ **Acceptation :** suite indépendante de la signature locale ; instrumentation sans effet sur les sorties fonctionnelles ; comparaison répétée de `query`, `impact` et séquences de requêtes. Les temps historiques de la version 1.2.0 restent identifiés comme tels.
93
+
94
+ ### Lot 1 — rendre les sorties fidèles au moteur
95
+
96
+ **Dépendance :** lot 0.
97
+
98
+ **Travaux**
99
+
100
+ - Définir les informations que chaque format doit restituer : contraintes, conflits pertinents, statut d’autorité, obligations de vérification et indications d’incomplétude.
101
+ - Corriger le Markdown : afficher les troncatures de toutes les sections plafonnées, les gates applicables, les faits utiles des observations et les relations nécessaires pour comprendre l’impact.
102
+ - Préserver la distinction entre conflit résolu et non résolu ; ne pas présenter toutes les décisions comme des contradictions encore ouvertes.
103
+ - Tester les sorties réellement sérialisées et les invocations CLI. L’évaluation de l’objet interne reste utile mais ne suffit plus.
104
+ - Ajouter des scénarios où une information critique se situe au-delà des plafonds par défaut.
105
+
106
+ **Fichiers :** `core/query.mjs`, `core/impact.mjs`, `bin/agentdoc.mjs`, `evals/harness.mjs`, `tests/modes.test.mjs`, `tests/evals.test.mjs`, `docs/QUERY.md`.
107
+
108
+ **Acceptation :** les reproductions Rust et Koda ne perdent plus silencieusement d’obligations ; les gates ne disparaissent pas au rendu ; toutes les omissions sont détectables par l’agent. La brièveté n’est pas un critère de refus de ce correctif.
109
+
110
+ **Livraison :** correctif autonome, compatible avec les commandes actuelles.
111
+
112
+ ### Lot 2 — installer l’évaluation avec de vrais agents
113
+
114
+ **Dépendance :** lot 0 ; mesurer la version avant et après le lot 1.
115
+
116
+ **Travaux**
117
+
118
+ - Créer un runner reproductible avec adaptateurs de modèles, limites d’appels, de temps et de coût, environnement isolé et collecte des sorties d’outils.
119
+ - Constituer un premier corpus de 30 tâches exécutables : correctifs, modifications de contrat, migrations, conflits de documentation, diagnostic à partir d’observations enregistrées et changements transverses.
120
+ - Utiliser des commits épinglés, des validateurs indépendants du graphe et des tests non exposés à l’agent. Une tâche doit pouvoir être évaluée sans compter les libellés choisis par AgentDoc.
121
+ - Séparer tâches de développement et tâches réservées à la validation, en séparant aussi les dépôts ou familles de tâches lorsque nécessaire pour limiter les fuites.
122
+ - Comparer recherche/lecture seules, AgentDoc de référence et variante candidate. Garder les mêmes outils de modification et de test, le même modèle et les mêmes budgets ; compter les instructions supplémentaires d’AgentDoc dans le coût.
123
+ - Commencer par un modèle pour stabiliser le runner, puis confirmer les décisions majeures sur au moins deux modèles épinglés. Exécuter au moins trois répétitions par tâche et configuration lors du pilote ; augmenter l’échantillon si la décision reste incertaine.
124
+ - Conserver les 30 scénarios déterministes actuels comme tests de régression séparés, avec leurs seuils inchangés.
125
+
126
+ **Fichiers :** nouveaux `evals/agent/`, `evals/agent/tasks/`, configuration des campagnes, `docs/EVALS.md`, script npm dédié.
127
+
128
+ **Acceptation :** les trois variantes peuvent résoudre la même tâche depuis le même état initial ; un patch erroné échoue même si son contexte semble correct ; les erreurs d’infrastructure sont distinguées des échecs de l’agent et restent comptabilisées dans les rapports d’exécution.
129
+
130
+ **Livraison :** runner et référence figée. Les campagnes payantes sont explicites, avec plafond configuré ; elles ne s’ajoutent pas automatiquement à chaque CI.
131
+
132
+ ### Lot 3 — livrer `prepare` et `expand`
133
+
134
+ **Dépendance :** lots 1 et 2.
135
+
136
+ **Travaux**
137
+
138
+ - Créer le schéma du paquet et le validateur des requêtes, puis brancher les deux commandes dans la table commune des commandes et de l’aide.
139
+ - Réutiliser un même graphe et un même index pour tous les chemins de la requête. Dédupliquer les obligations par identité et version.
140
+ - Calculer un périmètre pertinent pour les engagements de revue ; conserver les engagements globaux explicitement applicables, pas tous ceux des composants sans rapport.
141
+ - Fournir des extraits ciblés de contraintes et contrats, avec chemin, localisateur et empreinte. Une référence vers un document ne remplace pas automatiquement son contenu nécessaire à la décision.
142
+ - Donner aux vérifications un contexte d’exécution explicite. Préserver les commandes shell comme telles ; ne pas convertir naïvement une chaîne shell en liste d’arguments. Marquer une commande non exécutable automatiquement si son contexte ne peut pas être établi.
143
+ - Implémenter un classement déterministe : obligations applicables d’abord, preuves utiles ensuite, détails complémentaires enfin. L’ordre reste stable à entrée identique.
144
+ - Ajouter un adaptateur de comptage de tokens avec tokenizer et version épinglés. Le mode à budget strict refuse un tokenizer indisponible ; une estimation éventuelle est explicitement distincte.
145
+ - Compter le paquet final, y compris les métadonnées, erreurs et continuations. Recompter après sérialisation. Si même l’enveloppe minimale ne tient pas, refuser le budget demandé.
146
+ - Si les obligations dépassent le budget, retourner un état partiel et une continuation. Ne jamais présenter une sélection de checks comme la liste complète.
147
+ - Lier les continuations à l’instantané, à la requête et à la version du protocole. Un instantané disparu ou périmé appelle un nouveau `prepare` ; aucune continuation ne mélange deux versions du dépôt.
148
+
149
+ **Fichiers :** nouveaux `schemas/context.schema.json`, `core/context/`, modifications de `bin/commands.mjs`, `bin/agentdoc.mjs`, `core/query.mjs`, `core/impact.mjs`, `core/indexes.mjs`.
150
+
151
+ **Acceptation :** une invocation prépare un paquet multi-chemins ; tous les faits sont justifiables ; budgets stricts respectés sur la sortie réelle ; approfondissements sans perte ni duplication incohérente ; aucun programme du dépôt n’est exécuté par la préparation.
152
+
153
+ **Livraison :** commandes additives expérimentales ; `query` et `impact` restent utilisables avec leurs contrats existants.
154
+
155
+ ### Lot 4 — accélérer les lectures et partager les index
156
+
157
+ **Dépendance :** lot 3.
158
+
159
+ **Travaux**
160
+
161
+ - Introduire un instantané de lecture par requête avec cache des octets et des parsings. Inclure les options et versions du parseur dans les clés de réutilisation.
162
+ - Réutiliser les index d’entités, chemins, contrats, relations, assertions et dépendants au sein de cet instantané.
163
+ - Détecter une modification concurrente pendant la capture : vérifier la cohérence des entrées et listings, réessayer de façon bornée, puis signaler un dépôt instable. Ne pas publier un graphe composé de versions incompatibles.
164
+ - Éviter de relire un graphe disque si l’opération travaille explicitement sur l’instantané courant. Préserver la politique de fraîcheur existante de `query` pendant la migration.
165
+ - Borner la mémoire ; éviction et cache désactivé restent des modes corrects.
166
+
167
+ **Fichiers :** `core/snapshot.mjs`, `core/fsx.mjs`, `core/compile.mjs`, `core/context/`, `core/dependents.mjs`.
168
+
169
+ **Acceptation :** mêmes résultats avec et sans cache ; tests de mutation pendant une capture ; réduction mesurée des lectures physiques et reconstructions d’index ; absence de régression matérielle de mémoire sur les corpus choisis.
170
+
171
+ ### Lot 5 — compilation incrémentale persistante
172
+
173
+ **Dépendance :** lot 4.
174
+
175
+ **Travaux**
176
+
177
+ - Enregistrer les dépendances entre entrées, résultats d’extraction et faits produits. Commencer par les parsings et extracteurs dont les dépendances sont précisément connues ; recalculer les autres intégralement.
178
+ - Identifier les résultats par le contenu des entrées, les options et les versions du compilateur, des schémas et adaptateurs.
179
+ - Conserver les dépendances négatives : existence testée mais absente, listes de répertoires, règles d’exclusion et chemins candidats de résolution.
180
+ - Invalider sur modification, ajout, suppression, renommage, changement de résolution, de configuration, d’exclusion ou d’extracteur. Reprendre les règles existantes pour les chemins et liens symboliques.
181
+ - Garder l’évaluation temporelle des observations hors d’un cache supposé immuable : une observation peut expirer sans changement de fichier.
182
+ - Stocker le cache sous `.agentdoc/`, séparé du graphe publié. Écritures atomiques, concurrence contrôlée et récupération par recalcul après corruption ou interruption.
183
+ - Exécuter un mode comparatif qui calcule aussi la compilation complète. Activer progressivement le chemin incrémental après comparaison des résultats.
184
+ - Garder une compilation complète en CI comme référence indépendante du cache.
185
+
186
+ **Fichiers :** `core/cache/`, `core/compile.mjs`, `core/fsx.mjs`, adaptateurs progressivement instrumentés, tests de mutations et de déterminisme.
187
+
188
+ **Acceptation :** identité des graphes, diagnostics et provenances entre les deux chemins sur les mutations du corpus ; cache absent, corrompu ou périmé sans faux résultat frais ; bénéfice mesuré sur les petites modifications et requêtes répétées.
189
+
190
+ **Livraison :** activation optionnelle, puis par défaut après validation. Revenir au calcul complet ne change pas le protocole.
191
+
192
+ ### Lot 6 — mémoire de session et `refresh`
193
+
194
+ **Dépendance :** lots 3 et 4 ; le lot 5 accélère ce lot sans être nécessaire à sa correction.
195
+
196
+ **Travaux**
197
+
198
+ - Donner aux faits une identité logique stable et une version dépendant de leur contenu et de leurs preuves.
199
+ - Enregistrer ce qui a été livré et explicitement retenu par le système qui pilote l’agent. « Livré » ne signifie pas « compris » ni « encore présent dans le contexte ».
200
+ - Retourner les faits ajoutés, modifiés et rétractés, ainsi que les obligations de vérification invalidées.
201
+ - Répéter les obligations critiques actives dans une enveloppe compacte ; ne pas dépendre d’un souvenir implicite du modèle.
202
+ - Prévoir acquittement, réinitialisation et récupération d’un paquet complet après perte de session, compaction ou changement de modèle.
203
+ - Ajouter un contrat d’import des résultats de vérification : commande, contexte, instantané, statut, preuve de sortie. Un résultat ne reste valide que si les entrées pertinentes et les conditions d’exécution le permettent.
204
+ - Intégrer le runner d’agents pour remplacer le contexte actif et demander les preuves à la demande, au lieu d’empiler indéfiniment les réponses.
205
+ - Isoler les sessions par dépôt, tâche et client ; borner leur stockage et proposer leur suppression.
206
+
207
+ **Fichiers :** `core/session/`, `core/context/`, schéma de delta, commande `refresh`, intégration `evals/agent/`.
208
+
209
+ **Acceptation :** appliquer les deltas reconstruit le même état qu’un nouveau paquet complet ; suppressions et rétractions transmises ; aucune vérification périmée réutilisée ; reprise correcte après oubli de contexte. Mesurer les tokens cumulés de session, pas seulement la taille du delta.
210
+
211
+ ### Lot 7 — expérimenter la représentation et l’analyse sémantique
212
+
213
+ **Dépendance :** lots 2, 3 et 6.
214
+
215
+ **Travaux**
216
+
217
+ - Formaliser un vocabulaire de faits et obligations (`requires`, `forbids`, `depends_on`, `affects`, `verified_by`) avec portée, preuve, conditions et statut d’autorité.
218
+ - Réutiliser les assertions et exigences normatives existantes. Une interprétation proposée par l’IA reste une hypothèse tant que les règles d’autorité ne permettent pas sa promotion ; ne pas confondre format structuré et vérité démontrée.
219
+ - Comparer JSON compact, lignes typées et format tabulaire sur le même paquet sémantique. Inclure dans le coût l’apprentissage du format, les descriptions d’outils, les appels supplémentaires et les erreurs.
220
+ - Choisir une première famille de tâches pour les symboles, par exemple les modifications d’API TypeScript. Extraire les symboles et usages nécessaires à la demande, avec une solution de repli au niveau du composant pour les usages dynamiques ou ambigus.
221
+ - Garder les symboles dans un index auxiliaire versionné au début. Les cinq types d’entités normatifs du graphe ne sont pas étendus implicitement.
222
+ - Ne réduire une obligation de vérification que lorsqu’une preuve permet cette exclusion. Une classification d’intention ou un score de pertinence ne suffit pas.
223
+
224
+ **Acceptation :** le format ou l’analyse supplémentaire améliore le résultat sur les tâches réservées et sur les modèles retenus. Sinon, conserver le protocole précédent et retirer l’expérience du chemin par défaut.
225
+
226
+ **Livraison :** chaque expérience est indépendante et réversible ; aucun langage propriétaire n’est un prérequis des lots antérieurs.
227
+
228
+ ### Lot 8 — optimisation continue contrôlée
229
+
230
+ **Dépendance :** lot 2 ; chaque variante ne dépend que des fonctionnalités qu’elle modifie.
231
+
232
+ **Travaux**
233
+
234
+ - Autoriser un agent d’optimisation à proposer des changements bornés : classement, format, descriptions d’outils, stratégies d’approfondissement.
235
+ - Limiter chaque campagne en coût, temps et nombre de variantes ; journaliser configuration et version des candidats.
236
+ - Utiliser les tâches de développement pour la recherche et un jeu de validation séparé pour sélectionner les candidats. Réserver un test final aux décisions de livraison ; le renouveler quand des consultations répétées risquent de contaminer l’évaluation.
237
+ - Conserver les variantes qui améliorent le compromis réussite/coût/latence. Ne pas modifier automatiquement les obligations, la vérité attendue ou les seuils pour faire accepter une variante.
238
+ - Livrer les changements retenus par le processus normal du dépôt, avec mécanisme de retour à la version précédente. Ne pas auto-modifier le moteur en cours de session.
239
+
240
+ **Acceptation :** une variante nuisible à la fiabilité est rejetée malgré sa brièveté ; les décisions sont reproductibles depuis les artefacts de campagne ; aucune dépendance à un service de modèle n’est requise pour le fonctionnement déterministe courant.
241
+
242
+ ## 5. Mesures et critères de décision
243
+
244
+ | Mesure | Définition et usage |
245
+ |---|---|
246
+ | Réussite vérifiée | tâche terminée selon tests et contraintes indépendants d’AgentDoc |
247
+ | Coût par réussite | coût de tous les essais, échecs inclus, divisé par le nombre de réussites ; indéfini si aucune réussite |
248
+ | Erreurs critiques | obligation manquée, conflit masqué, preuve invalide, mauvais périmètre ou contexte d’exécution |
249
+ | Tokens de session | entrées, sorties et raisonnement facturé si disponible ; tokens mis en cache distingués |
250
+ | Latence | médiane et p95 des opérations et des tâches ; démarrage à froid séparé des appels répétés |
251
+ | Charge locale | lectures, parsings, CPU, mémoire maximale et stockage des caches |
252
+ | Coût des checks | temps réel des vérifications sélectionnées ; leur nombre seul ne mesure pas l’économie |
253
+
254
+ Avant chaque campagne comparative, figer corpus, versions, paramètres, règles de coût, plafond d’essai et critères statistiques. Utiliser une comparaison appariée par tâche et rendre l’incertitude visible. Le pilote de 30 tâches ne suffit pas automatiquement à conclure sur de faibles écarts.
255
+
256
+ Objectif initial proposé pour la refonte combinée : **réduire d’au moins 20 % le coût par réussite** sur la validation réservée, sans régression de fiabilité établie. Ce seuil est un objectif d’adoption à figer avant les essais, pas un gain déjà observé.
257
+
258
+ Pour la non-infériorité du taux de réussite, préenregistrer une marge maximale de 2 points et exiger que la borne inférieure de l’intervalle de confiance à 95 % de l’écart reste au-dessus de −2 points. Une nouvelle erreur critique reproductible bloque l’adoption indépendamment de cette marge. Si l’échantillon ne permet pas de conclure, élargir la campagne ou conserver la version de référence ; ne pas conclure à l’équivalence par défaut.
259
+
260
+ Les correctifs de fidélité restent livrables même s’ils augmentent les tokens. Les optimisations locales peuvent être intégrées si leur bénéfice est mesuré et leur correction démontrée, sans prétendre qu’elles satisfont seules l’objectif global de 20 %.
261
+
262
+ ## 6. Compatibilité, migration et livraison
263
+
264
+ - Conserver les commandes historiques pendant l’introduction du protocole. Modifier les instructions du skill seulement après validation de son nouveau parcours.
265
+ - Versionner séparément graphe, protocole et cache. Un format de cache incompatible peut être abandonné et recalculé ; un graphe incompatible doit être détecté et migré explicitement.
266
+ - Toute évolution des champs normatifs du graphe passe par la politique de version de `docs/SPEC.md`. Les schémas fermés existants interdisent les ajouts implicites.
267
+ - Pour `prepare`, annoncer explicitement l’utilisation de l’arbre de travail courant. Ne pas modifier silencieusement le contrat de fraîcheur du `query` historique.
268
+ - Garder le cœur sans dépendance à une API de modèle. Isoler les dépendances de tokenizer et d’évaluation ; documenter leur version et leur disponibilité. Une nouvelle dépendance de production doit apporter un bénéfice vérifié et apparaître dans le test d’installation du paquet.
269
+ - Tester l’installation depuis `npm pack`, la présence des nouveaux schémas et l’absence de dépendances accidentelles aux fichiers du dépôt de développement.
270
+ - Mettre à jour `docs/SPEC.md`, `docs/QUERY.md`, `docs/VERIFICATION.md`, `docs/EVALS.md`, `docs/CI.md`, le skill, l’aide CLI et le changelog avec chaque fonctionnalité livrée. Ne pas annoncer une cible comme une capacité déjà présente.
271
+ - Garder les tests déterministes sur la matrice Node 22/24/26. Les campagnes de modèles et de performance utilisent des environnements dédiés, épinglés, sans bloquer chaque changement documentaire.
272
+
273
+ ## 7. Ordre d’exécution et suivi
274
+
275
+ | Livraison | Lots | Condition de passage |
276
+ |---|---|---|
277
+ | A — fiabilité et référence | 0, 1, 2 | sorties fidèles, tests isolés, runner et référence disponibles |
278
+ | B — interface de travail | 3, 4 | paquet multi-chemins, budget vérifié, approfondissement et instantané cohérent |
279
+ | C — réutilisation | 5, 6 | équivalence incrémentale et deltas corrects, bénéfices mesurés |
280
+ | D — spécialisation | 7, 8 | amélioration confirmée sur validation réservée, retour arrière disponible |
281
+
282
+ Les lots 1 et 2 peuvent avancer indépendamment après le lot 0. Les lots 5 et 6 peuvent avancer indépendamment après le lot 4. Cet ordre décrit les dépendances ; il n’impose pas d’exécution multi-agent.
283
+
284
+ - [ ] Lot 0 — mesure et tests reproductibles.
285
+ - [ ] Lot 1 — fidélité de toutes les sorties.
286
+ - [ ] Lot 2 — évaluation de tâches par agents.
287
+ - [ ] Lot 3 — protocole `prepare` / `expand` et budget réel.
288
+ - [ ] Lot 4 — instantané, lectures et index partagés.
289
+ - [ ] Lot 5 — compilation incrémentale persistante.
290
+ - [ ] Lot 6 — mémoire de session et `refresh`.
291
+ - [ ] Lot 7 — formats et analyse sémantique expérimentaux.
292
+ - [ ] Lot 8 — boucle d’optimisation mesurée.
293
+
294
+ **Premier changement à implémenter :** isoler la signature Git des fixtures, ajouter les reproductions des omissions Markdown comme tests de régression, puis corriger le rendu. Cette livraison apporte un résultat concret avant d’engager la refonte.
295
+
296
+ ## 8. État de la livraison 1.5.0
297
+
298
+ | Lot | Résultat livré | Limite empirique ou fonctionnelle explicite |
299
+ |---|---|---|
300
+ | 0 | Fixtures sans signature héritée, télémétrie et benchmark local reproductible | Mesures locales sur six corpus ; pas de nouvelle campagne des dépôts publics |
301
+ | 1 | Sorties Markdown fidèles, omissions et gates visibles, tests CLI | Les budgets historiques restent des plafonds par section |
302
+ | 2 | Runner, 30 tâches synthétiques épinglées, driver Codex et smoke réel comparatif | Une tâche, un modèle, une répétition ne prouvent pas un gain général |
303
+ | 3 | prepare / expand / refresh, schéma fermé, budget exact, preuves et continuations | Le cwd des checks reste explicitement inconnu quand il n’est pas démontré ; mêmes obligations conservatrices pour chaque intention |
304
+ | 4 | Capture cohérente des octets et index partagé dans la préparation | Pas de serveur permanent ni cache des index entre processus |
305
+ | 5 | Cache persistant de compilation complète et parsing JSON par contenu | Pas de reconstruction granulaire de tous les extracteurs ; retour au compilateur complet si nécessaire |
306
+ | 6 | Deltas, rétractions, état logique complet, preuves d’exécution et nettoyage JS | L’intégration au contexte actif d’un harness externe reste à la charge de son appelant |
307
+ | 7 | Faits typés et candidats TypeScript à la demande via API JS | Analyse lexicale partielle ; aucune exclusion de checks ni adoption d’un nouveau format sans mesure |
308
+ | 8 | Optimiseur borné, proposeur de variantes déclarées, campagnes dev/holdout et sélection | Aucun gain de 20 % établi, aucune variante promue par le seul smoke ; validation finale indépendante exigée pour toute revendication |
309
+
310
+ Les cases de la section 7 représentent les acceptations complètes du plan, y compris les campagnes empiriques étendues. La release fournit les mécanismes permettant ces campagnes sans présenter leurs objectifs comme des résultats déjà obtenus. Les nouveaux protocoles sont additifs ; les expériences non validées ne remplacent pas le chemin historique.
package/docs/QUERY.md CHANGED
@@ -90,12 +90,16 @@ reading the whole specification.
90
90
  **Critical context is separated from the rest.** `authority.conflicts`,
91
91
  `authority.observations` and `constraints.constraints` are the things that cause
92
92
  the most damage when missed, and the markdown rendering puts them under explicit
93
- headings: `CONFLICTS (do not assume one is true)`, `RUNTIME OBSERVATIONS`,
94
- `CONSTRAINTS`.
93
+ headings: `CONFLICTS (do not assume one is true)` for unresolved conflicts,
94
+ `RESOLVED CONFLICTS` for recorded elections, `RUNTIME OBSERVATIONS`, and
95
+ `CONSTRAINTS`. Runtime observations include the actual keys, values and semantics,
96
+ not only their capture metadata.
95
97
 
96
98
  **Both sides of a conflict are printed.** A conflicted assertion shows its
97
99
  evidence class, its confidence and its value. The contradicted value is never
98
- withheld.
100
+ withheld within a displayed conflict. Resolved conflicts also show their election,
101
+ including the elected assertion and review condition; they are not presented as
102
+ open decisions. A budget that omits entire conflicts is explicitly reported.
99
103
 
100
104
  **A contract subject carries the provider's and consumers' checks.** Changing an
101
105
  endpoint is proved by running their suites, so `verification` for an API subject
@@ -174,6 +178,20 @@ complete arrays under `constraints.docs`, `constraints.constraints` and
174
178
  `constraints.runbooks`; these markdown-only caps do not shorten the JSON arrays
175
179
  or `entity.spec.context`.
176
180
 
181
+ The default Markdown format also displays typed relation directions and evidence
182
+ classes, API providers/consumers and contracts, resource users, journey peers,
183
+ assertions, contract operations and evidence pointers. Scoped checks retain their
184
+ IDs and configuration paths. Repository gates are a separate required list;
185
+ a scoped verification budget never removes them.
186
+
187
+ Every capped JSON section that was shortened is repeated in an `INCOMPLETE
188
+ CONTEXT` block, including nested authority sections, with its displayed and total
189
+ counts. For example, `verification [truncated: 1 of 4]` means three required
190
+ verification recommendations are still omitted. Request the same query with a
191
+ larger `--budget verification=...` before treating the list as complete. Truncated
192
+ relations and evidence are likewise identified rather than silently disappearing
193
+ from the default response.
194
+
177
195
  `--md` (the default) produces a compact block suitable for a prompt or a human:
178
196
 
179
197
  ```
@@ -184,7 +202,7 @@ Triggers governed endpoints on a platform schedule and owns no business logic.
184
202
  - CONSTRAINTS: workers/koda-cron/CONSTRAINTS.md
185
203
  - verify:
186
204
  - [unit] vitest run
187
- - CONFLICTS (do not assume one is true):
205
+ - RESOLVED CONFLICTS (use the recorded election; re-check its review condition):
188
206
  - schedule.cron [contradiction/resolved]
189
207
  - DERIVED/deterministic: "0 3 * * *"
190
208
  - OBSERVED_RUNTIME/direct: "0 * * * *,3 0 * * *"
@@ -267,6 +285,6 @@ Ask for `--md` and give the output to the agent as-is. Two rules keep it
267
285
  honest:
268
286
 
269
287
  1. Do not summarise a conflict away. If the context contains a `CONFLICTS`
270
- block, the agent must be told about it.
288
+ block, the agent must be told about it, including its status and any recorded election.
271
289
  2. If the context contains `UNRESOLVED` or a conflict with `basis: none`, the
272
290
  correct agent behaviour is to say so and stop, not to choose a side.
@@ -21,7 +21,7 @@ jobs:
21
21
  with: { node-version: '24' }
22
22
  - name: Install the agentdoc CLI
23
23
  # Unpinned tracks main. For CI reproducibility pin a tag or commit:
24
- # github:lbframe/agent-doc-system#v1.4.0
24
+ # github:lbframe/agent-doc-system#v1.5.1
25
25
  # A compiler upgrade intentionally invalidates committed graphs.
26
26
  run: npm install -g github:lbframe/agent-doc-system
27
27
  - name: Validate and compile
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ // Optional local Codex driver. Uses the user's configured model/provider unchanged.
3
+ import readline from 'node:readline';
4
+ import {spawn} from 'node:child_process';
5
+ const lines=readline.createInterface({input:process.stdin});
6
+ let request;
7
+ for await(const line of lines){request=JSON.parse(line);break;}
8
+ if(!request||request.protocol!=='agentdoc.eval.driver/v1')throw new Error('invalid evaluation request');
9
+ const prompt=[request.instructions,request.task.prompt,'Task paths: '+request.task.paths.join(', '),
10
+ 'Budget: '+JSON.stringify(request.budget),'Context supplied by '+request.condition+':',...request.context,
11
+ 'Work only in this temporary task repository. Finish after implementing and checking the fix.'].join('\n\n');
12
+ const child=spawn('codex',['exec','--json','--ephemeral','--skip-git-repo-check','-s','workspace-write','-C',request.workspace,'-'],{stdio:['pipe','pipe','pipe']});
13
+ const emit=x=>process.stdout.write(JSON.stringify(x)+'\n');
14
+ let inputTokens=0,outputTokens=0,cachedInputTokens=0,toolCalls=0,failed=false;
15
+ const usage=()=>({inputTokens,outputTokens,cachedInputTokens,toolCalls,costUsd:null});
16
+ const stop=()=>{failed=true;child.kill('SIGKILL');};
17
+ child.stdin.end(prompt);
18
+ child.stderr.on('data',chunk=>process.stderr.write(chunk));
19
+ const exited=new Promise(resolve=>{child.on('error',error=>{console.error(error.message);resolve(1);});child.on('close',resolve);});
20
+ const reader=readline.createInterface({input:child.stdout});
21
+ for await(const line of reader){
22
+ let event;try{event=JSON.parse(line);}catch{continue;}
23
+ if(event.type==='item.completed'&&['command_execution','mcp_tool_call','web_search'].includes(event.item?.type))toolCalls++;
24
+ if(event.type==='turn.completed'){
25
+ inputTokens+=event.usage?.input_tokens||0;outputTokens+=event.usage?.output_tokens||0;cachedInputTokens+=event.usage?.cached_input_tokens||0;
26
+ emit({type:'usage',usage:usage()});
27
+ }
28
+ if(event.type==='turn.failed'||event.type==='error'){failed=true;emit({type:'trace',message:event.error?.message||event.message||event.type});}
29
+ if(inputTokens+outputTokens>request.budget.maxTokens||toolCalls>request.budget.maxToolCalls)stop();
30
+ }
31
+ const code=await exited;
32
+ emit({type:'usage',usage:usage()});emit({type:'result',completed:code===0&&!failed});process.exitCode=code===0&&!failed?0:1;
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ // Bounded offline selection of agent-proposed context variants. Never edits core code.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {campaign,runProcess,selectCandidate} from './run.mjs';
7
+ import {tasks,publicTask} from './tasks/corpus.mjs';
8
+
9
+ export async function optimize(config){
10
+ if(!Number.isInteger(config.maxCandidates)||config.maxCandidates<1||config.maxCandidates>20)throw new Error('maxCandidates must be an integer in [1,20]');
11
+ const variants=config.variants;
12
+ if(!variants||!Object.keys(variants).length||Object.keys(variants).length>config.maxCandidates)throw new Error('declare at most maxCandidates context variants');
13
+ if(Object.keys(variants).some(id=>id==='reference'||!(/^[a-z][a-z0-9-]*$/).test(id)))throw new Error('variant names must be unique non-reference identifiers');
14
+ if(!config.reference)throw new Error('reference condition required');
15
+ let ids=Object.keys(variants);
16
+ if(config.proposer){
17
+ const r=await runProcess(config.proposer,{cwd:process.cwd(),timeoutMs:config.proposerTimeoutMs||30000,maxOutputBytes:65536,input:JSON.stringify({protocol:'agentdoc.eval.proposal/v1',developmentTasks:tasks.filter(t=>t.split==='development').map(publicTask),allowedVariants:variants,maxCandidates:config.maxCandidates})+'\n'});
18
+ if(r.code!==0||r.reason||r.error)throw new Error('proposal driver failed');
19
+ const proposed=JSON.parse(r.stdout);
20
+ if(!Array.isArray(proposed.variants)||!proposed.variants.length||proposed.variants.length>config.maxCandidates||new Set(proposed.variants).size!==proposed.variants.length||proposed.variants.some(id=>!Object.hasOwn(variants,id)))throw new Error('proposal contains an undeclared variant');
21
+ ids=proposed.variants;
22
+ }
23
+ const base=config.campaign;
24
+ if(!base||!Number.isFinite(config.maxTotalCostUsd)||config.maxTotalCostUsd<=0||!Number.isFinite(base.budget?.maxCostUsd)||base.budget.maxCostUsd<=0)throw new Error('optimization requires measured per-attempt and total dollar caps');
25
+ let spent=0;
26
+ const run=async(split,conditions)=>{
27
+ const remaining=config.maxTotalCostUsd-spent;
28
+ if(remaining<base.budget.maxCostUsd)throw new Error('optimization campaign budget exhausted');
29
+ const report=await campaign({...base,tasks:undefined,split,conditions,maxCampaignCostUsd:remaining});
30
+ if(report.summary.totalCostUsd===null)throw new Error('optimization stopped: unmeasured cost');
31
+ spent+=report.summary.totalCostUsd;
32
+ return report;
33
+ };
34
+ const conditions={reference:config.reference,...Object.fromEntries(ids.map(id=>[id,variants[id]]))};
35
+ const development=await run('development',conditions);
36
+ if(development.stopped||development.summary.infrastructureErrors)return {status:'inconclusive',reason:development.stopped||'infrastructure-errors',spent,development};
37
+ const ranked=ids.sort((a,b)=>{
38
+ const x=development.conditions[a],y=development.conditions[b];
39
+ return y.successRate-x.successRate||(x.costPerSuccess??Infinity)-(y.costPerSuccess??Infinity)||a.localeCompare(b);
40
+ });
41
+ const candidate=ranked[0];
42
+ const validation=await run('holdout',{reference:config.reference,[candidate]:variants[candidate]});
43
+ const decision=validation.stopped?{adopt:false,reason:validation.stopped}:selectCandidate(validation.attempts.filter(x=>x.condition==='reference'),validation.attempts.filter(x=>x.condition===candidate),config.criteria);
44
+ return {schemaVersion:'agentdoc.eval.optimization/v1',status:decision.adopt?'candidate-selected':'inconclusive',candidate,decision,spent,development,validation,publication:'not-performed',finalTest:'required-on-independent-tasks-before-production-performance-claims'};
45
+ }
46
+ if(process.argv[1]&&fs.existsSync(process.argv[1])&&fs.realpathSync(process.argv[1])===fs.realpathSync(fileURLToPath(import.meta.url))){
47
+ try{const config=JSON.parse(fs.readFileSync(process.argv[2],'utf8'));const report=await optimize(config);const text=JSON.stringify(report,null,2)+'\n';if(process.argv[3])fs.writeFileSync(process.argv[3],text);else process.stdout.write(text);if(report.status!=='candidate-selected')process.exitCode=1;}catch(e){console.error(e.message);process.exitCode=2;}
48
+ }