9.3 KiB
Ticket検索・close監査に必要な履歴visibilityが不足している
Tracking Ticket: 00001KZRNHB35
発生日
2026-08-06
概要
active Ticketから「Implementation reportやapprove、commit evidenceはあるがcloseされていないTicket」を監査した際、model-facing Ticket toolだけでは候補抽出とscope履歴の照合が難しかった。
この不足により、Workerが複数Ticketの履歴を目視で突き合わせ、00001KZ46DP6KのImplementation reportを別のWorkdir delete要件と誤対応させた。最終的にはfull thread、current source、commit e6a2da54を再確認して訂正したが、Ticket bodyの誤編集と誤った監査commentを発生させた。
誤判定自体はWorkerの確認不足である。一方、現在のtool surfaceはこの種の事故を防ぐための検索・version history・typed evidence projectionを提供していない。
観測した障壁
TicketListから候補を抽出できない
今回のmodel-facing結果では、TicketListが次のようなcount summaryだけを返す場合があった。
Listed 23 ticket(s) for state active
個々のTicket id、title、state、updated_atを取得できないため、既知のIDを使ってTicketShowを全件呼ぶ必要がある。pagination offsetやevent/evidence filterもない。
必要だった検索条件は以下。
- activeかつImplementation reportあり
- activeかつapproveあり
- activeかつcommit evidenceあり
doneだが未close- Implementation report後にitem body/titleが変更された
- unresolved
request_changesあり/なし - commit hashまたは本文文字列を含むTicket
TicketShowのprojectionが安定しない
同じTicketShowでも、state一行だけになる場合と、body/thread/relationsを含むfull JSON projectionになる場合があった。
Ticket 00001KZ46DP6K state planning
body_max_bytesとevent_limitを大きくしても常にfull projectionになるとは限らず、Workerは「eventがない」のか「表示が省略された」のかを区別できない。
Implementation reportがtyped eventではない
Implementation reportとcommit evidenceは通常のMarkdown commentとして保存されている。
## Implementation report
...
commit `e6a2da54`
そのため、backendは以下を構造化して検索できない。
- implementation reportの存在
- repository id
- base/head commit
- test evidence
- dirty state
- assignment id
- report対象revision
Markdown headingや文言に依存した監査になる。
item editのversion historyを復元できない
threadのitem_edit eventは、変更fieldとreplacement countだけを返す。
Ticket item updated: title, body. Body replacement applied to 10 occurrence(s).
編集前title/body、編集後snapshot、item revision idを取得できない。Implementation reportがどのitem revisionを対象にしたかも記録されない。
このため、「実装完了後にTicketが別scopeへrescopeされた」のか、「Implementation reportの読み違い」なのかをthreadだけから確実に判定できない。
lifecycle監査queryがない
TicketDoctorはschema/consistency diagnosticsには有効だが、次のsemantic lifecycle driftを検出しない。
- Implementation report + approve + reachable commitがあるのにplanning/inprogress
- state
doneだが未close - close後にunresolved request_changesが追加された
- Implementation report後のmaterial rescope
- report commitがcurrent repositoryで解決不能
- MR current revisionとreview対象revisionが不一致
relation削除operationがない
TicketRelationRecordとTicketRelationQueryはあるが、誤登録やstale relationを削除するtyped operationがない。storage直接編集はauthority bypassになるため実施できない。
影響
- active Ticket全件へのN+1
TicketShowが必要になる。 - known IDを持たないWorkerは候補自体を列挙できない。
- Markdown commentの目視照合で別Ticketのevidenceを混同しやすい。
- rescope後のcurrent bodyだけを見て過去Implementation reportを誤評価する。
- close漏れ監査が高コストで、Ticket state driftが蓄積する。
- 今回は誤ったTicket body editと監査commentを追加し、後から訂正eventを積むことになった。
提案
read toolをQuery / Showへ整理する
既存のselection-only TicketListへ検索責務を積み増すのではなく、read surfaceを次の責務へ整理する。
QueryTicket: Ticket workflowのselection、全文検索、structured filter、attention候補ShowTicket: 一件のcurrent item、version refs、bounded thread、resolution、artifactsQueryObjective: Objectiveのselection、全文検索、state/linked-Ticket filterShowObjective: 一件のcurrent bodyとlink projection
QueryTicketは次のoptional queryを受け取る。
QueryTicket {
query?: string,
states?: [...],
event_kinds?: [...],
evidence?: implementation_report | commit | approved,
review_status?: none | approved | request_changes | unresolved_changes,
attention?: done_not_closed
| implementation_report_not_closed
| report_after_rescope
| unresolved_review
| missing_commit
| blocked
| unblocked,
related_ticket_id?: TicketId,
relation_kind?: RelationKind,
linked_objective_id?: ObjectiveId,
updated_before?: timestamp,
updated_after?: timestamp,
limit,
cursor?,
}
attentionは自動mutationを行わず、候補と根拠だけを返す。Worker/UserがShowTicket、review、repository authorityを再読してclose判断する。
resultは常にbounded summaryを返す。
- Ticket id/title/state/readiness
- matched field/event kind
- bounded snippet
- event id/sequence
- updated_at
- unresolved blocker/review count
next_cursor/truncated
QueryObjectiveも同じ共通query infrastructureを使い、query、states、linked_ticket_id、updated_*、cursor paginationを提供する。domain固有filterとresult型は混ぜない。
横断検索toolは追加しない
同じqueryをQueryTicketとQueryObjectiveへそれぞれ実行すれば十分である。異なるauthorityとresult型をWorkspaceSearchへ混ぜるとsurfaceとprojectionが増えるため、横断toolは追加しない。
typed Implementation report
Markdown bodyに加えて、最低限次をtyped attributesとして保存する。
assignment_idrepository_idbase_commithead_commitmerge_request_id/revision_id- validation evidence refs
- dirty/untracked state
- source Runtime/Worker identity
reportは作成時のTicket item revisionを参照する。QueryTicket.evidenceとattentionはMarkdown headingをparseせず、このtyped authorityをqueryする。
retrievable item revisions
ShowTicketのoptional revision selectorまたはbounded version projectionでitem historyを取得できるようにする。専用tool追加は、同じprojectionではsize/authorityを分離できない場合だけ検討する。
TicketItemRevision {
revision_id,
title,
body_digest,
body or bounded diff,
edited_at,
source,
}
Implementation report/review/close resolutionから対象item revisionを参照する。
stable tool projection
QueryTicket、ShowTicket、QueryObjective、ShowObjectiveは、同じparameterなら常に同じshapeのbounded JSONを返す。省略時は明示的なtruncated、returned、next_cursorを返し、「entryなし」と「projection省略」を区別する。
write commandは副作用単位で明示する
relationのadd/remove、Queue、review、Close、item editなどはauthorization、precondition、idempotency、notification、compensation、audit/result型が異なるため、generic MutateTicketやMutateObjectiveへ統合しない。明示commandを維持し、model-facing tool数はprofile・role・Flow別catalog projectionで抑える。
Implementation reportはtyped Ticket thread eventとして扱い、item revision参照とbounded query結果から監査可能にする。
推奨順序
QueryTicketを追加し、全文検索・state・updated time・thread kind・resolution・artifact・relation filterとcursorを入れるShowTicketへitem/threadの安定したversion referenceを加えるQueryObjectiveを同じquery/cursor infrastructureで追加するShowObjectiveへlink projectionを加える- typed Implementation reportとprofile/role/Flow別catalog projectionを追加する
- WebUIに検索・filter・pagination・implementation-report表示を追加する
期待する監査手順
QueryTicket(states=active, attention=implementation_report_not_closed)で候補抽出。- candidateごとに
ShowTicketでcurrent item revision、report対象revision、latest reviewを取得。 - typed commit/MR evidenceをrepository authorityで検証。
- unresolved
request_changesとdependencyを確認。 - User/Orchestratorが明示的にcloseする。
この順序なら、全TicketのMarkdown threadを目視で横断せず、scopeの異なるevidenceを誤対応させずにclose漏れを監査できる。横断検索toolやgeneric mutation toolを増やさず、roleごとのcatalog projectionでsurfaceを限定できる。