zheref/ao

Met à jour une branche par rapport à sa base — rebase quand rien n'a été publié, merge quand c'est le cas, résout les conflits mécaniques et s'arrête en G5 avec les deux côtés affichés pour un conflit sémantique.

Qu'est-ce que ao ?

Ao est une compétence de manipulation Git avancée pour les agents IA (Claude Code, Codex, Cursor) qui permet de mettre à jour une branche de travail par rapport à sa base. Il distingue clairement les conflits mécaniques (déterminés par le dépôt) des conflits sémantiques (nécessitant une décision humaine). Avant toute résolution, Ao classe chaque chemin conflictuel et ne pousse jamais, ne force-pousse jamais, et ne réécrit jamais un commit déjà présent sur le dépôt distant. Cette compétence est utilisée par d'autres compétences (Murasaki, Aka, En) ou invoquée directement via `$ao [from <base>]`. Elle applique une règle stricte : rebase si la branche n'a rien publié, merge dans le cas contraire, et en cas de conflit sémantique, s'arrête en G5 en montrant les deux versions. La documentation complète couvre l'invocation, la classification par `nen wc classify`, la décision rebase/merge, la résolution mécanique, et les cas particuliers comme les collisions de version Hatsu.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/zheref/hatsu/tree/HEAD/surfaces/codex/ao

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Emplacement partagé de la politique : docs/DISCOVERY.md, docs/WORKFLOW.md, docs/LAUNCH-MIGRATION.md, docs/STANDALONE-ENTRY.md, docs/PROCESS.md, docs/using/README.md et docs/using/mirrors.md appartiennent à la racine du plugin Hatsu résolue, pas au dépôt consommateur. Sur une surface installée, utilisez la racine absolue affichée par ten pour lire ces fichiers (résoudre à nouveau via cette compétence si indisponible). Les liens relatifs ci-dessous identifient les emplacements source ; une copie docs/ manquante chez le consommateur n'est pas une politique manquante et ne doit pas déclencher un double dépôt. Ne copiez jamais et n'inventez jamais une seconde politique dans le dépôt cible.


Ao — la branche, mise à jour

Nature : Manipulateur. Réconcilier une branche avec sa base est une opération côté Git sur un corpus de travail qui n'est pas seulement le vôtre, quelle que soit la nature qui a écrit le diff.

Mets la base sous moi, résous ce qui n'est que du texte, et passe-moi tout ce qui est du sens.

Ao est la première étape de $murasaki, la troisième de $aka, et l'étape que $en exécute quand une PR prend du retard. Elle est également invocable seule. Toute sa discipline tient en une distinction — texte versus sens — et un refus : elle ne pousse jamais ce qu'elle a produit.


0. Entrée autonome — déjà totale

Ao lit déjà le checkout plutôt qu'un appelant. § 2 lit l'état avant tout, § 3 décide rebase-vs-merge selon que quelque chose a été publié, et from <base> porte la base avec nen/workflow.json → branch.base en dessous. docs/STANDALONE-ENTRY.md § 4 la liste comme déjà totale ; les clauses qui s'appliquent sont P1 — $ten ao quand aucun composite ne l'a exécutée, rattrapant les prérequis de cette phase (ten § 6) — et la base se résolvant par rapport à la référence origin/ récupérée, ce que § 3 exige déjà.

Rien dans un appel autonome n'assouplit § 6 : un conflit sémantique est un arrêt G5 avec les deux côtés affichés, et il n'est jamais résolu en choisissant le côté qui fait continuer l'exécution. Ao ne pousse toujours jamais, ne force-pousse jamais et ne réécrit jamais un commit déjà présent sur le dépôt distant.

Retour. Suite dans l'exécution câblée : l'appelant qui avait besoin de la branche à jour — $murasaki, $aka ou $en. Rien n'a été poussé, et les preuves prises avant ce rattrapage sont périmées si un chemin suivi a bougé.


1. Invocation

$ao [from <base>]
nen parse ao --grammar "from [<base>]" --line "<l'invocation, sans le préfixe $ao>"

