merge: integrate orchestration branch

This commit is contained in:
Keisuke Hirata 2026-06-13 10:53:20 +09:00
commit 20ce1dcda9
No known key found for this signature in database
27 changed files with 3096 additions and 208 deletions

View File

@ -0,0 +1,2 @@
{"id":"orch-plan-20260612-145604-1","ticket_id":"00001KTJXS31R","kind":"waiting_capacity_note","note":"Queue review 2026-06-12: leave queued for now because three active in-progress implementation branches are already delegated (`00001KTVJFT6F` Panel focus, `00001KTTW04W2` Companion progress notification, `00001KTVJGC0Y` Ticket language guidance). This Ticket's re-kick / active work-set scope overlaps conceptually and likely in code with Panel lifecycle / Companion progress notification and has duplicate-start / scheduler-boundary risk. Reconsider after at least the Panel/Companion-notify active work is merged or blocked, so implementation can validate active_inprogress suppression against current behavior.","author":"orchestrator","at":"2026-06-12T14:56:04Z"}
{"id":"orch-plan-20260612-154541-2","ticket_id":"00001KTJXS31R","kind":"accepted_plan","accepted_plan":{"summary":"`queued` Ticket の見落としを防ぐ starvation-prevention layer を実装する。Orchestrator が Idle かつ active_inprogress が導出されない場合だけ bounded work-list attention / re-kick を行い、active coder/reviewer/merge/cleanup 待ち中は queued があるだけでは re-kick しない。session-lifetime work set / role-session claims / visible Pods/worktrees / Ticket state を使い、scheduler・queue drain loop・blind spawn は作らない。","branch":"ticket/orchestrator-idle-queued-rekick","worktree":"/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick","role_plan":"Coder は child worktree に限定して idle Orchestrator queued work discovery / re-kick policy と session-lifetime active-work suppression を実装し、Panel/lifecycle/Ticket routing 周辺の focused tests を追加する。Reviewer は read-only で、scheduler 化していないこと、`queued -> inprogress` acceptance gate、duplicate-start prevention、active_inprogress suppression、waiting reason visibility、recent Companion progress notification / Panel focus behaviorとの整合を確認する。"},"author":"orchestrator","at":"2026-06-12T15:45:41Z"}

View File

@ -1,8 +1,8 @@
---
title: "Orchestrator Idle 時の queued Ticket 見落としを防ぐ"
state: 'queued'
state: 'closed'
created_at: "2026-06-08T06:12:35Z"
updated_at: '2026-06-12T14:49:40Z'
updated_at: '2026-06-12T16:12:42Z'
queued_by: 'workspace-panel'
queued_at: '2026-06-12T14:49:40Z'
---

View File

@ -0,0 +1,41 @@
Orchestrator Idle 時に queued Ticket を見落とさない bounded attention layer を実装した。
実装概要:
- `crates/tui/src/multi_pod.rs` に session-scoped `OrchestratorWorkSet` を追加し、Panel reload 境界で queued/actionable/planned/active_inprogress を導出するようにした。
- Idle かつ reachable な Orchestrator Pod にだけ bounded queued-work attention を送る。
- `active_inprogress` がある場合は re-kick を抑制し、waiting reason を session work set / Panel header detail に保持する。
- Duplicate-start guard は Ticket id に紐づく local claim / related visible Pods / worktree 表示情報から導出する。
- Session work set は `MultiPodApp` 内 runtime/session state に留め、durable per-Ticket artifact store は追加していない。
- `resources/prompts/panel/orchestrator_idle_queue_notice.md` を追加し、Orchestrator attention payload の prompt 本文を resource 化した。
- Scheduler loop、polling loop、queue drain loop、core Ticket state、implementation side effect、acceptance gate bypass は追加していない。
Review / integration:
- Implementation commit: `d2fae81a tui: add idle queued orchestrator attention`
- Reviewer: `yoi-reviewer-idle-queued-rekick` が approve。
- Orchestrator merge commit: `9538feb1 merge: idle queued orchestrator attention`
- Ticket completion commit: `60cf2d9f ticket: mark idle queued done`
Validation:
- `cargo test -p tui queued_attention`: pass, 3 tests
- `cargo test -p tui planned_queued_prompts`: pass, 1 test
- `cargo test -p tui rediscovered_queued_work`: pass, 1 test
- `cargo test -p tui active_inprogress_suppresses`: pass, 1 test
- `cargo test -p tui idle_orchestrator_gets_bounded_attention`: pass, 1 test
- `cargo test -p tui workspace_panel`: pass, 12 tests
- `cargo check -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known broad-suite failures:
- Existing broad `cargo test -p tui` failures noted in thread remain outside this Ticket and were not blockers for focused implementation/review.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick` removed。
- branch `ticket/orchestrator-idle-queued-rekick` deleted。
Non-blocking risks:
- Failed attention delivery is not fingerprint-marked, so a repeatedly reachable-but-rejecting socket can retry on subsequent Panel reloads; this is consistent with existing notice behavior but may be noisy。
- Duplicate guard is bounded to Panel-visible claim/Pod/worktree derivation and is not a full global scheduler/lock, matching this Ticket の scoped attention model。

View File

