# AI maintainer 用 WorkItem / Thread 抽象 ## 背景 現在の開発運用は `TODO.md` と `tickets/*.md` を中心に回している。これは Git 履歴で要件と完了条件を追うには十分だが、AI maintainer が単なる Coding Agent を超えて運用を担うには弱い。 特に、設計相談、実装 Pod の作業報告、review 指摘、修正依頼、完了判断、Pod run、lease、artifact が ticket file / review file / 会話 / git log に分散し、thread として扱いづらい。 repository-managed issue directory example の `issues/` directory のように、repository 内に issue / work item を置く運用は参考になる。一方で、同 repository の owner も指摘している通り、中央の `SEQUENCE` ファイルによる連番採番は並列 branch / worktree で conflict しやすい。将来的な network 越し workspace / remote coordination も想定すると、最初から Git directory や中央採番前提で API を固めるべきではない。 本チケットでは、`tickets/` を直ちに置き換えるのではなく、AI maintainer が扱う上位の **WorkItem / Thread / Event / Lease / Artifact** 抽象を設計し、最小 file backend を導入できる状態にする。 ## 方針 - WorkItem / Thread の正本は `.insomnia` ではなく、project-visible な repo-managed 領域に置く - `.insomnia` は local runtime state / memory / workflow / Pod run / lease cache の領域として分離する - API / domain model は Git に依存しない形にする - WorkItem ID は中央 `SEQUENCE` 連番ではなく、作成時刻ベースの衝突しにくい ID にする - 初期 backend は repo 内 directory(例: `work-items/` または `issues/`)でよい - network 越し workspace / remote hub は後回しにするが、将来差し替え可能な interface を先に切る - 既存 `tickets/` は当面維持し、WorkItem から link するか、file backend の一 view として扱えるようにする ## データ配置 初期設計では以下の分離を前提にする。 ```text repo/ work-items/ or issues/ # project-visible, git-managed coordination data tickets/ # 当面の既存 ticket docs/ # 設計・report .insomnia/ # local agent/runtime state memory/ workflow/ maintainer/ leases/ runs/ inbox/ ``` ### repo-managed に置くもの - WorkItem description - acceptance criteria - discussion thread - design decision - review comment - status history - linked branch / worktree / commit - durable artifact metadata ### `.insomnia` に置くもの - Pod run state - lease の local cache - SpawnedPod polling cursor - temporary inbox - local-only trial log - model / role runtime state ## WorkItem ID WorkItem ID は identity のためだけに使い、priority や処理順序を背負わせない。`SEQUENCE` のような中央連番ファイルは、複数 branch / worktree / Pod が同時に WorkItem を作ると conflict しやすいため採用しない。 初期 file backend では、directory name を immutable ID として扱う。 ```text YYYYMMDD-HHMMSS- YYYYMMDD-HHMMSS-- # 同一秒衝突を避けたい場合 ``` 例: ```text 20260510-184233-maintainer-work-items 20260510-184233-a1b2-maintainer-work-items ``` 要件: - lexical sort で概ね作成順になる - 中央採番ファイルを更新しない - collision 時は backend が短い random suffix や retry で解決する - human-visible `slug` / `title` と immutable `id` を分ける - priority / status / scheduling は `id` ではなく metadata で表す - 将来 remote backend に移る場合も ID 生成責務は backend 側に閉じ込める ## WorkItem model 最低限、以下の概念を持つ。 ```text WorkItem - id - slug - title - status - kind: feature | bug | refactor | design | ops | investigation - priority / labels - owner / assignee / current lease summary - acceptance criteria - linked ticket / docs / branches / worktrees / commits - thread events - artifacts ``` ```text ThreadEvent - id - work_item_id - occurred_at - author: human | orchestrator | pod: - role: comment | plan | decision | implementation_report | review | status_change | escalation | artifact - reply_to? - body - links ``` ```text Lease - id - work_item_id - holder - scope hint - worktree path - expires_at - status: active | released | expired ``` Lease はリアルタイム coordination に近いため、Git-managed thread の正本とは分ける。file backend 初期実装では `.insomnia/maintainer/leases/` か local DB を使ってよい。 ## backend interface AI maintainer / `/auto-maintain` は file path を直接前提にせず、概念上は store interface を通す。 ```text WorkItemStore - list(filter) - get(id) - create(item) - append_event(id, event) - update_status(id, status) - attach_artifact(id, artifact) ``` ```text LeaseStore - acquire(work_item_id, holder, scope, ttl) - refresh(lease_id) - release(lease_id) - list_active(filter) ``` 初期 backend 候補: - `file:///work-items` - `file:///issues` - `sqlite:///.insomnia/maintainer/work-items.db` 将来 backend 候補: - `http://maintainer-hub/...` - `github://owner/repo/issues` ## Query / listing 初期 file backend の list / query は、index や DB を作らず全 `item.md` frontmatter scan で行う。 対象: ```text work-items/{open,pending,closed}/*/item.md ``` `item.md` の frontmatter に query 用 metadata を集約する。 ```yaml --- id: 20260510-184233-a1b2-maintainer-work-items slug: maintainer-work-items title: AI maintainer 用 WorkItem / Thread 抽象 status: open kind: design priority: P2 labels: [maintainer, workflow] created_at: 2026-05-10T18:42:33Z updated_at: 2026-05-10T19:10:00Z assignee: null --- ``` `WorkItemStore::list` / `query` は frontmatter だけを読み、summary を返す。 - status / kind / labels / priority / assignee で filter する - title / slug / description excerpt の軽い substring query を提供する - sort は priority / updated_at / created_at を metadata で行う - `thread.jsonl` は一覧では読まず、`get(id)` / thread read 時だけ読む - `updated_at` は item metadata として持ち、必要なら thread append 時に更新する 当面の件数では全件 scan で十分であり、AI に directory を探索させて候補を推測させない。index / SQLite / search daemon は件数増加、全文検索、remote backend 同期が必要になった時点で検討する。 ### status の二重管理 file backend では directory と frontmatter の両方に status が出る。 ```text work-items/open//item.md frontmatter: status: open ``` これは人間の `ls` と backend abstraction の両方を成立させるため許容する。ただし linter / doctor で一致確認する。 - `work-items/open/*/item.md` は `status: open` - `work-items/pending/*/item.md` は `status: pending` - `work-items/closed/*/item.md` は `status: closed` 不一致は warning ではなく error とする。 ## 初期 file backend 案 ```text work-items/ open/ 20260510-184233-maintainer-work-items/ item.md thread.jsonl artifacts/ review.md test-log.txt pending/ 20260510-190102-transport-parameter-api/ item.md thread.jsonl artifacts/ closed/ 20260510-201522-anthropic-burst-bundling/ item.md thread.jsonl resolution.md artifacts/ ``` `item.md` は human-readable な issue 本文(背景、根拠、完了条件、非目標など)を持つ。`thread.jsonl` は append-only を基本にし、AI maintainer が conversation / decision / review / status change を追いやすい形にする。`resolution.md` は close 時の解決方法や検証結果を、人間が読みやすい形でまとめる任意ファイルとする。 ## `/auto-maintain` との関係 `/auto-maintain` は当面 `TODO.md` / `tickets/` を読むが、将来的には WorkItemStore を入口にする。 移行方針: 1. 既存 `tickets/` は維持 2. WorkItem 抽象と file backend schema を設計する 3. 新しい設計相談・並列作業・長い thread が必要な作業だけ WorkItem 化する 4. ticket は WorkItem の linked artifact として扱う 5. `work-items/open/` が安定したら、`TODO.md` は generated view または廃止候補にする 6. 十分に安定したら `tickets/` を WorkItem backend の view に寄せる ## 範囲外 - remote maintainer hub の実装 - index / SQLite / search daemon による query 最適化 - 既存 `tickets/` の即時移行 - 常駐 scheduler - Pod lifecycle / completion tracking の完全実装 - scope owner handoff の再設計 ## 完了条件 - WorkItem / Thread / Event / Lease / Artifact の domain model が docs に定義されている - repo-managed coordination data と `.insomnia` local runtime state の分担が明文化されている - `WorkItemStore` / `LeaseStore` 相当の interface 方針が決まっている - list / query は初期実装では全 `item.md` frontmatter scan で行う方針になっている - `thread.jsonl` は一覧では読まず、詳細 read 時だけ読む方針になっている - directory status と frontmatter status の一致を linter / doctor で確認する方針になっている - WorkItem ID scheme が中央連番ではなく timestamp-based になっている - 初期 file backend の directory schema が決まっている - `/auto-maintain` / AI maintainer が将来 WorkItemStore を入口にできる移行方針が書かれている - network 越し workspace / remote hub は後回しにしつつ、backend 差し替え可能性を潰していない ## 参照 - `docs/plan/ai-maintainer.md` - `tickets/auto-maintain-workflow.md` - `docs/report/2026-05-10-ticket-lifecycle-branch-placement.md`