Vérifié en direct à v0.3.0 (docs/ab/ao.md § 2.1) : from release/1.4 → base : release/1.4 ; un from nu s'analyse avec la clause absente, sortie 0. La clause est ancrée derrière un littéral pour la raison que $spiritual-message § 1 enregistre.

Sans clause, la base est nen/workflow.json → branch.base, par défaut main quand la clé ou le fichier est absent. Nommez la base à voix haute avant de la récupérer — une branche rattrapée silencieusement contre la mauvaise base est un diff que personne ne peut lire ensuite.

Un argument ou un élément de configuration manquant est demandé et configuré en ligne (argument-manquant, configuration-manquante ; WORKFLOW.md § 4 Demander, configurer, continuer).

2. Lire le checkout d'abord

nen wc classify --repo <chemin> --base <base> --json

Vérifié en direct à v0.3.0 (docs/ab/ao.md § 2.2), --json transporte exactement ce dont cette compétence a besoin avant de toucher à quoi que ce soit : state.branch, state.isTrunk, state.dirty, state.aheadOfBase, state.existingCommitSubjects[], state.uncommittedPaths[].

Cas nen wc classifyCe que fait ao
must-move — sur le troncRefuser. Il n'y a rien à rattraper : le tronc est la base. Dites-le et passez l'appelant à $breath ou $tensho, selon ce que la situation demande
on-branch-dirtyRefuser, en nommant les chemins non commités que le verbe a affichés. Un merge ou un rebase sur un travail non commité refuse ou bien enfouit le travail dans un conflit que personne ne peut démêler. Commitez-le ($kokusen) ou stash-le délibérément, puis relancez
on-branch-cleanPasser à § 3

nen wc classify n'est pas un détecteur de conflit, et un merge à moitié terminé se lit comme de la saleté ordinaire — vérifié en direct (docs/ab/ao.md § 2.2). Lancé à l'intérieur d'un merge non résolu, il rapporte on-branch-dirty avec les chemins conflictuels comptés parmi les "chemin(s) non commité(s)", ne disant rien du merge en cours. Donc demandez d'abord à git avant de classifier, jamais .git/ sur le disque (dans un worktree lié .git est un fichier) : git rev-parse -q --verify MERGE_HEAD qui résout, ou git rebase --show-current-patch qui sort 0 (un rebase arrêté sur un patch : un conflit, ou un arrêt edit), signifie qu'une opération précédente s'est arrêtée ici, et cette exécution rapporte cet état et ne commence rien — jamais une seconde opération par-dessus, et jamais une relance de wc catch-up depuis ici, qui commiterait un merge avec le message par défaut de git et sans construction re-prouvée (§ 5). Les autres réponses de la sonde : 1 (un rebase en pause sans patch actuel, à un break ou un exec échoué) n'est pas celui d'ao, donc l'exécution le rapporte avec --continue / --abort de git et s'arrête ici, ne comptant jamais sur catch-up pour le refuser, ce qu'un hôte encore sur nen 0.18.0 ou 0.18.1 ne fait pas (zheref/hatsu#182) ; 128 n'est pas un rebase, donc classifier ; tout le reste est laissé à la ligne de sonde sans réponse de § 3.

3. Quelle opération — rebase ou merge, décidé selon que quelque chose a été publié

Rebase quand rien sur cette branche n'a été publié. Merge quand quelque chose a été publié. Réécrire un commit que quelqu'un d'autre a peut-être déjà récupéré est la seule opération git qui coûte du travail aux autres, et le plan local ne le fait jamais.

nen wc catch-up --repo <chemin> --base <base> [--strategy rebase|merge|auto] [--dry-run] [--json]