@ -126,4 +126,390 @@ Intake refinement により、既存の plan store 実装との差分、current
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: orchestrator at: 2026-06-12T14:56:17Z -->
## Decision
Routing decision: leave queued for now (`waiting_capacity_note`)
Reason:
- This queue review already accepted and delegated three in-progress branches: `00001KTVJFT6F` (Panel focus model), `00001KTTW04W2` (Companion progress notification), and `00001KTVJGC0Y` (Ticket language guidance).
- This Ticket concerns Orchestrator idle queued re-kick / active work-set behavior and overlaps conceptually with the active Companion progress notification and Panel lifecycle work. Starting it now would raise duplicate-start / scheduler-boundary / integration-conflict risk rather than safe independent parallelism.
- Relation check: dependency relation target `00001KTG3MDFG` is closed, so this is not blocked by an unresolved relation; the current stop reason is capacity/conflict with active work.
Evidence checked:
- Ticket body/thread: active in-progress suppression, clean workspace gate, no queue-drain loop, active-work-set snapshot requirements, and escalation conditions.
- TicketRelationQuery: two relation records checked; `depends_on` target `00001KTG3MDFG` is closed.
- TicketOrchestrationPlanQuery: no prior records; added `waiting_capacity_note` `orch-plan-20260612-145604-1`.
- Workspace/Pod state: Orchestrator worktree clean; active sibling coder Pods are running for Panel focus, Companion progress notification, and Ticket language guidance.
Next action:
- Keep `queued` and reconsider after at least Panel focus / Companion progress notification are merged or blocked, so this Ticket can validate against the current Panel/notification behavior without duplicate scheduler semantics.
---
<!-- event: decision author: orchestrator at: 2026-06-12T15:46:19Z -->
## Decision
Routing decision: implementation_ready
Reason:
- 前回の waiting reason は、Panel focus / Companion progress notification / Ticket language guidance の active in-progress work と重なる capacity/conflict だった。現在それらは merge/close/cleanup 済みで、visible child Pod は 0、Orchestrator worktree は clean。
- Relation blocker はない。`depends_on` target `00001KTG3MDFG` は closed 済みで、incoming `related` は non-blocking context である。
- Ticket body/thread は、session-lifetime work set discovery / re-kick policy、active_inprogress suppression、duplicate-start prevention、no scheduler/no polling/no blind spawn、`queued -> inprogress` acceptance gate を binding decisions として明確にしている。
- risk flags は orchestration-policy / panel-lifecycle / persistence / role-session / authority-boundary / duplicate-start だが、bounded context check の結果、具体的な未決定 design/API/authority 判断は残っていない。実装方式は Panel/lifecycle/runtime boundary と local session work-set representation の local tactic に閉じている。
- OrchestrationPlan に accepted plan `orch-plan-20260612-154541-2` を記録済み。
Evidence checked:
- Ticket body / thread / artifacts: requirements, acceptance criteria, binding decisions, previous waiting_capacity_note, and accepted plan を確認。
- TicketRelationQuery: `depends_on` target `00001KTG3MDFG` closed、incoming `related` non-blocking。
- Related Ticket: `00001KTG3MDFG` closed。OrchestrationPlan record/tool surface は実装済みで、この Ticket では再実装しない前提を確認。
- Recent merged context: Panel focus model、Companion weak progress notify、Ticket language guidance は closed/merged/cleaned up 済み。
- Code map: `crates/tui/src/workspace_panel.rs`, `crates/tui/src/multi_pod.rs`, `crates/tui/src/role_session_registry.rs`, Ticket state/action surfaces, Pod visibility/state surfaces, recent `companion_progress` weak notify path を確認。
- Workspace/Pod state: Orchestrator branch `orchestration/yoi-orchestrator` is clean; visible child Pods 0。
IntentPacket:
Intent:
- Orchestrator が idle で actionable queued work を見落とすことを防ぐ bounded starvation-prevention layer を実装する。
- `active_inprogress` が導出されている間は queued/planned work があるだけでは re-kick しない。
- re-kick は inspection / work-set incorporation / next planned acceptance を促す attention であり、scheduler や blind implementation start ではない。
Binding decisions / invariants:
- `new_queued` / `planned_queued` / `active_inprogress` / `actionable_inprogress` は core Ticket state に追加しない。Ticket `state`、session-lifetime work set、role/session claims、visible Pod/worktree state、OrchestrationPlan records から導出する分類に留める。
- Work set は session-lifetime runtime state であり、Ticket ごとの durable artifact log として積まない。durable に残すべき判断だけ Ticket comment / state transition / OrchestrationPlan record に残す。
- 常時 polling / unattended scheduler loop / queue drain loop を作らない。
- `queued -> inprogress` acceptance なしに coder/reviewer Pod spawn、worktree 作成、implementation side effect を行わない。
- active coder/reviewer/planning-sync/merge/cleanup 等の完了待ち中は queued/planned work の存在だけで re-kick しない。
- duplicate Orchestrator/coder/reviewer/worktree start を防ぐ。
- Panel は authority/backend/scheduler にならず、bounded attention surface に留まる。
Requirements / acceptance criteria:
- Orchestrator Pod が `Idle``new_queued` work があるとき、bounded work-list attention または session work set incorporation に進める。
- `active_inprogress` がなく、planned queued work が unblocked/capacity-allowed のとき、next acceptance/routing に進める。
- `active_inprogress` が導出される間は queued/planned work の存在だけで re-kick しない。
- 開始しない planned queued work には session work set 上でユーザーに提示できる bounded waiting/blocking reason を保持する。
- Ticket state、session work set、role/session claims、visible Pod/worktree state を使って duplicate start を避ける。
- session work set が失われても `queued` Ticket から安全に再検出・再 inspection できる。
Implementation latitude:
- Panel open / Orchestrator restore/spawn / explicit user action のどの boundary で idle detection と attention payload を組むかは実装側で選んでよい。
- Session work-set の具体的な runtime representation は既存 local role/session registry や Panel app state に合わせて選んでよい。
- Bounded attention payload の具体形は実装側で選んでよいが、full Ticket thread / unbounded Pod output / hidden context-only injection は避ける。
- OrchestrationPlan types の最小拡張は必要なら検討してよいが、core Ticket lifecycle state や旧 `workflow_state` は復活させない。
Escalate if:
- Durable scheduler state / persistent queue runner / polling loop が必要になる。
- `queued -> inprogress` acceptance gate を迂回しないと実装できない。
- Duplicate start prevention に新しい global lock/lease authority が必要になる。
- Panel が lifecycle authority / scheduler になる必要が出る。
- Role/session claims から active_inprogress を安全に導出できない。
Validation:
- idle Orchestrator + queued detection。
- active_inprogress 導出時の re-kick suppression。
- planned queued waiting reason retention。
- duplicate-start prevention。
- session work set loss から queued Ticket 再検出。
- relevant `cargo test` for `tui` / panel / role session / ticket routing paths。
- `cargo fmt --check`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor` または同等。
- `nix build .#yoi`
Current code map:
- `crates/tui/src/workspace_panel.rs`: Ticket rows/actions and state-first Panel view model。
- `crates/tui/src/multi_pod.rs`: Panel lifecycle, Companion/Orchestrator interactions, recent progress notice / header behavior。
- `crates/tui/src/role_session_registry.rs`: local role/session claims。
- `crates/pod-store`, `crates/pod-registry`, and protocol Pod status surfaces only if needed for visible Pod/worktree state derivation。
- Ticket relation / OrchestrationPlan tool surfaces are already implemented and should be reused/read, not reimplemented as plan store。
Critical risks / reviewer focus:
- No scheduler / queue drain loop / background polling。
- No blind worktree/Pod spawn before `queued -> inprogress` acceptance。
- active_inprogress suppression works and avoids re-kick while coder/reviewer/merge/cleanup is active。
- duplicate start prevention uses actual Ticket state + claims + visible Pods/worktrees, not heuristic title/labels。
- session work set is runtime/session scoped, not a new durable per-Ticket artifact log。
- Recent Companion weak progress notify and Panel focus behavior remain coherent.
Next action:
- `queued -> inprogress` を記録してから、branch `ticket/orchestrator-idle-queued-rekick` / worktree `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick` を作成し、sibling coder に narrow write scope で実装を委譲する。Reviewer は coder evidence 後に read-only で起動する。
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T15:46:28Z from: queued to: inprogress reason: orchestrator_acceptance field: state -->
## State changed
Routing accepted for implementation. Ticket body/thread, dependency relation target, incoming non-blocking relation, previous waiting-capacity note, current Orchestrator workspace state, visible Pods, recent merged Panel/Companion/Ticket-language context, and relevant Panel/lifecycle/role-session code map were rechecked. No unresolved blocker or missing planning decision remains. Implementation side effects will start only after this accepted `queued -> inprogress` transition is recorded, using accepted plan `orch-plan-20260612-154541-2`.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:47:00Z -->
## Plan
Implementation worktree created for multi-agent handoff.
- Ticket: `00001KTJXS31R`
- Branch: `ticket/orchestrator-idle-queued-rekick`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Base: Orchestrator workspace HEAD `e72a4536` (`orchestration/yoi-orchestrator`), including the accepted routing record and `queued -> inprogress` transition.
- Scope rule: implementation work happens only in this child worktree. Root/original workspace must not be read, written, validated, merged, cleaned, or used for git operations.
- Next: spawn sibling coder with narrow write scope to the implementation worktree. Reviewer will be started after coder evidence is available.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:47:50Z -->
## Plan
Coder delegated.
- Coder Pod: `yoi-coder-idle-queued-rekick`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Branch: `ticket/orchestrator-idle-queued-rekick`
- Scope: write `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`; read child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Task: implement bounded idle-Orchestrator queued-work attention / session work-set rediscovery without scheduler/polling/queue-drain behavior, preserve `queued -> inprogress` acceptance gate, suppress re-kick while active_inprogress work exists, prevent duplicate starts, and add focused tests plus required validation.
- Constraint: coder was instructed not to use root/original workspace for decision evidence or git/validation/cleanup, and not to create generated memory/local/runtime/log/lock/secret-like `.yoi` paths.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T16:04:17Z -->
## Implementation report
Coder completed implementation.
Coder Pod:
- `yoi-coder-idle-queued-rekick`
Implementation branch/worktree:
- Branch: `ticket/orchestrator-idle-queued-rekick`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Commit: `d2fae81a tui: add idle queued orchestrator attention`
- Worktree status: clean
Changed surfaces:
- `crates/tui/src/multi_pod.rs`
- `resources/prompts/panel/orchestrator_idle_queue_notice.md`
Implementation summary:
- Adds session-scoped `OrchestratorWorkSet` derived at Panel reload boundary.
- Derives `active_inprogress`, new/actionable queued, planned queued, waiting reasons, and duplicate guards from Panel Ticket rows, local role-session claims, related Pods, blocked reasons, and live Orchestrator status.
- Sends bounded Orchestrator attention only when Orchestrator is live/reachable/idle and queued work is actionable.
- Suppresses attention when active_inprogress exists or duplicate-start guard indicates existing claim/Pod/worktree activity.
- Retains waiting reason / planned queued information in Panel header detail for session-visible explanation.
- Adds prompt resource `resources/prompts/panel/orchestrator_idle_queue_notice.md` for the attention payload, preserving the prompt-resource boundary.
- Does not add scheduler loop, polling loop, queue drain loop, core Ticket states, or persistent work-set artifact store.
Implementation note for reviewer attention:
- Coder report used the phrase `workflow_state` for `TicketPanelEntry.workflow_state`; this is existing Panel model naming over the typed Ticket state enum, not reintroduction of obsolete Ticket frontmatter `workflow_state`.
Orchestrator-verified evidence from child worktree:
- `git status --short --branch`: clean on `ticket/orchestrator-idle-queued-rekick`
- `cargo test -p tui queued_attention`: pass, 3 tests
- `cargo test -p tui planned_queued_prompts`: pass, 1 test
- `cargo test -p tui rediscovered_queued_work`: pass, 1 test
- `cargo test -p tui active_inprogress_suppresses`: pass, 1 test
- `cargo test -p tui idle_orchestrator_gets_bounded_attention`: pass, 1 test
- `cargo test -p tui workspace_panel`: pass, 12 tests
- `cargo check -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known broad-suite note from coder:
- `cargo test -p tui` still fails unrelated existing/neighboring expectation tests:
- `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`
- `spawn::tests::profile_choices_use_project_registry_default`
- `spawn::tests::profile_choices_include_builtin_and_project_default_marker`
- Focused tests for this Ticket pass; reviewer should confirm broad failures are unrelated and not introduced by this Ticket.
Next:
- Spawn read-only sibling reviewer against recorded intent, binding decisions/invariants, acceptance criteria, commit `d2fae81a`, diff, validation evidence, and known broad-suite failures.
---
<!-- event: plan author: orchestrator at: 2026-06-12T16:05:08Z -->
## Plan
Reviewer delegated.
- Reviewer Pod: `yoi-reviewer-idle-queued-rekick`
- Target branch/worktree: `ticket/orchestrator-idle-queued-rekick` at `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Commit under review: `d2fae81a tui: add idle queued orchestrator attention`
- Scope: read-only child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Review basis: recorded IntentPacket, binding decisions/invariants, acceptance criteria, implementation summary, diff, focused validation evidence, `nix build` evidence, and known broad-suite failures.
- Reviewer focus: no scheduler/polling/queue-drain behavior, no acceptance-gate bypass, active_inprogress suppression, duplicate-start prevention, session-scoped work set, prompt-resource boundary, recent Panel/Companion behavior compatibility, and robust focused tests.
---
<!-- event: review author: reviewer:yoi-reviewer-idle-queued-rekick at: 2026-06-12T16:10:24Z status: approve -->
## Review: approve
Approve.
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Commit: `d2fae81a tui: add idle queued orchestrator attention`
Evidence:
- 差分は `crates/tui/src/multi_pod.rs``resources/prompts/panel/orchestrator_idle_queue_notice.md` のみ。
- queued work への通知は idle かつ reachable な Orchestrator Pod に限定されている。
- `Method::Notify { auto_run: true }` は bounded attention / re-kick として使われるだけで、Ticket 状態変更・Pod spawn・worktree 作成・queue drain は追加されていない。
- Scheduler / queue drain / background worker は追加されていない。既存 Panel reload 後に fingerprint で重複抑制された通知を送る構成。
- `queued -> inprogress` acceptance は bypass されていない。通知 payload は Ticket state verification と通常 acceptance 記録を明示し、implementation side effect は行わない。
- `active_inprogress` suppression は実装されている。`TicketWorkflowState::InProgress` が存在する場合、queued attention は送られず、waiting reason として session work set に残る。
- Duplicate-start guard は title/label ではなく、Ticket id に紐づく local claim / related visible Pods / worktree 表示情報から導出している。
- Session work set は `MultiPodApp` 内の runtime/session-scoped state のみで、永続 per-Ticket artifact は追加されていない。
- Prompt 本文は `resources/prompts/panel/orchestrator_idle_queue_notice.md` に置かれており、Rust 側は include/render の境界に留まっている。
- `workflow_state` 命名は既存の typed `TicketWorkflowState` / Panel internal naming の利用であり、この差分で obsolete frontmatter authority を再導入しているものではない。
Reviewer-run validation:
- `cargo test -p tui queued_attention -- --nocapture`: pass, 3 tests
- `cargo test -p tui planned_queued_prompts -- --nocapture`: pass
- `cargo test -p tui rediscovered_queued_work -- --nocapture`: pass
- `cargo test -p tui idle_orchestrator_gets_bounded_attention -- --nocapture`: pass
- `cargo test -p tui active_inprogress_suppresses -- --nocapture`: pass
- `cargo test -p tui workspace_panel -- --nocapture`: pass, 12 tests
- `cargo check -p tui`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD && cargo fmt --check`: pass
Known broad-suite failures:
- `cargo test -p tui`: expected broad-suite failure, 312 passed / 3 failed.
- Failing tests:
- `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`
- `spawn::tests::profile_choices_use_project_registry_default`
- `spawn::tests::profile_choices_include_builtin_and_project_default_marker`
- The two `spawn` failures are in untouched `crates/tui/src/spawn.rs`.
- The `orchestrator_launch_context...` failure is in `multi_pod.rs`, but this diff does not touch `build_orchestrator_launch_context` or that test area; it remains the existing/neighboring expectation mismatch reported by coder. Not a blocker for this Ticket.
Non-blocking risks:
- Failed delivery is not fingerprint-marked, so a repeatedly reachable-but-rejecting socket can retry on subsequent Panel reloads; this is consistent with existing notice behavior but may be noisy.
- Duplicate guard depends on the Panels existing visible claim/pod/worktree derivation, so it prevents duplicate starts for locally visible state but is not a full global scheduler/lock. This matches the Tickets bounded Panel-attention scope.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T16:11:43Z -->
## Implementation report
Integration completed in the Orchestrator workspace.
Integrated implementation:
- Ticket: `00001KTJXS31R`
- Implementation branch: `ticket/orchestrator-idle-queued-rekick`
- Implementation commit: `d2fae81a tui: add idle queued orchestrator attention`
- Reviewer result: approve, no blockers
- Orchestrator merge commit: `9538feb1 merge: idle queued orchestrator attention`
- Integration target: `orchestration/yoi-orchestrator`
Post-integration validation from Orchestrator worktree:
- `cargo test -p tui queued_attention`: pass, 3 tests
- `cargo test -p tui planned_queued_prompts`: pass, 1 test
- `cargo test -p tui rediscovered_queued_work`: pass, 1 test
- `cargo test -p tui active_inprogress_suppresses`: pass, 1 test
- `cargo test -p tui idle_orchestrator_gets_bounded_attention`: pass, 1 test
- `cargo test -p tui workspace_panel`: pass, 12 tests
- `cargo check -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known broad-suite failures:
- Existing broad `cargo test -p tui` failures noted by coder/reviewer remain outside this Ticket and were not blockers for focused implementation/review.
Remaining non-blocking risks:
- Failed attention delivery is not fingerprint-marked, so a repeatedly reachable-but-rejecting socket can retry on subsequent Panel reloads; this is consistent with existing notice behavior but may be noisy.
- Duplicate guard is bounded to Panel-visible claim/Pod/worktree derivation and is not a full global scheduler/lock, matching this Ticket's scoped attention model.
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T16:11:51Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Implementation was merged into the Orchestrator branch, reviewer approved with no blockers, and post-integration validation passed. Cleanup and closure will be recorded next.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T16:12:22Z -->
## Implementation report
Cleanup completed.
- Stopped coder Pod: `yoi-coder-idle-queued-rekick`
- Stopped reviewer Pod: `yoi-reviewer-idle-queued-rekick`
- Removed child worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick`
- Deleted implementation branch: `ticket/orchestrator-idle-queued-rekick`
- Orchestrator worktree status after cleanup: clean
Cleanup was limited to child implementation worktree/branch and related child Pods. Root/original workspace was not touched.
---
<!-- event: state_changed author: hare at: 2026-06-12T16:12:42Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-12T16:12:42Z status: closed -->
## 完了
Orchestrator Idle 時に queued Ticket を見落とさない bounded attention layer を実装した。
実装概要:
- `crates/tui/src/multi_pod.rs` に session-scoped `OrchestratorWorkSet` を追加し、Panel reload 境界で queued/actionable/planned/active_inprogress を導出するようにした。
- Idle かつ reachable な Orchestrator Pod にだけ bounded queued-work attention を送る。
- `active_inprogress` がある場合は re-kick を抑制し、waiting reason を session work set / Panel header detail に保持する。
- Duplicate-start guard は Ticket id に紐づく local claim / related visible Pods / worktree 表示情報から導出する。
- Session work set は `MultiPodApp` 内 runtime/session state に留め、durable per-Ticket artifact store は追加していない。
- `resources/prompts/panel/orchestrator_idle_queue_notice.md` を追加し、Orchestrator attention payload の prompt 本文を resource 化した。
- Scheduler loop、polling loop、queue drain loop、core Ticket state、implementation side effect、acceptance gate bypass は追加していない。
Review / integration:
- Implementation commit: `d2fae81a tui: add idle queued orchestrator attention`
- Reviewer: `yoi-reviewer-idle-queued-rekick` が approve。
- Orchestrator merge commit: `9538feb1 merge: idle queued orchestrator attention`
- Ticket completion commit: `60cf2d9f ticket: mark idle queued done`
Validation:
- `cargo test -p tui queued_attention`: pass, 3 tests
- `cargo test -p tui planned_queued_prompts`: pass, 1 test
- `cargo test -p tui rediscovered_queued_work`: pass, 1 test
- `cargo test -p tui active_inprogress_suppresses`: pass, 1 test
- `cargo test -p tui idle_orchestrator_gets_bounded_attention`: pass, 1 test
- `cargo test -p tui workspace_panel`: pass, 12 tests
- `cargo check -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known broad-suite failures:
- Existing broad `cargo test -p tui` failures noted in thread remain outside this Ticket and were not blockers for focused implementation/review.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/orchestrator-idle-queued-rekick` removed。
- branch `ticket/orchestrator-idle-queued-rekick` deleted。
Non-blocking risks:
- Failed attention delivery is not fingerprint-marked, so a repeatedly reachable-but-rejecting socket can retry on subsequent Panel reloads; this is consistent with existing notice behavior but may be noisy。
- Duplicate guard is bounded to Panel-visible claim/Pod/worktree derivation and is not a full global scheduler/lock, matching this Ticket の scoped attention model。
---

View File

@ -1,8 +1,8 @@
---
title: 'Orchestrator進捗をAutoKickなしでCompanionへ通知する'
state: 'queued'
state: 'closed'
created_at: '2026-06-11T08:15:24Z'
updated_at: '2026-06-11T16:07:34Z'
updated_at: '2026-06-12T15:44:42Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-11T10:31:56Z'

View File

@ -0,0 +1,41 @@
Orchestrator progress を AutoKick なしで live/reachable Companion に通知する仕組みを実装した。
実装概要:
- `Method::Notify { auto_run: bool }` を追加し、`auto_run: false` では idle Pod に `RunForNotification` を stage しない weak notification にした。
- `auto_run: true` と legacy missing-field behavior は既存 Notify と互換にした。
- Panel から live/reachable Companion へ bounded progress notice を `Notify { auto_run: false }` で送るようにした。
- missing/stopped/unreachable Companion は best-effort no-op とし、spawn/restore しない。
- Progress summary は Ticket id/title/state、role pod status、short reason、`.yoi/tickets/<id>` refs に限定し、full thread、Pod output、diagnostics、provider errors、secret-like content を含めない。
- Panel に Companion progress freshness / last-updated indication を追加した。
- Reviewer request_changes を受け、Companion progress notice の LLM-facing framing を Rust 直書きから `resources/prompts/panel/companion_progress_notice.md` へ移し、Rust は bounded runtime values の rendering に限定した。
- Companion profile/tool authority は変更していない。
Review / integration:
- Implementation commits:
- `a87d3154 feat: weak companion progress notify`
- `61e6c068 fix: resource-back companion progress notice`
- Reviewer: `yoi-reviewer-companion-progress-notify` が初回 request_changes、fix 後 approve。
- Orchestrator merge commit: `56b10a2d merge: companion weak progress notify`
- Ticket completion commit: `2b64f428 ticket: mark companion notify done`
Validation:
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 6 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated broad-suite failures:
- Existing prompt/TUI broad-suite failures noted in thread remain outside this Ticket and were not blockers for focused implementation/review.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify` removed。
- branch `ticket/orchestrator-progress-companion-notify` deleted。
Non-blocking risk:
- Added `minijinja` dependency to `crates/tui`; it is already used elsewhere in the workspace, and `Cargo.lock` / `package.nix` were updated with passing Nix build.

