diff --git a/.yoi/tickets/00001KT0Z4BK8/item.md b/.yoi/tickets/00001KT0Z4BK8/item.md index 62382e18..3007b195 100644 --- a/.yoi/tickets/00001KT0Z4BK8/item.md +++ b/.yoi/tickets/00001KT0Z4BK8/item.md @@ -2,7 +2,7 @@ title: 'Plugin distribution package format and discovery' state: 'planning' created_at: '2026-06-01T06:49:53Z' -updated_at: '2026-06-13T15:29:21Z' +updated_at: '2026-06-14T14:34:33Z' --- ## Background @@ -13,8 +13,8 @@ MCP is intentionally not modeled as a Plugin package/runtime in this Ticket. MCP The desired initial direction is a single-file plugin package that can be placed in user or workspace plugin stores, for example: -- `~/.config/yoi/plugins/.yoi-plugin` -- `./.yoi/plugins/.yoi-plugin` +- `${XDG_DATA_HOME:-~/.local/share}/yoi/plugins/.yoi-plugin` +- `/.yoi/plugins/.yoi-plugin` The package should be easy to copy, inspect, cache, and pin while preserving Yoi's scope, permission, history, prompt-context, and trust invariants. Workspace plugins may come from a repository checkout and must not execute merely because an archive exists under `./.yoi/plugins`. @@ -26,10 +26,11 @@ The package should be easy to copy, inspect, cache, and pin while preserving Yoi - Support packaged assets such as `module.wasm`, JSON schemas, README, and license files. - Specify archive safety rules, including path traversal rejection, bounded extraction, and deterministic digest calculation. - Define plugin stores and source/trust mapping. - - User plugin store: `~/.config/yoi/plugins/`. - - Workspace/project plugin store: `./.yoi/plugins/`. - - Map stores to the existing source vocabulary (`User`, `Project`/workspace, and future `Builtin`). - - Treat `user:` and `project:` as distinct plugin references; ambiguous unqualified IDs should fail closed. + - User plugin store: `${XDG_DATA_HOME:-~/.local/share}/yoi/plugins/`. + - Workspace/project plugin store: `/.yoi/plugins/`. + - Builtin plugin source: Yoi-distributed `builtin:` registry. + - Map stores to the source vocabulary (`user`, `project`, `builtin`). + - Treat `user:` and `project:` as distinct plugin references; ambiguous unqualified IDs fail closed. - Separate discovery from enablement. - Yoi may discover plugin packages in configured stores. - Discovered packages must not register Tools/Hooks, initialize WASM, start services, or start MCP servers until explicitly enabled by manifest/profile configuration. @@ -80,7 +81,7 @@ The package should be easy to copy, inspect, cache, and pin while preserving Yoi ## Acceptance criteria - The repository has a documented plugin distribution/package proposal covering user and workspace plugin stores, single-file archive format, manifest fields, archive safety, cache/digest behavior, and discovery vs enablement. -- The proposal explicitly states that placing a package in `~/.config/yoi/plugins/` or `./.yoi/plugins/` is discovery only, not execution or registration. +- The proposal explicitly states that placing a package in `${XDG_DATA_HOME:-~/.local/share}/yoi/plugins/` or `/.yoi/plugins/` is discovery only, not execution or registration. - The design maps package sources to user/project/builtin trust categories and defines how ID collisions and ambiguous selectors are handled. - The design explains Plugin permission requests/grants as Plugin-layer policy, distinct from `pod::feature` authority/grant concepts. - Runtime-specific notes cover declarative hooks and WASM packages; MCP is called out as a separate feature-backed integration, not part of initial Plugin packaging. diff --git a/.yoi/tickets/00001KT0Z4BK8/thread.md b/.yoi/tickets/00001KT0Z4BK8/thread.md index 81d3942e..b779a36f 100644 --- a/.yoi/tickets/00001KT0Z4BK8/thread.md +++ b/.yoi/tickets/00001KT0Z4BK8/thread.md @@ -37,4 +37,17 @@ Distribution direction from user discussion: - `00001KSXRQ4G8` と `00001KT0Z4BK8` は Plugin permission を Plugin layer として扱い、MCP を初期 Plugin packaging/runtime から分離する。 +--- + + + +## Decision + +決定: +- Plugin discovery stores, source-qualified identity, discovery/enablement separation, Pod-startup initialization timing, restore behavior, and MCP boundaryをこの `00001KT0Z4BK8` の安定 contract として統合した。 +- User Plugin package store は `${XDG_DATA_HOME:-~/.local/share}/yoi/plugins/` とし、`~/.config/yoi/plugins/` は使わない。 +- Package presence は discovery only であり、実行・登録・runtime initialization は explicit enablement 後の Pod startup に限定する。 +- Restore は metadata snapshot の enabled Plugin plan を正本とし、fresh discovery で silent upgrade しない。 + + --- diff --git a/.yoi/tickets/00001KTFY8V80/item.md b/.yoi/tickets/00001KTFY8V80/item.md index d5555e1b..3f1d8dd4 100644 --- a/.yoi/tickets/00001KTFY8V80/item.md +++ b/.yoi/tickets/00001KTFY8V80/item.md @@ -1,8 +1,8 @@ --- title: "Preserve active workflows across compaction" -state: "planning" +state: 'ready' created_at: "2026-06-07T02:23:28Z" -updated_at: "2026-06-07T02:23:28Z" +updated_at: '2026-06-14T14:13:43Z' --- ## Background diff --git a/.yoi/tickets/00001KTFY8V80/thread.md b/.yoi/tickets/00001KTFY8V80/thread.md index c398d7a0..36b2c160 100644 --- a/.yoi/tickets/00001KTFY8V80/thread.md +++ b/.yoi/tickets/00001KTFY8V80/thread.md @@ -5,3 +5,61 @@ Created by LocalTicketBackend create. --- + + + +## Comment + +## Intake refinement + +既存 Ticket `00001KTFY8V80` を確認した。新規 duplicate Ticket は作成しない。 + +### Readiness + +- readiness: implementation_ready +- risk_flags: [prompt-context, persistence, workflow-state, compaction] + +この Ticket は、active workflow を compaction / rehydration 後も継続可能にする concrete work item として十分に bounded されている。実装戦術の調査余地は残るが、Orchestrator が implementation routing できる要件・受け入れ条件・検証観点は揃っている。 + +### Binding decisions / invariants + +- active workflow の進行中状態を、history に残らない transient context 注入だけで復元してはならない。 +- compaction / restore 後に「どの workflow が継続中か」「どの手順段階・義務が残っているか」をモデルが説明可能でなければならない。 +- workflow state の復元は、prompt context 加工原則に反しない形で durable source から再構成する。 +- missing / corrupt / obsolete workflow state は fail-closed または bounded diagnostic として扱い、silently stale instructions を実行しない。 +- Ticket / Pod history / workflow record / compaction output の authority boundary を混同しない。 + +### Implementation latitude + +- workflow state の永続化先・schema・snapshot 粒度は、既存 Pod/session/compaction architecture に合わせて選んでよい。 +- active workflow body を invocation-time snapshot として保持するか、rehydration 時に最新 resource を参照するかは、実装時に明示的に決定し、互換性・安全性の理由をコードまたは docs / Ticket 報告に残す。 +- UI/diagnostic 表示の具体的な文言や internal field 名は、既存設計に沿って調整してよい。 + +### Escalation conditions + +- workflow snapshot vs latest body の選択が authority boundary または backward compatibility を大きく変える場合。 +- compaction が workflow obligations を再現するために hidden context injection を必要としそうな場合。 +- persisted workflow state の migration / compatibility 方針が既存 records を破壊する場合。 +- implementation が Ticket lifecycle / Orchestrator queue semantics / workflow invocation semantics を広げる必要を見つけた場合。 + +### Related context checked + +- closed `00001KTG3AZQ8` / `00001KTG3BX0R` は Orchestrator routing / merge completion の完了済み関連文脈であり、本 Ticket の duplicate ではない。 + +--- + + + +## Intake summary + +既存 Ticket `00001KTFY8V80` を精査し、duplicate は作成しない方針で refinement を記録した。対象は active Workflow invocation/state/obligations を durable state/history と compaction/rehydration 経路に載せ、compaction 後も `/multi-agent-workflow` / `/worktree-workflow` などの active obligations を traceable に継続できるようにする実装 work item。readiness は implementation_ready。risk flags は prompt-context / persistence / workflow-state / compaction。Orchestrator は implementation routing 可能だが、snapshot vs latest workflow body の選択、hidden context injection 回避、missing/corrupt persisted state の fail-closed diagnostic、Ticket/Pod/history/workflow authority boundary を reviewer focus に含める。 + +--- + + + +## State changed + +Intake refinement が完了し、要件・受け入れ条件・binding invariants・escalation conditions が Ticket thread に記録されたため `planning -> ready` にします。実装 side effects は Orchestrator routing 後に行います。 + +--- diff --git a/.yoi/tickets/00001KTR81P9X/item.md b/.yoi/tickets/00001KTR81P9X/item.md index 0918b4d5..52c3e4df 100644 --- a/.yoi/tickets/00001KTR81P9X/item.md +++ b/.yoi/tickets/00001KTR81P9X/item.md @@ -1,8 +1,8 @@ --- title: 'Extend pod::feature API for external protocol-backed capability providers' -state: 'done' +state: 'closed' created_at: '2026-06-10T07:48:14Z' -updated_at: '2026-06-14T06:39:48Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['feature-api', 'tool-registry', 'permission-scope', 'prompt-context', 'dynamic-registry', 'service-lifecycle'] diff --git a/.yoi/tickets/00001KTR81P9X/resolution.md b/.yoi/tickets/00001KTR81P9X/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KTR81P9X/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KTR81P9X/thread.md b/.yoi/tickets/00001KTR81P9X/thread.md index 86d7b323..16f8fa70 100644 --- a/.yoi/tickets/00001KTR81P9X/thread.md +++ b/.yoi/tickets/00001KTR81P9X/thread.md @@ -178,4 +178,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `3d140dbb`, and validated in the Orchestrator worktree. Feature-provider focused tests, formatting, diff check, and workspace check passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KTZY8HK2/item.md b/.yoi/tickets/00001KTZY8HK2/item.md index eec9a6dd..894c0c04 100644 --- a/.yoi/tickets/00001KTZY8HK2/item.md +++ b/.yoi/tickets/00001KTZY8HK2/item.md @@ -1,8 +1,8 @@ --- title: 'Profile extend API を廃止して import + Lua 代入に寄せる' -state: 'done' +state: 'closed' created_at: '2026-06-13T07:31:09Z' -updated_at: '2026-06-14T06:34:34Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['profiles', 'lua-api', 'builtin-resources', 'migration'] diff --git a/.yoi/tickets/00001KTZY8HK2/resolution.md b/.yoi/tickets/00001KTZY8HK2/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KTZY8HK2/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KTZY8HK2/thread.md b/.yoi/tickets/00001KTZY8HK2/thread.md index 22d92fc3..39fc6de1 100644 --- a/.yoi/tickets/00001KTZY8HK2/thread.md +++ b/.yoi/tickets/00001KTZY8HK2/thread.md @@ -179,4 +179,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `58b15ee6`, and validated in the Orchestrator worktree. Focused manifest profile tests, formatting, diff check, `cargo build -p yoi`, and `nix build .#yoi` passed after cleanup freed disk space. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV09WYC6/item.md b/.yoi/tickets/00001KV09WYC6/item.md index b6d6a22a..66abf4ae 100644 --- a/.yoi/tickets/00001KV09WYC6/item.md +++ b/.yoi/tickets/00001KV09WYC6/item.md @@ -1,8 +1,8 @@ --- title: 'Workspace panel: show Ticket-associated Intake Pods adjacent to Ticket rows' -state: 'planning' +state: 'ready' created_at: '2026-06-13T10:54:31Z' -updated_at: '2026-06-13T10:54:31Z' +updated_at: '2026-06-14T14:12:11Z' assignee: null readiness: 'implementation_ready' risk_flags: ['panel-ux', 'local-role-session-registry', 'pod-session-state'] diff --git a/.yoi/tickets/00001KV09WYC6/thread.md b/.yoi/tickets/00001KV09WYC6/thread.md index 517a8f55..187376a4 100644 --- a/.yoi/tickets/00001KV09WYC6/thread.md +++ b/.yoi/tickets/00001KV09WYC6/thread.md @@ -5,3 +5,19 @@ LocalTicketBackend によって作成されました。 --- + + + +## Intake summary + +既存 Ticket 00001KV09WYC6 の body/thread/artifacts を確認した。要件、受け入れ条件、binding decisions / invariants、implementation latitude、escalation conditions、validation が揃っており、readiness は `implementation_ready` と判断できる。未解決の blocking open question はない。risk_flags は `panel-ux`, `local-role-session-registry`, `pod-session-state`。次は Orchestrator が routing し、実装時は Panel の selection/keyboard semantics、one-active-claim-per-Ticket invariant、pre-Ticket Intake の誤関連付け回避、registry schema migration 不要の維持を重点確認する。 + +--- + + + +## State changed + +Intake 確認により、既存 Ticket の要件は実装 routing 可能な状態と判断した。実装 side effect は Orchestrator の queue/routing flow に委ねる。 + +--- diff --git a/.yoi/tickets/00001KV09X0XC/item.md b/.yoi/tickets/00001KV09X0XC/item.md index 84763a35..a122fe00 100644 --- a/.yoi/tickets/00001KV09X0XC/item.md +++ b/.yoi/tickets/00001KV09X0XC/item.md @@ -1,8 +1,8 @@ --- title: 'Panel から ready Ticket を指示付きで planning に戻して Intake を再開できるようにする' -state: 'done' +state: 'closed' created_at: '2026-06-13T10:54:34Z' -updated_at: '2026-06-14T05:09:07Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['panel-action', 'ticket-lifecycle', 'role-session', 'authority-boundary'] diff --git a/.yoi/tickets/00001KV09X0XC/resolution.md b/.yoi/tickets/00001KV09X0XC/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV09X0XC/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV09X0XC/thread.md b/.yoi/tickets/00001KV09X0XC/thread.md index 664cf42a..19fd49a2 100644 --- a/.yoi/tickets/00001KV09X0XC/thread.md +++ b/.yoi/tickets/00001KV09X0XC/thread.md @@ -182,4 +182,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `7a6321d9`, and validated in the Orchestrator worktree. Focused TUI planning-return/intake/workspace-panel tests, Ticket tests, formatting, and diff check passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV0SP0TY/item.md b/.yoi/tickets/00001KV0SP0TY/item.md index 707cb26a..ff6d02a8 100644 --- a/.yoi/tickets/00001KV0SP0TY/item.md +++ b/.yoi/tickets/00001KV0SP0TY/item.md @@ -1,8 +1,8 @@ --- title: 'Remove feature-layer HostAuthority model' -state: 'done' +state: 'closed' created_at: '2026-06-13T15:30:22Z' -updated_at: '2026-06-13T19:02:01Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['feature-api', 'tool-registry', 'ticket-tools'] diff --git a/.yoi/tickets/00001KV0SP0TY/resolution.md b/.yoi/tickets/00001KV0SP0TY/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV0SP0TY/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV0SP0TY/thread.md b/.yoi/tickets/00001KV0SP0TY/thread.md index dd7c2bb5..3feba621 100644 --- a/.yoi/tickets/00001KV0SP0TY/thread.md +++ b/.yoi/tickets/00001KV0SP0TY/thread.md @@ -205,4 +205,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `297e95ef`, and validated in the Orchestrator worktree. Focused pod/ticket tests, formatting, diff check, and `cargo check --workspace --all-targets` passed after cleanup freed disk space. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV0X254D/item.md b/.yoi/tickets/00001KV0X254D/item.md index 76e0c226..02cb2219 100644 --- a/.yoi/tickets/00001KV0X254D/item.md +++ b/.yoi/tickets/00001KV0X254D/item.md @@ -1,8 +1,8 @@ --- title: 'Panel Orchestrator の orchestration branch 名を ticket.config.toml で設定可能にする' -state: 'done' +state: 'closed' created_at: '2026-06-13T16:29:25Z' -updated_at: '2026-06-14T05:05:57Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['config-schema', 'git-worktree', 'panel-orchestration'] diff --git a/.yoi/tickets/00001KV0X254D/resolution.md b/.yoi/tickets/00001KV0X254D/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV0X254D/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV0X254D/thread.md b/.yoi/tickets/00001KV0X254D/thread.md index d0e5b1b8..6ba85b56 100644 --- a/.yoi/tickets/00001KV0X254D/thread.md +++ b/.yoi/tickets/00001KV0X254D/thread.md @@ -189,4 +189,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `290c4230`, and validated in the Orchestrator worktree. Focused ticket config / TUI orchestration worktree / configured branch / queue action tests, formatting, diff check, `cargo build -p yoi`, and `yoi ticket doctor` passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV0YK5S0/item.md b/.yoi/tickets/00001KV0YK5S0/item.md index ac642456..3306f6da 100644 --- a/.yoi/tickets/00001KV0YK5S0/item.md +++ b/.yoi/tickets/00001KV0YK5S0/item.md @@ -1,8 +1,8 @@ --- title: 'E2E harness を完全な tmp runtime/data/workspace 隔離と cleanup に対応させる' -state: 'done' +state: 'closed' created_at: '2026-06-13T16:56:11Z' -updated_at: '2026-06-13T17:33:53Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'ready' queued_by: 'yoi ticket' diff --git a/.yoi/tickets/00001KV0YK5S0/resolution.md b/.yoi/tickets/00001KV0YK5S0/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV0YK5S0/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV0YK5S0/thread.md b/.yoi/tickets/00001KV0YK5S0/thread.md index e2e712eb..71a77753 100644 --- a/.yoi/tickets/00001KV0YK5S0/thread.md +++ b/.yoi/tickets/00001KV0YK5S0/thread.md @@ -192,4 +192,22 @@ Next: E2E tmp/runtime isolation follow-up was reviewed, merged into the Orchestrator branch as `20184eeb`, and validated in the Orchestrator worktree. Panel E2E now uses clean per-scenario tmp workspace/data/runtime fixtures, preserves artifacts under `target/e2e-artifacts`, removes fixture temp roots after runs, and does not inherit host runtime/credential environment. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV10SN02/item.md b/.yoi/tickets/00001KV10SN02/item.md index 64e743e0..bb05f0f5 100644 --- a/.yoi/tickets/00001KV10SN02/item.md +++ b/.yoi/tickets/00001KV10SN02/item.md @@ -1,8 +1,8 @@ --- title: 'E2E: close remaining critical-path gaps after panel harness' -state: 'done' +state: 'closed' created_at: '2026-06-13T17:34:41Z' -updated_at: '2026-06-14T05:39:03Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['e2e', 'tui', 'pty', 'quit-latency', 'mouse-input', 'rewind'] diff --git a/.yoi/tickets/00001KV10SN02/resolution.md b/.yoi/tickets/00001KV10SN02/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV10SN02/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV10SN02/thread.md b/.yoi/tickets/00001KV10SN02/thread.md index 5248dfe3..2c306416 100644 --- a/.yoi/tickets/00001KV10SN02/thread.md +++ b/.yoi/tickets/00001KV10SN02/thread.md @@ -298,4 +298,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `059b1fd4`, and validated in the Orchestrator worktree. Focused E2E, TUI rewind/mouse tests, formatting, diff check, `cargo build -p yoi`, and `nix build .#yoi` passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV11DHGZ/item.md b/.yoi/tickets/00001KV11DHGZ/item.md index 1e24d315..fc0ec931 100644 --- a/.yoi/tickets/00001KV11DHGZ/item.md +++ b/.yoi/tickets/00001KV11DHGZ/item.md @@ -1,8 +1,8 @@ --- title: 'Profile から concrete scope を外して launch policy で付与する' -state: 'done' +state: 'closed' created_at: '2026-06-13T17:45:32Z' -updated_at: '2026-06-14T07:04:22Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['scope', 'delegation-scope', 'profiles', 'launch-policy', 'orchestrator', 'spawnpod', 'restore'] diff --git a/.yoi/tickets/00001KV11DHGZ/resolution.md b/.yoi/tickets/00001KV11DHGZ/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV11DHGZ/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV11DHGZ/thread.md b/.yoi/tickets/00001KV11DHGZ/thread.md index ed9b3db6..77cc869c 100644 --- a/.yoi/tickets/00001KV11DHGZ/thread.md +++ b/.yoi/tickets/00001KV11DHGZ/thread.md @@ -210,4 +210,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `3a67b95b`, and validated in the Orchestrator worktree. Focused manifest/client/pod launch-policy/scope/restore tests, build, formatting, diff check, and `nix build .#yoi` passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/.yoi/tickets/00001KV12W2RT/item.md b/.yoi/tickets/00001KV12W2RT/item.md index 4fbfd3e5..d83ea315 100644 --- a/.yoi/tickets/00001KV12W2RT/item.md +++ b/.yoi/tickets/00001KV12W2RT/item.md @@ -1,8 +1,8 @@ --- title: 'Panel Ticket rows を2行表示にして gate 情報を分離する' -state: 'done' +state: 'closed' created_at: '2026-06-13T18:10:57Z' -updated_at: '2026-06-14T06:42:04Z' +updated_at: '2026-06-14T14:00:13Z' assignee: null readiness: 'implementation_ready' risk_flags: ['tui', 'workspace-panel', 'ticket-relations', 'mouse-input', 'layout'] diff --git a/.yoi/tickets/00001KV12W2RT/resolution.md b/.yoi/tickets/00001KV12W2RT/resolution.md new file mode 100644 index 00000000..7099abb2 --- /dev/null +++ b/.yoi/tickets/00001KV12W2RT/resolution.md @@ -0,0 +1 @@ +Closed after prior done-state completion. diff --git a/.yoi/tickets/00001KV12W2RT/thread.md b/.yoi/tickets/00001KV12W2RT/thread.md index faaacf84..0a27e85b 100644 --- a/.yoi/tickets/00001KV12W2RT/thread.md +++ b/.yoi/tickets/00001KV12W2RT/thread.md @@ -147,4 +147,22 @@ Next: Implementation branch was reviewed, approved, merged into the Orchestrator branch as `a9ece1dc`, and validated in the Orchestrator worktree. Focused TUI row/mouse/gate tests, Panel E2E tests, build, formatting, and diff check passed. Ticket implementation work is done; closure remains separate. +--- + + + +## State changed + +Ticket を closed にしました。 + + +--- + + + +## 完了 + +Closed after prior done-state completion. + + --- diff --git a/crates/ticket/src/config.rs b/crates/ticket/src/config.rs index ad0ef355..ee636cca 100644 --- a/crates/ticket/src/config.rs +++ b/crates/ticket/src/config.rs @@ -8,7 +8,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::fmt; use std::fs; -use std::path::{Path, PathBuf}; +use std::path::{Component, Path, PathBuf}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -16,6 +16,9 @@ use thiserror::Error; pub const TICKET_CONFIG_RELATIVE_PATH: &str = ".yoi/ticket.config.toml"; /// Workspace-relative default root for the built-in local Ticket backend. pub const DEFAULT_TICKET_BACKEND_RELATIVE_PATH: &str = ".yoi/tickets"; +const DEFAULT_ORCHESTRATION_BRANCH: &str = "orchestration"; +const DEFAULT_ORCHESTRATION_WORKTREE_DIR: &str = ".worktree"; +const DEFAULT_ORCHESTRATION_WORKTREE_NAME: &str = "orchestration"; /// Return the explicit workspace Ticket config scaffold written by `yoi ticket init`. /// @@ -36,7 +39,7 @@ pub fn ticket_config_scaffold() -> String { "\n# Optional durable Ticket record language. When unset, generated Ticket text keeps current defaults.\n# [ticket]\n# language = \"Japanese\"\n", ); out.push_str( - "\n# Optional Panel Orchestrator worktree branch. When unset, Panel uses orchestration/.\n# [orchestration]\n# branch = \"orchestration/\"\n", + "\n# Optional Panel Orchestrator worktree settings. When unset, Panel uses branch `orchestration` at `.worktree/orchestration`.\n# [orchestration]\n# branch = \"orchestration\"\n# worktree_dir = \".worktree\"\n# worktree_name = \"orchestration\"\n", ); for role in TicketRole::ALL { out.push_str(&format!( @@ -77,12 +80,30 @@ pub struct TicketConfig { #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct TicketOrchestrationConfig { pub branch: Option, + pub worktree_dir: Option, + pub worktree_name: Option, } impl TicketOrchestrationConfig { pub fn branch_name(&self) -> Option<&str> { self.branch.as_ref().map(GitBranchName::as_str) } + + pub fn effective_branch_name(&self) -> &str { + self.branch_name().unwrap_or(DEFAULT_ORCHESTRATION_BRANCH) + } + + pub fn worktree_dir(&self) -> &Path { + self.worktree_dir + .as_deref() + .unwrap_or_else(|| Path::new(DEFAULT_ORCHESTRATION_WORKTREE_DIR)) + } + + pub fn worktree_name(&self) -> &Path { + self.worktree_name + .as_deref() + .unwrap_or_else(|| Path::new(DEFAULT_ORCHESTRATION_WORKTREE_NAME)) + } } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] @@ -167,6 +188,27 @@ fn validate_git_branch_name_value(value: &str) -> Result<(), String> { Ok(()) } +fn validate_orchestration_relative_path(path: &Path, label: &str) -> Result<(), String> { + if path.as_os_str().is_empty() { + return Err(format!("{label} must not be empty")); + } + if path.is_absolute() { + return Err(format!("{label} must be workspace-relative")); + } + for component in path.components() { + match component { + Component::Normal(_) => {} + Component::CurDir | Component::ParentDir => { + return Err(format!("{label} must not contain `.` or `..` components")); + } + Component::RootDir | Component::Prefix(_) => { + return Err(format!("{label} must be workspace-relative")); + } + } + } + Ok(()) +} + impl TicketConfig { pub fn default_for_workspace(workspace_root: impl AsRef) -> Self { let workspace_root = workspace_root.as_ref(); @@ -636,13 +678,25 @@ struct RawTicketConfig { struct RawTicketOrchestrationConfig { #[serde(default)] branch: Option, + #[serde(default)] + worktree_dir: Option, + #[serde(default)] + worktree_name: Option, } impl RawTicketOrchestrationConfig { - fn resolve(self) -> TicketOrchestrationConfig { - TicketOrchestrationConfig { - branch: self.branch, + fn resolve(self) -> Result { + if let Some(path) = &self.worktree_dir { + validate_orchestration_relative_path(path, "orchestration.worktree_dir")?; } + if let Some(path) = &self.worktree_name { + validate_orchestration_relative_path(path, "orchestration.worktree_name")?; + } + Ok(TicketOrchestrationConfig { + branch: self.branch, + worktree_dir: self.worktree_dir, + worktree_name: self.worktree_name, + }) } } @@ -691,7 +745,12 @@ impl RawTicketConfig { } })?, ticket: self.ticket.resolve(), - orchestration: self.orchestration.resolve(), + orchestration: self.orchestration.resolve().map_err(|message| { + TicketConfigError::Invalid { + path: path.to_path_buf(), + message, + } + })?, roles, }) } @@ -797,6 +856,15 @@ mod tests { ); assert_eq!(config.ticket_record_language(), None); assert_eq!(config.orchestration.branch_name(), None); + assert_eq!( + config.orchestration.effective_branch_name(), + "orchestration" + ); + assert_eq!(config.orchestration.worktree_dir(), Path::new(".worktree")); + assert_eq!( + config.orchestration.worktree_name(), + Path::new("orchestration") + ); for role in TicketRole::ALL { let role_config = config.role(role); assert_eq!(role_config.profile.as_str(), "inherit"); @@ -820,6 +888,8 @@ language = "Japanese" [orchestration] branch = "orchestration/custom-panel" +worktree_dir = "custom-worktrees" +worktree_name = "custom-orchestrator" [roles.intake] profile = "project:intake" @@ -854,6 +924,18 @@ workflow = "multi-agent-workflow" config.orchestration.branch_name(), Some("orchestration/custom-panel") ); + assert_eq!( + config.orchestration.effective_branch_name(), + "orchestration/custom-panel" + ); + assert_eq!( + config.orchestration.worktree_dir(), + Path::new("custom-worktrees") + ); + assert_eq!( + config.orchestration.worktree_name(), + Path::new("custom-orchestrator") + ); assert_eq!( config.profile_for(TicketRole::Intake).as_str(), "project:intake" @@ -881,7 +963,7 @@ workflow = "multi-agent-workflow" assert!(scaffold.contains("root = \".yoi/tickets\"")); assert!(scaffold.contains("# [ticket]\n# language = \"Japanese\"")); assert!(scaffold.contains( - "# [orchestration]\n# branch = \"orchestration/\"" + "# [orchestration]\n# branch = \"orchestration\"\n# worktree_dir = \".worktree\"\n# worktree_name = \"orchestration\"" )); for role in TicketRole::ALL { assert!(scaffold.contains(&format!("[roles.{role}]"))); @@ -901,6 +983,15 @@ workflow = "multi-agent-workflow" .unwrap(); assert_eq!(config.backend_root(), temp.path().join(".yoi/tickets")); assert_eq!(config.orchestration.branch_name(), None); + assert_eq!( + config.orchestration.effective_branch_name(), + "orchestration" + ); + assert_eq!(config.orchestration.worktree_dir(), Path::new(".worktree")); + assert_eq!( + config.orchestration.worktree_name(), + Path::new("orchestration") + ); for role in TicketRole::ALL { let role_config = config.role_launch_config(role).unwrap(); assert_eq!(role_config.profile.as_str(), role.default_profile()); diff --git a/crates/tui/src/multi_pod.rs b/crates/tui/src/multi_pod.rs index 295e5e0a..f4e6b44c 100644 --- a/crates/tui/src/multi_pod.rs +++ b/crates/tui/src/multi_pod.rs @@ -27,7 +27,7 @@ use ratatui::text::{Line, Span}; use ratatui::widgets::{Block, Borders, Clear, Paragraph, Widget, Wrap}; use serde::Serialize; use session_store::FsStore; -use ticket::config::{GitBranchName, TicketConfig}; +use ticket::config::{GitBranchName, TicketConfig, TicketOrchestrationConfig}; use ticket::{ LocalTicketBackend, MarkdownText, TicketBackend, TicketIdOrSlug, TicketStateChange, TicketWorkflowState, @@ -2517,40 +2517,37 @@ struct OrchestrationWorktreeReady { status: OrchestrationWorktreeStatus, } -fn orchestration_worktree_layout_for_branch( +fn orchestration_worktree_layout_for_config( workspace_root: &Path, - branch: String, + orchestration: &TicketOrchestrationConfig, ) -> OrchestrationWorktreeLayout { - let stem = workspace_orchestrator_pod_name(workspace_root); OrchestrationWorktreeLayout { path: workspace_root - .join(".worktree") - .join("orchestration") - .join(&stem), - branch, + .join(orchestration.worktree_dir()) + .join(orchestration.worktree_name()), + branch: orchestration.effective_branch_name().to_string(), } } +#[cfg(test)] fn orchestration_worktree_layout(workspace_root: &Path) -> OrchestrationWorktreeLayout { - let stem = workspace_orchestrator_pod_name(workspace_root); - orchestration_worktree_layout_for_branch(workspace_root, format!("orchestration/{stem}")) + OrchestrationWorktreeLayout { + path: workspace_root.join(".worktree").join("orchestration"), + branch: "orchestration".to_string(), + } } fn resolved_orchestration_worktree_layout( workspace_root: &Path, ) -> Result { let config = TicketConfig::load_workspace(workspace_root) - .map_err(|err| format!("failed to load ticket config for orchestration branch: {err}"))?; - let branch = if let Some(branch) = config.orchestration.branch_name() { - branch.to_string() - } else { - orchestration_worktree_layout(workspace_root).branch - }; - GitBranchName::new(branch.clone()) + .map_err(|err| format!("failed to load ticket config for orchestration worktree: {err}"))?; + let branch = config.orchestration.effective_branch_name(); + GitBranchName::new(branch.to_string()) .map_err(|message| format!("invalid orchestration branch `{branch}`: {message}"))?; - Ok(orchestration_worktree_layout_for_branch( + Ok(orchestration_worktree_layout_for_config( workspace_root, - branch, + &config.orchestration, )) } @@ -5757,9 +5754,9 @@ mod tests { let layout = orchestration_worktree_layout(root); assert_eq!( layout.path, - PathBuf::from("/tmp/Yoi Workspace/.worktree/orchestration/yoi-workspace-orchestrator") + PathBuf::from("/tmp/Yoi Workspace/.worktree/orchestration") ); - assert_eq!(layout.branch, "orchestration/yoi-workspace-orchestrator"); + assert_eq!(layout.branch, "orchestration"); } #[test] @@ -5834,7 +5831,7 @@ mod tests { } #[test] - fn ensure_and_restore_use_configured_orchestration_branch() { + fn ensure_and_restore_use_configured_orchestration_layout() { let temp = TempDir::new().unwrap(); let root = temp.path().join("repo"); init_test_repo(&root); @@ -5843,6 +5840,8 @@ mod tests { r#" [orchestration] branch = "orchestration/custom-panel" +worktree_dir = "custom-worktrees" +worktree_name = "panel" "#, ); run_test_git(&root, &["add", ".yoi/ticket.config.toml"]).unwrap(); @@ -5850,11 +5849,7 @@ branch = "orchestration/custom-panel" let resolved = resolved_orchestration_worktree_layout(&root).unwrap(); assert_eq!(resolved.branch, "orchestration/custom-panel"); - assert!( - resolved - .path - .ends_with(".worktree/orchestration/repo-orchestrator") - ); + assert!(resolved.path.ends_with("custom-worktrees/panel")); let created = ensure_orchestration_worktree(&root).unwrap(); assert_eq!(created.status, OrchestrationWorktreeStatus::Created); @@ -5934,12 +5929,7 @@ branch = "orchestration/custom-panel" assert_eq!(restored.status, OrchestrationWorktreeStatus::Reused); assert_eq!(restored.layout.path, created.layout.path); assert_ne!(restored.layout.path, root); - assert!( - restored - .layout - .path - .ends_with(".worktree/orchestration/repo-orchestrator") - ); + assert!(restored.layout.path.ends_with(".worktree/orchestration")); } #[test]