Communityコーディング&開発github.com

zheref/ao

ブランチをベースブランチに追従させます。公開済みのコミットがない場合はリベース、ある場合はマージを行い、機械的な競合を解決し、意味的な競合がある場合はG5で停止して両側の差分を表示します。

ao とは?

このスキル(Ao)は、開発ブランチをそのベースブランチ(通常はmain)に追従させるためのgit操作スキルです。ブランチが公開済みかどうかに応じてリベースまたはマージを自動選択し、競合は「機械的なもの」と「意味的なもの」に分類します。機械的な競合(ロックファイルの再生成、両方で追記された領域の統合など)は自動解決しますが、意味的な競合(両方で同じ動作が変更された場合や一方で削除されたファイルなど)はG5で停止し、両側のコンテンツを表示して人間による判断を促します。Claude CodeやCodexなどのAIエージェントプラットフォーム上で動作し、`$ao [from <base>]` のように直接呼び出すか、`$murasaki`、`$aka`、`$en` といった他のスキルの一部として使用されます。絶対にプッシュやフォースプッシュを行わず、リモートにすでにあるコミットを書き換えることもありません。

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

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

共有ポリシーの場所: docs/DISCOVERY.md, docs/WORKFLOW.md, docs/LAUNCH-MIGRATION.md, docs/STANDALONE-ENTRY.md, docs/PROCESS.md, docs/using/README.md および docs/using/mirrors.md は、解決された Hatsu プラグイン ルート に属し、利用中のリポジトリには属しません。インストールされたサーフェス上では、ten が表示する絶対ルートを使用してそれらのファイルを読み取ってください(そのスキルを通じて再解決してください)。以下の相対リンクはソースの場所を示しています。コンシューマーの docs/ コピーがないことはポリシーがないことを意味せず、重複してファイルを作成してはなりません。ターゲットリポジトリに2番目のポリシーをコピーしたり作成したりしないでください。

Ao — ブランチを追従させる

性質: 操作系。 ブランチをベースに対して調整することは、あなただけのものではない作業に対するgit側の操作です。その差分を作成した性質がどちらであっても同じです。

ベースを私の下に置き、テキストのみを解決し、意味のあるものはすべて私に渡せ。

Ao は $murasaki の最初のステップ、$aka の3番目のステップ、そして PR が遅れたときに $en が実行するステップです。単独で呼び出すこともできます。その規律の全体は、ただ一つの区別 — テキスト対意味 — と、ただ一つの拒否 — 生成したものを決してプッシュしないこと — から成り立ちます。


0. スタンドアロンエントリ — すでに完全

Ao は呼び出し元ではなく、チェックアウトをすでに読み取ります。 § 2 は何よりも先に状態を読み取り、§ 3 は何が公開されたかに基づいてリベースかマージかを決定し、from <base> は nen/workflow.json → branch.base を介してベースを伴います。docs/STANDALONE-ENTRY.md § 4 はこれをすでに完全なものとしてリストしており、適用される条項は P1 — 複合が実行しなかった場合の $ten ao で、このフェーズの前提条件を満たします(ten § 6)— そしてベースは解決された フェッチされた origin/ 参照に対して解決されます。これは § 3 ですでに要求されています。

スタンドアロン呼び出しによって § 6 が緩和されることはありません: 意味的 競合は、両側の内容が表示された G5 停止であり、実行を続行させる側を選択することでは決して解決されません。Ao は決してプッシュせず、フォースプッシュもせず、リモート上にすでにあるコミットを書き換えることもありません。

ハンドバック. 配線された実行の次: ブランチを最新の状態にしたかった呼び出し元 — $murasaki、$aka または $en。何もプッシュされておらず、このキャッチアップの前に取得されたエビデンスは、追跡されたパスが移動した場合、古くなっています。


1. 呼び出し方

$ao [from <base>]
nen parse ao --grammar "from [<base>]" --line "<呼び出し文字列、$ao プレフィックスを除く>"

v0.3.0 でライブ検証済み(docs/ab/ao.md § 2.1): from release/1.4 → base: release/1.4; ベア from は句が存在しないものとしてパースし、終了コード 0。句はリテラルの後ろに固定されており、その理由は $spiritual-message § 1 に記録されています。