View File

@ -111,3 +111,406 @@ Next action:
- ユーザー/上位 Orchestrator から実装開始の explicit follow-up が来たら、side effect 前に TicketShow / relation / orchestration plan / git/worktree state を再確認し、問題なければ `queued -> inprogress` を記録してから worktree 作成と sibling coder/reviewer routing に進む。
---
<!-- event: decision author: orchestrator at: 2026-06-12T14:50:56Z -->
## Decision
Routing follow-up: implementation start authorized by user.
Recheck summary:
- Ticket remains `queued` and previously recorded `implementation_ready` still applies.
- TicketRelationQuery: no unresolved `depends_on` / incoming `blocks` for this Ticket.
- TicketOrchestrationPlan: accepted plan `orch-plan-20260611-160703-1` names branch/worktree and defers implementation until explicit follow-up; that follow-up has now arrived.
- Orchestrator worktree is clean.
- Visible active work: `00001KTVJFT6F` has coder `yoi-coder-panel-focus-model` running on a separate branch/worktree. There may be minor overlap in `crates/tui/src/multi_pod.rs` around Panel UI, so coder/reviewer must keep the Panel freshness change narrow and integration will recheck conflicts before merge.
Decision:
- Accept this Ticket now and proceed to `queued -> inprogress` before worktree/Pod side effects.
- Use existing accepted plan branch `ticket/orchestrator-progress-companion-notify` and worktree `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`.
- Continue to avoid root/original workspace operations; implementation side effects are limited to the child worktree and sibling Pods.
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T14:51:03Z from: queued to: inprogress reason: orchestrator_acceptance field: state -->
## State changed
Explicit user follow-up authorized starting the previously accepted implementation plan. Ticket body/thread, relation blockers, accepted orchestration plan, current Orchestrator workspace state, and visible active work were rechecked. No unresolved blocker or missing planning decision remains. Implementation side effects will start only after this accepted `queued -> inprogress` transition is recorded.
---
<!-- event: plan author: orchestrator at: 2026-06-12T14:51:31Z -->
## Plan
Implementation worktree created for multi-agent handoff.
- Ticket: `00001KTTW04W2`
- Branch: `ticket/orchestrator-progress-companion-notify`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Base: Orchestrator workspace HEAD `05fe1f6f` (`orchestration/yoi-orchestrator`), including the accepted routing record and `queued -> inprogress` transition.
- Concurrent work note: `00001KTVJFT6F` is active in `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection`; any Panel UI edits should be narrow and integration will recheck conflict risk.
- Scope rule: implementation work happens only in this child worktree. Root/original workspace must not be read, written, validated, merged, cleaned, or used for git operations.
- Next: spawn sibling coder with narrow write scope to the implementation worktree. Reviewer will be started after coder evidence is available.
---
<!-- event: plan author: orchestrator at: 2026-06-12T14:52:34Z -->
## Plan
Coder delegated.
- Coder Pod: `yoi-coder-companion-progress-notify`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Branch: `ticket/orchestrator-progress-companion-notify`
- Scope: write `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`; read child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Task: implement `Notify { auto_run: false }` weak progress notification semantics, bounded Orchestrator progress summary delivery to live/reachable Companion, missing/stopped no spawn/restore behavior, Panel freshness/last-updated indication, focused tests, and required validation.
- Concurrent work note: `00001KTVJFT6F` has active coder work in another worktree and may edit Panel UI; coder was instructed to keep Panel changes narrow and report overlap if it becomes a blocker.
- Constraint: coder was instructed not to use root/original workspace for decision evidence or git/validation/cleanup, and not to create generated memory/local/runtime/log/lock/secret-like `.yoi` paths.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:23:02Z -->
## Implementation report
Coder completed implementation and branch was synchronized with current Orchestrator HEAD before review.
Coder Pod:
- `yoi-coder-companion-progress-notify`
Implementation branch/worktree:
- Branch: `ticket/orchestrator-progress-companion-notify`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Implementation commit: `a87d3154 feat: weak companion progress notify`
- Sync merge commit on implementation branch: `724b79f1 Merge branch 'orchestration/yoi-orchestrator' into ticket/orchestrator-progress-companion-notify`
- Worktree status: clean
Changed surfaces:
- `crates/protocol/src/lib.rs`
- `crates/pod/src/controller.rs`
- `crates/pod/src/discovery.rs`
- `crates/pod/tests/controller_test.rs`
- `crates/tui/src/multi_pod.rs`
Implementation summary:
- Added `Method::Notify { auto_run: bool }`; missing `auto_run` defaults to `true`, `true` serializes like the old shape, and `false` is explicit.
- Idle Pod `Notify { auto_run: false }` does not stage `RunForNotification`; explicit next run drains notification history-backed through existing paths.
- Existing peer notify/discovery paths keep `auto_run: true`.
- Panel sends bounded progress notices to live/reachable Companion only via weak `Notify { auto_run: false }`.
- Missing/stopped/unreachable Companion is best-effort no-op; no spawn/restore.
- Progress summary is bounded to Ticket id/title/state, role pod status, and `.yoi/tickets/<id>` refs; no full thread, long output, diagnostics, provider errors, or secret-like content.
- Panel title shows Companion progress freshness/last-updated without adding a persistent snapshot store.
- Companion profile/tool authority is unchanged.
Orchestrator-verified evidence from child worktree after sync with current Orchestrator branch:
- `git status --short --branch`: clean on `ticket/orchestrator-progress-companion-notify`
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 5 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failures from coder full-suite notes:
- `cargo test -p pod` still fails existing prompt-resource assertion tests: `worker_instruction_override_from_resources`, `worker_instruction_uses_resource_template`.
- `cargo test -p tui` still fails existing tests: `multi_pod::tests::orchestrator_launch_context_includes_ticket_and_workspace_facts`, `multi_pod::tests::spawn_or_restore_companion_restores_live_pod`, `multi_pod::tests::spawn_or_restore_companion_spawns_missing_pod`.
- Focused weak-notify/progress tests pass; reviewer should confirm the broad failures are unrelated/pre-existing and not introduced by this Ticket.
Next:
- Spawn read-only sibling reviewer against the recorded intent, binding decisions/invariants, acceptance criteria, implementation commit `a87d3154`, synced review head `724b79f1`, diff, validation evidence, and known broad-suite failures.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:23:52Z -->
## Plan
Reviewer delegated.
- Reviewer Pod: `yoi-reviewer-companion-progress-notify`
- Target branch/worktree: `ticket/orchestrator-progress-companion-notify` at `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Implementation commit: `a87d3154 feat: weak companion progress notify`
- Synced review head: `724b79f1 Merge branch 'orchestration/yoi-orchestrator' into ticket/orchestrator-progress-companion-notify`
- Scope: read-only child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Review basis: recorded IntentPacket, binding decisions/invariants, acceptance criteria, implementation summary, diff after syncing with current Orchestrator branch, focused validation evidence, `nix build` evidence, and known broad-suite failures.
- Reviewer focus: no AutoKick/re-kick/scheduler behavior, legacy notify compatibility, bounded/history-backed progress notices, missing/stopped Companion no-op, no authority expansion, Panel freshness UI compatibility with merged focus model, and robust focused tests.
---
<!-- event: review author: reviewer:yoi-reviewer-companion-progress-notify at: 2026-06-12T15:30:03Z status: request_changes -->
## Review: request changes
Request changes.
Blocker:
- `crates/tui/src/multi_pod.rs``companion_progress_notice()` が、Companion の model context に入る progress notice の framing 文言を Rust に直書きしている。
- この notice は `dispatch_companion_progress_notice()` から `Notify { auto_run: false }` として送られ、NotifyBuffer 経由で history-backed な SystemItem / LLM context になるため、単なる Panel UI 文言ではなく LLM-facing framing と判断する。
- Ticket の明示要件「Prompt / workflow 文言を Rust code に直書きしない」「LLM-facing summary framing が必要な場合は `resources/prompts` 側に置く」に反している。
Requested change:
- Rust 側は bounded runtime values の組み立てに留める。
- progress notice の framing/template は `resources/prompts` 配下へ移す。
- template/resource rendering の focused test を追加または既存 `companion_progress` tests を更新し、framing が resource 側から来ることと bounded/sensitive-safe values が維持されることを確認する。
Good evidence confirmed:
- `auto_run:false` は idle Pod に `RunForNotification` を staged しない。
- `auto_run:true` と legacy missing field の挙動は維持されている。
- live/reachable Companion の socket に `Notify { auto_run: false }` を送るだけで、missing/stopped/unreachable では spawn/restore されない。
- 通知内容は Ticket id/title/state、role pod status、short reason、`.yoi/tickets/<id>` ref に絞られ、thread excerpt / diagnostics / provider error token はテストで除外確認されている。
- Companion profile / authority 強化は diff 上ない。
- Panel freshness は header detail 表示で、composer target / row selection の focus model には干渉していない。
Reviewer-run validation:
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 5 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Broad-suite failures:
- `cargo test -p pod` currently fails 2 prompt-resource assertion tests.
- `cargo test -p tui` currently fails 3 unrelated-looking tests.
- These broad-suite failures do not appear caused by the progress-notify diff and are not the requested-change blocker.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:31:01Z -->
## Plan
Fix loop delegated to coder.
Reviewer blocker:
- `companion_progress_notice()` hard-coded LLM-facing progress notice framing in Rust.
- The notice reaches Companion model context through `Notify { auto_run: false }` / NotifyBuffer, so it must follow the prompt-resource boundary.
Coder fix request:
- Move progress notice framing/template to `resources/prompts` using existing resource conventions.
- Keep Rust limited to bounded runtime values and resource rendering/loading.
- Preserve weak notify semantics, live/reachable-only delivery, missing/stopped no spawn/restore, bounded/sensitive-safe summary, no persistent snapshot store, and no authority expansion.
- Add/update focused tests proving resource-backed framing and bounded/sensitive-safe runtime values.
Status:
- Sent fix request to `yoi-coder-companion-progress-notify` on existing branch/worktree.
- Reviewer verdict remains `request_changes` until coder fix and second review.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:40:14Z -->
## Implementation report
Coder completed requested fix.
Coder Pod:
- `yoi-coder-companion-progress-notify`
Implementation branch/worktree:
- Branch: `ticket/orchestrator-progress-companion-notify`
- Worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Original implementation commit: `a87d3154 feat: weak companion progress notify`
- Sync merge commit: `724b79f1 Merge branch 'orchestration/yoi-orchestrator' into ticket/orchestrator-progress-companion-notify`
- Fix commit: `61e6c068 fix: resource-back companion progress notice`
- Worktree status: clean
Fix summary:
- Added `resources/prompts/panel/companion_progress_notice.md` for model-facing Companion progress notice framing.
- Removed hard-coded progress notice framing from Rust.
- Rust now builds bounded runtime values and renders the prompt resource via `minijinja`.
- Added focused test proving the notice renders from the prompt resource.
- Preserved live/reachable-only delivery, missing/stopped no-op, `auto_run:false`, bounded output, sensitive-field exclusion, and no persistent snapshot store.
- Added `minijinja` to `crates/tui/Cargo.toml`, updated `Cargo.lock`, and updated `package.nix` `cargoHash` for Nix packaging.
Orchestrator-verified evidence from child worktree after fix:
- `git status --short --branch`: clean on `ticket/orchestrator-progress-companion-notify`
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 6 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Next:
- Request reviewer re-review of fix commit `61e6c068`, focusing on the prompt-resource boundary blocker, retention of weak notify safety invariants, dependency/package updates, and validation evidence.
---
<!-- event: review author: reviewer:yoi-reviewer-companion-progress-notify at: 2026-06-12T15:42:21Z status: approve -->
## Review: approve
Approve.
The previous requested-change blocker is resolved.
Review findings:
- Prompt/resource boundary is now satisfied:
- Companion progress notice framing lives in `resources/prompts/panel/companion_progress_notice.md`.
- Rust only builds bounded runtime values and renders the prompt resource via `minijinja`.
- `COMPANION_PROGRESS_NOTICE_TEMPLATE` uses `include_str!` to load the resource.
- `render_companion_progress_notice_template()` renders with strict `minijinja` undefined behavior.
- Focused test `companion_progress_notice_uses_prompt_resource_template` confirms rendering comes from the resource.
- Grep for prior hard-coded framing found no Rust production copy of the prompt text; only test assertion remains.
- Weak notify invariants remain intact:
- Companion progress dispatch still uses `send_notify_only(..., false)`.
- `auto_run:false` controller behavior remains covered by pod controller tests.
- `auto_run:true` legacy behavior remains covered by protocol/controller tests.
- Missing/stopped/unreachable Companion remains no-op:
- Target selection still requires Companion panel state to be peer-reachable and a live reachable socket.
- No spawn/restore path is introduced for progress delivery.
- No Companion authority expansion found:
- The fix touches prompt rendering, TUI dependency metadata, `Cargo.lock`, and `package.nix`; it does not alter Companion profile/tool authority.
- Bounded/sensitive-safe summary remains preserved:
- Runtime values are bounded before/after rendering.
- The summary still uses ticket id/state/title/ref and role pod status, not thread excerpts, diagnostics, Pod output, or provider error details.
- Dependency/package updates are appropriate:
- `minijinja = "2.19.0"` is already used elsewhere in the workspace (`crates/pod`), so adding it to `crates/tui` does not introduce an unexpected new dependency family.
- `Cargo.lock` and `package.nix` `cargoHash` were updated, and `nix build .#yoi` passes.
Reviewer-run validation:
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo test -p tui companion_progress -- --nocapture`: pass, 6 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
No blocking issues remain.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:43:51Z -->
## Implementation report
Integration completed in the Orchestrator workspace.
Integrated implementation:
- Ticket: `00001KTTW04W2`
- Implementation branch: `ticket/orchestrator-progress-companion-notify`
- Implementation commits:
- `a87d3154 feat: weak companion progress notify`
- `61e6c068 fix: resource-back companion progress notice`
- Reviewer result: approve after fix-loop, no blockers remain
- Orchestrator merge commit: `56b10a2d merge: companion weak progress notify`
- Integration target: `orchestration/yoi-orchestrator`
Post-integration validation from Orchestrator worktree:
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 6 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Fix-loop resolution:
- Reviewer blocker about Rust-hard-coded LLM-facing progress notice framing was resolved by moving framing to `resources/prompts/panel/companion_progress_notice.md` and rendering it from bounded runtime values.
Remaining known broad-suite failures:
- Existing prompt/TUI broad-suite failures noted earlier remain outside this Ticket and were not blockers for the focused implementation/review.
Remaining risks:
- None blocking. Added `minijinja` dependency to `crates/tui`, already used elsewhere in workspace; `Cargo.lock` and `package.nix` were updated and Nix build passed.
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T15:43:57Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Implementation was merged into the Orchestrator branch after reviewer-requested fix, reviewer approved with no blockers, and post-integration validation passed. Cleanup and closure will be recorded next.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:44:26Z -->
## Implementation report
Cleanup completed.
- Stopped coder Pod: `yoi-coder-companion-progress-notify`
- Stopped reviewer Pod: `yoi-reviewer-companion-progress-notify`
- Removed child worktree: `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify`
- Deleted implementation branch: `ticket/orchestrator-progress-companion-notify`
- Orchestrator worktree status after cleanup: clean
Cleanup was limited to child implementation worktree/branch and related child Pods. Root/original workspace was not touched.
---
<!-- event: state_changed author: hare at: 2026-06-12T15:44:42Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-12T15:44:42Z status: closed -->
## 完了
Orchestrator progress を AutoKick なしで live/reachable Companion に通知する仕組みを実装した。
実装概要:
- `Method::Notify { auto_run: bool }` を追加し、`auto_run: false` では idle Pod に `RunForNotification` を stage しない weak notification にした。
- `auto_run: true` と legacy missing-field behavior は既存 Notify と互換にした。
- Panel から live/reachable Companion へ bounded progress notice を `Notify { auto_run: false }` で送るようにした。
- missing/stopped/unreachable Companion は best-effort no-op とし、spawn/restore しない。
- Progress summary は Ticket id/title/state、role pod status、short reason、`.yoi/tickets/<id>` refs に限定し、full thread、Pod output、diagnostics、provider errors、secret-like content を含めない。
- Panel に Companion progress freshness / last-updated indication を追加した。
- Reviewer request_changes を受け、Companion progress notice の LLM-facing framing を Rust 直書きから `resources/prompts/panel/companion_progress_notice.md` へ移し、Rust は bounded runtime values の rendering に限定した。
- Companion profile/tool authority は変更していない。
Review / integration:
- Implementation commits:
- `a87d3154 feat: weak companion progress notify`
- `61e6c068 fix: resource-back companion progress notice`
- Reviewer: `yoi-reviewer-companion-progress-notify` が初回 request_changes、fix 後 approve。
- Orchestrator merge commit: `56b10a2d merge: companion weak progress notify`
- Ticket completion commit: `2b64f428 ticket: mark companion notify done`
Validation:
- `cargo test -p protocol`: pass, 39 tests
- `cargo test -p pod --test controller_test`: pass, 36 tests
- `cargo test -p tui companion_progress -- --nocapture`: pass, 6 tests
- `cargo test -p tui send_notify_only_can_deliver_weak_notification_without_auto_run -- --nocapture`: pass, 1 test
- `cargo check -p protocol -p pod -p tui`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated broad-suite failures:
- Existing prompt/TUI broad-suite failures noted in thread remain outside this Ticket and were not blockers for focused implementation/review.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/orchestrator-progress-companion-notify` removed。
- branch `ticket/orchestrator-progress-companion-notify` deleted。
Non-blocking risk:
- Added `minijinja` dependency to `crates/tui`; it is already used elsewhere in the workspace, and `Cargo.lock` / `package.nix` were updated with passing Nix build.
---

