docs(tickets): file-ref-symlink-diagnostics完了

This commit is contained in:
Keisuke Hirata 2026-05-09 04:22:27 +09:00
parent 856a0a2432
commit 32ed5a812c
3 changed files with 0 additions and 114 deletions

View File

@ -22,7 +22,6 @@
- 巻き戻されたターンの入力テキストを編集領域に復元 → [tickets/tui-empty-turn-restore.md](tickets/tui-empty-turn-restore.md)
- セッションコンテキスト長 / ウィンドウ占有率の常時表示 → [tickets/tui-context-usage-indicator.md](tickets/tui-context-usage-indicator.md)
- Manifest: Tool Output / File Upload 上限の分離とデフォルト緩和 → [tickets/manifest-output-upload-limits.md](tickets/manifest-output-upload-limits.md)
- FileRef / file tools の symlink 診断と外部参照導線 → [tickets/file-ref-symlink-diagnostics.md](tickets/file-ref-symlink-diagnostics.md)
- Prune: 保護境界を turn 数から末尾 token budget に置き換え → [tickets/prune-token-budget.md](tickets/prune-token-budget.md)
- メモリ機構
- 使用頻度メトリクス + Knowledge 化候補レポート → [tickets/memory-usage-metrics.md](tickets/memory-usage-metrics.md)

View File

@ -1,82 +0,0 @@
# FileRef / file tools の symlink 診断と外部参照導線
## 背景
insomnia 開発では、外部の参考プロジェクトを `external checkout` のローカル clone として参照する運用がある。今回、workspace 内へ外部 clone を指す symlink を置き、`@tmp/<external-project>` として読ませようとしたが、参照側からは期待通りに読めなかった。
このような symlink は、壊れている場合、相対リンクの基準が利用者の期待と違う場合、または canonicalize 後の target が Pod の readable scope 外に出る場合がある。現状は `file not found` のように見えやすく、壊れた symlink なのか、scope 外なのか、Glob / FileRef が symlink directory を辿らない仕様なのか判断しにくい。
一方で、symlink を無条件に辿ると workspace scope の外へ読み書きできる escape になるため、単純に許可してはいけない。canonicalized target が effective scope 内かどうかを明確に検査し、失敗時は理由を出す必要がある。
## 要件
### symlink 診断
FileRef / completion / read 系の file handling で、対象 path または途中 component が symlink の場合に、失敗理由を区別して報告できるようにする。
最低限、以下を区別する。
- symlink target が存在しないbroken symlink
- symlink target が Pod の readable scope 外に解決される
- target は scope 内だが directory traversal / glob 側が symlink directory を辿っていない
- target は scope 内だが file / directory 種別が期待と違う
エラー文には、可能な範囲で元 path と解決後 target を含める。
### scope safety
symlink は canonicalize 後の target で scope 判定する。
- read: canonicalized target が readable scope 内の場合のみ許可
- write: canonicalized target が writable scope 内の場合のみ許可
- scope 外の場合は拒否し、`read scope に target を追加する` / `workspace 内へコピーする` / `正しい symlink を作り直す` などの対処を示す
既存の symlink escape 防止テストは維持する。
### 外部 external checkout 参照の導線
外部参考プロジェクトを `external checkout` から読む運用に対して、推奨手順を明文化する。
候補:
- Pod 起動時 / spawn 時に external checkout clone の実体 path を read scope に入れる
- workspace 内 symlink を使う場合も、target が readable scope 内に入っている必要があることを明記する
- broken relative symlink を検出した場合、絶対 symlink または正しい相対 symlink を促す
### 対象 surface
少なくとも以下のいずれか、または共通層を通じて同等の挙動になること。
- submit 時 `Segment::FileRef` の resolver
- TUI completion の file candidate 表示
- generic file read / glob 系 tool
- auto-read / fs view が同じ file handling を使う場合はその経路
## 範囲外
- readable scope 外 symlink を安全確認なしに自動許可すること
- symlink target を自動で scope に追加すること
- external checkout clone の自動探索や自動 clone
- write scope の owner handoff / Pod sleep など権限モデル自体の変更
- Git submodule / worktree の設計変更
## 完了条件
- broken symlink、scope 外 symlink、scope 内 symlink directory の挙動が区別できる
- scope 外 symlink は canonicalized target で拒否され、明確なエラーになる
- scope 内 symlink file / directory は、仕様として許可するか拒否するかが明文化され、テストされている
- FileRef または file tool のテストで symlink 経路がカバーされる
- external checkout など外部参照プロジェクトを読む場合の推奨手順が docs または ticket 内に記録されている
## 参照
- `crates/tools/src/scoped_fs.rs`
- `crates/tools/tests/edge_cases.rs`
- `crates/pod/src/pod.rs` `resolve_file_refs`
- `crates/pod/src/fs_view.rs`
- `crates/manifest/src/scope.rs`
## Review
- 状態: Approve with follow-up
- レビュー詳細: [./file-ref-symlink-diagnostics.review.md](./file-ref-symlink-diagnostics.review.md)
- 日付: 2026-05-07

