# TODO — design review findings

設計レビュー（2026-06）で挙がった改善点。重要度順。`file:line` は指摘時点の目安。

## 🔴 Critical — 主張と実装の乖離 / 安全性

- [x] **C1. 「git = memory」が実装に存在しない** — README/manual が "git = the loop's
      memory" と謳うが `git init/add/commit` はコードに皆無。
      → *対応済み: 主張を「memory is the files in the data dir」に撤回（#feat/remove-looop-run）。*
      将来 git 履歴（各tick=1コミット、ロールバック、`looop diff`）を入れるなら別タスクで再検討。
- [x] **C3. single-writer 不変条件を `looop run` が破る** — pulse 稼働中でも拒否せず
      並走し journal/goals/PLAYBOOK をレース。
      → *対応済み: `looop run <goal>` を全廃（#feat/remove-looop-run）。*
- [ ] **C2. RULE 1「1 tick = 1 move」が harness で強制されていない** — tick runner は
      `--dangerously-skip-permissions` でデータディレクトリ内・フルシェル権限。1 move も
      irreversible 承認もプロンプトの honor system のみ。
      `src/config.rs` (DEFAULT_CONFIG), `src/runner.rs` (run_streamed)
      - [ ] tick をデフォルトで box / 制限環境で走らせる選択肢
      - [ ] あるいは deny-list ラッパ（`rm -rf` / `git push` / `gh pr merge` / `kubectl delete` 等）
      - [ ] ドキュメントを「強制」ではなく「規律」と正直に表記

## 🟠 High — コスト暴走 / 堅牢性

- [ ] **H1. 失敗 tick にバックオフがない** — `.last-tick-hash` は成功時のみ書込のため、
      毎回失敗する tick が cadence ごとに無限リトライ＆無限課金。`src/tick.rs`
      - [ ] 連続失敗カウンタ + 指数バックオフ、または失敗時もhash書込 + 限定リトライ
- [ ] **H2. 予算上限 / サーキットブレーカがない** — `looop cost` で可視化のみ。
      config に `max_daily_usd` を追加し超過で tick skip + flag。`src/cost.rs`, `src/run.rs`
- [ ] **H3. claude ランナーの tick コストが計上されない** — pi は `| looop _fmt` を通すが
      claude tick は通さないため常にゼロ行。runner 間で会計挙動が非対称。`src/config.rs`
      - [ ] claude 側にも会計シームを足す、または挙動差をドキュメント明記
- [ ] **H4. `looop tick` が snapshots を共有してレースする** — `cmd_run_goal` は private temp を
      使っていたが `tick()`/`cmd_tick` は共有 `snapshots/` を wipe→再生成。二重起動 / cron 重複で
      互いの snapshots を消し合う。ロックも未取得。`src/tick.rs`
      - [ ] private snapshot dir 方式に統一、または `looop tick` でもロック取得

## 🟡 Medium — 整合性 / 設計

- [ ] **M1. 環境変数の名前空間汚染** — `export_env` が裸の `CONFIG` / `CLAIMS_DIR` /
      `REPORTS_DIR` / `COST_LEDGER` を全子プロセスに export。特に `CONFIG` は衝突の温床。
      `LOOOP_` プレフィックスへ統一（参照側の sensor/CONTRACT も移行）。`src/main.rs`
- [ ] **M2. `setup` ブートストラップが死んだ corpse で詰まる** — starter PLAYBOOK の
      "if a session setup already exists, do nothing" が Exited/Killed の corpse も
      「exists」と解釈し最大 retention(3d) 停止しうる。seed を "if a **live** setup session"
      に厳密化。`src/seed/PLAYBOOK.md`
- [ ] **M3. PLAYBOOK 編集は wake するが sensor 編集は wake しない（非対称）** —
      `world_hash` は sensors/*.sh をハッシュしない。意図的だが挙動差をドキュメント明記。
      `src/gate.rs`
- [ ] **M4. 判断は弱モデル・実行は強モデル** — tick=sonnet/low、worker=opus/medium。
      全体を左右する「どの一手か」を一番弱いモデルが下す配分の再考。`src/config.rs`
- [ ] **M5. config がプロファイル非スコープ** — `LOOOP_DATA_DIR` で分離してもconfigは共有。
      プロファイル別 runner/model には `LOOOP_CONFIG` 上書きが必要。最低限ドキュメント注記。
      `src/paths.rs`

## 🟢 Feature / UX

- [ ] **F1. `looop journal [--tail N]`** — 意思決定ログを一級コマンドで読む（今は cat か
      `log pulse`=イベント列のみ）。
- [ ] **F2. `looop tick --dry-run`** — プロンプトを組み立てて表示するだけで LLM を呼ばない
      （課金なしでプロンプト調整）。
- [ ] **F3. `max_daily_usd` サーキットブレーカ** — H2 と統合。
- [ ] **F4. `looop doctor`** — runner が PATH にあるか / config が parse できるか /
      データディレクトリ書込可か を診断。
- [ ] **F5. オンボーディング — runner 自動検出** — default が `pi` 固定 + モデル名ハードコード。
      claude しか無いユーザは config 編集必須。初回に検出。