View File

@ -1,8 +1,8 @@
---
title: 'Workspace panel の focus model を composer target と row selection に整理する'
state: 'inprogress'
state: 'closed'
created_at: '2026-06-11T14:48:26Z'
updated_at: '2026-06-12T14:46:41Z'
updated_at: '2026-06-12T15:09:15Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['tui-ux', 'input-safety']

View File

@ -0,0 +1,38 @@
Workspace panel の focus model を composer target と row selection に整理した。
実装概要:
- `yoi panel` の user-visible focus 表示から `item action focus` / `Right action focus` / `global composer` / `PanelFocus` / `ItemAction` 系の不要な focus model を除去した。
- composer target は送信先、row selection は空 composer 時の navigation / Enter 対象として扱う表示・挙動へ整理した。
- 非空 composer では composer draft / target を優先し、`Enter` は composer send / Intake 起動に向く。
- 空 composer では selected row が `Enter` 対象になり、既存 Ticket action dispatch / Pod open 経路を使う。
- `Tab` は composer target の切替のみで selected row と draft を保持する。
- `Esc` は row selection を解除し、composer draft と target は保持する。
- `Left` / `Right` は Panel focus 切替ではなく composer cursor 操作として扱う。
- Ticket action dispatch、Pod open、Intake launch、Companion send の authority / safety semantics は維持した。
Review / integration:
- Implementation commit: `c5ef6f79 tui: clarify panel composer target and row selection`
- Reviewer: `yoi-reviewer-panel-focus-model` が approve。
- Orchestrator merge commit: `d6166c72 merge: panel focus composer row selection`
- Ticket completion commit: `e330685e ticket: mark panel focus done`
Validation:
- `cargo test -p tui selected_ticket_row_with_non_empty_composer_shows_composer_enter_behavior`: pass
- `cargo test -p tui multi_esc_clears_row_selection_without_quitting_and_preserves_draft`: pass
- `cargo test -p tui multi_composer_target_switch_preserves_typed_text`: pass
- `cargo test -p tui multi_blank_ticket_intake_enter_uses_selected_row_and_preserves_input`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p tui multi_ --lib` still includes pre-existing failure `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`; this was verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection` removed。
- branch `ticket/panel-focus-composer-row-selection` deleted。
Non-blocking risks:
- Reviewer found none for this Ticket.

View File

