yoi/tickets/maintainer-work-items.md

285 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 として扱いづらい。
shiguredo/http3-rs の `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-<slug>
YYYYMMDD-HHMMSS-<short-rand>-<slug> # 同一秒衝突を避けたい場合
```
例:
```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:<name>
- 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://<repo>/work-items`
- `file://<repo>/issues`
- `sqlite://<workspace>/.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/<id>/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`