Skip to content

About

A two-phase development lifecycle for AI-agent collaboration: spec-driven bootstrap, guarantee-driven maintenance — on Nix.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

🇯🇵 日本語 | 🇬🇧 English

AI-Agent Development Environment as Code

CI

AI エージェントとの開発では、ボトルネックはコードの生成から、検証と意図伝達へ移る。 本リポジトリは、その前提で組んだ個人の開発基盤を、Nix 構成・役割分離の実行機構・skill 群ごとコードとして公開する実例である。守らせたい規則は文書に頼まず、環境(Nix・Claude Code の deny とフック・skill)に置いている。 チームのリポジトリへ持ち込める分は sdlc-kit に切り出しており、ここはその型を実際に回している環境にあたる。


Why

AI がコードを書くようになって、時間がかかるのは書くことではなくなった。残ったのは2つである。

1つは検証である。書かれたものを信じてよいか確かめることに時間がかかる。エージェントは自信を持ったまま静かに間違え、放っておけば破壊的な操作や機密の漏洩をそのまま本番へ通す。人が気をつけるという約束は、いずれ形骸化する。

もう1つは意図伝達である。依頼に書かれていない条件は、エージェントが推論で埋めて、動くものを仕上げてしまう。動くので、空白があったことに気づきにくい。これまで実装者の頭の中で下されていた判断を、実装の前にコードの外へ書き出して渡す必要がある。

そのため、この基盤は注意し続ける人間を前提にしない。環境差の排除・破壊的なコマンドの遮断・機密の隔離はコードと設定で固定し、人間のマージを最後の関門に置く。人間は「何が壊れてはいけないか」を決めて文書で承認し、実装とテストはエージェントに任せる。約束が破られれば機械が検知して止まるので、張り付いて見張らずに済む。

分かれ目は、書いて渡せるかである。挙動は書いて渡せるので、Issue に書いた確認をエージェントが自分で動かして確かめる。使い心地は、エージェントが意図や感覚を持ちにくく、人が言葉にしても渡しきれない。だから人が触って判断する。人間の仕事は、コードを書くことと動作を照合することから、約束を承認することと、書いて渡せない感覚を判断することへ移る。


Principles

仕組みは3つの原則で組んでいる。

  1. 守る約束を先に書く
  2. 確かめるのは仕組みと別の文脈
  3. 人には書けない判断だけを残す

1 と 2 が Why の2つのボトルネック(意図伝達と検証)に、3 がその分かれ目(書いて渡せるか)に答える。順序には依存がある。約束が書かれていないと、仕組みは何を守らせるかが、別の文脈は何を基準に確かめるかが決まらない。確かめる仕組みが無いと、人に残したはずの判断に照合と見張りが混ざる。

型の判定と規則の置き場、deny とフックは、規模によらず最初から要る。保証台帳と役割の分離は、公開物を持つとき、または複数のセッションを並行して回し始めたときに足す。


Design

1. 守る約束を先に書く

エージェントは、書かれていない条件を推論で埋める。だから人が決めることは、作る前に書いて渡す。

中心は保証駆動開発(Guarantee-Driven Development, GDD)である。何が壊れてはいけないか(保証)を人が Issue の保証節で承認し、それを固定するテストと実装はエージェントが書く。TDD がテストを先に書く規律なら、GDD は約束の承認を先に行う規律である。承認した保証は各リポの保証台帳 docs/guarantees.md に、裏付けるテストと一緒に積み上がる。台帳に載っていない振る舞いは約束ではない(guarantee-audit、Zenn: 保証駆動開発)。

開発は2つのフェーズで駆動文書を交代させる。方向が固まらない立ち上げ期は PLAN.md(残作業)と JUDGE.md(設計判断)が開発を駆動し(mvp-docs)、保証台帳が正式運用に上がった時点で台帳へ交代して Issue 駆動期に入る。考え方の全体は sdlc-kit の docs/lifecycle.md にある。

約束のほかにも、作る前に書いて渡すものがある。リポの型(類型と検証手段、README の種別)は書き始める前に決める(repo-standardize・repo-readme・module-dev)。規則は読まれる場面で置き場を分け、毎回守らせるものは CLAUDE.md に、「〜するとき」と条件を言える手順は skill に置く(skill-dev)。