View File

@ -1,31 +0,0 @@
# Review: FileRef / file tools の symlink 診断と外部参照導線
## 前提・要件の確認
- broken symlink / scope 外 symlink / symlink directory / file-vs-directory の診断: 概ね満たされている。`ToolsError` に `BrokenSymlink`、`SymlinkOutOfScope`、`SymlinkTargetIsDirectory`、`SymlinkDirectoryNotTraversed` が追加され、元 path と target を含むエラー文になっている(`crates/tools/src/error.rs:19-58`)。
- scope safety: 満たされている。`ScopedFs::read_bytes` / `write` は引き続き `scope.is_readable` / `scope.is_writable` を通し、symlink target が scope 外の場合は許可せず診断へ落としている(`crates/tools/src/scoped_fs.rs:108-141`, `crates/tools/src/scoped_fs.rs:160-226`)。既存 edge-case test でも外部 target が書き換わらないことを確認している(`crates/tools/tests/edge_cases.rs:83-158`)。
- scope 内 symlink file / directory の仕様: 満たされている。scope 内 symlink file は読み取り可能、既存 symlink file への write は symlink を置換せず canonical target を更新する仕様としてテストされている(`crates/tools/src/scoped_fs.rs:435-543`。symlink directory root は Glob/Grep で辿らず明示エラーにする実装になっている(`crates/tools/src/glob.rs:97-147`, `crates/tools/src/grep.rs:254-304`)。
- file tool のテスト: 満たされている。`ScopedFs` unit test と `edge_cases` で broken / out-of-scope / in-scope file / directory type がカバーされている(`crates/tools/src/scoped_fs.rs:389-543`, `crates/tools/tests/edge_cases.rs:83-158`)。
- 外部参照導線: 満たされている。外部 clone を読む場合は実体 path を read scope に入れること、workspace symlink だけでは権限が増えないこと、Glob/Grep は symlink directory を辿らないことが文書化された(`docs/file-ref-symlinks.md:1-12`)。
## アーキテクチャ・スコープ
- 変更は `tools` crate の scope-aware filesystem と Glob/Grep surface に閉じており、Pod / protocol / manifest の権限モデル自体には踏み込んでいない。チケットの範囲外である scope 自動追加や symlink の無条件許可も入っていない。
- symlink 診断は `ScopedFs` の helper と `ToolsError` に集約されており、既存の `Scope` 判定を迂回していない。scope escape safety を保ったまま診断を改善する方向として妥当。
- write で既存 symlink file の canonical target を更新する変更は、従来の atomic tempfile persist が symlink 自体を置換し得る挙動より安全で、今回の目的にも合っている。
## 指摘事項
### Non-blocking / Follow-up
- `Grep` でも symlink directory root の明示エラーが実装されているが、専用テストは `Glob` 側のみ確認できる(`crates/tools/src/grep.rs:298-304`, `crates/tools/src/glob.rs:344-372`)。挙動は単純で `cargo test -p tools` も通っているため blocking ではないが、将来の退行防止として `grep_reports_scope_inside_symlink_directory_is_not_traversed` 相当のテストを追加してもよい。
- nested symlink directory は walker の `follow_links(false)` により従来通りスキップされ、skip ごとの診断は出ない。実装 Pod の報告通り、per-entry diagnostics は結果形式の拡張が必要なので本チケットでは妥当な見送り。
## 判断
Approve with follow-up — 要件は満たされ、scope safety も維持されている。Grep の専用テスト追加と nested symlink directory 診断は follow-up として扱えばよい。
## 確認したコマンド
- `cargo test -p tools`
- `cargo fmt -p tools --check`