@ -149,3 +149,216 @@ Coder delegated.
- Constraint: coder was instructed not to use root/original workspace for decision evidence or git/validation/cleanup, and not to create generated memory/local/runtime/log/lock/secret-like `.yoi` paths.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:01:02Z -->
## Implementation report
Coder completed implementation.
Coder Pod:
- `yoi-coder-panel-focus-model`
Implementation branch/worktree:
- Branch: `ticket/panel-focus-composer-row-selection`
- Worktree: `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection`
- Commit: `c5ef6f79 tui: clarify panel composer target and row selection`
- Worktree status: clean
Changed surfaces:
- `crates/tui/src/multi_pod.rs`
- `crates/tui/src/workspace_panel.rs`
Implementation summary:
- Removed user-visible `PanelFocus` / `ItemAction` style focus model.
- `Tab` switches composer target without clearing selected row.
- `Esc` clears row selection while preserving composer draft and target.
- Non-empty composer prioritizes draft/text input and `Enter` targets composer send.
- Blank composer uses selected row as `Enter` target for Ticket action / Pod open.
- Title/status/actionbar/row hints no longer expose `global composer`, `item action`, or `Right action focus` as focus states.
- `Left` / `Right` are presented as composer cursor movement, not Panel focus switching.
Orchestrator-verified evidence from child worktree:
- `git status --short --branch`: clean on `ticket/panel-focus-composer-row-selection`
- Focused changed tests passed individually:
- `cargo test -p tui selected_ticket_row_with_non_empty_composer_shows_composer_enter_behavior`
- `cargo test -p tui multi_esc_clears_row_selection_without_quitting_and_preserves_draft`
- `cargo test -p tui multi_composer_target_switch_preserves_typed_text`
- `cargo test -p tui multi_blank_ticket_intake_enter_uses_selected_row_and_preserves_input`
- `cargo fmt --check`: pass
- `git diff --check`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p tui multi_ --lib` fails one test: `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`.
- The same focused failing test also fails on current Orchestrator branch before this implementation is merged, with `context.workspace_root` `/repo/yoi` vs expected `/repo/yoi/.worktree/orchestration/yoi-orchestrator`.
- The failure is not in the changed focus/composer/row-selection path, but reviewer should still confirm it is unrelated and not introduced by this Ticket.
Next:
- Spawn read-only sibling reviewer against the recorded intent, binding decisions/invariants, acceptance criteria, commit `c5ef6f79`, diff, focused validation evidence, `nix build` evidence, and the known pre-existing unrelated `multi_` failure.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:01:54Z -->
## Plan
Reviewer delegated.
- Reviewer Pod: `yoi-reviewer-panel-focus-model`
- Target branch/worktree: `ticket/panel-focus-composer-row-selection` at `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection`
- Commit under review: `c5ef6f79 tui: clarify panel composer target and row selection`
- Scope: read-only child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Review basis: recorded IntentPacket, binding decisions/invariants, acceptance criteria, implementation summary, diff, focused validation evidence, `nix build` evidence, and known pre-existing unrelated `multi_` failure evidence.
- Reviewer focus: composer input protection, blank/non-blank Enter behavior, status/actionbar/key hint consistency, removal of user-visible `item action` / `Right action focus`, Ticket/Pod authority preservation, and staying within Panel scope.
---
<!-- event: review author: reviewer:yoi-reviewer-panel-focus-model at: 2026-06-12T15:07:09Z status: approve -->
## Review: approve
Approve.
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection`
- Commit: `c5ef6f79 tui: clarify panel composer target and row selection`
Evidence:
- 差分は `crates/tui/src/multi_pod.rs``crates/tui/src/workspace_panel.rs` に限定され、single-Pod TUI transcript/block navigation は変更していない。
- `Right action focus` / `global composer` / `item action` / `PanelFocus` / `ItemAction` は現行ツリー上で user-visible 文言・型として残っていない。
- 非空 composer の `Enter` は composer target 送信 / Intake 起動に向き、row selection の Ticket action / Pod open は待機扱いになる。
- 空 composer では selected row が `Enter` 対象になり、既存 Ticket action dispatch / Pod open 経路を使う。
- `Tab` は composer target の切替のみで selected row と draft を保持する。
- `Esc` は row selection を解除し、composer draft と target は保持する。
- `Left` / `Right` は Panel focus 切替ではなく composer cursor 操作として扱われる。
- Ticket action dispatch は従来通り stale/current authority re-check 経路を通り、`ready -> queued` などの明示 action semantics は弱められていない。
- Companion send は workspace Companion 宛て固定の安全確認を維持し、selected Pod へ誤送信する形にはなっていない。
Reviewer-run validation:
- `cargo test -p tui selected_ticket_row_with_non_empty_composer_shows_composer_enter_behavior`: pass
- `cargo test -p tui multi_esc_clears_row_selection_without_quitting_and_preserves_draft`: pass
- `cargo test -p tui multi_composer_target_switch_preserves_typed_text`: pass
- `cargo test -p tui multi_blank_ticket_intake_enter_uses_selected_row_and_preserves_input`: pass
- `cargo fmt --check`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
Known broad failure:
- `cargo test -p tui multi_ --lib` fails only `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`.
- The failure is the same `/repo/yoi` vs `/repo/yoi/.worktree/orchestration/yoi-orchestrator` mismatch already confirmed on the current Orchestrator branch, and this implementation does not change that launch-context path. It is pre-existing and not a blocker for this Ticket.
Non-blocking risks:
- None identified. The added tests directly cover key boundaries, draft protection, and target/row-selection display without brittle full UI snapshots.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:08:05Z -->
## Implementation report
Integration completed in the Orchestrator workspace.
Integrated implementation:
- Ticket: `00001KTVJFT6F`
- Implementation branch: `ticket/panel-focus-composer-row-selection`
- Implementation commit: `c5ef6f79 tui: clarify panel composer target and row selection`
- Reviewer result: approve, no blockers
- Orchestrator merge commit: `d6166c72 merge: panel focus composer row selection`
- Integration target: `orchestration/yoi-orchestrator`
Post-integration validation from Orchestrator worktree:
- `cargo test -p tui selected_ticket_row_with_non_empty_composer_shows_composer_enter_behavior`: pass
- `cargo test -p tui multi_esc_clears_row_selection_without_quitting_and_preserves_draft`: pass
- `cargo test -p tui multi_composer_target_switch_preserves_typed_text`: pass
- `cargo test -p tui multi_blank_ticket_intake_enter_uses_selected_row_and_preserves_input`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure remains:
- `cargo test -p tui multi_ --lib` still includes pre-existing failure `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`; this was verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Remaining risks:
- None identified by reviewer for this Ticket.
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T15:08:11Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Implementation was merged into the Orchestrator branch, reviewer approved with no blockers, and post-integration validation passed. Cleanup and closure will be recorded next.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:08:59Z -->
## Implementation report
Cleanup completed.
- Stopped coder Pod: `yoi-coder-panel-focus-model`
- Stopped reviewer Pod: `yoi-reviewer-panel-focus-model`
- Removed child worktree: `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection`
- Deleted implementation branch: `ticket/panel-focus-composer-row-selection`
- Orchestrator worktree status after cleanup: clean
Cleanup was limited to child implementation worktree/branch and related child Pods. Root/original workspace was not touched.
---
<!-- event: state_changed author: hare at: 2026-06-12T15:09:15Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-12T15:09:15Z status: closed -->
## 完了
Workspace panel の focus model を composer target と row selection に整理した。
実装概要:
- `yoi panel` の user-visible focus 表示から `item action focus` / `Right action focus` / `global composer` / `PanelFocus` / `ItemAction` 系の不要な focus model を除去した。
- composer target は送信先、row selection は空 composer 時の navigation / Enter 対象として扱う表示・挙動へ整理した。
- 非空 composer では composer draft / target を優先し、`Enter` は composer send / Intake 起動に向く。
- 空 composer では selected row が `Enter` 対象になり、既存 Ticket action dispatch / Pod open 経路を使う。
- `Tab` は composer target の切替のみで selected row と draft を保持する。
- `Esc` は row selection を解除し、composer draft と target は保持する。
- `Left` / `Right` は Panel focus 切替ではなく composer cursor 操作として扱う。
- Ticket action dispatch、Pod open、Intake launch、Companion send の authority / safety semantics は維持した。
Review / integration:
- Implementation commit: `c5ef6f79 tui: clarify panel composer target and row selection`
- Reviewer: `yoi-reviewer-panel-focus-model` が approve。
- Orchestrator merge commit: `d6166c72 merge: panel focus composer row selection`
- Ticket completion commit: `e330685e ticket: mark panel focus done`
Validation:
- `cargo test -p tui selected_ticket_row_with_non_empty_composer_shows_composer_enter_behavior`: pass
- `cargo test -p tui multi_esc_clears_row_selection_without_quitting_and_preserves_draft`: pass
- `cargo test -p tui multi_composer_target_switch_preserves_typed_text`: pass
- `cargo test -p tui multi_blank_ticket_intake_enter_uses_selected_row_and_preserves_input`: pass
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p tui multi_ --lib` still includes pre-existing failure `multi_pod::tests::orchestrator_launch_context_uses_orchestration_root_for_runtime_workspace`; this was verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/panel-focus-composer-row-selection` removed。
- branch `ticket/panel-focus-composer-row-selection` deleted。
Non-blocking risks:
- Reviewer found none for this Ticket.
---

View File

@ -0,0 +1 @@
{"id":"orch-plan-20260612-145344-1","ticket_id":"00001KTVJGC0Y","kind":"accepted_plan","accepted_plan":{"summary":"`ticket.language` guidance を Ticket role launch 専用から外し、Ticket tools を持つすべての PodCompanion-style non-role context を含む)に durable/model-visible に届くようにする。既存 Ticket record の rewrite は行わず、language policy 境界と prompt-context principle を維持する。","branch":"ticket/ticket-language-guidance-all-tools","worktree":"/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools","role_plan":"Coder は child worktree に限定して Ticket language guidance の universal Ticket-capable context/tool-surface delivery と focused tests を実装する。Reviewer は read-only で、Ticket role / non-role Companion-style context の両方に guidance が model-visible で届くこと、worker/memory/ticket language 境界、prompt-context safety、tool/feature boundary を確認する。"},"author":"orchestrator","at":"2026-06-12T14:53:44Z"}

View File

@ -1,8 +1,8 @@
---
title: 'Ticket language guidance must apply to all Ticket tool users'
state: 'queued'
state: 'closed'
created_at: '2026-06-11T14:48:44Z'
updated_at: '2026-06-12T14:49:39Z'
updated_at: '2026-06-12T15:20:11Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['prompt-context', 'tool-description', 'feature-boundary', 'ticket-language', 'companion']

View File

@ -0,0 +1,35 @@
Ticket tool users 全体に `ticket.language` guidance が届くようにした。
実装概要:
- `crates/ticket/src/tool.rs` に shared `ticket_tool_description(name, record_language)` を追加し、configured `ticket.language` がある場合は Ticket tool description に durable Ticket record / Ticket tool body language guidance を追加するようにした。
- `crates/pod/src/feature/builtin/ticket.rs` の builtin Ticket feature `ToolDeclaration` descriptions でも同じ helper を使い、read-only Companion-style context と lifecycle/Ticket-role-style context の両方に guidance が届くようにした。
- guidance は `worker.language` / `memory.language` / `ticket.language` を区別し、protocol literals、file paths、commands、logs、identifiers、quoted external text は fidelity 優先で保持することを明記した。
- guidance は Ticket tool / capability surface で model-visible であり、hidden context injection や `ticket_role` launch prompt fragment ではない。
- Companion/read-only authority や mutating tool exposure は拡大していない。
Review / integration:
- Implementation commit: `92c4dee7 ticket: guide Ticket tool language universally`
- Reviewer: `yoi-reviewer-ticket-language-guidance` が approve。
- Orchestrator merge commit: `ec66cad8 merge: ticket language guidance for tool users`
- Ticket completion commit: `2ba97b67 ticket: mark language guidance done`
Validation:
- `cargo test -p ticket ticket_record_language_guidance`: pass
- `cargo test -p pod ticket_language_guidance`: pass
- `cargo test -p client ticket_record_language_stays_out_of_first_run_text`: pass
- `cargo test -p ticket`: pass, 68 tests
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p pod` still includes pre-existing failures in Pod orchestration guidance prompt assertion tests. These were verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools` removed。
- branch `ticket/ticket-language-guidance-all-tools` deleted。
Non-blocking risk:
- configured language guidance is appended to every Ticket tool description, including read-only tools. This repeats some prompt text, but it is the accepted universal capability-surface tradeoff for this Ticket.

View File

