Skip to content

feat: Vibe Localにコンテキストウィンドウサイズ(--context-window)の設定を追加 #374

@Kewton

Description

@Kewton

Note: このIssueは 2026-02-28 にレビュー結果(Stage 7: 影響範囲レビュー2回目)を反映して更新されました。
詳細: dev-reports/issue/374/issue-review/

背景

Issue #368 で実装されたVibe Local統合を拡張する。

Vibe Local選択時、現在はOllamaのモデル(-m オプション)のみ指定可能だが、--context-window によるコンテキスト長の指定もサポートしたい。

コンテキストウィンドウサイズはモデルの応答品質やメモリ使用量に直結する重要なパラメータであり、ユーザーがworktree単位で調整できるようにする。

現状

  • vibe-local -y -m {model} でセッション起動(src/lib/cli-tools/vibe-local.ts
  • モデル選択はDB(vibe_local_model カラム)に永続化し、AgentSettingsPaneのUIから変更可能
  • コンテキストウィンドウの指定手段はない

対応方針

モデル選択と同様のパターン(DB永続化 + UI + API + CLIオプション)で実装する。

スコープの明確化

スケジュール実行(claude-executor.ts 経由の -p モード)では --context-window オプションは今回のスコープ外とする。vibe-local の -p モードでの --context-window サポート状況が不明なため、対話モード(tmuxセッション)のみに適用する。スケジュール実行パスへの対応が必要な場合は、別Issueで schedule-manager.ts の SELECT 文・claude-executor.tsExecuteCommandOptions interface・buildCliArgs() の vibe-local ケースへの拡張を検討する。

1. データベース

  • worktrees テーブルに vibe_local_context_window INTEGER DEFAULT NULL カラムを追加(マイグレーション)
  • NULL = vibe-localデフォルト値を使用
  • 既存の updateVibeLocalModel と同様の単独関数 updateVibeLocalContextWindowdb.ts に実装する(既存パターンとの一貫性を優先。将来的な汎用化はリファクタリングIssueとして別途検討)
  • getWorktrees() および getWorktreeById() の SELECT 文に w.vibe_local_context_window を追加し、型キャスト(as 句)にもフィールドを追加し、返却オブジェクトのマッピング処理にも vibeLocalContextWindow を追加する(計6箇所の同期修正が必要)
  • upsertWorktree() は修正不要。vibeLocalModel と同様に、コンテキストウィンドウは個別の updateVibeLocalContextWindow() 関数で管理するパターンを踏襲する(upsertWorktree() は worktree の新規登録・基本情報更新を担当し、個別設定は専用の update 関数で管理する既存設計に従う)

2. API(PATCH /api/worktrees/[id])

  • vibeLocalContextWindow フィールドを受け付ける
  • バリデーション: null(リセット)または 128以上 2097152(2M tokens)以下の正の整数
    • 下限を128とする
    • 上限を2097152(2M tokens)とする。定数 VIBE_LOCAL_CONTEXT_WINDOW_MAX = 2097152src/lib/cli-tools/types.ts に定義し、APIバリデーションとdefense-in-depthバリデーションの両方で参照する(DRY原則)
    • 理由: Ollamaはモデルに応じて様々なコンテキスト長をサポートしており(例: Gemma2:2Bは2048推奨、Llama 3.1:405Bは128Kまで対応)、サーバー側で極端に大きな値を許容すると無意味な値やCLI引数の肥大化を招くため、実用的な上限を設ける
  • 既存の vibeLocalModel バリデーションと同じ箇所に追加
  • 新フィールドの追加は後方互換性を維持する('vibeLocalContextWindow' in body パターンによるオプショナルチェック。フィールド未送信時は既存動作に影響なし)

3. UI(AgentSettingsPane)

  • Ollamaモデルセレクターの下にコンテキストウィンドウ入力欄を追加
  • 数値入力(type="number"
    • step="1"(整数のみ)
    • min="128"(バリデーション範囲に合わせる)
    • プレースホルダーに「Default」表示
  • 空欄 = null(デフォルト値を使用)。入力欄を空欄にして保存した場合、null としてAPIに送信しデフォルト値に戻す(number inputのvalueが空文字列の場合にnullとして扱う)
  • i18nキー(schedule 名前空間):
    • vibeLocalContextWindow: ラベル — en: "Context Window" / ja: "コンテキストウィンドウ"
    • vibeLocalContextWindowDefault: プレースホルダー — en: "Default (auto)" / ja: "デフォルト(自動)"
  • 「変更はセッション再起動後に反映されます」のヒント表示を検討(vibeLocalModelと同様の挙動であるため、統一的な注意書きが望ましい)

4. セッション起動(vibe-local.ts)

  • DBから vibeLocalContextWindow を読み取り
  • 値が設定されている場合、起動コマンドに --context-window {value} を追加
    • 例: vibe-local -y -m llama3.2 --context-window 8192
  • defense-in-depth バリデーション: startSession() 内でコマンド文字列に値を埋め込む前に、以下の検証を行う
    // defense-in-depth: 数値以外の値によるコマンドインジェクションを防止
    // VIBE_LOCAL_CONTEXT_WINDOW_MAX は cli-tools/types.ts から import
    if (typeof value === 'number' && Number.isInteger(value) && value >= 128 && value <= VIBE_LOCAL_CONTEXT_WINDOW_MAX) {
      command += ` --context-window ${value}`;
    }

テスト戦略

ユニットテスト

  • バリデーション関数: 正の整数、128未満の拒否、2097152超の拒否、null許容、非整数の拒否、文字列の拒否
  • DBマイグレーション: カラム追加の確認、デフォルト値(NULL)の確認
  • CLIコマンド構築: --context-window 付与ケース、省略ケース(null時)
  • db-migrations.test.ts: CURRENT_SCHEMA_VERSION の期待値を 20 に更新する(L37, L430, L443 の3箇所)とテスト記述(it文のタイトル)の修正(例: 'should be 18 after Migration #18''should be 20 after Migration #20')。version 19 → 20 への変更に伴い、既存のバージョン番号アサーションと rollbackMigrations テストが影響を受ける。Issue feat: CMATEタブにAgent設定タブを追加し、表示するコーディングエージェントを選択可能にする #368 の version 19 と同様のパターンで down() 関数を実装する
  • down() 関数の必要性: version 20 の down() 関数を定義する必要がある。rollbackMigrations テスト(db-migrations.test.ts L427-438)が rollbackMigrations(db, 16) を呼ぶ際に version 20 → 19 → 18 → 17 の順に down() が実行される。down() 関数が未定義の場合、rollbackMigrations() は「no down() function defined」エラーを投げるため、既存テストが失敗する。version 18, 19 と同様に SQLite limitation 注記付きの console.log のみの down() 関数パターンで対応すること
  • 既存コンポーネントテストの更新: 既存の AgentSettingsPane.test.tsxNotesAndLogsPane.test.tsx の props factory に vibeLocalContextWindow / onVibeLocalContextWindowChange 関連 props の追加が必要(TypeScript strict mode により未提供 props はコンパイルエラーとなるため見落としリスクは低いが、修正箇所として認識しておくこと)

インテグレーションテスト

  • PATCH API: 以下のテストケースを網羅する
    • 正常値: 8192(許可)
    • null(リセット、許可)
    • 境界値: 128(許可)、127(拒否)
    • 上限境界値: 2097152(許可)、2097153(拒否)
    • 非整数: 128.5(拒否)
    • 負数: -1(拒否)
    • 文字列: 'abc'(拒否)

変更対象(想定)

  • src/lib/db-migrations.ts -- マイグレーション追加(version 20、CURRENT_SCHEMA_VERSION を 20 に更新)
  • src/lib/db.ts -- updateVibeLocalContextWindow 関数追加、getWorktrees()getWorktreeById() の SELECT 文・型キャスト・マッピング処理にフィールド追加
  • src/types/models.ts -- Worktreeインターフェースに vibeLocalContextWindow?: number | null フィールド追加
  • src/lib/cli-tools/types.ts -- VIBE_LOCAL_CONTEXT_WINDOW_MAX = 2097152 定数追加
  • src/app/api/worktrees/[id]/route.ts -- PATCHハンドラにバリデーション追加
  • src/lib/cli-tools/vibe-local.ts -- 起動コマンド構築に --context-window 追加(defense-in-depth バリデーション含む)
  • src/components/worktree/AgentSettingsPane.tsx -- UI入力欄追加
  • src/components/worktree/WorktreeDetailRefactored.tsx -- vibeLocalContextWindow の state 管理(useState/useCallback)、API レスポンスからの値取得、props 伝播
  • src/components/worktree/NotesAndLogsPane.tsx -- vibeLocalContextWindow の props 定義と AgentSettingsPane への伝播
  • locales/ja/schedule.json, locales/en/schedule.json -- i18nラベル追加(vibeLocalContextWindow, vibeLocalContextWindowDefault
  • CLAUDE.md -- (1) vibe-local.ts モジュール説明に --context-window オプション対応を追記、(2) AgentSettingsPane.tsx の説明にコンテキストウィンドウ入力欄の記述追加、(3) Worktree interface に vibeLocalContextWindow フィールドの記述追加

受け入れ基準

  • AgentSettingsPaneでVibe Local選択時にコンテキストウィンドウの入力欄が表示される
  • 入力した値がDBに永続化され、ページリロード後も保持される
  • セッション起動時に --context-window {value} が正しくCLI引数として渡される
  • 未設定(null)の場合はオプションが省略される(vibe-localのデフォルト動作)
  • 不正な値(負数、非整数、128未満、2097152超)がバリデーションで拒否される
  • コンテキストウィンドウの変更はセッション再起動後に反映される(vibeLocalModelと同じ挙動)
  • 他ツール(Claude/Codex/Gemini)のセッション動作に影響がないこと
  • 各レイヤーのユニットテスト・インテグレーションテストがパスする

レビュー履歴

Stage 1 (2026-02-28)

  • SF-001: テスト戦略セクションを追加(ユニットテスト・インテグレーションテストの要件明記)
  • SF-002: バリデーション範囲を「128以上の正の整数、上限なし」に変更し根拠を明記
  • SF-003: DB更新関数の実装パターンを明記(updateVibeLocalContextWindow 単独関数)
  • SF-004: セッション再起動時の反映タイミングを受け入れ基準に追加
  • NTH-001: UIのi18nキー名・HTML属性(step/min)・クリア挙動を明記
  • NTH-002: 背景セクションにIssue #368への参照を追加
  • NTH-003: 変更対象ファイルにCLAUDE.mdを追加

Stage 3 (2026-02-28) - 影響範囲レビュー

  • IR-001 [must-fix]: db.ts の getWorktrees()/getWorktreeById() の SELECT 文・型キャスト・マッピング処理(計6箇所)の同期修正を明記
  • IR-002 [should-fix]: 変更対象に WorktreeDetailRefactored.tsx と NotesAndLogsPane.tsx を追加(props 伝播のため)
  • IR-003 [should-fix]: セクション4に startSession() 内の defense-in-depth バリデーションコード例を追記
  • IR-004 [should-fix]: テスト戦略に db-migrations.test.ts の CURRENT_SCHEMA_VERSION 期待値更新を追加
  • IR-005 [should-fix]: i18n キーの具体的なテキスト値(en/ja)を明記
  • IR-006 [nice-to-have]: 受け入れ基準に「他ツール(Claude/Codex/Gemini)への影響なし」を追加
  • IR-007 [nice-to-have]: API セクションに後方互換性維持の旨を記載
  • IR-008 [nice-to-have]: データベースセクションに upsertWorktree() 修正不要の設計ノートを追加
  • IR-009 [should-fix]: IR-002 と同一指摘。変更対象ファイルに反映済み
  • IR-010 [nice-to-have]: CLAUDE.md の具体的な更新内容(3点)を明記

Stage 5 (2026-02-28) - 通常レビュー2回目

  • SF-005: db-migrations.test.ts の CURRENT_SCHEMA_VERSION 期待値更新を具体的行数(L37, L430, L443の3箇所)付きに詳細化し、テスト記述(it文タイトル)の修正も追記
  • NTH-004: インテグレーションテストに具体的なテストケース(正常値・null・境界値・非整数・負数・文字列)を列挙
  • NTH-005: UI仕様に空欄保存時のnullリセット操作方法を明記
  • NTH-006: upsertWorktree()修正不要の根拠(個別update関数で管理する既存設計パターン)を追記

Stage 7 (2026-02-28) - 影響範囲レビュー2回目

  • IR2-001 [should-fix]: 「スコープの明確化」セクションを追加し、スケジュール実行(claude-executor.ts経由の-pモード)ではcontext-windowオプションは今回のスコープ外であること、対話モード(tmuxセッション)のみに適用する設計判断を明記
  • IR2-002 [should-fix]: テスト戦略に「down()関数の必要性」サブセクションを追加し、version 20のdown()関数が未定義の場合にrollbackMigrationsテストが失敗するリスクと対応方法を明記
  • IR2-003 [should-fix]: バリデーション条件を「128以上 2097152以下の正の整数」に更新し、定数VIBE_LOCAL_CONTEXT_WINDOW_MAX=2097152をcli-tools/types.tsに定義、defense-in-depthバリデーションにも上限チェックを追加
  • IR2-004 [nice-to-have]: 変更対象のmodels.ts項に具体的な型定義vibeLocalContextWindow?: number | nullを追記
  • IR2-005 [nice-to-have]: テスト戦略に「既存コンポーネントテストの更新」としてAgentSettingsPane.test.tsxとNotesAndLogsPane.test.tsxのprops factory更新の必要性を追記
  • IR2-006 [nice-to-have]: 対応不要(PATCHレスポンスへのvibeLocalContextWindowの自動伝播はgetWorktreeById()のマッピング追加で実現される)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions