Chroniques du Panthéon

Les versions d'ulk dans l'ordre où elles sont arrivées : les arcanes entrées au Panthéon, les correctifs, et les ruptures.

61 versions consignées, de 17 janvier 2026 à 3 septembre 2026.

Sommaire

v8.2.0

⚠ Ruptures

  • nommage: les 73 slugs du roster sont renommés — toutes les invocations changent, aucun ancien nom ne survit comme alias, et une réinstallation (./install.sh) est requise. /ulk:bruce devient /ulk:aiguilleuse, /ulk:godspeed devient /ulk:triageuse, /ulk:peon devient /ulk:pointeuse, /ulk:analyze devient /ulk:controleuse, /ulk:vps devient /ulk:intendante-vps, les six deploy-* deviennent livreuse-* ; 71 slugs bougent au total, archiviste et sondeuse étaient déjà conformes. C'est le geste que l'entrée du 2026-09-01 avait explicitement écarté — elle chiffrait la voie slug à 787 illustrations, 144 fiches et 72 golden tests, et concluait « pour le même bénéfice de lisibilité ». Le chiffrage était juste (1 181 fichiers renommés, dont 568 illustrations), la conclusion non : le bénéfice n'est pas la lisibilité, c'est que le nom d'invocation cesse de demander une référence. Une épithète répare la fiche du site ; elle ne répare pas la ligne qu'on tape. Tant que le slug restait godspeed, l'audit agents-naming.md § Le test échouait à l'endroit exact où il compte — au moment d'invoquer. Le corollaire est que le garde-fou 4 devait tomber d'abord : il posait qu'un nom publié ne disparaît jamais, au motif de scripts et d'utilisateurs tiers qui, sur un dépôt à mainteneur unique, n'existent pas. Il a été réécrit le 2026-09-01 (« renommer, c'est remplacer »), et c'est cette réécriture qui rend la passe possible sans traîner 71 alias morts. Les 22 alias qui restent déclarés désignent des cibles vivantes — les cinq controleuse-* et les dix-sept *-vps sont des fichiers d'action, pas des noms retirés. Tombe avec la passe l'exemption des neuf agents « à nom fonctionnel » (bruce, analyze, vps, les six deploy-*) : elle laissait le roster à deux régimes de nommage, l'un tenu par les six garde-fous, l'autre par personne ; agents-naming.md § Ce qu'on ne renomme plus la remplace par une liste de noms stables, ce qui est une règle et non une dispense. Ce que la passe a fait remonter, et qu'aucun gate ne voyait : neuf textes Pedagogy() du catalogue d'install dépassaient leurs bornes une fois les noms allongés — la borne existait, la marge était fortuite ; l'allowlist EXTENDS_ALLOW d'agents-coherence.test.mjs gelait six agents sous leur ancien slug, et le test « l'allowlist ne contient pas d'entrée périmée » les a tous nommés d'un coup ; et l'empreinte CSP du <script> de la page d'accueil a bougé, parce que le jeu de cartes embarque les noms — un renommage de slug est donc aussi un changement de header HTTP, ce que rien n'annonçait avant que check-csp.mjs ne le refuse.

Ajouté

  • skills: ulk skills lock accepte --except <skill> — l'entrée nommée garde son empreinte épinglée, et son amont n'est pas interrogé. Né du gel de gstack le 2026-09-01, dont la nouvelle version amont exécutait un binaire local pilotant ses propres règles de préambule : lock n'avait alors aucun ciblage, si bien que geler une entrée imposait de tout re-locker puis de restaurer la ligne à la main dans le JSON — un geste hors outil, non reproductible, et qu'un lock ultérieur défaisait en silence. Le gel ne vivait nulle part ailleurs que dans la mémoire de qui l'avait posé. Trois choix portent la correction. Le flag refuse un nom absent du catalogue ou jamais épinglé, au lieu d'écrire le manifeste quand même : un --except gstak mal orthographié re-lockerait exactement l'entrée qu'on voulait protéger tout en annonçant un succès, et un gel qui échoue en silence est pire que pas de gel — on cesse de vérifier ce qu'on croit tenu. L'amont d'une entrée gelée n'est jamais relevé : le relever pour jeter le résultat dépenserait du quota API à produire une information déjà écartée, et ferait échouer le gel le jour où le dépôt est injoignable, alors qu'un gel n'a aucune raison de dépendre du réseau. Enfin le compteur frozen est tenu à part de kept : kept est subi — l'amont n'a pas répondu — quand frozen est voulu, et les fondre présenterait un incident réseau comme une décision, donc ferait cesser de relever un amont devenu muet. La sortie annonce chaque gel avec son empreinte et rappelle que ulk skills verify --upstream signalera ces entrées comme divergentes : c'est le gel, pas une régression.

  • agents: sondeuse (94) entre au roster — l'enquête par les données en cinq temps (protocole, ressources, qualification, analyse, valorisation), une action chargée à la demande par temps. Agent-geste de la sphère des oracles, dérivé d'un profil réel anonymisé ; sa conviction fondatrice est qu'une donnée n'a de valeur que si l'on sait à quelle question elle répond, d'où elle vient, et à qui on va la raconter. Le roster passe de 72 à 73 et le prochain identifiant libre à 95 ; docs/Nouveaux Agents/ est exclu du versionnage — c'est de la matière brute, avec les données personnelles qui vont avec. Deux sources MIT entrent dans skills-sources.json comme optionnelles de l'agent, citées « si installées » et délibérément hors loads_skills : thematic-analysis (grille de codage qualitatif, Temps 4) et data-science-claude-skills (auto-eda, dataset-doctor, experiment-tracker, paper-to-code, sql-optimizer, Temps 3). 35 → 37 skills externes aux crédits.

  • gates: deux oracles ferment la même cause — aucun gate ne reliait une doctrine à l'existence de ce qu'elle prescrit. check-dismantled refuse qu'une doctrine vivante prescrive de l'infrastructure démantelée : c'est le mode d'échec qui avait justifié la sortie de Faru, retrouvé intact une couche plus haut. Le dépôt avait supprimé les symptômes — 139 fichiers, 12 751 suppressions — sans traiter ce qui les avait laissés mentir, si bien que le résidu ne s'est vu que des semaines plus tard, par un audit ; sans ce gate, chaque démantèlement futur aurait laissé le même et aurait été découvert de la même façon. check-agent-naming.cjs en est l'instance appliquée au nommage : les garde-fous 1, 2, 5 et 6 de agents-naming.md ne tenaient que parce que quelqu'un les relisait au bon moment, et la passe épithète du 2026-09-01 a montré ce que ça laisse passer — trois tautologies de sphère publiées sur le site (celebrimbor « forgeron » chez les Forgerons, cerbere et chromie « gardien·ne » chez les Gardiens) et une épithète annonçant cinq masques pour six modes, parce que rien ne comparait une épithète à sa source. Les deux tournent au pre-commit. (#723, #734)

  • outils: todo-triage.cjs trie mécaniquement les TODO/FIXME/HACK/XXX du dépôt. Le chiffre brut — 254 occurrences — surestimait la dette sans qu'aucun moyen ne permette de le dire sans relire les 254 : la majorité vit sous _archived/ ou dans des gabarits de sortie, où XXX est un masque de numéro et non une dette. Le tri appliqué, la dette réellement vivante tombe à 2 gabarits. (#733)

