deterministic-task-protocol リポから miyabi-cli-standalone に統合: - docs/dtp/: PLAYBOOK, PLAN, UML, GIT-RULES, Codex レビュー 3件 - autorun/: Phase 0-8 の TASKS/ASSIGNMENT/GATE + INDEX/HANDOFF/ROLLBACK - project_memory/tasks.json: 全9 Phase の DAG SSOT - skills/: polaris-ops, rust-llm-pitfalls - .codex/instructions.md: Codex 設定 実装は miyabi-core に gate.rs, lock.rs, protocol.rs, store.rs を追加する方針。 既存の dag.rs, github.rs, approval.rs 等は変更不要。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
12 KiB
12 KiB
Review: Deterministic Task Execution Protocol
Findings
1. High: 計画は二層SSOTをまだ完全には実装しておらず、tasks.json を「事実の正」に昇格させすぎています
- 計画は「JSON の状態遷移だけが事実」と置いていますが、ビジョン文書と仕様文書はタスク状態のファクトSSOTを GitHub Issue / Projects に置いています。ここが正面衝突しています。
- 現状の設計だと
tasks.jsonは execution ledger と gate engine であるべきなのに、完了判定の authority まで持っています。二層SSOTを守るなら、- GitHub: 受入・完了・人間承認の正
tasks.json: ローカル実行状態、ロック、依存、再試行、監査 に役割を分ける必要があります。
doneの必要条件は「tasks.jsonにmergeCommitがあること」ではなく、「GitHub 上で受理された完了証跡を同期済みであること」にすべきです。tasks.jsonはそのミラーであるべきです。
2. High: GitHub 障害時の劣化モードが未定義で、決定性より停止性を失う可能性があります
- 計画は GitHub を強いゲートにしていますが、「GitHub API が落ちた」「レート制限」「ネットワーク断」のときに何が許可され、何が禁止されるかが定義されていません。
- Plan merge/close gating:
snuggly-bouncing-turtle.md - Current sync has no degraded mode, retry journal, or outage classification:
bidirectional-sync.tsbidirectional-sync.ts
- Plan merge/close gating:
- このままだと障害時に次の2択になります。
doneを絶対に付けられず運用停止- 人が裏口で進めて決定性崩壊
- 必要なのは「安全に止まる」中間状態です。少なくとも以下が必要です。
awaiting_github_syncまたはexternally_completed_unverified- GitHub API 障害と論理矛盾を分ける error class
- pull/push の retry queue と backoff
- 最後に確認できた GitHub 証跡の timestamp
- 明示的な human override と理由記録
3. High: 双方向同期の計画が危険で、Issue close をそのまま done に写像すると誤完了になります
- 計画は「GitHub で Closed なのにローカルで implementing → pull で done に更新」としていますが、Issue は PR merge 以外の理由でも閉じられます。これをそのまま
doneとみなすのは強すぎます。 - 逆方向の「ローカル done なのに Issue Open → blocked に巻き戻し」も不自然です。現行状態機械では
done -> blockedは無効で、許されるのはdone -> pendingだけです。- State machine:
task-state-machine.ts - Plan rollback idea:
snuggly-bouncing-turtle.md
- State machine:
- しかも既存
BidirectionalSync.sync()は pull 結果をローカル task/store に適用しておらず、衝突を集めるだけです。計画の「pull で done に更新」は、既存の延長では実現されません。 - 推奨は one-way authority を明確化することです。
- GitHub -> ローカル: 受理・クローズ・PR merge の事実を pull
- ローカル -> GitHub: 提案された状態を push
- ただし
doneは PR merge 証跡つき close のときだけ確定
4. Medium: merge commit hash の取得方法と検証経路が仕様化されていません
- 計画は
recordMerge(taskId, mergeCommit)を置いていますが、その hash をどこから、どうやって、何と突き合わせて取得するかが未定義です。 - 現状の sync 実装には PR 取得や merge SHA 取得の処理がありません。Issue/Label/Project しか見ていません。
- 取得方法は次のように固定するのがよいです。
recordPR()時にprNumberを必須保存する- merge 検証時は Issue API ではなく PR API を見る
- 第一候補: REST
GET /repos/{owner}/{repo}/pulls/{pull_number}のmerge_commit_sha - 代替: GraphQL
pullRequest.mergeCommit.oid - 追加で
mergedAt,merged,state,baseRefOid,headRefOidを保存する
- 重要なのは「Issue close から merge hash を推測しない」ことです。
prNumberがないタスクは merge-based completion を確定できません。
5. Medium: 正当な例外経路が不足しており、現実運用で手動回避が増えそうです
- 仕様は HIGH/CRITICAL に human approval を要求していますが、実際の例外経路が定義されていません。
- 必要なのは「抜け道」ではなく「監査可能な escape hatch」です。例えば:
- GitHub 障害時に一時的に
reviewingのまま凍結する - 外部で既に merge/close されたタスクを
reconcileで取り込む - ドキュメント作業や運用作業のように PR を伴わない legitimate completion を
completionMode=manual|github-pr|external-opで区別する - 強制 unlock / reopen / superseded / abandoned の理由欄を必須化する
- GitHub 障害時に一時的に
- 今の計画はコード変更中心の happy path には強いですが、実運用で必ず出る「PRなしで正当に終わる仕事」「外部作業」「GitHub障害中の継続作業」を吸収できません。
6. Medium: 現行同期実装の前提を踏まえると、Phase 6 は「強化」ではなく再設計に近いです
- 現在の
BidirectionalSyncは conflict strategy もlocal-winsがデフォルトで、newest-winsも未実装同然です。 - さらに current sync は
ManagedTaskを mutate せず、store 連携もありません。 - そのため deterministic sync を本当にやるなら、必要なのは conflict strategy 追加だけではなく、
- state reconciliation engine
- persistent sync cursor / version
- per-task sync status
- webhook event idempotency
- API failure taxonomy の実装です。
Direct Answers
What if GitHub API is down?
- 今の計画だけでは未対応です。
- 推奨は fail-closed ですが、完全停止ではなく
awaiting_github_syncへ遷移させることです。 - 実行中の作業は続けてもよいですが、
doneと lock release の一部は「GitHub未検証」のまま分離保存すべきです。 - 監査上は
completionRequestedAt,githubVerifiedAt,githubSyncErrorを残すべきです。
One-way push vs bidirectional?
- 完全双方向より「authority-aware bidirectional」が適切です。
- Push はローカルの提案状態を GitHub に反映するために使う。
- Pull は GitHub の受理状態をローカルへ反映するために使う。
- ただし authority は対称ではありません。
done/acceptedは GitHub 優先、実行中ロックや DAG はローカル優先です。 - 要するに transport は bidirectional、SSOT は asymmetric にすべきです。
How to get mergeCommit hash?
- Issue ではなく PR から取得します。
recordPR()時にprNumberを保存し、reconcile 時にその PR を取得します。- 実装候補:
- REST:
pulls.get(...).data.merge_commit_sha - GraphQL:
pullRequest.mergeCommit.oid
- REST:
mergeCommitだけでなくmerged,mergedAt,headSha,baseSha,mergeMethodも一緒に保持すると検証が安定します。
Does the plan fully implement two-layer SSOT?
- いいえ、未完成です。
- 現状は
tasks.jsonを事実の正に寄せすぎており、Vision/Spec が要求する「GitHub=ファクトSSOT、repo/tasks.json=文脈・実行ミラー」という分離が崩れています。
Escape hatches for legitimate work?
- まだ不十分です。
- 少なくとも
manual-completion,external-completion,awaiting-github-sync,force-unlock-with-reason,reconcile-from-githubは必要です。 - どれも「自由に bypass」ではなく、理由・操作者・時刻・承認者を残すべきです。
Recommended Changes
tasks.jsonの位置づけを「execution ledger / gate cache」に下げ、ファクトSSOTは GitHub のまま明記する。doneを単純 state ではなくaccepted=trueを含む受理イベントで確定させる。- sync を再設計し、
push proposalとpull authoritative factsを分ける。 Issue closed => doneを廃止し、PR merged + issue closed/linked acceptedを確定条件にする。- GitHub 障害時の
awaiting_github_sync系ステートと retry journal を追加する。 - manual/external completion の監査可能な escape hatch を先に仕様化する。
Overall
計画の方向性自体はかなり良いです。特に DAG、ロック、ゲートを tasks.json に集約して LLM の自然言語を無力化する発想は強いです。ただし GitHub Sync と end-to-end deterministic guarantee の観点では、いまの文面は「ローカル deterministic engine」は強い一方で、「GitHub を authority とした分散整合」はまだ甘いです。
決定的にしたいなら、tasks.json と GitHub のどちらも同じように信じるのではなく、「何の事実はどちらが authoritative か」を状態ごとに切り分ける必要があります。