複数のAIエージェントを起動し、別々のGit worktreeへ割り当てる方法は広く知られるようになりました。
しかし、本記事の対象は「同じIssueを複数AIに解かせ、最良案を選ぶ」方式ではありません。
扱うのは次の運用です。
この記事の位置付け
- 実務上の状態遷移と復旧方法は、Codex CLI /goalの6状態を実例で理解する――Blockedからの再開、BudgetLimited、Completeの違いで扱っています。
- 自律実行を状態機械・完了述語・Safety/Livenessとして整理した理論編は、AIコーディングエージェントの自律実行を状態機械として設計する――完了述語・Safety/Liveness・責任境界です。
- 本記事は、その考え方を複数の独立Goalの並列運用へ適用する実践編です。
異なるIssue
x
独立した複数の永続Goal
x
すべての成果を安全に完了へ収束させる
この運用では、worktreeを分けるだけでは足りません。次も分離する必要があります。
- Goalとchatの文脈
- branchとGit index
- file・directoryの書き込み所有権
- port、DB、cache、container、temporary files
- PR、review thread、Issueコメントのwriter
- merge順序と統合責任
本記事の中心命題は次です。
Safe Goal Parallelism
=
Isolated Goal State
+ Isolated Mutable State
+ Single Writer
+ Serializable Integration
初回確認日: 2026年8月8日
最終確認日: 2026年8月16日
主対象: Codex CLIのinteractive TUI、Git worktree、tmux、Linux/WSL2環境。OpenAIのDeveloper commandsはCLI、IDE extension、ChatGPT desktop appを同じページで扱うため、/worktreeの利用可否はsurfaceごとに区別して記述します。コマンドやUIは更新される可能性があるため、公開後はcodex --versionと各surfaceのコマンド一覧を確認してください。
先に結論
実務上の基本単位を次に固定します。
1 Issue
= 1 Goal
= 1 Codex chat
= 1 Codex process
= 1 Git branch
= 1 Git worktree
= 1 PR writer
全体構成は次です。
+----------------------+
| Integration owner |
| human or review Goal |
+----------+-----------+
|
merge order / reverify
|
+----------------------+----------------------+
| |
+----v-----+ +----v-----+
| PR A | | PR B |
| writer A | | writer B |
+----+-----+ +----+-----+
^ ^
| |
+----------+-----------+ +----------+-----------+
| Goal A / chat A | | Goal B / chat B |
| process A | | process B |
| worktree A / branch A| | worktree B / branch B|
| runtime namespace A | | runtime namespace B |
+----------------------+ +----------------------+
最も重要なルールは次です。
One mutable object -> One writer
同じPR、同じreview thread、同じDB migration、同じ共有設定へ複数Goalを書かせないことが、並列運用の基礎です。
比較型並列と運用型並列を分ける
AIを複数動かす目的は2種類あります。
| 方式 | 目的 | 典型例 | 最後に残す成果 |
|---|---|---|---|
| 比較型並列 | 同じ問題に複数案を出し、最良案を選ぶ | Claude、Codex、Geminiへ同じIssueを依頼 | 原則1案 |
| 運用型並列 | 独立した複数タスクを同時に完了させる | Issue #123と#124を別Goalで進める | 原則すべて |
比較型では、各worktreeは「候補案」です。重複しても問題ありません。
運用型では、各worktreeは「本番へ統合する予定の成果」です。次が必要になります。
- 所有範囲が重ならない
- 外部状態が衝突しない
- 依存順序が明確
- 各PRのwriterが一意
- すべてを統合するGateがある
本記事は後者を扱います。
同じchat内でGoalを切り替えない
公式のLong-running workガイドでは、各chatが独自のcontext、messages、results、Goalを持ち、複数chatを同時に実行できると説明されています。
一方、同一chat内に次のような名前付きGoal一覧を持つ運用ではありません。
/goal list
/goal select issue-123
/goal switch issue-124
独立作業でGoalを順次置き換えると、次が混ざります。
- 調査結果
- 追加指示
- 例外判断
- blocker履歴
- PR headの認識
- 許可されたscope
推奨構成:
chat A -> Goal A -> worktree A -> branch A -> PR A
chat B -> Goal B -> worktree B -> branch B -> PR B
chat C -> Goal C -> worktree C -> branch C -> PR C
Goalはchatのラベルではなく、独立した作業責任の単位として扱います。
並列化の4つのPlane
worktreeだけに注目すると、Git以外の衝突を見落とします。並列運用を4つのPlaneに分けます。
| Plane | 分離するもの | 代表的な対策 |
|---|---|---|
| Control | Goal、chat、履歴、指示、権限 | 1 Goal 1 chat、別process |
| Source | files、Git index、HEAD、branch | 別worktree、所有範囲 |
| Runtime | port、DB、cache、tmp、container、lock | namespace分離 |
| Integration | PR、review、Issue更新、merge順序 | single writer、統合Gate |
worktree isolation
only protects part of Source Plane
別worktreeでも、同じDBへmigrationを適用すれば競合します。同じPRへコメントすれば、headの認識とreview処理が競合します。
並列化できるかを先に判定する
作業量が多いから並列化するのではありません。可変状態を分離できる場合だけ並列化します。
開始前に次の表を作ります。
| Goal | Objective | Owned files | Shared contract | Runtime | PR | Dependency |
|---|---|---|---|---|---|---|
| A | auth timeout修正 | src/auth/** |
session interface v2 | port 3101 / db_a | PR A | なし |
| B | billing retry修正 | src/billing/** |
event envelope v1 | port 3102 / db_b | PR B | なし |
| C | 利用者ガイド更新 | docs/** |
auth/billing公開仕様 | なし | PR C | A・B後に最終化 |
次の質問へすべて答えます。
[ ] 成果を別々にcommitできるか
[ ] 別々にreviewできるか
[ ] 一方だけrevertできるか
[ ] 同じfileを変更しないか
[ ] 同じschema migrationを所有しないか
[ ] 同じexternal fixtureへ破壊的writeをしないか
[ ] 同じPRやreview threadへwriteしないか
[ ] 共有契約を開始前に固定できるか
[ ] merge順序を決められるか
1つでも不明なら、次のいずれかを行います。
- Goalを分割し直す
- 共通変更を先行PRへ切り出す
- 一方をpauseし、依存順に実行する
- 読み取り専用の調査だけを並列化する
独立Goalとsubagentの使い分け
| 作業 | 推奨方式 |
|---|---|
| 独立したIssueを別々に実装 | 別chat・別Goal・別worktree |
| 1つのPRを複数観点で調査 | 1 Goal+subagents |
| 同じ成果への短い補助調査 | /side |
| 同じ文脈から別解を比較 |
/fork+別worktree |
| 同じfileへ複数agentが同時write | 原則禁止 |
判断基準:
別々にcommit / review / revertする成果
-> independent Goals
1つの成果へ集約する調査・評価
-> subagents
1つのPRをセキュリティ、テスト、API互換性の3観点で確認する場合は、subagentを読み取り中心で使い、書き込みは親Goalだけにします。
Subagents: explore and report
Parent Goal: decide and write
OpenAIのSubagentsガイドも、最初はexploration、tests、triage、summarizationなどのread-heavy taskで並列化し、複数agentが同時にコードを編集するwrite-heavy workflowには慎重になるよう勧めています。
worktreeの作り方はsurfaceごとに異なる
OpenAIのDeveloper commandsは、Codex CLI、IDE extension、ChatGPT desktop appの説明を同じページ内に含みます。/worktreeという文字だけを検索すると、どのsurfaceの機能かを誤認しやすいため、次のように分けます。
| Surface | worktreeの作成・利用方法 | 本記事での扱い |
|---|---|---|
| Codex CLI TUI | 現行のCLI built-in slash command一覧には/worktreeがない。git worktreeで作成し、対象directoryでcodexを起動する |
主経路 |
| Codex IDE extension | composerの/worktreeで、新しいGit worktree上にchatを作成できる |
代替経路 |
| ChatGPT desktop app | composerの/worktree、Worktree選択UI、LocalとのHandoffを利用できる |
managed worktree経路 |
CLIで明示的に管理する基本形は次です。
git worktree add -b feature/issue-123 \
"$HOME/worktrees/example-project/issue-123" \
origin/main
codex -C "$HOME/worktrees/example-project/issue-123"
IDE extensionやdesktop appのmanaged worktreeを使っても、この記事の原則は変わりません。
1 Goal
= 1 isolated checkout
= 1 write owner
= 1 integration path
ただし、ChatGPT desktop appのmanaged worktreeは既定でdetached HEADから始まる場合があります。branch化、Handoff、Localへの移動方法はdesktop app側のUIとWorktreesガイドに従います。
Step 1――Codex CLIでworktreeとbranchを分ける
元リポジトリ:
~/work/example-project
worktree root:
~/worktrees/example-project/
worktreeは元リポジトリの外側へ置きます。検索、build、backup、file watcherへ別checkoutが混入しにくくなります。
set -euo pipefail
REPO="$HOME/work/example-project"
WTROOT="$HOME/worktrees/example-project"
BASE="origin/main"
# 元checkoutは統合・確認専用とし、開始時に状態を確認する
git -C "$REPO" status --short --branch
git -C "$REPO" fetch origin
git -C "$REPO" worktree list
mkdir -p "$WTROOT"
# Goal A
git -C "$REPO" worktree add \
-b feature/issue-123 \
"$WTROOT/issue-123" \
"$BASE"
# Goal B
git -C "$REPO" worktree add \
-b feature/issue-124 \
"$WTROOT/issue-124" \
"$BASE"
確認:
git -C "$REPO" worktree list
git -C "$WTROOT/issue-123" status --short --branch
git -C "$WTROOT/issue-124" status --short --branch
既存branchを割り当てる場合は-bを付けません。
git -C "$REPO" worktree add \
"$WTROOT/issue-123" \
feature/issue-123
Codex CLIの起動directoryを固定する
Codex CLI TUIでは、作成済みworktreeへ移動して起動するか、グローバルオプション-C/--cdで作業directoryを明示します。
# 作成済みworktreeへ移動して起動
cd "$WTROOT/issue-123"
codex
# または作業directoryを明示
codex -C "$WTROOT/issue-123"
起動直後はCodex内外の両方で対応関係を確認します。
/status
pwd
git status --short --branch
git worktree list
chat ID -> worktree -> branch -> Issue -> PRの対応を記録してからGoalを設定します。CLIを複数起動しただけでは、正しいworktreeへ接続している保証になりません。
また、IDE extensionやdesktop appで/worktreeを使う場合も、生成されたworktree、branchまたはdetached HEAD、対象Issue、PR writerの対応を開始時に記録します。managed UIはcheckoutを作成しても、ファイルやPRの論理的な所有権までは決めません。
Step 2――Runtime namespaceを分ける
Goalごとに次を割り当てます。
Goal A
- APP_PORT=3101
- TEST_DB=example_issue_123
- COMPOSE_PROJECT_NAME=example_123
- CACHE_NAMESPACE=issue_123
- TMPDIR=/tmp/example-issue-123
Goal B
- APP_PORT=3102
- TEST_DB=example_issue_124
- COMPOSE_PROJECT_NAME=example_124
- CACHE_NAMESPACE=issue_124
- TMPDIR=/tmp/example-issue-124
秘密情報を含まない設定だけを.env.goalへ保存する例:
cat > "$WTROOT/issue-123/.env.goal" <<'ENV'
APP_PORT=3101
TEST_DB=example_issue_123
COMPOSE_PROJECT_NAME=example_123
CACHE_NAMESPACE=issue_123
TMPDIR=/tmp/example-issue-123
ENV
cat > "$WTROOT/issue-124/.env.goal" <<'ENV'
APP_PORT=3102
TEST_DB=example_issue_124
COMPOSE_PROJECT_NAME=example_124
CACHE_NAMESPACE=issue_124
TMPDIR=/tmp/example-issue-124
ENV
secretは複製しません。既存のsecret manager、credential helper、環境注入方法を使います。
DB migrationのwriterを1つにする
危険な構成:
worktree A -----+
+--> same database / same schema migration
worktree B -----+
対策:
- GoalごとにDBまたはschemaを分ける
- migrationを所有するGoalを1つにする
- migration PRを先に完了させる
- dependent Goalは新しいbaseから開始する
- 読み取り専用テストだけを並列化する
同じmigration fileを別worktreeで編集できても、論理的なsingle writerではありません。
Step 3――Goal specificationへ所有権を書く
Goal A:
# Objective
Issue #123を実装し、PR Aを人間がレビュー可能な状態にする。
# Exclusive Write Ownership
- src/auth/**
- tests/auth/**
- docs/authentication.mdの関連節
- branch feature/issue-123
- PR A
- Issue #123の進捗コメント
# Read-only Dependencies
- src/session/contracts.ts
- database/schema/**
# Must Not Modify
- src/billing/**
- database/migrations/**
- PR B
- Issue #124
- main branch
# Runtime Namespace
- APP_PORT=3101
- TEST_DB=example_issue_123
- COMPOSE_PROJECT_NAME=example_123
# Shared Contract
- session interface v2
- endpointとerror codeは変更しない
# Conflict Policy
共有契約の変更が必要なら、勝手に変更せずBlockedとして停止する。
# Integration Boundary
- mergeしない
- PR AをReady-stateまで進める
- exact headと検証証拠を報告する
Goal Bも同様に、所有範囲と禁止範囲を反転させます。
Exclusive Write Ownershipだけでなく、次も書くことが重要です。
Read-only Dependencies
Must Not Modify
Conflict Policy
Integration Boundary
Step 4――tmuxで別processとして起動する
set -euo pipefail
WTROOT="$HOME/worktrees/example-project"
for session in codex-123 codex-124; do
if tmux has-session -t "$session" 2>/dev/null; then
echo "tmux session already exists: $session" >&2
exit 1
fi
done
tmux new-session -d -s codex-123 \
"cd '$WTROOT/issue-123' && exec codex"
tmux new-session -d -s codex-124 \
"cd '$WTROOT/issue-124' && exec codex"
tmux list-sessions
Goal Aへ接続:
tmux attach -t codex-123
Codex CLI内:
/rename issue-123-auth
/status
/goal docs/goals/issue-123.mdを唯一の実行正本として処理する。
完了条件を証拠付きで満たすまで継続する。
定義済みのConflict PolicyまたはBlocked条件に達した場合だけ停止する。
Goal B:
tmux attach -t codex-124
/rename issue-124-billing
/status
/goal docs/goals/issue-124.mdを唯一の実行正本として処理する。
完了条件を証拠付きで満たすまで継続する。
定義済みのConflict PolicyまたはBlocked条件に達した場合だけ停止する。
Step 5――Goal、chat、worktreeの対応を記録する
開始時にmanifestを残します。
Goal ID: issue-123-auth
Chat name: issue-123-auth
Session ID: <codex session id>
Tmux session: codex-123
Worktree: ~/worktrees/example-project/issue-123
Branch: feature/issue-123
Base SHA: <origin/main sha>
PR: pending or URL
Runtime: port 3101 / db example_issue_123
Writer scope: src/auth/**, tests/auth/**, PR A
再起動後は、chatだけでなくworkspaceを照合します。
cd "$HOME/worktrees/example-project/issue-123"
codex resume --last
codex resume --lastは、原則として現在のworking directoryに対応する直近chatを選びます。別directoryのsessionまで候補に含める場合は--allを使います。
codex resume --all
session IDを記録している場合は、worktreeを-Cで明示すると対応を固定できます。
codex -C "$HOME/worktrees/example-project/issue-123" \
resume SESSION_ID
保存されたsession directoryと現在directoryが異なる場合、Codexはどちらを使うか確認します。必要ならtui.resume_cwdを設定できますが、明示した-Cが優先されます。
再開直後:
/status
/goal
pwd
git status --short --branch
git rev-parse HEAD
git worktree list
次が一致しない場合は変更を開始しません。
Goal objective
chat / session
worktree path
branch
PR
runtime namespace
状態を考慮して複数Goalを監視する
並列Goalは同時に同じ状態になるとは限りません。
Goal A Complete
Goal B Blocked
Goal C Active
Goal D BudgetLimited
これは異常ではありません。Goalごとに次の操作を分けます。
| Goal状態 | 並列運用上の処理 |
|---|---|
Active |
ownership違反とruntime衝突を監視 |
Paused |
resourceを解放し、再開条件を記録 |
Blocked |
外部依存を担当者へ割り当て。他Goalは継続可能 |
UsageLimited |
slotを一時停止し、head driftを再開時に確認 |
BudgetLimited |
checkpointを保存し、WIPとして残すか再分割 |
Complete |
integration queueへ移し、勝手にmergeしない |
Blocked Goalが他Goalを止める条件
次の場合だけ、dependent Goalもpauseします。
- Blocked Goalが共有契約を所有している
- Blocked Goalのschema migrationが前提
- Blocked GoalのPR headをbaseとしている
- 同じ外部resource lockを保持している
それ以外は、独立Goalを継続できます。
Blocked A does not imply Blocked B
ただし、Aの仕様未確定をBが勝手に補完してはいけません。
PRとreviewのsingle-writer設計
ファイルだけでなくGitHub objectのwriterも一意にします。
| Mutable object | Goal A | Goal B | Integration owner |
|---|---|---|---|
| branch A | read/write | no write | read |
| branch B | no write | read/write | read |
| PR A | create/update/reply | no write | final review |
| PR B | no write | create/update/reply | final review |
| Issue #123 | progress update | no write | close decision |
| Issue #124 | no write | progress update | close decision |
| main | no write | no write | merge only |
| release | no action | no action | human only |
同じPRへ複数Goalを書かせると、次が競合します。
- commitとpush
- PR description
- review reply
- thread resolve
- head SHAの認識
- Ready/Draft切替
- CI再実行の判断
1 PR -> 1 writer Goal
複数観点のレビューはsubagentまたはread-only Goalへ任せ、修正writerは1つにします。
共有契約が変わる場合の扱い
並列開始時には独立していても、途中で共通utilityやAPIを変更したくなることがあります。
Goal A -> shared/date.tsを変更したい
Goal B -> shared/date.tsを変更したい
対応順:
- 両Goalをpauseする必要があるか判断
- shared objectのownerを決める
- 共通変更を前提PRへ切り出す
- 先行PRのexact headを固定する
- dependent Goalのbaseを更新する
- 完全な検証を再実行する
別worktreeだからそのまま続行してよい、とはなりません。
契約を固定できる場合
Shared contract v1:
- endpoint
- request/response schema
- error codes
- configuration keys
- database table ownership
この契約を各Goalへread-only dependencyとして記録します。変更が必要になったらBlockedにし、契約変更の新Goalを作ります。
Integration Gateを分ける
各Goalをmergeまで進めず、Ready-stateで統合Queueへ集めます。
Goal A --> PR A --+
|
Goal B --> PR B --+--> Integration Gate --> main
|
Goal C --> PR C --+
Integration ownerの責務:
- 各PRのexact head確認
- required checks確認
- unresolved review確認
- baseとmerge-base確認
- PR間依存関係確認
- merge順序決定
- conflict解消方針決定
- 先行merge後の再検証
- main全体の回帰テスト
- release判断を人間に残す
read-onlyの統合Goal例:
/goal PR A、PR B、PR Cを読み取り中心で監査し、
依存関係、競合、merge順序、各merge後の再検証手順を確定する。
各PRのexact head、base、CI、review状態を確認する。
merge、branch更新、force-push、repository設定変更は行わない。
Serializable Integration
並列に完成したPRを一度に信頼せず、順序を付けて統合します。
1. PR Aのheadを再確認
2. PR Aをmerge
3. mainの新headを記録
4. PR Bを新mainへ追随
5. PR Bの全必須検証を再実行
6. PR Bをmerge
7. main全体の回帰検証
各PRが個別にgreenでも、組み合わせがgreenとは限りません。
Pass(PR A) AND Pass(PR B)
does not imply
Pass(PR A + PR B)
main driftを前提にする
Goalが長時間動く間にmainは変化します。
開始時:
Goal A base = M0
Goal B base = M0
Aを先にmergeすると:
main = M1
Goal B base = M0
Bの開始時検証はM1上での正しさを保証しません。Integration Gateで次を行います。
- merge-baseを確認
- 必要ならrebaseまたはmerge main
- exact headを更新
- required verificationを再実行
- reviewの有効性を再評価
長時間Goalでは、開始時の証拠と統合時の証拠を分けて記録します。
並列数は人間の統合能力で制限する
AI processを増やすだけなら、多数並列も可能です。しかし、実効スループットは次で制限されます。
Effective Throughput
=
min(
Agent Throughput,
Review Capacity,
CI Capacity,
Isolated Runtime Slots,
Integration Capacity
)
5つのGoalが同時にReadyになっても、人間が1日に1PRしか精査できなければ、未統合在庫が増えます。
運用上はWIP limitを置きます。
Max active Goals
<=
同時に責任を持って監視・レビュー・復旧できる数
小規模チームでは、最初は2 Goalから始めます。計測する値:
- Goal実行時間
- Blocked待ち時間
- Readyからreview開始までの時間
- review修正回数
- integration待ち時間
- main driftによる再検証時間
- merge後回帰率
agent utilizationではなく、end-to-end lead timeで増減を判断します。
起動用の最小スクリプト
1 Issue分のworktreeとtmux sessionを作る例です。
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $0 <issue-number> [base-ref]" >&2
exit 2
}
[[ $# -ge 1 ]] || usage
ISSUE="$1"
BASE="${2:-origin/main}"
REPO="${REPO:-$HOME/work/example-project}"
WTROOT="${WTROOT:-$HOME/worktrees/example-project}"
BRANCH="feature/issue-${ISSUE}"
WORKTREE="${WTROOT}/issue-${ISSUE}"
SESSION="codex-${ISSUE}"
[[ "$ISSUE" =~ ^[0-9]+$ ]] || {
echo "issue-number must be numeric: $ISSUE" >&2
exit 2
}
command -v git >/dev/null || {
echo "git is required" >&2
exit 1
}
command -v tmux >/dev/null || {
echo "tmux is required" >&2
exit 1
}
git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
echo "Not a Git worktree: $REPO" >&2
exit 1
}
[[ ! -e "$WORKTREE" ]] || {
echo "Worktree path already exists: $WORKTREE" >&2
exit 1
}
tmux has-session -t "$SESSION" 2>/dev/null && {
echo "tmux session already exists: $SESSION" >&2
exit 1
}
mkdir -p "$WTROOT"
git -C "$REPO" fetch origin
git -C "$REPO" worktree add -b "$BRANCH" "$WORKTREE" "$BASE"
tmux new-session -d -s "$SESSION" \
"cd '$WORKTREE' && exec codex"
cat <<REPORT
Created:
issue: $ISSUE
branch: $BRANCH
worktree: $WORKTREE
tmux: $SESSION
Next:
1. allocate runtime namespace
2. write Goal ownership specification
3. tmux attach -t $SESSION
4. verify /status and git status before /goal
REPORT
このスクリプトはport、DB、PR、ownershipを自動決定しません。そこを自動化すると誤った並列化を固定するため、開始前の設計項目として残しています。
状態確認用の最小コマンド
#!/usr/bin/env bash
set -euo pipefail
for session in codex-123 codex-124; do
echo "===== $session ====="
if tmux has-session -t "$session" 2>/dev/null; then
tmux capture-pane -pt "$session" -S -40
else
echo "not running"
fi
done
Codex CLI内では次を使います。
/goal
/status
/ps
/agent
/agentの表示名はバージョンにより変わる可能性があります。slash menuを確認してください。
完了後のcleanup
1. Goalとprocessを確認する
/goal
/ps
必要なら:
/goal pause
/stop
2. 未保存状態を確認する
WT="$HOME/worktrees/example-project/issue-123"
git -C "$WT" status --short --branch
git -C "$WT" log -1 --oneline
git -C "$WT" rev-parse HEAD
未commit、未push、未報告の変更がある状態でworktreeを削除しません。
3. tmux sessionを終了する
tmux kill-session -t codex-123
4. worktreeを削除する
REPO="$HOME/work/example-project"
WT="$HOME/worktrees/example-project/issue-123"
git -C "$REPO" worktree remove "$WT"
git -C "$REPO" worktree prune
git -C "$REPO" worktree list
branch削除は、PRのmerge、close、保存方針を確認してから別に行います。
典型的な失敗
別worktreeなら同じfileを変更してよい
ローカル上書きは避けられても、統合時のconflictと意味上の競合は残ります。
branchだけ分け、DBとportを共有する
Source Planeは分かれてもRuntime Planeが衝突します。
同じPRへ複数Goalを書かせる
commitだけでなく、description、review reply、thread resolution、head認識が競合します。
Blocked Goalが共有resourceを保持する
開発サーバー、DB lock、test environmentを解放し、他Goalの進行を妨げない状態へします。
すべてのGoalへmergeを許可する
依存関係と順序を判断する主体が消えます。各GoalはReady-stateで止め、Integration Gateへ集めます。
Goal数を増やしすぎる
監視、blocker解消、review、統合がボトルネックになります。WIP limitを置きます。
subagentを独立writerとして使う
同じ親Goalの内部で複数writerを作ると、結果集約が不安定になります。subagentは原則として調査と報告に寄せます。
運用チェックリスト
Goal isolation
[ ] 1 Issue = 1 Goal = 1 chatを維持している
[ ] chatとworktreeの対応を記録した
[ ] Goalごとにbranchとprocessが異なる
Source ownership
[ ] Exclusive Write Ownershipを定義した
[ ] Read-only Dependenciesを定義した
[ ] Must Not Modifyを定義した
[ ] 共有契約変更時のConflict Policyがある
Runtime isolation
[ ] portを分けた
[ ] DBまたはschemaを分けた
[ ] cache / tmp / container namespaceを分けた
[ ] secretを平文複製していない
Integration
[ ] 同じPR・Issueへのwriterが1つである
[ ] 各Goalはmergeしない
[ ] Integration ownerを決めた
[ ] merge順序を決めた
[ ] main drift後の再検証を定義した
[ ] 全体回帰テストを定義した
Capacity
[ ] 並列数がreview能力を超えていない
[ ] Blocked対応の担当がいる
[ ] CIとruntime slotに余裕がある
まとめ
複数のCodex Goalは、別chatで同時に実行できます。しかし、複数起動しただけでは安全な並列開発になりません。
Concurrency capability != Safe parallelism
運用型並列の基本単位は次です。
1 Issue
= 1 Goal
= 1 chat
= 1 process
= 1 branch
= 1 worktree
= 1 PR writer
さらに4つのPlaneを分離します。
Control
Source
Runtime
Integration
そして、すべての可変objectへsingle-writerを割り当て、最後に1つのIntegration Gateで順序付きに統合します。
Safe Goal Parallelism
=
Isolated Goal State
+ Isolated Mutable State
+ Single Writer
+ Serializable Integration
worktreeとtmuxは、この設計を実装する手段です。中心にあるのはツールではなく、誰がどの状態を書き、誰が最終統合を判断するかという所有権設計です。
関連記事
- Codex CLI /goalの6状態を実例で理解する――Blockedからの再開、BudgetLimited、Completeの違い
- AIコーディングエージェントの自律実行を状態機械として設計する――完了述語・Safety/Liveness・責任境界