2. 確かめるのは仕組みと別の文脈

エージェントは自信を持ったまま静かに間違える。人が気をつけるという約束は形骸化するので、確かめることを人の注意に預けない。

仕組み:外れてはいけないもの(rebuild 系、flake.lock の編集、ssh、機密の対応表)は deny とフックで止める。フックの拒否文には、止めた理由と正しい経路を書く。エージェントは拒否されると別の手を試し、何を試すかは拒否文で決まるからである。元のチェックアウトでのブランチの切り替えはフックが止め、永続メモリへの書き込みには承認を挟む。subagent を呼ぶことも、その都度頼まずに手順へ組み込む。書き換えた日本語の文書は、コミットの前に書き手が校正役(jp-proofreader)に通す。

別の文脈:同じモデルが作って確かめると、外したことに自分では気づけない。相談者が Issue を設計し(local-issue)、実行者が実装し(pr-workflow)、確認者(issue-verifier)が Issue だけを基準に確かめる。確認者に実行者の説明を渡さないのは、渡すと実行者の意図を前提に読み、約束から外れたところが見えなくなるからである。テストも実行者が書くので、実装の出力を写した期待値は誤りごと通る。確認者は、証拠にしたテストの期待値を Issue から自分で出し直す。画面に出る変更は screen-operator が操作して、見えたものを返す。subagent は、すでに別の文脈が確かめている段には足さない。足す理由は客観性・速さ・自動化に限る(skill-dev の 6)。規則同士の食い違いも書いた本人には見つけにくいので、consolidate-rules が別に棚卸しする。

振り分け:確かめる手段は、決定的な検査(フック・スクリプト・CI)、別の文脈(確認者などの LLM)、人の順に振り分ける。LLM の確認は、同じ入力でも判定が変わることがある。決定的に確かめられるものは LLM に読ませず、スクリプトやフックに実装させる。別の文脈が受け持つのは、読まないと答えられないもの(期待値の出し直し、約束から外れていないか、規則同士の矛盾)だけにする。人に残すのは、書いて渡せない判断だけで、次の節で扱う。このリポでは、フックの回帰テスト・文書の参照切れ・フックの配線は CI が、差分と Issue の 対象 の一致はスクリプト(check-scope.sh)が検査する。件数・一覧・索引のように他から導ける値も、手で書かずにスクリプトと CI が書き出し、ずれがあれば失敗させる。

flowchart TD
    U([user]) -->|承認| I[issues/ の Issue]
    C([相談者]) -->|設計| I
    subgraph local [ローカルの worktree・実行者のセッション]
        I -->|i で起動| E([実行者])
        E --> L[コミット]
        L --> J{{確認者}}
        J -->|不合格| E
        J -->|合格| V{{user に見てもらうものがあるか}}
        V -->|あり| H{{使い心地・合意から外れたこと・実機の確認}}
        H -->|指摘| E
    end
    V -->|なし| P
    H -->|OK| P
    subgraph remote [GitHub]
        P[実行者が PR を出す] -->|user がマージ| M[main]
    end
Loading

役割の境目は、zsh の関数 i 1つで渡す。worktree ごとに実行者を起動し、マージと後片付けまでを受け持つ(docs/issue-workflow.md、Zenn: Issue 駆動ワークフロー)。並行する実行者のあいだに取りまとめのセッションは置かない。前後のある Issue は depends: に先の Issue を書き、i は先の Issue がマージされるまで後の Issue を候補に出さない。順序を見張る役を置かず、Issue 自身に持たせる。

3. 人には書けない判断だけを残す

分かれ目は、書いて渡せるかである。挙動は書いて渡せるので、1 で約束し、2 で確かめる。使い心地や意図に合っているかは、エージェントが意図や感覚を持ちにくく、人が言葉にしても渡しきれない。人に残すのはこれだけにする。

user が持つのは4つである。保証節の承認、実行者のセッションでの使い心地と実機の確認、約束から外れたことを採るかの判断、マージ。実行者が止まるのは、2つめと3つめに当たるものがあるときだけで、無ければ PR まで進む。リモートへ出る関門で必ず通るのはマージだけになる。挙動の照合は頼まず、同じものを2つの段で見せない。

使い心地は先に見る。画面に出る変更は、テストと台帳を書く前に画面を渡す。使い心地で形が変わると、先に書いたテストが無駄になる。