@ -29,4 +29,337 @@ LocalTicketBackend によって作成されました。
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: orchestrator at: 2026-06-12T14:54:15Z -->
## Decision
Routing decision: implementation_ready
Reason:
- Ticket body は `ticket.language` guidance を Ticket role launch prompt 専用ではなく、Ticket tools を持つすべての Pod に model-visible に届ける要件を明確に記録している。
- `worker.language` / `memory.language` / `ticket.language` の責務分離、hidden context-only injection 禁止、既存 Ticket record の一括 rewrite 禁止が binding invariant として記録済みである。
- risk flags は prompt-context / tool-description / feature-boundary / ticket-language / companion だが、bounded context check の結果、具体的な未決定 design/API/authority 判断は残っていない。実装方式は Ticket capability/tool surface または feature-scoped system prompt path の範囲で coder が選べる。
- Relation blocker はなく、OrchestrationPlan に accepted plan `orch-plan-20260612-145344-1` を記録済み。
- 現在 active coder は `00001KTVJFT6F`Panel focus`00001KTTW04W2`Companion progress notifyだが、この Ticket の主対象は Ticket language guidance の prompt/tool/feature boundary であり、Panel UI 変更とは独立している。Companion-adjacent確認はあるが、authority強化や progress notify implementation と結合しないように実装・reviewで確認する。
Evidence checked:
- Ticket body / thread: requirements, acceptance criteria, binding decisions, implementation latitude, escalation conditions, validation, intake summary, `ready -> queued` event を確認。
- TicketRelationQuery: outgoing/incoming relation なし、blocker なし。
- TicketOrchestrationPlanQuery: 既存 record なし、今回 accepted plan を記録。
- Code/resource map: `ticket.language` / `Ticket record language` / Ticket tool/backend/feature/prompt surfaces を narrow search で確認。直近の role launch split により Ticket role first-run prompt から language guidance が外れているため、本 Ticket の universal delivery 実装が次の自然な境界であることを確認。
- Workspace/Pod state: Orchestrator worktree clean、active child worktree は別 branch/scope。
IntentPacket:
Intent:
- `ticket.language` guidance を Ticket role 固有の launch prompt ではなく、Ticket-writing tools を持つすべての Pod に durable/model-visible な形で届ける。
- Companion-style non-Ticket-role context でも Ticket tool body / durable Ticket record を configured `ticket.language` に従って書く guidance が見えるようにする。
Binding decisions / invariants:
- `ticket.language` は durable Ticket record / Ticket tool body writing policy であり、Ticket role 固有 policy ではない。
- `worker.language` は通常 prose、`memory.language` は Memory/Knowledge generation、`ticket.language` は durable Ticket records / Ticket tool bodies の責務に分ける。
- `ticket.language` が設定されていても protocol literals、file paths、commands、logs、identifiers、quoted external text を不要に翻訳しない。
- hidden context-only injection を作らない。guidance は tool surface / feature-scoped system prompt / committed prompt path など、モデルから見える根拠を残す。
- 既存 Ticket records を翻訳・一括 rewrite しない。
- Companion default authority を強化しない。
Requirements / acceptance criteria:
- Ticket tools を持つ non-Ticket-role Pod、特に Companion-style context でも guidance が model-visible になる。
- Ticket role Pods でも同等 guidance が届き、既存挙動が退行しない。
- guidance source は universal Ticket capability / tool surface または feature-scoped system prompt path にあり、Ticket role launch prompt 専用ではない。
- `worker.language``ticket.language` を override しない。
- focused test または snapshot-style verification で Ticket role と generic / Companion-style Ticket-capable context の両方を確認する。
- `nix build .#yoi` が通る。
Implementation latitude:
- Ticket tool descriptions/schema text に configured Ticket language instruction を入れる方式、または Ticket feature/capability が有効な Pod への feature-scoped prompt guidance を使う方式を選んでよい。
- 既存 architecture を広く作り替えず、現在の ToolRegistry/feature/prompt resource 境界に合う最小実装を選ぶ。
- Tests は prompt snapshot 全体に brittle にせず、language guidance の存在/非混同を直接確認する。
Escalate if:
- Tool descriptions が configured Ticket language に依存できず、広い ToolRegistry redesign が必要になる。
- feature-scoped prompt guidance が history に残らない context mutation を必要とする。
- Companion の Ticket capability path から Ticket config にアクセスできない。
- 実装が Ticket record language と worker response language を混同する。
- Companion authority を増やす必要が出る。
Validation:
- Ticket role prompt/context の focused test。
- generic / Companion-style Ticket-capable context の guidance 確認 test。
- relevant focused `cargo test`
- `cargo fmt --check`
- `git diff --check`
- `./result/bin/yoi ticket doctor` または同等。
- `nix build .#yoi`
Current code map:
- `crates/ticket/src/config.rs`: `ticket.language` config parsing / validation。
- `crates/ticket/src/tool.rs`: Ticket tool definitions/descriptions and tests。
- `crates/pod/src/feature/builtin/ticket.rs`: Ticket feature registration/capability/tool exposure。
- `crates/pod/src/prompt/*`: feature/system prompt integration if needed。
- `crates/client/src/ticket_role.rs`: ensure Ticket role launch still receives guidance through the new universal path, not first-run Submit prose。
Critical risks / reviewer focus:
- guidance が Ticket role launch prompt 専用に戻っていないこと。
- non-role Ticket-capable context にも model-visible に届くこと。
- hidden ephemeral context injection ではなく、tool/feature/prompt surface として履歴・prompt根拠が残ること。
- `worker.language``ticket.language` を混同しないこと。
- Companion authority / Ticket mutation authority を強化しないこと。
Next action:
- `queued -> inprogress` を記録してから、branch `ticket/ticket-language-guidance-all-tools` / worktree `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools` を作成し、sibling coder に narrow write scope で実装を委譲する。Reviewer は coder evidence 後に read-only で起動する。
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T14:54:22Z from: queued to: inprogress reason: orchestrator_acceptance field: state -->
## State changed
Routing accepted for implementation. Ticket body/thread, relation blockers, orchestration plan, relevant Ticket language / tool / feature / prompt code map, current Orchestrator workspace state, and active parallel work were rechecked. No unresolved blocker or missing planning decision remains. Implementation side effects will start only after this accepted `queued -> inprogress` transition is recorded, using accepted plan `orch-plan-20260612-145344-1`.
---
<!-- event: plan author: orchestrator at: 2026-06-12T14:54:49Z -->
## Plan
Implementation worktree created for multi-agent handoff.
- Ticket: `00001KTVJGC0Y`
- Branch: `ticket/ticket-language-guidance-all-tools`
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Base: Orchestrator workspace HEAD `76d358e8` (`orchestration/yoi-orchestrator`), including the accepted routing record and `queued -> inprogress` transition.
- Parallel work note: active child worktrees are `panel-focus-composer-row-selection` and `orchestrator-progress-companion-notify`; this Ticket should stay within Ticket language/tool/feature/prompt guidance surfaces and avoid coupling to their implementation branches.
- Scope rule: implementation work happens only in this child worktree. Root/original workspace must not be read, written, validated, merged, cleaned, or used for git operations.
- Next: spawn sibling coder with narrow write scope to the implementation worktree. Reviewer will be started after coder evidence is available.
---
<!-- event: plan author: orchestrator at: 2026-06-12T14:55:42Z -->
## Plan
Coder delegated.
- Coder Pod: `yoi-coder-ticket-language-guidance`
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Branch: `ticket/ticket-language-guidance-all-tools`
- Scope: write `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`; read child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Task: make configured `ticket.language` guidance model-visible for all Ticket-capable Pods, including non-role Companion-style contexts; preserve worker/memory/ticket language boundaries; avoid hidden context-only injection; add focused tests and required validation.
- Parallel work note: active sibling worktrees for Panel focus and Companion progress notification exist; coder was instructed to avoid coupling and report concrete merge/design conflict if found.
- Constraint: coder was instructed not to use root/original workspace for decision evidence or git/validation/cleanup, and not to create generated memory/local/runtime/log/lock/secret-like `.yoi` paths.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:10:38Z -->
## Implementation report
Coder completed implementation.
Coder Pod:
- `yoi-coder-ticket-language-guidance`
Implementation branch/worktree:
- Branch: `ticket/ticket-language-guidance-all-tools`
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Commit: `92c4dee7 ticket: guide Ticket tool language universally`
- Worktree status: clean
Changed surfaces:
- `crates/ticket/src/tool.rs`
- `crates/pod/src/feature/builtin/ticket.rs`
Implementation summary:
- Ticket tool `ToolMeta.description` now derives from configured `LocalTicketBackend::record_language()`.
- Added shared `ticket_tool_description(name, record_language)` so all Ticket tool descriptions can include configured Ticket record language guidance.
- Guidance distinguishes durable Ticket record / Ticket tool body text from normal `worker.language` prose and `memory.language` Memory/Knowledge generation.
- Guidance preserves protocol literals, file paths, commands, logs, identifiers, and quoted external text when fidelity matters.
- Feature descriptor `ToolDeclaration` descriptions use the same helper, so Ticket role launch is not the only guidance path.
- Focused tests cover configured-language presence, unset-language omission, read-only Companion-style context, and lifecycle/Ticket-role-style context.
- Companion/read-only authority was not changed.
Orchestrator-verified evidence from child worktree:
- `git status --short --branch`: clean on `ticket/ticket-language-guidance-all-tools`
- `cargo test -p ticket ticket_record_language_guidance`: pass
- `cargo test -p pod ticket_language_guidance`: pass
- `cargo test -p ticket`: pass, 68 tests
- `cargo fmt --check`: pass
- `git diff --check`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p pod` fails two prompt assertion tests:
- `prompt::catalog::tests::pod_orchestration_guidance_section_renders_resource_body`
- `prompt::system::tests::pod_orchestration_guidance_is_included_for_pod_management_tools`
- The same two focused tests fail on current Orchestrator branch before this implementation is merged, with the same missing phrase `worktree status, diff, and test results`.
- These failures are in Pod orchestration guidance prompt assertions, outside the Ticket tool language guidance change, but reviewer should confirm they are unrelated and not introduced by this Ticket.
Next:
- Spawn read-only sibling reviewer against the recorded intent, binding decisions/invariants, acceptance criteria, commit `92c4dee7`, diff, validation evidence, and known pre-existing unrelated `cargo test -p pod` failures.
---
<!-- event: plan author: orchestrator at: 2026-06-12T15:11:23Z -->
## Plan
Reviewer delegated.
- Reviewer Pod: `yoi-reviewer-ticket-language-guidance`
- Target branch/worktree: `ticket/ticket-language-guidance-all-tools` at `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Commit under review: `92c4dee7 ticket: guide Ticket tool language universally`
- Scope: read-only child worktree plus minimal non-recursive runtime-root read required by spawn validation.
- Review basis: recorded IntentPacket, binding decisions/invariants, acceptance criteria, implementation summary, diff, focused validation evidence, `nix build` evidence, and known pre-existing unrelated `cargo test -p pod` failure evidence.
- Reviewer focus: universal Ticket tool/capability guidance, Ticket role and generic/Companion-style coverage, worker/memory/ticket language separation, no hidden context-only injection, no authority expansion, and robust focused tests.
---
<!-- event: review author: reviewer:yoi-reviewer-ticket-language-guidance at: 2026-06-12T15:16:59Z status: approve -->
## Review: approve
Approve.
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Commit: `92c4dee7 ticket: guide Ticket tool language universally`
Evidence:
- 差分は `crates/ticket/src/tool.rs``crates/pod/src/feature/builtin/ticket.rs` に限定されている。
- guidance は shared `ticket_tool_description(name, record_language)` で生成され、registered Ticket tools の `ToolMeta.description` と builtin Ticket feature の `ToolDeclaration` descriptions の両方に使われている。
- guidance は Ticket tool / capability surface で model-visible であり、hidden context injection でも `ticket_role` launch prompt fragment でもない。
- `ticket.language``worker.language` / `memory.language` と区別され、protocol literals、paths、commands、logs、identifiers、quoted external text は fidelity 優先で保持する guidance が明記されている。
- read-only Companion-style access は read-only のままで、mutating tool exposure は拡大していない。
- Ticket role-style lifecycle access も同じ universal tool-description path でカバーされている。
- first-run Ticket role text は record-language guidance を launch prose に戻していない。
Reviewer-run validation:
- `cargo test -p ticket ticket_record_language_guidance`: pass
- `cargo test -p pod ticket_language_guidance`: pass
- `cargo test -p ticket`: pass, 68 tests
- `cargo test -p client ticket_record_language_stays_out_of_first_run_text`: pass
- `cargo fmt --check`: pass
- `git diff --check orchestration/yoi-orchestrator...HEAD`: pass
- `cargo run -p yoi -- ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known broad `cargo test -p pod` failures:
- Reviewer reproduced the two prompt assertion failures on HEAD, both for missing `worktree status, diff, and test results`.
- This branch has no diff under `crates/pod/src/prompt` or `resources/prompts`, and implementation diff is confined to Ticket tool/feature files.
- Together with Orchestrators base-branch verification, these failures are pre-existing/unrelated and not a blocker for this Ticket.
Non-blocking risk:
- When configured, language guidance is appended to every Ticket tool description, including read-only tools. This repeats some prompt text, but it is an intentional universal capability-surface tradeoff and satisfies the acceptance criteria.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:19:24Z -->
## Implementation report
Integration completed in the Orchestrator workspace.
Integrated implementation:
- Ticket: `00001KTVJGC0Y`
- Implementation branch: `ticket/ticket-language-guidance-all-tools`
- Implementation commit: `92c4dee7 ticket: guide Ticket tool language universally`
- Reviewer result: approve, no blockers
- Orchestrator merge commit: `ec66cad8 merge: ticket language guidance for tool users`
- Integration target: `orchestration/yoi-orchestrator`
Post-integration validation from Orchestrator worktree:
- `cargo test -p ticket ticket_record_language_guidance`: pass
- `cargo test -p pod ticket_language_guidance`: pass
- `cargo test -p client ticket_record_language_stays_out_of_first_run_text`: pass
- `cargo test -p ticket`: pass, 68 tests
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure remains:
- `cargo test -p pod` still includes pre-existing failures in Pod orchestration guidance prompt assertion tests. These were verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Remaining non-blocking risk:
- When configured, Ticket language guidance is appended to every Ticket tool description, including read-only tools. This repeats some prompt text, but it is the accepted universal capability-surface tradeoff for this Ticket.
---
<!-- event: state_changed author: orchestrator at: 2026-06-12T15:19:29Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Implementation was merged into the Orchestrator branch, reviewer approved with no blockers, and post-integration validation passed. Cleanup and closure will be recorded next.
---
<!-- event: implementation_report author: orchestrator at: 2026-06-12T15:19:54Z -->
## Implementation report
Cleanup completed.
- Stopped coder Pod: `yoi-coder-ticket-language-guidance`
- Stopped reviewer Pod: `yoi-reviewer-ticket-language-guidance`
- Removed child worktree: `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools`
- Deleted implementation branch: `ticket/ticket-language-guidance-all-tools`
- Orchestrator worktree status after cleanup: clean
Cleanup was limited to child implementation worktree/branch and related child Pods. Root/original workspace was not touched.
---
<!-- event: state_changed author: hare at: 2026-06-12T15:20:11Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-12T15:20:11Z status: closed -->
## 完了
Ticket tool users 全体に `ticket.language` guidance が届くようにした。
実装概要:
- `crates/ticket/src/tool.rs` に shared `ticket_tool_description(name, record_language)` を追加し、configured `ticket.language` がある場合は Ticket tool description に durable Ticket record / Ticket tool body language guidance を追加するようにした。
- `crates/pod/src/feature/builtin/ticket.rs` の builtin Ticket feature `ToolDeclaration` descriptions でも同じ helper を使い、read-only Companion-style context と lifecycle/Ticket-role-style context の両方に guidance が届くようにした。
- guidance は `worker.language` / `memory.language` / `ticket.language` を区別し、protocol literals、file paths、commands、logs、identifiers、quoted external text は fidelity 優先で保持することを明記した。
- guidance は Ticket tool / capability surface で model-visible であり、hidden context injection や `ticket_role` launch prompt fragment ではない。
- Companion/read-only authority や mutating tool exposure は拡大していない。
Review / integration:
- Implementation commit: `92c4dee7 ticket: guide Ticket tool language universally`
- Reviewer: `yoi-reviewer-ticket-language-guidance` が approve。
- Orchestrator merge commit: `ec66cad8 merge: ticket language guidance for tool users`
- Ticket completion commit: `2ba97b67 ticket: mark language guidance done`
Validation:
- `cargo test -p ticket ticket_record_language_guidance`: pass
- `cargo test -p pod ticket_language_guidance`: pass
- `cargo test -p client ticket_record_language_stays_out_of_first_run_text`: pass
- `cargo test -p ticket`: pass, 68 tests
- `cargo fmt --check`: pass
- `git diff --check HEAD~1..HEAD`: pass
- `./result/bin/yoi ticket doctor`: `doctor: ok`
- `nix build .#yoi`: pass
Known unrelated validation failure:
- `cargo test -p pod` still includes pre-existing failures in Pod orchestration guidance prompt assertion tests. These were verified on the Orchestrator branch before merge and reviewed as unrelated to this Ticket.
Cleanup:
- coder/reviewer Pods stopped。
- child worktree `/home/hare/Projects/yoi/.worktree/ticket-language-guidance-all-tools` removed。
- branch `ticket/ticket-language-guidance-all-tools` deleted。
Non-blocking risk:
- configured language guidance is appended to every Ticket tool description, including read-only tools. This repeats some prompt text, but it is the accepted universal capability-surface tradeoff for this Ticket.
---

