Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions docs/local-llm-offload-analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> **位置づけ**: 本ファイルは「残作業の **次に何をするか** だけ」を持つ実行計画。完了済みの分析・実装・dogfood 計測・retrospective は [local-llm-offload-history.md](local-llm-offload-history.md) に切り出した。
>
> **状態**: 試験運用 (Phase a 完了 = PR #130 land / Phase b 完了 = conditional GO 2026-05-08, PR #131 / Phase c MVP 完了 = PR #132 land 2026-05-08 / **Phase c+ Bundle i 完了 = PR #135 land 2026-05-09 / §8.D 完了 = PR #136 land 2026-05-09 (num_ctx 8192、agreement 86.7% / verdict GO)**、Phase d 着手前提条件は全て充足済、kickoff 待機)。
> **状態**: 試験運用 (Phase a 完了 = PR #130 land / Phase b 完了 = conditional GO 2026-05-08, PR #131 / Phase c MVP 完了 = PR #132 land 2026-05-08 / **Phase c+ Bundle i 完了 = PR #135 land 2026-05-09 / §8.D 完了 = PR #136 land 2026-05-09 (num_ctx 8192、agreement 86.7% / verdict GO) / Phase d kickoff prep 完了 = 2026-05-10 ([docs/local-llm-offload-phase-d-guide.md](local-llm-offload-phase-d-guide.md) 参照)**、実 dogfood (3-5 PR、long-running) 待機)。
>
> **引退条件**: 以下のいずれかで本ファイルを削除する (docs-governance.md retirement workflow 準拠)。`local-llm-offload-history.md` も同タイミングで判断する。
> - 残作業 (§8.D / §8.E / §8.F, §1 Phase b/c/d) が **すべて land または却下** された場合 → permanent value (採用された設計判断、却下理由) を ADR-038 に migrate して両ファイルを削除
Expand Down Expand Up @@ -197,8 +197,23 @@ cargo test -p cli-finding-classifier --test lint_screen_evals -- \

#### 次に何をするか (優先度順)

1. **Phase d kickoff prep** (session 内で完結可能): `push-runner-config.toml [lint_screen] enabled = true` への切替判断、metrics 計測スクリプト整備、dogfood 運用ガイド作成、過去 dogfood 阻害要因 3 種 (findings ゼロ / review body 抽出漏れ / rate-limit) への対処設計。**前提条件 (a)-(d) は PR #135 + PR #136 で全充足済**
2. **Phase d 実 dogfood** (long-running、数日〜数週間): kickoff 後の通常 PR 3-5 件で lint_screen の token 削減 / latency / 大規模 diff JSON 完全性を実観測。`feedback_dogfood_evals_two_phase` (evals → dogfood の 2 段階) の dogfood 段階に該当
1. **Phase d kickoff prep** ✅ **完了 (2026-05-10)**: 運用ガイド = [docs/local-llm-offload-phase-d-guide.md](local-llm-offload-phase-d-guide.md) として独立 doc 化。決定事項: (a) **session-only opt-in** (config commit せず session 内のみ enable / kill-switch 即可)、(b) metrics = **latency p50/p95 + fallback rate + Claude session input token 削減効果 (質的傾向)**、(c) kill-switch = **fallback rate > 50% で停止**。過去 dogfood の 3 obstacles (findings ゼロ / review body 抽出漏れ / rate-limit) は classifier 専用で lint_screen は CR 非依存のため scope 外と確定。**前提条件 (a)-(d) は PR #135 + PR #136 で全充足済**
2. **Phase d 実 dogfood** (long-running、数日〜数週間): kickoff 後の通常 PR 5 件で lint_screen の token 削減 / latency / 大規模 diff JSON 完全性を実観測。`feedback_dogfood_evals_two_phase` (evals → dogfood の 2 段階) の dogfood 段階に該当。具体運用は [docs/local-llm-offload-phase-d-guide.md](local-llm-offload-phase-d-guide.md) §1-3 に従う

**dogfood 対象 PR roster** (`docs/todo-summary.md` から選定、size ramp-up 順序):

| Order | 構成 | Effort | Diff Profile | dogfood signal |
|---|---|---|---|---|
| P-1 | Bundle h (順位 89+90) + Bundle g-2 (順位 87+88) | M | global rules markdown 4 file | docs-only で `informational` 期待、false-positive 検証 baseline |
| P-2 | Bundle j-1 (順位 94 — `../docs/` 相対パス detect lint rule) | S | TOML config + 軽い Rust regex | 小規模 mixed diff |
| P-3 | Bundle g-1 (順位 85+86 — cli-pr-monitor verdict guard + transition test) | M | Rust impl + Rust test | 中規模 Rust、`auto_fix` 期待 |
| P-4 | Bundle d (順位 68 — no-ephemeral-todo-reference self-exclusion test) | S | Rust test only | 狭 scope test diff |
| P-5 | Bundle c-1 (順位 63+64+67 — cli-merge-pipeline Drop guard + reaper + ADR) | L | Rust impl ×2 + ADR | 大規模 Rust (PR #132 868 行 stress 再現候補) |

**設計判断のポイント**:
- **Effort 分布 M→S→M→S→L**: 前半小規模 / 後半大規模で kill-switch (fallback > 50%) signal の質を切り分け可能 (小規模で発動 = 設計 issue / 大規模で発動 = num_ctx 再到達)
- **Bundle h + g-2 を 1 PR に統合**: 共通テーマ「global rules consolidation (process/lifecycle codification)」、reviewer も「rule 追加 4 件まとめ」として認識しやすい
- **Bundle f 除外**: `(defer)` 表記 = systemic 性未確認のため Phase d で push 圧力を加えない
3. **Phase d 結果集約**: 計測結果から §8.E 採用 / §8.F 着手 / kill-switch を判定。dogfood 完了後

優先度低の独立 task (Phase d を block しない):
Expand Down
114 changes: 114 additions & 0 deletions docs/local-llm-offload-phase-d-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Phase d (lint_screen 実環境 dogfood) 運用ガイド

> **位置づけ**: ADR-038 試験運用配下の §8.E (lint screen facet) を 3-5 通常 PR で dogfood し、**本採用 / 却下** を判定するための operational guide。
>
> **対象**: `cli-push-runner` の `lint_screen` stage (PR #132 / #135 / #136 で land 済)。`cli-finding-classifier` の dogfood (`local-llm-offload-history.md` §A-2) とは **別 feature**、CR 非依存。
>
> **状態**: 試験運用 (kickoff prep land 後、実 dogfood は次回以降の通常 PR で実施)。
>
> **引退条件**: Phase d 完了 (3-5 PR で実観測) → §8.E 採否判定 → ADR-038 を「採用」or「却下」に昇格 → 本ファイル削除 + analysis.md / history.md も同タイミングで再評価。

## 1. Setup (session-only opt-in)

`push-runner-config.toml` は default OFF のまま。dogfood する session で **手動で `enabled = true` に切り替え (commit しない)**。

```bash
# 1. Ollama 起動確認
curl -s http://localhost:11434/api/tags | jq '.models | map({name, size})'
# 期待: mistral:7b が含まれる

# 2. config 切替 (commit しない、session 内のみ)
# push-runner-config.toml の [lint_screen] section で
# enabled = false → enabled = true
# 編集後、jj diff で確認 (push 時に意図せず commit に乗らないよう注意)

# 3. cli-finding-classifier.exe deploy 確認
ls -la .claude/cli-finding-classifier.exe
# 期待: ファイル存在、~2.2MB

# 4. dogfood 完了後、必ず enabled = false に戻す (revert)
jj diff push-runner-config.toml # 確認
# 編集して enabled = false に戻す、または jj restore push-runner-config.toml
```

**意義**: kill-switch が即可能、他人 / 派生プロジェクトの push に影響なし、設計 (default OFF, 試験運用 opt-in) との整合性。

## 2. 計測 (各 dogfood PR で実施)

ユーザー判断 (Phase d kickoff、2026-05-10) で以下 3 metrics を採用:

### 2-1. lint_screen latency p50/p95

```bash
# push 後、push-runner log から抽出
grep "lint-screen.*出力:" .takt/runs/<latest>/logs/*.jsonl
# 期待 format: "出力: .takt/lint-screen-report.md (Ns)"
```

3-5 PR 集計後に p50 / p95 を算出。**baseline**: Bundle i evals dogfood で p50=4.5s / p95=8.4s (eval fixtures、num_ctx=8192)。

### 2-2. fallback rate

```bash
# .takt/lint-screen-report.md の冒頭に "fallback_reason" が記録されていれば fallback 経路
grep -l "fallback_reason" .takt/lint-screen-report.md
# 5 PR 中の fallback 件数を数える
```

**threshold**: kill-switch = fallback > 50% (3 / 5 PR で fallback 発生で停止)。

### 2-3. Claude session input token 削減効果

**現状実装 caveat**: lint_screen は `.takt/lint-screen-report.md` 出力のみで、Claude には自動転送されない。token 削減効果を計測するには以下のいずれか:

- (a) **手動転送**: dogfood 中に Claude が `.takt/lint-screen-report.md` を Read して advisory として参照する (実 dogfood で運用試行)
- (b) **将来実装**: takt facet `review-simplicity.md` instruction で advisory 読み込みを自動化 (PR #132 で部分的に実装済、Phase d 効果次第で深化判断)
- (c) **計測のみ**: Claude session の `/cost` 出力を dogfood 前後で記録 (lint_screen 利用 vs 非利用で比較、ただし他要因の混入あり)

Phase d 期間中は **(a) 手動転送 + (c) /cost 計測** の組合せで **質的傾向**を観察。定量化は (b) 実装後に再計測。

## 3. Kill-switch criteria (fallback rate > 50%)

3 / 5 PR (= 60%) で fallback が発生したら **即停止**:

1. config を `enabled = false` に戻す (jj restore push-runner-config.toml で確実に revert)
2. fallback 原因を `.takt/lint-screen-report.md` の `fallback_reason` から特定:
- `ollama error: ...` → Ollama 側問題 (down / model unloaded / 通信)
- `JSON parse error: missing field ...` → mistral 出力崩壊 (順位 98 = num_ctx overflow detection で診断強化予定)
- `diff over limit` → `max_diff_lines` 設定不足 (config tweak で再 dogfood 可)
- `timeout` → `timeout_secs` 設定不足 (latency 増を許容するか re-tune)
3. ADR-038 §試験運用→採用条件の **未達** として retrospective を `local-llm-offload-history.md` に追記
4. §8.D 改善 (prompt v2) または別技術 (llama2:13b 等) への switch 判断

## 4. 過去 dogfood 阻害要因の scope 再確認

**`local-llm-offload-history.md` §11.2 の 3 obstacles は本 Phase d では scope 外**:

| 旧 obstacle | 旧 scope (classifier) | 本 Phase d (lint_screen) との関係 |
|---|---|---|
| findings ゼロ | CR が APPROVE で classifier 入力なし | ❌ scope 外: lint_screen は CR 非依存、`jj diff` を直接読む |
| review body 抽出漏れ | check-ci-coderabbit の parser scope 限界 | ❌ scope 外: lint_screen は CR review を読まない |
| CR rate-limit | per-hour commit quota で review blocked | ❌ scope 外: lint_screen は pre-push、CR より前に走る |

代わりに **lint_screen 固有の懸念**:

- **Ollama 起動状態**: dogfood session 開始時に確認 (Setup §1)
- **mistral:7b 出力安定性**: num_ctx 8192 で agreement 86.7% (eval fixtures)、実 PR diff で再計測する (本 Phase d の主目的)
- **push pipeline UX impact**: latency p95 監視 (現状 ~8s で許容範囲)

## 5. Phase d 完了 → 結果集約 → §8.E 採否判定

3-5 PR 完了後:

1. metrics 集計 (latency / fallback / token 質的傾向) を `local-llm-offload-history.md` の dogfood 計測ログ (§A-2 と同形式) に追記
2. ADR-038 §試験運用→採用条件 (5 PR 以上 / token 削減 / classification 妥当性) との突合
3. 採用判定:
- **採用**: ADR-038 を「採用」に昇格 + 派生プロジェクト deploy 計画 + 本ガイド削除
- **却下**: ADR-038 を「却下」に更新 + lint_screen stage 物理削除 PR + 本ガイド削除
- **継続**: 課題 ID 化 + 改善 task として todo 系列に追加 + 次 dogfood 計画策定

## 関連リンク

- [docs/local-llm-offload-analysis.md](local-llm-offload-analysis.md) — Phase d を含む実行計画 (ephemeral)
- [docs/local-llm-offload-history.md](local-llm-offload-history.md) — §A-2 (classifier dogfood retrospective) / §11 (evals 形式への切替)
- [ADR-038](adr/adr-038-local-llm-finding-classification.md) — 提案 1 / 2 / 3 の元設計、本採用判定の base
1 change: 1 addition & 0 deletions docs/todo-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
| 95 | 🔧 Tier 2 | **`docs/todo*.md` preamble file count 自動照合スクリプト (PR #133 T2-#4 採用) ★ Bundle j** | todo6.md | S | なし (PR #133 で todo6.md「六つ」/ todo7.md「七つ」が実 8 ファイルと乖離した実例。todo*.md 分割が今後も繰り返す pattern (todo3 → 4 → 5 → 6 → 7) のため CI 層で自動検証) |
| 96 | 🔧 Tier 2 | **Markdown cross-reference validator CI step (PR #133 T2-#3 採用) ★ Bundle j** | todo6.md | M | 順位 10 (ADR-032 PR-broken-link) と方向性が近接、fold-in 検討の余地あり。順位 94 (regex 規約) + 順位 95 (count 照合) と組み合わせて docs/ 整合性の多層検証 |
| 97 | 🔧 Tier 2 | **`with_num_ctx(X)` override 値 serialization 検証テスト (PR #136 T2-#1 採用)** | todo6.md | S | なし (PR #136 で追加した builder method の wiring を mockito で seal、Phase d で num_ctx tweak する局面の silent degrade 防止、CodeRabbit が見逃した test gap を post-merge-feedback agent が独立発見) |
| 98 | 🚀 Tier 1 | **`num_ctx` overflow detection — JSON parse error 検知時の context window 診断ログ (PR #137 T1-#1 採用)** | todo6.md | M | なし (PR #136 で誤診 pivot を発生させた blind spot を decisive に塞ぐ runtime hint、`lib-ollama-client` の response validation 層に warn log 追加、`prompt_eval_count` ≈ `num_ctx` cap で truncation を即診断) |

**戦略**: Tier 1 を 2〜3 セッションで片付け → Tier 2 で ADR-032 の前提 + rate-limit + convergence cost 削減を進める → Tier 3 で ADR-032 を land + ドキュメント整備。Tier 4-5 は cleanup / 外部展開で daily efficiency への直接効果は小さい。

Expand Down
54 changes: 54 additions & 0 deletions docs/todo6.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,57 @@ config.rs + push-runner-config.toml + review-simplicity.md + ADR で family_tag
#### 詰まっている箇所

なし。Effort S / 既存 test の duplicate 風で実装容易。

---

### `num_ctx` overflow detection — JSON parse error 検知時の context window 診断ログ (PR #137 T1-#1 採用)

> **動機**: PR #136 セッションで「mistral:7b の JSON schema breakdown」を観測した際、Claude は当初「prompt 設計の問題」と誤診し `§8.D v4 prompt 改訂ループ` という名前の誤った means に向かいかけた (実 root cause は `num_ctx` default 4096 超過)。advisor の指摘 + raw Ollama output dump で軌道修正されたが、**runtime layer に診断 hint が出ていれば pivot 時間を短縮できる** ことが判明。`lib-ollama-client` の response validation 層で JSON parse error 検知時に `num_ctx` / `prompt_eval_count` / response length を warn log で auto-emit することで、将来の同型事故 (LLM dogfood 全般で systemic に再発し得る) を decisive に診断できる。
>
> **本タスクの位置づけ**: PR #137 post-merge-feedback Tier 1 #1 採用 (Severity Medium / Frequency Low / Effort M / Adoption Risk: 派生プロジェクト deploy コストのみ、低)。ADR-038 試験運用配下の infrastructure 強化、Phase d で num_ctx tweak する局面に入る前の安全網としても機能。
>
> **参照**: `.claude/feedback-reports/137.md` Tier 1 #1、PR #136 で `__dump_raw_ollama.sh` で確認した `prompt_eval_count: 4096` 上限到達 (現在は scratch ファイル削除済、`docs/local-llm-offload-history.md` に経緯記録)、`src/lib-ollama-client/src/lib.rs` の `generate_raw_json` / `OllamaResponse` 構造体
>
> **実行優先度**: 🚀 **Tier 1** — Effort M。Phase d kickoff 前か実 dogfood 中に整備するのが理想 (dogfood で実際に context overflow を起こした PR があれば即診断できる layer になる)。

#### 設計決定 (案)

- **配置先**: `src/lib-ollama-client/src/lib.rs` の `generate_json::<T>` ヘルパー (型付き parse 失敗時) または raw response 検証層
- **emit 条件 (案)**:
- **A (主軸)**: `serde_json::from_str` が `missing field` 系 error を返した場合 → `prompt_eval_count` が response の `eval_count` field と比較して context cap に近接していれば warn log
- **B (補助)**: response length が threshold (例: 100 chars) 未満で truncate を疑える場合
- **C (簡易)**: 常に `prompt_eval_count` / `eval_count` を debug log で emit (low-noise、auto OFF default)
- **emit 内容 (案)**:
```text
[lib-ollama-client] WARN: Ollama JSON output may be truncated.
parse_error: <serde error message>
prompt_eval_count: <N> (vs num_ctx: <M>)
eval_count: <K>, response_length: <L> chars
hint: 大規模 prompt は num_ctx を増やすことで解決可能 (with_num_ctx で override)。
```
- **fallback 経路への副作用**: 既存 fallback (block しない、`human_review` + `fallback_reason` を埋める) は維持、log は副次的な diagnostic 出力のみ

#### 作業計画

- [ ] `OllamaResponse` 構造体に `eval_count` / `prompt_eval_count` フィールドを追加 (現状 `response` / `error` のみ deserialize)
- [ ] `generate_json::<T>` ヘルパー (型付き parse) で error 時に上記情報を warn log emit (`log::warn!` または `eprintln!`)
- [ ] threshold ベースの判定ロジック (主軸 A) を実装、補助 B はオプション
- [ ] tests:
- `warn_log_emitted_on_truncated_response_when_prompt_eval_count_high` (mockito + log capture)
- `no_warn_emitted_for_parse_errors_unrelated_to_truncation` (e.g., format-违反 JSON)
- [ ] PR #136 で観測した eval13/15 fixture の `prompt_eval_count: 4096` 状況を dogfood で再現し、log が emit されることを確認
- [ ] cli-finding-classifier 経由でも log が表面化することを smoke 確認 (push-runner step ログに乗るか)
- [ ] 派生プロジェクト (techbook-ledger / auto-review-fix-vc) 向け deploy 判断 (lib-ollama-client は本リポ専用なら deploy 不要、共有なら別途配布計画)
- [ ] 本 todo6.md エントリを削除

#### 完了基準

- JSON parse error + context cap 近接の併発時に warn log が emit される
- 既存 fallback 経路 (block しない、graceful degradation) を破壊しない
- LLM dogfood セッションで「context window 起因か prompt 起因か」を log だけで切り分けられる構造
- 単体テストで diagnostic log の emit 条件 + non-emit 条件の両方を seal

#### 詰まっている箇所

- **派生プロジェクト deploy 戦略**: `lib-ollama-client` が本リポ専用なら deploy なし、共有 crate 化するなら別 repo への copy / git submodule / cargo registry の判断が必要。Phase d 着手判定と合わせて検討
- **log destination**: `eprintln!` (cli 用途で十分) vs `tracing` / `log` crate 統合 (既存の cli-* との一貫性)。本 lib は現状 ureq + serde_json のみで logging crate なし、初期は `eprintln!` で warn 接頭辞付け、将来必要なら crate 統合という段階導入が自然