絞るのは、人の判断を薄めないためでもある。速度が上がるほど人の把握は減り、承認は形だけになりやすい。挙動の照合を手放した分、人は挙動を自分で辿らなくなる。その代わりに、人が見るものを本人にしか判断できないものへ絞る。並行を依存し合わない Issue の3本までにして、確認と直しを実行者のセッションごとに閉じているのも、本数が増えても一つ一つの承認が成り立つようにするためである。


Foundation

全端末で道具を揃える

macOS と Linux の開発機を1つの Flake で管理する。端末ごとに道具の有無や版が違うと、エージェントはコマンドが見つからない、実行時に失敗する、といった形で止まる。

構成 OS 役割
linux-desktop NixOS(disko / SSD) 主開発機。相談者チャットと i の起動元
macbook macOS(nix-darwin) home-manager 層を Linux 機と共有する

OS の差は、Nix 側では pkgs.stdenv.isDarwin、シェル側では os.sh のシム(_is_darwin / _sed_i / _open / _linux_only)に閉じ込め、それ以外は両 OS が同じファイルを読む。エージェントが brew や npm -g に手を伸ばすと block-non-nix-install.sh が止め、Nix で入れる手順(nix-tool-install)へ案内する。

規則を1か所から全セッションへ配る

.claude/ の settings・hooks・skills と home-manager/config/claude/common.md が正本で、home-manager/modules/claude.nix が rebuild のたびに ~/.claude へ実体コピーする。どのリポジトリ、どの端末で Claude Code を開いても、同じ規則が効く。~/.claude 側は生成物になるので、そこを直接編集しようとすると block-live-claude-config-edit.sh が止め、正本のパスを返す。永続メモリは memory.nix で git の経路に乗せ、端末間で揃える。

機密を地の文に出さない

Issue・PR・コミットの地の文には、IP・ポート・実ホスト名を書かずに <PLACEHOLDER> を使う。実値とプレースホルダの対応表は secrets-agents/ に置き、エージェントからは読み書きさせない。

対応表が1台にしか無いと、別の端末では何を伏せるべきか分からないまま書くことになる。対応表は sops(age)で暗号化して git で配り、各端末が自分の鍵で復号する(sops-secrets)。


Skills

手順と基準は、それを使う skill が持つ。全体の一覧と、何を公開するかの基準は .claude/skills/README.md にある。subagent の定義は .claude/agents/、フックは .claude/hooks/ にある。


Tech Stack

Layer Technology Reason
構成管理 Nix Flakes・home-manager 全端末の道具と設定を1つの宣言から作れる。エージェントが端末差で止まらない
macOS nix-darwin macOS でも home-manager 層を Linux 機と共有できる
ディスク disko パーティション構成まで Nix の宣言に含められる
機密 sops-nix・age 暗号文のまま git で配り、各端末が自分の鍵で復号できる。平文を端末間で運ばない
エージェント Claude Code settings.json の deny と PreToolUse フックで、禁止を文書ではなく機構として置ける
レビュー crit 実行者の差分とローカルのページを、user とエージェントが同じ入口からレビューできる
受け渡し zsh worktree の作成から公開までを、役割の境目ごとに1コマンドにできる
セッション tmux・tmux-claude-session-manager 並行する Claude Code のセッションを渡り歩ける

Scope

稼働中の dotfiles から、エージェントとの開発に関わる層(Claude Code・メモリ・機密・レビュー・tmux のセッション管理)だけを抜き出している。稼働側の Flake は、ここに載せた2台のほかに headless のサーバーや WSL も束ね、エディタ・デスクトップの設定やフリートの状態確認も持つが、それらは含めていない。Nix による道具の統一・~/.claude の配布・対応表の復号・永続メモリは端末に紐づき、チームのリポジトリからは効かせられないので、sdlc-kit には入れずここに残している。

clone して各自の端末へ適用することは想定しておらず、動かす手順も載せていない。デバイス構成は実機のハードウェアと鍵を前提にしていて、secrets/ の暗号文も含めていないためである。CI の nix flake check は、公開している構成が評価できる状態にあることを確かめている。

About

A two-phase development lifecycle for AI-agent collaboration: spec-driven bootstrap, guarantee-driven maintenance — on Nix.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages