diff --git a/CHANGELOG.md b/CHANGELOG.md index d289981..b43e08c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,26 @@ All notable changes to this project are documented in this file. This changelog ## [Unreleased] +## [0.7.0] - 2026-03-19 + +### Added + +- Added a first-class public workbook editing API under `exstruct.edit`, including public patch/make entrypoints, shared patch-op schema helpers, and edit-owned request/result models. +- Added public editing CLI commands under the existing `exstruct` console script: `patch`, `make`, `ops`, and `validate`. +- Added maintainer-facing editing documentation coverage, including architecture/spec updates, ADR alignment, and agent workflow guidance that closes out issue `#99`. + +### Changed + +- Changed workbook editing layering so `exstruct.edit` is the canonical editing core while MCP remains a host-managed integration and compatibility layer. +- Updated README and docs positioning to clarify canonical usage across Python, CLI, and MCP workflows, including dry-run guidance for editing operations. + +### Fixed + +- Fixed top-level `sheet` fallback handling for workbook editing requests while preserving `op.sheet` precedence. +- Fixed legacy monkeypatch compatibility across `exstruct.mcp.patch_runner` and related compatibility shims by restoring live override visibility and entrypoint precedence coverage. +- Fixed rename-reservation cleanup on openpyxl failure paths so placeholder output files are removed when apply fails. +- Fixed dry-run, backend-selection, and CLI failure wording drift in the docs so it matches current runtime behavior. + ## [0.6.1] - 2026-03-12 ### Added diff --git a/dev-docs/architecture/overview.md b/dev-docs/architecture/overview.md index 1eb12ee..4e202da 100644 --- a/dev-docs/architecture/overview.md +++ b/dev-docs/architecture/overview.md @@ -121,6 +121,7 @@ MCP editing remains the integration layer around the public edit API. - `patch_runner.py` → compatibility facade for maintaining existing import paths and syncing host overrides - `patch/internal.py` → compatibility facade re-exporting edit-owned internal implementation - `patch/service.py` / `patch/runtime.py` / `patch/engine/*` → compatibility shims around `exstruct.edit` +- Legacy monkeypatch compatibility in these shims should prefer live module lookup over copied function aliases, and override precedence should be verified at the highest public compatibility entrypoint. - `patch/ops/openpyxl_ops.py` / `patch/ops/xlwings_ops.py` → legacy op entry points kept for compatibility - `patch/normalize.py` / `patch/specs.py` → op normalization and spec metadata - `shared/a1.py` / `shared/output_path.py` → shared utilities for A1 notation and output paths diff --git a/docs/release-notes/v0.7.0.md b/docs/release-notes/v0.7.0.md new file mode 100644 index 0000000..f35707a --- /dev/null +++ b/docs/release-notes/v0.7.0.md @@ -0,0 +1,43 @@ +# v0.7.0 Release Notes + +This release publishes the workbook editing work completed under issue `#99`, +including the new `exstruct.edit` API surface, the editing CLI, compatibility +follow-ups, and maintainer-facing documentation needed to keep the layering +clear for future changes. + +## Next steps + +Currently, the CLI startup is slow due to issues with the initial implementation, +so we plan to release an update in the near future to improve its performance. + +## Highlights + +- Added a first-class workbook editing API under `exstruct.edit`, including: + - public `patch_workbook()` / `make_workbook()` entrypoints + - public request/result models + - shared patch-op schema discovery helpers +- Added public editing CLI commands under `exstruct`: + - `patch` + - `make` + - `ops` + - `validate` +- Clarified the editing architecture split so `exstruct.edit` is the canonical + core and MCP remains the host-managed integration / compatibility layer. +- Updated public docs to explain canonical usage across Python, CLI, and MCP, + including the recommended `dry_run -> inspect -> apply` workflow and the + `backend="auto"` caveat for same-engine comparisons. +- Added maintainer-facing documentation coverage for editing architecture, + specs, ADR alignment, and agent workflow expectations used during the issue + `#99` closeout. +- Fixed release-significant review follow-ups, including: + - top-level `sheet` fallback while preserving `op.sheet` precedence + - legacy monkeypatch compatibility across compatibility shims + - rename-reservation cleanup on openpyxl failure paths + - dry-run / backend / CLI failure wording drift in docs + +## Notes + +- The legacy extraction CLI invocation (`exstruct INPUT.xlsx ...`) is unchanged. +- MCP tool names and payload shapes remain compatible in `v0.7.0`. +- Patch backend policy remains `auto` / `com` / `openpyxl`; this release does + not change backend selection semantics. diff --git a/mkdocs.yml b/mkdocs.yml index f98c4d4..a153829 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,6 +28,7 @@ nav: - MCP Server: mcp.md - Concept / Why ExStruct?: concept.md - Release Notes: + - v0.7.0: release-notes/v0.7.0.md - v0.6.1: release-notes/v0.6.1.md - v0.6.0: release-notes/v0.6.0.md - v0.5.3: release-notes/v0.5.3.md diff --git a/pyproject.toml b/pyproject.toml index 38c5107..f4d1184 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "exstruct" -version = "0.6.1" +version = "0.7.0" description = "Excel to structured JSON (tables, shapes, charts) for LLM/RAG pipelines" readme = "README.md" license = { file = "LICENSE" } diff --git a/tasks/feature_spec.md b/tasks/feature_spec.md index dba47f9..fe3d38b 100644 --- a/tasks/feature_spec.md +++ b/tasks/feature_spec.md @@ -1,503 +1,44 @@ # Feature Spec -## 2026-03-18 pr #106 codacy and review follow-up +## 2026-03-19 v0.7.0 release closeout ### Goal -- PR `#106` の Codacy warning 1 件と review 指摘を現行実装で再確認し、妥当な文書指摘だけを最小差分で取り込む。 -- workbook editing docs の dry-run guidance と CLI failure wording を、実際の backend selection / exit-code behavior に合わせて補正する。 -- public contract や runtime behavior は変えず、docs-only で整合性を回復する。 +- Publish the `v0.7.0` release-prep artifacts for the workbook editing work delivered through issue `#99`. +- Collapse temporary issue and review logs after moving the only remaining maintainer-facing rule into permanent documentation. +- Keep a compact closeout record that states where permanent information now lives and how the release-prep work was verified. -### Accepted findings +### Permanent destinations -- Codacy warning `docs/api.md:24` は妥当。TOC link fragment 自体は site build では解決されていたが、punctuation を含む heading / anchor の組み合わせが lint と食い違いやすいため、見出し名と TOC を URL-safe な表現へ寄せるのが安全。 -- `docs/mcp.md` の「dry run 後に同じ request を再実行すればよい」という説明は、`backend="auto"` かつ COM 利用可能環境では不正確。`src/exstruct/edit/internal.py` の `_requires_openpyxl_backend()` と `_select_patch_engine()` により、`dry_run` は openpyxl を強制する一方で、実適用は COM に切り替わり得る。 -- `docs/cli.md` の「`patch` は `PatchResult.error` があるときだけ exit 1」という説明は過剰。`src/exstruct/cli/edit.py` の `_run_patch_command()` は JSON parse failure、request validation failure、`OSError` / `RuntimeError` でも stderr を出して exit `1` を返し、その場合 stdout に `PatchResult` JSON は出ない。 +- `CHANGELOG.md` + - Holds the `0.7.0` `Added` / `Changed` / `Fixed` summary for the public release. +- `docs/` + - `docs/release-notes/v0.7.0.md` records the user-facing release narrative for issue `#99`, review follow-ups, and maintainer-facing documentation work. + - `mkdocs.yml` keeps the canonical `Release Notes` navigation entry for `v0.7.0`. +- `dev-docs/architecture/overview.md` + - Records the legacy monkeypatch compatibility precedence note for compatibility shims. +- `dev-docs/specs/` + - No new spec migration was required for this closeout; the existing editing API and CLI specs remain the canonical contract source. +- `dev-docs/adr/` + - No new ADR or ADR update was required; existing `ADR-0006` and `ADR-0007` continue to cover the policy boundary. +- `tasks/feature_spec.md` and `tasks/todo.md` + - Retain only this release-closeout record plus verification, not the historical phase-by-phase work log. -### Chosen constraints +### Constraints -- runtime code、backend selection policy、CLI exit-code semantics 自体は変更しない。 -- dry-run guidance の修正は `docs/cli.md` と `docs/mcp.md` だけでなく、同じ推奨を載せている README 英日と `docs/api.md` にも波及させる。 -- internal spec / task docs にも、`backend="auto"` caveat と CLI stderr failure distinction を反映して再発を防ぐ。 +- Public API / CLI / MCP contracts and backend selection policy remain unchanged in this closeout. +- `README.md` and `docs/index.md` do not gain direct release-note links; `mkdocs.yml` stays the canonical route. +- `uv.lock` is not fully regenerated; only the local `exstruct` package version is aligned to `0.7.0`. -### Test plan +### Verification -- `uv run task build-docs` を実行し、docs build が通ることを確認する。 -- `uv run task precommit-run` を実行する。 -- PR metadata として次を確認する: - - Codacy warning が消えること - - `docs/cli.md` の exit-code wording が現行実装と一致すること - - `docs/mcp.md` / README / `docs/api.md` の dry-run guidance が `backend="auto"` caveat を含むこと +- `uv run task build-docs` +- `uv run task precommit-run` +- `rg -n "0\.7\.0|v0\.7\.0" pyproject.toml uv.lock CHANGELOG.md mkdocs.yml docs/release-notes/v0.7.0.md` +- `rg -n "^## " tasks/feature_spec.md tasks/todo.md` +- `git diff --check -- CHANGELOG.md docs/release-notes/v0.7.0.md mkdocs.yml pyproject.toml uv.lock tasks/feature_spec.md tasks/todo.md dev-docs/architecture/overview.md` ### ADR verdict - `not-needed` -- rationale: docs-only review follow-up であり、public contract / implementation policy の意味変更はない。 - -## 2026-03-18 pr #105 unresolved review follow-up - -### Goal - -- PR `#105` の現時点の未解決レビュー thread を再取得し、妥当なものだけを取り込む。 -- `on_conflict="rename"` の atomic reservation で生じる zero-byte placeholder file が、openpyxl failure path で残らないようにする。 -- legacy monkeypatch compatibility は既存 contract を維持し、妥当でない review は非採用理由を残す。 - -### Accepted findings - -- `src/exstruct/edit/service.py` の `_apply_with_openpyxl()` は `ValueError` / `FileNotFoundError` / `OSError` を素通しで再送出しており、rename reservation 済み output path の zero-byte placeholder cleanup を行わない。 -- `src/exstruct/mcp/patch/service.py` の `_sync_compat_overrides()` から `edit_service.apply_openpyxl_engine` / `apply_xlwings_engine` を差し替える経路は、Python の module global lookup により `edit.service` 内関数実行時にも有効であるため、「captured reference で monkeypatch が効かない」という指摘は現行コードでは不成立。 - -### Chosen constraints - -- public API / CLI / MCP payload shape / backend selection policy は変更しない。 -- cleanup 対象は rename reservation で作った zero-byte placeholder file のみとし、既存の user-managed file は削除しない。 -- invalid 判定の review thread に合わせた実装修正は入れず、既存 monkeypatch regression test を再確認する。 - -### Test plan - -- `tests/edit/test_edit_service.py` に、rename reservation 済み output path で `apply_openpyxl_engine()` が `ValueError` / `FileNotFoundError` / `OSError` を送出したとき placeholder file が cleanup される回帰を追加する。 -- `tests/mcp/patch/test_service.py` の既存 legacy monkeypatch regression を再実行し、`mcp.patch.service` 指摘が再現しないことを確認する。 - -### ADR verdict - -- `not-needed` -- rationale: cleanup bug fix と review validation であり、public contract や architecture policy の意味変更はない。 - -## 2026-03-17 pr #105 review follow-up - -### Goal - -- PR `#105` の未解決レビュー指摘を現行実装で再検証し、妥当なものだけを最小差分で取り込む。 -- edit core の output-path / formula preflight / monkeypatch compatibility / runtime shim backward compatibility を維持する。 -- public MCP guide は stable surface に寄せ、内部実装トポロジは `dev-docs/` に残す。 - -### Accepted findings - -- `src/exstruct/edit/output_path.py` の `next_available_path()` は `exists()` 判定だけで rename 候補を返しており、競合時に同じ候補を返し得る。 -- `src/exstruct/edit/output_path.py` の `next_available_directory()` は helper 単体では policy check より先に `_reserve_directory()` を実行し、副作用順序が逆転している。 -- `src/exstruct/edit/service.py` の preflight formula error attribution は `typed_formula_issues[0]` を採っており、先頭が warning の場合に誤帰属し得る。 -- `src/exstruct/mcp/patch_runner.py` は `edit.runtime` までは `get_com_availability` override を同期するが、`edit.internal` module-global は未同期で、`.xls` path の内部判定を取り逃す。 -- `src/exstruct/mcp/patch/internal.py` と `src/exstruct/mcp/patch/runtime.py` は compatibility shim を名乗る一方で、legacy monkeypatch / `policy=` kwarg surface の一部を落としている。 -- `src/exstruct/mcp/patch/service.py` の compatibility surface は実行上は動くが、legacy boundary より型情報が緩くなっている。 -- `src/exstruct/edit/models.py` / `src/exstruct/edit/runtime.py` / `docs/mcp.md` / `tasks/todo.md` には ownership rename 後の stale wording が残っている。 - -### Chosen constraints - -- public API / CLI / MCP payload shape / backend selection policy は変更しない。 -- runtime shim の `policy` kwarg は legacy import path でのみ維持し、canonical `exstruct.edit.runtime` には持ち込まない。 -- `next_available_path()` の原子的予約で生じる placeholder file は、dry-run や失敗時に cleanup して既存契約を崩さない。 -- `tasks/todo.md` の旧ファイル名は、rename 再現手順として意味がある箇所は維持し、stale な成果記述だけ更新する。 - -### Test plan - -- `tests/edit/test_edit_output_path.py` を追加し、rename path reservation と directory policy ordering を固定する。 -- `tests/edit/test_edit_service.py` に preflight formula issue の warning/error 混在回帰を追加する。 -- `tests/mcp/test_make_runner.py` に `patch_runner.get_com_availability` override が `.xls` make validation まで届く回帰を追加する。 -- `tests/mcp/patch/test_legacy_runner_ops.py` に `mcp.patch.internal.get_com_availability` monkeypatch が legacy make path で効く回帰を追加する。 -- `tests/mcp/patch/test_runtime_shim.py` を追加し、legacy runtime shim の `policy=` kwarg surface を固定する。 - -### ADR verdict - -- `not-needed` -- rationale: compatibility bug fix と documentation cleanup であり、public contract や safety boundary の意味変更はない。 - -## 2026-03-18 issue #99 phase 4 canonical usage documentation - -### Goal - -- issue `#99` の Phase 4 として、Phase 1-3 で確立した編集機能の責務分離を公開文書で canonical usage として明文化する。 -- Python library caller に対しては `exstruct.edit` を前面には出さず、通常の imperative editing は `openpyxl` / `xlwings` が適していることを案内する。CLI には canonical operational / agent interface の役割を持たせ、MCP は host-owned integration / compatibility layer として位置づける。 -- 既存の public API / CLI / MCP contract を変えずに、README / docs landing / API・CLI・MCP guides の導線と語彙を揃える。 - -### Chosen scope - -- 公開 docs の更新対象は README 英日、docs landing、`docs/api.md`、`docs/cli.md`、`docs/mcp.md` とする。 -- internal docs の更新対象は `dev-docs/specs/editing-api.md` と `dev-docs/specs/editing-cli.md` を最低ラインとし、architecture 文書は wording drift があれば補正する。 -- 既存ページの拡張で完了させ、新しい public docs page や nav item は追加しない。 -- docs build verification は今回の完了条件に含めるが、`mkdocs strict`、link checker、docs 専用 CI policy の追加は Phase 4 では扱わない。 - -### Public contract invariants - -- `exstruct.edit` の public import path、`patch_workbook()` / `make_workbook()` / patch-op schema discovery surface は変更しない。 -- CLI の public command surface (`patch`, `make`, `ops`, `validate`) と exit-code / JSON output contract は変更しない。 -- MCP tools (`exstruct_patch`, `exstruct_make` など) の tool 名、payload shape、`PathPolicy` ownership、artifact mirroring behavior は変更しない。 -- backend selection / fallback policy、`PatchResult` shape、warning / error payload shape は変更しない。 - -### Documentation deliverables - -- README 英日: - - extraction-only に見える冒頭説明を、extraction + workbook editing の並立が分かる説明へ寄せる - - 「どの interface を使うか」を短い案内として追加する - - editing CLI に canonical operational / agent interface の説明を添える - - `exstruct.edit` は quick start の主導線にはせず、必要時だけ触れる控えめな記述に留める - - MCP は host-managed / sandboxed integration に向く位置づけであることを冒頭近くで明示する -- `docs/index.md`: - - docs landing から Python API / CLI / MCP の選び方が分かるように再構成する - - extraction API だけでなく editing surface へもトップから誘導する -- `docs/api.md`: - - editing section は advanced/shared-contract surface として控えめに記述し、通常の Python editing には `openpyxl` / `xlwings` が適していることを明記する - - backend capability / known limitations / CLI・MCP との責務分離を追記する -- `docs/cli.md`: - - editing CLI を canonical operational / agent interface と明記する - - `dry_run -> inspect PatchResult/warnings -> apply` の推奨ワークフローを追加する - - local operator tooling と MCP host policy の境界を説明する -- `docs/mcp.md`: - - MCP を public core の代替ではなく integration / compatibility layer として冒頭近くで説明する - - editing 向け agent flow を `dry_run` 前提で再整理する - - MCP-only editing から CLI / Python API への migration note を追加する - -### Internal docs retention - -- `dev-docs/specs/editing-api.md` には、`exstruct.edit` を advanced/shared-contract surface として扱い、通常の Python editing では `openpyxl` / `xlwings` を優先案内する obligation を記録する。 -- `dev-docs/specs/editing-cli.md` には、editing CLI を canonical operational / agent interface として案内し、MCP は host-layer compatibility path であることを public docs でも維持する obligation を記録する。 -- ADR verdict は `not-needed`。既存 ADR-0006 / ADR-0007 が既に role split を記録しており、Phase 4 はその documentation sync だからである。 -- ただし docs policy 自体を新しい恒久ルールとして追加する場合は ADR を再判定する。 - -### Verification requirements - -- `uv run task build-docs` を実行し、docs build が通ることを確認する。 -- `uv run task precommit-run` を実行する。 -- 文書差分として次を確認する: - - README / docs landing が interface selection を一貫して説明する - - API guide が `exstruct.edit` を advanced/shared-contract surface として説明し、通常の Python editing には `openpyxl` / `xlwings` を案内する - - CLI guide が dry-run oriented operational flow を説明する - - MCP guide が integration layer と migration path を説明する - - `README.ja.md` が英語 README の新しい positioning に追従する - -## 2026-03-16 issue #99 phase 3 legacy monkeypatch compatibility follow-up - -### Goal - -- `exstruct.edit` を canonical core のまま維持しつつ、`exstruct.mcp.patch_runner` / `exstruct.mcp.patch.service` の legacy monkeypatch 互換を修復する。 -- `patch_runner.run_patch()` / `run_make()` が `patch_runner.get_com_availability` monkeypatch を実際の engine selection に反映するよう戻す。 -- `mcp.patch.service.run_patch()` / `run_make()` が `mcp.patch.engine.*.apply_*` monkeypatch を経由して edit core に伝播するよう戻す。 - -### Accepted findings - -- `patch_runner._sync_legacy_overrides()` は `mcp.patch.internal` の shim module と `edit.runtime` にしか `get_com_availability` を同期しておらず、直後の `mcp.patch.service._sync_compat_overrides()` が `patch.runtime.get_com_availability` で `edit.runtime` を上書きするため、`patch_runner.get_com_availability` monkeypatch が実効値として失われる。 -- `mcp.patch.service._sync_compat_overrides()` は `exstruct.edit.engine.*` を `edit.service` に注入しているため、`mcp.patch.engine.openpyxl_engine.apply_openpyxl_engine` / `mcp.patch.engine.xlwings_engine.apply_xlwings_engine` を monkeypatch しても `service.run_patch()` / `run_make()` では反映されない。 - -### Chosen constraints - -- `exstruct.edit` 配下へ `exstruct.mcp.*` import は追加しない。 -- 互換優先順位は明示する。 - - `patch_runner.run_*` 経由では `patch_runner.get_com_availability` を canonical source とする。 - - `mcp.patch.service.run_*` を直接呼ぶ場合は `mcp.patch.runtime.get_com_availability` を canonical source とする。 -- `mcp.patch.service.apply_*` monkeypatch 互換は維持したまま、`mcp.patch.engine.*.apply_*` monkeypatch も有効にする。 -- public API / CLI / MCP payload shape / backend policy は変更しない。 - -### Test plan - -- `tests/mcp/test_patch_runner.py` に、`patch_runner.run_patch()` / `run_make()` が `patch_runner.get_com_availability` monkeypatch を保持したまま edit core に到達する回帰を追加する。 -- `tests/mcp/patch/test_service.py` に、`mcp.patch.engine.xlwings_engine.apply_xlwings_engine` と `mcp.patch.engine.openpyxl_engine.apply_openpyxl_engine` の monkeypatch が `service.run_patch()` で効く回帰を追加する。 -- 既存の `service.apply_*` monkeypatch テストは維持し、両 compat surface の共存を確認する。 - -### ADR verdict - -- `not-needed` -- rationale: 既存 compatibility shim の実装修正であり、public contract や safety boundary は変えない。 - -## 2026-03-16 issue #99 phase 3 follow-up edit core decoupling from MCP implementation - -### Goal - -- `src/exstruct/edit/**` から `exstruct.mcp.*` import を排除し、`exstruct.edit` を物理的にも workbook editing の canonical core にする。 -- public API / CLI / MCP tool contract、backend selection/fallback policy、warning/error payload shape、`PathPolicy` safety boundaryは維持したまま、implementation ownership を `edit` 配下へ寄せる。 -- MCP は host path policy と compatibility shim のみを持ち、editing behavior の source of truth にはならない。 - -### Current state - -- `src/exstruct/edit/service.py` は canonical orchestration だが、`PathPolicy` 型を `exstruct.mcp.io` から import し、internal path canonicalization も受け持っている。 -- `src/exstruct/edit/runtime.py` は `exstruct.mcp.patch.internal` を実効実装として参照し、`OnConflictPolicy` / `PathPolicy` も MCP 側から import している。 -- `src/exstruct/edit/errors.py` は `PatchOpError` を `exstruct.mcp.patch.ops.common` から再 export している。 -- `src/exstruct/edit/normalize.py` と `src/exstruct/edit/engine/*` はそれぞれ `exstruct.mcp.shared.a1` と `exstruct.mcp.patch.ops.*` を参照している。 -- `src/exstruct/mcp/patch_runner.py` は compatibility facade だが、core 側がまだ MCP 実装に依存しているため、ownership が完全には反転していない。 - -### Chosen scope - -- acceptance criteria は `rg -n "exstruct\\.mcp" src/exstruct/edit` が 0 件になることとする。 -- `PatchOp`, `PatchRequest`, `MakeRequest`, `PatchResult` など public editing model の shape は変更しない。 -- `edit.service.patch_workbook()` / `make_workbook()` は `policy` kwarg を廃止し、pure core orchestration に戻す。 -- `PathPolicy` による root/deny_glob enforcement と request path canonicalization は `mcp.patch_runner` に集約する。 -- `mcp.patch.internal`, `mcp.patch.ops.*`, `mcp.patch.runtime`, `mcp.patch.service`, `mcp.shared.*` は互換 import path を保つ shim として残してよいが、editing behavior の実体は持たない。 - -### Implementation decisions - -- `src/exstruct/edit/errors.py` に `PatchOpError` の実体を置き、`src/exstruct/mcp/patch/ops/common.py` は re-export shim にする。 -- `src/exstruct/edit/a1.py` に `parse_range_geometry` を含む edit 利用分の A1 helper を集約し、`edit.normalize` は edit-owned helper のみを使う。 -- `src/exstruct/edit/runtime.py` は backend selection / fallback / conflict handling / make seed helper / supported extension / output path helper / large-op warning / range expansionを edit-owned 実装として持ち、`mcp.patch.internal` 依存を外す。 -- `src/exstruct/edit/engine/openpyxl_engine.py` と `xlwings_engine.py` は edit-owned 実装を直接呼ぶ。必要なら `src/exstruct/edit/ops/` を新設し、既存 `mcp.patch.ops.*` から実装を移す。 -- `src/exstruct/mcp/patch_runner.py` は `PathPolicy` を使って request path を許可済み絶対 path に正規化したうえで edit core を呼ぶ。`get_com_availability` monkeypatch も edit-owned runtime/helper に同期する。 -- `src/exstruct/mcp/patch/service.py` / `runtime.py` / `engine/*` / `ops/*` / `internal.py` / `shared/a1.py` / `shared/output_path.py` は、repo 既存テストが依存している import path を維持する互換 shim へ寄せる。 - -### Contract invariants - -- `exstruct.edit` の public import path と `patch_workbook(request)` / `make_workbook(request)` signature は維持する。 -- CLI (`exstruct patch`, `exstruct make`, `exstruct ops`, `exstruct validate`) の引数・JSON 出力・exit code は変更しない。 -- MCP tools (`exstruct_patch`, `exstruct_make`) の入出力 shape、tool 名、artifact mirroring、server default `on_conflict` は変更しない。 -- backend selection / fallback policy と既存 warning / error payload shape は変更しない。 -- repo 既存テストが使っている legacy monkeypatch points (`mcp.patch_runner.get_com_availability`, `mcp.patch.service.apply_*`) は維持する。 - -### Test and verification requirements - -- `tests/edit` に、fresh import で `import exstruct.edit` が MCP side effect に依存しないことと、`src/exstruct/edit/**` に `exstruct.mcp` import が存在しないことを固定する static/architecture test を追加する。 -- `tests/edit` は openpyxl/com/auto fallback/make seed flow/preflight/inverse ops と `PatchOpError` payload shape を core 観点で固定する。 -- `tests/mcp/test_patch_runner.py` / `tests/mcp/test_make_runner.py` は `PathPolicy` root/deny_glob/relative path canonicalization と COM availability override sync を host behavior として維持する。 -- `tests/mcp/patch/test_service.py` / `test_ops.py` / `test_models_internal_coverage.py` は legacy import path と monkeypatch compatibility が維持されることだけを確認する shim test に寄せる。 -- 最終検証は `uv run pytest tests/edit -q`、`uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py tests/mcp/patch -q`、`uv run task precommit-run` とする。 - -### ADR / docs retention - -- ADR verdict は現時点で `not-needed`。ADR-0006 が既に `exstruct.edit` canonical core / MCP host boundary を記録しており、今回の変更はその implementation cleanup だからである。 -- ただし public contract / backend policy / safety boundary / compatibility policy の意味変更が必要になった場合は ADR-0006 更新または新規 ADR を再判定する。 -- 恒久文書の更新対象は `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md` Appendix A、`dev-docs/architecture/overview.md`、`docs/mcp.md` を最低ラインとする。 - -## 2026-03-16 issue #99 phase 3 MCP rewiring to public edit core - -### Goal - -- issue `#99` の Phase 3 として、MCP patch/make 実行経路を `exstruct.edit` 正本の editing core に再配線する。 -- workbook editing の source of truth を `exstruct.edit` に寄せ、MCP は host/integration layer と互換 facade に責務を限定する。 -- public API / CLI / MCP tool contract、`PathPolicy` safety boundary、backend selection/fallback policy は維持したまま内部 ownership を整理する。 - -### Current state - -- `src/exstruct/edit/service.py` の `patch_workbook()` / `make_workbook()` は `exstruct.mcp.patch.service.run_patch()` / `run_make()` を `policy=None` で呼ぶだけの薄い wrapper である。 -- `src/exstruct/mcp/tools.py` の `run_patch_tool()` / `run_make_tool()` は `PatchRequest` / `MakeRequest` を組み立てて `exstruct.mcp.patch_runner.run_patch()` / `run_make()` に委譲している。 -- `src/exstruct/mcp/patch_runner.py` は `service.run_patch()` / `run_make()` に委譲する互換 facade であり、`get_com_availability` monkeypatch 伝播だけを自前で持っている。 -- editing model の実体は依然として `src/exstruct/mcp/patch/models.py` にあり、`src/exstruct/edit/models.py` はそれを再 export している。 -- `src/exstruct/mcp/patch/runtime.py` と `src/exstruct/mcp/patch/engine/*` は patch/make orchestration の実効依存として残っている。 - -### Chosen scope - -- 今回の canonical core は `edit.models` / `edit.runtime` / `edit.engine.*` / `edit.service` までを対象とする。 -- 低レベル op 実装 (`mcp.patch.internal`, `mcp.patch.ops.*`) は Phase 3 では全面移管しない。必要最小限の import 差し替えで edit-backed engine から再利用する。 -- `mcp.patch.models` / `runtime` / `engine.*` / `service` / `patch_runner` は backward compatibility を維持する shim として残す。 -- `mcp.tools` / `mcp.server` は host 責務のみを維持し、tool payload shape、artifact mirroring、thread offload、server default `on_conflict` を保持する。 - -### Contract invariants - -- `exstruct.edit` の public import path は維持する。 -- `PatchOp`, `PatchRequest`, `MakeRequest`, `PatchResult`, `PatchDiffItem`, `PatchErrorDetail`, `FormulaIssue` は `exstruct.edit` と `exstruct.mcp.patch_runner` の両方から引き続き import 可能にする。 -- CLI (`exstruct patch`, `exstruct make`, `exstruct ops`, `exstruct validate`) の引数・JSON 出力・exit code は変更しない。 -- MCP tools (`exstruct_patch`, `exstruct_make`) の入出力 shape、tool 名、`mirror_artifact`, `mirrored_out_path`, server default `on_conflict` 挙動は変更しない。 -- `PathPolicy` は引き続き MCP host-owned behavior とし、`exstruct.edit` の public API には持ち込まない。 -- backend selection / fallback policy と既存 warning / error payload shape は変更しない。 - -### Implementation decisions - -- `src/exstruct/edit/models.py` に editing models の実体を移し、`src/exstruct/mcp/patch/models.py` は edit models を再 export する互換 module に変える。 -- `src/exstruct/edit/runtime.py` を新設または同等の ownership 移管で、path-policy 非依存な runtime helper を保持する。MCP 固有の path 解決はここに置かない。 -- `src/exstruct/edit/engine/openpyxl_engine.py` と `src/exstruct/edit/engine/xlwings_engine.py` を canonical engine boundary にし、既存 `mcp.patch.ops.*` を内部 backend adapter として呼ぶ。 -- `src/exstruct/edit/service.py` が patch/make orchestration の正本となり、`src/exstruct/mcp/patch/service.py` は request を edit core に流す wrapper にする。 -- `src/exstruct/mcp/patch_runner.py` は `PathPolicy` を使って request path を許可済み絶対 path に正規化し、その後で edit core を呼ぶ。`get_com_availability` の monkeypatch も edit runtime に同期する。 -- `src/exstruct/mcp/tools.py` は request/result tool model の変換と artifact mirroring を担当し続けるが、editing behavior 自体は持たない。 - -### Test and verification requirements - -- `tests/edit/test_api.py` は public API の成功経路に加えて、editing models の ownership が `edit` 側へ寄った後も import compatibility が保たれることを検証する。 -- patch/make orchestration の主要回帰は `tests/edit` 側に移し、backend auto/com/openpyxl、fallback、formula preflight、make seed flow を core 観点で固定する。 -- `tests/mcp/test_patch_runner.py` / `tests/mcp/test_make_runner.py` は `PathPolicy` による root/deny_glob と相対 path 解決、legacy monkeypatch override を固定する shim test として維持する。 -- `tests/mcp/test_tools_handlers.py` / `tests/mcp/test_server.py` は tool payload 変換、default `on_conflict`、artifact mirroring、thread offload など host behavior の不変性を確認する。 -- `tests/mcp/patch/test_models_internal_coverage.py` は `mcp.patch.models` が `edit.models` の互換 facade であることを確認する方向へ更新する。 -- 最終検証は `uv run pytest tests/edit -q`、`uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py -q`、`uv run pytest tests/mcp/patch -q`、`uv run task precommit-run` とする。 - -### ADR / docs retention - -- 現時点の ADR verdict は `not-needed`。理由は ADR-0006 が既に「public edit API を正本、MCP は host boundary」という方針を記録しており、Phase 3 はその内部実装寄せだからである。 -- ただし implementation 中に public contract、backend policy、safety boundary、MCP payload shape のいずれかを変更する必要が出た場合は、ADR-0006 更新または新規 ADR を再判定する。 -- 恒久文書の更新対象は `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md` Appendix A、`dev-docs/architecture/overview.md`、`docs/mcp.md` を最低ラインとする。 - -## 2026-03-16 pr #103 unresolved review follow-up - -### Goal - -- issue `#99` の現行 PR `#103` に残っている未解決 review thread を確認し、妥当なものだけを最小差分で取り込む。 -- editing CLI の失敗契約を維持し、internal invariant break が起きても traceback ではなく `stderr` エラー + exit `1` に収束させる。 -- legacy extraction entrypoint を維持し、bare token が edit subcommand 名と衝突する場合でも既存ファイル入力を優先できるようにする。 - -### Accepted finding - -- `src/exstruct/cli/edit.py` の `_load_patch_ops()` は `resolve_top_level_sheet_for_payload()` の defensive guard で `TypeError` を投げており、`patch` / `make` の caller 側 catch 範囲から外れている。 -- `dev-docs/specs/editing-cli.md` は JSON parse / validation / local I/O failure を CLI error + exit `1` と規定しており、同モジュール内の invariant guard だけ例外挙動が異なる理由はない。 -- `src/exstruct/cli/main.py` の first-token dispatch は `patch` / `make` / `ops` / `validate` と同名の既存ファイル入力を edit CLI に誤送しうるため、legacy extraction compatibility の要件と衝突する。 -- 既存回帰テストは `patch.xlsx` のような非衝突ケースしか見ておらず、command-name collision を防げない。 -- explicit edit syntax の判定は `--input=book.xlsx` のような `--flag=value` 形式を見落としており、同名ファイルが存在すると valid な edit invocation を extraction に誤送しうる。 - -### Chosen constraints - -- public CLI surface と exit-code policy は変更しない。 -- defensive guard は `TypeError` 拡張ではなく `ValueError` に統一し、既存の user-facing error path に載せる。 -- 回帰テストは monkeypatch で helper 契約破壊を注入し、`patch` と `make` の双方で clean failure を確認する。 -- edit dispatch は bare token だけではなく edit 固有シグナルも見て判定し、既存ファイル名との衝突時は extraction を優先する。 -- explicit edit syntax には `--flag value` だけでなく `--flag=value` の long-option form も含める。 - -## 2026-03-15 tasks document cleanup - -### Goal - -- `tasks/feature_spec.md` と `tasks/todo.md` から、完了済みの過去 task section を除去する。 -- 恒久情報は `dev-docs/`、`docs/`、`AGENTS.md`、既存 ADR に残し、tasks には今回の棚卸し結果だけを残す。 - -### Retained references - -- ADR: `dev-docs/adr/ADR-0001-extraction-mode-boundaries.md`, `dev-docs/adr/ADR-0002-rich-backend-fallback-policy.md`, `dev-docs/adr/ADR-0003-output-serialization-omission-policy.md`, `dev-docs/adr/ADR-0004-patch-backend-selection-policy.md`, `dev-docs/adr/ADR-0005-path-policy-safety-boundary.md` -- Internal specs: `dev-docs/specs/excel-extraction.md`, `dev-docs/specs/adr-index.md`, `dev-docs/specs/adr-review.md`, `dev-docs/testing/test-requirements.md` -- Agent governance: `dev-docs/agents/adr-governance.md`, `dev-docs/agents/adr-criteria.md`, `dev-docs/agents/adr-workflow.md`, `AGENTS.md` -- Public docs: `docs/api.md`, `docs/cli.md`, `docs/mcp.md`, `docs/release-notes/v0.6.1.md`, `CHANGELOG.md` - -### ADR verdict - -- `adr-suggester`: `not-needed` -- rationale: tasks 側に残っていたのは完了済みタスクの仕様メモと作業ログであり、既存恒久文書で説明できない policy-level decision は確認できなかった。 -- `adr-reconciler` audit scope: `ADR-0001`〜`ADR-0005`, `dev-docs/specs/excel-extraction.md`, `dev-docs/testing/test-requirements.md`, `docs/api.md`, `docs/cli.md`, `docs/mcp.md`, `AGENTS.md` -- `adr-reconciler` findings: なし -- next action: `no-action` - -## 2026-03-15 issue #99 phase 1 public edit API - -### Goal - -- Excel editing を `exstruct.edit` から利用できる first-class Python API として公開する。 -- `PatchOp` / `PatchRequest` / `MakeRequest` / `PatchResult` と既存 op 契約を維持したまま、MCP 固有の path policy を public API から外す。 -- MCP は互換レイヤとして維持し、tool I/O と host safety policy を担当し続ける。 - -### Public contract - -- Primary public import path: `exstruct.edit` -- Public entry points: - - `patch_workbook(request: PatchRequest) -> PatchResult` - - `make_workbook(request: MakeRequest) -> PatchResult` -- Public helpers: - - `coerce_patch_ops` - - `resolve_top_level_sheet_for_payload` - - `list_patch_op_schemas` - - `get_patch_op_schema` -- Preserved Phase 1 contract: - - existing op names remain unchanged - - existing warning/error payload shapes remain unchanged - - existing MCP compatibility imports remain valid - -### Boundary - -- `PathPolicy`, artifact mirroring, MCP tool payloads, server defaults, and thread offloading remain MCP-owned behavior. -- Phase 1 intentionally reuses the existing `exstruct.mcp.patch.*` execution pipeline under the hood to reduce backend regression risk while promoting the public API. - -### Permanent references - -- ADR: `dev-docs/adr/ADR-0006-public-edit-api-and-host-boundary.md` -- Internal specs: - - `dev-docs/specs/editing-api.md` - - `dev-docs/specs/data-model.md` - - `dev-docs/architecture/overview.md` -- Public docs: - - `docs/api.md` - - `docs/mcp.md` - -## 2026-03-15 pr #102 review follow-up - -### Goal - -- PR #102 の妥当な review 指摘だけを取り込み、Phase 1 の公開契約を変えずに不整合と正規化漏れを修正する。 -- `coerce_patch_ops` / `resolve_top_level_sheet_for_payload` の JSON-string op 対応を、dict op と同じ indexed error shape で安定化する。 -- ADR-0006 の status metadata を `accepted` に統一し、PR metadata warning は最小範囲で解消する。 - -### Accepted findings - -- `coerce_patch_ops([None])` が `AttributeError` を漏らし、indexed validation error にならない。 -- `resolve_top_level_sheet_for_payload` が JSON-string op を未解決のまま返し、top-level `sheet` fallback を適用できない。 -- `ADR-0006` の本文と index artifacts の status が不一致。 - -### Chosen constraints - -- public API signature と import path は変更しない。 -- invalid op 型の失敗は `ValueError(build_patch_op_error_message(...))` に統一する。 -- docstring warning 対応は、この PR で新規追加した `src/exstruct/edit/*.py` の不足 module docstring 補完までに限定する。 -- PR 本文は `.github/pull_request_template.md` の見出し構造に合わせるが、Acceptance Criteria は issue #99 phase 1 用に書き換える。 - -## 2026-03-15 pr #102 docs review follow-up - -### Goal - -- PR #102 の docs review 指摘のうち、import path 表記の誤りと architecture tree の欠落だけを最小差分で修正する。 -- 永続文書の説明を現行実装と一致させ、Phase 1 の API / runtime 契約自体は変更しない。 - -### Accepted findings - -- `dev-docs/specs/data-model.md` の “actual locations” 先頭 bullet が import path と言いながら filesystem path を示している。 -- `dev-docs/architecture/overview.md` の `edit/` tree に `chart_types.py` と `errors.py` が抜けている。 - -## 2026-03-15 issue #99 phase 2 editing CLI - -### Goal - -- Excel editing を first-class CLI として公開し、`exstruct.edit` を薄く包む operational interface を追加する。 -- 既存の抽出 CLI `exstruct INPUT.xlsx ...` は互換維持し、編集系だけ subcommand を追加する。 -- `PatchResult` と既存 patch op/schema 契約を崩さず、agent 向けに JSON-first な CLI を提供する。 - -### Public contract - -- New CLI subcommands: - - `exstruct patch` - - `exstruct make` - - `exstruct ops list` - - `exstruct ops describe` - - `exstruct validate` -- Chosen Phase 2 boundaries: - - keep legacy extraction CLI entrypoint unchanged - - do not add `exstruct extract` in this phase - - `validate` means input-file readability validation, not patch request static validation - - default output for new edit commands is JSON to stdout -- `patch` contract: - - required flags: `--input`, `--ops` - - optional flags: `--output`, `--sheet`, `--on-conflict`, `--backend`, `--auto-formula`, `--dry-run`, `--return-inverse-ops`, `--preflight-formula-check`, `--pretty` - - `--ops` accepts a top-level JSON array from file or stdin (`-`) - - exit `0` when `PatchResult.error is None`; otherwise emit serialized `PatchResult` and exit `1` -- `make` contract: - - required flag: `--output` - - optional flags: `--ops`, `--sheet`, `--on-conflict`, `--backend`, `--auto-formula`, `--dry-run`, `--return-inverse-ops`, `--preflight-formula-check`, `--pretty` - - omitted `--ops` defaults to `[]` -- `ops` contract: - - `list` returns compact JSON summaries (`op`, `description`) - - `describe` returns detailed schema metadata for one op -- `validate` contract: - - required flag: `--input` - - output shape follows the existing input validation result (`is_readable`, `warnings`, `errors`) - -### Implementation boundary - -- `patch` / `make` / `ops` use `exstruct.edit` as the primary integration surface. -- `validate` may reuse the existing validation logic, but must not require MCP `PathPolicy`. -- Phase 2 does not change: - - backend selection/fallback policy - - patch result schema - - MCP tool payloads or server safety policy -- Phase 2 also excludes: - - backup / confirmation / allow-root / deny-glob flags - - summary-mode output - - request-envelope JSON input - -### ADR verdict - -- `adr-suggester`: `required` -- rationale: public CLI contract and CLI/API/MCP responsibility alignment change at policy level, while legacy extraction CLI compatibility is intentionally preserved. -- existing ADR candidates: - - `ADR-0006-public-edit-api-and-host-boundary` - - `ADR-0005-path-policy-safety-boundary` - - `ADR-0004-patch-backend-selection-policy` -- suggested next action: `new-adr` -- candidate ADR title: `Editing CLI as Public Operational Interface` - -### Permanent references - -- ADR: - - `dev-docs/adr/ADR-0007-editing-cli-as-public-operational-interface.md` -- Internal specs: - - `dev-docs/specs/editing-api.md` - - `dev-docs/specs/editing-cli.md` - - `dev-docs/architecture/overview.md` -- Public docs: - - `docs/cli.md` - - `docs/api.md` - - `README.md` - - `README.ja.md` +- rationale: this was release preparation and task-log retention cleanup. The policy decisions already live in `ADR-0006`, `ADR-0007`, and the editing specs. diff --git a/tasks/todo.md b/tasks/todo.md index 6b36988..a1fb48d 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -1,339 +1,28 @@ # Todo -## 2026-03-18 pr #106 codacy and review follow-up +## 2026-03-19 v0.7.0 release closeout ### Planning -- [x] Codacy issue と PR review comments を取得し、現行実装と照合して妥当性を確認する -- [x] `tasks/feature_spec.md` に accepted findings / constraints / verification を記録する -- [x] `docs/api.md` の TOC / heading wording を URL-safe な形へ調整する -- [x] README 英日、`docs/api.md`、`docs/cli.md`、`docs/mcp.md` の dry-run guidance と CLI failure wording を修正する -- [x] `dev-docs/specs/editing-cli.md` と `tasks/lessons.md` に再発防止ルールを追記する -- [x] `uv run task build-docs` を実行する -- [x] `uv run task precommit-run` を実行する +- [x] Add the `0.7.0` changelog entry with `Added` / `Changed` / `Fixed`. +- [x] Create `docs/release-notes/v0.7.0.md` for issue `#99` and maintainer-facing docs changes. +- [x] Add `v0.7.0` to the `Release Notes` nav in `mkdocs.yml`. +- [x] Align the local package version in `pyproject.toml` and `uv.lock` to `0.7.0`. +- [x] Move the legacy monkeypatch compatibility precedence note to `dev-docs/architecture/overview.md`. +- [x] Compress `tasks/feature_spec.md` and `tasks/todo.md` to a single release-closeout section. +- [x] Run `uv run task build-docs`. +- [x] Run `uv run task precommit-run`. +- [x] Run the release-prep `rg` and `git diff --check` consistency checks. ### Review -- Codacy warning 1 件と review 指摘 2 件を確認した。採用したのは `docs/api.md` の TOC/heading wording、`docs/mcp.md` の `backend="auto"` caveat、`docs/cli.md` の exit-code wording で、いずれも現行コードに照らして妥当だった。 -- `docs/api.md` は TOC と対応見出しを punctuation の少ない wording へ揃え、anchor 解決の曖昧さを減らした。 -- README 英日、`docs/api.md`、`docs/cli.md`、`docs/mcp.md` は、dry run と実適用で同じ engine を前提にしないよう修正した。same-engine 比較が必要な場合は `openpyxl` 固定、`backend="auto"` では `PatchResult.engine` 確認を促す形にした。 -- `docs/cli.md` は、`PatchResult.error` ベースの exit `1` と、JSON parse / validation / local runtime error の stderr exit `1` を区別する説明に修正した。 -- 恒久方針は `dev-docs/specs/editing-cli.md` と `tasks/lessons.md` に反映した。ADR verdict は `not-needed`。 +- `CHANGELOG.md`, `docs/release-notes/v0.7.0.md`, `mkdocs.yml`, `pyproject.toml`, and `uv.lock` now describe and label the `0.7.0` release consistently. +- `dev-docs/architecture/overview.md` now holds the maintainer-facing note that compatibility shims must preserve live monkeypatch visibility and verify override precedence at the highest public entrypoint. +- Historical issue `#99`, PR follow-up, and prior cleanup logs were intentionally removed from `tasks/feature_spec.md` and `tasks/todo.md` after permanent information was classified and retained in `CHANGELOG.md`, `docs/`, and `dev-docs/architecture/`. +- No new `dev-docs/specs/` or `dev-docs/adr/` migration was required for this closeout; `ADR-0006`, `ADR-0007`, and the editing specs remain the canonical permanent sources. - Verification: - `uv run task build-docs` - `uv run task precommit-run` - -## 2026-03-18 pr #105 unresolved review follow-up - -### Planning - -- [x] GitHub から PR `#105` の未解決 review thread を再取得する -- [x] 各指摘を現行コードと既存回帰テストで妥当性確認する -- [x] `src/exstruct/edit/service.py` の openpyxl failure path cleanup を修正する -- [x] `tests/edit/test_edit_service.py` に cleanup 回帰を追加する -- [x] targeted pytest と `uv run task precommit-run` を実行する -- [x] Review section に妥当性判定と残課題を記録する - -### Review - -- 2026-03-18 時点で PR `#105` の未解決 thread は 2 件だった。 -- 採用: `src/exstruct/edit/service.py` の `_apply_with_openpyxl()` で `ValueError` / `FileNotFoundError` / `OSError` 再送出時に zero-byte reservation file cleanup が漏れる指摘。現行コードを確認すると、`PatchOpError` / generic `Exception` / dry-run / preflight error は cleanup 済みだが、この 3 分岐だけ未処理だった。 -- 非採用: `src/exstruct/mcp/patch/service.py` の `_sync_compat_overrides()` が `edit.service` 内の imported engine reference に効かないという指摘。`edit.service` は module global 名を実行時 lookup しており、`service_module.apply_openpyxl_engine = ...` / `apply_xlwings_engine = ...` の再束縛で呼び先は差し替わる。既存 `tests/mcp/patch/test_service.py` の legacy monkeypatch regression もこの解釈と一致して通過した。 -- `src/exstruct/edit/service.py` は `ValueError` / `FileNotFoundError` / `OSError` の各 re-raise 直前にも `_cleanup_empty_reserved_output()` を呼ぶようにした。 -- `tests/edit/test_edit_service.py` には、rename reservation 済み output path で openpyxl path が上記 3 例外を送出したとき placeholder file が残らない回帰を追加した。 -- 恒久仕様や ADR に移すべき新規 policy はなく、この section は session 記録として保持する。 -- Verification: - - `uv run pytest tests/edit/test_edit_service.py -q` - - `uv run pytest tests/mcp/patch/test_service.py -q` - - `uv run task precommit-run` - -## 2026-03-17 pr #105 review follow-up - -### Planning - -- [x] PR `#105` の review threads / inline comments を取得して妥当性を確認する -- [x] `tasks/feature_spec.md` に今回の対応境界と accepted findings を記録する -- [x] `src/exstruct/edit/output_path.py` の rename reservation と directory policy ordering を修正する -- [x] `src/exstruct/edit/service.py` の preflight attribution と fallback hardening を調整する -- [x] `src/exstruct/mcp/patch_runner.py` / `patch/internal.py` / `patch/runtime.py` / `patch/service.py` の互換 surface を修正する -- [x] docs / docstring / `tasks/todo.md` の stale wording を更新する -- [x] 回帰テストと `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/edit/output_path.py` は file rename 候補を原子的に予約するようにし、directory helper は policy check 後に予約する順序へ揃えた。rename 予約で作る placeholder file は `src/exstruct/edit/service.py` 側で dry-run / error 時に cleanup する。 -- `src/exstruct/edit/service.py` は formula preflight で先頭 error issue を採るようにし、COM fallback 判定も `getattr(detail, "error_code", None)` ベースへ harden した。 -- `src/exstruct/mcp/patch_runner.py` は `edit.internal.get_com_availability` まで override を同期するようにし、`src/exstruct/mcp/patch/internal.py` は direct import ではなく wrapper 経由で legacy monkeypatch surface を維持するよう戻した。 -- `src/exstruct/mcp/patch/runtime.py` は legacy shim の `policy=` kwarg surface を wrapper で復元し、`src/exstruct/mcp/patch/service.py` は legacy engine boundary に合わせた型注釈へ戻した。 -- `docs/mcp.md` は stable MCP surface に絞り、内部 layering 詳細は `dev-docs/architecture/overview.md` / `dev-docs/specs/editing-api.md` を参照する形へ整理した。`src/exstruct/edit/models.py` / `src/exstruct/edit/runtime.py` の stale docstring も更新した。 -- `tasks/todo.md` の stale filename 指摘は、rename 再現手順として旧名が必要な箇所は残しつつ、成果記述の `tests/edit/test_service.py` だけ `tests/edit/test_edit_service.py` へ修正した。 -- Review 妥当性判断: - - 採用: output-path 2 件、preflight attribution、`patch_runner` override sync、`patch.internal` legacy override、`patch.runtime` policy kwarg 互換、docs/docstring/stale wording。 - - 参考対応: `exc.detail` guard は現行契約上は必須ではなかったが、低リスクの hardening として取り込んだ。 - - 非対応: `tasks/todo.md` の大規模な historical section pruning は今回の主目的ではなく、恒久情報の取りこぼしも確認できなかったため見送った。 -- Verification: - - `uv run pytest tests/edit/test_edit_output_path.py tests/edit/test_edit_service.py tests/edit/test_architecture.py tests/mcp/test_make_runner.py tests/mcp/patch/test_legacy_runner_ops.py tests/mcp/patch/test_runtime_shim.py -q` - - `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/patch/test_service.py tests/mcp/patch/test_legacy_runner_ops.py tests/mcp/patch/test_runtime_shim.py tests/edit/test_edit_service.py tests/edit/test_edit_output_path.py tests/edit/test_architecture.py -q` - - `uv run task precommit-run` - -## 2026-03-16 issue #99 phase 3 legacy monkeypatch compatibility follow-up - -### Planning - -- [x] `tasks/feature_spec.md` に legacy monkeypatch compatibility 修正方針を記録する -- [x] `patch_runner._sync_legacy_overrides()` で `patch_runner.get_com_availability` を `mcp.patch.runtime` まで同期する -- [x] `mcp.patch.service` を live module lookup ベースの legacy engine wrapper に切り替える -- [x] `tests/mcp/test_patch_runner.py` に `run_patch` / `run_make` の override 回帰を追加する -- [x] `tests/mcp/patch/test_service.py` に legacy engine monkeypatch 回帰を追加する -- [x] `tasks/lessons.md` に compat shim の monkeypatch 設計ルールを追記する -- [x] targeted pytest と `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/mcp/patch_runner.py` は `patch_runner.get_com_availability` を `mcp.patch.runtime` にも同期するようにし、`service._sync_compat_overrides()` を経由しても caller override が失われないようにした。 -- `src/exstruct/mcp/patch/service.py` は `edit.engine.*` の copied alias ではなく、`mcp.patch.engine.*` を live module lookup する wrapper を `edit.service` に注入する形へ切り替えた。 -- これにより `mcp.patch.service.apply_*` monkeypatch と `mcp.patch.engine.*.apply_*` monkeypatch の両方が `service.run_patch()` / `run_make()` 経路で有効になった。 -- `tests/mcp/test_patch_runner.py` と `tests/mcp/test_make_runner.py` に entrypoint override precedence の回帰を追加し、`tests/mcp/patch/test_service.py` に legacy engine monkeypatch 回帰を追加した。 -- `tasks/lessons.md` には compat shim で copied function alias を避け、public entrypoint で override precedence を回帰テスト化するルールを追加した。 -- Verification: - - `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/patch/test_service.py -q` - - `uv run pytest tests/mcp/patch/test_ops.py tests/mcp/patch/test_legacy_runner_ops.py -q` - - `uv run pytest tests/edit -q` - - `uv run task precommit-run` - -## 2026-03-16 issue #99 phase 3 follow-up edit core decoupling from MCP implementation - -### Planning - -- [x] `tasks/feature_spec.md` に `src/exstruct/edit/**` から `exstruct.mcp.*` import を排除する follow-up 仕様を反映する -- [x] `edit.errors` / `edit.a1` / `edit.runtime` / `edit.engine.*` の ownership を edit 配下へ寄せ、edit から MCP import を除去する -- [x] `mcp.patch_runner` 側 path policy 経路を維持したまま、`edit.service` の `policy` 非依存化を完了する -- [x] `mcp.patch.internal` / `ops.*` / `runtime` / `service` を edit-backed compatibility path に整理する -- [x] core test を `tests/edit` に寄せ、MCP 側は shim / host behavior 回帰に絞る -- [x] `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md`、`dev-docs/architecture/overview.md`、`docs/mcp.md` を現行実装に合わせて更新する -- [x] `uv run pytest tests/edit -q` を実行する -- [x] `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py tests/mcp/patch -q` を実行する -- [x] `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/edit/**` から `exstruct.mcp.*` import は排除した。acceptance criteria の `rg -n "exstruct\\.mcp" src/exstruct/edit` は 0 件になった。 -- `src/exstruct/edit/internal.py` を追加し、low-level patch implementation を edit-owned に移した。`edit.runtime` / `edit.service` / `edit.engine.*` はこの edit-owned implementation を使う。 -- `src/exstruct/edit/service.py` は `policy` 非依存の pure core orchestration に戻し、MCP 側の path canonicalization は `src/exstruct/mcp/patch/service.py` の compatibility path で吸収した。 -- `src/exstruct/mcp/patch/internal.py` は `exstruct.edit.internal` の typed compatibility shim に切り替え、repo 既存 tests が使う internal surface は維持した。 -- `tests/edit/test_architecture.py` を追加し、`edit` package の import graph と fresh import での MCP side-effect 非依存を固定した。 -- 恒久文書は `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md`、`dev-docs/architecture/overview.md`、`docs/mcp.md` に反映した。ADR verdict は継続して `not-needed`。 -- Verification: - - `uv run pytest tests/edit -q` - - `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py tests/mcp/patch -q` - - `uv run task precommit-run` - -## 2026-03-16 pytest collect collision follow-up - -### Planning - -- [x] `tests/edit/test_service.py` と `tests/mcp/patch/test_service.py` の collect 衝突を再現確認する -- [x] edit 側 test module basename を一意な名前へ変更する -- [x] `tasks/lessons.md` に pytest test module naming の再発防止ルールを記録する -- [x] collect-only と関連 pytest を再実行して回帰がないことを確認する - -### Review - -- `uv run pytest tests/edit/test_service.py tests/mcp/patch/test_service.py --collect-only -q` で `import file mismatch` を再現し、指摘が妥当であることを確認した。 -- `tests/edit/test_service.py` は `tests/edit/test_edit_service.py` に rename し、`tests/mcp/patch/test_service.py` との basename 衝突を解消した。 -- 恒久ルールは `tasks/lessons.md` に移し、この section は session 記録として保持する。 -- Verification: - - `uv run pytest tests/edit/test_edit_service.py tests/mcp/patch/test_service.py --collect-only -q` - - `uv run pytest tests/edit tests/mcp/patch -q` - - `uv run task precommit-run` - -## 2026-03-18 issue #99 phase 4 canonical usage documentation - -### Planning - -- [x] `tasks/feature_spec.md` に Phase 4 の scope / invariants / docs deliverables / verification を記録する -- [x] README 英日と docs landing を更新し、Python API / CLI / MCP の役割分担を入口で説明する -- [x] `docs/api.md`、`docs/cli.md`、`docs/mcp.md` を更新し、canonical usage / workflow / migration note を揃える -- [x] `dev-docs/specs/editing-api.md` と `dev-docs/specs/editing-cli.md` の wording を同期する -- [x] `uv run task build-docs` を実行する -- [x] `uv run task precommit-run` を実行する - -### Review - -- README 英日と `docs/index.md` を更新し、editing CLI / MCP を主導線にしつつ、Python editing では `openpyxl` / `xlwings` が適していることを入口で分かるようにした。 -- `docs/api.md` は editing API を advanced/shared-contract surface として控えめに扱い、backend capability と known limits を追加した。 -- `docs/cli.md` は editing CLI を canonical operational / agent interface として明示し、`dry_run -> inspect -> apply` フローを追加した。 -- `docs/mcp.md` は MCP を host-managed integration / compatibility layer として冒頭で説明し、editing 向け migration note と dry-run 前提フローへ寄せた。 -- `dev-docs/specs/editing-api.md` と `dev-docs/specs/editing-cli.md` には public docs wording を維持するための documentation obligations を追記した。 -- ADR verdict は `not-needed` を維持した。既存 ADR-0006 / ADR-0007 の方針を文書化した変更であり、新しい policy decision は追加していない。 -- Verification: - - `uv run task build-docs` - - `uv run task precommit-run` - -## 2026-03-16 issue #99 phase 3 MCP rewiring to public edit core - -### Planning - -- [x] `exstruct.edit` を workbook editing の canonical core にする Phase 3 境界を固定する -- [x] `edit.models` を editing model の正本にし、`mcp.patch.models` を互換 shim に切り替える -- [x] `edit.runtime` に backend 選択・conflict handling・make seed orchestration を集約する -- [x] `edit.engine.*` を canonical engine boundary にし、`mcp.patch.engine.*` を互換 shim に寄せる -- [x] `edit.service` に patch/make orchestration を移し、`mcp.patch.service` を edit-backed wrapper に整理する -- [x] `mcp.patch_runner` で `PathPolicy` による path canonicalization と legacy monkeypatch override を吸収する -- [x] `mcp.tools` / `mcp.server` は tool payload、default `on_conflict`、artifact mirroring、thread offload など host 責務のみを維持する -- [x] core test と MCP shim test を分離して回帰を追加する -- [x] `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md`、`dev-docs/architecture/overview.md`、`docs/mcp.md` を現行実装に合わせて更新する -- [x] `uv run pytest tests/edit -q` を実行する -- [x] `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py -q` を実行する -- [x] `uv run pytest tests/mcp/patch -q` を実行する -- [x] `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/edit/models.py` を canonical model 定義に切り替え、`src/exstruct/mcp/patch/models.py` は `edit.models` を再 export する shim に整理した。 -- `src/exstruct/edit/runtime.py` と `src/exstruct/edit/engine/*` を canonical core とし、`src/exstruct/mcp/patch/runtime.py` と `src/exstruct/mcp/patch/engine/*` は互換 shim に寄せた。 -- `src/exstruct/edit/service.py` に patch/make orchestration を置いたまま、public API の `policy` 非公開契約は `src/exstruct/edit/api.py` の wrapper で維持した。 -- `src/exstruct/mcp/patch_runner.py` は `get_com_availability` monkeypatch を `edit.runtime` と legacy internal の両方へ同期する compatibility facade に整理した。 -- `src/exstruct/mcp/patch/service.py` は legacy monkeypatch 先を `edit.service` / `edit.runtime` に伝播する wrapper として残し、既存 test monkeypatch 互換を維持した。 -- `tests/edit/test_edit_service.py` を追加し、COM 優先、auto fallback、make seed flow を core 観点で固定した。既存の `tests/mcp/*` は shim / host behavior 回帰として維持した。 -- 恒久情報は `dev-docs/specs/editing-api.md`、`dev-docs/specs/data-model.md`、`dev-docs/architecture/overview.md`、`docs/mcp.md` に反映済みで、今回の task section は session 記録として保持する。 -- ADR verdict は継続して `not-needed`。内部 ownership 移管であり、public contract / backend policy / safety boundary は変更していない。 -- Verification: - - `uv run pytest tests/edit -q` - - `uv run pytest tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py tests/mcp/test_tools_handlers.py tests/mcp/test_server.py -q` - - `uv run pytest tests/mcp/patch -q` - - `uv run task precommit-run` - -## 2026-03-16 pr #103 unresolved review follow-up - -### Planning - -- [x] issue #99 の現行実装 PR を特定し、未解決 review thread を取得する -- [x] 指摘内容を現行コードと `editing-cli` 仕様に照らして妥当性確認する -- [x] `_load_patch_ops` の defensive guard を CLI 契約に沿う例外型へ揃える -- [x] 回帰テストを追加して `patch` / `make` の failure path を検証する -- [x] command-name collision で legacy extraction が壊れないよう dispatch を調整する -- [x] explicit edit syntax 判定が `--flag=value` form も扱えるようにする -- [x] targeted pytest と `uv run task precommit-run` を実行する - -### Review - -- `harumiWeb/exstruct` には PR `#99` は存在せず、issue `#99` の現行実装 PR `#103` を対象に確認した。着手時点の未解決 thread は 3 件で、いずれも妥当だった。 -- `src/exstruct/cli/edit.py` の `_load_patch_ops()` だけ `TypeError` を投げると `patch` / `make` の clean error path から漏れる余地があったため、`ValueError` に統一した。 -- `_load_patch_ops()` の defensive guard を `ValueError` に統一し、既存の `stderr` エラー + exit `1` 契約に載せた。 -- `tests/cli/test_edit_cli.py` に helper 契約破壊を monkeypatch で注入する回帰テストを追加し、`patch` / `make` の両方で clean failure を確認した。 -- `src/exstruct/cli/edit.py` の dispatch 判定は edit 固有シグナルがない限り既存ファイル名を優先するように調整し、`patch` / `make` / `ops` / `validate` と同名の legacy input を extraction path に戻した。 -- `tests/cli/test_edit_cli.py` に command-name collision の回帰テストと、衝突時でも `--input` / `ops list` / `--help` などの explicit edit syntax が edit CLI を維持するテストを追加した。 -- PR `#104` の追加 review 指摘に対応し、explicit edit syntax 判定は `--input=book.xlsx` / `--ops=ops.json` / `--input=...` の `--flag=value` form も edit CLI として扱うようにした。 -- 永続化が必要な新規仕様や ADR 判断はなく、この task section は session 記録としてのみ保持する。 -- Verification: - - `uv run pytest tests/cli/test_edit_cli.py -q` - - `uv run task precommit-run` - -## 2026-03-15 tasks document cleanup - -### Planning - -- [x] `tasks/feature_spec.md` と `tasks/todo.md` の全 `##` section を棚卸しする -- [x] 既存 `dev-docs/`, `docs/`, `AGENTS.md`, ADR への吸収状況を確認する -- [x] `adr-suggester` と `adr-reconciler` の観点で ADR 追加要否を判定する -- [x] 過去 section を tasks から除去し、現行の cleanup 記録だけを残す -- [x] 差分と参照整合性を検証する - -### Review - -- `tasks/feature_spec.md` と `tasks/todo.md` の過去 section は全削除した。 -- 恒久情報の正本は既存文書に揃っているため、ADR の新規追加・更新は不要だった。 -- 主な恒久参照先: `dev-docs/adr/ADR-0001-extraction-mode-boundaries.md`, `dev-docs/adr/ADR-0002-rich-backend-fallback-policy.md`, `dev-docs/adr/ADR-0003-output-serialization-omission-policy.md`, `dev-docs/adr/ADR-0004-patch-backend-selection-policy.md`, `dev-docs/adr/ADR-0005-path-policy-safety-boundary.md`, `dev-docs/specs/excel-extraction.md`, `dev-docs/testing/test-requirements.md`, `dev-docs/agents/adr-governance.md`, `dev-docs/agents/adr-criteria.md`, `dev-docs/agents/adr-workflow.md`, `docs/api.md`, `docs/cli.md`, `docs/mcp.md`, `docs/release-notes/v0.6.1.md`, `CHANGELOG.md`, `AGENTS.md` -- `adr-suggester` verdict: `not-needed` -- `adr-reconciler` findings: なし -- Verification: `rg -n "^## " tasks/feature_spec.md tasks/todo.md` -- Verification: `git diff --check -- tasks/feature_spec.md tasks/todo.md` - -## 2026-03-15 issue #99 phase 1 public edit API - -### Planning - -- [x] issue #99 の Phase 1 境界を確認し、public API / MCP host boundary を整理する -- [x] `exstruct.edit` の公開面を定義する -- [x] op schema / normalize / type metadata の public import path を追加する -- [x] 既存 MCP compatibility path を維持する -- [x] ADR / internal spec / public docs を更新する -- [x] `uv run task precommit-run` を完走する - -### Review - -- `src/exstruct/edit/` を追加し、`patch_workbook` / `make_workbook` と patch 契約の公開 import path を導入した。 -- `exstruct.edit` は `PathPolicy` を要求せず、既存の patch request/result 契約をそのまま利用する。 -- `src/exstruct/mcp/patch/types.py`, `chart_types.py`, `specs.py`, `normalize.py`, `src/exstruct/mcp/op_schema.py` は `exstruct.edit` の契約モジュールを参照する互換 path に更新した。 -- 恒久文書として `dev-docs/specs/editing-api.md` と `dev-docs/adr/ADR-0006-public-edit-api-and-host-boundary.md` を追加し、ADR index artifacts も同期した。 -- Verification: - - `uv run pytest tests/edit/test_api.py` - - `uv run pytest tests/mcp/patch/test_normalize.py -q` - - `uv run pytest tests/mcp/patch/test_service.py tests/mcp/test_patch_runner.py tests/mcp/test_make_runner.py -q` - - `uv run task precommit-run` - -## 2026-03-15 pr #102 review follow-up - -### Planning - -- [x] `normalize.py` の non-dict/non-str op handling を indexed `ValueError` に統一する -- [x] top-level `sheet` fallback が JSON-string op にも適用されるようにする -- [x] ADR-0006 の status を本文と index artifacts で同期する -- [x] review regression tests を追加する -- [x] PR 本文を template structure に合わせて更新する -- [x] targeted pytest と `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/edit/normalize.py` に raw op coercion helper を追加し、unsupported 型を indexed `ValueError` で拒否するようにした。 -- `resolve_top_level_sheet_for_payload` は JSON-string op も dict 化してから alias 正規化と top-level `sheet` fallback を適用するようにした。 -- ADR-0006 の status は `README.md`, `index.yaml`, `decision-map.md` を `accepted` に揃えた。 -- review regression tests を `tests/mcp/patch/test_normalize.py`, `tests/mcp/test_tool_models.py`, `tests/mcp/test_server.py` に追加した。 -- docstring warning 対応として、新規 `src/exstruct/edit/*.py` の不足 module docstring を補った。 -- PR 本文は `.github/pull_request_template.md` の見出し構造に合わせて更新した。 -- Verification: - - `uv run pytest tests/mcp/patch/test_normalize.py tests/mcp/test_tool_models.py tests/mcp/test_server.py -q` - - `uv run task precommit-run` - -## 2026-03-15 pr #102 docs review follow-up - -### Planning - -- [x] unresolved review thread の内容を確認し、実文書との差分だけを直す -- [x] `data-model.md` の import path 表記を Python module path に揃える -- [x] `architecture/overview.md` の `edit/` tree を実ファイル構成に合わせる -- [x] 文書差分を確認し、必要なら PR thread を resolve する - -### Review - -- `dev-docs/specs/data-model.md` の “actual locations” は filesystem path ではなく Python import path を示す表現に修正した。 -- `dev-docs/architecture/overview.md` の `edit/` tree に `chart_types.py` と `errors.py` を追加した。 -- Verification: - - `git diff --check` - - `uv run task precommit-run` - -## 2026-03-15 issue #99 phase 2 editing CLI - -### Planning - -- [x] issue #99 の Phase 2 を CLI 追加として固定し、legacy extraction CLI との互換境界を明文化する -- [x] `patch` / `make` / `ops list` / `ops describe` / `validate` の CLI surface を実装する -- [x] `patch` / `make` を `exstruct.edit` に接続し、JSON-first 出力と exit code 契約を整える -- [x] `validate` を入力ファイル検証 CLI として追加し、MCP `PathPolicy` なしで動作させる -- [x] CLI 回帰/新規テストを追加し、legacy extraction path の互換を確認する -- [x] ADR / internal spec / public docs / README.ja parity を更新する -- [x] targeted pytest と `uv run task precommit-run` を実行する - -### Review - -- `src/exstruct/cli/edit.py` を追加し、`patch` / `make` / `ops` / `validate` の editing CLI を実装した。 -- `src/exstruct/cli/main.py` は first-token dispatch で editing subcommands だけを edit parser に回し、legacy extraction CLI はそのまま維持した。 -- `patch` / `make` は `exstruct.edit` を呼び、`PatchResult` JSON を stdout に出したうえで `error is None` のときだけ exit `0` にした。 -- `validate` は既存の入力ファイル検証ロジックを CLI に昇格し、`is_readable` / `warnings` / `errors` を JSON で返すようにした。 -- 恒久文書として `dev-docs/specs/editing-cli.md` と `dev-docs/adr/ADR-0007-editing-cli-as-public-operational-interface.md` を追加し、ADR index artifacts と CLI/API/README 文書を更新した。 -- Verification: - - `uv run pytest tests/cli/test_edit_cli.py tests/cli/test_cli.py tests/cli/test_cli_alpha_col.py tests/edit/test_api.py tests/mcp/test_validate_input.py -q` - - `uv run pytest tests/core/test_mode_output.py -q` - - `uv run task precommit-run` - - `git diff --check` + - `rg -n "0\.7\.0|v0\.7\.0" pyproject.toml uv.lock CHANGELOG.md mkdocs.yml docs/release-notes/v0.7.0.md` + - `rg -n "^## " tasks/feature_spec.md tasks/todo.md` + - `git diff --check -- CHANGELOG.md docs/release-notes/v0.7.0.md mkdocs.yml pyproject.toml uv.lock tasks/feature_spec.md tasks/todo.md dev-docs/architecture/overview.md` diff --git a/uv.lock b/uv.lock index 5bd4e9e..3fcde34 100644 --- a/uv.lock +++ b/uv.lock @@ -651,7 +651,7 @@ wheels = [ [[package]] name = "exstruct" -version = "0.6.1" +version = "0.7.0" source = { editable = "." } dependencies = [ { name = "defusedxml" },