Les décisions de flotte
Une seconde série d'ADR, à côté des 192 d'ADVE-project. C'est un risque assumé : les séries parallèles meurent, l'une prend le pas et l'autre se fossilise. Deux règles la maintiennent en vie.
Règle 1 — elle ne gouverne qu'entre composants
Une décision interne à un composant reste chez lui. ADVE-project garde sa série ADR-NNNN sous docs/governance/adr/, et rien ici ne la remplace.
SHK- n'arbitre que ce qu'aucun dépôt ne peut trancher seul : le partage d'une source entre deux composants, le rang d'un composant dans le programme, la frontière entre ce qui est référencé et ce qui est versé.
Le préfixe existe pour qu'aucune collision de numéro ne soit possible : SHK-0001 et ADR-0001 ne se confondent pas, même cités hors contexte.
Règle 2 — l'audit la lit
Toute ADR Accepted qui énonce une règle vérifiable déclare un signal d'audit, et ce signal existe dans galahad/engine/skills/audit-fleet.json.
## Signal d'audit id-du-signal — ce qui est attendu, et ce qui constitue une violation.
Une ADR sans signal est une ADR que personne ne vérifie : l'audit la signale comme telle. Une décision qu'aucun contrôle ne défend n'a pas d'effet, et vaut mieux écrite nulle part qu'écrite et ignorée — c'est ainsi qu'on obtient un document qui affirme le contraire de la réalité.
Une ADR peut légitimement n'avoir aucun signal — elle porte alors Signal d'audit : aucun, et dit pourquoi. C'est une déclaration, pas un oubli.
Forme
docs/adr/SHK-NNNN-slug.md, numéros attribués dans l'ordre, jamais réutilisés.
# SHK-NNNN — Titre
- Statut : Proposed | Accepted | Superseded by SHK-NNNN
- Date : AAAA-MM-JJ
- Composants : ceux que la décision engage
## Contexte ce qui a été constaté, avec de quoi le recouper ## Décision ce qui est tranché ## Signal d'audit comment on vérifie que ça tient ## Portée ce que la décision ne dit pas
SHK-0001 — Le programme, et ses deux étages
- Statut : Accepted
- Date : 2026-09-14
- Composants : tous les dépôts portant le topic
shinkiro
Contexte
Trois noms circulaient pour trois choses différentes, et le même mot désignait tantôt l'ensemble, tantôt une de ses pièces. « Galahad 360 » nommait le programme entier ; galahad nommait aussi une équipe d'agents auto-hébergée, qui n'en est qu'un composant. Une confusion de ce genre ne reste pas verbale longtemps : elle finit en dépôt créé deux fois.
Elle l'a déjà fait. ADVE-project/docs/governance/adr/0100-argos-hunter-backend-port.md, daté du 14 juin 2026, ouvre son contexte par « Argos n'était pas déployable — 0 % de backend » et réimplémente le harvester à neuf.
Le même jour, dans Argos-studio, il y avait 184 fichiers. Une API v1 complète — agencies, awards, brands, assets, markets, references, sectors, years, ingest/dossier — un schema.prisma, une migration 20260512171730_init et un seed. Le tout posé en un seul commit le 15 mai, et intouché depuis. C'est vérifiable en une commande :
gh api 'repos/xtincell/Argos-studio/commits?until=2026-06-14T23:59:59Z&per_page=1'
Un mois d'écart. Un backend reconstruit parce que rien, nulle part, ne disait que l'autre existait. Le coût n'est pas le temps perdu : c'est qu'il y a désormais deux modèles de dossier de campagne à tenir d'accord.
Deuxième constat, de nature différente : les composants n'ont pas la même masse. Le relevé déterministe donne 101 855 Ko d'arbre pour ADVE-project contre 233 Ko pour galahad — 437 pour 1. Les traiter pareil, c'est soit imposer à un outil de trois fichiers la cérémonie d'un dépôt de 3 314, soit charger le programme de cent mégaoctets à chaque clonage.
Décision
Shinkiro est le programme, et la suite. Il ne contient aucun code de produit : il porte le manifeste, l'ordre de construction, les décisions de flotte, l'audit, et la présentation qu'il génère de lui-même. galahad est un produit du portefeuille — une équipe d'IA qui fait tourner l'agence en autonomie depuis un serveur dédié — et non un simple composant de livraison. ADVE est la méthode, et son dépôt canonique est ADVE-project. Ces trois noms ne sont pas interchangeables, et le README l'énonce avant toute autre chose.
Un composant appartient à un étage, et un seul.
reference | verse | |
|---|---|---|
| Ce que c'est | composant autonome | outil léger |
| Son dépôt | le sien, son cycle, sa CI | le sien aussi |
| Dans shinkiro | cloné à côté par make clone-all | submodule sous tools/ |
| Critère | se déploie et se vérifie seul | ne vit que dans le flux d'un autre |
| Côté client | s'adopte seul | ne s'adopte pas seul |
Le critère n'est pas la taille — c'est l'autonomie. Et cette autonomie n'est pas une commodité de dépôt : c'est une propriété commerciale. Shinkiro est une suite, et une suite s'achète par morceaux. reference nomme ce qu'un client peut prendre seul — radar sans rien d'autre, la-barre sur un poste, galahad sur son propre serveur. verse nomme ce qui n'a de sens que dans le flux d'un autre.
La taille n'explique qu'une chose : pourquoi les deux étages ne peuvent pas être un seul. Verser ADVE-project en submodule imposerait ses 100 Mo à quiconque clone le programme pour lire trois fichiers de doctrine.
Le programme ne porte aucun code de produit. Sa propre surface de présentation fait exception, et ce n'en est pas une : un portail généré depuis fleet.yml est une lecture du manifeste, pas une application. Le placer ailleurs créerait une source partagée sans propriétaire — ce que SHK-0002 interdit.
L'appartenance au programme se déclare par le topic shinkiro, et par lui seul. C'est ce que le relevé interroge ; un dépôt sans le topic n'existe pas pour la flotte, un dépôt avec le topic mais absent de fleet.yml est une dérive.
fleet.yml porte le jugement, fleet.lock.yml porte les faits. Le premier est écrit à la main et dit à quoi sert un composant ; le second est régénéré par make releve et dit ce qu'il est. Trois champs du premier — vitalite, licence, deploiement.mode — ressemblent à des faits mais sont des jugements : c'est précisément leur contradiction par le second qui constitue un signal.
Signal d'audit
non-classe— un dépôt du compte qui ne porte pas le topicshinkiroet quehors_perimetren'écarte pas nommément. Constaté : cinq outils vivaient hors de tout manifeste avant le 14 septembre 2026.absent-du-manifeste— un dépôt qui porte le topic mais n'apparaît dansfleet.ymlni comme composant, ni comme lignée morte. Il est entré dans la flotte sans être jugé.etage-invalide— un composant dontetagen'est nireferenceniverse, ou qui se déclare versé sans submodule correspondant soustools/. Constaté : les cinq outils versés l'étaient sur le papier seulement.faits-dans-le-jugement— un champ factuel réapparu dansfleet.yml. La scission ne tient que si personne ne la défait par commodité.licence-absente,vitalite-dementie,racine-fantome,entree-fantome— les trois champs de jugement démentis par le relevé, plus le point d'entrée.releve-perime— unfleet.lock.ymlde plus de quinze jours redevient ce qu'il remplaçait : un instantané qui affirme.mode-dementi— un modecoolify,dockerousystemdsans l'artefact qu'il exige, et sans état déclaré qui l'assume. Ajouté le 10 novembre 2026 : ce champ était annoncé comme surveillé depuis l'origine, sans qu'aucun contrôle le lise.
Le signal qui aurait épargné l'ADR-0100 — deux composants, un seul produit — n'est pas dans cette liste. Il demande une recherche de code à travers les dépôts, donc un jeton, donc le workflow et non la patrouille ; et il n'a de sens qu'une fois désigné le dépôt canonique d'Argos. Il relève de SHK-0002, et c'est là qu'il sera écrit. Le nommer ici sans l'implémenter aurait produit exactement ce que cette ADR combat : un document qui affirme un contrôle absent.
Portée
Cette ADR ne dit pas où tel composant doit aller — fleet.yml le dit, composant par composant, et se corrige sans ADR.
Elle ne crée pas de monorepo et n'impose pas un mode de déploiement unique. Cinq modes coexistent — Coolify, systemd, Vercel, Docker autonome, statique — parce qu'ils correspondent à cinq réalités ; les uniformiser casserait ce qui tourne. docs/TOPOLOGIE.md en tient le détail.
Elle ne dit rien du contenu des composants. Un dépôt reste maître de ses propres décisions ; SHK- n'arbitre qu'entre eux.
docs/adr/SHK-0001-programme-et-deux-etages.md
SHK-0002 — Argos : une bibliothèque, deux surfaces
- Statut : Accepted
- Date : 2026-09-14
- Composants :
Argos-studio,ADVE-project
Contexte
ADR-0100 d'ADVE-project, datée du 14 juin 2026, constate « Argos n'était pas déployable — 0 % de backend » et réimplémente le harvester à neuf. Argos-studio existait depuis le 15 mai, 184 fichiers, API v1 complète. Le récit de cette dérive est dans docs/DERIVE.md.
Mais le relevé des deux modèles dément la lecture simple — « deux fois la même chose ». Ce n'est pas le cas, et c'est ce qui rend l'arbitrage possible.
Argos-studio porte une bibliothèque. Neuf entités relationnelles autour de Reference : une taxonomie de patterns (patternKind, manipulationMode, funnelStage, piliers ADVE, operationGoals, victoryTypes), une preuve de performance à niveau d'attribution explicite — PROVEN_CAUSAL, CORRELATED, ESTIMATED, CLAIMED — la filiation entre campagnes, les annotations d'expert, la provenance nominative du chercheur. Plus une API v1 sur neuf familles de ressources et une voie d'entrée POST /api/v1/ingest/dossier, validée en Zod et idempotente sur le slug : une resoumission amende au lieu de dupliquer.
ADVE-project/src/server/services/seshat/argos/ porte une gouvernance. Un CampaignReferenceDossier à champs JSON — dna, editorial, sources — mais surtout ce que le studio n'a pas : un verdict de sûreté déterministe et sans LLM (PASS / QUARANTINE / REJECT, auto-publication si et seulement si PASS), le passage obligé par le LLM Gateway, les intents SESHAT_HARVEST_REFERENCE et OPERATOR_CREATE_REFERENCE_DOSSIER avec leurs SLO, la parité manual-first, et le lien intentEmissionId vers le journal de gouvernance.
Le recouvrement réel est étroit mais coûteux : les deux persistent une référence de campagne avec marque, secteur, marché et sources, et les deux ont une notion de publication. Deux modèles à tenir d'accord, indéfiniment.
Décision
Argos-studio est canonique pour la bibliothèque. Un seul modèle de référence, une seule taxonomie, une seule échelle d'attribution. C'est là que vit le fonds.
ADVE-project en devient un client gouverné. Il garde intégralement ce qui fait sa valeur et que le studio n'a pas — mais comme politique au-dessus d'une source partagée, plus comme seconde bibliothèque :
- Le Hunter récolte via le Gateway, inchangé.
computeSafetyVerdictrend son verdict, déterministe, inchangé.- Sur
PASSuniquement, le dossier est projeté enresearch-dossier-v1et poussé surPOST /api/v1/ingest/dossier. L'idempotence sur le slug fait que rejouer est sans danger. CampaignReferenceDossiercesse d'être la bibliothèque et devient le journal de gouvernance : ce qui a été récolté, par quel intent, quel verdict, par qui, quand. C'est une trace d'audit, pas un fonds documentaire.- Les lectures publiques —
listPublicDossiers,getPublicDossierByRef— passent par l'API v1 du studio.
L'autonomie des deux est préservée, et c'est une contrainte, pas un effet de bord. Argos-studio se déploie seul sur Vercel depuis app/ : c'est sa raison d'être, la bibliothèque publique et son moteur de recherche. ADVE-project fonctionne sans lui : le studio injoignable, la porte de gouvernance continue de juger et de journaliser, et la projection se rejoue plus tard — l'idempotence est ce qui rend ce report sûr.
Les trois interdits vendor d'ADR-0100 restent entiers. Ils portent sur docs/external-design/argos-hunter-v1/, qui n'est ni importé, ni exécuté, ni modifié. Cette ADR ne les touche pas.
ADR-0100 est amendée, non annulée. Son port est valable et le reste : la gouvernance qu'elle a construite est précisément ce qui manquait au studio. Seule sa prémisse — « 0 % de backend » — est corrigée.
Signal d'audit
source-partagee— lorsque deux composants se partagent une source,fleet.ymlle déclare : unproduitcommun, exactement unrole: canonique, et toutrole: clientnomme l'interfaceviapar laquelle il y accède. Zéro canonique signifie que personne ne possède la source ; deux signifient qu'on a rebâti ce qui existait.
C'est le contrôle qui aurait épargné ADR-0100 : contraint de déclarer qui possède Argos, son auteur aurait trouvé Argos-studio.
Il est volontairement déclaratif et sans réseau, donc exécutable par la patrouille à coût nul. Une recherche de code à travers les dépôts dirait mieux, mais exige un jeton, donc le workflow, donc une seule exécution par semaine — et surtout elle ne détecte qu'un symbole déjà dupliqué, quand celui-ci détecte l'intention de le faire.
Portée
Cette ADR ne fusionne pas les dépôts. Absorber Argos-studio dans ADVE-project détruirait l'autonomie qui est l'objet même de la contrainte posée.
Elle ne dicte pas le calendrier du branchement. Le côté ADVE est un dépôt gouverné — 192 ADR, plugin ESLint maison, intents et SLO — et son propre processus décide comment et quand. SHK- arbitre entre composants ; il ne légifère pas à l'intérieur.
Elle ne traite pas de la migration des dossiers déjà récoltés côté ADVE. Ils sont rejouables sur la voie d'entrée, précisément parce qu'elle est idempotente.
docs/adr/SHK-0002-argos-unifie-et-autonome.md
SHK-0003 — Deux moteurs, pas trois
- Statut : Accepted
- Date : 2026-09-14
- Composants :
galahad,talos,hulysse
Contexte
Ce manifeste a porté, sur talos, la note suivante :
src/recouvregalahad/engine/src/. Le moteur existe en trois exemplaires — galahad, talos, hulysse — alors que le README de galahad promet « une image moteur, trois rôles ». C'est la dette structurelle n°1.
Elle était fausse, et un plan de fusion par git subtree en a découlé. Personne ne l'avait mesurée : trois répertoires portant les mêmes noms de fichiers avaient suffi à conclure.
La mesure, reproductible par scripts/mesure-divergence.mjs :
| Paire | Fichiers partagés | Divergence |
|---|---|---|
talos ↔ hulysse | 10 | 17 % |
galahad ↔ talos | 9 | 73 % |
galahad ↔ hulysse | 9 | 71 % |
Il n'y a pas trois exemplaires. Il y en a deux, et un troisième moteur différent.
talos et hulysse sont bien le même moteur : journal.js, ollama.js et telegram.js sont identiques à l'octet, tools.js ne diffère que par ses commentaires. Ce qui les sépare est fonctionnel, pas structurel — talos porte cron, heartbeat et le pont MCP vers radar ; hulysse porte goals et veille.
galahad est autre chose. Aucun de ses fichiers n'est identique à son homologue. Là où les deux autres appellent ollama.js, il appelle brain.js, agnostique au fournisseur. Il porte roles.js, skill-runner.js, integrations.js, jobs.js — que ni l'un ni l'autre n'a. Son agent-loop.js fait 47 lignes contre 105 et 96 : une session roulante par processus, là où les autres persistent des fils dans sessions.json avec compaction.
Et la promesse citée à l'appui de la note ne disait pas ce qu'on lui faisait dire. « Une seule image, trois rôles » désigne chef, guardian et traveler — trois personas de galahad, déjà livrés par roles.js en pure configuration :
A role is pure configuration: the same engine binary runs any of them.
Cette promesse est tenue, à l'intérieur de galahad. Elle n'a jamais porté sur talos ni hulysse.
Décision
La convergence porte sur talos et hulysse, et sur eux seuls. Ils deviennent un moteur unique à deux rôles — exactement le motif que galahad a déjà éprouvé avec roles.js : cron, heartbeat et le pont MCP d'un côté, goals et veille de l'autre, deviennent des capacités de rôle et non deux forks. Les trois fichiers identiques à l'octet cessent d'exister en double le jour où la fusion est faite.
galahad ne fusionne pas. À 73 % et 71 %, ce ne serait pas une fusion mais une réécriture, et elle détruirait ce qui fait sa valeur propre — l'agnosticisme au fournisseur, le skill-runner qui porte cet audit même, les rôles, les jobs. Le programme assume deux moteurs : l'un agnostique et outillé, l'autre lié à Ollama et multi-fils.
Aucune duplication ne s'affirme plus sans être chiffrée. Une déclaration de divergence dans fleet.yml porte sa mesure, son chemin et sa date. Le chiffre est reproductible par scripts/mesure-divergence.mjs, qui compte par plus longue sous-séquence commune — la seule mesure indépendante de l'ordre des arguments.
Signal d'audit
divergence-perimee— toutedivergence:déclarée porteavec,chemin,mesure_pctetle. Quand les deux dépôts se trouvent clonés côte à côte, le contrôle refait la mesure : plus de dix points d'écart avec le chiffre déclaré est une dérive, pas une approximation. Sinon il vérifie que la mesure a moins de quatre-vingt-dix jours.
Une opinion écrite dans un manifeste finit par être lue comme un fait, puis par fonder un plan. C'est ce qui vient de se produire, et c'est ce que ce contrôle empêche de recommencer.
Portée
Cette ADR n'exécute pas la fusion de talos et hulysse. Ce sont deux agents en service sur le VPS, sous systemd ; leur convergence est un travail de code à mener avec ses tests de vie, pas un effet de bord documentaire.
Elle ne dit rien du protocole MCP talos ↔ radar, qui reste à reconstituer depuis radar-mcp/test-client.mjs. C'est un prérequis à la fusion : mcp.js doit devenir une capacité de rôle, et on ne déplace pas ce qu'on ne sait pas décrire.
Elle ne révise pas la promesse de galahad. Elle est tenue.
Actualisation de portée — 2026-10-07
La mesure et la décision ci-dessus décrivent les dépôts historiques examinés en septembre. La lecture des services Talos/Hulysse révèle depuis une convergence non représentée dans ces dépôts : quinze modules identiques, onze identiques au Galahad initial et quatre portant missions/Agora. Le rapport de réception qualifie les capacités actives et donneuses séparément. Cette observation ne supprime pas les anciennes capacités et n’exécute aucune migration. Une convergence de déploiement doit recevoir leur parité, leurs stocks et leurs politiques ; elle ne peut être déduite de la seule mesure Git ni de cette note.
docs/adr/SHK-0003-deux-moteurs-pas-trois.md
SHK-0004 — Jointure des taxonomies d'écart
- Statut : Accepted (11 novembre 2026, option C)
- Date : 2026-11-10
- Composants :
market-expansion-system,la-barre,radar
Contexte
Lu sur origin/main le 10 novembre 2026 : la-barre au commit 2586992, market-expansion-system au commit df37018, radar au commit 2e8d92f. Les lignes citées valent pour ces commits. Celles de shinkiro valent pour le commit 835fdeb ; le plan bouge vite, il est aussi cité par numéro de geste.
Un mot, deux objets
Le Market Expansion System classe ce qui change d'un marché à l'autre : langue, marque, produit/SKU, réglementaire (market-expansion-system/METHODE.md:26-33). Pour lui, un écart est une différence autorisée entre le master et une variante (market-expansion-system/METHODE.md:15-22). Tout autre écart « se refuse, ou il se facture » (market-expansion-system/METHODE.md:35).
La Barre classe qui doit la reprise : brief, plateforme, bigidea, agence, donneur (la-barre/app/ecarts.js:7-14). Chaque origine porte qui et facturable (la-barre/app/ecarts.js:20-36). Pour elle, un écart est une modification due par quelqu'un (la-barre/app/ecarts.js:1-5).
Les deux se complètent (shinkiro/docs/TOPOLOGIE.md:202-211). Mais elles s'opposent sur un point. La méthode veut un écart déclaré avant (market-expansion-system/METHODE.md:86-87). La Barre veut un écart calculé, jamais saisi (la-barre/app/ecarts.js:40-42, la-barre/app/ecarts.js:56-57). La jointure doit trancher cette opposition avant de fixer une forme de données.
Ce que La Barre stocke aujourd'hui
Rien. Les écarts sont recalculés à chaque lecture (la-barre/app/ecarts.js:58-78). Seule une mise à l'écart serait conservée, dans ecartsEcartes, sous la clé projet|livrable|origine|quoi (la-barre/app/ecarts.js:82, la-barre/app/ecarts.js:218-226).
Mais ecarterUn n'a aucun appelant, et facturable n'est lu nulle part (constat F4, shinkiro/docs/PLAN-ACHEVEMENT.md:244 ; revérifié sur 2586992). La clé contient le libellé quoi : changer un libellé ferait réapparaître un écart déjà écarté.
Où vit le marché dans La Barre
Un marché du référentiel porte code, nom, langues, zone, sku et mentions (la-barre/app/amorce.js:25-38).
Une adaptation est un KV réécrit pour un marché. Elle porte niveau: "adaptation", maitre, marche et un bloc kv : marque, accroche, langue, SKU, mentions, restrictions (la-barre/app/kv-modele.js:136-156). Un marché peut en avoir une, ou zéro (la-barre/app/kv-modele.js:41-49). Elle dépend d'une piste (la-barre/app/kv-modele.js:107-108, la-barre/app/kv-modele.js:142).
Les contrôles de conformité couvrent déjà trois des quatre types de la méthode : la langue (la-barre/app/kv-modele.js:236-242), les SKU (la-barre/app/kv-modele.js:248-254) et les mentions (la-barre/app/kv-modele.js:272-278). La marque n'est contrôlée que par sa présence, pas par sa différence avec le master (la-barre/app/kv-modele.js:233-234). Ces manquements deviennent des écarts d'origine brief (la-barre/app/ecarts.js:92-99).
Le couple projet × marché n'a pas d'objet propre. Le périmètre et chaque volet portent une simple liste d'identifiants de marchés (la-barre/app/vue-matrice.js:624, la-barre/app/vue-matrice.js:656, la-barre/app/intake.js:162). Un projet ouvert depuis une campagne en hérite les marchés (la-barre/app/vue-projets.js:686-708).
vue-matrice.js croise supports et marchés, et crée un livrable par case (la-barre/app/vue-matrice.js:652-686, la-barre/app/vue-matrice.js:761-781). Sur main, le « + » d'une case vide plante encore : volets n'y est pas défini (la-barre/app/vue-matrice.js:773). La correction est dans la-barre#14, ouverte, non fusionnée au commit lu.
Un type ou plusieurs : le Ghana
La méthode cite le Ghana deux fois : en langue et en marque (market-expansion-system/METHODE.md:30-31, market-expansion-system/README.md:27-28).
Le gabarit de cadrage n'a qu'une colonne ecart_type. La ligne du Ghana y vaut marque, alors que sa colonne ecart_declare dit « bascule marque + langue » (market-expansion-system/gabarits/cadrage-matrice.csv:10). La langue est perdue dès la saisie.
Le même gabarit emploie des valeurs hors des quatre types : référence (market-expansion-system/gabarits/cadrage-matrice.csv:2) et aucun (market-expansion-system/gabarits/cadrage-matrice.csv:7-9). Il classe en produit une déclinaison par genre, un marché pilote et un support véhicule (market-expansion-system/gabarits/cadrage-matrice.csv:3-6). La méthode réserve produit au format, au grammage et au prix (market-expansion-system/METHODE.md:32). Dans La Barre, une déclinaison par genre serait un choix de direction artistique déclaré par la campagne (la-barre/app/kv-modele.js:24-27), pas un écart de marché.
Le second gabarit n'a pas de colonne de type (market-expansion-system/gabarits/matrice-deploiement-modele.csv:1). La méthode le nomme Matrice de déploiement — modèle.csv (market-expansion-system/METHODE.md:74) : ce nom n'existe pas dans le dépôt.
Déduire le type en comparant chaque ligne au master ne suffit pas. mentions_legales vaut « standard » suivi du code pays sur toutes les lignes (market-expansion-system/gabarits/cadrage-matrice.csv:2-10). Le type réglementaire serait coché partout.
Où il se déclare
Dans la méthode, l'écart se déclare sur le couple projet × marché : une ligne par code projet et par pays (market-expansion-system/gabarits/cadrage-matrice.csv:1-10). Il se déclare au cadrage, « avant le premier crayon » (market-expansion-system/METHODE.md:41-42, market-expansion-system/METHODE.md:73).
Dans La Barre, le seul objet par marché est l'adaptation. Elle naît en production et dépend de la piste (la-barre/app/kv-modele.js:119-156).
La promesse d'import (geste 4.10, constat F9)
Le README promet que les gabarits « s'importent sans retraitement » dans Radar : cadrage-briefs.csv vers briefs, cadrage-matrice.csv vers client_markets (market-expansion-system/README.md:40-44). La promesse ne tient pas.
- L'amorçage CSV de Radar attend des en-têtes en français, « N° », « Client »… (
radar/server/pgrest.js:114-121). Le gabarit emploie les noms de colonnes (market-expansion-system/gabarits/cadrage-briefs.csv:1). Aucune ligne n'a dendegreconnu : toutes sont sautées (radar/server/pgrest.js:136). - Cet amorçage ne joue que sur une base vide, et avec
RADAR_SEED_CSV(radar/server/pgrest.js:157-161). client_marketsporteid,clientetdata(radar/server/pgrest.js:37). C'est une fiche par client, lue par le wiki (radar/briefs/supa.js:185-189). Elle n'a pas de clé de projet : la matrice projet × marché n'y a pas de place. La page wiki lit d'ailleursmarque,pays,langueau premier niveau (radar/briefs/marques.html:149-150). La forme attendue d'une ligne n'est pas établie.- La nomenclature diffère. Le ticket s'écrit
-R<NN>dans la méthode (market-expansion-system/METHODE.md:60) et.R<N>dans Radar (radar/server/ingest.js:74).
La matrice est implémentée dans La Barre, pas dans Radar (shinkiro/docs/TOPOLOGIE.md:213-215). La cible de la promesse dépend donc de l'option retenue.
Décision
Tranché le 11 novembre 2026 par le propriétaire (arbitrage 5.4) : option C. Un écart peut porter plusieurs types et se déclare sur le couple projet × marché. Mis en œuvre par market-expansion-system#2 (codes langue, marque, produit, reglementaire, format ecarts-marche v1, colonne ecart_types séparée par +) et la-barre#21 (déclaration sous perimetre.ecarts[marché], import et export du format, types portés par les écarts calculés).
Complété le 12 novembre 2026 par la-barre #23, sur décision du propriétaire : une adaptation qui change ce que son marché n'a pas déclaré n'est pas bloquée. Elle est signalée « hors écart déclaré », avec la dimension qui sort, et la revue tranche. Le point de départ de l'adaptation (master, version, champs reçus) est désormais posé à sa création ; une adaptation plus ancienne est « non évaluée », comptée, jamais signalée. La revue corrige soit la déclaration, soit l'adaptation, chaque fois par la fabrique de décision.
Reste ouvert : la règle « déclaré avant le premier crayon » n'est pas contrôlée.
Les trois options posées le 10 novembre sont conservées ci-dessous. Les chemins marqués « à créer » étaient des propositions de nom.
Option A — Une correspondance de lecture, rien de stocké
La Barre garde sa règle : l'écart est calculé. Chaque écart calculé reçoit, en plus de son origine, le type de la méthode qui lui correspond.
| Type de la méthode | Contrôle La Barre existant |
|---|---|
| langue | « Langue du marché » (la-barre/app/kv-modele.js:238) |
| produit / SKU | « SKU distribués ici » (la-barre/app/kv-modele.js:250) |
| réglementaire | « Mentions obligatoires » (la-barre/app/kv-modele.js:275) |
| marque | « Marque », présence seule (la-barre/app/kv-modele.js:233) |
Un écart calculé a au plus un type. Un marché en porte plusieurs, sur plusieurs lignes : le Ghana en aurait deux. Les autres contrôles — accroche, choix de direction artistique — restent sans type.
- Fichiers
la-barre:app/kv-modele.js, pour ajouter le type aux contrôles (la-barre/app/kv-modele.js:233-278) ;app/ecarts.js, pour le porter dans chaque écart (la-barre/app/ecarts.js:80-88) ; l'affichage dansapp/vue-attentes.js(la-barre/app/vue-attentes.js:37-38) etapp/file-action.js(la-barre/app/file-action.js:115-117). Surmain, aucun test ne couvreecarts.js; la-barre#15, ouverte, en ajoute. - Fichiers
market-expansion-system:METHODE.md, pour écrire la correspondance (market-expansion-system/METHODE.md:26-35) ;README.md, pour retirer ou réécrire la promesse d'import (market-expansion-system/README.md:40-44). La colonneecart_typedes gabarits devient indicative. - Migration : aucune, puisque rien n'est stocké. Les clés de
ecartsEcartesrestent valides tant que les libellés ne changent pas (la-barre/app/ecarts.js:82). - Ce qui casse : rien de stocké. Mais la règle « déclarer avant » reste hors de La Barre. Le type
marquene détecte pas une bascule, faute de comparaison au master. Un écart de confort reste invisible : rien n'est déclaré, donc rien n'est dépassé. - Ce qu'elle rend possible : compter les reprises par type et par origine, avec le compteur existant (
la-barre/app/ecarts.js:236-243). Lire dans un même relevé ce qui change et qui paie. C'est l'option la moins chère. - Promesse d'import : elle reste sans cible. Le geste 4.10 la retire, ou la réécrit vers Radar après conversion.
Option B — Plusieurs types, déclarés sur l'adaptation
L'adaptation porte la liste de ses écarts déclarés, de zéro à quatre. La Barre compare chaque champ kv de l'adaptation à celui de son master. Une différence hors de la liste devient un écart calculé.
- Fichiers
la-barre:app/kv-modele.js— le champ dansCHAMPS_KV(la-barre/app/kv-modele.js:15-22), son initialisation danscreer(la-barre/app/kv-modele.js:119-156), la comparaison au master dansconformite(la-barre/app/kv-modele.js:227-281) ;app/ecarts.js, une source d'écart de plus (la-barre/app/ecarts.js:68) ; l'affichage dansapp/vue-planche.js(la-barre/app/vue-planche.js:116-119) etapp/vue-route.js(la-barre/app/vue-route.js:201-214) ; des tests. - Fichiers
market-expansion-system:METHODE.md, pour une colonne à plusieurs valeurs (market-expansion-system/METHODE.md:26-35,market-expansion-system/METHODE.md:71-77) ; l'en-tête des deux gabarits (market-expansion-system/gabarits/cadrage-matrice.csv:1,market-expansion-system/gabarits/matrice-deploiement-modele.csv:1). - Migration : un champ ajouté à des objets existants. Aucune collection nouvelle, donc
VERSION_SCHEMAn'a pas à bouger (la-barre/app/depot.js:20,la-barre/app/depot.js:32-35). Les adaptations existantes n'ont pas de déclaration : « absent » doit se lire « non déclaré », pas « aucun écart ». - Ce qui casse : un marché sans adaptation ne peut rien déclarer (
la-barre/app/kv-modele.js:41-49). La déclaration suit la piste : une nouvelle piste retenue la remet à zéro (la-barre/app/kv-modele.js:107-108). Elle arrive en production, pas au cadrage, contremarket-expansion-system/METHODE.md:86-87. Enfin, l'origine d'un écart non déclaré n'est pas calculable. La méthode dit qu'il se refuse ou se facture (market-expansion-system/METHODE.md:35) :agenceoudonneur, selon qui l'a demandé (la-barre/app/ecarts.js:30-35). Aucun champ ne dit qui l'a demandé, etdefretombe suragence(la-barre/app/ecarts.js:38). - Ce qu'elle rend possible : le Ghana porte ses deux types. La variante qui touche autre chose que son écart (
market-expansion-system/METHODE.md:21-22) devient détectable sur les champs du KV. - Promesse d'import : inchangée. Le gabarit gagne une colonne à plusieurs valeurs, sans cible d'import.
Option C — Plusieurs types, déclarés sur le couple projet × marché, au cadrage
Chaque marché du périmètre porte une déclaration : types, détail, date, auteur. Adaptations et formats de ce marché sont jugés contre elle. La date de déclaration se compare à celle de la première pièce du marché.
- Fichiers
la-barre:app/vue-matrice.js— la saisie dans le périmètre et le volet (la-barre/app/vue-matrice.js:623-650,la-barre/app/vue-matrice.js:963-990), les en-têtes de la grille (la-barre/app/vue-matrice.js:669-672) ;app/kv-modele.js, dontconformitelit la déclaration du marché (la-barre/app/kv-modele.js:227-281) ;app/ecarts.js, une source de plus (la-barre/app/ecarts.js:68) ; l'initialisation dansapp/intake.js(la-barre/app/intake.js:162) etapp/vue-projets.js(la-barre/app/vue-projets.js:708). Un import du gabarit, à créer sousoutils/, rapproche le code pays demarches.code(la-barre/app/amorce.js:25-38). - Fichiers
market-expansion-system:METHODE.md(market-expansion-system/METHODE.md:71-77) ;README.md, dont l'import vise La Barre (market-expansion-system/README.md:40-44) ;gabarits/cadrage-matrice.csv, avec une colonne à plusieurs valeurs, sansréférenceniaucun, et un usage deproduitconforme à la méthode. - Migration, en deux variantes :
- C1 — une table à côté, indexée par marché, sous le périmètre. Aucune migration ; « absent » vaut « non déclaré ».
- C2 — les listes
marchesdu périmètre et des volets deviennent des listes d'objets. Il faut une étape dansmigrer(la-barre/app/depot.js:663-787) et incrémenterVERSION_SCHEMA(la-barre/app/depot.js:20). Un poste plus ancien refuse alors le fichier : « Version de base incompatible » (la-barre/app/depot.js:228). Tous les lecteurs de ces listes changent, par exemplela-barre/app/vue-matrice.js:385,la-barre/app/vue-matrice.js:656,la-barre/app/dispositif.js:158etla-barre/app/compilateur.js:404.
- Ce qui casse : deux projets d'une même campagne qui servent le même marché déclarent deux fois. Or la campagne porte déjà les marchés (
la-barre/app/vue-projets.js:686-708). Le bon niveau — projet ou campagne — reste à fixer. La saisie passe par une grille dont le « + » plante surmain(la-barre/app/vue-matrice.js:773). - Ce qu'elle rend possible : la règle « déclaré avant » devient vérifiable. Le Ghana porte ses deux types. La matrice de la méthode s'importe là où elle est implémentée.
- Promesse d'import : tenue côté La Barre. Radar n'est plus la cible de la matrice. L'import de
cadrage-briefs.csvversbriefsreste à réécrire ou à retirer.
À trancher par le propriétaire :
- Un écart a-t-il un type, ou plusieurs ?
- Se déclare-t-il sur l'adaptation, sur le couple projet × marché, ou sur le couple campagne × marché ?
- La Barre accepte-t-elle un écart déclaré, ou garde-t-elle sa règle « calculé, jamais saisi » ?
- La promesse d'import du Market Expansion System : tenue vers La Barre, réécrite vers Radar, ou retirée ?
- Le sort des valeurs
référenceetaucun, et l'usage deproduitdans les gabarits.
Signal d'audit
Ajouté le 11 novembre dans shinkiro/scripts/signaux-flotte.mjs. Il n'est pas encore dans galahad/engine/skills/audit-fleet.json.
ecart-types-alignes— la liste des types d'écart est la même dans les gabarits du Market Expansion System et dans le code de La Barre. Toute valeur deecart_typeappartient à cette liste. Si plusieurs types sont admis, le séparateur est celui que la méthode documente. Violation : une valeur hors liste, ou deux listes qui divergent. Le contrôle ne joue que si les deux dépôts sont clonés côte à côte, commedivergence-perimee(shinkiro/scripts/signaux-flotte.mjs:189). Avec l'option A, il vérifie en plus que chaque type nomme un contrôle présent danskv-modele.js.
Le 10 novembre, ce signal se serait allumé : référence et aucun étaient hors liste. Depuis market-expansion-system#2, aucun vaut « aucun écart » et référence a disparu : le signal est vert.
Portée
Écrite le 10 novembre sans choisir ni écrire de code ; le choix et le code sont venus le 11 (voir Décision).
Elle ne corrige ni le « + » de la grille (F1), ni facturable jamais lu (F4). Mais une option qui prétend dire qui paie devra lire facturable.
Elle ne traite pas des tickets mineurs ou majeurs (market-expansion-system/METHODE.md:65-67). Ils touchent pourtant la mesure du pilote : voir SHK-0005.
Elle ne règle pas le reste du geste 4.10. La méthode annonce neuf pays et en liste huit (market-expansion-system/METHODE.md:4-6) ; le README en liste neuf (market-expansion-system/README.md:5-8).
docs/adr/SHK-0004-jointure-des-taxonomies-ecart.md
SHK-0005 — Câblage La Barre → Radar
- Statut : Accepted (sens 1 — arbitrage 5.5 du 11 novembre 2026 ; indicateurs et bascule — arbitrage 5.6 du 12 novembre 2026)
- Date : 2026-11-10
- Composants :
la-barre,radar
Contexte
Lu sur origin/main le 10 novembre 2026 : la-barre au commit 2586992, radar au commit 2e8d92f. Les lignes citées valent pour ces commits. Celles de shinkiro valent pour le commit 835fdeb ; le plan bouge vite, il est aussi cité par numéro de geste ou d'arbitrage.
Ce que vend le portefeuille
Le Transformation Pilot promet une mesure avant/après : « le before/after est mesuré, pas déclaré » (shinkiro/docs/PORTFOLIO.md:49). Sa méthode de preuve repose sur Radar et La Barre (shinkiro/docs/PORTFOLIO.md:65). Le même document pose la condition : tant que La Barre ne verse pas ses décisions dans Radar, le before/after se rédige (shinkiro/docs/PORTFOLIO.md:72-75). Aucun code ne calcule cette mesure (shinkiro/docs/PLAN-ACHEVEMENT.md:428-430).
Aucun câblage dans la flotte
la-barre n'appelle pas l'API de Radar : aucune occurrence de rest/v1, de RADAR_API_KEY ni de X-Radar-Key dans le dépôt, hors bibliothèque tierce. radar ne lit rien de La Barre. Son propre reçu le dit : la correction du journal « ne reçoit ni un raccord La Barre → Radar idempotent » (radar/docs/RECEPTION-JOURNAL.md:48-53).
Une admission existe dans l'installation de l'employeur, hors flotte (shinkiro/fleet.yml:247-250). Elle n'est ni décrite ni reprise ici (shinkiro/docs/CLOISON.md:6-17). Son sort relève de l'arbitrage 5.15 (shinkiro/docs/PLAN-ACHEVEMENT.md:505).
Un relevé existe dans l'autre sens, et il porte des briefs, pas des décisions. outils/ingerer-corpus.mjs lit un CSV de briefs Radar déposé à la main (la-barre/outils/ingerer-corpus.mjs:118) et écrit le dépôt (la-barre/outils/ingerer-corpus.mjs:25-26). Le registre l'affiche (la-barre/app/registre-radar.js:15-16, la-barre/app/depot.js:50-56). La clé est ndeg (la-barre/outils/ingerer-corpus.mjs:237, la-barre/app/registre-radar.js:117). Un projet garde la liste de ses codes Radar (la-barre/outils/ingerer-corpus.mjs:540, la-barre/app/vue-projets.js:273-276), sans identifiant stable ni instance.
La forme des décisions dans La Barre
Les décisions forment une collection du dépôt (la-barre/app/depot.js:77). Huit écrivains l'alimentent.
| Écrivain | Type écrit |
|---|---|
la-barre/app/bigidea-ecoles.js:242-243 | bigidea |
la-barre/app/campagne.js:361-371 | reference-campagne |
la-barre/app/validation.js:169-172 | la clé de la section validée |
la-barre/app/vue-atelier.js:221-223 | idee |
la-barre/app/vue-bigidea.js:341-342 | piste |
la-barre/app/vue-livrable.js:432-433 | livrable |
la-barre/app/vue-revue.js:284-287 | le type de la pièce revue |
la-barre/app/vue-route.js:397-398 | piste |
Leur forme commune : objet, type, projet, verdict, motif, quand, qui, titre. DEPOT.ajoute pose id et cree_le (la-barre/app/depot.js:95-101). Deux écrivains ajoutent acteur, version et portee (la-barre/app/validation.js:169-172, la-barre/app/campagne.js:361-366). Celui de la campagne ajoute remplace : une décision peut en supplanter une autre (la-barre/app/campagne.js:366). Il y a quatre verdicts : approuve, reserve, retour, hors (la-barre/app/maison-base.js:243-248).
Quatre faits comptent pour un câblage.
- L'identifiant est un préfixe suivi de six caractères aléatoires (
la-barre/app/outils.js:163-165). Rien ne vérifie son unicité (la-barre/app/depot.js:95-98). - L'auteur n'est pas authentifié.
quivaut le poste titulaire de l'installation,direction-generalepar défaut (la-barre/app/maison-base.js:166).acteurest choisi sur le poste ; « les accès serveur restent distincts » (la-barre/app/acteur.js:1-2). - Le projet est un identifiant La Barre, pas un dossier Radar (
la-barre/app/vue-livrable.js:432,la-barre/app/campagne.js:362). - La soumission n'est pas datée : sur
main,soumis_len'est écrit par aucun écrivain (la-barre/app/bilan.js:137-141; constat F3,shinkiro/docs/PLAN-ACHEVEMENT.md:243). La-barre#15, ouverte, change la lecture du délai de verdict.
Le geste 4.9 demande une fabrique unique pour ces huit écrivains. Il est noté prérequis de ce câblage (shinkiro/docs/PLAN-ACHEVEMENT.md:399).
Comment La Barre conserve et expose
Le dépôt est un seul fichier JSON sous depots/ (la-barre/servir.mjs:171-177). depots/manifeste.json nomme le fichier de référence (la-barre/app/depot.js:494-500). Le serveur le sert en GET, avec une empreinte de version, l'ETag (la-barre/servir.mjs:471-476). Il l'écrit en PUT conditionnel, par remplacement atomique (la-barre/servir.mjs:421-444, la-barre/servir.mjs:158-163).
Il n'y a ni route de décisions, ni export dédié. DEPOT.exporter télécharge toute la base (la-barre/app/depot.js:555-566). Elle contient aussi les personnes et les pièces de facturation (la-barre/app/depot.js:39, la-barre/app/depot.js:64-68).
Le journal local se tronque au-delà de 2 000 entrées, sauf celles qui nomment une marque (la-barre/app/depot.js:143-149). Les décisions, elles, ne sont pas tronquées.
servir.mjs n'a aucune authentification (la-barre/servir.mjs:140-143). Sur main, il écoute sur toutes les interfaces par défaut (la-barre/servir.mjs:487 ; constat S4, shinkiro/docs/PLAN-ACHEVEMENT.md:229). En production, il est servi derrière le raccord authentifié de La Fusée (la-barre/docs/INSTALLATION-ENTREPRISE.md:58-63).
Ce que l'API Radar accepte
- Routes :
/rest/v1/<table>,/index.csv,/jour.json,/ingest,/visuels,/token,/profil,/feed.xml,/activity.json(radar/server/index.js:53-72). Aucune tâche périodique : le démarrage prépare la base et purge les visuels orphelins, rien d'autre (radar/server/index.js:89-94). - Tables : une liste blanche (
radar/server/pgrest.js:25-50). Aucune table de décision, aucune colonne pour une référence externe.briefsa cinq colonnes JSON libres :brief_client,brief_creatif,brief_production,case_study,suivi(radar/server/pgrest.js:31-32). - Écritures :
POSTinsère sans clé qui empêcherait un doublon (radar/server/pgrest.js:354-385).PATCHetDELETEexigent un filtre et frappent toutes les lignes qui le satisfont (radar/server/pgrest.js:387-419). Le filtre suridest permis (radar/server/pgrest.js:26). ndeg: un index simple, non unique (radar/server/pgrest.js:67). Un commentaire sur un code ambigu est refusé en 409 (radar/server/pgrest.js:221-226). Le geste 4.4 constate le reste : unPOSTrejoué crée un doublon, unPATCHparndegfrappe tous les homonymes (shinkiro/docs/PLAN-ACHEVEMENT.md:394). L'arbitrage 5.7 décide de son unicité (shinkiro/docs/PLAN-ACHEVEMENT.md:497).- Journal :
task_eventsest en lecture seule par REST (radar/server/pgrest.js:41,radar/server/pgrest.js:274). Un déclencheur surbriefsl'écrit (radar/server/journal.sql:15-53), les visuels aussi (radar/server/visuels.js:141-144,radar/server/visuels.js:203-206). Les commentaires n'y écrivent rien. Les types émis sontcreated,deleted,frozen,unfrozen,closed,reopened,status,reassigned,deadline,visibilityetupdated(radar/server/journal.sql:22-40). Aucun type « décision ». Une ligne inchangée, horsupdated_at, n'émet rien (radar/server/journal.sql:27). L'heureatest celle de l'écriture (radar/server/pgrest.js:85;radar/server/journal.sql:42-43ne la fixe pas). /activity.json: public par défaut,FEED_TOKENen option (radar/functions/_feed.js:136-142,radar/functions/_middleware.js:145-146). Il ne publie que les mouvements publics qualifiés (radar/functions/_feed.js:52-55), 200 au plus (radar/functions/_feed.js:46). Un élément porte le codendeg, pasbrief_id(radar/functions/_feed.js:78).- Authentification : la clé
RADAR_API_KEY, enBearerou enX-Radar-Key, donne l'identitéservice@radaret lève la confidentialité (radar/functions/_middleware.js:148-160; constat S3,shinkiro/docs/PLAN-ACHEVEMENT.md:228). Sinon, le mur Basic et son cookie (radar/functions/_middleware.js:187-233), avec trois rôles (radar/functions/_authz.js:8-11,radar/functions/_authz.js:70-82). Aucune clé de portée réduite n'existe (radar/docs/RECEPTION-JOURNAL.md:51-53). - Navigateur :
/rest/v1n'envoie aucun en-tête d'accès entre origines (CORS). Seuls les flux et/jour.jsonen portent (radar/functions/_feed.js:156,radar/functions/_feed.js:160,radar/server/index.js:40). - Entrées existantes :
/ingesttransforme un texte libre en tâches par un modèle local, en statut « Reçu » (radar/server/ingest.js:1-14,radar/server/ingest.js:148-175). L'amorçage CSV ne joue que sur une base vide (radar/server/pgrest.js:157-161). Aucune n'accepte un lot de décisions.
Décision
Tranché par le propriétaire.
- Arbitrage 5.5, 11 novembre 2026 : sens 1. Radar va lire, La Barre n'envoie rien. La correspondance projet ↔ dossier vit dans Radar. Les décisions restent privées, hors de
briefset detask_events. L'authentification est un jeton machine dédié, pasRADAR_API_KEY. La route d'admission de l'employeur n'est pas reprise (5.15 : admission écrite neuve). - Arbitrage 5.6, 12 novembre 2026. Les trois familles d'indicateurs sont retenues :
- durée et ponctualité, tirées de Radar ;
- reprises et tours au-delà du vendu, tirés de La Barre ;
- réouvertures, réattributions, reports et révisions, tirés de Radar.
La bascule est le jour où Radar commence à lire La Barre en production : 12 novembre 2026, 11 h 06 UTC, première lecture réussie de l'instance radar-agence.
Mis en œuvre.
- la-barre #22 sert
GET /radar/decisions, derrièreBARRE_RADAR_TOKEN. - Radar #8 écrit le lecteur
server/barre.jset les tablesbarre_recus,barre_projets,barre_lectures, ainsi que la vuebarre_decisions. - Radar #9 rend
ndegunique par instance et les flux privés par défaut (5.7).
Le contrat est écrit dans INTERFACES.
En production. Une instance Radar dédiée à l'agence, base propre, lit La Barre par le réseau interne du VPS. La première lecture a reçu zéro décision, La Barre de production étant vide. Les suivantes répondent « inchangé ».
Reste ouvert.
Le calcul des indicateurs retenus: fait le 12 novembre (Radar #10), avec la règle des dossiers ouverts avant la bascule et clos après (comptés à part, « à cheval »). Le taux de reprise sur versions et les tours au-delà du vendu restent non calculables depuis Radar.- La saisie de la correspondance projet ↔ dossier dans l'écran Radar.
- Le traitement des 125 événements anciens, privés jusqu'à leur relecture (5.7).
Les trois sens posés le 10 novembre sont conservés ci-dessous. Les chemins marqués « à créer » étaient des propositions de nom.
Ce qui vaut pour les trois sens
- La clé de liaison n'existe pas. Une décision nomme un projet La Barre. Radar identifie un dossier par
briefs.id;ndegn'est pas unique. Il faut une correspondance projet ↔ (instance Radar,briefs.id), tenue d'un côté ou de l'autre. - La décision n'a pas de place dans Radar. Trois choix sont possibles. La traduire en changement de
statut, qui émetstatus. L'écrire dans une colonne JSON, qui émetupdatedavec le seul texte « Dossier modifié » (radar/server/journal.sql:40). Ou créer une table ou un type d'événement, ce qui change le contrat du journal et les libellés du flux (radar/functions/_feed.js:14-28). - La confidentialité. Une décision La Barre ne porte pas de
private_to. Écrite dans un dossier public, elle part dans le flux public par défaut (radar/functions/_feed.js:136-138). - L'horloge.
atest l'heure d'écriture dans Radar. La date de la décision,quand, doit voyager à part. Sinon, tout retard de transfert fausse les délais mesurés. - La fabrique unique du geste 4.9 donne une seule forme de décision à transférer.
Sens 1 — Radar lit le fichier, ou un export, de La Barre
Radar va chercher. Il lit le dépôt désigné par depots/manifeste.json, ou une route qui ne sert que les décisions.
- Fichiers
radar: un lecteur, à créer (server/barre.js) ; son déclenchement dansserver/index.js, qui n'a aucune tâche périodique (radar/server/index.js:89-94) ; une table de reçus et la correspondance projet ↔ dossier, à créer dans le schéma (radar/server/pgrest.js:55-97) ou dansserver/journal.sql; leurs cas danstests/reception.test.mjs. - Fichiers
la-barre: aucun si Radar lit tout le dépôt. Sinon, une route de lecture dansservir.mjs(la-barre/servir.mjs:307-485) qui ne sert que les décisions. - Authentification :
servir.mjsn'en a pas. En production, l'accès passe par La Fusée. Un accès machine à ce raccord n'est décrit dans aucun des dépôts lus : non trouvé. Côté Radar, l'écriture est interne, sans requête HTTP. - Rejeu sans doublon : un reçu par (instance La Barre,
decision.id). L'ETagpermet de sauter un fichier inchangé (la-barre/servir.mjs:475). Le remplacement atomique évite de lire un fichier à moitié écrit (la-barre/servir.mjs:158-163). Il faut une règle pour une décision supprimée ou remplacée (la-barre/app/campagne.js:366). - Ce qu'il engage : sans route dédiée, Radar reçoit toute la base, personnes et facturation comprises. L'intervalle de lecture décale
at.
Sens 2 — La Barre pousse vers l'API Radar
La Barre écrit dans Radar. Le navigateur ne peut pas le faire : /rest/v1 ne porte pas d'en-tête CORS, et la clé y serait exposée. La poussée part donc de servir.mjs, ou d'un outil sous outils/.
- Fichiers
la-barre: la fabrique unique, à créer (geste 4.9), et les huit écrivains qui l'appellent ; une file d'envoi déclarée dansvide()(la-barre/app/depot.js:26-80), car une collection absente de cette liste est perdue au chargement (la-barre/app/depot.js:32-35) ; la route d'envoi dansservir.mjs; leurs tests, leur script danspackage.jsonet leur ligne dans.github/workflows/verification.yml. - Fichiers
radar: aucun, si l'on s'en tient à la REST existante ; la décision est alors forcée dans une colonne debriefs. Ou une route d'admission dédiée, à créer (server/barre.js, aiguillée dansradar/server/index.js:53-72), avec sa table de reçus et ses tests. Cette route recouvre ce que pose l'arbitrage 5.15. - Authentification : soit
RADAR_API_KEY, accès complet et confidentialité levée ; soit un compte du mur en Basic, rôlesupervisor, qui voit tout le non-privé (radar/functions/_authz.js:75,radar/functions/_authz.js:96). Ce compte ne touche pas un dossier privé d'autrui. Le secret vit côté serveur La Barre. - Rejeu sans doublon : un
POSTrejoué crée un doublon. UnPATCHparid, au contenu identique, n'émet aucun événement (radar/server/journal.sql:27) : il se rejoue sans doublon. UnPATCHparndegfrappe les homonymes. La Barre doit donc connaîtrebriefs.idet l'instance ; elle ne garde que des codes. Une réponse perdue se reprend depuis la file d'envoi et son reçu. - Ce qu'il engage : le transfert est immédiat, et
atreste proche dequand. Le dossier Radar peut avoir changé entre-temps : il faut dire qui l'emporte.
Sens 3 — Un humain dépose un paquet
La Barre exporte les décisions ; une personne dépose le fichier dans Radar.
- Fichiers
la-barre: un export des seules décisions, à créer à côté deexporter(la-barre/app/depot.js:555-566), avec un bouton sur le modèle de celui des réglages (la-barre/app/vue-reglages.js:101-102). - Fichiers
radar: une route de dépôt, une page sousbriefs/et une table de reçus, tous à créer. Aucune entrée existante ne convient :/ingestpasse par un modèle et crée des tâches (radar/server/ingest.js:1-14). - Authentification : la session Radar du déposant. Elle authentifie le dépôt, pas l'auteur de la décision, qui reste déclaré (
la-barre/app/acteur.js:1-2). - Rejeu sans doublon : un reçu par
decision.id. Le même paquet rejoué ne change rien ; deux paquets qui se recouvrent se dédoublonnent. Le précédent existe dans l'autre sens (la-barre/outils/ingerer-corpus.mjs:25-26,la-barre/outils/ingerer-corpus.mjs:118). - Ce qu'il engage : la cadence est humaine, et
atest l'heure du dépôt. Sans la datequand, un paquet hebdomadaire écrase toute mesure de délai.
À trancher par le propriétaire (arbitrage 5.5, shinkiro/docs/PLAN-ACHEVEMENT.md:495) : lequel des trois sens ; où vit la correspondance projet ↔ dossier ; où vit la décision dans Radar ; quelle authentification ; et si la route d'admission s'écrit neuve ou reprend celle de l'employeur (arbitrage 5.15).
Ce que l'arbitrage 5.6 doit fixer
L'arbitrage 5.6 choisit les indicateurs et la date de bascule (shinkiro/docs/PLAN-ACHEVEMENT.md:496). Les candidats ci-dessous sont ceux que les données permettent aujourd'hui. Aucun n'est choisi ici.
Candidats tirés de Radar :
- la durée d'un dossier, de
createdàclosed, parbrief_id(radar/server/journal.sql:25,radar/server/journal.sql:34) ; - les réouvertures,
reopened(radar/server/journal.sql:35) ; - les réattributions,
reassigned(radar/server/journal.sql:37) ; - les reports d'échéance,
deadline(radar/server/journal.sql:38) ; - la ponctualité,
closed_atavantdeadline(radar/briefs/sla.html:114-117) ; - les révisions par dossier maître : entrées
Révision, de codePARENT.RN(radar/server/ingest.js:65-75,radar/server/ingest.js:161-169).
Candidats tirés de La Barre :
- le taux de reprise sur les versions (
la-barre/app/bilan.js:155-183) ; - les tours au-delà du vendu (
la-barre/app/bilan.js:185-200) ; - les propositions retenues au premier tour (
la-barre/app/bilan.js:124-133) ; - les écarts par origine, dont ceux du donneur d'ordre, facturables (
la-barre/app/ecarts.js:236-243). Ils sont calculés à la lecture, sans historique : leur valeur « avant » n'existe que si on la photographie.
Non calculables sur main :
- le délai de verdict, faute de
soumis_le(la-barre/app/bilan.js:137-141) ; - la reprise mineure ou majeure de la méthode (
market-expansion-system/METHODE.md:65-67) : aucun champ, ni dansradarni dansla-barre— non trouvé.
Ce que 5.6 doit fixer en plus des indicateurs :
- La date de bascule : à partir de quand chaque décision est transmise. Et la règle des dossiers ouverts avant la bascule et clos après.
- La fenêtre « avant » et sa source. Si l'équipe n'utilisait pas Radar avant la bascule, il n'y a pas d'« avant » mesuré.
- L'histoire ancienne : 125 événements à confidentialité inconnue (
radar/docs/RECEPTION-JOURNAL.md:13-14). Les anciens n'ont nibrief_idni instantané de périmètre (radar/server/journal.sql:1-8). Les inclure, ou non. - Ce qui termine un dossier.
closedcouvre Livré, Closed, Clôturé, Terminé (radar/server/journal.sql:34). Le périmètre d'autorité tient aussi pour finis « Envoyé dans Slack », « Livré (cycle) », « Validé », « Bouclé », « Archivé » (radar/functions/_authz.js:61). « Validé » ou « Bouclé » produisentstatus, pasclosed. Etclosedne prouve ni livraison ni accord client (radar/docs/RECEPTION-JOURNAL.md:49-51). - L'horloge :
atde Radar ouquandde La Barre ; et le fuseau de l'instance (radar/.env.example:11-12,radar/functions/_authz.js:59-60). - Les champs saisis.
deadlineetdate_receptionsont du texte (radar/server/pgrest.js:28). La ponctualité ne compte que les échéances au format jour (radar/briefs/sla.html:124,radar/briefs/sla.html:131). - La cohorte : quelle instance Radar, quelle installation La Barre, quels projets.
- L'assise minimale. La Barre distingue déjà un zéro mesuré d'un registre vide (
la-barre/app/bilan.js:7-14). Chaque chiffre doit dire sur combien de faits il repose. - L'accès en lecture. Le flux public s'arrête à 200 éléments publics (
radar/functions/_feed.js:46,radar/functions/_feed.js:52-55). La mesure demande la REST avec une identité, ou la base elle-même.
Signal d'audit
decisions-barre-radar— La Barre et Radar nomment la même route (/radar/decisions), la même variable (BARRE_RADAR_TOKEN) et le même seuil de jeton, au moins 32 caractères. Radar n'écrit aucune décision dansbriefsni danstask_events, qui alimentent les flux. Violation : une route ou une variable absente d'un côté, deux seuils différents ou inférieurs à 32, ou uninsert into briefs|task_eventsdansserver/barre.jsouserver/barre.sql. Le contrôle ne joue que si les deux dépôts sont clonés à côté deshinkiro, commeecart-types-alignes.
Deux contrôles avaient été proposés le 10 novembre ; ils ne sont pas écrits. Le premier, une déclaration de flux dans fleet.yml, attend que le manifeste porte des flux. Le second, garder la condition « le before/after se rédige » de docs/PORTFOLIO.md tant qu'aucun flux n'existe, est dépassé : le flux existe, et le calcul des indicateurs aussi (Radar #10) ; les tests de Radar défendent ce calcul.
Portée
Cette ADR ne choisit ni le sens ni les indicateurs. Elle n'écrit aucun code.
Elle ne rend pas ndeg unique : c'est le geste 4.4 et l'arbitrage 5.7. Les sens 1 et 2 en dépendent pourtant.
Elle ne décrit ni ne reprend l'admission de l'installation de l'employeur. Elle ne touche ni au pont MCP entre talos et radar, ni à La Fusée.
Elle ne reçoit aucune mesure. Un flux câblé rend la mesure possible ; il ne la prouve pas.
docs/adr/SHK-0005-cablage-la-barre-radar.md