0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI coding agentを「1チャット」ではなく「1変更セッション」で運用する

0
Posted at

AI coding agentを「1チャット」ではなく「1変更セッション」で運用する

coding agentから「実装しました。テストも通っています」と返ってきたのに、翌朝見たら現在地が分からない。

  • どのcommitを起点にしたのか
  • どこまで変更してよかったのか
  • 途中で何に詰まったのか
  • そのテストは別processでも通るのか

情報はchatに残っています。ただ、長いtranscriptから毎回拾い直すのはつらい。background実行やremote agentを増やすと、chatを開いている人とreviewする人が別になるので、さらに追いづらくなります。

自分なら、chatはagentを操作するUIとして使います。仕事の単位はrepository側に置く「変更セッション」です。

ここでいう変更セッションは、base commit、作業branch、変更scope、完了条件、checkpoint、review evidenceを一つのtask IDへ結びつけたものです。特定のcoding agent専用機能ではありません。Claude CodeでもGitHub Copilotでも、repoへ変更を届けるなら同じ外枠を使えます。

coding agentの進化を「セッション管理」として見る

最近のcoding toolは、生成モデル以外の部分がかなり厚くなっています。

Claude Code 2.1.232のchangelogには、subagent forkの既定化、非team agentのbackground実行、セッション間メンションなどが並んでいます。VS CodeのAgents windowも、remote agent、複数セッション、session syncを扱います。v0は既存GitHub repoのimportからsandbox、chat単位のbranch、PR、merge後のdeployまでを一つの経路にしています。

これらが同じ内部architectureを採用している、という話ではありません。fork、chat branch、Git branchも別物です。

製品ごとの仕組みは違っても、reviewerが困る場所は似ています。実行場所やsessionが増えるほど、「どの変更を、何を根拠にmergeするか」をtoolの外側で揃えたくなる。chat transcriptだけでは、その境界が弱いからです。

repositoryに変更セッションを置く

最小構成なら、taskごとに次のdirectoryを作ります。

.agent-runs/
  ACCT-241/
    task.yaml
    checkpoint.json
    evidence/
      acceptance.tsv
      lint.log
      typecheck.log
      test.log
      diff-check.log
    review.md

ACCT-241はissueやticketと対応するtask IDです。agentを起動する前にdirectoryを作り、最終報告にも同じIDを出させます。

このdirectoryをcommitするか、CI artifactや外部storeへ逃がすかはteam次第です。processが消えてもtaskの入口と出口を再構成できるなら、保存先は自由です。

まずtask contractを固定する

.agent-runs/ACCT-241/task.yamlには、agentへのお願いではなく、変更の契約を書きます。

