320 Commits
Author SHA1 Message Date
Hare 159704dc6f fix: clear encrypted-only thinking snapshots 2026-06-25 20:28:51 +09:00
Hare 6492f10f42 test: update pod prompt expectations 2026-06-25 18:43:57 +09:00
Hare a525ba4d01 merge: plugin runtime implementation chain 2026-06-25 18:18:14 +09:00
Hare c261aea021 ticket: mark plugin pdk service events done 2026-06-25 16:57:31 +09:00
Hare 8d4fee231b merge: 00001KVXK0WEA plugin pdk service events 2026-06-25 16:55:35 +09:00
Hare 307d38453f ticket: approve plugin pdk service events 2026-06-25 16:55:35 +09:00
Hare d2a8a79ac6 ticket: record plugin pdk template fix 2026-06-25 16:53:19 +09:00
Hare 6c8998878d fix: declare plugin service websocket authority 2026-06-25 16:52:20 +09:00
Hare 41283c8dd9 ticket: request plugin pdk template fix 2026-06-25 16:44:57 +09:00
Hare fa29cc2c95 ticket: record plugin pdk implementation report 2026-06-25 16:38:53 +09:00
Hare 7a4fd97526 feat: update plugin service authoring templates 2026-06-25 16:37:37 +09:00
Hare 103077dfae ticket: record plugin pdk coder start 2026-06-25 16:09:47 +09:00
Hare cd2006305e ticket: accept plugin pdk service events task 2026-06-25 16:08:53 +09:00
Hare a453c6e2da ticket: route plugin pdk service events task 2026-06-25 16:08:34 +09:00
Hare 16247ce7c5 ticket: mark plugin websocket driver done 2026-06-25 16:06:42 +09:00
Hare b9e786e106 merge: 00001KVXK0WE4 plugin websocket driver 2026-06-25 16:03:57 +09:00
Hare ccd4d83d43 ticket: approve plugin websocket driver 2026-06-25 16:03:57 +09:00
Hare 3a9ac1b1b7 ticket: record plugin websocket implementation report 2026-06-25 15:56:44 +09:00
Hare f2c51ffe39 feat: add plugin websocket service driver 2026-06-25 15:54:36 +09:00
Hare ef17955369 ticket: record plugin websocket coder start 2026-06-25 15:24:27 +09:00
Hare 62e467c035 ticket: accept plugin websocket driver task 2026-06-25 15:23:25 +09:00
Hare 4950749c5d ticket: route plugin websocket driver task 2026-06-25 15:22:55 +09:00
Hare dc2f8b409d ticket: mark plugin output commands done 2026-06-25 15:20:33 +09:00
Hare d2aa92a729 merge: 00001KVXK0WDX plugin output commands 2026-06-25 15:18:43 +09:00
Hare 86017a5abc ticket: approve plugin output commands 2026-06-25 15:18:43 +09:00
Hare 799998639a ticket: record plugin output implementation report 2026-06-25 15:13:08 +09:00
Hare 755d460f0d feat: add plugin service output commands 2026-06-25 15:11:30 +09:00
Hare 07f9793bc6 ticket: record plugin output coder start 2026-06-25 14:47:52 +09:00
Hare 89a40db79e ticket: accept plugin output command task 2026-06-25 14:46:54 +09:00
Hare 84a8423611 ticket: route plugin output command task 2026-06-25 14:46:20 +09:00
Hare 8e79c1dc96 ticket: mark plugin service lifecycle done 2026-06-25 06:51:18 +09:00
Hare 000afbbe19 merge: 00001KVXK0WDQ plugin service lifecycle 2026-06-25 06:49:43 +09:00
Hare db1a2f567b ticket: approve plugin service lifecycle 2026-06-25 06:49:43 +09:00
Hare bdd05dce4d ticket: record plugin service implementation report 2026-06-25 06:44:06 +09:00
Hare 4e138b7e36 feat: add plugin service ingress queue 2026-06-25 06:42:56 +09:00
Hare 1839acb3d0 ticket: record plugin service coder start 2026-06-25 06:24:15 +09:00
Hare f26c7e0d09 ticket: accept plugin service lifecycle task 2026-06-25 06:23:22 +09:00
Hare 437ef5b56b ticket: route plugin service lifecycle task 2026-06-25 06:23:06 +09:00
Hare 7d64b443f2 ticket: mark plugin manifest rejection done 2026-06-25 06:20:51 +09:00
Hare 449745ee24 merge: 00001KVXK0WDH plugin manifest rejection 2026-06-25 06:19:01 +09:00
Hare e66efc746f ticket: approve plugin manifest rejection 2026-06-25 06:19:01 +09:00
Hare 436bcc812d ticket: record plugin manifest rejection report 2026-06-25 06:12:05 +09:00
Hare 6086099fe4 feat: reject legacy plugin runtime manifests 2026-06-25 06:11:03 +09:00
Hare 390f468471 ticket: record plugin manifest coder start 2026-06-25 05:54:51 +09:00
Hare ef1d8d9af2 ticket: accept plugin manifest rejection task 2026-06-25 05:53:53 +09:00
Hare ceb7b95096 ticket: route plugin manifest rejection 2026-06-25 05:53:14 +09:00
Hare 237c985f2c ticket: correct legacy wasm merge record 2026-06-25 05:51:08 +09:00
Hare 66c5be16f8 ticket: mark legacy wasm removal done 2026-06-25 05:50:51 +09:00
Hare bedbb670e4 merge: 00001KVXK0WD3 legacy wasm removal 2026-06-25 05:49:01 +09:00
Hare 0591fd528c ticket: approve legacy wasm removal 2026-06-25 05:49:01 +09:00
Hare 19ff3724ed ticket: record legacy wasm removal report 2026-06-25 05:43:58 +09:00
Hare 741d71327a refactor: remove legacy wasm plugin runtime 2026-06-25 05:42:52 +09:00
Hare 27117f3246 ticket: record legacy wasm coder start 2026-06-25 05:15:02 +09:00
Hare 1b5a39dbc9 ticket: accept legacy wasm removal task 2026-06-25 05:14:13 +09:00
Hare f65f0e3b8f ticket: route plugin runtime cleanup chain 2026-06-25 05:13:59 +09:00
Hare e2df9f9493 ticket: queue 00001KVXK0WEA 2026-06-25 05:12:05 +09:00
Hare 959b497135 ticket: queue 00001KVXK0WE4 2026-06-25 05:12:03 +09:00
Hare ef08b873ce ticket: queue 00001KVXK0WDX 2026-06-25 05:12:02 +09:00
Hare 2f975808bb ticket: queue 00001KVXK0WDQ 2026-06-25 05:12:00 +09:00
Hare 273f10e954 ticket: queue 00001KVXK0WDH 2026-06-25 05:11:58 +09:00
Hare f349738257 ticket: queue 00001KVXK0WD3 2026-06-25 05:11:56 +09:00
Hare 577bf75051 ticket: split plugin runtime redesign 2026-06-25 04:56:03 +09:00
Hare 79df31ccf6 ticket: return plugin runtime redesign to planning 2026-06-25 04:40:59 +09:00
Hare 72812878c0 ticket: queue 00001KVXHVCR5 2026-06-25 04:39:36 +09:00
Hare cea115ecd9 merge: sync orchestration before queue 00001KVXHVCR5 2026-06-25 04:39:36 +09:00
Hare 4c3b15d8d6 ticket: plan plugin wasm runtime redesign 2026-06-25 04:39:33 +09:00
Hare 45d21ac032 ticket: mark backend orchestrator design done 2026-06-25 04:15:48 +09:00
Hare 4e713fce19 merge: 00001KVWSQM22 backend orchestrator design 2026-06-25 04:15:14 +09:00
Hare 428b7d0fef ticket: approve backend orchestrator design 2026-06-25 04:15:14 +09:00
Hare 5ddc8dceac ticket: record backend orchestrator design report 2026-06-25 04:12:38 +09:00
Hare f901b9bee3 docs: design backend internal orchestrator runtime 2026-06-25 04:11:47 +09:00
Hare 2f9604a12f ticket: record backend orchestrator coder start 2026-06-25 04:08:16 +09:00
Hare 893122781d ticket: accept backend orchestrator runtime plan 2026-06-25 04:07:16 +09:00
Hare f367d73231 ticket: queue 00001KVWSQM22 2026-06-25 04:04:55 +09:00
Hare 5fa480904d merge: sync orchestration before queue 00001KVWSQM22 2026-06-25 04:04:55 +09:00
Hare 0618de21eb ticket: plan backend internal orchestrator 2026-06-25 03:49:58 +09:00
Hare d5012d3e16 ticket: mark cleanup cli done 2026-06-24 21:36:19 +09:00
Hare 28d53aadf2 nix: update yoi cleanup cargo hash 2026-06-24 21:35:28 +09:00
Hare 4fb75ec324 merge: 00001KVWPVHFJ storage cleanup cli
# Conflicts:
#	.yoi/tickets/00001KVWPVHFJ/item.md
#	.yoi/tickets/00001KVWPVHFJ/thread.md
2026-06-24 21:30:57 +09:00
Hare 091ee764a4 ticket: approve cleanup cli implementation 2026-06-24 21:30:49 +09:00
Hare 439f967cb8 chore: record cleanup cli implementation report 2026-06-24 21:22:58 +09:00
Hare 80d6861aba feat: add pod and session cleanup CLI 2026-06-24 21:22:19 +09:00
Hare d2ec533585 ticket: mark thinking grouping done 2026-06-24 21:20:15 +09:00
Hare b52b7c963c merge: 00001KVWPW3KX thinking grouping
# Conflicts:
#	.yoi/tickets/00001KVWPW3KX/item.md
#	.yoi/tickets/00001KVWPW3KX/thread.md
2026-06-24 21:19:16 +09:00
Hare 89910a1a29 ticket: approve thinking grouping implementation 2026-06-24 21:18:56 +09:00
Hare 7ee2b78bbb ticket: report thinking grouping implementation 2026-06-24 21:14:43 +09:00
Hare 0b2ce6ca1f tui: group consecutive thinking blocks 2026-06-24 21:14:06 +09:00
Hare bca8ba6ed9 ticket: record ui and cleanup coder starts 2026-06-24 21:05:18 +09:00
Hare 5c9331e848 ticket: accept queued ui and cleanup tasks 2026-06-24 21:04:13 +09:00
Hare bb6bc9f6a1 ticket: queue 00001KVWPVHFJ 2026-06-24 21:01:42 +09:00
Hare 845817d3bf ticket: queue 00001KVWPW3KX 2026-06-24 21:01:41 +09:00
Hare 1d98921a45 merge: sync orchestration before queue 00001KVWPW3KX 2026-06-24 21:01:41 +09:00
Hare 7ede927d5a ticket: add pod cleanup and thinking aggregation plans 2026-06-24 20:57:23 +09:00
Hare 6081448a7e fix: trace codex requests and clear reasoning snapshots 2026-06-24 20:37:42 +09:00
Hare 70162d5001 ticket: mark worker registry done 2026-06-24 20:15:18 +09:00
Hare b975812c18 nix: update yoi cargo hash 2026-06-24 20:14:41 +09:00
Hare 1251c0ca70 merge: 00001KVWECEQG worker runtime registry 2026-06-24 20:11:00 +09:00
Hare dd40c41f45 ticket: approve worker registry implementation 2026-06-24 20:11:00 +09:00
Hare 428d255b27 ticket: record worker registry fixes 2026-06-24 20:09:08 +09:00
Hare 38d25582b2 fix: make worker runtime ids resolvable 2026-06-24 20:08:23 +09:00
Hare cdc0a5da33 ticket: request worker registry changes 2026-06-24 20:01:52 +09:00
Hare c96cc49d0a ticket: record worker registry implementation report 2026-06-24 19:57:10 +09:00
Hare 9bd1550715 feat: add worker runtime registry overview 2026-06-24 19:56:08 +09:00
Hare 81fa035a1c ticket: record worker registry orchestration start 2026-06-24 19:38:55 +09:00
Hare 371fd7c6e5 ticket: accept worker runtime registry task 2026-06-24 19:37:58 +09:00
Hare d231f41300 ticket: mark worker runtime spawn done 2026-06-24 19:35:06 +09:00
Hare 97555bb5a1 merge: 00001KVTNAY20 worker runtime spawn 2026-06-24 19:33:35 +09:00
Hare d62ab6e1de docs: record worker runtime implementation report 2026-06-24 19:26:14 +09:00
Hare 217a4828d7 feat: abstract worker runtime spawn boundary 2026-06-24 19:24:18 +09:00
Hare bc2b8513f7 ticket: defer worker runtime registry routing 2026-06-24 18:24:57 +09:00
Hare 73122c10fd ticket: queue 00001KVWECEQG 2026-06-24 18:22:55 +09:00
Hare b84db7fac7 merge: orchestration branch 2026-06-24 18:21:37 +09:00
Hare 911df3df77 ticket: mark worker runtime registry ready 2026-06-24 18:21:37 +09:00
Hare acf1f5fb53 ticket: plan worker runtime registry 2026-06-24 18:12:39 +09:00
Hare 1044b39c3f ticket: plan ticket management api ui 2026-06-24 04:42:37 +09:00
Hare a729d68600 ticket: record coder startup blocker 2026-06-24 04:33:52 +09:00
Hare b83886554f ticket: record worker runtime orchestration start 2026-06-24 04:32:02 +09:00
Hare 5a8bcebdf4 ticket: accept worker runtime spawn task 2026-06-24 04:27:45 +09:00
Hare a479d3e32d ticket: queue 00001KVTNAY20 2026-06-24 04:25:09 +09:00
Hare f399d7383c ticket: mark worker spawn abstraction ready 2026-06-24 04:25:09 +09:00
Hare e8e019eb76 fix: keep initialized ticket directory 2026-06-24 03:26:22 +09:00
Hare 3c2fd5d760 ticket: separate pod launch from orchestration 2026-06-24 03:15:07 +09:00
Hare 1ca5663298 fix: harden StopPod registry cleanup 2026-06-24 00:23:10 +09:00
Hare b28d64c3c6 ticket: close 00001KVSMJJNV 2026-06-23 22:56:21 +09:00
Hare 76c800542c merge: 00001KVSMJJNV paused ctrl-x cancel 2026-06-23 22:54:38 +09:00
Hare cca073f8aa ticket: approve 00001KVSMJJNV implementation 2026-06-23 22:53:20 +09:00
Hare c0f4c184ca ticket: report 00001KVSMJJNV review fix 2026-06-23 22:49:40 +09:00
Hare 8c8fb01426 fix: log paused cancel lifecycle explicitly 2026-06-23 22:48:21 +09:00
Hare 052408392d ticket: update 00001KVSMJJNV review metadata 2026-06-23 22:43:05 +09:00
Hare cfb215ab0c ticket: review 00001KVSMJJNV changes 2026-06-23 22:42:52 +09:00
Hare 3501e0dffe ticket: update 00001KVSMJJNV metadata 2026-06-23 22:38:06 +09:00
Hare af683af2d2 ticket: report 00001KVSMJJNV implementation 2026-06-23 22:38:01 +09:00
Hare 90b1a1fccb tui: cancel paused turns with ctrl-x 2026-06-23 22:37:40 +09:00
Hare 5954021cc5 ticket: accept 00001KVSMJJNV 2026-06-23 22:21:56 +09:00
Hare 108088d811 ticket: queue 00001KVSMJJNV 2026-06-23 17:41:00 +09:00
Hare ca2ad18ded merge: sync orchestration before queue 00001KVSMJJNV 2026-06-23 17:41:00 +09:00
Hare d2e6a2a1a7 ui: simplify workspace sidebar identity 2026-06-23 16:56:00 +09:00
Hare e275a80f4c ticket: close workspace identity 2026-06-23 16:39:16 +09:00
Hare 2745f3d516 merge: workspace identity persistence 2026-06-23 16:35:17 +09:00
Hare 8f7b87a29e ticket: record workspace identity approval 2026-06-23 16:35:13 +09:00
Hare 2a7b659be4 ticket: restart workspace identity review 2026-06-23 16:31:38 +09:00
Hare 3dd680683c ticket: record workspace identity fix 2026-06-23 16:30:50 +09:00
Hare 49c9e19074 fix: return persisted workspace identity 2026-06-23 16:29:48 +09:00
Hare ddd2f86e26 ticket: reroute workspace identity fixes 2026-06-23 16:25:39 +09:00
Hare fac79dc962 ticket: request workspace identity changes 2026-06-23 16:25:03 +09:00
Hare 71a39002fb ticket: close dashboard selection 2026-06-23 16:24:24 +09:00
Hare 58904c441a merge: dashboard no auto selection 2026-06-23 16:23:16 +09:00
Hare 1e812b793b ticket: record dashboard selection review 2026-06-23 16:23:11 +09:00
Hare ff8aa6bcbf ticket: start dashboard selection review 2026-06-23 16:16:42 +09:00
Hare 2b213a8add ticket: record dashboard selection implementation 2026-06-23 16:15:59 +09:00
Hare 021aca8d5e ticket: start workspace identity review 2026-06-23 16:14:48 +09:00
Hare 21b14ba440 ticket: record workspace identity implementation 2026-06-23 16:13:56 +09:00
Hare 5c242d9620 fix: keep dashboard row selection explicit 2026-06-23 16:13:37 +09:00
Hare 31565c9b9e feat: persist workspace identity 2026-06-23 16:12:39 +09:00
Hare 99f31e0055 ticket: start workspace identity and selection work 2026-06-23 15:51:53 +09:00
Hare 4cda83b748 ticket: accept workspace identity and selection work 2026-06-23 15:50:36 +09:00
Hare 13e76d3544 ticket: queue 00001KVSKGDYS 2026-06-23 15:47:18 +09:00
Hare 85b6d9f027 ticket: queue 00001KVSKJ0EA 2026-06-23 15:47:17 +09:00
Hare 8daf9eacb7 merge: sync orchestration before queue 00001KVSKJ0EA 2026-06-23 15:47:17 +09:00
Hare 48672e4317 fix: canonicalize workspace server root 2026-06-23 15:47:11 +09:00
Hare eb998f0ad4 ticket: add workspace identity initialization 2026-06-23 15:44:29 +09:00
Hare 9cbb5b9b71 ticket: record dashboard hint cleanup cleanup 2026-06-23 15:33:30 +09:00
Hare 108666664a ticket: complete dashboard hint cleanup 2026-06-23 15:32:57 +09:00
Hare 5abf16f9e6 merge: dashboard hint cleanup 2026-06-23 15:31:31 +09:00
Hare 78c98a34d1 ticket: approve dashboard hint cleanup 2026-06-23 15:31:31 +09:00
Hare 68f1ddbd5a ticket: start dashboard hint cleanup review 2026-06-23 15:29:26 +09:00
Hare 71284cdc92 ticket: record dashboard hint cleanup implementation 2026-06-23 15:28:24 +09:00
Hare 03ad525fcc tui: trim dashboard redundant hints 2026-06-23 15:27:04 +09:00
Hare af9e940873 ticket: record protocol ts cleanup 2026-06-23 15:22:07 +09:00
Hare b547203fde ticket: complete protocol ts generation 2026-06-23 15:21:30 +09:00
Hare 9728b533b4 merge: protocol typescript generation 2026-06-23 15:17:09 +09:00
Hare 9c4d1559fd ticket: approve protocol ts generation 2026-06-23 15:17:09 +09:00
Hare e0ec8ce78a ticket: record kanban lazy rows cleanup 2026-06-23 15:16:19 +09:00
Hare 9de04f7266 ticket: complete kanban lazy rows 2026-06-23 15:15:33 +09:00
Hare eea26f9174 merge: kanban lazy rows 2026-06-23 15:13:43 +09:00
Hare 0b1e9fdc5b ticket: approve kanban lazy rows 2026-06-23 15:13:43 +09:00
Hare 277af3dec3 ticket: start dashboard hint cleanup 2026-06-23 15:13:01 +09:00
Hare 3bfd1ca07d ticket: accept dashboard hint cleanup 2026-06-23 15:11:48 +09:00
Hare 0e635ba6b4 ticket: start protocol ts review 2026-06-23 15:10:38 +09:00
Hare 017ac70876 ticket: record protocol ts generation 2026-06-23 15:09:50 +09:00
Hare 5428837605 ticket: queue 00001KVSFXY88 2026-06-23 15:08:42 +09:00
Hare 87482df956 merge: sync orchestration before queue 00001KVSFXY88 2026-06-23 15:08:42 +09:00
Hare a13fb6933b protocol: generate workspace TypeScript types 2026-06-23 15:08:22 +09:00
Hare d775e09688 ticket: update workspace web tickets 2026-06-23 15:07:46 +09:00
Hare f1ab40bf01 ticket: start kanban lazy rows review 2026-06-23 15:06:57 +09:00
Hare c92bc447cc ticket: record kanban lazy rows implementation 2026-06-23 15:06:11 +09:00
Hare 6f68bb8d95 web: group repository ticket kanban rows 2026-06-23 15:04:03 +09:00
Hare f39127b752 ticket: start kanban lazy rows 2026-06-23 14:55:34 +09:00
Hare a6f9019edd ticket: accept kanban lazy rows 2026-06-23 14:54:43 +09:00
Hare 2865abb65a ticket: queue 00001KVSGFM65 2026-06-23 14:53:22 +09:00
Hare f6eb11e567 merge: sync orchestration before queue 00001KVSGFM65 2026-06-23 14:53:22 +09:00
Hare ee750363d2 ticket: add workspace kanban improvement 2026-06-23 14:51:34 +09:00
Hare d8f467e30f ticket: start protocol ts generation 2026-06-23 14:42:24 +09:00
Hare 746c51c701 ticket: accept protocol ts generation 2026-06-23 14:41:34 +09:00
Hare f9ca777afe ticket: queue 00001KVSEBF56 2026-06-23 14:40:01 +09:00
Hare 4189b80004 ticket: add protocol type generation work 2026-06-23 14:14:17 +09:00
Hare 6013048f68 merge: orchestration 2026-06-22 20:15:48 +09:00
Hare 1d626cdea6 ui: refine workspace web layout 2026-06-22 20:03:54 +09:00
Hare 615c02501a ticket: record workspace schema cleanup 2026-06-22 18:27:16 +09:00
Hare 7a7891d467 ticket: complete workspace db schema v0 2026-06-22 18:26:32 +09:00
Hare 38bd122dd0 merge: workspace db schema v0 2026-06-22 18:24:14 +09:00
Hare 9c0c7badcf ticket: approve workspace db schema v0 2026-06-22 18:24:14 +09:00
Hare c3798559d2 ticket: record workspace schema migration fix 2026-06-22 18:18:37 +09:00
Hare d89ace5b9c workspace: canonicalize legacy workspaces 2026-06-22 18:17:21 +09:00
Hare 1994d2d668 ticket: request changes on workspace schema migration 2026-06-22 18:13:17 +09:00
Hare 1c3ec71361 ticket: start workspace db schema review 2026-06-22 18:03:59 +09:00
Hare e7333f2e4d ticket: record workspace db schema implementation 2026-06-22 18:03:09 +09:00
Hare 5149ab703f workspace: implement db schema v0 bootstrap 2026-06-22 18:01:38 +09:00
Hare 1e0f2158ba ticket: start workspace db schema v0 2026-06-22 17:51:17 +09:00
Hare f17a458a04 ticket: accept workspace db schema v0 2026-06-22 17:50:22 +09:00
Hare 5f06af81cb ticket: queue 00001KVNKD56W 2026-06-22 17:48:39 +09:00
Hare 8407ce22b4 merge: sync orchestration before queue 00001KVNKD56W 2026-06-22 17:48:39 +09:00
Hare c6ddff159f docs: design workspace db schema v0 2026-06-22 17:48:37 +09:00
Hare b7c890d3f6 ticket: record repository objective cleanup 2026-06-22 02:31:56 +09:00
Hare 4b1f1e593d ticket: complete repository objective pages 2026-06-22 02:31:21 +09:00
Hare 7ee702b162 merge: repository objective pages 2026-06-22 02:30:17 +09:00
Hare 680b2a4160 ticket: approve repository objective pages 2026-06-22 02:30:17 +09:00
Hare 076c504640 ticket: start repository objective review 2026-06-22 02:24:06 +09:00
Hare 2c76675110 ticket: record repository objective implementation 2026-06-22 02:23:23 +09:00
Hare ceb1ee3b56 feat: add repository objective pages 2026-06-22 02:21:51 +09:00
Hare de43209643 ticket: start repository objective pages 2026-06-22 02:03:46 +09:00
Hare 0f7e78c164 ticket: accept repository objective pages 2026-06-22 02:03:04 +09:00
Hare eb2e5907ea ticket: record workspace sidebar cleanup 2026-06-22 02:01:56 +09:00
Hare c29eba0c70 ticket: complete workspace sidebar 2026-06-22 02:01:22 +09:00
Hare 613f412659 merge: workspace sidebar navigation 2026-06-22 02:00:22 +09:00
Hare 5d55e47e9b ticket: approve workspace sidebar 2026-06-22 02:00:22 +09:00
Hare 8066f71b51 ticket: start sidebar review 2026-06-22 01:54:57 +09:00
Hare 5ad588f059 ticket: record sidebar conflict resolution 2026-06-22 01:54:16 +09:00
Hare 4ab696b434 Merge branch 'orchestration' into impl/00001KVNG9B9Z-workspace-sidebar
# Conflicts:
#	web/workspace/src/routes/+page.svelte
2026-06-22 01:52:53 +09:00
Hare d3b8bdfddc feat: add workspace sidebar skeleton 2026-06-22 01:45:46 +09:00
Hare a607a1f20d ticket: defer repository pages behind sidebar 2026-06-22 01:41:16 +09:00
Hare 520209f38c ticket: queue 00001KVNGJPRG 2026-06-22 01:40:36 +09:00
Hare ae2d80ba5a merge: sync orchestration before queue 00001KVNGJPRG 2026-06-22 01:40:35 +09:00
Hare 8652041855 ticket: add repository objective pages 2026-06-22 01:40:33 +09:00
Hare 04f15623f2 ticket: record workspace host worker cleanup 2026-06-22 01:39:51 +09:00
Hare a4ed5fb082 ticket: complete workspace host workers 2026-06-22 01:39:21 +09:00
Hare c884d51702 merge: workspace host workers 2026-06-22 01:38:12 +09:00
Hare ea47e54399 ticket: approve workspace host workers 2026-06-22 01:38:12 +09:00
Hare d953049d7d ticket: start workspace sidebar work 2026-06-22 01:37:40 +09:00
Hare 2c7ef24a29 ticket: accept workspace sidebar ui 2026-06-22 01:36:58 +09:00
Hare 48c09fd709 ticket: queue 00001KVNG9B9Z 2026-06-22 01:35:06 +09:00
Hare 6ebe4f7752 merge: sync orchestration before queue 00001KVNG9B9Z 2026-06-22 01:35:06 +09:00
Hare d4de8e26ce ticket: start workspace host worker review 2026-06-22 01:32:27 +09:00
Hare 42c9e9144c ticket: record workspace host worker implementation 2026-06-22 01:31:54 +09:00
Hare 06a9f2f5fd ticket: add workspace sidebar UI 2026-06-22 01:30:58 +09:00
Hare 58143ead83 feat: expose workspace hosts and workers 2026-06-22 01:30:48 +09:00
Hare b193e3e088 ticket: start workspace host workers 2026-06-22 01:11:53 +09:00
Hare e1f02ffca3 ticket: accept workspace host workers 2026-06-22 01:10:56 +09:00
Hare bd5f2b75c3 ticket: queue 00001KVNEKH9Q 2026-06-22 01:09:10 +09:00
Hare 2bad74046e merge: integrate orchestration branch 2026-06-22 01:06:48 +09:00
Hare dfbfd6ed82 dev: add workspace web hot reload setup 2026-06-22 01:06:37 +09:00
Hare de1a20c007 ticket: add local host worker API 2026-06-22 01:01:43 +09:00
Hare 7abc3c7751 ticket: record plugin websocket cleanup 2026-06-21 22:27:34 +09:00
Hare e8103477a4 ticket: complete plugin websocket host api 2026-06-21 22:26:32 +09:00
Hare 354f1e1081 merge: plugin websocket host api 2026-06-21 22:21:07 +09:00
Hare 8a5b341e5e ticket: approve plugin websocket api 2026-06-21 22:20:58 +09:00
Hare 2232149be0 ticket: record plugin websocket bounds fix 2026-06-21 22:16:11 +09:00
Hare a766048f29 fix: bound plugin websocket open 2026-06-21 22:14:58 +09:00
Hare 168951b668 fix: declare deno workspace frontend deps 2026-06-21 22:08:37 +09:00
Hare 519730e7d3 ticket: request changes on websocket bounds 2026-06-21 21:43:11 +09:00
Hare 27f6b3366c ticket: start plugin websocket review 2026-06-21 21:33:07 +09:00
Hare 07782704d4 ticket: record plugin websocket branch hygiene 2026-06-21 21:32:27 +09:00
Hare e58355e7e3 ticket: record plugin websocket implementation 2026-06-21 21:21:02 +09:00
Hare ce62d23502 chore: keep plugin websocket branch code-only 2026-06-21 21:20:55 +09:00
Hare 4c1b8c3d0a feat: add plugin websocket host api 2026-06-21 21:19:28 +09:00
Hare 8578bc1c29 ticket: record inflight snapshot cleanup 2026-06-21 21:00:38 +09:00
Hare 77b5276fd3 ticket: complete inflight snapshot fix 2026-06-21 21:00:10 +09:00
Hare b21638f56c merge: inflight reconnect snapshot 2026-06-21 20:56:55 +09:00
Hare 08edc767b5 ticket: approve inflight snapshot fix 2026-06-21 20:56:49 +09:00
Hare 4cd4ae9cb5 ticket: record inflight snapshot race fix 2026-06-21 20:53:05 +09:00
Hare 061136d798 fix: close in-flight snapshot commit race 2026-06-21 20:51:48 +09:00
Hare ecdc52fce9 ticket: request changes on inflight snapshot 2026-06-21 20:37:40 +09:00
Hare 406c057025 ticket: start plugin websocket implementation 2026-06-21 20:37:08 +09:00
Hare 3eac7f8eae ticket: accept plugin websocket host api 2026-06-21 20:36:06 +09:00
Hare 79a0e45dbc ticket: queue 00001KVMGAEJN 2026-06-21 20:34:07 +09:00
Hare 2e2fdae8ef merge: sync orchestration before queue 00001KVMGAEJN 2026-06-21 20:34:07 +09:00
Hare d802778104 ticket: start inflight snapshot review 2026-06-21 20:32:03 +09:00
Hare de5f3ba49e ticket: record inflight snapshot implementation 2026-06-21 20:31:18 +09:00
Hare 74aca6f6c5 fix: snapshot in-flight stream state 2026-06-21 20:30:01 +09:00
Hare 2a23b8d770 ticket: record deno tooling cleanup 2026-06-21 20:14:32 +09:00
Hare 54d325aeb4 ticket: complete deno tooling migration 2026-06-21 20:14:07 +09:00
Hare 6dc78e3f2a merge: workspace spa deno tooling 2026-06-21 20:13:04 +09:00
Hare 108b6dc787 ticket: approve deno tooling migration 2026-06-21 20:12:57 +09:00
Hare 395de19639 ticket: start deno tooling review 2026-06-21 20:06:08 +09:00
Hare cc25201c4f ticket: record deno tooling implementation 2026-06-21 20:05:32 +09:00
Hare 66f04e0424 feat: migrate workspace spa tooling to deno 2026-06-21 20:04:08 +09:00
Hare 5f9797fdd6 ticket: ready websocket host api 2026-06-21 20:01:28 +09:00
Hare b4d2b3a442 ticket: start deno and inflight snapshot work 2026-06-21 20:00:13 +09:00
Hare 155e039e66 ticket: route deno and inflight snapshot work 2026-06-21 19:58:49 +09:00
Hare b4786b407a ticket: queue 00001KVMT2J25 2026-06-21 19:56:32 +09:00
Hare a59d935bd3 ticket: queue 00001KVMV03QY 2026-06-21 19:56:31 +09:00
Hare 6e95e497f7 ticket: add workspace follow-up items 2026-06-21 19:56:10 +09:00
Hare ef12c6b185 ticket: close workspace server launcher 2026-06-21 19:56:04 +09:00
Hare e6f68496b4 feat: add workspace server launcher 2026-06-21 19:55:55 +09:00
Hare be517417ff ticket: start workspace server launcher 2026-06-21 19:55:46 +09:00
Hare 3fc0dd0bde merge: integrate orchestration branch 2026-06-21 18:01:45 +09:00
Hare 89eb59505b ticket: record plugin request cleanup 2026-06-21 17:12:42 +09:00
Hare 2601bfa9f0 ticket: complete plugin request host api 2026-06-21 17:12:13 +09:00
Hare 8a15cca567 merge: plugin request host api 2026-06-21 17:08:13 +09:00
Hare ece35c391c ticket: approve plugin request api 2026-06-21 17:08:09 +09:00
Hare 6c3ac08c54 ticket: record plugin request grant fix 2026-06-21 17:04:55 +09:00
Hare 0e14e7c14e plugin: align request grant inspection coverage 2026-06-21 17:04:03 +09:00
Hare 2704b8c4bd ticket: request changes on plugin request grants 2026-06-21 16:58:12 +09:00
Hare d5338f9244 ticket: start plugin request review 2026-06-21 16:48:59 +09:00
Hare e447f177e0 ticket: record plugin request implementation 2026-06-21 16:48:13 +09:00
Hare 962b769989 plugin: replace https host api with request grants 2026-06-21 16:47:06 +09:00
Hare 52a786c780 ticket: record workspace web cleanup 2026-06-21 16:46:59 +09:00
Hare f33415c7e2 ticket: complete workspace web bootstrap 2026-06-21 16:46:25 +09:00
Hare 3e03e53627 merge: workspace web control plane 2026-06-21 16:44:59 +09:00
Hare 794e43a534 ticket: approve workspace web bootstrap 2026-06-21 16:44:54 +09:00
Hare 9f721ba437 ticket: start workspace web review 2026-06-21 16:38:19 +09:00
Hare 4a5e28067e ticket: record workspace web implementation 2026-06-21 16:37:39 +09:00
Hare ab7658c1f2 feat: bootstrap workspace web control plane 2026-06-21 16:34:36 +09:00
Hare 6cc0065d15 ticket: start plugin request implementation 2026-06-21 16:19:01 +09:00
Hare 4cd4a06e98 ticket: route plugin request capabilities 2026-06-21 16:17:57 +09:00
Hare f164483e62 ticket: queue 00001KVMGAEJN 2026-06-21 16:15:42 +09:00
Hare faf9bb0a82 ticket: queue 00001KVMG8FTW 2026-06-21 16:15:41 +09:00
Hare df150647c4 merge: sync orchestration before queue 00001KVMG8FTW 2026-06-21 16:15:41 +09:00
Hare 9f664c751a ticket: start workspace web implementation 2026-06-21 16:15:08 +09:00
Hare 1d27f6c90a ticket: accept workspace web control plane 2026-06-21 16:13:54 +09:00
241 changed files with 30305 additions and 2678 deletions
+1
View File
@@ -1,2 +1,3 @@
/memory/
tickets/.ticket-backend.lock
/workspace.db*
+34 -15
View File
@@ -2,8 +2,8 @@
title: "Plugin platform roadmap"
state: "active"
created_at: "2026-06-19T13:18:58Z"
updated_at: "2026-06-19T13:18:58Z"
linked_tickets: ["00001KV5R5V2S", "00001KV5W3PHA", "00001KV5W3PHW", "00001KV5W3PJ3", "00001KVFD3YSV", "00001KVFDX9AF", "00001KVFDX9AY", "00001KVG0HR96"]
updated_at: "2026-06-24T19:55:00Z"
linked_tickets: ["00001KV5R5V2S", "00001KV5W3PHA", "00001KV5W3PHW", "00001KV5W3PJ3", "00001KVFD3YSV", "00001KVFDX9AF", "00001KVFDX9AY", "00001KVG0HR96", "00001KVXHVCR5", "00001KVXK0WD3", "00001KVXK0WDH", "00001KVXK0WDQ", "00001KVXK0WDX", "00001KVXK0WE4", "00001KVXK0WEA"]
---
## Goal
@@ -42,10 +42,10 @@ Research of common Wasm extension systems points to the same pattern: mature sys
- Package presence never registers a Tool/Hook, executes Wasm, starts a Service, reads files, opens network, or injects context.
- Explicit enablement and Plugin grants are required before registration/execution/host API use.
- Tool calls/results continue through ordinary ToolRegistry and Worker history paths.
- Treat Component Model as the preferred future Plugin runtime shape.
- Treat Component Model as the active Plugin runtime shape before public release.
- New typed Plugin host APIs should be designed in WIT-compatible terms.
- `runtime.kind = "wasm-component"` should become the preferred runtime once implemented.
- Current `yoi-plugin-wasm-1` raw core-Wasm ABI remains a compatibility / migration bridge until Component Model execution and authoring are validated.
- `runtime.kind = "wasm-component"` is the current Plugin runtime authority for new work.
- The earlier `yoi-plugin-wasm-1` raw core-Wasm compatibility bridge is retired from the active roadmap because Plugin has not been publicly released and compatibility would preserve the wrong boundary.
- Sequence the platform in usable layers:
1. Package discovery / explicit enablement / digest-pinned restore. Completed foundation.
2. Tool surface registration. Completed foundation.
@@ -53,30 +53,49 @@ Research of common Wasm extension systems points to the same pattern: mature sys
4. Permission grants. Completed foundation.
5. Read-only Plugin CLI inspection (`yoi plugin list/show`) for debugging discovery/enablement/grants/runtime metadata.
6. `https` and `fs` host APIs for Tool Plugins, grant-gated and WIT-compatible.
7. Component Model runtime migration and authoring model.
8. Guest SDK/PDK, examples, `check`/`pack`/`new` authoring tooling.
9. Service / Ingress / WebSocket or inbound HTTP only after Tool + host API foundations are stable.
7. Remove the raw core-Wasm compatibility bridge and reject legacy runtime manifests.
8. Component Model runtime and authoring model become the only active Plugin runtime path.
9. Guest SDK/PDK, examples, `check`/`pack`/`new` authoring tooling target Component Model only.
10. Service / Ingress runtime is developed as host-managed lifecycle, event queue, output command, and diagnostics slices.
11. WebSocket support for long-lived integrations is host-owned connection driver + ingress event delivery + output command, not Plugin-owned polling with `recv(timeout)`.
- Keep Discord-style bridge goals split into two stages.
- Outbound Discord/webhook Tool is possible after `https`.
- Bidirectional Discord bridge requires Service + Ingress + WebSocket or inbound HTTP and host routing policy.
## Current implementation split
The broad Plugin runtime redesign is tracked by `00001KVXHVCR5` as context only; implementation should proceed through concrete Tickets instead of routing that umbrella as a single coding task.
1. `00001KVXK0WD3` Remove legacy raw WASM Plugin runtime.
- Deletes the active `LegacyToolAdapter` / raw-Wasm execution path.
2. `00001KVXK0WDH` Reject legacy Plugin runtime in manifest and CLI diagnostics.
- Makes `plugin.toml`, `yoi plugin check/list/show`, docs, and fixtures reflect Component Model only runtime authority.
3. `00001KVXK0WDQ` Define Plugin Service lifecycle and ingress queue runtime.
- Adds host-managed lifecycle, bounded queue, serial dispatch, backpressure, timeout, and diagnostics.
4. `00001KVXK0WDX` Add Plugin service output command model.
- Lets service handlers request side effects as grant-checked commands rather than ambient authority.
5. `00001KVXK0WE4` Add host-owned WebSocket driver for Plugin services.
- Converts incoming WS frames into ingress events and sends outbound frames through output commands.
6. `00001KVXK0WEA` Update Plugin WIT PDK templates for service event runtime.
- Aligns authoring API, WIT, PDK, templates, and docs with the new event/command execution model.
## Success criteria / exit conditions
- Users can inspect Plugin discovery/enablement/grant/runtime state through a read-only CLI without executing Plugin code.
- Plugin authors can build a Tool Plugin without writing raw memory/pointer ABI plumbing.
- Tool Plugins can safely call grant-gated `https` and `fs` host APIs.
- Component Model support is available or a documented migration path is active, with WIT-compatible host API types and measured packaging/runtime impact.
- Component Model is the only active Plugin runtime path, with WIT-compatible host API types and measured packaging/runtime impact.
- Plugin grants remain authoritative over registration, execution, and host API calls.
- Plugin diagnostics explain missing package, invalid manifest, digest/version mismatch, missing grant, rejected schema, runtime mismatch, and unsupported host API cases safely.
- Existing raw core-Wasm Plugin tests either remain passing or have an explicit compatibility/deprecation decision.
- Documentation covers package format, runtime kinds, Component Model direction, host API authority, authoring SDK/templates, and operational debugging.
- Service/Ingress work starts only after Tool Plugin + host API + diagnostics foundations are usable.
- Plugin diagnostics explain missing package, invalid manifest, digest/version mismatch, missing grant, rejected schema, runtime mismatch, legacy runtime rejection, and unsupported host API cases safely.
- Raw core-Wasm Plugin compatibility is removed before public release; tests and docs no longer treat it as a current runtime.
- Documentation covers package format, Component Model runtime, host API authority, authoring SDK/templates, Service/Ingress event runtime, and operational debugging.
- Service/Ingress work is host-managed: services have lifecycle/status, ingress uses bounded queues, side effects are output commands, and WebSocket integrations use host-owned connection drivers.
## Decision context
- This Objective is roadmap context, not Ticket authority. Implementation still requires reading concrete Ticket bodies, threads, artifacts, and relations.
- Component Model direction supersedes making Yoi's custom raw ABI the long-term authoring interface, but does not require an immediate flag-day rewrite.
- Component Model direction supersedes Yoi's custom raw ABI as both long-term and current active Plugin runtime authority before public release.
- `https` / `fs` work should avoid choices that conflict with later WIT typed interfaces.
- Guest SDK work should either target Component Model directly or keep the raw ABI wrapper clearly transitional.
- Guest SDK work targets Component Model directly; raw ABI wrappers are not a supported transitional authoring path.
- Plugin and MCP remain separate. Component Model adoption for Plugin does not imply MCP server execution, MCP prompt/resource injection, or MCP trust policy changes.
- Plugin surfaces remain Tool / Hook / Service / Ingress; outbound side effects are Tool metadata and host API grants, not a separate surface.
+7 -2
View File
@@ -2,7 +2,7 @@
title: "Team workspace control plane and runner architecture"
state: "active"
created_at: "2026-06-20T14:26:29Z"
updated_at: "2026-06-21T06:57:06Z"
updated_at: "2026-06-21T18:10:00Z"
linked_tickets: ["00001KVMFFYVX"]
---
@@ -175,6 +175,10 @@ Web UI は Ticket、Objective、Memory、Knowledge、Run、Runner、Artifact を
Cloud/remote execution を成立させるには、多数のエージェント実行を安く管理できる必要がある。logical agent session と runtime process/resource placement を分ける。
初期 Workspace DB では、Worker を canonical table として永続化しない。Host / Worker 一覧は backend-local runtime inspection や将来の Host protocol から逐次取得する live view とし、Ticket に関わった Worker は Ticket thread events と WorkerRef snapshot / TicketWorkerLink として記録する。
Worker の一元管理、データ永続化、アーカイブは将来的には必要になる。これは Host protocol、remote/self-hosted/hosted worker lifecycle、worker identity、retention policy、audit requirements が固まった後に、dedicated Worker registry / archive model として追加する。v0 で Pod metadata の代替として Worker table を作らない。
検討対象:
- Agent identity と process/runtime placement の分離。
@@ -241,4 +245,5 @@ Cloud/remote execution を成立させるには、多数のエージェント実
- Web frontend を最初の primary team UI とする。Desktop app は web/control-plane model が安定した後に検討する。
- Git は重要な Repository provider / materialization backend として使うが、Workspace identity と authority を Git Repository root に固定しない。
- Ticket と Objective は Workspace 配下に平たく持つ。対象コードベースや ref は Repository target selector として表現し、Run が concrete RepositoryPoint に解決する。
- Memory の本格再設計は後回しにする。先に Workspace / Ticket / Run / Repository / Runner / Control plane の基盤を固め、Memory の保存先を Workspace backend に移すタイミングで、意味論・抽出・承認・検索・staleness 処理をまとめて回収する。
- Memory の本格再設計は後回しにする。先に Workspace / Ticket / Repository / Host/Worker live view / Control plane の基盤を固め、Memory の保存先を Workspace backend に移すタイミングで、意味論・抽出・承認・検索・staleness 処理をまとめて回収する。
- Worker の一元管理・データ永続化・アーカイブも後続設計に回す。初期 DB では Worker を Pod metadata の代替として永続化せず、live view と Ticket-linked WorkerRef 記録に留める。
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-071337-1","ticket_id":"00001KVMFFYVX","kind":"accepted_plan","accepted_plan":{"summary":"Bootstrap a single-workspace Rust Workspace control-plane backend with store abstraction + SQLite, bounded read APIs over workspace/tickets/objectives, static SvelteKit SPA skeleton serving, and package/Nix-safe frontend handling while preserving existing `.yoi` record workflows.","branch":"impl/00001KVMFFYVX-workspace-web-control-plane","worktree":"/home/hare/Projects/yoi/.worktree/00001KVMFFYVX-workspace-web-control-plane","role_plan":"Orchestrator records acceptance and creates child worktree. Coder receives narrow write scope for that worktree and implements backend crate/store/SPA/API/bootstrap. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T07:13:37Z"}
+2 -2
View File
@@ -1,8 +1,8 @@
---
title: 'Workspace web control plane bootstrap'
state: 'queued'
state: 'closed'
created_at: '2026-06-21T06:57:06Z'
updated_at: '2026-06-21T07:11:58Z'
updated_at: '2026-06-21T07:46:46Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-21T07:11:58Z'
+25
View File
@@ -0,0 +1,25 @@
Workspace web control plane bootstrap を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- New backend library crate `yoi-workspace-server` / `crates/workspace-server` を追加。
- Axum-based read-only HTTP API と static/SPA serving surface を追加。
- `/api/...` と static/SPA fallback を分離し、API route miss を SPA fallback に飲ませない設計にした。
- `ControlPlaneStore` trait と SQLite implementation `SqliteWorkspaceStore` を追加。
- SQLite migration/version table、WAL、foreign keys、busy timeout を設定。
- `.yoi/tickets``.yoi/objectives` を canonical read sources として扱う local project-record bridge を追加し、既存 record workflow を移行・変更しない。
- Read APIs: `/api/workspace`, `/api/tickets`, `/api/tickets/{id}`, `/api/objectives`, `/api/objectives/{id}`, `/api/runs`, `/api/runners`
- Future runner/event-stream extension seams を response/state shape に用意しつつ、scheduler/runner dispatch/write API は実装しない。
- SvelteKit static SPA skeleton を `web/workspace` に追加し、npm lockfile、static adapter、README、generated artifact ignore/source-filter handling を追加。
- `Cargo.lock``package.nix` cargo hash / source filtering を更新。
統合・検証:
- Merge commit: `3e03e536 merge: workspace web control plane`
- Implementation commit: `ab7658c1 feat: bootstrap workspace web control plane`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `cargo check -p yoi`, `cd web/workspace && npm ci && npm run check && npm run build`, `cargo run -p yoi -- ticket doctor`, `cargo run -p yoi -- objective doctor`, and `nix build .#yoi --no-link`
範囲外 / deferrals:
- Product CLI/server launch command は未追加。backend library exposes `serve(...)`; launch surface は future Ticket で設計する。
- Write API、runner job dispatch、scheduler、hosted/multi-tenant auth、billing/quota、memory migration は実装していない。
- Event stream implementation は未実装で、extension seam のみ。
- Generated SPA assets are not committed; configured static directory such as `web/workspace/build` can be served after frontend build。
+405
View File
@@ -30,4 +30,409 @@ Marked ready by `yoi ticket state`.
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T07:13:24Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body は Workspace web control plane の bootstrap slice として backend crate、store abstraction + SQLite、static SPA skeleton、initial read API、static serving、packaging/Nix hygiene、validation criteria まで具体化されている。
- Objective `00001KVJPT2PP` は Web frontend を primary team UI とし、control plane / runner architecture を段階実装する背景として整合している。
- Relations / orchestration plan に blocker はない。
- Current queued Ticket はこの Ticket のみ。
- Orchestrator worktree は clean on `orchestration` at `5fa0846d` で、対象 Ticket 用 worktree / branch は未作成。
- Visible Pods に対象 Ticket の child Pod は存在しない。
Evidence checked:
- Ticket body / thread via direct read。
- Objective `00001KVJPT2PP` via direct read。
- `TicketRelationQuery(00001KVMFFYVX)`: no relations / blockers。
- `TicketOrchestrationPlanQuery(00001KVMFFYVX)`: no records。
- `TicketList(state=queued)`: queued Ticket はこの Ticket のみ。
- `ListPods`: current visible Pods に対象 Ticket の coder/reviewer はない。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `Cargo.toml` workspace members exist under `crates/*`
- Existing project-record / Objective CLI code is in `crates/yoi/src/objective_cli.rs` and Ticket CLI code in `crates/yoi/src/ticket_cli.rs`
- No existing frontend package/root was found in active source; frontend skeleton location is an implementation decision。
- Dependency search found no current web backend crate; adding one is expected。
IntentPacket:
Intent:
- Bootstrap a local single-workspace Workspace web control plane that can serve a static SPA and bounded read APIs while preserving existing `.yoi` Ticket / Objective workflows as canonical project records。
- Establish architecture seams for future multi-workspace hosted control plane, runner connections, event streams, and store implementations without implementing hosted SaaS or runner scheduling in this Ticket。
Binding decisions / invariants:
- Product CLI ownership remains in `yoi` crate; new backend crate must not become the product CLI façade。
- Initial server is single-workspace and local/dev oriented, but internal API/state models should carry `workspace_id` or equivalent to avoid blocking multi-workspace later。
- Store layer has an explicit trait/interface boundary; SQLite is the initial implementation, not an authority leak through frontend or handlers。
- SQLite setup should include server-appropriate basics: WAL, foreign keys, busy timeout, and minimal schema versioning/migration mechanism。
- Existing `.yoi/tickets` and `.yoi/objectives` local record workflow remains canonical and must not be migrated or broken in this Ticket。
- Frontend is static SPA skeleton, not SSR authority and not a place for lifecycle/business authority。
- Rust backend must separate `/api/...` from SPA fallback/static serving。
- Auth can be explicit local-only/dev-token placeholder, but must not imply production SaaS auth is solved。
- No write API, runner dispatch, billing/quota, memory migration, or hosted multi-tenant operations in this Ticket。
- Packaging/Nix/repository hygiene must remain valid; generated build artifacts should not be checked in unless explicitly justified。
Requirements / acceptance criteria:
- Add a workspace control plane backend Rust crate to Cargo workspace。
- Provide HTTP API + static SPA serving surfaces and future extension points for event stream / runner connection。
- Add store abstraction plus initial SQLite implementation with migration/versioning。
- Add bounded initial read APIs at least for workspace, tickets, and objectives; candidate additional empty/skeleton endpoints for runs/runners are allowed if clean。
- Add SvelteKit static SPA skeleton in monorepo and document/encode package manager + lockfile + build artifact handling。
- Backend can serve built static assets and use SPA routing fallback separately from `/api/...`
- Existing local `.yoi` Ticket / Objective record workflow remains working。
- Validation before completion includes `cargo fmt --check`, relevant `cargo test` / `cargo check`, frontend check/build, `git diff --check`, `yoi ticket doctor`, `yoi objective doctor`, and `nix build .#yoi --no-link`
Implementation latitude:
- Crate names and paths may be chosen by Coder, with preference for clear names such as `workspace-server` / `workspace` / `control-plane` and avoiding ambiguity with runtime workspace root semantics。
- Static asset embedding/serving may be implemented as fallback directory serving, optional embedded assets, or a documented dev/static-dir path if the initial bootstrap remains runnable and package-safe。
- SQLite crate choice may follow current project style/dependency constraints; dependency/package hash updates must be handled if new dependencies are added。
- Frontend package manager may be npm/pnpm/etc. if lockfile and Nix/package handling are explicit and reproducible enough for this bootstrap。
- API JSON schemas can be minimal and bounded; do not overbuild mutation or runner dispatch。
- Add focused tests around store migration, `.yoi` record read bridge, handler/API shape, and static/API route separation.
Escalate if:
- Adding frontend build tooling cannot be reconciled with Nix/package build in this slice。
- SQLite dependency/package updates create unresolved Nix cargo hash/source-filter failures。
- Serving built SPA assets would require checking in generated artifacts without agreement。
- `.yoi` Ticket/Objective canonical record compatibility becomes ambiguous or requires migration。
- Implementing this bootstrap forces public auth/hosted SaaS decisions beyond local/dev mode。
- The change grows into write API / runner dispatch / scheduler design rather than bootstrap/read-heavy surface。
Validation plan for Coder and Reviewer:
- Rust: `cargo fmt --check`, focused tests for new crate / yoi integration, `cargo check` for affected crates and workspace-facing binary。
- Frontend: install/check/build command appropriate to chosen package manager, with lockfile committed if needed。
- Repository/package: `git diff --check`, `yoi ticket doctor`, `yoi objective doctor`, `nix build .#yoi --no-link` if dependency/package/source-filter/frontend handling changed。
- Smoke: start or exercise server routes in a test/noninteractive way for `/api/workspace`, `/api/tickets`, `/api/objectives`, and static/SPA fallback。
Critical risks / reviewer focus:
- Keep authority in Rust backend/store, not frontend。
- Ensure `/api/...` routes do not fall through to SPA fallback incorrectly。
- Ensure local `.yoi` records remain canonical and existing CLI doctor workflows still pass。
- Ensure SQLite migrations are deterministic and not tied to process cwd accidentally。
- Ensure frontend package files and generated artifacts do not pollute package/Nix builds。
- Ensure new dependencies and Nix cargo hash/source filtering are updated consistently。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T07:13:29Z from: queued to: inprogress reason: human_authorized_unblocked_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria and no recorded blockers, so Orchestrator accepts implementation and will create a child implementation worktree before spawning sibling Coder/Reviewer roles.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:15:03Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMFFYVX-workspace-web-control-plane`
- Created branch:
- `impl/00001KVMFFYVX-workspace-web-control-plane`
- Base commit:
- `1d27f6c9 ticket: accept workspace web control plane`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVMFFYVX`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVMFFYVX-workspace-web-control-plane`
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff. Orchestrator will not merge/close until reviewer approval and validation evidence are available。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:37:30Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVMFFYVX`.
Implementation commit:
- `ab7658c1 feat: bootstrap workspace web control plane`
Changed areas:
- New Cargo workspace crate:
- `crates/workspace-server`
- HTTP router with `/api/...` separation from static/SPA fallback。
- Local/dev workspace API state carrying `workspace_id`
- Bounded read APIs for `/api/workspace`, `/api/tickets`, `/api/tickets/{id}`, `/api/objectives`, `/api/objectives/{id}`, `/api/runs`, `/api/runners`
- Reserved extension-point response fields for future event streams and runner connections。
- Store abstraction and SQLite implementation:
- `ControlPlaneStore` trait。
- `SqliteWorkspaceStore`
- migration/version table。
- WAL, foreign keys, busy timeout。
- initial schema for workspace/runtime/projection seams while keeping `.yoi` records canonical。
- Local project-record bridge:
- reads existing `.yoi/tickets`
- reads existing `.yoi/objectives`
- does not migrate or mutate canonical records。
- SvelteKit static SPA skeleton:
- `web/workspace`
- npm + committed `package-lock.json`
- static adapter build output to `web/workspace/build`
- generated artifact handling documented in `web/workspace/README.md`
- Packaging/source handling:
- added Rust dependencies and updated `Cargo.lock`
- updated `package.nix` cargo hash。
- excluded generated frontend directories from Nix package source filtering。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cargo check -p yoi`: passed
- `cd web/workspace && npm run check && npm run build`: passed
- `git diff --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `cargo run -p yoi -- objective doctor`: passed
- `nix build .#yoi --no-link`: passed after updating `cargoHash`
Coder dependency/package/frontend decisions:
- Used `axum` for HTTP routing。
- Used `rusqlite` with bundled SQLite to avoid system SQLite packaging requirements。
- Backend remains a library crate, not a product CLI façade。
- No product `yoi` CLI command was added in this slice。
- Frontend uses npm/SvelteKit static adapter with committed lockfile; generated build output is not checked in。
- Nix package does not build frontend in this bootstrap; it excludes generated frontend artifacts from source filtering。
Known deferrals reported:
- No write API。
- No runner job dispatch or scheduler。
- No hosted/multi-tenant auth or SaaS behavior。
- No event stream implementation yet; only reserved extension-point seam。
- No checked-in generated SPA assets; backend can serve configured static directory such as `web/workspace/build` after running frontend build。
Orchestrator evidence checked:
- Implementation worktree is clean on `impl/00001KVMFFYVX-workspace-web-control-plane`
- HEAD is `ab7658c1`
- Diff `1d27f6c9..HEAD` touches expected backend/frontend/package files: 18 files, about 3377 insertions / 1 deletion。
- `git diff --check 1d27f6c9..HEAD` produced no diagnostics。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket and Objective context。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T07:38:14Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVMFFYVX-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVMFFYVX-workspace-web-control-plane`
- Branch: `impl/00001KVMFFYVX-workspace-web-control-plane`
- Baseline: `1d27f6c9`
- Implementation commit: `ab7658c1 feat: bootstrap workspace web control plane`
- Diff: `1d27f6c9..ab7658c1`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Acceptance criteria for backend crate, store abstraction + SQLite, static SPA, bounded read APIs, static/API route separation, package/Nix/frontend hygiene。
- No write API / scheduler / SaaS overreach。
- `.yoi` Ticket / Objective records remain canonical and read-only。
- SQLite migrations/settings are deterministic and server-appropriate。
- Frontend generated artifacts are not committed and source filtering is safe。
- Validation evidence includes Rust tests/checks, frontend check/build, doctors, and `nix build .#yoi --no-link`
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVMFFYVX-r1 at: 2026-06-21T07:44:49Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket/context:
- `.yoi/tickets/00001KVMFFYVX/item.md`
- `.yoi/tickets/00001KVMFFYVX/thread.md`
- `.yoi/objectives/00001KVJPT2PP/item.md`
- Diff `1d27f6c9..ab7658c1`:
- `Cargo.toml`
- `Cargo.lock`
- `crates/workspace-server/Cargo.toml`
- `crates/workspace-server/src/lib.rs`
- `crates/workspace-server/src/server.rs`
- `crates/workspace-server/src/store.rs`
- `crates/workspace-server/src/records.rs`
- `package.nix`
- `web/workspace/package.json`
- `web/workspace/package-lock.json`
- `web/workspace/.gitignore`
- `web/workspace/README.md`
- `web/workspace/svelte.config.js`
- `web/workspace/vite.config.ts`
- `web/workspace/tsconfig.json`
- `web/workspace/src/app.html`
- `web/workspace/src/routes/+layout.ts`
- `web/workspace/src/routes/+page.svelte`
Blocking issues:
- None found。
Acceptance verification:
- New `yoi-workspace-server` crate is a library/backend crate, not a product CLI façade。
- Existing `yoi` CLI ownership is preserved; `yoi` does not depend on the new crate。
- HTTP routes are read-only `GET` routes for `/api/workspace`, `/api/tickets`, `/api/tickets/{id}`, `/api/objectives`, `/api/objectives/{id}`, `/api/runs`, `/api/runners`
- SPA/static fallback explicitly rejects `/api` and `/api/...`, so API paths are not swallowed by SPA fallback。
- `.yoi/tickets` and `.yoi/objectives` remain canonical read sources; no `.yoi` write/migration path was introduced。
- Store abstraction is explicit via `ControlPlaneStore`; SQLite is behind `SqliteWorkspaceStore`
- SQLite setup includes migrations/version table, WAL, foreign keys, and busy timeout。
- Runtime tables for runs/runners are skeletal/read-only and do not implement scheduling or dispatch。
- Auth is explicitly represented as local/dev placeholder, not production SaaS auth。
- SvelteKit frontend is static SPA skeleton with npm lockfile; generated `node_modules`, `.svelte-kit`, and `build` are ignored/excluded。
- `package.nix` source filtering excludes frontend generated artifacts; `nix build .#yoi --no-link` passed with updated cargo hash。
Non-blocking concerns:
- No committed CLI/binary entrypoint or full listener smoke test for starting the server end-to-end. Library exposes `serve(...)` and router tests cover API/static separation, acceptable for bootstrap; follow-up should add launch surface when product command is designed。
- Detail responses for tickets/objectives do not include `workspace_id`, while list/runtime responses do. Future multi-workspace API expansion should make detail shapes consistently workspace-qualified。
- Missing valid objective IDs appear likely to map filesystem `Io` errors to HTTP 500 rather than 404. Tighten when read API contract is hardened。
- Static path traversal rejects `..`, but symlink escape hardening is not implemented. Acceptable for configured local build/static directory and local/dev bootstrap, revisit before non-local exposure。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 1d27f6c9..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cargo check -p yoi`: passed
- `cd web/workspace && npm run check && npm run build`: initially failed because `node_modules` absent。
- `cd web/workspace && npm ci && npm run check && npm run build`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `cargo run -p yoi -- objective doctor`: passed
- `nix build .#yoi --no-link`: passed
- Focused route/static validation:
- Inspected router definitions and fallback logic。
- Existing `yoi-workspace-server` tests exercise `/api/workspace`, `/api/tickets`, `/api/objectives`, `/api/runners`, static asset serving, SPA fallback, and `/api/...` miss separation。
- Store migration/persistence and local record read bridge are covered by crate tests。
Worktree status:
- Tracked worktree clean at `ab7658c1` on `impl/00001KVMFFYVX-workspace-web-control-plane`
- Ignored validation artifacts remain in the implementation worktree: `web/workspace/node_modules/`, `web/workspace/.svelte-kit/`, `web/workspace/build/`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:45:59Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `3e03e536 merge: workspace web control plane`
- Merged branch: `impl/00001KVMFFYVX-workspace-web-control-plane`
- Implementation commit:
- `ab7658c1 feat: bootstrap workspace web control plane`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cargo check -p yoi`: passed
- `cd web/workspace && npm ci && npm run check && npm run build`: passed
- `npm ci` reported 4 low severity vulnerabilities via npm audit output; build/check succeeded and no blocking validation failure occurred。
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `cargo run -p yoi -- objective doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `3e03e536`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T07:46:04Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、Rust/frontend/Nix/doctor validation が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T07:46:19Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T07:46:19Z status: closed -->
## 完了
Workspace web control plane bootstrap を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- New backend library crate `yoi-workspace-server` / `crates/workspace-server` を追加。
- Axum-based read-only HTTP API と static/SPA serving surface を追加。
- `/api/...` と static/SPA fallback を分離し、API route miss を SPA fallback に飲ませない設計にした。
- `ControlPlaneStore` trait と SQLite implementation `SqliteWorkspaceStore` を追加。
- SQLite migration/version table、WAL、foreign keys、busy timeout を設定。
- `.yoi/tickets``.yoi/objectives` を canonical read sources として扱う local project-record bridge を追加し、既存 record workflow を移行・変更しない。
- Read APIs: `/api/workspace`, `/api/tickets`, `/api/tickets/{id}`, `/api/objectives`, `/api/objectives/{id}`, `/api/runs`, `/api/runners`
- Future runner/event-stream extension seams を response/state shape に用意しつつ、scheduler/runner dispatch/write API は実装しない。
- SvelteKit static SPA skeleton を `web/workspace` に追加し、npm lockfile、static adapter、README、generated artifact ignore/source-filter handling を追加。
- `Cargo.lock``package.nix` cargo hash / source filtering を更新。
統合・検証:
- Merge commit: `3e03e536 merge: workspace web control plane`
- Implementation commit: `ab7658c1 feat: bootstrap workspace web control plane`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `cargo check -p yoi`, `cd web/workspace && npm ci && npm run check && npm run build`, `cargo run -p yoi -- ticket doctor`, `cargo run -p yoi -- objective doctor`, and `nix build .#yoi --no-link`
範囲外 / deferrals:
- Product CLI/server launch command は未追加。backend library exposes `serve(...)`; launch surface は future Ticket で設計する。
- Write API、runner job dispatch、scheduler、hosted/multi-tenant auth、billing/quota、memory migration は実装していない。
- Event stream implementation は未実装で、extension seam のみ。
- Generated SPA assets are not committed; configured static directory such as `web/workspace/build` can be served after frontend build。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:46:46Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVMFFYVX`
- `yoi-reviewer-00001KVMFFYVX-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMFFYVX-workspace-web-control-plane`
- Deleted implementation branch:
- `impl/00001KVMFFYVX-workspace-web-control-plane`
- Orchestrator worktree remains clean on `orchestration` at `f33415c7`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-071725-1","ticket_id":"00001KVMG8FTW","kind":"accepted_plan","accepted_plan":{"summary":"Refactor Plugin one-shot outbound host API from `host_api.https` / `grants.https` to URL-permission-based `host_api.request`, including manifest request targets, enablement grants, runtime two-stage authorization, local/private explicit permissions, inspection diagnostics, docs/templates, and focused tests.","branch":"impl/00001KVMG8FTW-plugin-request-host-api","worktree":"/home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api","role_plan":"Orchestrator accepts parallel implementation, creates a child worktree, and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator will integrate into `orchestration`, validate, record closure, and clean only the child worktree/branch. Coordinate manually if active Workspace web branch creates Cargo.lock/package.nix conflicts."},"author":"yoi-orchestrator","at":"2026-06-21T07:17:25Z"}
+4 -2
View File
@@ -1,11 +1,13 @@
---
title: 'Plugin: host_api.https を廃止して URL 権限ベースの host_api.request に統合する'
state: 'ready'
state: 'closed'
created_at: '2026-06-21T07:10:30Z'
updated_at: '2026-06-21T07:10:30Z'
updated_at: '2026-06-21T08:12:34Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['plugin', 'host-api', 'public-api', 'permissions', 'security', 'local-network', 'breaking-change']
queued_by: 'workspace-panel'
queued_at: '2026-06-21T07:15:41Z'
---
## User claims / request snapshot
+23
View File
@@ -0,0 +1,23 @@
Plugin host API の one-shot outbound request capability を `host_api.https` / `grants.https` から URL permission based `host_api.request` に置き換え、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Active API / docs / WIT naming を `request` に移行。
- Manifest に `host_api.request``[[request]]` target declaration を追加。
- Enablement grant を request target grant として扱うよう変更。
- Runtime authorization を manifest-declared request target と enabled request grant の両方が URL/method/scheme/host/port/path coverage で許可する場合のみ network I/O に進む形にした。
- Grant-only / missing-grant / broad / partial-coverage states を static inspection と `yoi plugin show` diagnostics で区別。
- Broad/covering grant と broad manifest + narrower grant の intersection semantics を runtime と static inspection で一致させた。
- Loopback/local/private target は ambient ではなく、URL host declaration + grant に基づく明示 authority として扱う方針を docs に記録。
- Embedded credentials、credential-like headers、WebSocket URLs/upgrades、SSE/event-stream requests を reject/unsupported にした。
- Old `host_api.https` / `grants.https` / `PluginHttps*` / old WIT names は active code/docs/resources から削除。
- Focused manifest / pod / yoi plugin CLI tests を追加・更新。
統合・検証:
- Merge commit: `8a15cca5 merge: plugin request host api`
- Implementation commits: `962b7699`, `0e14e7c1`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p manifest request --quiet`, `cargo test -p pod feature::plugin::tests --lib --quiet`, `cargo test -p yoi plugin_cli::tests --quiet`, `cargo check -p manifest -p pod -p yoi --quiet`, stale active naming grep, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Regex URL target matching は追加していない。
- WebSocket/SSE/persistent connection support は `host_api.request` に含めていない。WebSocket は別 capability / design Ticket 側で扱う。
+504
View File
@@ -5,3 +5,507 @@
LocalTicketBackend によって作成されました。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T07:15:41Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T07:17:14Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body は `host_api.https` 廃止、`host_api.request` 統一、manifest-declared URL/request target permissions、enablement grant 照合、runtime fail-closed、local/private target 明示 grant、broad/arbitrary URL 表示、docs/tests/diagnostics 更新まで具体化されている。
- `readiness: implementation_ready` で、relations / orchestration plan に blocker はない。
- Current active implementation `00001KVMFFYVX` は Workspace web control plane bootstrap で、主対象は backend/frontend/store/Nix packaging。This Ticket の主対象は plugin manifest/pod runtime/plugin CLI/docs/tests で直接の semantic blocker はない。過去のユーザー指示「blocker無いなら並列に」に従い、並列実装可能と判断する。
- Orchestrator worktree is clean on `orchestration` at `f164483e` で、対象 Ticket 用 worktree / branch は未作成。
- Visible Pods に対象 Ticket の child Pod は存在しない。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct `item.md` read。
- `TicketRelationQuery(00001KVMG8FTW)`: no relations / blockers。
- `TicketOrchestrationPlanQuery(00001KVMG8FTW)`: no records。
- `ListPods`: active child is only `yoi-coder-00001KVMFFYVX`; no child for this Ticket。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `crates/manifest/src/plugin.rs`: `PluginGrantConfig.https`, `PluginHttpsGrant`, `PluginHostApi::Https`, permission/grant resolution/tests。
- `crates/pod/src/feature/plugin.rs`: `PluginHttps*` runtime request path, `yoi:host/https@1.0.0` / raw wasm `yoi:https` imports, URL validation, request bounds, credential header checks, public-IP guard, allowlist checks, plugin tests。
- `crates/yoi/src/plugin_cli.rs`: inspection formatting for configured HTTPS grants。
- `docs/development/plugin-development.md`: active `host_api.https` / `grants.https` docs。
IntentPacket:
Intent:
- Replace public/model/config-facing `host_api.https` with URL-permission based one-shot `host_api.request`.
- Keep existing safe outbound request behavior where applicable, but generalize schemes/targets so explicit manifest + enablement grants can authorize loopback/private/local targets.
- Keep WebSocket / SSE / persistent connections out of `request`.
Binding decisions / invariants:
- Do not add backward compatibility aliases for `host_api.https`, `PluginHttps*`, or `grants.https` in active APIs unless explicitly escalated and reapproved。
- Model/config-facing naming must be `request`; internal names should also avoid `PluginHttps*` unless truly private transitional code is justified and not exposed。
- Runtime authorization requires both manifest-declared request target permission and enablement grant for that target。
- Grant-only without manifest request must fail closed or be explicitly diagnosed as unsafe/unused override; do not silently expand authority。
- Requested-but-ungranted target must fail closed before network I/O。
- Localhost/loopback/private/local targets are not ambient; they require manifest declaration and enablement grant。
- Arbitrary URL / broad network access must be visibly distinguished from normal target grants in inspection/diagnostics。
- Embedded credentials, credential-like headers, request/response bounds, external-content untrusted treatment, and no hidden context injection remain mandatory。
- WebSocket URL / upgrade / persistent stream must be rejected or explicitly unsupported by `request`
- Existing HTTPS request use cases must continue under `host_api.request` with explicit request permission/grant。
Requirements / acceptance criteria:
- Active API naming uses `host_api.request` / request grant naming。
- Plugin manifest statically declares request target permissions readable from manifest alone。
- Enablement config grants request targets and is matched against manifest-declared targets。
- Runtime checks method/scheme/host/port/path prefix against declared+granted URL permission。
- `http://localhost` / loopback request can be allowed only with explicit declaration+grant。
- Existing public HTTPS use case works as request。
- Broad/arbitrary URL is supported only with clear broad display/diagnostic if implemented。
- `yoi plugin show` / static inspection distinguishes requested, granted, denied/missing, and broad request permissions。
- Docs/templates/tests/diagnostics are updated to request naming and WebSocket separate-capability policy。
Implementation latitude:
- Exact Rust/TOML type names are up to Coder, but active names should be request-oriented, e.g. `PluginRequestGrant`, `PluginRequestTarget`, `host_api.request`.
- Regex support is optional. If added, it must include review-readable normalized display/warning/label and tests for broad/opaque handling。
- Request target schema may start with exact scheme/host/optional port/method/path prefix. Keep permission review human-readable。
- Internal runtime can reuse/refactor existing HTTPS client/request code, but reviewer should see active API renaming and policy changes。
- Raw wasm/component import migration may choose new import names with tests; if keeping an internal compatibility import is unavoidable, escalate before committing.
Escalate if:
- Compatibility alias for old `host_api.https` / `grants.https` seems required。
- Local/private target policy would open without both manifest declaration and grant。
- Arbitrary URL access becomes visually indistinguishable from normal grants。
- WebSocket/SSE/daemon lifecycle begins to enter `request`
- Secret-bearing headers/env/config would flow from guest memory without explicit SecretRef/grant design。
- Regex support becomes opaque or hard to review。
- Parallel active `00001KVMFFYVX` work creates unavoidable `Cargo.lock` / `package.nix` conflict; report rather than broad-rebasing alone。
Validation plan:
- `cargo fmt --check`
- Focused manifest plugin tests for request permission parsing/resolution and naming removal。
- Focused pod plugin tests for grant allow/deny, requested-but-ungranted, granted-but-unrequested, loopback/local allow/deny, WebSocket/upgrade rejection, request/response bounds/credential-header safety。
- Focused yoi plugin CLI tests for request permission/grant/broad/missing diagnostics。
- Docs/template grep ensuring active `host_api.https` / `grants.https` / `PluginHttps*` naming is removed except historical Ticket text or explicitly justified migration notes。
- `cargo check` for affected crates, `git diff --check`, `yoi ticket doctor`
Reviewer focus:
- Breaking-change intent is real: no stale active docs/templates/CLI inspection still teaching `host_api.https`
- Authorization must be two-stage: manifest request + grant。
- Local/private network must not become ambient。
- Old public HTTPS use case must still work under request naming。
- External content and hidden context constraints remain intact。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T07:17:18Z from: queued to: inprogress reason: human_authorized_unblocked_parallel_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria and no recorded blockers; active Workspace web control plane implementation is semantically separate enough for parallel implementation. Orchestrator accepts this Plugin host API refactor into implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:18:48Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api`
- Created branch:
- `impl/00001KVMG8FTW-plugin-request-host-api`
- Base commit:
- `4cd4a06e ticket: route plugin request capabilities`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVMG8FTW`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api`
Parallelization note:
- `00001KVMFFYVX` remains in progress in a separate child worktree. Coder was instructed to avoid unnecessary Cargo.lock/package.nix churn and report if unavoidable conflicts appear。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff. Orchestrator will not merge/close until reviewer approval and validation evidence are available。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T07:48:07Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVMG8FTW`.
Implementation commit:
- `962b7699 plugin: replace https host api with request grants`
Changed areas:
- `crates/manifest/src/plugin.rs`
- Replaced active host API/grant naming with `request`
- Added manifest-declared `[[request]]` URL targets with `scheme`, `host`, optional `port`, `methods`, and `path_prefixes`
- Added request grant parsing/labels/broad diagnostics and tests that legacy HTTPS-facing names are not accepted。
- `crates/pod/src/feature/plugin.rs`
- Renamed runtime path/imports to request-oriented naming。
- Runtime now requires both manifest request target declaration and enabled request grant before network I/O。
- Checks scheme/host/port/path/method, rejects embedded credentials, credential-like headers, WebSocket URLs/upgrades, and SSE/event-stream requests。
- Allows loopback/local/private targets only when explicitly declared and granted。
- Adds static inspection entries for requested/granted/missing/grant-only/broad request targets。
- `crates/yoi/src/plugin_cli.rs`
- Shows configured request grants and request target eligibility diagnostics, including broad/missing/grant-only states。
- `resources/plugin/wit/*`
- Updated WIT import/interface from HTTPS host API to `yoi:host/request@1.0.0`
- `docs/development/plugin-development.md`
- Rewrote host API docs for `request`, including manifest targets, enablement grants, loopback policy, broad target diagnostics, and WebSocket/SSE exclusion。
- `docs/design/plugin-component-model.md`
- Updated design wording/import references。
- `crates/pod/src/pod.rs`
- Updated test fixture initialization for the new manifest request target field。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p manifest request`: passed
- `cargo test -p pod feature::plugin::tests --lib`: passed
- `cargo test -p yoi plugin_cli::tests`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `git diff --check`: passed
- Active naming grep for `host_api.https|grants.https|PluginHttps|yoi:host/https|yoi:https` under `crates docs resources`: no matches
- `target/debug/yoi ticket doctor`: passed
Coder dependency/package report:
- No `Cargo.lock`, `package.nix`, or flake changes。
- No dependency/package churn。
Known deferrals:
- Regex URL target matching was not added。
- WebSocket/SSE/persistent connection support remains explicitly outside `host_api.request`
Orchestrator evidence checked:
- Implementation worktree is clean on `impl/00001KVMG8FTW-plugin-request-host-api`
- HEAD is `962b7699`
- Diff `4cd4a06e..HEAD` touches 9 expected manifest/pod/plugin-doc/WIT files, about 768 insertions / 448 deletions。
- Active stale naming grep under `crates docs resources` returned no matches。
- `git diff --check 4cd4a06e..HEAD` produced no diagnostics。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket and IntentPacket。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T07:48:53Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVMG8FTW-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api`
- Branch: `impl/00001KVMG8FTW-plugin-request-host-api`
- Baseline: `4cd4a06e`
- Implementation commit: `962b7699 plugin: replace https host api with request grants`
- Diff: `4cd4a06e..962b7699`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Active API/docs/WIT/CLI naming uses request, not stale https names。
- No compatibility alias remains for old `host_api.https` / `grants.https` unless explicitly justified。
- Runtime authorization requires both manifest request target and enablement grant before network I/O。
- Grant-only and missing-grant cases fail closed / diagnose clearly。
- Local/private/loopback targets require explicit declaration and grant。
- WebSocket/SSE/persistent stream behavior is rejected or explicitly unsupported by `request`
- Broad/arbitrary URL grants are visibly distinguished。
- Existing public HTTPS use case still works through request naming。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVMG8FTW-r1 at: 2026-06-21T07:58:08Z status: request_changes -->
## Review: request changes
Verdict: `request_changes`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVMG8FTW/item.md`
- `.yoi/tickets/00001KVMG8FTW/thread.md`
- Implementation diff `4cd4a06e..962b7699`:
- `crates/manifest/src/plugin.rs`
- `crates/pod/src/feature/plugin.rs`
- `crates/pod/src/pod.rs`
- `crates/yoi/src/plugin_cli.rs`
- `docs/design/plugin-component-model.md`
- `docs/development/plugin-development.md`
- `resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit`
- `resources/plugin/wit/yoi-plugin-instance-v1.wit`
- `resources/plugin/wit/yoi-plugin-tool-v1.wit`
Blocking issue:
1. Static inspection and runtime authorization disagree for broad / covering request grants。
Static inspection currently treats request target grants as matching only by exact equality:
- `crates/pod/src/feature/plugin.rs:420-425`
- `let granted = record.grants.request.iter().any(|grant| grant == target);`
- `crates/pod/src/feature/plugin.rs:440-455`
- grants without exact equality are reported as `grant-only`, `eligible=false`
Runtime authorization checks manifest targets and grants independently by URL coverage:
- `crates/pod/src/feature/plugin.rs:1397-1409`
- URL must be allowed by some manifest target and some enabled grant。
- `crates/pod/src/feature/plugin.rs:1420-1449`
- broad grants such as `*://*` or broader path/host scopes can cover a concrete URL even when not equal to the manifest target。
Concrete mismatch:
- Manifest declares exact target: `https://api.example.test ... /v1`
- Enablement grants broad target: `*://* GET *`
- Inspection reports:
- manifest target `requested=true granted=false eligible=false`
- broad grant as `grant-only ... eligible=false`
- Runtime still allows `GET https://api.example.test/v1/data`, because URL is covered by both manifest target and broad grant。
The added CLI test appears to codify this inconsistent reporting:
- `crates/yoi/src/plugin_cli.rs:1566-1574`
- expects broad grant display as `grant-only`
- expects requested target as `granted=false eligible=false`
This violates the Ticket acceptance/invariants that inspection distinguish requested/granted/denied/broad request permissions accurately, and that grant-only / requested-but-ungranted cases do not silently diverge from runtime behavior。
Required fix:
- Align static inspection and runtime semantics。
- If broad / covering grants are valid authorization for declared manifest targets, inspection should report the manifest target as covered/granted, while visibly labeling the covering grant as broad。
- If only exact target grants are intended to authorize, runtime should deny non-equal grant coverage before network I/O。
- Apply same reasoning to the inverse shape: broad manifest request plus narrower exact grant can be runtime-allowed for URLs in the intersection while inspection currently reports both sides as ineligible/grant-only。
Non-blocking concern:
- DNS/private-target semantics are now URL-permission based rather than resolved-address-category based。There is an explicit test allowing a declared/granted hostname to resolve to `127.0.0.1` (`crates/pod/src/feature/plugin.rs:4841-4847`)。This may be acceptable under the new model, but it should be documented/reconfirmed because the Ticket says local/private communication must not be ambient。The implementation interprets “explicit” as declared/granted URL host, not necessarily literal `localhost` / private IP grant。
Reviewer validation passed:
- `cargo fmt --check`
- `git diff --check 4cd4a06e..HEAD`
- `cargo test -p manifest request --quiet` (`7 passed`)
- `cargo test -p pod feature::plugin::tests --lib --quiet` (`67 passed`)
- `cargo test -p yoi plugin_cli::tests --quiet` (`18 passed`)
- `cargo check -p manifest -p pod -p yoi --quiet`
- `target/debug/yoi ticket doctor`
- Stale active naming grep under `crates docs resources` for `host_api.https|grants.https|PluginHttps|yoi:host/https|yoi:https`: no matches。
Worktree status:
- Clean on `impl/00001KVMG8FTW-plugin-request-host-api`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T08:04:50Z -->
## Implementation report
Coder r1-fix report received from `yoi-coder-00001KVMG8FTW`.
New fix commit:
- `0e14e7c1 plugin: align request grant inspection coverage`
Branch commits now:
- `962b7699 plugin: replace https host api with request grants`
- `0e14e7c1 plugin: align request grant inspection coverage`
Fix summary:
- `crates/pod/src/feature/plugin.rs`
- Static inspection now uses request target coverage/intersection semantics instead of exact equality。
- Broad/covering grants are reported as granted/eligible when they cover or intersect manifest targets in a way runtime can allow。
- Broad manifest + narrower grant is also reported as eligible with partial-coverage diagnostics。
- Truly grant-only/no-manifest-intersection grants remain ineligible。
- Added focused static inspection tests for exact manifest target + broad grant and broad manifest target + narrower exact grant。
- `crates/yoi/src/plugin_cli.rs`
- Updated CLI/static inspection test expectations to match aligned broad grant semantics。
- `docs/development/plugin-development.md`
- Documented that explicit request authority is URL-host based, and a granted DNS hostname may resolve to loopback/private addresses if that hostname was intentionally declared/granted。
Coder validation reported:
- `cargo fmt --check`: passed
- `git diff --check 4cd4a06e..HEAD`: passed
- `cargo test -p manifest request --quiet`: passed
- `cargo test -p pod feature::plugin::tests --lib --quiet`: passed
- `cargo test -p yoi plugin_cli::tests --quiet`: passed
- `cargo check -p manifest -p pod -p yoi --quiet`: passed
- `target/debug/yoi ticket doctor`: passed
- stale active naming grep under `crates docs resources` for old HTTPS names: no matches
Orchestrator evidence checked:
- Implementation worktree clean on `impl/00001KVMG8FTW-plugin-request-host-api`
- HEAD is `0e14e7c1`
- r1-fix diff `962b7699..HEAD` touches only `crates/pod/src/feature/plugin.rs`, `crates/yoi/src/plugin_cli.rs`, and `docs/development/plugin-development.md`
- Active stale naming grep under `crates docs resources` returned no matches。
- `git diff --check 4cd4a06e..HEAD` produced no diagnostics。
Next action:
- Route back to Reviewer for r2 verification of static inspection/runtime coverage alignment and final acceptance。
---
<!-- event: review author: yoi-reviewer-00001KVMG8FTW-r1 at: 2026-06-21T08:08:04Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- r1-fix diff `962b7699..0e14e7c1`:
- `crates/pod/src/feature/plugin.rs`
- `crates/yoi/src/plugin_cli.rs`
- `docs/development/plugin-development.md`
- Overall changed-file set `4cd4a06e..0e14e7c1`:
- `crates/manifest/src/plugin.rs`
- `crates/pod/src/feature/plugin.rs`
- `crates/pod/src/pod.rs`
- `crates/yoi/src/plugin_cli.rs`
- `docs/design/plugin-component-model.md`
- `docs/development/plugin-development.md`
- `resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit`
- `resources/plugin/wit/yoi-plugin-instance-v1.wit`
- `resources/plugin/wit/yoi-plugin-tool-v1.wit`
Previous blocker verification:
- r1 blocker is resolved。
- Static inspection now evaluates request grant coverage/intersection rather than exact equality。
- Exact manifest target + broad grant is now reported as granted/eligible with broad diagnostics, not `grant-only`
- Broad manifest target + narrower exact grant is now reported as runtime-eligible with partial-coverage diagnostics。
- CLI/static inspection expectations were updated so broad grants are shown as usable grants, not ineligible grant-only。
- DNS/private-target reviewer concern is documented in `docs/development/plugin-development.md`
Blocking issues:
- None。
Non-blocking concerns:
- None requiring changes before merge。
Overall Ticket satisfaction spot-check:
- Active API/docs/WIT naming use `request`; stale active `host_api.https` / `grants.https` / `PluginHttps*` / old WIT names were not found under `crates docs resources`
- No compatibility alias for old HTTPS naming was visible in active code/docs。
- Runtime still requires both manifest `host_api.request` / request target declaration and enablement `host_api.request` / matching request grant。
- Runtime URL checks remain method/scheme/host/port/path based。
- WebSocket URLs, upgrade headers, and SSE/event-stream requests remain rejected。
- Embedded URL credentials and credential-like headers remain rejected。
- Local/private/loopback targets are not ambient; documented authority is URL-host declaration + grant。
Reviewer validation passed:
- `cargo fmt --check`
- `git diff --check 4cd4a06e..HEAD`
- `cargo test -p manifest request --quiet` (`7 passed`)
- `cargo test -p pod feature::plugin::tests --lib --quiet` (`69 passed`)
- `cargo test -p yoi plugin_cli::tests --quiet` (`18 passed`)
- `cargo check -p manifest -p pod -p yoi --quiet`
- `target/debug/yoi ticket doctor` (`doctor: ok`)
- Stale active naming grep under `crates docs resources`: no matches。
Worktree status:
- Clean at HEAD `0e14e7c1` on `impl/00001KVMG8FTW-plugin-request-host-api`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T08:11:43Z -->
## Implementation report
Reviewer r2 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `8a15cca5 merge: plugin request host api`
- Merged branch: `impl/00001KVMG8FTW-plugin-request-host-api`
- Implementation commits:
- `962b7699 plugin: replace https host api with request grants`
- `0e14e7c1 plugin: align request grant inspection coverage`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p manifest request --quiet`: passed (`7 passed`)
- `cargo test -p pod feature::plugin::tests --lib --quiet`: passed (`69 passed`)
- `cargo test -p yoi plugin_cli::tests --quiet`: passed (`18 passed`)
- `cargo check -p manifest -p pod -p yoi --quiet`: passed
- Stale active naming grep: `git grep -n -E 'host_api\.https|grants\.https|PluginHttps|yoi:host/https|yoi:https' -- crates docs resources`: no matches
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Final Orchestrator worktree status after validation: clean on `orchestration` at `8a15cca5`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T08:11:51Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、focused plugin request tests/checks、stale naming grep、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T08:12:06Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T08:12:06Z status: closed -->
## 完了
Plugin host API の one-shot outbound request capability を `host_api.https` / `grants.https` から URL permission based `host_api.request` に置き換え、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Active API / docs / WIT naming を `request` に移行。
- Manifest に `host_api.request``[[request]]` target declaration を追加。
- Enablement grant を request target grant として扱うよう変更。
- Runtime authorization を manifest-declared request target と enabled request grant の両方が URL/method/scheme/host/port/path coverage で許可する場合のみ network I/O に進む形にした。
- Grant-only / missing-grant / broad / partial-coverage states を static inspection と `yoi plugin show` diagnostics で区別。
- Broad/covering grant と broad manifest + narrower grant の intersection semantics を runtime と static inspection で一致させた。
- Loopback/local/private target は ambient ではなく、URL host declaration + grant に基づく明示 authority として扱う方針を docs に記録。
- Embedded credentials、credential-like headers、WebSocket URLs/upgrades、SSE/event-stream requests を reject/unsupported にした。
- Old `host_api.https` / `grants.https` / `PluginHttps*` / old WIT names は active code/docs/resources から削除。
- Focused manifest / pod / yoi plugin CLI tests を追加・更新。
統合・検証:
- Merge commit: `8a15cca5 merge: plugin request host api`
- Implementation commits: `962b7699`, `0e14e7c1`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p manifest request --quiet`, `cargo test -p pod feature::plugin::tests --lib --quiet`, `cargo test -p yoi plugin_cli::tests --quiet`, `cargo check -p manifest -p pod -p yoi --quiet`, stale active naming grep, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Regex URL target matching は追加していない。
- WebSocket/SSE/persistent connection support は `host_api.request` に含めていない。WebSocket は別 capability / design Ticket 側で扱う。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T08:12:34Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVMG8FTW`
- `yoi-reviewer-00001KVMG8FTW-r1`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api`
- Deleted implementation branch:
- `impl/00001KVMG8FTW-plugin-request-host-api`
- Orchestrator worktree remains clean on `orchestration` at `2601bfa9`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-113559-1","ticket_id":"00001KVMGAEJN","kind":"accepted_plan","accepted_plan":{"summary":"Implement separate `host_api.websocket` Plugin capability with manifest WebSocket target declarations, enablement grants, static inspection/CLI diagnostics, host-owned bounded connection handles, runtime allow/deny policy, request API continued WebSocket rejection, docs/WIT/API updates, and focused tests.","branch":"impl/00001KVMGAEJN-plugin-websocket-host-api","worktree":"/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates plugin manifest/runtime/CLI/docs tests and Nix if dependency changes occur, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T11:35:59Z"}
@@ -0,0 +1,13 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KVMGAEJN",
"kind": "depends_on",
"target": "00001KVMG8FTW",
"note": "WebSocket capability design should reuse or deliberately diverge from the URL permission/request-target schema produced by `host_api.request`; current Ticket remains requirements_sync_needed until those design decisions are resolved.",
"author": "yoi-orchestrator",
"at": "2026-06-21T07:17:46Z"
}
]
}
+80 -74
View File
@@ -1,11 +1,13 @@
---
title: 'Plugin: URL 権限ベースの別 capability として WebSocket support を設計する'
state: 'ready'
title: 'Plugin: URL 権限ベースの WebSocket host API を実装する'
state: 'closed'
created_at: '2026-06-21T07:11:34Z'
updated_at: '2026-06-21T07:14:05Z'
updated_at: '2026-06-21T13:27:28Z'
assignee: null
readiness: 'requirements_sync_needed'
readiness: 'implementation_ready'
risk_flags: ['plugin', 'host-api', 'websocket', 'service', 'ingress', 'lifecycle', 'permissions', 'security', 'persistence']
queued_by: 'workspace-panel'
queued_at: '2026-06-21T11:34:07Z'
---
## User claims / request snapshot
@@ -13,124 +15,128 @@ risk_flags: ['plugin', 'host-api', 'websocket', 'service', 'ingress', 'lifecycle
- WebSocket / bidirectional communication は `host_api.request` に混ぜず、別 capability としてサポートする。
- WebSocket も、対象 URL を Plugin 側が権限として要求する前提でよい。
- 任意 URL access は便利だが大きすぎる権限であり、導入時に何が可能になる権限を要求しているかがわかりやすいことを重視する。
- Regex を許す余地はあるが、本来の権限ニーズは permission review の可読性にある
- Service/Plugin instance は状態を持てるため、WebSocket API 自体は「WebSocket を扱う host API」として提供すればよい
- WebSocket 接続後の処理、incoming message の解釈、Ingress 発火、Service 状態更新などは Plugin instance 側が既存 Service/Ingress lifecycle と host-mediated action path を使って組み立てる。
## Confirmed facts / sources
- `docs/development/plugin-development.md` は現行 `https` host API を outbound-only / grant-gated とし、WebSocket/Gateway/inbound HTTP surface ではないと説明している
- Closed Ticket `00001KVFDX9AF` は WebSocket / SSE / timer host APIs, Service surface lifecycle, Ingress surface, Discord Gateway bridge, Inbound HTTP server を non-goals として HTTPS host API を実装した。
- Closed Ticket `00001KVJHYP4Q` は Plugin Service/Ingress component lifecycle surface を実装し、PluginInstance lifecycle と in-process ingress dispatch path の基盤を入れたが、実外部 socket/event source は scope 外だった
- `docs/design/plugin-component-model.md` / `docs/design/plugin-packages.md` は Plugin instance lifecycle、Service/Ingress、future MCP/plugin bridge、external process authority/lifecycle/permission/diagnostics/trust model の必要性に触れている。
- Closed Ticket `00001KVMG8FTW` は one-shot request/response を `host_api.request` に統合し、WebSocket / persistent streaming / bidirectional connection は別 capability とする方針で完了した
- Closed Ticket `00001KVJHYP4Q` は Plugin Service/Ingress component lifecycle surface を実装し、Plugin instance が lifecycle と state を持てる前提を作った。
- `docs/development/plugin-development.md` と Plugin design docs は Tool call の中に long-lived connection を隠さず、Service/Ingress surface に分ける方針を持つ
- 現行 code map では WebSocket 専用 host API / persistent bidirectional Plugin transport はまだ active API として確認できていない。
## Unverified hypotheses
- WebSocket capability は `host_api.websocket` のような host API になるか、Service surface 専用 transport になる可能性がある。
- Incoming messages は PluginInstance / Service / Ingress lifecycle と接続するのが自然だが、connection ownership と dispatch route は設計判断が必要。
- URL permission model は `request` と共通概念にできるが、WebSocket は persistent lifecycle / reconnect / shutdown / inbound events を持つため、grant と runtime management は別 schema になる可能性が高い。
## Undecided points / open questions
- WebSocket connection を Yoi host が所有するのか、Plugin instance が host API を通じて所有するのか。
- Incoming message を Ingress に dispatch するのか、Service event/status stream として扱うのか。
- Reconnect / backoff / heartbeat / shutdown / cancellation / restore 時の扱いをどこまで初回に含めるか。
- WebSocket auth/headers/secrets を URL permission とどう分けて表示・grant するか。
- 初回 work item を design/spec のみで閉じるか、最小実装 slice まで含めるか。
## Background
`host_api.request` は one-shot request/response の authority として設計し、WebSocket / persistent connection / bidirectional event handling を含めない方針になった。一方で、Plugin と外部プロセス・Gateway・bridge service が双方向通信するにはWebSocket 等の persistent transport が必要になる。
`host_api.request` は one-shot request/response の authority として設計し、WebSocket / persistent connection / bidirectional event handling を含めない方針になった。一方で、Plugin と外部プロセス・Gateway・bridge service が双方向通信するには WebSocket 等の persistent transport が必要になる。
この Ticket は、WebSocket を `request` とは別 capability として扱い、URL permission を前提にした権限表示・grant・runtime lifecycle・Service/Ingress 接続を設計するための concrete design/spec work item である。実装に進む場合も、Tool call の中に長時間 connection や background daemon を隠さないことを前提にする。
## Requirements
- WebSocket は `host_api.request` に混ぜず、別 capability / host API / transport として設計する。
- WebSocket も URL permission を前提にし、Plugin package manifest 側が必要な WebSocket URL targets を静的に要求できること。
- Workspace/user enablement grant は、manifest-declared WebSocket URL permission を明示的に承認する model にすること。
- Arbitrary WebSocket URL / broad network access は通常 target grant と区別して「大きい権限」として表示・診断すること。
- Regex を許す場合も、導入時に可能範囲が読める normalized display / warning / label を持つこと。
- Tool call の中に long-lived WebSocket connection や background daemon を隠さないこと。
- Service / Ingress / PluginInstance lifecycle との関係を設計すること。
- Connection ownership, shutdown, cancellation, reconnect/backoff, heartbeat, diagnostics, bounds を設計対象に含めること。
- Incoming messages が history/model context に入る場合は hidden context injection にせず、durable/visible/routable path を通すこと。
- Secrets/credentials/auth headers は ambient env ではなく、explicit config / SecretRef / grant model に乗せること。
- Package discovery / `yoi plugin list/show` は Plugin code 実行、socket connection、external process startup を行わないこと。
## Acceptance criteria
- WebSocket responsibility が `host_api.request` から明確に分離される。
- WebSocket URL permission の manifest declaration と enablement grant の関係が定義される。
- Plugin inspection で WebSocket URL permission 要求と grant 状態が bounded / human-readable に表示される設計になる。
- Arbitrary URL / broad WebSocket access が通常 target grant と区別して表示される。
- Connection ownership と lifecycle boundary が明確になる。
- Incoming messages の dispatch path が Service / Ingress / PluginInstance / host routing のどこに属するか決まる。
- Hidden context injection を避ける durable/visible event path が定義される。
- Cancellation, shutdown, reconnect/backoff, timeout, message size bounds, diagnostics, redaction の方針が定義される。
- Auth/secrets handling が explicit config / SecretRef / grant に限定される。
- 最小実装 slice と non-goals が明確になる。
この Ticket は、WebSocket を `request` とは別`host_api.websocket` capability として追加する実装 work item である。WebSocket は Service/Plugin instance が使う host API であり、Yoi が独自に ingress routing policy を抱え込むものではない。Plugin instance は接続 handle と内部状態を保持し、受信メッセージをどう扱うか、Ingress/action/status にどう変換するかを Plugin の Service/Ingress logic として実装する。
## Binding decisions / invariants
- WebSocket は `host_api.request` に含めない。
- WebSocket authority は URL permission を前提にする。
- Plugin 側が対象 WebSocket URL scope を権限として要求し、user/workspace enablement がそれを承認する二段階 model にする。
- 任意 URL / broad WebSocket access は大きい権限として明示されなければならない
- Long-lived connection を Tool call の中に隠さない
- External incoming messages を hidden context injection しない
- Public/config-facing name は `host_api.websocket`する。
- Plugin package manifest は必要な WebSocket URL targets を静的に要求する
- Workspace/user enablement grant は、manifest-declared WebSocket URL target を明示的に承認する
- WebSocket 接続は Plugin instance / Service lifecycle の中で使う host API resource とする
- Yoi host は permission check、resource bounds、redaction、shutdown/cancellation cleanup を担当する。
- Plugin instance は connection handle を使い、send/receive/close と自身の state/lifecycle を管理する。
- Incoming message は Yoi が自動的に history/model context に注入しない。
- Incoming message の解釈、Ingress 発火、SystemItem/Notify/diagnostic 等への変換は Plugin instance が既存の host-mediated API / action path を使って行う。
- Long-lived connection を Tool call の中に隠さない。Tool は必要なら Service instance に command/query を投げるだけにする。
- Package discovery / static inspection は socket connection や process startup を意味しない。
- External content is untrusted and bounded.
- Broad/arbitrary WebSocket URL access は大きい権限として表示・診断する。
## Requirements
- `host_api.websocket` capability / host API を追加する。
- WebSocket URL permission は `host_api.request` の URL target model と整合させる。
- 少なくとも scheme, host, optional port, path prefix を人間が読める形で表現できること。
- `ws` / `wss` を扱う。HTTP request の method permission とは分ける。
- Plugin manifest 側に WebSocket target permission declaration を追加する。
- Plugin enablement grant 側に WebSocket target grant を追加する。
- Runtime authorization は「manifest で要求された target」かつ「enablement で grant された target」だけを許可する。
- Manifest で要求されていない target への WebSocket 接続は grant だけがあっても fail closed する、または明示 override として安全に診断される。
- WebSocket host API は Plugin instance が保持できる connection handle/resource を返す。
- Host API は最低限の操作を提供する。
- connect/open
- send text/binary
- receive next message with bounds/timeout/cancellation
- close
- status/diagnostic where needed
- Host は message size bounds、timeout/cancellation、shutdown cleanup、diagnostics、redaction を実装する。
- Reconnect/backoff/heartbeat policy は初回 host API の必須機能にしない。
- Plugin Service が state と timer/lifecycle で組み立ててよい。
- Host は failed/closed/cancelled を bounded diagnostic として返す。
- Auth/headers/secrets は ambient env ではなく explicit config / SecretRef / grant model に乗せる。
- 初回で SecretRef header injection が未実装の場合は non-goal として fail closed / future follow-up にする。
- `yoi plugin list/show` / static inspection は WebSocket URL permission 要求と grant 状態を bounded / human-readable に表示する。
- Arbitrary URL / broad WebSocket access は通常 target grant と区別して表示・診断する。
- Docs/templates/tests を `host_api.request` と WebSocket 別 capability 方針に更新する。
## Acceptance criteria
- `host_api.websocket``host_api.request` とは別 capability として定義される。
- Plugin manifest だけを見れば、その Plugin がどの WebSocket URL target 権限を要求しているか分かる。
- Enablement grant が manifest-declared WebSocket target と照合される。
- Grant されていない requested target への WebSocket connect は fail closed する。
- Manifest で要求されていない target への WebSocket connect は fail closed する、または明示 override として安全に診断される。
- `yoi plugin show` 相当の inspection で requested/granted/denied/broad WebSocket permission が bounded / human-readable に表示される。
- Plugin instance / Service lifecycle 内で WebSocket connection handle を保持し、send/receive/close できる。
- Incoming messages は自動で history/model context に入らず、Plugin instance の処理を通る。
- Hidden context injection が導入されていない。
- Tool call の中に long-lived WebSocket connection を隠さない設計・テストになっている。
- Shutdown/cancellation で open connection が cleanup される。
- Message size bounds / timeout / redaction / diagnostics のテストがある。
- Existing `host_api.request` behavior は壊れない。
## Implementation latitude
- 初回は design/spec Ticket として閉じてもよい。
- `host_api.websocket` として設計するか、Service surface 専用 transport として設計するかは比較して決めてよい。
- URL permission expression は `host_api.request` と共通の exact scheme/host/port/path model を流用してもよい
- Regex support は入れても入れなくてもよいが、入れる場合は permission review の可読性を守ること。
- Reconnect/backoff は初回実装 non-goal にしてもよいが、その場合も明示的な failure/diagnostic behavior を定義すること
- Internal type names are implementation latitude, but public/config-facing names should use `websocket`.
- URL permission expression は `host_api.request` と共通の exact scheme/host/port/path model を流用してよい。
- Regex support は入れても入れなくてもよい。入れる場合は permission review の可読性を守ること
- Initial implementation may support only text messages if binary support would expand scope too much, but binary handling must then fail closed and be documented.
- Reconnect/backoff/heartbeat は host API ではなく Plugin Service layer の responsibility としてよい
## Readiness
- readiness: requirements_sync_needed
- readiness: implementation_ready
- risk_flags: [plugin, host-api, websocket, service, ingress, lifecycle, permissions, security, persistence]
## Escalation conditions
- WebSocket を `host_api.request` に混ぜたくなる場合。
- Connection lifecycle が Tool call / Tool result に隠れそうな場合。
- WebSocket runtime が Tool call / Tool result に隠れそうな場合。
- Incoming message が history/context に非永続・非可視に注入されそうな場合。
- URL permission が broad なのに導入時表示で目立たない場合。
- Secret/auth handling が ambient env や raw config leakage に寄る場合。
- Restore / cancellation / shutdown / reconnect 方針が決まらないまま実装に進みそうな場合。
- Host 側が Plugin Service の reconnect/application protocol policy まで抱え込みそうな場合。
## Validation
Design/spec の場合:
- Docs/design update review.
- Existing Plugin Service/Ingress design との整合性確認。
- Ticket body の open questions が resolution / follow-up Ticket に変換されていること。
実装を含める場合:
- Focused WebSocket capability tests.
- Focused WebSocket host API tests.
- Manifest-declared WebSocket URL permission parsing/resolution tests.
- Grant allow/deny tests.
- Requested-but-ungranted and granted-but-unrequested denial tests.
- Broad/arbitrary URL display/diagnostic tests.
- Lifecycle shutdown/cancellation tests.
- Message bounds/redaction diagnostics tests.
- No hidden context injection tests.
- `host_api.request` regression tests.
- Docs/template updates.
- `cargo fmt --check`
- relevant `cargo test`
- `cargo check`
- `git diff --check`
- `nix build .#yoi --no-link`
## Related work
- `00001KVFDX9AF` — Plugin HTTPS host API, closed.
- `00001KVJHYP4Q` — Plugin Service/Ingress component lifecycle surface, closed.
- `00001KSXRQ4G8` — Plugin runtime/surface/host API design record, closed/superseded.
- `00001KVMG8FTW` — Plugin: host_api.https を廃止して URL 権限ベースの host_api.request に統合する
- `00001KVMG8FTW` — Plugin: host_api.https を廃止して URL 権限ベースの host_api.request に統合する, closed.
- `docs/development/plugin-development.md`
- `docs/design/plugin-component-model.md`
- `docs/design/plugin-packages.md`
+28
View File
@@ -0,0 +1,28 @@
URL permission based Plugin WebSocket host API を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `host_api.websocket``host_api.request` とは別 capability として追加。
- Manifest `[[websocket]]` target declaration と enablement `grants.websocket` を追加し、request targets/grants とは独立させた。
- Static inspection / `yoi plugin show` が WebSocket requested/granted/missing/grant-only/broad diagnostics を request diagnostics とは別に表示するようにした。
- Runtime connect は manifest target と enablement grant の両方が URL を許可する場合のみ network I/O に進む。
- URL checks cover scheme (`ws`/`wss`), host, port, and path prefix。
- Local/private/loopback WebSocket targets は ambient ではなく、明示 declaration + grant が必要。
- Host-owned WebSocket handle API を追加: open, send_text / send-text, recv, close。
- Text-only / explicit bounded receive とし、binary receive は fail closed / unsupported。
- Guest arbitrary handshake headers / embedded credentials を reject。
- Request API は WebSocket/SSE/persistent attempts を引き続き reject。
- Open path は pre-dial capacity reservation と bounded async `tokio-tungstenite` open under `tokio::time::timeout` により max-open / timeout semantics を network I/O 前から enforce。
- Reservation cleanup on open failure / failed commit を追加。
- WIT resource `yoi:host/websocket@1.0.0` と docs を更新。
- `tungstenite`, `tokio-tungstenite`, `futures-util` dependencies と `Cargo.lock` / `package.nix` cargo hash を更新。
統合・検証:
- Merge commit: `354f1e10 merge: plugin websocket host api`
- Implementation commits: `4c1b8c3d`, `ce62d235`, `a766048f`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p pod websocket`, `cargo test -p manifest websocket`, `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`, `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`, `cargo check -p manifest -p pod -p yoi`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Discord bridge 本体は実装していない。
- Reconnect/backoff/heartbeat scheduler、hidden context/history injection、Dashboard channel、Ticket mutation、direct model Tool invocation は追加していない。
- SecretRef-based credential injection は future follow-up。
+590
View File
@@ -21,3 +21,593 @@ LocalTicketBackend によって作成されました。
ユーザーから「readyにして」と明示されたため `planning` から `ready` へ遷移する。未決定点は残っているため、後続 Orchestrator routing では requirements/design sync として扱う。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T07:15:42Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T07:17:40Z -->
## Decision
Routing decision: `return_to_planning_requirements_sync`
Reason:
- Ticket frontmatter has `readiness: requirements_sync_needed`
- Intake summary explicitly says this should be handled as WebSocket capability design/spec sync, not implementation-direct routing。
- Ticket body still lists concrete open questions that must be resolved before implementation or worktree side effects:
- WebSocket connection ownership: Yoi host-owned vs Plugin-instance-owned host API。
- Incoming message dispatch route: Ingress vs Service event/status stream vs other host routing。
- Reconnect / backoff / heartbeat / shutdown / cancellation / restore scope for first slice。
- Auth/headers/secrets model and grant/display split。
- Whether this work item closes as design/spec only or includes a minimal implementation slice。
- Related Ticket `00001KVMG8FTW` is now routed for implementation of the `host_api.request` URL permission model. WebSocket design should reuse or intentionally diverge from that resulting URL permission schema after it stabilizes。
Decision:
- Do not create implementation worktree or spawn Coder/Reviewer for this Ticket now。
- Return to `planning` with concrete missing requirements/design decisions。
- Record relation to `00001KVMG8FTW` so WebSocket design can be resumed after request permission model lands。
Required next planning output before queueing again:
- Decide whether this is design/spec only or includes a minimal implementation slice。
- Decide connection ownership and lifecycle boundary。
- Decide incoming-message durable/visible dispatch path and no-hidden-context behavior。
- Decide WebSocket URL permission/grant schema relative to `host_api.request` request-target schema。
- Decide auth/secrets display/grant model and non-goals for reconnect/backoff/heartbeat in first slice。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T07:17:52Z from: queued to: planning reason: requirements_sync_needed_connection_lifecycle_and_scope_decisions field: state -->
## State changed
Ticket remains `requirements_sync_needed` and has unresolved design questions around connection ownership, incoming-message dispatch path, lifecycle bounds, auth/secrets handling, and design-vs-implementation scope. Returning to planning rather than starting implementation side effects.
---
<!-- event: intake_summary author: hare at: 2026-06-21T11:01:20Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T11:01:20Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T11:34:07Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T11:35:44Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket was previously returned to planning because it needed concrete WebSocket connection ownership / lifecycle / permission model decisions。
- Current Ticket body is now retitled and refined as implementation work: `Plugin: URL 権限ベースの WebSocket host API を実装する`
- It defines explicit `host_api.websocket` semantics, URL permission/grant model, lifecycle/bounds/non-goals, acceptance criteria, tests, docs, and validation。
- Recorded dependency `00001KVMGAEJN depends_on 00001KVMG8FTW` is now satisfied because `00001KVMG8FTW` is `closed` and `host_api.request` URL permission model is integrated。
- Relations / orchestration plan have no remaining blockers。
- Active `00001KVMT2J25` work is protocol/pod/TUI reconnect snapshot and is semantically separate from Plugin WebSocket host API; parallel implementation is acceptable。
- Orchestrator worktree is clean on `orchestration` at `d8027781` before routing side effects; target worktree / branch is not present。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct `item.md` read。
- `TicketRelationQuery(00001KVMGAEJN)`: one `depends_on 00001KVMG8FTW`, target Ticket is `closed`
- `TicketOrchestrationPlanQuery(00001KVMGAEJN)`: no records。
- `TicketList(state=queued)`: this Ticket is the only queued Ticket。
- `ListPods`: only active child for other work is `yoi-reviewer-00001KVMT2J25-r1`
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `crates/manifest/src/plugin.rs` now has `host_api.request`, `PluginRequestGrant`, and manifest request target schema。
- `crates/pod/src/feature/plugin.rs` has `PluginRequestClient`, `validate_plugin_request_request`, request allowlist inspection, and explicit WebSocket rejection in request path。
- No existing tungstenite/tokio-tungstenite/websocket dependency found in Cargo manifests。
- Docs currently state WebSocket/persistent transports require a separate Plugin capability。
IntentPacket:
Intent:
- Add a separate URL-permission-based Plugin WebSocket host API, not an extension of `host_api.request`, suitable as a foundation for Discord/gateway-like integrations without implementing Discord itself。
Binding decisions / invariants:
- API name is `host_api.websocket`; do not fold WebSocket into `host_api.request`
- URL permission model should mirror/reuse the `host_api.request` target/grant review semantics where sensible, while keeping websocket-specific lifecycle/bounds explicit。
- Authority requires both manifest-declared WebSocket target and enablement grant before opening a connection。
- WebSocket connection is host-owned and Plugin-driven: guest requests open/send/recv/close via host API, but host enforces handles, bounds, timeouts, and shutdown cleanup。
- No ambient network/socket access, no raw WASI sockets, no arbitrary URL by default。
- Secrets/auth headers are not solved by guest-memory arbitrary credential headers; keep credential-bearing header policy conservative and explicit。
- Incoming messages from WebSocket are delivered to the guest through explicit host API return values or bounded polling/receive operations, not hidden model context injection。
- No direct model Tool calls, Ticket mutation, Dashboard UI channel, or hidden history/context mutation。
- `host_api.request` must keep rejecting WebSocket/SSE/persistent connection attempts。
- First slice should avoid full background daemon scheduler unless it is minimal and bounded; preserve instance lifecycle cleanup。
Requirements / acceptance criteria:
- Manifest can declare WebSocket targets independently from request targets。
- Enablement config can grant WebSocket targets independently from request grants。
- Static inspection / `yoi plugin show` reports WebSocket requested/granted/missing/broad diagnostics separately from request。
- Runtime refuses connect unless manifest target and grant both allow the URL。
- URL checks cover scheme (`ws`/`wss`), host, port, path prefix, and any method/protocol constraints chosen for handshake。
- Local/private/loopback WebSocket targets require explicit declaration+grant。
- WebSocket API has bounded handle lifetime, max frame/message size, max open connections per Plugin instance, timeout/cancellation behavior, and cleanup on instance stop/trap/drop。
- Send/receive operations are bounded and typed; binary/text behavior is documented。
- Credential-like headers are rejected or explicitly not supported until SecretRef/grants exist。
- Tests cover allow/deny, grant-only/missing-grant, loopback allow/deny, broad diagnostics, request API still rejecting WebSocket, bounds/cleanup, and no hidden context mutation。
Implementation latitude:
- Rust dependency choice is Coders decision, e.g. `tokio-tungstenite` if suitable, but dependency/package/Nix implications must be handled。
- WIT/API shape can be handle-based with `open`, `send_text`/`send_binary`, `recv`, `close`, or similar. Keep it minimal and reviewable。
- If a fully live network integration test is hard, use local test server / mock client abstraction to validate runtime policy and handle lifecycle。
- Reuse request target/grant matching helpers where appropriate, but avoid overgeneralizing if it obscures WebSocket semantics。
Escalate if:
- Implementing safe host-owned connection handles requires a broader Plugin service/instance actor redesign than current runtime supports。
- SecretRef/auth header requirements become necessary for useful functionality。
- Background receive delivery requires hidden context/history mutation or direct model Tool invocation。
- Cargo/Nix dependency updates become blocked by unavailable crates or source filtering。
- Public API compatibility for new WIT world/import names becomes unclear。
Validation plan:
- `cargo fmt --check`
- Focused manifest tests for websocket permission/target/grant parsing and independence from request。
- Focused pod plugin tests for connection allow/deny policy, loopback explicit grants, grant-only/missing-grant, bounds, handle cleanup, and request API rejection of WebSocket。
- Focused yoi plugin CLI tests for WebSocket diagnostics。
- `cargo check` for affected crates。
- `git diff --check`
- stale/boundary grep to ensure request docs still reject WebSocket and WebSocket docs do not claim hidden event injection。
- `yoi ticket doctor`
- `nix build .#yoi --no-link` if dependencies/package/source-filter changed。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T11:35:51Z from: queued to: inprogress reason: human_authorized_dependency_satisfied_websocket_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Previously recorded dependency on `00001KVMG8FTW` is now satisfied because `host_api.request` is closed/integrated, and this Ticket now has implementation-ready WebSocket host API requirements. Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:37:01Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api`
- Created branch:
- `impl/00001KVMGAEJN-plugin-websocket-host-api`
- Base commit:
- `3eac7f8e ticket: accept plugin websocket host api`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVMGAEJN`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api`
Parallelization note:
- `00001KVMT2J25` remains active in review and targets protocol/pod/TUI reconnect snapshot semantics. This Ticket should stay limited to Plugin WebSocket host API / manifest / runtime / CLI / docs / tests。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T12:20:55Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVMGAEJN`.
Implementation commit reported:
- `4c1b8c3d feat: add plugin websocket host api`
Changed areas reported:
- Manifest/config schema:
- Added independent `host_api.websocket` capability。
- Added manifest `[[websocket]]` targets and enablement `grants.websocket`
- Runtime:
- Added host-owned WebSocket handle lifecycle for raw Wasm and component imports。
- Added `open`, `send_text` / `send-text`, `recv`, and `close`
- Enforces manifest+grant URL allowlist before network I/O。
- Bounds open descriptor size, text/message size, max open connections, recv timeout, handle lifetime, and cleanup。
- Rejects embedded credentials, guest handshake headers, unsupported subprotocols, non-`ws`/`wss` schemes, and binary message receive。
- Static inspection / CLI:
- Reports WebSocket requested/granted/missing/grant-only/broad diagnostics separately from request diagnostics。
- `yoi plugin show` now includes `configured_websocket_grants`
- Docs/WIT:
- Added `yoi:host/websocket@1.0.0` WIT interface。
- Documented text-only API, explicit bounded receive, no hidden context/history injection, and future SecretRef credential follow-up。
- Dependency/package:
- Added `tungstenite` to `crates/pod`
- Updated `Cargo.lock`
- Updated `package.nix` cargo hash to `sha256-TZrw6nJclXVRpFIUlYvimGTDXlxBMaQt6oM5C5DIGIU=`
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p manifest websocket`: passed
- `cargo test -p pod websocket`: passed
- `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`: passed
- `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `git diff --check`: passed
- stale/boundary grep for request/WebSocket docs and hidden context claims: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
Nix status reported:
- First `nix build .#yoi --no-link` exposed expected cargo hash mismatch; Coder updated `package.nix`
- After hash update, build advanced into dependency compilation then failed in sandbox compiling `aws-lc-sys` with `No space left on device`
- Coder treated this as environmental disk-space failure, not Rust/package hash failure。
Orchestrator evidence checked:
- Worktree clean at `4c1b8c3d`
- Diff `3eac7f8e..HEAD` includes expected code/docs/package areas but also includes child worktree edits to `.yoi/tickets/00001KVMGAEJN/{item.md,thread.md}`
- Because Orchestrator owns durable Ticket records in this workflow, Coder was asked to remove those `.yoi/tickets` edits from the implementation branch before Reviewer routing。
Next action:
- Wait for Coder hygiene fix, then route code-only implementation diff to Reviewer。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T12:32:21Z -->
## Implementation report
Coder hygiene fix received from `yoi-coder-00001KVMGAEJN`.
New commit:
- `ce62d235 chore: keep plugin websocket branch code-only`
Result:
- Implementation branch now contains code/docs/package changes only; child-worktree Ticket record edits were removed from the branch diff。
- `git diff --name-status 3eac7f8e..HEAD -- .yoi/tickets/00001KVMGAEJN`: no output。
- Worktree clean at `ce62d235`
- Diff `3eac7f8e..HEAD` now touches 11 expected files: Cargo/package, manifest/pod/yoi plugin CLI, docs, and WIT resources。
- `git diff --check 3eac7f8e..HEAD`: passed。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T12:33:03Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVMGAEJN-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api`
- Branch: `impl/00001KVMGAEJN-plugin-websocket-host-api`
- Baseline: `3eac7f8e`
- Implementation commits:
- `4c1b8c3d feat: add plugin websocket host api`
- `ce62d235 chore: keep plugin websocket branch code-only`
- Diff: `3eac7f8e..ce62d235`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- `host_api.websocket` remains distinct from `host_api.request`
- Manifest target + enablement grant are both required before opening a connection。
- Host-owned WebSocket handle lifecycle is bounded and cleaned up。
- Credential/header, binary/text, local/private/loopback, broad diagnostics, and no-hidden-context semantics are safe。
- Request API still rejects WebSocket/SSE/persistent attempts。
- Cargo/package/Nix changes are sound; Coder reported Nix advanced past hash check then failed due `No space left on device` in `aws-lc-sys` build。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVMGAEJN-r1 at: 2026-06-21T12:43:06Z status: request_changes -->
## Review: request changes
Verdict: `request_changes`
確認範囲:
- Diff `3eac7f8e..ce62d235` in worktree `/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api`:
- `Cargo.lock`
- `crates/manifest/src/plugin.rs`
- `crates/pod/Cargo.toml`
- `crates/pod/src/feature/plugin.rs`
- `crates/pod/src/pod.rs`
- `crates/yoi/src/plugin_cli.rs`
- `docs/development/plugin-development.md`
- `package.nix`
- `resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit`
- `resources/plugin/wit/yoi-plugin-instance-v1.wit`
- `resources/plugin/wit/yoi-plugin-tool-v1.wit`
- Ticket authority:
- `.yoi/tickets/00001KVMGAEJN/item.md`
- `.yoi/tickets/00001KVMGAEJN/thread.md`
Blocking issue:
1. WebSocket open が実際には bounded / cancellable ではなく、open-connection limit も network I/O 後にしか適用されていない。
Evidence:
- `crates/pod/src/feature/plugin.rs:922-931`
- `execute_plugin_websocket_open` は URL/grant validation 後に `client.open(...)` を呼び、その後で handle table に insert している。
- `crates/pod/src/feature/plugin.rs:2536-2558`
- `TungstenitePluginWebSocketClient::open` は最初に `tungstenite::client::connect_with_config(...)` を呼ぶ。
- `set_system_websocket_timeouts(...)` は connection established 後にしか呼ばれない。
- `crates/pod/src/feature/plugin.rs:2687-2698`
- `PLUGIN_WEBSOCKET_MAX_OPEN_CONNECTIONS``PluginWebSocketHandleTable::insert` 内で check されるため、`client.open(...)` 完了後、つまり network I/O 後にしか適用されない。
Implications:
- DNS/TCP/TLS/WebSocket handshake が Yoi の WebSocket timeout 適用前に OS/library behavior に従って block し得る。
- `PLUGIN_WASM_TIMEOUT` wrapper は plugin Tool execution に timeout を返すが、spawned blocking task の open 自体は cancel しないため background で継続し得る。
- handle table が満杯でも、新しい outbound WebSocket connection を開いた後で reject するため、max open connections の resource-bound intent を破り、意図しない network side effect が発生し得る。
Why this blocks:
- Ticket は WebSocket API に bounded handle lifetime、max open connections、timeout/cancellation behavior、cleanup を要求している。
- capacity / timeout / cancellation の enforcement が network I/O 前に fail closed していないため、この acceptance criteria を満たしていない。
Required fix:
- Network I/O 前に capacity を reserve/check する。
- Open path を bounded/cancellable にする、または bound を保証できない場合は dialing 前に fail closed する。
- Timeout/cancellation/resource-bound semantics を tests で固定する。
Non-blocking concerns:
- WebSocket host API は component/tool WIT surface に追加され、raw helper path tests はあるが、「long-lived WebSocket connection を Tool call 内に隠さず Plugin instance/Service lifecycle として扱う」という Ticket invariant を pin する integration test/diagnostic は見当たらなかった。現行 Plugin instance が Tool/Service state を共有するなら許容可能だが、lifecycle boundary の regression test/diagnostic があるとより明確。
- `close_all` / drop cleanup と component `stop` cleanup はあるが、active blocking host calls は blocking operation が戻るまで handle-table mutex を保持し得る。これは open timeout/cancellation blocker の副次的問題。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 3eac7f8e..HEAD`: passed
- `cargo test -p manifest websocket`: passed
- `cargo test -p pod websocket`: passed, 6 focused pod WebSocket tests
- `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`: passed
- `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed; reviewer did not reproduce earlier disk-space failure。
- Boundary/stale grep over docs/resources/manifest/pod/yoi CLI for `host_api.request`, `host_api.websocket`, WebSocket/SSE, hidden context/history, Dashboard/Ticket/Discord/reconnect terms found no hidden context injection, Ticket mutation, Dashboard channel, reconnect daemon, or Discord-specific overreach in inspected changes。
Worktree status:
- Clean on `impl/00001KVMGAEJN-plugin-websocket-host-api`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T13:16:05Z -->
## Implementation report
Coder r1-fix report received from `yoi-coder-00001KVMGAEJN`.
New fix commit:
- `a766048f fix: bound plugin websocket open`
Branch commits now:
- `4c1b8c3d feat: add plugin websocket host api`
- `ce62d235 chore: keep plugin websocket branch code-only`
- `a766048f fix: bound plugin websocket open`
Fix summary:
- `crates/pod/src/feature/plugin.rs`
- Added pre-dial WebSocket capacity reservation / permit flow。
- Max-open-connections now fails before invoking network client/open path。
- Reservation is released on open failure。
- Replaced sync `tungstenite` open path with bounded async `tokio-tungstenite` open under `tokio::time::timeout`
- Added deterministic fail-closed abstraction for clients that cannot guarantee bounded/cancellable open。
- Added focused tests for max-open pre-dial rejection, open failure reservation cleanup, and unbounded open client fail-closed before dialing。
- `crates/pod/Cargo.toml` / `Cargo.lock`
- Added `tokio-tungstenite` and `futures-util`
- `package.nix`
- Updated `cargoHash` to `sha256-cZxkmM42kbDp1Rv9gn4sCD5WIQLc0wCbjj4GbKjuA9Q=`
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p pod websocket`: passed
- `cargo test -p manifest websocket`: passed
- `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`: passed
- `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `git diff --check 3eac7f8e..HEAD`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVMGAEJN-plugin-websocket-host-api` at `a766048f`
- r1-fix diff `ce62d235..HEAD` touches only `Cargo.lock`, `crates/pod/Cargo.toml`, `crates/pod/src/feature/plugin.rs`, and `package.nix`
- `git diff --name-status 3eac7f8e..HEAD -- .yoi/tickets/00001KVMGAEJN`: no output。
- `git diff --check 3eac7f8e..HEAD`: passed。
Next action:
- Route back to Reviewer for r2 verification of WebSocket open capacity/timeout/cancellation bounds and final acceptance。
---
<!-- event: review author: yoi-reviewer-00001KVMGAEJN-r1 at: 2026-06-21T13:20:53Z status: approve -->
## Review: approve
Verdict: `approve`
r1-fix diff inspected:
- Reviewed `ce62d235..a766048f`:
- `Cargo.lock`
- `crates/pod/Cargo.toml`
- `crates/pod/src/feature/plugin.rs`
- `package.nix`
- Also re-checked overall implementation diff `3eac7f8e..a766048f` against Ticket authority and previous r1 blocker。
Previous blocker verification:
- Resolved。
Evidence in `crates/pod/src/feature/plugin.rs`:
- `execute_plugin_websocket_open` now:
- validates URL / manifest / grant before dialing。
- fails closed if selected client cannot guarantee bounded open。
- reserves WebSocket capacity before `client.open(...)`
- commits reservation only after successful open。
- `PluginWebSocketHandles` / `PluginWebSocketHandleTable` now track reserved slots separately from active handles, so `PLUGIN_WEBSOCKET_MAX_OPEN_CONNECTIONS` rejects before network I/O。
- Reservation cleanup is RAII-style:
- failed open drops the reservation。
- failed commit also drops/releases reservation。
- `TungstenitePluginWebSocketClient` now uses `tokio-tungstenite` async connect under `tokio::time::timeout(...)`, replacing previous synchronous `tungstenite::client::connect_with_config(...)` path。
- Focused tests cover:
- max-open rejecting before network open。
- open failure releasing reservation。
- unbounded clients failing closed before dialing。
Overall Ticket fit:
- `host_api.websocket` remains separate from `host_api.request`
- Manifest `[[websocket]]` targets and `grants.websocket` remain independent from request targets/grants。
- Runtime connect requires both manifest target and grant before network I/O。
- URL matching covers scheme, host, port, and path prefix。
- WebSocket API is text-only, explicit receive only, and does not inject incoming messages into hidden context/history。
- Guest arbitrary handshake headers / embedded credentials remain rejected。
- Request API continues to reject WebSocket/SSE/persistent request attempts。
- Static inspection / `yoi plugin show` diagnostics distinguish request and WebSocket grant/target states。
- No Ticket mutation, Dashboard channel, scheduler/reconnect daemon, direct model Tool call, or Discord-specific overreach found in reviewed branch。
Blocking issues:
- None。
Non-blocking concerns:
- None requiring changes。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 3eac7f8e..HEAD`: passed
- `cargo test -p pod websocket`: passed
- `cargo test -p manifest websocket`: passed
- `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`: passed
- `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed; disk-space failure did not reproduce。
Worktree status:
- Clean on `impl/00001KVMGAEJN-plugin-websocket-host-api` at `a766048f`
- Branch diff no longer includes `.yoi/tickets/00001KVMGAEJN/*`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T13:26:05Z -->
## Implementation report
Reviewer r2 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `354f1e10 merge: plugin websocket host api`
- Merged branch: `impl/00001KVMGAEJN-plugin-websocket-host-api`
- Implementation commits:
- `4c1b8c3d feat: add plugin websocket host api`
- `ce62d235 chore: keep plugin websocket branch code-only`
- `a766048f fix: bound plugin websocket open`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p pod websocket`: passed
- `cargo test -p manifest websocket`: passed
- `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`: passed
- `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`: passed
- `cargo check -p manifest -p pod -p yoi`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Final Orchestrator worktree status after validation: clean on `orchestration` at `354f1e10`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T13:26:12Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、focused manifest/pod/yoi plugin tests、cargo check、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T13:26:27Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T13:26:27Z status: closed -->
## 完了
URL permission based Plugin WebSocket host API を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `host_api.websocket``host_api.request` とは別 capability として追加。
- Manifest `[[websocket]]` target declaration と enablement `grants.websocket` を追加し、request targets/grants とは独立させた。
- Static inspection / `yoi plugin show` が WebSocket requested/granted/missing/grant-only/broad diagnostics を request diagnostics とは別に表示するようにした。
- Runtime connect は manifest target と enablement grant の両方が URL を許可する場合のみ network I/O に進む。
- URL checks cover scheme (`ws`/`wss`), host, port, and path prefix。
- Local/private/loopback WebSocket targets は ambient ではなく、明示 declaration + grant が必要。
- Host-owned WebSocket handle API を追加: open, send_text / send-text, recv, close。
- Text-only / explicit bounded receive とし、binary receive は fail closed / unsupported。
- Guest arbitrary handshake headers / embedded credentials を reject。
- Request API は WebSocket/SSE/persistent attempts を引き続き reject。
- Open path は pre-dial capacity reservation と bounded async `tokio-tungstenite` open under `tokio::time::timeout` により max-open / timeout semantics を network I/O 前から enforce。
- Reservation cleanup on open failure / failed commit を追加。
- WIT resource `yoi:host/websocket@1.0.0` と docs を更新。
- `tungstenite`, `tokio-tungstenite`, `futures-util` dependencies と `Cargo.lock` / `package.nix` cargo hash を更新。
統合・検証:
- Merge commit: `354f1e10 merge: plugin websocket host api`
- Implementation commits: `4c1b8c3d`, `ce62d235`, `a766048f`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p pod websocket`, `cargo test -p manifest websocket`, `cargo test -p yoi render_show_distinguishes_request_grant_statuses_and_broad_targets`, `cargo test -p manifest request_host_api_manifest_and_grant_parse_with_request_names`, `cargo check -p manifest -p pod -p yoi`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Discord bridge 本体は実装していない。
- Reconnect/backoff/heartbeat scheduler、hidden context/history injection、Dashboard channel、Ticket mutation、direct model Tool invocation は追加していない。
- SecretRef-based credential injection は future follow-up。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T13:27:28Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVMGAEJN`
- `yoi-reviewer-00001KVMGAEJN-r1`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMGAEJN-plugin-websocket-host-api`
- Deleted implementation branch:
- `impl/00001KVMGAEJN-plugin-websocket-host-api`
- Orchestrator worktree remains clean on `orchestration` at `e8103477`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-105843-1","ticket_id":"00001KVMT2J25","kind":"accepted_plan","accepted_plan":{"summary":"Implement protocol/pod/TUI support for connect-time snapshot of in-flight assistant text, thinking, and tool-call args so late attach/reconnect displays unfinished blocks and continues live deltas without gaps or duplicates.","branch":"impl/00001KVMT2J25-inflight-snapshot","worktree":"/home/hare/Projects/yoi/.worktree/00001KVMT2J25-inflight-snapshot","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates protocol/pod/TUI tests, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T10:58:43Z"}
+120
View File
@@ -0,0 +1,120 @@
---
title: 'Pod protocol: in-flight LLM response reconnect snapshot should include unfinished blocks'
state: 'closed'
created_at: '2026-06-21T10:02:01Z'
updated_at: '2026-06-21T12:00:31Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['protocol', 'session-history', 'persistence', 'tui-reconnect', 'stream-state']
queued_by: 'workspace-panel'
queued_at: '2026-06-21T10:56:32Z'
---
## User claims / request snapshot
- プロトコル実装の問題として、LLM 応答中に接続すると、まだ完了していない block の途中内容が欠落する。
- 応答完了後に接続し直すと見える。
- 対象 workspace は `yoi`。Panel handoff の orchestrator Pod は `yoi-orchestrator`
## Confirmed facts / sources
- 既存 Ticket 確認:
- active duplicate は見当たらない。
- `00001KSVP63K8` は in-flight TUI composer injection で、実行中 turn への入力注入の設計 Ticket。今回の「途中出力の late attach / reconnect 表示欠落」とは別件。
- `crates/protocol/src/lib.rs`
- `Event::Snapshot` は接続開始時に一度送られ、`entries` は subscribe 時点の session-log mirror。
- コメント上、Snapshot 後の live 更新は `TextDelta` / `ToolCall*` / `ToolResult` 等で流れ、generic な committed entry broadcast はない。
- `crates/pod/src/segment_log_sink.rs`
- `SegmentLogSink::subscribe_with_snapshot()` は committed `LogEntry` の prefix と live receiver を gap-free に分ける設計。
- `AssistantItem` / `ToolResult` などは mirror には反映されるが live broadcast されず、live 表示は streaming events に依存する。
- `crates/pod/src/controller.rs`
- text / thinking / tool-call args の途中 delta は `Event::TextDelta` / `ThinkingDelta` / `ToolCallArgsDelta` として direct broadcast される。
- `crates/tui/src/app.rs`
- Snapshot は `restore_snapshot(&entries, greeting)` で session-log entries から復元される。
- live delta は TUI 側で block に追記される。
- 以上から、コード上も「接続前に流れたがまだ committed history になっていない途中 delta」を late subscriber が復元する lane が見当たらない。
## Unverified hypotheses
- 実際の欠落原因は、未完了 block の accumulator が `Event::Snapshot` に含まれず、live subscriber は subscribe 後の delta しか受け取れないことだと思われる。
- 応答完了後に再接続すると見えるのは、finalized assistant/tool history が session log mirror に committed され、Snapshot entries から復元できるためだと思われる。
- 修正は、protocol-level に in-flight block state を snapshot へ含める、または bounded replay/sequence 付き live event buffer を導入する形が自然そう。
## Undecided points / open questions
- blocking な未決定点はなし。
- 実装戦術として、`Event::Snapshot` に structured `in_flight` state を追加するか、sequence 付き replay buffer を使うかは Coder がコード調査して選んでよい。
- protocol crate の wire shape 変更なので、既存 serde roundtrip / older snapshot fallback をどこまで持つかは実装時に最小限で判断する。不要な後方互換は作らない。
## Background
LLM の応答中に Console / TUI / attach client が接続した場合、ユーザーはその時点までに出ている assistant text、thinking、tool-call args などの unfinished block を見られる必要がある。現在の構造では、接続時 Snapshot は committed session-log entries だけを seed し、途中 delta は live broadcast のみなので、接続前に流れた unfinished delta が見えない可能性がある。
## Requirements
- LLM 応答中に新しく接続・再接続した client が、接続時点までに蓄積済みの unfinished block 内容を表示できるようにする。
- 対象 block は少なくとも以下を含む:
- assistant text streaming block
- thinking/reasoning streaming block
- tool-call arguments streaming block
- Snapshot と Snapshot 後の live events の境界で、欠落も重複も起こさない。
- 応答完了後の reconnect では、従来通り finalized session-log から完全な表示を復元できること。
- protocol-level の整合性として直す。TUI だけの偶然の workaround にしない。
- 未完了 model output を、finalized assistant history として誤って永続化しない。
- prompt/history/context に hidden injection しない。
## Acceptance criteria
- LLM 応答中に client が接続した場合、接続前に生成済みの unfinished text / thinking / tool-call args が表示される。
- 接続後に続く delta は同じ block に継続して追記され、途中内容の欠落・二重表示がない。
- Run 完了後に接続し直しても、finalized transcript は従来通り Snapshot entries から復元される。
- Snapshot/live 境界の gap-free / duplicate-free 性をテストで確認する。
- TUI の `Event::Snapshot` 処理と live delta 処理の regression がない。
- focused validation として、少なくとも protocol/pod/TUI の関連 test または unit test が追加・更新される。
## Binding decisions / invariants
- 「応答完了後に接続し直せば見える」は workaround であり、正しい完了条件ではない。
- Late attach は、実行中 Pod の現在表示可能な stream state を復元できるべき。
- Committed session-log の gap-free semantics は壊さない。
- Unfinished block は finalized assistant history と混同しない。
- Provider stream 自体を巻き戻したり mutate したりしない。
- Hidden context/history injection はしない。
## Implementation latitude
- `Event::Snapshot` に in-flight block state を追加する案、または bounded/sequence 付き stream replay buffer を導入する案のどちらでもよい。
- Controller / Pod 側で text/thinking/tool-call args の current accumulator を保持する設計にしてよい。
- TUI 側は Snapshot から unfinished block を seed し、その後の live delta を同一 block に継続適用できればよい。
- wire compatibility は必要最小限。長期保守・型安全性を優先する。
## Readiness
- readiness: implementation_ready
- risk_flags: [protocol, session-history, persistence, tui-reconnect, stream-state]
## Escalation conditions
- unfinished output をどの durable history item として永続化するかの設計変更が必要になった場合。
- Snapshot に含める in-flight state が大きくなり、boundedness / memory usage / truncation policy が必要になった場合。
- protocol public surface として互換方針を決める必要が出た場合。
- TUI だけではなく Dashboard / Pod list preview など複数 surface の UX 方針に広がる場合。
## Validation
- `cargo test -p protocol` の relevant roundtrip / serialization tests。
- `cargo test -p pod` の subscriber/snapshot/live-stream focused tests。
- `cargo test -p tui` または targeted app snapshot/live delta tests。
- `cargo fmt --check`
- 必要なら `cargo check -p pod -p tui -p protocol`
## Related work
- Related but not duplicate:
- `00001KSVP63K8` — Support immediate in-flight TUI composer injection
- Relevant files:
- `crates/protocol/src/lib.rs`
- `crates/pod/src/segment_log_sink.rs`
- `crates/pod/src/controller.rs`
- `crates/pod/src/pod.rs`
- `crates/tui/src/app.rs`
+20
View File
@@ -0,0 +1,20 @@
In-flight LLM response 中の reconnect / late attach snapshot に unfinished blocks を含める protocol/pod/TUI 実装を統合した。
主な成果:
- `Event::Snapshot` に typed `InFlightSnapshot` / `InFlightBlock` を追加。
- Pod 側に assistant text / thinking / tool-call args の in-flight accumulator を追加。
- Streaming callbacks が accumulator 更新と live delta broadcast を同じ stream path で行うようにした。
- Connect-time snapshot が in-flight stream state を含むようにした。
- Session-log mirror snapshot と in-flight snapshot、および finalized `AssistantItem` publish/clear の critical section を揃え、mirror-only assistant commit が snapshot/live boundary で消える race を防止した。
- Finalized assistant item が committed snapshot に含まれる場合は matching in-flight state を clear して duplicate を防ぐ。
- TUI snapshot restore が unfinished text/thinking/tool-call args blocks を seed し、後続 live deltas が同じ logical block に continuation されるようにした。
- Serialization/default compatibility、snapshot/live no-gap/no-duplicate、TUI continuation の focused regression tests を追加。
統合・検証:
- Merge commit: `b21638f5 merge: inflight reconnect snapshot`
- Implementation commits: `74aca6f6`, `061136d7`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --all --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p protocol`, `cargo test -p pod --lib in_flight`, `cargo test -p pod session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`, `cargo test -p pod committed_assistant_snapshot_does_not_duplicate_in_flight_block`, `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`, `cargo test -p tui`, `cargo check -p protocol -p pod -p tui`, and `cargo run -p yoi -- ticket doctor`
既知の無関係事項:
- Full `cargo test -p pod` は既存の prompt-resource assertion 2 件で失敗することが reviewer により確認済み。この Ticket の差分とは無関係。
+583
View File
@@ -0,0 +1,583 @@
<!-- event: create author: LocalTicketBackend at: 2026-06-21T10:02:01Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T10:07:42Z from: ready to: planning reason: panel_return_to_planning field: state -->
## State changed
Panel returned ready Ticket 00001KVMT2J25 to planning for requirements sync. This is not Queue routing and must not start implementation.
## User refinement instruction
今あるフロントSPAをnodeからdenoにしたい。
https://hareworks.net/blog/tech/sveltekit-with-deno
---
<!-- event: comment author: ticket-intake at: 2026-06-21T10:09:52Z -->
## Comment
## Intake requirements sync result
対象 Ticket `00001KVMT2J25` の item/thread/artifacts と関連 Ticket/source を確認した結果、今回の refinement instruction はこの Ticket の既存スコープとは一致しないため、`00001KVMT2J25` を ready に戻したり queue routing したりせず、requirements sync の結果としてここに記録する。
### User claims / request snapshot
- ユーザーは「今あるフロントSPAを node から deno にしたい」と述べた。
- 参考 URL として `https://hareworks.net/blog/tech/sveltekit-with-deno` が提示された。
### Confirmed facts / sources
- `00001KVMT2J25` の item は「Attach mid-stream TUI client without losing in-flight content」で、protocol / pod / TUI reconnect / stream-state の実装 Ticket である。
- `00001KVMT2J25` の thread には、Panel が ready から planning に戻した理由として上記 frontend/Deno refinement instruction が記録されている。
- 関連する closed Ticket `00001KVMFFYVX` は Workspace web control plane bootstrap で、SvelteKit static SPA skeleton を `web/workspace` に追加した作業である。
- `web/workspace/README.md` は現在の package manager を npm とし、`npm install`, `npm run check`, `npm run build` を案内している。
- `web/workspace/package.json` は SvelteKit static SPA の scripts / devDependencies を持ち、`package-lock.json` が存在する。
- `web/workspace/svelte.config.js``@sveltejs/adapter-static` を使い、`build/` に static output を出す設定である。
- `package.nix``web/workspace/node_modules`, `.svelte-kit`, `build` を source filter から除外している。
- `devshell.nix` には `deno` が含まれている。
### Intake conclusion
- この refinement は `00001KVMT2J25` の late-attach / stream-state work item とは別目的であり、同一 Ticket の requirements / acceptance criteria に混ぜると work item が破綻する。
- 既存の frontend bootstrap Ticket `00001KVMFFYVX` は closed であり、現在の npm 採用は当時の bootstrap decision / implementation detail として記録されている。Deno 移行は closed Ticket の再オープンではなく、別の concrete follow-up Ticket として扱うのが妥当。
- 現時点では、ユーザーが「新規 Ticket を作成して」と明示していないため、duplicate/new Ticket は作成しない。
### Candidate follow-up draft if user approves new Ticket
Title: Workspace web SPA の frontend tooling を npm/Node から Deno に移行する
Readiness: implementation_ready
Risk flags: [frontend-tooling, packaging, nix-source-filter, validation]
Requirements:
- `web/workspace` の開発・検証・build 手順を npm/Node 前提から Deno 前提へ移行する。
- SvelteKit static SPA であること、Rust backend が business/API authority を持つこと、static output が `web/workspace/build/` に出ることは維持する。
- `web/workspace/README.md` の package manager / command guidance を Deno 前提に更新する。
- lockfile と依存関係管理を Deno 前提で明確にし、古い npm lockfile/source-of-truth が残る場合は理由を明示する。
- generated artifacts (`node_modules`, `.svelte-kit`, `build` など) が git/Nix package source に混入しない状態を維持する。
Acceptance criteria:
- `web/workspace` の check/build が Deno command で成功する。
- README と project files から、通常の frontend 作業者が Deno で install/check/build できることが分かる。
- npm lockfile / npm scripts / Node-only guidance が不要なら削除され、必要なら Deno 移行後も残す理由が code/docs に明確である。
- `package.nix` / devshell / repository hygiene が Deno 移行後の generated artifacts と矛盾しない。
- 既存の Rust backend static serving assumptions と `.yoi` records as authority の境界を変えない。
Implementation latitude:
- Deno project layout は `deno.json` / `deno.lock` / `deno task` を使う形でよい。
- SvelteKit/Vite を Deno の npm compatibility で動かすか、最小限の package metadata を残すかは実装時に選んでよい。ただし source-of-truth と command guidance は曖昧にしない。
Validation:
- `cd web/workspace && deno task check`
- `cd web/workspace && deno task build`
- `git diff --check`
- packaging/source-filter を変更する場合は `nix build .#yoi --no-link` または Orchestrator が妥当と判断する同等確認
Next routing recommendation:
- `00001KVMT2J25` はこの refinement では implementation_ready に戻さない。
- ユーザーが Deno 移行の新規 Ticket 作成を承認した場合、上記 draft を別 Ticket として materialize する。
- ユーザーがあくまで `00001KVMT2J25` の差し替えを望む場合は、既存 Ticket を repurpose するのではなく、Orchestrator/maintainer に cancel/close/replacement 方針の判断を戻す。
---
<!-- event: intake_summary author: ticket-intake at: 2026-06-21T10:23:54Z -->
## Intake summary
ユーザーから、Deno 移行 refinement は `00001KVMT2J25` に誤って付いたものであり、`00001KVMT2J25` は ready に戻してよいとの明示指示があった。再確認したところ、`00001KVMT2J25` の body は late attach / in-flight stream snapshot の concrete work item で、readiness は `implementation_ready`、blocking open question はない。Deno 移行は別 Ticket `00001KVMV03QY` として作成済みであり、本 Ticket の要件には混ぜない。
---
<!-- event: state_changed author: ticket-intake at: 2026-06-21T10:23:54Z from: planning to: ready reason: requirements_sync_resolved field: state -->
## State changed
Deno 移行 refinement は誤付与として分離済み。`00001KVMT2J25` は元の protocol reconnect / unfinished block snapshot Ticket として Orchestrator routing 可能な ready 状態へ戻す。queue routing や implementation start は行わない。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T10:56:32Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T10:58:27Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body は in-flight LLM response reconnect snapshot の問題、affected blocks、protocol/pod/TUI relevant files、acceptance criteria、validation が具体化されている。
- `readiness: implementation_ready` で、relations / orchestration plan に blocker はない。
- Requirements sync で Deno refinement は誤付与として分離済みで、この Ticket は original protocol reconnect scope に戻されている。
- 同時 queued の `00001KVMV03QY` は frontend Deno tooling migration であり、この Ticket の protocol/pod/TUI stream-state work と主対象が異なるため並列実装可能と判断する。
- Orchestrator worktree は clean on `orchestration` at `b4786b40` で、対象 Ticket 用 worktree / branch は未作成。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct `item.md` read。
- `TicketRelationQuery(00001KVMT2J25)`: no relations / blockers。
- `TicketOrchestrationPlanQuery(00001KVMT2J25)`: no records。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `crates/protocol/src/lib.rs`: `Event::Snapshot`, `TextDelta`, `ThinkingDelta`, `ToolCallArgsDelta`, serialization tests。
- `crates/pod/src/segment_log_sink.rs`: committed `LogEntry` snapshot / live entry receiver。
- `crates/pod/src/controller.rs`: direct broadcast of streaming deltas and current controller comments around stream reconstruction。
- `crates/pod/src/ipc/server.rs`: connect-time snapshot event construction。
- `crates/tui/src/app.rs`: `restore_snapshot` and live delta handling for text/thinking/tool-call args。
IntentPacket:
Intent:
- Ensure late attach / reconnect during an in-flight LLM response can display already-generated unfinished text/thinking/tool-call args, then continue live deltas without gaps or duplicates。
Binding decisions / invariants:
- Fix at protocol/pod state level, not TUI-only workaround。
- Do not persist unfinished model output as finalized assistant history。
- Do not mutate/replay provider stream itself。
- Preserve committed session-log gap-free semantics。
- Preserve post-run reconnect behavior from finalized Snapshot entries。
- No hidden context/history injection。
- Keep in-flight snapshot bounded and typed; if large/unbounded policy is required, escalate。
Requirements / acceptance criteria:
- New client connecting during response sees unfinished assistant text, thinking/reasoning, and tool-call args generated before connect。
- Live deltas after connect append to same logical block without missing or duplicated content。
- Completed run reconnect still restores finalized transcript from normal Snapshot entries。
- Snapshot/live boundary gap-free / duplicate-free behavior is tested。
- TUI Snapshot restore + live delta handling has regression coverage。
- Focused validation covers protocol/pod/TUI relevant paths。
Implementation latitude:
- Add structured `in_flight` state to `Event::Snapshot`, or implement bounded/sequence replay buffer if cleaner。
- Controller/Pod may keep current accumulators for text/thinking/tool-call args。
- TUI may seed unfinished blocks from Snapshot and continue applying live deltas to the same block。
- Wire compatibility should be minimal; prioritize type safety and maintainability。
Escalate if:
- Design requires persisting unfinished output as durable history item。
- In-flight snapshot state becomes large enough to need truncation/bounding policy beyond a straightforward current-turn accumulator。
- Public protocol compatibility policy becomes a product decision。
- Scope spreads to Dashboard/Pod list preview or broader UX surfaces beyond TUI/console attach。
Validation plan:
- `cargo fmt --check`
- Focused `cargo test -p protocol` roundtrip/serialization tests for snapshot in-flight state。
- Focused `cargo test -p pod` tests for connect-time snapshot/live boundary and accumulator behavior。
- Focused `cargo test -p tui` tests for snapshot seeding plus live delta continuation。
- `cargo check -p protocol -p pod -p tui`
- `git diff --check`
- `yoi ticket doctor`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T10:58:33Z from: queued to: inprogress reason: human_authorized_unblocked_protocol_stream_state_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria, no recorded blockers, and is semantically separate from the frontend Deno tooling Ticket, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:00:09Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMT2J25-inflight-snapshot`
- Created branch:
- `impl/00001KVMT2J25-inflight-snapshot`
- Base commit:
- `155e039e ticket: route deno and inflight snapshot work`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVMT2J25`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVMT2J25-inflight-snapshot`
Parallelization note:
- `00001KVMV03QY` is active in a separate child worktree and targets frontend Deno tooling. This Ticket should stay limited to protocol/pod/TUI in-flight snapshot semantics。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:31:12Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVMT2J25`.
Implementation commit:
- `74aca6f6 fix: snapshot in-flight stream state`
Changed areas:
- `crates/protocol/src/lib.rs`
- Added typed `InFlightSnapshot` / `InFlightBlock` state on `Event::Snapshot`
- Added serialization/default compatibility coverage。
- `crates/pod/src/in_flight.rs`
- New in-flight accumulator for assistant text, thinking/reasoning, and tool-call args。
- Snapshot/live boundary tests for no gap/duplicate。
- `crates/pod/src/controller.rs`
- Streaming callbacks update the in-flight accumulator and broadcast live deltas from the same path。
- `crates/pod/src/ipc/alerter.rs`, `crates/pod/src/ipc/server.rs`
- Connect-time snapshot now includes alerts plus typed in-flight stream state while subscribing live events。
- `crates/pod/src/pod.rs`
- Clears matching in-flight blocks once committed assistant items reach durable session log entries。
- `crates/tui/src/app.rs`
- Snapshot restore seeds unfinished assistant text/thinking/tool-call blocks。
- Live deltas continue those seeded blocks。
- Added regression coverage for snapshot seeding plus live continuation。
- Other touched files update test Snapshot constructors for the new `in_flight` field。
Coder validation reported:
- `cargo fmt --all --check`: passed
- `cargo test -p protocol`: passed
- `cargo test -p protocol event_snapshot_in_flight_roundtrip_and_default`: passed
- `cargo test -p pod in_flight`: passed
- `cargo test -p pod subscribe_with_alerts_and_in_flight_snapshot_splits_snapshot_and_live_deltas`: passed
- `cargo test -p tui`: passed
- `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`: passed
- `cargo check -p protocol -p pod -p tui`: passed
- `git diff --check`: passed
- `target/debug/yoi ticket doctor`: passed
Known unrelated validation note:
- Full `cargo test -p pod` still fails on two prompt-resource assertion tests unrelated to this change:
- `prompt::catalog::tests::pod_orchestration_guidance_section_renders_resource_body`
- `prompt::system::tests::pod_orchestration_guidance_is_included_for_pod_management_tools`
- Both assert missing text: `worktree status, diff, and test results`
Orchestrator evidence checked:
- Implementation worktree is clean on `impl/00001KVMT2J25-inflight-snapshot`
- HEAD is `74aca6f6`
- Diff `155e039e..HEAD` touches 17 protocol/pod/TUI files, adding `crates/pod/src/in_flight.rs` and updating Snapshot constructors/tests。
- `git diff --check 155e039e..HEAD` produced no diagnostics。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T11:31:55Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVMT2J25-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVMT2J25-inflight-snapshot`
- Branch: `impl/00001KVMT2J25-inflight-snapshot`
- Baseline: `155e039e`
- Implementation commit: `74aca6f6 fix: snapshot in-flight stream state`
- Diff: `155e039e..74aca6f6`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Snapshot/live subscription ordering is gap-free。
- Seeded unfinished blocks and later live deltas do not duplicate content。
- Accumulator lifecycle clears after durable assistant commit and does not leak across runs。
- Tool-call args partial JSON string deltas accumulate correctly。
- Thinking/reasoning blocks remain separated and safe。
- Finished-run reconnect still restores finalized transcript normally。
- No unfinished model output is persisted as finalized history。
- TUI restore seeding is compatible with existing live delta handlers。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVMT2J25-r1 at: 2026-06-21T11:37:35Z status: request_changes -->
## Review: request changes
Verdict: `request_changes`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVMT2J25/item.md`
- `.yoi/tickets/00001KVMT2J25/thread.md`
- Diff `155e039e..74aca6f6`, including:
- `crates/protocol/src/lib.rs`
- `crates/pod/src/in_flight.rs`
- `crates/pod/src/controller.rs`
- `crates/pod/src/ipc/alerter.rs`
- `crates/pod/src/ipc/server.rs`
- `crates/pod/src/pod.rs`
- `crates/pod/src/segment_log_sink.rs`
- `crates/tui/src/app.rs`
- constructor/test updates in pod/TUI/discovery/spawn/dashboard-related test files
Blocking issue:
1. Snapshot/live boundary still has a gap for finalized assistant items committed between the session-log snapshot and the in-flight snapshot。
The implementation makes in-flight streaming deltas mostly gap-free by holding the in-flight mutex across subscribe/snapshot, but the full connection snapshot is not atomic across the committed session-log mirror and the new in-flight accumulator。
Relevant path:
- `crates/pod/src/ipc/server.rs:112` takes `handle.sink.subscribe_with_snapshot()` first。
- `crates/pod/src/ipc/server.rs:118-120` then subscribes/snapshots alerts + in-flight state。
- `crates/pod/src/pod.rs:182-191` persists an entry, clears matching in-flight state for `LogEntry::AssistantItem`, then publishes to the session-log sink。
- `crates/pod/src/segment_log_sink.rs:90-103` documents that `AssistantItem` is mirror-only and not live-broadcast。
- `crates/pod/src/segment_log_sink.rs:120-127` confirms only `SegmentStart`, `UserInput`, `SystemItem`, and `Invoke` are live-relevant。
Race:
1. New client connects。
2. Server snapshots session-log entries at N。
3. LLM response finalizes and appends `LogEntry::AssistantItem`
4. `append_entry` clears the matching in-flight text/thinking block。
5. `SegmentLogSink::publish` mirrors the `AssistantItem`, but does not broadcast it live。
6. Server snapshots in-flight state, now empty/cleared。
7. Client receives `Event::Snapshot` with no finalized assistant item in `entries`, no unfinished/finalized in-flight block, and no live committed assistant event forthcoming。
This violates the Ticket invariant that Snapshot and post-Snapshot live events must be gap-free and duplicate-free。
Required fix:
- Make the connection snapshot atomic enough across session-log mirror and in-flight state, or otherwise ensure committed assistant items cannot disappear in this boundary。
- Add an integrated regression test around session-log snapshot + in-flight snapshot + mirror-only assistant commit boundary。
- Ensure the fix still avoids persisting unfinished output as final history and still does not duplicate content when final AssistantItem is included in committed snapshot。
Non-blocking concerns:
- The suggested focused test name `subscribe_with_alerts_and_in_flight_snapshot_splits_snapshot_and_live_deltas` selected 0 tests; no matching test exists。Add/rename an integrated focused test so validation can target the boundary reliably。
- Minor protocol doc issue: `Greeting` doc comment appears displaced so “Pod self-description...” now sits immediately before `InFlightSnapshot` in `crates/protocol/src/lib.rs`。Not blocking but should be cleaned up if easy。
Reviewer validation:
- `git diff --check 155e039e..HEAD`: passed
- `cargo fmt --all --check`: passed
- `cargo test -p protocol`: passed, 40 tests
- `cargo test -p pod in_flight`: passed selected tests
- `cargo test -p pod subscribe_with_alerts_and_in_flight_snapshot_splits_snapshot_and_live_deltas`: selected 0 tests / no matching test
- `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`: passed
- `cargo test -p tui`: passed, 367 tests
- `cargo check -p protocol -p pod -p tui`: passed
- `target/debug/yoi ticket doctor`: passed (`doctor: ok`)
- Full `cargo test -p pod`: failed only on the two known unrelated prompt-resource assertion tests。
Worktree status:
- Clean on `impl/00001KVMT2J25-inflight-snapshot`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:53:00Z -->
## Implementation report
Coder r1-fix report received from `yoi-coder-00001KVMT2J25`.
New fix commit:
- `061136d7 fix: close in-flight snapshot commit race`
Branch commits now:
- `74aca6f6 fix: snapshot in-flight stream state`
- `061136d7 fix: close in-flight snapshot commit race`
Fix summary:
- `crates/pod/src/ipc/server.rs`
- Connect-time snapshot now holds the in-flight stream lock while taking the session-log mirror snapshot, preventing finalized mirror-only `AssistantItem` entries from falling between committed snapshot entries and in-flight snapshot state。
- `crates/pod/src/pod.rs`
- `append_entry` now clears matching in-flight assistant state and publishes finalized `AssistantItem` to the mirror under the same in-flight critical section。
- `crates/pod/src/in_flight.rs`
- Added `clear_for_committed_item_then` helper for atomic clear + publish ordering。
- Added integrated regression tests:
- `session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`
- `committed_assistant_snapshot_does_not_duplicate_in_flight_block`
- `crates/pod/src/ipc/alerter.rs`
- Removed earlier non-atomic combined alert/in-flight snapshot helper。
- `crates/protocol/src/lib.rs`
- Fixed displaced `Greeting` doc comment。
Coder validation reported:
- `cargo fmt --all --check`: passed
- `cargo test -p protocol`: passed
- `cargo test -p pod --lib in_flight`: passed
- `cargo test -p pod session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`: passed
- `cargo test -p pod committed_assistant_snapshot_does_not_duplicate_in_flight_block`: passed
- `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`: passed
- `cargo test -p tui`: passed
- `cargo check -p protocol -p pod -p tui`: passed
- `git diff --check`: passed
- `target/debug/yoi ticket doctor`: passed
Known unrelated validation note:
- Full `cargo test -p pod` still fails only on the known unrelated prompt-resource assertions:
- `prompt::catalog::tests::pod_orchestration_guidance_section_renders_resource_body`
- `prompt::system::tests::pod_orchestration_guidance_is_included_for_pod_management_tools`
Orchestrator evidence checked:
- Implementation worktree clean on `impl/00001KVMT2J25-inflight-snapshot`
- HEAD is `061136d7`
- r1-fix diff `74aca6f6..HEAD` touches expected protocol/pod files: `crates/pod/src/in_flight.rs`, `crates/pod/src/ipc/alerter.rs`, `crates/pod/src/ipc/server.rs`, `crates/pod/src/pod.rs`, and `crates/protocol/src/lib.rs`
- `git diff --check 155e039e..HEAD` produced no diagnostics。
Next action:
- Route back to Reviewer for r2 verification of the commit-boundary race fix and final acceptance。
---
<!-- event: review author: yoi-reviewer-00001KVMT2J25-r1 at: 2026-06-21T11:56:44Z status: approve -->
## Review: approve
Verdict: `approve`
r2 review result:
- r1 blocker is resolved。
- The fix establishes a single critical section around session-log mirror snapshot and in-flight snapshot, and uses the same in-flight lock while clearing/publishing finalized `AssistantItem`s。
Relevant safe interleavings:
- If connect-time snapshot gets the in-flight lock first: session-log snapshot may not include finalized mirror-only `AssistantItem`, but unfinished/finished in-flight block is still present in `Event::Snapshot.in_flight`
- If commit gets the in-flight lock first: it clears in-flight and publishes to session-log mirror under that lock, so later session-log snapshot includes finalized `AssistantItem` and `in_flight` is empty。
- Since `AssistantItem` remains mirror-only for live clients, this avoids the previous “absent from both snapshot and live events” gap。
- Duplicate prevention is preserved by clearing matching in-flight state before publishing finalized assistant entry。
Files / diff inspected:
- r1-fix diff `74aca6f6..061136d7`:
- `crates/pod/src/in_flight.rs`
- `crates/pod/src/ipc/alerter.rs`
- `crates/pod/src/ipc/server.rs`
- `crates/pod/src/pod.rs`
- `crates/protocol/src/lib.rs`
- Overall scope/diff `155e039e..061136d7` against Ticket authority:
- `.yoi/tickets/00001KVMT2J25/item.md`
- `.yoi/tickets/00001KVMT2J25/thread.md`
Blocking issues:
- None。
Non-blocking concerns:
- None requiring changes. Integrated regression tests cover the r1 commit-boundary race and duplicate case。
Reviewer validation:
- `git diff --check 155e039e..HEAD`: passed
- `cargo fmt --all --check`: passed
- `cargo test -p protocol`: passed, 40 tests
- `cargo test -p pod --lib in_flight`: passed, 5 selected tests
- `cargo test -p pod session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`: passed
- `cargo test -p pod committed_assistant_snapshot_does_not_duplicate_in_flight_block`: passed
- `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`: passed
- `cargo test -p tui`: passed, 367 tests
- `cargo check -p protocol -p pod -p tui`: passed
- `target/debug/yoi ticket doctor`: passed (`doctor: ok`)
- `cargo test -p pod`: failed only on the known unrelated prompt-resource assertions; summary 424 passed, 2 failed。
Worktree status:
- Clean on `impl/00001KVMT2J25-inflight-snapshot` at `061136d7`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:59:39Z -->
## Implementation report
Reviewer r2 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `b21638f5 merge: inflight reconnect snapshot`
- Merged branch: `impl/00001KVMT2J25-inflight-snapshot`
- Implementation commits:
- `74aca6f6 fix: snapshot in-flight stream state`
- `061136d7 fix: close in-flight snapshot commit race`
Orchestrator worktree validation:
- `cargo fmt --all --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p protocol`: passed (`40 passed`)
- `cargo test -p pod --lib in_flight`: passed (`5 selected tests`)
- `cargo test -p pod session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`: passed
- `cargo test -p pod committed_assistant_snapshot_does_not_duplicate_in_flight_block`: passed
- `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`: passed
- `cargo test -p tui`: passed (`367 passed`)
- `cargo check -p protocol -p pod -p tui`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
Known unrelated validation note:
- Full `cargo test -p pod` was not repeated in Orchestrator after merge because Reviewer confirmed it still fails only on pre-existing prompt-resource assertions unrelated to this diff。
Final Orchestrator worktree status after validation: clean on `orchestration` at `b21638f5`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T11:59:47Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、protocol/pod/TUI focused tests、cargo check、Ticket doctor が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T12:00:02Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T12:00:02Z status: closed -->
## 完了
In-flight LLM response 中の reconnect / late attach snapshot に unfinished blocks を含める protocol/pod/TUI 実装を統合した。
主な成果:
- `Event::Snapshot` に typed `InFlightSnapshot` / `InFlightBlock` を追加。
- Pod 側に assistant text / thinking / tool-call args の in-flight accumulator を追加。
- Streaming callbacks が accumulator 更新と live delta broadcast を同じ stream path で行うようにした。
- Connect-time snapshot が in-flight stream state を含むようにした。
- Session-log mirror snapshot と in-flight snapshot、および finalized `AssistantItem` publish/clear の critical section を揃え、mirror-only assistant commit が snapshot/live boundary で消える race を防止した。
- Finalized assistant item が committed snapshot に含まれる場合は matching in-flight state を clear して duplicate を防ぐ。
- TUI snapshot restore が unfinished text/thinking/tool-call args blocks を seed し、後続 live deltas が同じ logical block に continuation されるようにした。
- Serialization/default compatibility、snapshot/live no-gap/no-duplicate、TUI continuation の focused regression tests を追加。
統合・検証:
- Merge commit: `b21638f5 merge: inflight reconnect snapshot`
- Implementation commits: `74aca6f6`, `061136d7`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --all --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p protocol`, `cargo test -p pod --lib in_flight`, `cargo test -p pod session_log_and_in_flight_snapshot_prevents_mirror_only_assistant_gap`, `cargo test -p pod committed_assistant_snapshot_does_not_duplicate_in_flight_block`, `cargo test -p tui snapshot_in_flight_blocks_continue_with_live_deltas`, `cargo test -p tui`, `cargo check -p protocol -p pod -p tui`, and `cargo run -p yoi -- ticket doctor`
既知の無関係事項:
- Full `cargo test -p pod` は既存の prompt-resource assertion 2 件で失敗することが reviewer により確認済み。この Ticket の差分とは無関係。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T12:00:31Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVMT2J25`
- `yoi-reviewer-00001KVMT2J25-r1`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMT2J25-inflight-snapshot`
- Deleted implementation branch:
- `impl/00001KVMT2J25-inflight-snapshot`
- Orchestrator worktree remains clean on `orchestration` at `77b5276f`
Root/original workspace was not used for merge/validation/cleanup operations。
---
+40
View File
@@ -0,0 +1,40 @@
---
title: 'Workspace server binary and CLI launcher'
state: 'closed'
created_at: '2026-06-21T10:15:30Z'
updated_at: '2026-06-21T10:41:20Z'
assignee: null
queued_by: 'yoi ticket'
queued_at: '2026-06-21T10:16:04Z'
---
## 背景
Workspace web control plane bootstrap により `crates/workspace-server` は library crate として HTTP router / `serve(...)` / SQLite store を提供している。一方で、現状は product CLI から直接起動できず、手元で試すには別の harness が必要になる。
方針として、workspace server は `yoi` binary にリンクして内包しない。`crates/workspace-server` 側に独立 binary entrypoint を置き、`yoi workspace serve` は外部 `yoi-workspace-server` executable を解決して exec/spawn する薄い launcher にする。
## 要件
- `crates/workspace-server/src/main.rs` を追加し、独立 binary `yoi-workspace-server` として起動できるようにする。
- server binary は少なくとも `serve` subcommand を持つ。
- server binary options:
- `--workspace <PATH>` / `--workspace=<PATH>`: default cwd。
- `--db <PATH>` / `--db=<PATH>`: default `<workspace>/.yoi/workspace.db`
- `--frontend <PATH>` / `--frontend=<PATH>`: optional static SPA build dir。
- `--listen <ADDR>` / `--listen=<ADDR>`: default `127.0.0.1:8787`
- `--help` / `-h`
- `yoi workspace serve ...` を追加する。
- `yoi` crate は `yoi-workspace-server` crate に依存しない。
- launcher は `YOI_WORKSPACE_SERVER_COMMAND` override または current exe と同じ directory の `yoi-workspace-server` を解決する。
- launcher は引数を外部 server binary に渡し、終了 status を反映する。
- package build では `yoi``yoi-workspace-server` を別 binary として build/install する。
- help に `yoi workspace serve` を表示する。
## 受け入れ条件
- `cargo run -p yoi-workspace-server -- serve --workspace . --db .yoi/workspace.db --listen 127.0.0.1:8787` 相当で server が起動できる。
- `yoi workspace serve ...` が外部 `yoi-workspace-server` binary を起動する。
- `crates/yoi``yoi-workspace-server` に依存しない。
- `yoi --help` / `yoi workspace --help` に起動方法が出る。
- `cargo fmt --check`、関連 `cargo test` / `cargo check``git diff --check``yoi ticket doctor``nix build .#yoi --no-link` が通る。
+1
View File
@@ -0,0 +1 @@
Added standalone yoi-workspace-server binary entrypoint with serve command and options for workspace/db/frontend/listen. Added yoi workspace serve launcher that resolves an external executable via YOI_WORKSPACE_SERVER_COMMAND or sibling yoi-workspace-server without linking the workspace-server crate into yoi. Updated package.nix to build/install both separate binaries. Validation passed: cargo fmt --check; cargo check -p yoi -p yoi-workspace-server; cargo test -p yoi workspace; cargo test -p yoi-workspace-server; cargo build -p yoi -p yoi-workspace-server; help/launch smoke tests; cargo tree dependency check; git diff --check; yoi ticket doctor; yoi objective doctor; nix build .#yoi --no-link.
+69
View File
@@ -0,0 +1,69 @@
<!-- event: create author: "yoi ticket" at: 2026-06-21T10:15:30Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-21T10:16:04Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T10:16:04Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T10:16:04Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `yoi ticket` が queued にしました。
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T10:16:04Z from: queued to: inprogress reason: cli_state field: state -->
## State changed
State changed to `inprogress`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T10:41:20Z from: inprogress to: done reason: cli_state field: state -->
## State changed
State changed to `done`.
---
<!-- event: state_changed author: hare at: 2026-06-21T10:41:20Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T10:41:20Z status: closed -->
## 完了
Added standalone yoi-workspace-server binary entrypoint with serve command and options for workspace/db/frontend/listen. Added yoi workspace serve launcher that resolves an external executable via YOI_WORKSPACE_SERVER_COMMAND or sibling yoi-workspace-server without linking the workspace-server crate into yoi. Updated package.nix to build/install both separate binaries. Validation passed: cargo fmt --check; cargo check -p yoi -p yoi-workspace-server; cargo test -p yoi workspace; cargo test -p yoi-workspace-server; cargo build -p yoi -p yoi-workspace-server; help/launch smoke tests; cargo tree dependency check; git diff --check; yoi ticket doctor; yoi objective doctor; nix build .#yoi --no-link.
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-105758-1","ticket_id":"00001KVMV03QY","kind":"accepted_plan","accepted_plan":{"summary":"Migrate `web/workspace` SvelteKit static SPA frontend tooling from npm/Node-primary to Deno-primary, including Deno config/tasks/lockfile, README/source-of-truth cleanup, generated artifact ignore/source-filter checks, and Deno check/build validation without changing backend authority.","branch":"impl/00001KVMV03QY-workspace-spa-deno","worktree":"/home/hare/Projects/yoi/.worktree/00001KVMV03QY-workspace-spa-deno","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates Deno/frontend/package hygiene, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T10:57:58Z"}
+129
View File
@@ -0,0 +1,129 @@
---
title: 'Workspace web SPA の frontend tooling を npm/Node から Deno に移行する'
state: 'closed'
created_at: '2026-06-21T10:18:10Z'
updated_at: '2026-06-21T11:14:27Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['frontend-tooling', 'packaging', 'nix-source-filter', 'validation']
queued_by: 'workspace-panel'
queued_at: '2026-06-21T10:56:31Z'
---
## User claims / request snapshot
- ユーザーは「今あるフロントSPAを node から deno にしたい」と述べた。
- 参考 URL として `https://hareworks.net/blog/tech/sveltekit-with-deno` が提示された。
- この依頼は、Panel から planning に戻された `00001KVMT2J25` の requirements sync 中に追加された。
## Confirmed facts / sources
- `00001KVMT2J25` は protocol / pod / TUI reconnect / stream-state の Ticket であり、frontend tooling 移行とは別目的である。
- `00001KVMT2J25` の thread に、今回の refinement は別 follow-up Ticket として扱うべきことを Intake comment として記録済み。
- Closed Ticket `00001KVMFFYVX` は Workspace web control plane bootstrap で、SvelteKit static SPA skeleton を `web/workspace` に追加した。
- `00001KVMFFYVX` の resolution は、frontend が npm + committed `package-lock.json` を使い、generated `node_modules/`, `.svelte-kit/`, `build/` を ignore/source-filter する方針だったことを記録している。
- 現在の `web/workspace/package.json` は npm scripts と SvelteKit/Vite devDependencies を持つ。
- 現在の `web/workspace/package-lock.json` は npm lockfile として存在する。
- 現在の `web/workspace/README.md` は package manager を npm とし、`npm install`, `npm run check`, `npm run build` を案内している。
- 現在の `web/workspace/svelte.config.js``@sveltejs/adapter-static` を使い、`web/workspace/build/` に static output を出す。
- 現在の `package.nix``web/workspace/node_modules`, `web/workspace/.svelte-kit`, `web/workspace/build` を source filter から除外している。
- 現在の `devshell.nix` には `deno` が含まれている。
- 参考 URL の内容は untrusted web content として確認した。記事は SvelteKit を Deno task / npm compatibility / `deno.json` ベースで運用する例、Svelte LSP 用 `tsconfig.json` が残りうる点、Deno 用 adapter への言及を含む。
## Unverified hypotheses
- `web/workspace` は static SPA skeleton なので、Deno 移行は backend/API authority を変えず frontend tooling の範囲に収められる可能性が高い。
- SvelteKit/Vite/svelte-check は Deno の npm compatibility と `deno task` で動かせる可能性が高い。
- Svelte LSP / svelte-check のために `tsconfig.json` を完全削除できない可能性がある。
- Deno 移行後も `node_modules` 相当の local generated state が発生する可能性があり、ignore/source-filter の再確認が必要。
## Undecided points / open questions
- blocking な未決定点はなし。
- `package.json` を完全に削除できるか、SvelteKit/Vite ecosystem 互換のため最小限残すかは実装調査で判断してよい。ただし source-of-truth と command guidance を曖昧にしない。
- `tsconfig.json` を維持するか `deno.json` へ寄せるかは、Svelte LSP / svelte-check の実動作に基づいて判断してよい。
- `@sveltejs/adapter-static` を維持するか Deno 向け adapter へ変えるかは、Rust backend が static assets を serve する現方針と矛盾しない範囲で判断してよい。
## Background
Workspace web control plane の frontend は `web/workspace` にある SvelteKit static SPA skeleton である。bootstrap 時点では npm + `package-lock.json` を採用したが、ユーザーは既存 frontend SPA の tooling を Node/npm 前提から Deno 前提へ移行したい。
この Ticket は frontend tooling / package-manager migration の concrete follow-up であり、protocol reconnect Ticket `00001KVMT2J25` とは別 work item として扱う。
## Requirements
- `web/workspace` の開発・検証・build 手順を npm/Node 前提から Deno 前提へ移行する。
- Deno 側の project configuration を明確にする。候補は `deno.json` または `deno.jsonc``deno.lock``deno task`
- SvelteKit static SPA であることを維持する。
- Rust backend が business/API authority を持ち、frontend は lifecycle/business authority を持たない境界を維持する。
- static build output が backend から serve できる形を維持する。既存の `web/workspace/build/` を変える場合は backend/README/package hygiene と整合させる。
- `web/workspace/README.md` の package manager / command guidance を Deno 前提に更新する。
- lockfile と依存関係管理を Deno 前提で明確にする。
- 古い npm lockfile / npm scripts / Node-only guidance が不要なら削除し、残す必要がある場合は理由を project files または docs に明記する。
- generated artifacts (`node_modules`, `.svelte-kit`, `build` など) が git / Nix package source に混入しない状態を維持する。
- `package.nix` source filtering と devshell/package guidance が Deno 移行後の frontend generated state と矛盾しないことを確認する。
## Acceptance criteria
- `web/workspace` の check が Deno command で成功する。
- `web/workspace` の build が Deno command で成功する。
- README と project files から、通常の frontend 作業者が Deno で install/check/build できることが分かる。
- npm lockfile / npm scripts / Node-only guidance が不要なら削除されている。
- npm/Node 関連ファイルを残す場合、そのファイルが canonical source-of-truth なのか compatibility artifact なのかが明確である。
- SvelteKit static SPA と Rust backend static serving の前提が壊れていない。
- `web/workspace/build/`, `.svelte-kit/`, `node_modules` または Deno 移行後の同等 generated artifacts が git/Nix package source に混入しない。
- 既存の `.yoi` records as authority、Ticket/Objective workflow、Rust backend API authority を変更しない。
## Binding decisions / invariants
- この Ticket は frontend tooling migration であり、Workspace backend の API authority / Ticket lifecycle authority / `.yoi` canonical records を変更しない。
- Frontend を SSR authority や business/lifecycle authority にしない。
- Static SPA と Rust backend serving の境界を維持する。
- `00001KVMT2J25` は protocol reconnect Ticket として残し、本 Ticket に混ぜない。
- Tooling source-of-truth を npm と Deno の二重管理で曖昧にしない。
- Generated artifacts を committed source や Nix package source に混入させない。
## Implementation latitude
- Deno project layout は `deno.json` / `deno.lock` / `deno task` を使う形でよい。
- SvelteKit/Vite を Deno の npm compatibility で動かすか、最小限の package metadata を残すかは実装時に選んでよい。
- `tsconfig.json` は Svelte LSP / svelte-check の都合で必要なら残してよい。
- `@sveltejs/adapter-static` を維持してよい。Deno adapter を採用する場合は、この workspace の Rust backend static serving 方針と矛盾しないことを確認する。
- `package.nix` / devshell / README の更新範囲は、Deno 移行後の generated artifact と validation command に合わせて最小限でよい。
## Readiness
- readiness: implementation_ready
- risk_flags: [frontend-tooling, packaging, nix-source-filter, validation]
## Escalation conditions
- Deno だけでは SvelteKit check/build が安定せず、Node/npm を primary に残す必要が出た場合。
- `package.json` / `package-lock.json` を残すか削除するかが project policy decision になる場合。
- Static SPA ではなく SSR / Deno runtime server / Deno Deploy 前提へ移る必要が出た場合。
- Rust backend static serving path や package/Nix build 方針の大きな変更が必要になった場合。
- Generated artifacts の source-filter / ignore 境界が不明確になる場合。
## Validation
- `cd web/workspace && deno task check`
- `cd web/workspace && deno task build`
- `git diff --check`
- frontend generated artifacts が ignored / source-filtered されていることの確認。
- packaging/source-filter を変更する場合は `nix build .#yoi --no-link` または Orchestrator が妥当と判断する同等確認。
- 必要に応じて `cargo check -p yoi-workspace-server` または static serving 周辺の focused tests。
## Related work
- `00001KVMT2J25` — protocol reconnect / in-flight stream snapshot Ticket。今回の Deno 移行とは別件。
- `00001KVMFFYVX` — Workspace web control plane bootstrap。`web/workspace` の SvelteKit static SPA skeleton と npm/package-lock 採用元。
- Relevant files:
- `web/workspace/package.json`
- `web/workspace/package-lock.json`
- `web/workspace/README.md`
- `web/workspace/svelte.config.js`
- `web/workspace/vite.config.ts`
- `web/workspace/tsconfig.json`
- `web/workspace/.gitignore`
- `package.nix`
- `devshell.nix`
+22
View File
@@ -0,0 +1,22 @@
Workspace web SPA の frontend tooling を npm/Node-primary から Deno-primary に移行し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `web/workspace/deno.json` を追加し、Deno task を canonical workflow にした。
- `web/workspace/deno.lock` を追加。
- `web/workspace/package-lock.json` を削除。
- `web/workspace/package.json` は SvelteKit/Vite ecosystem compatibility metadata のみに縮小し、scripts/dependencies を削除。
- README を Deno workflow (`deno install`, `deno task check`, `deno task build`, `deno task preview`) と source-of-truth 説明に更新。
- Static SPA output path `web/workspace/build/``@sveltejs/adapter-static` assumptions を維持。
- Rust backend/static serving code、Workspace API authority、Ticket/Objectives authority、`.yoi` canonical record workflows には変更を加えていない。
- Generated artifacts (`node_modules`, `.svelte-kit`, `build`) は ignored/source-filtered のまま。
統合・検証:
- Merge commit: `6dc78e3f merge: workspace spa deno tooling`
- Implementation commit: `66f04e04 feat: migrate workspace spa tooling to deno`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `deno task install`, `cargo check -p yoi-workspace-server`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Backend API / static serving implementation は変更していない。
- Protocol reconnect work (`00001KVMT2J25`) には触れていない。
- SSR / Deno runtime server / Deno Deploy assumptions は追加していない。
+379
View File
@@ -0,0 +1,379 @@
<!-- event: create author: ticket-intake at: 2026-06-21T10:18:10Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T10:56:31Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T10:57:43Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body は `web/workspace` の frontend tooling を npm/Node から Deno に移行する concrete follow-up として、requirements / acceptance criteria / validation が具体化されている。
- `readiness: implementation_ready` で、relations / orchestration plan に blocker はない。
- `00001KVMFFYVX` Workspace web control plane bootstrap は closed 済みで、移行対象の `web/workspace` が現在の `orchestration` に存在する。
- `00001KVMT2J25` は protocol reconnect Ticket として別件であり、この Ticket の scope には混ぜないことが body に明記されている。
- 同時 queued の `00001KVMT2J25` は protocol/pod/TUI stream-state work で、主対象が異なるため並列実装可能と判断する。
- Orchestrator worktree は clean on `orchestration` at `b4786b40` で、対象 Ticket 用 worktree / branch は未作成。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct `item.md` read。
- `TicketRelationQuery(00001KVMV03QY)`: no relations / blockers。
- `TicketOrchestrationPlanQuery(00001KVMV03QY)`: no records。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `web/workspace/package.json`, `package-lock.json`, `README.md`, `svelte.config.js`, `vite.config.ts`, `tsconfig.json`, `.gitignore` are current frontend tooling files。
- `package.nix` currently excludes `web/workspace/node_modules`, `.svelte-kit`, and `build`
- `devshell.nix` already includes `deno`
IntentPacket:
Intent:
- Move Workspace web SPA frontend tooling from npm/Node-primary to Deno-primary while keeping SvelteKit static SPA and Rust backend authority unchanged。
Binding decisions / invariants:
- This is frontend tooling migration only; do not change Workspace backend API authority, Ticket/Objectives authority, or `.yoi` canonical record workflows。
- Keep static SPA and Rust backend static-serving boundary。
- Do not turn frontend into SSR/business/lifecycle authority。
- Avoid ambiguous dual source-of-truth between npm and Deno。
- Generated artifacts must remain out of git and Nix package source。
- `00001KVMT2J25` protocol reconnect work remains separate。
Requirements / acceptance criteria:
- `web/workspace` check/build succeeds through Deno commands。
- Add/clarify Deno project config such as `deno.json`/`deno.lock`/`deno task`
- README and project files make normal Deno install/check/build workflow clear。
- Remove npm lockfile/scripts/Node-only guidance if unnecessary; if any npm/Node metadata remains, document whether it is compatibility artifact or canonical source-of-truth。
- Preserve static output usable by Rust backend, default `web/workspace/build/` unless deliberately changed and documented。
- Keep `web/workspace/build/`, `.svelte-kit/`, `node_modules` or Deno equivalents ignored/source-filtered。
- Update `package.nix` / `devshell` / README only as needed for generated artifacts and validation commands。
Implementation latitude:
- Use Deno npm compatibility for SvelteKit/Vite/svelte-check if practical。
- Keep `tsconfig.json` if Svelte LSP / svelte-check needs it。
- Keep `@sveltejs/adapter-static` if static backend serving remains compatible。
- Minimal `package.json` can remain if ecosystem requires it, but source-of-truth must be clear。
Escalate if:
- Deno-only check/build is unstable and Node/npm must remain primary。
- Keeping/removing `package.json` or `package-lock.json` becomes a policy decision rather than implementation detail。
- Migration requires SSR/Deno runtime server/Deno Deploy assumptions。
- Rust backend static serving path or Nix package strategy requires major redesign。
- Generated artifact boundaries become unclear。
Validation plan:
- `cd web/workspace && deno task check`
- `cd web/workspace && deno task build`
- `git diff --check`
- generated artifact ignore/source-filter check。
- `nix build .#yoi --no-link` if package/source-filter changes。
- `cargo check -p yoi-workspace-server` or focused server/static tests if static serving assumptions change。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T10:57:48Z from: queued to: inprogress reason: human_authorized_unblocked_frontend_tooling_migration field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria, no recorded blockers, and is semantically separate from the protocol reconnect Ticket, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:00:00Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMV03QY-workspace-spa-deno`
- Created branch:
- `impl/00001KVMV03QY-workspace-spa-deno`
- Base commit:
- `155e039e ticket: route deno and inflight snapshot work`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVMV03QY`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVMV03QY-workspace-spa-deno`
Parallelization note:
- `00001KVMT2J25` is active in a separate child worktree and targets protocol/pod/TUI stream state. This Ticket should stay limited to `web/workspace` frontend tooling and package/source-filter docs as needed。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:05:28Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVMV03QY`.
Implementation commit:
- `66f04e04 feat: migrate workspace spa tooling to deno`
Changed areas:
- Added Deno-primary frontend tooling:
- `web/workspace/deno.json`
- `web/workspace/deno.lock`
- Removed npm lockfile:
- deleted `web/workspace/package-lock.json`
- Reduced `web/workspace/package.json` to minimal SvelteKit/Vite ecosystem metadata only:
- no scripts
- no dependencies
- `deno.json` / `deno.lock` are canonical source of truth
- Updated `web/workspace/README.md` with Deno workflow:
- `deno install`
- `deno task check`
- `deno task build`
- npm compatibility usage and generated artifact boundaries
- Preserved static SPA output path:
- `web/workspace/build/`
Coder validation reported:
- `cd web/workspace && deno task check`: passed
- `cd web/workspace && deno task build`: passed
- `cd web/workspace && deno task install`: passed
- `git diff --check`: passed
- `target/debug/yoi ticket doctor`: passed (`doctor: ok`)
- Generated artifact ignore/source-filter check:
- `web/workspace/node_modules`, `.svelte-kit`, and `build` are ignored by `web/workspace/.gitignore`
- existing `package.nix` source filter already excludes those same trees
Not run by Coder:
- `nix build .#yoi --no-link`: not run because `package.nix` / source filter were not changed。
- `cargo check -p yoi-workspace-server`: not run because Rust backend/static-serving assumptions and code were not changed。
Generated artifacts cleanup:
- Removed `web/workspace/node_modules/`, `.svelte-kit/`, and `build/` after validation。
Orchestrator evidence checked:
- Implementation worktree is clean on `impl/00001KVMV03QY-workspace-spa-deno`
- HEAD is `66f04e04`
- Diff `155e039e..HEAD` touches expected frontend tooling files only: `README.md`, `deno.json`, `deno.lock`, `package.json`, and deleted `package-lock.json`
- `git diff --check 155e039e..HEAD` produced no diagnostics。
- `git status --ignored --short web/workspace` showed no remaining generated frontend artifacts。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T11:06:03Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVMV03QY-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVMV03QY-workspace-spa-deno`
- Branch: `impl/00001KVMV03QY-workspace-spa-deno`
- Baseline: `155e039e`
- Implementation commit: `66f04e04 feat: migrate workspace spa tooling to deno`
- Diff: `155e039e..66f04e04`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Deno task check/build works from clean generated-artifact state。
- `deno.json` / `deno.lock` are canonical source of truth。
- `package.json` remains only compatibility metadata if retained; no npm scripts / Node-only guidance remains active。
- Static output path and Rust backend serving assumptions remain valid。
- Generated artifacts remain ignored/source-filtered and are not committed。
- No protocol/backend authority scope creep。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVMV03QY-r1 at: 2026-06-21T11:12:52Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVMV03QY/item.md`
- `.yoi/tickets/00001KVMV03QY/thread.md`
- Diff `155e039e..66f04e04`:
- `web/workspace/README.md`
- `web/workspace/deno.json`
- `web/workspace/deno.lock`
- `web/workspace/package.json`
- deleted `web/workspace/package-lock.json`
- Boundary / generated artifact files:
- `web/workspace/.gitignore`
- `web/workspace/svelte.config.js`
- `web/workspace/vite.config.ts`
- `web/workspace/tsconfig.json`
- `web/workspace/src/routes/+layout.ts`
- `package.nix`
- `devshell.nix`
Blocking issues:
- None。
Findings:
- Deno is now the clear frontend tooling source of truth:
- `web/workspace/deno.json` defines Deno tasks and pinned npm-compat dependencies。
- `web/workspace/deno.lock` is committed。
- `package-lock.json` is removed。
- `package.json` is reduced to package metadata only, with no scripts or dependencies。
- README explicitly says canonical tooling is `deno.json` / `deno.lock`, and `package.json` is compatibility metadata only。
- Static SPA assumptions are preserved:
- `svelte.config.js` still uses `@sveltejs/adapter-static`
- output remains `web/workspace/build/`
- `+layout.ts` still has `ssr = false` and `prerender = true`
- diff does not touch Rust backend/API authority, protocol reconnect scope, or `.yoi` canonical records。
- Generated artifact boundaries remain intact:
- `.gitignore` ignores `node_modules`, `.svelte-kit`, and `build`
- `package.nix` still excludes `web/workspace/node_modules`, `web/workspace/.svelte-kit`, and `web/workspace/build`
- `devshell.nix` already provides `deno`
Non-blocking concern:
- `deno task build` succeeds but upstream SvelteKit/Vite emits generic `Run npm run preview to preview your production build locally.` The project README and `deno.json` correctly provide `deno task preview`, and there are no npm scripts in the repo, so this is not blocking。
Reviewer validation:
- `git diff --check 155e039e..66f04e04`: passed
- `cd web/workspace && deno --version && rm -rf node_modules .svelte-kit build && deno task check && deno task build`: passed with Deno `2.7.14`; `svelte-check found 0 errors and 0 warnings`; build completed to `build`
- `cd web/workspace && deno task install`: passed
- `target/debug/yoi ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
- `git show --no-patch --format='%H %s' 66f04e04` and `git diff --quiet 66f04e04..HEAD`: HEAD matches implementation commit
Generated artifacts:
- Reviewer did not clean generated ignored artifacts after validation。
- Ignored artifacts present in implementation worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `git check-ignore -v` confirms all three are ignored by `web/workspace/.gitignore`; `package.nix` excludes same paths。
Worktree status:
- Tracked status clean at `66f04e04` on `impl/00001KVMV03QY-workspace-spa-deno`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:13:42Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `6dc78e3f merge: workspace spa deno tooling`
- Merged branch: `impl/00001KVMV03QY-workspace-spa-deno`
- Implementation commit:
- `66f04e04 feat: migrate workspace spa tooling to deno`
Orchestrator worktree validation:
- `git diff --check HEAD^1..HEAD`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed and wrote static site to `build/`
- `cd web/workspace && deno task install`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `6dc78e3f`
Non-blocking note:
- Upstream SvelteKit/Vite still prints generic `Run npm run preview...` during build; project README and `deno.json` provide `deno task preview`, and no npm scripts remain, so this is accepted as upstream output rather than project guidance。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T11:13:48Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、Deno check/build/install、workspace-server check、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T11:14:00Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T11:14:00Z status: closed -->
## 完了
Workspace web SPA の frontend tooling を npm/Node-primary から Deno-primary に移行し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `web/workspace/deno.json` を追加し、Deno task を canonical workflow にした。
- `web/workspace/deno.lock` を追加。
- `web/workspace/package-lock.json` を削除。
- `web/workspace/package.json` は SvelteKit/Vite ecosystem compatibility metadata のみに縮小し、scripts/dependencies を削除。
- README を Deno workflow (`deno install`, `deno task check`, `deno task build`, `deno task preview`) と source-of-truth 説明に更新。
- Static SPA output path `web/workspace/build/``@sveltejs/adapter-static` assumptions を維持。
- Rust backend/static serving code、Workspace API authority、Ticket/Objectives authority、`.yoi` canonical record workflows には変更を加えていない。
- Generated artifacts (`node_modules`, `.svelte-kit`, `build`) は ignored/source-filtered のまま。
統合・検証:
- Merge commit: `6dc78e3f merge: workspace spa deno tooling`
- Implementation commit: `66f04e04 feat: migrate workspace spa tooling to deno`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `deno task install`, `cargo check -p yoi-workspace-server`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Backend API / static serving implementation は変更していない。
- Protocol reconnect work (`00001KVMT2J25`) には触れていない。
- SSR / Deno runtime server / Deno Deploy assumptions は追加していない。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T11:14:27Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVMV03QY`
- `yoi-reviewer-00001KVMV03QY-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVMV03QY-workspace-spa-deno`
- Deleted implementation branch:
- `impl/00001KVMV03QY-workspace-spa-deno`
- Orchestrator worktree remains clean on `orchestration` at `54d325ae`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-161049-1","ticket_id":"00001KVNEKH9Q","kind":"accepted_plan","accepted_plan":{"summary":"Add read-only Workspace backend Host / Worker APIs over local Pod metadata/state, migrate/remove runners placeholder as needed, display Host/Worker list in static SPA, preserve Pod as implementation detail and avoid transcript/secret exposure.","branch":"impl/00001KVNEKH9Q-workspace-host-workers","worktree":"/home/hare/Projects/yoi/.worktree/00001KVNEKH9Q-workspace-host-workers","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates workspace-server/frontend/Nix as needed, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T16:10:49Z"}
@@ -0,0 +1,13 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KVNEKH9Q",
"kind": "related",
"target": "00001KVMFFYVX",
"note": "Extends workspace web control plane bootstrap with local host/worker inspection",
"author": "yoi ticket",
"at": "2026-06-21T16:01:33Z"
}
]
}
+69
View File
@@ -0,0 +1,69 @@
---
title: 'Workspace backend: expose local host and worker list'
state: 'closed'
created_at: '2026-06-21T16:00:49Z'
updated_at: '2026-06-21T16:39:43Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-21T16:09:10Z'
---
## 背景
Workspace web control plane は read-only API / static SPA / SQLite skeleton まで立ち上がっているが、実行環境の表示はまだ `runner` placeholder のままで、実際に稼働中の local Pod / session を表示できない。
当面の設計語は `Host` / `Worker` とする。
- Host: 実行環境。最初の実装では workspace backend が動いている local machine を表す。
- Worker: Host 上で動いている agent/runtime session。現行 local runtime では Pod に対応する。
- Pod: 現行 local implementation detail。API では `implementation.kind = "local_pod"` のように表現する。
初期実装では、現行 TUI dashboard / panel が local state を見るのと同じ感覚で、backend process が動いている host 上の local Pod metadata / socket/session state を read-only に検出し、Workspace API から host / worker 一覧を返す。これは hosted/multi-host runner protocol の完成を待たずに、Web UI で現在の local execution state を見られるようにするための bridge である。
## 要件
- Workspace backend API に host / worker list endpoint を追加する。
- 例: `GET /api/hosts`
- 例: `GET /api/hosts/{host_id}/workers` または `GET /api/workers`
- 既存 `runner` placeholder は `host` naming に寄せる。破壊的変更でよい。
- 初期 Host は backend process が動いている local machine として検出する。
- stable-ish `host_id`、label、kind/status、last_seen/observed_at、capability summary を返す。
- capability は詳細実装しすぎず、local pod inspection available / workspace_root / os など bounded summary でよい。
- Worker list は現行 local Pod state から read-only に生成する。
- `~/.yoi/pods/<pod_name>/metadata.json` などの現在の Pod metadata authority を使う。
- active socket/session/runtime hints は利用してよいが、metadata と session logs を壊さない。
- local Pod は Worker の implementation detail として返す。
- API response は Web/control-plane domain を優先する。
- `worker_id`
- `host_id`
- `label` / `pod_name`
- `role` or `profile` if known
- `workspace_root`
- `state` / `status` if known
- `implementation: { kind: "local_pod", pod_name: ... }`
- bounded diagnostics
- Secrets / prompt contents / session transcript contents / hidden metadata は返さない。
- backend が local Pod data dir を読めない場合は fail closed ではなく、empty list + diagnostic または host capability unavailable として返す。
- Web UI skeleton で host / worker list を表示できる範囲までつなぐ。
- これは remote/self-hosted/cloud runner protocol の実装ではない。将来の Host/Worker protocol に置き換えられる local bridge として実装する。
## Non-goals
- Worker start/stop/attach/notify 操作。
- remote runner / cloud runner registration protocol。
- Run と Worker の完全な紐付け。
- Pod metadata schema migration。
- session transcript / model context / tool result content の表示。
- Host resource scheduling / quota / billing。
## 受け入れ条件
- `GET /api/hosts` が backend-local Host を bounded JSON で返す。
- `GET /api/workers` または `GET /api/hosts/{host_id}/workers` が local Pod 由来の Worker 一覧を bounded JSON で返す。
- response naming は `host` / `worker` を使い、`pod` は implementation detail に閉じる。
- 既存 `/api/runners` placeholder は削除または `hosts` へ移行され、frontend / tests も追従している。
- Web UI に Host / Worker 一覧が表示される。
- local Pod metadata が存在しない環境でも API は安全に empty/diagnostic response を返す。
- secrets、session transcript、prompt contents は response に含まれない。
- Focused tests cover host list, worker list, missing local pod data dir, and response bounds/redaction.
- Validation before completion includes `cargo fmt --check`, `cargo test -p yoi-workspace-server`, frontend check/build, `cargo check`, `git diff --check`, `yoi ticket doctor`, and `nix build .#yoi --no-link`.
+22
View File
@@ -0,0 +1,22 @@
Workspace backend に local Host / Worker read API を追加し、Web UI に Host / Worker list を表示する変更を統合した。
主な成果:
- Workspace backend に `/api/hosts`, `/api/workers`, `/api/hosts/{host_id}/workers` を追加。
- `/api/runners` placeholder を削除 / Host-Worker naming に移行。
- Local Pod metadata を read-only bridge として Worker domain object に投影。
- Pod は primary domain ではなく `implementation: { kind: "local_pod", pod_name: ... }` として表現。
- Worker response includes bounded `worker_id`, `host_id`, label/pod name, role/profile when known, `workspace_root`, state/status, implementation detail, and diagnostics。
- Missing/unreadable Pod metadata root は process/server failure ではなく empty workers + bounded diagnostics / unavailable capability に degrade。
- Session transcript / tool result / prompt contents / raw session JSONL は読まない。
- Web UI static SPA に Host / Worker list を追加。
- Existing Ticket / Objective canonical workflows remain unchanged。
統合・検証:
- Merge commit: `c884d517 merge: workspace host workers`
- Implementation commit: `58143ead feat: expose workspace hosts and workers`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Remote/cloud runner registration, scheduling, start/stop/attach/notify operations, and full run-worker correlation were not implemented。
- Frontend remains static SPA and does not own backend business/lifecycle authority。
+393
View File
@@ -0,0 +1,393 @@
<!-- event: create author: "yoi ticket" at: 2026-06-21T16:00:49Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-21T16:01:33Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T16:01:33Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T16:09:10Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T16:10:32Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body は Workspace backend に local Host / Worker read API を追加し、Web UI skeleton に表示する範囲まで具体化されている。
- Related Ticket `00001KVMFFYVX` は Workspace web control plane bootstrap で、既に `closed` / integrated。This Ticket はその read-only API / SPA skeleton の自然な follow-up。
- Relation metadata は `related` のみで blocker relation はない。
- Current queued Ticket はこの Ticket のみ。
- Orchestrator worktree is clean on `orchestration` at `7abc3c77` before routing side effects; target worktree / branch is not present。
- Visible Pods に対象 Ticket の child Pod は存在しない。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct `item.md` read。
- `TicketRelationQuery(00001KVNEKH9Q)`: one non-blocking `related` relation to closed `00001KVMFFYVX`
- `TicketOrchestrationPlanQuery(00001KVNEKH9Q)`: no records。
- `TicketList(state=queued)`: this Ticket is the only queued Ticket。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `crates/workspace-server/src/{server.rs,store.rs,records.rs}` contains current read-only workspace/ticket/objective/runs/runners API skeleton。
- `web/workspace/src/routes/+page.svelte` currently renders workspace/tickets/objectives/runs/runners sections through Deno/SvelteKit frontend。
- `crates/pod-store/src/lib.rs` contains current Pod metadata authority (`{data_dir}/pods/<pod_name>/metadata.json`) and list/read helpers。
- `manifest::paths::data_dir()` resolves local data dir.
IntentPacket:
Intent:
- Extend the Workspace web control plane so it can display the local execution environment as Host / Worker domain objects, with local Pods exposed only as implementation details。
Binding decisions / invariants:
- API naming should prioritize Host / Worker; Pod remains implementation detail under `implementation.kind = "local_pod"` / `pod_name` fields。
- This is read-only local bridge over existing Pod metadata/state; do not mutate Pod metadata, session logs, Tickets, Objectives, or runtime state。
- Do not expose secrets, prompt contents, session transcript contents, tool result contents, or hidden metadata。
- Missing/unreadable local Pod data dir must degrade to empty worker list + bounded diagnostic or host capability unavailable, not a process-fatal error。
- Existing `.yoi` Ticket / Objective canonical workflows remain unchanged。
- This is not remote runner / cloud runner registration protocol, scheduling, start/stop/attach/notify, or full run-worker correlation。
- Existing `/api/runners` placeholder may be removed or migrated to host/worker naming; breaking API change is acceptable。
- Frontend remains static SPA; do not introduce SSR/business authority。
Requirements / acceptance criteria:
- `GET /api/hosts` returns backend-local Host as bounded JSON with stable-ish `host_id`, label, kind/status, observed/last-seen timestamp, and bounded capability summary。
- `GET /api/workers` or `GET /api/hosts/{host_id}/workers` returns Worker list from local Pod metadata/state。
- Worker response uses `worker_id`, `host_id`, `label`/`pod_name`, optional role/profile if known, `workspace_root`, state/status, `implementation: { kind: "local_pod", pod_name: ... }`, and bounded diagnostics。
- Local Pod metadata absence/unreadability yields safe empty/diagnostic response。
- `/api/runners` placeholder is removed or migrated to Host/Worker naming and tests/frontend are updated。
- Web UI displays Host / Worker list。
- Focused tests cover host list, worker list, missing local Pod data dir, and redaction/bounds。
Implementation latitude:
- Reuse `pod-store` crate for metadata listing if practical; otherwise use a narrow read-only adapter with the same authority/path semantics。
- Host id can be deterministic local id derived from workspace/data-dir/machine label if no existing host id exists; keep it stable-ish and non-secret。
- Worker status can be coarse from metadata active flag / socket hint if available; avoid live socket probing unless bounded and read-only。
- Runners placeholder can be removed or preserved only as compatibility alias if clearly documented; Ticket allows breaking migration to host naming。
- Frontend UI can be simple table/cards; prioritize data shape and redaction over visual polish。
Escalate if:
- Pod metadata schema lacks enough information to derive bounded worker fields without reading session transcripts。
- Need to read session JSONL contents to satisfy requested fields。
- Host id generation would require storing new durable host metadata in `.yoi`
- Existing frontend/backend API shape requires a broad redesign beyond local bridge。
- Deno/frontend tooling or package/Nix changes become unrelatedly unstable。
Validation plan:
- `cargo fmt --check`
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi-workspace-server`
- frontend: `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link` if package/source-filter/frontend/dependency handling changed; otherwise strongly preferred because Workspace backend/frontend package surface is touched。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T16:10:40Z from: queued to: inprogress reason: human_authorized_unblocked_host_worker_api_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria, related bootstrap work is complete, and no blockers are recorded, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:11:47Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNEKH9Q-workspace-host-workers`
- Created branch:
- `impl/00001KVNEKH9Q-workspace-host-workers`
- Base commit:
- `e1f02ffc ticket: accept workspace host workers`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVNEKH9Q`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVNEKH9Q-workspace-host-workers`
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:31:48Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVNEKH9Q`.
Implementation commit:
- `58143ead feat: expose workspace hosts and workers`
Changed areas observed by Orchestrator:
- `crates/workspace-server/src/hosts.rs` added:
- Host / Worker API domain models and local Pod metadata bridge。
- Safe degradation for missing/unreadable Pod metadata directory via bounded diagnostics。
- Redaction/bounding tests。
- `crates/workspace-server/src/server.rs` updated:
- Host / Worker API routes added。
- `/api/runners` placeholder removed/migrated away from runner naming。
- Tests updated for host/worker API and static/API separation。
- `crates/workspace-server/src/store.rs` updated:
- Runners placeholder removed。
- `web/workspace/src/routes/+page.svelte` updated:
- UI displays Host / Worker list instead of runners placeholder。
- Package/dependency updates:
- `crates/workspace-server/Cargo.toml`
- `Cargo.lock`
- `package.nix`
Orchestrator evidence checked:
- Implementation worktree clean on `impl/00001KVNEKH9Q-workspace-host-workers`
- HEAD is `58143ead`
- Diff `e1f02ffc..HEAD` touches 8 expected backend/frontend/package files, about 913 insertions / 75 deletions。
- `git diff --check e1f02ffc..HEAD` produced no diagnostics。
- Validation had produced ignored frontend artifacts in child worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Orchestrator removed those ignored artifacts before reviewer routing; tracked worktree remains clean。
Next action:
- Route to read-only Reviewer Pod for acceptance review against the Ticket。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T16:32:22Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVNEKH9Q-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVNEKH9Q-workspace-host-workers`
- Branch: `impl/00001KVNEKH9Q-workspace-host-workers`
- Baseline: `e1f02ffc`
- Implementation commit: `58143ead feat: expose workspace hosts and workers`
- Diff: `e1f02ffc..58143ead`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Host / Worker API domain shape and redaction/bounding。
- Safe read-only local Pod metadata bridge。
- Missing/unreadable Pod metadata dir degradation。
- `/api/runners` placeholder migration/removal and frontend/test updates。
- Static SPA displays Host / Worker list without backend authority changes。
- Package/Nix/frontend generated artifact hygiene。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVNEKH9Q-r1 at: 2026-06-21T16:38:05Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVNEKH9Q/item.md`
- `.yoi/tickets/00001KVNEKH9Q/thread.md`
- Diff/changed areas `e1f02ffc..58143ead`:
- `crates/workspace-server/src/hosts.rs`
- `crates/workspace-server/src/server.rs`
- `crates/workspace-server/src/store.rs`
- `crates/workspace-server/src/lib.rs`
- `crates/workspace-server/src/main.rs`
- `crates/workspace-server/Cargo.toml`
- `Cargo.lock`
- `package.nix`
- `web/workspace/src/routes/+page.svelte`
- `web/workspace/svelte.config.js`
- Supporting inspection:
- `crates/pod-store/src/lib.rs`
- `runners` references and session/prompt/tool-result exposure grep。
Blocking issues:
- None。
Acceptance verification:
- API domain naming is Host / Worker:
- Routes added for `/api/hosts`, `/api/workers`, and `/api/hosts/{host_id}/workers`
- `/api/runners` placeholder is removed and test-covered as `404`
- Local Pods are implementation detail:
- Worker model exposes domain fields (`worker_id`, `host_id`, `label`, `state`, `status`, etc.)。
- Pod-specific detail is limited to `pod_name` and `implementation: { kind: "local_pod", pod_name: ... }`
- Local Pod bridge is read-only:
- Reads local Pod `metadata.json` under configured local data dir。
- No mutation of Pod runtime metadata, session logs, Tickets, or Objectives observed。
- Redaction / sensitive data:
- No session JSONL/transcript/tool-result/prompt content reads introduced。
- `resolved_manifest_snapshot` is not serialized wholesale; role/profile extraction is bounded/sanitized。
- Tests include a snapshot containing `secret_token` / `system_prompt` and assert they are not returned。
- Missing/unreadable metadata degradation:
- Missing Pod metadata root returns empty workers plus bounded diagnostics。
- Host capability degrades to unavailable instead of failing the server。
- Frontend:
- Static Svelte page fetches/displays Hosts and Workers。
- No SSR/business authority addition observed。
- Existing Ticket/Objective workflows remain preserved; `ticket doctor` passes。
Non-blocking concerns:
- None。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check e1f02ffc..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`6 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed (`svelte-check found 0 errors and 0 warnings`; static build completed)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Generated artifacts:
- Frontend validation produced ignored generated artifacts only:
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `web/workspace/node_modules/`
- Reviewer did not clean them due review-only scope; they are ignored and not tracked。
Worktree status:
- Tracked/untracked status is clean on `impl/00001KVNEKH9Q-workspace-host-workers`
- Ignored generated frontend artifacts remain as listed above。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:38:57Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `c884d517 merge: workspace host workers`
- Merged branch: `impl/00001KVNEKH9Q-workspace-host-workers`
- Implementation commit:
- `58143ead feat: expose workspace hosts and workers`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `c884d517`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T16:39:02Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、workspace-server tests/check、Deno check/build、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T16:39:15Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T16:39:15Z status: closed -->
## 完了
Workspace backend に local Host / Worker read API を追加し、Web UI に Host / Worker list を表示する変更を統合した。
主な成果:
- Workspace backend に `/api/hosts`, `/api/workers`, `/api/hosts/{host_id}/workers` を追加。
- `/api/runners` placeholder を削除 / Host-Worker naming に移行。
- Local Pod metadata を read-only bridge として Worker domain object に投影。
- Pod は primary domain ではなく `implementation: { kind: "local_pod", pod_name: ... }` として表現。
- Worker response includes bounded `worker_id`, `host_id`, label/pod name, role/profile when known, `workspace_root`, state/status, implementation detail, and diagnostics。
- Missing/unreadable Pod metadata root は process/server failure ではなく empty workers + bounded diagnostics / unavailable capability に degrade。
- Session transcript / tool result / prompt contents / raw session JSONL は読まない。
- Web UI static SPA に Host / Worker list を追加。
- Existing Ticket / Objective canonical workflows remain unchanged。
統合・検証:
- Merge commit: `c884d517 merge: workspace host workers`
- Implementation commit: `58143ead feat: expose workspace hosts and workers`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Remote/cloud runner registration, scheduling, start/stop/attach/notify operations, and full run-worker correlation were not implemented。
- Frontend remains static SPA and does not own backend business/lifecycle authority。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:39:43Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVNEKH9Q`
- `yoi-reviewer-00001KVNEKH9Q-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNEKH9Q-workspace-host-workers`
- Deleted implementation branch:
- `impl/00001KVNEKH9Q-workspace-host-workers`
- Orchestrator worktree remains clean on `orchestration` at `a4ed5fb0`
Root/original workspace was not used for merge/validation/cleanup operations。
Note for related active work:
- `00001KVNG9B9Z` sidebar UI work was branched before this merge and may need to integrate the Host/Worker UI/API changes from `c884d517` during review/merge。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260621-163647-1","ticket_id":"00001KVNG9B9Z","kind":"accepted_plan","accepted_plan":{"summary":"Add left sidebar navigation skeleton to `web/workspace` static SPA with workspace header/settings placeholder, repositories/objectives/workers sections, objectives API read, workers placeholder/API boundary, responsive layout, and section-level error/empty states while avoiding backend authority changes.","branch":"impl/00001KVNG9B9Z-workspace-sidebar","worktree":"/home/hare/Projects/yoi/.worktree/00001KVNG9B9Z-workspace-sidebar","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope frontend Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, resolving any conflict with Host/Worker work if it has merged, validates Deno/frontend/Nix as needed, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T16:36:47Z"}
@@ -0,0 +1,21 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KVNG9B9Z",
"kind": "related",
"target": "00001KVMFFYVX",
"note": "Extends workspace web control plane bootstrap with initial navigation UI",
"author": "yoi ticket",
"at": "2026-06-21T16:30:49Z"
},
{
"ticket_id": "00001KVNG9B9Z",
"kind": "related",
"target": "00001KVNEKH9Q",
"note": "Workers section will consume or placeholder the local host/worker API",
"author": "yoi ticket",
"at": "2026-06-21T16:30:49Z"
}
]
}
+72
View File
@@ -0,0 +1,72 @@
---
title: 'Workspace web UI: add sidebar navigation panel'
state: 'closed'
created_at: '2026-06-21T16:30:12Z'
updated_at: '2026-06-21T17:01:46Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-21T16:35:06Z'
---
## 背景
Workspace web UI は static SPA skeleton と read-only API まで立ち上がっている。次に、Workspace control plane の基本情報へ移動するための左サイドパネルを作り、Workspace / Repository / Objective / Worker を一覧できる最初の navigation surface を用意する。
初期イメージ:
```text
my-workspace ⚙
---
repositories
- yoi
objectives
---
<workers list>
```
この Ticket は UX skeleton の実装を対象にする。深い編集機能や complex layout はまだ扱わず、Web UI の基本構造を早めに固定する。
## 要件
- Workspace web SPA に左サイドパネルを追加する。
- サイドパネル上部に workspace name / label を表示する。
- 例: `my-workspace`
- 右側に settings entry point として `⚙` または同等の icon/button を置く。
- settings は初期実装では disabled / placeholder / diagnostics panel でもよい。
- `repositories` section を表示する。
- 初期は API 由来の Repository list が未実装なら placeholder / local workspace repository summary でよい。
- 既存 API に合わせて、後続で Repository API に接続しやすい component boundary にする。
- `objectives` section を表示する。
- 既存 `/api/objectives` から objective list を取得して表示する。
- title と state が分かる最小表示でよい。
- `workers` section を表示する。
- `00001KVNEKH9Q` の Host/Worker API が入る前は placeholder でよい。
- API が存在する場合は `GET /api/workers` または `GET /api/hosts/.../workers` に接続できるよう component boundary を分ける。
- 表示名は `workers` とし、Pod は implementation detail として出さない。
- main content とは layout を分け、サイドパネルが常時表示される基本構成にする。
- narrow viewport では壊れない最低限の responsive behavior を持つ。
- 初期は横スクロール回避 / fixed min-width 程度でよい。
- API failure は sidebar 全体を落とさず、section ごとに bounded error / empty state を表示する。
- style は現行 skeleton に合わせ、過剰な design system 化はしない。
## Non-goals
- settings 画面の本実装。
- Repository CRUD / Repository API の本実装。
- Objective detail/edit UI。
- Worker start/stop/attach 操作。
- drag-and-drop / collapsible tree / complex navigation。
- auth / multi-workspace switcher。
## 受け入れ条件
- Workspace web UI に左サイドパネルが表示される。
- sidebar header に workspace name と settings placeholder が表示される。
- `repositories` / `objectives` / `workers` の section が表示される。
- Objectives section は existing `/api/objectives` 由来の data を表示する。
- Workers section は Host/Worker API 未実装でも placeholder として安全に表示され、API 接続を後で差し替えやすい component boundary になっている。
- API failure / empty state が section 単位で表示される。
- `deno task check``deno task build` が通る。
- `cargo test -p yoi-workspace-server` または backend 変更がある場合の relevant tests が通る。
- `git diff --check``yoi ticket doctor``nix build .#yoi --no-link` が通る。
+26
View File
@@ -0,0 +1,26 @@
Workspace web UI に sidebar navigation panel を追加し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `web/workspace/src/lib/workspace-sidebar/` に sidebar components を追加:
- `WorkspaceSidebar.svelte`
- `RepositoriesNavSection.svelte`
- `ObjectivesNavSection.svelte`
- `WorkersNavSection.svelte`
- `types.ts`
- `web/workspace/src/routes/+page.svelte` を sidebar + main content の responsive two-column layout に更新。
- Sidebar header に workspace label/name と disabled settings placeholder を表示。
- `repositories`, `objectives`, `workers` sections を追加。
- Objectives section は `/api/objectives` を読み、title/state と empty/error states を section-local に表示。
- Workers section は `/api/workers` を読み、Worker label/state/status/role を表示し、Pod を primary UI naming として露出しない。
- Repository section は future Repository API に繋げやすい placeholder seam として実装。
- Host/Worker API/UI merge 後の `+page.svelte` conflict を解消し、main Host/Worker content と sidebar skeleton を両方維持。
- Backend/API authority, SSR, mutation/business logic は追加していない。
統合・検証:
- Merge commit: `613f4126 merge: workspace sidebar navigation`
- Implementation commits: `d3b8bdfd`, `4ab696b4`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `cargo test -p yoi-workspace-server`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Settings page, Repository CRUD/API, Objective edit/detail UI, Worker start/stop/attach controls, drag/drop/collapsible tree, auth, multi-workspace switcher は実装していない。
+388
View File
@@ -0,0 +1,388 @@
<!-- event: create author: "yoi ticket" at: 2026-06-21T16:30:12Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-21T16:30:49Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T16:30:49Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T16:35:06Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T16:36:30Z -->
## Decision
Routing decision: `implementation_ready_parallel_with_conflict_risk`
Reason:
- Ticket body は Workspace web UI に左 sidebar navigation panel を追加する UX skeleton として、header / repositories / objectives / workers sections、responsive behavior、section-level error handling、Deno validation まで具体化されている。
- Relations are `related` only to `00001KVMFFYVX` and `00001KVNEKH9Q`; no blocking dependency is recorded。
- `00001KVMFFYVX` is closed/integrated。
- `00001KVNEKH9Q` is currently in review and touches Host/Worker API plus `web/workspace/src/routes/+page.svelte`; this creates merge-conflict risk but not an authority blocker. Ticket body explicitly allows Workers section to be placeholder before Host/Worker API exists and asks for component boundary that can later connect to that API。
- Current queued Ticket is this Ticket only。
- Orchestrator worktree is clean on `orchestration` at `d4de8e26`; target worktree / branch is not present。
Evidence checked:
- Ticket body via direct `item.md` read。
- `relations.json`: related to `00001KVMFFYVX` and `00001KVNEKH9Q` only。
- `TicketOrchestrationPlanQuery(00001KVNG9B9Z)`: no records。
- `TicketList(state=queued)`: this Ticket is the only queued Ticket。
- `00001KVNEKH9Q` current state is `inprogress` / reviewer running; no approval/merge yet。
- Orchestrator git state / worktree list / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
IntentPacket:
Intent:
- Add a left sidebar navigation skeleton to Workspace web SPA that surfaces Workspace / Repository / Objective / Worker navigation without adding deep editing or business authority。
Binding decisions / invariants:
- Frontend-only UI skeleton unless a minimal API read is already available; do not change backend authority without need。
- Keep static SPA; no SSR or frontend lifecycle/business authority。
- Objective section should read existing `/api/objectives` and display bounded title/state data。
- Worker section should use a component/data boundary that can connect to Host/Worker API, but must safely show placeholder/empty/error if API is absent or in flux。
- Do not expose Pod as primary UI/domain naming; use `workers`
- API failures are section-local and must not take down the whole page。
- Avoid broad design-system churn; keep current skeleton style direction。
- Be aware that `00001KVNEKH9Q` may merge Host/Worker UI/API changes concurrently; keep sidebar changes narrow and componentized to reduce conflict。
Requirements / acceptance criteria:
- Left sidebar is visible in Workspace web UI。
- Sidebar header displays workspace name/label plus settings placeholder/icon/button。
- Sections present: `repositories`, `objectives`, `workers`
- Objectives section fetches existing `/api/objectives` and displays title/state minimal info。
- Workers section safely displays placeholder/empty/error if Host/Worker API is not yet integrated; if API is available in branch, it may use it through a component boundary。
- Main content and sidebar layout are separated and responsive enough to avoid narrow-viewport breakage / horizontal overflow。
- Section-level error/empty states are bounded。
- Deno check/build passes。
Implementation latitude:
- Split Svelte components under `web/workspace/src/lib` if useful。
- Keep repository section placeholder/local summary if no Repository API exists。
- Use simple CSS layout; no full design system。
- If concurrent `00001KVNEKH9Q` merge creates conflict, report rather than broad rewrite。
Escalate if:
- Implementing sidebar requires backend API redesign beyond minimal frontend skeleton。
- Workers section cannot be safely decoupled from unmerged Host/Worker API。
- Deno/Svelte tooling fails for reasons unrelated to this Ticket。
- Merge conflict with `00001KVNEKH9Q` becomes non-trivial and requires orchestration sequencing。
Validation plan:
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link` preferred because Workspace frontend package surface is touched。
- `cargo test -p yoi-workspace-server` only if backend code changes。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T16:36:37Z from: queued to: inprogress reason: human_authorized_unblocked_sidebar_ui_implementation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete frontend acceptance criteria and no blocking relation; related Host/Worker API work is in review and creates merge-conflict risk but not an authority blocker. Orchestrator accepts implementation with narrow frontend scope.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:37:34Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNG9B9Z-workspace-sidebar`
- Created branch:
- `impl/00001KVNG9B9Z-workspace-sidebar`
- Base commit:
- `2c7ef24a ticket: accept workspace sidebar ui`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVNG9B9Z`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVNG9B9Z-workspace-sidebar`
Parallelization note:
- `00001KVNEKH9Q` remains active in review and may merge Host/Worker API plus `web/workspace/src/routes/+page.svelte` changes. Coder was instructed to keep sidebar work narrow/componentized and report if conflicts become non-trivial。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T16:54:08Z -->
## Implementation report
Coder conflict-resolution report received from `yoi-coder-00001KVNG9B9Z`.
Final implementation HEAD:
- `4ab696b4` merge commit from current `orchestration` into `impl/00001KVNG9B9Z-workspace-sidebar`
Relevant commits:
- `d3b8bdfd feat: add workspace sidebar skeleton`
- `4ab696b4` merge/conflict-resolution commit
Conflict resolution summary:
- Resolved `web/workspace/src/routes/+page.svelte` conflict after Host/Worker API/UI from `00001KVNEKH9Q` landed。
- Preserved merged Host/Worker main content/cards/table。
- Preserved sidebar navigation skeleton。
- Updated sidebar Workers section to consume available `/api/workers` response through typed `ListResponse<Worker>`
- Kept Pod naming out of sidebar, presenting workers by label/state/status/role。
- Changes remain scoped to Workspace frontend。
Coder validation reported:
- `cd web/workspace && deno task check`: passed
- `cd web/workspace && deno task build`: passed
- `git diff --check`: passed
- `git diff --check orchestration..HEAD`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed
- `cargo test -p yoi-workspace-server`: not run because backend code was not changed during conflict resolution
Generated artifact cleanup:
- Coder removed generated/ignored frontend artifacts after validation:
- `web/workspace/.svelte-kit`
- `web/workspace/build`
- `web/workspace/node_modules`
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVNG9B9Z-workspace-sidebar` at `4ab696b4`
- Diff `orchestration..HEAD` touches expected frontend files only: new `web/workspace/src/lib/workspace-sidebar/*` components and `web/workspace/src/routes/+page.svelte`
- `git diff --check orchestration..HEAD`: passed。
- Merge-tree conflict scan vs current `orchestration`: no conflict markers / no changed-in-both diagnostics。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T16:54:49Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVNG9B9Z-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVNG9B9Z-workspace-sidebar`
- Branch: `impl/00001KVNG9B9Z-workspace-sidebar`
- Current implementation HEAD: `4ab696b4`
- Implementation commits:
- `d3b8bdfd feat: add workspace sidebar skeleton`
- `4ab696b4` merge/conflict-resolution commit from current `orchestration`
- Primary review diff: `orchestration..HEAD` inside implementation worktree, so review sees final sidebar changes on top of current Host/Worker API/UI state。
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Sidebar visibility/layout/responsive behavior。
- Workspace header/settings placeholder。
- Repositories/objectives/workers sections。
- Objective and worker section bounded loading/empty/error handling。
- Worker naming avoids Pod-primary UI。
- Main Host/Worker content from `00001KVNEKH9Q` remains preserved after conflict resolution。
- No backend authority/SSR/business logic changes。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVNG9B9Z-r1 at: 2026-06-21T17:00:16Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVNG9B9Z/item.md`
- `.yoi/tickets/00001KVNG9B9Z/thread.md`
- Implementation diff:
- `git diff --name-status orchestration..HEAD`
- implementation-only diff against merge-base `a607a1f20d0622b1f556c36cca155da68109fe25..HEAD`
- Frontend files:
- `web/workspace/src/routes/+page.svelte`
- `web/workspace/src/lib/workspace-sidebar/WorkspaceSidebar.svelte`
- `web/workspace/src/lib/workspace-sidebar/RepositoriesNavSection.svelte`
- `web/workspace/src/lib/workspace-sidebar/ObjectivesNavSection.svelte`
- `web/workspace/src/lib/workspace-sidebar/WorkersNavSection.svelte`
- `web/workspace/src/lib/workspace-sidebar/types.ts`
- API shape spot-check:
- `crates/workspace-server/src/server.rs`
- `crates/workspace-server/src/hosts.rs`
- `crates/workspace-server/src/records.rs`
Blocking issues:
- None。
Acceptance verification:
- Left sidebar is wired into `+page.svelte` and layout is separated from main content。
- Sidebar header shows workspace label/name and disabled settings placeholder。
- `repositories`, `objectives`, and `workers` sections are present。
- Objectives section fetches `/api/objectives` and handles loading/error/empty locally。
- Workers section fetches `/api/workers`, uses Worker naming in visible UI, and handles 404/empty/error locally。
- Main Host/Worker content from current orchestration branch is preserved。
- No backend/API authority changes were introduced by the implementation-only diff。
- Responsive CSS uses a two-column layout on wide viewports and single-column layout below 760px, with `min-width: 0`, wrapping, and table overflow containment。
Non-blocking concerns:
- `orchestration..HEAD` currently shows apparent `.yoi/tickets/00001KVNG9B9Z/item.md` / `thread.md` reversions because `orchestration` has newer review-routing/report commits after the implementation branchs merge-base. The implementation-only diff against the merge-base is frontend-only, and `git merge-tree --write-tree orchestration HEAD` reports a clean merge. This should not block a normal merge, but avoid applying the literal `orchestration..HEAD` patch/squash in a way that drops newer ticket thread entries。
Reviewer validation:
- `git diff --check`: passed
- `git diff --check orchestration..HEAD`: passed
- `git diff --check $(git merge-base orchestration HEAD)..HEAD`: passed
- `cd web/workspace && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed; static adapter wrote site to `build`
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
- `cargo test -p yoi-workspace-server`: passed (`6 passed; 0 failed`)
- `git merge-tree --write-tree orchestration HEAD`: passed with status 0; produced merged tree `24e0e026264333fc63d60c0e2d649839445acb64`
Generated artifacts:
- Reviewer did not clean generated ignored artifacts after validation:
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `web/workspace/node_modules/`
- They are ignored and not tracked; `git ls-files --others --exclude-standard` reports `0`
Worktree status:
- Clean tracked state on `impl/00001KVNG9B9Z-workspace-sidebar` at `4ab696b4`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:00:46Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `613f4126 merge: workspace sidebar navigation`
- Merged branch: `impl/00001KVNG9B9Z-workspace-sidebar`
- Implementation commits:
- `d3b8bdfd feat: add workspace sidebar skeleton`
- `4ab696b4` merge/conflict-resolution commit from current `orchestration`
Orchestrator worktree validation:
- `git diff --check HEAD^1..HEAD`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo test -p yoi-workspace-server`: passed (`6 passed`)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `613f4126`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T17:00:59Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、Deno check/build、workspace-server tests、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T17:01:13Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T17:01:13Z status: closed -->
## 完了
Workspace web UI に sidebar navigation panel を追加し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `web/workspace/src/lib/workspace-sidebar/` に sidebar components を追加:
- `WorkspaceSidebar.svelte`
- `RepositoriesNavSection.svelte`
- `ObjectivesNavSection.svelte`
- `WorkersNavSection.svelte`
- `types.ts`
- `web/workspace/src/routes/+page.svelte` を sidebar + main content の responsive two-column layout に更新。
- Sidebar header に workspace label/name と disabled settings placeholder を表示。
- `repositories`, `objectives`, `workers` sections を追加。
- Objectives section は `/api/objectives` を読み、title/state と empty/error states を section-local に表示。
- Workers section は `/api/workers` を読み、Worker label/state/status/role を表示し、Pod を primary UI naming として露出しない。
- Repository section は future Repository API に繋げやすい placeholder seam として実装。
- Host/Worker API/UI merge 後の `+page.svelte` conflict を解消し、main Host/Worker content と sidebar skeleton を両方維持。
- Backend/API authority, SSR, mutation/business logic は追加していない。
統合・検証:
- Merge commit: `613f4126 merge: workspace sidebar navigation`
- Implementation commits: `d3b8bdfd`, `4ab696b4`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `cargo test -p yoi-workspace-server`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Settings page, Repository CRUD/API, Objective edit/detail UI, Worker start/stop/attach controls, drag/drop/collapsible tree, auth, multi-workspace switcher は実装していない。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:01:46Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVNG9B9Z`
- `yoi-reviewer-00001KVNG9B9Z-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNG9B9Z-workspace-sidebar`
- Deleted implementation branch:
- `impl/00001KVNG9B9Z-workspace-sidebar`
- Orchestrator worktree remains clean on `orchestration` at `c29eba0c`
Root/original workspace was not used for merge/validation/cleanup operations。
Follow-up note:
- `00001KVNGJPRG` had been left queued behind this sidebar work due `do_not_parallelize`; this blocker is now cleared for re-routing on top of the settled sidebar/navigation structure。
---
@@ -0,0 +1,2 @@
{"id":"orch-plan-20260621-164056-1","ticket_id":"00001KVNGJPRG","kind":"do_not_parallelize","related_ticket":"00001KVNG9B9Z","note":"Repository/objective pages and sidebar navigation both modify the Workspace SPA navigation/layout surface, especially `web/workspace/src/routes/+page.svelte` and route/component structure. Start this Ticket after `00001KVNG9B9Z` lands or after its implementation diff is known enough to route a non-conflicting continuation.","author":"yoi-orchestrator","at":"2026-06-21T16:40:56Z"}
{"id":"orch-plan-20260621-170253-2","ticket_id":"00001KVNGJPRG","kind":"accepted_plan","accepted_plan":{"summary":"Add read-only current-workspace Repository APIs/pages with bounded Git summary/log and Ticket Kanban, plus Objective list page and sidebar links, preserving filesystem Ticket/Objective authority and static SPA boundaries.","branch":"impl/00001KVNGJPRG-repository-objective-pages","worktree":"/home/hare/Projects/yoi/.worktree/00001KVNGJPRG-repository-objective-pages","role_plan":"Orchestrator creates a dedicated child worktree from current sidebar-integrated `orchestration` and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates workspace-server/frontend/Nix, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-21T17:02:53Z"}
@@ -0,0 +1,21 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KVNGJPRG",
"kind": "related",
"target": "00001KVMFFYVX",
"note": "Extends workspace web bootstrap with repository/objective pages",
"author": "yoi ticket",
"at": "2026-06-21T16:36:06Z"
},
{
"ticket_id": "00001KVNGJPRG",
"kind": "related",
"target": "00001KVNG9B9Z",
"note": "Sidebar navigation should link to repository and objective pages",
"author": "yoi ticket",
"at": "2026-06-21T16:36:06Z"
}
]
}
+83
View File
@@ -0,0 +1,83 @@
---
title: 'Workspace web: repository and objective pages'
state: 'closed'
created_at: '2026-06-21T16:35:19Z'
updated_at: '2026-06-21T17:31:43Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-21T16:40:35Z'
---
## 背景
Workspace web control plane の初期段階では、Ticket / Objective の操作系が Web で十分に実装され、移行できる状態になるまでは、既存 `.yoi/tickets` / `.yoi/objectives` の filesystem record を read-through authority として扱う。
SQLite は Workspace server の runtime/projection/store seam として使うが、Ticket / Objective の canonical write path を中途半端に DB へ移さない。少なくとも Ticket 作成・コメント・状態遷移・close、Objective 作成/更新、validation/audit が Web/API 側で成立するまでは、Web UI は filesystem records を読む方向で進める。
次の UI slice として、Workspace sidebar から遷移できる Repository page と Objective list page を追加する。
Repository page では、当面は backend が動いている Workspace root の Git repository を primary Repository として扱う。Git repository である場合は、簡易的な Git 情報、直近 log、Repository に関係する Ticket の Kanban view を表示する。Repository target metadata がまだ Ticket schema に十分無い場合は、初期実装では workspace-local tickets 全体または既存 metadata から安全に導ける範囲を表示し、target selector 対応は follow-up にできる。
## 方針
- Ticket / Objective は当面 filesystem read-through で表示する。
- Web UI からの mutation / DB migration は、この Ticket の主目的にしない。
- Repository は Git 専売の概念ではないが、初期 page は Git Repository の read-only summary から始める。
- Repository page は将来の Repository provider / RepositoryPoint / target selector model に繋がる形にする。
- Ticket Kanban は Ticket state を column として表示する。
- Objective list は existing `/api/objectives` を使い、Objective の title/state/summary を一覧できるようにする。
## 要件
### Backend / API
- Repository list/detail の read-only API を追加する、または既存 `/api/workspace` に必要最小限の Repository summary を追加する。
- 初期は current workspace root を 1 つの local Repository として返してよい。
- Git repository の場合は branch/head/root/dirty status/remote URL summary などを bounded に返す。
- Git でない場合は `kind = "local"` / `git = unavailable` 相当の diagnostic を返す。
- Git log summary API を追加する。
- 直近 N 件だけ返す。
- commit hash、subject、author name/email の扱い、timestamp を bounded にする。
- full diff / patch / file contents は返さない。
- Repository Ticket Kanban 用の read model を追加する。
- 初期は Ticket state ごとに group した bounded list でよい。
- Ticket target Repository metadata がない場合の fallback を明記する。
- 将来 target selector が入ったら Repository ごとの filter に差し替えられる形にする。
- Objective list/detail は既存 filesystem read-through API を継続利用する。
### Frontend
- Sidebar の `repositories` section から Repository page に遷移できる。
- Repository page を追加する。
- Repository summary。
- Git summary / recent log。
- Ticket Kanban columns。
- API failure / non-Git / empty tickets を section 単位で表示。
- Objective list page を追加する。
- Objective title/state/updated_at などの一覧。
- Objective detail への遷移は可能なら行う。無理なら placeholder でよい。
- UI は static SPA のまま実装し、frontend に authority logic を持たせない。
## Non-goals
- Ticket / Objective の DB canonical migration。
- Web からの Ticket mutation / Objective mutation。
- Repository CRUD / remote Git hosting integration。
- Full Git diff viewer / file browser / blame。
- Ticket target selector schema の完成。
- Multi-repository selection UI の完成。
- Kanban drag-and-drop / state mutation。
## 受け入れ条件
- Ticket / Objective は引き続き filesystem read-through authority から表示される。
- Repository page が表示できる。
- Git repository の場合、Repository summary と recent log が bounded に表示される。
- Repository Ticket Kanban が state columns で表示される。
- Ticket target metadata が未整備でも安全な fallback 表示になる。
- Objective list page が表示できる。
- Sidebar から repositories / objectives に遷移できる。
- API failure、non-Git repository、empty state が UI で壊れず表示される。
- `deno task check``deno task build` が通る。
- backend 変更がある場合は `cargo test -p yoi-workspace-server` が通る。
- `cargo fmt --check``cargo check``git diff --check``yoi ticket doctor``nix build .#yoi --no-link` が通る。
+30
View File
@@ -0,0 +1,30 @@
Workspace web に Repository / Objective pages を追加し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Read-only Repository backend APIs を追加:
- `/api/repositories`
- `/api/repositories/local`
- `/api/repositories/local/log`
- `/api/repositories/local/tickets`
- Current workspace root を local Repository として扱う bounded repository summary を追加。
- Git repository では bounded branch/head/root/dirty/remote/recent log summary を返す。
- Non-Git workspace では `git.status = unavailable` と bounded diagnostics に degrade。
- Git log summary は recent commit hash/subject/author/timestamp に限定し、diff/patch/file content/blame/config は読まない。
- Remote URL summary は URL-scheme userinfo を redact。
- Read-only Ticket Kanban を Ticket state ごとに grouping し、workspace-local Ticket fallback diagnostic を含めた。
- Objective list summaries を filesystem Objective records から追加。
- Static SPA に hash-navigation Repository / Objectives pages を追加。
- Sidebar Repository/Objectives links を新 pages に接続。
- Repository page に summary, Git summary/log, diagnostics, read-only Ticket Kanban を表示。
- Objective page に title/state/updated_at/summary と detail placeholder links を表示。
- Ticket / Objective canonical authority remains filesystem read-through records; mutation API / DB canonical migration は追加していない。
統合・検証:
- Merge commit: `7ee702b1 merge: repository objective pages`
- Implementation commit: `ceb1ee3b feat: add repository objective pages`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外 / follow-up notes:
- Repository CRUD/API, Objective edit/detail mutation, full Git browser/diff/file views, drag/drop Kanban, and write APIs were not implemented。
- Reviewer noted possible follow-ups: keep `#/objectives` sidebar link visible even on objective empty/error states, and further tighten remote URL sanitization for query-param or SCP-like token forms if needed。
+414
View File
@@ -0,0 +1,414 @@
<!-- event: create author: "yoi ticket" at: 2026-06-21T16:35:19Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-21T16:36:06Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T16:36:06Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-21T16:40:35Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T16:41:09Z -->
## Decision
Routing decision: `wait_do_not_parallelize_with_sidebar`
Reason:
- Ticket body is implementation-ready in isolation, but it is directly coupled to the currently active sidebar navigation work `00001KVNG9B9Z`
- Relations show this Ticket is related to `00001KVNG9B9Z` with note: “Sidebar navigation should link to repository and objective pages”。
- `00001KVNG9B9Z` is already `inprogress`, has a live Coder Pod, and is expected to change `web/workspace/src/routes/+page.svelte` / sidebar component structure。
- Starting this Ticket in parallel now would likely produce overlapping route/layout/sidebar changes and non-trivial semantic merge work, rather than independent implementation。
- Host/Worker API work `00001KVNEKH9Q` just landed, further increasing the need to base the page/navigation work on current SPA state。
Decision:
- Do not create a worktree or spawn Coder for `00001KVNGJPRG` yet。
- Leave Ticket `queued` and record an orchestration `do_not_parallelize` note with `00001KVNG9B9Z`
- Re-route this Ticket after sidebar work lands, or if sidebar implementation report shows a stable component boundary that makes repository/objective pages non-conflicting。
No implementation side effects were performed for this Ticket。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-21T17:02:35Z -->
## Decision
Routing decision: `implementation_ready_after_sidebar_landed`
Reason:
- This Ticket was previously left queued due `do_not_parallelize` with `00001KVNG9B9Z` because repository/objective pages and sidebar navigation both touched the Workspace SPA navigation/layout surface。
- `00001KVNG9B9Z` is now `closed` and integrated (`613f4126 merge: workspace sidebar navigation`), so the sequencing blocker is cleared。
- Related bootstrap Ticket `00001KVMFFYVX` is also closed/integrated。
- Ticket body has concrete backend/API/frontend requirements, acceptance criteria, and validation requirements。
- Relations are `related` only; no blocking relation remains。
- Orchestrator worktree is clean on `orchestration` at `eb2e5907`; target worktree / branch is not present。
IntentPacket:
Intent:
- Add Repository and Objective pages reachable from the Workspace sidebar, using filesystem read-through Ticket/Objective authority and bounded read-only Repository/Git summaries。
Binding decisions / invariants:
- Ticket / Objective canonical authority remains existing filesystem records; do not migrate canonical writes to SQLite or add mutation APIs。
- Repository page is read-only initial slice for current workspace root as local Repository。
- Git info and log summaries must be bounded; do not expose full diffs, file contents, blame, or secret-like config。
- Repository Ticket Kanban is read-only and grouped by Ticket state; no drag/drop or state mutation。
- Objective list uses existing filesystem read-through `/api/objectives` data, with detail links/placeholders as practical。
- Frontend remains static SPA; no SSR/business authority。
- Sidebar links should use the now-landed navigation/component structure。
- API failures, non-Git repo, and empty state must be section-local。
Requirements / acceptance criteria:
- Add read-only Repository list/detail/summary API or minimal workspace repository summary。
- For Git repository: bounded branch/head/root/dirty/remote/recent log summary。
- For non-Git repository: safe `kind = local` / git unavailable diagnostic。
- Add bounded Git log summary API returning recent N commit hash/subject/author/timestamp only。
- Add Repository Ticket Kanban read model grouped by Ticket state, with safe fallback to workspace-local tickets when target metadata is absent。
- Add Repository page showing summary, Git summary/log, and Ticket Kanban。
- Add Objective list page showing objective title/state/updated_at/summary and detail link/placeholder if feasible。
- Sidebar repositories/objectives links navigate to these pages。
- Deno check/build and backend validation pass。
Implementation latitude:
- Use SvelteKit static SPA client-side routing/hash/router approach or simple stateful navigation if current skeleton lacks route generation; keep static output compatible。
- Backend API names may be pragmatic, e.g. `/api/repositories`, `/api/repositories/{id}`, `/api/repositories/{id}/log`, `/api/repositories/{id}/tickets`
- Current workspace root can be the only repository for this slice。
- Ticket Kanban fallback can group all workspace tickets by state with diagnostic that target metadata is not yet available。
- Keep UI simple and avoid broad design-system churn。
Escalate if:
- Implementing repository APIs would require reading file contents/diffs or unsafe Git config/secrets。
- Objective detail requires mutation or schema changes。
- Static SPA route approach conflicts with SvelteKit adapter/static constraints。
- Sidebar/navigation architecture from `00001KVNG9B9Z` cannot support pages without broad rewrite。
Validation plan:
- `cargo fmt --check`
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi-workspace-server`
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T17:02:42Z from: queued to: inprogress reason: sidebar_dependency_landed_unblocked_implementation field: state -->
## State changed
Previously recorded `do_not_parallelize` sequencing reason is cleared because sidebar navigation Ticket `00001KVNG9B9Z` is closed and integrated. Human queue authorization remains applicable, and the Ticket has concrete implementation requirements, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:03:39Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNGJPRG-repository-objective-pages`
- Created branch:
- `impl/00001KVNGJPRG-repository-objective-pages`
- Base commit:
- `0f7e78c1 ticket: accept repository objective pages`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVNGJPRG`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVNGJPRG-repository-objective-pages`
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:23:16Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVNGJPRG`.
Implementation commit:
- `ceb1ee3b feat: add repository objective pages`
Changed areas:
- Backend repository read APIs:
- Added `crates/workspace-server/src/repositories.rs`
- Added bounded local repository/Git summary and log reader。
- Added endpoints:
- `/api/repositories`
- `/api/repositories/local`
- `/api/repositories/local/log`
- `/api/repositories/local/tickets`
- Added read-only Ticket Kanban grouping by Ticket state with workspace-local fallback diagnostic。
- Added Objective list summaries from existing filesystem Objective records。
- Frontend Workspace SPA:
- Added hash-navigation pages for Repository and Objectives。
- Wired sidebar Repository/Objectives links to the new pages。
- Added Repository summary, Git summary/log, diagnostics, and read-only Ticket Kanban UI。
- Added Objective list with title/state/updated_at/summary and detail placeholder links。
- Tests:
- Extended workspace-server API tests for repository endpoints and Objective summary。
- Added Git URL sanitization/log parsing unit tests。
Coder validation reported:
- `cargo fmt --all`: passed
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check`: passed
- `cd web/workspace && deno task build`: passed
- `git diff --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed after staging newly added `repositories.rs` so Git-backed flake source filtering included it。
Generated artifact cleanup:
- Coder removed `web/workspace/build` and `web/workspace/.svelte-kit`
- Orchestrator additionally removed ignored `web/workspace/node_modules/` before Reviewer routing。
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVNGJPRG-repository-objective-pages` at `ceb1ee3b`
- Diff `0f7e78c1..HEAD` touches 8 expected backend/frontend files, about 1228 insertions / 142 deletions。
- `git diff --check 0f7e78c1..HEAD`: passed。
- No generated frontend artifacts remain in child worktree status。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-21T17:23:58Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVNGJPRG-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVNGJPRG-repository-objective-pages`
- Branch: `impl/00001KVNGJPRG-repository-objective-pages`
- Baseline: `0f7e78c1`
- Implementation commit: `ceb1ee3b feat: add repository objective pages`
- Diff: `0f7e78c1..ceb1ee3b`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Read-only bounded Repository APIs and Git summaries。
- No diffs/file contents/blame/secret-like config exposure。
- Sanitized remote URL summary。
- Non-Git degradation。
- Read-only Ticket Kanban grouped by state。
- Objective list uses filesystem read-through records。
- Static SPA navigation/pages and section-local error handling。
- Generated artifact / Nix source filtering hygiene。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVNGJPRG-r1 at: 2026-06-21T17:30:09Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVNGJPRG/item.md`
- `.yoi/tickets/00001KVNGJPRG/thread.md`
- Diff `0f7e78c1..ceb1ee3b`:
- `crates/workspace-server/src/lib.rs`
- `crates/workspace-server/src/records.rs`
- `crates/workspace-server/src/repositories.rs`
- `crates/workspace-server/src/server.rs`
- `web/workspace/src/lib/workspace-sidebar/ObjectivesNavSection.svelte`
- `web/workspace/src/lib/workspace-sidebar/RepositoriesNavSection.svelte`
- `web/workspace/src/lib/workspace-sidebar/types.ts`
- `web/workspace/src/routes/+page.svelte`
Blocking issues:
- None found。
Acceptance verification:
- Repository APIs are read-only `GET` routes only。
- Git commands use fixed argument vectors through `Command::new("git").arg("-C").arg(workspace_root).args(args)`; no shell interpolation。
- Git summary/log is bounded:
- log limit clamps to `1..=50`
- command output capped at `4096`
- fields capped at `240`, hash at `40`
- no diff/patch/file content/blame/config commands are used。
- Remote URL summary strips URL-scheme userinfo and marks `redacted`
- Non-Git workspaces return `git.status = "unavailable"` plus diagnostics rather than failing the Repository page model。
- Ticket Kanban reads filesystem Ticket summaries and groups by state; no Ticket mutation route/UI was added。
- Objective list continues to use filesystem read-through `/api/objectives`; no Objective mutation/API authority added。
- Frontend remains static SPA/hash navigation; no SSR/business authority introduced。
- Nix build succeeds with the new Rust source file。
Non-blocking concerns:
- `ObjectivesNavSection.svelte` only shows the “All objectives” sidebar link when objectives are successfully loaded and non-empty. In an empty/error state, the page is still reachable from hero links, but the sidebar itself does not provide a stable top-level Objectives link. Consider keeping `#/objectives` visible in all non-loading states in a follow-up。
- Remote sanitization removes URL-scheme userinfo, but does not attempt query-param or SCP-like token redaction. Acceptable for the initial bounded summary, but worth tightening if remote URLs may include local secret-bearing config。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 0f7e78c1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`8 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Generated artifacts:
- Reviewer did not clean generated ignored artifacts after validation。
- Ignored generated artifacts present:
- `target/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `web/workspace/node_modules/`
- No untracked non-ignored files。
Worktree status:
- Clean tracked/non-ignored state on `impl/00001KVNGJPRG-repository-objective-pages` at `ceb1ee3b`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:30:51Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `7ee702b1 merge: repository objective pages`
- Merged branch: `impl/00001KVNGJPRG-repository-objective-pages`
- Implementation commit:
- `ceb1ee3b feat: add repository objective pages`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`8 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `7ee702b1`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-21T17:30:58Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、workspace-server tests/check、Deno check/build、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-21T17:31:14Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-21T17:31:14Z status: closed -->
## 完了
Workspace web に Repository / Objective pages を追加し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Read-only Repository backend APIs を追加:
- `/api/repositories`
- `/api/repositories/local`
- `/api/repositories/local/log`
- `/api/repositories/local/tickets`
- Current workspace root を local Repository として扱う bounded repository summary を追加。
- Git repository では bounded branch/head/root/dirty/remote/recent log summary を返す。
- Non-Git workspace では `git.status = unavailable` と bounded diagnostics に degrade。
- Git log summary は recent commit hash/subject/author/timestamp に限定し、diff/patch/file content/blame/config は読まない。
- Remote URL summary は URL-scheme userinfo を redact。
- Read-only Ticket Kanban を Ticket state ごとに grouping し、workspace-local Ticket fallback diagnostic を含めた。
- Objective list summaries を filesystem Objective records から追加。
- Static SPA に hash-navigation Repository / Objectives pages を追加。
- Sidebar Repository/Objectives links を新 pages に接続。
- Repository page に summary, Git summary/log, diagnostics, read-only Ticket Kanban を表示。
- Objective page に title/state/updated_at/summary と detail placeholder links を表示。
- Ticket / Objective canonical authority remains filesystem read-through records; mutation API / DB canonical migration は追加していない。
統合・検証:
- Merge commit: `7ee702b1 merge: repository objective pages`
- Implementation commit: `ceb1ee3b feat: add repository objective pages`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外 / follow-up notes:
- Repository CRUD/API, Objective edit/detail mutation, full Git browser/diff/file views, drag/drop Kanban, and write APIs were not implemented。
- Reviewer noted possible follow-ups: keep `#/objectives` sidebar link visible even on objective empty/error states, and further tighten remote URL sanitization for query-param or SCP-like token forms if needed。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-21T17:31:43Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVNGJPRG`
- `yoi-reviewer-00001KVNGJPRG-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNGJPRG-repository-objective-pages`
- Deleted implementation branch:
- `impl/00001KVNGJPRG-repository-objective-pages`
- Orchestrator worktree remains clean on `orchestration` at `4b1f1e59`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260622-085006-1","ticket_id":"00001KVNKD56W","kind":"accepted_plan","accepted_plan":{"summary":"Align Workspace server SQLite bootstrap/migrations and tests with the canonical `schema-v0.md` artifact: typed repository/ticket-target/worker-link/artifact/audit schema, no canonical runs/hosts/workers/generic JSON/validation result tables, while preserving filesystem Ticket/Objective authority and existing read APIs.","branch":"impl/00001KVNKD56W-workspace-db-schema-v0","worktree":"/home/hare/Projects/yoi/.worktree/00001KVNKD56W-workspace-db-schema-v0","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation/design alignment commit(s). After approval, Orchestrator integrates into `orchestration`, validates workspace-server schema/tests/Nix if needed, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-22T08:50:06Z"}
@@ -0,0 +1,21 @@
{
"version": 1,
"relations": [
{
"ticket_id": "00001KVNKD56W",
"kind": "related",
"target": "00001KVMFFYVX",
"note": "Defines canonical DB model for workspace web control plane",
"author": "yoi ticket",
"at": "2026-06-21T17:25:34Z"
},
{
"ticket_id": "00001KVNKD56W",
"kind": "related",
"target": "00001KVNEKH9Q",
"note": "Host/Worker naming and local execution state should align with canonical DB schema",
"author": "yoi ticket",
"at": "2026-06-21T17:25:34Z"
}
]
}
@@ -0,0 +1,520 @@
# Workspace DB canonical schema v0 design
## Purpose
This document defines the first concrete Workspace control-plane schema target. It is precise enough that implementation work can create migrations and API read/write surfaces without inventing meanings ad hoc.
The important corrections in this version are:
- **Ticket thread/events remain the execution history authority**.
- A separate top-level `Run` entity is not part of v0.
- Separate `validation_results` / CI tables are not part of v0.
- Worker is not a DB-canonical entity in v0. Worker state is obtained from runtime inspection / Host protocol as a live view.
- Ticket-to-Worker management is represented by typed WorkerRef snapshots on Ticket events and Ticket-Worker association records.
- v0 does **not** use generic JSON payload/metadata columns. If a value matters, give it a typed column or a small relation table. If it is large evidence, store it as an Artifact.
## Schema categories
1. **Current-state records**: long-lived records with stable ids and current snapshots, such as Ticket, Objective, Repository, Artifact.
2. **Event logs**: append-oriented records attached to current-state records, primarily `ticket_events` and `audit_events`.
3. **Relationship records**: explicit links such as Ticket-to-WorkerRef, Ticket-to-Repository target, Objective-to-Ticket.
4. **Snapshot references**: typed authorship / worker / host references embedded in event or relation records. These are not full entities in v0.
5. **Live views**: API results produced by inspecting local runtime or future Host protocol state. Host/Worker lists are live views in v0, not canonical DB tables.
All main tables include `workspace_id`. v0 is SQLite-first, but table shapes should not prevent later Postgres/multi-workspace hosting.
## Design rules
- Ticket and Objective belong to Workspace, not to Repository.
- Repository is a Workspace-connected source/storage. Git Repository is one provider, not the definition of Repository.
- Ticket target selectors are mutable intent/scope. Evidence artifacts may record the concrete repository revision they were produced from with typed source fields.
- Ticket thread is the human-readable and structured execution/audit history for work on that Ticket.
- Ticket current state is a snapshot derived/maintained from structured state transition events.
- Worker is a logical agent/session participating in work, but Worker registry/persistence is out of v0 DB scope.
- Host is an execution environment or observed placement. In v0, Host/Worker information is returned as a live view from local runtime inspection or future Host protocol, not stored as canonical DB records.
- Ticket-associated Worker management uses WorkerRef fields and `ticket_worker_links` snapshots. This lets the Ticket be managed without making the Worker itself DB-canonical.
- Orchestrator should be able to operate from DB/API records only: Ticket, TicketEvents, TicketWorkerLinks, live Host/Worker views, Artifact, and review/evidence summaries.
- Raw fs/Bash/Git authority belongs to Host/Worker execution, not to Orchestrator.
- Memory/Knowledge are intentionally out of v0 canonical schema. They are deferred until Workspace storage migration for Memory.
- Event authorship is mandatory, but a full Actor table is not required in v0.
- Generic JSON columns are intentionally excluded in v0. Do not add `metadata_json`, `payload_json`, `diagnostics_json`, or similar catch-all fields.
## Common columns and conventions
### IDs
Use opaque string ids allocated by the control plane for DB-canonical records.
Recommended prefixes are implementation detail, but the type must be obvious from column names:
- `workspace_id`
- `ticket_id`
- `event_id`
- `objective_id`
- `repository_id`
- `target_id`
- `artifact_id`
- `audit_event_id`
Worker and Host references use `*_ref_kind` / `*_ref_key` in v0 because they are not canonical DB entities.
### Timestamps
Store UTC timestamps as RFC3339 strings in SQLite v0.
Common names:
- `created_at`
- `updated_at`
- `observed_at`
- `started_at`
- `finished_at`
- `closed_at`
- `last_seen_at`
### No catch-all payload columns
v0 avoids generic JSON/text payload columns because they make the schema ambiguous and move authority into untyped blobs.
Rules:
- Fields used for lifecycle transitions, permissions, joins, filtering, or orchestration decisions must be typed columns or relation tables.
- Event kinds may have nullable typed columns such as `subject_kind`, `subject_id`, `previous_state`, `new_state`, `status`, `activity_id`, or `artifact_id`.
- Repository capabilities are derived from `repositories.kind` / `repositories.provider` and backend configuration in v0; do not add a separate capability table until provider-specific overrides are actually needed.
- Paths use relation tables such as `ticket_target_paths`.
- Diagnostics that matter should be Ticket events or Artifacts.
- Large logs, diffs, transcripts, prompts, raw tool outputs, and file contents must not be embedded in records. Store them in an artifact file/blob store and link through Artifact URI records.
- Secrets are never stored in this schema. Secret references, if needed, use typed reference columns such as `auth_ref_kind` and `auth_ref_key`.
## Authorship fields v0
Authorship is an embedded typed snapshot, not a full table in v0.
Use the following columns on event/request/audit records that need authorship:
```text
author_kind text not null
author_key text not null
author_display text not null
author_source_kind text null
author_source_key text null
```
`author_kind` allowed values:
- `human`
- `agent`
- `system`
- `integration`
- `unknown`
`author_key` is stable within its source namespace, for example:
- `local-user`
- `agent:orchestrator`
- `worker:<worker_ref_key>`
- `system:yoi-control-plane`
- `integration:ci:<provider>`
`author_display` is a display snapshot at event creation time. It must be sufficient for historical display even if a future Actor/User record changes name.
`author_source_kind` and `author_source_key` can point to bounded source context such as `worker`, `profile`, `external_account`, or `provider`. They must not hold secrets.
A future `actors` table may be added for auth, assignment, team membership, and permissions. v0 must not require it. If it is added later, historical events still keep their authorship snapshot and may optionally link to `actor_id`.
## WorkerRef and HostRef v0
Worker and Host are runtime concepts in v0. They are referenced by typed snapshots instead of DB foreign keys.
Use WorkerRef fields where a Ticket event, Ticket association, artifact, or check report needs to identify a Worker:
```text
worker_ref_kind text null -- local_pod | remote_worker | hosted_worker | external | unknown
worker_ref_key text null
worker_display text null
```
Examples:
- `worker_ref_kind = local_pod`, `worker_ref_key = coder-sidebar`, `worker_display = Coder sidebar`
- `worker_ref_kind = hosted_worker`, `worker_ref_key = worker_...`, `worker_display = Hosted coder`
Use HostRef fields only when observed placement matters:
```text
host_ref_kind text null -- local | self_hosted | cloud | external | unknown
host_ref_key text null
host_display text null
```
HostRef is not ownership. It means “this Worker or event was observed on this execution environment at this time”.
Future work may add canonical `workers`, `hosts`, `worker_archive`, and `host_connections` tables when Worker lifecycle, persistence, and archive requirements are concrete. v0 deliberately does not create those tables.
## Execution model without a Run entity
v0 does not create a separate `runs` table.
A concrete execution attempt is represented by:
- a `ticket_event` such as `execution_requested`, `worker_assigned`, `worker_status`, `implementation_report`, `review`, `check_report`, `artifact_link`, or `state_transition`;
- optional `activity_id` on related `ticket_events` to group a burst of execution activity;
- `ticket_worker_links` records showing which WorkerRefs are associated with the Ticket and in what role/status;
- `artifacts` linked to `ticket_id`, `event_id`, optional WorkerRef fields, and optional typed repository source revision fields.
`activity_id` is a correlation key, not an authority entity. It can be generated when a user/Orchestrator accepts an execution request, but the Ticket thread remains the authority.
This avoids duplicating Ticket events and Run records while preserving machine-readable execution state.
## Live Host/Worker API view
v0 API may expose Host and Worker lists, but they are live views, not DB tables.
Examples:
- `GET /api/hosts` may inspect the backend-local machine and return one synthetic local Host.
- `GET /api/workers` may scan current local Pod metadata and sockets and return Worker summaries.
- Future Host protocol can provide the same API shape from heartbeat/connection state.
These API responses must not imply DB persistence. If a Worker disappears from runtime inspection, it can disappear from the live view. Durable history belongs to Ticket events, TicketWorkerLinks, and Artifacts.
## Tables
### `workspaces`
```text
workspace_id text primary key
display_name text not null
state text not null -- active | archived
created_at text not null
updated_at text not null
```
### `tickets`
Current Ticket state and body snapshot.
```text
workspace_id text not null
ticket_id text primary key
title text not null
state text not null -- planning | ready | queued | inprogress | done | closed
priority text null
assignee_kind text null
assignee_key text null
assignee_display text null
body_md text not null
created_at text not null
updated_at text not null
closed_at text null
resolution_event_id text null
```
Notes:
- `tickets` stores the current read model.
- Historical changes belong to `ticket_events`.
- Ticket state transitions must be represented by structured `ticket_events`.
- Assignee is a snapshot, not a foreign key to `actors` in v0.
### `ticket_events`
Append-oriented Ticket thread/event log. This is also the execution history authority for work on a Ticket.
```text
workspace_id text not null
event_id text primary key
ticket_id text not null
event_seq integer not null
kind text not null
activity_id text null
author_kind text not null
author_key text not null
author_display text not null
author_source_kind text null
author_source_key text null
created_at text not null
body_md text null
subject_kind text null -- ticket | worker | artifact | check | repository | objective | system
subject_id text null
previous_state text null
new_state text null
status text null
artifact_id text null
worker_ref_kind text null
worker_ref_key text null
worker_display text null
host_ref_kind text null
host_ref_key text null
host_display text null
repository_id text null
caused_by_event_id text null
```
`kind` allowed values in v0:
- `comment`
- `plan`
- `decision`
- `review`
- `implementation_report`
- `state_transition`
- `close`
- `execution_requested`
- `worker_assigned`
- `worker_status`
- `check_report`
- `artifact_link`
- `system_note`
Constraints:
- unique `(ticket_id, event_seq)`.
- events are append-only except administrative repair migrations.
- state transitions and close events must include `previous_state` and `new_state` where applicable.
- execution events should use typed columns such as `activity_id`, WorkerRef fields, `artifact_id`, and `repository_id` instead of opaque payloads.
### `ticket_relations`
```text
workspace_id text not null
source_ticket_id text not null
target_ticket_id text not null
kind text not null -- depends_on | blocks | related | supersedes | duplicate_of
created_at text not null
author_kind text not null
author_key text not null
author_display text not null
author_source_kind text null
author_source_key text null
note text null
primary key (source_ticket_id, target_ticket_id, kind)
```
### `objectives`
```text
workspace_id text not null
objective_id text primary key
title text not null
state text not null -- active | paused | done | closed | archived
body_md text not null
created_at text not null
updated_at text not null
```
### `objective_ticket_links`
```text
workspace_id text not null
objective_id text not null
ticket_id text not null
kind text not null -- tracks | related | milestone | blocker
created_at text not null
primary key (objective_id, ticket_id, kind)
```
### `repositories`
Workspace-connected source/storage. Git is one provider.
```text
workspace_id text not null
repository_id text primary key
name text not null
kind text not null -- git | local | object_store | artifact_store | custom
provider text null -- git, local_fs, s3, etc.
uri text not null
default_ref text null
auth_ref_kind text null
auth_ref_key text null
created_at text not null
updated_at text not null
```
Notes:
- `uri` is identity/config data. It may be redacted in API responses.
- `auth_ref_kind` / `auth_ref_key` contain secret references only, never secret values.
- v0 does not store per-Repository capability rows. Capabilities are derived from `kind`, `provider`, and backend configuration. Add explicit capability/override records later only if a real provider needs per-Repository variance.
### `ticket_targets`
Ticket scope/intent against one or more Repositories.
```text
workspace_id text not null
ticket_id text not null
target_id text not null
repository_id text not null
role text not null -- primary | related | reference | check | output
intent text not null -- read | change | check | output
ref_selector text null
created_at text not null
updated_at text not null
primary key (ticket_id, target_id)
```
### `ticket_target_paths`
```text
workspace_id text not null
ticket_id text not null
target_id text not null
path text not null
primary key (ticket_id, target_id, path)
```
### `ticket_worker_links`
Current relationship between Ticket and a WorkerRef.
```text
workspace_id text not null
ticket_id text not null
worker_ref_kind text not null
worker_ref_key text not null
worker_display text null
role text not null -- companion | intake | orchestrator | coder | reviewer | validator | custom
status text not null -- requested | assigned | active | blocked | completed | released | failed | cancelled
activity_id text null
assigned_at text null
released_at text null
last_event_id text null
primary key (ticket_id, worker_ref_kind, worker_ref_key, role)
```
Notes:
- This is the main DB management relation for Ticket-associated Workers.
- It is not a Worker registry.
- Ticket thread events should record assignment/release/status changes.
### `artifacts`
Evidence/output linked to Ticket, Objective, event, WorkerRef, or Repository source revision.
Artifact content is not stored inline in the DB. Every Artifact points to a URI. The URI may be served by the Workspace backend's artifact/static-file service, a blob store, or an external system.
```text
workspace_id text not null
artifact_id text primary key
kind text not null -- diff | patch | log | report | check_report | review | file | external_link | summary
uri text not null
media_type text null
sha256 text null
size_bytes integer null
summary text null
created_at text not null
created_by_kind text not null
created_by_key text not null
created_by_display text not null
created_by_source_kind text null
created_by_source_key text null
ticket_id text null
objective_id text null
event_id text null
worker_ref_kind text null
worker_ref_key text null
worker_display text null
repository_id text null
source_kind text null -- git_commit | file_snapshot | object_version | custom
source_revision text null -- commit hash, snapshot id, or object version id
```
Rules:
- `uri` is mandatory.
- DB rows store metadata and summary only, never artifact body content.
- `source_kind` / `source_revision` are optional typed source fields for artifacts produced against a concrete repository revision. They do not represent branch/ref selectors; mutable selectors remain on `ticket_targets.ref_selector` or in the related Ticket event.
- Workspace-owned artifact content should use a stable internal URI scheme or backend-served URL, for example `artifact://<workspace_id>/<artifact_id>` or `/api/artifacts/<artifact_id>/content`.
- External artifacts may use redacted `https://...` or provider-specific URIs when policy allows.
- API list/detail responses return artifact metadata and URI by default. Fetching content is a separate artifact-content operation with bounds and permission checks.
## CI / actions-like checks are future work
v0 does not add `validation_results`, `ci_results`, or action tables.
For now, local checks, CI summaries, and check evidence are represented by:
- `ticket_events.kind = check_report` or `artifact_link`;
- Artifacts such as logs, check reports, or external CI URLs;
- Ticket state transitions or review events that reference those artifacts.
If first-class CI status is needed, design it as a separate actions-like subsystem rather than a generic validation table inside the core Ticket schema. That future subsystem should model workflow/check names, jobs, steps, attempts, statuses, logs, annotations, external provider ids, retention, and rerun semantics explicitly.
### `audit_events`
Control-plane operation audit trail.
```text
workspace_id text not null
audit_event_id text primary key
created_at text not null
actor_kind text not null
actor_key text not null
actor_display text not null
actor_source_kind text null
actor_source_key text null
action text not null
target_kind text not null
target_id text null
outcome text not null -- allowed | denied | succeeded | failed
request_id text null
summary text null
```
Audit events record the control-plane action and outcome. They should not duplicate full Ticket event payloads unless needed for audit.
## Read surfaces for Orchestrator without fs/Bash
The DB/API must let an Orchestrator read:
- Ticket current state, thread events, relations, targets, and TicketWorkerLinks.
- Objective body and linked Tickets.
- Repository summaries, Ticket target selectors, and Artifact source revision fields.
- Live Host/Worker views from runtime inspection or future Host protocol.
- Artifact summaries and selected artifact contents through bounded artifact APIs.
- Check/CI summaries as TicketEvents and Artifacts.
- Review evidence as TicketEvents/Artifacts.
## Write surfaces for Orchestrator without fs/Bash
The DB/API must let an Orchestrator create:
- Ticket comments/decisions/state transition requests.
- Ticket execution request events with target selectors and optional `activity_id`.
- TicketWorkerLink assignment/release/status changes.
- Review/check request events.
- Artifact links for logs, reports, diffs, CI/external check URLs, and review evidence.
- Close/done decisions that reference evidence artifacts and structured Ticket events.
The Orchestrator must not need raw repository filesystem reads, shell execution, or direct Git merge authority to perform control-plane routing.
## Migration stance
v0 implementation should support three modes conceptually:
1. `filesystem_read_through`: current `.yoi/tickets` and `.yoi/objectives` remain authority; DB holds runtime/projection tables.
2. `imported_projection`: filesystem records are imported into DB read models, but filesystem remains the write authority.
3. `db_authority`: Ticket/Objective write path moves to DB; filesystem export becomes compatibility/export snapshot.
This Ticket designs the schema target and can implement non-breaking migrations, but it does not require switching active authority to DB.
## Minimal implementation guidance
If implementation is included in this Ticket, prefer a small non-breaking migration:
- Keep Host/Worker API as live runtime views in v0.
- Add explicit schema versioning.
- Add tables that are safe to create empty: `repositories`, `ticket_targets`, `ticket_target_paths`, `ticket_worker_links`, `artifacts`, `audit_events`.
- Keep existing filesystem read APIs working.
- Do not create a full `actors` table in v0.
- Do not create `hosts` / `workers` canonical tables in v0.
- Do not create a separate `runs` table in v0; use structured Ticket events and TicketWorkerLink relationships.
## Implementation alignment notes
The `yoi-workspace-server` SQLite bootstrap migration implements this v0 schema as schema version 2. Fresh databases create the typed tables listed above and deliberately do not create canonical `runs`, `hosts`, `workers`, `actors`, or check/validation result tables. Host and Worker HTTP read APIs remain live runtime views backed by local inspection, not DB tables.
For databases created by the earlier workspace-server bootstrap, migration version 2 preserves old `workspaces`, `repositories`, `runs`, `artifacts`, `ticket_projections`, and `objective_projections` data by renaming those tables to `legacy_workspaces`, `legacy_repositories`, `legacy_runs`, `legacy_artifacts`, `legacy_ticket_projections`, and `legacy_objective_projections`, then creating the v0 typed tables. Existing legacy workspace rows are copied into the canonical v0 `workspaces` table with `state = active` when the old row had no typed state. The legacy names are compatibility preservation only and are not canonical schema tables or active write authority.
+131
View File
@@ -0,0 +1,131 @@
---
title: 'Workspace DB canonical schema design'
state: 'closed'
created_at: '2026-06-21T17:24:43Z'
updated_at: '2026-06-22T09:27:06Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-22T08:48:39Z'
---
## 背景
Workspace web control plane は、Rust backend / SQLite store / static SPA / read-only filesystem bridge まで立ち上がっている。ただし現在の SQLite schema は起動・API skeleton 用の足場であり、Ticket / Objective / Repository / Host / Worker / Artifact を将来 DB 正本にするための canonical schema はまだ固まっていない。
DB 設計は過度に難しく扱わず、まずは既存 filesystem Ticket/Objective model と現在の orchestration 運用を素直に relational/event model へ写す。重要なのは、`.yoi` filesystem record をすぐ捨てることではなく、Web/API/Orchestrator が将来 DB authority に移れるだけの record 境界を決めること。
長期方針:
- Ticket / Objective は Workspace 配下に平たく存在する。
- Repository は Workspace に接続される source/storage であり、Git Repository はその一種。
- Ticket は必要に応じて Repository target selector を持つ。
- Ticket thread/events が実行履歴の authority であり、Ticket state は current snapshot として持つ。
- Worker は Ticket に関連づく logical agent/session だが、v0 では DB 正本として永続化しない。Host/Worker 一覧は runtime inspection / future Host protocol から逐次取得する live view とする。
- Worker の一元管理、データ永続化、アーカイブは将来必要になるが、Host/Worker protocol と lifecycle requirements が固まるまで v0 schema には入れない。
- Host は Worker が観測される実行環境または capacity を表すが、v0 では canonical table ではなく live view とする。
- CI/check information should be represented as Ticket events plus Artifact links in v0. If richer CI status is needed, design it later as a separate actions-like subsystem rather than a generic validation table.
- Orchestrator は将来的に fs/Bash/Git を直接持たず、Ticket / TicketEvent / TicketWorkerLink / live Host/Worker view / Artifact / Review の DB/API surface だけを見る。
- Memory / Knowledge の本格再設計はこの Ticket では扱わず、保存先を Workspace backend へ移す時に回収する。
## 要件
### Canonical records / tables
DB design は `artifacts/schema-v0.md` を主たる設計記録とする。Ticket 本文では scope と要求だけを示す。
`schema-v0.md` では以下を明確に定義する。
- record / event / reference の区別。
- ID / timestamp / no-catch-all-payload column conventions。
- `AuthorRef` v0。
- event author/source を記録する typed snapshot。
- 初期実装では full `actors` table を必須にしない。
- auth / permission / assignment / team membership が必要になった時点で `actors` table へ昇格できる。
- table candidates and required columns:
- `workspaces`
- `tickets`
- `ticket_events`
- `ticket_relations`
- `objectives`
- `objective_ticket_links`
- `repositories`
- `ticket_targets`
- `ticket_target_paths`
- `ticket_worker_links`
- `artifacts`
- `audit_events`
- Orchestrator no-fs/no-bash の read/write surfaces。
- filesystem read-through から DB authority への migration modes。
初期設計で曖昧な `actors` entity を置かない。必要なのは event authorship であり、v0 では `AuthorRef` fields として扱う。
### Authority / migration stance
- 当面は `.yoi/tickets` / `.yoi/objectives` filesystem read-through を維持する。
- DB schema は canonical target として設計するが、この Ticket だけで full migration はしない。
- import/projection/export の方針を決める。
- filesystem -> DB import。
- DB -> filesystem export / compatibility snapshot。
- read-through bridge と DB authority の切り替え条件。
- 二重正本を避けるため、write path をいつ DB に切り替えるかを明記する。
- SQLite first でよいが、将来 Postgres/multi-tenant へ進めるよう、`workspace_id` を全主要 record に含める。
### Orchestrator no-fs/no-bash surface
DB/API だけを見て Orchestrator が判断できるように、以下の read/write surface を設計する。
Orchestrator が読むもの:
- Ticket state/thread/relations/targets。
- Ticket-associated WorkerRef links and worker status events。
- Objective context。
- Live Host/Worker view from runtime inspection or future Host protocol。
- Repository target and artifact source revision fields。
- Artifact summaries/diff metadata/log summaries。
- Review evidence。
Orchestrator が作るもの:
- Ticket comment/decision/state transition request。
- Ticket execution request / WorkerRef assignment / worker status events。
- Worker job request / assignment request。
- Review/check request。
- Close/done decision with evidence references。
fs/Bash/Git 操作は Host/Worker に閉じ込める。Orchestrator は raw repository filesystem や shell access を authority として持たない。
### Initial implementation slice
この Ticket は design-only でもよいが、可能なら最小 schema migration まで含める。
- `crates/workspace-server` の SQLite schema を canonical design に合わせて整理する。
- 既存 placeholder `runs` / `runners` naming を、structured ticket events / live Host/Worker API / `ticket_worker_links` へ寄せる。
- Migration versioning の方針を明記する。
- Existing read API を壊さない。
## Non-goals
- Full DB migration of existing `.yoi/tickets` / `.yoi/objectives`
- Web UI からの Ticket/Objective mutation 実装。
- Memory / Knowledge の本格再設計。
- Multi-tenant production SaaS schema の完全設計。
- Auth/billing/quota/security の完全実装。
- Git hosting service の実装。
- Orchestrator profile から fs/Bash を実際に剥がすこと。
## 受け入れ条件
- Workspace DB canonical schema design が `artifacts/schema-v0.md` または同等の design record として記録されている。
- `schema-v0.md` が record / event / reference の区別を定義している。
- Table/record 境界として Workspace / Ticket / TicketEvent / TicketRelation / Objective / ObjectiveTicketLink / Repository / TicketTarget / TicketTargetPath / TicketWorkerLink / Artifact / AuditEvent が定義されている。
- Separate top-level Run entity/table を v0 では作らず、structured Ticket events と TicketWorkerLink relation を execution history/management surface とする方針が明記されている。
- Host/Worker は v0 DB canonical table ではなく live runtime view とし、Ticket には WorkerRef snapshot/link を保存する方針が明記されている。
- Event/request/audit authorship は `AuthorRef` v0 として required fields まで定義されている。
- 初期実装で full Actor entity/table を必須にしない方針と、将来 actors table へ昇格できる条件が明記されている。
- CI/check status は v0 core schema では Ticket events + Artifact links として扱い、actions-like subsystem は future work とする方針が明記されている。
- `.yoi` filesystem read-through から DB authority へ移る migration/export/import 方針が明記されている。
- Orchestrator no-fs/no-bash を可能にする DB/API read/write surface が明記されている。
- Memory / Knowledge は deferred として扱われ、この schema design の必須 scope から外れている。
- SQLite first だが、全主要 record に `workspace_id` を持たせる方針が明記されている。
- 既存 `runner` placeholder naming を Host/Worker に移す方針が明記されている。
- 実装まで含める場合は `cargo fmt --check``cargo test -p yoi-workspace-server``cargo check``git diff --check``yoi ticket doctor``nix build .#yoi --no-link` が通る。
+36
View File
@@ -0,0 +1,36 @@
Workspace DB canonical schema v0 design を `schema-v0.md` artifact と workspace-server SQLite bootstrap/migrations に整合させ、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- SQLite schema version を `2` に進め、canonical schema v0 を実装。
- Typed v0 tables を追加:
- `tickets`
- `ticket_events`
- `ticket_relations`
- `objectives`
- `objective_ticket_links`
- `repositories`
- `ticket_targets`
- `ticket_target_paths`
- `ticket_worker_links`
- `artifacts`
- `audit_events`
- Canonical v0 から top-level `runs`, `hosts`, `workers`, `actors`, validation/CI result tables を除外。
- Generic `metadata_json`, `payload_json`, `diagnostics_json` のような catch-all payload columns を canonical v0 tables に追加しない方針を維持。
- `/api/runs` と frontend Runs card/reference を削除し、404 test を追加。
- Host/Worker APIs は DB authority ではなく live runtime views として維持。
- Legacy bootstrap tables は non-canonical `legacy_*` preservation tables に demote。
- Legacy `workspaces``legacy_workspaces` に preserve し、active canonical `workspaces` を v0 column set で作り直して既存行を copy。
- Post-upgrade `upsert_workspace()` for new workspace id が通る regression test を追加。
- `schema-v0.md` に SQLite version 2 / legacy preservation alignment notes を追加。
統合・検証:
- Merge commit: `38bd122d merge: workspace db schema v0`
- Implementation commits: `5149ab70`, `d89ace5b`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Ticket/Objective write authority migration to DB is not implemented。
- Host/Worker canonical DB tables are not added。
- Validation/CI result tables and Actor table are not added。
- Full TicketEvents/TicketWorkerLinks/Artifacts write surfaces are not implemented beyond schema/bootstrap alignment。
+541
View File
@@ -0,0 +1,541 @@
<!-- event: create author: "yoi ticket" at: 2026-06-21T17:24:43Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-21T17:25:35Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-21T17:25:35Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-22T08:48:39Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-22T08:49:46Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket includes a concrete `schema-v0.md` artifact defining the Workspace DB canonical schema target and migration stance。
- Artifact is precise enough to implement a non-breaking schema/migration alignment slice and/or finish design documentation without inventing semantics。
- Relations are non-blocking context relations; no blocker relation is recorded。
- Current Workspace backend has an older bootstrap SQLite schema in `crates/workspace-server/src/store.rs` with `runs`, `ticket_projections`, `objective_projections`, and run-linked artifacts, while `schema-v0.md` explicitly says no separate `Run` entity and Host/Worker are live views. This gives a concrete implementation alignment target。
- Orchestrator worktree is clean on `orchestration` at `b7c890d3`; target worktree / branch is not present。
- Current queued Ticket is this Ticket only。
Evidence checked:
- Ticket body / thread / artifacts via `TicketShow` and direct read of `artifacts/schema-v0.md`
- `TicketRelationQuery(00001KVNKD56W)`: 2 relation records, no blocking relation reported。
- `TicketOrchestrationPlanQuery(00001KVNKD56W)`: no records。
- `TicketList(state=queued)`: this Ticket is the only queued Ticket。
- Orchestrator git state / branch list checked from `/home/hare/Projects/yoi/.worktree/orchestration` only。
- Bounded code map:
- `crates/workspace-server/src/store.rs` currently owns SQLite migrations and schema versioning。
- Current store still has bootstrap `runs` and projection-oriented tables; `schema-v0.md` says v0 should not include separate `runs`, Host/Worker canonical DB tables, generic JSON blobs, or validation result tables。
- Current repository/objective/ticket read APIs are filesystem read-through and must keep working。
IntentPacket:
Intent:
- Turn the Workspace DB canonical schema v0 design into a durable implementation/design artifact and align the current SQLite bootstrap migration where safely non-breaking。
Binding decisions / invariants:
- Ticket and Objective filesystem records remain the active authority; do not switch write authority to DB。
- No generic JSON/payload/metadata columns in the v0 canonical schema。
- Do not add canonical `hosts` / `workers` DB tables; Host/Worker remain live runtime views。
- Do not add a top-level `runs` canonical table; execution history belongs to Ticket events, TicketWorkerLinks, and Artifacts。
- Do not add CI/validation result tables in this Ticket。
- Do not add Actor table in v0; authorship is embedded typed snapshot fields。
- Keep existing Workspace APIs/tests working。
- Non-breaking migration is acceptable; destructive migration of existing user DBs is not required in this slice unless clearly safe and tested。
Requirements / acceptance criteria:
- `schema-v0.md` remains consistent with implemented/bootstrap migration semantics。
- Workspace-server migration/schema tests cover new v0 schema version and expected tables/absence of forbidden tables。
- Empty/safe tables from minimal implementation guidance may be added: `repositories`, `ticket_targets`, `ticket_target_paths`, `ticket_worker_links`, `artifacts`, `audit_events`, and supporting Ticket/Objective current/event tables if included。
- Remove or replace obsolete `runs` table/API/store concept if it conflicts with v0, or clearly demote it to non-canonical compatibility only if removal is out of scope。
- No canonical host/worker tables are added。
- Existing filesystem read-through APIs for Tickets/Objectives/Repository pages keep passing。
- Docs/tests make clear that Host/Worker API is live view and Ticket thread/events are execution authority。
Implementation latitude:
- If full schema migration is too large, implement the smallest safe migration alignment plus tests and record remaining tables as future follow-up comments。
- Prefer typed tables/columns over catch-all text/json columns。
- SQLite schema version can advance if migrations change。
- `runs` API placeholder may be removed if no longer used; ensure frontend/tests do not depend on it。
- Keep API surface read-only unless Ticket explicitly requires otherwise; this one does not require write APIs。
Escalate if:
- Removing current `runs` table/API would break existing accepted frontend or tests in a way that needs product decision。
- Existing DB migration compatibility requires a complex destructive migration or data backfill policy。
- Implementing full TicketEvents/TicketWorkerLinks/Artifacts read/write surfaces grows beyond schema/bootstrap alignment。
- Schema design conflicts with recent Repository/Objectives pages in a way not anticipated by artifact。
Validation plan:
- `cargo fmt --check`
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi-workspace-server`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link` if package/source/dependency behavior changes。
- Deno check/build only if frontend/runs API removal touches frontend。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-22T08:49:57Z from: queued to: inprogress reason: human_authorized_schema_design_alignment field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has a concrete schema-v0 design artifact and current workspace-server migration has a clear non-breaking alignment target, so Orchestrator accepts implementation/design alignment.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-22T08:51:00Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNKD56W-workspace-db-schema-v0`
- Created branch:
- `impl/00001KVNKD56W-workspace-db-schema-v0`
- Base commit:
- `f17a458a ticket: accept workspace db schema v0`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVNKD56W`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVNKD56W-workspace-db-schema-v0`
Next action:
- Wait for Coder implementation/design-alignment report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-22T09:02:51Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVNKD56W`.
Implementation commit:
- `5149ab70 workspace: implement db schema v0 bootstrap`
Changed areas:
- `.yoi/tickets/00001KVNKD56W/artifacts/schema-v0.md`
- Added implementation alignment notes for SQLite schema version 2。
- Documented legacy preservation/demotion for old bootstrap tables。
- `crates/workspace-server/src/store.rs`
- Replaced old bootstrap schema with Workspace DB canonical schema v0 tables。
- Advanced schema version to `2`
- Added typed v0 tables: `tickets`, `ticket_events`, `ticket_relations`, `objectives`, `objective_ticket_links`, `repositories`, `ticket_targets`, `ticket_target_paths`, `ticket_worker_links`, `artifacts`, `audit_events`
- Removed active/canonical `runs` store concept and `RunSummary`
- Added legacy migration handling that renames old bootstrap tables to `legacy_*` preservation tables instead of treating them as canonical。
- Added tests for fresh v0 schema boundaries and legacy upgrade behavior, including forbidden table absence。
- `crates/workspace-server/src/server.rs`
- Removed `/api/runs` route。
- Kept Host/Worker APIs as live runtime views。
- Added test coverage that `/api/runs` is no longer served。
- `web/workspace/src/routes/+page.svelte`
- Removed Runs endpoint card/reference。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `git diff --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `cd web/workspace && deno task check`: passed
- `cd web/workspace && deno task build`: passed
Not run by Coder:
- `nix build .#yoi --no-link`: not run because no dependency/package/source-filter changes。
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVNKD56W-workspace-db-schema-v0` at `5149ab70`
- Diff `f17a458a..HEAD` touches expected design/backend/frontend files only。
- `git diff --check f17a458a..HEAD`: passed。
- Deno validation generated ignored frontend artifacts; Orchestrator removed `web/workspace/node_modules/`, `.svelte-kit/`, and `build/` before Reviewer routing。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-22T09:03:49Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVNKD56W-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVNKD56W-workspace-db-schema-v0`
- Branch: `impl/00001KVNKD56W-workspace-db-schema-v0`
- Baseline: `f17a458a`
- Implementation commit: `5149ab70 workspace: implement db schema v0 bootstrap`
- Diff: `f17a458a..5149ab70`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Consistency between `schema-v0.md` and implemented SQLite migration/version 2。
- Absence of canonical `runs`, `hosts`, `workers`, `actors`, generic JSON/payload/metadata columns, and validation/CI result tables。
- Legacy table preservation/demotion behavior。
- Existing read APIs for Tickets/Objectives/Repositories/Hosts/Workers still work。
- `/api/runs` removal is intentional and test-covered。
- Design artifact updates remain concise and consistent。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVNKD56W-r1 at: 2026-06-22T09:13:06Z status: request_changes -->
## Review: request changes
Verdict: `request_changes`
確認範囲:
- Ticket/design authority:
- `.yoi/tickets/00001KVNKD56W/item.md`
- `.yoi/tickets/00001KVNKD56W/thread.md`
- `.yoi/tickets/00001KVNKD56W/artifacts/schema-v0.md`
- Implementation diff `f17a458a..5149ab70`:
- `crates/workspace-server/src/store.rs`
- `crates/workspace-server/src/server.rs`
- `web/workspace/src/routes/+page.svelte`
- schema artifact updates
- Target branch/head:
- Branch: `impl/00001KVNKD56W-workspace-db-schema-v0`
- Head: `5149ab703f63`
Blocking issue:
1. Legacy-upgraded `workspaces` table remains non-canonical and can reject new workspace inserts。
Fresh schema defines canonical `workspaces` as:
- `workspace_id`
- `display_name`
- `state`
- `created_at`
- `updated_at`
This matches `schema-v0.md`
However, legacy migration does not rebuild or demote the old bootstrap `workspaces` table. It only adds `state`:
- `crates/workspace-server/src/store.rs:198-200`
- `ALTER TABLE workspaces ADD COLUMN state TEXT NOT NULL DEFAULT 'active';`
Then `create_schema_v0_tables()` is called, but because it uses `CREATE TABLE IF NOT EXISTS workspaces`, the old table is left in place:
- `crates/workspace-server/src/store.rs:218-227`
The old v1 bootstrap `workspaces` table had extra `local_root TEXT NOT NULL` and `record_authority TEXT NOT NULL` columns. Those remain on upgraded DBs even though they are not part of canonical v0。
This is not merely cosmetic: `upsert_workspace()` now inserts only v0 columns:
- `crates/workspace-server/src/store.rs:87-89`
For an upgraded legacy DB, inserting a new `workspace_id` would fail on old `local_root` / `record_authority` NOT NULL columns because the insert no longer supplies them. Updating the already-existing legacy workspace may pass due conflict/update path, which is why current tests do not catch this。
Why this blocks:
- Upgraded canonical schema does not actually match `schema-v0.md`
- Legacy handling is not safe enough because active canonical `workspaces` remains partly old schema and incompatible with the new write path。
Required fix:
- Rebuild/copy `workspaces` into canonical v0 shape, or otherwise explicitly preserve old workspace data without leaving obsolete NOT NULL columns on the active canonical table。
- Add tests asserting upgraded `workspaces` column set。
- Add a post-upgrade insert/upsert test for a new workspace id。
Non-blocking concerns:
- Existing tests cover fresh forbidden table absence and legacy demotion for old `runs` / projections / artifact / repository tables, but not upgraded `workspaces` column set or post-upgrade insert; add coverage with the fix。
- Runs card/reference removal is narrow and `/api/runs` removal is test-covered with 404 assertion。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check f17a458a..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`10 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
- `nix build .#yoi --no-link --print-out-paths`: passed/cached output `/nix/store/i0dr920x6kf217zddbnaqyljh8l1gwri-yoi-0.1.0`
Generated/ignored artifacts remain in reviewer worktree after validation:
- `target/`
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
Worktree status:
- Tracked status clean; only ignored generated artifacts present。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-22T09:18:29Z -->
## Implementation report
Coder r1-fix report received from `yoi-coder-00001KVNKD56W`.
New fix commit:
- `d89ace5b workspace: canonicalize legacy workspaces`
Branch commits now:
- `5149ab70 workspace: implement db schema v0 bootstrap`
- `d89ace5b workspace: canonicalize legacy workspaces`
Fix summary:
- `crates/workspace-server/src/store.rs`
- Legacy migration now preserves old non-canonical `workspaces` by renaming it to `legacy_workspaces`
- Active canonical v0 `workspaces` is created with only:
- `workspace_id`
- `display_name`
- `state`
- `created_at`
- `updated_at`
- Existing legacy workspace rows are copied into canonical `workspaces`, defaulting `state` to `active` when no typed state existed。
- Previous legacy demotion for `repositories`, `runs`, `artifacts`, `ticket_projections`, and `objective_projections` is preserved。
- Added upgrade test assertions for:
- upgraded `workspaces` column set exactly matches v0。
- `legacy_workspaces` preserves old obsolete columns。
- old workspace data is copied into canonical table。
- post-upgrade `upsert_workspace()` succeeds for a new workspace id。
- `.yoi/tickets/00001KVNKD56W/artifacts/schema-v0.md`
- Updated implementation alignment notes to document `legacy_workspaces` preservation and canonical copy behavior。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `git diff --check f17a458a..HEAD`: passed
- `cargo run -p yoi -- ticket doctor`: passed
Not rerun by Coder for the r1 fix:
- Deno check/build and Nix build, because the fix touched only schema artifact and workspace-server store code and Reviewer had validated frontend/Nix before the blocker。
Generated artifact cleanup:
- Coder removed reviewer-generated frontend artifacts:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVNKD56W-workspace-db-schema-v0` at `d89ace5b`
- r1-fix diff `5149ab70..HEAD` touches only `crates/workspace-server/src/store.rs` and `schema-v0.md`
- `git diff --check f17a458a..HEAD`: passed。
- No ignored frontend artifacts remain under `web/workspace`
Next action:
- Route back to Reviewer for r2 verification of legacy `workspaces` canonicalization and final acceptance。
---
<!-- event: review author: yoi-reviewer-00001KVNKD56W-r1 at: 2026-06-22T09:24:03Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- r1-fix diff `5149ab70..d89ace5b`:
- `crates/workspace-server/src/store.rs`
- `.yoi/tickets/00001KVNKD56W/artifacts/schema-v0.md`
- Overall diff `f17a458a..d89ace5b`:
- `.yoi/tickets/00001KVNKD56W/artifacts/schema-v0.md`
- `crates/workspace-server/src/server.rs`
- `crates/workspace-server/src/store.rs`
- `web/workspace/src/routes/+page.svelte`
Previous blocker verification:
- Resolved。
Evidence:
- Non-canonical legacy `workspaces` is now detected by exact v0 column comparison and renamed to `legacy_workspaces`
- Canonical v0 `workspaces` is then created with exactly:
- `workspace_id`
- `display_name`
- `state`
- `created_at`
- `updated_at`
- Legacy workspace rows are copied into canonical `workspaces`, with `state` defaulted to `active` when absent。
- Tests assert:
- upgraded `workspaces` columns exactly match v0。
- `legacy_workspaces` preserves old obsolete columns。
- legacy workspace data is readable through canonical `get_workspace`
- post-upgrade `upsert_workspace()` succeeds for a new workspace id。
Blocking issues:
- None。
Non-blocking concerns:
- None requiring changes。
Ticket/design fit:
- Fresh schema creates typed v0 tables and does not create canonical top-level `runs`, `hosts`, `workers`, `actors`, or validation/CI result tables。
- Legacy `runs` is preserved only as `legacy_runs`; it does not masquerade as canonical。
- Host/Worker APIs remain live runtime views, not DB authority。
- `/api/runs` remains removed/404-tested。
- Canonical schema avoids generic `metadata_json`, `payload_json`, `diagnostics_json`, and catch-all payload columns。
- `schema-v0.md` update is narrow and consistent with migration behavior。
- No accidental frontend authority/business-logic expansion found。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check f17a458a..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`10 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link --print-out-paths`: passed, output `/nix/store/fnz7650sshl3md2vdwb4a1q8dc0hf542-yoi-0.1.0`
Not rerun in r2:
- Deno frontend check/build, because r1-fix diff touches only `store.rs` and `schema-v0.md`; r1 had already validated frontend for original `/api/runs` card removal。
Worktree status:
- Clean tracked status on `impl/00001KVNKD56W-workspace-db-schema-v0` at `d89ace5b`
- Ignored artifact present: `target/` only; no ignored frontend artifacts under `web/workspace`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-22T09:25:49Z -->
## Implementation report
Reviewer r2 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `38bd122d merge: workspace db schema v0`
- Merged branch: `impl/00001KVNKD56W-workspace-db-schema-v0`
- Implementation commits:
- `5149ab70 workspace: implement db schema v0 bootstrap`
- `d89ace5b workspace: canonicalize legacy workspaces`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`10 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `38bd122d`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-22T09:26:02Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、workspace-server tests/check、Deno check/build、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-22T09:26:19Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-22T09:26:19Z status: closed -->
## 完了
Workspace DB canonical schema v0 design を `schema-v0.md` artifact と workspace-server SQLite bootstrap/migrations に整合させ、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- SQLite schema version を `2` に進め、canonical schema v0 を実装。
- Typed v0 tables を追加:
- `tickets`
- `ticket_events`
- `ticket_relations`
- `objectives`
- `objective_ticket_links`
- `repositories`
- `ticket_targets`
- `ticket_target_paths`
- `ticket_worker_links`
- `artifacts`
- `audit_events`
- Canonical v0 から top-level `runs`, `hosts`, `workers`, `actors`, validation/CI result tables を除外。
- Generic `metadata_json`, `payload_json`, `diagnostics_json` のような catch-all payload columns を canonical v0 tables に追加しない方針を維持。
- `/api/runs` と frontend Runs card/reference を削除し、404 test を追加。
- Host/Worker APIs は DB authority ではなく live runtime views として維持。
- Legacy bootstrap tables は non-canonical `legacy_*` preservation tables に demote。
- Legacy `workspaces``legacy_workspaces` に preserve し、active canonical `workspaces` を v0 column set で作り直して既存行を copy。
- Post-upgrade `upsert_workspace()` for new workspace id が通る regression test を追加。
- `schema-v0.md` に SQLite version 2 / legacy preservation alignment notes を追加。
統合・検証:
- Merge commit: `38bd122d merge: workspace db schema v0`
- Implementation commits: `5149ab70`, `d89ace5b`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p yoi-workspace-server`, `cargo check -p yoi-workspace-server`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Ticket/Objective write authority migration to DB is not implemented。
- Host/Worker canonical DB tables are not added。
- Validation/CI result tables and Actor table are not added。
- Full TicketEvents/TicketWorkerLinks/Artifacts write surfaces are not implemented beyond schema/bootstrap alignment。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-22T09:27:06Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVNKD56W`
- `yoi-reviewer-00001KVNKD56W-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal if present:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVNKD56W-workspace-db-schema-v0`
- Deleted implementation branch:
- `impl/00001KVNKD56W-workspace-db-schema-v0`
- Orchestrator worktree remains clean on `orchestration` at `7a7891d4`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-054125-1","ticket_id":"00001KVSEBF56","kind":"accepted_plan","accepted_plan":{"summary":"Feature-split `crates/protocol` so tokio JSONL stream is optional, generate Workspace web TypeScript types from protocol wire DTOs with drift checking, import generated types from frontend, and record minimal backend proxy stance without implementing full Worker operation UI.","branch":"impl/00001KVSEBF56-protocol-typescript-types","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSEBF56-protocol-typescript-types","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates protocol/frontend/Nix, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-23T05:41:25Z"}
+87
View File
@@ -0,0 +1,87 @@
---
title: 'Generate Workspace web TypeScript types from protocol crate'
state: 'closed'
created_at: '2026-06-23T05:13:22Z'
updated_at: '2026-06-23T06:22:01Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-23T05:40:01Z'
---
## 背景
Workspace web から Worker / Pod 操作 UI を実装するにあたり、Frontend と Backend が Pod protocol の wire 型を共有する必要がある。TypeScript 側で protocol 型を手書きすると Rust 側の `crates/protocol` と容易に乖離するため、Rust の serde DTO を authority として TypeScript 型を自動生成する。
方針:
- `crates/protocol` を Pod protocol の wire schema authority とする。
- Browser は Pod Unix socket に直接接続せず、Workspace backend が proxy する。
- Backend proxy は Worker identity 解決、socket 接続、stale/missing Worker の検出、必要最小限の method block/allow 判断を行う。
- 現時点では user permission model がないため、web 専用 protocol を過剰に多重化しない。Pod protocol の `Method` / `Event` を基本に扱い、危険または UI 対象外の操作だけ backend 側で止める。
- TypeScript 型共有の本線は `ts-rs` 等による自動生成とする。wasm 化は protocol crate の portability / optional codec 用であり、TS discriminated union 型生成の代替として扱わない。
## 要件
### protocol crate の transport 非依存化
- `crates/protocol` の DTO 部分を browser/wasm target でも compile できるようにする。
- `stream.rs``tokio::io` JSONL reader/writer は optional feature に分離する。
- 例: default feature `stream`
- `tokio` dependency は `stream` feature 配下の optional dependency にする。
- `lib.rs``#[cfg(feature = "stream")] pub mod stream;` のようにし、`--no-default-features` では DTO のみが compile されるようにする。
- 少なくとも以下が通る状態にする。
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`
### TypeScript 型自動生成
- `protocol` の主要 wire 型から Workspace web 用 TypeScript 型を自動生成する。
- 手書きの protocol mirror 型を増やさない。
- 第一候補は `ts-rs`
- `serde` attribute compatibility を使い、`#[serde(tag = ..., content = ..., rename_all = ...)]` の wire 表現と TS 型を合わせる。
- `uuid::Uuid``serde_json::Value``PathBuf` などの扱いを明示する。必要なら feature や `#[ts(type = "...")]` / `#[ts(as = "...")]` を使う。
- 生成対象の root type は少なくとも以下を含める。
- `Method`
- `Event`
- `Segment`
- Worker 操作 UI / stream 表示で直接参照する関連 DTO
- 生成ファイルは Workspace web が import できる場所に置く。
- 例: `web/workspace/src/lib/generated/protocol.ts` または同等の generated directory。
- 生成物の更新漏れを検出できる検証手段を用意する。
- 例: cargo test / xtask / generator binary で生成し、差分が出たら失敗する check。
### Workspace backend proxy 方針
- Browser から Pod protocol を直接 socket に送らず、Workspace backend 経由にする設計にする。
- Backend は `worker_id` から local Pod identity/socket を解決する。
- Backend は proxy 時に最低限以下を確認する。
- 対象 Worker が Workspace runtime view から見えること。
- Pod socket が存在し接続可能であること。
- UI/API から許可する `Method` であること。
- stale/missing/disconnected Worker の error を明示的に返すこと。
- user permission model が入るまでは、別 protocol による権限モデルを先取りしない。
### Frontend integration stance
- Workspace web は generated TypeScript types を import して Worker 操作 UI / event handling に使う。
- Protocol 型の handwritten mirror を残す場合は、暫定互換や UI 専用 view model として明示し、wire type と混同しない。
- WebSocket/SSE/HTTP の transport 選択は後続実装で決めてよいが、wire payload 型は generated protocol types に寄せる。
## Non-goals
- Full Worker operation UI の完成。
- Full WebSocket session UI の完成。
- User / role / permission model の設計。
- Browser から Pod Unix socket へ直接接続する実装。
- Pod protocol の全面的な再設計。
- OpenAPI / JSON Schema への全面移行。
## 受け入れ条件
- `crates/protocol``tokio` stream 依存が optional feature 化されている。
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features` が通る。
- `protocol` の主要 wire DTO から TypeScript 型が自動生成される。
- Workspace web が手書き mirror ではなく generated TypeScript 型を import できる。
- `serde` tagged enum / rename などの wire 表現と generated TS 型の整合性が検証されている。
- 生成物の更新漏れを検出する check がある。
- Backend proxy は browser request を Pod socket に直接丸投げせず、Worker identity 解決と最低限の method allow/block 判断を挟む方針が実装または設計記録に反映されている。
- 実装まで含める場合は `cargo test -p protocol``cargo check -p protocol --target wasm32-unknown-unknown --no-default-features``cd web/workspace && deno task check && deno task build``git diff --check``nix build .#yoi --no-link` が通る。
+29
View File
@@ -0,0 +1,29 @@
Protocol crate 由来の Workspace web TypeScript type generation を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `crates/protocol``stream` module / tokio dependency を default `stream` feature に分離し、DTO-only build で tokio を不要にした。
- Optional `typescript` feature と `ts-rs` による TypeScript export を追加。
- Protocol DTOs に `cfg_attr(feature = "typescript", derive(ts_rs::TS))` を追加。
- Deterministic generator を追加:
- `crates/protocol/src/typescript.rs`
- `crates/protocol/examples/generate_typescript.rs`
- Drift check を追加:
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`
- Generated artifact を追加:
- `web/workspace/src/lib/generated/protocol.ts`
- Workspace web が generated root protocol types を re-export:
- `PodProtocolMethod`
- `PodProtocolEvent`
- `PodProtocolSegment`
- Workspace backend extension-point notes に、browser が Pod Unix socket に直接接続せず、将来の backend proxy が Worker identity と method allow/block boundary を enforce する方針を記録。
- `Cargo.lock``package.nix` cargo hash を更新。
統合・検証:
- Merge commit: `9728b533 merge: protocol typescript generation`
- Implementation commit: `a13fb693 protocol: generate workspace TypeScript types`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p protocol`, `cargo test -p protocol --features typescript generated_protocol_types_are_current`, `cargo test -p protocol --features typescript`, `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
既知の非ブロッキング事項:
- `ts-rs``#[serde(other)]` on `Segment::Unknown` に warning を出すが、generated artifact には `{ "kind": "unknown" }` が含まれ、current validation は pass。
- 一部 `Option<T>` + `skip_serializing_if` fields は TS で optional field ではなく required nullable に出る。将来 UI が該当 field を使う際は注意。
+392
View File
@@ -0,0 +1,392 @@
<!-- event: create author: "yoi ticket" at: 2026-06-23T05:13:22Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-23T05:14:09Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-23T05:14:09Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T05:40:01Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T05:41:02Z -->
## Decision
Routing decision: `implementation_ready`
Reason:
- Ticket body has concrete requirements for protocol DTO feature-splitting, generated TypeScript types, generated-output drift check, and Workspace web integration stance。
- No blocking relations / orchestration plan records exist。
- Current queued Ticket is this Ticket only。
- Orchestrator worktree is clean on `orchestration` at `615c0250`; target worktree / branch is not present。
- Existing code map confirms `crates/protocol` currently has `tokio` dependency and `stream.rs` enabled unconditionally, while frontend has local hand-written types for Workspace entities but no generated protocol types yet。
IntentPacket:
Intent:
- Make `crates/protocol` the Rust authority for Pod wire DTOs and generate Workspace web TypeScript types from those DTOs instead of hand-writing protocol mirror types。
Binding decisions / invariants:
- DTO authority remains Rust `crates/protocol`; do not create a separate web-only protocol authority。
- Browser must not connect directly to Pod Unix sockets。
- Backend proxy may be design-recorded or minimally scaffolded, but must preserve Worker identity resolution and method allow/block boundary; do not implement broad Worker operation UI in this Ticket。
- `stream.rs` / JSONL tokio transport should be optional behind a default `stream` feature; DTO-only crate should compile without tokio for wasm/no-default-features。
- Generated TypeScript must reflect serde wire shape for tagged enums / rename conventions as closely as practical。
- Generated artifacts should be committed only if they are intended import artifacts and have a drift check。
- Avoid broad protocol redesign or permission-model invention。
Requirements / acceptance criteria:
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features` passes, or if target installation is unavailable in environment, the code is structured correctly and validation limitation is documented。
- Protocol root types at least include `Method`, `Event`, `Segment`, and related DTOs needed by Worker operation UI / stream display。
- Workspace web can import generated protocol TypeScript types from a generated directory/file。
- Generated-output drift check exists, e.g. cargo test/generator check that fails if committed generated TS is stale。
- `cargo test -p protocol` passes。
- Deno check/build passes。
- `git diff --check` and `nix build .#yoi --no-link` pass if dependencies/package hash changed。
- Backend proxy stance is represented in implementation or design notes without direct browser-to-Pod socket exposure。
Implementation latitude:
- Use `ts-rs` if it fits; otherwise choose a small generator that preserves serde-tagged shape and is reviewable。
- Put generated types under `web/workspace/src/lib/generated/protocol.ts` or similarly clear generated path。
- Generator can be a test in `protocol`, a small binary/example, or another deterministic Cargo path; keep it simple and reproducible。
- If adding `ts-rs` feature annotations is invasive, cover a useful initial subset and document unsupported types clearly, but keep `Method`, `Event`, and `Segment` included。
- For `uuid::Uuid`, `PathBuf`, `serde_json::Value`, choose clear TS representations (`string`, `unknown`/JSON value, etc.) and document/test them。
Escalate if:
- `ts-rs` cannot represent current serde-tagged enums without unacceptable manual mirrors。
- Making protocol DTOs wasm/no-default-features compatible requires broad type redesign beyond optional `stream` feature。
- Generated file would include secret/project-local content or nondeterministic ordering。
- Backend proxy implementation scope expands into full Worker operation UI/session WebSocket implementation。
Validation plan:
- `cargo fmt --check`
- `cargo test -p protocol`
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`
- Type generation drift check command/test。
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link` if Cargo.lock/package.nix/source behavior changes。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T05:41:13Z from: queued to: inprogress reason: human_authorized_unblocked_protocol_types_generation field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria and no recorded blockers, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T05:42:14Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSEBF56-protocol-typescript-types`
- Created branch:
- `impl/00001KVSEBF56-protocol-typescript-types`
- Base commit:
- `746c51c7 ticket: accept protocol ts generation`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVSEBF56`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVSEBF56-protocol-typescript-types`
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:09:42Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVSEBF56`.
Implementation commit:
- `a13fb693 protocol: generate workspace TypeScript types`
Changed areas:
- `crates/protocol`
- Made `stream` optional behind default feature `stream`
- Added optional `typescript` feature using `ts-rs`
- Added `cfg_attr(feature = "typescript", derive(ts_rs::TS))` to protocol DTOs。
- Added deterministic generator module and example:
- `crates/protocol/src/typescript.rs`
- `crates/protocol/examples/generate_typescript.rs`
- Added drift check:
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`
- `web/workspace`
- Added generated TypeScript artifact:
- `web/workspace/src/lib/generated/protocol.ts`
- Re-exported generated root protocol types from workspace sidebar types:
- `PodProtocolMethod`
- `PodProtocolEvent`
- `PodProtocolSegment`
- `crates/workspace-server`
- Updated extension-point notes to explicitly preserve no direct browser-to-Pod socket exposure and require future Workspace-server proxy enforcement of Worker identity / method allow-block boundaries。
- Packaging/dependencies:
- Updated `Cargo.lock`
- Updated `package.nix` `cargoHash`
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p protocol`: passed
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`: passed
- `cargo test -p protocol --features typescript`: passed
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `git diff --check`: passed
- `nix build .#yoi --no-link`: passed
Generated artifact cleanup:
- Only intended generated TypeScript import artifact is tracked。
- Orchestrator removed ignored `web/workspace/node_modules/` before Reviewer routing; no ignored frontend artifacts remain under `web/workspace`
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSEBF56-protocol-typescript-types` at `a13fb693`
- Diff `746c51c7..HEAD` touches expected protocol/frontend/workspace-server/package files only。
- `git diff --check 746c51c7..HEAD`: passed。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T06:10:31Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVSEBF56-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSEBF56-protocol-typescript-types`
- Branch: `impl/00001KVSEBF56-protocol-typescript-types`
- Baseline: `746c51c7`
- Implementation commit: `a13fb693 protocol: generate workspace TypeScript types`
- Diff: `746c51c7..a13fb693`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Generated TS shape vs serde wire shape。
- `Method` / `Event` / `Segment` coverage。
- Deterministic drift check。
- `stream` feature gating and wasm/no-default protocol compile。
- No direct browser-to-Pod socket implication。
- Package/Nix updates。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVSEBF56-r1 at: 2026-06-23T06:16:54Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVSEBF56/item.md`
- `.yoi/tickets/00001KVSEBF56/thread.md`
- Diff `746c51c7..a13fb693`:
- `crates/protocol/Cargo.toml`
- `crates/protocol/src/lib.rs`
- `crates/protocol/src/typescript.rs`
- `crates/protocol/examples/generate_typescript.rs`
- `web/workspace/src/lib/generated/protocol.ts`
- `web/workspace/src/lib/workspace-sidebar/types.ts`
- `crates/workspace-server/src/server.rs`
- `Cargo.lock`
- `package.nix`
Blocking issues:
- None。
Non-blocking concerns:
- `cargo test -p protocol --features typescript` emits `ts-rs` warnings for `#[serde(other)]` on `Segment::Unknown`: `ts-rs failed to parse this attribute. It will be ignored.` The generated artifact still includes `{ "kind": "unknown" }`, and this does not break current validation, but TS generator is not fully understanding serde fallback semantics。
- Some `Option<T>` fields with `skip_serializing_if = "Option::is_none"` are generated as required nullable rather than optional nullable, e.g. `RewindTarget.disabled_reason: string | null` and `warning: string | null`. Acceptable for this initial generated-types ticket, but future UI code should be careful because runtime JSON may omit those fields。
Review findings:
- `crates/protocol` remains Rust DTO authority。
- `stream` is now an optional default feature:
- `default = ["stream"]`
- `stream = ["dep:tokio"]`
- `tokio` is optional。
- DTO-only/no-default protocol build compiles for wasm without `tokio`
- `typescript` feature is optional and uses `ts-rs`
- Generated TS root includes `Method`, `Event`, `Segment`, plus related DTOs such as `PodEvent`, `ScopeRule`, `Greeting`, `InFlight*`, rewind DTOs, completion DTOs, status/result/error enums。
- Generated TS file is committed at `web/workspace/src/lib/generated/protocol.ts`
- Workspace web re-exports generated root protocol types as `PodProtocolMethod`, `PodProtocolEvent`, and `PodProtocolSegment`
- Generated TS tagged enums and casing match observed serde wire shape for critical roots:
- `Method`: `{ "method": "...", "params": ... }`
- `Event`: `{ "event": "...", "data": ... }`
- `Segment` / `PodEvent` / `InFlightBlock`: internal `"kind"` tags with snake_case variants。
- Drift check `generated_protocol_types_are_current` compares committed generated artifact to deterministic generator output。
- Backend proxy stance is represented in Workspace API extension-point notes and does not add direct browser-to-Pod socket access or broad Worker operation UI。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 746c51c7..HEAD`: passed
- `cargo test -p protocol`: passed (`40 passed`)
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`: passed; emitted non-blocking `ts-rs` warning for `serde(other)`
- `cargo test -p protocol --features typescript`: passed (`41 passed`); emitted same non-blocking warning。
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`: passed
- `cd web/workspace && deno task check && deno task build`: passed (`svelte-check found 0 errors and 0 warnings`; build succeeded)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Generated artifact status:
- `web/workspace/src/lib/generated/protocol.ts` remained unchanged after validation。
- SHA-256 after validation: `3984a043ded1179545656e5402171c49b2d22b5529aa17f016b675e394b7e553`
Worktree status:
- Clean on `impl/00001KVSEBF56-protocol-typescript-types` at `a13fb693`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:20:49Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `9728b533 merge: protocol typescript generation`
- Merged branch: `impl/00001KVSEBF56-protocol-typescript-types`
- Implementation commit:
- `a13fb693 protocol: generate workspace TypeScript types`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p protocol`: passed
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`: passed
- `cargo test -p protocol --features typescript`: passed
- Non-blocking `ts-rs` warning for `#[serde(other)]` on `Segment::Unknown` remains as reviewer noted。
- `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `9728b533`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:21:01Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、protocol tests/drift check/wasm no-default check、Deno check/build、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-23T06:21:19Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T06:21:19Z status: closed -->
## 完了
Protocol crate 由来の Workspace web TypeScript type generation を実装し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- `crates/protocol``stream` module / tokio dependency を default `stream` feature に分離し、DTO-only build で tokio を不要にした。
- Optional `typescript` feature と `ts-rs` による TypeScript export を追加。
- Protocol DTOs に `cfg_attr(feature = "typescript", derive(ts_rs::TS))` を追加。
- Deterministic generator を追加:
- `crates/protocol/src/typescript.rs`
- `crates/protocol/examples/generate_typescript.rs`
- Drift check を追加:
- `cargo test -p protocol --features typescript generated_protocol_types_are_current`
- Generated artifact を追加:
- `web/workspace/src/lib/generated/protocol.ts`
- Workspace web が generated root protocol types を re-export:
- `PodProtocolMethod`
- `PodProtocolEvent`
- `PodProtocolSegment`
- Workspace backend extension-point notes に、browser が Pod Unix socket に直接接続せず、将来の backend proxy が Worker identity と method allow/block boundary を enforce する方針を記録。
- `Cargo.lock``package.nix` cargo hash を更新。
統合・検証:
- Merge commit: `9728b533 merge: protocol typescript generation`
- Implementation commit: `a13fb693 protocol: generate workspace TypeScript types`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p protocol`, `cargo test -p protocol --features typescript generated_protocol_types_are_current`, `cargo test -p protocol --features typescript`, `cargo check -p protocol --target wasm32-unknown-unknown --no-default-features`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
既知の非ブロッキング事項:
- `ts-rs``#[serde(other)]` on `Segment::Unknown` に warning を出すが、generated artifact には `{ "kind": "unknown" }` が含まれ、current validation は pass。
- 一部 `Option<T>` + `skip_serializing_if` fields は TS で optional field ではなく required nullable に出る。将来 UI が該当 field を使う際は注意。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:22:01Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVSEBF56`
- `yoi-reviewer-00001KVSEBF56-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal if present:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSEBF56-protocol-typescript-types`
- Deleted implementation branch:
- `impl/00001KVSEBF56-protocol-typescript-types`
- Orchestrator worktree remains clean on `orchestration` at `b547203f`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-061132-1","ticket_id":"00001KVSFXY88","kind":"accepted_plan","accepted_plan":{"summary":"Remove redundant Workspace Dashboard title/actionbar key hints and selected-row textual status display while preserving row selection markers and Dashboard keyboard/action semantics, updating render tests accordingly.","branch":"impl/00001KVSFXY88-dashboard-hint-cleanup","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSFXY88-dashboard-hint-cleanup","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates TUI tests, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-23T06:11:32Z"}
+103
View File
@@ -0,0 +1,103 @@
---
title: 'TUI Dashboard の冗長な key hints と selected-row 状態表示を削る'
state: 'closed'
created_at: '2026-06-23T05:40:56Z'
updated_at: '2026-06-23T06:33:21Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['tui-ux', 'terminal-layout']
queued_by: 'workspace-panel'
queued_at: '2026-06-23T06:08:42Z'
---
## User claims / request snapshot
- ユーザーは TUI Dashboard の key hints を消したい。
- 対象として、Composer 下部の hint、最上行の hint、最上行側に出ている selected-row / 選択中表示が挙げられた。
- 選択中の情報は Composer 側で賄えているため、別表示はいらない、という意図。
## Confirmed facts / sources
- `crates/tui/src/dashboard/render.rs``draw_title` が最上行の guidance/hint を描画している。
- `crates/tui/src/dashboard/render.rs``target_status_line` が composer target と selected Ticket / selected Pod / selected Intake Pod / no row selected などの状態行を描画している。
- `crates/tui/src/dashboard/render.rs``actionbar_left_text` / `actionbar_right_text` が Composer 下部の actionbar/key hints を描画している。
- `crates/tui/src/dashboard/render.rs``panel_row_title_line` / `push_ticket_primary_marker_span` などは list 内の選択マーカーを描画しており、今回の「最上行の選択中表示」とは分けて扱うのが安全そう。
- closed Ticket `00001KTFQ109V` / `Remove workspace panel direct Pod send` は direct Pod send の UI/key hints を除去済みで、今回の依頼と矛盾しない。
## Unverified hypotheses
- 「最上行の選択中の表示」は、list 内の `▶` marker ではなく、`target_status_line` に出ている selected Ticket / selected Pod などの textual status を指している、という前提。
- Composer 下部の「奴」は `draw_actionbar` で描画される actionbar 全体、または少なくとも右側の key hint string を指している、という前提。
## Undecided points / open questions
- blocking open question はない。
- 実装時の確認前提: list 内の選択マーカー `▶` / selected row の色・bold は残す。消すのは説明文・key hint・選択中状態のテキスト表示であり、キーボード操作自体は変えない。
## Background
Dashboard は composer target と row selection の関係を複数箇所で説明しているが、現在は Composer 側で十分に文脈を伝えられるため、画面上の hint / status 表示が冗長になっている。
## Requirements
- Dashboard の最上行から key hint / 操作説明の guidance を削る。
- Composer 下部の actionbar から常時表示される key hints を削る、または最小化する。
- selected Ticket / selected Pod / selected Intake Pod / no row selected などの専用 status line 表示を削る。
- Composer target / draft submit の必要な情報は Composer 近傍または既存 composer 表示で賄う。
- row selection / keyboard operation の実際の挙動は維持する。
- Ticket Queue / Intake launch / Pod open-attach / Companion target の既存動作は変えない。
## Acceptance criteria
- `yoi panel` の最上行に `Row selection``blank Enter``Tab target` 等の key hint 文言が出ない。
- Composer 下部の actionbar に常時 key hint 群が出ない。
- selected row の textual status line が出ない、または selected-row 表示として認識される冗長情報がなくなる。
- list 内では現在の選択行を視認できる。
- 既存の Dashboard 操作は維持される:
- blank Enter の row action
- text Enter の composer target action
- Tab target switching
- Esc clear selection
- Pod open/attach
- Ticket Intake / Queue 関連動作
- 関連 render/unit tests が新しい表示仕様に更新される。
## Binding decisions / invariants
- この Ticket では Dashboard の表示整理だけを扱う。
- Console / single-Pod TUI の key hints は対象外。
- list 内の選択行マーカーや keyboard navigation visibility は削らない。
- direct selected-Pod send を再導入しない。
- Companion lifecycle / Orchestrator lifecycle / Ticket workflow semantics は変更しない。
## Implementation latitude
- `target_status_line` の layout row を完全に削るか、空/最小表示にするかは実装側で判断してよい。
- actionbar は完全削除・左側 notice のみ残す・一時 notice のみ残す等、既存 layout とテストに自然な形を選んでよい。
- 既存 tests は snapshot 的に文字列を確認している箇所を中心に更新してよい。
## Readiness
- readiness: implementation_ready
- risk_flags: [tui-ux, terminal-layout]
## Escalation conditions
- row selection marker まで削る必要が出た場合。
- Composer だけでは current target / action が分からなくなり、代替表示が必要だと判断した場合。
- layout row を削ることで terminal resize / hitbox / mouse selection に副作用が出る場合。
## Validation
- `cargo test -p tui dashboard --lib` または Dashboard 関連の focused tests。
- 必要に応じて `cargo test -p tui workspace_panel --lib`
- `cargo fmt --check`
- `git diff --check`
- 可能なら `yoi panel` の実表示確認。
## Related work
- `00001KTFQ109V` — Remove workspace panel direct Pod send
- `crates/tui/src/dashboard/render.rs`
- `crates/tui/src/dashboard/mod.rs`
- `crates/tui/src/dashboard/tests.rs`
+20
View File
@@ -0,0 +1,20 @@
TUI Dashboard の冗長な key hints と selected-row textual status display を削除し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Top title line から `Row selection`, `blank Enter`, `Tab target` などの key hint guidance を削除。
- Selected Ticket / Pod / Intake / no-row selected textual status line を blank にした。
- Composer bottom actionbar を always-on key hints ではなく notices / diagnostics only に最小化。
- Row marker / highlighting rendering は維持。
- Keyboard/action behavior は変更していない。
- Unused selected-row display-status helper を削除。
- Dashboard render/unit tests を新 display contract に更新し、selected row marker の visibility assertion は維持。
統合・検証:
- Merge commit: `5abf16f9 merge: dashboard hint cleanup`
- Implementation commit: `03ad525f tui: trim dashboard redundant hints`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p tui dashboard --lib`, `cargo test -p tui workspace_panel --lib`, and `cargo run -p yoi -- ticket doctor`
範囲外:
- Console / single-Pod TUI hints は変更していない。
- Manual/PTY `yoi panel` visual check は実施していない。Focused render/unit tests を主 validation とした。
+306
View File
@@ -0,0 +1,306 @@
<!-- event: create author: ticket-intake at: 2026-06-23T05:40:56Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T06:08:42Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T06:11:11Z -->
## Decision
Routing decision: `implementation_ready_parallel`
Reason:
- Ticket body has concrete Dashboard render targets and acceptance criteria。
- No relations / blockers / orchestration plan records exist。
- Active work `00001KVSEBF56` (protocol TS generation) and `00001KVSGFM65` (Workspace web Kanban review) are separate from TUI Dashboard render code。
- Orchestrator worktree is clean on `orchestration` at `0e635ba6`; target worktree / branch is not present。
- Bounded code map confirms relevant functions in `crates/tui/src/dashboard/render.rs`: `draw_title`, `target_status_line`, `actionbar_left_text`, `actionbar_right_text`, `draw_actionbar`, and tests in `crates/tui/src/dashboard/tests.rs`
IntentPacket:
Intent:
- Remove redundant Dashboard key hints and selected-row textual status while preserving actual row selection visibility and keyboard behavior。
Binding decisions / invariants:
- This Ticket only changes Dashboard display cleanup。
- Console / single-Pod TUI key hints are out of scope。
- Do not remove list row selection markers / highlighting / keyboard navigation visibility。
- Do not reintroduce direct selected-Pod send。
- Companion lifecycle / Orchestrator lifecycle / Ticket workflow semantics must not change。
- Existing Dashboard actions must remain: blank Enter row action, text Enter composer-target action, Tab target switching, Esc clear selection, Pod open/attach, Ticket Intake/Queue flows。
Requirements / acceptance criteria:
- Top title line no longer shows key hint guidance such as `Row selection`, `blank Enter`, `Tab target`
- Composer bottom actionbar no longer shows always-on key hint groups, or is minimized to non-redundant notices only。
- Selected Ticket / selected Pod / selected Intake Pod / no row selected textual status line is removed or no longer recognized as redundant selected-row status。
- List still visibly indicates current selected row。
- Related render/unit tests are updated to the new display specification。
Implementation latitude:
- `target_status_line` layout row may be removed, made empty/minimal, or repurposed only if it does not show redundant selected-row status。
- Actionbar may be fully removed, notice-only, or otherwise minimized depending on layout/tests。
- Keep row markers like `▶` and selected styling unless explicitly escalated。
- If layout row removal creates resize/hitbox complications, choose minimal empty/notice behavior and document the tradeoff。
Escalate if:
- Removing status/actionbar rows makes current composer target/action ambiguous enough to require alternative UI。
- Row selection marker/visibility also needs removal。
- Layout changes cause terminal resize / hitbox / mouse selection side effects that require broader Dashboard layout refactor。
Validation plan:
- `cargo fmt --check`
- `cargo test -p tui dashboard --lib`
- `cargo test -p tui workspace_panel --lib` if affected by shared tests/helpers。
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- Manual/PTY `yoi panel` check if practical, but focused render tests are primary。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:11:22Z from: queued to: inprogress reason: human_authorized_unblocked_dashboard_hint_cleanup field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete Dashboard render acceptance criteria and no recorded blockers, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:12:36Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSFXY88-dashboard-hint-cleanup`
- Created branch:
- `impl/00001KVSFXY88-dashboard-hint-cleanup`
- Base commit:
- `3bfd1ca0 ticket: accept dashboard hint cleanup`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVSFXY88`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVSFXY88-dashboard-hint-cleanup`
Parallelization note:
- Active Workspace web / protocol work is separate from TUI Dashboard rendering. This Ticket should stay limited to `crates/tui/src/dashboard/*` unless tests reveal a narrow shared helper impact。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:28:12Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVSFXY88`.
Implementation commit:
- `03ad525f tui: trim dashboard redundant hints`
Changed areas:
- `crates/tui/src/dashboard/render.rs`
- Removed top title key-hint guidance。
- Made selected-row/composer target status line blank。
- Minimized actionbar to notices/diagnostic-only text。
- Preserved row marker/highlighting rendering。
- `crates/tui/src/dashboard/mod.rs`
- Removed now-unused selected-row display-status helper。
- `crates/tui/src/dashboard/tests.rs`
- Updated render/unit expectations for no redundant hints/status。
- Added title guidance cleanup assertion。
- Kept assertions that selected rows remain visibly marked。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p tui dashboard --lib`: passed
- `cargo test -p tui workspace_panel --lib`: passed
- `git diff --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed
Manual/PTY `yoi panel` check:
- Not run; focused render/unit tests were used as primary validation。
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSFXY88-dashboard-hint-cleanup`
- HEAD is `03ad525f`
- Diff `3bfd1ca0..HEAD` touches expected dashboard render/module/tests files only。
- `git diff --check 3bfd1ca0..HEAD`: passed。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T06:28:54Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVSFXY88-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSFXY88-dashboard-hint-cleanup`
- Branch: `impl/00001KVSFXY88-dashboard-hint-cleanup`
- Baseline: `3bfd1ca0`
- Implementation commit: `03ad525f tui: trim dashboard redundant hints`
- Diff: `3bfd1ca0..03ad525f`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Removal of redundant title/actionbar key hints and selected-row textual status。
- Preservation of visible row selection marker/highlighting。
- No keyboard behavior/action semantics changes。
- Dashboard render tests updated to new display contract。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVSFXY88-r1 at: 2026-06-23T06:31:21Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVSFXY88/item.md`
- `.yoi/tickets/00001KVSFXY88/thread.md`
- Diff `3bfd1ca0..03ad525f`:
- `crates/tui/src/dashboard/render.rs`
- `crates/tui/src/dashboard/mod.rs`
- `crates/tui/src/dashboard/tests.rs`
Evidence:
- Top title guidance was removed; `title_line` now keeps only `workspace dashboard` plus companion/orchestrator status。
- `target_status_line` now renders blank, removing selected Ticket / Pod / Intake / no-row textual status。
- Actionbar is reduced to sending/refreshing/notices/diagnostic text; always-on key hint groups are gone。
- Row marker/highlighting paths remain; tests assert selected row marker strings such as `▶ ready`, `▶ queued`, and ` ▶ live`
- Keyboard/action behavior was not altered in the diff; removed helpers were display-only and no remaining references exist。
- No Console/single-Pod TUI files changed。
- No direct selected-Pod send was reintroduced; existing dashboard behavior tests still pass。
Blocking issues:
- None。
Non-blocking concerns:
- Manual `yoi panel` PTY visual check was not run; focused render/unit coverage was used as primary validation, as suggested。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 3bfd1ca0..HEAD`: passed
- `cargo test -p tui dashboard --lib`: passed (`107 passed`)
- `cargo test -p tui workspace_panel --lib`: passed (`23 passed`)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
Worktree status:
- Clean on `impl/00001KVSFXY88-dashboard-hint-cleanup` at `03ad525f`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:32:25Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `5abf16f9 merge: dashboard hint cleanup`
- Merged branch: `impl/00001KVSFXY88-dashboard-hint-cleanup`
- Implementation commit:
- `03ad525f tui: trim dashboard redundant hints`
Orchestrator worktree validation:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p tui dashboard --lib`: passed (`107 passed`)
- `cargo test -p tui workspace_panel --lib`: passed (`23 passed`)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
Final Orchestrator worktree status after validation is clean on `orchestration` at `5abf16f9`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:32:37Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、focused Dashboard / workspace_panel tests、Ticket doctor が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-23T06:32:49Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T06:32:49Z status: closed -->
## 完了
TUI Dashboard の冗長な key hints と selected-row textual status display を削除し、Orchestrator worktree の `orchestration` branch に統合した。
主な成果:
- Top title line から `Row selection`, `blank Enter`, `Tab target` などの key hint guidance を削除。
- Selected Ticket / Pod / Intake / no-row selected textual status line を blank にした。
- Composer bottom actionbar を always-on key hints ではなく notices / diagnostics only に最小化。
- Row marker / highlighting rendering は維持。
- Keyboard/action behavior は変更していない。
- Unused selected-row display-status helper を削除。
- Dashboard render/unit tests を新 display contract に更新し、selected row marker の visibility assertion は維持。
統合・検証:
- Merge commit: `5abf16f9 merge: dashboard hint cleanup`
- Implementation commit: `03ad525f tui: trim dashboard redundant hints`
- Reviewer final verdict: approve
- Validation passed: `cargo fmt --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p tui dashboard --lib`, `cargo test -p tui workspace_panel --lib`, and `cargo run -p yoi -- ticket doctor`
範囲外:
- Console / single-Pod TUI hints は変更していない。
- Manual/PTY `yoi panel` visual check は実施していない。Focused render/unit tests を主 validation とした。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:33:21Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVSFXY88`
- `yoi-reviewer-00001KVSFXY88-r1`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSFXY88-dashboard-hint-cleanup`
- Deleted implementation branch:
- `impl/00001KVSFXY88-dashboard-hint-cleanup`
- Orchestrator worktree remains clean on `orchestration` at `10866666`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-055433-1","ticket_id":"00001KVSGFM65","kind":"accepted_plan","accepted_plan":{"summary":"Refactor Repository Ticket Kanban into grouped frontend component with display-only planning+ready and queued+inprogress groups, priority sort, per-group scroll areas, independent lazy visible counts, original state badges, and design-token styling without backend lifecycle changes.","branch":"impl/00001KVSGFM65-kanban-lazy-rows","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSGFM65-kanban-lazy-rows","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope frontend Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates Deno/Nix, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-23T05:54:33Z"}
+83
View File
@@ -0,0 +1,83 @@
---
title: 'Improve Workspace web ticket Kanban grouping and lazy rows'
state: 'closed'
created_at: '2026-06-23T05:50:36Z'
updated_at: '2026-06-23T06:16:10Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-23T05:53:22Z'
---
## 背景
Workspace web の Repository Ticket Kanban は Ticket state ごとに縦方向へ列/行を増やして表示しているが、`closed` など件数の多い state が画面を圧迫しやすい。実運用では `planning``ready``queued``inprogress` は近い段階としてまとめて見たい一方で、各 group 内では実行に近い state を上に表示したい。
Repository page の Ticket 表示を、state group ごとの独立スクロール領域と lazy row loading に変更する。必要に応じて Kanban 表示コンポーネントを切り出し、page component の責務を軽くする。
## 要件
### State grouping / sort
- `planning``ready` を同じ表示 group に統合する。
- 表示 label は実装時に自然なものを選んでよいが、両 state が同じ group だと分かること。
- group 内の sort は `ready``planning` より上に来ること。
- `queued``inprogress` を同じ表示 group に統合する。
- group 内の sort は `inprogress``queued` より上に来ること。
- その他の state は既存意味を保つ。
- 例: `done`, `closed` は独立 group のままでよい。
- 各 Ticket row には元の `state` が識別できる表示を残す。
### Per-group independent scroll
- すべての Kanban group / row list は独立した scroll area を持つ。
- 各 scroll area の高さはおおむね Ticket 10件分を表示できる高さにする。
- 件数の多い state/group が page 全体を圧迫しないこと。
- page 全体の scroll と group 内 scroll の責務が不自然に競合しないこと。
### Lazy row loading
- 各 group は初期表示 30件までに制限する。
- group 内 scroll area の下部付近まで到達したら、その group だけ追加件数を読み込んで表示する。
- lazy loading は group ごとに独立していること。
- `closed` を下まで scroll しても `ready/planning` など他 group の表示件数は増えない。
- Backend API の pagination 実装までは必須にしない。
- 既存 API がまとめて返す範囲内で、Frontend 側の表示件数を段階的に増やす実装でよい。
- ただし将来 backend pagination に差し替えられるよう、表示 state は group 単位で管理する。
### Component boundary
- Kanban 表示は `WorkspacePage.svelte` から切り出してよい。
- 切り出す場合は、少なくとも以下の責務を component に寄せる。
- state grouping
- group 内 sort
- per-group visible count
- scroll bottom detection
- Ticket row rendering
- page component は repository data fetch / high-level layout に寄せる。
### Design system alignment
- Workspace web design system に沿い、不要な角丸/縁取り/filled card を増やさない。
- group 境界は余白・文字サイズ・文字色・細い rule を優先して表現する。
- 色は `web/workspace/src/app.css` の token を使い、raw color を追加しない。
## Non-goals
- Backend pagination API の本格実装。
- Ticket state lifecycle の変更。
- Ticket mutation UI の追加。
- Repository target metadata / DB schema の実装。
- TUI Dashboard / Panel の Kanban 表示変更。
## 受け入れ条件
- Repository Ticket Kanban で `planning``ready` が同一 group として表示される。
- その group 内で `ready` Ticket が `planning` Ticket より上に表示される。
- Repository Ticket Kanban で `queued``inprogress` が同一 group として表示される。
- その group 内で `inprogress` Ticket が `queued` Ticket より上に表示される。
- 各 group は独立 scroll area を持ち、おおむね 10件分の高さでスクロールできる。
- 各 group は初期 30件だけ表示し、下部まで scroll するとその group だけ追加表示される。
- 件数の多い `closed` group が page 全体の縦幅を大きく圧迫しない。
- Ticket row には元 state が分かる表示がある。
- 必要な場合、Kanban 表示が再利用可能な Svelte component に切り出されている。
- `cd web/workspace && deno task check && deno task build``git diff --check``nix build .#yoi --no-link` が通る。
+22
View File
@@ -0,0 +1,22 @@
Workspace web Repository Ticket Kanban の grouping / lazy rows 改善を統合した。
主な成果:
- Repository Ticket Kanban を `RepositoryTicketKanban.svelte` component に分離。
- `planning` + `ready` を display-only group とし、`ready``planning` より上に表示。
- `queued` + `inprogress` を display-only group とし、`inprogress``queued` より上に表示。
- `done`, `closed`, `other` は独立 group として維持。
- 各 row に original Ticket state を表示。
- 各 group の初期表示行数を 30 に cap。
- 各 group に独立 scroll area と independent lazy visible count を実装。
- High-volume `closed` group が page height を無制限に伸ばさないようにした。
- `WorkspacePage.svelte` から inline Kanban logic/markup を削減。
- Styling は existing design tokens を使い、backend/API/Ticket lifecycle semantics は変更していない。
統合・検証:
- Merge commit: `eea26f91 merge: kanban lazy rows`
- Implementation commit: `6f68bb8d web: group repository ticket kanban rows`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Backend pagination、Ticket state mutation UI、drag/drop Kanban、browser/manual scroll E2E tests は追加していない。
+372
View File
@@ -0,0 +1,372 @@
<!-- event: create author: "yoi ticket" at: 2026-06-23T05:50:36Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-23T05:51:34Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-23T05:51:34Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T05:53:22Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T05:54:11Z -->
## Decision
Routing decision: `implementation_ready_parallel`
Reason:
- Ticket body has concrete frontend requirements for Repository Ticket Kanban grouping, sort order, per-group independent scroll, lazy row loading, component boundary, and Deno/Nix validation。
- No relations / blockers / orchestration plan records exist。
- Active Ticket `00001KVSEBF56` is protocol TypeScript generation and is expected to touch protocol crate / generated types; this Kanban ticket primarily targets Workspace Repository page UI and can proceed in parallel with narrow frontend scope。
- Current queued Ticket is this Ticket only。
- Orchestrator worktree is clean on `orchestration` at `2865abb6`; target worktree / branch is not present。
- Current code map shows Repository Ticket Kanban is currently inline in `web/workspace/src/lib/workspace-pages/WorkspacePage.svelte`, using `repositoryTickets.columns` from `/api/repositories/local/tickets`
IntentPacket:
Intent:
- Improve Repository Ticket Kanban display so high-volume states do not dominate the page, related states are grouped, and each group lazy-loads independently。
Binding decisions / invariants:
- Frontend display behavior only unless absolutely necessary; do not change Ticket lifecycle semantics or add mutation UI。
- Backend pagination is not required; frontend-only visible count per group is acceptable。
- Original Ticket state must remain visible on each row。
- Grouping is display-only: `planning+ready`, `queued+inprogress`, other states independent。
- Group sort priority: `ready` before `planning`, `inprogress` before `queued`
- Each group has independent scroll/visible count state; scrolling one group must not increase other groups。
- Use existing design tokens from `web/workspace/src/app.css`; avoid raw colors and heavy card chrome。
- Keep static SPA / Deno tooling boundaries。
- Do not touch protocol TS generation scope from `00001KVSEBF56` unless unavoidable。
Requirements / acceptance criteria:
- `planning` and `ready` display in the same group, with `ready` above `planning`
- `queued` and `inprogress` display in the same group, with `inprogress` above `queued`
- `done`, `closed`, and other states keep independent display meaning。
- Each group has an independent scroll area approximately 10 rows tall。
- Initial visible rows per group are capped at 30。
- Near-bottom scroll within a group increases only that groups visible count。
- `closed` or other high-volume group does not expand page height excessively。
- Row displays original Ticket state。
- Kanban display is preferably split into reusable Svelte component(s), moving grouping/sort/visible-count/scroll logic out of `WorkspacePage.svelte`
- Deno check/build, `git diff --check`, and `nix build .#yoi --no-link` pass。
Implementation latitude:
- Component can live under `web/workspace/src/lib/workspace-pages/` or another clear frontend component path。
- Backend response shape may remain unchanged; grouping can be performed client-side from returned columns/items。
- Add minimal frontend tests only if current tooling supports it cheaply; otherwise validation via Svelte check/build is acceptable。
- CSS can be simple rule/typography/spacing approach; no need for full design system。
Escalate if:
- Svelte 5 event/scroll handling requires a broader frontend state management rewrite。
- Backend response shape prevents group-level lazy display without changing API semantics。
- Deno build/check breaks due unrelated protocol type generation work。
Validation plan:
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link`
- `cargo test -p yoi-workspace-server` only if backend API changes。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T05:54:22Z from: queued to: inprogress reason: human_authorized_unblocked_frontend_kanban_improvement field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete frontend acceptance criteria and no recorded blockers; active protocol TypeScript generation work is separate enough for parallel implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T05:55:23Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSGFM65-kanban-lazy-rows`
- Created branch:
- `impl/00001KVSGFM65-kanban-lazy-rows`
- Base commit:
- `a6f9019e ticket: accept kanban lazy rows`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVSGFM65`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVSGFM65-kanban-lazy-rows`
Parallelization note:
- `00001KVSEBF56` remains active and targets protocol TypeScript generation. This Ticket should stay limited to Workspace Repository Ticket Kanban frontend display。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:05:59Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVSGFM65`.
Implementation commit:
- `6f68bb8d web: group repository ticket kanban rows`
Changed areas:
- `web/workspace/src/lib/workspace-pages/RepositoryTicketKanban.svelte`
- New reusable Kanban component。
- Groups `ready + planning`, with `ready` sorted above `planning`
- Groups `inprogress + queued`, with `inprogress` sorted above `queued`
- Keeps `done`, `closed`, and `other` as distinct display groups。
- Shows each rows original `ticket.state`
- Caps initial rendered rows per group at 30。
- Adds independent per-group scroll/lazy row expansion。
- Uses design tokens from `app.css`
- `web/workspace/src/lib/workspace-pages/WorkspacePage.svelte`
- Replaced inline Repository Ticket Kanban markup with extracted component。
- `web/workspace/src/app.css`
- Removed now-unused global inline Kanban styles。
Coder validation reported:
- `cd web/workspace && deno task check`: passed
- `cd web/workspace && deno task build`: passed
- `git diff --check HEAD~1..HEAD`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed
Notes:
- No backend API changes; `cargo test -p yoi-workspace-server` was not run。
- No protocol TypeScript generation scope touched。
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSGFM65-kanban-lazy-rows` at `6f68bb8d`
- Diff `a6f9019e..HEAD` touches expected frontend files only。
- `git diff --check a6f9019e..HEAD`: passed。
- Validation generated ignored frontend artifacts; Orchestrator removed `web/workspace/node_modules/`, `.svelte-kit/`, and `build/` before Reviewer routing。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T06:06:45Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVSGFM65-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSGFM65-kanban-lazy-rows`
- Branch: `impl/00001KVSGFM65-kanban-lazy-rows`
- Baseline: `a6f9019e`
- Implementation commit: `6f68bb8d web: group repository ticket kanban rows`
- Diff: `a6f9019e..6f68bb8d`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Display grouping/sort order: `ready > planning`, `inprogress > queued`
- Per-group independent visible count and scroll expansion。
- High-volume `closed` bounded by group scroll area。
- Original Ticket state visible per row。
- Component boundary and design-token styling。
- No backend/lifecycle/protocol scope creep。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-reviewer-00001KVSGFM65-r1 at: 2026-06-23T06:13:34Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket authority:
- `.yoi/tickets/00001KVSGFM65/item.md`
- `.yoi/tickets/00001KVSGFM65/thread.md`
- Diff `a6f9019e..6f68bb8d`:
- `web/workspace/src/lib/workspace-pages/RepositoryTicketKanban.svelte`
- `web/workspace/src/lib/workspace-pages/WorkspacePage.svelte`
- `web/workspace/src/app.css`
Review evidence:
- Grouping/sort:
- `planning` + `ready` are grouped as `ready-planning`, labelled `Ready / Planning`
- `queued` + `inprogress` are grouped as `inprogress-queued`, labelled `In progress / Queued`
- `statePriority()` places `ready` before `planning`, and `inprogress` before `queued`
- Other states:
- `done`, `closed`, and `other` remain separate group keys via `state:${state}` / `state:other`
- Per-group lazy state:
- `visibleRowsByGroup` is keyed by group key。
- Initial visible rows are `INITIAL_VISIBLE_ROWS = 30`
- Scroll handling updates only `[group.key]`
- Near-bottom threshold is `NEAR_BOTTOM_PX = 96`
- High-volume containment:
- Each non-empty group row list has its own `.ticket-list-scroll`
- `.ticket-list-scroll` uses `max-height: 34rem; overflow-y: auto;`, so `closed` cannot expand page vertically without bound。
- Original row state:
- Each ticket row renders `<span class="ticket-state">{ticket.state}</span>`
- Component boundary:
- Kanban logic and row rendering moved into `RepositoryTicketKanban.svelte`
- `WorkspacePage.svelte` now delegates with `<RepositoryTicketKanban tickets={repositoryTickets} />`
- Design / boundary:
- Styling uses existing CSS tokens such as `var(--space-*)`, `var(--line)`, `var(--text-muted)`, `var(--text-faint)`, `var(--text-strong)`
- No backend/API/protocol TypeScript generation scope touched。
- No mutation UI added。
Blocking issues:
- None found。
Non-blocking concerns:
- No browser/manual scroll interaction test was run; validation is by code inspection plus Svelte check/build. Given the tickets frontend-only scope and current test tooling, this is acceptable。
Reviewer validation:
- `git diff --check a6f9019e..6f68bb8d`: passed
- `git diff --check a6f9019e..HEAD`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check && deno task build`: passed (`svelte-check found 0 errors and 0 warnings`; static build completed)
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
- `cargo test -p yoi-workspace-server`: not run; no backend/API changes were made。
Generated artifacts:
- Ignored validation artifacts present after review:
- `target/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `web/workspace/node_modules/`
- No generated artifacts are tracked。
Worktree status:
- Clean tracked state on `impl/00001KVSGFM65-kanban-lazy-rows` at `6f68bb8d`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:15:01Z -->
## Implementation report
Reviewer r1 approvalを受けて、実装ブランチを Orchestrator worktree の `orchestration` branch に統合した。
統合:
- Merge commit: `eea26f91 merge: kanban lazy rows`
- Merged branch: `impl/00001KVSGFM65-kanban-lazy-rows`
- Implementation commit:
- `6f68bb8d web: group repository ticket kanban rows`
Orchestrator worktree validation:
- `git diff --check HEAD^1..HEAD`: passed
- `cd web/workspace && rm -rf node_modules .svelte-kit build && deno task check`: passed (`svelte-check found 0 errors and 0 warnings`)
- `cd web/workspace && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Validation generated ignored frontend artifacts in Orchestrator worktree:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
These were removed after validation. Final Orchestrator worktree status after validation cleanup is clean on `orchestration` at `eea26f91`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:15:09Z from: inprogress to: done reason: implementation_merged_and_validated field: state -->
## State changed
Reviewer approval、Orchestrator worktree への統合、Deno check/build、Ticket doctor、Nix build が完了したため `done` に遷移する。
---
<!-- event: state_changed author: hare at: 2026-06-23T06:15:22Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T06:15:22Z status: closed -->
## 完了
Workspace web Repository Ticket Kanban の grouping / lazy rows 改善を統合した。
主な成果:
- Repository Ticket Kanban を `RepositoryTicketKanban.svelte` component に分離。
- `planning` + `ready` を display-only group とし、`ready``planning` より上に表示。
- `queued` + `inprogress` を display-only group とし、`inprogress``queued` より上に表示。
- `done`, `closed`, `other` は独立 group として維持。
- 各 row に original Ticket state を表示。
- 各 group の初期表示行数を 30 に cap。
- 各 group に独立 scroll area と independent lazy visible count を実装。
- High-volume `closed` group が page height を無制限に伸ばさないようにした。
- `WorkspacePage.svelte` から inline Kanban logic/markup を削減。
- Styling は existing design tokens を使い、backend/API/Ticket lifecycle semantics は変更していない。
統合・検証:
- Merge commit: `eea26f91 merge: kanban lazy rows`
- Implementation commit: `6f68bb8d web: group repository ticket kanban rows`
- Reviewer final verdict: approve
- Validation passed: `git diff --check HEAD^1..HEAD`, `deno task check`, `deno task build`, `cargo run -p yoi -- ticket doctor`, and `nix build .#yoi --no-link`
範囲外:
- Backend pagination、Ticket state mutation UI、drag/drop Kanban、browser/manual scroll E2E tests は追加していない。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:16:10Z -->
## Implementation report
Post-close cleanup completed。
- Stopped child Pods and reclaimed scope:
- `yoi-coder-00001KVSGFM65`
- `yoi-reviewer-00001KVSGFM65-r1`
- Removed ignored frontend validation artifacts from child worktree before worktree removal if present:
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- Removed implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSGFM65-kanban-lazy-rows`
- Deleted implementation branch:
- `impl/00001KVSGFM65-kanban-lazy-rows`
- Orchestrator worktree remains clean on `orchestration` at `9de04f72`
Root/original workspace was not used for merge/validation/cleanup operations。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-065020-1","ticket_id":"00001KVSKGDYS","kind":"accepted_plan","accepted_plan":{"summary":"Add tracked `.yoi/workspace.toml` schema/loader/create-if-missing path for safe local Workspace identity and use persisted workspace id in Workspace APIs/repository/host id derivation, with tests for missing/existing/invalid/no-path-leak behavior.","branch":"impl/00001KVSKGDYS-workspace-identity","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope Workspace backend Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates workspace-server/frontend/Nix as needed, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-23T06:50:20Z"}
+119
View File
@@ -0,0 +1,119 @@
---
title: 'Persist local Workspace identity in .yoi/workspace.toml'
state: 'closed'
created_at: '2026-06-23T06:43:28Z'
updated_at: '2026-06-23T07:39:10Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-23T06:47:18Z'
---
## 背景
Workspace server の local dev bootstrap は現在、`workspace_id``local:{display}` のように workspace root の basename から導出している。これは暫定 namespace としては分かりやすいが、DB の primary key / Workspace identity としては不適切である。
問題:
- `workspace_id` が表示名 / path basename から予測可能に作られている。
- 同じ basename の workspace が複数あると衝突しうる。
- workspace root の rename / move で identity が変わる。
- `local:` namespace と display label が DB PK に混ざっている。
- `--workspace .` のような相対 path では display fallback に落ちるなど、初期化責務が `ServerConfig::local_dev` に寄りすぎている。
Workspace identity は `.yoi/workspace.toml` を local Workspace record として永続化し、未作成なら Workspace backend の初期化処理で払い出す。これにより、DB を再作成しても Workspace identity は維持され、将来の DB authority / hosted Workspace / migration でも扱いやすくなる。
## 方針
- `.yoi/workspace.toml` を local Workspace identity の authority とする。
- `workspace_id` は path / display name から導出しない。
- 新規 local Workspace 初期化時に UUIDv7 を発行して `workspace_id` として保存する。
- `display_name` は identity ではなく UI label として保存する。
- 初期値は canonicalized workspace root の basename でよい。
- 将来的に rename 可能な field として扱う。
- `ServerConfig::local_dev` は Workspace ID を生成しない。
- CLI/bootstrap 層で workspace root canonicalization と `.yoi/workspace.toml` load-or-init を行い、結果を `ServerConfig` に渡す。
- `.yoi/workspace.toml` が壊れている場合は勝手に上書きせず、明示的な error で止める。
- 既存 `.yoi/workspace.db` 内の `local:*` workspace row については、初期実装では destructive migration を必須にしない。
- 新しい UUIDv7 workspace row を upsert し、古い row は残してよい。
- 必要なら後続で cleanup/migration policy を設計する。
## `.yoi/workspace.toml` v0
最小 schema:
```toml
workspace_id = "0197..." # UUIDv7 canonical string
created_at = "2026-06-23T...Z"
display_name = "yoi"
```
Validation:
- `workspace_id` は UUID として parse できること。
- 可能なら UUID version 7 であることを検証する。
- `created_at` は RFC3339 UTC timestamp として parse できること。
- `display_name` は空文字列でないこと。
- unknown fields の扱いは将来拡張を考え、明示的に決める。
- v0 では deny でも preserve でもよいが、選択理由を実装に残す。
## 初期化フロー
`yoi-workspace-server serve --workspace <path>` の local bootstrap は将来的に以下の責務分離にする。
1. `--workspace` を canonicalize する。
2. workspace root 配下の `.yoi/` を確認し、なければ作成する。
3. `.yoi/workspace.toml` を読む。
4. 存在しない場合:
- UUIDv7 `workspace_id` を発行する。
- `created_at` を現在 UTC にする。
- `display_name` を canonicalized workspace root basename から作る。
- `.yoi/workspace.toml` を atomic-ish に書き込む。
5. 存在する場合:
- parse / validate する。
- 壊れていたら停止し、上書きしない。
6. `ServerConfig` には canonicalized workspace root と Workspace identity を渡す。
7. SQLite `workspaces` row は `.yoi/workspace.toml``workspace_id` / `display_name` で upsert する。
8. API `/api/workspace` は DB row / identity record を元に stable id と display name を返す。
## 実装候補
- `crates/workspace-server` に Workspace identity loader を追加する。
- 例: `workspace_identity.rs` または `identity.rs`
- 型例:
```rust
struct WorkspaceIdentity {
workspace_id: Uuid,
created_at: DateTime<Utc>,
display_name: String,
}
impl WorkspaceIdentity {
fn load_or_init(root: &Path) -> Result<Self, WorkspaceIdentityError>;
}
```
- `uuid` crate の UUIDv7 support を確認し、必要なら依存 feature を追加する。
- TOML parse/write には既存 dependency を優先し、なければ最小 dependency を検討する。
- `ServerConfig::local_dev``workspace_id` / `display_name` を引数または identity object で受け取る形に寄せる。
## Non-goals
- Hosted / multi-user Workspace identity の完全設計。
- Workspace rename UI。
- 既存 `.yoi/workspace.db` の destructive migration。
- Ticket / Objective storage の DB authority migration。
- `.yoi/workspace.toml` を全 Workspace settings store に拡張すること。
## 受け入れ条件
- local Workspace identity が `.yoi/workspace.toml` に永続化される。
- `.yoi/workspace.toml` 未作成時、Workspace backend 初期化時に UUIDv7 `workspace_id` が払い出される。
- `workspace_id` が path basename / display name から導出されなくなる。
- `display_name``.yoi/workspace.toml` の field として扱われ、identity と分離されている。
- `--workspace .` でも canonicalized workspace root をもとに初期化される。
- `.yoi/workspace.toml` が壊れている場合、勝手に再生成/上書きせず error で停止する。
- `ServerConfig::local_dev` または同等の bootstrap helper が workspace id を自前生成しない。
- SQLite `workspaces` row は `.yoi/workspace.toml` の identity を使って upsert される。
- 既存 `local:{display}` 形式は新規 workspace id として生成されない。
- `cargo test -p yoi-workspace-server``git diff --check``nix build .#yoi --no-link` が通る。
+38
View File
@@ -0,0 +1,38 @@
Local Workspace identity を tracked `.yoi/workspace.toml` に永続化する実装を完了した。
完了内容:
- `.yoi/workspace.toml` を local Workspace identity の authority として追加。
- v0 schema は `workspace_id`, `created_at`, `display_name` のみ。
- `workspace_id` は UUIDv7 canonical string として検証し、path / display basename から導出しない。
- `created_at` は UTC RFC3339 timestamp として検証。
- `display_name` は空文字列を拒否。
- unknown fields は v0 では明示的に deny。
- invalid existing file は fail closed し、自動上書きしない。
- missing file 初期化では `OpenOptions::create_new(true)` を使い、既存 file が race で作られた場合は persisted identity を read/parse して返す。
- fixed temp file / `path.exists()` + `rename` finalization は使わない。
- `ServerConfig::local_dev``local:{display}` を生成せず、persisted `WorkspaceIdentity` を受け取る。
- SQLite `workspaces` upsert、Workspace API、repository ids、host ids は persisted Workspace id を使う。
- legacy `/api/repositories/local` alias は維持。
- 既存 `local:*` DB rows の destructive migration はしない。
- `.yoi/workspace.toml` は絶対 path / secret / socket / runtime data を含まない安全な project identity record として維持。
統合:
- Implementation: `31565c9b feat: persist workspace identity`
- Fix: `49c9e190 fix: return persisted workspace identity`
- Merge: `2745f3d5 merge: workspace identity persistence`
検証:
- Reviewer approval: `yoi-reviewer-00001KVSKGDYS-r1`
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
生成物 cleanup:
- orchestration worktree の `target/`, `web/workspace/node_modules/`, `web/workspace/.svelte-kit/`, `web/workspace/build/` を削除済み。
残作業:
- なし。将来必要なら legacy `local:*` row cleanup / migration policy は別 Ticket で扱う。
+536
View File
@@ -0,0 +1,536 @@
<!-- event: create author: "yoi ticket" at: 2026-06-23T06:43:28Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-23T06:44:19Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-23T06:44:19Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T06:47:18Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T06:49:54Z -->
## Decision
Routing decision: `implementation_ready_parallel`
Reason:
- Ticket body has concrete `workspace.toml` semantics, backend/API consistency requirements, migration-safe behavior, tests, and validation criteria。
- No relations / blockers / orchestration plan records exist。
- Active Dashboard no-auto-selection work is TUI-only and separate from Workspace backend identity persistence, so parallel implementation is acceptable。
- Orchestrator worktree is clean on `orchestration` at `13e76d35`; target worktree / branch is not present。
- Current Workspace backend has ad-hoc/stable-ish IDs; Ticket asks for tracked local identity at `.yoi/workspace.toml`
IntentPacket:
Intent:
- Persist local Workspace identity in tracked `.yoi/workspace.toml` and use it as the stable local Workspace id across backend APIs, repository IDs, host ID derivation, and frontend display where applicable。
Binding decisions / invariants:
- `.yoi/workspace.toml` is tracked project record, not local runtime/secret file。
- It should contain only safe project identity fields, e.g. `workspace_id`, `display_name`, `created_at` or equivalent; no absolute paths, user names, socket paths, data-dir paths, tokens, or runtime secrets。
- Existing checkouts without the file must remain usable with safe auto-create or fallback behavior。
- Workspace id should not change on process restart, repo path move, or sibling worktree checkout when the file is present。
- Avoid changing Ticket/Objectives canonical authority。
- Do not confuse this with Profile/manifest/override runtime config。
- Handle invalid/corrupt `workspace.toml` fail-closed with clear diagnostic; do not silently generate a different id over a bad tracked file unless explicitly safe。
Requirements / acceptance criteria:
- Define `.yoi/workspace.toml` schema and parser/loader.
- Add create-if-missing behavior for local workspace server/bootstrap path, or a documented CLI/tool path if auto-create is unsuitable.
- Use persisted workspace id in Workspace API responses and any Repository/Host ids derived from workspace id.
- Ensure generated file is safe to commit and has no local absolute paths/secrets.
- Existing tests updated to deterministic temp workspace identity behavior。
- Add tests for missing file creation/fallback, existing stable id, invalid file error, and no local path leakage。
- Validation includes workspace-server tests, Deno check/build if frontend output changes, git diff check, Ticket doctor, and Nix build if package/source behavior changes。
Implementation latitude:
- Put parser in `workspace-server` crate if currently only the web backend needs it, or a small shared crate if needed; avoid broad architecture churn。
- Workspace id can reuse project-record id allocator if suitable, or a stable slug/uuid/base32 type if already used。
- If auto-writing tracked file during server startup is risky, implement explicit ensure function used by tests/bootstrap and document behavior; but Ticket prefers tracked persistence。
- Frontend can just display the id returned by existing `/api/workspace` if backend response changes。
Escalate if:
- Creating tracked `.yoi/workspace.toml` from a server process violates current project-record write boundaries。
- Workspace id generation requires global registry/coordination beyond local checkout。
- Existing code strongly assumes workspace id is derived from path and changing it would break multiple APIs unexpectedly。
- Nix/source filtering excludes `.yoi/workspace.toml` unexpectedly and package behavior needs product decision。
Validation plan:
- `cargo fmt --check`
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi-workspace-server`
- `cd web/workspace && deno task check && deno task build` if frontend-visible changes occur。
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link` if package/source filtering or tracked file behavior changed。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:50:08Z from: queued to: inprogress reason: human_authorized_unblocked_workspace_identity_persistence field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete local workspace identity requirements and no recorded blockers, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:51:44Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
- Created branch:
- `impl/00001KVSKGDYS-workspace-identity`
- Base commit:
- `4cda83b7 ticket: accept workspace identity and selection work`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVSKGDYS`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
Parallelization note:
- `00001KVSKJ0EA` is active separately and targets TUI Dashboard selection semantics. This Ticket should stay limited to Workspace backend identity persistence and safe project record behavior。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T07:13:47Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVSKGDYS`.
Implementation commit:
- `31565c9b feat: persist workspace identity`
Changed areas:
- Added tracked project identity record:
- `.yoi/workspace.toml`
- current contents are safe project identity fields only: `workspace_id`, `created_at`, `display_name`
- Added Workspace identity schema/loader:
- `crates/workspace-server/src/identity.rs`
- strict TOML parser with `workspace_id`, `created_at`, `display_name`
- UUIDv7 validation。
- UTC RFC3339 `created_at` validation。
- unknown fields rejected。
- create-if-missing behavior。
- invalid existing file fails closed without rewrite。
- tests for missing creation, stable existing identity, invalid file, no path leakage。
- Integrated persisted identity into workspace server/bootstrap:
- `crates/workspace-server/src/main.rs`
- `crates/workspace-server/src/server.rs`
- workspace API uses persisted `workspace_id` / display metadata。
- Updated repository ID behavior:
- `crates/workspace-server/src/repositories.rs`
- local repository ids derive from persisted Workspace id。
- legacy `/api/repositories/local` remains accepted as an alias。
- Host ID derivation now receives persisted Workspace id through existing API flow。
- Added dependencies / packaging update:
- `crates/workspace-server/Cargo.toml`
- `Cargo.lock`
- `package.nix` cargo hash。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `git diff --check`: passed
- `git diff --cached --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed
Generated artifact cleanup:
- Coder removed generated frontend artifacts:
- `web/workspace/.svelte-kit`
- `web/workspace/build`
- `web/workspace/node_modules`
- Coder removed generated Rust build cache:
- `target`
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSKGDYS-workspace-identity` at `31565c9b`
- Diff `4cda83b7..HEAD` touches expected Workspace identity/backend/package files and adds `.yoi/workspace.toml`
- `git diff --check 4cda83b7..HEAD`: passed。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T07:14:37Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVSKGDYS-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
- Branch: `impl/00001KVSKGDYS-workspace-identity`
- Baseline: `4cda83b7`
- Implementation commit: `31565c9b feat: persist workspace identity`
- Diff: `4cda83b7..31565c9b`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Safety and tracked-project-record suitability of `.yoi/workspace.toml`
- Stable persisted id usage in Workspace API / repository / host ids。
- Missing/existing/invalid file behavior。
- No local path/secret leakage。
- Package/Nix updates。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-orchestrator at: 2026-06-23T07:24:58Z status: request_changes -->
## Review: request changes
Reviewer Pod `yoi-reviewer-00001KVSKGDYS-r1` requested changes.
Reviewed target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
- Branch: `impl/00001KVSKGDYS-workspace-identity`
- Implementation: `31565c9b feat: persist workspace identity`
- Diff: `4cda83b7..31565c9b`
Blocking issue:
1. Missing-file create path can return/use an identity that is not the persisted `.yoi/workspace.toml` identity under a local bootstrap race。
Evidence:
- `crates/workspace-server/src/identity.rs` generates a new `WorkspaceIdentity`, calls `identity.write_new(path)?`, and then returns the generated identity。
- In `write_new`, if another process creates `workspace.toml` after the initial missing-file path, the code validates the existing file but discards the parsed identity:
```rust
if path.exists() {
let _ = fs::remove_file(&tmp);
let raw = fs::read_to_string(path)?;
return Self::parse_str(&raw, path).map(|_| ());
}
```
- The caller still returns the newly generated identity, so a server instance can upsert SQLite / serve Workspace API / repository / host ids using an id that is not the tracked file and will not survive restart。
- Related TOCTOU risk: `path.exists()` followed by `fs::rename(tmp, path)` can overwrite a concurrently created file on Unix, and fixed temp path `workspace.toml.tmp` can be clobbered by concurrent creators。
Required fix direction:
- Ensure the returned `WorkspaceIdentity` is always the identity actually persisted or read from `.yoi/workspace.toml`
- Use a no-overwrite / create-new style finalization or equivalent safe retry/read behavior for local bootstrap races。
- Add focused test coverage for the race/return-authority behavior if feasible。
Non-blocking reviewer findings:
- `.yoi/workspace.toml` contents look safe to track。
- Unknown fields are intentionally denied and documented/tested。
- `ServerConfig::local_dev` no longer derives `local:{display}` internally。
- Workspace API/store/repository/host plumbing appears correctly based on persisted identity once loaded。
- Existing `local:*` rows are not destructively migrated。
Reviewer validation all passed before request_changes:
- `cargo fmt --check`
- `git diff --check 4cda83b7..HEAD`
- `cargo test -p yoi-workspace-server` (`15 passed`)
- `cargo check -p yoi-workspace-server`
- `cd web/workspace && deno task check && deno task build`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link`
Reviewer notes generated ignored artifacts from validation remained in worktree:
- `target/`
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T07:25:27Z -->
## Comment
Rerouted request-changes feedback to Coder Pod `yoi-coder-00001KVSKGDYS`.
Requested fix:
- `WorkspaceIdentity::load_or_init` must return the identity actually persisted/read from `.yoi/workspace.toml`
- Missing-file creation must handle local bootstrap races without returning an unpersisted generated identity。
- Avoid or safely handle TOCTOU / fixed temp-file clobbering around `workspace.toml.tmp`
- Add focused deterministic test coverage if feasible。
Validation requested after fix:
- `cargo fmt --check`
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi-workspace-server`
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- `git diff --cached --check`
- `cargo run -p yoi -- ticket doctor`
- `nix build .#yoi --no-link`
Coder was also asked to remove ignored validation artifacts before reporting。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T07:30:46Z -->
## Implementation report
Coder fix report received from `yoi-coder-00001KVSKGDYS` after request_changes。
New commit:
- `49c9e190 fix: return persisted workspace identity`
Fix summary:
- Replaced temp-file + `rename` finalization in `crates/workspace-server/src/identity.rs`
- New creation path uses `OpenOptions::create_new(true)` directly on `.yoi/workspace.toml`
- If creation succeeds, generated identity is written and returned。
- If creation fails because the file already exists from a concurrent bootstrap race, the existing file is read/parsed and that persisted identity is returned。
- Removed fixed `workspace.toml.tmp` path and the `path.exists()` + `rename` TOCTOU overwrite risk。
Test coverage:
- Added deterministic unit test `create_new_race_returns_existing_persisted_identity`
- Test verifies an already-persisted identity wins over a generated candidate, returned identity matches the file, and the file is not rewritten。
- Existing tests for missing creation, stable existing identity, invalid fail-closed behavior, no path leakage, and unknown field rejection remain。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `git diff --check`: passed
- `git diff --cached --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed
- `nix build .#yoi --no-link`: passed
Cleanup reported:
- Removed ignored validation artifacts:
- `target/`
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSKGDYS-workspace-identity` at `49c9e190`
- Diff `4cda83b7..HEAD` still touches expected Workspace identity/backend/package files。
- Latest fix commit changes only `crates/workspace-server/src/identity.rs`
- `git diff --check 4cda83b7..HEAD`: passed。
- Spot-check of `identity.rs` confirmed `write_new_or_read_existing` returns parsed persisted identity on `AlreadyExists` and no longer uses fixed temp file / rename finalization。
Next action:
- Route back to Reviewer Pod for re-review of request_changes fix。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T07:31:34Z -->
## Comment
Re-review routing:
Sent the request_changes fix back to Reviewer Pod:
- `yoi-reviewer-00001KVSKGDYS-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
- Branch: `impl/00001KVSKGDYS-workspace-identity`
- Baseline: `4cda83b7`
- Previous implementation: `31565c9b feat: persist workspace identity`
- Fix commit: `49c9e190 fix: return persisted workspace identity`
- Main review diff: `4cda83b7..49c9e190`
- Focus diff: `31565c9b..49c9e190`
Reviewer was asked to verify the prior blocking issue is fixed and re-run validation including workspace-server tests/checks, web check/build, TicketDoctor, and Nix build。
---
<!-- event: review author: yoi-orchestrator at: 2026-06-23T07:35:05Z status: approve -->
## Review: approve
Reviewer Pod `yoi-reviewer-00001KVSKGDYS-r1` approved the request_changes fix and the full implementation.
Reviewed target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKGDYS-workspace-identity`
- Branch: `impl/00001KVSKGDYS-workspace-identity`
- Final HEAD: `49c9e190 fix: return persisted workspace identity`
- Full diff: `4cda83b7..49c9e190`
- Fix diff: `31565c9b..49c9e190`
Reviewer result:
- Prior blocker is fixed。
- `write_new_or_read_existing` now uses `OpenOptions::new().write(true).create_new(true).open(path)` for no-overwrite creation。
- On successful create, generated identity is written/synced and returned。
- On `AlreadyExists`, existing `.yoi/workspace.toml` is read/parsed and the persisted identity is returned。
- Fixed temp path and `path.exists() + rename` finalization are gone。
- This satisfies the invariant that the returned identity is the persisted/read authority under a local bootstrap race。
Blocking issues:
- なし。
Non-blocking concern:
- Direct final-file `create_new` write can expose an empty/partial file to a concurrent reader during the short write window or after crash/write failure, but this fails closed rather than returning the wrong identity and was not considered blocking for local bootstrap scope。
Requirement checks:
- Missing-file creation writes minimal v0 TOML schema。
- Invalid existing file fails closed without overwrite。
- Unknown fields remain denied and tested。
- UUIDv7 validation is real: UUID parse + version check + canonical lowercase hyphenated form check。
- `ServerConfig::local_dev` no longer constructs `local:{display}`
- SQLite `workspaces` upsert uses `.yoi/workspace.toml` identity values。
- Repository ids and host ids derive from persisted workspace id。
- Legacy `/api/repositories/local` alias remains accepted。
- Existing `local:*` DB rows are not destructively migrated。
- `.yoi/workspace.toml` remains safe to track and contains only `workspace_id`, `created_at`, `display_name`
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 4cda83b7..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed (`16 passed`)
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Worktree status:
- clean for tracked/untracked files at `49c9e190`
- Reviewer validation left only ignored generated artifacts in the child worktree。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T07:38:38Z -->
## Implementation report
Merge and validation completed.
Merged implementation:
- Merge commit: `2745f3d5 merge: workspace identity persistence`
- Implementation commits:
- `31565c9b feat: persist workspace identity`
- `49c9e190 fix: return persisted workspace identity`
Post-merge validation in orchestration worktree:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed (`svelte-check` 0 errors / 0 warnings; build completed)
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
Generated artifact cleanup:
- Removed validation artifacts from orchestration worktree:
- `target/`
- `web/workspace/node_modules/`
- `web/workspace/.svelte-kit/`
- `web/workspace/build/`
- `git status --short --branch --ignored` shows only ignored `.yoi/tickets/.ticket-backend.lock`
Outcome:
- Local Workspace identity now persists in tracked `.yoi/workspace.toml`
- New ids are UUIDv7 and no longer derived from path/display basename。
- `.yoi/workspace.toml` parsing validates UUIDv7, UTC RFC3339 timestamp, non-empty display name, canonical id form, and denies unknown fields。
- Invalid existing identity files fail closed and are not overwritten。
- Missing-file creation returns the identity actually persisted/read, including `AlreadyExists` race handling。
- Workspace API / SQLite upsert / repository ids / host ids use the persisted Workspace identity。
- Existing legacy `local:*` DB rows are not destructively migrated。
- `.yoi/workspace.toml` remains a minimal safe project identity record, not a runtime/settings/secret store。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T07:38:42Z from: inprogress to: done reason: merged_and_validated field: state -->
## State changed
Reviewer approval 後に implementation を orchestration worktree へ merge し、post-merge validation と生成物 cleanup が完了したため done とする。
---
<!-- event: state_changed author: hare at: 2026-06-23T07:39:10Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T07:39:10Z status: closed -->
## 完了
Local Workspace identity を tracked `.yoi/workspace.toml` に永続化する実装を完了した。
完了内容:
- `.yoi/workspace.toml` を local Workspace identity の authority として追加。
- v0 schema は `workspace_id`, `created_at`, `display_name` のみ。
- `workspace_id` は UUIDv7 canonical string として検証し、path / display basename から導出しない。
- `created_at` は UTC RFC3339 timestamp として検証。
- `display_name` は空文字列を拒否。
- unknown fields は v0 では明示的に deny。
- invalid existing file は fail closed し、自動上書きしない。
- missing file 初期化では `OpenOptions::create_new(true)` を使い、既存 file が race で作られた場合は persisted identity を read/parse して返す。
- fixed temp file / `path.exists()` + `rename` finalization は使わない。
- `ServerConfig::local_dev``local:{display}` を生成せず、persisted `WorkspaceIdentity` を受け取る。
- SQLite `workspaces` upsert、Workspace API、repository ids、host ids は persisted Workspace id を使う。
- legacy `/api/repositories/local` alias は維持。
- 既存 `local:*` DB rows の destructive migration はしない。
- `.yoi/workspace.toml` は絶対 path / secret / socket / runtime data を含まない安全な project identity record として維持。
統合:
- Implementation: `31565c9b feat: persist workspace identity`
- Fix: `49c9e190 fix: return persisted workspace identity`
- Merge: `2745f3d5 merge: workspace identity persistence`
検証:
- Reviewer approval: `yoi-reviewer-00001KVSKGDYS-r1`
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -p yoi-workspace-server`: passed
- `cargo check -p yoi-workspace-server`: passed
- `cd web/workspace && deno task check && deno task build`: passed
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `nix build .#yoi --no-link`: passed
生成物 cleanup:
- orchestration worktree の `target/`, `web/workspace/node_modules/`, `web/workspace/.svelte-kit/`, `web/workspace/build/` を削除済み。
残作業:
- なし。将来必要なら legacy `local:*` row cleanup / migration policy は別 Ticket で扱う。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-064931-1","ticket_id":"00001KVSKJ0EA","kind":"accepted_plan","accepted_plan":{"summary":"Change Workspace Dashboard selection semantics so initial display and reload/background refresh do not auto-select rows; explicit keyboard/mouse selection still works; no-selection + TicketIntake composer submits global/new Intake; add focused tests.","branch":"impl/00001KVSKJ0EA-dashboard-no-auto-selection","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSKJ0EA-dashboard-no-auto-selection","role_plan":"Orchestrator creates a dedicated child worktree and spawns a narrow-scope TUI Coder. Reviewer will be spawned read-only after Coder reports implementation commit(s). After approval, Orchestrator integrates into `orchestration`, validates TUI focused tests, records closure, and cleans only the child worktree/branch."},"author":"yoi-orchestrator","at":"2026-06-23T06:49:31Z"}
+107
View File
@@ -0,0 +1,107 @@
---
title: 'Dashboard reload と初期表示で row を自動選択しない'
state: 'closed'
created_at: '2026-06-23T06:44:20Z'
updated_at: '2026-06-23T07:24:20Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['tui-ux', 'panel-selection', 'reload-state']
queued_by: 'workspace-panel'
queued_at: '2026-06-23T06:47:17Z'
---
## User claims / request snapshot
- Dashboard で `Esc` を押して row selection を消しても、reload によって頻繁に選択が戻る。
- そのため、実使用上は「何も選択していない状態」で composer を global / 新規 Intake として使うのが難しい。
- reload で勝手に row selection しないようにしたい。
- 追加合意: 初回 `yoi panel` 起動時から未選択にする。
## Confirmed facts / sources
- `crates/tui/src/dashboard/mod.rs`
- Dashboard は `selected_row: Option<PanelRowKey>` を持ち、`None` の未選択状態が実装上存在する。
- `Esc` 経路で `clear_panel_selection()` が呼ばれ、selection を消せる。
- reload / snapshot 更新後の selection visibility 補正により、visible row があると selection が戻る可能性がある。
- `crates/tui/src/dashboard/tests.rs`
- `Esc` が row selection を clear する既存テストがある。
- 関連 Ticket:
- `00001KTNS1AA8` closed: Panel composer / no-selection / `Esc` semantics の過去文脈。
- `00001KTFMMZP0` closed: background reload と selection/composer preservation の過去文脈。
## Unverified hypotheses
- 現行の reload 完了時の `ensure_selection_visible()` 系処理が、明示的な no-selection と「まだ selection がない初期/補正状態」を区別していない可能性が高い。
- 初期表示時の自動選択も同じ selection visibility 補正または初期化経路に由来している可能性がある。
## Undecided points / open questions
- なし。初回表示から未選択にする方針で合意済み。
## Background
Dashboard composer は row selection と composer target の組み合わせで挙動が変わる。`TicketIntake` target で Ticket row が選択されていると、入力が既存 Ticket の詳細化 / planning return として扱われる経路がある。一方、ユーザーが global / 新規 Intake として入力したい場合は row selection がない状態を維持できる必要がある。
現状は `Esc` で selection を消せても、background reload 等で選択が戻るため、ユーザーが意図した no-selection 状態を維持しづらい。
## Requirements
- 初回 `yoi panel` 表示時は、Ticket row / Pod row を自動選択しない。
- ユーザーが `Esc` で row selection を clear した後、reload / background reload / snapshot 更新が完了しても `selected_row = None` を維持する。
- reload によって既存の明示選択がまだ visible な場合は、その selection を維持してよい。
- reload によって選択中 row が消えた場合は安全に未選択へ落とす。
- Up/Down、mouse click、その他既存の明示的な row selection 操作では従来どおり selection を作れる。
- 未選択状態で `TicketIntake` target に非空 composer 入力して Enter した場合、既存 Ticket refinement ではなく global / 新規 Intake launch として扱われる。
## Acceptance criteria
- 初回 `yoi panel` 起動後、visible row があっても row selection はない。
- `Esc` で selection を clear した後、panel reload completion を挟んでも selection は復活しない。
- 未選択状態で `TicketIntake` target に composer 入力して Enter すると、新規/global Intake handoff になり、既存 Ticket の詳細化 handoff にならない。
- keyboard navigation または mouse click により、ユーザーは明示的に row を再選択できる。
- 既存の selected-row action、queue/close/open 操作、Ticket workflow state semantics は変えない。
- focused tests で少なくとも以下を確認する:
- initial Dashboard state has no selected row when rows exist;
- `Esc` clear -> reload completion -> still no selected row;
- no-selection + `TicketIntake` composer submit routes to global/new Intake rather than selected Ticket refinement.
## Binding decisions / invariants
- no-selection は first-class UX state として扱う。
- reload は、ユーザーが明示的に作った no-selection state を勝手に解除しない。
- 初回表示でも自動選択しない。
- composer draft は reload / selection clear によって失わない。
- Ticket state transition / lifecycle authority は変更しない。
- row click は selection のみを変更し、click だけで action dispatch しない既存方針を維持する。
## Implementation latitude
- 実装は `selected_row: Option<PanelRowKey>` に加えて「明示 no-selection」フラグを持つ、または selection visibility 補正の呼び出し条件を整理するなど、局所的に選んでよい。
- 初期表示・reload 完了・row 消失・navigation 開始の各経路で、selection を作る責務を明示的 user action に寄せられればよい。
- UI 表示文言の小変更は許容するが、この Ticket の主目的は selection semantics の修正であり、広い Dashboard layout redesign は含めない。
## Readiness
- readiness: implementation_ready
- risk_flags: [tui-ux, panel-selection, reload-state]
## Escalation conditions
- 初回未選択にすると keyboard-only navigation や blank Enter action の既存 contract が大きく変わることが判明した場合。
- selection visibility 補正が reload 以外の重要な safety/correctness を担っており、単純に止めると stale selection や action 誤爆が起きる場合。
- focused tests では確認できず、実端末 `yoi panel` / PTY 経路での挙動確認が必要になった場合。
## Validation
- `cargo test -q -p tui workspace_panel`
- 必要に応じて Dashboard 関連の focused test 名指定。
- 変更範囲に応じて `cargo fmt --check``git diff --check``cargo check -q`
- terminal delivery / timing に依存する挙動が疑わしい場合は、既存の Panel PTY/E2E 系テストまたは実 `yoi panel` で確認する。
## Related work
- `00001KTNS1AA8` — Panel composer / no-selection / `Esc` semantics の関連 closed Ticket。
- `00001KTFMMZP0` — Dashboard background reload / selection preservation の関連 closed Ticket。
- `crates/tui/src/dashboard/mod.rs`
- `crates/tui/src/dashboard/tests.rs`
- `crates/tui/src/dashboard/render.rs`
+26
View File
@@ -0,0 +1,26 @@
Dashboard の row selection を明示的 user action の結果として扱うように修正した。
完了内容:
- 初期表示で visible row があっても自動選択しない。
- reload / snapshot reconciliation で `selected_row = None` を勝手に selection へ戻さない。
- `Esc` による no-selection が reload を跨いで維持される。
- 選択中 row が消えた場合は `None` へ安全に落とす。
- keyboard navigation では no-selection から明示的に selection を作成できる。
- `list.selected_name` は実際の Pod row selection と同期し、no-selection / non-Pod selection では clear する。
- no-selection + `TicketIntake` composer submit が既存 Ticket refinement ではなく global/new Intake route へ進むことを focused test で確認した。
統合:
- Implementation: `5c242d96 fix: keep dashboard row selection explicit`
- Merge: `58904c44 merge: dashboard no auto selection`
検証:
- Reviewer approval: `yoi-reviewer-00001KVSKJ0EA-r1`
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -q -p tui workspace_panel`: passed (`27 passed`)
- `cargo test -q -p tui dashboard`: passed (`111 passed`)
- reviewer 側追加確認 `cargo test -q -p tui`: passed (`372 passed`)
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
残作業:
- なし。
+313
View File
@@ -0,0 +1,313 @@
<!-- event: create author: LocalTicketBackend at: 2026-06-23T06:44:20Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: ticket-intake at: 2026-06-23T06:46:36Z -->
## Intake summary
ユーザー合意により ready 化。Ticket は `implementation_ready` で、初回 `yoi panel` 表示時から未選択、`Esc` 後の no-selection を reload が復活させない、未選択 + `TicketIntake` composer submit を global/new Intake に流す、という要件・受け入れ条件・validation が明記されている。未決定点なし。
---
<!-- event: state_changed author: ticket-intake at: 2026-06-23T06:46:36Z from: planning to: ready reason: user_requested_ready field: state -->
## State changed
ユーザーから `readyにして` の明示指示があり、対象 Ticket の item/thread を確認した。要件・受け入れ条件・risk flags・validation が揃っており、Orchestrator が routing 可能なため `ready` に遷移する。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T06:47:17Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T06:49:08Z -->
## Decision
Routing decision: `implementation_ready_parallel`
Reason:
- Ticket body has concrete Dashboard selection semantics and focused test requirements。
- No relations / blockers / orchestration plan records exist。
- Active queued Workspace identity Ticket is backend/workspace-server focused and separate from TUI Dashboard row-selection code, so parallel implementation is acceptable。
- Orchestrator worktree is clean on `orchestration` at `13e76d35`; target worktree / branch is not present。
- Code map from Ticket body points to `crates/tui/src/dashboard/mod.rs`, `tests.rs`, and `render.rs`
IntentPacket:
Intent:
- Treat no-selection as a first-class Dashboard UX state: initial panel display and reload/background refresh must not auto-select rows, while explicit keyboard/mouse selection still works。
Binding decisions / invariants:
- Initial `yoi panel` display should have `selected_row = None` even when rows are visible。
- `Esc` clear must persist across reload/snapshot refresh; reload must not recreate selection after explicit no-selection。
- If a user explicitly selected a row and it remains visible after reload, that selection may be preserved。
- If selected row disappears after reload, fall back safely to no-selection。
- Composer draft must survive selection clear/reload。
- Existing row actions, queue/close/open operations, Ticket workflow state semantics, and row-click-is-selection-only policy must remain unchanged。
- No broad Dashboard layout redesign in this Ticket。
Requirements / acceptance criteria:
- Initial Dashboard state has no selected row when rows exist。
- Esc clear -> reload completion -> still no selected row。
- No-selection + `TicketIntake` composer submit routes to global/new Intake, not selected Ticket refinement。
- Keyboard navigation or mouse click can explicitly create selection again。
- Focused tests cover the above semantics。
Implementation latitude:
- Use an explicit no-selection flag or refine selection visibility correction conditions。
- The key is to make selection creation happen only from explicit user navigation/click/action paths, not from reload/init visibility correction。
Escalate if:
- Initial no-selection substantially breaks keyboard-only navigation or blank Enter action contract。
- Existing selection visibility correction has safety roles that cannot be preserved with a local change。
- Real terminal / PTY behavior is required beyond focused tests。
Validation plan:
- `cargo fmt --check`
- `cargo test -q -p tui workspace_panel`
- Dashboard focused tests as needed。
- `git diff --check`
- `cargo run -p yoi -- ticket doctor`
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T06:49:18Z from: queued to: inprogress reason: human_authorized_unblocked_dashboard_no_auto_selection field: state -->
## State changed
Human authorized queue routing from Workspace Dashboard. Ticket has concrete Dashboard selection semantics and no recorded blockers, so Orchestrator accepts implementation.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T06:51:32Z -->
## Implementation report
Implementation start report:
- Created child implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSKJ0EA-dashboard-no-auto-selection`
- Created branch:
- `impl/00001KVSKJ0EA-dashboard-no-auto-selection`
- Base commit:
- `4cda83b7 ticket: accept workspace identity and selection work`
- Confirmed tracked Ticket project records are visible in the child worktree。
- Confirmed `.yoi/memory` has no tracked/untracked entries in the child worktree check。
- Spawned sibling Coder Pod:
- `yoi-coder-00001KVSKJ0EA`
- Coder scope:
- read: `/home/hare/Projects/yoi`
- write: `/home/hare/Projects/yoi/.worktree/00001KVSKJ0EA-dashboard-no-auto-selection`
Parallelization note:
- `00001KVSKGDYS` is active separately and targets Workspace backend identity persistence. This Ticket should stay limited to TUI Dashboard selection semantics。
Next action:
- Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T07:15:44Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVSKJ0EA`.
Implementation commit:
- `5c242d96 fix: keep dashboard row selection explicit`
Changed areas:
- `crates/tui/src/dashboard/mod.rs`
- Reload/snapshot reconciliation preserves only an explicitly selected visible row。
- Initial/reload visibility correction no longer auto-selects a row。
- Stale/disappeared selections fall back to `None`
- `Esc` clear state remains no-selection across reload。
- Keyboard navigation from no-selection explicitly creates selection on first visible row。
- `list.selected_name` stays aligned with actual Pod row selection and clears for non-Pod/no-selection states。
- `crates/tui/src/dashboard/tests.rs`
- Added focused coverage for initial visible rows with no selected row。
- Added `Esc` clear surviving reload while preserving composer draft。
- Added no-selection + `TicketIntake` submit routing to global/new Intake。
- Added keyboard navigation creating selection explicitly。
- Added reload fallback to no-selection when selected row disappears。
- Updated existing Dashboard tests to explicitly select rows where previous behavior depended on auto-selection。
Coder validation reported:
- `cargo fmt --check`: passed
- `cargo test -q -p tui workspace_panel`: passed
- `cargo test -q -p tui dashboard`: passed
- `git diff --check`: passed
- `cargo run -p yoi -- ticket doctor`: passed (`doctor: ok`)
Orchestrator evidence checked:
- Worktree clean on `impl/00001KVSKJ0EA-dashboard-no-auto-selection` at `5c242d96`
- Diff `4cda83b7..HEAD` touches expected Dashboard model/tests only。
- `git diff --check 4cda83b7..HEAD`: passed。
Next action:
- Route to read-only Reviewer Pod for acceptance review。
---
<!-- event: comment author: yoi-orchestrator at: 2026-06-23T07:16:33Z -->
## Comment
Review routing:
Spawned read-only Reviewer Pod:
- `yoi-reviewer-00001KVSKJ0EA-r1`
Review target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKJ0EA-dashboard-no-auto-selection`
- Branch: `impl/00001KVSKJ0EA-dashboard-no-auto-selection`
- Baseline: `4cda83b7`
- Implementation commit: `5c242d96 fix: keep dashboard row selection explicit`
- Diff: `4cda83b7..5c242d96`
Reviewer scope:
- read-only `/home/hare/Projects/yoi`
Reviewer focus:
- Initial/reload no-auto-selection semantics。
- Esc clear persistence and composer draft preservation。
- Explicit keyboard/mouse selection still works。
- Stale selection falls back to none。
- No-selection TicketIntake composer routing。
- `list.selected_name` sync and no stale Pod selection。
- No row-action / workflow semantic regressions。
Orchestrator will wait for reviewer verdict before integration。
---
<!-- event: review author: yoi-orchestrator at: 2026-06-23T07:23:02Z status: approve -->
## Review: approve
Reviewer Pod `yoi-reviewer-00001KVSKJ0EA-r1` approved the implementation.
Reviewed target:
- Worktree: `/home/hare/Projects/yoi/.worktree/00001KVSKJ0EA-dashboard-no-auto-selection`
- Branch: `impl/00001KVSKJ0EA-dashboard-no-auto-selection`
- Implementation: `5c242d96 fix: keep dashboard row selection explicit`
- Diff: `4cda83b7..5c242d96`
Reviewer evidence:
- 初期表示 / reload path は row selection を自動生成しない。
- `selected_row = None``Esc` 後も reload/snapshot reconciliation を跨いで維持される。
- 明示的な keyboard navigation は no-selection から selection を作成できる。
- 明示的 selection は row が visible な間は維持される。
- 消えた / stale row selection は `None` へ落ちる。
- `list.selected_name` は no-selection / non-Pod selection で clear され、実際の Pod row selection のみで設定される。
- no-selection + `TicketIntake` submit は global/new Intake launch へ進む。
- mouse click は selection-only のまま。
- 差分は Dashboard selection logic と focused tests に限定され、layout / render / workflow semantic の不要変更はない。
Blocking issues:
- なし。
Non-blocking concerns:
- なし。
Reviewer validation:
- `cargo fmt --check`: passed
- `git diff --check 4cda83b7..HEAD`: passed
- `cargo test -q -p tui workspace_panel`: passed (`27 passed`)
- `cargo test -q -p tui dashboard`: passed (`111 passed`)
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
- `cargo test -q -p tui`: passed (`372 passed`)
Worktree status:
- clean at `5c242d96`
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T07:24:05Z -->
## Implementation report
Merge and validation completed.
Merged implementation:
- Merge commit: `58904c44 merge: dashboard no auto selection`
- Implementation commit: `5c242d96 fix: keep dashboard row selection explicit`
Post-merge validation in orchestration worktree:
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -q -p tui workspace_panel`: passed (`27 passed`)
- `cargo test -q -p tui dashboard`: passed (`111 passed`)
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
Outcome:
- 初期表示と reload/snapshot reconciliation が row selection を自動生成しなくなった。
- `Esc` 後の no-selection は reload を跨いで維持される。
- 明示的 keyboard navigation による selection 作成は維持された。
- `TicketIntake` composer の no-selection submit は global/new Intake route になる。
- stale selection は安全に `None` へ落ちる。
- Ticket lifecycle / row action semantics は変更していない。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T07:24:10Z from: inprogress to: done reason: merged_and_validated field: state -->
## State changed
実装は reviewer approval 後に orchestration worktree へ merge され、post-merge validation も通過したため done とする。
---
<!-- event: state_changed author: hare at: 2026-06-23T07:24:20Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T07:24:20Z status: closed -->
## 完了
Dashboard の row selection を明示的 user action の結果として扱うように修正した。
完了内容:
- 初期表示で visible row があっても自動選択しない。
- reload / snapshot reconciliation で `selected_row = None` を勝手に selection へ戻さない。
- `Esc` による no-selection が reload を跨いで維持される。
- 選択中 row が消えた場合は `None` へ安全に落とす。
- keyboard navigation では no-selection から明示的に selection を作成できる。
- `list.selected_name` は実際の Pod row selection と同期し、no-selection / non-Pod selection では clear する。
- no-selection + `TicketIntake` composer submit が既存 Ticket refinement ではなく global/new Intake route へ進むことを focused test で確認した。
統合:
- Implementation: `5c242d96 fix: keep dashboard row selection explicit`
- Merge: `58904c44 merge: dashboard no auto selection`
検証:
- Reviewer approval: `yoi-reviewer-00001KVSKJ0EA-r1`
- `cargo fmt --check`: passed
- `git diff --check HEAD^1..HEAD`: passed
- `cargo test -q -p tui workspace_panel`: passed (`27 passed`)
- `cargo test -q -p tui dashboard`: passed (`111 passed`)
- reviewer 側追加確認 `cargo test -q -p tui`: passed (`372 passed`)
- `cargo run -q -p yoi -- ticket doctor`: passed (`doctor: ok`)
残作業:
- なし。
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260623-132129-1","ticket_id":"00001KVSMJJNV","kind":"accepted_plan","accepted_plan":{"summary":"Ticket 00001KVSMJJNV を implementation worktree `.worktree/00001KVSMJJNV-paused-ctrlx-cancel` / branch `work/00001KVSMJJNV-paused-ctrlx-cancel` で開始する。Paused 中の `Ctrl+X` が shutdown ではなく cancel になり、paused turn を破棄して次入力可能にすることが主目的。","branch":"work/00001KVSMJJNV-paused-ctrlx-cancel","worktree":"/home/hare/Projects/yoi/.worktree/00001KVSMJJNV-paused-ctrlx-cancel","role_plan":"Coder Pod: implementation worktree で TUI key handling / controller paused cancel semantics / focused tests を実装し、ローカル commit まで行う。Orchestrator: output/diff/tests を確認後、Reviewer Pod に recorded IntentPacket に基づく review を依頼する。"},"author":"yoi-orchestrator","at":"2026-06-23T13:21:29Z"}
+105
View File
@@ -0,0 +1,105 @@
---
title: 'TUI Console: Paused 中の Ctrl+X で中断ターンをキャンセルできるようにする'
state: 'closed'
created_at: '2026-06-23T07:02:07Z'
updated_at: '2026-06-23T13:56:16Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['tui-keybinding', 'pod-lifecycle']
queued_by: 'workspace-panel'
queued_at: '2026-06-23T08:41:00Z'
---
## User claims / request snapshot
- TUI Console で、`Ctrl+C` により Pause している状態のとき、`Ctrl+X` でキャンセルできるようにしたい。
## Confirmed facts / sources
- 既存 Ticket:
- 未完了 Ticket に直接 duplicate は確認できなかった。
- `00001KSVP63K8 Support immediate in-flight TUI composer injection` は TUI 実行中入力に関連するが、「Do not interrupt/cancel the current run」が non-goal なので今回の要求とは別件。
- `crates/tui/src/console/mod.rs`
- 現在の `Ctrl+X``PodStatus::Running` のときだけ `Method::Cancel` を返す。
- `PodStatus::Paused | PodStatus::Idle` のときは `Method::Shutdown` を返している。
- `Ctrl+C` は Running では `Method::Pause`、Idle/Paused では TUI 終了の 2-tap guard として扱われている。
- 既存 test `pause_and_cancel_clear_queued_input` は名前上 pause/cancel を扱うが、`Ctrl+C` 後に app status を Paused に更新していないため、Paused 状態での `Ctrl+X` cancel は実質カバーしていない。
- `crates/protocol/src/lib.rs`
- `Method::Pause` は in-flight turn を止めて Paused に遷移するもの。
- コメント上、`Cancel` は破棄して Idle に戻る意味を持ち、Paused は `Resume` または新規 `Run` が可能。
- `crates/pod/src/controller.rs`
- 非 running 側の `Method::Cancel` は現状 `NotRunning` error を返す経路があるため、TUI keymap 変更だけでなく Paused 状態の cancel semantics を確認・必要なら実装する必要がある。
## Unverified hypotheses
- 実装は比較的小さい可能性が高いが、`Paused` 状態で `Method::Cancel` を受け取った時に、Worker/Pod の interrupted state や orphan tool-use cleanup をどう clear するべきかは実装時に確認が必要。
- UI 表示は paused hint に `Ctrl+X to cancel` 相当を追加するだけで足りる可能性がある。
## Undecided points / open questions
- blocking な未決定点はなし。
- Orchestrator/実装者判断で、`Ctrl+X` の Idle 挙動を現状通り `Shutdown` に残すか、Paused のみ `Cancel` に分岐するのがよさそう。
## Background
`Ctrl+C` で Pause した turn は resume 可能だが、ユーザーが「やっぱりこの中断 turn は破棄したい」と判断した時に、Console 上の自然な操作として `Ctrl+X` cancel が効くべき。現在は Paused/Idle の `Ctrl+X` が shutdown に割り当てられており、Paused turn のキャンセル導線として機能していない。
## Requirements
- TUI Console で Pod が `Paused` のとき、`Ctrl+X` は shutdown ではなく paused/interrupted turn の cancel を要求する。
- `Running` 中の `Ctrl+X -> Method::Cancel` は維持する。
- `Idle` 中の `Ctrl+X` の挙動は、意図的に変更する理由がなければ現状の shutdown を維持する。
- Paused 状態で cancel した後、Pod は resume 可能な paused turn を残さず、Idle 相当として次の入力を受けられる。
- queued input がある場合は、既存 Running cancel と同様に誤送信されないよう clear される。
- UI の paused hint / actionbar / tests など、ユーザーが操作を理解できる範囲を必要に応じて更新する。
## Acceptance criteria
- `Ctrl+C` で Running turn を Pause した後、Console 上で `Ctrl+X` を押すと、TUI 終了や Pod shutdown ではなく turn cancel が実行される。
- Paused cancel 後、`Enter` で前の turn を resume しようとしても resume されない。
- Paused cancel 後、新規入力は通常の新規 turn として扱われる。
- Running 中の `Ctrl+X` cancel と Idle 中の `Ctrl+X` 挙動に意図しない regressions がない。
- Focused tests が Paused 状態の `Ctrl+X` key handling と Pod/controller 側の cancel semantics をカバーする。
## Binding decisions / invariants
- `Ctrl+C` の Pause semantics は変更しない。
- `Ctrl+C` の Idle/Paused 2-tap TUI quit guard は、この Ticket では置き換えない。
- この Ticket は in-flight input injection / history append policy を扱わない。
- provider stream を直接 mutate しない。
- cancel は hidden context/history mutation ではなく、既存の typed `Method::Cancel` semantics またはそれに準じる明示的 lifecycle 操作で表現する。
## Implementation latitude
- `Paused` 中の `Ctrl+X``Method::Cancel` に変えるだけで足りるか、controller/worker 側に Paused cancel handling を追加するかは実装調査で判断してよい。
- UI hint の文言や配置は実装者に任せてよい。
- 必要なら既存 test を修正・分割して、「Running cancel」と「Paused cancel」を明確に分ける。
## Readiness
- readiness: implementation_ready
- risk_flags: [tui-keybinding, pod-lifecycle]
## Escalation conditions
- `Method::Cancel` を Paused 状態に拡張すると session/history cleanup や orphan tool-result closure の設計判断が必要になる場合は、実装者は Orchestrator/maintainer に戻す。
- `Ctrl+X` の Idle 挙動変更が必要になる場合は、別途合意を取る。
## Validation
- Focused tests:
- `cargo test -p tui pause` または該当 TUI key handling tests
- `cargo test -p pod cancel` または controller paused cancel の focused tests
- 通常確認:
- `cargo fmt --check`
- 必要に応じて `cargo check -q`
- terminal UX 変更なので、可能なら実機 TUI/manual check も推奨。
## Related work
- Related, not duplicate: `.yoi/tickets/00001KSVP63K8`
- Files:
- `crates/tui/src/console/mod.rs`
- `crates/tui/src/ui.rs`
- `crates/protocol/src/lib.rs`
- `crates/pod/src/controller.rs`
+28
View File
@@ -0,0 +1,28 @@
Ticket 00001KVSMJJNV は完了。
実装内容:
- TUI Console の `Paused` 状態で `Ctrl+X` を TUI/Pod shutdown ではなく `Method::Cancel` として扱うようにした。
- `Idle``Ctrl+X` shutdown behavior と、`Running` の cancel behavior は維持した。
- paused cancel 後に resume 可能な interrupted state が残らず、次の入力が fresh run になるよう controller / Pod lifecycle を更新した。
- paused cancel を normal `RunCompleted { Finished }` として永続化せず、typed session log entry `LogEntry::PausedTurnAbandoned { ts }` として記録するようにした。
- replay / restore で `PausedTurnAbandoned``last_run_interrupted` を clear するようにした。
- focused tests を追加・更新し、TUI key handling、controller behavior、session log JSON/replay semantics、fake normal-finished run が残らないことを確認した。
主要 commits:
- `90b1a1fc tui: cancel paused turns with ctrl-x`
- `8c8fb014 fix: log paused cancel lifecycle explicitly`
- `76c80054 merge: 00001KVSMJJNV paused ctrl-x cancel`
Review:
- 初回 review は lifecycle log semantics の不一致で request_changes。
- `PausedTurnAbandoned` による typed lifecycle representation を追加後、Reviewer が approve。
Validation:
- `cargo test -p session-store paused_turn_abandoned -- --nocapture`
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture`
- `cargo test -p tui ctrl_x -- --nocapture`
- `cargo fmt --check`
- `git diff --check HEAD~1..HEAD`
Merge note:
- orchestration branch で実装・Ticket 記録・close resolution をまとめ、merge target へ fast-forward 予定。
+318
View File
@@ -0,0 +1,318 @@
<!-- event: create author: ticket-intake at: 2026-06-23T07:02:07Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T08:41:00Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T12:42:28Z -->
## Decision
Routing decision: blocked_by_dependency_or_missing_authority
Reason:
- Ticket 自体は `implementation_ready` と判断できる。目的、binding decisions / invariants、acceptance criteria、validation、escalation conditions は揃っており、`tui-keybinding` / `pod-lifecycle` risk は reviewer focus として扱える。
- ただし routing 時点の merge target `/home/hare/Projects/yoi` に、この Ticket の対象ではない `crates/tui/src/dashboard/mod.rs``crates/tui/src/dashboard/tests.rs` の未コミット変更がある。workflow の dirty-state gate に従い、この状態では implementation worktree 作成 / Coder Pod 起動 / merge へ進めない。
- 既存 worktree entry `.worktree/00001KVSMJJNV-paused-ctrlx-cancel``git worktree list` 上で prunable と表示され、gitdir が存在しないため、再利用には cleanup/recreate 判断が必要。
Evidence checked:
- Ticket body / thread / artifacts: TicketShow で body、queued event、artifacts なしを確認。
- Ticket relations: TicketRelationQuery で blocker relation なし。
- Orchestration plan: TicketOrchestrationPlanQuery で accepted-plan / conflict / waiting record なし。
- Queue state: queued Ticket はこの 1 件のみ。ready / inprogress は 0 件。
- Workspace/worktree/Pod state: `/home/hare/Projects/yoi``develop...origin/develop [ahead 48]` かつ dashboard files に dirty change あり。`.worktree/orchestration` は clean。visible Pods は peer `yoi` idle と self `yoi-orchestrator` running、spawned child なし。
Next action:
- merge target の未コミット dashboard 変更を所有者が commit / revert / 明示的に退避許可した後、この Ticket を再 routing する。
- その時点で blocker がなければ `queued -> inprogress` を記録してから、worktree を clean に recreate し、Coder/Reviewer loop に渡す。
Escalate if:
- dashboard 変更がこの Ticket と同時に保持すべき作業なら、別 Ticket/branch として扱うか、今回の implementation worktree/merge 計画に含めるかを人間が決める。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T13:21:02Z -->
## Decision
Routing correction:
直前の `blocked_by_dependency_or_missing_authority` 判断は取り下げる。merge target `/home/hare/Projects/yoi` の dashboard files dirty は最終 merge 時の確認事項だが、この Ticket の implementation acceptance / implementation worktree 作成を止める gate として扱うのは過剰だった。
Corrected routing decision: implementation_ready
Evidence checked:
- Ticket body / thread: 目的、requirements、acceptance criteria、binding decisions / invariants、implementation latitude、escalation conditions、validation が揃っている。
- TicketRelationQuery: blocker relation なし。
- TicketOrchestrationPlanQuery: accepted-plan / conflict / blocker / waiting-capacity record なし。
- Queue/capacity: queued Ticket はこの 1 件。visible spawned child はなし。
- Worktree state: orchestration worktree は Ticket 記録変更のみ。既存 `.worktree/00001KVSMJJNV-paused-ctrlx-cancel` は prunable なので cleanup/recreate 対象。
Next action:
- `queued -> inprogress` を記録する。
- stale/prunable implementation worktree entry を掃除して、`.worktree/00001KVSMJJNV-paused-ctrlx-cancel` を作り直す。
- Coder Pod に IntentPacket を渡して実装を開始する。
Merge note:
- merge target 側の unrelated dashboard dirty は final merge 前に再確認し、必要なら人間へ確認する。implementation worktree 内の作業開始 blocker にはしない。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T13:21:07Z from: queued to: inprogress reason: orchestrator_acceptance field: state -->
## State changed
Orchestrator acceptance: Ticket evidence、relation blockers、orchestration plan、worktree/capacity 状態を再確認し、implementation_ready と判断した。implementation side effect 前に queued -> inprogress を記録する。
Acceptance basis:
- blocker relation なし。
- orchestration plan blocker/conflict なし。
- queued Ticket はこの 1 件で child capacity あり。
- risk flags は `tui-keybinding` / `pod-lifecycle` として IntentPacket の reviewer focus に反映する。
Next:
- implementation worktree を clean に作成し、Coder Pod に routing する。
---
<!-- event: plan author: yoi-orchestrator at: 2026-06-23T13:21:47Z -->
## Plan
IntentPacket for implementation
Intent:
- TUI Console で Pod が `Paused` のとき、`Ctrl+X` を TUI shutdown ではなく paused/interrupted turn の cancel として扱えるようにする。
- Paused cancel 後は resume 可能な paused turn を残さず、次の新規入力を通常の新規 turn として受けられる状態にする。
Binding decisions / invariants:
- `Ctrl+C` の Running -> Pause semantics は変更しない。
- `Ctrl+C` の Idle/Paused 2-tap TUI quit guard はこの Ticket では置き換えない。
- `Running` 中の `Ctrl+X -> Method::Cancel` は維持する。
- `Idle` 中の `Ctrl+X` は、必要な明示理由がなければ現状の shutdown を維持する。
- in-flight input injection / history append policy は扱わない。
- provider stream を直接 mutate しない。
- cancel は hidden context/history mutation ではなく、既存の typed `Method::Cancel` semantics またはそれに準じる明示的 lifecycle 操作で表現する。
Requirements / acceptance criteria:
- `Ctrl+C` で Running turn を Pause した後、Console 上で `Ctrl+X` を押すと TUI exit / Pod shutdown ではなく turn cancel が実行される。
- Paused cancel 後、`Enter` で前の turn が resume されない。
- Paused cancel 後、新規入力は通常の新規 turn として扱われる。
- Running cancel と Idle `Ctrl+X` に意図しない regression がない。
- focused tests が Paused 状態の `Ctrl+X` key handling と Pod/controller 側の cancel semantics をカバーする。
Implementation latitude:
- `Paused` 中の `Ctrl+X``Method::Cancel` に変えるだけで足りるか、controller/worker 側に Paused cancel handling を追加するかは実装調査で判断してよい。
- UI hint の文言や配置は実装者に任せてよい。
- 既存 test の修正・分割は許容する。
Escalate if:
- `Method::Cancel` を Paused 状態に拡張すると session/history cleanup や orphan tool-result closure の新しい設計判断が必要になる。
- `Ctrl+X` の Idle 挙動変更が必要になる。
- provider stream / history mutation / lifecycle authority の境界を変える必要が出る。
Validation:
- focused: `cargo test -p tui pause` または該当 TUI key handling tests。
- focused: `cargo test -p pod cancel` または controller paused cancel tests。
- `cargo fmt --check`
- 必要に応じて `cargo check -q`
Current code map:
- 主対象: `crates/tui/src/console/mod.rs`
- 関連: `crates/tui/src/ui.rs`, `crates/protocol/src/lib.rs`, `crates/pod/src/controller.rs`
- 既存事実: `Ctrl+X` は Running のみ `Method::Cancel`、Paused/Idle は shutdown 側。controller の非-running Cancel は `NotRunning` 経路がある可能性。
Critical risks / reviewer focus:
- Paused と Idle の key handling を混同して shutdown behavior を壊していないか。
- Running cancel の既存 behavior / queued input clear に regression がないか。
- Paused cancel 後に resume 可能な interrupted state が残らないか。
- Cancel semantics が hidden history/context mutation になっていないか。
- tests が実際に app status を Paused に更新した状態をカバーしているか。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T13:37:51Z -->
## Implementation report
Implementation report
Worktree / branch:
- `/home/hare/Projects/yoi/.worktree/00001KVSMJJNV-paused-ctrlx-cancel`
- `work/00001KVSMJJNV-paused-ctrlx-cancel`
Commit:
- `90b1a1fc tui: cancel paused turns with ctrl-x`
Implemented changes:
- `crates/tui/src/console/mod.rs`: `Ctrl+X` key handling を Paused 状態でも cancel path に乗せ、Idle の shutdown behavior と分離。
- `crates/tui/src/ui.rs`: Paused UI hint を cancel 操作に合わせて更新。
- `crates/pod/src/controller.rs` / `crates/pod/src/pod.rs`: Paused 状態の `Method::Cancel``NotRunning` ではなく paused turn cancel として処理し、resume 可能な interrupted state を破棄して次入力を fresh run として扱う経路を追加。
- `crates/pod/tests/controller_test.rs`: Paused cancel 後に resume されず、次入力が fresh run になることを確認する focused test を追加。
Validation run by Orchestrator:
- `cargo test -p tui ctrl_x -- --nocapture`
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture`
- `git diff --check`
- `cargo fmt --check`
Next:
- Reviewer Pod に recorded IntentPacket と commit diff を基準に review を依頼する。
---
<!-- event: review author: reviewer-00001KVSMJJNV-ctrlx-cancel at: 2026-06-23T13:42:48Z status: request_changes -->
## Review: request changes
Review result: request_changes
Findings:
- `crates/pod/src/pod.rs:1871-1884` は paused cancel cleanup を `LogEntry::RunCompleted { result: WorkerResult::Finished, interrupted: false }` として記録している。しかしここでは `run()` / `resume()` が完了したわけではなく、paused turn を明示的に abandon している。`crates/session-store/src/segment_log.rs:31` および `:100-106` の session log semantics では、`RunCompleted``run()` / `resume()` call の終了を表し、`Finished` は通常の Worker completion を意味する。現在の immediate replay は `interrupted` を使うため focused behavior は通るが、durable session/audit stream が cancel 後に normal `Finished` run を記録してしまう。
- Ticket の invariant は cancel を explicit typed lifecycle semantics で表現することなので、typed paused-cancel / abandoned-turn lifecycle record を追加するか、log schema / consumers / tests を更新して durable history が normal `Finished` run を主張しないようにする必要がある。
Validation performed:
- `cargo test -p tui ctrl_x -- --nocapture` passed
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture` passed
- `git diff --check 5954021c..90b1a1fc` passed
- `cargo fmt --check` passed
- `git status --short` clean
Rationale:
- TUI key handling separation は正しい。`Paused``Ctrl+X``Method::Cancel``Idle``Shutdown` のまま、`Ctrl+C` quit/pause behavior も変更されていない。
- controller test は Pod を実際に `Paused` にし、cancel 後の `Resume` rejection と次入力の fresh `Run` を確認している。
- blocker は persisted lifecycle representation。functional state reset は実装されているが、session log が abandoned paused turn を normal finished run として記録している点が durable semantics と不一致。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T13:49:36Z -->
## Implementation report
Implementation report update after review request
Reviewer-requested change addressed in implementation worktree:
- `/home/hare/Projects/yoi/.worktree/00001KVSMJJNV-paused-ctrlx-cancel`
- branch `work/00001KVSMJJNV-paused-ctrlx-cancel`
New commit:
- `8c8fb014 fix: log paused cancel lifecycle explicitly`
Change summary:
- `crates/session-store/src/segment_log.rs`: typed `LogEntry::PausedTurnAbandoned { ts }` を追加し、replay / `collect_state``last_run_interrupted` を clear するようにした。JSON round-trip と replay semantics の tests を追加。
- `crates/pod/src/pod.rs`: paused cancel cleanup で fake `RunCompleted { result: Finished }` を記録せず、`PausedTurnAbandoned` を記録するように変更。
- `crates/pod/src/segment_log_sink.rs`: lifecycle コメントを更新。
- `crates/pod/tests/controller_test.rs`: paused cancel が `PausedTurnAbandoned` を記録し、normal finished run としては記録されないことを確認する assertion を追加。
Validation run by Orchestrator:
- `cargo test -p session-store paused_turn_abandoned -- --nocapture`
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture`
- `cargo test -p tui ctrl_x -- --nocapture`
- `git diff --check 5954021c..HEAD`
Next:
- Reviewer に再 review を依頼する。
---
<!-- event: review author: reviewer-00001KVSMJJNV-ctrlx-cancel at: 2026-06-23T13:53:16Z status: approve -->
## Review: approve
Review result: approve
Findings:
- なし。
Validation performed by Reviewer:
- `cargo test -p session-store paused_turn_abandoned -- --nocapture` — passed
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture` — passed
- `cargo test -p tui ctrl_x -- --nocapture` — passed
- `git diff --check 5954021c..HEAD` — passed
- `cargo fmt --check` — passed
- `git status --short` — clean
Rationale:
- prior blocker は解消済み。`Pod::cancel_paused_turn()` は fake `RunCompleted { Finished, interrupted: false }` ではなく `LogEntry::PausedTurnAbandoned` を記録する。
- typed lifecycle entry は session log schema / replay に含まれ、`last_run_interrupted` を clear するため restore 後も resume 不可になる。
- tests は JSON kind `paused_turn_abandoned`、replay semantics、explicit lifecycle log、fake normal-finished run が残らないことを確認している。
- TUI acceptance criteria も満たしている。Paused `Ctrl+X``Method::Cancel`、Idle `Ctrl+X` は shutdown のまま、Running cancel は queued input clear を含む既存 behavior を維持している。
- controller test は Paused 到達、cancel 後 Idle、resume rejection、cancel/resume で追加 LLM request が発生しないこと、次入力が fresh run になることを確認している。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T13:56:05Z from: inprogress to: done reason: implementation_review_validation_passed field: state -->
## State changed
Implementation, review, and post-merge validation completed in orchestration worktree.
Evidence:
- Implementation commits merged into orchestration: `90b1a1fc`, `8c8fb014`, merge commit `76c80054`.
- Reviewer approved after requested lifecycle-log fix.
- Validation on merged orchestration branch passed:
- `cargo test -p session-store paused_turn_abandoned -- --nocapture`
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture`
- `cargo test -p tui ctrl_x -- --nocapture`
- `cargo fmt --check`
- `git diff --check HEAD~1..HEAD`
Next:
- Close Ticket with resolution, then fast-forward merge target if safe.
---
<!-- event: state_changed author: hare at: 2026-06-23T13:56:16Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-23T13:56:16Z status: closed -->
## 完了
Ticket 00001KVSMJJNV は完了。
実装内容:
- TUI Console の `Paused` 状態で `Ctrl+X` を TUI/Pod shutdown ではなく `Method::Cancel` として扱うようにした。
- `Idle``Ctrl+X` shutdown behavior と、`Running` の cancel behavior は維持した。
- paused cancel 後に resume 可能な interrupted state が残らず、次の入力が fresh run になるよう controller / Pod lifecycle を更新した。
- paused cancel を normal `RunCompleted { Finished }` として永続化せず、typed session log entry `LogEntry::PausedTurnAbandoned { ts }` として記録するようにした。
- replay / restore で `PausedTurnAbandoned``last_run_interrupted` を clear するようにした。
- focused tests を追加・更新し、TUI key handling、controller behavior、session log JSON/replay semantics、fake normal-finished run が残らないことを確認した。
主要 commits:
- `90b1a1fc tui: cancel paused turns with ctrl-x`
- `8c8fb014 fix: log paused cancel lifecycle explicitly`
- `76c80054 merge: 00001KVSMJJNV paused ctrl-x cancel`
Review:
- 初回 review は lifecycle log semantics の不一致で request_changes。
- `PausedTurnAbandoned` による typed lifecycle representation を追加後、Reviewer が approve。
Validation:
- `cargo test -p session-store paused_turn_abandoned -- --nocapture`
- `cargo test -p pod paused_cancel_abandons_resume_and_next_input_is_fresh_run -- --nocapture`
- `cargo test -p tui ctrl_x -- --nocapture`
- `cargo fmt --check`
- `git diff --check HEAD~1..HEAD`
Merge note:
- orchestration branch で実装・Ticket 記録・close resolution をまとめ、merge target へ fast-forward 予定。
---
@@ -0,0 +1,37 @@
# 実装報告: 00001KVTNAY20
## 変更概要
- `client::spawn``PodProcessLaunchConfig``PodProcessLaunchOptions` を導入し、低レベルの Pod プロセス起動設定から Ticket role marker を分離した。
- Ticket role 起動は `TicketRoleLaunchPlan::spawn_options()` 経由で hidden CLI marker を渡す形にし、`TicketRoleLaunchResult` に Run 受理証跡 (`TicketRoleLaunchAcceptanceEvidence`) を追加した。
- Workspace server の `LocalRuntimeBridge``WorkspaceWorkerRuntime` trait の実装として整理し、hosts/workers 一覧、worker lookup、spawn/stop typed request/result、将来の proxy/stream 接続点を型として追加した。
- Workspace 側の spawn request shape は policy intent ベースにし、browser/API caller から raw `workspace_root` / `cwd` / executable path / raw profile selector を受け取らない形にした。
- Dashboard/TUI 側の直接 spawn 呼び出しを新しい low-level config/options 分離に追従した。
## 変更ファイル
- `crates/client/src/lib.rs`
- `crates/client/src/spawn.rs`
- `crates/client/src/ticket_role.rs`
- `crates/tui/src/dashboard/mod.rs`
- `crates/tui/src/spawn.rs`
- `crates/workspace-server/src/hosts.rs`
- `crates/workspace-server/src/server.rs`
## 検証結果
- `cargo test -p yoi-workspace-server`: 成功
- `cargo check -p yoi`: 成功
- `cd web/workspace && deno task check && deno task build`: 成功
- `cargo test -p client`: 成功(追加確認)
- `git diff --check`: 成功
## コミット
- 実装コミット: `217a4828d73ab553b5406cc7e22e43b1ec7be48e`
## 残リスク / 非ゴールとして残したもの
- `WorkspaceWorkerRuntime::spawn_worker` / `stop_worker` は typed boundary と request/result を用意した段階で、実際の Worker operation UI 完成、stream proxy、remote Host protocol、認可/権限、registry locking までは実装していない。
- low-level launcher は trusted in-process resolver からの追加 CLI args を受け取れるが、Ticket role などのドメイン概念は `PodProcessLaunchConfig` からは除外している。
- TS 型生成やフロントエンド API surface の追加は本 Ticket の非ゴールとして変更していない。
@@ -0,0 +1,2 @@
{"id":"orch-plan-20260623-192711-1","ticket_id":"00001KVTNAY20","kind":"accepted_plan","accepted_plan":{"summary":"Ticket 00001KVTNAY20 は implementation_ready。専用 worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` と branch `work/00001KVTNAY20-worker-runtime-spawn` で、Workspace Worker runtime spawn abstraction を実装し、routing record の IntentPacket を基準に coder/reviewer sibling loop へ進める。root/original workspace では git/read/write/validate/merge/cleanup を行わない。","branch":"work/00001KVTNAY20-worker-runtime-spawn","worktree":"/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn","role_plan":"Orchestrator: acceptance/routing, worktree creation, final integration/validation/cleanup. Coder: implementation in dedicated child worktree with narrow write scope. Reviewer: read-only review by default against recorded IntentPacket, validation evidence, and diff. Orchestrator handles merge into orchestration branch after reviewer approval."},"author":"yoi-orchestrator","at":"2026-06-23T19:27:11Z"}
{"id":"orch-plan-20260623-193340-2","ticket_id":"00001KVTNAY20","kind":"waiting_capacity_note","note":"Coder sibling execution is temporarily blocked by runtime/provider startup failures, not by Ticket requirements. `builtin:coder` started but both initial run and retry failed with provider API error `Unsupported content type`; alternate `inherit` / `builtin:default` / `builtin:companion` recovery attempts did not produce a socket within 10s. Worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` remains clean at orchestration commit `b8388655`; no implementation diff exists yet. Human/tooling follow-up is needed before continuing multi-agent implementation, unless Orchestrator is explicitly authorized to implement directly.","author":"yoi-orchestrator","at":"2026-06-23T19:33:40Z"}
+158
View File
@@ -0,0 +1,158 @@
---
title: 'Abstract Workspace Worker runtime spawn operations'
state: 'done'
created_at: '2026-06-23T16:34:39Z'
updated_at: '2026-06-24T10:35:01Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-23T19:25:09Z'
---
## 背景
Workspace web / Workspace backend から Worker を起動・停止・操作する UI/API を作るには、現在 read-only live view として実装されている runtime bridge を、Worker 操作も扱える backend abstraction に拡張する必要がある。
現状:
- `crates/workspace-server/src/hosts.rs``LocalRuntimeBridge` は local runtime metadata を読んで `HostSummary` / `WorkerSummary` を返す read-only bridge である。
- `/api/hosts``/api/workers``/api/hosts/{host_id}/workers` はこの bridge を直接使っている。
- Worker 起動の最終境界は `yoi pod [POD_OPTIONS]` process launch である。
- 既存の `client::spawn::SpawnConfig``yoi pod` 起動 options の typed 表現に近いが、`ticket_role` のような Ticket/Orchestration domain の情報も混ざっている。
- Workspace backend には Worker spawn / stop / protocol proxy の抽象境界がまだない。
- Worker 起動を web backend から実装する際、workspace root / cwd / pod name / profile / role-session claim の経路が TUI とズレると、Panel 表示や workspace 所属判定が壊れる。
この Ticket では、Workspace backend から Worker spawn 操作を実装する前段として、**Pod process 起動境界**と**Ticket / Orchestration intent 境界**を分離して整理する。低レベル起動は Ticket system を知らず、Ticket/Orchestration 情報は上位 resolver / launch policy が低レベル config へ落とす。
## 要件
### Layering / responsibility split
起動系は少なくとも以下の層に分ける。
1. **Pod process launch layer**
- `yoi pod [POD_OPTIONS]` を起動する唯一の低レベル境界。
- Ticket / Orchestration / Role / TicketId を直接知らない。
- `workspace_root``pod_name``profile``manifest``project``store``cwd``initial_input``workflow``require_pod_state` のような process 起動 options だけを扱う。
2. **Worker runtime layer**
- Workspace backend / API から見える Worker 操作境界。
- hosts/workers live view、worker lookup、spawn/stop/protocol proxy の entrypoint を持つ。
- API intent を低レベル Pod process launch config へ解決する。
3. **Ticket / Orchestration resolver layer**
- Ticket ID、Ticket role、Orchestrator/Coder/Reviewer といった workflow domain を扱う。
- Role/Profile/Workflow/Ticket context を解決し、低レベル Pod process launch config と必要な launch policy / prompt input を作る。
- Ticket/Orchestration 情報を低レベル launcher に直接漏らさない。
### Pod process launch abstraction
- `SpawnConfig` をそのまま Workspace backend API の入力として扱わない。
- 低レベルの起動 config は Ticket/Orchestration domain を持たない形に整理する。
- 既存 `SpawnConfig` を改名/分割するか、別の `PodProcessLaunchConfig` / `PodLaunchOptions` を導入する。
- `ticket_role` は低レベル process config から分離する。
- 必要なら `PodLaunchPolicy` / `ProfileLaunchPolicy` のような別引数/別 layer に移す。
- `--ticket-role` は現状 hidden CLI marker として存在してよいが、汎用 `yoi pod` 起動 config の概念には含めない。
- 低レベル launcher は `Command::new("yoi")` 相当の process 起動と acceptance evidence 取得に責務を限定する。
- TUI/Panel、SpawnPod tool、Workspace backend はこの低レベル launcher を共有できるようにする。
### Worker runtime abstraction
- `LocalRuntimeBridge` 相当の read-only live view を、Worker 操作用の抽象境界へ整理する。
- trait 名は実装時に決めてよいが、概念としては `WorkerRuntime` / `WorkspaceWorkerRuntime` / `HostRuntime` のような境界を作る。
- 最低限、以下の責務を同じ abstraction から扱えるようにする。
- hosts list
- workers list
- worker detail / lookup
- worker spawn request
- worker stop request
- 将来の protocol method proxy / event stream の接続点
- v0 では local implementation のみでよい。
- 例: `LocalPodRuntime` / `LocalWorkspaceRuntime`
- 将来 Host protocol / remote worker backend を差し替えられるよう、Workspace API handler が concrete local implementation に密結合しすぎない形にする。
### Spawn operation abstraction
- Backend API から Worker を起動するための typed request / result を設計する。
- Browser から `workspace_root` / `cwd` / executable path / raw profile selector を自由入力させない。
- Frontend/API request は intent を中心にする。
- 例: generic worker profile launch、orchestrator start、ticket coder/reviewer start。
- ticket_id が必要な operation は path または typed field から受ける。
- Backend / resolver が以下を解決する。
- canonical workspace root
- process cwd
- pod name
- profile / manifest / project
- initial input / workflow
- optional launch policy
- role-session claim
- Orchestrator の dedicated worktree 起動では、runtime workspace identity と cwd を混同しない。
- `workspace_root` は original/main workspace
- `cwd` は orchestration worktree
- Coder / Reviewer / Orchestrator の Ticket-specific 起動経路は、低レベル Pod process launch config を生成する上位 resolver として扱う。
- Workspace backend が独自に `Command::new("yoi")` を組み立てて挙動を分岐させない。
### Ticket / Orchestration information boundary
- Ticket ID、Ticket role、Orchestration role は低レベル `PodProcessLaunchConfig` に入れない。
- Ticket/Orchestration resolver は以下を出力する。
- low-level Pod process launch config
- optional profile/launch policy
- role-session claim metadata
- model-visible initial input / workflow selection
- Role は Profile と同一視しない。
- Role は workflow 上の責務。
- Profile は Pod recipe。
- Role/Profile/Ticket の対応は上位 resolver の責務であり、低レベル launcher の責務ではない。
- Role を使わない generic Worker 起動では Ticket/Orchestration 情報を一切要求しない。
### API surface planning
- 実装する API はこの Ticket で確定しなくてもよいが、初期案として以下を検討する。
- generic: `POST /api/workers/spawn`
- operation: `POST /api/workers/{worker_id}/stop`
- orchestration: `POST /api/orchestrator/start`
- ticket-specific: `POST /api/tickets/{ticket_id}/workers`
- 起動 operation は HTTP command として扱う。
- 状態観測 / stream / transcript は後続 Ticket で SSE/WebSocket を検討する。
- spawn success は process start だけでなく、socket/connect/snapshot 等の acceptance evidence を持つこと。
### Role-session / Panel integration
- Backend spawn でも Panel が Worker を見つけられるようにする。
- 起動成功後に必要な local role-session claim を作る、または既存 helper を共有する。
- Runtime registry、Pod metadata、role-session registry のどれを authority / hint として扱うかを明確にする。
- stale/missing/already-running の扱いを typed error として返す。
### Safety / authority boundary
- Browser は local Unix socket path や runtime registry path を直接知らない。
- Backend が worker identity を解決し、対象 Worker が current Workspace から見えることを確認する。
- user permission model はこの Ticket の scope 外だが、将来挟める場所を backend abstraction に残す。
- Raw Pod protocol を browser から受ける場合でも、backend が最低限の method allow/block を挟める構造にする。
## Non-goals
- Worker operation UI の完成。
- WebSocket/SSE event stream の完成。
- Full permission / user auth model の設計。
- Remote Host protocol implementation。
- Pod protocol TypeScript 型生成の実装。
- Workspace identity `.yoi/workspace.toml` 実装。
- StopPod / registry locking の追加修正。
- Ticket/Orchestration domain を廃止すること。
- `--ticket-role` hidden CLI marker の即時削除。
## 受け入れ条件
この Ticket は planning から開始する。ready に進める前に以下を満たす。
- Workspace backend runtime abstraction の責務境界が明文化されている。
- `yoi pod [POD_OPTIONS]` process launch 境界と Ticket/Orchestration resolver 境界が分離されている。
- 低レベル Pod process launch config が Ticket ID / Ticket role / Orchestration role を直接持たない方針が明記されている。
- 既存 `SpawnConfig``ticket_role` をどう分離するかが決まっている。
- 現在の `LocalRuntimeBridge` をどう trait / service に置き換えるかが決まっている。
- Worker spawn request / result の typed shape が設計されている。
- Orchestrator / Coder / Reviewer の起動時に `workspace_root``cwd` をどう決めるかが明記されている。
- TUI/Panel、SpawnPod tool、Workspace backend が低レベル Pod process launcher を共有する方針が明記されている。
- Ticket/Orchestration resolver が低レベル launch config・launch policy・role-session claim を生成する方針が明記されている。
- Backend API endpoint の初期案が整理されている。
- role-session claim / Pod metadata / runtime registry との連携方針が明記されている。
- 実装まで含める場合は `cargo test -p yoi-workspace-server``cargo check -p yoi``cd web/workspace && deno task check && deno task build``git diff --check``nix build .#yoi --no-link` が通る。
+291
View File
@@ -0,0 +1,291 @@
<!-- event: create author: "yoi ticket" at: 2026-06-23T16:34:39Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-23T18:26:48Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-23T18:26:48Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-23T19:25:09Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-23T19:26:52Z -->
## Decision
Routing decision: implementation_ready
Reason:
- Dashboard Queue により人間が Orchestrator routing を許可した queued Ticket として確認した。
- Ticket body は Workspace backend の Worker runtime / Pod process launch / Ticket-Orchestration resolver の境界分離、typed spawn request/result、role-session 連携、安全境界、non-goals、validation を具体的に列挙している。
- `TicketRelationQuery` では blocking relation は 0 件、`TicketOrchestrationPlanQuery` では既存の ordering / blocker / conflict / accepted-plan 記録は 0 件だった。
- orchestration worktree は `## orchestration` で dirty changes なし、既存 implementation worktree は別 Ticket `00001KVSMJJNV-paused-ctrlx-cancel` と orchestration worktree のみで、この Ticket 用 worktree/branch はまだ無い。
- `crates/client/src/spawn.rs``crates/client/src/ticket_role.rs``crates/workspace-server/src/hosts.rs``crates/workspace-server/src/server.rs` を bounded に確認し、Ticket に書かれた現状認識と実装対象の code map が一致している。残る不確実性は local tactic / bounded investigation に収まる。
Evidence checked:
- Ticket body / thread: `item.md``thread.md`。thread は create、planning->ready、ready->queued のみで、未解決 blocker は記録されていない。
- related Ticket / orchestration plan records: relation 0 件、orchestration plan 0 件。
- code paths: `crates/client/src/spawn.rs``crates/client/src/ticket_role.rs``crates/workspace-server/src/hosts.rs``crates/workspace-server/src/server.rs`
- workspace state: `/home/hare/Projects/yoi/.worktree/orchestration``git status --short --branch` は clean な `## orchestration`。visible Pods は `yoi` peer と current `yoi-orchestrator` のみ。
IntentPacket:
Intent:
- Workspace backend から Worker spawn/stop/proxy を実装できる前段として、低レベル Pod process launch 境界と Worker runtime 境界、Ticket/Orchestration resolver 境界を分離し、既存 read-only `LocalRuntimeBridge` を操作境界へ拡張できる形に整理する。
Binding decisions / invariants:
- 低レベル Pod process launch layer は `yoi pod [POD_OPTIONS]` 起動だけを扱い、Ticket ID / Ticket role / Orchestration role を直接知らない。
- `SpawnConfig` をそのまま Workspace backend API 入力にしない。`ticket_role` は低レベル process config から分離する。
- Browser/API から `workspace_root` / `cwd` / executable path / raw profile selector を自由入力させない。backend/resolver が canonical workspace root、cwd、pod name、profile、initial input、workflow、launch policy、role-session claim を解決する。
- Orchestrator dedicated worktree 起動では runtime `workspace_root` と process `cwd` を混同しない。`workspace_root` は original/main workspace、`cwd` は orchestration worktree。
- Workspace backend が独自に `Command::new("yoi")` を組み立てて分岐する設計にしない。共有可能な低レベル launcher / config / acceptance evidence 境界を使う。
- この Ticket では Worker operation UI、SSE/WebSocket stream、full auth/permission、remote Host protocol、TypeScript protocol generation、Workspace identity `.yoi/workspace.toml`、StopPod/registry locking の追加修正は non-goal。
Requirements / acceptance criteria:
- Workspace backend runtime abstraction の責務境界を code/docs/tests で追える形にする。
- Pod process launch config と Ticket/Orchestration resolver 境界を分離し、低レベル config が Ticket/role/orchestration domain を持たないことを型・モジュール境界で示す。
- `LocalRuntimeBridge` 相当を Worker runtime trait/service として整理し、hosts/workers list、worker lookup、spawn/stop request、将来 proxy/stream 接続点を表現できるようにする。
- Worker spawn request/result の typed shape と acceptance evidence の扱いを導入する。
- role-session claim / Pod metadata / runtime registry の連携方針を実装境界または明文化された設計として残す。
- validation として少なくとも `cargo test -p yoi-workspace-server``cargo check -p yoi``cd web/workspace && deno task check && deno task build``git diff --check` を実施する。`nix build .#yoi --no-link` は変更量・依存/packaging 影響に応じて Orchestrator が最終判断する。
Implementation latitude:
- trait / struct 名は Ticket の例示に縛られず、既存 module organization に沿ってよい。
- `SpawnConfig` を rename/split するか、新規 `PodProcessLaunchConfig` / `PodLaunchOptions` を導入するかは coder が code map を見て選んでよい。
- API endpoint の完全実装ではなく、backend abstraction と typed request/result の初期 shape / handler 接続点を優先してよい。
- tests は既存 workspace-server/client test style に合わせて最小限でよい。
Escalate if:
- Browser から raw local path / raw executable / raw profile selector を受ける必要が出る。
- Ticket/Orchestration 情報を低レベル launcher に持たせないと実装できないと判断した場合。
- workspace_root / cwd / runtime identity / role-session authority の境界を変える必要が出る。
- public API endpoint shape をこの Ticket の初期案から大きく固定する必要が出る。
- existing Panel/role-session semantics を破壊する変更が必要になる。
Validation:
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi`
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- 必要に応じて `nix build .#yoi --no-link`
Current code map:
- Primary: `crates/workspace-server/src/hosts.rs`, `crates/workspace-server/src/server.rs`, `crates/client/src/spawn.rs`, `crates/client/src/ticket_role.rs`
- Secondary if needed: workspace API/client integration, role-session helpers, Pod runtime command utilities, docs/resources prompts only when implementation requires。
- Avoid: unrelated UI completion, broad permission model, remote Host protocol, root/original workspace operations。
Critical risks / reviewer focus:
- Ticket/role/orchestration fields leaking into the low-level launcher.
- Workspace runtime abstraction becoming a UI-specific concrete local bridge instead of a backend boundary.
- Browser/API accepting authority-bearing raw paths or executable/profile selectors.
- `workspace_root` and `cwd` confusion for dedicated Orchestrator/Coder/Reviewer launches.
- acceptance evidence treated as mere process start.
- role-session claim / metadata / runtime registry authority and hint semantics left ambiguous.
Next action:
- `queued -> inprogress` を記録してから、worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` を作成し、multi-agent-workflow で sibling coder/reviewer loop に進める。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-23T19:27:22Z from: queued to: inprogress reason: orchestrator_acceptance_unblocked field: state -->
## State changed
Orchestrator acceptance: queued -> inprogress
- 直前確認で `TicketShow` は state `queued`、blocking relation は 0 件、accepted plan は `orch-plan-20260623-192711-1` のみだった。
- routing decision と IntentPacket は Ticket thread に記録済み。
- orchestration worktree は clean な `## orchestration` で、この Ticket 用 implementation worktree/branch はまだ作成していない。
- これ以降に worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` を作成し、multi-agent-workflow に接続する。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T19:30:10Z -->
## Implementation report
Implementation orchestration update:
- worktree-workflow に従い、implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` と branch `work/00001KVTNAY20-worker-runtime-spawn` を作成した。
- child worktree では sparse-checkout を設定し、tracked `.yoi` project records は見える一方で `.yoi/memory`、local/runtime/log/lock/secret-like `.yoi` paths を除外する方針にした。
- Coder Pod `yoi-coder-00001KVTNAY20-worker-runtime` を sibling として起動した。write scope は child worktree に限定し、runtime workspace root `/home/hare/Projects/yoi` は startup 要件を満たすため non-recursive read のみにした。Coder には root/original workspace と orchestration worktree で read/write/validation/git operation を行わないよう明示した。
- 初回 spawn は workspace root read scope が不足して失敗したため、implementation side effect は残さず scope を修正して再試行した。現在 reachable child Pod として起動済み。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T19:31:58Z -->
## Implementation report
Implementation orchestration recovery:
- `yoi-coder-00001KVTNAY20-worker-runtime` は provider API error `Unsupported content type` で初回実行・再送とも assistant output を生成できなかった。
- child worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` は実装差分なしで、last commit は routing acceptance commit `5a8bcebd ticket: accept worker runtime spawn task` のままだった。
- 失敗 Pod は停止して scope を回収した。
- 実装 side effect の回復として、同じ child worktree/branch を使い、別 profile で Coder role を再起動する。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-23T19:33:48Z -->
## Implementation report
Implementation orchestration blocked:
- Coder sibling execution is blocked by runtime/provider failures, not by Ticket requirements or repository state.
- `builtin:coder` Pod `yoi-coder-00001KVTNAY20-worker-runtime` started, but both initial run and retry failed before assistant output with provider API error: `Unsupported content type`.
- That Pod was stopped and scope reclaimed. child worktree status remained clean with no implementation diff.
- Recovery attempts using `inherit` (`yoi-coder-00001KVTNAY20-worker-runtime-2`), `builtin:default` (`...-3`), and `builtin:companion` (`...-4`) did not produce sockets within 10s.
- Worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` and branch `work/00001KVTNAY20-worker-runtime-spawn` are prepared and clean at orchestration commit `b8388655`.
- `orch-plan-20260623-193340-2` に waiting-capacity note を残した。
Next action:
- Coder Pod/profile/provider startup issue の解消後に同じ worktree/branch で multi-agent workflow を再開する。
- あるいは人間が明示的に Orchestrator direct implementation を許可する場合のみ、Orchestrator がこの child worktree で実装へ進む。
---
<!-- event: implementation_report author: hare at: 2026-06-24T10:26:04Z -->
## Implementation report
# 実装報告: 00001KVTNAY20
## 変更概要
- `client::spawn``PodProcessLaunchConfig``PodProcessLaunchOptions` を導入し、低レベルの Pod プロセス起動設定から Ticket role marker を分離した。
- Ticket role 起動は `TicketRoleLaunchPlan::spawn_options()` 経由で hidden CLI marker を渡す形にし、`TicketRoleLaunchResult` に Run 受理証跡 (`TicketRoleLaunchAcceptanceEvidence`) を追加した。
- Workspace server の `LocalRuntimeBridge``WorkspaceWorkerRuntime` trait の実装として整理し、hosts/workers 一覧、worker lookup、spawn/stop typed request/result、将来の proxy/stream 接続点を型として追加した。
- Workspace 側の spawn request shape は policy intent ベースにし、browser/API caller から raw `workspace_root` / `cwd` / executable path / raw profile selector を受け取らない形にした。
- Dashboard/TUI 側の直接 spawn 呼び出しを新しい low-level config/options 分離に追従した。
## 変更ファイル
- `crates/client/src/lib.rs`
- `crates/client/src/spawn.rs`
- `crates/client/src/ticket_role.rs`
- `crates/tui/src/dashboard/mod.rs`
- `crates/tui/src/spawn.rs`
- `crates/workspace-server/src/hosts.rs`
- `crates/workspace-server/src/server.rs`
## 検証結果
- `cargo test -p yoi-workspace-server`: 成功
- `cargo check -p yoi`: 成功
- `cd web/workspace && deno task check && deno task build`: 成功
- `cargo test -p client`: 成功(追加確認)
- `git diff --check`: 成功
## コミット
- 実装コミット: `217a4828d73ab553b5406cc7e22e43b1ec7be48e`
## 残リスク / 非ゴールとして残したもの
- `WorkspaceWorkerRuntime::spawn_worker` / `stop_worker` は typed boundary と request/result を用意した段階で、実際の Worker operation UI 完成、stream proxy、remote Host protocol、認可/権限、registry locking までは実装していない。
- low-level launcher は trusted in-process resolver からの追加 CLI args を受け取れるが、Ticket role などのドメイン概念は `PodProcessLaunchConfig` からは除外している。
- TS 型生成やフロントエンド API surface の追加は本 Ticket の非ゴールとして変更していない。
---
<!-- event: review author: yoi-reviewer-00001KVTNAY20-worker-runtime at: 2026-06-24T10:33:54Z status: approve -->
## Review: approve
Review result: approve
Read-only で Ticket `00001KVTNAY20`、implementation report、`a729d686..HEAD` の差分を確認した。ファイル変更・Ticket review 記録・merge/cleanup は reviewer では行っていない。
確認した主な点:
- 低レベル Pod launcher は `crates/client/src/spawn.rs``PodProcessLaunchConfig` / options に分離され、Ticket/role/orchestration 固有の型や field は入っていない。`--workspace` と process `cwd` も別 field のまま扱われている。
- Ticket role 起動は `crates/client/src/ticket_role.rs` 側に寄せられ、role/profile/workflow/prompt/初回 `Run` の組み立ては launcher ではなく role 層で処理されている。
- 起動成功は単なる process start ではなく、既存 socket readiness に加えて Ticket role launch では `Method::Run` 送信後の `UserMessage` / `InvokeStart(UserSend)` / `TurnStart` を待つ形になっている。
- Workspace server 側は `WorkspaceWorkerRuntime` trait と `WorkerSpawnRequest` / `WorkerStopRequest` / `WorkerProtocolProxyRequest` を導入し、現在の local 実装は Pod metadata read boundary + unsupported lifecycle operation として明示されている。Browser/API request shape に `workspace_root` / `cwd` / executable path / raw profile selector は受けていない。
- Dedicated Orchestrator launch では runtime `workspace_root` と process `cwd` を混同しないテストが追加されており、original workspace と orchestration checkout が分離されている。
- 非ゴールである実 scheduler、E2E、merge/cleanup automation 等の scope creep は入っていない。
Validation evidence:
- reviewer は read-only 制約のため build/test は再実行していない。
- 実装報告の検証結果として `cargo test -p yoi-workspace-server``cargo check -p yoi``cd web/workspace && deno task check && deno task build``cargo test -p client``git diff --check` の成功を確認した。
- reviewer 側では read-only な `git diff --check a729d686..HEAD` を実行し、問題なし。
Non-blocking notes:
- `WorkerSpawnRequest` はまだ実 endpoint 未接続かつ local runtime では `Unsupported` なのでこの Ticket では問題ない。今後実装時は `requested_worker_name` を backend 側で厳格に validate し、Browser 由来の値を Pod authority として扱わないことを明示すると安全。
- `launch_ticket_role_pod` の acceptance 待ちは fresh spawn 前提では妥当。将来既存 Pod restore/競合を扱う場合は、connect-time `Snapshot`/`Alert` の drain と「送信した Run に対応する evidence」の対応付けをより強くするとよい。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-24T10:34:55Z -->
## Implementation report
Integration outcome:
- Coder retry `yoi-coder-00001KVTNAY20-worker-runtime-retry1` が完走し、implementation branch `work/00001KVTNAY20-worker-runtime-spawn` に実装を commit した。
- Reviewer `yoi-reviewer-00001KVTNAY20-worker-runtime` は read-only review で `approve`。低レベル launcher と Ticket/role/orchestration resolver の分離、Workspace runtime abstraction、raw authority input 非受理、`workspace_root`/`cwd` 分離、acceptance evidence、scope creep なしを確認した。
- Orchestrator worktree `/home/hare/Projects/yoi/.worktree/orchestration` で branch `work/00001KVTNAY20-worker-runtime-spawn` を merge 済み。
- merge commit: `97555bb5 merge: 00001KVTNAY20 worker runtime spawn`
- implementation commit: `217a4828 feat: abstract worker runtime spawn boundary`
- implementation report commit: `d62ab6e1 docs: record worker runtime implementation report`
Validation in Orchestrator worktree:
- `cargo test -p yoi-workspace-server`: success
- `cargo check -p yoi`: success
- `cd web/workspace && deno task check`: success
- `cd web/workspace && deno task build`: success
- `git diff --check`: success
Notes:
- Reviewer non-blocking note: future actual spawn endpoint should validate any requested worker name server-side and avoid treating Browser-provided values as Pod authority.
- Reviewer non-blocking note: future restore/competition handling may need stronger association between a sent `Run` and acceptance evidence after connect-time `Snapshot`/`Alert` drain.
Next action:
- Mark Ticket done after this integration/validation evidence.
- Then stop related child Pods and remove only the child implementation worktree/branch.
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-24T10:35:01Z from: inprogress to: done reason: merged_validated field: state -->
## State changed
Implementation is merged into the orchestration branch and validated.
Evidence:
- merge commit: `97555bb5 merge: 00001KVTNAY20 worker runtime spawn`
- reviewer result: approve
- validation in `/home/hare/Projects/yoi/.worktree/orchestration` succeeded:
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi`
- `cd web/workspace && deno task check`
- `cd web/workspace && deno task build`
- `git diff --check`
Closure is not performed here; this state records implementation completion after merge/validation.
---
+90
View File
@@ -0,0 +1,90 @@
---
title: 'Planning Ticket API and UI without queue operations'
state: 'planning'
created_at: '2026-06-23T19:41:51Z'
updated_at: '2026-06-23T19:41:51Z'
assignee: null
---
## 背景
Ticket 管理 UI を作るにあたり、最初から DB migration や Queue 操作まで含めると authority 境界が大きくなりすぎる。現行の Ticket authority は `.yoi/tickets/<ticket-id>/` の flat file backend であり、Workspace server 側にも Ticket 用 SQLite schema の器はあるが、現時点では authority ではない。
この Ticket では migration を行わず、まず Workspace backend に Ticket 操作用 API を整備し、その API を操作する最小 UI を実装する。対象は Planning Ticket の作成・確認に限定し、`ready -> queued` の Queue 操作や Orchestrator 起動には踏み込まない。
## 目的
- Workspace web から Ticket を確認し、Planning 状態の Ticket を作成できるようにする。
- UI は backend API を通じて Ticket を操作し、frontend が `.yoi/tickets` の内部ファイル構造や authority path に依存しないようにする。
- 将来 DB authority / migration に進む余地を残しつつ、この Ticket では現行 file backend を正として扱う。
## 要件
### Backend API
- Workspace server に Ticket 管理用 API を追加または整理する。
- v0 では現行 `LocalTicketBackend` / project record reader を authority として使い、DB migration はしない。
- API は少なくとも以下を扱う。
- Ticket 一覧取得
- Ticket 詳細取得
- Planning 状態の Ticket 作成
- 作成 API は title と本文/背景/受け入れ条件などの必要最小限の入力を受け、canonical Ticket ID を返す。
- frontend から raw `.yoi/tickets` path や内部 artifact path を直接指定させない。
- Ticket ID は canonical ID のみを扱い、title slug や legacy alias を API contract にしない。
- API の error は typed response として扱う。
- invalid input
- duplicate / conflict
- backend unavailable
- workspace not found / outside current workspace
### UI
- Workspace web に Ticket 管理画面または Ticket 作成導線を追加する。
- v0 UI は Planning Ticket の作成までに限定する。
- 作成フォームは最低限以下を扱う。
- title
- 背景 / 要件の本文
- 受け入れ条件
- 作成後は作成された canonical Ticket ID と状態を表示し、詳細画面または一覧へ反映する。
- UI は API response を authority とし、frontend 側で Ticket file layout を再実装しない。
### Scope boundary
- Queue 操作は実装しない。
- `ready -> queued`
- Panel / Workspace UI からの Queue button
- Orchestrator / Coder / Reviewer 起動
- role-session claim 作成
- Ticket DB migration は実装しない。
- 既存 `.yoi/tickets` authority を変更しない。
- 既存 Ticket CLI / Pod tool の挙動を壊さない。
### Safety / authority
- Browser は local path / runtime path / socket path を直接 authority として渡さない。
- Workspace backend が current workspace の Ticket backend root を解決する。
- Ticket 作成は current workspace の `.yoi/tickets` に限定する。
- 将来 permission model を挟めるよう、API handler と backend operation の境界を分ける。
## Non-goals
- Ticket storage の DB migration。
- SQLite `tickets` schema を authority に昇格すること。
- Queue / ready / inprogress / close などの lifecycle mutation UI。
- Orchestrator 起動、Worker spawn、role-session claim 連携。
- Ticket relation / artifact / orchestration-plan 編集 UI。
- SSE/WebSocket による live Ticket update。
## 受け入れ条件
- Workspace server に Ticket list/detail/create planning 用 API がある。
- Planning Ticket 作成 API が canonical Ticket ID を返す。
- 作成された Ticket は既存 `yoi ticket list/show` から確認できる。
- Workspace web から Planning Ticket を作成できる。
- UI から Queue 操作はできない。
- DB migration や SQLite Ticket authority 化を行っていない。
- `cargo test -p yoi-workspace-server` が通る。
- `cargo check -p yoi` が通る。
- `cd web/workspace && deno task check && deno task build` が通る。
- `git diff --check` が通る。
- `nix build .#yoi --no-link` が通る。
+7
View File
@@ -0,0 +1,7 @@
<!-- event: create author: "yoi ticket" at: 2026-06-23T19:41:51Z -->
## 作成
LocalTicketBackend によって作成されました。
---
@@ -0,0 +1,3 @@
{"id":"orch-plan-20260624-092429-1","ticket_id":"00001KVWECEQG","kind":"do_not_parallelize","related_ticket":"00001KVTNAY20","note":"`00001KVWECEQG` と inprogress `00001KVTNAY20` はどちらも `LocalRuntimeBridge` / Workspace Worker runtime abstraction / runtime identity・cwd 境界を扱い、primary code surface が `crates/workspace-server/src/hosts.rs` と API handler 層で重なる。`00001KVTNAY20` は Coder runtime/provider blocker で実装未開始のまま child worktree を保持しているため、並列実装すると registry abstraction と spawn abstraction の境界を二重に固定する conflict risk が高い。先に `00001KVTNAY20` の blocker 解消または明示的な ordering/design decision が必要。","author":"yoi-orchestrator","at":"2026-06-24T09:24:29Z"}
{"id":"orch-plan-20260624-092435-2","ticket_id":"00001KVWECEQG","kind":"waiting_capacity_note","note":"Queued routing was authorized, and the Ticket appears implementation-ready after bounded evidence checks, but current Coder sibling capacity is unavailable: prior inprogress Ticket `00001KVTNAY20` already attempted multi-agent startup and hit provider/startup failures (`Unsupported content type`, alternate profiles no socket). Because this Ticket overlaps the same Worker runtime abstraction surface and no Coder/Reviewer loop can currently run safely, leave `00001KVWECEQG` queued rather than accepting `queued -> inprogress`. Resume when Coder runtime is healthy or when a human explicitly authorizes Orchestrator direct implementation/order.","author":"yoi-orchestrator","at":"2026-06-24T09:24:35Z"}
{"id":"orch-plan-20260624-103655-3","ticket_id":"00001KVWECEQG","kind":"accepted_plan","accepted_plan":{"summary":"`00001KVTNAY20` は done/merged/validated になったため、以前の do_not_parallelize/waiting-capacity blocker は解消済みとして扱う。`00001KVWECEQG` は dedicated worktree `/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry` と branch `work/00001KVWECEQG-worker-runtime-registry` で Worker runtime registry / capability / overview abstraction を実装する。root/original workspace では git/read/write/validate/merge/cleanup を行わない。","branch":"work/00001KVWECEQG-worker-runtime-registry","worktree":"/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry","role_plan":"Orchestrator: routing acceptance, worktree creation, final integration/validation/cleanup. Coder: implementation in dedicated child worktree with narrow write scope, using current `00001KVTNAY20` result as base. Reviewer: read-only review against recorded IntentPacket, diff, and validation evidence."},"author":"yoi-orchestrator","at":"2026-06-24T10:36:55Z"}
+162
View File
@@ -0,0 +1,162 @@
---
title: 'Abstract Worker runtime registry and overview reporting'
state: 'done'
created_at: '2026-06-24T09:11:38Z'
updated_at: '2026-06-24T11:15:13Z'
assignee: null
queued_by: 'workspace-panel'
queued_at: '2026-06-24T09:22:55Z'
---
## 背景
Workspace backend には現状 `LocalRuntimeBridge` があり、local Pod metadata から `HostSummary` / `WorkerSummary` を返す read-only live view として動いている。しかしこれは concrete local 実装に近く、将来の Backend internal runtime、local Pod runtime、remote / multi-machine runtime を同じ control plane から扱う抽象境界にはまだなっていない。
今後の Ticket / Worker 管理 UI では、Backend が Worker を直接 `yoi pod` や local metadata path として扱うのではなく、複数の Worker runtime を束ねる control plane になる必要がある。Companion / Intake / routing-only Orchestrator のような filesystem を必須としない Worker は Backend internal runtime で動かせるべきであり、Coder / Reviewer / build-heavy Worker は local / remote の filesystem-capable runtime に配置できるべきである。
また、Worker session を Backend が raw log として全量・恒久的に収集する設計にはしない。raw session / provider trace / detailed event stream は execution runtime 側の prune 可能な debug/source log とし、Backend は Worker run overview、usage aggregate、lifecycle event、Ticket / role / runtime link、artifact reference、failure summary のような後から使える durable projection を持つ。
この Ticket では、既存 `LocalRuntimeBridge` をレベル上げして、Workspace backend の Worker runtime registry / runtime abstraction として整理する。
## 目的
- Workspace backend が複数の Worker runtime を扱える抽象境界を持つ。
- 既存 local Pod metadata read-only bridge を `LocalPodRuntime` 相当の runtime 実装として位置付ける。
- Backend が runtime registry を持ち、API handler が concrete local bridge に直接依存しないようにする。
- raw session を Backend authority にせず、overview / metrics / durable outcome を中心に扱う方針を型と API 境界に反映する。
- 後続の spawn / stop / protocol proxy / remote runtime / internal runtime 実装に進める基盤を作る。
## 要件
### Worker runtime abstraction
- `LocalRuntimeBridge` をそのまま API handler から直接使う構造をやめ、Worker runtime trait / service 境界を導入する。
- 概念名は実装時に決めてよいが、`WorkerRuntime` / `WorkspaceWorkerRuntime` / `RuntimeRegistry` / `WorkerRuntimeRegistry` のような責務が明確な名前にする。
- v0 では少なくとも以下の read operations を抽象化する。
- runtime / host list
- runtime / host detail
- worker list
- worker detail / lookup
- 後続 operation の接続点を型として残す。
- spawn worker
- stop worker
- send input / interrupt / compact などの worker command routing
- bounded transcript / debug session read
- event stream / run overview stream
- v0 で未実装の operation は unsupported として typed error を返せるようにする。
### Runtime registry
- Workspace backend は単一の concrete `LocalRuntimeBridge` ではなく、runtime registry 経由で Worker / Host を取得する。
- registry は複数 runtime を保持できる構造にする。
- backend internal runtime
- local Pod runtime
- future remote runtime
- v0 では local Pod runtime のみ登録してよい。
- runtime_id / host_id / worker_id は API contract 上 opaque id として扱う。
- `pod_name` は local Pod runtime の implementation detail / display hint とし、外部操作の主キーにはしない。
- API handler は runtime_id / worker_id を registry に解決させ、raw local path / socket path / metadata path を browser に出さない。
### Runtime capability model
- Runtime / Host detail は capability summary を返す。
- 少なくとも以下のような区別ができること。
- can_list_workers
- can_get_worker
- can_spawn_worker
- can_stop_worker
- can_accept_input
- can_stream_events
- can_read_bounded_transcript / debug session
- has_workspace_fs
- has_shell
- has_git
- supports_worktrees
- supports_backend_internal_tools / ticket tools
- Companion / Intake / routing-only Orchestrator は filesystem なし runtime でも動かせる、Coder / Reviewer は filesystem-capable runtime が必要、という placement 判断を後続で表現できる shape にする。
### Worker identity / visibility
- Worker identity は runtime scoped に扱う。
- runtime_id
- worker_id
- optional active run id
- optional active session id / segment id は implementation detail または debug field
- Workspace UI の通常表示では current workspace から見える Worker だけを返す。
- local Pod runtime では `PodMetadata.workspace_root` を current workspace root と比較して visibility を決める。
- `cwd` と runtime workspace identity を混同しない。
- dedicated Orchestrator worktree があっても、runtime workspace identity は original/main workspace root である。
- workspace root が無い / 不一致 / metadata invalid な Worker は diagnostics または debug scope として扱い、通常 UI の authority を歪めない。
### Session / overview boundary
- Backend は raw session log を恒久 authority として持たない。
- raw session / provider trace / verbose event stream は execution runtime 側に残し、runtime retention / prune 対象とする。
- Backend が durable に持つものは以下を中心にする。
- Worker run overview
- lifecycle event
- usage aggregate
- Ticket / role / runtime / worker link
- durable outcome summary
- failure summary
- artifact / report reference
- Runtime interface は必要に応じて bounded transcript / debug session tail を読める接続点を持つが、これは debug / live UI 用であり Backend DB の durable authority ではない。
- usage dashboard は raw session ingest ではなく、runtime からの usage event / aggregate を元に構築できる形にする。
### Backend internal runtime planning
- Backend internal runtime はこの Ticket で完全実装しなくてよいが、registry / capability / identity model がそれを表現できること。
- Backend internal runtime は filesystem tool を前提にしない Worker 用とする。
- Companion
- Intake
- Ticket planning / routing assistant
- Dashboard assistant
- Backend internal Worker は Ticket / Workspace API を tool として使う形を想定し、raw local filesystem authority を要求しない。
### Local Pod runtime migration
- 既存 `LocalRuntimeBridge` の read-only local metadata 実装を `LocalPodRuntime` 相当へ移す、または薄い adapter として registry に登録する。
- 既存 API の挙動を壊さない。
- `GET /api/hosts`
- `GET /api/workers`
- `GET /api/hosts/{host_id}/workers`
- 追加可能であれば worker detail endpoint を追加する。
- `GET /api/workers/{worker_id}`
- `GET /api/hosts/{host_id}/workers/{worker_id}`
- local Pod metadata の raw content / snapshot content / socket path は API response に出さない。
### API / error boundary
- API response は runtime registry 経由の typed response にする。
- unknown runtime / host / worker は typed error として返す。
- runtime unavailable、operation unsupported、worker not visible、invalid query は区別できるようにする。
- Browser は local Unix socket path、runtime registry file path、Pod metadata path、raw session path を authority として渡さない。
## Non-goals
- Worker spawn / stop の本実装。
- Remote runtime protocol の本実装。
- Backend internal runtime で実際に LLM Worker を起動すること。
- raw session 全量の Backend DB ingest。
- Session log schema migration。
- Ticket storage migration。
- Worker operation UI の完成。
- SSE/WebSocket event stream の完成。
- Permission / auth model の完成。
## 受け入れ条件
この Ticket は planning から開始する。ready に進める前に以下を満たす。
- Worker runtime / runtime registry / local Pod runtime の責務境界が明文化されている。
- 既存 `LocalRuntimeBridge` をどう level-up / rename / adapter 化するかが決まっている。
- Backend が複数 runtime を保持できる registry 構造の方針が決まっている。
- runtime_id / host_id / worker_id の identity 方針が決まっている。
- local Pod `pod_name` を external operation key にしない方針が明記されている。
- Runtime capability model の最小 field が整理されている。
- current workspace visibility と workspace_root / cwd の扱いが明記されている。
- raw session を Backend durable authority にしない方針が明記されている。
- Backend に残す Worker run overview / usage aggregate / lifecycle projection の方針が明記されている。
- bounded transcript / debug session read は runtime-local optional operation とする方針が明記されている。
- 既存 `/api/hosts` / `/api/workers` を registry 経由へ移す方針が明記されている。
- 実装まで含める場合は `cargo test -p yoi-workspace-server``cargo check -p yoi``git diff --check``nix build .#yoi --no-link` が通る。
+377
View File
@@ -0,0 +1,377 @@
<!-- event: create author: "yoi ticket" at: 2026-06-24T09:11:38Z -->
## 作成
LocalTicketBackend によって作成されました。
---
<!-- event: intake_summary author: hare at: 2026-06-24T09:21:22Z -->
## Intake summary
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: "yoi ticket" at: 2026-06-24T09:21:22Z from: planning to: ready reason: cli_state field: state -->
## State changed
Marked ready by `yoi ticket state`.
---
<!-- event: state_changed author: workspace-panel at: 2026-06-24T09:22:55Z from: ready to: queued reason: queued field: state -->
## State changed
Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-24T09:24:52Z -->
## Decision
Routing decision: blocked_by_dependency_or_missing_authority
Reason:
- Dashboard Queue により人間が Orchestrator routing を許可した queued Ticket として確認した。
- Ticket body は Worker runtime registry / overview reporting / runtime capability / identity / visibility / raw-session boundary / local Pod runtime migration を具体的に列挙しており、実装意図と受け入れ条件は implementation-ready に近い。
- `TicketRelationQuery` では blocking relation は 0 件、初回 `TicketOrchestrationPlanQuery` では既存 plan record は 0 件だった。
- ただし現在 `00001KVTNAY20` (`Abstract Workspace Worker runtime spawn operations`) が `inprogress` で、同じ `LocalRuntimeBridge` / Workspace Worker runtime abstraction / runtime identity・cwd 境界と `crates/workspace-server/src/hosts.rs` 周辺を扱っている。
- `00001KVTNAY20` は multi-agent startup が provider/runtime error で停止しており、implementation worktree は clean だが Coder sibling capacity が実質利用できない状態である。
- この Ticket を今 `queued -> inprogress` にすると、同じ runtime abstraction の registry 側と spawn 側を別 branch で同時に固定して conflict risk が高い。さらに Coder/Reviewer loop を起動できないため、acceptance 後に進められない。
Evidence checked:
- Ticket body / thread: `00001KVWECEQG` の item/thread。thread は create、planning->ready、ready->queued のみで未解決 planning question は記録されていない。
- Relations / orchestration plan: `00001KVWECEQG` は relation 0 件、既存 plan 0 件。routing 中に `orch-plan-20260624-092429-1` (`do_not_parallelize` with `00001KVTNAY20`) と `orch-plan-20260624-092435-2` (waiting capacity note) を記録した。
- Related Ticket: `00001KVTNAY20``inprogress`、accepted plan と waiting-capacity note があり、Coder Pod startup/provider failure により実装未開始。
- Workspace state: `/home/hare/Projects/yoi/.worktree/orchestration` は clean。既存 implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVTNAY20-worker-runtime-spawn` は clean at `a729d686`
- Visible Pods: `yoi`, current `yoi-orchestrator`, and stopped/restorable failed `yoi-coder-00001KVTNAY20-worker-runtime` metadata only; active usable Coder/Reviewer sibling は無い。
Decision:
- `00001KVWECEQG` は planning へ戻さない。Ticket の missing decision / missing information は現時点で具体化していない。
- ただし `queued -> inprogress` acceptance は行わず、queued のまま待機させる。
- Blocker は Ticket 要件ではなく、(1) `00001KVTNAY20` との runtime abstraction/code-surface conflict、(2) Coder sibling runtime/provider capacity failure。
Next action:
- 先に `00001KVTNAY20` の Coder runtime/provider blocker を解消して multi-agent workflow を再開する、または人間が Orchestrator direct implementation / ordering を明示的に許可する。
- その後、この Ticket を再 routing し、必要なら `00001KVTNAY20` の実装結果に合わせて registry abstraction の IntentPacket を作る。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-24T10:37:25Z -->
## Decision
Routing decision: implementation_ready
Reason:
- ユーザーから「進めて」と明示 follow-up があり、以前 `queued` のまま待機させた blocker を再確認した。
- Ticket body は Worker runtime registry / overview reporting / runtime capability / identity / visibility / raw-session boundary / local Pod runtime migration を具体的に列挙しており、observable な acceptance criteria と reviewer focus がある。
- `TicketRelationQuery` は blocking relation 0 件。
- 以前の `do_not_parallelize` / waiting-capacity note は `00001KVTNAY20``done` になり、merge/validation 済みになったことで解消済みとして扱える。
- 現在の `crates/workspace-server/src/hosts.rs` には `00001KVTNAY20` の結果として `WorkspaceWorkerRuntime`、typed spawn/stop/proxy request/result、local Pod metadata overview が入り、今回の registry/capability/overview abstraction をその上に重ねられる。残る不確実性は local tactic / bounded investigation に収まる。
- orchestration worktree は clean で、同一 Ticket 用 worktree/branch はまだ無い。
Evidence checked:
- Ticket body / thread: `00001KVWECEQG` の item/thread。前回 routing decision 以降の missing planning question はなし。
- Relations / orchestration plan: relation 0 件。既存 plan は前回の `do_not_parallelize` / waiting-capacity と、今回記録した accepted plan `orch-plan-20260624-103655-3`
- Related Ticket: `00001KVTNAY20``done`。review approve、orchestration merge、validation success、child cleanup 済み。
- Code map: `crates/workspace-server/src/hosts.rs`, `crates/workspace-server/src/server.rs` を current orchestration branch で確認。
- Workspace state: `/home/hare/Projects/yoi/.worktree/orchestration` は clean。
IntentPacket:
Intent:
- Workspace backend の Worker runtime surface を、single local bridge から registry / host / capability / overview reporting の境界へ抽象化し、Dashboard/API が runtime 一覧・worker 一覧・capability/diagnostic を安全に表示できる基盤を作る。
Binding decisions / invariants:
- registry/overview は local Pod metadata と role-session/runtime metadata の安全な summary を扱う。raw session contents や unchecked private/runtime paths を API response に出さない。
- Browser/API 由来の値を runtime authority として扱わない。worker/host id は backend が解決・検証した bounded identifier として扱う。
- runtime identity / workspace_root / process cwd / role-session claim は混同しない。
- `00001KVTNAY20` で入った low-level launch boundary と Ticket/role/orchestration resolver separation を崩さない。
- remote Host protocol、full scheduler、operation UI、stream/proxy 実装、permission/auth の完成、raw session inspection は non-goal。
Requirements / acceptance criteria:
- Worker runtime registry/service abstraction が、複数 runtime/host summary と capability/diagnostic reporting を表現できる。
- `LocalRuntimeBridge` 由来の local runtime が registry の一実装/entry として扱われ、API handler が concrete bridge に直接密結合しすぎない。
- overview response は bounded/safe fields のみで、local Pod metadata failure や unavailable capability を diagnostic として返せる。
- existing `/api/hosts` / `/api/workers` semantics を維持または明確に migration し、UI が使う shape を壊す場合は対応も含める。
- validation として少なくとも `cargo test -p yoi-workspace-server`, `cargo check -p yoi`, `cd web/workspace && deno task check && deno task build`, `git diff --check` を実施する。
Implementation latitude:
- registry trait/struct 名、module split、capability enum/string shape、diagnostic aggregation の詳細は coder が既存 code style に合わせて決めてよい。
- API の大規模追加ではなく、current endpoints の内部境界整理と typed overview/capability shape の初期導入を優先してよい。
- UI 変更は必要最小限でよい。既存 web build/typecheck を通すための追随は行ってよい。
Escalate if:
- Browser/API から raw path/session/executable/profile 等を受けないと実装できない。
- runtime registry を scheduler/lease/remote Host protocol として固定する必要が出る。
- `00001KVTNAY20` の launch boundary を戻す/破る必要が出る。
- raw session content や private metadata を overview に出す必要がある。
Validation:
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi`
- `cd web/workspace && deno task check && deno task build`
- `git diff --check`
- 影響範囲に応じて追加 Rust tests。
Current code map:
- Primary: `crates/workspace-server/src/hosts.rs`, `crates/workspace-server/src/server.rs`
- Secondary: Workspace web API consumers under `web/workspace`, role-session/local metadata helpers if needed, `crates/client/src/spawn.rs` / `crates/client/src/ticket_role.rs` only to preserve boundaries.
- Avoid: root/original workspace operations, unrelated Panel UI completion, remote Host protocol, scheduler/queue implementation, raw session reading.
Critical risks / reviewer focus:
- registry abstraction becoming a scheduler or authority layer by accident.
- leaking raw session/private paths/unchecked metadata into overview responses.
- host/worker ids derived from user-controlled strings without bounding/validation.
- breaking the launch boundary from `00001KVTNAY20`.
- conflating runtime workspace root, process cwd, role-session claim, and local metadata hints.
Next action:
- `queued -> inprogress` を記録してから、worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry` を作成し、multi-agent-workflow で Coder/Reviewer sibling loop に進める。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-24T10:37:43Z from: queued to: inprogress reason: orchestrator_acceptance_unblocked field: state -->
## State changed
Orchestrator acceptance: queued -> inprogress
- 直前確認で `TicketShow` は state `queued`、blocking relation は 0 件。
- 以前の blocker だった `00001KVTNAY20``done` になり、orchestration branch に merge/validated 済み。
- `TicketOrchestrationPlanQuery` では過去の do_not_parallelize / waiting-capacity note と、今回の accepted plan `orch-plan-20260624-103655-3` を確認した。過去 blocker は解消済みとして扱う。
- routing decision と IntentPacket は Ticket thread に記録済み。
- これ以降に worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry` を作成し、multi-agent-workflow に接続する。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-24T10:38:50Z -->
## Implementation report
Implementation orchestration update:
- worktree-workflow に従い、implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry` と branch `work/00001KVWECEQG-worker-runtime-registry` を作成した。
- child worktree では tracked `.yoi` project records を見える状態にし、`.yoi/memory`、local/runtime/log/lock/secret-like `.yoi` paths を sparse-checkout で除外する方針にした。
- Coder Pod `yoi-coder-00001KVWECEQG-worker-registry` を sibling として起動した。write scope は child worktree に限定し、runtime workspace root `/home/hare/Projects/yoi` は startup 要件を満たすため non-recursive read のみにした。
- Coder には root/original workspace と orchestration worktree で read/write/validation/git operation を行わないよう明示した。
---
<!-- event: implementation_report author: yoi-coder-00001KVWECEQG-worker-registry at: 2026-06-24T10:57:04Z -->
## Implementation report
Implementation report:
実装概要:
- `crates/workspace-server/src/hosts.rs`
- `WorkerRuntimeRegistry` を追加。
- `WorkspaceWorkerRuntime` trait を runtime entry の抽象境界として再整理。
- 既存 local Pod metadata 読み取りを `LocalPodRuntime` adapter として registry に登録。
- `RuntimeSummary`, `RuntimeCapabilitySummary`, `WorkerCapabilitySummary`, `WorkerWorkspaceSummary`, typed `RuntimeDiagnostic` を追加。
- API caller 由来の `host_id` / `worker_id` を backend 側で bounded identifier として検証。
- raw session contents / socket path / metadata file path / raw workspace path を summary に出さないよう整理。
- metadata の `workspace_root` は runtime workspace identity との照合にだけ使い、API には `current_workspace` summary として出す。
- 他 workspace / workspace_root missing の Pod metadata は通常 worker overview から除外し、typed diagnostic のみ返す。
- 先行 Ticket `00001KVTNAY20` の low-level launch 境界用 typed request/intent/result shape は維持。
- `crates/workspace-server/src/server.rs`
- server state を `Arc<WorkerRuntimeRegistry>` に変更。
- `/api/hosts`, `/api/workers`, `/api/hosts/{host_id}/workers` を registry 経由に変更。
- `/api/runtimes` を追加し、runtime overview を返せるようにした。
- invalid runtime identifier / unknown worker / unsupported capability の API error mapping を追加。
- server tests を registry source / runtime overview / safe summary 仕様に更新。
- `crates/workspace-server/src/lib.rs`
- registry/worker/capability 用 error variant を追加。
- `crates/workspace-server/src/repositories.rs`
- shared typed diagnostic severity に合わせて更新。
- `web/workspace/src/lib/workspace-sidebar/types.ts`
- runtime / capability / worker workspace summary 型を更新。
- raw `workspace_root` / local `pod_name` 前提を削除。
- `web/workspace/src/lib/workspace-pages/WorkspacePage.svelte`
- Host/Worker overview 表示を safe summary fields に合わせて更新。
Validation:
- `cargo test -p yoi-workspace-server`: success
- `cargo check -p yoi`: success
- `cd web/workspace && deno task check`: success
- `cd web/workspace && deno task build`: success
- `git diff --check`: success
Commit:
- `9bd15507 feat: add worker runtime registry overview`
Residual risks / notes:
- remote Host protocol / scheduler / stream proxy / worker control operation は non-goal のまま、typed capability/diagnostic で unsupported/pending を返す境界に留めた。
- API response から raw workspace/session/private path は出さない方針に寄せたため、UI は workspace path ではなく `current_workspace` scope/identity summary を表示する。
- `nix build .#yoi --no-link` は Cargo/Deno validation が通過済みだが、最終統合 confidence を上げる場合は Orchestrator 側判断で実行可能。
---
<!-- event: review author: yoi-reviewer-00001KVWECEQG-worker-registry at: 2026-06-24T11:01:43Z status: request_changes -->
## Review: request changes
Review result: request_changes
確認範囲:
- child worktree `/home/hare/Projects/yoi/.worktree/00001KVWECEQG-worker-runtime-registry` のみで read-only inspection。
- Ticket `item.md` / `thread.md` / orchestration plan、`371fd7c6..HEAD` の差分、主に `crates/workspace-server/src/hosts.rs` / `server.rs` / web 型・表示を確認。
- read-only のため、テスト・ビルド・`git diff --check` は実行していない。
良い点:
- `WorkspaceWorkerRuntime` trait、`WorkerRuntimeRegistry``LocalPodRuntime` が導入され、`WorkspaceApi``Arc<WorkerRuntimeRegistry>` を保持し、`/api/hosts` / `/api/workers` / `/api/hosts/{host_id}/workers` / 新規 `/api/runtimes` が registry 経由になっている。
- `HostSummary` / `WorkerSummary` は raw `workspace_root` / metadata path / socket path / raw session を直接返さない形に整理されており、UI 側も新しい safe summary shape に追随している。
- spawn/stop/proxy/stream は unsupported/reserved の型・diagnostic に留めており、scheduler / remote host protocol / raw session ingest には踏み込んでいない。
Blockers:
1. worker detail/lookup の id 解決が opaque id 境界を満たしていない。
- `worker_id_for_pod()``pod_name` を sanitize/lowercase/truncate して `local-pod-*` を作る一方、`LocalPodRuntime::worker()``local-pod-` を strip した値をそのまま `pod_root/<pod_name>/metadata.json` のディレクトリ名として使っている。
- 実 Pod 名に大文字、`.` などの置換対象文字、truncate 対象が含まれると、`list_workers()` が返した `worker_id` から同じ Worker を lookup できない。
- Yoi の実 Pod 名には Ticket ID 由来の大文字を含むものがあり得るため現実的に壊れる。これは Ticket の「worker detail / lookup」「`pod_name` を external operation key にしない」「worker_id は backend が解決する opaque id」という要件に反する。
2. id の bounded/unique 性が full id に対して保証されていない。
- `sanitize_identifier()` は fragment を最大 120 にするが、`local-pod-` / `local-` prefix 付与後の id は `validate_backend_identifier()``MAX_IDENTIFIER_LEN = 120` を超え得る。
- sanitize による衝突(例: `foo.bar``foo-bar`)も避けられていない。将来 detail endpoint や operation routing を足した時に、一覧で返した id が lookup/validation で拒否される・別 Worker に衝突するリスクがある。
Required fixes:
- `worker_id` は返却後に確実に backend で再解決できる opaque/stable id にする。raw pod name を authority として外へ出さず、scan した metadata/dir entry から `generated_worker_id -> actual pod dir` を backend 内で照合する、または衝突しない hash/digest を含める。
- `MAX_IDENTIFIER_LEN` は prefix を含む full id に対して満たすようにし、生成側と検証側の不一致をなくす。
- 大文字 Ticket ID を含む Pod 名、`.` など sanitize される Pod 名、長い Pod 名、衝突ケースについて、`list_workers()` が返した `worker_id``registry.worker()` / `LocalPodRuntime::worker()` で引けるテストを追加する。
Non-blocking note:
- Ticket acceptance には `nix build .#yoi --no-link` も含まれている一方、coder 報告にはない。必要なら修正後に Orchestrator 判断で実施・明示すること。
---
<!-- event: implementation_report author: yoi-coder-00001KVWECEQG-worker-registry at: 2026-06-24T11:09:03Z -->
## Implementation report
Follow-up implementation report after review request_changes:
対応内容:
- `worker_id` を raw Pod dir 名から逆算する実装を廃止した。
- `LocalPodRuntime::worker()` は Pod registry を backend 側で scan し、生成済み opaque `worker_id` と実 Pod dir を照合して解決する。
- API caller が渡す `worker_id` は raw path / raw Pod name authority ではなく、backend-resolved identifier として扱う。
- `worker_id` / `host_id` の生成を bounded + collision-resistant に変更した。
- prefix を含む full id が `MAX_IDENTIFIER_LEN = 120` 以下になるよう制御。
- `sha2` digest の短縮 hex を suffix として含め、`foo.bar` / `foo-bar` や長大名 truncation による collision を避ける。
- 生成 id は既存 validation を通る形式に限定。
- focused tests を追加・更新した。
- uppercase Ticket-ID-like Pod name。
- `.` / `@` / `#` 等の sanitized char。
- `foo.bar` vs `foo-bar` collision case。
- long/truncated names。
- `list_workers()` が返す id を `registry.worker()` / `LocalPodRuntime::worker()` に渡して解決できること。
- id が bounded / validation-compatible / duplicate-free であること。
変更ファイル:
- `Cargo.lock`
- `crates/workspace-server/Cargo.toml`
- `crates/workspace-server/src/hosts.rs`
- `crates/workspace-server/src/server.rs`
Validation:
- `cargo test -p yoi-workspace-server`: success
- `cargo check -p yoi`: success
- `cd web/workspace && deno task check`: success
- `cd web/workspace && deno task build`: success
- `git diff --check`: success
Commit:
- `38d25582 fix: make worker runtime ids resolvable`
Residual risks / notes:
- `sha2.workspace = true``yoi-workspace-server` に追加したため、`Cargo.lock` の workspace-server dependency entry が更新された。
- raw session/private path leak、scheduler/remote protocol scope creep、`00001KVTNAY20` の low-level launch boundary は維持している。
---
<!-- event: review author: yoi-reviewer-00001KVWECEQG-worker-registry at: 2026-06-24T11:10:55Z status: approve -->
## Review: approve
Review result: approve
確認内容:
- child worktree のみで `9bd15507..HEAD` fix diff と必要箇所の現行実装を read-only 確認。
- ビルド/テストは read-only 指示のため再実行せず、coder 報告を参照。
判断:
- 以前の blocker 2件は解消されている。
根拠:
- `LocalPodRuntime::worker()``local-pod-` strip で raw Pod dir 名へ戻す実装をやめ、`pod_names()` で registry を scan し、各 actual Pod dir name から生成した `worker_id_for_pod()` と照合して backend 内部で解決する形になっている。これにより、大文字・記号・sanitize 対象文字を含む Pod 名でも list→lookup が成立する。
- `worker_id_for_pod()` / `host_id_for_workspace()``bounded_backend_identifier()` 経由になり、prefix を含む full id が `MAX_IDENTIFIER_LEN` 内に収まるよう body を切り詰め、SHA-256 digest suffix を付けて sanitize/truncation collision を避ける設計になっている。
- 追加テストで Ticket-like uppercase Pod 名、`.`/`-` collision、`#`/`@`、長い Pod 名、duplicate-free、validation-compatible、registry/runtime lookup roundtrip がカバーされている。
- raw metadata path / socket path / workspace root / raw session を overview API に出さない方針、registry 経由の read-only API、spawn/stop/proxy 非実装の unsupported 境界は維持されている。
Non-blocking notes:
- `worker_id` は sanitize 済み body を含むため完全な無意味 IDではないが、操作キーとしては backend 解決の opaque id になっており、今回の Ticket 意図には十分合っている。
- reported validation は通過とのことだが、reviewer では再実行していない。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-24T11:15:04Z -->
## Implementation report
Integration outcome:
- Coder `yoi-coder-00001KVWECEQG-worker-registry` が implementation branch `work/00001KVWECEQG-worker-runtime-registry` に実装を commit した。
- Reviewer `yoi-reviewer-00001KVWECEQG-worker-registry` は初回 review で `worker_id` opaque lookup / bounded unique id の blocker を指摘し、Coder が `38d25582 fix: make worker runtime ids resolvable` で修正した。
- Follow-up review は `approve``LocalPodRuntime::worker()` の backend 内部 scan/照合、bounded digest 付き id 生成、list→lookup roundtrip tests、raw path/session 非公開、unsupported capability boundary が確認された。
- Orchestrator worktree `/home/hare/Projects/yoi/.worktree/orchestration` で branch `work/00001KVWECEQG-worker-runtime-registry` を merge 済み。
- merge commit: `1251c0ca merge: 00001KVWECEQG worker runtime registry`
- implementation commit: `9bd15507 feat: add worker runtime registry overview`
- fix commit: `38d25582 fix: make worker runtime ids resolvable`
- `sha2.workspace = true` 追加により `Cargo.lock` が変わったため、Nix package cargoHash を更新した。
- package hash commit: `b975812c nix: update yoi cargo hash`
Validation in Orchestrator worktree:
- `cargo test -p yoi-workspace-server`: success
- `cargo check -p yoi`: success
- `cd web/workspace && deno task check`: success
- `cd web/workspace && deno task build`: success
- `git diff --check`: success
- `nix build .#yoi --no-link`: success after updating `package.nix` cargoHash to `sha256-rR8mrMDg1CCXb3Y5MnhUqSd0vAsI5OStFQCRIrvx8fg=`
Notes:
- Initial `nix build .#yoi --no-link` failed only because cargoHash was stale after the new dependency; this was fixed and revalidated.
- Reviewer non-blocking note: generated `worker_id` still includes a sanitized body fragment, but as an operation key it is now backend-resolved opaque id and acceptable for this Ticket.
Next action:
- Mark Ticket done after this integration/validation evidence.
- Then stop related child Pods and remove only the child implementation worktree/branch.
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-24T11:15:13Z from: inprogress to: done reason: merged_validated field: state -->
## State changed
Implementation is merged into the orchestration branch and validated.
Evidence:
- merge commit: `1251c0ca merge: 00001KVWECEQG worker runtime registry`
- package hash commit: `b975812c nix: update yoi cargo hash`
- reviewer result: approve after requested changes were fixed
- validation in `/home/hare/Projects/yoi/.worktree/orchestration` succeeded:
- `cargo test -p yoi-workspace-server`
- `cargo check -p yoi`
- `cd web/workspace && deno task check`
- `cd web/workspace && deno task build`
- `git diff --check`
- `nix build .#yoi --no-link`
Closure is not performed here; this state records implementation completion after merge/validation.
---
@@ -0,0 +1 @@
{"id":"orch-plan-20260624-120242-1","ticket_id":"00001KVWPVHFJ","kind":"accepted_plan","accepted_plan":{"summary":"Ticket `00001KVWPVHFJ` は implementation_ready。専用 worktree `/home/hare/Projects/yoi/.worktree/00001KVWPVHFJ-storage-cleanup-cli` と branch `work/00001KVWPVHFJ-storage-cleanup-cli` で、safe Pod/session storage cleanup CLI を実装する。destructive operations は dry-run/force/live refusal/path-safety を厳守する。","branch":"work/00001KVWPVHFJ-storage-cleanup-cli","worktree":"/home/hare/Projects/yoi/.worktree/00001KVWPVHFJ-storage-cleanup-cli","role_plan":"Orchestrator: routing acceptance, worktree creation, final integration/validation/cleanup. Coder: CLI/storage implementation in dedicated child worktree. Reviewer: read-only review focusing on path safety, live Pod refusal, dry-run/force semantics, and session history preservation."},"author":"yoi-orchestrator","at":"2026-06-24T12:02:42Z"}
+150
View File
@@ -0,0 +1,150 @@
---
title: 'Pod/session storage cleanup CLI を追加する'
state: 'done'
created_at: '2026-06-24T11:39:41Z'
updated_at: '2026-06-24T12:36:12Z'
assignee: null
readiness: 'implementation_ready'
risk_flags: ['pod-lifecycle', 'persistence', 'destructive-operation', 'cli-ux', 'session-history', 'authority-boundary']
queued_by: 'workspace-panel'
queued_at: '2026-06-24T12:01:42Z'
---
## User claims / request snapshot
- Pod 名を指定して Pod を消去する CLI コマンドを実装する。
- Pod から参照されていないセッションを削除するコマンドを用意する。
- 古い Pod / セッションを削除するコマンドを用意する。
- コマンド名は以下で合意済み:
- `yoi pod delete <NAME> [--force] [--dry-run]`
- `yoi pod prune [--older-than <DURATION>] [--force] [--dry-run]`
- `yoi session prune --unreferenced [--older-than <DURATION>] [--force] [--dry-run]`
## Confirmed facts / sources
- 関連 closed Ticket `00001KTJ7MACG` は fresh-start 専用 UX を実装しない方針で closed 済み。ただし resolution で、Pod 名を明示的に空ける archive/delete と storage cleanup/prune commands は必要になれば別 Ticket として扱う、と記録されている。
- `crates/pod-store/src/lib.rs` では Pod metadata authority は `{data_dir}/pods/{pod_name}/metadata.json` であり、`PodMetadataStore::delete_by_name` / `FsPodStore::delete_by_name` が既に存在する。
- `crates/session-store/src/fs_store.rs` / `crates/session-store/src/lib.rs` では session log は `{sessions_root}/{session_id}/{segment_id}.jsonl` と trace jsonl で、`FsStore``list_sessions`, `list_segments`, `lookup_session_of` を持つ。確認範囲では削除用 public API は見当たらない。
- `crates/yoi/src/main.rs` では `yoi pod ...` は現在 `pod::entrypoint::run_cli_from("yoi pod", args)` に委譲されており、Pod runtime spawn/restore 用 entrypoint として使われている。
- `crates/yoi/src/session_cli.rs` では `yoi session ...` は現在 `analyze <SESSION_JSONL_PATH> --json` のみ。
- `crates/pod/src/entrypoint.rs` では `--pod <NAME>` は name-keyed Pod state があれば restore、なければ fresh create する。sessions dir は `--store` または `manifest::paths::sessions_dir()`、Pod store は `manifest::paths::data_dir()/pods` から解決している。
- duplicate / related search では、直接同じ目的の open Ticket は見つからなかった。関連 closed Ticket は `00001KTJ7MACG`, `00001KSTRGFX0`, `00001KSXXRRC8`
## Unverified hypotheses
- live Pod protection は runtime socket / Pod registry / discovery layer と組み合わせて判定できる可能性が高いが、実装時に正確な helper/API を確認する必要がある。
- orphan session 判定は「active Pod metadata から参照されない SessionId」を基本にできそうだが、fork/segment lineage、trace file、古い closed metadata、manual session restore use case をどこまで保存対象にするかは実装時に注意する必要がある。
- `yoi pod delete` を runtime entrypoint に足すより、product CLI 側で `yoi pod delete` を捕捉するほうが安全かもしれないが、既存 `yoi pod` の意味と衝突しない設計確認が必要。
## Undecided points / open questions
- Blocking open question は現時点ではない。
- 実装中に CLI boundary が既存 `yoi pod` runtime entrypoint と衝突する場合は、Orchestrator / maintainer に escalate する。
- orphan session 判定で session lineage semantics や manual restore use case への影響が大きい場合は、削除範囲を安全側に狭めるか follow-up に分ける。
## Background
以前の fresh-start Ticket では、restore bypass 専用 path を作らず、Pod 名の衝突解消や古い履歴蓄積は Pod/session storage cleanup commands として扱う方針になった。現在も Pod metadata と session logs は durable authority が分かれており、手で `~/.yoi/pods``~/.yoi/sessions` を消すのは危険で discoverable ではない。公式 CLI と safety rails が必要。
## Requirements
- Pod 名を指定して、name-keyed Pod metadata を削除できる CLI を追加する。
- コマンド名は `yoi pod delete <NAME> [--force] [--dry-run]` とする。
- 削除後、同じ Pod 名の通常起動は既存の `missing -> spawn fresh` path に乗る。
- session logs/history は `pod delete` では削除しない。
- live/reachable Pod の metadata 削除は拒否する。
- 実装が live 判定できない場合は安全側に倒し、削除せず診断する。
- live Pod を止める操作や stop semantics の変更はこの Ticket の主目的にしない。
- orphan session cleanup CLI を追加する。
- コマンド名は `yoi session prune --unreferenced [--older-than <DURATION>] [--force] [--dry-run]` とする。
- Pod metadata の active pointer から参照されていない session/segment を候補として列挙できる。
- 実削除は `--force` が必要。
- 初期実装は dry-run / report を重視し、削除対象と根拠を表示する。
- old Pod / old session cleanup CLI を追加する。
- Pod 側は `yoi pod prune [--older-than <DURATION>] [--force] [--dry-run]` とする。
- 「古い」の判定は暗黙 default を持たせず、`--older-than <DURATION>` のような明示 threshold を要求する。
- threshold 未指定で「古い」と判断して削除しない。
- destructive operation は共通で:
- default は dry-run または削除拒否にする。
- 実削除には `--force` を要求する。
- 削除対象、保持対象、拒否理由を bounded に表示する。
- product CLI help/docs を更新し、manual data-dir surgery ではなく公式 command を案内する。
- `yoi pod` が既存 runtime entrypoint として使われている境界を壊さない。
- management subcommands を product CLI 側で捕捉するか、runtime entrypoint 側に安全に追加するかは実装判断でよいが、既存 spawn/restore options と互換的に動くこと。
## Acceptance criteria
- `yoi pod delete <NAME>` 相当の公式 CLI で stopped/restorable Pod metadata を削除できる。
- 削除後、同名 Pod 起動は existing metadata restore ではなく fresh create path になる。
- live/reachable Pod に対する delete/prune は拒否され、理由が表示される。
- `pod delete` は session logs を削除しない。
- Pod metadata から参照されていない session を dry-run で列挙でき、`--force` 指定時だけ削除できる。
- 古い Pod / session cleanup は `--older-than` 等の明示条件なしでは削除しない。
- prune/delete の出力は、削除予定/削除済み/保持/拒否をユーザーが確認できる。
- focused tests が以下を cover する:
- stopped/restorable Pod delete success。
- live Pod delete refusal。
- Pod delete 後の same-name missing/fresh behavior。
- referenced session is preserved。
- unreferenced session prune dry-run and force behavior。
- old Pod/session prune requires explicit threshold。
- CLI parsing/help。
## Binding decisions / invariants
- No silent restore bypass. Fresh same-name start は、ユーザーが明示的に metadata を削除した結果としてのみ発生する。
- Pod metadata delete の副作用として session history を自動削除しない。
- live/reachable Pod metadata を削除しない。
- 暗黙の “old” threshold を持たせない。old Pod/session cleanup では age criteria をユーザーが明示する。
- destructive deletion には明示的な `--force` を要求し、dry-run/report behavior を提供する。
- Pod metadata authority は `pod-store`、session log authority は `session-store` のままにする。
- legacy top-level resume flags や bare Pod-name inference を再導入しない。
- この Ticket では Panel/TUI を broad Pod manager にしない。CLI 実装で十分とし、Panel integration は必要なら follow-up に分ける。
## Implementation latitude
- 合意済み command spelling は維持する。ただし clap/parser 上の曖昧さを避けるための minor option shape 調整は、既存 UX を壊さない範囲で許容する。
- product CLI 側で management subcommands を捕捉するか、runtime entrypoint 側へ安全に追加するかは実装判断でよい。
- 必要なら product CLI から使う shared cleanup module を作ってよい。
- 必要なら `session-store` に削除 API を追加してよい。その場合は path safety と trace/log cleanup の tests を追加する。
- Orphan session detection は初期実装では active `PodMetadata.active.session_id` references を authority としてよい。より高度な lineage-aware retention は、referenced sessions を削除しない限り follow-up に分けてよい。
- Output は初期実装では human-readable でよい。JSON output は周辺 CLI と自然に揃えられる場合を除き follow-up でよい。
## Readiness
- readiness: implementation_ready
- risk_flags: [pod-lifecycle, persistence, destructive-operation, cli-ux, session-history, authority-boundary]
## Escalation conditions
以下の場合は実装を進める前に Orchestrator / maintainer に escalate する。
- live Pod detection を安全に拒否できるほど reliable にできない。
- orphan detection が session lineage semantics の変更を必要とする。
- Pod delete の副作用として sessions を削除する必要が出る。
- storage migration や compatibility fallback が必要になる。
- command design が `yoi pod` runtime entrypoint usage と衝突する。
- cleanup が Panel role-session/Ticket claims、worktrees、branches、Ticket state を mutate しようとする。
## Validation
- `cargo fmt --check`
- focused `cargo test` for `yoi`, `pod-store`, `session-store`, and affected Pod/discovery code
- `cargo check -p yoi -p pod -p pod-store -p session-store`
- `target/debug/yoi ticket doctor` または `yoi ticket doctor`
- `git diff --check`
Reviewer は path safety、live/refusal behavior、dry-run/force semantics、session history を accidental に削除しないことを重点確認する。
## Related work
- Related closed Ticket: `00001KTJ7MACG` — Add Pod archive and fresh-start path.
- Related closed Ticket: `00001KSTRGFX0` — Split Pod metadata into a dedicated pod-store crate.
- Related closed Ticket: `00001KSXXRRC8` — Pod tools: unify pod listing and rename restore operation.
- Files inspected:
- `crates/yoi/src/main.rs`
- `crates/yoi/src/session_cli.rs`
- `crates/pod/src/entrypoint.rs`
- `crates/pod-store/src/lib.rs`
- `crates/session-store/src/fs_store.rs`
- `crates/session-store/src/lib.rs`

Some files were not shown because too many files have changed in this diff Show More