ticket: use base32 project record ids

This commit is contained in:
2026-06-09 22:10:47 +09:00
parent 0803bc3725
commit 4203988d74
798 changed files with 477 additions and 105 deletions
@@ -0,0 +1,13 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KTJXS31R",
"kind": "depends_on",
"target": "00001KTG3MDFG",
"note": "この Ticket の残り範囲は、既に closed 済みの OrchestrationPlan record/tool surface を前提にした re-kick / active work set discovery 層として扱う。Plan store 自体を再実装しないための canonical prerequisite 記録。",
"author": "intake",
"at": "2026-06-09T11:34:44Z"
}
]
}
+127
View File
@@ -0,0 +1,127 @@
---
title: "Prevent idle starvation in Ticket orchestration planning"
state: 'ready'
created_at: "2026-06-08T06:12:35Z"
updated_at: '2026-06-09T11:35:29Z'
---
## Background
The current Panel Queue automation mostly handles the transition-time event:
```text
ready -> queued
-> notify workspace Orchestrator
```
That is not enough for robust orchestration. Queued Tickets can remain after missed notifications, Orchestrator restarts, planning returns, capacity limits, or multi-ticket coordination. The Orchestrator also needs a lightweight way to remember planned queued work across turns without relying only on session memory.
There is an existing related Ticket:
- `ticket-orchestration-plan-tool`
That Ticket asks for a TaskStore-like surface for Ticket ordering/dependency/conflict/capacity/accepted-plan records. This Ticket folds that need together with queued-backlog re-kick semantics into a narrower operational requirement:
> If runnable queued work exists and the Orchestrator is otherwise idle, the system should not wait indefinitely for another user instruction. The Orchestrator should be kicked with a bounded work set so it can either incorporate new queued work into the plan or start the next planned queued Ticket.
This is starvation prevention and explicit work-set planning, not a constant background scheduler loop.
## Goal
Implement an Orchestrator attention/re-kick policy and planning store for active Ticket work: distinguish new queued work from planned queued work and accepted in-progress work, persist the plan, and kick the Orchestrator only when work can progress and no active Orchestrator-managed operation is already being waited on.
## Planning model
The OrchestrationPlan store should distinguish at least:
- `new_queued`: Tickets with `workflow_state = queued` that have not yet been incorporated into the OrchestrationPlan.
- `planned_queued`: queued Tickets that the Orchestrator has considered and placed into an explicit plan/order/waiting set, but has not yet accepted as `inprogress`.
- `inprogress`: Tickets accepted by the Orchestrator and currently awaiting worktree/coder/reviewer/planning-sync/merge/cleanup progress.
The names do not need to become final public API names, but the state distinction is required.
## Requirements
### Active work set discovery / re-kick
- Provide a mechanism to identify Tickets that need Orchestrator attention, including at least:
- `workflow_state = queued` Tickets not yet present in the OrchestrationPlan (`new_queued`);
- planned queued Tickets that are not blocked/capacity-limited and can be started when there is no active in-progress work;
- `workflow_state = inprogress` Tickets accepted by Orchestrator whose next action is not merely waiting for an active coder/reviewer/planning-sync/merge step;
- queued Tickets left behind after Orchestrator restart, missed notification, or previous capacity stop.
- On Panel open/Orchestrator restore/spawn, or explicit user action, surface a bounded work list to the Orchestrator when there is actionable work.
- Avoid unbounded background polling. Prefer explicit events, Panel lifecycle kick, and explicit user/Orchestrator actions.
- Prevent duplicate starts: re-kick should prompt inspection/planning or acceptance of the next planned item, not blindly start coder Pods.
### Re-kick / starvation-prevention semantics
- If `new_queued` work exists and the Orchestrator is idle/not occupied by an active in-progress operation, kick or notify the Orchestrator so it can incorporate those Tickets into the plan.
- If no active `inprogress` work exists and runnable `planned_queued` work exists, kick or notify the Orchestrator so it can accept/start the next planned Ticket rather than waiting indefinitely for user instruction.
- If active `inprogress` work exists and the next expected event is coder/reviewer/planning-sync/merge completion, do not re-kick merely because queued/planned queued work also exists.
- If planned queued work is blocked, dependency-waiting, conflict-waiting, or capacity-limited, record the reason so the Panel/user can see why nothing starts.
- A re-kick is an attention signal plus bounded context, not authority to bypass `queued -> inprogress` acceptance or spawn implementation Pods without inspection.
### Orchestration plan record
- Provide or define a TaskStore-like but Ticket-domain planning surface for Orchestrator use.
- The plan should be scoped to Ticket orchestration and support records such as:
- current active target set;
- state bucket: `new_queued` / `planned_queued` / `inprogress` or equivalent;
- ordering: Ticket A before Ticket B;
- dependency/blocker: A blocks B / B blocked by A;
- conflict: do not run A and B in parallel;
- capacity/waiting notes;
- accepted work plan: worktree/branch/coder/reviewer plan;
- current next action for each target.
- Distinguish durable project-relevant routing decisions from local runtime/session claims.
- Project-relevant decisions should live in Ticket records/thread/artifacts or a typed Ticket orchestration record under project authority.
- Local Pod/session claims remain in the local role session registry.
- Records should survive compaction and be queryable by Ticket id/slug and relation kind.
- Keep the first version lightweight; do not implement a full scheduler/graph solver.
### Plan update semantics
- The Orchestrator should update the plan at meaningful routing boundaries:
- new queued work incorporated into the plan;
- queued -> inprogress acceptance;
- inprogress -> blocked/waiting/planning/done;
- capacity stop -> leave planned queued/waiting with reason;
- merge-ready/done -> mark complete and consider the next planned queued Ticket if no active work remains.
- Each update should produce a bounded, inspectable record of:
- what was considered;
- what was incorporated into the plan;
- what was accepted/started;
- what was blocked/deferred/returned to planning;
- what remains planned queued/waiting.
- Re-kick should use the current plan/work set so the Orchestrator does not forget leftover queued Tickets between turns.
### Relationship to existing work
- This Ticket should either subsume or update `ticket-orchestration-plan-tool` so there is one coherent plan/re-kick design.
- It should coordinate with:
- `replace-intake-state-with-planning` as a prerequisite that defines the planning lane before this plan/re-kick layer builds on it;
- `panel-close-done-tickets` for done -> closed handling;
- local role session registry for active Pod/session ownership;
- direct/delegation authority work for actual child Pod spawning.
## Non-requirements
- Do not turn the Panel itself into the scheduler.
- Do not auto-start unqueued Tickets.
- Do not re-kick continuously while active coder/reviewer/planning-sync/merge work is already in progress.
- Do not blindly spawn coder Pods from re-kick without Orchestrator inspection and `queued -> inprogress` acceptance.
- Do not implement a full dependency graph solver in the first version.
## Acceptance criteria
- The system can distinguish new queued work, planned queued work, and accepted in-progress work.
- New queued Tickets are not left unnoticed while the Orchestrator is otherwise idle.
- Runnable planned queued Tickets are not left unstarted when there is no active in-progress work and capacity/policy allows progress.
- The system does not re-kick merely because queued/planned work exists while Orchestrator-managed in-progress work is waiting on coder/reviewer/planning-sync/merge completion.
- Missed/stale queued Tickets can be surfaced to the Orchestrator without requiring the user to manually requeue each one.
- The Orchestrator can record and query a lightweight Ticket orchestration plan covering active targets, order/dependency/conflict/capacity, state bucket, and next actions.
- Plan records survive compaction and do not rely solely on session-lifetime TaskStore state.
- Re-kick/plan updates leave an auditable record of what was incorporated, started, blocked, returned to planning, or left waiting.
- Duplicate implementation starts are prevented by consulting current Ticket state, local role/session claims, and plan records.
- Relevant workflows/prompts/docs are updated.
- Focused tests, `target/debug/yoi ticket doctor`, `cargo fmt --check`, and `git diff --check` pass.
+120
View File
@@ -0,0 +1,120 @@
<!-- event: create author: LocalTicketBackend at: 2026-06-08T06:12:35Z -->
## Created
Created by LocalTicketBackend create.
---
<!-- event: decision author: hare at: 2026-06-08T06:15:37Z -->
## Decision
## Scope refinement: avoid idle starvation, not constant iteration
The phrase "continuously iterate" should not mean that the Orchestrator constantly re-kicks itself regardless of current work. The desired behavior is narrower:
- Do not leave newly queued work unnoticed while the Orchestrator is otherwise idle.
- Do not leave planned queued work unstarted when there is no in-progress work and capacity/policy allows starting it.
- Do not re-kick just because queued work exists if the Orchestrator is already waiting for an active coder/reviewer/preflight/merge step.
Refined planning model:
- `new_queued`: Tickets with `workflow_state = queued` that have not yet been incorporated into the OrchestrationPlan.
- `planned_queued`: queued Tickets that the Orchestrator has considered and placed into an explicit plan/order/waiting set, but has not yet accepted as `inprogress`.
- `inprogress`: Tickets accepted by the Orchestrator and currently awaiting worktree/coder/reviewer/preflight/merge/cleanup progress.
Desired scheduling/re-kick semantics:
1. If there is `new_queued` work and the Orchestrator is idle/not occupied by an active in-progress operation, it should be kicked or shown a bounded work list so it can incorporate the new Tickets into the plan.
2. If there is no `inprogress` work and there is `planned_queued` work that is not blocked/capacity-limited, the Orchestrator should be kicked to start/accept the next planned Ticket rather than waiting indefinitely for user instruction.
3. If there is active `inprogress` work whose next expected event is coder/reviewer/preflight/merge completion, do not re-kick merely because queued/planned work exists. The Orchestrator should wait for the active work or an explicit user action/capacity decision.
4. If planned queued work is blocked or waiting for capacity, the plan should record that reason so the panel/user can see why nothing starts.
This should be framed as starvation prevention and explicit work-set planning, not a background scheduler loop.
---
<!-- event: decision author: hare at: 2026-06-08T06:27:33Z -->
## Decision
## Dependency ordering: planning lane before re-kick planning layer
`replace-intake-state-with-planning` owns the behavior for cases where work cannot be planned/implemented yet because requirements or preflight are missing: return the Ticket to the planning lane with a visible reason.
This Ticket assumes that behavior exists and builds the `new_queued` / `planned_queued` / `inprogress` re-kick model on top of the clarified workflow states. Implementation order should be: settle `replace-intake-state-with-planning` first, then implement the OrchestrationPlan/re-kick layer.
Therefore, the OrchestrationPlan/re-kick layer should not introduce its own separate `preflight_needed` bucket or cleanup logic.
---
<!-- event: decision author: intake at: 2026-06-09T11:35:09Z -->
## Decision
## Intake refinement: ready scope for Orchestrator routing
既存 Ticket の本文と thread を確認し、関連 work と現在の Ticket lifecycle vocabulary に合わせて、残りの実装対象を以下に整理する。
### Scope after related work
- この Ticket は、Orchestrator が `queued` work を見落とさず、かつ active work を待っている最中に無駄な再 kick を繰り返さないための **active work set discovery / re-kick policy** を実装対象にする。
- OrchestrationPlan record/tool surface は既に別 Ticket で実装済みの前提として扱い、この Ticket で plan store 自体を再実装しない。
- 既存本文・thread の `workflow_state` という語は現在 schema の authoritative field ではない。実装では Ticket frontmatter の `state` を authority とし、既存記録中の `workflow_state = queued` などは historical wording / conceptual alias として読む。
### Binding decisions / invariants
- `new_queued` / `planned_queued` / `inprogress` は新しい core Ticket state として追加しない。必要な work-set classification は、現在の Ticket `state`、OrchestrationPlan records、role/session claim、visible Pod/worktree state から導出する。
- `queued` は Orchestrator が routing/start-if-unblocked を検討できる状態であり、implementation side effects は必ず `queued -> inprogress` が記録された後に限る。
- Panel や local lifecycle hook が Orchestrator に attention / kick を与えることはできるが、unattended scheduler loop や常時 polling にはしない。
- Orchestrator が active coder/reviewer/preflight/merge/cleanup 等の完了待ちである間は、queued/planned work が存在するだけでは再 kick しない。
- `planned_queued` work を開始しない理由が capacity / dependency / conflict / dirty workspace 等で説明できる場合は、bounded reason を OrchestrationPlan record または既存の適切な durable artifact に残し、Panel/user が理解できるようにする。
- duplicate start を避けるため、Ticket state、role/session claims、Plan records、visible Pod/worktree state を確認してから attention/kick/acceptance を行う。
### Implementation latitude
- どの runtime/panel boundary で idle Orchestrator を検出して kick するか、どの view-model/helper に work-set derivation を置くか、bounded payload の具体形は実装側で選んでよい。
- 既存 OrchestrationPlan types で waiting/capacity reason が足りない場合、最小の typed extension は検討してよい。ただし core Ticket lifecycle state の増殖や旧 `workflow_state` 復活は避ける。
- Panel 表示は state-first / heuristic-free の原則を維持する。title text、labels、thread event の有無、Pod 名 substrings を lifecycle authority にしない。
### Acceptance criteria
- Orchestrator が idle/not occupied のとき、new queued work を検出して plan incorporation または bounded work-list attention に進める。
- Inprogress work が存在せず、planned queued work が unblocked かつ capacity/policy 上開始可能なとき、Orchestrator が次の acceptance/routing を行える。
- Active inprogress operation の完了待ち中は、queued/planned work の存在だけで再 kick しない。
- 開始しない planned queued work には、ユーザーが確認できる bounded waiting/blocking reason が残る。
- 既存の human gate、`queued -> inprogress` acceptance step、dirty-workspace/dependency/conflict/capacity checks を迂回しない。
- duplicate Orchestrator/coder/reviewer/worktree start を起こさない。
### Validation
- `nix build .#yoi` を通す。
- Ticket / panel / orchestrator routing 周辺の既存テストまたは追加テストで、少なくとも idle queued detection、active-work wait suppression、waiting reason recording、duplicate-start prevention の主要分岐を確認する。
- 実装報告では、どの authority を work-set classification に使ったか、implementation side effects が `queued -> inprogress` 後に限定されていることを明示する。
### Readiness
- readiness: implementation_ready
- risk_flags: [orchestration-policy, panel-lifecycle, persistence, role-session, authority-boundary, duplicate-start]
- blocking open questions: none
この refinement により、Orchestrator はこの Ticket を implementation candidate として routing できる。
---
<!-- event: intake_summary author: intake at: 2026-06-09T11:35:29Z -->
## Intake summary
Ticket 00001KTJXS31R は implementation_ready。残り範囲は既に実装済みの OrchestrationPlan record/tool surface を前提にした active work set discovery / Orchestrator re-kick policy。`new_queued` / `planned_queued` / `inprogress` は新しい core Ticket state ではなく、現在の Ticket `state`、OrchestrationPlan records、role/session claims、visible Pod/worktree state から導出する分類として扱う。Panel/lifecycle hook は idle Orchestrator に bounded attention を与えるが、unattended scheduler loop や常時 polling にはしない。`queued -> inprogress` acceptance 前の implementation side effects、blind spawn、duplicate start は禁止。active coder/reviewer/preflight/merge/cleanup 待ち中は queued/planned work の存在だけで re-kick しない。risk_flags: [orchestration-policy, panel-lifecycle, persistence, role-session, authority-boundary, duplicate-start]。blocking open questions はない。
---
<!-- event: state_changed author: intake at: 2026-06-09T11:35:29Z from: planning to: ready reason: intake_ready field: state -->
## State changed
Intake refinement により、既存の plan store 実装との差分、current `state` vocabulary、binding invariants、implementation latitude、validation focus が整理され、Orchestrator が routing できる状態になった。
---