id: ACCT-241
base_commit: "<base-sha>"
branch: agent/acct-241-checkout-empty-state
scope:
  allow:
    - src/checkout/**
    - tests/checkout/**
  deny:
    - infra/**
    - .env*
acceptance:
  - pnpm typecheck
  - pnpm test --run tests/checkout
stop_when:
  - scope外の変更が必要
  - public APIの変更が必要
  - credentialまたはproduction操作が必要

最初から長いspecを作る必要はありません。自分が外したくないのは次の項目です。

項目 何を固定するか
id taskとrunを結ぶ識別子
base_commit diffの起点
branch 変更を回収する場所
scope 触ってよいpathと触らないpath
acceptance 外部processから再実行するcommand
stop_when agentが人へ戻す条件

「checkoutのempty stateを直す」だけでは、完了判定がagentの解釈に寄ります。pnpm typecheckのようなcommandを併記すると、少なくとも同じ判定を人やCIが再実行できます。

task.yamlを書いただけでscope違反を防げるわけではありません。wrapperやCIでgit diff --name-onlyを検査して、契約を実行可能なgateへつなぐ必要があります。YAMLは正本であって、sandboxではない。この区別は残しておきます。

1セッションを1 worktreeへ分ける

並列agentへ同じworking treeを渡すと、片方のformatやpackage installがもう片方の観測へ混ざります。branchを分けただけでは、同じdirectoryを同時に触るprocessまでは隔離できません。

git fetch origin

git worktree add ../agent-acct-241 \
  -b agent/acct-241-checkout-empty-state \
  origin/main

agentは../agent-acct-241で起動します。task ID、branch名、worktree名を揃えておくと、止まったrunを探しやすいです。

Gitは通常、同じbranchを複数のworktreeへ同時にcheckoutさせません。開始時の衝突検知として使えるので、ここで--forceして回避しないほうがいいです。ただし、同じworktreeへ複数processを入れれば普通に競合します。launcher側でも「1 worktreeにつき実行中sessionは1つ」を守ります。

agent製品側のforkやremote sessionは、その製品が持つ実行機構です。worktreeはrepository上の変更境界。この二つを同一視せず、外側のGit境界だけは自分たちで握ります。

chatの生死とtaskの状態を分ける

chatが閉じても、taskが終わったとは限りません。承認待ちなら、むしろ「止まっているが再開可能」が正しい状態です。

state 意味 次の担当
planned contract作成済み、未着手 agentを起動する人
running scope内で作業中 agent
blocked 承認、情報、scope変更待ち human
needs-review gateとhandoffを作成済み reviewer
accepted review済み mergeまたはcloseする人

checkpointは小さなJSONで足ります。

{
  "sessionId": "ACCT-241",
  "status": "blocked",
  "baseCommit": "<base-sha>",
  "headCommit": "<head-sha-or-null>",
  "completed": [
    "empty state component added"
  ],
  "next": "public propsを増やしてよいか確認する",
  "evidence": []
}

更新するタイミングは、少なくとも次の4か所です。

  1. agentを起動したとき
  2. commitまたは意味のある作業単位を終えたとき
  3. 承認や追加情報が必要になったとき
  4. reviewへ渡すとき

Cloudflare Agents SDK v0.16.1が扱うapproval待ちからの再開やdurable executionも、中断とtask終了を分ける例として分かりやすいです。自前のcoding workflowでも、blockedを失敗や完了へ丸めないほうが復旧しやすい。

再開時にchat transcriptを全部読ませる必要はありません。まずtask.yaml、Gitのbase/head、checkpoint.jsonを読む。transcriptは判断理由を調べたいときの補助資料に下げます。

完了判定はagentの外側で回す

agent自身が実装と採点を両方やると、最終メッセージだけきれいに成功することがあります。acceptance commandは別processで実行し、exit statusとlogを残します。

たとえば、次のscriptをworktreeのrootから実行します。

#!/usr/bin/env bash
set -u -o pipefail

RUN_DIR=".agent-runs/ACCT-241/evidence"
BASE="${BASE:-origin/main}"
mkdir -p "$RUN_DIR"
: > "$RUN_DIR/acceptance.tsv"

overall=0

run_gate() {
  local name="$1"
  local code
  shift

  if "$@" 2>&1 | tee "$RUN_DIR/$name.log"; then
    code=0
  else
    code=${PIPESTATUS[0]}
  fi

  printf '%s\t%s\n' "$name" "$code" >> "$RUN_DIR/acceptance.tsv"
  if [ "$code" -ne 0 ]; then
    overall=1
  fi
}

run_gate lint pnpm lint
run_gate typecheck pnpm typecheck
run_gate test pnpm test --run tests/checkout
run_gate diff-check git diff --check "$BASE...HEAD"

git diff --name-only "$BASE...HEAD" > "$RUN_DIR/changed-paths.txt"
git diff --stat "$BASE...HEAD" > "$RUN_DIR/diff-stat.txt"

exit "$overall"

これは最小例です。実際のrepositoryでは、task.yamlからbaseとacceptance commandを読み、allow/deny pathも検査します。pnpm test --runが存在しないprojectなら、そのrepoのscriptへ置き換えます。

frontendの変更では、commandの成否だけでは足りません。次もevidenceへ追加します。

  • preview URLと対象route
  • viewportやtest accountなどの再現条件
  • 変更前後のscreenshot
  • console error
  • Playwright traceなどの実行artifact

「画面を確認した」ではなく、reviewerが同じrouteを開ける形にします。

review packetは会話の要約にしない

PR本文をchatの長い要約にすると、結局どこを確認すればよいか散らかります。.agent-runs/ACCT-241/review.mdは、reviewに必要な項目だけに絞ります。

# ACCT-241 review

- session_id: ACCT-241
- base_commit: <base-sha>
- head_commit: <head-sha>
- changed_paths: evidence/changed-paths.txt
- acceptance_results: evidence/acceptance.tsv
- preview: <preview-url-or-none>
- open_risks: <known-risk-or-none>
- rollback: revert <head-sha>
- review_status: needs-review

見る順番も固定します。

  1. base_commitが想定した起点か
  2. scope外のfileが混ざっていないか
  3. acceptance commandを独立実行して通るか
  4. diffとpreviewがtaskの意図に合うか
  5. open riskとrollbackが書かれているか
  6. 人がacceptedへ進めるか決める

model名やagentの自信度は、このpacketの主役ではありません。base、head、diff、gate、previewが揃っていれば、別の人でも変更を追えます。

happy pathより先に「止めても戻れるか」を試す

仕組みを入れたら、最初に成功runを眺めるよりfailure pathを試したほうが早いです。

  • agent processを作業途中で止め、branchとcheckpointだけで残作業を説明できるか
  • public API変更が必要になったらblockedで止まり、勝手にscopeを広げないか
  • 同じbranchを別worktreeへcheckoutしようとしたとき、開始を拒否できるか
  • testが落ちたrunをneeds-reviewacceptedへ進めないか
  • remote sessionを失っても、base/headとevidenceを作り直せるか
  • previewが必要なUI変更で、URLやartifactが空のままacceptedにならないか

ここで復旧できなければ、通常時に速く見えても運用はまだchat依存です。

最初は1種類のtaskだけでよい

すべてのcoding taskへ巨大な管理layerを入れると、先に運用が嫌になります。自分なら、まずfrontendの小さなUI修正だけを対象にします。

  • 1 task ID
  • 1 worktree
  • 1つのpath scope
  • typecheckと対象test
  • preview URLとscreenshot
  • 1枚のreview packet

この構成で、途中停止とscope超過を一度ずつ試す。困った項目だけcontractへ足します。

coding agentは、forkやbackground実行によって何度でも作業を並べられるようになりました。だからこそ、chatを保存するだけでは足りません。変更の起点、停止位置、完了証拠をrepository側へ残しておけば、sessionが消えても仕事は消えません。生成速度を落とすための管理ではなく、その速さをmerge可能な変更へ変えるための足場です。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?