From 0900e05f9e5ae38dcfe0ac5d10f85302e33412e4 Mon Sep 17 00:00:00 2001 From: Hare Date: Fri, 8 May 2026 01:50:55 +0900 Subject: [PATCH] =?UTF-8?q?docs(tickets):=20=E8=87=AA=E5=B7=B1=E6=94=B9?= =?UTF-8?q?=E5=96=84workflow=E3=81=AE=E8=A8=AD=E8=A8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .insomnia/workflow/auto-maintain.md | 6 +- .insomnia/workflow/worktree-workflow.md | 2 + TODO.md | 2 + tickets/file-ref-symlink-diagnostics.md | 77 +++++++++++++++++++++++++ tickets/workflow-crate-extraction.md | 68 ++++++++++++++++++++++ 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 tickets/file-ref-symlink-diagnostics.md create mode 100644 tickets/workflow-crate-extraction.md diff --git a/.insomnia/workflow/auto-maintain.md b/.insomnia/workflow/auto-maintain.md index 5e3d4a9b..7fb3b59a 100644 --- a/.insomnia/workflow/auto-maintain.md +++ b/.insomnia/workflow/auto-maintain.md @@ -10,6 +10,8 @@ requires: [] この Workflow は常駐 scheduler ではない。ユーザーが `/auto-maintain` を明示的に呼んだ時だけ動く。 +この Workflow は親 Pod / orchestrator 専用である。実装 Pod に `/auto-maintain` を渡してはならない。実装 Pod には、親 Pod が選んだ ticket、既に用意した child worktree、許可された write scope、禁止事項を具体的に渡す。 + ## 基本方針 - main workspace は制御面として扱う。 @@ -69,7 +71,7 @@ TODO と tickets の不整合を見つけた場合は、勝手に ticket を作 ## Worktree 作成 -実装差分を隔離する必要がある場合、`/worktree-workflow` の手順を使う。要点は以下。 +実装差分を隔離する必要がある場合、親 Pod が `/worktree-workflow` の手順を使う。実装 Pod に worktree 作成を任せてはならない。要点は以下。 ```bash git worktree add .worktree/ -b @@ -85,7 +87,7 @@ git -C .worktree/ sparse-checkout set --no-cone \ ## 実装 Pod の spawn -実装 Pod を使う場合は、対象 ticket、child worktree path、write scope、禁止事項を明示する。 +実装 Pod を使う場合は、対象 ticket、既に作成済みの child worktree path、write scope、禁止事項を明示する。実装 Pod は `/auto-maintain` や `/worktree-workflow` を実行せず、与えられた worktree 内で実装・確認・報告だけを行う。 推奨 scope: diff --git a/.insomnia/workflow/worktree-workflow.md b/.insomnia/workflow/worktree-workflow.md index ffcff2db..638fd433 100644 --- a/.insomnia/workflow/worktree-workflow.md +++ b/.insomnia/workflow/worktree-workflow.md @@ -10,6 +10,8 @@ Git worktree を使って、実装差分を main workspace から分離して進 この Workflow は `.claude/skills/worktree-workflow/SKILL.md` の運用を insomnia 向けに移植したもの。insomnia では Pod の write scope が排他的に委譲されるため、子 worktree に `.insomnia` を置かず、親 Pod が main workspace 側の管理ファイルを書ける状態を保つ。 +この Workflow は親 Pod / orchestrator が worktree を用意するための手順である。実装 Pod にこの Workflow を渡して worktree を作らせてはならない。実装 Pod は親 Pod から既存 child worktree を受け取り、その中で実装・build・test・報告だけを行う。 + ## 原則 - 1 セッション / 1 ticket / 1 task につき 1 worktree を作る。 diff --git a/TODO.md b/TODO.md index 123b8e87..523298e4 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ - Workflow / Skills - 内部 Worker / 内部 Pod の Workflow 化 → [tickets/internal-worker-workflow.md](tickets/internal-worker-workflow.md) - 半自動開発運用 Workflow → [tickets/auto-maintain-workflow.md](tickets/auto-maintain-workflow.md) + - Workflow を memory crate から独立させる → [tickets/workflow-crate-extraction.md](tickets/workflow-crate-extraction.md) - パーミッション: パターンベースのツール実行制御 → [tickets/permission-extension-point.md](tickets/permission-extension-point.md) - Pod CLI: マニフェスト関連フラグの整理 → [tickets/pod-cli-manifest-flags.md](tickets/pod-cli-manifest-flags.md) - Pod: 空応答ターン (Submit 後 AI 応答ゼロで Pause/Cancel) を自動巻き戻し → [tickets/pod-empty-turn-rollback.md](tickets/pod-empty-turn-rollback.md) @@ -22,6 +23,7 @@ - Compaction 進行中のライブ表示 → [tickets/tui-compact-progress.md](tickets/tui-compact-progress.md) - Assistant 応答の Markdown スタイル表示 → [tickets/tui-assistant-markdown.md](tickets/tui-assistant-markdown.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) diff --git a/tickets/file-ref-symlink-diagnostics.md b/tickets/file-ref-symlink-diagnostics.md new file mode 100644 index 00000000..184e4c0e --- /dev/null +++ b/tickets/file-ref-symlink-diagnostics.md @@ -0,0 +1,77 @@ +# FileRef / file tools の symlink 診断と外部参照導線 + +## 背景 + +insomnia 開発では、外部の参考プロジェクトを `external checkout` のローカル clone として参照する運用がある。今回、workspace 内へ外部 clone を指す symlink を置き、`@tmp/` として読ませようとしたが、参照側からは期待通りに読めなかった。 + +このような 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` diff --git a/tickets/workflow-crate-extraction.md b/tickets/workflow-crate-extraction.md new file mode 100644 index 00000000..ea360f53 --- /dev/null +++ b/tickets/workflow-crate-extraction.md @@ -0,0 +1,68 @@ +# Workflow を memory crate から独立させる + +## 背景 + +`tickets/workflow-directory-layout.md` で Workflow の物理配置を `.insomnia/workflow/` に分離した。これにより Workflow は概念上 memory state(session-derived / generated)と別物として整理されたが、ソースコード上は依然として `crates/memory/` 配下に同居している: + +- `crates/memory/src/workflow.rs`(`WorkflowRecord` / `WorkflowRegistry` / `WorkflowSource` / `load_workflows` / `WorkflowLoadError` / `WORKFLOW_DESCRIPTION_HARD_CAP` / `ResidentWorkflowEntry` / `ShadowedSkill`) +- `crates/memory/src/schema/workflow.rs`(`WorkflowFrontmatter`) +- `crates/memory/src/skill.rs`(Skill → Workflow projection) +- `crates/memory/src/linter/mod.rs::lint_workflow`(人間編集向けの workflow linter) +- `crates/memory/src/error.rs::LintError::WorkflowWriteForbidden` + +memory crate のドメインは「decisions / requests / summary / knowledge / staging / consolidation」に絞り、Workflow は独立した crate に出す。`tickets/internal-worker-workflow.md` で内部 Worker の Workflow 化が予定されており、bundled default や `internal_role` 追加の置き場として独立 crate がある方が自然。 + +## 要件 + +### crate の分離 + +`crates/workflow/` を新設し、上記の Workflow 関連型 / 関数 / スキーマ / Skill projection / human-edit linter を移す。 + +- 新 crate からは memory crate に依存しないか、`WorkspaceLayout` 経由で薄く依存するに留める +- `crates/memory/` から workflow 関連の `pub use` 再エクスポートは削除(呼び出し側が新 crate を直接 import する) +- Workflow 用の linter は memory crate の `Linter` を共有しないでよい場合は単独で持つ。共有が必要なら共通部分を別 crate(例: `crates/lint-common/`)に切る判断を行う + +### `WorkspaceLayout` の扱い + +`workflow_dir()` / `workflow_path()` が memory crate に残るかは設計判断: + +- memory crate に残し、workflow crate がそれを利用する形でよい +- 別 crate(例: `crates/workspace-layout/`)に切り出す場合は memory / workflow 両方が参照する形にする + +どちらでもよいが、結果として循環依存を生まないこと。 + +### 既存 use site の更新 + +- `crates/pod/`(`pod.rs` / `prompt/system.rs` / `workflow/mod.rs`) +- `crates/tui/` +- その他 `memory::Workflow*` を import している箇所 + +これらが新 crate を import する形に書き換わる。 + +### Skill ingestion の所属 + +`SKILL.md` パーサと `WorkflowRecord` への projection は workflow crate に同居する。Skills は外部入力だが最終的に Workflow registry に流れるので、workflow crate を窓口にする方がレイヤとして自然。 + +### scope deny の整理 + +`crates/memory/src/scope.rs::deny_write_rules` は memory / knowledge / workflow の 3 ディレクトリを deny している。workflow crate 側で `.insomnia/workflow/` の deny を表明し、Pod 起動時に両方を合成する形にするか、あるいは scope deny は呼び出し側(pod)で集約する形に再設計する。 + +## 範囲外 + +- Workflow の機能変更(frontmatter schema 変更、resolver 改修等) +- bundled default Workflow 機構(`tickets/internal-worker-workflow.md` の対象) +- memory crate 内部の他モジュール再編 + +## 完了条件 + +- `crates/workflow/` crate が独立して存在し、`WorkflowRecord` / `WorkflowRegistry` / `load_workflows` / `WorkflowFrontmatter` / Skill projection / human-edit linter がそこに住む +- memory crate に workflow / skill 関連のソースが残っていない(reexport も無し) +- 既存テストが新構造で通る +- 既存呼び出し側(pod / tui 等)が新 crate を import する形に更新されている +- scope deny が memory / workflow を矛盾なく合成できる構成になっている + +## 参照 + +- 直前: `tickets/workflow-directory-layout.md`(git log) +- 後続: `tickets/internal-worker-workflow.md` +- 関連: `docs/plan/workflow.md`