diff --git a/README.ja.md b/README.ja.md
index 9071fe2..d5b658c 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -52,11 +52,14 @@ exstruct input.xlsx --format yaml # YAML(pyyaml が必要)
exstruct input.xlsx --format toon # TOON(python-toon が必要)
exstruct input.xlsx --sheets-dir sheets/ # シートごとに分割出力
exstruct input.xlsx --auto-page-breaks-dir auto_areas/ # COM 限定(利用可能な環境のみ表示)
+exstruct input.xlsx --alpha-col # 列キーを A, B, ..., AA 形式で出力
exstruct input.xlsx --mode light # セル+テーブル候補のみ
exstruct input.xlsx --pdf --image # PDF と PNG(Excel 必須)
```
自動改ページ範囲の書き出しは API/CLI 両方に対応(Excel/COM が必要)し、CLI は利用可能な環境でのみ `--auto-page-breaks-dir` を表示します。
+CLI の既定では列キーは従来どおり 0 始まりの数値文字列(`"0"`, `"1"`, ...)です。Excel 形式(`"A"`, `"B"`, ...)が必要な場合は `--alpha-col` を指定してください。
+注意: MCP の `exstruct_extract` は `options.alpha_col=true` が既定で、CLI の既定(`false`)とは異なります。
## MCPサーバー (標準入出力)
diff --git a/README.md b/README.md
index 04eb201..cec60fa 100644
--- a/README.md
+++ b/README.md
@@ -55,11 +55,14 @@ exstruct input.xlsx --format toon # TOON (needs python-toon)
exstruct input.xlsx --sheets-dir sheets/ # split per sheet in chosen format
exstruct input.xlsx --auto-page-breaks-dir auto_areas/ # COM only; option appears when available
exstruct input.xlsx --print-areas-dir areas/ # split per print area (if any)
+exstruct input.xlsx --alpha-col # output column keys as A, B, ..., AA
exstruct input.xlsx --mode light # cells + table candidates only
exstruct input.xlsx --pdf --image # PDF and PNGs (Excel required)
```
Auto page-break exports are available via API and CLI when Excel/COM is available; the CLI exposes `--auto-page-breaks-dir` only in COM-capable environments.
+By default, CLI keeps legacy 0-based numeric string column keys (`"0"`, `"1"`, ...). Use `--alpha-col` to emit Excel-style column keys (`"A"`, `"B"`, ...).
+Note: MCP `exstruct_extract` defaults to `options.alpha_col=true`, while CLI defaults to `false` unless `--alpha-col` is specified.
## MCP Server (stdio)
diff --git a/docs/README.en.md b/docs/README.en.md
index d47dcc8..996dcab 100644
--- a/docs/README.en.md
+++ b/docs/README.en.md
@@ -55,11 +55,14 @@ exstruct input.xlsx --format toon # TOON (needs python-toon)
exstruct input.xlsx --sheets-dir sheets/ # split per sheet in chosen format
exstruct input.xlsx --auto-page-breaks-dir auto_areas/ # COM only; option appears when available
exstruct input.xlsx --print-areas-dir areas/ # split per print area (if any)
+exstruct input.xlsx --alpha-col # output column keys as A, B, ..., AA
exstruct input.xlsx --mode light # cells + table candidates only
exstruct input.xlsx --pdf --image # PDF and PNGs (Excel required)
```
Auto page-break exports are available via API and CLI when Excel/COM is available; the CLI exposes `--auto-page-breaks-dir` only in COM-capable environments.
+By default, CLI keeps legacy 0-based numeric string column keys (`"0"`, `"1"`, ...). Use `--alpha-col` to emit Excel-style column keys (`"A"`, `"B"`, ...).
+Note: MCP `exstruct_extract` defaults to `options.alpha_col=true`, while CLI defaults to `false` unless `--alpha-col` is specified.
## MCP Server (stdio)
diff --git a/docs/README.ja.md b/docs/README.ja.md
index 328597e..ac01981 100644
--- a/docs/README.ja.md
+++ b/docs/README.ja.md
@@ -52,11 +52,14 @@ exstruct input.xlsx --format yaml # YAML(pyyaml が必要)
exstruct input.xlsx --format toon # TOON(python-toon が必要)
exstruct input.xlsx --sheets-dir sheets/ # シートごとに分割出力
exstruct input.xlsx --auto-page-breaks-dir auto_areas/ # COM 限定(利用可能な環境のみ表示)
+exstruct input.xlsx --alpha-col # 列キーを A, B, ..., AA 形式で出力
exstruct input.xlsx --mode light # セル+テーブル候補のみ
exstruct input.xlsx --pdf --image # PDF と PNG(Excel 必須)
```
自動改ページ範囲の書き出しは API/CLI 両方に対応(Excel/COM が必要)し、CLI は利用可能な環境でのみ `--auto-page-breaks-dir` を表示します。
+CLI の既定では列キーは従来どおり 0 始まりの数値文字列(`"0"`, `"1"`, ...)です。Excel 形式(`"A"`, `"B"`, ...)が必要な場合は `--alpha-col` を指定してください。
+注意: MCP の `exstruct_extract` は `options.alpha_col=true` が既定で、CLI の既定(`false`)とは異なります。
## MCPサーバー (標準入出力)
diff --git a/docs/agents/FEATURE_SPEC.md b/docs/agents/FEATURE_SPEC.md
index c78a1bf..3d210a2 100644
--- a/docs/agents/FEATURE_SPEC.md
+++ b/docs/agents/FEATURE_SPEC.md
@@ -1,697 +1 @@
# Feature Spec for AI Agent (Phase-by-Phase)
-
-本ドキュメントは、ExStruct MCP に新規追加する編集ツール `exstruct_patch` の MVP 仕様を定義します。
-
----
-
-## 1. 目的・スコープ
-
-- **MVP対象**: セル値更新 / 数式更新 / 新規シート追加
-- **非対象**: 図形・チャート編集、大規模レイアウト変更
-- **再計算**: 行わない(Excel側の再計算に委ねる)
-
----
-
-## 2. ツールI/F定義(OpenAPI / Pydantic想定)
-
-### Tool名
-
-- `exstruct_patch`
-
-### Input
-
-- `xlsx_path: str`
-- `ops: list[PatchOp]`
-- `out_dir: str | None`
-- `out_name: str | None`
-- `on_conflict: "overwrite" | "skip" | "rename" | None`
-- `auto_formula: bool`(default: false)
-
-### Output
-
-- `out_path: str`
-- `patch_diff: list[PatchDiffItem]`
-- `warnings: list[str]`
-- `error: PatchErrorDetail | null`
-
----
-
-## 3. 操作種別(PatchOp)
-
-### set_value
-
-- `op: "set_value"`
-- `sheet: str`
-- `cell: str` (A1形式)
-- `value: str | int | float | None`(nullでクリア)
-
-### set_formula
-
-- `op: "set_formula"`
-- `sheet: str`
-- `cell: str` (A1形式)
-- `formula: str`(必ず `=` から開始)
-
-### add_sheet
-
-- `op: "add_sheet"`
-- `sheet: str`(新規シート名)
-
----
-
-## 4. バリデーション規則
-
-- `xlsx_path`
- - 存在するファイルであること
- - 許可パス内であること(PathPolicy)
- - 拡張子は `.xlsx` / `.xlsm` / `.xls`(`.xls` は COM 利用可能環境のみ)
-- `sheet`
- - 空文字禁止
- - `add_sheet` は既存名と重複禁止
- - `set_value` / `set_formula` は存在シートのみ
-- `cell`
- - A1形式を必須(例: `B3`)
-- `set_value`
- - `value` が `=` から始まる場合は通常は拒否
- - `auto_formula=true` のときは `set_formula` 相当として処理
-- `set_formula`
- - `formula` は必ず `=` から開始
-
----
-
-## 5. 実行セマンティクス
-
-- opsは **順序通り** に評価・適用
-- **全て成功した場合のみ保存**(原子性)
-- 失敗時は **Excelを変更せずエラー** を返す
-- `add_sheet` 実行後にのみ、そのシートへの `set_value` / `set_formula` を許可
-
----
-
-## 6. 出力差分(patch_diff)
-
-最低限の構造:
-
-- `op: "set_value" | "set_formula" | "add_sheet"`
-- `op_index: int`
-- `sheet: str`
-- `cell: str | null`
-- `before: PatchValue | null`
-- `after: PatchValue | null`
-- `status: "applied" | "skipped"`
-
-`PatchValue`:
-
-- `kind: "value" | "formula" | "sheet"`
-- `value: str | int | float | null`
-
-`PatchErrorDetail`:
-
-- `op_index: int`
-- `op: "set_value" | "set_formula" | "add_sheet"`
-- `sheet: str`
-- `cell: str | null`
-- `message: str`
-
----
-
-## 7. バックエンド方針
-
-- **Windows + COM利用可能**: COM優先
-- **それ以外**: openpyxl
-- openpyxl使用時は、図形/チャート等の保持制限を `warnings` で通知
-
----
-
-## 8. 競合ポリシー
-
-- `on_conflict` 未指定時は **サーバー起動時の `--on-conflict` 設定値** を既定値とする
-- `skip` の場合:
- - `patch_diff` は空配列
- - `warnings` にスキップ理由を記載
-
-出力名の既定:
-
-- `out_name` 未指定時は `"{stem}_patched{suffix}"`
-
----
-
-## 9. エラー処理
-
-- パス違反 / セル不正 / 数式不正: `ValueError`
-- シート不在 / 操作不正: `PatchErrorDetail` を `error` に格納
-- 読み込み不能: `FileNotFoundError` / `OSError`
-- バックエンド例外: `RuntimeError`
-
----
-
-## 10. 例
-
-### set_value
-
-```json
-{
- "xlsx_path": "book.xlsx",
- "ops": [
- {
- "op": "set_value",
- "sheet": "フォーム",
- "cell": "B2",
- "value": "山田太郎"
- }
- ]
-}
-```
-
-### set_formula
-
-```json
-{
- "xlsx_path": "book.xlsx",
- "ops": [
- {
- "op": "set_formula",
- "sheet": "計算",
- "cell": "C10",
- "formula": "=SUM(Sheet1!A:A)"
- }
- ]
-}
-```
-
-### add_sheet
-
-```json
-{
- "xlsx_path": "book.xlsx",
- "ops": [
- { "op": "add_sheet", "sheet": "売上集計" },
- { "op": "set_value", "sheet": "売上集計", "cell": "A1", "value": "月" }
- ]
-}
-```
-
----
-
-## 11. レビュー対応仕様(MVP修正)
-
-### 11.1 `on_conflict` 既定値の統一
-
-- サーバーCLI引数 `--on-conflict` の既定値・指定値は、`exstruct_extract` と `exstruct_patch` の双方に同一に適用する
-- `exstruct_patch` で固定値 `rename` を持たない
-- ツール呼び出しで `on_conflict` が未指定の場合:
- - サーバー起動時の `--on-conflict` を適用
-- ツール呼び出しで `on_conflict` が指定された場合:
- - ツール引数を最優先する
-
-### 11.2 出力ディレクトリ生成の明確化
-
-- `exstruct_patch` は保存前に `out_path.parent.mkdir(parents=True, exist_ok=True)` 相当を実行する
-- `out_dir` が存在しない場合でも保存可能にする
-
-### 11.3 `.xls` サポート条件の明確化
-
-- `.xls` は **COM利用可能環境のみ編集対象** とする
-- COM利用不可時の `.xls` は `ValueError` を返す(メッセージで「COM必須」を明示)
-- バリデーション規則の拡張子記述を次に更新する:
- - `.xlsx` / `.xlsm`: 常時対象
- - `.xls`: 条件付き対象(Windows + COM)
-
-### 11.4 後方互換性
-
-- 既存の `PatchOp` / `PatchResult` スキーマは変更しない
-- 変更はデフォルト解決順序・保存前処理・エラーメッセージの明確化に限定する
-
-### 11.5 テスト要件(レビュー対応分)
-
-- `exstruct_patch` で `on_conflict` 未指定時にサーバー既定値が反映されること
-- `exstruct_patch` で `on_conflict` 指定時にツール引数が優先されること
-- 未作成 `out_dir` 指定で保存成功すること
-- `.xls` + COM不可時に期待どおり `ValueError` となること(メッセージ確認を含む)
-
----
-
-## 12. 次フェーズ仕様(便利機能 1〜5)
-
-### 12.1 対象機能
-
-- `dry_run`(非破壊プレビュー)
-- `undo` 用逆パッチ生成
-- 範囲操作(値一括設定 / 数式フィル)
-- 条件付き更新(CAS)
-- 数式ヘルスチェック
-
-### 12.2 ツールI/F拡張
-
-`exstruct_patch` の Input に以下を追加:
-
-- `dry_run: bool = false`
-- `return_inverse_ops: bool = false`
-- `preflight_formula_check: bool = false`
-
-`exstruct_patch` の Output に以下を追加:
-
-- `inverse_ops: list[PatchOp]`(default: `[]`)
-- `formula_issues: list[FormulaIssue]`(default: `[]`)
-
-`FormulaIssue`:
-
-- `sheet: str`
-- `cell: str`
-- `level: "warning" | "error"`
-- `code: "invalid_token" | "ref_error" | "name_error" | "div0_error" | "value_error" | "na_error" | "circular_ref_suspected"`
-- `message: str`
-
-### 12.3 操作種別拡張(PatchOp)
-
-#### set_range_values
-
-- `op: "set_range_values"`
-- `sheet: str`
-- `range: str`(A1範囲形式、例: `B2:D4`)
-- `values: list[list[str | int | float | None]]`
-- `shape(values)` と `range` サイズが一致しない場合は `ValueError`
-
-#### fill_formula
-
-- `op: "fill_formula"`
-- `sheet: str`
-- `range: str`(縦または横の連続範囲)
-- `base_cell: str`
-- `formula: str`(`=` 始まり)
-- `formula` を `base_cell` に置いたときの相対参照を、`range` 内に展開する
-
-#### set_value_if
-
-- `op: "set_value_if"`
-- `sheet: str`
-- `cell: str`
-- `expected: str | int | float | None`
-- `value: str | int | float | None`
-- 現在値が `expected` と一致した場合のみ更新
-- 不一致時は `PatchDiffItem.status="skipped"` とし、`warnings` に理由を追加
-
-#### set_formula_if
-
-- `op: "set_formula_if"`
-- `sheet: str`
-- `cell: str`
-- `expected: str | int | float | None`
-- `formula: str`(`=` 始まり)
-- 条件判定は `set_value_if` と同様
-
-### 12.4 実行セマンティクス(追加)
-
-- `dry_run=true` の場合:
- - 保存しない
- - `patch_diff` / `warnings` / `formula_issues` / `inverse_ops` のみ返す
- - `out_path` は保存予定パスを返す
-- `return_inverse_ops=true` の場合:
- - `applied` な変更のみ逆操作を生成する
- - 逆操作順は「適用順の逆順」とする
-- `preflight_formula_check=true` の場合:
- - 適用後ワークブックを走査し `formula_issues` を返す
- - `level=error` がある場合の扱い:
- - `dry_run=false`: 変更は保存せず `error` を返す
- - `dry_run=true`: 保存なしのため `error` は返さず、問題一覧のみ返す
-
-### 12.5 バリデーション規則(追加)
-
-- `range` は A1 範囲形式(例: `A1:C3`)必須
-- `fill_formula.range` は単一行または単一列のみ(MVP制約)
-- 条件付き更新の `expected` 比較は「内部正規化後の値一致」で判定
-- `set_value_if` で `value` が `=` 始まりかつ `auto_formula=false` の場合は既存 `set_value` と同様に拒否
-
-### 12.6 後方互換性
-
-- 既存 `set_value` / `set_formula` / `add_sheet` の仕様は変更しない
-- 新規フィールドは optional 追加のみで、既存クライアントを破壊しない
-
-### 12.7 受け入れ基準
-
-- `dry_run=true` でファイル更新時刻が変化しない
-- `return_inverse_ops=true` で、逆パッチ適用により元状態へ戻せる
-- `set_range_values` がサイズ不一致を検知できる
-- `set_value_if` / `set_formula_if` が不一致時に `skipped` を返せる
-- `preflight_formula_check=true` で `#REF!` 等を検出して `formula_issues` に反映できる
-
----
-
-## 13. ABC列名キー出力オプション(`alpha_col`)
-
-### 13.1 背景・目的
-
-AIエージェントがExStruct MCPで抽出した結果をもとに `exstruct_patch` でセル編集を行う際、
-`CellRow.c` のキーが 0-based 数値文字列(`"0"`, `"12"`, `"18"` 等)のため、
-Excel上の列名(A, M, S 等)との対応が直感的に取れず、**誤ったセル座標への書き込みが頻発する**。
-
-本機能は、抽出結果の `CellRow.c` キーを Excel 列名形式(A, B, ..., Z, AA, AB, ...)で
-出力するオプションを提供し、AIエージェントの座標理解精度を大幅に改善する。
-
-### 13.2 スコープ
-
-- **対象**: `CellRow.c` のキー、`CellRow.links` のキー
-- **非対象**: `MergedCells.items` / `PrintArea` / `formulas_map` / `colors_map` の列インデックス(整数のまま)
-- **変換方式**: 0-based 数値 → Excel列名(`0` → `A`, `1` → `B`, `25` → `Z`, `26` → `AA`)
-
-### 13.3 I/F
-
-#### 本体 API(`ExStructEngine` / `extract()` / `process_excel()`)
-
-- `StructOptions` に `alpha_col: bool = False` を追加
-- `True` の場合、抽出結果の `CellRow.c` / `CellRow.links` のキーを ABC 形式に変換する
-
-#### CLI
-
-- `--alpha-col` フラグを追加(`action="store_true"`)
-- `process_excel()` に `alpha_col` パラメータを追加
-
-#### MCP ツール(`exstruct_extract`)
-
-- `ExtractOptions` に `alpha_col: bool = False` を追加
-- `ExtractToolInput.options.alpha_col` をエンジンに連携
-
-### 13.4 変換ユーティリティ
-
-- `exstruct.models.col_index_to_alpha(index: int) -> str` を新設
- - 0-based 整数 → Excel 列名文字列
- - 例: `0` → `"A"`, `25` → `"Z"`, `26` → `"AA"`, `701` → `"ZZ"`
-- `exstruct.models.convert_row_keys_to_alpha(row: CellRow) -> CellRow` を新設
- - `CellRow` の `c` / `links` キーを一括変換した新しい `CellRow` を返す
-- `exstruct.models.convert_sheet_keys_to_alpha(sheet: SheetData) -> SheetData` を新設
- - `SheetData.rows` 内の全 `CellRow` を変換した新しい `SheetData` を返す
-
-### 13.5 変換タイミング
-
-- `extract_workbook()` でデータ抽出が完了した **後**、シリアライズの **前** に変換する
-- パイプライン上の位置: `ExStructEngine.extract()` の返却直前
-
-### 13.6 出力例
-
-#### `alpha_col=False`(デフォルト: 従来通り)
-
-```json
-{ "r": 6, "c": { "0": "氏 名", "12": "生年月日", "18": "年" } }
-```
-
-#### `alpha_col=True`
-
-```json
-{ "r": 6, "c": { "A": "氏 名", "M": "生年月日", "S": "年" } }
-```
-
-### 13.7 後方互換性
-
-- デフォルト `False` のため、既存の出力は一切変更されない
-- `alpha_col=True` は opt-in のみ
-- `_safe_col_index()` 等の下流処理は数値キーを前提としているが、変換はシリアライズ直前のため影響なし
-
-### 13.8 受け入れ基準
-
-- `col_index_to_alpha(0)` → `"A"`, `col_index_to_alpha(25)` → `"Z"`, `col_index_to_alpha(26)` → `"AA"`
-- `alpha_col=True` で抽出した `CellRow.c` のキーがすべて A-Z 形式
-- `alpha_col=True` で `CellRow.links` のキーも同様に変換される
-- `alpha_col=False`(デフォルト)で従来通り数値キー
-- CLI `--alpha-col` フラグが正しく `process_excel()` に伝播する
-- MCP `exstruct_extract` の `options.alpha_col` がエンジンに伝播する
-
-### 13.9 `merged_ranges` 出力(`alpha_col` 時)
-
-#### 背景
-
-`alpha_col=True` 時に `CellRow.c` / `links` は ABC 列名になるため、`merged_cells.items`
-(`(r1, c1, r2, c2, v)` の数値列インデックス)との参照体系が混在する。
-AIエージェントの編集座標推論の一貫性を高めるため、A1形式の `merged_ranges` を別フィールドで出力する。
-
-#### 仕様
-
-- `SheetData` に `merged_ranges: list[str]` を追加する(例: `["A1:C3", "F10:G12"]`)
-- `alpha_col=True` のときのみ `merged_ranges` を生成する
-- `alpha_col=True` では `merged_cells` は出力しない(可読性優先)
-- `alpha_col=False` のときは従来どおり `merged_cells` を出力し、`merged_ranges` は空とする
-
-#### 受け入れ基準(追加)
-
-- `alpha_col=True` かつ `merged_cells` が存在するシートで `merged_ranges` が出力される
-- `merged_ranges` の各要素は `"A1:C3"` 形式で、`items` と同じ範囲を表す
-- `alpha_col=True` では `merged_cells` は出力されない
-- `alpha_col=False` では `merged_ranges` は空(実質非出力)となる
-
----
-
-## 14. `exstruct_patch.ops` 入力スキーマ整合(AIエージェント運用改善)
-
-### 14.1 背景
-
-一部のMCPクライアントは、`ops` を `PatchOp` オブジェクト配列ではなく、
-JSON文字列配列として送信する場合がある。
-この差異により、AIエージェントがツール定義どおりに呼び出しても
-入力バリデーションで失敗するケースがある。
-
-### 14.2 目的
-
-- `exstruct_patch` の受け口を明確化し、実装とツール入力スキーマの体験差を解消する
-- AIエージェントがクライアント差異を意識せず patch を実行できるようにする
-
-### 14.3 入力仕様
-
-- 正式入力: `ops: list[object]`(各要素は `PatchOp` 相当のJSONオブジェクト)
-- 互換入力: `ops: list[str]`(各要素は `PatchOp` オブジェクトを表すJSON文字列)
-- サーバー内部で次を行う:
- - object はそのまま採用
- - string は `json.loads()` で object に変換
- - 変換後に `PatchToolInput`(`ops: list[PatchOp]`)で厳密検証
-
-### 14.4 エラー仕様
-
-- JSON文字列のパース失敗時:
- - `ValueError`
- - メッセージに失敗した `ops[index]` を含める
- - 「object 形式の推奨入力例」を併記する
-- JSONとして有効でもobjectでない場合(配列/数値など):
- - `ValueError`
- - 「JSON object 必須」を明記する
-
-### 14.5 後方互換性
-
-- 既存の object 配列クライアントは変更不要
-- string 配列クライアントはサーバー側で吸収し、破壊的変更を回避する
-- `PatchOp` 自体のスキーマと patch 実行ロジックは変更しない
-
-### 14.6 受け入れ基準
-
-- object 配列入力で従来どおり patch が実行できる
-- JSON文字列配列入力でも patch が実行できる
-- 不正JSON文字列で `ops[index]` を含む明確なエラーが返る
-- object 以外のJSON型入力で「object必須」エラーが返る
-
----
-
-## 15. MCP モード/チャンク指定ガイド改善
-
-### 15.1 背景
-
-MCP運用時、次の迷いが発生しやすい。
-
-- `exstruct_extract.mode` に無効値を入れて失敗する
-- `exstruct_read_json_chunk` で `sheet` 未指定のまま再試行して失敗する
-- `max_bytes` の調整方針が不明でリトライ回数が増える
-- `alpha_col=true` 出力時に `filter.cols` が使いにくい
-
-### 15.2 目的
-
-- モード指定とチャンク指定の「最短成功パターン」を文書化する
-- エラー時に次の行動が分かるメッセージへ改善する
-- `alpha_col=true` でも列フィルタを直感的に使えるようにする
-
-### 15.3 スコープ
-
-- `docs/mcp.md` の実運用ガイド追加
-- `src/exstruct/mcp/server.py` のツールDocstring詳細化
-- `src/exstruct/mcp/chunk_reader.py` のエラーメッセージ改善
-- `src/exstruct/mcp/chunk_reader.py` の `filter.cols` を英字列キー対応
-- 関連テスト追加
-
-### 15.4 仕様
-
-#### 15.4.1 ドキュメント強化(`docs/mcp.md`)
-
-- `validate_input -> extract(standard) -> read_json_chunk` の推奨3ステップを追加
-- `mode` の許容値(`light`/`standard`/`verbose`)と用途を表形式で明記
-- `read_json_chunk` の主要引数(`sheet`, `max_bytes`, `filter`, `cursor`)を具体化
-- エラー/警告ごとの再試行手順を表形式で明記
-
-#### 15.4.2 ツール説明の詳細化(`server.py`)
-
-- `exstruct_extract` Docstringに `mode` の意味と許容値を明記
-- `exstruct_read_json_chunk` Docstringに `filter.rows/cols` の
- 1-based inclusive 仕様と `max_bytes` 調整指針を明記
-
-#### 15.4.3 エラーメッセージ改善(`chunk_reader.py`)
-
-- 大きすぎる生JSONに対するエラー文言を、`sheet`/`filter` 指定例付きへ変更
-- 複数シート時の `sheet` 必須エラーに、利用可能シート名と再実行ヒントを追加
-
-#### 15.4.4 `filter.cols` の英字列キー対応(`chunk_reader.py`)
-
-- 列キーが数値文字列(`"0"`)に加え英字列名(`"A"`, `"AA"`)でも判定可能にする
-- `filter.cols` は従来どおり 1-based inclusive の列番号指定を維持する
-- 英字列名は大文字小文字を区別しない
-
-### 15.5 後方互換性
-
-- 既存の `filter.cols` 数値キー挙動は維持する
-- `read_json_chunk` の入出力スキーマは変更しない
-- 変更はガイド追加・メッセージ改善・列キー判定拡張に限定する
-
-### 15.6 受け入れ基準
-
-- `docs/mcp.md` だけで、初回利用者が mode/chunk 再試行を完了できる
-- `Output is too large` エラーに次アクションが含まれる
-- `Sheet is required when multiple sheets exist` エラーにシート候補が含まれる
-- `filter.cols` が数値キー・英字キー双方で機能する
-- 既存テストと追加テストが通過する
-
----
-
-## 16. 読み取りツール拡張(`read_range` / `read_cells` / `read_formulas`)
-
-### 16.1 背景
-
-`exstruct_read_json_chunk` は汎用性が高い一方、確認作業では以下が冗長になりやすい。
-
-- 範囲取得に `sheet` / `filter` / `cursor` の組み合わせが必要
-- 単発セル確認でもチャンク前提の手順が必要
-- 数式点検で `formulas_map` から座標を手作業で読む必要がある
-
-### 16.2 目的
-
-- `A1:G10` のような直感的指定で値確認できるようにする
-- 指定セル群のピンポイント確認を1コールで完結させる
-- 数式点検を専用ツールで高速化する
-
-### 16.3 スコープ
-
-- 新規MCPツールを3つ追加する
- - `exstruct_read_range`
- - `exstruct_read_cells`
- - `exstruct_read_formulas`
-- 既存の `exstruct_extract` / `exstruct_read_json_chunk` は後方互換を維持し、変更しない
-
-### 16.4 共通方針
-
-- 入力元は `exstruct_extract` で生成された `out_path`(JSON)とする
-- シート選択ルールは `read_json_chunk` と同一
- - `sheet` 指定あり: そのシートを使用
- - `sheet` 省略かつ単一シート: 自動選択
- - `sheet` 省略かつ複数シート: エラー
-- 参照座標はA1形式で統一する
-- `alpha_col=true` 出力(英字キー)と数値キー出力の両方を透過的に扱う
-
-### 16.5 ツールI/F
-
-#### 16.5.1 `exstruct_read_range`
-
-Input:
-
-- `out_path: str`
-- `sheet: str | None = None`
-- `range: str`(A1範囲。例: `A1:G10`)
-- `include_formulas: bool = false`
-- `include_empty: bool = true`
-- `max_cells: int = 10000`
-
-Output:
-
-- `book_name: str | None`
-- `sheet_name: str`
-- `range: str`
-- `cells: list[CellReadItem]`
-- `warnings: list[str]`
-
-`CellReadItem`:
-
-- `cell: str`(A1)
-- `value: str | int | float | bool | None`
-- `formula: str | None`(`include_formulas=true` の場合のみ設定)
-
-#### 16.5.2 `exstruct_read_cells`
-
-Input:
-
-- `out_path: str`
-- `sheet: str | None = None`
-- `addresses: list[str]`(A1セル番地。例: `["J98","J124"]`)
-- `include_formulas: bool = true`
-
-Output:
-
-- `book_name: str | None`
-- `sheet_name: str`
-- `cells: list[CellReadItem]`(入力順を維持)
-- `missing_cells: list[str]`(シート範囲外など)
-- `warnings: list[str]`
-
-#### 16.5.3 `exstruct_read_formulas`
-
-Input:
-
-- `out_path: str`
-- `sheet: str | None = None`
-- `range: str | None = None`(未指定時はシート全体)
-- `include_values: bool = false`
-
-Output:
-
-- `book_name: str | None`
-- `sheet_name: str`
-- `range: str | None`
-- `formulas: list[FormulaReadItem]`
-- `warnings: list[str]`
-
-`FormulaReadItem`:
-
-- `cell: str`(A1)
-- `formula: str`
-- `value: str | int | float | bool | None`(`include_values=true` の場合のみ設定)
-
-### 16.6 バリデーション規則
-
-- `out_path` は存在ファイルかつ許可パス内であること
-- `range` はA1範囲形式であること(`A1:G10`)
-- `addresses` は空配列禁止、各要素がA1セル形式であること
-- `max_cells` は正数で、展開セル数が上限を超えた場合は `ValueError`
-- `exstruct_read_formulas` で `formulas_map` が無い場合:
- - エラーではなく空結果 + `warnings` で `mode=verbose` 推奨を返す
-
-### 16.7 実行セマンティクス
-
-- 1回の呼び出しでJSONを1回だけ読み込み・パースする
-- セル値参照は `sheet.rows[].c` から取得する
-- 数式参照は `sheet.formulas_map` を主データソースとする
-- 返却順:
- - `read_range`: 行優先(top-left -> bottom-right)
- - `read_cells`: 入力順
- - `read_formulas`: セル番地昇順(row, col)
-
-### 16.8 エラー処理
-
-- A1形式不正: `ValueError`
-- シート不在: `ValueError`
-- 複数シートで `sheet` 未指定: `ValueError`(候補名を含める)
-- JSON構造不正: `ValueError`
-
-### 16.9 後方互換性
-
-- 既存ツールの入出力スキーマは変更しない
-- 新規ツール追加のみ(破壊的変更なし)
-- `read_json_chunk` の既存運用はそのまま利用可能
-
-### 16.10 受け入れ基準
-
-- `exstruct_read_range(range="A1:G10")` で70セルを取得できる
-- `exstruct_read_cells(addresses=["J98","J124"])` で2セルを入力順に取得できる
-- `exstruct_read_formulas(range="J2:J201")` で対象範囲の式一覧を取得できる
-- `alpha_col=true/false` どちらのJSONでも同じ結果を返せる
-- 不正A1指定で明確なエラーが返る
-- `uv run task precommit-run` が通過する
diff --git a/docs/agents/TASKS.md b/docs/agents/TASKS.md
index 504b130..f2b0652 100644
--- a/docs/agents/TASKS.md
+++ b/docs/agents/TASKS.md
@@ -1,113 +1,3 @@
# Task List
未完了 [ ], 完了 [x]
-
-- [x] `FEATURE_SPEC.md` に exstruct_patch の詳細仕様(I/F、検証、差分、エラー)を記載
-- [x] `mcp/patch_runner.py` を新設し、`PatchRequest/Result` を定義
-- [x] `mcp/tools.py` に `PatchToolInput/Output` と `run_patch_tool` を追加
-- [x] `mcp/server.py` に `exstruct_patch` 登録を追加
-- [x] パス制御・競合ポリシー・保存ロジックを実装
-- [x] openpyxlベースの適用処理を実装
-- [x] COM利用時の分岐(可能なら)とwarning出力
-- [x] ユニットテスト(非COM)を追加
-
-## レビュー対応タスク(MVP修正)
-
-- [x] `mcp/server.py`: `exstruct_patch` の `on_conflict` 解決で固定 `rename` を廃止し、サーバー既定値(`default_on_conflict`)を利用する
-- [x] `mcp/patch_runner.py`: 保存前に出力先ディレクトリ作成処理を追加する(未作成 `out_dir` 対応)
-- [x] `mcp/patch_runner.py`: `.xls` + COM不可時のエラーメッセージを「COM必須」が明確な文言に調整する
-- [x] `docs/agents/FEATURE_SPEC.md`: 拡張子要件を「`.xls` はCOM利用可能環境のみ」に更新する(本文整合)
-- [x] `tests/mcp/test_server.py`: patch ツールの `on_conflict` 既定値伝播を検証するテストを追加/更新する
-- [x] `tests/mcp/test_patch_runner.py`: 未作成 `out_dir` 保存成功ケースを追加する
-- [x] `tests/mcp/test_patch_runner.py`: `.xls` + COM不可エラーの期待値(型・文言)を追加する
-- [x] `ruff check .` / `mypy src/exstruct --strict` / 関連pytest を実行し、結果を記録する
-
-## 次フェーズタスク(便利機能 1〜5)
-
-- [x] `mcp/patch_runner.py`: `PatchRequest` に `dry_run` / `return_inverse_ops` / `preflight_formula_check` を追加する
-- [x] `mcp/patch_runner.py`: `PatchResult` に `inverse_ops` / `formula_issues` を追加する
-- [x] `mcp/patch_runner.py`: `PatchOp` に `set_range_values` / `fill_formula` / `set_value_if` / `set_formula_if` を追加する
-- [x] `mcp/patch_runner.py`: A1範囲パース・範囲サイズ検証・値行列検証ユーティリティを実装する
-- [x] `mcp/patch_runner.py`: `set_range_values` の openpyxl 実装を追加する
-- [x] `mcp/patch_runner.py`: `fill_formula` の相対参照展開ロジックを実装する(単一行/列制約)
-- [x] `mcp/patch_runner.py`: `set_value_if` / `set_formula_if` の比較・`skipped` 差分出力を実装する
-- [x] `mcp/patch_runner.py`: 逆パッチ生成ロジック(`applied` のみ、逆順)を実装する
-- [x] `mcp/patch_runner.py`: `dry_run=true` で非保存実行に分岐する
-- [x] `mcp/patch_runner.py`: 数式ヘルスチェック(`#REF!` 等)を実装し、`formula_issues` に反映する
-- [x] `mcp/patch_runner.py`: `preflight_formula_check=true` かつ `level=error` の保存抑止ルールを実装する
-- [x] `mcp/tools.py`: `PatchToolInput/Output` の新規フィールドをツールI/Fへ公開する
-- [x] `mcp/server.py`: `exstruct_patch` ツール引数に新規3フラグを追加し、ハンドラへ連携する
-- [x] `docs/agents/FEATURE_SPEC.md`: 実装差分(命名、エラーコード、制約)を最終反映する
-- [x] `tests/mcp/test_patch_runner.py`: `dry_run` 非保存・逆パッチ・範囲操作・条件付き更新・数式検査の単体テストを追加する
-- [x] `tests/mcp/test_tools_handlers.py`: 入出力モデル拡張の受け渡しテストを追加する
-- [x] `tests/mcp/test_server.py`: 新規ツール引数の受け渡しテストを追加する
-- [x] `ruff check .` / `mypy src/exstruct --strict` / 関連pytest を実行し、結果を記録する
-
-## ABC列名キー出力オプション(`alpha_col`)
-
-- [x] `models/__init__.py`: `col_index_to_alpha()` 変換ユーティリティを追加する
-- [x] `models/__init__.py`: `convert_row_keys_to_alpha()` / `convert_sheet_keys_to_alpha()` を追加する
-- [x] `engine.py`: `StructOptions` に `alpha_col: bool = False` を追加する
-- [x] `engine.py`: `ExStructEngine.extract()` で `alpha_col=True` 時に変換を適用する
-- [x] `__init__.py`: `extract()` / `process_excel()` に `alpha_col` パラメータを追加する
-- [x] `cli/main.py`: `--alpha-col` CLI フラグを追加する
-- [x] `mcp/extract_runner.py`: `ExtractOptions` に `alpha_col` を追加し、`process_excel()` へ連携する
-- [x] `mcp/server.py`: `exstruct_extract` ツールに `alpha_col` パラメータを追加する
-- [x] `tests/models/`: `col_index_to_alpha()` の単体テストを追加する
-- [x] `tests/models/`: `convert_row_keys_to_alpha()` / `convert_sheet_keys_to_alpha()` のテストを追加する
-- [x] `tests/engine/`: `alpha_col=True` でのエンジン抽出テストを追加する
-- [x] `tests/cli/`: `--alpha-col` CLI フラグのテストを追加する
-- [x] `tests/mcp/`: MCP extract の `alpha_col` 連携テストを追加する
-- [x] `ruff check .` / `mypy src/exstruct --strict` / 関連pytest を実行し、結果を記録する
-
-## `merged_ranges` 出力(`alpha_col`時)
-
-- [x] `docs/agents/FEATURE_SPEC.md`: `merged_ranges` 仕様に更新する
-- [x] `models/__init__.py`: `SheetData` に `merged_ranges` フィールドを追加する
-- [x] `models/__init__.py`: `alpha_col=True` 変換時に `merged_cells.items` から `merged_ranges` を生成する
-- [x] `models/__init__.py`: `alpha_col=True` 変換時に `merged_cells` を非表示化する
-- [x] `tests/models/test_alpha_col.py`: `merged_ranges` 生成と非生成(alpha_col=False相当)を検証する
-- [x] `tests/engine/test_engine_alpha_col.py`: エンジン経由で `merged_ranges` が出力されることを検証する
-- [x] `uv run task precommit-run` を実行し、静的解析・型検査の通過を確認する
-
-## `exstruct_patch.ops` 入力スキーマ整合(AIエージェント運用改善)
-
-- [x] `docs/agents/FEATURE_SPEC.md`: `ops` の正式入力(object配列)と互換入力(JSON文字列配列)を定義する
-- [x] `mcp/server.py`: `ops` 正規化ヘルパー(object/string両対応)を追加する
-- [x] `mcp/server.py`: `_patch_tool` で正規化済み `ops` を `PatchToolInput` に渡す
-- [x] `mcp/server.py`: 不正JSON時に `ops[index]` と入力例を含むエラー文言を返す
-- [x] `tests/mcp/test_server.py`: `ops` 正規化ヘルパーの単体テスト(成功/失敗)を追加する
-- [x] `tests/mcp/test_server.py`: `exstruct_patch` が JSON文字列配列 `ops` を受理できることを検証する
-- [x] `tests/mcp/test_server.py`: 不正JSON文字列 `ops` が明確な `ValueError` になることを検証する
-- [x] `ruff check src/exstruct/mcp/server.py tests/mcp/test_server.py` を実行し、静的解析を確認する
-- [x] `pytest tests/mcp/test_server.py` を実行し、回帰がないことを確認する
-
-## MCP モード/チャンク指定ガイド改善
-
-- [x] `docs/agents/FEATURE_SPEC.md`: mode/chunk ガイド改善仕様(目的/スコープ/受け入れ基準)を定義する
-- [x] `docs/mcp.md`: 推奨3ステップ(validate/extract/chunk)と mode 比較表を追加する
-- [x] `docs/mcp.md`: chunk パラメータ説明、エラー別リトライ表、cursor利用手順を追加する
-- [x] `src/exstruct/mcp/server.py`: `exstruct_extract` Docstring に mode の許容値と意図を追記する
-- [x] `src/exstruct/mcp/server.py`: `exstruct_read_json_chunk` Docstring に `filter.rows/cols` と `max_bytes` 指針を追記する
-- [x] `src/exstruct/mcp/chunk_reader.py`: 大容量時エラー文言に再実行ヒントを追加する
-- [x] `src/exstruct/mcp/chunk_reader.py`: 複数シート時エラー文言に利用可能シート名を追加する
-- [x] `src/exstruct/mcp/chunk_reader.py`: `filter.cols` を英字列キー(`A`, `AA`)対応に拡張する
-- [x] `tests/mcp/test_chunk_reader.py`: 英字列キー対応と新エラーメッセージのテストを追加する
-- [x] `uv run task precommit-run` を実行し、静的解析・型検査・テスト通過を確認する
-
-## 読み取りツール拡張(`read_range` / `read_cells` / `read_formulas`)
-
-- [x] `docs/agents/FEATURE_SPEC.md`: 新規3ツールのI/F・バリデーション・受け入れ基準を定義する
-- [x] `src/exstruct/mcp/sheet_reader.py`: A1セル/範囲パーサーと共通読み取りロジックを実装する
-- [x] `src/exstruct/mcp/sheet_reader.py`: `read_range`(A1範囲指定)を実装する
-- [x] `src/exstruct/mcp/sheet_reader.py`: `read_cells`(複数セル指定)を実装する
-- [x] `src/exstruct/mcp/sheet_reader.py`: `read_formulas`(数式一覧+任意で値)を実装する
-- [x] `src/exstruct/mcp/tools.py`: `ReadRangeToolInput/Output`、`ReadCellsToolInput/Output`、`ReadFormulasToolInput/Output` を追加する
-- [x] `src/exstruct/mcp/tools.py`: `run_read_range_tool`、`run_read_cells_tool`、`run_read_formulas_tool` を追加する
-- [x] `src/exstruct/mcp/server.py`: `exstruct_read_range`、`exstruct_read_cells`、`exstruct_read_formulas` を登録する
-- [x] `src/exstruct/mcp/server.py`: Docstringに利用例(`A1:G10`、`[\"J98\",\"J124\"]`)を追加する
-- [x] `tests/mcp/test_sheet_reader.py`: A1パース、範囲上限、alpha_col互換、エラー系テストを追加する
-- [x] `tests/mcp/test_tools_handlers.py`: 新規3ツールの入出力ハンドリングテストを追加する
-- [x] `tests/mcp/test_server.py`: 新規3ツールの登録・引数連携テストを追加する
-- [x] `docs/mcp.md`: 新規3ツールの使用手順と推奨フロー(extract→read_*)を追記する
-- [x] `uv run task precommit-run` を実行し、静的解析・型検査・テスト通過を確認する
diff --git a/docs/cli.md b/docs/cli.md
index 60d9e80..12dce58 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -21,6 +21,7 @@ exstruct INPUT.xlsx --format toon # TOON output (needs python-toon)
| `-o, --output PATH` | Output path. Omit to write to stdout. |
| `-f, --format {json,yaml,yml,toon}` | Serialization format (default: `json`). |
| `-m, --mode {light,standard,verbose}` | Extraction detail level.
- light: cells + table candidates + print areas (no COM shapes/charts).
- standard: shapes with text/arrows + charts + print areas.
- verbose: all shapes/charts with size + hyperlinks. |
+| `--alpha-col` | Output column keys as Excel-style names (`A`, `B`, ..., `AA`) instead of 0-based numeric keys (`"0"`, `"1"`, ...). Default: disabled (legacy numeric keys). |
| `--pretty` | Pretty-print JSON (indent=2). |
| `--image` | Render per-sheet PNGs (requires Excel + COM + `pypdfium2`). |
| `--pdf` | Render PDF (requires Excel + COM + `pypdfium2`). |
@@ -59,3 +60,4 @@ exstruct sample.xlsx --pdf --image --dpi 144 -o out.json
- Optional dependencies are lazy-imported. Missing packages raise a `MissingDependencyError` with install hints.
- On non-COM environments, shapes/charts are empty and print areas come from openpyxl; commands still succeed.
- `--sheets-dir` and `--print-areas-dir` accept existing or new directories (created if missing).
+- `--alpha-col` switches row column keys from legacy numeric strings (`"0"`, `"1"`, ...) to Excel-style keys (`"A"`, `"B"`, ...). CLI default is disabled for backward compatibility.