1
Cargo.lock generated
View File

@ -3962,6 +3962,7 @@ dependencies = [
"crossterm 0.28.1",
"llm-worker",
"manifest",
"minijinja",
"pod-registry",
"pod-store",
"protocol",

View File

@ -125,6 +125,10 @@ impl PendingRun {
}
}
fn should_auto_run_notification(status: PodStatus, auto_run: bool) -> bool {
auto_run && status == PodStatus::Idle
}
// ---------------------------------------------------------------------------
// PodController — actor that owns a Pod
// ---------------------------------------------------------------------------
@ -774,7 +778,7 @@ async fn controller_loop<C, St>(
pending = Some(PendingRun::Run(input));
}
Method::Notify { message } => {
Method::Notify { message, auto_run } => {
// Client-side live echo is delivered as `Event::SystemItem`
// once the interceptor commits the corresponding
// `LogEntry::SystemItem` entry — drained out of the
@ -784,10 +788,10 @@ async fn controller_loop<C, St>(
// RUNNING / Paused: the buffer push is the entire
// operation; an in-flight turn (or the next
// Resume/Run) will drain it at its next
// pending_history_appends. IDLE: auto-start a turn so the LLM
// sees the buffered notification(s) without a human
// Run.
if shared_state.get_status() == PodStatus::Idle {
// pending_history_appends. IDLE: only `auto_run`
// notifications stage RunForNotification; weak progress
// notices stay queued until an explicit run/resume.
if should_auto_run_notification(shared_state.get_status(), auto_run) {
pending = Some(PendingRun::RunForNotification(protocol::InvokeKind::Notify));
}
}
@ -1145,7 +1149,7 @@ where
.into(),
});
}
Some(Method::Notify { message }) => {
Some(Method::Notify { message, .. }) => {
// Live echo arrives via `Event::SystemItem` once
// the in-flight turn's next `pending_history_appends`
// drains this entry through the interceptor.
@ -1337,6 +1341,14 @@ mod tests {
);
}
#[test]
fn notification_auto_run_gate_only_allows_idle_auto_run() {
assert!(should_auto_run_notification(PodStatus::Idle, true));
assert!(!should_auto_run_notification(PodStatus::Idle, false));
assert!(!should_auto_run_notification(PodStatus::Running, true));
assert!(!should_auto_run_notification(PodStatus::Paused, true));
}
struct DriveTurnEnv {
// Held to keep the channel alive; without this `method_rx.recv()`
// would observe channel-closed and confuse the select! arm.

View File

@ -913,7 +913,14 @@ where
}
async fn send_peer_notify(socket_path: &Path, message: String) -> io::Result<()> {
connect_and_send(socket_path, &Method::Notify { message }).await
connect_and_send(
socket_path,
&Method::Notify {
message,
auto_run: true,
},
)
.await
}
fn json_content<T: Serialize>(value: &T) -> Result<String, ToolError> {
@ -1395,7 +1402,8 @@ mod tests {
.await
.unwrap();
let method = reader.next::<Method>().await.unwrap().unwrap();
if let Method::Notify { message } = method {
if let Method::Notify { message, auto_run } = method {
assert!(auto_run);
tx.send(message).await.unwrap();
} else {
panic!("expected Notify, got {method:?}");

View File

@ -12,7 +12,7 @@ use ticket::{
tool::{
TICKET_BASE_READ_ONLY_TOOL_NAMES, TICKET_BASE_TOOL_NAMES,
TICKET_ORCHESTRATION_READ_ONLY_TOOL_NAMES, TICKET_ORCHESTRATION_TOOL_NAMES,
TICKET_READ_ONLY_TOOL_NAMES, TICKET_TOOL_NAMES, ticket_tools,
TICKET_READ_ONLY_TOOL_NAMES, TICKET_TOOL_NAMES, ticket_tool_description, ticket_tools,
},
};
@ -178,7 +178,10 @@ impl FeatureModule for TicketFeature {
));
let enabled_tool_names = self.enabled_tool_names();
for name in &enabled_tool_names {
descriptor = descriptor.with_tool(ToolDeclaration::new(*name, tool_description(name)));
descriptor = descriptor.with_tool(ToolDeclaration::new(
*name,
ticket_tool_description(name, self.record_language.as_deref()),
));
}
descriptor
}
@ -227,37 +230,6 @@ impl FeatureModule for TicketFeature {
}
}
fn tool_description(name: &str) -> &'static str {
match name {
"TicketCreate" => "Create a Ticket through the typed local Ticket backend.",
"TicketList" => {
"List Tickets as a lightweight bounded overview for id selection; use TicketShow before decisions."
}
"TicketShow" => {
"Show one Ticket through the typed local Ticket backend as the detailed authority."
}
"TicketComment" => {
"Append a comment/plan/decision/implementation_report event to a Ticket."
}
"TicketReview" => "Append an approve/request_changes review event to a Ticket.",
"TicketIntakeReady" => {
"Mark an intake Ticket ready and append the typed intake summary/state transition events."
}
"TicketWorkflowState" => {
"Transition Ticket state; queued -> inprogress is the accepted implementation start, so implementation side effects should happen only after that transition is accepted and recorded."
}
"TicketClose" => "Close a Ticket with a resolution through the typed local Ticket backend.",
"TicketOrchestrationPlanRecord" => {
"Append a durable typed Ticket orchestration plan record without changing state or starting work."
}
"TicketOrchestrationPlanQuery" => {
"Query durable Ticket orchestration plan records by Ticket and/or relation kind."
}
"TicketDoctor" => "Run typed local Ticket backend consistency checks.",
_ => "Typed Ticket backend tool.",
}
}
pub fn ticket_tools_feature(workspace: impl AsRef<Path>) -> TicketFeature {
TicketFeature::for_workspace(workspace)
}
@ -298,6 +270,19 @@ mod tests {
std::fs::write(yoi_dir.join("ticket.config.toml"), content).unwrap();
}
fn pending_tool_description(
pending_tools: &[llm_worker::tool::ToolDefinition],
name: &str,
) -> String {
pending_tools
.iter()
.find_map(|definition| {
let (meta, _) = definition();
(meta.name == name).then_some(meta.description)
})
.expect("tool exists")
}
#[test]
fn descriptor_declares_ticket_tools_and_backend_authority() {
let temp = TempDir::new().unwrap();
@ -407,6 +392,45 @@ mod tests {
}
}
#[test]
fn read_only_companion_style_context_exposes_ticket_language_guidance() {
let temp = TempDir::new().unwrap();
write_ticket_config(
temp.path(),
r#"
[ticket]
language = "Japanese"
"#,
);
make_ticket_root(&temp.path().join(DEFAULT_TICKET_BACKEND_RELATIVE_PATH));
let feature = ticket_tools_feature_with_access(temp.path(), TicketFeatureAccess::ReadOnly);
let descriptor = feature.descriptor();
let descriptor_description = descriptor
.tools
.iter()
.find(|tool| tool.name == "TicketShow")
.expect("TicketShow declared")
.description
.clone();
assert!(descriptor_description.contains("Ticket record language: Japanese"));
let mut pending_tools = Vec::new();
let mut hooks = HookRegistryBuilder::default();
let report = FeatureRegistryBuilder::new()
.with_module(feature)
.install_into_pending(&mut pending_tools, &mut hooks);
assert_eq!(pending_tools.len(), TICKET_READ_ONLY_TOOL_NAMES.len());
assert_eq!(
report.reports[0].installed_tools,
TICKET_READ_ONLY_TOOL_NAMES
);
let description = pending_tool_description(&pending_tools, "TicketShow");
assert!(description.contains("Ticket record language: Japanese"));
assert!(description.contains("distinct from worker.language"));
assert!(description.contains("Preserve protocol literals"));
}
#[test]
fn lifecycle_installation_exposes_lifecycle_tools() {
let temp = TempDir::new().unwrap();
@ -444,6 +468,35 @@ mod tests {
);
}
#[test]
fn lifecycle_ticket_role_style_context_exposes_ticket_language_guidance() {
let temp = TempDir::new().unwrap();
write_ticket_config(
temp.path(),
r#"
[ticket]
language = "Japanese"
"#,
);
make_ticket_root(&temp.path().join(DEFAULT_TICKET_BACKEND_RELATIVE_PATH));
let mut pending_tools = Vec::new();
let mut hooks = HookRegistryBuilder::default();
let report = FeatureRegistryBuilder::new()
.with_module(ticket_tools_feature_with_access(
temp.path(),
TicketFeatureAccess::Lifecycle,
))
.install_into_pending(&mut pending_tools, &mut hooks);
assert_eq!(pending_tools.len(), TICKET_TOOL_NAMES.len());
assert_eq!(report.reports[0].installed_tools, TICKET_TOOL_NAMES);
let description = pending_tool_description(&pending_tools, "TicketComment");
assert!(description.contains("Ticket record language: Japanese"));
assert!(description.contains("durable Ticket record and Ticket tool body text"));
assert!(description.contains("distinct from worker.language"));
assert!(description.contains("memory.language"));
}
#[test]
fn installs_ticket_tools_when_default_root_is_usable() {
let temp = TempDir::new().unwrap();

View File

@ -1025,6 +1025,7 @@ async fn notify_while_idle_auto_starts_turn_and_injects_system_message() {
handle
.send(Method::Notify {
message: "turn finished".into(),
auto_run: true,
})
.await
.unwrap();
@ -1105,6 +1106,62 @@ async fn notify_while_idle_auto_starts_turn_and_injects_system_message() {
);
}
#[tokio::test]
async fn notify_while_idle_with_auto_run_false_waits_for_explicit_run() {
let client = MockClient::new(simple_text_events());
let client_for_assert = client.clone();
let pod = make_pod(client).await;
let handle = spawn_controller(pod).await;
handle
.send(Method::Notify {
message: "progress snapshot".into(),
auto_run: false,
})
.await
.unwrap();
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
assert_eq!(handle.shared_state.get_status(), PodStatus::Idle);
assert!(
client_for_assert.captured_requests().is_empty(),
"weak Notify must not stage RunForNotification while idle"
);
handle.send(Method::run_text("continue")).await.unwrap();
let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(2);
loop {
if !client_for_assert.captured_requests().is_empty() {
break;
}
assert!(
tokio::time::Instant::now() < deadline,
"explicit run did not reach the mock LLM"
);
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
}
wait_for_status(&handle, PodStatus::Idle).await;
let requests = client_for_assert.captured_requests();
assert_eq!(
requests.len(),
1,
"explicit run should drain the queued notification"
);
let notify_in_request = requests[0].items.iter().any(|i| {
i.as_text()
.is_some_and(|t| t.contains("[Notification]") && t.contains("progress snapshot"))
});
assert!(
notify_in_request,
"queued weak notification must be history-backed on the next explicit run; got items: {:?}",
requests[0]
.items
.iter()
.filter_map(|i| i.as_text())
.collect::<Vec<_>>()
);
}
#[tokio::test]
async fn pod_event_turn_ended_while_idle_auto_starts_turn_and_injects_system_message() {
let client = MockClient::new(simple_text_events());
@ -1259,6 +1316,7 @@ async fn notify_while_running_does_not_emit_already_running_error() {
handle
.send(Method::Notify {
message: "ping".into(),
auto_run: true,
})
.await
.unwrap();

View File

@ -4,6 +4,14 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};
fn default_true() -> bool {
true
}
fn is_true(value: &bool) -> bool {
*value
}
// ---------------------------------------------------------------------------
// Method (Client → Pod via Unix Socket)
// ---------------------------------------------------------------------------
@ -15,10 +23,15 @@ pub enum Method {
input: Vec<Segment>,
},
/// Human-readable text injected into the target Pod's LLM context
/// as a non-blocking system message. No side effects beyond LLM
/// context; use `PodEvent` for typed lifecycle reports.
/// as a non-blocking system message. `auto_run` controls whether an
/// idle target is kicked into `RunForNotification`; weak notifications
/// (`auto_run: false`) are only queued for the next turn/resume/run.
/// No side effects beyond LLM context; use `PodEvent` for typed
/// lifecycle reports.
Notify {
message: String,
#[serde(default = "default_true", skip_serializing_if = "is_true")]
auto_run: bool,
},
/// Typed lifecycle report from a child Pod to its direct parent.
PodEvent(PodEvent),
@ -1027,17 +1040,28 @@ mod tests {
}
#[test]
fn method_notify_json_roundtrip() {
fn method_notify_json_roundtrip_defaults_to_auto_run() {
let json = r#"{"method":"notify","params":{"message":"turn done"}}"#;
let method: Method = serde_json::from_str(json).unwrap();
assert!(matches!(
method,
Method::Notify { ref message } if message == "turn done"
Method::Notify { ref message, auto_run: true } if message == "turn done"
));
let serialized = serde_json::to_string(&method).unwrap();
assert_eq!(serialized, json);
}
#[test]
fn method_notify_weak_json_roundtrip_serializes_auto_run_false() {
let json = r#"{"method":"notify","params":{"message":"progress","auto_run":false}}"#;
let method: Method = serde_json::from_str(json).unwrap();
assert!(matches!(
method,
Method::Notify { ref message, auto_run: false } if message == "progress"
));
assert_eq!(serde_json::to_string(&method).unwrap(), json);
}
#[test]
fn method_list_completions_roundtrip() {
let method = Method::ListCompletions {

View File

@ -131,6 +131,41 @@ explicit state decisions.";
const DOCTOR_DESCRIPTION: &str = "Run typed Ticket backend consistency checks and return bounded \
diagnostics through the typed backend without shelling out to external commands.";
fn base_tool_description(name: &str) -> &'static str {
match name {
"TicketCreate" => CREATE_DESCRIPTION,
"TicketList" => LIST_DESCRIPTION,
"TicketShow" => SHOW_DESCRIPTION,
"TicketComment" => COMMENT_DESCRIPTION,
"TicketReview" => REVIEW_DESCRIPTION,
"TicketIntakeReady" => INTAKE_READY_DESCRIPTION,
"TicketWorkflowState" => WORKFLOW_STATE_DESCRIPTION,
"TicketClose" => CLOSE_DESCRIPTION,
"TicketRelationRecord" => RELATION_RECORD_DESCRIPTION,
"TicketRelationQuery" => RELATION_QUERY_DESCRIPTION,
"TicketOrchestrationPlanRecord" => ORCHESTRATION_PLAN_RECORD_DESCRIPTION,
"TicketOrchestrationPlanQuery" => ORCHESTRATION_PLAN_QUERY_DESCRIPTION,
"TicketDoctor" => DOCTOR_DESCRIPTION,
_ => "Ticket backend tool.",
}
}
/// Build the model-visible Ticket tool description for a configured Ticket backend.
///
/// `record_language` is the durable Ticket record/tool-body language, distinct from
/// worker response language and Memory/Knowledge language. Keeping this on the tool
/// surface ensures every Ticket-capable Pod sees the policy without hidden context
/// injection or role-launch-only prose.
pub fn ticket_tool_description(name: &str, record_language: Option<&str>) -> String {
let mut description = base_tool_description(name).to_string();
if let Some(language) = record_language.filter(|language| !language.trim().is_empty()) {
description.push_str("\n\nTicket record language: ");
description.push_str(language.trim());
description.push_str(". Use this language for durable Ticket record and Ticket tool body text, including Ticket item bodies, thread comments/plans/decisions/implementation reports, reviews, resolutions, intake summaries, and orchestration plan notes. This policy is distinct from worker.language for normal prose and memory.language for Memory/Knowledge. Preserve protocol literals, file paths, commands, logs, identifiers, and quoted external text when translation would reduce fidelity.");
}
description
}
#[derive(Debug, Deserialize, schemars::JsonSchema)]
struct TicketCreateParams {
/// Ticket title. Must not be empty.
@ -1273,18 +1308,15 @@ fn json_output(summary: String, value: impl Serialize) -> ToolOutput {
}
}
fn tool_definition<T>(
name: &'static str,
description: &'static str,
backend: LocalTicketBackend,
) -> ToolDefinition
fn tool_definition<T>(name: &'static str, backend: LocalTicketBackend) -> ToolDefinition
where
T: Tool + From<LocalTicketBackend> + 'static,
{
let description = ticket_tool_description(name, backend.record_language());
Arc::new(move || {
let schema_value = input_schema(name);
let meta = ToolMeta::new(name)
.description(description)
.description(description.clone())
.input_schema(schema_value);
let tool: Arc<dyn Tool> = Arc::new(T::from(backend.clone()));
(meta, tool)
@ -1348,43 +1380,25 @@ impl_from_backend!(TicketDoctorTool);
/// Build all MVP Ticket tool definitions over one local backend root.
pub fn ticket_tools(backend: LocalTicketBackend) -> Vec<ToolDefinition> {
vec![
tool_definition::<TicketCreateTool>("TicketCreate", CREATE_DESCRIPTION, backend.clone()),
tool_definition::<TicketListTool>("TicketList", LIST_DESCRIPTION, backend.clone()),
tool_definition::<TicketShowTool>("TicketShow", SHOW_DESCRIPTION, backend.clone()),
tool_definition::<TicketCommentTool>("TicketComment", COMMENT_DESCRIPTION, backend.clone()),
tool_definition::<TicketReviewTool>("TicketReview", REVIEW_DESCRIPTION, backend.clone()),
tool_definition::<TicketIntakeReadyTool>(
"TicketIntakeReady",
INTAKE_READY_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketWorkflowStateTool>(
"TicketWorkflowState",
WORKFLOW_STATE_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketCloseTool>("TicketClose", CLOSE_DESCRIPTION, backend.clone()),
tool_definition::<TicketRelationRecordTool>(
"TicketRelationRecord",
RELATION_RECORD_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketRelationQueryTool>(
"TicketRelationQuery",
RELATION_QUERY_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketCreateTool>("TicketCreate", backend.clone()),
tool_definition::<TicketListTool>("TicketList", backend.clone()),
tool_definition::<TicketShowTool>("TicketShow", backend.clone()),
tool_definition::<TicketCommentTool>("TicketComment", backend.clone()),
tool_definition::<TicketReviewTool>("TicketReview", backend.clone()),
tool_definition::<TicketIntakeReadyTool>("TicketIntakeReady", backend.clone()),
tool_definition::<TicketWorkflowStateTool>("TicketWorkflowState", backend.clone()),
tool_definition::<TicketCloseTool>("TicketClose", backend.clone()),
tool_definition::<TicketRelationRecordTool>("TicketRelationRecord", backend.clone()),
tool_definition::<TicketRelationQueryTool>("TicketRelationQuery", backend.clone()),
tool_definition::<TicketOrchestrationPlanRecordTool>(
"TicketOrchestrationPlanRecord",
ORCHESTRATION_PLAN_RECORD_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketOrchestrationPlanQueryTool>(
"TicketOrchestrationPlanQuery",
ORCHESTRATION_PLAN_QUERY_DESCRIPTION,
backend.clone(),
),
tool_definition::<TicketDoctorTool>("TicketDoctor", DOCTOR_DESCRIPTION, backend),
tool_definition::<TicketDoctorTool>("TicketDoctor", backend),
]
}
@ -1412,6 +1426,16 @@ mod tests {
.expect("tool exists")
}
fn tool_description_by_name(backend: LocalTicketBackend, name: &str) -> String {
ticket_tools(backend)
.into_iter()
.find_map(|definition| {
let (meta, _) = definition();
(meta.name == name).then_some(meta.description)
})
.expect("tool exists")
}
#[test]
fn ticket_tool_name_partitions_are_explicit() {
assert_eq!(
@ -1463,6 +1487,29 @@ mod tests {
assert!(meta.description.contains("implementation side effects"));
}
#[test]
fn tool_descriptions_include_configured_ticket_record_language_guidance() {
let temp = TempDir::new().unwrap();
let backend = backend(&temp).with_record_language(Some("Japanese"));
let description = tool_description_by_name(backend, "TicketComment");
assert!(description.contains("Ticket record language: Japanese"));
assert!(description.contains("durable Ticket record and Ticket tool body text"));
assert!(description.contains("distinct from worker.language"));
assert!(description.contains("memory.language"));
assert!(description.contains("Preserve protocol literals"));
assert!(description.contains("file paths, commands, logs, identifiers"));
}
#[test]
fn tool_descriptions_omit_ticket_record_language_guidance_when_unset() {
let temp = TempDir::new().unwrap();
let description = tool_description_by_name(backend(&temp), "TicketComment");
assert!(!description.contains("Ticket record language:"));
assert!(!description.contains("worker.language"));
}
#[tokio::test]
async fn ticket_tools_create_list_show_and_doctor() {
let temp = TempDir::new().unwrap();
@ -2256,7 +2303,6 @@ mod tests {
let temp = TempDir::new().unwrap();
let create = tool(tool_definition::<TicketCreateTool>(
"TicketCreate",
CREATE_DESCRIPTION,
backend(&temp),
));
let _ = create;

View File

@ -22,6 +22,7 @@ pod-registry = { workspace = true }
provider = { workspace = true }
ticket = { workspace = true }
serde = { workspace = true, features = ["derive"] }
minijinja = "2.19.0"
pulldown-cmark = { version = "0.13.3", default-features = false }
llm-worker.workspace = true

File diff suppressed because it is too large Load Diff

View File

@ -894,7 +894,7 @@ fn pod_row(entry: &PodListEntry) -> PanelRow {
ticket: None,
related_pods: Vec::new(),
disabled_reason: entry.actions.disabled_reason.clone(),
key_hint: Some("Enter opens/attaches; Right marks action focus".to_string()),
key_hint: Some("Enter opens/attaches for inspection".to_string()),
}
}

View File

@ -40,7 +40,7 @@ rustPlatform.buildRustPackage rec {
filter = sourceFilter;
};
cargoHash = "sha256-WvMpHbTswYeRrkw5I4V4E1RnG7j13PbuQCbeas/XILs=";
cargoHash = "sha256-o47Erp9UrS2Rgwd0JNpuYPO4pZmv62DkzY9KXMQpyAM=";
depsExtraArgs = {
# Older fetchCargoVendor utilities used crates.io's API download endpoint,

View File

@ -0,0 +1,12 @@
Orchestrator progress context (read-only weak notification; no auto-run).
Reason: workspace Panel refreshed bounded orchestration progress for Companion explanation.
Roles: Companion {{ companion.pod_name }} is {{ companion.status }}; Orchestrator {{ orchestrator.pod_name }} is {{ orchestrator.status }}.
{% if tickets %}Tickets (first {{ tickets | length }} visible, bounded):
{% for ticket in tickets %}- {{ ticket.id }} [{{ ticket.state }}] {{ ticket.title }} (ref: {{ ticket.reference }})
{% endfor %}{% if omitted_ticket_count > 0 %}- … {{ omitted_ticket_count }} more ticket(s) omitted from this bounded notice.
{% endif %}{% else %}Tickets: none visible in the current Panel snapshot.
{% endif %}{% if role_pods %}
Role pod status snapshot:
{% for role_pod in role_pods %}- {{ role_pod.name }}: {{ role_pod.status }}
{% endfor %}{% endif %}

View File

@ -0,0 +1,24 @@
<system-reminder>
Workspace panel observed that this Orchestrator Pod is idle while queued Ticket work is present.
This is bounded attention only, not scheduler authority. Do not drain the queue automatically. Before implementation side effects, verify the Ticket state and record the normal `queued -> inprogress` acceptance through Ticket tools.
Workspace: {{ workspace }}
Actionable queued Tickets:
{% for ticket in actionable_tickets -%}
- {{ ticket.id }} — {{ ticket.title }} [{{ ticket.classification }}]
{% endfor -%}
{% if waiting_tickets | length > 0 -%}
Queued Tickets retained in the session work set but currently waiting:
{% for ticket in waiting_tickets -%}
- {{ ticket.id }} — {{ ticket.title }} [{{ ticket.classification }}]: {{ ticket.waiting_reason }}
{% endfor -%}
{% endif -%}
{% if omitted_ticket_count > 0 -%}
Additional queued Tickets omitted from this bounded notice: {{ omitted_ticket_count }}
{% endif -%}
Preserve the existing human gate, dependency/conflict/capacity/dirty-workspace checks, and duplicate-start checks using actual Ticket state, role/session claims, visible Pods, and worktrees.
</system-reminder>