Le verbe récupère d'abord, puis décide, et la décision est prise par rapport à ce qu'origin dit maintenant, jamais par rapport à ce que ce checkout a entendu la dernière fois. auto (ce qu'ao passe) rebase quand rien de la branche n'est sur @{upstream} et merge autrement ; --strategy rebase|merge en nomme un seulement là où l'appelant a une raison, dite à voix haute. La sortie 0 rapporte {base, strategy, before, after, behindBefore, aheadBefore, noOp}, et un noOp: true est toujours rapporté avec les deux SHA, jamais comme "rien à faire". Chaque autre sortie, lue depuis nen v0.20.0 :

SortieCe que c'estAo
1, avec un rapport dont conflicted[] n'est pas videun conflit ; la ligne d'abandon est affichée§ 4 prend le relais
3, un rapport dont les chemins conflicted[] sont tous dans le bloc mechanical de premier niveau de nen/contract.json (v0.20.0)un conflit que nen a classé comme manifeste, changelog ou miroir ; la ligne d'abandon et les commandes de chaque classe sont affichées, aucune exécutée§ 4 prend le relais, les classes et commandes de nen citées comme preuve ; § 4 classifie toujours chaque chemin lui-même
1, pas de rapportun échec de récupération, de statut ou de lecture de HEAD, un rebase ou merge échoué sans conflit, ou un --continue échouéarrêter : citer la phrase de stderr de nen textuellement, dire que l'arbre est tel que git l'a laissé ; jamais § 4
2, un rebase en pause à un break ou un exec échoué (v0.18.2)pas le rebase d'aociter la phrase de nen, qui nomme git rebase --continue / --abort ; jamais continuer ou abandonner
2, une sonde de rebase à laquelle git n'a pas répondu (v0.18.2)il n'y a peut-être pas de rebase du toutciter la phrase de nen et arrêter, sans nommer de commande git
2, autre choseun refus avant toute mutation : un arbre sale, un --base que git rejette, un --strategy en désaccord avec l'opération en cours, un git trop vieux pour --end-of-options, pas de racine de dépôtle citer textuellement et arrêter
toute autre sortieinattenduarrêter et le citer
  • strategy : merge → la branche existe sur le dépôt distant → la base fusionnée.
  • strategy : rebase → rien publié → la branche rejouée sur origin/<base>.

Un rebase avec rien sur quoi rebaser réécrit quand même le SHA, et c'est attendu. Vérifié en direct : une branche déjà assise directement sur le sommet de origin/<base> a répondu "Successfully rebased and updated" et a déplacé HEAD de c8826c7 à 84b0444 — même arbre, même message, nouvel objet commit, parce que le rebase rejoue le commit plutôt que de remarquer qu'il n'en a pas besoin. Il est inoffensif ici et seulement ici : § 3 rebase uniquement une branche non publiée, donc le commit réécrit est un que personne n'a récupéré. Il n'est pas inoffensif de le rapporter comme "rien à faire" — § 7 demande la base et son SHA résolu, et une exécution qui dit pas de changement alors que HEAD a bougé laisse chaque référence ultérieure au vieux SHA silencieusement erronée.

Dites lequel le verbe a choisi et pourquoi, en une ligne, depuis son rapport, et nommez l'actualisation : "origin récupéré ; la branche est sur @{upstream}, donc strategy : merge, pas un rebase."

RETIRÉ à nen 0.5, remplacé à 0.13. La moitié merge passait par nen pr cascade-main --repo <chemin> --trunk <base> --no-push (vérifié en direct à v0.5.0, docs/ab/ao.md § Retiré à nen 0.5) et la moitié rebase n'avait de verbe à aucun drapeau. Les deux moitiés sont maintenant nen wc catch-up's, qui ne pousse jamais. cascade-main garde sa ligne mutating dans la table d'automatisation d'izanami, --no-push inclus, et n'est plus ce qu'ao appelle.

4. Classifier chaque chemin conflictuel avant d'en résoudre un

git -C <chemin> status --porcelain                    # les lignes de conflit
git -C <chemin> diff --name-only --diff-filter=U      # les chemins conflictuels, seuls
git -C <chemin> ls-files -u                           # quelles étapes chaque chemin a

Vérifié en direct contre un fixture construit portant un de chaque (docs/ab/ao.md § 2.4) :

PorcelaineTypeÉtapes présentes
UUtwo modified — les deux côtés ont changé le même fichier1 base, 2 nôtre, 3 leur
AAadd-add — les deux côtés ont créé le même chemin2 nôtre, 3 leur ; pas de base
UD / DUdelete-modify — un côté a supprimé ce que l'autre a éditéseulement le côté survivant
DD, AU, UAles formes plus rares ; classifier par la même table et les nommercomme git les rapporte

nen wc catch-up --json transporte conflicted[] à la sortie 1 ou 3, une entrée par chemin non fusionné, avec ours et theirs textuels (et, depuis nen.wc.catch-up/v0.2, la class de nen). Ce qu'il ne transporte pas est le type, donc le tableau de porcelaine ci-dessus est toujours lu pour cela, et § 6 montre ours/theirs exactement comme le verbe les a affichés. La règle propre du verbe est celle qui vaut la peine d'être citée là où elle atterrit : il ne choisit jamais un côté.

Classifiez chaque chemin avant d'en résoudre un, et affichez le tableau. Une exécution qui résout les trois premiers et découvre que le quatrième est sémantique a déjà dépensé la confiance du mainteneur sur les trois premiers.

5. Mécanique, ou sémantique

Mécanique — la résolution est déterminée, par le dépôt, choisie par personne :

  • une région append-only que les deux côtés ont complétée (un bloc d'import, un .gitignore, une liste de changelog) — garder les deux, dans l'ordre que la convention propre du fichier donne ;
  • un fichier généré ou verrouillé que le dépôt regénère (un lockfile, un snapshot, un miroir) — prendre le côté de la base et regénérer (miroirs Hatsu : bash scripts/surface_mirror_regenerate.sh), puis le prouver avec la construction déclarée (nen shu build ; la table de sortie est celle de $rasengan § 6) ;
  • une divergence de formatage pur ou d'espacement blanc sans différence comportementale ;
  • un changement identique fait des deux côtés.

Une collision de version Hatsu peut survivre à un rattrapage propre : des branches parallèles peuvent avoir choisi le même numéro. Après chaque rattrapage, comparez les deux manifests réels (.claude-plugin/plugin.json et .codex-plugin/plugin.json) avec la base fraîche. Si la version de la branche est inférieure ou égale à celle de la base, re-augmentez les deux à la même version strictement supérieure à cette base avant la préparation ; mettez à jour la ligne de version dans le fragment changelog.d/ existant de cet effort aussi. Ceci est la rédaction Hatsu, pas un re-augmentation automatique de nen wc catch-up. Une fois la prochaine version décidée, lancez bash scripts/plugin_version_refs.sh --from <ancien> --to <nouveau> --body-file <brouillon-local> pour lister les références suivies et les lignes de brouillon. Ajoutez --write pour réécrire les formulaires suivis déclarés et chaque jeton exact d'ancienne version sur des lignes de brouillon non ambiguës ; lisez les lignes review affichées, qui restent inchangées. L'assistant ne choisit jamais la version, ne réécrit pas les miroirs générés et n'édite pas une PR distante. Regénérez les miroirs avec la commande ci-dessus, puis rafraîchissez les faits de corps invalidés par le rattrapage :

Fait de corpsRe-dériver après rattrapage
Version du plugingit show HEAD:.claude-plugin/plugin.json et git show HEAD:.codex-plugin/plugin.json après avoir commité l'augmentation
Commits head et basegit rev-parse HEAD origin/<base> après le commit final et la récupération
Chiffres mesurés par rapport à la base (octets, diff, couverture, preuve de revue)re-mesurer par rapport à cette base fraîche et head final
Numéro de PR dans la ligne Drivegh pr list --repo <propriétaire/nom> --state open --head <branche> --json number,url ; utiliser la PR actuelle retournée
Ligne de prérequis du fragment de changelogre-mesurer par rapport au contrat de dépendance rattrapé et aux prérequis réels de cet effort

Révisez le brouillon local rafraîchi, puis utilisez nen pr edit-body comme rédacteur distant. Relancez la vérification d'augmentation par rapport à la base fraîche ; le point de branche original ne peut pas prouver cette comparaison.

Sémantique — tout ce où une personne doit préférer une intention à une autre. UD/DU est toujours sémantique : "supprimé" et "encore en cours d'édition" sont deux croyances sur l'existence d'une chose, et aucun algorithme de merge ne détient la croyance. Il en va de même pour un UU où les deux côtés ont changé le même comportement, et un AA dont les deux fichiers ne sont pas le même fichier.

**Le cas classique, vérifié en direct (docs/ab/ao.md § 2.

… [tronqué pour la traduction]

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills associés