Modifié

  • nommage: les 72 épithètes du roster passent au corpus des métiers humains ordinaires, dans la couche épithète et nulle part ailleurs. Le corpus de 67 remplacements avait été proposé le 2026-08-28 par astride (docs/reports/astride-nommage-arcanes-2026-08-28.md) comme une vague de renommages ; le garde-fou 5, écrit le même jour mais après le rapport, arbitre l'inverse — un métier proposé comme nouveau nom est presque toujours une épithète qui s'est trompée d'emplacement. Appliquer le corpus là où il appartient coûte 65 lignes de frontmatter ; l'appliquer aux slugs aurait touché 787 illustrations, 144 fiches de site et 72 golden tests pour le même bénéfice de lisibilité, et cassé les invocations. 65 épithètes réécrites, 7 laissées telles quelles parce qu'elles satisfaisaient déjà la forme (archiviste, bruce, benjamin, shuri, hardcode, peon, jony). Mesure après passe sur les 72 : 0 majuscule initiale, 0 point final, 0 article initial, médiane 4 mots — la grammaire du garde-fou 5 tient sur l'ensemble, pas seulement sur les nouvelles. La répartition des têtes passe à 57 féminines, 10 épicènes, 4 masculines plus la citation de peon : c'est le correctif du garde-fou 3 appliqué là où il ne coûte rien, et réversible à la même adresse — un genre d'épithète se change sans toucher une commande. Trois tautologies de sphère tombent au passage (celebrimbor « forgeron » chez les Forgerons, cerbere et chromie « gardien·ne » chez les Gardiens), que le garde-fou 1 interdisait déjà sans que rien ne le vérifie. Et un défaut factuel qu'aucun gate ne pouvait voir, parce qu'une épithète est de la prose : blackemperor annonçait « empereur aux cinq masques » pour six modes — la correction d'août n'avait touché que descriptions-fr.json côté site, jamais l'épithète du registre. Deux doc citaient l'ancien état comme exemple vivant et sont réalignées ; agents-naming.md § 5 consigne la passe et sa mesure, pour que la prochaine proposition de renommage trouve le précédent au lieu de le refaire.

  • cli: la TUI passe à Charm v2 — bubbletea 2.0.9, bubbles 2.2.1, lipgloss 2.0.6, sur les deux modules Go. Migration d'API sur toute la surface : imports charm.land/*/v2, View() rend un tea.View (l'écran alternatif se demande désormais sur la vue, tea.WithAltScreen et WithMouseCellMotion n'existent plus), KeyMsg devient KeyPressMsg avec .Code et .Text là où .Type et .Runes servaient, lipgloss.Color cède la place à color.Color. Le point que le compilateur ne voyait pas : lipgloss v2 rend toujours en couleurs vraies et ne regarde plus si la sortie est un terminal, ce qui aurait injecté des séquences ANSI dans tout pipe et tout fichier. tui/output.go écrit donc via lipgloss.Fprint*, rétablissant la parité v1 — sortie non-TTY dépouillée, NO_COLOR et CLICOLOR_FORCE honorés ; vérifié, ulk status | cat -v ne contient aucune séquence d'échappement. La règle renovate.json qui désactivait le major Charm après trois reverts (#381/#382, #410/#411, #532) est retirée : Charm rentre dans le droit commun des majors Go, à approbation Dashboard. (#727)

  • agents: le backlog des agents suit la bascule vers GitHub issues, décidée en 8.1.2 et jusque-là appliquée aux seules cartes. shuri écrit spec et todo sur des issues et sait migrer un board Obsidian existant, task-runner, peon et godspeed lisent le backlog là, scully vérifie des issues, et les protocoles _shared ne parlent plus de cartes. Le HARD-GATE gate: spec-required de bruce est retiré : il exigeait une surface qui n'existe plus, donc il bloquait sur une condition devenue insatisfiable. C'est le reste que la bascule avait laissé câblé — retirer les cartes sans reprendre ce qui les lisait aurait reconduit d'un cran plus bas exactement le défaut qu'elle corrigeait. (#713, #714, #715, #716)

  • agents: les impératifs TOUJOURS/JAMAIS cèdent la place aux critères qui portent leur raison — astride, tony, georges, agathe, sauron, plus 182 en-têtes reformulés. Un impératif dit quoi faire sans dire pourquoi : il se suit tant qu'il est lisible et se contourne dès qu'il gêne, alors qu'un critère se discute et se mesure. Les blocs générés sortent du compte au passage — ils sont réécrits par un générateur, les compter revenait à mesurer l'outil plutôt que la prose. (#725)

  • gates: le seuil d'impératifs de la cheat sheet passe de 800 à 1200, sur une base assainie. Le seuil datait d'avant #725, posé comme la moitié de la mesure d'alors (1525, blocs générés compris) : la base a changé deux fois, la cible jamais, si bien que 1341 > 800 en permanence — et un ⚠ qui ne s'éteint jamais n'est plus un signal, c'est du décor. 1200 = base mesurée (1107) plus environ 8 % de marge, donc le vert redevient atteignable et la première retombée au rouge dit quelque chose. La regex cesse de compter les citations et le code — blocs, code inline, lignes >, guillemets — soit 234 occurrences de bruit sur 1341 ; un signal de concentration par fichier s'ajoute au-delà de 25 (maximum mesuré : 20), un dossier qui accumule étant plus parlant qu'un total qui dilue. Non bloquant, et maintenu tel : un impératif peut protéger une perte irréversible, la conversion reste un jugement. (#740)

  • site: spheres.json devient la source unique des sphères — FIGURES y est absorbée, FAMILLES et SOCLES échouent bruyamment plutôt que de diverger en silence, et neuf énumérations tombent à quatre. Le gate qui vérifiait la concordance des clés disparaît avec son objet : une énumération qui ne peut plus diverger n'a plus besoin d'être surveillée. (#722)

Corrigé

  • credits: CREDITS.md ne publie plus de lien portant une expansion shell. Le générateur dérive le lien d'un outil CLI de la première URL trouvée dans sa recette d'installation, et écartait déjà les substitutions $(…) et les backticks — « pas un vrai lien ». Épingler la recette obscura à sa version (ci-dessous) a produit le cas qui manquait, la variable simple : .../releases/download/$VER/... est une URL correcte dans le shell qui la développe, et un lien mort partout ailleurs. CREDITS.md étant publié, il a annoncé une release nommée « $VER ». La garde couvre maintenant toute expansion ; obscura retombe sur la page de son dépôt, qui est de toute façon la meilleure cible pour un lien de crédits. Le contrôle ajouté porte sur l'artefact et non sur la fonction — aucun lien de CREDITS.md ne contient $ ni backtick — pour qu'une future source de liens en hérite sans qu'on y pense. (#742)

  • agents: les gabarits de nom de fichier sous docs/ disent YYYY-MM-DD, le format que tous les fichiers réels pratiquent. La doctrine était partagée en deux : report-formats.md et une trentaine de corps d'agents prescrivaient <agent>-YYYYMMDD.md, seize autres YYYY-MM-DD, et docs/audits/README.md énonçait le second — les treize fichiers datés de docs/audits/ et docs/reports/ sont tous en YYYY-MM-DD, aucun en compact. Le format compact a existé (six noms dans l'historique, tous horodatés -HHMM), il a été abandonné dans les faits sans que la doctrine le sache. Alignement de 99 lignes sur 49 sources, arbres générés resynchronisés ; dredd garde son heure (YYYY-MM-DD-HHMM). Les noms de branche, de sauvegarde (.bak-, doc-backup-) et de dossier de captures (.visual-audit-) ne sont pas des rapports et restent tels quels. Suite de #731. (#737)

  • audits: docs/audits/ et docs/reports/ portent chacun un README qui dit ce qui vit chez l'un et pas chez l'autre. La convention existait (framework/agents/CLAUDE.md § Convention) mais n'était lisible que depuis là : l'audit sargeras du 2026-09-01 a trouvé docs/audits/ presque vide — résidu du nettoyage b4d2b28a, 21 fichiers retirés — et en a conclu à deux dossiers pour un même genre, et à un audit-to-backlog.cjs qui n'en connaîtrait qu'un. Le script prend le rapport en argument et n'en connaît aucun ; le critère qui sépare audit et rapport — la récurrence — est désormais écrit dans les deux README et dans base-rules/report-formats.md, là où un auditeur choisit son dossier. (#731)

  • skills: ulk skills verify --upstream ne conseille plus une commande qui défait ce qu'il vient de signaler. Sur une divergence, il renvoyait vers ulk skills lock — seule issue quand le lock ne savait pas geler. Depuis --except, ce conseil est devenu piégeux : un lock sans argument re-locke tout, donc adopte aussi l'entrée qu'on tenait délibérément gelée, et le fait en silence puisque adopter un amont est exactement ce que la commande est censée faire. On suivait le message affiché par l'oracle et on perdait le gel que ce même oracle venait de relever comme divergent. La sortie présente maintenant les deux issues côte à côte — adopter, ou geler — avec les noms divergents pré-remplis dans la commande --except (le flag refusant un nom inconnu, recopier à la main ce que la sortie affiche déjà n'ouvrirait qu'une occasion de faute de frappe), et dit explicitement qu'un lock nu adopte tout ce qui a bougé. Le conseil est rendu par une fonction pure, comme unreachableAdvice (#607) : un conseil peut être faux, il doit pouvoir être mis en échec par un test.

  • hooks: le pre-commit ne peut plus se lire « vert » en taisant ce qu'il n'a pas exécuté. Il portait seize if command -v … ; then sans else, plus la garde [ -f hardcode-check.sh ], et aucune ligne de verdict : un outil absent faisait taire son oracle sans que rien ne le dise, et le silence se lisait comme un succès — le défaut que le registre des skips avait fermé côté pre-push, retrouvé intact côté commit, dans un dépôt dont les hooks sont le seul gate. Le mécanisme SKIP_LOG/skip_note quitte donc le pre-push pour scripts/hooks/lib-skip.sh et gagne skip_verdict, plutôt que d'être recopié : deux copies d'un registre divergent en silence, ce qui est précisément le mode de défaillance qu'il existe pour fermer. Le verdict reste non bloquant des deux côtés — un gate plus strict qui devient pénible se contourne, et un gate contourné est pire qu'un gate absent ; ce qui change n'est pas le droit de commiter, c'est l'impossibilité de lire « vert » sans lire à la même ligne ce qui n'a pas tourné. La mesure a corrigé l'énoncé au passage : les quatorze gardes node ne sont pas atteignables par l'absence de node, le § 1 échoue bruyamment avant elles ; les sauts réellement silencieux étaient shellcheck, gofmt et hardcode-check. (#741)

  • gates: sept evals « live » déclarés mais jamais exécutés apparaissent désormais comme tels dans le verdict du pre-push. Skippés faute de clé d'API, ils donnaient une couverture apparente sans couverture réelle — et ils portent précisément ce que les tests structurels ne peuvent pas voir, le comportement réel des agents. Un test qui ne tourne jamais est une croyance, pas une mesure ; à défaut de tourner, il doit au moins se déclarer. (#732)

  • site: deux défauts d'accessibilité relevés par l'audit du 2026-09-02, nés de la même cause — une règle écrite pour la prose et appliquée trop large. Contraste (WCAG 1.4.3 AA) : .prose :global(pre) compilait en .prose.astro-hash pre, de spécificité supérieure à .astro-code, donc le fond clair de la page écrasait celui de Shiki pendant que les six couleurs de token restaient calibrées pour un fond sombre — en thème clair, #E1E4E8 sur #EBE3F7 mesure 1,02:1 là où AA exige 4,5, les cinq autres montant au mieux à 3,87:1. Seul le fond étant disputé, il passe sous pre:not(.astro-code) tandis que la géométrie du bloc reste commune : poser le :not() sur la règle entière, comme le suggérait le rapport, aurait privé tous les blocs Shiki de leur remplissage et de leur conteneur de défilement — la correction d'un contraste aurait cassé la mise en page de 73 fiches. Niveaux de titre (WCAG 1.3.1 A) : une carte d'arcane porte un h3 et les pages de sphère n'avaient aucun h2 entre leur h1 et lui ; un h2 sr-only est posé avant le paquet, le bandeau annonçant déjà le compte à l'écran. L'index du panthéon obtenait déjà ce résultat par un autre chemin — c'est cette asymétrie, jamais écrite, qui a fait passer le défaut pour corrigé pendant un mois. Les 12 pages de métier, hors du périmètre compté par l'audit, portaient le même défaut et sont corrigées avec. (#743)

  • doc-counts: le filet des comptes nus s'étend à .claude/rules/, qui porte la même prose que le site sans que rien ne la surveille — « 85 agents » y a survécu douze incréments de roster, dans deux fichiers. La cause passe avant les symptômes : checkBareCounts balaie une liste de racines au lieu du seul site/src, et BARE_COUNT_ALLOW accepte une seconde forme de clé (chemin:terme) pour le fichier dont le terme est hors sujet de bout en bout — install-reference.md compte dix fois un bundle tiers, jamais le catalogue. La forme étroite reste le défaut : agents-authoring.md n'obtient aucune exemption large sur « agent », son sous-ensemble est exempté à la ligne près et son défaut de roster reste attrapable. 17 emplois, 4 signalés, 13 déclarés ; les quatre signalés sont rattachés à leur source. agents-naming.md rejoint au passage l'index des règles scopées de CLAUDE.md, où il manquait depuis sa création. (#745)

  • nommage: la fonction: de chromie tenait en deux mots — « non-régression visuelle » nommait la technique, pas le métier. Le garde-fou 6 fixe 3 à 6 mots pour une raison mesurée : la fonction est ce que lit qui n'a pas la référence, et sous trois mots elle redevient une étiquette technique, donc elle ne remplit plus la colonne qu'elle est censée tenir. Seul écart sur les 72 après la passe épithète, et aucun gate ne pouvait le voir — la longueur d'une fonction est de la prose, comme l'épithète. check-agent-naming.cjs le voit désormais.

  • gitignore: les copies impeccable-*.md écrites sous .claude/agents/ rejoignent celles déjà ignorées sous .github/agents/. L'installeur du skill produit les deux jeux, seul le second était couvert depuis le correctif du 2026-08-12 : quatre fichiers restaient non suivis à chaque session sans qu'aucune règle ne les vise.

Sécurité

  • install: la recette d'installation d'obscura cesse d'exécuter du code non vérifié. Elle téléchargeait depuis releases/latest — une cible qui change sous vous —, sans somme de contrôle, vers un chemin /tmp prévisible, puis faisait sudo mv vers /usr/local/bin/ : CWE-494 doublé d'un CWE-367, la fenêtre entre l'écriture dans /tmp et le mv privilégié. Les quatre faiblesses tombent ensemble — version épinglée à v0.2.1, mktemp -d à la place de /tmp, shasum -a 256 -c - (macOS) / sha256sum -c - (Linux) avant toute extraction, et sudo install -m755 qui réduit la part privilégiée à la copie finale. Vérifié par rejeu de bout en bout plutôt que par lecture : empreinte correcte → sortie 0 et les binaires en place ; empreinte falsifiée → shasum: WARNING: 1 computed checksum did NOT match, sortie 1, rien d'installé. L'amont ne publie aucun fichier de sommes : les deux empreintes sont calculées sur les archives du 2026-09-03, et un bump de version impose de les recalculer — c'est écrit dans la note de l'entrée, faute de quoi le prochain bump les recopierait telles quelles. Un défaut d'exécution tombe au passage, invisible à la lecture de la recette : l'archive porte deux binaires, obscura appelle obscura-worker à l'exécution, et l'ancienne recette ne posait que le premier — l'outil était donc installé cassé depuis le 2026-05-07. Ce que la correction ne fait pas, écrit dans la note pour ne pas être relu comme un acquis : l'architecture reste choisie sur la seule foi de la plateforme, donc un Mac Intel reçoit toujours l'archive arm64 ; l'empreinte vérifie l'archive, pas son adéquation à la machine. (#742)

  • install: aucune nouvelle recette d'installation ne peut plus télécharger du code sans en vérifier l'empreinte — un cliquet au pre-commit, pas une campagne. Le chiffre qui a ouvert l'issue, « 198 recettes sur 204 sans somme de contrôle », était le mauvais dénominateur : il comptait brew install, apt install et npm i -g, qui délèguent l'intégrité à leur gestionnaire et n'ont rien à porter. Sur les 273 recettes du registre, 30 téléchargent réellement ; 6 déclarent un sha, 3 se vérifient elles-mêmes, 7 sont excusées par le unpinned_reason posé par l'audit #466 pour les entrypoints vendeurs servis en continu. La dette réelle est de 14, et c'est elle que framework/tools/install-checksum-debt.json fige, entrée par entrée, épinglée par l'empreinte de la recette. D'où trois propriétés que ne donne pas une liste d'exceptions : modifier une recette de dette la fait redevenir rouge, puisque son empreinte ne correspond plus ; une entrée devenue inutile — recette vérifiée depuis, ou disparue du registre — est elle-même une erreur, donc résorber consiste à supprimer une ligne ; et le registre ne peut que rétrécir. Le check porte un second oracle, qui n'est jamais grand-père : déclarer un <plateforme>_sha256 sur une recette qui n'est pas de la forme exacte curl <url> | sh est refusé. Le champ route vers installer.VerifiedInstall, dont ParseCurlPipe rejette tout le reste, et bundle.go:113 compte l'erreur en failed++ sans repli : le sha casserait l'installation au lieu de la protéger. C'est ce qui a rendu inapplicable le correctif tel que l'issue le formulait pour obscura — « router par VerifiedInstall » — et la recette a été durcie dans le shell à la place. Le second temps de l'issue, résorber les 14, n'est pas dans ce lot : il est long, et le cliquet existe précisément pour que la dette ne croisse pas pendant. (#742)

v8.1.2

⚠ Ruptures

  • backlog: le backlog quitte les cartes Faru pour GitHub issues. Ce n'est pas une préférence d'outil : croisées à l'état réel de leur issue, les 115 cartes actives ne faisaient pas doublon avec GitHub, elles le contredisaient à 47 % — 48 todo et 6 wip pointaient sur des issues closed, 54 done sur des issues closed, et une seule carte sur 115 décrivait du travail réellement ouvert. Le mode d'échec est structurel, pas un défaut d'hygiène : rien ne mettait à jour le status: d'une carte quand le code bougeait, et aucun gate ne pouvait le voir — un status: périmé est un fichier parfaitement valide. Une surface qui n'est jamais infirmée par l'exécution finit toujours par mentir. Les 114 cartes actives sont supprimées ; docs/backlog/archive/ (271 cartes) est gelée en lecture seule — elle porte des mesures et des arbitrages que les issues n'ont jamais contenus, c'est de la mémoire de projet, pas du backlog. Avant suppression, les 6 cartes que GitHub ne couvrait pas ont été isolées une par une : cinq visaient des PR mergées, la sixième — deux décisions différées sur woz, avec leur protocole de mesure et une échéance au 2026-11-26 — portait un issue: qui désignait une PR sans rapport et aurait disparu sans trace ; elle est portée en #712 avant que le git rm ne parte. Le démantèlement passe par le point de convergence plutôt que par 139 fichiers : _shared/faru-protocol.md passe de 772 lignes (corps + 4 satellites) à 85, ce qui assèche la création de cartes pour ses 47 consommateurs d'un coup et rend ~700 lignes de contexte par invocation d'agent. Le fichier garde son nom : c'est son contenu qui change, pas son adresse. L'infrastructure restante (faru.config.json, check-card-spec.cjs, sync-issues.sh, kanban.cjs, backlog-grooming.sh) reste câblée le temps de la transition et ne valide plus qu'une chose — que les 271 cartes gelées restent bien formées ; aucune ne doit servir à en créer une nouvelle. 30 liens morts réparés dans 27 fichiers au passage, résolus vers archive/ quand la carte y est, vers son issue sinon

  • install: le module d'install faru disparaît, et avec lui les flags --with-faru / --without-faru — un script qui les passe encore échoue au parsing, pflag refuse un flag inconnu. C'est la deuxième passe du démantèlement ouvert par la bascule vers GitHub issues : la première a supprimé les cartes, celle-ci supprime ce qui les produisait. Tombent avec elle faru.config.json, le gate check-card-spec.cjs et son entrée au pre-push, framework/cheatheet/kanban.cjs, framework/tools/sync-issues.sh, evaluate/backlog-grooming.sh, la skill et la routine sync-issues, leurs trois suites de tests, et l'entrée faru du cli-registry.json (l'entrée voisine dont l'id vaut faru est ant, mal nommée depuis l'origine — elle reste). Le module Go méritait d'être nommé : enabledByDefault: true, il faisait npm install -g github:fluado/faru chez tout installateur, pour piloter un board qui n'existe plus. C'est exactement la dérive que la bascule vient de corriger, une couche plus bas. Reste câblé, non arbitré : les mentions de cartes dans les agents, la sonde faru.config.json de godspeed, et le HARD-GATE gate: spec-required.

  • audits: tools/audit-to-backlog.cjs n'écrit plus de dossiers de cartes, il ouvre des issues. C'est la troisième et dernière passe du démantèlement : le seul reste qui produisait encore des cartes. Il était le cas le moins évident à trancher, parce qu'il n'était pas mort — un audit de quarante findings vaut mieux converti que recopié à la main, et son parseur avait coûté trois issues (#603, #604, #612) pour cesser de rendre zéro finding sur les rapports réellement émis par ed209 et sargeras. Ce parseur est intact, à la ligne près ; c'est la couche de sortie qui change. Une issue par finding, la gravité en label (🔴→P0 … 🟢→P3, plus agent-generated), le corps passé à gh par stdin plutôt qu'en argument — un finding réel dépasse la limite d'un argument de commande, et un --body en clair exposerait son contenu à qui lit la table des processus. Trois garde-fous que le format carte n'imposait pas : les labels absents du dépôt sont écartés au lieu de faire échouer la création en bloc (le script tourne aussi hors d'ulk, où P0 peut ne pas exister), un titre déjà ouvert n'est pas recréé — relancer sur le même rapport est sans effet —, et un gh muet arrête tout avant la première création plutôt qu'à mi-parcours. --dry-run n'appelle plus rien du tout et rend le plan complet : c'est ce que l'utilisateur valide avant d'ouvrir quarante issues d'un coup. Les 27 tests sont réécrits sur la nouvelle sortie — parsing lu sur le plan, émission exercée par un faux gh injecté via GH_BIN qui enregistre argv et stdin, ce qui teste la commande construite sans toucher GitHub

  • vps: les prérequis entre domaines VPS bloquent. « 🔗 Agent Sécurité (02) : serveur sécurisé » était une phrase en tête d'agent : elle se lisait, et rien ne vérifiait qu'elle avait été suivie. Chaque vps-actions/<domaine>.md ouvre désormais sur une table de contrôles exécutables, et un STOP qui échoue arrête l'action — docker network inspect proxy, sudo ufw status, find /opt/backups -mtime -1. Les usages qui s'affranchissaient du graphe en pratique — déployer sans reverse-proxy, nettoyer sans sauvegarde fraîche, durcir SSH sans session de secours — cessent de passer. C'est voulu : c'est le gain de sûreté qui justifie la fusion, et non un effet de bord. Passer outre reste possible, mais demande de le dire à l'utilisateur et de lui faire trancher (#690)

Nouveautés

  • agents: la famille analyze passe de cinq agents à un, et la règle qui produit ce résultat entre dans agents-authoring.md : l'unité de variation d'ulk est le fichier d'action, pas l'agent — un geste nouveau justifie un agent, une cible nouvelle du même geste est un fichier d'action. La preuve était structurelle avant d'être une opinion : analyze (5 agents) et deploy (6) étaient exactement les deux familles sans aucun dossier -actions/, quand 28 autres agents en avaient un ; la duplication d'agent était le seul mécanisme de variation disponible, donc c'est celui qui a servi. Les cinq analyseurs partageaient six phases identiques — Mission, Détection, Inventaire, Problèmes, Rapport, todo.md — et ne divergeaient que sur la grammaire de leur stack. Ce qui coûtait n'était pas leur corps mais leur description:, chargée en permanence dans toutes les sessions où ulk est installé, qu'on les invoque ou non : 2 272 caractères, ~649 tokens à chaque démarrage. Le corps passe de 2 133 lignes à 135 ; les cinq grammaires sont intactes sous analyze-actions/{astro,next,nuxt,spip,swiftui}.md, lues une à la fois. Roster 92 → 88. Trois points ne se fusionnaient pas mécaniquement, et chacun a été tranché plutôt que contourné : analyze-swiftui vivait chez les pomiculteurs quand les quatre autres étaient chez les eclaireusesagents-naming.md départage (le geste l'emporte quand l'agent fonctionne partout), d'où les eclaireuses, qui tombent du coup à un seul agent, fait porté à #682 ; loads_skills: spip et l'extends: cli-tools-protocol.md de SPIP descendent dans le fichier d'action de leur cible, jamais dans le frontmatter commun, sinon les quatre autres cibles les paieraient ; et le mécanisme d'alias que le garde-fou 4 suppose (un nom publié ne disparaît jamais) n'existait pas — zéro agent du registry en portait un. Il est construit : SLUG_ALIASES dans command-layout.cjs génère cinq shims de commande, description réduite à 46 caractères contre ~450, corps qui délègue à analyze avec la cible pré-remplie. /ulk:analyze-next résout donc toujours, et le gain de la fusion est conservé — c'est la description qui pèse dans chaque session, pas le corps, lu seulement à l'invocation. Les shims vivent dans framework/commands/ seulement : dans framework/agents/, ils porteraient un name:, compteraient au roster et annuleraient exactement le gain qu'on vient de faire. command-slug-aliases.test.mjs au pre-push ancre les quatre invariants, sondé failable sur le plus silencieux d'entre eux — un shim qui regagnerait la description complète de l'agent qu'il remplace ne casserait rien de visible. Côté site, les quatre fiches supprimées sont redirigées en 301 vers celle d'analyze, la règle splat préexistante /agents/scribes/analyze-* comprise : elle pointait désormais vers des fiches absentes, et Cloudflare Pages n'appliquant qu'une passe, le 404 serait passé sans signal. Laravel (#686) et Flutter (#687) entrent maintenant comme fichiers d'action, sans coût de roster (#688)

  • agents: les dix-sept agents *-vps fusionnent en un agent vps et seize fichiers d'action — roster 92 → 76. J'avais recommandé de ne pas fusionner, sur un argument de sécurité : un agent unique rendrait impossible la restriction d'outils par tâche, sur des opérations destructives visant un serveur de production. La mesure invalide l'argument — les seize spécialistes portaient [AskUserQuestion, Bash, Glob, Grep, Read, Write], le même jeu, à l'identique, et l'orchestrateur y ajoutait Task pour dispatcher ses frères. Le découpage n'achetait aucune restriction, il la promettait. Ce qui décide n'est pas la taille de la famille mais son graphe : douze agents sur dix-sept déclaraient des prérequis sur un autre agent VPS, souvent OBLIGATOIRES, et quand douze agents doivent être enchaînés dans un ordre imposé, la logique d'enchaînement est le produit — elle vivait pourtant dans un orchestrateur qui dispatchait seize frères, chacun rechargeant l'état du serveur à son tour, pour rien : les dix-sept étaient sonnet, ce n'était même pas un changement de modèle (§7 de #685). La Phase 1 de vps absorbe l'orchestrateur (00), qui n'existait que pour router à l'intérieur de sa propre famille, et relève l'état une seule fois pour la séance. Rendu : ~996 tokens de contexte permanent, les dix-sept description: cumulées, soit ~15 % du budget des descriptions du roster. Les cinq dossiers -actions/ existants passent sous vps-actions/<domaine>/ sans être réécrits (#690)

  • commands: SLUG_ALIASES accueille un alias sans cible et le registre expose les alias d'un agent. Le mécanisme de #688 supposait qu'un alias vise toujours une cible du geste fusionné — vrai pour les cinq analyze-*, faux pour orchestrateur-vps, dont le travail était le routage et qui n'a donc aucun fichier d'action à nommer : lui en inventer un produisait un renvoi vers vps/null.md, un shim qui délègue dans le vide en prétendant l'inverse. arg: null rend ce cas explicite, et command-slug-aliases.test.mjs vérifie désormais les deux formes — avec cible, le shim doit nommer son fichier d'action installé ; sans cible, il ne doit en nommer aucun et doit nommer l'agent. Second manque, invisible tant qu'aucune famille opt-in n'avait fusionné : pruneDisabledModuleCommands parcourt registry.json et retire <name>.md pour chaque agent dont le module_flag est désactivé — les alias n'y figuraient pas, donc un ulk install sans --with-vps aurait laissé dix-sept commandes qui ne mènent nulle part. Le registre porte maintenant aliases, retourné depuis SLUG_ALIASES par le générateur plutôt que redéclaré en Go, et l'installateur les emporte avec leur agent. TestPruneDisabledCommandsIsDataDriven s'appuyait jusqu'ici sur RemoveGlobs: commands/ulk/vps, un dossier disparu avec le layout plat de #689 : il vérifiait l'absence d'un chemin absent avant même l'installation, donc il passait quoi qu'il arrive. Réécrit sur le registre (#690)

  • commands: /ulk:<nom> invoque n'importe quel agent du roster — le layout d'installation devient plat. Claude Code ne lit pas le nom d'une slash command dans le frontmatter : il le dérive du chemin sous ~/.claude/commands/, un segment : par dossier traversé. L'arbre reproduisait jusqu'ici la catégorie de rangement, si bien qu'appeler agathe demandait /ulk:agents:agathe — un segment qui disait où le mainteneur avait classé le fichier, pas ce que l'utilisateur voulait appeler, et qu'il fallait pourtant connaître pour taper la commande. Seul bruce y échappait, par un alias racine posé à la main. Les 92 agents s'installent désormais en commands/ulk/<nom>.md ; la catégorie continue de gouverner la source (rangement, sphères du site, parcours du générateur) et ne gouverne plus l'invocation. Trois trous que l'aplatissement ouvre sont fermés avec lui, aucun ne se serait signalé seul : un name: devient globalement unique — deux homonymes viseraient le même fichier, le second écrasant le premier sans que le générateur baisse d'un cran son compte d'écritures, d'où le refus de collision avant écriture ; le pruning de --with-vps n'a plus de dossier commands/ulk/vps à supprimer et passe par le module_flag du registry, agent par agent, donc ajouter un agent VPS ne demande plus rien côté Go ; et une mise à jour depuis l'ancien layout gardait tout l'arbre par catégorie sur disque, fsCopyDir écrivant sans jamais effacer — l'utilisateur aurait hérité de /ulk:agathe et d'un /ulk:agents:agathe figé à la version installée ce jour-là. Le nettoyage énumère les sous-dossiers plutôt qu'une liste de noms d'époque, pour que le prochain changement de layout se nettoie tout seul. 613 mentions réécrites dans les surfaces vivantes depuis la table exacte du registry, jamais par regex sur la forme ; CHANGELOG, CREDITS et rapports laissés intacts — ils datent ce qui était vrai à leur date. Deux garde-fous nouveaux au pre-push : l'arbre compilé n'a aucun sous-dossier, et les noms d'agents sont uniques

  • mobile: l'outillage Android et Flutter entre au cli-registry.jsonflutter, dart, fvm, melos, adb, avdmanager, gradle, bundletool, ktlint, detekt (registre 2.3.0 → 2.4.0, 136 → 146 outils). Andreide vérifiait déjà quatre d'entre eux par command -v, dans sa propre table : ça marchait dans l'agent, et nulle part ailleurs — _shared/cli-tools-protocol.md n'avait rien vers quoi router, aucun autre agent ne pouvait s'y appuyer, et ulk check ne savait pas dire qu'il manquait un SDK. Une vérification locale à un agent n'est pas une capacité du toolkit. La table de 48-andreide.md devient un renvoi au registre, par cible (#687)

  • cli: ulk check lit le registre selon la stack du répertoire courant. Il ne le lisait qu'avec --impact ; son rapport venait d'une liste de douze CLIs en dur dans status.go, si bien que déclarer flutter au registre ne suffisait pas à ce qu'il en dise un mot — le critère d'acceptation de #687 tenait à un endroit que #687 ne touchait pas. stackProbes mappe un fichier-marqueur (pubspec.yaml, build.gradle, build.gradle.kts) vers l'agent qui porte cette stack, jamais vers une liste d'outils : ceux-ci sont collectés dans cli-registry.json par required_by, donc un outil déclaré au registre y remonte sans une ligne de Go. Ajouter flutter à keyTools aurait rebâti le même mur une rangée plus haut, et laissé la stack suivante aussi aveugle. Mesure sur un projet Flutter : stack reconnue, 22 outils rapportés contre 12 ; hors projet mobile, le comportement ne bouge pas (12, aucune stack). Cinq tests le tiennent, dont un qui interroge le vrai registre — une fixture seule passerait pendant que ulk check resterait aveugle sur une machine réelle (#687)

  • mobile: les deux cibles d'andreide se séparent en fichiers d'action — andreide-actions/kotlin-compose.md et andreide-actions/flutter.md — chacun portant sa détection, son outillage, sa boucle de vérification et ses skills. Un agent bi-cible ne peut pas être routé par cible ; la réponse n'est pas deux agents opus, c'est un fichier par cible, en application de la règle de #688 (l'unité de variation d'ulk est le fichier d'action, pas l'agent). Le roster ne bouge pas, le corps passe de 359 à 264 lignes, et une session ne paie plus le contexte de la cible qu'elle ne construit pas. Le pendant Flutter de woz (93) est écarté par la même règle : l'audit passe par sargeras (45) et ed209 (52), le repli est écrit dans les deux fichiers plutôt que sous-entendu (#687)

  • site: le Panthéon ouvre une seconde entrée, par métier (/pantheon/metier/<clé>/). L'axe existait déjà — category est rempli sur tout le roster — mais il n'ouvrait aucune page, si bien que /pantheon affirmait que « les catégories techniques du registre classent par nature, les sphères par usage » sans que rien ne mène à cette autre classification : chercher « les agents design » demandait de visiter six pages. site/src/data/metiers.json lui donne un libellé et une meta sur le modèle de spheres.json, source unique dont generate-jeu.mjs refuse de dériver si une catégorie du registry n'y figure pas (sondé failable). Douze pages, une liste en bas du Panthéon, un lien retour depuis chaque fiche d'agent. Les cartes y gardent la couleur de leur sphère d'origine : sur /pantheon/metier/frontend/, les sept agents s'affichent sur trois sphères — la dispersion se voit au lieu de se raconter (#692)

  • gates: phase: devient une liste fermée. generate-registry.cjs refuse désormais une valeur hors des sept du cycle, un doublon, ou une quatrième phase — le même mécanisme que sphere: juste au-dessus, qui avait laissé quarante valeurs fausses s'installer faute d'un moyen d'avoir tort à voix haute (#692)

  • evals: les jeux de mesure de déclenchement des skills entrent dans le dépôt. Les quinze jeux de 16 requêtes rédigés pour le banc d'essai de #664 vivaient dans le scratchpad de leur session ; il a expiré, et #669 promettait depuis une mesure « sans travail de rédaction » sur des fichiers qui n'existaient plus — ce qui manquait n'était pas l'exécution, c'étaient les jeux. Les dix visés sont réécrits sous framework/evals/trigger/, et non à côté des skills : hermes/install.sh rsync le dossier skills/ entier vers le vault Obsidian de l'utilisateur, un evals/ par skill l'aurait suivi. Chaque négative porte un champ sibling nommant la skill sœur dont elle est tirée — run_eval.py l'ignore, et c'est le seul contrôle mécanisable de la règle qui fait la valeur de la mesure : une négative qui cesse d'être une quasi-collision rend le taux de faux positifs flatteur sans que rien ne le signale, et c'est ce taux que #664 publie à 0 % des deux côtés. run-trigger-eval.sh impose les trois conditions que #669 déclare non négociables au lieu de les rappeler — séquentiel, racine d'évaluation jetable, choix d'un Python 3.10+ que le python3 de macOS ne satisfait pas — parce qu'un opérateur qui les oublie n'obtient pas une erreur, il obtient un chiffre faux (#669)

  • gates: eval-trigger-sets.test.mjs au pre-push — forme du tableau attendue par run_eval.py, 16 requêtes dont 8 positives, aucun doublon interne, sibling présent sur chaque négative et résolvant vers une skill hermès réelle, jamais vers la skill mesurée elle-même

  • evals: run-trigger-eval.sh refuse de mesurer depuis un environnement qui fausserait son résultat, et c'est le point le plus important que le pilote a établi. Rejouer checkpoint a rendu 0 % de rappel — le symptôme que #669 décrit comme artefact et non comme signal. Test de contrôle : ci-fix, que #664 chiffre à 100 %, rend 0 % dans le même environnement, à jeu, description et racine identiques. Deux causes cumulatives, toutes deux propres à un poste de travail équipé d'ulk : la commande temporaire que run_eval.py dépose concourt avec ~200 slash commands dont le roster entier — peon, robocop, godspeed couvrent exactement le territoire des skills mesurées — et neuf hooks SessionStart s'injectent dans chaque claude -p, dont un qui énonce « avant de répondre, considère l'agent pertinent — Pivots : bruce, godspeed, shuri, task-runner, robocop, peon ». Ce que ça change à #669 : le reste n'est pas « lancer 6 400 appels », c'est obtenir un environnement de mesure d'abord. Un CLAUDE_CONFIG_DIR jetable isolerait les deux causes mais emporte l'authentification (Not logged in, vérifié). Deux artefacts de moindre rang trouvés au passage : la « racine d'évaluation vide » de #669, prise au pied de la lettre, produit un dossier sans projet où « est-ce que je peux pousser ? » se répond par ls -la && git status sans jamais appeler la skill — d'où framework/evals/fixture/, un projet ordinaire que le script déploie en dépôt git jetable ; et run_eval.py annote en str | None, que le python3 3.9 de macOS refuse à l'import. La signature commune de ces pannes est ce qui les rend coûteuses : toutes les négatives passent, faute que rien ne déclenche jamais, et le tableau affiche 0 % de faux positifs — la métrique qu'on surveille — en ne mesurant rien

  • site: chaque arcane porte désormais sa fonction — le métier en trois à six mots, sans figure à décoder. Naviguer le panthéon suppose de reconnaître WarCraft, Alien, Tolkien et X-Files : la porte est ouverte techniquement et fermée culturellement, et le critère de sortie de #682 demande qu'on comprenne à quoi sert chaque agent sans quitter la page. fonction: entre au frontmatter des agents et voyage jusqu'aux cartes par la chaîne déjà en place — parse-agent.cjsregistry.jsonjeu.json → fiches — plutôt que par une table d'affichage à côté, dont #683 vient de montrer qu'elle finit par contredire sa source. Trois surfaces l'affichent, et chacune corrigeait un manque distinct. Le recto des cartes de sphère : firstSentence(rite) y tenait lieu de rôle, médiane 137 caractères et maximum 235 pour un -webkit-line-clamp: 3 (TarotCard.astro § .arcane-rite) — le texte était donc coupé sans que rien ne le dise, et il tombe à 40 caractères au pire sur les Juges. La fiche d'agent : la fonction s'insère sous le nom, avant l'épithète, si bien que qui n'a pas la référence sait quand même de quoi il s'agit sans descendre jusqu'au rite. Et /pantheon lui-même, qui n'affichait aucun agent — neuf sphères, douze métiers, et pas un nom d'arcane : le critère de sortie y était littéralement inatteignable. Ce qui s'y ajoute est une liste, jamais un troisième paquet de cartes : passé quelques dizaines d'entrées, la carte cesse d'être un raccourci de lecture et redevient un obstacle. La règle entre dans agents-naming.md en garde-fou 6 : le nom dit QUI, l'épithète dit QUOI, la fonction dit À QUOI ÇA SERT — trois couches, trois grammaires, et un nom déjà transparent en porte une lui aussi (deploy-vercel reste « déploiement sur Vercel »), parce qu'une colonne à trous ne se lit plus (#682)

Correctifs

  • gates: check-dispatch-model.cjs câble le --verbose que son en-tête documentait depuis l'origine. Biome signalait la variable comme morte ; le correctif mécanique était de la supprimer, mais c'est le drapeau qui avait raison et le code qui manquait — le fichier promettait une sortie détaillée à qui la demanderait, et ne rendait rien. Ce qu'il manquait n'était pas cosmétique : l'oracle compte les dispatchs réellement examinés, or un gate devenu inerte — parsing cassé, périmètre vidé — passe au vert exactement comme un gate satisfait, et rien dans sa sortie ne les distingue. La ligne de succès porte désormais le compte (439 fichiers audités, 17 dispatch(s) examiné(s)), et --verbose nomme les 15 fichiers qui en portent. auditFile gagne un accumulateur optionnel : sa signature de retour ne bouge pas, donc les deux consommateurs de module.exports sont intacts. Reste non traité : le fichier n'a toujours aucune suite de tests, alors qu'il est le seul gate de #685

  • gates: les deux autres oracles de dérive du site jugent l'index git, et le geste se factorise. Le correctif d'index posé sur generate-jeu.mjs valait pour ses voisins de la même chaîne : generate-content.mjs --check (#666, les fiches d'agents) et generate-docs-spheres.mjs --check (le tableau des sphères de /docs/) comparaient eux aussi au disque, donc à un état que le commit n'embarque pas dès qu'on committe partiellement. Le troisième trou était le moins visible : generate-content.mjs inventoriait les dossiers de fiches par readdirSync, si bien qu'un dossier obsolète encore versionné passait inaperçu s'il avait déjà été supprimé localement, et qu'un dossier créé sans être stagé faisait rougir un commit qui ne le contenait pas. Sous --check, les trois générateurs lisent désormais sources, sorties et inventaire dans l'index (git show :<path>, git ls-files) ; hors --check, et hors dépôt git, ils lisent et écrivent le disque, inchangés — un générateur produit ce que le disque dit, et c'est le disque qu'il purge. La lecture versionnée cesse d'être recopiée dans chaque script : elle vit dans site/scripts/lib/versionne.mjs, une implémentation unique portant sa propre motivation, que les trois importent. Sondé sur les trois oracles et les trois formes de dérive — spheres.json modifié, une fiche d'agent réécrite, un dossier fantôme — non stagée → 0 sur les trois, stagée → 1 sur les trois (#700)

  • cli: ulk wt done cesse de déclarer « non mergée » une branche mergée, et d'enseigner -D là où il ne sert à rien. git branch -d a deux motifs de refus, et le code les attribuait tous au premier : la branche n'est pas intégrée, ou bien elle l'est mais elle a un upstream — auquel cas git compare à origin/<branche>, pas à HEAD, et une ref de suivi en retard suffit à faire refuser une branche parfaitement intégrée. Git le dit lui-même dans le texte du refus (« even though it is merged to HEAD ») ; l'information était là, et elle était jetée. C'est le chemin heureux qui produit ce faux message, pas un cas limite : wt new → push → PR → merge en local → la ref distante reste en arrière. La commande se trompait donc systématiquement là où tout s'était bien passé, et le remède qu'elle affichait était le geste destructeur — inutile sur ce cas, et coûteux sur l'autre, celui où wt done protège délibérément du travail non intégré (politique #228). Un outil qui a tort sur le chemin heureux apprend à ne plus être lu, et c'est le message qui protège qu'on cesse alors de croire. Le fait est désormais établi avant d'être dit : wtDefaultBranch lit la branche par défaut depuis refs/remotes/origin/HEAD — jamais « main » en dur, repli sur la branche courante — puis merge-base --is-ancestor tranche, et sans référence lisible le message ne conclut pas plutôt que de réaffirmer « non mergée » par défaut. Le remède annoncé sur le cas mergé n'est pas celui que la carte supposait : git fetch --prune ne purge la ref que si la branche distante a disparu ; quand elle existe encore et n'est qu'en retard — dès qu'un commit local n'a pas été poussé avant le merge — le prune ne change rien et le refus persiste, mesuré dans les deux sens. C'est git branch --unset-upstream qui est annoncé : il retire la comparaison fausse sans retirer le fail-safe, vérifié par un test dédié qui exige que -d refuse toujours une branche non intégrée après. Le défaut avait passé parce que la fixture ne pouvait pas l'atteindre : TestWtDoneFlowRemovesWorktreeKeepsUnmergedBranch fabriquait une branche sans upstream, donc sans remote, donc sans le second motif de refus — le cas 2 n'était pas exprimable. newTestRepoWithRemote monte le bare local et pose origin/HEAD comme le ferait un clone ; cinq tests couvrent ce qui n'était pas atteignable (#698)

  • gates: jeu.json ne peut plus être committé périmé. site/src/data/jeu.json porte les 92 cartes du jeu du site — nom, sphère, office, invocation — et se dérive intégralement du registry, mais son générateur ne tourne qu'en prebuild : le build le régénérait en local avant de compiler, donc il passait vert quel que soit l'état du fichier committé. C'est la forme coûteuse de l'absence de gate — non pas un contrôle qui manque et se voit, mais un contrôle qui semble exister parce que le générateur tourne, et dont le passage ne dit rien du dépôt. Constat sur #689 : un merge a repris la version de main et les 92 cartes ont recommencé à annoncer /ulk:agents:<nom>, une forme qui n'existe plus ; le pre-commit affichait bien ✓ site content up to date (92 fiches), mais il parlait des fiches d'agents. Repéré par un grep à la main. check-jeu.mjs, qui tourne dans la même chaîne, n'aurait pas pu le voir : il vérifie la conformité des cartes (10 sphères, monochromes), pas leur fraîcheur — les cartes périmées étaient parfaitement conformes. Le correctif reprend le modèle posé par #666 sur les fiches d'agents : generate-jeu.mjs --check n'écrit rien, compare au fichier versionné et sort 1 sur écart, appelé depuis le pre-commit en section 3septies. Le point de comparaison existait déjà — le script était idempotent et testait avant === rendu avant d'écrire ; il ne manquait qu'une branche. Sous --check, sources et jeu se lisent dans l'index git (git show :<path>), jamais sur le disque — même geste que generate-credits.cjs (#453) : un hook juge ce que le commit embarque, et les deux divergent dès qu'on committe partiellement (git commit -- <pathspec>, git add sélectif), le hook tournant alors sur un index temporaire qui vaut HEAD hors le pathspec. Lire le disque rendrait un verdict sur des fichiers absents du commit — faux dans les deux sens : vert alors qu'un jeu.json périmé part au commit, rouge sur un index pourtant cohérent. Sondé en échec avant d'être déclaré posé, sur les trois états : périmé non stagé → 0 (le commit n'embarque rien), périmé stagé → 1, restauré stagé → 0. La génération reste au prebuild, où elle a sa place (#700)

  • agents: ripley (05) cesse d'auditer les projets, geste qui appartenait déjà à sargeras (45). Les deux portaient un audit complet de codebase et deux description: également plausibles : un utilisateur qui voulait « auditer son projet » n'avait aucun critère pour trancher, et la table de routage de bruce entretenait la confusion en offrant audit code → ripley et audit omniscient → sargeras, deux formulations que rien ne distingue côté utilisateur. Ce qui départage les deux agents n'est pas leur intitulé mais leur outillage : sargeras est opus + effort: xhigh, détecte la stack, score dix axes et porte un dossier sargeras-actions/ ; ripley portait 398 lignes monolithiques dont un second pipeline — Phases A1→A5, huit dimensions, scoring — qui refaisait le premier en moins bien. L'arbitrage retenu ne replie pas ripley sur sargeras : son mode simplify est réellement distinct, il applique des changements là où un audit documente, et le supprimer aurait coûté un agent publié, sa fiche de site, trois thèmes du jeu et le câblage de sept agents pour régler un problème d'affichage. Le pipeline d'audit sort, le pipeline de simplification reste, et la frontière est écrite dans les deux sens (phase: review, buildbuild, périmètre d'écriture réduit à docs/reports/**). Les dix sites qui appelaient ripley mode=audit — blackemperor sur trois modes, 23-phase-qualite, context-protocol, routines-protocol, bundles/backend, legacy-revival — pointent vers sargeras ; un mode qui n'existe plus n'est plus dispatchable. Deux scories tombent avec : la description de ripley narrait une fusion de 2026 en citant code-auditor et code-simplifier, deux noms morts chargés en contexte à chaque session, et l'ancien nom vision occupait encore la position d'affichage sur ~30 surfaces vivantes dont la table de routage — l'inverse exact du garde-fou 4 de agents-naming.md, qui veut le nouveau nom affiché et l'ancien résoluble en silence. vision reste alias d'invocation, comme prévu par ce garde-fou (#691)

  • gates: routing-table-names.test.mjs au pre-push — 29-table-routage.md est chargée à chaque message utilisateur, ce qui fait d'une dérive locale un coût par tour. Trois invariants : tout nom (id) cité existe dans registry.json sous son name — un alias en position d'affichage rougit —, l'id cité est celui du registry, et le schéma d'identifiants abandonné NN-categorie/NN est refusé. Il attrape les deux défauts que #691 a trouvés dans ce seul fichier : vision (05) survivant au renommage de #443, et khadgar (15-frontend/02) là où le registry donne 2. Sondé failable sur les trois formes de retour avant d'être posé

  • gates: release-bump.test.mjs mesure enfin la fenêtre qu'il nomme. Sa non-régression #680 s'annonçait « v8.0.1..v8.1.0 » et invoquait release-bump.sh v8.0.1 — or le script court jusqu'à HEAD, si bien que la fenêtre mesurée s'allongeait à chaque commit et valait 44 commits de plus que celle du titre. Elle rendait « minor » tant qu'aucune rupture n'y entrait : le premier feat!: du dépôt (#689) l'a fait tomber en disant vrai sur une fenêtre que personne ne voulait mesurer, et aurait bloqué toute rupture future de la même façon. release-bump.sh prend désormais une borne haute optionnelle, le test la passe, et un dépôt jetable vérifie qu'un refactor!: postérieur à la borne ne compte plus — ce qu'aucun test ne pouvait exprimer tant que la borne n'était pas un argument

  • credits: la licence publiée pour flutter-tester et owasp-mobile-security était fausse, et leur URL amont morte. CREDITS.md les donnait en BSD-3-Clause quand OWNERSHIP.md et 48-andreide.md disaient MIT — trois enregistrements, deux licences pour les deux mêmes fichiers. L'upstream tranche : Harishwarrior/flutter-claude-skills est MIT (© 2025 Flutter Claude Skills Contributors), et le dépôt publié dans les deux registres — Harishwarrior/claude-code-skillsrend 404, il a été renommé. Le mécanisme de la dérive est nommable : le familyOverrides.flutter de credits-manual.json ne remplit que les champs vides d'un frontmatter, or ces deux skills n'en déclaraient aucun — la licence BSD-3-Clause des dix skills officielles débordait donc sur les deux communautaires. Le correctif est à la source : license: MIT dans leur frontmatter, URL corrigée, et le LICENSE amont déposé sur disque à côté de LICENSE-flutter-official. C'était le seul point de #687 dont la portée dépasse le dépôt (#687)

  • skills: OWNERSHIP.md déclarait 2 skills Flutter pour 12 sur disque, et 2 skills Kepano pour 5. Le contrôle de dérive des credits ne regarde pas ce fichier — c'est ce qui a laissé les deux écarts tenir sans signal. Les 18 sections ont été remesurées : 16 justes, 2 fausses, corrigées avec leurs deux sources chacune et les licences vérifiées à l'upstream (Kepano : obsidian-skills et defuddle, tous deux MIT — la licence publiée était juste, le compte et l'URL non). Le balayage rend un troisième constat, laissé ouvert faute d'appartenir à ce lot : 25 dossiers de skills sur disque n'ont aucune section ici, si bien qu'« absent d'OWNERSHIP.md » ne distingue pas « maison, rien à surveiller » d'« oublié ». Le remède durable est un gate qui compare ce fichier au disque, pas une relecture annuelle (#687)

  • skills: ULK-081 n'existe pas — ni issue, ni carte de backlog, ni flag --profile dans install.sh. OWNERSHIP.md y renvoyait trois fois comme au correctif de l'installation par défaut des skills Swift et Flutter ; l'arbitrage est donc en suspens depuis, sans porteur. Les comptes de la table de décision ULK-085 ont dérivé dans le même angle mort et sont remesurés : Swift 7 → 13, Flutter 2 → 12, Obsidian 2 → 5. L'incohérence que la décision acceptait de reporter porte aujourd'hui sur 25 skills de plateforme installées par défaut, contre 9 quand le statu quo a été choisi (#687)

  • cli: ulk agents stats cesse de couper en deux un même ensemble de phases. Il groupait par la chaîne entière du champ, si bien que build, review (minitel) et review, build (ripley) — le même ensemble — sortaient sur deux lignes : quatorze seaux pour sept valeurs. Le correctif que #692 prescrivait était d'imposer un ordre canonique au frontmatter ; il a été implémenté puis retiré, parce qu'il repose sur une prémisse fausse de l'issue — que phase serait de la métadonnée morte. officePrincipal() (site/src/lib/doctrine.mjs) lit la première phase d'un champ composite pour en tirer l'office de l'arcane et sa seconde encre, visibles sur chaque fiche du site : trier le champ faisait passer ripley, qui auditait alors, de « Verdict » à « Forge », et son encre de BLEU SEUL à BLEU + ROSE — mesuré sur jeu.json avant retour en arrière. #691 a depuis fait passer ripley en build mono-phase, ce qui le sort de la démonstration sans rien changer au fond : le même tri ferait passer astride, review, define, de « Verdict » à « Définition », et sept autres composites portent un ordre qui dit quelque chose. Le champ portait deux informations, l'ensemble et la primauté, et un seul consommateur en ignorait une. Le tri vit donc là où il manquait, au regroupement (phaseBucket, internal/registry/agents.go) : quatorze seaux ramenés à treize, aucun frontmatter touché, aucune carte modifiée. Deux tests Go ancrent la propriété — même ensemble, même seau — plutôt que l'implémentation (#692)

  • site: site/src/data/descriptions-fr.json est supprimé, son contenu remonté dans le frontmatter des agents. La couche existait pour traduire un registry anglais ; elle en doublait un français depuis sept semaines. 47 de ses 50 entrées recopiaient une description déjà en français, ce que son propre $comment interdisait. La cause n'est ni une duplication de commodité ni une captation des corrections au fil de l'eau — les deux hypothèses de la carte, l'une et l'autre infirmées par la mesure : 29 des 44 doublons n'avaient jamais été retouchés depuis leur création, et 27 avaient été créés d'un seul geste. Ce que dit le git log : c1abcd3d (2026-07-06) traduit 42 frontmatters, régénère le registry et supprime le fichier ; 15e3963e (le lendemain) rétablit la couche en remettant registry.json — un arbre généré — sans toucher un seul fichier de framework/ ; ee3c74a5, le même jour, régénère le registry depuis les frontmatters restés français et efface ce retour en arrière. La couche était orpheline dès son deuxième jour. Une copie que rien ne tient à sa source finit par la contredire : cinq modes annoncés pour blackemperor contre six au registry, un renvoi vers friday archivé chez brigitte, un renvoi vers verify inexistant chez brienne. Les 27 descriptions où la couche disait mieux que la source — dont les réécritures de voix du 2026-08-28 sur sargeras, ed209, peon, robocop — sont remontées telles quelles ; les 23 où le registry disait mieux sont conservées. Le gabarit de description: passe au français : les charnières Use for / Not for, seule justification restante d'une traduction pour 13 agents, disparaissent des frontmatters comme des règles (agents-authoring.md, discovery-protocol.md) et du scoring de description-audit.py, dont les verbes d'action et les mots d'exclusion étaient anglocentrés. Garde-fou : site-description-layer.test.mjs au pre-push, sondé failable sur les trois formes de retour (couche sous un autre nom, charnière EN réinjectée, câblage rétabli) — il porte sur le mécanisme, un roles-fr.json rouvrirait la même brèche. Au passage, description-audit.py ne s'exécutait plus du tout sous le Python 3.9 de macOS (str | None en annotation, sans from __future__ import annotations) : l'outil que deux règles citent comme moyen de vérification était mort

  • gates: hardcode-check.sh exempte framework/evals/fixture/, bornée à ce dossier. La fixture est la racine où tournent les salves de mesure, et hardcode-scan fait partie des dix skills mesurées : elle doit porter une URL d'environnement et une valeur magique, sinon la requête « il reste des secrets en dur ? » n'a pas de terrain. Le pragma # nocheck n'était pas une option ici pour une raison propre au cas — la fixture est lue par le modèle sous test, et une annotation ulk visible dans son code l'orienterait ; elle doit rester un projet ordinaire. Deux tests ancrent la borne, pas l'exemption : framework/evals/trigger/ reste scanné, un vrai secret dans un jeu de requêtes serait toujours bloqué

  • agents: aucun des 33 sites de dispatch du dépôt ne portait de model:, et le sous-agent héritait donc du modèle de la session. Le patron employé partout — subagent_type: "general-purpose" puis Read agents/NN-nom.md — ne transmet rien au harnais : le model: du frontmatter de l'agent cible est du texte que le sous-agent découvre une fois démarré, et general-purpose n'ayant pas de modèle propre, l'appel retombe sur la session. Conséquence de coût, invisible parce qu'elle ne casse rien : Bruce tournant sur opus dispatchait godspeed — agent haiku, diagnostic read-only — sur opus, comme toutes ses collectes. worktree-protocol.md avait déjà noté que le frontmatter est « purement documentaire » dans ce patron, pour isolation:, sans le tirer jusqu'au modèle. Les 16 sites vivants portent leur tier, dérivé du frontmatter de la cible quand il y en a une (registry.json fait foi) ou de la table tâche → tier sinon ; generate-registry.cjs produisait lui-même le patron non conforme — la dérive était générée, pas subie — et produit désormais le paramètre. Deux fichiers de doctrine affirmaient de surcroît que general-purpose « utilise Sonnet par défaut », ce qui rendait l'omission rassurante : corrigés. Gate C14 dans agents-coherence.test.mjs, qui refuse un dispatch sans model: et une version de modèle en dur — la règle alias-only vaut au dispatch comme au frontmatter. Aucun agent du roster modifié (#644)

  • backlog: le mode OpenRouter demandé par #644 est écarté sur vérification, pas sur préférence. La carte partait de « la couche d'indirection existe, il ne manque que la table » : faux deux fois — la table existe aussi, nativement (ANTHROPIC_DEFAULT_{OPUS,SONNET,HAIKU}_MODEL), et ce qui manque n'est pas du code ulk mais l'autorisation du harnais, Anthropic ne supportant pas de router Claude Code vers des modèles non-Claude quelle que soit la gateway. framework/tools/model-map.json aurait réinventé un mécanisme natif pour desservir un usage non couvert. Le multi-fournisseur n'existe que dans un harnais qui sait router : c'est un cas d'usage de l'axe harnais (#639/#641), pas une carte autonome. Reste ouvert et noté : ma.go porte api.anthropic.com et un défaut claude-sonnet-5 en dur — seul endroit du code d'ulk qui choisit vraiment un modèle

  • gates: l'exemption Google Fonts de hardcode-check.sh exigeait un « / » après l'hôte, ce qui ne couvrait que la feuille de style elle-même. Les deux <link rel="preconnect"> qui la précèdent visent les mêmes hôtes, sont émis par la même constante, et annoncent la connexion que la ligne suivante ouvre — ils restaient signalés comme URL en dur. Exempter un côté et pas l'autre reproduisait exactement l'asymétrie que ce bloc corrige, et poussait à désarmer la règle plus largement pour s'en débarrasser. Motif élargi aux quatre terminaisons possibles (/, guillemet, apostrophe, espace), avec le test de non-régression qui manquait — celui qui existait ne vérifiait que le cas inverse, qu'un autre hôte reste bien signalé

  • release: le calcul auto de version de release.sh grepait « BREAKING CHANGE » dans le corps entier des commits — la chaîne matche aussi quand un commit la cite (a6d487dc la mentionne comme intitulé de section à traduire), et la fenêtre v8.0.1..HEAD de la release v8.1.0 aurait coupé un v9.0.0 fantôme. Défaut symétrique : la forme feat!: n'était pas détectée du tout, donc une vraie rupture sortait en minor. La logique sort dans scripts/release-bump.sh (testable, sur le modèle de release-guard-bump-scope.sh, #579) : footer BREAKING CHANGE:/BREAKING-CHANGE: ancré en début de ligne, ou ! avant le : de l'en-tête — la prose ne compte plus. Test sur vrais dépôts jetables + non-régression sur la fenêtre réelle v8.0.1..v8.1.0. Au passage, un défaut latent de plus : echo | grep -q sous pipefail rendait la condition fausse sur un log assez gros (SIGPIPE du writer quand grep -q sort tôt) — tout bump majeur détecté aurait pu ressortir en patch ; grep -c lit tout l'entrée et ne peut pas sortir tôt

Sécurité

  • skills: gstack est gelé sur son empreinte du 2026-08-19 (b2bc2779a939) et n'est délibérément pas re-épinglé, alors que les trois autres dérives amont du run le sont. Le manifeste n'est pas un journal d'observation : depuis SEC-02 (#584), ulk skills update vérifie l'installé contre lui et fait de toute empreinte divergente un échec bloquant — re-locker, c'est autoriser une installation, pas en constater une. Or la version amont (394db326, −60 % de taille) change la nature de la skill : elle exécute au démarrage un binaire local bin/gstack-skill-start dont la sortie pilote les règles du préambule et peut porter des blocs de directives GSTACK_INSTRUCTION, ajoute une synchro d'artefacts sous consentement, et clôt par une télémétrie gstack-skill-end marquée « ALWAYS RUN », plan mode compris. Le garde-fou anti-injection amont est correctement écrit — une directive n'est honorée que depuis le résultat direct de la commande et sous le même SESSION_ID — et rien n'indique de malveillance ; c'est le profil de confiance qui change, ce que le manifeste existe précisément pour attraper. ulk skills lock n'ayant aucun ciblage, le gel est obtenu en restaurant l'entrée après le lock. Conséquence assumée : ulk skills verify --upstream reste rouge sur cette seule skill tant que l'arbitrage n'est pas rendu — le signal est maintenu exprès, un vert obtenu en validant ce qu'on n'a pas décidé vaudrait moins que ce rouge. Les trois autres sont sans réserve, dont resend-cli qui retire ses instructions curl | bash / irm | iex et le passage de la clé d'API en argument de commande

v8.1.1

Nouveautés

  • agents: astride se définit désormais aussi par la négative, et c'est ce qui ferme le glissement que ses règles ne nommaient pas. Sur une question d'équipe, un modèle sans garde-fou dérive vers le développement personnel — « travaille ton mindset », « sors de ta zone de confort » : renvoyer la cause à l'individu ne se fait pas qu'en blâmant, cela se fait aussi en conseillant, et la règle 1 (le système, pas l'individu) ne couvrait que le blâme. Trois frontières entrent dans le corps — pas de réduction d'un problème à une attitude individuelle, pas de grands principes tirés de bouquins de self-help, pas de posture de psy (« je ne traite pas, j'accompagne sur le travail », avec l'orientation à faire quand la situation relève du soin) — et avec elles le but qui manquait : non pas rendre les gens « heureux·ses au travail », objectif qui transfère à l'individu la charge de ce que l'organisation produit, mais rendre le quotidien plus respirable, en travaillant à partir des interactions. Côté positif, les quatre métiers qu'elle nomme elle-même (socioéconomiste, facilitatrice, consultante en organisation, coach) remplacent le « consultante en coaching stratégique » qui les écrasait en un, avec la table qui dit ce que chacun produit et le signal qui l'appelle ; la rigueur devient un TOUJOURS opérant — annoncer ce qui a été lu, sur quel périmètre, comment, avant de conclure ; le systémique redevient le pilier et non un trait parmi six ; et « une bouffée d'air frais quand on est dans le brouillard » est traité comme un critère de sortie, d'où la tension avec l'exhaustivité héritée, tranchée dans le corps plutôt que laissée au hasard : hiérarchiser, pas amputer. context_budget 8000 → 9000, la définition seule pesant désormais ~7,9 k tokens — un plafond qui ne plafonne plus n'en est pas un. Golden test : les deux sections nouvelles en required_sections, cinq ancres textuelles en required_patterns, sans quoi un refactor de persona effacerait la distinction qui définit le métier sans qu'aucun test ne bronche

Correctifs

  • agents: la table de routage de bruce envoyait encore vers l'astride d'avant. Trois lignes proposaient une « revue de code snob » (mode=review), une « parodie McKinsey » (mode=consultant) et un mode=roast — trois modes que l'agent ne porte plus, et dont le premier est exactement le registre que sa persona interdit désormais. Le point d'entrée du roster décrivait donc un agent qui n'existe plus, pendant que son usage principal — lecture organisationnelle, coaching d'équipe — n'était routable par aucune formulation. Quatre lignes exactes remplacent les trois, sur les commandes que l'agent porte réellement : astride review, astride advice, astride roast, astride consultant. Même dérive corrigée dans framework/agents/Readme.md, qui résumait encore astride par « Code review sarcastique + conseils vraie vie »
  • site: astride portait une entrée dans descriptions-fr.json alors que sa description de registry est déjà en français — le cas que le $comment du fichier exclut explicitement. La copie avait dérivé (« turnover » là où la source dit « désengagement », guillemets droits contre chevrons) et c'est elle, pas la source, qui alimentait la fiche du site et le rite du jeu. Entrée retirée : les deux surfaces retombent sur la source unique

v8.1.0

Nouveautés

  • agents: charon (92), passeur SPIP → Astro — la skill /spip2astro entre au catalogue derrière --with-spip2astro. Le plugin Spip2Astro fait déjà la traversée côté serveur ; ce qui manquait est ce qui l'encadre. L'agent inventorie les deux rives avant l'export (volumes, groupes de mots, logos par voie SPIP 4 et par scan legacy IMG/arton42.jpg, URLs propres), lit le spip2astro-manifest.json plutôt que l'absence d'erreur, extrait la table spip_id → chemin sans laquelle aucun second export n'est rejouable ni aucune redirection générable, et clôt sur quatre contrôles chiffrés — liens internes non résolus, documents manquants, comptage par collection, astro check/build. La skill porte ce que le plugin ne fait pas : reference() entre collections (authors et rubrique sortent en z.string(), donc un lien mort passe le build), redirections des anciennes URLs, import Zod déprécié depuis Astro 6, et le contenu des pièces jointes — confié à markitdown en CLI, pour indexer et jamais pour republier, l'amont annonçant lui-même une sortie destinée aux outils d'analyse de texte
  • agents: woz (93), auditeur SwiftUI — applique les 16 axes de la guidance vérifiable d'Apple à du code existant : sweep grep exhaustif, puis jugement de chaque hit contre les sections Do NOT flag de son axe, puis score de 1 à 5 par axe sur le seul périmètre déclaré courant. Comble un trou de phase : l'écosystème Apple d'ulk savait concevoir (jony 91), construire (isaac 27), monétiser (tim 81) et lancer (buzz 83), mais son unique relecteur était la phase 4 d'analyze-swiftui — un grep -rn "!" sur tous les .swift, sans gardes ni sévérité. Trois modes : audit (défaut, docs/audits/woz-<date>.md), miroir (banque de quiz, face-à-face déclaré vs observé), ciblé
  • skills: swift-apple-code-review entre au catalogue — corpus vendorisé depuis do-i-code-like-apple (Orka, MIT) : une règle par axe (motifs ERE en frontmatter, sous-règles numérotées avec sévérité et mode GREP/JUDGMENT, section Do NOT flag obligatoire, correctif de cinq minutes, références developer.apple.com), matrice COVERAGE.md (378 recommandations Apple → axe.sous-règle), banque de 25 questions, runner de sweep et gabarit de rapport HTML autonome. Vendorisé verbatim hors SKILL.md : une release amont se resynchronise par diff. Installée par défaut avec la famille swift/ (profils ios/mobile/full)
  • gates: apple-axes-fixture.test.mjs au pre-push — chacun des 16 axes doit se déclencher sur la fixture d'anti-patterns, les formes correctes ne doivent en déclencher aucun, et le sweep par grep -E -f doit retrouver les )! que l'expansion d'historique du shell mange en silence. Un motif ERE qui cesse de matcher ne lève aucune erreur : il rend l'axe vert par vacuité, et l'audit affirme alors « aucun finding » là où il n'a rien cherché
  • skills: /spip entre au catalogue — savoir génératif SPIP 4.1+ derrière --with-spip : squelettes (sections de boucle, pagination, {doublons} sur les deux boucles, récursion), balises et filtres (image_reduire avant image_recadre), <INCLURE> et {ajax} sur l'inclusion et non sur le critère, plugins (paquet.xml, pipelines, API sql_*, autorisations, objets éditoriaux), formulaires CVT et Saisies, fichiers de langue. Comble un trou que la comparaison avec epilibre-design/spip-skills a rendu visible : analyze-spip (18) audite un site existant mais ne portait aucun savoir génératif — sur « écris-moi une boucle paginée », ulk n'avait rien. L'agent cite désormais la skill (loads_skills: spip). Rédaction ulk, l'amont n'ayant aucun LICENSE : seuls trois motifs de forme sont repris (table de routage, glossaire des termes conservés, routage négatif), crédités dans CREDITS.md § Inspirations & patterns
  • gates: le pre-commit refuse un intitulé de section ### que LIBELLES_SECTION ne traduit pas. Allowlist inversée, sur le modèle de BARE_COUNT_ALLOW : traduire, ou exempter avec sa raison. Une liste d'intitulés anglais connus aurait laissé passer le prochain Chores — le réglage par défaut doit être l'échec, c'est le seul qui attrape ce qu'on n'a pas prévu
  • hooks: --with-session-persist — l'état de session survit à la session. SessionEnd (fin réelle : clear, logout, exit) et PreCompact écrivent un instantané mécanique dans .claude/state/session-persist/ — horodatage, déclencheur, branche, HEAD, arbre de travail borné, cinq derniers commits — que SessionStart relit s'il a moins de sept jours. Le trou qu'il ferme est un choix d'événement : memory-loop et handoff se branchent sur Stop, qui se déclenche à la fin de chaque tour d'assistant et non de la session, et tous deux se contentent d'un rappel — « lance peon », « lance /handoff » — qui n'aboutit que si quelqu'un le lit. La sortie d'un hook SessionEnd n'étant jamais affichée, celui-ci écrit au lieu de rappeler. Complémentaire de --with-handoff-hook, pas redondant : /handoff porte l'intention et coûte des tokens, ce hook porte les faits et n'en coûte aucun ; si HANDOFF.md est plus frais, SessionStart s'efface devant lui plutôt que d'afficher deux blocs
  • hooks: --with-compact-threshold — la règle 4 d'hygiène de contexte devient exécutable. Elle prescrivait /compact entre 50 et 60%, mais rien ne mesurait le contexte : l'auto-compact ne tombe qu'à 80%, après la dérive qu'elle veut éviter, et PreCompact ne peut pas combler le trou puisqu'il se déclenche par la compaction. Le hook lit le bloc usage de la dernière réponse dans le transcript (input + cache lu + cache écrit + output) — une mesure, pas une heuristique sur la longueur des prompts — et rappelle la règle au franchissement du seuil, avec escalade vers /clear au-delà de 80%. Le stdout d'un hook UserPromptSubmit entrant dans le contexte, l'anti-nag est structurel : un rappel par palier de 10% et par session, remis à zéro par PreCompact sans quoi une session longue ne serait plus jamais avertie après son premier franchissement. Réglages ULK_COMPACT_THRESHOLD / ULK_CONTEXT_WINDOW
  • gates: l'eval comportemental tire k fois et gate sur pass^k, pas sur pass@k. Le probe live est non déterministe et le runner le savait — il l'écrivait dans ses limites (« un échec isolé se rejoue avant d'être traité comme une régression »), c'est-à-dire qu'il déléguait sa propre statistique à la main de qui le lançait. ULK_BEHAVIORAL_K=n rejoue chaque scénario et rapporte les deux métriques, qui ne disent pas la même chose : pass@k mesure la capacité (la discipline est atteignable), pass^k la fiabilité (elle ne se relâche jamais). C'est la seconde qui gate, et le choix n'est pas cosmétique : pour un agent dont la valeur est la discipline, « il y arrive parfois » est un échec — un gate sur pass@k validerait exactement le comportement que les scénarios décrivent en RED. Seuil réglable par scénario (live_min_pass_rate, défaut 1), qui échoue fermé sur une valeur illisible (0,8 donnait NaN, donc un gate toujours vert). Le bras nu tire lui aussi k fois : la comparaison agent / modèle nu devient un écart de taux au lieu d'une anecdote. k=1 par défaut — le coût ne bouge pas sans demande explicite
  • gates: generate-reference-toc.cjs — cinquième et dernier contrôle de dérive documentaire du dépôt. Le skill-creator pose la règle : au-delà de 300 lignes, un fichier de référence porte un sommaire, sinon la lecture progressive n'en est plus une — le modèle charge les 1 814 lignes de css-patterns.md pour en utiliser 40, et le bénéfice du découpage en references/ est perdu. 38 fichiers en ont reçu un, dérivé de leurs titres ##/### et inséré entre marqueurs ; les 12 qui portaient déjà un sommaire écrit en amont sont laissés strictement intacts, en ajouter un second serait pire que rien. L'écriture est additive — aucune ligne d'origine touchée, ce qui compte puisque tout le périmètre est vendorisé. Deux pièges produisent un sommaire qui ment, et un sommaire qui ment coûte plus qu'un sommaire absent puisque rien ne signale l'ancre morte : GitHub ne fusionne pas les espaces consécutifs (« Modal / Sheet » perd son / et garde deux espaces, donc #modal--sheet-presentation — les sommaires amont du dépôt le confirmaient déjà), et les titres en clôture de code ne sont pas des sections (ces fichiers sont majoritairement des exemples). Vérifié : 1 051 ancres, 0 morte. --check au pre-commit
  • agents: les procédures de 25 agents descendent d'un cran — le corps garde le raisonnement et l'aiguillage, chaque procédure vit dans <agent>-actions/NN-slug.md, lue une à la fois, avec un index marqué en tête du corps. Ces lignes étaient chargées intégralement à chaque invocation, qu'elles servent ou non. Vingt-quatre agents passent sous 500 lignes ; seul bruce reste au-dessus (1 433 → 767) et c'est délibéré : ce qui lui reste est sa table de routage unifiée, son roster par rôle et ses commandes rapides, consultés à chaque message — les descendre reviendrait à sortir le routeur du routeur. Une ligne s'est dégagée en route et vaut pour tout le chantier : une phase descend, un contrat de sortie reste. Le premier essai a descendu les rapports finals d'ed209 et de sargeras ; les golden ont rougi sur les tables et les patterns requis, et ils avaient raison — un agent dont le contrat de sortie vit dans un fichier qu'on peut ne pas charger ne promet plus rien. Même raisonnement pour les règles qu'un agent doit appliquer à chaque interaction (khadgar, robocop) et pour les garde-fous du killswitch de picsou
  • gates: C12 (agents-coherence) apprend que le corps d'un agent s'étend à ses actions. L'invariant « extends: déclaré ⇒ cité dans le corps » a rougi sur quinze paires au découpage — non pas parce que le protocole avait cessé d'être appliqué, mais parce qu'il l'est désormais une couche plus bas. 56-picsou.md et picsou-actions/* sont un seul prompt, chargé en deux temps ; le gate ne regardait que le premier. L'élargissement ne l'affaiblit pas, il le rend juste : deux écarts gelés de longue date se sont révélés résorbés au passage (shuri / grilling-protocol, task-runner / memory-protocol, tous deux déjà découpés), et sortent de EXTENDS_ALLOW, qui ne peut que décroître par construction
  • skills: les 8 descriptions vendorisées qui disaient quoi sans dire quand sont réécrites sur le patron mesuré à +44 points de rappel — ce que la skill fait, quand l'utiliser avec les formulations réelles, où s'arrête son territoire. La réserve qui bloquait — réécrire diverge de l'upstream — ne tenait que pour deux d'entre elles : les six autres (caveman-output, context-mode, hardcode-audit, merge, nextjs-setup-better-auth, symbols) sont maison ou absorbées d'une inbox puis retravaillées, aucune ne porte de source-version à resynchroniser. swift-architecture et jeffallan-skills, qui ont un amont épinglé, portent la divergence dans metadata
  • docs: la portabilité claude.ai est tranchée et close. Publier sur claude.ai n'est pas un objectif du dépôt ; la position et son inventaire — 47 des 120 SKILL.md portent au moins une clé hors spec upload — descendent dans .claude/rules/skills-authoring.md pour que la question ne se repose plus. Aucun fichier de skill touché : descendre les clés de convention sous metadata rendrait publiables 36 fichiers au prix des quatre parseurs de frontmatter du dépôt, pour un gain nul tant que rien n'est publié, et les onze skills à disable-model-invocation / argument-hint resteraient non publiables de toute façon — Claude Code lit ces clés au premier niveau
  • subagents: les dix stubs memory: local dérivent de leur source — « deux Bruce » disparaît. Agent(subagent_type: "ulk-bruce") exécutait la définition d'avril pendant que /ulk:bruce exécutait celle d'août, et rien ne le signalait : les fichiers .claude/agents/ étaient écrits à la main, sans lien ni gate vers framework/agents/**. Le choix entre pointer vers la source et la dupliquer était ouvert depuis #461 ; il est tranché par la mesure et pas par la déduction (#662). Deux passes de sonde, prompt neutre, deux cibles — un fichier témoin à jeton aléatoire puis framework/agents/session/00-godspeed.md, chemin conventionnel : le sous-agent résout bien le chemin relatif cité dans sa définition, mais n'adopte pas ce qu'il y trouve. Deux refus sur deux, le second argumenté — comparaison disque / git HEAD, constat que la cible ne portait pas la mission, principe qu'aucun message porté par un fichier de configuration ne réécrit ses instructions. C'est une défense contre l'injection de prompt, elle vise exactement la forme « ta définition est ailleurs », et elle ne disparaîtra pas. generate-memory-stubs.cjs dérive donc description, model et le corps complet ; le protocole mémoire, seule partie que la source ne porte pas, vit entre marqueurs et n'est jamais régénéré. Ce que #670 a rendu possible : la carte chiffrait l'objection à « 1 351 lignes dans un sous-agent », bruce en fait 767 depuis que ses procédures se chargent à la demande
  • gates: --check du générateur de stubs au pre-commit, son test au pre-push. L'heuristique de dates qui tenait lieu de détection de dérive est retirée : une comparaison de contenu la rend inutile, et elle se trompait — un stub régénéré puis commité avant sa source paraissait « en retard » alors qu'il était exact au caractère près. Un substitut ne vaut que tant qu'on n'a pas la mesure

Correctifs

  • commands: les renvois d'action de l'arbre installé ne pointaient vers rien. Depuis le 2026-08-19, peon.md et shuri.md expédiaient des renvois vers peon-actions/… — chemins relatifs au dossier de l'agent dans le dépôt, qui ne désignent rien une fois le fichier lu depuis ~/.claude/commands/ulk/ avec le projet de l'utilisateur pour cwd ; #670 a porté le cas de deux agents à vingt-huit. Silencieux par construction : un renvoi qui ne résout pas ne lève aucune erreur, il laisse l'agent incapable de charger la procédure qu'il annonce. Les fichiers d'action ne peuvent pas suivre sous commands/ — Claude Code y dérive une slash command de chaque .md, et 210 fichiers y créeraient autant de commandes parasites — ils s'installent donc sous ~/.claude/ulk-actions/<agent>/, et l'adaptateur Claude réécrit les renvois de l'arbre généré. La première réécriture était trop large : elle transformait aws-actions/configure-aws-credentials@v2, une action GitHub citée dans un extrait de CI, en chemin absurde — un renvoi mort remplacé par un autre. Bornée aux agents portant réellement un dossier <nom>-actions/
  • installer: ulk install signale les orphelins au lieu de les taire. agentOrphans n'était pas en cause — sa logique est juste ; FindOrphans n'était atteint que par ulk clean, commande manuelle dont l'aide dit elle-même « à lancer après avoir tiré une version qui a renommé des agents ». C'est ainsi que ulk-2b3 a survécu au renommage 2b3 → peon et est resté exposé comme subagent_type. Signaler plutôt que purger : supprimer sous ~/.claude/ sans demande explicite est plus lourd que le problème
  • subagents: isaac s'enregistrait hors du namespace ulk — son stub déclarait name: isaac là où les dix autres déclarent ulk-<nom>. Le name: du frontmatter est ce que Claude Code enregistre comme subagent_type, pas le nom de fichier : le sous-agent atterrissait dans l'espace global des agent types, et hors du préfixe ulk- sur lequel agentOrphans reconnaît un installé ulk — donc invisible à la détection d'orphelins
  • docs: native-features.md recopiait la liste qu'il prétendait déléguer — « 9 agents » et neuf noms, dont alex et agathe dont la doc spécifie la clé mémoire alors qu'aucun stub n'existe pour l'écrire, le tout en renvoyant dans la même phrase à la table canonique qui en portait onze. La page pointe désormais au lieu de recopier, et l'oracle vérifie que le renvoi reste un renvoi
  • docs: .claude/rules/cheatheet.md affirmait que generate-commands --check compare « disque ↔ disque ». Faux depuis #453 : la comparaison porte sur l'index git, donc régénérer ne suffit pas à faire verdir le gate — il faut stager l'arbre. La règle envoyait chercher un défaut de générateur là où il ne manque qu'un git add
  • site: quatre fiches d'agents portaient encore la description d'avant #668, en anglais — woz, jony, analyze-swiftui, pick-ui-library. C'est le piège que la note de méthode de #666 décrit : sans --force, le générateur ignore les fiches existantes et le site garde silencieusement l'ancien texte. Aucun gate ne compare une fiche à sa source ; personne ne l'aurait vu
  • agents: chez bruce, toute la procédure de vérification des mises à jour vivait sous le titre « Phase 0.7 — Ledger de décisions », alors que la Phase 0.6 qui l'annonce n'avait qu'un renvoi. Défaut révélé par le découpage : les deux sont séparées, chacune sous son propre titre
  • skills: les 132 motifs du corpus apple-code-review passent en POSIX ERE pur. \s, \w et \b sont des extensions GNU : un moteur strict y lit le caractère littéral qui suit l'antislash et ne matche rien, en silence. Mesuré avant conversion avec mawk comme oracle POSIX strict : 32 motifs sur 132 trouvaient zéro, sur 13 des 16 axes — sur une plateforme au grep strict (BSD, donc macOS, donc là où l'on écrit du SwiftUI) woz aurait sous-rapporté sur la moitié de son corpus sans rien dire. Conversion vérifiée dans les deux sens : 126 hits avant, 126 après sous GNU (sémantique intacte), et plus aucune divergence sous moteur strict (portabilité acquise). Les frontières de mot passent par l'alternation explicite (^|[^[:alnum:]_]), idiome que l'axe 15 employait déjà
  • gates: deux verrous sur la portabilité des motifs — une interdiction statique de toute construction non-POSIX (généralise le contrôle limité aux classes [...]), et un oracle empirique qui rejoue chaque motif sous mawk, moteur ERE strict, en déclarant le test sauté si le binaire manque plutôt qu'en rendant un vert silencieux. Vérifiés par réintroduction d'un motif GNU : les deux rougissent
  • hooks: handoff.sh fonctionne sous Linux. Il datait ses fichiers par stat -f %m || stat -c %Y, en supposant que la forme BSD échoue proprement ailleurs — or sous GNU coreutils -f interroge le système de fichiers et sort en 0 avec un dump : le repli ne se déclenchait jamais, l'arithmétique recevait du texte, et le hook sortait en Illegal number au lieu d'afficher HANDOFF.md. Le hook n'échouait donc pas là où on l'aurait vu — il crachait un dump de système de fichiers dans le contexte de démarrage. Ordre inversé (GNU d'abord) et validation que le résultat est bien un entier ; trouvé en écrivant session-persist.sh, qui portait la même ligne
  • skills: l'axe 9 du corpus apple-code-review se déclenche à nouveau — son détecteur principal s'écrivait ^\s{16,}if[\s(], et POSIX rend l'antislash littéral dans une expression entre crochets : [\s(] matche un antislash, jamais une espace. Le motif se lisait juste en RegExp JavaScript et ne trouvait rien sous grep -E, qui est ce qui exécute le sweep — l'axe était mort en production pendant que le gate le voyait vert. Porté en classes POSIX ([[:space:]]) ; unique occurrence du corpus, trouvée au premier rodage de woz (93)
  • gates: apple-axes-fixture.test.mjs mesure désormais avec grep, le moteur qui exécute réellement le sweep, et non plus avec RegExp JavaScript. Un gate qui valide sur un autre moteur que la production ne peut pas voir un axe mort : c'est le « vert par vacuité » qu'il traque, retourné contre lui-même. La parité des deux moteurs cesse d'être une propriété à vérifier — elle devient structurelle. Assertion neuve en complément : aucun échappement non-POSIX (\s/\d/\w) à l'intérieur d'une classe [...]. Vérifié par réintroduction du motif d'origine : rouge, là où il passait au vert la veille
  • gates: _shared/model-policy/attribution-tables.md entre dans les cibles de check-doc-counts.cjs. Le fichier porte un marqueur ulk:count:model-opus que C8 (agents-coherence) vérifie mais que --fix ne savait pas atteindre : le gate exigeait un compte à jour qu'il fallait corriger à la main — soit la dérive silencieuse que le marqueur existe précisément pour empêcher. Constaté à l'ajout de woz (93)
  • agents: analyze-swiftui ne rend plus de verdict de qualité. Sa phase 4 « Problèmes et optimisations » passait la main à un grep -rn "!" sur tous les .swift (force-unwraps de test compris), grep -rn "{ self\." et un relevé de .foregroundColor — sans gardes, sans sévérité, sans jugement. L'agent cartographie (ce qu'il y a), woz (93) juge (ce que ça vaut) ; sa phase 4 est désormais un passage de relais, et son golden test assère le renvoi
  • site: les intitulés issus de conventional-commits sont traduits sur /changelogFeatures, Bug Fixes, Performance Improvements, Reverts et ⚠ BREAKING CHANGES sortaient en anglais brut sur tout l'historique. LIBELLES_SECTION ne couvrait que la famille keep-a-changelog, donc précisément pas les intitulés les plus fréquents du fichier
  • site: la date des versions au format conventional-changelog est lue. RE_VERSION ne prévoyait ni le lien de comparaison après le ] ni la date entre parenthèses : 11 versions sur 57 sortaient sans date, les 11 plus récentes, et le chapeau de page bornait la plage à « 29 juillet 2026 » quand la dernière release datait du 24 août. Le test qui aurait dû l'attraper sautait les dates vides d'un continue
  • site: neuf correctifs d'audit — noms de sphère dérivés de spheres.json (28 fiches affichaient l'identifiant brut), balisage og:/twitter: et JSON-LD, Arcanes Majeures du Codex dérivées du même fichier, robots.txt + sitemap.xml + llms.txt, @font-face réduits à un bloc par police variable (29 blocs morts retirés), cibles tactiles de l'accueil à 44 px, et coupure clamp() à la frontière de phrase réelle (88 fiches régénérées) (#653, #654, #655, #656, #657, #658, #659, #660, #661)
  • skills: le name de cli-productivity vaut ulk-cli-productivity, soit le dossier que copyUlkSkills installe. opencode exige name == dossier, Claude Code lit le champ tel quel : un seul nom sert les deux harnais. skills-conformance.test.mjs couvre désormais framework/skills/, le défaut corrigé étant précisément hors gate (#642)

Documentation

  • decisions: ADR-015 acte la skill /spip écrite plutôt que vendorisée, et opt-in — l'amont ne porte aucun LICENSE (créditer ne tient pas lieu de licence) et SPIP est un CMS de niche, qui ne doit pas coûter de contexte à qui n'en fait pas. Conséquence assumée et écrite : les modules opt-in ne sont pas stagés par release-installer.sh, la skill s'installe depuis un clone. Flag documenté dans .claude/rules/install-reference.md, comparaison complète dans docs/reports/spip-skills-comparaison-2026-08-26.md
  • site: la page Hygiène de contexte cesse de ne prescrire que des gestes manuels — la règle 2 renvoie à --with-session-persist, la règle 4 à --with-compact-threshold, et les deux flags entrent dans la liste d'options de /install. Les cinq règles étaient publiées comme de la discipline à tenir soi-même ; deux d'entre elles ont maintenant un exécutant, et le site le disait nulle part
  • readme: la table Ce que contient le dépôt nomme framework/tools/hooks/. Elle listait scripts/hooks/ — les gates git — et taisait les hooks Claude Code, si bien que la seule entrée « hooks » du tableau désignait l'autre famille, celle qu'on ne cherche pas quand on cherche celle-là
  • credits: everything-claude-code (WorldFlowAI, MIT) entre en Inspirations & patterns — trois mécaniques reprises comme idées, rien de recopié : hooks de cycle de vie de session, suggestion de compaction stratégique, cadrage pass@k de leur eval-harness. Leurs agents, skills et rules doublonnent le roster ; leurs mcp-configs contredisent la priorité CLI sur MCP (_shared/cli-tools-protocol.md) et sont écartés
  • protocoles: behavioral-eval-protocol.md documente le nombre de tirages (pass@k vs pass^k, seuil par scénario, lecture d'un échec) et le type de grader — programmatique sur liste fermée, le moins expressif et le plus fiable : aucun modèle ne juge, donc rien à re-valider quand le juge change. La regex sur prose libre y figure comme piste essayée et abandonnée, avec le cas qui l'a tuée
  • claude-md: la liste des gates est alignée sur les hooks réels. Elle divergeait dans les deux sens : whitespace-check.sh était attribué au pre-commit alors qu'il est la section 0 du pre-push, et la dérive de framework/commands/, celle des intitulés du CHANGELOG et gofmt n'y figuraient pas. Une liste fausse est pire qu'absente — elle fait chercher au mauvais endroit quand un gate échoue
  • product: les comptes d'agents et de sphères de PRODUCT.md passent aux marqueurs dérivés ulk:count au lieu de rester figés, le fichier entre dans les cibles de check-doc-counts.cjs, et la section Register (v4 des modes visiteurs) est retirée
  • docs: la racine perd trois fichiers — RELEASE.md, BENCHMARK.md et ulk-schema.svg rejoignent docs/. Liens mis à jour (README, carte go-install, chemin d'écriture de benchmark-ulk.cjs) ; la racine passe de 24 à 21 fichiers suivis

v8.0.1

Nouveautés

  • agents: jony (91), design lead macOS/iOS — design system natif (tokens, composants, light/dark, matériau Liquid Glass), wireframes via /design, direction via impeccable ; la skill macos-design entre au catalogue. isaac (27) implémente en SwiftUI, celebrimbor (58) et agathe (60) co-lead (#646)
  • skills: ponytail entre au catalogue — six skills anti-suringénierie vendorisées sous framework/community-skills/, derrière --with-ponytail-skills. Les hooks amont restent dehors : ils allumaient le mode à chaque démarrage de session, l'inverse de ce qu'un module opt-in promet (#640)
  • site: les trois traitements tarot de jony (carte dark, gravure serrée, carte pixel), budgets ≤ 190 Ko, empreinte CSP du jeu remplacée. Les quatre univers artistiques ne le couvrent pas encore : il y garde son illustration d'origine

Correctifs

  • installer: go test ./... retombe de 600 s à 11 s — les tests unitaires de copie exécutaient pour de vrai les npm install -g / pip install des modules externes, et le pre-push le payait à la seconde près. En production, ExternalModule.Install est bornée à son tour : une installation qui pend n'immobilise plus ulk install (#415)
  • installer: verifiedInstall borne l'exécution du script téléchargé — la fetch avait un timeout HTTP, l'exécution qui suit n'en avait aucun ; resolveLink retombe sur le chemin d'origine au-delà de 8 symlinks plutôt que de comparer une résolution partielle (#643)
  • gates: generate-commands --check compare à l'index git, plus disque↔disque — un staging partiel (source stagée, arbre régénéré seulement sur disque) passait en silence et la dérive entrait dans l'historique. Aligné sur le pattern credits (#611)
  • site: un seul sélecteur d'illustrations — la navbar portait deux boutons agissant sur le même src, le second clic annulait le premier, et sur un agent sans œuvre le bouton univers ne faisait rien (#645)
  • skills: ponytail ne peut plus se rallumer par la porte du modèle — disable-model-invocation: true, et la section Persistence réécrite sur ce qui tient réellement ici, sans les hooks non vendorisés (#640)
  • backlog: la carte ponytail portait un frontmatter sans issue ; check-card-spec l'a refusée au pre-push, c'est le bon endroit pour l'attraper (#640)

Documentation

  • site: ponytail devient trouvable — section dédiée dans /docs/skills/, --with-ponytail-skills listé dans les options d'installation, et framework/community-skills/ entre dans la table du README (#640)
  • reports: mesure de disjonction Tier 1 — quatre cartes rejouées par un checker d'un autre fournisseur, 0 CRITICAL et 0 MAJOR manqués, quatre MINOR de durcissement. Le critère pré-fixé conclut au statu quo, critères d'escalade élargis (#643)
  • backlog: carte du mode openrouter — le choix de modèle est statique par agent, OpenRouter absent du dépôt ; une carte de code est nécessaire, mais après #643 et une décision produit (#644)

Mis à jour

  • deps: astro 7.2.4, marked 18.0.10, @biomejs/biome 2.5.10

v8.0.0

⚠ Ruptures

  • cli: skills-lock.json décrit désormais ce qu'ulk distribue, plus ce qu'une machine porte. Un lock produit avant cette version asserte un état local que le nouveau format ne gouverne pas — le régénérer avec ulk skills lock (#606)
  • ci: les deux workflows GitHub Actions sont supprimés. Les hooks git (scripts/hooks/) sont désormais le seul gate : un merge côté serveur n'exécute rien, il faut merger en local. Doctrine : _shared/full-local-gate-protocol.md

Nouveautés

  • design: compétence /design ouverte aux agents design — _shared/design-canvas-protocol.md, l'étape 0 ancrée sur docs/design.md plutôt qu'un scan du code, sources d'artboards versionnées, canvas rendu du shotgun ; celebrimbor (58) et agathe (60) porteurs, numerobis (01) / arya (03) / vinci (80) consommateurs (#617)
  • design: premier canvas ARCANA — la doctrine éprouvée sur un cas réel, et ce qu'il a corrigé au protocole (nommage de carte, fontes en data: URI, exemption hardcode-check) (#620)
  • site: quatre univers d'illustrations couvrant les 89 agents du roster d'alors — Abstraction, Moyen Âge, Antiquité → Renaissance, plus un sélecteur d'univers ; œuvres PD/CC0 vérifiées et sourcées (#619)
  • cli: skills-lock.json devient le manifeste de distribution (#606)
  • gates: l'oracle amont des skills (verify --upstream) devient exécutable, et son absence se déclare au lieu de passer inaperçue (#606)
  • gates: gate pre-commit de dérive sur framework/commands/ — l'arbre généré ne peut plus diverger de ses sources en silence
  • tools: intégration de Graft CLI (graphe de contexte du dépôt), flag --with-graft
  • backlog: carte de suivi pour éprouver la doctrine design-canvas sur un vrai canvas (#620)

Correctifs

  • cli: le lock épinglait une traduction japonaise et une variante Gemini
  • cli: lock n'épingle plus ce que verify vient de dire de ne pas épingler (#615)
  • cli: verify --upstream distingue le retard de version de l'incident réseau (#607)
  • gates: l'oracle amont quitte la CI pour le check quotidien
  • skills: sandbox-sdk suit sa scission amont vers sandbox-stable — un 429 cesse de passer pour une skill retirée
  • tools: audit-to-backlog lit les rapports que les agents écrivent réellement (#612)
  • tools: audit-to-backlog honore les options en forme espace (#603) et dérive le type de carte de la priorité (#604)
  • docs: restaure le spike contexte emporté par un .gitignore non ancré (#528)
  • site: 16 pages servies sans leur CSS — la CSP refusait des feuilles que rien ne contrôlait (#449)
  • gates: check-card-spec bloque à nouveau, la dernière carte sans issue est rattachée

Documentation

  • agents: bruce — § Outils déduplique vers cli-tools-protocol
  • agents: la cinquième règle d'hygiène de contexte atteint enfin ses enforcers (#613)
  • site: --with-graft listé dans les options d'installation
  • docs: la référence décrit le manifeste de distribution, plus l'ancien régime (#606)
  • backlog: les trois verrous qui interdisent go install sont nommés (#618)
  • site: institutions sourcées et dédoublonnées — 42 mentions ramenées à 25 (#619)
  • backlog: spec de portabilité opencode — ce qui est déjà acquis, et ce qui contredit une doctrine écrite (#639)

v7.14.0

Nouveautés

  • agents: ledger de décisions persisté — docs/decisions.md (ADR), chargé par bruce/godspeed/task-runner (#595)
  • agents: convertisseur rapports d'audit → cartes Faru — tools/audit-to-backlog.cjs, câblé sargeras/ed209 (#596)

Correctifs

  • docs: restaure le vault docs/_memory/ (9 fichiers) + protocoles réparés (#600)
  • docs: _HOME.md réécrit — 19/19 wikilinks valides (#597)
  • docs: migration voice → brand-voice complétée sur 12 fichiers (#598)
  • docs: .papergeist retiré du suivi git (#599)
  • install-remote.sh: trap EXIT réel — exec → bash+exit, nettoyage TMP_DIR (#593)
  • release.sh: bump landing releases.regrets.app automatisé (#586)
  • ci: setup-go pinne go-version exacte 1.26.6 — gate vert (#602)
  • go: toolchain cli bumpée à 1.26.6 (6 vulnérabilités stdlib net/http, GO-2026-5026)
  • go: toolchain installer bumpée à 1.25.13 (4 vulnérabilités, GO-2026-5026)
  • npm: nanoid bumpé à 3.3.18 (GHSA-2v37-7h3g-55p8, high)
  • skills: SKILL.md restructuré trouvé en amont via l'arbre du dépôt (#594)

v7.13.1

Correctifs

  • gate: acter la suppression d'AGENTS.md dans les deux oracles qui l'exigeaient (0567f00)
  • gitignore: ignorer aussi l'installation de skills du second harnais (ee587f3)
  • gitignore: ignorer aussi l'installation de skills du second harnais (fbe03df)

v7.13.0

Nouveautés

  • /a-propos/ — illustration + crédits complets (design, images, fonts, stack, équipe) (549a7e6)
  • /changelog/ — parsed from CHANGELOG.md, with illustration + nav link (48542b4)
  • 3rd tarot theme — Castlevania SOTN Pixel Art (aa4a8ec)
  • 8 renames pop-culture + sphere « Les Agents » (Matrix) (555e7d6)
  • accessibility + animations + perf improvements (0496b82)
  • add agent portrait thumbnails to pipeline cards (1532ad9)
  • add grimoire illustration to /docs/ page (Sombre + Doré) (6e48810)
  • add Jimothy agent (#85) — beloved cryptid raccoon, digital trash scavenger (0104a24)
  • add tarot illustration to install page (Sombre + Doré) (5681ed4)
  • agent punisher (85) — release totale radicale (8f5dc01)
  • agent punisher (85) + renommages sauron (ex-obiwan) et peon (ex-2b3) (83c8402)
  • agents: extends: devient un invariant vérifié — gate C12 (3ba8ffa)
  • agents: chaque agent signe d'un emoji au démarrage — Bruce est un loup (49f05e4)
  • agents: chromie — agent de régression visuelle (Playwright + Docker) (#391) (19c51a4)
  • agents: descriptions routage auto-suffisantes — QUAND l'utiliser + exclusions, 19 agents (#487) (a6c6252)
  • agents: destiny (88) — audit de vérité du contexte + oracle AG002 (#528) (4e591f2)
  • agents: memory-capabilities — détection de capacités par preuve repo + confirmation user, banque mémoire vault (#552) (f9f198c)
  • agents: rend extends: base-rules.md portant — noyau injecté dans les corps (3c3eec2)
  • agents: renommer brique → Numérobis, l'architecte (issue #495) (fa36494)
  • agents: renommer brique → Numérobis, l'architecte + nouveaux visuels (issue #495) (74d8610)
  • agents: renommer visual-auditor → Tyrion + visuels ranx (issue #497) (6d0af6b)
  • agents: renommer visual-auditor → Tyrion, l'œil qui juge (issue #497) + visuels ranx (60d4123)
  • aidd: #550 reliquat (1/2) — shuri (01) pivoté en routeur : 16 actions auto-contenues (shuri-actions/, contrat I/O/Process/Test) + manifeste 1213→260 lignes, golden mis à jour, 931 tests verts (7d8e35a)
  • aidd: #550 reliquat (2/2) — peon (08) pivoté en routeur : 15 actions auto-contenues (peon-actions/, contrat I/O/Process/Test) + manifeste 979→322 lignes, golden à jour, 931 tests verts — reliquat #550 terminé (1d827f9)
  • aidd: #554 protocole executor/checker (Tier 1 scully + Tier 2 dredd, vérificateur ne corrige jamais) ; #555 proof-gate (85% de 'vérifié' sans preuve mesurés, étape 1 de 04-verifier réécrite) ; #556 lifecycle status étendu (additif, 335 fichiers épargnés) + outcomes CARD remplis (c7946b2)
  • aidd: #557 vcs-conventions-protocol (never assume main, 11 types de commit mesurés, règle 11 base-rules) ; #559 change-set-protocol (7 champs + 3 modes d'autorité, #558 comme exemple du mode 3) — CLAUDE.md restauré (budget 2477/2500) ; #558 extraction prête : la CI n'aura qu'à appeler pre-push (source unique, en attente décision Mathieu) (6ef5606)
  • aidd: P2 jeudi — #560 condense-stats (ligne machine-parseable + coût réel depuis transcript JSONL) · #561 shadow-areas taxonomie verrouillée (phil-connors) · #562 fact-check cascade cheapest-first + hedge-don't-delete (protocole, 4 agents d'audit) · #563 routeur bruce (argument>env>état>intention + engagement irrévocable) (a231a6d)
  • aidd: P2 vendredi — #564 vcs-protocol (PR draft + label par prefixe + lien preuves QA, cable peon/task-runner) · #565 release.sh semver auto (BREAKING CHANGE/feat/patch, tag annote, garde version-manager) · #566 kanban.cjs frontmatter (5 buckets, --by-wave) + tests · #567 godspeed mode onboard etat-aware (ee94d43)
  • apply Impeccable anti-pattern fixes + DM Sans typography (e70e4fe)
  • apply Minitel microcopy audit — renforcer métaphore tarot (6f3ba22)
  • bruce: gate d'isolation de session + lecture d'une carte Faru collée (d66d124)
  • bruce: le mode de sortie se choisit, une fois par session (dca64fc)
  • budget: le « CLAUDE.md < 2500 tokens » cesse d'être un vœu (8d37f09)
  • dual tarot theme — Cthulhu Dark (dark) and Gustave Doré (light) (d79e33b)
  • evals: l'eval comportementale live existe et s'exécute — et dit autre chose (4564be5)
  • gate: budget CLAUDE.md warn → block — budget tenu (2477/2500), dérive désormais bloquante (#486, #482) (76a757b)
  • gate: skills verify entre au pre-push — l'arbitrage est tranché (434dc37)
  • gate: surveiller les dépôts tiers cités hors registry (#425) (#434) (cdf6da3)
  • governance: l'échelle de promotion du savoir — éphémère → prose → exécutable (4ee50d2)
  • Hermes page redesign — tarot hero, skill cards with agent portraits, full arcana identity (15dce48)
  • hermes: automatise la publication (--publish / --deploy) (bed9f4c)
  • hermes: flag --github (tag + GitHub Release, latest=false) (50e4d8f)
  • hermes: tarball déterministe (reproductible byte-à-byte) (8ca798a)
  • hooks: ulk-memory-sync SessionStart — bloc mémoire 2-tiers idempotent entre marqueurs (#553) (e64bd7e)
  • installer: le bundle a enfin un producteur, et la clé entre au build (81ba0f5)
  • install: impeccable et i-have-adhd s'installent enfin par un chemin du dépôt (275f4ca)
  • new installer — binaire Go statique + TUI Bubble Tea (a39792a)
  • Opus 5 redesign — Install (Le Rituel, cartes visuelles) + Hermès (cartes skills améliorées) (f4a09ae)
  • picsou: mode frugon — repricing empirique des modèles (T1→T3) (#367) (4450ab2)
  • prose-lint: C10 — les commandes et flags cités doivent exister (693e612)
  • prose-lint: C11 — les chemins cités, sur le périmètre qui a du signal (297df3c)
  • prose-lint: la cohérence scanne enfin CLAUDE.md et les _shared (4b3af89)
  • redesign Hermes page — tarot illustration hero (Sombre + Doré), improved layout (781d9ae)
  • roster: #441 clé name documentée + unicité verrouillée (test) ; #448 couverture marketing réelle (sauron + product-marketing) documentée ; #459 triggers[] déprécié — champ mort prouvé (0 peupleur, CLI Go ne lit pas, pseudocode mensonger retiré) (c72c4de)
  • routine → maria — l'automate des rites récurrents (Metropolis) (9b3defd)
  • security: intègre les 3 couches sécurité natives Claude Code (#390) (cd41545)
  • seo: /claude-seo devient titulaire du besoin — la boucle vide est fermée (74dede0)
  • site: « Le Tirage » devient la page d'accueil — l'ancienne est archivée, pas supprimée (70968c8)
  • site: CSP fermée — style-src 'self' (1123 style= → 0, Shiki → classes shiki-<hex>), font-src 'self' (18 woff2 auto-hébergés, plus de Google Fonts), LCP thème unique (#449 #455) (b517993)
  • site: la home devient La Coupe — un fold, une carte, le panthéon derrière (0209221)
  • site: le changelog perdait la moitié de ce qu'on y écrit (7a0409d)
  • site: mode paquet du panthéon — feuilleter les arcanes au doigt (#503) (d86837f)
  • site: redirects 301 fusion sphères — intendants + messagers reclassés vers maitres-d-oeuvre (#520) (69194bf)
  • site: section Hermes — catalogue 27 skills portées + doc + nav (#362) (#378) (c275669)
  • site: un oracle de contraste, parce qu'aucune des six paires fautives n'était vérifiée (025cf77)
  • site: une CSP qui ferme script-src par empreinte, et un gate qui l'empêche de pourrir (b030fb3)
  • site: visuels définitifs sauron / peon / punisher + crédits (090d409)
  • skills: #509 arbitrage — grille 5 axes (7 skills), reject humanizer (patterns récupérés) + unified-memory (mono-harnais, purge Codex), adopt brand-voice (docs/brand-voice.md source vérité + 5 agents), skills écartées consignées (#510 #517 #516 #515) (6a12984)
  • skills: #511 ios-icon-gen + #514 article-writing adopt (affaan-m/ECC, MIT vérifiée) — entrées skills-sources + loads_skills isaac/shuri/brigitte/sauron + cascade éditoriale + install-reference ; reliquat #548 : routage browser-qa (deckard/chromie/scully/task-runner/peon) + politique .webm (gitignore) + premier run réel (qa.md, preuve #520) (0bed097)
  • skills: verify --upstream nomme la cause d'une dérive (81acb10), closes #413
  • skills: câbler HyperResearch sur les huit agents qui cherchent dehors (c2e87d1), closes #404
  • skills: check-skill-repos vérifie aussi description et source_url (720a90a), closes #425
  • skills: porter zine-web-interface + Ranx (87) depuis la PR #375 (44aaf1c)
  • skills: table d'alias slug↔nom installé + résolveur (invariant C7) (3ceb052)
  • skills: ulk calcule ses propres empreintes — l'outil n'en produit pas dans notre mode d'usage (18e115b)
  • skills: vendoriser browser-qa — la preuve vidéo d'un parcours, bornée par une carte (3c3a951)
  • skills: vendoriser browser-qa — QA navigateur post-review, preuve vidéo bornée par une carte (98f2eb7)
  • sortie: i-have-adhd passe en always-on, et le format apprend à dire « plugin » (bddb4da)
  • sphere agents → « Les Hommes en noir » (MIB) — nom/role/meta + palette ardoise (253a958)
  • sphere illustrations in Cthulhu Dark Tarot style (9 spheres) (ed81a9d)
  • test-unit → wall-e (Pixar, 🧱) + complétion scully/thanos (d9c0f8b)
  • wave-5: #472 pipeline figma unique documenté + 17 orphelines OWNERSHIP + lien numbering vérifié ; #522 étude parité (68/27/5%, 0 femme orchestrateurs, 14 propositions à valider) ; #458 agent 89 pick-ui-library (curation ulk datée, golden, registry/commands/counts/site resynchronisés) (98fcc82)
  • wave-6+P3: #456 design-shotgun-protocol (agathe/celebrimbor câblés) ; #440 déjà résolu (a-propos.astro importe credits-counts) ; #492 app-store-policy (isaac/tim/buzz) ; #465 correcteur FR aspell+aspell-fr (installé+vérifié VPS, avoid-ai-writing-protocol, cli-registry) (3b4c1bf)

Correctifs

  • a11y: le titre de /hermes peignait avec les joyaux, et les liens ne se distinguaient que par leur teinte (4194206)
  • a11y: les 85 fiches d'agents rendent leur nom aux lecteurs d'écran (4781272)
  • add jimothy to gardiens sphere list on site (3fc44c2)
  • add missing chromie image + regenerate VPS agents in Cthulhu Dark Tarot style (208a219)
  • agent modal dvh units — fix scroll madness on iOS Safari (a6660c8)
  • agent89: règles héritées injectées (base-rules + stack-detection) — gate inject-inherited-rules vert (18d677d)
  • agents: anti-triggers croisés gandalf/xavier + mot-clé audit visuel (visual-auditor/agathe) (342b536)
  • agents: blackemperor — déclencheur mode frontend dans la description (#487) (ec1754e)
  • agents: bruce annonce 82 agents (était 78) (1ce7617)
  • agents: écrire la signature dans le bloc de chaque agent, pas dans un renvoi (9dbedbc)
  • agents: emoji memory-capabilities 🗺️ (🧭 pris par astride) (#552) (9950426)
  • agents: gandalf — retire claude-code-mastery (4893 tok, non essentiel pour un agent haiku), budget réaliste sans gonflage (#489) (fb8effe)
  • agents: memory-capabilities → ID 90 (89 réservé par 2 cartes backlog) + resync counts (#552) (22bfb64)
  • agents: rediriger les handoffs Ranma (31, archivé) vers tony (50) mode=audit (1a0827b)
  • auto-generate AGENT_ILLUSTRATIONS from filesystem — every agent gets its portrait (96c8ae7)
  • bonjour: restaure le garde-fou fichier absent + repli sed sans jq (#368) (f14b48d)
  • changelog path resolution — build passes (108 pages) (b5a48ca)
  • CHANGELOG Unreleased section dupliquée (#346) (37534a1)
  • cheatheet: generate-registry redevient idempotent — il salissait l'arbre chaque jour (7feed49)
  • ci: #542 gate voit les merges — renovate gomod major dashboard-approval + bonjour signale l'amont + hook SessionStart go-build-verify ; #543 lock versionné : npm_ci_align + 3 commentaires corrigés ; #451 hook format : NO-GO documenté (fd3af2e)
  • cli-registry: épingle curl.md et docker sur leur source amont (79ef51a)
  • cli,site: aligner installateur et CSP sur les renames (numerobis + tyrion) (6cc3315)
  • cli: #481 conformité spec Agent Skills — skillInstallName anti-double-préfixe (helpers + clean, fixtures Go corrigées) + gate skills-conformance (name==dossier, description≤1024) câblé pre-push ; rattrapage framework/commands (miroirs en retard : brand-voice/article-writing/browser-qa) (1b6b69d)
  • cli: restaure les options Bubble Tea + détracke le binaire installateur (865f1a9), closes #389 #394
  • cohérence C12 — maria cite cli-tools-protocol, allowlist purge (2144054)
  • cohérence modèle Opus 5 / Sonnet 5 — items 1-5 de l'audit + D11 (379a5f2)
  • coherence: invocation scully cassée, ID 88 collisionné, carte #523 (#528) (95c75b6)
  • commands: raccorde gardiens/ au générateur — /ulk:agents:jimothy invocable (7789b1c)
  • condense: corrections review #560 — cache tokens (write 1.25x, read 0.1x) inclus dans le cout reel, % marque estime dans la ligne machine-parseable, readFileSync tolerant (267af33)
  • contexte: recoller les 24 références mortes du corpus + durcir le gate AG002 (#528) (9412a9a)
  • counts: bruce annonce 83 agents (roster réel) + garde-fou (#364) (fd8bab9)
  • counts: dérive les « 27 skills » Hermès et étend le gate aux .md du site (830ce58)
  • credits: les cinq totaux se dérivent — ils étaient recopiés à la main (5c5f563)
  • credits: lire les sources depuis l'index git, pas le working tree (#321) (96a5710)
  • CSP JEU (303 cibles — cerbere) (ceaf0e3)
  • deps: aligner bubbles sur v1.0.0 dans l'installateur (31338d2)
  • deps: sortir esbuild de la plage vulnérable — par le bas, faute de mieux (4575fcb)
  • deps: update module github.com/charmbracelet/bubbles to v2 (#381) (9cb557a)
  • deps: update module github.com/charmbracelet/bubbles to v2 (#410) (e136fa9)
  • deps: update module github.com/charmbracelet/bubbletea to v2 (#382) (15360a5)
  • deps: update module github.com/charmbracelet/bubbletea to v2 (#411) (ae13ce9)
  • deps: update module github.com/charmbracelet/lipgloss to v2 (96f0810)
  • deps: update module github.com/charmbracelet/lipgloss to v2 (3991129)
  • deps: update module github.com/spf13/pflag to v1.0.10 (#380) (83f36a9)
  • design.md case, bonjour.sh jq, govulncheck crash, test collisions (9400113)
  • design: les deux arbitrages DA tranchés — sans qu'une couleur nouvelle entre dans le système (b3d5fa7)
  • docs: #571 refs mortes post-renames purgées (docs + site, 0 résidu vivant) ; #443 registres nettoyés (vision→ripley, stark→celebrimbor, ci-guard→cerbere…) ; #464 gate budget CLAUDE.md warn→block (hook + test) (be5b4f6)
  • docs: corrections review — #571 CLAUDE.md routine→maria, site-content VERIFY/PLAN, comptages 88 ; #443 registres nettoyés sans reformatage (diff minimal) (7a20978)
  • escape single quote in L'Ordonnance sphere role (e86b6bd)
  • evals: ULK_BEHAVIORAL_LIVE=1 échoue franchement au lieu de rendre un vert vide (ceb3b03)
  • final Jimothy portrait based on Wikipedia photo analysis (short spine syndrome) (00f832c)
  • FR dashboard supprimer, CHANGELOG Unreleased, backlog cards done (37534a1)
  • gate: corriger les 3 dérives de dépôts et installer les deps au wt new (#425, #429) (#475) (3b1943d)
  • gate: fraîcheur des hooks (#452), tests couverts par le sweep (#445), credits index vs disque (#453) (b849e36)
  • gate: impeccable devient résolvable par le dépôt, et la suite cohérence entre au pre-push (b6a16f3)
  • gate: le pre-push mourait en silence sur skills verify, et son oracle ne gardait rien en CI (6cb6c91)
  • gate: le pre-push mourait en silence sur skills verify, et son oracle ne gardait rien en CI (9a007f3)
  • gate: le verdict du pre-push dit ce qu'il a mesuré (#429) (#432) (67756c7)
  • gate: les cinq oracles du site tournaient après le push, pas avant (b5fb3e6)
  • gate: les deux oracles Go étaient inertes par notre faute, pas celle de l'amont (#414) (2377065)
  • gate: les trois mailles du filet full-local retiennent enfin quelque chose (2b306e2)
  • gate: npm audit n'auditait que la racine — site/ échappait au gate (e2df804)
  • gate: skills verify échouait sans avoir rien vérifié, et accusait une skill (46d5494)
  • GitHub button same height as toggles (same padding/font/border) (77e27f4)
  • go-cli: une sortie 0 à pipe orphelin n'est plus un échec d'installation (#422) (e89cc91)
  • go: désépingler les toolchains sur les patchs qui corrigent la stdlib (cc0b16f), closes #414
  • gofmt agents_test.go (97c14a3)
  • golden: memory-capabilities — pattern case-sensitive + fermeture frontmatter (#552) (7b3cd66)
  • go: revert bubbletea/bubbles v1→v2 — imports incompatibles, API v2 trop large (#388) (7f478e4)
  • go: revert bubbletea/bubbles v1→v2 (bis) et bloquer le major côté Renovate (325e7af)
  • go: revert lipgloss v1→v2 et bloquer le major côté Renovate (#541) (954c4a7)
  • handoff: task-brief.sh lit stdin via '-' — /dev/stdin non-device en conteneur/CI (#445 gate sweep) (b871cf5)
  • hardcode-check: #442 review — règle AST étendue aux template literals, regex dédoublonnée (b19056c)
  • Hermes hero — side-image layout instead of full-bleed background (readable text) (4eca344)
  • hermes: durcit release.sh — set -e, trap cleanup, source unique payload (#387) (0d85c99)
  • hooks: go-build-verify — go build borné en temps (120s) comme le fetch, promesse 'jamais de blocage' tenue (#542 review) (f4fbd95)
  • hooks: shellcheck ne tournait plus nulle part — le hook qui le portait était mort (0b0f396)
  • hooks: ws-check en /bin/sh (POSIX, plus de here-string) + appel direct dans pre-push — verdict #429 vert (5/5) (83acf81)
  • identifiant brique + extends alphabétique (#355 #348 #347) (7c08e57)
  • installer: ulk-installer upgrade déclenche le mode mise à jour (#427) (c50edba)
  • installer: upgrade annonçait un résultat qu'il n'avait pas cherché (45baa4e)
  • installer: borner l'attente d'un pipe tenu par un petit-fils détaché (12837aa), closes #415
  • installer: honour declared SHA256 in the bundle path + no silent truncated copies (43e72a4)
  • installer: la clé qu'on croyait embarquée, et le préflight en double (09eb586)
  • installer: le « binaire statique » de la spec ne l'était pas (#393) (b07d4e2)
  • installer: le bundle porte les skills que ulk install pose (43097f0)
  • installer: le lien symbolique qui franchissait sa propre garde (1c5e262)
  • installer: le TUI installe pour de vrai, et refuse ce qu'il ne peut pas vérifier (517add5)
  • installer: sentinel redevient un choix de projet, pas un défaut d'install (750b170)
  • install: neuf fichiers de référence squattaient le namespace de commandes (83ba1cd)
  • install: vérifier le tarball avant de l'extraire — le contrôle ne s'exécutait jamais (#466 SEC-03) (#539) (746264a)
  • isaac: retirer les deux skills FoundationModels mortes, garder le besoin (#426) (#431) (2e91433)
  • jimothy portrait v2 — emphasize spinal deformity (kyphosis/round body) (29b6aac)
  • jimothy portrait v3 — pure description of kyphosis/spinal deformity (84c4fb2)
  • jimothy portrait v4 — no tail (compact silhouette) (255396a)
  • la dérive « 83 agents » — dériver le count ou le retirer, jamais le réécrire (19f9386)
  • managed-agents: le générateur fabriquait des agents à partir de n'importe quel .md, et ne supprimait jamais rien (#523) (#546) (a906929)
  • memory: aligne context-hygiene + banner-mode sur #490 — plus de staging manuel en session interactive (#490) (34b1ce8)
  • mobile menu redesign — left-aligned, consistent spacing, theme+togglestogether (d314336)
  • mobile menu v2 — solid bg, toggles in pill row, GitHub as outline, reset style (daff0ab)
  • mobile menu v3 — GitHub icon, inline tarot icon, flex fix, toggles aligned (2234a2d)
  • model-policy: trois liens morts dans le document qui fait autorité sur les modèles (6d3c933)
  • npm: versionner les lockfiles, sans quoi le gate npm audit ne garde rien (20d2388)
  • obiwan: retire 5 skills fantomes de loads_skills (plugins opt-in, pas registry) (c866d2c)
  • pipeline agent images 50% width (1/4 area) (75ac467)
  • pre-push: confiner GOTOOLCHAIN au module dont il est dérivé (afb7afc)
  • protocols: préséances entre protocoles co-chargés + 4 evals comportementales — 6 collisions (#484) (5be0483)
  • refs: les trois derniers renvois morts de la vague 2 — #523 close (#547) (4c65931)
  • refusal-scope: même bypass inexécutable que sentinel, et sa limite (5965941)
  • regenerate all light images with agent-specific prompts from registry (71e1261)
  • regenerate ci-guard (no text) + doc-reset (no Cthulhu) (a1aa077)
  • regenerate Jimothy portrait based on real photo (spinal deformity) (f278d04)
  • regenerate stark image (was still old version) (2b8f928)
  • registry,site,docs: dérive la slash command du layout d'installation (581eb0a)
  • registry: dériver la sphère depuis spheres.json (issue #463) (e5e45d5)
  • règles héritées injectées (renames) (3f66d31)
  • règles héritées injectées (wall-e/scully/thanos) (7d06527)
  • release-installer: $VAR… tuait la publication après signature et build (d505bda)
  • release-installer: exiger le terminal avant de travailler, pas au moment de signer (c32b76c)
  • release-please: migrer au format manifest et retirer la CI de la publication (ef858c0)
  • release: garde-fou miroir anti-404 brew (pré-check VPS + verify-mirror) (8d04933)
  • release: le bundle ne contient aucune skill par défaut — défaut 5 (f1e7c64)
  • release: release.sh repose le label autorelease que la CI ne pose plus (#477) (0533cb3)
  • remove remaining magenta glow (page-lisere box-shadow) — Impeccable audit clean (82aa1ef)
  • rename docs/DESIGN.md to docs/design.md (dea403c)
  • rename docs/DESIGN.md to docs/design.md (fc6150d)
  • rename toggle labels to Tarot Sombre / Tarot Doré (102411f)
  • replace Jimothy social media publish with email report (48ece71)
  • review: refuses punisher étendus + alias legacy routage bruce + handoff skills-radar (70dee91)
  • roster: jimothy quitte une catégorie qui n'existe pas (28296d8)
  • rules: native-features ne se chargeait pour personne depuis le split — plus l'oracle qui le dira (#523) (#544) (fee4dd6)
  • rules: purge les références mortes des renames vagues 1+2 (.claude/rules/ + mémoire peon) — #507 #523 (fce7648)
  • sdk: ulk-sdk et le status-board voyaient un roster vide — et leurs tests l'entérinaient (481d72f)
  • sec: #466 recettes curl|bash épinglées ou documentées (unpinned_reason + test) — audit SEC-01/02 ; feat(spec): #551 validateur CARD exécutable (TBD: anti-invention, 9 champs, warn gate) (590c8c1)
  • securite: hooks-resync passe en portée projet — il installait les hooks de n'importe quel dépôt (c229535)
  • securite: la garde de hooks-resync passe de la config au code (7418159)
  • securite: le dashboard garde aussi ses lectures, et le lockfile des skills cesse d'être jeté (5f1a1a4)
  • security: trois gardes qui ne gardaient rien (#402, #403, #392) (0ed9177)
  • sentinel: le bypass one-shot n'était pas exécutable par un shell (829a440)
  • sentinel: résoudre le dépôt visé, pas le cwd de la session (c9810a6)
  • site: « arcane » est féminin — accord tranché et harmonisé (0202cb5), closes #395
  • site: #437 compte de sphères dérivé de spheres.json (le '9' était FAUX : 10 sphères, la 10e 'Les Hommes en noir' jamais listée) — gate check-doc-counts étendu (3e source + exclusion _archive) ; #450 7 skills emilkowalski déclarées (83) + trou animation documenté ; #548 déjà résolu (vendoré 3c3a9514) ; #454 piste CWV sans Lighthouse documentée (6f338fa)
  • site: #458 — pick-ui-library dans la sphère oracles (spheres.json + meta) — bijection sphères ↔ roster rétablie (45a0cf6)
  • site: /install était illisible en thème clair — encres basculantes sur voile fixe (966a6c5)
  • site: B3 — inert sur le contenu sous-jacent + hamburger dans le piège au focus (e1bbd68)
  • site: dernières références mortes de la vague 2 — #523 close (#528) (0e6e943)
  • site: durcissement — échappement du markdown agents, fin de l'eval au build (lot 3) (65c7fe7)
  • site: en-têtes de sécurité CF Pages (B5) + suivi Lot 2 (9acd520)
  • site: la gravure du fold était un mur, pas une carte (844bbf7)
  • site: la modale d'un agent reprend là où sa fiche s'arrête (26d973f)
  • site: la tranche du paquet remplace le compteur, la colonne n'a plus qu'une marge (6a71cb9)
  • site: le compte des skills registry suivait d'une unité (5f9e1ff)
  • site: le fold court tient à 941×640, et la forme des gravures a un gate (0582d92)
  • site: le fold mobile tient sur tout le jeu, et l'inventaire des gravures dit vrai (cfdf76d)
  • site: le site publiait une commande qui n'existe pas — benjamin (fcd8bfe)
  • site: le thème suit la préférence système — le tarot le faisait déjà, pas lui (b79a640)
  • site: les cartes coupaient les rôles au milieu des noms de fichiers (#395) (a87237a)
  • site: les fiches d'agents remontent le préambule de leur définition (4f68f15)
  • site: lot 2 de l'audit front — a11y clavier, contraste, hiérarchie, oracle de thème (4af055d)
  • site: lot 5 — câblage du gate design, contrôle des counts, tokenisation (7fef1a6)
  • site: métas uniques par page et logique des sphères exposée (#395 P2/P3) (60b3e70)
  • site: noms d'agents périmés dans la copie publique + faille nanoid (#528) (dbd115d)
  • site: passes impeccable 1-4 sur l'accueil — a11y, responsive, typographie (b804d61)
  • site: purge .ulk-reports + assets morts + fragments EN résiduels (#366) (1222a7f)
  • site: registry resynchronisé — sphere pick-ui-library = oracles (projeté depuis spheres.json) (1cce4e8)
  • site: reliquats de #444 — atreides déployé, deux fragments EN ratés par le grep (#538) (2464fef)
  • site: rendre les cartes lisibles sans la gravure ni la souris (7e6af64)
  • site: répare le prebuild mort + 3 défauts de rendu (Lot 1 audit front) (219cf9c)
  • site: retire les kickers de /install et /pantheon — suite de b804d61e (1a55293)
  • site: thème manquant sur les vignettes d'étapes de /install/ (B2) (9972255)
  • site: une page 404, pour que le site cesse de répondre 200 à tout (a283ef3)
  • skills: asc-skills — description et source_url pointaient l'ancienne org (f19321a), closes #421
  • skills: contenir hyperresearch — il écrit dans le dépôt, pas dans le HOME (1640aa9), closes #404
  • skills: corrections review — licence affaan-m/ECC vérifiée (MIT) propagée à CREDITS (source = index git), fallback conjoint SF Symbols+Iconify indisponibles dans 27-isaac (a8dab94)
  • skills: le lock cite les dépôts canoniques, et le garde-fou le vérifie (#420) (#433) (f21b36e)
  • skills: les 7 sources qui n'installaient rien — trois causes, trois réponses (9071e58)
  • skills: re-locker complète le manifeste au lieu de l'amputer (110e470), closes #413
  • skills: trois sources déclarées sous un nom qui n'existe plus (#406) (4ada8d8)
  • skills: verify accusait l'amont d'une dérive qui n'avait pas eu lieu (#413) (0b0f306)
  • sphere thumbnails use .jpg, compress all images (332MB->21MB), fix tarot toggle (273deb2)
  • spheres.json — routine → maria (bijection) (066b0cd)
  • subagent-handoff: lire le flux hérité au lieu de rouvrir /dev/stdin (f4e3fe7)
  • sync-issues: diagnostic + exit code dédié, alerte unique en env sans gh (#369) (a0f45d6)
  • tarot FOUC prevention + prefers-color-scheme fallback (1db6a4c)
  • test: C7 ne voyait pas les 30 skills vendorisées à plat (0c0a8aa)
  • tests: #558 — avecFauxClaude aussi dans TestSansManifestURL + TestValidationÉchouéeDéclencheLeRollback (tous les tests runInstall ont un environnement déterministe) (57c8847)
  • tests: #558 — tests TUI déterministes en CI : faux binaire claude dans le PATH de test (le check preflight ClaudeCode est FATAL et claude est absent sur GitHub Actions — les 6 tests runInstall échouaient sans que le code soit en cause) (5bdac3f)
  • tests: résolveur skills aveugle aux symlinks + voie registry morte (bc6e5b5)
  • update Jimothy agent with full Wikipedia backstory + short spine syndrome portrait (1593a3c)
  • update-check: le binaire Homebrew n'était jamais vérifié (027be4a)
  • visuel cerbere dark complété (git mv raté) (27d0aa4)
  • visuels — deckard dark complété, pixel.jpg compressés (5), CSP JEU (4a9b162)
  • vps: l'orchestrateur annonçait 15 agents et n'en listait que 15 sur 16 (b8731ba)
  • wave-1: #461 gate anti-dérive subagents + doc 11 agents ; #435 dashboard auth token + allowlist install_cli ; #446 rapport skills pré-install ; #447 parseurs YAML unifiés (lib/frontmatter.cjs) ; #460 déjà résolu (SEC-03) (c12024a)
  • wave-1: #468 déjà résolu (préséance tdd/base-rules, cas référencé) — close documentée ; #438 gate whitespace ciblé (espace final unique vs hard break) + 21 parasites nettoyés ; #442 étage ast-grep dans hardcode-check (règle AST string, bypass # nocheck/ // nocheck, ast-grep + entrée cli-registry) (9befb1d)

Performances

  • convert all images to WebP (agents + spheres), prefer webp in auto-gen (2747199)
  • hooks: hardcode-check en deux étages — 108 s à 282 ms (9854507)
  • re-optimize WebP (quality 65%, method 6) — 72KB avg vs 83KB JPG (86e9c70)
  • site: convertit les illustrations pixel en WebP — 125,2 Mo → 13,0 Mo (4f68282)
  • site: récupérer ~18 Mo en cinq passes mécaniques (issue #471) (59c3a33)
  • site: règles de cache dans _headers — 185 Mo cessent d'être revalidés (fe59ee7)

Retours arrière

  • restore Hermes page to pre-subagent redesign (side-layout hero, clean cards) (9a828d0)

v7.12.0

Nouveautés

  • agents: descriptions routage auto-suffisantes — QUAND l'utiliser + exclusions, 19 agents (#487) (a6c6252)
  • agents: memory-capabilities — détection de capacités par preuve repo + confirmation user, banque mémoire vault (#552) (f9f198c)
  • aidd: #554 protocole executor/checker (Tier 1 scully + Tier 2 dredd, vérificateur ne corrige jamais) ; #555 proof-gate (85% de 'vérifié' sans preuve mesurés, étape 1 de 04-verifier réécrite) ; #556 lifecycle status étendu (additif, 335 fichiers épargnés) + outcomes CARD remplis (c7946b2)
  • aidd: #557 vcs-conventions-protocol (never assume main, 11 types de commit mesurés, règle 11 base-rules) ; #559 change-set-protocol (7 champs + 3 modes d'autorité, #558 comme exemple du mode 3) — CLAUDE.md restauré (budget 2477/2500) ; #558 extraction prête : la CI n'aura qu'à appeler pre-push (source unique, en attente décision Mathieu) (6ef5606)
  • gate: budget CLAUDE.md warn → block — budget tenu (2477/2500), dérive désormais bloquante (#486, #482) (76a757b)
  • hooks: ulk-memory-sync SessionStart — bloc mémoire 2-tiers idempotent entre marqueurs (#553) (e64bd7e)
  • site: CSP fermée — style-src 'self' (1123 style= → 0, Shiki → classes shiki-<hex>), font-src 'self' (18 woff2 auto-hébergés, plus de Google Fonts), LCP thème unique (#449 #455) (b517993)
  • site: redirects 301 fusion sphères — intendants + messagers reclassés vers maitres-d-oeuvre (#520) (69194bf)
  • skills: #509 arbitrage — grille 5 axes (7 skills), reject humanizer (patterns récupérés) + unified-memory (mono-harnais, purge Codex), adopt brand-voice (docs/brand-voice.md source vérité + 5 agents), skills écartées consignées (#510 #517 #516 #515) (6a12984)
  • skills: vendoriser browser-qa — la preuve vidéo d'un parcours, bornée par une carte (3c3a951)
  • skills: vendoriser browser-qa — QA navigateur post-review, preuve vidéo bornée par une carte (98f2eb7)

Correctifs

  • agents: blackemperor — déclencheur mode frontend dans la description (#487) (ec1754e)
  • agents: emoji memory-capabilities 🗺️ (🧭 pris par astride) (#552) (9950426)
  • agents: gandalf — retire claude-code-mastery (4893 tok, non essentiel pour un agent haiku), budget réaliste sans gonflage (#489) (fb8effe)
  • agents: memory-capabilities → ID 90 (89 réservé par 2 cartes backlog) + resync counts (#552) (22bfb64)
  • ci: #542 gate voit les merges — renovate gomod major dashboard-approval + bonjour signale l'amont + hook SessionStart go-build-verify ; #543 lock versionné : npm_ci_align + 3 commentaires corrigés ; #451 hook format : NO-GO documenté (fd3af2e)
  • gate: fraîcheur des hooks (#452), tests couverts par le sweep (#445), credits index vs disque (#453) (b849e36)
  • golden: memory-capabilities — pattern case-sensitive + fermeture frontmatter (#552) (7b3cd66)
  • handoff: task-brief.sh lit stdin via '-' — /dev/stdin non-device en conteneur/CI (#445 gate sweep) (b871cf5)
  • hooks: go-build-verify — go build borné en temps (120s) comme le fetch, promesse 'jamais de blocage' tenue (#542 review) (f4fbd95)
  • managed-agents: le générateur fabriquait des agents à partir de n'importe quel .md, et ne supprimait jamais rien (#523) (#546) (a906929)
  • memory: aligne context-hygiene + banner-mode sur #490 — plus de staging manuel en session interactive (#490) (34b1ce8)
  • protocols: préséances entre protocoles co-chargés + 4 evals comportementales — 6 collisions (#484) (5be0483)
  • refs: les trois derniers renvois morts de la vague 2 — #523 close (#547) (4c65931)
  • rules: native-features ne se chargeait pour personne depuis le split — plus l'oracle qui le dira (#523) (#544) (fee4dd6)
  • rules: purge les références mortes des renames vagues 1+2 (.claude/rules/ + mémoire peon) — #507 #523 (fce7648)
  • sec: #466 recettes curl|bash épinglées ou documentées (unpinned_reason + test) — audit SEC-01/02 ; feat(spec): #551 validateur CARD exécutable (TBD: anti-invention, 9 champs, warn gate) (590c8c1)
  • site: #437 compte de sphères dérivé de spheres.json (le '9' était FAUX : 10 sphères, la 10e 'Les Hommes en noir' jamais listée) — gate check-doc-counts étendu (3e source + exclusion _archive) ; #450 7 skills emilkowalski déclarées (83) + trou animation documenté ; #548 déjà résolu (vendoré 3c3a9514) ; #454 piste CWV sans Lighthouse documentée (6f338fa)
  • subagent-handoff: lire le flux hérité au lieu de rouvrir /dev/stdin (f4e3fe7)
  • wave-1: #461 gate anti-dérive subagents + doc 11 agents ; #435 dashboard auth token + allowlist install_cli ; #446 rapport skills pré-install ; #447 parseurs YAML unifiés (lib/frontmatter.cjs) ; #460 déjà résolu (SEC-03) (c12024a)

v7.11.0

Nouveautés

  • 8 renames pop-culture + sphere « Les Agents » (Matrix) (555e7d6)
  • agents: renommer brique → Numérobis, l'architecte (issue #495) (fa36494)
  • agents: renommer brique → Numérobis, l'architecte + nouveaux visuels (issue #495) (74d8610)
  • agents: renommer visual-auditor → Tyrion + visuels ranx (issue #497) (6d0af6b)
  • agents: renommer visual-auditor → Tyrion, l'œil qui juge (issue #497) + visuels ranx (60d4123)
  • routine → maria — l'automate des rites récurrents (Metropolis) (9b3defd)
  • sphere agents → « Les Hommes en noir » (MIB) — nom/role/meta + palette ardoise (253a958)
  • test-unit → wall-e (Pixar, 🧱) + complétion scully/thanos (d9c0f8b)

Correctifs

  • cli,site: aligner installateur et CSP sur les renames (numerobis + tyrion) (6cc3315)
  • cohérence C12 — maria cite cli-tools-protocol, allowlist purge (2144054)
  • CSP JEU (303 cibles — cerbere) (ceaf0e3)
  • gofmt agents_test.go (97c14a3)
  • registry: dériver la sphère depuis spheres.json (issue #463) (e5e45d5)
  • règles héritées injectées (renames) (3f66d31)
  • règles héritées injectées (wall-e/scully/thanos) (7d06527)
  • site: rendre les cartes lisibles sans la gravure ni la souris (7e6af64)
  • spheres.json — routine → maria (bijection) (066b0cd)
  • visuel cerbere dark complété (git mv raté) (27d0aa4)
  • visuels — deckard dark complété, pixel.jpg compressés (5), CSP JEU (4a9b162)

v7.10.1

Correctifs

  • release: release.sh repose le label autorelease que la CI ne pose plus (#477) (0533cb3)

Performances

  • site: récupérer ~18 Mo en cinq passes mécaniques (issue #471) (59c3a33)

v7.10.0

Nouveautés

  • agents: chaque agent signe d'un emoji au démarrage — Bruce est un loup (49f05e4)
  • gate: surveiller les dépôts tiers cités hors registry (#425) (#434) (cdf6da3)
  • skills: verify --upstream nomme la cause d'une dérive (81acb10), closes #413
  • skills: câbler HyperResearch sur les huit agents qui cherchent dehors (c2e87d1), closes #404
  • skills: check-skill-repos vérifie aussi description et source_url (720a90a), closes #425
  • skills: porter zine-web-interface + Ranx (87) depuis la PR #375 (44aaf1c)

Correctifs

  • agents: écrire la signature dans le bloc de chaque agent, pas dans un renvoi (9dbedbc)
  • deps: sortir esbuild de la plage vulnérable — par le bas, faute de mieux (4575fcb)
  • deps: update module github.com/charmbracelet/bubbles to v2 (#410) (e136fa9)
  • deps: update module github.com/charmbracelet/bubbletea to v2 (#411) (ae13ce9)
  • gate: corriger les 3 dérives de dépôts et installer les deps au wt new (#425, #429) (#475) (3b1943d)
  • gate: le verdict du pre-push dit ce qu'il a mesuré (#429) (#432) (67756c7)
  • go-cli: une sortie 0 à pipe orphelin n'est plus un échec d'installation (#422) (e89cc91)
  • go: revert bubbletea/bubbles v1→v2 (bis) et bloquer le major côté Renovate (325e7af)
  • installer: ulk-installer upgrade déclenche le mode mise à jour (#427) (c50edba)
  • installer: upgrade annonçait un résultat qu'il n'avait pas cherché (45baa4e)
  • installer: borner l'attente d'un pipe tenu par un petit-fils détaché (12837aa), closes #415
  • installer: le bundle porte les skills que ulk install pose (43097f0)
  • isaac: retirer les deux skills FoundationModels mortes, garder le besoin (#426) (#431) (2e91433)
  • release-installer: $VAR… tuait la publication après signature et build (d505bda)
  • release-installer: exiger le terminal avant de travailler, pas au moment de signer (c32b76c)
  • site: « arcane » est féminin — accord tranché et harmonisé (0202cb5), closes #395
  • site: métas uniques par page et logique des sphères exposée (#395 P2/P3) (60b3e70)
  • site: une page 404, pour que le site cesse de répondre 200 à tout (a283ef3)
  • skills: asc-skills — description et source_url pointaient l'ancienne org (f19321a), closes #421
  • skills: contenir hyperresearch — il écrit dans le dépôt, pas dans le HOME (1640aa9), closes #404
  • skills: le lock cite les dépôts canoniques, et le garde-fou le vérifie (#420) (#433) (f21b36e)
  • skills: re-locker complète le manifeste au lieu de l'amputer (110e470), closes #413
  • skills: trois sources déclarées sous un nom qui n'existe plus (#406) (4ada8d8)

Performances

  • hooks: hardcode-check en deux étages — 108 s à 282 ms (9854507)

v7.9.1

Correctifs

  • go: désépingler les toolchains sur les patchs qui corrigent la stdlib (cc0b16f), closes #414
  • npm: versionner les lockfiles, sans quoi le gate npm audit ne garde rien (20d2388)
  • pre-push: confiner GOTOOLCHAIN au module dont il est dérivé (afb7afc)
  • refusal-scope: même bypass inexécutable que sentinel, et sa limite (5965941)
  • release-please: migrer au format manifest et retirer la CI de la publication (ef858c0)
  • sentinel: le bypass one-shot n'était pas exécutable par un shell (829a440)
  • sentinel: résoudre le dépôt visé, pas le cwd de la session (c9810a6)
  • update-check: le binaire Homebrew n'était jamais vérifié (027be4a)

v7.9.0

Nouveautés

  • bruce: le mode de sortie se choisit, une fois par session (dca64fc)

Correctifs

  • gate: les deux oracles Go étaient inertes par notre faute, pas celle de l'amont (#414) (2377065)
  • gate: skills verify échouait sans avoir rien vérifié, et accusait une skill (46d5494)
  • installer: le « binaire statique » de la spec ne l'était pas (#393) (b07d4e2)
  • security: trois gardes qui ne gardaient rien (#402, #403, #392) (0ed9177)
  • site: les cartes coupaient les rôles au milieu des noms de fichiers (#395) (a87237a)
  • skills: verify accusait l'amont d'une dérive qui n'avait pas eu lieu (#413) (0b0f306)
  • test: C7 ne voyait pas les 30 skills vendorisées à plat (0c0a8aa)

v7.8.1

Une question — « pourquoi le site affiche cette commande ? » — à laquelle la bonne réponse n'était pas de corriger la commande citée, mais de vérifier si les autres tenaient. Le site était fiable à 84 fiches sur 85 ; ce qui manquait, c'est ce qui garantissait de le rester. Dans la foulée, neuf commandes qui n'auraient jamais dû exister ont quitté le namespace de l'utilisateur. 3 commits depuis la 7.8.0.

Corrigé

  • Le site publiait une commande morte. benjamin (64) était rangé dans agents/analyze/, au milieu des analyseurs de framework (astro, next, nuxt, spip, swiftui) — le nom d'une commande étant dérivé de son chemin, le devil's advocate s'annonçait /ulk:analyze:benjamin. Remis en agents/audit/ auprès d'astride, agathe et frodo : /ulk:agents:benjamin. Deux défauts découverts en le corrigeant. 50-tony.md:327 lisait le chemin en dur, donc mort au déplacement : Tony ne pouvait plus invoquer Benjamin, alors que c'est lui qui le convoque sur les bets techniques. Et surtout npm run gen est idempotent-only — il saute toute fiche existante, si bien qu'une fiche publiée ne se resynchronise jamais sans --force et affiche ses valeurs d'origine indéfiniment, sans erreur. Les 85 fiches ont été resynchronisées ; une seule avait dérivé, ce qui borne le dégât.
  • Neuf fichiers de référence squattaient le namespace de commandes. Claude Code dérive une slash command de chaque .md sous ~/.claude/commands/ — il ne lit pas le frontmatter pour décider si le fichier en est une. Tout ce qu'on dépose dans l'arbre devient donc invocable : /ulk:README, /ulk:agents:CLAUDE, /ulk:agents:Readme, /ulk:agents:ci-guard-patterns et les cinq /ulk:frontend:checklists:*. Le critère retenu est celui que porte la donnée — un fichier n'est une commande que s'il a un frontmatter : les 85 agents en ont un, les neuf pseudo-commandes n'en avaient aucun. SKIP_FILES ne couvrait que les noms connus d'avance, donc un nouveau fichier de référence dans une catégorie compilée repassait en commande sans bruit. Les agents ne perdent rien : ils lisent ces fichiers par chemin repo, jamais par slash command — le précédent existait déjà, _shared/checklists/ (6 fichiers) n'est dans aucune catégorie compilée et n'a jamais manqué à personne.

Ajouté

  • site-commands-conformance.test.mjs — le maillon site ↔ registry n'était couvert par rien (registry ↔ commandes l'était par agents-commands-coverage), et c'est précisément celui qui a lâché. Quatre assertions : l'invocation publiée est celle du registry, aucune commande citée n'est absente de framework/commands/, et les 17 commandes livrées par --with-vps annoncent leur flag d'install. Sondé failable avant câblage au pre-push — réinjecter l'ancienne commande fait tomber deux assertions, avec le remède dans le message.
  • Deux garde-fous plutôt qu'un sur le namespace, parce qu'ils protègent des choses différentes : isCommand() dans le générateur décide ce qu'on produit (94 → 86 fichiers), pruneNonCommands() dans l'installateur décide ce que l'utilisateur obtient. La seconde couche n'est pas redondante — fsCopyDir ne supprime pas les fichiers obsolètes de la destination, donc sans elle les neuf fichiers déjà installés seraient restés dans ~/.claude/commands/ulk/ même après réinstallation. Les installations existantes se réparent au prochain ./install.sh.
  • Deux recettes rejouables closent les cartes du 2026-07-28 restées ouvertes faute de preuve par exécution. poc-hooks-resync.sh prouve la garde d'identité en la jouant, jamais en lisant le code — et sa version vulnérable est dérivée du script courant, avec un échec bruyant si la dérivation ne retire plus rien, sans quoi un renommage en amont rendrait un faux vert en ne testant plus rien. recette-adhd-install.sh obtient l'état « machine sans état préalable » par un HOME déplacé plutôt qu'une VM, et garde un contrôle négatif sur le HOME réel — sans lui, un fichier préexistant chez l'utilisateur ferait passer la recette sans que l'installateur ait rien posé.

Notes

  • /ulk:analyze:benjamin n'existe plus. L'agent reste joignable en langage naturel (« benjamin », « sparring », « débat », « challenge ça ») et par /ulk:agents:benjamin après réinstallation. Le retrait des huit autres commandes ne casse aucun usage documenté : aucune n'était un agent.
  • La fixture de installer_test.go créait ses commandes sans frontmatter, ce qui ne reflétait pas ce que produit le générateur. Corrigée — sinon le nouveau prune les supprimait toutes, et le test le disait.
  • Le commentaire d'en-tête de command-layout.cjs renvoyait à framework/cheatheet/tests/command-layout.test.cjs, un test qui n'a jamais existé. L'invariant était bien couvert, mais ailleurs.

v7.8.0

Une journée passée à vérifier que les garde-fous gardent quelque chose. Trois gates rendaient vert sans rien contrôler, un quatrième était rouge en permanence depuis des mois et masquait sept sources mortes. Tous réparés, puis sondés — un gate qu'on n'a pas vu échouer n'est pas un gate. Six nouveaux s'y ajoutent. Et l'eval comportementale, une fois écrite pour de bon, a dit autre chose que ce qu'on attendait d'elle. 40 commits depuis la 7.7.0.

Ajouté

  • Trois nouvelles mailles de cohérence statique — C10, C11, C12. C10 vérifie que les commandes et flags cités dans la prose existent ; C11 que les _shared/*.md et les fichiers de code cités existent ; C12 que tout protocole déclaré en extends: est bien cité par le corps de l'agent. Chacune est sondée : on l'a fait échouer volontairement avant de la garder. Le périmètre de C11 est délibérément étroit — gater « tous les chemins » aurait produit un rouge permanent à 34 %, donc un gate désactivé dans la semaine.
  • extends: devient un invariant, après arbitrage. Le champ avait trois lectures défendables et aucune n'avait été choisie ; 149 paires étaient déclarées sans que le corps les cite. La lecture retenue engage le corps à honorer la déclaration. Les 149 écarts sont gelés, pas nettoyés — chaque retrait est une décision par agent, et supprimer les lignes aurait détruit l'information qui permet de trancher.
  • L'échelle de promotion du savoir (agents-authoring.md) — trois barreaux, éphémère → prose → exécutable, avec les questions de garde à poser avant d'ajouter une règle. Une règle prématurée coûte des tokens à chaque session et fige une décision non prise.
  • Un budget de contexte mesurablecheck-context-budget.cjs compare CLAUDE.md à sa cible de 2 500 tokens. Il avertit sans bloquer, parce que le budget n'est pas tenu (≈ 2 816) : durcir une contrainte avant de la tenir, c'est se garantir qu'elle sera retirée.
  • Un oracle de contraste WCAGcheck-contrast.mjs mesure les paires encre × surface dans les deux thèmes. Aucune des six paires fautives n'était vérifiée par quoi que ce soit.
  • ulk skills lock / verify — ulk calcule ses propres empreintes SHA-256 des skills installées, npx skills add n'en produisant aucune dans notre mode d'usage. 66 sources épinglées.
  • L'eval comportementale live existe et s'exécute — chaque scénario force un choix dans une liste fermée de premiers gestes, et vérifie conjointement la décision annoncée et le geste choisi.

Modifié

  • i-have-adhd passe en always-on et devient la doctrine de sortie unique. base-rules.md cède sur deux anti-patterns qu'il contredisait : deux sources de vérité qui se contredisent ne produisent pas un compromis, mais un agent qui arbitre au hasard.
  • Dégonflage des skills — 266 → 181. Un --skill "" installait l'intégralité des catalogues Google Cloud et ASC.
  • La cohérence scanne enfin CLAUDE.md et les _shared/ — jusqu'ici elle ne regardait que les corps d'agents, alors que cette prose est lue par tous les agents.

Corrigé

  • ulk-sdk et le status-board voyaient un roster vide — et leurs tests entérinaient le bug. Trois défauts empilés : un chemin de scan périmé, l'absence de récursion, et un parseur de frontmatter qui aplatissait les sous-blocs. La cause racine était un Set vide retourné en silence ; il lève désormais.
  • Les cinq totaux de CREDITS.md étaient recopiés à la main — ils se dérivent.
  • generate-registry.cjs n'était plus idempotent et salissait l'arbre à chaque exécution.
  • Sept sources de skills n'installaient rien — trois causes distinctes, trois réponses. Elles étaient masquées par un ulk skills update en échec permanent.
  • Les 85 fiches d'agents ne rendaient pas leur nom aux lecteurs d'écran ; le titre de /hermes peignait avec les joyaux et les liens ne se distinguaient que par leur teinte (WCAG 1.4.1).
  • Le thème du site ne suivait pas la préférence système — le tarot le faisait déjà, pas lui.
  • Trois liens morts dans model-policy.md, le document qui fait autorité sur les modèles.
  • ULK_BEHAVIORAL_LIVE=1 rendait un vert vide. Le test contenait un assert.ok(true) : activer le drapeau — geste que la politique prescrivait — produisait un faux positif. Passé en échec franc, puis implémenté.

Sécurité

  • RCE par ouverture d'un dépôt tiers (CWE-829 / CWE-494)hooks-resync.sh était un hook SessionStart global dont la seule condition d'activation était la présence de scripts/hooks/pre-push dans le dépôt courant. Cloner un dépôt hostile et l'ouvrir suffisait à faire installer ses hooks en exécutable ; le payload partait au premier git commit. PoC exécuté en sandbox. Ramené en portée projet, puis doté d'une garde d'identité dans le code lui-même — la protection ne résidait que dans la façon dont il était déclaré.
  • Le dashboard ne gardait que ses écritures — les trois GET étaient exposés au DNS rebinding. sameOriginGuard enveloppe désormais le mux entier.
  • Trois gates rendaient vert sans rien vérifiernpm audit n'auditait pas site/ (ENOLOCK avalé par un motif hors-ligne), Biome tournait en preset: none (0 règle), et le test de conformité des sphères plantait à l'import. Réparés et sondés.

Notes

L'eval comportementale, une fois exécutée, a produit un résultat qui va contre son intention : sur les trois scénarios, le modèle nu se comporte exactement comme l'agent doté de son protocole. Les trois verts ne valident donc pas les protocoles — ils constatent que le modèle courant n'en a pas besoin ici. Le verdict de durabilité reste indécidable, et la raison a changé : ce n'est plus un câblage manquant, c'est un instrument qui ne sépare pas l'agent de son modèle. Le résultat est écrit dans l'outil plutôt que passé sous silence.

v7.7.0

Le site devient un jeu de tarot — « Le Tirage » en accueil, trois thèmes, illustrations refaites — et l'installateur devient un binaire signé qui refuse ce qu'il ne peut pas vérifier. 162 commits depuis la 7.6.0.

Ajouté

  • « Le Tirage » — la page d'accueil devient un tirage — la home s'organise autour d'un fold unique, d'une carte tirée et du panthéon derrière elle (« La Coupe »). L'ancienne page n'est pas supprimée mais archivée : une refonte d'accueil qui efface ce qu'elle remplace interdit de comparer.
  • Trois thèmes tarot — Cthulhu Sombre et Gustave Doré (couple sombre/clair, bascule explicite), puis un troisième en pixel art Castlevania SOTN. Les 9 sphères et l'intégralité des portraits d'agents ont été régénérés dans l'identité Cthulhu Dark Tarot, AGENT_ILLUSTRATIONS étant désormais dérivé du système de fichiers — un agent sans portrait devient visible au lieu de rester silencieux.
  • Nouvel installateur — binaire Go statique + TUI Bubble Tea — remplace le script shell : téléchargement du manifeste, vérification minisign, extraction du bundle, validation d'installation, le tout câblé dans le TUI (il installait auparavant en simulation). Le SHA256 déclaré est honoré et une copie tronquée échoue au lieu de passer.
  • ulk-bundle — le bundle a enfin un producteur — générateur de tarball déterministe + manifest.json, avec injection de la clé publique au build (Makefile) plutôt qu'une constante figée dans le code. release-installer.sh déroule la chaîne complète.
  • /changelog/ — ce fichier rendu sur le site, avec navigation et ancres par version.
  • /a-propos/ — crédits complets : design, illustrations, fontes, stack, outillage, et renvoi vers CREDITS.md.
  • Section Hermès sur le site (#362, #378) — catalogue des 27 skills portées, documentation et entrée de navigation.
  • Agent jimothy — raton laveur de Seattle, charognard du dépôt : rapports par email plutôt que publication sociale.
  • Agent chromie (#391) — régression visuelle par toHaveScreenshot() (Playwright + Docker), diffs postés en commentaire de PR.
  • picsou — mode frugon (#367) — repricing empirique des modèles (T1→T3).
  • Sécurité native Claude Code intégrée (#390) — les trois couches (security-guidance, /security-review, claude-security) câblées et documentées.
  • Le build du site entre au gate — les cinq oracles tournaient après le push, donc trop tard ; ils sont désormais au pre-push (2 prebuild + 3 postbuild, ~2,5 s). L'installateur, lui, vivait sans aucun oracle : il en a maintenant huit suites (~1 200 lignes) et son propre go_gate.
  • Invariant de cohérence C9 — managed-agents ↔ sources (#365).

Modifié

  • Sentinel repasse en opt-in (--with-sentinel) — actif par défaut depuis le 11 juillet au titre d'AIDD V2, le hook interposait une cascade d'audits (xavier+ed209 au push, picsou+ed209 au deploy) sur tout ulk install. Engager le rythme de travail d'un projet à chaque git push est une décision de projet, pas un défaut d'installation — d'autant que le filet qui couvre le repo quoi qu'il arrive reste scripts/hooks/ (full-local gate), que Sentinel soit installé ou non. Le module ne change pas : demandé explicitement, il sème toujours .ulk/config.json en mode: remind, et le mode effectif reste piloté par ce fichier. TestSentinelIsOptIn épingle la décision dans les deux sens — éteint sans le flag, allumé avec — parce qu'un défaut qui rebascule en silence est exactement ce que ce test existe pour attraper.
  • Illustrations converties en WebP — 125,2 Mo → 13,0 Mo — le dépôt portait des images pixel non optimisées (332 Mo avant les premières passes). Réencodage à qualité 65 / méthode 6, WebP préféré à la génération automatique.
  • Règles de cache dans _headers — 185 Mo cessent d'être revalidés à chaque visite ; cumul vérifié en production, pas seulement en local.
  • extends: base-rules.md devient portant — le noyau de règles est injecté dans le corps des agents au lieu d'être une simple mention : un extends qui ne charge rien est une promesse non tenue à l'échelle du roster.
  • Binaires hébergés sur la release du tap public, miroir VPS retiré (#377) — une source de vérité au lieu de deux, avec garde-fou anti-404 sur le miroir tant qu'il existait.
  • Hermès 0.1.0 → 0.3.0 — tarball reproductible byte-à-byte, publication automatisée (--publish / --deploy), tag et GitHub Release (--github), et durcissement de release.sh (set -e, trap de nettoyage, source unique du payload).
  • Bruce (25) — gate d'isolation de session + lecture d'une carte Faru collée directement dans le prompt.
  • Épinglage des recettes curl | shcurl.md et docker pointent leur source amont, doctrine consignée dans cli-registry.json.
  • Purge de 63 rapports d'audit datés et des fragments morts du site (#366) — les renvois vers les rapports supprimés ont été réparés dans le même mouvement, faute de quoi la purge n'aurait fait que déplacer la dette.

Retiré

  • --without-sentinel retiré — un opt-out n'a pas d'objet sur un module opt-in. Le flag avait deux semaines (introduit avec le défaut du 11 juillet) ; la rupture de compatibilité est nominale.
  • .hooks/ supprimé — doublon jamais installénpm run prepare ne copie que scripts/hooks/*, mais .hooks/pre-commit restait versionné, s'auto-documentait comme la procédure d'installation (« cp .hooks/pre-commit .git/hooks/ ») et était cité comme source de vérité dans framework/tools/cli-registry.json et la mémoire de peon. Les deux fichiers avaient divergé sans plus rien partager. Ce qu'il portait est préservé : les golden tests tournent au pre-push depuis la migration, shellcheck est réintégré au pre-commit (voir Fixed).
  • .codex/ supprimé — cible retirée du codeulk export --target codex renvoie « target retiré — ulk est désormais 100 % Claude Code + Mistral Vibe » (framework/cli/cmd/export.go) depuis la bascule Vibe, mais 11 .toml figés au 18 juillet restaient versionnés. Ils n'étaient plus régénérables, ne couvraient qu'une fraction du roster, et rien ne signalait leur péremption. Cible unique : vibe (_shared/vibe-protocol.md).

Corrigé

  • shellcheck ne tournait plus nulle part — porté par le seul .hooks/pre-commit, il a cessé d'être exécuté à la mort silencieuse de ce hook : ni au commit, ni au push. Les golden tests du même fichier, eux, avaient été repris au pre-push — d'où une perte invisible, un gate sur deux ayant survécu à la migration. Réintégré dans scripts/hooks/pre-commit sur les scripts stagés, hooks sans extension compris. Base soldée au passage : trois avertissements dormants dans bonjour-collisions.test.sh, sync-issues.sh et hermes/release.sh, pour qu'aucun contributeur ne soit arrêté par des alertes qu'il n'a pas causées.
  • Garde-fou anti-hook-fantôme (framework/tests/hooks-conformance.test.mjs) — échoue si un pre-commit/pre-push/commit-msg/post-merge est versionné hors de scripts/hooks/, et si package.json → prepare cesse d'installer depuis ce répertoire : sans ce second volet, l'emplacement imposé ne serait plus celui qui s'exécute.
  • EXCLUDE_AUTHORS trompeur (framework/tools/sync-issues.sh) — variable jamais lue, voisine d'EXCLUDE_LABELS qui, lui, pilote vraiment le filtre et se surcharge en CLI. La liste des bots est en dur dans le case du bloc descendant ; la symétrie laissait croire qu'ajouter un bot à la variable changeait le comportement. Retirée au profit d'un renvoi vers la logique réelle.
  • Mémoire de peon corrigée — elle affirmait qu'un hook lançait go mod tidy sur les changements de cli/, en citant le titre du commit f3744eb (« golden guard + go mod tidy ») qui décrivait un tidy fait dans ce commit. Aucun hook ne l'a jamais fait : go.mod/go.sum ne bougent pas seuls au commit.
  • La dérive des comptes d'agents — « 83 agents » annoncés par Bruce et par le site pour un roster de 85, l'orchestrateur VPS en annonçant 15 pour 16, les « 27 skills » Hermès figées en dur. Règle appliquée partout : dériver le compte de sa source ou le retirer, jamais le réécrire à la main. Le gate check-doc-counts couvre désormais aussi les .md du site.
  • 93 liens internes audités, 43 réparés — le dépôt renvoyait vers des cibles déplacées ou purgées.
  • Le changelog perdait la moitié de ce qu'on y écrit — le parseur tronquait le rendu ; corrigé, ainsi que la résolution de chemin qui cassait le build.
  • Accessibilité du siteinert sur le contenu sous-jacent et hamburger inclus dans le piège au focus, contraste et hiérarchie de titres (lot 2 de l'audit front), thème manquant sur les vignettes de /install/, /install illisible en thème clair.
  • Modale d'agent sur iOS Safari — unités dvh au lieu de vh : le défilement devenait incontrôlable. La modale reprend par ailleurs là où la fiche s'arrête, et les fiches remontent le préambule de leur définition.
  • bonjour — garde de non-régression sur le bloc Collisions (#336), fuite du watchdog, garde-fou fichier absent restauré et repli sed quand jq manque (#368).
  • sync-issues — diagnostic explicite et code de sortie dédié, alerte unique dans un environnement sans gh (#369).
  • credits — lecture des sources depuis l'index git et non le working tree (#321) : le générateur voyait des fichiers non commités.
  • Résolveur de skills aveugle aux symlinks + voie registry morte, et framework/commands/gardiens/ jamais raccordé au générateur (/ulk:agents:jimothy était ininvocable).
  • Cohérence des modèles Opus 5 / Sonnet 5 — items 1 à 7 de l'audit de durabilité, frontière des modèles mesurée sans run facturé.
  • bubbletea/bubbles v2 annulés (#388) — imports incompatibles et surface d'API trop large ; l'installateur a rejoint la stack Charm du CLI par MVS (v1.1.0) plutôt que par un saut majeur.

Sécurité

  • CSP qui ferme script-src par empreinte — les 5 scripts du site sont hachés, aucun script externe n'est admis, et un gate (check-csp.mjs) empêche la politique de pourrir : il scanne CSS et HTML sur les 6 pages types et échoue sur violation. Vérifié sur le site déployé, pas seulement au build.
  • En-têtes de sécurité Cloudflare Pages (site/public/_headers) — vérifiés en production.
  • Fin de l'eval au build + échappement du markdown des agents — le rendu des fiches injectait du markdown non échappé et le build évaluait du code ; les deux voies sont fermées.
  • npm audit n'auditait que la racinesite/ échappait entièrement au gate, alors que c'est la surface publiée. Étendu.
  • Chaîne d'installation fail-closed — clé publique injectée au build et non figée en constante, préflight dédoublonné, manifeste signé (minisign) vérifié avant toute écriture : l'installateur refuse ce qu'il ne peut pas vérifier plutôt que de continuer.
  • sharp^0.35.0 (#396) et yaml v3.0.5 dans le CLI, passés par le gate local et non par la porte GitHub.
  • Les liens symboliques quittent l'extraction de bundle — la garde anti-zip-slip résolvait la cible d'un lien avec filepath.Join, qui traite sa seconde composante comme relative même quand elle commence par / : une cible absolue franchissait le contrôle puis était écrite telle quelle, et un second membre de l'archive passant par ce lien atterrissait hors du répertoire d'installation. Exploitation conditionnée à la compromission de la clé de signature — défense en profondeur, pas porte ouverte. Le producteur n'émettant que des fichiers réguliers, la capacité est supprimée plutôt que gardée : ExtractBundle refuse désormais tout lien. Trouvé par ED-209 (docs/audits/ed209-20260727.md), reproduit par test.

v7.6.0

Le Punisher (85) rejoint les souverains — release totale radicale — et deux agents pivots changent d'identité : sauron (ex-obiwan) et peon (ex-2b3), visuels inclus.

Modifié

  • Renommage obiwan (61) → sauron — le Chief Product Officer devient l'Œil : vision panoptique du portefeuille produit, épithète « l'œil qui voit tout le portefeuille ». Rapports docs/reports/sauron-*, invocation /ulk:sauron (« obiwan » conservé en alias legacy). Renommage transverse : agents, protocoles _shared/, règles, CLI Go, miroirs commands, site (fiche + sphère oracles + descriptions FR), golden test.
  • Renommage 2b3 (08) → peon — le checkpoint de fin de session devient le Péon (Warcraft II/III) : défini par sa fonction, dos voûté, répliques cultes VF câblées sur le style caveman (« Zug-zug » = phase reçue · « Dabu » = phase ok · « Travailler, travailler… » = pipeline en cours · « Encore du travail ? » = commit scellé). Invocation /ulk:peon (« 2b3 » conservé en alias legacy), mémoire .claude/agent-memory-local/ulk-peon/, managed agent ulk ma peon, fiche site sphère gardiens. L'historique (CHANGELOG, docs/audits/, backlog archivé) garde les anciens noms.
  • Illustrations définitivessauron.jpg (Œil de Sauron, © New Line Cinema / Warner Bros.), peon.jpg (péon orc Warcraft, © Blizzard Entertainment), punisher.jpg (couverture © Marvel Comics) + entrée AGENT_ILLUSTRATIONS et crédits illustrations.ts à jour.
  • Purge docs/_inbox — 600 fichiers de triage supprimés (−129 500 lignes), README docs/ réorganisé par dossiers, palette source déplacée vers docs/visuels/.

Ajouté

  • Agent punisher (85) — release totale radicale — orchestrateur qui exécute la release complète de bout en bout, là où blackemperor mode=release rend un verdict et mode=ship livre vite : gate GO/NO-GO (délégué à blackemperor 18), rangement radical du repo (fichiers errants, cartes done archivées, code mort, TODO fantômes), doc scellée (CHANGELOG Keep-a-Changelog, README, CLAUDE.md via shuri 01 + /claude-md-improver, générateurs projet), site régénéré + build de contrôle, et kit de communication dans un dossier dédié docs/release/vX.Y.Z/ (RELEASE-NOTES, posts par canal x/linkedin/bluesky/mastodon, email partenaires, note interne — rédaction déléguée à brigitte 24, skill avoid-ai-writing). Règle d'or « prépare tout, ne publie rien » : refuses: sur force-push, push main, gh pr merge, gh release create ; tag local non poussé, publication humaine. Golden test + fiche site (sphère souverains). Spec : docs/backlog/archive/2026-07-18-spec-punisher-release-totale/CARD.md.
  • Suite d'invariants cohérence C5–C8 (framework/tests/agents-coherence.test.mjs) — refs archivées (C5), numéros nom (NN) (C6), loads_skills résolvables (C7), count opus ↔ table de justification model-policy (C8) ; table d'alias slug↔nom installée framework/skills-aliases.json + résolveur, fixtures golden otto (C4). Issu de l'audit cohérence roster 2026-07-17.

Corrigé

  • Handoffs vers agents archivés — les renvois vivants vers Ranma (31) redirigés vers tony (50) mode=audit ; handoff skills-radar (archivé) → sauron (61). Bruce annonce le bon compte d'agents (83).
  • 5 skills fantômes retirées des loads_skills de sauron (ex-obiwan) — plugins opt-in, pas des skills registry.
  • Collisions de routage à la saisie — anti-triggers croisés gandalf/xavier, mot-clé « audit visuel » désambiguïsé (visual-auditor/agathe), identifiant brique, extends alphabétique (#355, #348, #347).
  • DESIGN.md casing (#354, merci @Devil1716), bonjour.sh dépendance jq, crash govulncheck dans le hook pre-push.

v7.5.0

Intégration design (impeccable), autopilote de backlog (otto), récupération d'espace disque (ulk reclaim) et vérification de mise à jour quotidienne.

Ajouté

  • Intégration impeccable (design) — skill/plugin de direction artistique + lint déterministe (pbakaus, bâtie sur frontend-design d'Anthropic) : /impeccable init (→ PRODUCT.md/DESIGN.md), 23 commandes /impeccable (craft, critique, bolder, quieter, distill, audit…) et 46 détecteurs d'anti-patterns exécutés sans LLM ni clé API. Câblée en loads_skills des 5 agents design (stark 58, agathe 60, brique 01, visual-auditor 03, agamotto 17) et positionnée complémentaire à hallmark dans _shared/design-source-protocol.md §5ter (règle de coexistence : docs/design.md reste la source de vérité ; le DESIGN.md/PRODUCT.md d'impeccable l'alimentent). Install : npx impeccable install.
  • Agent otto (84) — autopilote ticket→PR (#338) — orchestrateur qui déroule le backlog : délègue l'implémentation, ouvre une PR draft, attend le merge avant de passer au suivant. Nouveau protocole _shared/executor-protocol.md (retry borné sur gate échoué, blocage séquentiel une unité en vol par working tree, report sans silent caps), câblé aussi dans task-runner (04).
  • ulk reclaim (#284) — récupération d'espace disque : scanne les répertoires régénérables (dépendances, sorties de build, caches d'outils). Dry-run par défaut (--apply pour agir), heuristique de sûreté (noms génériques dist/build/out/target réclamés seulement à côté d'un manifeste projet), flags --older-than N / --only deps,build,cache / --json.
  • Vérification de mise à jour — check quotidien propose-only (binaire ulk, agents/skills, CLIs requises manquantes) piloté par Bruce (25) Phase 0.6, et rappel mensuel de la maintenance native /checkup (alias de /doctor), gated 1×/mois calendaire. Pur shell, 0 token, jamais appliqué sans accord.
  • Intégration grill-me / grilling (interview pré-build, #350) — skills externes (mattpocock/skills, MIT) qui stress-testent un plan/design avant le build : interrogatoire descendant l'arbre de décision une question à la fois (réponse recommandée jointe, faits cherchés dans l'environnement, pas d'action avant shared understanding). grill-me = front door user-invoquée stateless (/grill-me) ; grilling = primitive model-invoquée. Nouveau protocole _shared/grilling-protocol.md (coexistence avec triple-questioning agent-interne et le questionnaire de tony, sans doublon), enregistrement registry (skills-sources.json), référence dans base-rules.md + agents/CLAUDE.md, et loads_skills: grill-me sur les 4 porteurs canoniques : tony (50), bruce (25), obiwan (61), shuri (01). Artefacts d'install locaux gitignorés (non vendorés, réinstallés via ulk skills update).

Corrigé

  • Dérive des miroirs framework/commands/task-runner (source enrichie d'_shared/executor-protocol.md sans régénération du miroir) et otto (miroir de l'agent 84 jamais généré) resynchronisés via generate-commands.cjs (idempotent, déterminisme vérifié).

v7.4.1

Correctif. Deux skills promises depuis toujours et jamais installées, plus la porte d'entrée de session (/ulk:bonjour) et ses défauts de robustesse.

Corrigé

  • HookModule n'installait jamais la skill qu'il promettaithandoff-hook et context-mode annonçaient « Unlocks : Skill … » dans leur pédagogie, mais HookModule n'exposait que scriptSrc + configSrc : aucun champ n'installait de skill. Les deux SKILL.md étaient versionnés dans framework/community-skills/ et copiés nulle part. L'installateur imprimait la promesse et n'en tenait que la moitié, sans erreur ni avertissement. HookModule accepte désormais communitySubdir + skillPrefix (même contrat que SkillModule), et Uninstall honore removeGlobs. /ulk:handoff et /context-mode s'installent enfin réellement.
  • Test de non-régression sur la classe entièreTestModulePromisingSkillInstallsOne échoue si un module dont Unlocks mentionne « Skill » n'en déclare aucune. Vérifié par mutation : rouge sans le correctif.
  • bonjour.sh — ancrage à la racine du dépôt — le script supposait cwd == racine sans jamais l'imposer. Lancé depuis un sous-dossier, il ne plantait pas : il rendait silencieusement « mode obsidian » et « rien à lister » sur un projet faru peuplé, et semait un .claude/state/ orphelin dans chaque répertoire d'invocation (chaque dossier avait alors son propre tampon de gate). Une sortie fausse sans erreur est pire qu'un échec franc.
  • bonjour.sh — borne réelle sur les appels réseau — sans coreutils, macOS n'a ni timeout ni gtimeout : l'ancien fallback exécutait la commande nue. La promesse « un brief matinal ne bloque jamais l'ouverture d'une session » était fausse précisément sur la plateforme principale. Remplacé par un watchdog bash pur, sans dépendance.
  • bonjour.sh — fenêtre des PR mergées — « PR récemment mergées » remontait les 5 dernières sans filtre temporel, fussent-elles vieilles de six mois. Ajout de --search "merged:>=<dernier brief>".
  • bonjour.shforce amputait la fenêtre du lendemainforce est un rejeu, pas un nouveau brief ; il avançait pourtant la borne de collecte, vidant le bloc « Hier (toi) » du brief suivant. La borne n'avance plus qu'au premier brief du jour.
  • feedback-loop (16) — dégradation gracieuse — l'agent sortait en erreur dès que accountability.jsonl était absent, alors que 2 de ses 4 patterns ne dépendent que de git log. Il dégrade désormais au sous-ensemble git-only au lieu d'échouer.

Ajouté

  • /ulk:bonjour (#336) — brief de début de journée, symétrique de 2b3 : le cycle de session avait une porte de sortie, pas de porte d'entrée. Urgences (CI rouge, PR à relire, issues P0, cartes blocked) · collisions (fichiers modifiés des deux côtés, toi et l'amont) · activité du remote · commits de la veille · cartes wip/todo · un cap. Collecte en pur shell (framework/tools/bonjour.sh), read-only, gaté 1×/jour. Câblé dans Bruce (25) Phase 0.7, non bloquant.

    ⚠️ Le bloc Collisions — désigné par sa propre carte comme la raison d'être du skill — n'a pas encore été validé sur un repo multi-contributeur : il ne peut pas l'être sur ulk, qui est mono-contributeur. Issue #336 volontairement laissée ouverte jusqu'à cette validation.

v7.4.0

Trois axes : automatisation full-local (label-to-pr, seed sentinel, gate sécurité), refonte de l'installateur (T1–T8 #324, défauts opt-out), et extension mobile/Apple (tim/illidan/buzz, 5 skills Swift).

Ajouté

  • Pipeline label-to-pr (#325) — module opt-in --with-label-to-pr : une issue GitHub agent-ready déclenche un /loop local → robocop (11) en GitHub Issue Mode → PR draft. Skill + script label-to-pr.sh, 100 % full-local (aucun cloud).
  • Seed .ulk/config.json (#313) — l'installateur sème la config projet en mode remind : le hook sentinel est réellement actif après install (fail-safe no-op hors projets ulk).
  • Module hooks-resync (--with-hooks-resync) — resynchronise .git/hooks/ depuis scripts/hooks/ au SessionStart : le gate full-local est toujours présent et à jour (clone frais, worktree neuf, désync multi-sessions). Catalogue CLI : 53 → 55 modules.
  • Cycle mobile app-builder complet (#327)tim (81), illidan (82), buzz (83) ; roster 78 → 81 agents. happy gagne un mode implement BaaS (Supabase/Firebase).
  • Prompt Library câblée (#317) — intégrée dans bruce (25) et blackemperor (18).
  • Champ outcome faru + checkpoint obiwan Phase Ship (#315) — alignement AIDD.
  • Champ featured (#251) — peuplé dans le contrat ulk agents list.
  • 5 skills Apple spécialisées — bundle swift-skills : 7 → 12 skills (widgets, intents, IAP, CloudKit…) + registry swiftui-performance.
  • Cloudflare — agent deploy modernisé + 10 skills first-party enregistrées.
  • Gate full-local formalisé (_shared/full-local-gate-protocol.md) — govulncheck + npm audit dans les hooks git versionnés.

Modifié

  • Installateur T1–T8 (#324) — catalogue = source unique des flags (T1), module vps absorbé via RemoveGlobs (T2), NoopModule justifiés (T3), profils déclaratifs via base.Profiles (T4), dedup du re-sign ~/.local/bin/ulk (T5), help --profile dérivé de ProfileNames (T7), gardes anti-drift + tests de couverture flags/profils (T8).
  • Accountability + sentinel actifs par défaut (#313)enabledByDefault au premier install, opt-out --without-accountability / --without-sentinel. Comble le Gap #1 (Sécurité) de l'audit AIDD : ownership traçable des mutations IA. Installs existantes intactes.
  • Toggle auto-skill-review — câblé vers l'état runtime auto-dream (state/auto-skill-review.json).
  • Voice FR-first (#301) — contrat CLI + casse marque site francisés ; re-audit minitel : cohérence copy 8/10.
  • LLM local apfel-only — purge du câblage résiduel ollama (bundle ai-clis, status, dashboard).
  • Dé-bloat orchestrateurs — isaac/lovecraft/bruce allégés, bloc partagé _shared/skill-detection-block.md.
  • Épic HERMES-ADAPTATION (#255) clos — 27/27 cartes done, validation déterministe passée, cartes généralisées sans référence personnelle.
  • Backlog Faru — archivage massif (109 + 12 cartes closes), priorités uniformisées (P→mots), casse des préfixes TYPE normalisée, réalignement backlog ↔ issues GH.

Retiré

  • Flag mort --wizard (#324) — déprécié depuis que le wizard est le mode par défaut, consommé nulle part (audit binaire 2026-07-03). --with-faru / --with-update-check conservés (no-ops documentés, API user-facing).

Corrigé

  • feedback-loop (#318) — boucle échec→signal AIDD P11 réparée + golden test verrouillant l'invariant git-only.
  • subagent-handoff (#229) — garde-fou MAIN_REPO worktree-safe.
  • Gate pre-push — rendu worktree/hook-safe.
  • Site — menu mobile cassé sur ≤ 860 px (containing block).
  • vibe (#280) — strip du trailing whitespace des TOML générés + resync des .vibe périmés.
  • sync-issues — préservation de l'URL des issues sans label (read/IFS tab).
  • Agents — conformité frontmatter tools + loads_skills dupliqué ; garde-fou anti-récidive archivage (remap de 118 réfs mortes).
  • Hooks — faux positif commentaire inline hooks-conformance (#231) verrouillé en test ; scrub du SENTINEL_BYPASS hérité dans le test sentinel-hook.

v7.3.0

Ajouté

  • Intégration /checkup natif (CC ≥ 2.1.202) — routine mensuelle de maintenance de l'installation Claude Code. /checkup est l'alias du /doctor revampé (« full setup checkup that can diagnose and fix issues ») : cleanup skills/MCP/plugins inutilisés, dedup CLAUDE.md local vs versionné, éclatement du CLAUDE.md racine, hooks lents, mise à jour CC, auto mode, pré-approbation des commandes read-only refusées — confirme avant chaque changement. Section canonique : .claude/rules/native-features.md § /checkup (cadence, interdiction mid-session Règle 5, table de positionnement vs gandalf 34 / /context-audit / /health / update-check / /claude-md-improver, garde-fou marqueurs ulk:count). Câblage : session-practices + CLAUDE.md (§ Hygiène de contexte), _shared/claude-code-mastery.md § 11, hint gandalf (34) Phase 6, page site hygiene-contexte.
  • Rappel mensuel /checkup dans le hook update-checkframework/tools/hooks/update-check.sh émet une ligne maintenance CC 1×/mois calendaire (clé last_checkup_month dans .claude/state/ulk-update-check.json), propose-only, émise même si le binaire ulk est absent du PATH. Protocole : _shared/update-check-protocol.md § Rappel mensuel.

Modifié

  • README — badge version (resté sur 7.2.0 depuis le cut 7.2.1) + ligne /checkup (2.1.202) dans la table Compatibilité Claude Code 2.1.
  • Installateur — module update-check (catalog.go) : description + pedagogy mentionnent le rappel mensuel /checkup ; idem ligne --with-update-check d'install-reference.md.

v7.2.1

Corrigé

  • scripts/release.sh — fallback gh auth token pour HOMEBREW_TAP_TOKEN (parité avec le fallback GITHUB_TOKEN existant) + export requis par goreleaser (process enfant). Supprime le point de friction du cut v7.2.0 où une entrée Keychain introuvable avait fait échouer les étapes Homebrew tap + upload VPS.

v7.2.0

Ajouté

  • Review & Simplify Gate (_shared/review-gate-protocol.md) — review + simplification rendues systématiques sur le diff (plus opt-in par phase). Profondeur adaptative par taille de tâche : XS/S → 1× feature-dev:code-reviewer · M → /pr-review-toolkit:review-pr · L/XL → Quality Review de /feature-dev (anti-doublon). Trois niveaux d'enforcement : gate dur task-runner Phase 3.1.6 (bloque wip→done sur findings 🔴), backstop 2b3 Phase 4.5, convention base-rules (édition ad-hoc). Filet mécanique opt-in --with-review-gate : hook Stop pur shell (0 token) qui rappelle /code-review + /simplify si un fichier non-doc a changé sans review récente. Catalogue CLI : 52 → 53 modules.

v7.1.0

Trois axes : hardening sécurité CLI (SHA256 fail-closed, CWE-78, 7 Dependabot résolus), site vitrine Arcana (Astro 7, 78 fiches agents), et extension du framework (vinci #80, 16 skills opt-in, pacing protocol, intégration avoid-ai-writing 35 agents).

Ajouté

  • vinci (#80) — agent Claude Design générique : point d'entrée unique pour les workflows design impliquant hallmark, hue, figma, open-design. 6 modes : list, sync, impl, audit, card, dashboard.
  • 16 skills opt-in — dev workflow (6 : oneshot, prompt-creator, merge, skill-manager, environments-manager, agents-managers — absorption croisée inbox Melvynx), Next.js bundle (4 : nextjs-setup-project, nextjs-add-prisma-db, nextjs-setup-better-auth, create-vitejs-app), QA live (playwright-qa). Catalogue CLI : 44 → 52 modules.
  • Site vitrine Arcana (site/) — Astro 7 statique, design system Ulk–Arcana, 9 sphères, 78 fiches agents (/agents/[sphere]/[agent]/), page /install/. Plugin @izo/hyperfocale (routing, pagination). https://ulk.regrets.app.
  • _shared/pacing-protocol.md — protocole pacing (rythme énergétique) : 5 règles (incréments digestes, points d'arrêt reprenables, anti boom-bust, prévisibilité, rythme fixé par l'humain). Signal pacing: low|normal|deep. Hérité par base-rules.md, gardé par gandalf (34) Phase 1.8.
  • Intégration avoid-ai-writing — 6 couches : protocole _shared/prose-protocol.md, section §Prose dans base-rules.md, 35 agents avec règles prose natives, CLI detector, gate 2b3, signal Bruce Phase 5.
  • asc-skills × 22 (rudrankriyam, registry) — suite App Store Connect via CLI asc : signing, build, TestFlight, submission, metadata, ASO, crash triage, notarisation, pricing, IAP RevenueCat, release notes IA.
  • _shared/routines-protocol.md — protocole Cloud Routines (/schedule, agent routine 53).

Modifié

  • _shared/base-rules.md — §Prose (avoid-ai-writing) + §Pacing.
  • framework/agents/CLAUDE.md — table protocols étendue (pacing-protocol.md).
  • .claude/rules/agents-authoring.md — documentation pacing + extends: guidance.
  • gandalf (34) — Phase 1.8 : garde le pacing (signal pacing: → adapter le rythme de sortie).
  • bruce (25), 2b3 (08), task-runner (04) — référence pacing-protocol.md.
  • Biome — migration 2.4.x → 2.5.1 (schema, rules.preset: none, exclusions dist/ + *.d.ts).
  • CLAUDE.md racine — section Pacing + count agents corrigé (78, était 98 sur index.astro).
  • Registryregistry.json + registry.md régénérés (78 agents, date 2026-06-30).

Corrigé

  • Biome hookfiles.includes avec !**/dist/** + !**/*.d.ts + overrides redondant : hook pre-commit stable sur les dist/ compilés.
  • install.sh compte agentsindex.astro affichait 98 agents → corrigé 78.
  • Conflits merge registryregistry.json + registry.md (date 2026-06-28 vs 2026-06-30) résolus.

Sécurité

  • self-update durci (c5341d2a) — SHA256 vérifié fail-closed avant extraction, staging temp imprévisible, guard path-traversal tar. CWE-494/367/377/22.
  • InstallCmdAllowed factorisé (7d1bbd93) — comble le gap CWE-78 sur exec.Command ; whitelist centralisée + confirm/checksum.
  • gstack vendorisé supprimé (ed15e2ae) — 7 alertes Dependabot résolues.
  • npx -y supprimé (048b9794) — CWE-494 (téléchargement sans vérification).
  • yaml CVE-2026-33532 (9d1127de) — override npm ^2.8.3.

v7.0.0

Trois chantiers structurants : support Gemini via Vertex AI ADC, intégration GCP native (skills, MCP Toolbox, Developer Knowledge MCP), et refonte de l'architecture agents (policy de modèles, durabilité, context manifests).

Ajouté

  • ulk export --target vertex — génère VERTEX.md à la racine du projet : auth ADC (gcloud auth application-default login), mapping modèles (gemini-2.5-pro/flash/2.0-flash), guide Workload Identity pour CI/CD. Vertex AI est désormais un target de première classe aux côtés de Codex / Gemini CLI / Mistral Vibe.
  • google-cloud-skills × 20 (google/skills, Apache-2.0) au registry — cherry-pick par slug : google-cloud-basics · google-cloud-run · google-cloud-storage · google-cloud-armor · google-cloud-bigquery · google-cloud-firestore · google-cloud-sql · google-cloud-logging · google-agent-builder · google-cloud-well-architected + 10 autres. Install : ulk skills update ou npx skills add google/skills --skill <slug>.
  • _shared/gcp-protocol.md — protocole GCP ulk : MCP Toolbox for Databases (googleapis/mcp-toolbox, 6 sources : BigQuery/Firestore/AlloyDB/Cloud SQL/Spanner/Looker, ADC-only), Developer Knowledge MCP (anti-hallucination API Google sur Cloud/Firebase/Android/SecOps), cherry-pick skills, cohérence ADC.
  • Developer Knowledge MCP documenté dans multi-provider-protocol.md — ancre les agents sur la documentation Google officielle et à jour.
  • Context Manifests (_shared/context-manifest-protocol.md, ULK-CM1) — frontmatter étendu context_budget + loads_skills + mcp_cap_strategy sur 3 agents pilotes (sargeras 45, ed209 52, tony 50). Bruce calcule la somme avant routing pour prévenir le context rot.

Modifié

  • Protocole modèles (_shared/model-policy.md) — politique formalisée opus/sonnet/haiku : critères de choix, table de routage par agent, règle effort (xhigh sur tous les agents model: opus, low sur model: haiku), durabilité Wulveryck.
  • Durabilité agents — 77 agents classés amplifier / compensatory / mixed (See, Act, Correct, Wulveryck). Roster : 74 amplificateurs / 2 mixed / 1 compensateur. Audit : docs/audits/durability-2026-06-05.md. Rejouable à chaque sortie de modèle.
  • Archivage 2026-06-09 — 21 agents archivés dans framework/agents/_archived/ (traîne morte epic consolidation-maturité). Fusions : picsou (56) = ex-killbill + ex-picsou (26) ; benjamin (64) absorbe rodin (46). Agents persona préservés (alex 59, astride 40, brigitte 24).
  • _shared/local-llm-protocol.md — modèle de référence mis à jour : gemma3:1bqwen3.6:35b-a3b-mlx-bf16 (MoE 35B, 3.5B actifs, 128K ctx, MLX Apple Silicon, ~2-5s/appel).
  • Table des alias modèles (CLAUDE.md + multi-provider-protocol.md) — colonne Gemini → Gemini / Vertex AI ; note ADC explicite.
  • Hints GCP dans 3 agents pivots :
    • tony (50) §3.4 : note Vertex/Cloud Run/skills GCP
    • ed209 (52) : section GCP dans Points de vigilance (Cloud Armor WAF, IAM principe du moindre privilège, Secret Manager, audit logs)
    • picsou (56) §A.4 : GCS + table GCP enterprise (BigQuery, Firestore, Cloud SQL, Cloud Run, pricing indicatif)
  • gcloud CLI documenté dans install-reference.md comme opt-in (Vertex AI ADC uniquement).
  • install-reference.md — section google-cloud-skills × 20 dans les Skills externes (cherry-pick, ADC, protocole).
  • ulk export — commande étendue : codex|gemini|mistral|vertex|all (était codex|gemini|mistral|all).
  • Registryregistry.json + registry.md régénérés (77 agents, durability annotations).

Corrigé

  • Alignement CLAUDE.md racine avec la table Multi-LLM (Vertex AI ADC, VERTEX.md).

v6.3.0

Import des garanties d'exécution de Superpowers (epic W1–W8) + refonte du Panthéon + portail de releases auto-hébergé.

Ajouté

  • Epic Superpowers W1–W8 — garanties d'exécution importées (8 cartes, 3 PRs) — forcing-functions de obra/superpowers (MIT) câblées dans l'architecture _shared/ ulk sans renier l'invocation manuelle :
    • W1 — Protocole TDD (_shared/tdd-protocol.md) : loi RED-GREEN-REFACTOR, aucun code de production sans un test qui échoue d'abord, format TDD Evidence (commande + sortie rouge → verte). Résout ULK-049. Câblé task-runner (04) Phase 2.2.
    • W2 — Verification Gate (_shared/base-rules.md) : aucun claim sans preuve fraîche (IDENTIFY→RUN→READ→VERIFY→CLAIM) + table de Red Flags. Câblé 2b3 (08) Phase 4.5.
    • W3 — Review anti-auto-notation (_shared/verify-protocol.md) : « ne pas faire confiance au rapport » ; le rationale invoqué ne dégrade jamais la sévérité ; calibration Superpowers ↔ ulk.
    • W4 — HARD-GATE spec→code (opt-in) : gate: spec-required dans le frontmatter CLAUDE.md ou ULK_SPEC_GATE=1 → task-runner (04) / bruce (25) refusent le build sans carte type: spec approuvée. Défaut OFF (flux rapide intact).
    • W5 — Handoff sous-agents par fichiers (_shared/subagent-handoff-protocol.md + 3 scripts) : workspace .ulk/handoff/ auto-ignoré (jamais sous .git/), brief/diff/rapport par fichiers, ~3–5K → ~150–300 tokens sur un diff de 400 lignes. Scripts écrits en TDD (dogfooding de W1 : 🔴 3 failed → 🟢 3 passed).
    • W6 — Modèle obligatoire au dispatch (_shared/model-policy.md) : model: requis sur tout dispatch de sous-agent, table de routage haiku/sonnet/opus.
    • W7 — Evals comportementaux (framework/tests/agents-behavioral/) : mini-runner node:test (arbitrage vs drill/tmux documenté), 3 scénarios de pression adversariaux (2b3, task-runner, verify), mode structure 0-token en CI + mode live gated ULK_BEHAVIORAL_LIVE=1, rejoués au kata durability.
    • W8 — Hook bootstrap agents (opt-in, --with-agent-bootstrap) : mini-carte des pivots + règle « vérifie un agent pertinent avant de répondre » + Red Flags en SessionStart, pur shell (0 token), no-op hors repo git. ⚠️ altère le préfixe de cache → strictement opt-in, off par défaut.
    • Patterns de persuasion (Meincke et al. 2025, N=28 000 — Authority / Commitment / Red-Flags) intégrés dans agents-authoring.md pour que les gates résistent à la dérive. CLAUDE.md non modifié (budget < 2 500 tok préservé — tout le câblage vit dans _shared/).
  • Portail de releases auto-hébergé (releases.regrets.app) — page d'index GoReleaser, design ulk-zed-orange (light-first, radius 0, Geist Sans/Mono), liens binaires macOS/Linux corrigés (underscore → dash), déployé sur VPS Coolify.
  • Skill shadcn/improve (registry) — advisor codebase read-only, audit 9 catégories, priorisation par leverage (impact ÷ effort), plans de handoff auto-suffisants dans plans/. Complémentaire à sargeras (45) / ed209 (52) / tech-debt-audit / verify (65).

Modifié

  • Migration Biome v1.9.4 → v2.4.16organizeImportsassist.actions.source, files.ignorefiles.includes, nouvelle règle useIterableCallbackReturn (4 forEachfor...of dans todo-parser.test.ts).
  • Refonte du Panthéon (site) — 77 agents avec sphère + épithète complets, navigation /agents/pantheon, filtres avancés (recherche / modèle / durabilité), 254 pages WCAG AA vérifiées (shot-scraper accessibility).
  • Registry régénéré (registry.{json,md}) après le renommage khadgar ; exports .gemini / .vibe resynchronisés.

Retiré

  • Carte usage-integration annulée/usage natif jamais sorti en GA, blocage indéfini.

v6.2.0

Modifié

  • Renommage frontend-qakhadgar (frontend/02, 2026-06-16) — l'auditeur frontend gagne un nom de persona (Khadgar, l'archiviste-mage de la Kirin Tor ; sphère juges, épithète « inquisiteur des interfaces vivantes » conservés). Renommage transverse propagé : fichier agent + golden, registry.{json,md}, commands/, managed-agents/, exports .gemini/.vibe, AGENTS.md, registres tools/{cli,skills}-registry.json, credits, site (agent-icons.ts). Compte d'agents inchangé (77). Les occurrences frontend-qa restantes sont volontaires (archives datées, skills tierces homonymes). Nettoyage de 2 orphelins managed-agents d'agents archivés.

Ajouté

  • Khadgar — mode walkthrough (recette QA filmée) (2026-06-16) — 4ᵉ mode de l'agent khadgar (ex-frontend-qa, frontend/02) : test joué en live et filmé via mb record, navigation démonstrative (mb move = mousemove, highlight outline, marqueur de chapitre 3 s), audits console/liens/images/responsive, puis rapport HTML auto-suffisant (screenshots base64) partageable à un non-tech. Portage iso 1:1 de la recette QA de Shubham Sharma (playwright-climb, Playwright interdit par la règle ulk). Table de correspondance commande-par-commande dans l'agent. Outputs : docs/audits/walkthrough-<name>-YYYYMMDD.{html,webm}.
  • .goreleaser.yaml — releases Homebrew automatisées (-X .../cmd.version={{.Version}} injecté au build → la version = le tag git).
  • Vague v7 (backlog) — cartes multi-llm v2, gcp/vertex, agents-v2 + note GCC.

v6.1.0

Retiré

  • Archivage du roster 93 → 77 agents (2026-06-09, epic consolidation-maturité v7) — 21 agents déplacés dans framework/agents/_archived/ (traîne morte). Fusions : picsou (56) = ex-killbill + ex-picsou (26) ; benjamin (64) absorbe ex-rodin (46). Rapports : docs/audits/archivage-roster-2026-06-09.md + archivage-justifications-2026-06-09.md.

Corrigé

  • Propagation de l'archivage (remédiation audit sargeras 2026-06-09) — le compte d'agents et le routage avaient dérivé du registre (seul registry.json/registry.md était à jour) :
    • Comptes d'agents alignés sur registry.json (77) : CLAUDE.md, framework/agents/CLAUDE.md, README.md, AGENTS.md, GEMINI.md, site (BaseLayout, docs, pantheon, ia), model-policy.md, credits-manual.json, portail releases.
    • Garde-fou : ulk agents stats réconcilie désormais 6 cibles (ajout GEMINI.md + README.md) ; nouveau test Go TestReconcileTargetsMatchRegistry échoue en cas de drift.
    • Routage _shared/*.md purgé des 16 agents archivés (remap killbill/cutkiller→picsou, rodin→benjamin, obsidian-vault→lovecraft, friday→shuri) ; chaîne de délégation vault réparée.
    • Config site purgée : sphere-mapping.ts (21 mappings morts + 2 remaps) et agent-icons.ts (18 icônes mortes).
  • Gate de test rétabli (scripts/hooks/pre-push) — remplace le test.yml supprimé le 2026-06-04 : go test + node --test (generators, golden, core, status-board) avant chaque push.
  • 4 tests rouges réparés : cheatheet.test.mjs (génère les .agent.yaml gitignorés avant assert), status-board/exporter.test.js (fixtures déterministes au lieu du repo live), script test de @ulk/status-board (glob cwd-robuste).

Modifié

  • Audit Fable 5 du roster — clos (2026-06-10) — étapes 3 et 5 tranchées par analyse : effort: xhigh frontmatter conservé (la règle Fable 5 « high défaut » vise l'effort de session ; les agents opus restent sur Opus 4.8) · thor/loki restent opus (bascule fable = condition de réouverture : bench mesuré ou prix ÷ 2). Carte 2026-06-10-task-fable-5-agent-audit → done.

  • Audit Fable 5 du roster — passe exécutée (2026-06-10) — durabilité run #3 (docs/audits/durability-2026-06-10.md : 0 SUNSET-NOW, file WATCH réduite à godspeed+xavier par l'archivage, gandalf seul SUNSET-CANDIDATE) · allègement : verdict « défaut OK » (marqueurs = labels de sévérité, pas d'instructions) · scan reasoning_extraction : 0 occurrence non-vendorée · règles runs longs câblées dans thor (74), loki (75) et managed-agents-protocol.md § 3bis · invariant « une leçon = un fichier vault » dans memory-protocol.md. Restent ouverts : benchs effort xhigh et thor/loki fable (carte en wip).

  • Adaptation prompts Fable 5 (2026-06-10) — règles canoniques dans model-policy.md § Adaptation des prompts à Fable 5 : alléger avant de réinstruire · effort comme réglage principal · piège reasoning_extraction (« explique ton raisonnement » → refus + fallback Opus 4.8 ; scan : 1 occurrence vendorée Figma, flaguée) · règles runs longs (claim-audit contre résultats d'outils, rappel autonomie, timeouts longs) · leçons mémoire 1 fichier/run. Nouveau bloc base-rules.md § Frontières — diagnostic ≠ action (hérité par tous les agents ; anti-suringénierie et brevity y existaient déjà). Chantier roster : docs/backlog/archive/2026-06-10-task-fable-5-agent-audit/CARD.md (fusionné avec kata durabilité run #3).

  • Intégration Claude Fable 5 (sortie 2026-06-09) — Fable 5 (claude-fable-5, classe Mythos) est un nouveau tier au-dessus d'Opus ($10/$50 par MTok, 2× Opus 4.8 ; contexte 1M ; surface API identique à Opus 4.8 sauf thinking: {type: "disabled"} explicite → 400). L'alias opus continue de résoudre vers claude-opus-4-8aucun agent ne bascule. Politique : fable est session-only (/model fable), pas d'attribution frontmatter sans mesure coût/gain ; candidats à évaluer au kata durabilité run #3 (thor 74, loki 75). Mythos 5 (safeguards levés, Project Glasswing) : pas d'accès API public, hors périmètre. Mises à jour :

    • _shared/model-policy.md — alias fable, critères « model: fable — quand ? », trigger kata run #3.
    • CLAUDE.md, GEMINI.md, _shared/multi-provider-protocol.md — ligne fable dans les tables de mapping (fallback top tier chez Codex/Gemini/Mistral).
    • agents-authoring.md, framework/agents/CLAUDE.md — règle de gouvernance frontmatter.
  • Alignement Claude Opus 4.8 (sortie 2026-05-28, Claude Code 2.1.154) — les alias relatifs opus/sonnet/haiku résolvent automatiquement vers 4.8, aucune modification d'agent requise. Mises à jour documentaires :

    • _shared/model-policy.md, agents-authoring.md — le défaut effort Opus passe de xhigh (4.7) à high (4.8) ; ulk conserve effort: xhigh sur tous les agents opus, désormais comme surcharge délibérée au-dessus du défaut (et non plus alignement sur le défaut).
    • CLAUDE.md, GEMINI.md, _shared/multi-provider-protocol.md, README.md — table de mapping modèles → claude-opus-4-8 ; ajout note fast mode (2× rate / 2,5× vitesse, 3× moins cher que sur modèles précédents).
    • _shared/context-hygiene-protocol.md (Règle 5) — nuance : la Messages API accepte des entrées system mid-task → injection de contexte par les orchestrateurs cache-safe (changer modèle/MCP reste un cache miss).
    • _shared/verify-protocol.md — note honnêteté Opus 4.8 (~4× moins de défauts laissés passer) ; le filet /ulk:verify reste obligatoire.
    • docs/site-docs/{token-economy,reference}.md, session-defaults skill + install-reference.md — défaut effort + mentions 1M context rendues version-agnostiques (4.7/4.8).
  • Dynamic Workflows (native-features.md) — documentation de la feature native research-preview (orchestration de dizaines–centaines de sous-agents, Enterprise/Team/Max) et de son positionnement vs bruce (25) / blackemperor (18). À surveiller, pas d'intégration tant que gated par plan + preview. /simplify mis à jour (cleanup-only + applique les fixes depuis 2.1.154).

Ajouté

  • Durabilité des agents — amplificateur vs compensateur (cadre See, Act, Correct, O. Wulveryck, 2026-06-04) — nouvel axe de classification du roster qui répond à « cet agent sera-t-il plus ou moins utile quand le modèle sera 2× plus intelligent ? ».
    • _shared/model-policy.md § Durabilité — rubrique : amplificateur (exploite une capacité que le modèle fait mieux en progressant → KEEP), compensateur (contourne une limite actuelle — budget tokens, oubli, introspection runtime → dette transitoire, sunset_when obligatoire), mixed (cœur durable + coque compensatoire).
    • Frontmatter agents — champs durability: / sunset_when: appliqués à l'ensemble du roster ; tout compensatory DOIT déclarer une condition d'invalidation.
    • docs/audits/durability-2026-06-05.md — premier audit (baseline) : 90 amplificateurs / 4 mixed / 4 compensateurs (92 % durables). 2 candidats au sunset (gandalf 34, code-graph 63), invalidés par le même basculement : contexte large + bon marché avec introspection runtime native.
    • Câblage : revue semestrielle + rejouer l'audit à chaque sortie de modèle (kata 2026-06-05-kata-agent-durability-audit) — une sortie de modèle est l'événement d'invalidation réel de la dette compensatoire.
    • Hygiène pré-release : dédup des clés durability, dégraissage de la coque compensatoire des 8 agents de dette, regen registry + golden.
  • Mécanisme anti-données-hardcodées (3 couches + agent) — détecte secrets/tokens, config env-spécifique (URLs/IPs), magic numbers et PII/fake data.
    • scripts/hooks/hardcode-check.sh — hook pre-commit strict (POSIX, 0 dépendance), bypass ligne via # nocheck / # hardcode-ok. Câblé dans scripts/hooks/pre-commit (dispatcher Biome → hardcode).
    • framework/community-skills/hardcode-audit/ — skill /hardcode-audit (scan), :fix (migration .env + constantes nommées), :install (hook).
    • framework/agents/audit/72-hardcode.md — agent d'audit dédié (#72), rapport docs/audits/hardcode-<date>.md, mode --fix AI-powered.
    • 2b3 (08) Phase 4.6.4 — scan config env + PII sur le diff de session (réutilise le hook si présent).

v6.0.2

Ajouté

  • LLM local (apfel + ollama) — pattern sonde+guard intégré à 6 orchestrateurs (sargeras, ed209, robocop, blackemperor…) pour les micro-tâches gratuites (classification TODO, breakdown) ; flag caveman:true sur les agents concernés. Protocole : _shared/local-llm-protocol.md.
  • CREDITS.md auto-généré (generate-credits.cjs) + page /credits du site data-driven (site/src/data/credits.json).

Corrigé

  • ulk self-update --check — normalisation du préfixe v dans la comparaison de versions.

Retiré

  • vllm-mlx — serveur d'inférence locale expérimental opt-in retiré.

v6.0.1

Corrigé

  • C1 — Troncature UTF-8 rune-safe (framework/cli/cmd/export.go) — buildAgentsMD tronquait les descriptions/invocations au byte, produisant U+FFFD sur les chaînes accentuées (ex: frodo — « audit générationnel »). Remplacé par []rune(s)[:n] sur les deux troncatures (descriptions > 90 chars, invocations > 40 chars). Ajout de 3 tests unitaires vérifiant utf8.ValidString sur des strings accentuées.
  • C2 — Idempotence ulk export (framework/cli/cmd/export.go) — ulk export --target codex|gemini écrasait AGENTS.md / GEMINI.md maintenus manuellement (contenu enrichi perdu). Option B retenue : exportCodex et exportGemini skippent désormais ces fichiers et affichent un message informatif. Périmètre export = sous-agents .gemini/agents/ et .vibe/agents/ uniquement. Invariant d'idempotence (Principe 7 de multi-provider-protocol.md) restauré.

Ajouté

  • W1 — .vibe/agents/verify.toml — agent verify portés côté Mistral Vibe (modèle mistral-small-3-1), portant la matrice 3 dimensions (completeness × correctness × coherence) depuis .gemini/agents/verify.md. Parité Gemini 6 ↔ Mistral 6 agents atteinte.

v6.0.0

Ajouté

  • Multi-LLM support — ulk est désormais portable vers trois CLI IA alternatives via ulk export :
    • AGENTS.md — contexte ulk pour OpenAI Codex CLI + Mistral Vibe (93 agents groupés par catégorie, 17 KB, dans la limite 32 KiB Codex)
    • GEMINI.md — contexte pour Google Gemini CLI avec 6 sub-agents dans .gemini/agents/ (bruce · godspeed · sargeras · 2b3 · task-runner · verify)
    • .vibe/agents/ — 5 configurations TOML pour Mistral Vibe (bruce · godspeed · sargeras · 2b3 · task-runner) avec mapping modèle mistral-medium-3-5 / mistral-small-3-1 / mistral-nemo (verify ajouté en v6.0.1)
    • ulk export --target codex|gemini|mistral|all — commande CLI Go qui régénère les fichiers de contexte depuis registry.json ; options --output <dir> et --dry-run
    • framework/agents/_shared/multi-provider-protocol.md — protocole canonique multi-provider : mapping outils (Read→read_file, Task→remote agents…), mapping modèles, limitations par plateforme, format sub-agent Gemini, format TOML Mistral

Ajouté

  • /ulk:verify (agent 65) — spec ↔ code conformance, matrice 3 dimensions (completeness × correctness × coherence) × 3 sévérités (CRITICAL/WARNING/SUGGESTION) ; pipeline 6 étapes ; graceful degradation selon sections présentes dans la carte ; rapport docs/audits/verify-<slug>-<date>.md ; exit codes 0 (clean) / 1 (CRITICAL — bloque archive) / 2 (carte introuvable). Mode faru (carte unique) + mode obsidian legacy supportés. Inspiré du workflow /opsx:verify d'OpenSpec (Fission-AI, MIT).
  • _shared/verify-protocol.md — protocole canonique : matrice, sévérités, gradient de vérification (tasks seul → +requirements → +design), heuristiques anti-faux-positifs, anti-patterns interdits, câblage agents.
  • 2b3 (08) Phase 4.7 — Verify Matrix — non-bloquant ; détecte les cartes Faru touchées dans la session, run /ulk:verify sur chacune, agrège les findings ; rapport docs/audits/verify-*.md.
  • Bruce (25) Phase 5.0 — Verify pre-audit — bloque les audits coûteux (sargeras/ed209/perf) si CRITICAL trouvé sur les cartes complétées de la session ; bypass possible avec trailer ⚠️ verify-bypassed:<slugs> en Phase 7.
  • Task-runner (04) Phase 3.1.5 — Pre-done verify gate — bloque transition wip → done si CRITICAL ; override possible avec trailer verify-overridden:<slug> + motif requis.
  • base-rules.md § Sélection ambiguëAskUserQuestion obligatoire quand ≥ 2 candidats et le contexte ne tranche pas (carte, branche, environnement…). Interdit aux agents l'auto-sélection silencieuse (« le plus récent », « le premier »…). Inspiré d'OpenSpec.
  • base-rules.md § Dégradation gracieuse — continuer avec les artefacts présents, noter explicitement les checks sautés, ne jamais planter sur champ manquant (sauf minimum vital absent). Règle de tendance : en cas de doute, SUGGESTION > WARNING > CRITICAL.
  • generate-commands.cjs adapter pattern — refactor en pattern adapter pour permettre l'émission vers d'autres outils que Claude Code (Cursor, Codex, Windsurf…) sans toucher au générateur central. Architecture : lib/parse-agent.cjs (parser .md → CommandContent tool-agnostique) + adapters/<tool>.cjs (implémentent toolId, getOutputRoot(), getFilePath(), formatFile()). Adapter claude.cjs (default, passthrough verbatim — comportement historique préservé) + adapter cursor.cjs (proof-of-concept, output gitignored). Usage : node framework/cheatheet/generate-commands.cjs --target=claude,cursor. Inspiré de src/core/command-generation/ d'OpenSpec.

Modifié

  • Total agents : 87 → 88 (Verify ajouté en framework/agents/session/65-verify.md).
  • Prochain numéro d'agent : 65 → 66 (CLAUDE.md + .claude/rules/agents-authoring.md).
  • base-rules.md : 8 → 10 règles absolues (ajout Ne jamais auto-sélectionner sur ambiguïté + Graceful degradation).

v5.2.0

Ajouté

  • Faru promu mode documentaire par défaut — une spec = un dossier = un CARD.md dans docs/backlog/ ; faru.config.json ajouté ; migration docs/07-spec/ + docs/todo.md → cartes faru
  • TUI Mole-styleulk bare ouvre un menu interactif (launcher) ; panels Bubble Tea viewport pour toutes les commandes display ; sortie styled Catppuccin Mocha sur toutes les sous-commandes
  • Skill /session-defaults (--with-session-defaults) — écrit CLAUDE_CODE_DISABLE_1M_CONTEXT=1 + CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=80 dans ~/.claude/settings.json ; désactive contexte 1M Opus 4.7, force compact à 80%
  • Token economy — règle 5 session lock (invalide cache prefix) + règle PDF (pdftotext > Read) + règle Task Delegation (Haiku/Sonnet/Opus selon complexité sous-tâche) ; /effort per-prompt sur framework/agents/_shared/
  • Caveman auto-activation sur 4 agents : godspeed (00), 2b3 (08), gandalf (34), ci-guard (54) — mode output télégraphique activé par frontmatter caveman: true
  • ulk install didactique — couche pédagogique sur 4 surfaces (splash, progress, résultats, wizarddrilldown) ; distinction outils déjà présents / n/a OS / échec avec recette
  • Skills externalisées — remplacement des skills bundlées par des sources externes vérifiées (framework/skills-sources.json) ; skills rogertinch UX & game-design + wire 6 agents (ux-movement-design, laws-of-ux-design, lang-game-design)
  • accountability-report.sh --read-coverage — rapport frère de l'audit trail (ratio doc loadable / doc effectivement lue)

Corrigé

  • ulk self-update : extraction du binaire depuis l'archive .tar.gz avant installation (bug fonctionnel depuis 5.0.0 — binaire corrompu) ; warning explicite quand checksums.txt absent d'une release (CWE-345, auparavant skip silencieux)
  • TUI : doctor RunPanel + skills list routing (73323b7) ; chemin absolu via os.Executable() dans le launcher (074d897)
  • Install : persistance du répertoire source dans ~/.ulk/source-path après install (f9bcfee) ; re-signature binaire ulk après build sur macOS Sequoia+ (779d565)
  • Caveman SKILL.md : réécrit comme instructions directes — activation immédiate sans lecture préambule
  • Installer : robustification des recettes d'install CLI pour 6 outils ; erreurs d'outils non-fatales (pip échoue → warning + continue)
  • CLI : affichage version binaire dans le splash (pas la version sauvegardée)

Modifié

  • docs/ : suppression des préfixes numériques des dossiers ; réorganisation en docs/guides/, docs/research/, docs/audits/, docs/backlog/, docs/_archive/
  • framework/agents/audit/62-frodo.md : ajout context_budget: 20000

Sécurité

  • selfupdate.go : warning os.Stderr explicite quand checksums.txt absent → SHA256 skip visible (CWE-345, HIGH-3 ED-209 v5.2.0) ; extractBinary() ajouté — goreleaser tar.gz extrait avant écriture
  • Skills sources : HIGH-1 (pin SHA/commit sur npx skills add) + HIGH-2 (SHA256 tarball obscura/curl.md) documentés comme known issues → hotfix v5.2.1 sous 14j
  • PII dans read-coverage.jsonl : chemins .ssh/.aws/.env sans denylist → MEDIUM-1, hotfix v5.2.1

v5.0.0

Ruptures

  • WebFetch supprimé des tools: de tous les agents — les 7 agents qui utilisaient WebFetch dans leur frontmatter ont migré vers curl.md <url> dans le corps. Agents tiers qui référencent ces agents par leur tools: doivent mettre à jour leurs attentes.
  • mb (mini-browser) requis par défaut./install.sh nu installe désormais mb (npm install -g @runablehq/mini-browser) ; ajouter --without-mb si non souhaité. Bootstrap Chrome requis une fois par machine : mb-start-chrome.
  • curl.md requis par défaut./install.sh installe curl.md ; premier réflexe pour toute consultation URL dans les agents (remplace WebFetch et defuddle parse <url>).

Ajouté

  • ulk clean — commande CLI pour supprimer les fichiers orphelins (agents/skills/commands renommés ou supprimés) ; --dry-run pour prévisualiser sans supprimer ; --source <dir> pour override
  • Context Manifest — frontmatter étendu context_budget, loads_skills, loads_mcps, loads_files, mcp_cap_strategy sur 7 agents orchestrateurs (bruce, sargeras, task-runner, blackemperor, godspeed, frodo, lovecraft)
  • Biome configuré sur framework/packages/ + framework/cheatheet/ + framework/tools/
  • Validation frontmatter CI — step dédié dans test-agents.yml vérifie tous les agents numérotés ; invocation: présent sur 100% des 87 agents

Modifié

  • curl.md promu required + activé par défaut (était opt-in) ; defuddle rétrogradé à fallback
  • mb / mini-browser promu required + activé par défaut ; règle de routage : interactif → mb, one-shot visuel/PDF → shot-scraper, scraping parallèle → Obscura, texte URL → curl.md
  • Tous les agents : corps WebFetch → curl.md migré (P0→P3, 25+ agents mis à jour)
  • Bruce (25) : Banner Mode + Triple Questioning extraits vers _shared/banner-mode-protocol.md + _shared/triple-questioning.md (−228L)
  • invocation: ajouté ou normalisé sur tous les agents sans exception (100% conformité)

Corrigé

  • CI P0 : install_helpers_test.go::registeredCmd() ne déclarait pas --with-mini-browserTestParseInstallFlagsDefaults + TestParseInstallFlagsBoolsPropagate en échec depuis PR #165
  • framework/agents/audit/26-picsou.md:565,621 — références stale WebSearch dans le corps après suppression du tools: (commit 41d76e6)
  • ExternalModule.Install() : erreurs d'outils non fatales — pip échoue → warning + continue (plus de blocage install)
  • Sentinel : SENTINEL_BYPASS=1 en préfixe inline ignoré ; faux positifs hors projets ulk

Sécurité

  • Audit OWASP ED-209 : 8.0/10 — 0 finding CRITIQUE, 0 path traversal, 0 injection shell
  • ulk clean : pas de path traversal (allowlist isUlkSkill + os.ReadDir mono-segment)
  • Connu (selfupdate.go:104) : remplacement binaire écrit le .tar.gz brut au lieu du binaire extrait — SHA256 vérifié donc non-exploitable, mais ulk update fonctionnellement cassé → correctif prévu en 5.0.1
  • Connu : catalog.go:152,183 — npm @latest sans pin pour caveman-shrink + mini-browser → recommandation : pin vers une version mineure stable

v4.3.0

Ajouté

  • Agents #61–64 : Obiwan (61, senior product strategist), Frodo (62, audit générationnel 5 cohortes), Jean-Claude (63, agent support virtuel GitHub/Linear), Benjamin (64, devil's advocate & DD lens)
  • Application macOS native (apps/macos/Ulk/) — SwiftUI + Swift Package Manager ; CI workflows macos-app.yml + macos-release.yml
  • install.sh → wrapper Go (install.sh délègue à ulk install ; binaire compilé à la demande ; 75 → 110+ tests Go)
  • Managed Agents (framework/managed-agents/) — sessions cloud sans machine locale ; 102 .agent.yaml générés ; agents portés : ed209, sargeras, 2b3, ci-guard, lovecraft ; ulk ma <agent> "<prompt>"
  • Auto Dream (framework/tools/hooks/auto-dream.sh) — consolidation mémoire REM-style (merge doublons, normalise horodatages, archive obsolètes, reconstruit MOC) ; hook SessionStart ; sandbox scoped-write
  • curl.md — adopté en base (required) comme premier réflexe URL→Markdown ; --with-curl-md activé par défaut
  • mb / mini-browser — adopté en base (required) comme CLI navigateur primaire pour agents ; --with-mini-browser activé par défaut ; mb go/text/shot/snap/fill/click/record/audit
  • Obscura (--with-obscura) — headless browser Rust ; scraping JS, multi-URL parallèle, serveur CDP ; 85 ms page load vs ~500 ms Chrome
  • Shot-scraper — activé par défaut (enabledByDefault: true) ; remplace mcp__chrome-devtools__*
  • caveman-shrink MCP proxy (--with-caveman-shrink) — compresse descriptions MCP tools/list ; −60% cache write (~$10–25/mois)
  • skill /tech-debt-audit (--with-tech-debt-skill) — audit dette technique file:line, 9 dimensions, TECH_DEBT_AUDIT.md
  • Skill SKILL.md agentskills.io spec — toutes les skills conformes à la spécification agentskills.io
  • Context Mode (--with-context-mode) — hook PostToolUse SQLite ; stocke outputs > 2K tokens ; économie −$8 à −$24/mois
  • Accountability (--with-accountability) — audit trail mutations (Edit/Write/Bash) → .ulk-reports/accountability.jsonl
  • Sentinel (--with-sentinel) — cascade xavier+ed209 pre-push, killbill+ed209 pre-deploy
  • Bruce Banner Mode (ULK-258) — triple questionnement pourquoi/risques/impact, vérification livrables 4 critères, activation sur signaux critiques

Modifié

  • install.sh : de 6 lignes (wrapper Bash pur) à 15 lignes (compilation Go conditionnelle + dispatch commandes)
  • Agent count : 80 → 87 agents enregistrés
  • framework/cli/ : factorisation 2.5K Bash → 43 modules Go typés ; install.sh 1122 → 7 lignes puis 15 lignes après ajout dispatch
  • CI : matrix Go multiplateforme renforcée ; couverture ≥ 90% ; diagnostic verbose ; runner macos-15 (Xcode 16)
  • Faru : mode coexist auto-détecté si docs/backlog/ existe ; config consolidée .faru

Corrigé

  • CI rouge depuis PR#165 : with-mini-browser absent de registeredCmd() mock → TestParseInstallFlagsDefaults + TestParseInstallFlagsBoolsPropagate
  • ExternalModule.Install() erreurs outil non fatales — pip échoue → warning + ToolOutcome{Status:"failed"}, install continue
  • Sentinel : SENTINEL_BYPASS=1 ignoré en préfixe inline ; faux positifs hors projets ulk
  • Faru : compatibilité agents — spec alignment + agents wiring

v4.2.0

Ajouté

  • CLI Go natif (framework/cli/) — binaire ulk multiplateforme (darwin/linux × arm64/amd64) :
    • Commandes : install, update, uninstall, status, verify, check
    • TUI bubbletea : wizard sélecteur de modules + barre de progression
    • Distribution goreleaser + homebrew tap (brew install izo/tap/ulk)
    • 75 tests unitaires Go ≥ 90% coverage
  • Epic Maturité & Stabilité Phase 4 (ULK-181→188) :
    • Framework golden files agents (framework/tests/agents/ — 21+ agents testés, CI test-agents.yml)
    • Hook PreToolUse token estimator + skill killbill api-budget + alerte coût pré-audit Bruce
    • Mode First Run Bruce (5 agents restreints, bruce unlock) + commandes verbes métier (audit code, audit security, budget)
  • Portabilité & Communauté (ULK-189→193) :
    • Guide portabilité Cursor/Aider/Codex (docs/guides/portability.md)
    • CONTRIBUTING.md reécrit + template issue "agent en 5 min"
    • Flag --audit-only dans install.sh.ulk-reports/audit-<ts>.json
    • CI matrix multiplateforme ubuntu-latest + macos-latest (Go)
    • Schémas JSON structurés : report-sargeras.json + report-ed209.json
  • Skills community (ULK-194→195) :
    • logo-generator (op7418, MIT) — SVG+PNG via Gemini API — opt-in --with-logo-generator-skill
    • architecture-diagram (Cocoon-AI, MIT) — HTML+SVG self-contained, $0 — bundlé par défaut
  • Agents #52–60 : ED-209 (audit sécu OWASP), Routine (cloud routines), CI Guard (auto-fix CI), Context Audit, Killbill (cost killer), Xavier (context vérificateur), Stark (designer en chef), Alex (musitech), Agathe (DA)
  • Site Astro — pages /skills, /cli, /ia (apfel/vision/ollama) ; page /agents restructurée (majeurs ↑, VPS ↓)
  • Chaîne CMS migration : Tony (Phase 1bis) → Ranma → Stark — analyse SPIP/WordPress/Kirby/Drupal automatique

Modifié

  • docs/spec.md v4.1.0 → v4.2.0 : 10 drifts corrigés (82 agents, structure framework/**, 11 subagents, 36 _shared, 13 schemas, 50 CLIs, §5.6 CLI Go, agents #52-60)
  • CLAUDE.md : 11 subagents (ajout tony/xavier/andreide/tools-checker) ; URL site → ulk.regrets.app
  • install.sh : --audit-only flag ; wrapper mince vers ulk install si binaire Go disponible

v4.1.0

Ajouté

  • Figma Skills (7) — Skills officiels Figma pour MCP, vendorisés depuis github.com/figma/mcp-server-guide :
    • figma-use — skill général Figma MCP (lecture, écriture, inspection)
    • figma-implement-design — implémenter un design Figma en code production
    • figma-generate-library — générer une design library complète (variables, composants, doc)
    • figma-create-design-system-rules — extraire les règles d'un design system existant
    • figma-create-new-file — créer un nouveau fichier Figma depuis Claude Code
    • figma-generate-design — générer des écrans Figma depuis une description
    • figma-code-connect — connecter des composants Figma au code source
  • community-skills/figma/ — 45 fichiers vendorisés (7 SKILL.md + 11 références + 9 wwds + 9 scripts JS + 9 autres)
  • agents/_shared/figma-protocol.md — référence partagée : 15+ outils MCP, config, skills, workflow
  • install.sh --with-figma-mcp — configure automatiquement le MCP server Figma (https://mcp.figma.com/mcp)
  • Agent brique (frontend/01) — intègre le workflow figma-implement-design + design system rules
  • Agent agamotto (17) — étend figma-protocol
  • Plugins officiels Anthropic (v4.1.0 release) — délégation vers feature-dev, code-simplifier, commit-commands, pr-review-toolkit, frontend-design, claude-md-management, claude-code-setup

Modifié

  • install.sh — Figma skills (7) installés par défaut au même titre que Swift (7) et Flutter (2)
  • CLAUDE.md, README.md, site/ — documentation mise à jour

v4.0.1

Corrigé

  • generate-commands.cjs — l'alias de commande dérive désormais du champ name: du frontmatter (source de vérité) plutôt que du nom de fichier. Fallback sur stripNumber(filename) si absent — aucune régression.
  • 47-obsidian-doc.md47-lovecraft.md — nom de fichier aligné sur name: lovecraft du frontmatter ; /ulk:lovecraft fonctionne désormais correctement.
  • site/index.htmlagentFileMap mis à jour avec le nouveau chemin 47-lovecraft.md.
  • Version schizophrèneinstall.sh lit désormais la version depuis package.json (source de vérité unique) au lieu du VERSION="4.0.0" hardcodé. package.json aligné sur 4.0.1.
  • install.sh symlink crashcp échouait avec code 1 sur les subagents symlinked (macOS "identical file" error) + set -e tuait le script avant l'écriture de .version. Fix : rm -f avant cp.

v4.0.0

Ruptures

  • install.sh interface redesigned — Le script install.sh est réécrit en Bash pur. Les arguments et comportements changent :
    • --check-tools → remplacé par --check (l'ancien flag n'existe plus)
    • --with-community-skills → remplacé par --with-addy-skills (plus précis)
    • --with-obsidian-skills — nouveau flag, non présent en v3.x
  • Agent 47 renommé : obsidian-doclovecraft — l'invocation /ulk:obsidian-doc ne fonctionne plus
  • Commande uninstall.sh — reste fonctionnelle mais est désormais un wrapper ; utiliser ./install.sh --uninstall

Migration depuis v3.x

# Mettre à jour l'installation
git pull
./install.sh

# Si vous utilisiez --check-tools
./install.sh --check      # remplace --check-tools

# Si vous utilisiez /ulk:obsidian-doc
# Utiliser désormais :
/ulk:lovecraft

Ajouté

  • install.sh v5 — Pure Bash — Installateur unifié zero-dépendance

    • ./install.sh — installation avec rapport coloré (NO_COLOR aware)
    • ./install.sh --uninstall — désinstallation (remplace uninstall.sh)
    • ./install.sh --check — diagnostic CLI/Skills via tools/cli-registry.json (python3 natif, plus besoin de jq)
    • ./install.sh --verify — 6 vérifications d'installation avec rapport pass/fail
    • ./install.sh --dry-run — simulation sans modification
    • ./install.sh --with-teams/vps/addy-skills/memory-loop — options d'installation
    • Wrappers rétrocompatibles : uninstall.sh, tools/check-tools.sh, diagnostic-skills.sh
    • install-remote.sh simplifié : download tarball + exécute install.sh
  • CLIG compliance — Conformité clig.dev sur tous les scripts shell

    • Support NO_COLOR, TERM=dumb, non-TTY, --no-color
    • Flags --help / -h sur tous les scripts
    • Messages d'erreur sur stderr, codes de sortie cohérents
    • Usage standardisé ./script.sh [OPTIONS]
  • Site refonte — Swiss International Style — Réécriture complète de site/index.html

    • Layout split asymétrique 38/62 (colonne gauche sticky, colonne droite scrollable)
    • Palette navy #02065D + orange #FF9A04 (référence CBC annual report)
    • 10 use cases numérotés et expandables (Alpine.js accordion)
    • Grille 71 agents avec filtres par catégorie et modal markdown
    • Terminal typing animation (3 lignes), cercles géométriques animés
    • Section Features 3 piliers, section Install "SHIP TODAY"
    • Mobile responsive (layout stack vertical < 768px)
  • Doc refonte — Réécriture de la documentation

    • README.md réduit à 49 lignes (vitrine projet)
    • docs/guide.md — 3 workflows, FAQ, tips
    • docs/reference.md — 71+ agents par catégorie
    • docs/adr.md — 10 ADR (ADR-001 à ADR-010)
    • docs/glossaire.md — 32 termes et agents

Modifié

  • site/index.html — Réécriture complète (Swiss design, Alpine.js, Tailwind CDN v3)
  • site/data/commands.json — Version bump 4.0.0
  • Alpine.js pinné à @3.14.1 (était @3.x.x)
  • agentFileMap complet avec chemins post-réorganisation (29 agents)
  • Fetch ./data/commands.json (relatif, compatible GitHub Pages subpath)

v3.5.0

Ajouté

  • CLI-first Architecture — Migrate from MCP to CLI tools

    • New tools/cli-registry.json: Central registry of 24 CLI tools
    • New tools/skills-registry.json: Registry of 12 custom + 4 community skills
    • New tools/check-tools.sh: CLI & Skills diagnostic script (TUI consistent with install.sh)
    • New agents/_shared/cli-tools-protocol.md: Shared protocol (CLI > MCP)
    • JSON Schemas: schemas/cli-registry.schema.json, schemas/skills-registry.schema.json
  • Skills System — 12 custom SKILL.md files in skills/

    • cli-github: Replaces GitHub MCP (gh CLI)
    • cli-deploy-vercel: Replaces Vercel MCP (vercel CLI)
    • cli-neon: Replaces Neon MCP (neonctl CLI)
    • cli-docker, cli-spip, cli-asc, cli-figma, cli-shadcn
    • cli-pgcli, cli-pandoc, cli-productivity, ulk-find-skill
    • Skills installed to ~/.claude/skills/ulk-*/ by install.sh
  • Community Skills — Optional community skills via --with-community-skills

    • frontend-design (anthropics/skills)
    • react-best-practices (vercel-labs/agent-skills)
    • find-skills (vercel-labs/skills)
  • Installer enhancements

    • --check-tools: Run CLI + Skills diagnostic only
    • --with-community-skills: Install recommended community skills
    • Skills auto-install during regular ./install.sh
    • CLI diagnostic after installation (requires jq)
  • Site — New "CLI & Skills" section on landing page

  • Tools category in site/data/commands.json (check, list)

Modifié

  • Agents now reference _shared/cli-tools-protocol.md: bruce, blackemperor, robocop, brigitte, 2b3, isaac, deploy:vercel, analyze:spip
  • Each modified agent includes CLI tool sections with command -v verification
  • Brigitte: MCP detection expanded to CLI-first with fallback
  • uninstall.sh: Now cleans skills from ~/.claude/skills/ulk-*/
  • install-remote.sh: Now installs skills
  • diagnostic-skills.sh: New section 9 for skills verification
  • README.md: CLI Tools & Skills section added

Notes

  • MCP servers NOT removed — marked as fallback for services without viable CLI (Figma, Notion, Linear)
  • ./install.sh without arguments still works as before (backward compatible)
  • Skills custom ulk prefixed ulk- to avoid naming conflicts

v3.1.0

Ajouté

  • Frontend Agent Family (agents/15-frontend/) — New agent group

    • Regrouped 6 frontend agents (brique, frontend-qa, visual-auditor, backoffice-auditor, svg-analyzer, pencil-generator) into a dedicated family
    • New Frontend Orchestrator (00-orchestrateur.md) routes to the right sub-agent
    • New namespace: /ulk:frontend:* (backward compat: /ulk:agents:* still works)
    • Follows existing family pattern (10-analyze/, 11-deploy/, 12-test/)
  • Adaptive Brique Agent — Pixel-perfect Figma/HTML conversion

    • Phase 0: Automatic Stack Detection — Detects React/Vue, Next/Nuxt, TypeScript, Tailwind
    • Design System Rules — JSON mapping Figma tokens to Tailwind/shadcn classes
    • 95-100% fidelity (vs 70-80% without rules)
    • New JSON Schema: schemas/figma-design-system-rules.schema.json
    • Documentation: agents/15-frontend/design-system/README.md
    • Generate rules via /figma:create-design-system-rules
  • macOS App Improvements (packages/apple/)

    • Design Token system (DesignTokens.swift, AppConstants.swift)
    • Fixed Claude Code CLI detection (dynamic path resolution)
    • Dynamic agent loading with multi-source support
    • Native macOS styling improvements
    • Agent check-for-updates and pull-and-update support

Modifié

  • Frontend agents moved from root agents/ to agents/15-frontend/
  • Install scripts now display Frontend category in stats
  • install-remote.sh Usage section synchronized with install.sh

Corrigé

  • Broken symlinks in commands/agents/ after frontend regrouping
  • Missing commands/ directory structure (agents, analyze, deploy, test, frontend)
  • install-remote.sh missing Frontend count in stats display

v3.0.1

Corrigé

  • Documentation: Added missing godspeed agent to README files
  • Documentation: Corrected blackemperor description in root README (4→5 modes)

v3.0.0

Ruptures

  • Entry point renamed: Bruce replaces Godspeed as the primary entry point (/ulk:agents:bruce)
  • Agent renamed: C3PO → Bruce — the Viking dog becomes the main orchestrator
  • Godspeed demoted: Now a diagnostic sub-agent called by Bruce automatically
  • Agent consolidation: Niche agents removed, unified agents introduced

Migration depuis v2.x

# Mettre à jour l'installation
git pull
./install.sh

# L'agent d'entrée change
# Avant (v2.x) :
/ulk:agents:godspeed   # ou /ulk:agents:c3po

# Après (v3.x) :
/ulk:agents:bruce      # nouveau point d'entrée principal

# Les agents supprimés/consolidés :
# - c3po.md → renommé bruce.md (symlink cassé à supprimer manuellement)
# - Agents niche supprimés : beetlejuice intégré dans bifrost

Ajouté

  • macOS App (packages/apple/) — Complete SwiftUI macOS application

    • NavigationSplitView with sidebar agent browser (31 agents, unique SF Symbol icons)
    • Chat interface with Claude Code CLI integration
    • 3-panel layout: sidebar, file editor, repo browser
    • Multi-source agent loading: installed, repo, custom, bundled
    • Nord theme (dark/light), keyboard shortcuts, GitHub bar
    • XcodeGen workflow (project.yml)
  • New Agent: Astride (40) — Snobisme de combat

    • Sarcastic code reviews with real-life advice wrapped in contempt
    • Consultant parody with genuinely excellent advice
  • New Agent: Backoffice Auditor (39) — Back Office consistency

    • Next.js (App Router) + Shadcn UI expert
    • UX/UI coherence audit, standardization plans
  • New Agent: Beetlejuice (37) — Markdown to Notion QA

    • Transforms Markdown test files into enriched Notion databases
    • Smart conversion: technical tasks → User Stories with emojis
  • New Agent: Marketing Maestro (36) — Marketing orchestrator

    • CRO, copywriting, digital presence for showcase sites
  • New Agent: Visual Auditor (35) — Chrome DevTools MCP audit

    • Screenshots, DOM/CSS analysis, visual performance (LCP/CLS/FCP)
  • Black Emperor mode: review — Code completeness vs spec/prompt

    • Extracts requirements from spec, issues, prompts, or PRs
    • Generates completeness matrix (REQ-001, REQ-002...)
    • Effort estimation (T-shirt sizing) for gaps
    • Output: docs/reviews/review-YYYYMMDD.md
  • Agent Teams support — Experimental collaborative mode

    • Multiple Claude instances working as a coordinated team
    • Shared mailbox, task list, and independent context windows
    • Supported by Bruce, Black Emperor, and other orchestrators
  • Boris Cherny Claude Code tips integrated across all agents

    • Parallel work with git worktrees
    • Plan mode first, auto-fix patterns, self-improvement loop
    • Subagents, voice dictation, advanced prompting patterns
  • Status Board (packages/status-board/) — Unified project dashboard

    • Things/Apple minimal design with Google Sans Flex font
    • Admin interface for repository management
  • Nova extension (extensions/Ulk-nova/) — Claude Code extension for Panic Nova

  • JSON Schemas (schemas/) — Cross-platform contracts (JS ↔ Swift)

    • todo.schema.json, project.schema.json, dashboard.schema.json

Modifié

  • 11 agents downgraded from opus → sonnet (cost optimization)
  • Model choice evaluation documented (docs/evaluation-model-choice.md)
  • All agent references standardized across 41 agents
  • Token usage optimized for shared tips/protocols
  • Ghost agent references removed from all documentation

Corrigé

  • Installation audit: 8 corrections to install procedure
    • Broken symlink c3po.md removed
    • Missing symlinks created: bruce.md, astride.md
    • 3 standalone files converted to symlinks (visual-auditor, beetlejuice, marketing-maestro)
    • Ghost commands fixed in install-remote.sh
    • Entry point updated in install.sh (godspeed → bruce)
  • Site content consistency audit and fixes

v2.1.1

Amélioré

  • Agent Black Emperor (30) - Enhanced delivery orchestrator
    • Added Phase 2.5: Documentation Organization (conditional)
      • Triggers on major versions, 5+ docs files modified, or --with-docs-cleanup flag
      • Integrates documentalist agent for /docs folder maintenance
      • Validates frontmatter, reorganizes files, updates index, archives obsolete files
    • Added CLAUDE.md update in Phase 4
      • Now updates both README.md and CLAUDE.md
      • Verifies essential commands, architecture, workflow, and important notes
    • Updated agent orchestration table (added documentalist 2.5, brigitte 24, split 4a/4b)
    • Added --with-docs-cleanup command option
    • Enhanced final report with ORGANISATION DOCS and README & CLAUDE.md sections

Corrigé

  • Image URLs corrected to use proper repository case (Ulk)
  • Optimized images via ImgBot

v2.1.0

Ajouté

  • New Agent: SEO & GEO Auditor (32) - Comprehensive SEO and AI optimization audit

    • Technical SEO: meta tags, sitemap.xml, robots.txt, canonical URLs, schema.org markup
    • On-page SEO: heading structure (H1-H6), content analysis, internal linking
    • Performance: Core Web Vitals integration, page speed analysis
    • GEO (Generative Engine Optimization): optimization for AI citations (ChatGPT, Claude, Perplexity)
      • Answer-first content structure
      • FAQ schema markup for AI extraction
      • E-E-A-T signals (Experience, Expertise, Authoritativeness, Trustworthiness)
      • Structured data for AI comprehension
    • Output: docs/audits/audit-seo-YYYYMMDD.md
    • GO/NO-GO checklist for launch readiness
    • Model: opus (complex multi-dimensional analysis)
  • New Agent: Pencil Page Generator (33) - Next.js to Pencil file generator

    • Nicknamed "Jean-Marie" - methodical and exhaustive analyzer
    • Scans Next.js projects (App Router and Pages Router)
    • Detects all pages, layouts, and their hierarchy
    • Extracts design tokens from globals.css_tokens.pen
    • Generates .pen files for each page with:
      • Layout imports (_layouts/*.pen)
      • shadcn/ui component references with props/variants
      • Visual structure preservation
    • Supports advanced routing:
      • Dynamic routes ([id], [...slug])
      • Route groups ((marketing))
      • Parallel routes and intercepting routes
    • Commands: scan, generate [page], generate-all, sync-tokens, status
    • Output: design/ folder with organized .pen files
    • Model: opus (complex analysis and faithful generation)

Mis à jour

  • install.sh: Added pencil-generator to usage examples
  • CLAUDE.md: Added both agents to workflow examples and file structure
  • commands/README.md: Added both agents to command reference table

v2.0.0

Ruptures

  • Project renamed from Woodman to ulk
    • All command prefixes changed: /woodman: and /wm:/ulk:
    • Repository URL: github.com/izo/ulk
    • Installation command updated
    • All agent invocations now use /ulk: prefix exclusively

Modifié

  • Renamed image files: woodman.pngulk.png, woodman-mini.pngulk-mini.png
  • Updated all install scripts with new paths and branding
  • Updated site with new branding and URLs
  • Updated all 50+ agent markdown files with new invocations
  • Updated CLAUDE.md, README.md with new project name

Migration depuis v1.x (Woodman)

Les anciennes installations Woodman sont automatiquement nettoyées par le nouvel installateur.

# Désinstaller l'ancienne version (Woodman)
# Supprimer manuellement les anciennes commandes si elles existent :
rm -f ~/.claude/commands/woodman* ~/.claude/commands/wm*

# Installer ulk
curl -fsSL https://raw.githubusercontent.com/izo/ulk/main/install-remote.sh | bash

# Mettre à jour toutes les invocations dans vos projets
# Avant (v1.x) :
/woodman:agents:godspeed
/wm:agents:bruce

# Après (v2.x) :
/ulk:agents:godspeed
/ulk:agents:bruce

Note: Les noms d'agents eux-mêmes n'ont pas changé, seul le préfixe /ulk: remplace /woodman: et /wm:.


v1.14.0

Ajouté

  • New Agent: Jobs (29) - Apple implementation architect
    • Isaac's mandatory adjoint for native Apple implementation
    • Prerequisite: requires docs/api/ generated by Isaac (refuses to start without it)
    • Multi-platform SwiftUI architecture: iOS, macOS, watchOS, tvOS, visionOS
    • Generates compilable Swift starter kit in docs/apple-starter-kit/
    • Package.swift with multi-target configuration
    • MVVM + @Observable pattern (iOS 17+) with fallback to ObservableObject
    • Conditional compilation with #if os() for platform-specific code
    • Services layer: APIClient, AuthService, TokenManager, KeychainManager
    • Interactive questionnaire: platforms, deployment targets, architecture, persistence, networking
    • Screen inventory matrix by platform with navigation patterns
    • Output: docs/apple-starter-kit/, docs/apple-implementation-guide-*.md, docs/apple-roadmap-*.md
    • Tasks with #SWIFT-NNN prefix, priorities P0/P1/P2
    • Model: opus (complex multi-platform architecture)

Workflow

  • Isaac → Jobs pipeline: Complete path from web project to native Apple app
    /ulk:agents:isaac → docs/api/
    /ulk:agents:jobs → docs/apple-starter-kit/
    

Mis à jour

  • Site: Added isaac, jobs, svg-analyzer to commands.json
  • Site: Added "App Apple native" workflow
  • README: Added jobs agent and Isaac → Jobs workflow
  • install.sh: Added isaac and jobs to usage examples

v1.13.0

Ajouté

  • New Agent: SVG Analyzer (28) - React/Next.js project analysis and SVG mockup generation
    • Phase 1 - Analysis: Scans project, identifies all pages, layouts, and shadcn/ui components
    • Phase 2 - Generation: Generates SVG for each page via Shad2SVG API (localhost:3000)
    • Framework detection: Next.js App/Pages Router, Vite, Remix, Astro
    • Component tracing: follows custom components to shadcn/ui primitives
    • Substitution strategies for unsupported components (Dialog, Sheet, Select, etc.)
    • Output: ANALYSE_PAGES.md (component inventory) + output/pages/*.svg + output/index.html (preview gallery)
    • Shortcut: /svg-analyzer (in addition to /ulk:agents:svg-analyzer)
    • Model: opus (complex analysis and faithful code generation)

Cas d'usage

  • Generate visual mockups of existing React/Next.js projects
  • Inventory all shadcn/ui components used across pages
  • Create SVG previews for design reviews
  • Document page layouts with ASCII art structures

v1.12.0

Ajouté

  • New Agent: Picsou (26) - Hosting cost estimator
    • Scans project infrastructure: stack, database, storage, external services
    • Interactive questionnaire: traffic, users, geography, budget, constraints (GDPR, HA)
    • Resource matrix calculation: Hobby / Startup MVP / Production / Scale profiles
    • Multi-provider comparison: Vercel, Netlify, Cloudflare, Railway, Render, Fly.io, Hetzner, Scaleway, OVH
    • Managed DB comparison: Supabase, Neon, PlanetScale, Turso
    • Object storage comparison: Cloudflare R2, Backblaze B2, AWS S3
    • Decision matrix with weighted scoring (cost, simplicity, performance, scalability, GDPR, DevOps)
    • 12-month cost projection with growth scenarios
    • Hidden costs tracking: domain, SSL, monitoring, backups, emails, CI/CD
    • Special cases: static sites (free), GPU/ML projects, unpredictable traffic
    • Output: docs/reports/estimation-couts-YYYYMMDD.md
    • Model: opus (multi-dimensional analysis)

Cas d'usage

  • Estimate hosting costs before launching a project
  • Compare providers for an existing infrastructure
  • Budget planning for startups and PMEs
  • GDPR-compliant hosting recommendations for European projects

v1.11.0

Ajouté

  • New Agent: Gybe (00) - Entry point and dispatcher
    • Analyzes project state instantly (spec, todo, code, git, docs)
    • Detects project phase: New, Specified, Planned, In Progress, Advanced, Legacy, Ready to Ship
    • Suggests relevant agents based on context
    • Quick commands: go, next, audit, fix, ship, sync
    • Help system with all agents listed
    • Model: sonnet (fast diagnostic)

Cas d'usage

  • Start working on any project without knowing which agent to use
  • Get instant project diagnostic
  • Quick navigation to the right agent

v1.10.0

Ajouté

  • New Agent: Bruce (25) - Product Manager orchestrator (formerly C3PO)
    • Transforms ideas into structured projects through conversational workflow
    • Orchestrates all agents: spec-writer → todo-generator → task-runner → audits → external-sync
    • Synchronizes with Notion (documentation) and Linear (tasks) at the end
    • Conversational personality inspired by the protocol droid
    • Phase-based workflow: Discovery → Specification → Planning → Implementation → Quality → External Sync → Finalization
    • Multiple modes: Assisted, Autonomous (Ralph Loop), Manual
    • Checkpoints and confirmations at each major step
    • Model: opus (complex orchestration and strategic decisions)

Cas d'usage

  • Start a new project from a vague idea
  • Get guided through the entire development process
  • Have a PM that orchestrates everything for you

v1.9.2

Ruptures

  • Structure /docs standardisée — Les rapports d'agents sont maintenant dans des sous-dossiers organisés (plus de fichiers à la racine de docs/)
    • docs/audits/ — Tous les rapports d'audit
    • docs/reports/ — Outputs orchestrateurs
    • docs/imports/ — Imports externes (Notion)
    • docs/communications/ — Outputs brigitte

Migration depuis v1.9.1

# Créer les nouveaux sous-dossiers
mkdir -p docs/audits docs/reports docs/imports docs/communications

# Déplacer les anciens rapports
mv docs/audit-*.md docs/audits/ 2>/dev/null || true
mv docs/update-*.md docs/communications/ 2>/dev/null || true
mv docs/spec_notion.md docs/imports/ 2>/dev/null || true
mv docs/todo_notion.md docs/imports/ 2>/dev/null || true
mv docs/.notion-import-meta.json docs/imports/ 2>/dev/null || true

Modifié

  • BREAKING: Standardized /docs output structure - All agent reports now go to organized subdirectories
    • docs/audits/ - All audit reports (code, perf, a11y, shadcn, frontend, landing)
    • docs/reports/ - Orchestrator outputs (pre-release, legacy-revival, simplifier, audit-summary)
    • docs/imports/ - External imports (spec_notion, todo_notion, spec_landing)
    • docs/communications/ - Brigitte outputs (update-YYYYMMDD)

Corrigé

  • All commands in commands/ are now symlinks to agents/ (was 12 divergent copies)
  • 12 agents updated to use new /docs structure

Ajouté

  • docs/00-structure.md - Convention documentation for /docs organization

v1.9.1

Ajouté

  • New Agent: brigitte (24) - Friendly communications for non-technical teams
    • Transforms commits, changelog, and code evolution into human-readable updates
    • Multiple output formats: email, Slack/Teams, weekly report, release notes
    • Zero jargon: explains "why" before "what" with everyday metaphors
    • Warm, celebratory tone that values the team's work
    • Automatically filters out internal technical details
    • Model: sonnet

Cas d'usage

  • Weekly team updates without technical jargon
  • Client-facing release notes
  • Internal newsletters
  • Slack/Teams announcements
  • Executive summaries

v1.9.0

Ajouté

  • New Agent: shadcn-auditor (23) - Dedicated shadcn/ui audit for React/Next.js projects
    • Configuration audit: components.json, CSS variables, cn() utility, aliases
    • Imports/Usage audit: local imports vs direct Radix, variants, composition patterns
    • Theming audit: dark mode, CSS variables (20+), hardcoded colors detection
    • Accessibility audit: DialogTitle/Description, FormLabel, focus visible
    • Anti-patterns detection: reimplementations, incorrect cn() usage, inline CSS
    • Scoring system: 5 categories with 0-10 scale and severity levels
    • Generates detailed report: docs/audit-shadcn-YYYYMMDD.md
    • Updates spec.md and todo.md with #SHAD-XXX prefixed tasks
    • Model: sonnet (structured analysis)

Documentation

  • Updated CLAUDE.md with shadcn-auditor agent reference
  • Updated agents/CLAUDE.md with agent in table and model distribution
  • Added commands/agents/shadcn-auditor.md for global installation

Détails techniques

  • Scope: React/Next.js only (shadcn/ui original)
  • Non-destructive: audit only, no code modifications
  • Output: scoring report with actionable corrections

v1.8.0

Ajouté

  • New Agent: notion-importer (21) - Unidirectional Notion content extraction
    • Reads Notion master page with recursive link exploration
    • Extracts content from Notion databases (optional)
    • Generates docs/spec_notion.md (specifications, architecture, context)
    • Generates docs/todo_notion.md (prioritized tasks P0-P3)
    • Smart content categorization (spec vs tasks vs notes)
    • Tracks import metadata in .notion-import-meta.json
    • Configurable exploration depth (1-3 levels or unlimited)
    • Model: opus (complex content analysis)

Cas d'usage

  • Project onboarding from existing Notion workspace
  • Notion → Linear migration (import then external-sync)
  • Backup/archive of Notion content for offline access

Documentation

  • Updated CLAUDE.md with notion-importer workflow examples
  • Updated agents/CLAUDE.md with agent capabilities and model distribution
  • Updated agents/README.md and commands/README.md with new agent reference
  • Added separation of responsibilities section distinguishing from external-sync (08)

Détails techniques

  • Direction: Unidirectional (Notion → Local only)
  • Output location: /docs with _notion suffix to avoid conflicts
  • Different from external-sync: no bidirectional sync, focused on one-time extraction
  • Requires MCP: mcp__notion

v1.7.3

Corrigé

  • Remove shell operators from code-auditor causing security warnings

v1.7.2

Corrigé

  • Fix agent invocation issues

v1.7.1

Ajouté

  • Ralph Loop Integration

v1.7.0

Modifié

  • Standardize agent report outputs across all agents

v1.6.0

Ajouté

  • Orchestrator agents (audit-complet, legacy-revival, pre-release)