句がない場合のベースは nen/workflow.json → branch.base、デフォルトは main です(キーまたはファイルが存在しない場合)。フェッチする前にベースの名前を声に出して言ってください — 間違ったベースに対して静かにキャッチアップされたブランチは、後で誰も読めない差分になります。

引数または設定項目がない場合は、インラインで尋ねられてセットアップされます(missing-argument、missing-configuration; WORKFLOW.md § 4 尋ね、セットアップし、続行する)。

2. まずチェックアウトを読み取る

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

v0.3.0 でライブ検証済み(docs/ab/ao.md § 2.2)、--json はこのスキルが何かに触れる前に必要なものを正確に運びます: state.branch、state.isTrunk、state.dirty、state.aheadOfBase、state.existingCommitSubjects[]、state.uncommittedPaths[]。

nen wc classify のケースao の動作
must-move — トラック上拒否。 キャッチアップするものはありません: トラックは ベース です。そう伝え、状況に応じて呼び出し元を $breath または $tensho に渡します
on-branch-dirty拒否、動詞が出力した未コミットのパスを挙げます。 未コミットの作業に対するマージやリベースは、git 自身の手で拒否されるか、誰も解きほぐせない競合の中に作業を埋めてしまいます。コミットする($kokusen)か、意図的にスタッシュしてから再実行してください
on-branch-clean§ 3 に進む

