docs(tickets): 自己改善workflowの設計

This commit is contained in:
Keisuke Hirata 2026-05-08 01:50:55 +09:00
parent d036d53096
commit 0900e05f9e
5 changed files with 153 additions and 2 deletions

View File

@ -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/<task-name> -b <task-name>
@ -85,7 +87,7 @@ git -C .worktree/<task-name> 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:

View File

@ -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 を作る。

View File

@ -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)

View File

@ -0,0 +1,77 @@
# 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`

View File

@ -0,0 +1,68 @@
# Workflow を memory crate から独立させる
## 背景
`tickets/workflow-directory-layout.md` で Workflow の物理配置を `.insomnia/workflow/` に分離した。これにより Workflow は概念上 memory statesession-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`