diff --git a/builtins/en/config.yaml b/builtins/en/config.yaml index 9358150..d4bee1d 100644 --- a/builtins/en/config.yaml +++ b/builtins/en/config.yaml @@ -1,105 +1,91 @@ # TAKT global configuration sample # Location: ~/.takt/config.yaml -# ---- Core ---- -language: en -default_piece: default -log_level: info +# ===================================== +# General settings (piece-independent) +# ===================================== +language: en # UI language: en | ja +log_level: info # Log level: debug | info | warn | error +provider: claude # Default provider: claude | codex | opencode | mock +# model: sonnet # Optional model name passed to provider -# ---- Provider ---- -# provider: claude | codex | opencode | mock -provider: claude +# Execution control +# worktree_dir: ~/takt-worktrees # Base directory for shared clone execution +# auto_pr: false # Auto-create PR after worktree execution +branch_name_strategy: ai # Branch strategy: romaji | ai +concurrency: 2 # Concurrent task execution for takt run (1-10) +# task_poll_interval_ms: 500 # Polling interval in ms during takt run (100-5000) +# prevent_sleep: false # Prevent macOS idle sleep while running -# Model (optional) -# Claude examples: opus, sonnet, haiku -# Codex examples: gpt-5.2-codex, gpt-5.1-codex -# OpenCode format: provider/model -# model: sonnet - -# Per-persona provider override -# persona_providers: -# coder: codex -# reviewer: claude - -# Provider-specific movement permission policy -# Priority: -# 1) project provider_profiles override -# 2) global provider_profiles override -# 3) project provider_profiles default -# 4) global provider_profiles default -# 5) movement.required_permission_mode (minimum floor) -# provider_profiles: -# codex: -# default_permission_mode: full -# movement_permission_overrides: -# ai_review: readonly -# claude: -# default_permission_mode: edit - -# Provider-specific runtime options -# provider_options: -# codex: -# network_access: true -# claude: -# sandbox: -# allow_unsandboxed_commands: true - -# ---- API Keys ---- -# Environment variables take priority: -# TAKT_ANTHROPIC_API_KEY / TAKT_OPENAI_API_KEY / TAKT_OPENCODE_API_KEY -# anthropic_api_key: "" -# openai_api_key: "" -# opencode_api_key: "" - -# ---- Runtime ---- -# Global runtime preparation (piece_config.runtime overrides this) -# runtime: -# prepare: -# - gradle -# - node - -# ---- Execution ---- -# worktree_dir: ~/takt-worktrees -# auto_pr: false -# prevent_sleep: false - -# ---- Run Loop ---- -# concurrency: 1 -# task_poll_interval_ms: 500 -# interactive_preview_movements: 3 -# branch_name_strategy: romaji - -# ---- Output ---- -# minimal_output: false -# notification_sound: true -# notification_sound_events: +# Output / notifications +# minimal_output: false # Minimized output for CI logs +# verbose: false # Verbose output mode +# notification_sound: true # Master switch for sounds +# notification_sound_events: # Per-event sound toggle (unset means true) # iteration_limit: true # piece_complete: true # piece_abort: true # run_complete: true # run_abort: true # observability: -# provider_events: true +# provider_events: false # Persist provider stream events -# ---- Builtins ---- -# enable_builtin_pieces: true -# disabled_builtins: -# - magi +# Credentials (environment variables take priority) +# anthropic_api_key: "sk-ant-..." # Claude API key +# openai_api_key: "sk-..." # Codex/OpenAI API key +# opencode_api_key: "..." # OpenCode API key +# codex_cli_path: "/absolute/path/to/codex" # Absolute path to Codex CLI -# ---- Pipeline ---- +# Pipeline # pipeline: -# default_branch_prefix: "takt/" -# commit_message_template: "feat: {title} (#{issue})" -# pr_body_template: | +# default_branch_prefix: "takt/" # Prefix for pipeline-created branches +# commit_message_template: "feat: {title} (#{issue})" # Commit template +# pr_body_template: | # PR body template # ## Summary # {issue_body} # Closes #{issue} -# ---- Preferences ---- -# bookmarks_file: ~/.takt/preferences/bookmarks.yaml -# piece_categories_file: ~/.takt/preferences/piece-categories.yaml +# Misc +# bookmarks_file: ~/.takt/preferences/bookmarks.yaml # Bookmark file location -# ---- Debug ---- -# debug: -# enabled: false -# log_file: ~/.takt/logs/debug.log +# ===================================== +# Piece-related settings (global defaults) +# ===================================== +# 1) Route provider per persona +# persona_providers: +# coder: codex # Run coder persona on codex +# reviewer: claude # Run reviewer persona on claude + +# 2) Provider options (global < project < piece) +# provider_options: +# codex: +# network_access: true # Allow network access for Codex +# opencode: +# network_access: true # Allow network access for OpenCode +# claude: +# sandbox: +# allow_unsandboxed_commands: false # true allows unsandboxed execution for listed commands +# excluded_commands: +# - "npm publish" # Commands excluded from sandbox + +# 3) Movement permission policy +# provider_profiles: +# codex: +# default_permission_mode: full # Base permission: readonly | edit | full +# movement_permission_overrides: +# ai_review: readonly # Per-movement override +# claude: +# default_permission_mode: edit + +# 4) Runtime preparation before execution (recommended: enabled) +runtime: + prepare: + - gradle # Prepare Gradle cache/env under .runtime + - node # Prepare npm cache/env under .runtime + +# 5) Piece list / categories +# enable_builtin_pieces: true # Enable built-in pieces from builtins/{lang}/pieces +# disabled_builtins: +# - magi # Built-in piece names to disable +# piece_categories_file: ~/.takt/preferences/piece-categories.yaml # Category definition file +# interactive_preview_movements: 3 # Preview movement count in interactive mode (0-10) diff --git a/builtins/ja/config.yaml b/builtins/ja/config.yaml index 7c86fec..323f511 100644 --- a/builtins/ja/config.yaml +++ b/builtins/ja/config.yaml @@ -1,105 +1,91 @@ # TAKT グローバル設定サンプル # 配置場所: ~/.takt/config.yaml -# ---- 基本 ---- -language: ja -default_piece: default -log_level: info +# ===================================== +# 通常設定(ピース非依存) +# ===================================== +language: ja # 表示言語: ja | en +log_level: info # ログレベル: debug | info | warn | error +provider: claude # デフォルト実行プロバイダー: claude | codex | opencode | mock +# model: sonnet # 省略可。providerに渡すモデル名 -# ---- プロバイダー ---- -# provider: claude | codex | opencode | mock -provider: claude +# 実行制御 +# worktree_dir: ~/takt-worktrees # 共有clone作成先ディレクトリ +# auto_pr: false # worktree実行後に自動PR作成するか +branch_name_strategy: ai # ブランチ名生成: romaji | ai +concurrency: 2 # takt run の同時実行数(1-10) +# task_poll_interval_ms: 500 # takt run のタスク監視間隔ms(100-5000) +# prevent_sleep: false # macOS実行中のスリープ防止(caffeinate) -# モデル(任意) -# Claude 例: opus, sonnet, haiku -# Codex 例: gpt-5.2-codex, gpt-5.1-codex -# OpenCode 形式: provider/model -# model: sonnet - -# ペルソナ別プロバイダー上書き -# persona_providers: -# coder: codex -# reviewer: claude - -# プロバイダー別 movement 権限ポリシー -# 優先順: -# 1) project provider_profiles override -# 2) global provider_profiles override -# 3) project provider_profiles default -# 4) global provider_profiles default -# 5) movement.required_permission_mode(下限補正) -# provider_profiles: -# codex: -# default_permission_mode: full -# movement_permission_overrides: -# ai_review: readonly -# claude: -# default_permission_mode: edit - -# プロバイダー別ランタイムオプション -# provider_options: -# codex: -# network_access: true -# claude: -# sandbox: -# allow_unsandboxed_commands: true - -# ---- API キー ---- -# 環境変数が優先: -# TAKT_ANTHROPIC_API_KEY / TAKT_OPENAI_API_KEY / TAKT_OPENCODE_API_KEY -# anthropic_api_key: "" -# openai_api_key: "" -# opencode_api_key: "" - -# ---- ランタイム ---- -# グローバルなランタイム準備(piece_config.runtime があればそちらを優先) -# runtime: -# prepare: -# - gradle -# - node - -# ---- 実行 ---- -# worktree_dir: ~/takt-worktrees -# auto_pr: false -# prevent_sleep: false - -# ---- Run Loop ---- -# concurrency: 1 -# task_poll_interval_ms: 500 -# interactive_preview_movements: 3 -# branch_name_strategy: romaji - -# ---- 出力 ---- -# minimal_output: false -# notification_sound: true -# notification_sound_events: +# 出力・通知 +# minimal_output: false # 出力を最小化(CI向け) +# verbose: false # 詳細ログを有効化 +# notification_sound: true # 通知音全体のON/OFF +# notification_sound_events: # イベント別通知音(未指定はtrue扱い) # iteration_limit: true # piece_complete: true # piece_abort: true # run_complete: true # run_abort: true # observability: -# provider_events: true +# provider_events: false # providerイベントログを記録 -# ---- Builtins ---- -# enable_builtin_pieces: true -# disabled_builtins: -# - magi +# 認証情報(環境変数優先) +# anthropic_api_key: "sk-ant-..." # Claude APIキー +# openai_api_key: "sk-..." # Codex APIキー +# opencode_api_key: "..." # OpenCode APIキー +# codex_cli_path: "/absolute/path/to/codex" # Codex CLI絶対パス -# ---- Pipeline ---- +# パイプライン # pipeline: -# default_branch_prefix: "takt/" -# commit_message_template: "feat: {title} (#{issue})" -# pr_body_template: | +# default_branch_prefix: "takt/" # pipeline作成ブランチの接頭辞 +# commit_message_template: "feat: {title} (#{issue})" # コミット文テンプレート +# pr_body_template: | # PR本文テンプレート # ## Summary # {issue_body} # Closes #{issue} -# ---- Preferences ---- -# bookmarks_file: ~/.takt/preferences/bookmarks.yaml -# piece_categories_file: ~/.takt/preferences/piece-categories.yaml +# その他 +# bookmarks_file: ~/.takt/preferences/bookmarks.yaml # ブックマーク保存先 -# ---- Debug ---- -# debug: -# enabled: false -# log_file: ~/.takt/logs/debug.log +# ===================================== +# ピースにも関わる設定(global defaults) +# ===================================== +# 1) ペルソナ単位でプロバイダーを切り替える +# persona_providers: +# coder: codex # coderペルソナはcodexで実行 +# reviewer: claude # reviewerペルソナはclaudeで実行 + +# 2) provider 固有オプション(global < project < piece) +# provider_options: +# codex: +# network_access: true # Codex実行時のネットワークアクセス許可 +# opencode: +# network_access: true # OpenCode実行時のネットワークアクセス許可 +# claude: +# sandbox: +# allow_unsandboxed_commands: false # trueで対象コマンドを非サンドボックス実行 +# excluded_commands: +# - "npm publish" # 非サンドボックス対象コマンド + +# 3) movement の権限ポリシー +# provider_profiles: +# codex: +# default_permission_mode: full # 既定権限: readonly | edit | full +# movement_permission_overrides: +# ai_review: readonly # movement単位の上書き +# claude: +# default_permission_mode: edit + +# 4) 実行前のランタイム準備(推奨: 有効化) +runtime: + prepare: + - gradle # Gradleキャッシュ/環境を .runtime 配下に準備 + - node # npmキャッシュ/環境を .runtime 配下に準備 + +# 5) ピース一覧/カテゴリ +# enable_builtin_pieces: true # builtins/{lang}/pieces を有効化 +# disabled_builtins: +# - magi # 無効化するビルトインピース名 +# piece_categories_file: ~/.takt/preferences/piece-categories.yaml # カテゴリ定義ファイル +# interactive_preview_movements: 3 # 対話モードのプレビュー件数(0-10) diff --git a/docs/README.ja.md b/docs/README.ja.md index c99c158..eb2bb9b 100644 --- a/docs/README.ja.md +++ b/docs/README.ja.md @@ -292,9 +292,6 @@ takt eject instruction plan --global # 各ムーブメント・フェーズの組み立て済みプロンプトをプレビュー takt prompt [piece] -# パーミッションモードを設定 -takt config - # ピースカテゴリをビルトインのデフォルトにリセット takt reset categories ``` @@ -562,76 +559,182 @@ Claude Code はエイリアス(`opus`、`sonnet`、`haiku`、`opusplan`、`def ### グローバル設定 -デフォルトのプロバイダーとモデルを `~/.takt/config.yaml` で設定: +`~/.takt/config.yaml` のサンプルです。 +コメントで「通常設定」と「ピースにも関わる設定」を分けています。 ```yaml # ~/.takt/config.yaml -language: ja -default_piece: default -log_level: info -provider: claude # デフォルトプロバイダー: claude、codex、または opencode -model: sonnet # デフォルトモデル(オプション) -branch_name_strategy: romaji # ブランチ名生成: 'romaji'(高速)または 'ai'(低速) -prevent_sleep: false # macOS の実行中スリープ防止(caffeinate) -notification_sound: true # 通知音の有効/無効 -notification_sound_events: # タイミング別の通知音制御 - iteration_limit: false - piece_complete: true - piece_abort: true - run_complete: true # 未設定時は有効。false を指定すると無効 - run_abort: true # 未設定時は有効。false を指定すると無効 -concurrency: 1 # takt run の並列タスク数(1-10、デフォルト: 1 = 逐次実行) -task_poll_interval_ms: 500 # takt run 中の新タスク検出ポーリング間隔(100-5000、デフォルト: 500) -interactive_preview_movements: 3 # 対話モードでのムーブメントプレビュー数(0-10、デフォルト: 3) -# ランタイム環境デフォルト(piece_config.runtime で上書き可能) -# runtime: -# prepare: -# - gradle # Gradle のキャッシュ/設定を .runtime/ に準備 -# - node # npm キャッシュを .runtime/ に準備 +# ===================================== +# 通常設定(ピース非依存) +# ===================================== +language: ja # 表示言語: ja | en +log_level: info # ログレベル: debug | info | warn | error +provider: claude # デフォルト実行プロバイダー: claude | codex | opencode | mock +# model: sonnet # 省略可。providerに渡すモデル名 -# ペルソナ別プロバイダー設定(オプション) -# ピースを複製せずに特定のペルソナを異なるプロバイダーにルーティング +# 実行制御 +# worktree_dir: ~/takt-worktrees # 共有clone作成先ディレクトリ +# auto_pr: false # worktree実行後に自動PR作成するか +branch_name_strategy: ai # ブランチ名生成: romaji | ai +concurrency: 2 # takt run の同時実行数(1-10) +# task_poll_interval_ms: 500 # takt run のタスク監視間隔ms(100-5000) +# prevent_sleep: false # macOS実行中のスリープ防止(caffeinate) + +# 出力・通知 +# minimal_output: false # 出力を最小化(CI向け) +# verbose: false # 詳細ログを有効化 +# notification_sound: true # 通知音全体のON/OFF +# notification_sound_events: # イベント別通知音(未指定はtrue扱い) +# iteration_limit: true +# piece_complete: true +# piece_abort: true +# run_complete: true +# run_abort: true +# observability: +# provider_events: false # providerイベントログを記録 + +# 認証情報(環境変数優先) +# anthropic_api_key: "sk-ant-..." # Claude APIキー +# openai_api_key: "sk-..." # Codex APIキー +# opencode_api_key: "..." # OpenCode APIキー +# codex_cli_path: "/absolute/path/to/codex" # Codex CLI絶対パス + +# パイプライン +# pipeline: +# default_branch_prefix: "takt/" # pipeline作成ブランチの接頭辞 +# commit_message_template: "feat: {title} (#{issue})" # コミット文テンプレート +# pr_body_template: | # PR本文テンプレート +# ## Summary +# {issue_body} +# Closes #{issue} + +# その他 +# bookmarks_file: ~/.takt/preferences/bookmarks.yaml # ブックマーク保存先 + +# ===================================== +# ピースにも関わる設定(global defaults) +# ===================================== +# 1) ペルソナ単位でプロバイダーを切り替える # persona_providers: -# coder: codex # coder を Codex で実行 -# ai-antipattern-reviewer: claude # レビュアーは Claude のまま +# coder: codex # coderペルソナはcodexで実行 +# reviewer: claude # reviewerペルソナはclaudeで実行 + +# 2) provider 固有オプション(global < project < piece) +# provider_options: +# codex: +# network_access: true # Codex実行時のネットワークアクセス許可 +# opencode: +# network_access: true # OpenCode実行時のネットワークアクセス許可 +# claude: +# sandbox: +# allow_unsandboxed_commands: false # trueで対象コマンドを非サンドボックス実行 +# excluded_commands: +# - "npm publish" # 非サンドボックス対象コマンド + +# 3) movement の権限ポリシー +# provider_profiles: +# codex: +# default_permission_mode: full # 既定権限: readonly | edit | full +# movement_permission_overrides: +# ai_review: readonly # movement単位の上書き +# claude: +# default_permission_mode: edit + +# 4) 実行前のランタイム準備(推奨: 有効化) +runtime: + prepare: + - gradle # Gradleキャッシュ/環境を .runtime 配下に準備 + - node # npmキャッシュ/環境を .runtime 配下に準備 + +# 5) ピース一覧/カテゴリ +# enable_builtin_pieces: true # builtins/{lang}/pieces を有効化 +# disabled_builtins: +# - magi # 無効化するビルトインピース名 +# piece_categories_file: ~/.takt/preferences/piece-categories.yaml # カテゴリ定義ファイル +# interactive_preview_movements: 3 # 対話モードのプレビュー件数(0-10) +``` + +主要な設定項目の説明: + +**通常設定** +| 項目 | 説明 | +|------|------| +| `language` | 表示言語(`ja` / `en`) | +| `log_level` | ログレベル(`debug` / `info` / `warn` / `error`) | +| `provider` | デフォルト実行プロバイダー(`claude` / `codex` / `opencode` / `mock`) | +| `model` | モデル名(provider にそのまま渡される) | +| `auto_pr` | worktree 実行後のPR作成挙動 | +| `concurrency` | `takt run` の同時実行数(1-10) | +| `task_poll_interval_ms` | `takt run` のタスク監視間隔(100-5000ms) | +| `minimal_output` | CI向けの簡易出力モード | +| `verbose` | 詳細ログ出力 | +| `notification_sound` / `notification_sound_events` | 通知音のON/OFFとイベント別制御 | +| `pipeline.*` | pipeline 実行時のブランチ/コミット/PRテンプレート | + +**ピースにも関わる設定** +| 項目 | 説明 | +|------|------| +| `persona_providers` | ペルソナ単位の provider 上書き | +| `provider_options` | provider固有オプション(例: `codex.network_access`、`claude.sandbox.*`) | +| `provider_profiles` | movement ごとの permission mode 解決ルール | +| `runtime.prepare` | 実行前の環境準備(`gradle` / `node` / 任意スクリプト) | +| `enable_builtin_pieces` / `disabled_builtins` | ビルトインピースの有効化/除外 | +| `piece_categories_file` | ピースカテゴリ定義ファイルの場所 | +| `interactive_preview_movements` | 対話モードで表示する movement プレビュー数 | + +### プロジェクトローカル設定 + +`.takt/config.yaml` のサンプルです。 +チーム/リポジトリごとの既定値を置く用途です。 + +```yaml +# .takt/config.yaml + +# ===================================== +# 通常設定(ピース非依存) +# ===================================== +piece: default # このプロジェクトで使う既定ピース名 +provider: claude # プロジェクト既定プロバイダー: claude | codex | opencode | mock +# verbose: false # このプロジェクトだけ詳細ログを有効化する場合 +# auto_pr: false # worktree実行後に自動PR作成するか + +# ===================================== +# ピースにも関わる設定(project overrides) +# ===================================== +# provider_options: +# codex: +# network_access: true # グローバル設定をこのプロジェクトで上書き +# claude: +# sandbox: +# allow_unsandboxed_commands: false +# excluded_commands: +# - "npm publish" -# プロバイダー別パーミッションプロファイル(オプション) -# 優先順: project override → global override → project default → global default → required_permission_mode(下限) # provider_profiles: # codex: # default_permission_mode: full # movement_permission_overrides: # ai_review: readonly -# claude: -# default_permission_mode: edit - -# API Key 設定(オプション) -# 環境変数 TAKT_ANTHROPIC_API_KEY / TAKT_OPENAI_API_KEY / TAKT_OPENCODE_API_KEY で上書き可能 -anthropic_api_key: sk-ant-... # Claude (Anthropic) を使う場合 -# openai_api_key: sk-... # Codex (OpenAI) を使う場合 -# opencode_api_key: ... # OpenCode を使う場合 - -# Codex CLI パスの上書き(オプション) -# Codex SDK が使用する CLI バイナリを上書き(実行可能ファイルの絶対パスを指定) -# 環境変数 TAKT_CODEX_CLI_PATH で上書き可能 -# codex_cli_path: /usr/local/bin/codex - -# ビルトインピースのフィルタリング(オプション) -# builtin_pieces_enabled: true # false でビルトイン全体を無効化 -# disabled_builtins: [magi, passthrough] # 特定のビルトインピースを無効化 - -# パイプライン実行設定(オプション) -# ブランチ名、コミットメッセージ、PRの本文をカスタマイズできます。 -# pipeline: -# default_branch_prefix: "takt/" -# commit_message_template: "feat: {title} (#{issue})" -# pr_body_template: | -# ## Summary -# {issue_body} -# Closes #{issue} ``` +プロジェクトローカルで使える主な項目: + +| 項目 | 説明 | +|------|------| +| `piece` | プロジェクト既定のピース | +| `provider` | プロジェクト既定のプロバイダー | +| `verbose` | ローカル詳細ログ | +| `auto_pr` | ローカル既定のPR作成挙動 | +| `provider_options` | provider固有オプションのローカル上書き | +| `provider_profiles` | movement権限ポリシーのローカル上書き | + +設定解決の優先順位(高 → 低): +1. 環境変数(`TAKT_*`) +2. `.takt/config.yaml`(プロジェクトローカル) +3. `~/.takt/config.yaml`(グローバル) +4. デフォルト値 + **注意:** Codex SDK は Git 管理下のディレクトリでのみ動作します。`--skip-git-repo-check` は Codex CLI 専用です。 **API Key の設定方法:** diff --git a/docs/testing/e2e.md b/docs/testing/e2e.md index ffd9502..f4da4bf 100644 --- a/docs/testing/e2e.md +++ b/docs/testing/e2e.md @@ -144,14 +144,6 @@ E2Eテストを追加・変更した場合は、このドキュメントも更 - `takt list --non-interactive --action diff --branch ` で差分統計が出力されることを確認する。 - `takt list --non-interactive --action try --branch ` で変更がステージされることを確認する。 - `takt list --non-interactive --action merge --branch ` でブランチがマージされ削除されることを確認する。 -- Config permission mode(`e2e/specs/cli-config.e2e.ts`) - - 目的: `takt config` でパーミッションモードの切り替えと永続化を確認。 - - LLM: 呼び出さない(LLM不使用の操作のみ) - - 手順(ユーザー行動/コマンド): - - `takt config default` を実行し、`Switched to: default` が出力されることを確認する。 - - `takt config sacrifice-my-pc` を実行し、`Switched to: sacrifice-my-pc` が出力されることを確認する。 - - `takt config sacrifice-my-pc` 実行後、`.takt/config.yaml` に `permissionMode: sacrifice-my-pc` が保存されていることを確認する。 - - `takt config invalid-mode` を実行し、`Invalid mode` が出力されることを確認する。 - Reset categories(`e2e/specs/cli-reset-categories.e2e.ts`) - 目的: `takt reset categories` でカテゴリオーバーレイのリセットを確認。 - LLM: 呼び出さない(LLM不使用の操作のみ) diff --git a/e2e/fixtures/config.e2e.yaml b/e2e/fixtures/config.e2e.yaml index fca15ce..4cbdd6e 100644 --- a/e2e/fixtures/config.e2e.yaml +++ b/e2e/fixtures/config.e2e.yaml @@ -1,7 +1,6 @@ provider: claude language: en log_level: info -default_piece: default notification_sound: false notification_sound_events: iteration_limit: false diff --git a/e2e/specs/cli-config.e2e.ts b/e2e/specs/cli-config.e2e.ts deleted file mode 100644 index 19a6433..0000000 --- a/e2e/specs/cli-config.e2e.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest'; -import { readFileSync } from 'node:fs'; -import { join } from 'node:path'; -import { createIsolatedEnv, type IsolatedEnv } from '../helpers/isolated-env'; -import { runTakt } from '../helpers/takt-runner'; -import { createLocalRepo, type LocalRepo } from '../helpers/test-repo'; - -// E2E更新時は docs/testing/e2e.md も更新すること -describe('E2E: Config command (takt config)', () => { - let isolatedEnv: IsolatedEnv; - let repo: LocalRepo; - - beforeEach(() => { - isolatedEnv = createIsolatedEnv(); - repo = createLocalRepo(); - }); - - afterEach(() => { - try { repo.cleanup(); } catch { /* best-effort */ } - try { isolatedEnv.cleanup(); } catch { /* best-effort */ } - }); - - it('should switch to default mode with explicit argument', () => { - // Given: a local repo with isolated env - - // When: running takt config default - const result = runTakt({ - args: ['config', 'default'], - cwd: repo.path, - env: isolatedEnv.env, - }); - - // Then: exits successfully and outputs switched message - expect(result.exitCode).toBe(0); - const output = result.stdout; - expect(output).toMatch(/Switched to: default/); - }); - - it('should switch to sacrifice-my-pc mode with explicit argument', () => { - // Given: a local repo with isolated env - - // When: running takt config sacrifice-my-pc - const result = runTakt({ - args: ['config', 'sacrifice-my-pc'], - cwd: repo.path, - env: isolatedEnv.env, - }); - - // Then: exits successfully and outputs switched message - expect(result.exitCode).toBe(0); - const output = result.stdout; - expect(output).toMatch(/Switched to: sacrifice-my-pc/); - }); - - it('should persist permission mode to project config', () => { - // Given: a local repo with isolated env - - // When: running takt config sacrifice-my-pc - runTakt({ - args: ['config', 'sacrifice-my-pc'], - cwd: repo.path, - env: isolatedEnv.env, - }); - - // Then: .takt/config.yaml contains permissionMode: sacrifice-my-pc - const configPath = join(repo.path, '.takt', 'config.yaml'); - const content = readFileSync(configPath, 'utf-8'); - expect(content).toMatch(/permissionMode:\s*sacrifice-my-pc/); - }); - - it('should report error for invalid mode name', () => { - // Given: a local repo with isolated env - - // When: running takt config with an invalid mode - const result = runTakt({ - args: ['config', 'invalid-mode'], - cwd: repo.path, - env: isolatedEnv.env, - }); - - // Then: output contains invalid mode message - const combined = result.stdout + result.stderr; - expect(combined).toMatch(/Invalid mode/); - }); -}); diff --git a/src/__tests__/cli-worktree.test.ts b/src/__tests__/cli-worktree.test.ts index 24fc270..405f939 100644 --- a/src/__tests__/cli-worktree.test.ts +++ b/src/__tests__/cli-worktree.test.ts @@ -66,7 +66,6 @@ vi.mock('../infra/config/index.js', () => ({ vi.mock('../infra/config/paths.js', () => ({ clearPersonaSessions: vi.fn(), - getCurrentPiece: vi.fn(() => 'default'), isVerboseMode: vi.fn(() => false), })); diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index 4dc3dea..7e5284b 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -1,5 +1,5 @@ /** - * Tests for takt config functions + * Tests for config functions */ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; @@ -13,7 +13,6 @@ import { loadPiece, listPieces, loadPersonaPromptFromPath, - getCurrentPiece, setCurrentPiece, getProjectConfigDir, getBuiltinPersonasDir, @@ -297,47 +296,6 @@ describe('loadPersonaPromptFromPath (builtin paths)', () => { }); }); -describe('getCurrentPiece', () => { - let testDir: string; - - beforeEach(() => { - testDir = join(tmpdir(), `takt-test-${randomUUID()}`); - mkdirSync(testDir, { recursive: true }); - }); - - afterEach(() => { - if (existsSync(testDir)) { - rmSync(testDir, { recursive: true, force: true }); - } - }); - - it('should return default when no config exists', () => { - const piece = getCurrentPiece(testDir); - - expect(piece).toBe('default'); - }); - - it('should return saved piece name from config.yaml', () => { - const configDir = getProjectConfigDir(testDir); - mkdirSync(configDir, { recursive: true }); - writeFileSync(join(configDir, 'config.yaml'), 'piece: default\n'); - - const piece = getCurrentPiece(testDir); - - expect(piece).toBe('default'); - }); - - it('should return default for empty config', () => { - const configDir = getProjectConfigDir(testDir); - mkdirSync(configDir, { recursive: true }); - writeFileSync(join(configDir, 'config.yaml'), ''); - - const piece = getCurrentPiece(testDir); - - expect(piece).toBe('default'); - }); -}); - describe('setCurrentPiece', () => { let testDir: string; @@ -373,7 +331,7 @@ describe('setCurrentPiece', () => { setCurrentPiece(testDir, 'first'); setCurrentPiece(testDir, 'second'); - const piece = getCurrentPiece(testDir); + const piece = loadProjectConfig(testDir).piece; expect(piece).toBe('second'); }); diff --git a/src/__tests__/e2e-helpers.test.ts b/src/__tests__/e2e-helpers.test.ts index f7b25d6..62a5254 100644 --- a/src/__tests__/e2e-helpers.test.ts +++ b/src/__tests__/e2e-helpers.test.ts @@ -85,7 +85,6 @@ describe('createIsolatedEnv', () => { expect(config.language).toBe('en'); expect(config.log_level).toBe('info'); - expect(config.default_piece).toBe('default'); expect(config.notification_sound).toBe(false); expect(config.notification_sound_events).toEqual({ iteration_limit: false, @@ -173,7 +172,6 @@ describe('createIsolatedEnv', () => { [ 'language: en', 'log_level: info', - 'default_piece: default', 'notification_sound: true', 'notification_sound_events: true', ].join('\n'), diff --git a/src/__tests__/globalConfig-resolvers.test.ts b/src/__tests__/globalConfig-resolvers.test.ts index 9f211cc..8314198 100644 --- a/src/__tests__/globalConfig-resolvers.test.ts +++ b/src/__tests__/globalConfig-resolvers.test.ts @@ -97,7 +97,6 @@ describe('GlobalConfig load/save with API keys', () => { it('should load config with API keys from YAML', () => { const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'anthropic_api_key: sk-ant-from-yaml', @@ -113,7 +112,6 @@ describe('GlobalConfig load/save with API keys', () => { it('should load config without API keys', () => { const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); @@ -128,7 +126,6 @@ describe('GlobalConfig load/save with API keys', () => { // Write initial config const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); @@ -147,7 +144,6 @@ describe('GlobalConfig load/save with API keys', () => { it('should not persist API keys when not set', () => { const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); @@ -183,7 +179,6 @@ describe('resolveAnthropicApiKey', () => { process.env['TAKT_ANTHROPIC_API_KEY'] = 'sk-ant-from-env'; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'anthropic_api_key: sk-ant-from-yaml', @@ -198,7 +193,6 @@ describe('resolveAnthropicApiKey', () => { delete process.env['TAKT_ANTHROPIC_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'anthropic_api_key: sk-ant-from-yaml', @@ -213,7 +207,6 @@ describe('resolveAnthropicApiKey', () => { delete process.env['TAKT_ANTHROPIC_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); @@ -254,7 +247,6 @@ describe('resolveOpenaiApiKey', () => { process.env['TAKT_OPENAI_API_KEY'] = 'sk-openai-from-env'; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'openai_api_key: sk-openai-from-yaml', @@ -269,7 +261,6 @@ describe('resolveOpenaiApiKey', () => { delete process.env['TAKT_OPENAI_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'openai_api_key: sk-openai-from-yaml', @@ -284,7 +275,6 @@ describe('resolveOpenaiApiKey', () => { delete process.env['TAKT_OPENAI_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); @@ -318,7 +308,6 @@ describe('resolveCodexCliPath', () => { process.env['TAKT_CODEX_CLI_PATH'] = envCodexPath; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: codex', `codex_cli_path: ${configCodexPath}`, @@ -334,7 +323,6 @@ describe('resolveCodexCliPath', () => { const configCodexPath = createExecutableFile('config-codex'); const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: codex', `codex_cli_path: ${configCodexPath}`, @@ -349,7 +337,6 @@ describe('resolveCodexCliPath', () => { delete process.env['TAKT_CODEX_CLI_PATH']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: codex', ].join('\n'); @@ -395,7 +382,6 @@ describe('resolveCodexCliPath', () => { delete process.env['TAKT_CODEX_CLI_PATH']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: codex', `codex_cli_path: ${join(testDir, 'missing-codex-from-config')}`, @@ -427,7 +413,6 @@ describe('resolveOpencodeApiKey', () => { process.env['TAKT_OPENCODE_API_KEY'] = 'sk-opencode-from-env'; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'opencode_api_key: sk-opencode-from-yaml', @@ -442,7 +427,6 @@ describe('resolveOpencodeApiKey', () => { delete process.env['TAKT_OPENCODE_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', 'opencode_api_key: sk-opencode-from-yaml', @@ -457,7 +441,6 @@ describe('resolveOpencodeApiKey', () => { delete process.env['TAKT_OPENCODE_API_KEY']; const yaml = [ 'language: en', - 'default_piece: default', 'log_level: info', 'provider: claude', ].join('\n'); diff --git a/src/__tests__/it-pipeline-modes.test.ts b/src/__tests__/it-pipeline-modes.test.ts index e2aa3e2..b419cf6 100644 --- a/src/__tests__/it-pipeline-modes.test.ts +++ b/src/__tests__/it-pipeline-modes.test.ts @@ -109,7 +109,6 @@ vi.mock('../infra/config/paths.js', async (importOriginal) => { updatePersonaSession: vi.fn(), loadWorktreeSessions: vi.fn().mockReturnValue({}), updateWorktreeSession: vi.fn(), - getCurrentPiece: vi.fn().mockReturnValue('default'), getProjectConfigDir: vi.fn().mockImplementation((cwd: string) => join(cwd, '.takt')), }; }); diff --git a/src/__tests__/it-pipeline.test.ts b/src/__tests__/it-pipeline.test.ts index 3efcf89..2410ec2 100644 --- a/src/__tests__/it-pipeline.test.ts +++ b/src/__tests__/it-pipeline.test.ts @@ -91,7 +91,6 @@ vi.mock('../infra/config/paths.js', async (importOriginal) => { updatePersonaSession: vi.fn(), loadWorktreeSessions: vi.fn().mockReturnValue({}), updateWorktreeSession: vi.fn(), - getCurrentPiece: vi.fn().mockReturnValue('default'), getProjectConfigDir: vi.fn().mockImplementation((cwd: string) => join(cwd, '.takt')), }; }); diff --git a/src/core/models/global-config.ts b/src/core/models/global-config.ts index ed3fba2..a60c1dd 100644 --- a/src/core/models/global-config.ts +++ b/src/core/models/global-config.ts @@ -110,7 +110,6 @@ export interface GlobalConfig { /** Project-level configuration */ export interface ProjectConfig { piece?: string; - agents?: CustomAgentConfig[]; provider?: 'claude' | 'codex' | 'opencode' | 'mock'; providerOptions?: MovementProviderOptions; /** Provider-specific permission profiles */ diff --git a/src/core/models/schemas.ts b/src/core/models/schemas.ts index 05e43d0..b0ac604 100644 --- a/src/core/models/schemas.ts +++ b/src/core/models/schemas.ts @@ -468,7 +468,6 @@ export const GlobalConfigSchema = z.object({ /** Project config schema */ export const ProjectConfigSchema = z.object({ piece: z.string().optional(), - agents: z.array(CustomAgentConfigSchema).optional(), provider: z.enum(['claude', 'codex', 'opencode', 'mock']).optional(), provider_options: MovementProviderOptionsSchema, provider_profiles: ProviderPermissionProfilesSchema, diff --git a/src/index.ts b/src/index.ts index 416deb0..e4d138b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,7 +35,6 @@ export { export { saveProjectConfig, updateProjectConfig, - getCurrentPiece, setCurrentPiece, isVerboseMode, type ProjectLocalConfig, diff --git a/src/infra/config/paths.ts b/src/infra/config/paths.ts index ccde49f..214950b 100644 --- a/src/infra/config/paths.ts +++ b/src/infra/config/paths.ts @@ -117,7 +117,6 @@ export { loadProjectConfig, saveProjectConfig, updateProjectConfig, - getCurrentPiece, setCurrentPiece, type ProjectLocalConfig, } from './project/projectConfig.js'; diff --git a/src/infra/config/project/index.ts b/src/infra/config/project/index.ts index 4476961..db97287 100644 --- a/src/infra/config/project/index.ts +++ b/src/infra/config/project/index.ts @@ -6,7 +6,6 @@ export { loadProjectConfig, saveProjectConfig, updateProjectConfig, - getCurrentPiece, setCurrentPiece, type ProjectLocalConfig, } from './projectConfig.js'; diff --git a/src/infra/config/project/projectConfig.ts b/src/infra/config/project/projectConfig.ts index fa2d7e6..2671ba9 100644 --- a/src/infra/config/project/projectConfig.ts +++ b/src/infra/config/project/projectConfig.ts @@ -136,14 +136,6 @@ export function updateProjectConfig( saveProjectConfig(projectDir, config); } -/** - * Get current piece from project config - */ -export function getCurrentPiece(projectDir: string): string { - const config = loadProjectConfig(projectDir); - return config.piece || 'default'; -} - /** * Set current piece in project config */ diff --git a/src/infra/config/types.ts b/src/infra/config/types.ts index e806e3c..e5d659a 100644 --- a/src/infra/config/types.ts +++ b/src/infra/config/types.ts @@ -13,8 +13,6 @@ export interface ProjectLocalConfig { provider?: 'claude' | 'codex' | 'opencode' | 'mock'; /** Auto-create PR after worktree execution */ auto_pr?: boolean; - /** Auto-create PR after worktree execution (camelCase alias) */ - autoPr?: boolean; /** Verbose output mode */ verbose?: boolean; /** Provider-specific options (overrides global, overridden by piece/movement) */