nen wc classify は競合検出器ではなく、中途半端なマージは通常のダーティとして読み取られます — ライブ検証済み(docs/ab/ao.md § 2.2)。 未解決のマージ内で実行すると、競合したパスを「未コミットのパス」に含めて on-branch-dirty を報告し、進行中のマージについては何も言いません。したがって、分類する前に git に問い合わせてください。決してディスク上の .git/ に対してではありません(リンクされたワークツリーでは .git はファイルです): git rev-parse -q --verify MERGE_HEAD が解決する、または git rebase --show-current-patch が終了コード 0 で終了する(パッチで停止したリベース: 競合、または edit 停止)ことは、以前の操作がここで停止したことを意味し、この実行は その状態を報告し、何も開始しません — その上に2番目の操作を決して行わず、ここから wc catch-up を再実行することもありません。これは git のデフォルトメッセージと再証明されていないビルド(§ 5)でマージをコミットすることになるからです。プローブのその他の応答: 1(現在のパッチなしで一時停止したリベース、break または失敗した exec)は ao の管轄外なので、実行は git 自身の --continue / --abort で報告し、ここで停止します。キャッチアップに拒否を依存することは決してありません。これは、nen 0.18.0 または 0.18.1 のホストでは行われないからです(zheref/hatsu#182); 128 はリベースなしなので、分類します; その他はすべて § 3 の未回答プローブ行に委ねられます。

3. どの操作か — リベースかマージか、何が公開されたかで決定

このブランチで何も公開されていない場合はリベース。何か公開されている場合はマージ。 他の誰かがすでにフェッチしているかもしれないコミットを書き換えることは、他の人に作業を強いる唯一の git 操作であり、ローカルプレーンはそれを決して行いません。

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

動詞はまずフェッチし、それから決定します。決定は origin が今言っていることに対して行われます、このチェックアウトが最後に聞いたことに対してではありません。auto(ao が渡すもの)は、ブランチの何も @{upstream} にない場合はリベースし、そうでなければマージします; --strategy rebase|merge は、呼び出し元に理由がある場合にのみ、声に出して名前を指定します。終了コード 0 は {base, strategy, before, after, behindBefore, aheadBefore, noOp} を報告し、noOp: true の場合でも両方の SHA が報告され、「何もすることはない」とは決して報告されません。その他の終了コードは、nen v0.20.0 から読み取ります:

終了コードそれが何かao
1、かつ conflicted[] が空でないレポートがある場合競合; アボート行が出力される§ 4 が引き継ぐ
3、conflicted[] パスが すべて nen/contract.json のトップレベル mechanical ブロックにあるレポート(v0.20.0)nen がマニフェスト、チェンジログ、またはミラーとして分類した競合; アボート行と各クラスのコマンドが出力されるが、実行されない§ 4 が引き継ぎ、nen のクラスとコマンドが証拠として引用される; § 4 はそれでも各パスを自分で分類する
1、レポートなしフェッチ、ステータス、または HEAD の読み取りに失敗した、競合なしでリベースまたはマージが失敗した、または --continue が失敗した停止: nen の stderr の文を逐語的に引用し、ツリーは git が残したままであると言う; 決して § 4 ではない
2、break または失敗した exec でリベースが一時停止した場合(v0.18.2)ao のリベースではないnen の文を引用し、git rebase --continue / --abort を指定する; 決して継続またはアボートしない
2、git が応答しなかったリベースプローブの場合(v0.18.2)リベースがまったくない可能性があるnen の文を引用し、git コマンドを指定せずに停止する
2、その他変更前の拒否: ダーティツリー、git が拒否する --base、進行中の操作と矛盾する --strategy、--end-of-options には古すぎる git、リポジトリルートがない逐語的に引用して停止する
その他の終了コード予期しない停止して引用する
  • strategy: merge → ブランチがリモートに存在する → ベースがマージされた。
  • strategy: rebase → 何も公開されていない → ブランチが origin/<base> にリプレイされた。

リベース先が何もないリベースでも SHA は書き換わりますが、それは予期された動作です。 ライブ検証済み: すでに origin/<base> の先端に直接あるブランチに対して "Successfully rebased and updated" と応答し、HEAD を c8826c7 から 84b0444 に移動しました — 同じツリー、同じメッセージ、新しいコミットオブジェクトです。これはリベースがコミットをリプレイし、必要ないことに気づかないからです。これはここでのみ無害です: § 3 は 未公開の ブランチのみをリベースするため、書き換えられたコミットは誰もフェッチしていないものです。「何もすることはない」と報告するのは無害ではありません — § 7 はベースとその解決された SHA を要求し、HEAD が移動したのに 変更なし と言う実行は、古い SHA への後のすべての参照を静かに間違ったものにします。

動詞がどちらを選んだか、そしてその理由を、そのレポートから一行で言ってください。そしてリフレッシュを指定してください: "origin をフェッチしました; ブランチは @{upstream} 上にあるため、strategy: merge であり、リベースではありません。"

nen 0.5 で退役、0.13 で置き換えられました。 マージ半分は nen pr cascade-main --repo <path> --trunk <base> --no-push を通じて実行され(v0.5.0 でライブ検証済み、docs/ab/ao.md § Retired at nen 0.5)、リベース半分にはどのフラグにも動詞がありませんでした。両方の半分は現在 nen wc catch-up のものです。これは決してプッシュしません。cascade-main は izanami の自動化テーブルに mutating 行を保持しており、--no-push を含み、ao が呼び出すものではなくなりました。

4. 解決する前にすべての競合パスを分類する

git -C <path> status --porcelain                    # 競合行
git -C <path> diff --name-only --diff-filter=U      # 競合パスのみ
git -C <path> ls-files -u                           # 各パスがどのステージを持つか

それぞれ1つずつ含む構築済みフィクスチャに対してライブ検証済み(docs/ab/ao.md § 2.4):

Porcelain種類存在するステージ
UU両方変更 — 両側が同じファイルを変更した1 ベース, 2 こちら, 3 相手
AA追加-追加 — 両側が同じパスを作成した2 こちら, 3 相手; ベースなし
UD / DU削除-変更 — 一方が他方が編集したものを削除した生き残った側のみ
DD, AU, UAよりまれな形状; 同じテーブルで分類して名前を付けるgit が報告する通り

nen wc catch-up --json は、終了コード 1 または 3 で conflicted[] を運びます。マージされていないパスごとに1エントリで、ours と theirs がそのまま含まれています(そして、nen.wc.catch-up/v0.2 からは、nen の class)。それが運ばないのは 種類 です。そのため、上記の Porcelain テーブルは依然としてそのために読み取られ、§ 6 は ours/theirs を動詞が出力したとおりに正確に表示します。動詞自身のルールが引用する価値があるのは、それが置かれる場所です: それは決して片方を選択しません。

いずれかを解決する前にすべてのパスを分類し、テーブルを出力してください。 最初の3つを解決し、4つ目が意味的であることを発見した実行は、最初の3つに対してすでにメンテナの信頼を費やしています。

5. 機械的、または意味的

機械的 — 解決策は 決定されて おり、誰かによって選ばれるのではなく、リポジトリによって決まります:

  • 両側が追記した追記専用領域(インポートブロック、.gitignore、チェンジログリスト) — ファイル自身の規則が与える順序で両方を保持する;
  • リポジトリが再生成する生成済みまたはロックされたファイル(ロックファイル、スナップショット、ミラー) — ベースの側を採用して 再生成 する(Hatsu ミラー: bash scripts/surface_mirror_regenerate.sh)、そして宣言されたビルドで証明する(nen shu build; 終了テーブルは $rasengan § 6 のもの);
  • 動作の違いがない純粋なフォーマットまたは空白の相違;
  • 両側で同一の変更。

Hatsu バージョンの衝突は、クリーンなキャッチアップでも生き残ることがあります: 並行ブランチが同じ番号を選択した可能性があります。キャッチアップのたびに、両方の実際のマニフェスト(.claude-plugin/plugin.json と .codex-plugin/plugin.json)を新鮮なベースと比較してください。ブランチのバージョンがベースのバージョン以下である場合、準備完了前に両方を同じバージョンに 厳密にそのベースより上に 再バンプしてください; この取り組みの既存の changelog.d/ フラグメントのバージョン行も更新してください。これは Hatsu の作成作業であり、自動的な nen wc catch-up の再バンプではありません。次のバージョンが決定された後、bash scripts/plugin_version_refs.sh --from <old> --to <new> --body-file <local-draft> を実行して、追跡された参照とドラフト行をリストアップしてください。--write を追加して、宣言された追跡フォームと、曖昧さのないドラフト行上のすべての正確な古いバージョントークンを書き換えます; 出力された review 行は読み取ってください。これらは変更されません。このヘルパーは決してバージョンを選択せず、生成されたミラーを書き換えず、リモート PR を編集しません。上記のコマンドでミラーを再生成し、次にキャッチアップで無効になったボディファクトをリフレッシュしてください:

ボディファクトキャッチアップ後に再導出
プラグインバージョンバンプをコミットした後、git show HEAD:.claude-plugin/plugin.json と git show HEAD:.codex-plugin/plugin.json
ヘッドとベースのコミット最終コミットとフェッチの後、git rev-parse HEAD origin/<base>
ベースに対して測定された数値(バイト数、差分、カバレッジ、レビューエビデンス)その新鮮なベースと最終ヘッドに対して 再測定
Drive 行の PR 番号gh pr list --repo <owner/name> --state open --head <branch> --json number,url; 返された現在の PR を使用
チェンジログフラグメントの前提条件行キャッチアップされた依存関係コントラクトとこの取り組みの実際の前提条件に対して 再測定

リフレッシュされたローカルドラフトをレビューし、その後 nen pr edit-body をリモートライターとして使用してください。新鮮なベースに対してバンプチェックを再実行してください; 元のブランチポイントはこの比較を証明できません。

意味的 — 人 が一方の意図をもう一方よりも優先させなければならないもの。UD/DU は常に意味的です: 「削除された」と「まだ編集されている」は、何かが存在するかどうかについての2つの信念であり、マージアルゴリズムはどちらの信念も保持しません。両側が同じ動作を変更した UU も同様であり、2つのファイルが同じファイルではない AA も同様です。

教科書的なケース、ライブ検証済み(docs/ab/ao.md § 2.5): 一方の側が fn eszett() のシグネチャを変更し、もう一方の側がそのすべての呼び出し元を書き直す。競合パスは1つだけです: src/eszett.c のシグネチャ行。残りの数十のパスは git によってクリーンにマージされます。それでもそれは意味的です: どちらの変更の結果として誰がどのパラメータを期待するかという決定は、人間が下す必要があります。機械的なルールはこの区別を認識しません。nen wc catch-up --json は class に機械的とは報告しません(実際、conflicted[] はパスを1つだけ含むため、それがすべて mechanical であるという条件は満たされません)が、§ 4 のテーブルはそれを「両方変更」としてリストし、§ 5 のテキストはそれを意味的として分類することを強制します。§ 6 は停止します。

6. 停止 — 意味的競合

# 停止: 意味的競合 — 両側の内容を表示する
git -C <path> diff --cc                                # 統合 diff
git -C <path> diff MERGE_HEAD --name-only              # 相手の側の変更全体
git -C <path> diff @{1} --name-only                    # こちらの側の変更全体

ベース git diff を使用してください。しかし、意味的であると 分類 された各パスについて、名前を付け、その種類を引用し、それぞれに対して git diff コマンドの1つを表示してください:

"src/eszett.c で意味的競合を検出: UU — 関数シグネチャが両側で異なります (git -C <repo> diff --cc -- src/eszett.c)。"

そして停止します。G5 停止。 git merge --abort または git rebase --abort が何もなかったかのようにツリーを戻しますが、それは行わないでください — それはキャッチアップのエビデンスを破棄し、誰も違いを見られなくします。代わりに、競合パスと両側の内容を表示したままにします。wc catch-up がツリーをマージ状態またはリベース状態のままにした場合、ao はそれをそのままにします。呼び出し元($murasaki、$aka、$en、または人間)が自分で解決します。

$MURASAKI、$AKA、または $EN はこの出力を解析しません。 彼らはそのまま表示します。

停止時に「こちら」対「相手」として表示される内容は、§ 3 の動詞が conflicted[] で出力した内容です。キャッチアップがリベースであった場合、「こちら」はリプレイされたコミットであり、「相手」はベースです。マージであった場合、「こちら」はブランチであり、「相手」はベースです。両方とも動詞が印刷したとおりに表示します — 決して推測しないでください。

Ao は意味的競合を解決しません。 このファイルの冒頭の引用をもう一度読んでください: "私の下にベースを置き、テキストのみを解決し、意味のあるものはすべて私に渡せ。"
区分を尊重しないことは、リポジトリの自動化戦略全体への信頼を損なうため、許可されていません。

ハンドバック. 次: 呼び出し元。何もプッシュされておらず、ao はこの停止を開始したエビデンスを収集しませんでした。 最初のエビデンスの収集は、呼び出し元が意味的競合の解決を人間に委ねるときに再度行われます。


7. エビデンス — リリース承認のためのベースとその解決された SHA

Ao はそれ自体はエビデンスを収集しませんが、呼び出し元のためにベースを解決します。呼び出し元($murasaki、$aka、$en)は、その後エビデンスを収集します。この節は、ベースとそのSHAがどのように利用可能になるかを文書化します。

呼び出し元が $ao from <base> を呼び出す場合:

  • ベース名は <base> です。
  • 解決された SHA は git rev-parse origin/<base> です(§ 3 がフェッチした後)。
  • 現在のブランチの SHA は git rev-parse HEAD です(§ 2 の後、およびあらゆるリベース/マージの後)。

この情報は、呼び出し元がエビデンス(テスト結果、カバレッジなど)を収集するために利用できます。異なる呼び出し元の連鎖の外側では、この情報は破棄されます。

nen wc catch-up は、呼び出し元が以前のキャッチアップの SHA を必要とする場合に備えて、独自の before と after を報告します。 ao はこれらの SHA に対してアクションを実行しません。

8. 責任範囲

Ao の責任は次のとおりです:

  1. チェックアウトの状態の分類(§ 2)。
  2. リベースまたはマージ戦略の選択と実行(§ 3)。
  3. 競合パスの分類(§ 4)。
  4. 機械的競合の解決(§ 5)。
  5. 意味的競合の検出と G5 停止(§ 6)。
  6. 呼び出し元のためのベース解決の提供(§ 7)。

Ao の責任外:

  • プッシュまたはフォースプッシュ(§ 3 の動詞は nen wc catch-up であり、決してプッシュしない)。
  • リモート上にすでにあるコミットの書き換え(§ 3 のリベース決定はこれを防ぐ)。
  • 意味的競合の解決(§ 6 は常に停止する)。
  • エビデンスの収集(§ 7 はベースを解決するだけで、エビデンスは収集しない)。
  • リリースの作成またはバージョンの決定(§ 5 のバージョン衝突チェックは Hatsu 作成者のアクションを必要とする)。

Individual skills in this repo

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

関連スキル