3538 Commits
Author SHA1 Message Date
Hare 96592b1a24 fix: project Worker delete persistence diagnostics 2026-09-17 04:16:33 +09:00
Hare d70dee77a9 fix: retain Worker identity after delete persistence failure 2026-09-17 04:13:45 +09:00
Hare 1402240ef0 Merge remote-tracking branch 'refs/remotes/origin/develop' into work/T-612-persisted-worker-identity 2026-09-17 03:54:59 +09:00
Hare decd1311cb fix: recover interrupted Runtime store migrations 2026-09-17 03:47:26 +09:00
Hare c4622e9e3a refactor: separate Worker identity from execution state 2026-09-17 03:25:40 +09:00
Hare 360387c986 fix: classify file content conflicts as retryable 2026-09-17 02:54:37 +09:00
Hare bc0342b03e fix: discard legacy top-level run generation 2026-09-17 02:07:55 +09:00
Hare 10ebac142e refactor: make worker state snapshots authoritative 2026-09-17 02:02:51 +09:00
Hare d6bef5d1c7 fix: address lifecycle review findings 2026-09-17 00:36:08 +09:00
Hare 9d8e0114f5 fix: serialize runtime worker lifecycle 2026-09-17 00:14:33 +09:00
Hare 93070a3a93 fix(runtime): reject duplicate removal revisions 2026-09-16 21:04:30 +09:00
Hare d1b94625b1 fix(runtime): fence removed internal worker activity 2026-09-16 20:57:17 +09:00
Hare fbbea1bf91 fix: scope compaction suppression to one run 2026-09-16 07:27:21 +09:00
Hare a0f8ee51a4 fix: guard automatic compaction retries 2026-09-16 07:16:31 +09:00
Hare ffc1933f06 fix: separate compaction metric correlation 2026-09-16 06:34:15 +09:00
Hare b6960878a6 fix: align compaction metric schema 2026-09-16 06:24:45 +09:00
Hare fef3b6f4a0 fix: preserve compaction metric precision and CAS category 2026-09-16 06:13:32 +09:00
Hare c0a73c12ec feat: record compaction lifecycle metrics 2026-09-16 06:01:04 +09:00
Hare f40714efc2 feat: add explicit session metrics export 2026-09-16 06:00:57 +09:00
Hare 07ed908ae6 test: cover compaction restart boundaries 2026-09-16 05:14:16 +09:00
Hare cfe772ea7d fix: fence compaction commit and status 2026-09-16 04:58:38 +09:00
Hare c0fe20e8a2 fix: serialize compaction pointer commits 2026-09-16 04:41:27 +09:00
Hare df22526a0d fix: render compaction on worker status 2026-09-16 04:25:37 +09:00
Hare 1d06d4b08a fix: keep compaction lifecycle runtime-only 2026-09-16 04:19:02 +09:00
Hare 4e7a314a00 fix: make compaction activation atomic 2026-09-16 03:44:48 +09:00
Hare 016dbd7cb1 fix: preserve worker run generations across restore 2026-09-15 01:17:30 +09:00
Hare 7210d3c202 fix: reject failed worker restores before attach 2026-09-15 00:47:12 +09:00
Hare 572204b49a fix: resolve CLI connections before async runtime 2026-09-15 00:28:25 +09:00
Hare 86dd67a24c fix: skip stopped worker protocol subscriptions 2026-09-14 23:31:14 +09:00
Hare beeba1fdfc fix: migrate legacy worker snapshots 2026-09-14 22:28:01 +09:00
Hare 41b7b289d0 fix: serialize Workdir lease admission with writes 2026-09-14 20:32:21 +09:00
Hare 24237249d1 Merge remote-tracking branch 'origin/develop' into work/T-604-workdir-symlink-policy 2026-09-14 20:05:34 +09:00
Hare e448073b98 fix: fence resolved Workdir lease aliases 2026-09-14 20:05:27 +09:00
Hare c08152d069 fix: share workspace creation wire contract 2026-09-14 19:45:18 +09:00
Hare 3995561220 Merge remote-tracking branch 'refs/remotes/origin/develop' into work/T-468-remove-local-workspace-authority 2026-09-14 19:26:44 +09:00
Hare aea51caeb4 fix: resolve workspaces through backend repositories 2026-09-14 19:24:44 +09:00
Hare 3eca380bd8 Merge remote-tracking branch 'origin/develop' into work/T-604-workdir-symlink-policy 2026-09-14 19:12:17 +09:00
Hare 8a3e06bc81 feat: add selective Workdir symlink policies 2026-09-14 19:09:12 +09:00
Hare c4274c42cb fix: align plugin help with offline commands 2026-09-14 18:52:00 +09:00
Hare a61ad15767 refactor: remove ambient plugin authority 2026-09-14 18:40:42 +09:00
Hare 7f1e374fd7 fix: remove repository-local workspace selection 2026-09-14 18:31:04 +09:00
Hare e3f5445a02 fix: move workspace metadata authority to server database 2026-09-14 18:31:04 +09:00
Hare d2cb50d081 fix: fence runtime removal races and retries 2026-09-13 02:54:01 +09:00
Hare 6c609808c9 fix: use authoritative runtime removal result 2026-09-13 02:30:24 +09:00
Hare 2d4c7b383a feat: add guarded runtime removal operation 2026-09-13 02:30:15 +09:00
Hare c21ed7dff2 fix: preserve credential candidates across Workdir retries 2026-09-13 01:24:26 +09:00
Hare 448e392a0e fix: persist Workdir credential candidate snapshots 2026-09-13 01:14:39 +09:00
Hare d97c40d6af fix: reject plain HTTP repository sources 2026-09-13 01:12:01 +09:00
Hare 2d512b6be6 fix: remove stale HTTP repository access branch 2026-09-13 01:04:46 +09:00
Hare f061a95b48 fix: validate repository URI before source kind 2026-09-13 00:45:43 +09:00
Hare eefdef1bef fix: lock verified runtime public keys 2026-09-13 00:32:44 +09:00
Hare 7675f81999 fix: reject plain HTTP repository sources 2026-09-13 00:29:16 +09:00
Hare 8fb592071f fix: fence stale repository SSH probes 2026-09-13 00:27:32 +09:00
Hare 2528312142 fix: lock verified Runtime public keys in settings 2026-09-13 00:23:25 +09:00
Hare 08d7965ea8 fix: centralize repository access expiry 2026-09-13 00:20:25 +09:00
Hare e0badad91f fix: invalidate stale repository SSH probes 2026-09-13 00:17:12 +09:00
Hare f0a91ce2d8 fix: centralize repository access expiry 2026-09-13 00:11:03 +09:00
Hare 24cab83f48 test: cover repository credential rotate visibility 2026-09-13 00:05:14 +09:00
Hare 33a2b5d702 fix: unify workspace request routing 2026-09-12 23:49:13 +09:00
Hare 7f807004ad Update AGENTS.md 2026-09-12 22:47:35 +09:00
Hare 5564425488 fix: retry retained workdir removal 2026-09-12 13:30:25 +09:00
Hare 4a89c04732 fix: allow corrupted workdir removal 2026-09-12 01:43:37 +09:00
Hare ec5a403ec6 feat: replace linked worktrees with runtime clones 2026-09-12 01:43:21 +09:00
Hare f6ce1df766 feat: support workspace-managed SSH repository access 2026-09-11 22:55:06 +09:00
Hare 9d7ddcc04a fix: enforce Workspace Runtime binding lifecycle 2026-09-09 13:20:00 +09:00
Hare 3df611636b feat: complete Workspace Runtime management flow 2026-09-09 09:38:26 +09:00
Hare d0999326bd fix: use Backend audience for embedded Runtime requests 2026-09-09 09:38:26 +09:00
Hare 6fbc65476c fix: migrate standalone Worker manifest snapshots 2026-09-09 01:22:59 +09:00
Hare fcc7d79d80 feat: authorize scoped symlink paths lexically 2026-09-09 00:51:21 +09:00
Hare 18fd6a1f5e fix: restore remote Runtime management contracts 2026-09-09 00:26:04 +09:00
Hare a072562034 chore: merge develop into hare/develop 2026-09-08 13:04:10 +09:00
Hare 2b4a2bc688 fix: fail closed on missing workspace capability 2026-09-08 12:40:04 +09:00
Hare 3344d9f8b2 refactor: remove server-global runtime trust 2026-09-08 12:19:39 +09:00
Hare fae36d220d fix: complete Runtime verification cutover 2026-09-08 10:11:18 +09:00
Hare 7b6a84a550 feat: project Runtime verification state 2026-09-08 09:22:44 +09:00
Hare f29c343879 feat: verify Workspace-signed Runtime bindings 2026-09-08 08:13:58 +09:00
Hare f5e9f49a13 fix: bind Runtime WebSockets to egress policy 2026-09-08 05:29:53 +09:00
Hare 73a35599d2 fix: complete configured Runtime onboarding 2026-09-08 05:15:14 +09:00
Hare 5080d7860e fix: preserve Runtime binding trust boundaries 2026-09-08 04:54:23 +09:00
Hare 7fb1d4056c feat: add manual Runtime trust setup UI 2026-09-08 04:22:45 +09:00
Hare 243a081874 feat: add configured Workspace Runtime bindings 2026-09-08 04:22:32 +09:00
Hare 04924cf796 fix: bound Runtime issuer trust surfaces 2026-09-08 02:31:58 +09:00
Hare 8f0917b8bc docs: remove obsolete local profile override guidance 2026-09-08 02:13:26 +09:00
Hare d4ad46127a feat: add GPT-6 Astra model catalog entry 2026-09-08 02:13:26 +09:00
Hare fba5ecf54c fix: harden Workspace issuer bootstrap 2026-09-08 02:00:19 +09:00
Hare e035df9e7b feat: add Runtime Workspace issuer trust 2026-09-08 01:54:10 +09:00
Hare 3baf0b6358 feat: integrate Workspace signing identity authority 2026-09-08 00:48:45 +09:00
Hare 4de04e42b5 fix: harden identity publication recovery 2026-09-08 00:30:38 +09:00
Hare ebec98a14c feat: add Workspace signing identity authority 2026-09-07 23:52:20 +09:00
Hare f966470d33 fix: acknowledge durable submissions before run preparation 2026-09-07 21:38:19 +09:00
Hare c76ede2ab4 fix: allow slow initial input commits 2026-09-07 20:21:22 +09:00
Hare 2fd043b634 fix: expand worker creation timeout budgets 2026-09-07 19:43:26 +09:00
Hare fb6bbe9145 fix: wait for worker shutdown before deletion 2026-09-07 19:31:32 +09:00
Hare d1585d7483 fix: route worker failure logs through tracing 2026-09-07 18:14:07 +09:00
Hare 13d853217d fix: log failed worker creations to stdout 2026-09-07 04:56:54 +09:00
Hare cc27d57e4a fix: reclaim failed worker creations 2026-09-07 04:44:19 +09:00
Hare f5c5ea5a0b fix: route worker consoles through logical resources 2026-09-07 03:53:34 +09:00
Hare f1baea1705 feat: distribute latest workspace config to runtimes 2026-09-07 02:40:03 +09:00
Hare 31f7d39647 feat: add Server database migration command 2026-09-06 16:17:48 +09:00
Hare c5a834bfd2 fix: restore composable Workspace schema migrations 2026-09-06 16:17:40 +09:00
Hare 1eef9b75ee Merge branch 'develop' into hare/develop 2026-09-06 13:39:37 +09:00
Hare ba9c885f52 feat: integrate Worker state authority 2026-09-06 11:00:00 +09:00
Hare 88683a8d8f test: provide authoritative websocket snapshot 2026-09-06 10:41:20 +09:00
Hare 0c48c5dee3 fix: fail closed without worker snapshots 2026-09-06 10:33:45 +09:00
Hare 101a0acb6b fix: terminalize removed worker reservations 2026-09-06 10:32:45 +09:00
Hare 2d1956b653 fix: separate worker state from runtime lifecycle 2026-09-06 10:05:54 +09:00
Hare b7bba8b53a fix: preserve workspace deletion checkpoints 2026-09-06 10:02:18 +09:00
Hare 7b25b767f8 fix: checkpoint workspace cleanup children 2026-09-06 09:35:44 +09:00
Hare 4631b95144 fix: fence workspace deletion side effects 2026-09-06 09:21:37 +09:00
Hare 38627c498b fix: harden workspace deletion recovery 2026-09-06 08:57:54 +09:00
Hare 282a8d31b5 fix: enforce monotonic worker state projection 2026-09-06 07:56:25 +09:00
Hare ab4fb4c1ee fix: enforce workspace deletion blockers 2026-09-06 07:54:52 +09:00
Hare e3e9e83bc1 feat: add guarded workspace deletion workflow 2026-09-06 07:22:33 +09:00
Hare 4269ebec04 chore: merge develop into worker state snapshot 2026-09-06 07:17:40 +09:00
Hare e8b9adcde4 feat: add revisioned worker execution state 2026-09-06 06:54:29 +09:00
Hare 668a9062b3 fix: fence runtime detail route state 2026-09-06 06:11:23 +09:00
Hare 5fd2ccf084 fix: gate runtime key reveal and revoke confirmation 2026-09-06 05:50:29 +09:00
Hare 5686bbc9fd fix: preview runtime trust rotation fingerprint 2026-09-06 05:25:03 +09:00
Hare 2cd57a32b2 fix: align runtime trust schema and built-in controls 2026-09-06 05:17:27 +09:00
Hare 89f4f99622 Merge branch 'develop' into work/T-595-runtime-trust-key-management
# Conflicts:
#	web/workspace/deno.json
2026-09-06 05:07:26 +09:00
Hare 78d571ed14 feat: add workspace runtime trust key management 2026-09-06 05:06:37 +09:00
Hare e5332f4a7f feat: route SubWorker workdir execution through parent 2026-09-06 04:28:52 +09:00
Hare 3ed1545c3c feat: integrate worker submit queue 2026-09-06 04:24:07 +09:00
Hare 9da20d15da fix: compose passive notify with queued submit 2026-09-06 04:15:30 +09:00
Hare 052d60bd7d fix: fence late command events and spawn rollback 2026-09-06 04:10:23 +09:00
Hare 2456d6fda5 fix: preserve pending activation order on restore 2026-09-06 04:00:02 +09:00
Hare e7803d1aba fix: qualify runtime binding helper 2026-09-06 03:52:42 +09:00
Hare ca5fddf89b fix: fence recursive SubWorker shutdown 2026-09-06 03:48:54 +09:00
Hare 88fad3893e Merge commit '5e9f7a7dc3d1169118412376f16b72850aab63f2' into work/T-593-workspace-runtime-bindings
# Conflicts:
#	crates/workspace-server/src/server.rs
2026-09-06 03:46:09 +09:00
Hare 82f9b0e48c chore: merge current develop into T-588 2026-09-06 03:45:30 +09:00
Hare ddb4c1454d fix: enable running composer delivery 2026-09-06 03:32:23 +09:00
Hare 7b1cf854f2 fix: serialize scoped command teardown 2026-09-06 03:29:50 +09:00
Hare 51c6d7f835 fix: require authenticated runtime bindings 2026-09-06 03:28:19 +09:00
Hare 9d55ce0a87 fix: reconcile interrupted upload pins 2026-09-06 03:15:44 +09:00
Hare 0f8d61188a fix: order SubWorker cleanup before Workdir release 2026-09-06 03:12:55 +09:00
Hare 7363dffb9d fix: gate runtime projection broadcasts 2026-09-06 03:00:36 +09:00
Hare 8e4b7deaa4 fix: preserve authenticated submit source 2026-09-06 02:56:51 +09:00
Hare ec845cbc25 fix: fence revoked runtime bindings 2026-09-06 02:52:15 +09:00
Hare e7079e223f fix: close scoped SubWorker command authority 2026-09-06 02:37:13 +09:00
Hare dea5bd581d fix: secure submit activation handoff 2026-09-06 02:31:10 +09:00
Hare 75b85b46d1 feat: scope runtime bindings by workspace 2026-09-06 02:30:13 +09:00
Hare 68f00bc948 refactor: broker SubWorker Workdir tools through parent 2026-09-06 02:17:44 +09:00
Hare 5e9f7a7dc3 feat: add versioned runtime connection ping 2026-09-06 02:17:26 +09:00
Hare b038f022d3 fix: harden submit queue durability 2026-09-06 01:35:26 +09:00
Hare cf7515fb35 fix: keep tool overview neutral on failures 2026-09-06 01:20:39 +09:00
Hare bb4c1dfe4f docs: update flow submit protocol example 2026-09-05 23:25:25 +09:00
Hare 72b56964c3 chore: refresh T-588 onto develop 2026-09-05 23:19:52 +09:00
Hare 5b0a6691f8 fix: fence pending queue controls 2026-09-05 23:16:19 +09:00
Hare 1239c638a5 Merge branch 'develop' into hare/develop 2026-09-05 22:39:57 +09:00
Hare d2fa0787d8 fix: retain child-local bash output scope 2026-09-05 22:29:19 +09:00
Hare a7056702e8 fix: keep worker-host paths out of remote delegations 2026-09-05 22:18:46 +09:00
Hare bb56283063 feat: persist worker submit activation queue 2026-09-05 22:06:59 +09:00
Hare 130ef1f0fe fix: align Backend worker picker columns 2026-09-05 21:19:18 +09:00
Hare 724205b1df feat: create Backend workers from bare TUI launch 2026-09-05 21:19:12 +09:00
Hare 69824ea45d fix: defer resident Memory loading until first run 2026-09-05 07:52:47 +09:00
Hare 15bc299987 fix: align integrated validation contracts 2026-09-05 06:49:06 +09:00
Hare 87bdb0c6ed chore: integrate develop into hare/develop candidate 2026-09-05 04:15:47 +09:00
Hare aa96bbedbc fix: harden Memory restore and scheduling 2026-09-05 00:24:00 +09:00
Hare 4df277c81f fix: preserve Memory consolidation enablement 2026-09-04 23:53:59 +09:00
Hare 12646b6ca0 refactor: install Memory prompt contributions through Feature 2026-09-04 23:40:12 +09:00
Hare 1e674d70c2 refactor: unify Memory feature configuration authority 2026-09-04 22:55:37 +09:00
Hare 5ee77698db fix: gate workspace memory lifecycle authority 2026-09-04 20:53:27 +09:00
Hare d1f5661881 test: cover memory lifecycle outcomes 2026-09-04 20:11:29 +09:00
Hare 532d078720 test: exercise memory lifecycle background behavior 2026-09-04 19:41:04 +09:00
Hare 27e5df106f fix: complete memory lifecycle feature boundaries 2026-09-04 19:16:01 +09:00
Hare 33d98868c3 refactor: move memory extraction into lifecycle feature 2026-09-04 18:44:50 +09:00
Hare fb13e53cb5 test: cover start race at rewrite barrier 2026-09-04 16:53:35 +09:00
Hare 60a5495ccd fix: hold feature task barrier across rewrites 2026-09-04 16:34:15 +09:00
Hare f1dc90621c fix: fence feature task shutdown races 2026-09-04 16:13:35 +09:00
Hare eecb116709 fix: bound feature lifecycle execution 2026-09-04 16:04:10 +09:00
Hare 783d25b1c4 fix: project ticket blockers from current DTO shape 2026-09-04 15:47:11 +09:00
Hare af06eecfd0 feat: add executable feature lifecycle hooks 2026-09-04 14:50:44 +09:00
Hare 9bd08a3a5b fix: bound Skill API response handling 2026-09-04 13:55:13 +09:00
Hare 3d66247e11 test: include Skill API contract suite 2026-09-04 13:36:36 +09:00
Hare 4390554477 feat: share Skill REST DTO authority 2026-09-04 13:30:39 +09:00
Hare 74457db4eb Merge commit '89856eb7c3dd6b659ff952d7e3be4a8c0885bf98' into work/T-584-agen-typed-interceptor 2026-09-04 13:01:55 +09:00
Hare 5d61da481b fix: consume internal tool batch cancellation 2026-09-04 13:01:37 +09:00
Hare 89856eb7c3 chore: replace legacy SQLite migrations with baselines 2026-09-04 12:48:45 +09:00
Hare 64c268582d fix: keep runtime SSH sockets below path limits 2026-09-04 12:48:25 +09:00
Hare bb6558e7bf fix: log Worker execution restore failures 2026-09-04 12:48:15 +09:00
Hare 42d109cae3 Merge commit '4ca8ea1694d88db501c48dd4947fdbd6f2828136' into work/T-584-agen-typed-interceptor 2026-09-04 12:28:30 +09:00
Hare 9b48b1ff5d fix: terminalize parallel tool siblings on interceptor stop 2026-09-04 12:27:59 +09:00
Hare 4ca8ea1694 feat: merge REST DTO updates from develop 2026-09-03 19:09:12 +09:00
Hare c10d6c6914 fix: keep Cargo artifacts local to workdirs 2026-09-03 19:06:57 +09:00
Hare 3a94c845cf fix: harden auth response validation 2026-09-03 18:08:43 +09:00
Hare bc810beb3b feat: centralize auth REST contracts 2026-09-03 17:35:24 +09:00
Hare eac4a0c071 fix: harden interceptor lifecycle contracts 2026-09-03 16:46:02 +09:00
Hare c1dfb1add5 Merge remote-tracking branch 'refs/remotes/origin/develop' into work/T-566-memory-rest-dto 2026-09-03 16:07:53 +09:00
Hare e67f9bee08 Merge branch 'develop' into hare/develop 2026-09-03 16:00:05 +09:00
Hare 7c1d81cee9 chore: optimize build 2026-09-03 15:59:40 +09:00
Hare 5cec2eef60 feat: unify Memory REST DTO authority 2026-09-03 15:54:48 +09:00
Hare e62c7cf4f5 Merge commit '7abc6aca45a82665d33115612148536f3a5dd275' into work/T-584-agen-typed-interceptor 2026-09-03 15:47:21 +09:00
Hare 0245980ea5 refactor: finalize interceptor lifecycle boundaries 2026-09-03 15:33:15 +09:00
Hare 7abc6aca45 Merge commit '80221289935e227820aec902988a4f987273e05e' into work/T-549-provider-published-ref
# Conflicts:
#	crates/worker-runtime/src/runtime.rs
2026-09-03 15:25:34 +09:00
Hare f1bcd41ad9 fix: route embedded repository ref observation 2026-09-03 15:05:30 +09:00
Hare 8022128993 Merge branch 'refs/heads/develop' into work/T-565-worker-launch-rest-dto 2026-09-03 14:54:19 +09:00
Hare 68b1aa64e9 feat: type async interceptor failures 2026-09-03 14:46:07 +09:00
Hare f3af8f21dc fix: validate canonical Worker launch segments 2026-09-03 14:43:53 +09:00
Hare 7c056b1db8 fix: publish merge request ref diagnostic DTO 2026-09-03 14:34:09 +09:00
Hare da14c82f71 fix: expose provider ref blockers without failing reads 2026-09-03 14:25:51 +09:00
Hare 1f32c693df refactor: share Worker launch REST DTOs 2026-09-03 14:23:33 +09:00
Hare 74bfbe941e fix: detach stopped worker execution handles 2026-09-03 13:50:25 +09:00
Hare 2884c08466 fix: harden provider ref review boundaries 2026-09-03 13:49:20 +09:00
Hare 85e1ea320a feat: unify worker lifecycle restore semantics 2026-09-03 13:23:31 +09:00
Hare 7be428d8bf fix: require provider-published merge request refs 2026-09-03 12:56:17 +09:00
Hare 56798f9fb4 feat: observe repository refs through runtime providers 2026-09-03 12:56:06 +09:00
Hare 6b1b8a8846 fix: migrate legacy repository references 2026-09-03 11:09:55 +09:00
Hare 9fb1b90856 Merge remote-tracking branch 'refs/remotes/origin/hare/develop' into develop 2026-09-03 09:47:53 +09:00
Hare 30d4023475 fix: preserve blocked TUI submissions 2026-09-03 08:57:28 +09:00
Hare 70432f3d12 fix: retain attachments through TUI retry 2026-09-03 08:44:28 +09:00
Hare 7ee6c307fc fix: require exact attachment acceptance 2026-09-03 08:38:15 +09:00
Hare 36cfbbe6d2 fix: preserve attachment replay evidence 2026-09-03 08:21:11 +09:00
Hare a2e1a3d939 fix: preserve attachment lifecycle boundaries 2026-09-03 08:10:35 +09:00
Hare 9dc8d9a77a fix: fence attachment grants and lifecycle cleanup 2026-09-03 07:22:07 +09:00
Hare 3f6bb65eb1 test: align fork checkpoint regression 2026-09-03 05:55:48 +09:00
Hare 8a70f3cb26 fix: harden uploaded attachment retention and replay 2026-09-03 05:50:47 +09:00
Hare 6c5b8315a3 chore: remove generated test bindings 2026-09-03 05:07:14 +09:00
Hare 690ed0f121 fix: fence uploaded attachment lifecycle 2026-09-03 05:07:03 +09:00
Hare fd60c2b8be fix: render TUI attachment notices with supported alert level 2026-09-03 05:03:49 +09:00
Hare e27b4feb25 feat: upload client-local files from Web and TUI 2026-09-03 04:59:35 +09:00
Hare 09a33e7283 feat: add session-owned uploaded file attachments 2026-09-03 04:58:11 +09:00
Hare d87441448e test: normalize formatted workdir TypeScript 2026-09-03 03:18:09 +09:00
Hare f783f10f6e Merge branch 'work/companion' into hare/develop 2026-09-03 03:06:10 +09:00
Hare 70bdb2d723 test: align client workdir fixture with repository key 2026-09-03 03:03:32 +09:00
Hare 4c1ef04378 fix: show workspace list throughout global sidebar 2026-09-03 02:49:58 +09:00
Hare a595af133c feat: merge durable Workdir updates from develop
# Conflicts:
#	docs/README.md
#	docs/design/durable-operations.md
#	web/workspace/deno.json
2026-09-03 02:47:50 +09:00
Hare f74f3cd133 fix: reject conflicting repository import intent 2026-09-03 02:44:24 +09:00
Hare bcd4848458 Merge branch 'work/companion' into hare/develop 2026-09-03 02:39:54 +09:00
Hare fc05bf9711 fix: restore cursor after inline terminal menus 2026-09-03 02:34:27 +09:00
Hare 63ad590262 fix: remove implicit repository startup selection 2026-09-02 20:00:12 +09:00
Hare 0fd1193b6b fix: harden repository key projections 2026-09-02 19:53:18 +09:00
Hare d996822957 feat: list accessible workspaces in global sidebar 2026-09-02 19:22:45 +09:00
Hare 96349721cb feat: project repository keys across public clients 2026-09-02 19:03:55 +09:00
Hare 8344921b65 feat: add Composer input history navigation 2026-09-02 18:33:43 +09:00
Hare c97b3b7b77 feat: introduce workspace-scoped repository keys 2026-09-02 16:43:28 +09:00
Hare e00e675ed1 feat: add Worker actions to workspace sidebar 2026-09-02 16:24:29 +09:00
Hare 538da1f2b2 fix: validate workspace profile responses 2026-09-02 15:24:33 +09:00
Hare bad37ddc7d feat: centralize workspace profile DTOs 2026-09-02 15:24:12 +09:00
Hare 175eda9f29 fix: authenticate remote worker removal through workspace router 2026-09-02 14:43:49 +09:00
Hare 14c806d38f docs: define durable operation boundaries 2026-09-02 14:43:49 +09:00
Hare 925100fb82 fix: stabilize configuration editor completion 2026-09-02 14:18:51 +09:00
Hare b29b003ea3 feat: define orchestrator cleanup ownership 2026-09-02 02:26:35 +09:00
Hare faa727965b fix: fence orphan recovery claims 2026-09-02 01:59:32 +09:00
Hare d2ffbf2c40 fix: guard Workdir removal recovery ownership 2026-09-02 01:40:48 +09:00
Hare 5418fad7d7 fix: serialize Workdir removal attempts 2026-09-02 01:00:24 +09:00
Hare 510795f1c5 fix: fence Workdir removal retries 2026-09-02 00:25:21 +09:00
Hare 9e0d499987 Merge remote-tracking branch 'origin/develop' into work/T-578-durable-workdir-removal 2026-09-02 00:01:26 +09:00
Hare e96fde0632 feat: add durable Workdir removal authority 2026-09-02 00:01:16 +09:00
Hare eea79dead4 fix: bound Web UX review evidence and cleanup 2026-09-01 23:44:24 +09:00
Hare c4a3f4ba1e fix: harden Web UX capture profiles 2026-09-01 23:00:28 +09:00
Hare 4a4a01b730 feat: add repeatable Web UX inspection workbench 2026-09-01 22:48:26 +09:00
Hare a664e72488 feat: merge Composer paste handling from develop 2026-09-01 22:06:01 +09:00
Hare 21317123a4 fix: deduplicate CodeMirror completion state 2026-09-01 22:03:25 +09:00
Hare 409245cb52 fix: fence disabled Composer mutations 2026-09-01 21:00:26 +09:00
Hare 1aeb6fdb35 fix: enforce Composer read-only state 2026-09-01 20:48:16 +09:00
Hare 816fa96e07 fix: restore workers with remote workdir attachments 2026-09-01 20:41:37 +09:00
Hare 8fbe4218c6 fix: delete complete Composer selections 2026-09-01 20:34:23 +09:00
Hare 00c8df0fc9 fix: preserve exact short paste text 2026-09-01 20:19:53 +09:00
Hare c52c7ead19 feat: add atomic paste chips to Web Composer 2026-09-01 19:50:26 +09:00
Hare d1e8a827c2 fix: preserve configuration completion context 2026-09-01 18:59:16 +09:00
Hare 12d96fb03d fix: preserve short paste line endings 2026-09-01 18:49:44 +09:00
Hare 171a191873 test: run shared composer paste contract 2026-09-01 18:27:21 +09:00
Hare 47dabd8793 fix: keep short composer pastes as text 2026-09-01 18:23:23 +09:00
Hare 2bb661f1cf fix: complete paste artifact storage contract 2026-09-01 17:51:24 +09:00
Hare 04e296a4ef feat: store large paste inputs as artifacts 2026-09-01 17:26:58 +09:00
Hare 4bba227af5 fix: remove legacy resume flag 2026-09-01 16:10:59 +09:00
Hare 5cc78d63c6 fix: merge Companion repository response validation 2026-09-01 13:21:13 +09:00
Hare 323f5dc09c fix: validate repository settings wire response 2026-09-01 13:13:01 +09:00
Hare fb97edfe95 fix: validate workspace schema before owner migration 2026-09-01 12:41:14 +09:00
Hare 070f62ef12 fix: harden workspace owner migration preflight 2026-09-01 12:22:29 +09:00
Hare 981749aa3d feat: require account owners for workspaces 2026-09-01 12:10:52 +09:00
Hare e01b46b30a chore: shard Cargo build cache by workspace 2026-09-01 09:33:47 +09:00
Hare a1b659c45d chore: merge develop into hare/develop
# Conflicts:
#	crates/client/src/lib.rs
#	web/workspace/deno.json
2026-09-01 09:15:10 +09:00
Hare 37a012ef92 chore: configure shared Cargo build caching 2026-09-01 09:04:00 +09:00
Hare 4927e8a843 chore: merge current develop into workspace catalog DTO source
# Conflicts:
#	crates/workspace-api/src/lib.rs
#	crates/workspace-server/src/server.rs
#	web/workspace/deno.json
#	web/workspace/src/lib/workspace/sidebar/types.ts
2026-09-01 08:17:25 +09:00
Hare 025d6ddb47 refactor: make workspace API own workdir projections 2026-09-01 03:16:31 +09:00
Hare 01a4dfd5d3 fix: remove unused workspace API dependency 2026-09-01 02:52:11 +09:00
Hare 1d7158a0bf chore: merge current develop into T-563 source 2026-09-01 02:39:08 +09:00
Hare 9de2afbfc6 fix: validate ticket repository summaries 2026-09-01 02:37:44 +09:00
Hare 9013754a3a refactor: name the workspace catalog list response 2026-09-01 02:24:11 +09:00
Hare 21eea0b104 fix: consume shared workdir create contract 2026-09-01 02:14:57 +09:00
Hare 15e8d7365c test: run workspace DTO boundary regressions 2026-09-01 02:05:07 +09:00
Hare 88e3bf7065 fix: preserve optional workdir wire fields 2026-09-01 02:00:19 +09:00
Hare 2765138bf3 chore: merge current develop into Companion DTO work
# Conflicts:
#	web/workspace/deno.json
2026-09-01 01:59:39 +09:00
Hare 6b20ceac46 fix: validate workspace repository browser payloads 2026-09-01 01:49:38 +09:00
Hare d748274905 refactor: centralize workspace repository response DTOs 2026-09-01 01:49:25 +09:00
Hare e1578217d5 fix: preserve workdir status display contract 2026-09-01 01:45:32 +09:00
Hare 3481682cb4 feat: validate shared workdir REST contracts in web 2026-09-01 01:42:17 +09:00
Hare 996b7f2468 refactor: centralize workdir REST DTOs 2026-09-01 01:42:05 +09:00
Hare 879993b9b1 fix: accept zero-length Companion transcripts 2026-09-01 01:41:16 +09:00
Hare 6604154e3f test: cover repository access loader failures 2026-09-01 01:39:55 +09:00
Hare a9ad42a970 fix: align Companion REST DTO contracts 2026-09-01 01:29:04 +09:00
Hare 8b3d1302c6 fix: share repository access API contracts 2026-09-01 01:22:27 +09:00
Hare ac9269d6ce fix: omit local bash spill path from remote commands 2026-08-31 23:14:33 +09:00
Hare 8ffb716817 fix: preserve workdir operation error classifications 2026-08-31 23:14:23 +09:00
Hare 23f671fa48 fix: remove redundant settings overview 2026-08-31 20:09:29 +09:00
Hare d7cdcde443 fix: preserve standalone scope conflict details 2026-08-31 19:28:09 +09:00
Hare 95a81faf63 chore: merge hare/develop into companion work 2026-08-31 18:45:32 +09:00
Hare bb8bb6d099 feat: restore interactive standalone profile selection 2026-08-31 18:43:46 +09:00
Hare 310801a29b feat: add repository settings registration 2026-08-31 18:20:17 +09:00
Hare 7d09b20445 feat: add workspace repository registration API 2026-08-31 18:12:08 +09:00
Hare 456a06f194 fix: propagate browser actor to workspace routes 2026-08-31 16:55:45 +09:00
Hare 62eaefb1fa feat: spill long bash output to worker temp storage 2026-08-31 16:52:27 +09:00
Hare 10264b4019 Merge branch 'work/companion' into hare/develop 2026-08-31 15:51:36 +09:00
Hare ab9765d91d feat: refine workspace navigation chrome 2026-08-31 15:50:49 +09:00
Hare e7f4c6864f fix: make WorkerId the standalone primary identity 2026-08-31 14:37:46 +09:00
Hare bde1dea2a5 fix: require confirmation before Ctrl-X shutdown 2026-08-31 13:07:39 +09:00
Hare 13a021c480 feat: add TUI run status spinner 2026-08-31 12:46:47 +09:00
Hare a7f09fad98 fix: route standalone protocol through client transports 2026-08-31 12:11:35 +09:00
Hare 10eaf4a5fb refactor: name worker event channels by role 2026-08-31 11:21:14 +09:00
Hare bcada300e3 fix: mark standalone TUI connection ready 2026-08-31 09:44:13 +09:00
Hare 9756174676 chore: merge standalone feature into companion integration
# Conflicts:
#	crates/client/src/target.rs
#	crates/client/src/ticket_role.rs
#	crates/manifest/src/profile.rs
#	crates/tui/src/dashboard/tests.rs
#	crates/tui/src/worker_list.rs
#	crates/workspace-server/src/hosts.rs
#	crates/yoi/src/main.rs
2026-08-31 02:01:38 +09:00
Hare 6dd8461a46 chore: merge develop into companion integration
# Conflicts:
#	crates/workspace-server/src/server.rs
2026-08-31 01:51:13 +09:00
Hare 12cc2eb0e9 feat: unify workspace settings and runtime resources 2026-08-31 01:32:31 +09:00
Hare 38dd717aa6 test: lock discovery control grant separation 2026-08-30 23:07:27 +09:00
Hare 6640c902de feat: add privileged workspace worker discovery 2026-08-30 22:48:26 +09:00
Hare 583c343d08 fix: reject duplicate backend selectors 2026-08-30 21:57:50 +09:00
Hare dfc48f7a05 fix: preserve login backend selection 2026-08-30 21:48:07 +09:00
Hare cd9d854595 fix: reject standalone runtime selectors 2026-08-30 21:36:33 +09:00
Hare 766cbd17e5 refactor: centralize worker control routing 2026-08-30 21:26:29 +09:00
Hare 6df95bf981 fix: make workers help backend specific 2026-08-30 21:26:27 +09:00
Hare 6398ca0893 docs: clarify standalone resume help 2026-08-30 21:16:45 +09:00
Hare 62372a48cc fix: parse product help before target resolution 2026-08-30 21:08:08 +09:00
Hare 733632509a fix: keep product help target independent 2026-08-30 20:57:16 +09:00
Hare e1c13ec314 chore: merge final develop into T-556 2026-08-30 20:49:02 +09:00
Hare 928ff0eabe fix: isolate standalone target resolution 2026-08-30 20:45:40 +09:00
Hare 406559b13d refactor: remove legacy local client authority 2026-08-30 20:35:26 +09:00
Hare 20c16aa6fd chore: merge current develop into T-556 2026-08-30 20:32:20 +09:00
Hare 44ba5fd6d4 fix: expose canonical SubWorker control tools 2026-08-30 20:25:17 +09:00
Hare 745c6adbf2 fix: apply Grep filters to direct files 2026-08-30 20:15:01 +09:00
Hare a9aa09636f fix: preserve Workdir operation error classification 2026-08-30 20:07:46 +09:00
Hare 6945986dd1 fix: use canonical standalone session path 2026-08-30 19:53:31 +09:00
Hare 80c1f48f0e fix: allow Grep to target a file 2026-08-30 19:50:57 +09:00
Hare 31e18205f0 fix: fail closed on unknown standalone leases 2026-08-30 19:44:15 +09:00
Hare e84a9d3f9b fix: synchronize Resume busy state from protocol events 2026-08-30 14:11:12 +09:00
Hare 133feb8c76 feat: add standalone resume picker 2026-08-30 13:46:24 +09:00
Hare c5fd9c01e5 feat: persist standalone sessions for restore 2026-08-30 13:46:16 +09:00
Hare a7bf5ceac3 test: update client session snapshot fixture 2026-08-30 13:23:56 +09:00
Hare 74139aeb7e chore: merge develop into hare/develop 2026-08-30 13:19:24 +09:00
Hare 0cae4fd05c fix: retry device login code collisions 2026-08-30 12:55:12 +09:00
Hare 4b3b4fda61 feat: connect standalone host to local TUI 2026-08-30 12:40:22 +09:00
Hare adb684a6bf fix: preserve typed user input snapshots 2026-08-30 12:33:15 +09:00
Hare 8493472983 refactor: require annotated session log history 2026-08-30 12:18:44 +09:00
Hare 862eeb7add fix: route runtime workers through shared bootstrap 2026-08-30 11:54:20 +09:00
Hare 4d9b211d69 feat: add in-process standalone worker host 2026-08-30 11:29:59 +09:00
Hare ebb272324c Merge branch 'work/T-552-ticket-relation-projection' into hare/develop 2026-08-30 10:15:33 +09:00
Hare c0290512b3 fix: align Ticket relation projection 2026-08-30 10:15:23 +09:00
Hare 4ec56fe41e Merge remote-tracking branch 'origin/develop' into work/T-545-canonical-session-snapshot 2026-08-30 09:42:57 +09:00
Hare f8a7c46cf9 fix(session): preflight migration and retain timestamps 2026-08-30 09:42:46 +09:00
Hare 2bab8a9bb6 fix: distinguish Ticket activity notifications 2026-08-30 09:00:48 +09:00
Hare 89e6a6215a Merge remote-tracking branch 'origin/develop' into work/T-545-canonical-session-snapshot
# Conflicts:
#	web/workspace/src/lib/workspace/console/model.ts
2026-08-30 00:42:29 +09:00
Hare 88be87e03e feat(session): expose canonical public snapshots 2026-08-30 00:41:51 +09:00
Hare 22867faa9c test: align Profile consumers with explicit default 2026-08-30 00:37:52 +09:00
Hare 16c0fc704d feat: unify builtin Profile resolution authority 2026-08-30 00:28:58 +09:00
Hare 32fdd076bf feat: authenticate Backend target requests 2026-08-29 23:41:55 +09:00
Hare 402ae0d466 fix: replay annotated history in Web Console 2026-08-29 23:10:32 +09:00
Hare acb3c6d68b fix: separate Ticket keys from assignment identity 2026-08-29 22:52:03 +09:00
Hare 40ac83e632 chore: merge develop into hare/develop 2026-08-29 13:25:32 +09:00
Hare 58da395941 fix: merge workdir registry cleanup 2026-08-29 13:21:40 +09:00
Hare 0e3ef94c9e feat: merge web console tool call presentation 2026-08-29 13:21:35 +09:00
Hare 1f68dfc2b5 fix: group grep content output by file 2026-08-28 02:05:12 +09:00
Hare 84977a464c feat: improve web console tool call presentation 2026-08-28 00:05:00 +09:00
Hare 62ada5eaa4 fix: bound safe-boundary pause escalation 2026-08-27 23:57:20 +09:00
Hare f5ff0b7c13 fix: confirm bash cancellation cleanup 2026-08-27 23:01:06 +09:00
Hare 3337cafcdf feat: own cancellable tool execution lifecycle 2026-08-27 23:01:00 +09:00
Hare e87784118b fix: preserve resumable paused tool calls 2026-08-27 21:48:59 +09:00
Hare 40fada28ea fix: preserve confirmed output on interceptor abort 2026-08-27 21:30:04 +09:00
Hare 58cc94d4b7 fix: terminalize interrupted tool executions 2026-08-27 20:54:13 +09:00
Hare ccabea59c9 fix: terminalize parallel tool outputs on completion 2026-08-27 19:16:49 +09:00
Hare 8cc1dc042d fix: remove deleted workdirs from registry 2026-08-27 18:36:17 +09:00
Hare 183c37446e fix: fence running snapshots on input commit 2026-08-27 15:42:20 +09:00
Hare 7aa06afc45 chore: preserve reviewed source lineage
# Conflicts:
#	crates/agen/README.md
#	crates/agen/examples/engine_cancel_demo.rs
#	crates/agen/examples/engine_cli.rs
#	crates/agen/src/engine.rs
#	crates/agen/tests/annotated_history_test.rs
#	crates/agen/tests/callback_test.rs
#	crates/agen/tests/engine_fixtures.rs
#	crates/agen/tests/engine_state_test.rs
#	crates/agen/tests/parallel_execution_test.rs
#	crates/agen/tests/reasoning_round_trip_test.rs
#	crates/session-store/tests/session_test.rs
#	crates/worker/src/worker.rs
2026-08-27 15:13:27 +09:00
Hare 1515a2fb86 fix: reconcile typed history with run exits 2026-08-27 15:12:05 +09:00
Hare ec798c58d7 fix: preserve annotated history through rewind 2026-08-27 14:54:24 +09:00
Hare e365189276 feat: add provenance-aware worker history 2026-08-27 14:54:24 +09:00
Hare 116d610ad0 fix: project Ticket mutation outputs to human keys 2026-08-27 14:18:48 +09:00
Hare 75c570962d Merge commit '7edc588202dfbfd4c834f677f510ddda7f3d6451' into work/00001M10HW6BV-model-facing-resource-projection 2026-08-27 13:46:19 +09:00
Hare cae8ac1799 fix: allow missing Objective query snippets 2026-08-27 13:46:10 +09:00
Hare 917cc222a3 fix: resolve relation summaries to Ticket keys 2026-08-27 13:22:08 +09:00
Hare 7edc588202 chore: refresh T-528 after T-541 2026-08-27 13:09:44 +09:00
Hare c83461508b Merge commit '21b3dd1da1b1bbf18799a0623bf67dbe6266067c' into work/00001M10HW6BV-model-facing-resource-projection 2026-08-27 13:09:15 +09:00
Hare 651d64f34d Merge branch 'work/00001M10N3Z0H-ticket-detail-route-sync' into hare/develop 2026-08-27 12:57:52 +09:00
Hare b98d4b59f5 fix: synchronize reused ticket detail routes 2026-08-27 12:55:01 +09:00
Hare 374449e663 feat: add provenance-aware worker history 2026-08-27 12:51:01 +09:00
Hare 4c876a201b fix: validate projected resource keys canonically 2026-08-27 12:49:59 +09:00
Hare 21b3dd1da1 Merge commit '0496cd907bc7bb96e9aa1c6d385bedb616bf3233' into work/00001M10FJVA2-orchestrator-queue-notice 2026-08-27 12:46:27 +09:00
Hare 5ca0ea9228 fix: sanitize orchestrator queue attention 2026-08-27 12:46:10 +09:00
Hare d5c3a68a37 fix: use Ticket resource keys in handoffs 2026-08-27 12:45:08 +09:00
Hare 2b33b9158d chore: refresh T-528 against develop 2026-08-27 12:45:01 +09:00
Hare b31642e284 feat: project Ticket and Objective human references 2026-08-27 12:39:28 +09:00
Hare 3a7a3307ef fix: map internal worker terminal lifecycles 2026-08-27 12:27:55 +09:00
Hare 0496cd907b fix: use Ticket resource keys in handoffs 2026-08-27 12:24:19 +09:00
Hare 975b4fa700 feat: add typed engine run exits 2026-08-27 11:42:49 +09:00
Hare 060f280fdf fix: allow parent commands during write delegation 2026-08-27 11:27:27 +09:00
Hare 7aaf189247 fix: scope delegated commands by cwd 2026-08-27 11:11:06 +09:00
Hare df6d99c07d Merge branch 'develop' into hare/develop 2026-08-27 09:21:58 +09:00
Hare 63306cf017 feat: integrate runtime Git cache materialization 2026-08-27 08:30:38 +09:00
Hare 08be5e85e4 fix: preserve command sessions across access refresh 2026-08-27 08:09:22 +09:00
Hare 9843510e1f fix: remove conflicting coder worker control provider 2026-08-26 23:52:25 +09:00
Hare 83bda3dfb2 fix: restore companion subworker control 2026-08-26 22:06:34 +09:00
Hare 0ab15aa227 chore: merge hare/develop into develop 2026-08-26 19:44:31 +09:00
Hare 29c2fb8e06 fix: refresh repository access for worker workdirs 2026-08-26 19:27:10 +09:00
Hare 4ebc465e8d fix: constrain repository SSH commands to authorized source 2026-08-26 19:02:20 +09:00
Hare 4b132a21e9 fix: bind repository SSH secrets to one-shot resources 2026-08-26 18:28:22 +09:00
Hare b644971d45 fix: preauthorize repository access without persisting secrets 2026-08-26 17:23:43 +09:00
Hare df34533765 fix: broker read-only repository SSH operations 2026-08-26 16:48:37 +09:00
Hare 6f4efb36bb fix: order optional feature service bindings 2026-08-26 16:28:54 +09:00
Hare 108d5b14d7 fix: withhold write-capable credentials from read-only sessions 2026-08-26 16:23:48 +09:00
Hare f633b86b35 chore: integrate current develop for review 2026-08-26 16:12:48 +09:00
Hare 1873e18f8e fix: enforce attachment access transitions 2026-08-26 16:10:39 +09:00
Hare 3cdcbb47bf fix: preserve selector retries and workdir observations 2026-08-26 16:05:14 +09:00
Hare aaa9c7987c fix: reject ambiguous feature service providers 2026-08-26 16:01:06 +09:00
Hare 048007a042 test: complete tool output fixture 2026-08-26 15:47:34 +09:00
Hare cb35b40b9d feat: plan feature service installation 2026-08-26 15:47:27 +09:00
Hare 3b71fe03b4 fix: include merge request status regression in web tests 2026-08-26 15:27:19 +09:00
Hare 471db64bcc fix: preserve repository access across retries 2026-08-26 15:21:52 +09:00
Hare 5e2234763c fix: distinguish completed review requests in merge request status 2026-08-26 15:20:13 +09:00
Hare 1d140be715 feat: align merge request review workflow with selector refs 2026-08-26 15:03:26 +09:00
Hare ffb2a34ae5 fix: enforce repository access and cache boundaries 2026-08-26 14:39:37 +09:00
Hare ccf7de1a55 fix: preserve run budget across segment forks 2026-08-26 14:13:43 +09:00
Hare ccf3c80d29 fix: clear abandoned run budget before compaction 2026-08-26 14:03:07 +09:00
Hare 3a3c89e0b4 feat: materialize repositories through runtime Git cache 2026-08-26 13:54:25 +09:00
Hare 17c629136a fix: scope max turns to logical runs 2026-08-26 13:47:35 +09:00
Hare 52a5c4141f chore: merge current develop into Ticket source 2026-08-26 12:24:14 +09:00
Hare c9ba27c333 fix: update RepositoryRecord test URI access 2026-08-26 11:50:41 +09:00
Hare 46f6e2c58b fix: complete Repository access management contracts 2026-08-26 11:38:23 +09:00
Hare d1f47e5a22 fix: align Repository access DCDL fields 2026-08-26 11:06:19 +09:00
Hare 65de94bad3 feat: expose compaction as an internal worker 2026-08-26 10:39:43 +09:00
Hare 4e935c6203 test: refresh clean-build fixtures and assertions 2026-08-26 10:16:18 +09:00
Hare eac07cf5a8 fix: provide subworker control service 2026-08-26 10:16:10 +09:00
Hare 260259d461 fix: return ticket queue outcomes to web clients 2026-08-26 10:16:03 +09:00
Hare a9fb092834 feat: add Repository access settings UI 2026-08-26 08:51:23 +09:00
Hare 3a21a68792 feat: add Workspace Repository SSH secret authority 2026-08-26 08:51:15 +09:00
Hare 9d572d18bc fix: accept reserved workers during initial flow resolution 2026-08-26 07:52:04 +09:00
Hare f7852e8034 fix: remove misleading runtime capability projections 2026-08-26 06:19:33 +09:00
Hare 8c075de147 fix: allow remote runtime workdir creation 2026-08-26 05:13:21 +09:00
Hare 864367f4f5 fix: remove repository-local server configuration paths 2026-08-26 03:56:35 +09:00
Hare 33db2ea7f4 fix: unify browser origin configuration 2026-08-26 02:37:14 +09:00
Hare 8396d09891 fix: limit coder ticket comments to handoffs 2026-08-25 13:21:47 +09:00
Hare bf7171924d feat: integrate dependency queue planning 2026-08-25 13:08:09 +09:00
Hare 097c363fbc fix: block internal dependency cycles in projections 2026-08-25 12:54:47 +09:00
Hare 7dd8809e38 fix: fail closed without queue target authority 2026-08-25 12:44:03 +09:00
Hare 1749757036 fix: align queue eligibility with target authority 2026-08-25 12:24:31 +09:00
Hare 5857e6121c fix: preserve dependency queue atomicity 2026-08-25 12:05:43 +09:00
Hare a41147916b fix: confirm queue closures across clients 2026-08-25 11:51:40 +09:00
Hare cabe38db1d fix: align queue projections with dependency closure 2026-08-25 11:19:27 +09:00
Hare f079479160 feat: queue ready dependency closures atomically 2026-08-25 10:53:31 +09:00
Hare 87e160a01a test: track current migration version in dry run 2026-08-25 10:29:48 +09:00
Hare f94d829bf8 feat: integrate hare/develop 2026-08-25 10:29:41 +09:00
Hare 9a05bfa0c3 feat: allow ticket implementation cancellation 2026-08-25 09:52:21 +09:00
Hare c1d46859a3 fix: block cleanup for assigned workers 2026-08-25 09:39:33 +09:00
Hare 87ecbcb113 fix: validate non-worker ticket assignments 2026-08-25 08:09:31 +09:00
Hare 1fb2949561 fix: give reviewer write-scoped command tools 2026-08-25 04:45:17 +09:00
Hare 11be777fc0 fix: verify signed Workspace query targets 2026-08-25 01:12:24 +09:00
Hare ff94161fc0 test: authenticate workdir route fixtures 2026-08-25 00:54:28 +09:00
Hare c2ab9a950f feat: integrate Workspace API authorization 2026-08-25 00:54:13 +09:00
Hare 8e26a0f5a8 chore: merge latest develop into Ticket source
# Conflicts:
#	crates/workspace-server/src/store.rs
2026-08-24 23:24:12 +09:00
Hare d1c15ee295 fix: protect direct auth mutation routes 2026-08-24 14:58:34 +09:00
Hare 00a96234c6 fix: enforce CSRF on server mutations 2026-08-24 14:50:15 +09:00
Hare fc3b663510 fix: authorize Runtime profile archive fetches 2026-08-24 14:39:16 +09:00
Hare e4e045d059 fix: preserve Workdir provider rejection codes 2026-08-24 14:30:34 +09:00
Hare 436feaf33d fix: close remaining Workspace auth gaps 2026-08-24 14:28:44 +09:00
Hare 29f450b962 fix: map missing default Runtime to bad request 2026-08-24 14:16:38 +09:00
Hare db343893c8 fix: secure HTTPS browser session cookies 2026-08-24 14:11:51 +09:00
Hare 554906ec02 fix: treat legacy Runtime config as unconfigured 2026-08-24 14:07:42 +09:00
Hare 18c37f4842 fix: persist Workdir Runtime failure classifications 2026-08-24 13:59:52 +09:00
Hare 83382b824a fix: protect legacy Workspace API routes 2026-08-24 13:56:46 +09:00
Hare 6203316aa1 fix: defer local repository validation to runtimes 2026-08-24 13:46:02 +09:00
Hare d57b4d1d5e fix: align ticket queue projection test 2026-08-24 13:42:39 +09:00
Hare 379ae214fc feat: queue tickets with dependency context 2026-08-24 13:40:33 +09:00
Hare 163a403636 feat: support typed remote repository sources 2026-08-24 13:35:19 +09:00
Hare 53edaadc3a feat: authenticate Workspace API requests 2026-08-24 13:32:55 +09:00
Hare 3c2664c3ce feat: sign Runtime workspace requests 2026-08-24 13:32:49 +09:00
Hare d9048954a5 fix: reject unsupported Workdir runtimes before delegation 2026-08-24 13:24:59 +09:00
Hare 4f84dfd73f feat: resolve default Runtime for Workdir creation 2026-08-24 13:15:18 +09:00
Hare d69c367285 feat: prepare agen crates for publication 2026-08-23 03:41:51 +09:00
Hare aa8dd4f89e test: align workspace server fixtures with current authority 2026-08-23 02:19:36 +09:00
Hare b12e0785e2 fix: migration error 2026-08-23 02:10:03 +09:00
Hare 24291a4545 fix: resolve ticket assignment target integration 2026-08-23 00:23:38 +09:00
Hare 92d073ff36 fix: accept queued lifecycle assignments 2026-08-22 23:58:55 +09:00
Hare bc57ef38c1 fix: guard state change event transitions 2026-08-22 23:48:11 +09:00
Hare ae8a0316d8 fix: guard state field workflow transitions 2026-08-22 23:41:35 +09:00
Hare 2cfbb1caea fix: make role assignment retries idempotent 2026-08-22 23:34:52 +09:00
Hare 703398bd2c fix: reject invalid coder principals safely 2026-08-22 23:27:27 +09:00
Hare 10c80ae514 fix: close ticket start authority gaps 2026-08-22 23:17:44 +09:00
Hare 285763f4ae fix: enforce ticket assignment mutation fences 2026-08-22 23:06:28 +09:00
Hare 8030045602 feat: generalize ticket role assignments 2026-08-22 22:48:56 +09:00
Hare 8c85b93e7d feat: integrate ticket notify delivery warnings 2026-08-22 21:59:21 +09:00
Hare 4017992c7d fix: share ticket query route contracts 2026-08-22 20:20:38 +09:00
Hare 9dc6d8f144 fix: preserve backend product authority boundaries 2026-08-22 20:03:27 +09:00
Hare 779ced82b1 fix: allow workspace clients through ticket REST operations 2026-08-22 19:43:18 +09:00
Hare 30e4985f9a feat: route product commands through backend targets 2026-08-22 19:16:14 +09:00
Hare 1a1e3c286f feat: integrate workspace memory settings authority 2026-08-22 00:34:30 +09:00
Hare 71c906e04d fix: reject legacy workspace worker restore 2026-08-22 00:28:33 +09:00
Hare e6bfb27fa9 fix: make workdir command completion stateful 2026-08-22 00:20:45 +09:00
Hare 2a3ece0364 fix: validate workspace memory settings authority 2026-08-21 22:16:41 +09:00
Hare 61d174b174 fix: enforce workspace memory settings contract 2026-08-21 22:05:53 +09:00
Hare c4814115de feat: bind memory language to workspace settings 2026-08-21 21:50:12 +09:00
Hare f84377b2fe feat: integrate ticket notify delivery warnings 2026-08-21 20:32:26 +09:00
Hare 19f506f8bc fix: restore reviewer ticket and merge request reads 2026-08-21 20:23:26 +09:00
Hare 0a9d09b958 test: cover complete notification delivery failure 2026-08-21 19:19:26 +09:00
Hare 83c6d290b4 fix: complete notification warning context 2026-08-21 19:11:16 +09:00
Hare 831db34acf fix: surface failed Ticket notification delivery 2026-08-21 19:05:53 +09:00
Hare 4a276b0af0 fix: scope console and workspace shell widths 2026-08-21 18:34:40 +09:00
Hare c2b82a2591 fix: contain ticket operation rail layout 2026-08-21 18:30:38 +09:00
Hare 99daaf31b6 fix: widen workspace shell to 920px 2026-08-21 18:08:53 +09:00
Hare 94e51ea6d1 fix: clean up console task summary 2026-08-21 18:06:55 +09:00
Hare f2d2ab0102 fix: center workspace shell at 720px 2026-08-21 18:04:48 +09:00
Hare 6f42f23d2b fix: enlarge overview activity summaries 2026-08-21 17:40:33 +09:00
Hare 8f54fa2a00 fix: remove console composer overhang 2026-08-21 17:37:37 +09:00
Hare c110965911 fix: remove redundant console chrome 2026-08-21 17:26:47 +09:00
Hare 2a48dfc41a fix: set bash output to compact terminal sizing 2026-08-21 15:22:52 +09:00
Hare 0451142d41 fix: align bash sizing with xterm defaults 2026-08-21 15:18:32 +09:00
Hare 65f18b0cdb fix: match bash output to terminal cell sizing 2026-08-21 15:11:15 +09:00
Hare ea31c7ca81 fix: tighten bash terminal line spacing 2026-08-21 13:46:52 +09:00
Hare dd47dba5b0 feat: render bash ANSI colors in web console 2026-08-21 13:36:03 +09:00
Hare cbedc76d06 fix: simplify live bash output presentation 2026-08-21 13:12:50 +09:00
Hare a4aa1a1848 fix: preserve command telemetry through workdir delegation 2026-08-21 13:01:44 +09:00
Hare ee8ee360ef fix: share workspace runtime worker contracts 2026-08-21 12:35:58 +09:00
Hare 72cae33ea6 chore: merge develop into work/companion 2026-08-21 11:38:47 +09:00
Hare 0cd5ca11cc feat: expose merge requests as workspace resources 2026-08-21 11:31:45 +09:00
Hare ccb9d03865 feat: add workspace switcher menu 2026-08-21 11:30:23 +09:00
Hare 41cd2d044a fix: verify resource key schema drift 2026-08-21 10:32:25 +09:00
Hare 85d1815dcf feat: adopt Workspace resource keys 2026-08-21 10:20:32 +09:00
Hare 9989aed916 Merge branch 'work/companion' into develop 2026-08-21 07:21:09 +09:00
Hare 3f2ba9df47 fix: migration error 2026-08-21 07:20:48 +09:00
Hare cd9f0f009e chore: merge develop into work/companion
# Conflicts:
#	crates/tui/src/app.rs
2026-08-21 07:18:07 +09:00
Hare b49abce798 fix: locate multiline Console Tasks source 2026-08-21 07:13:46 +09:00
Hare 51b381a701 feat: switch Web SubWorker views 2026-08-21 07:12:37 +09:00
Hare bea121ade0 feat: switch TUI SubWorker views 2026-08-21 07:12:20 +09:00
Hare 18112d29a6 feat: project SubWorker activity in sidebar 2026-08-21 07:12:04 +09:00
Hare 8bedfcda84 fix: remove caller worker revision fence 2026-08-21 07:11:45 +09:00
Hare 402543d617 Merge remote-tracking branch 'origin/develop' into develop 2026-08-21 05:37:57 +09:00
Hare a21ef31ee7 fix: make authentication workspace independent 2026-08-21 05:04:17 +09:00
Hare e8c159247a fix: serve chooser before workspace creation 2026-08-21 04:51:44 +09:00
Hare 5dd9392575 fix: serve workspace chooser at root 2026-08-21 04:45:05 +09:00
Hare da2296bc9c fix: restore workspace routing contracts 2026-08-21 04:36:40 +09:00
Hare 8e4f35eb3f fix: update TUI command snapshot fixture 2026-08-21 04:21:18 +09:00
Hare 9917c09b19 feat: integrate workspace switching 2026-08-21 04:18:32 +09:00
Hare 4445501f6c fix: recover command snapshots after provider lag 2026-08-21 04:09:42 +09:00
Hare 6fe36f3e46 feat: integrate command output streaming 2026-08-21 03:54:47 +09:00
Hare cfb173c570 fix: preserve command stream boundaries and lifecycle evidence 2026-08-21 03:49:45 +09:00
Hare ad729af592 feat: add web workspace chooser and creation 2026-08-20 18:34:28 +09:00
Hare 17abe1c40c feat: add scoped TUI workspace selection 2026-08-20 18:34:18 +09:00
Hare 4b8dc302ee fix: fence workspace bootstrap and resource routing 2026-08-20 17:52:23 +09:00
Hare cf2e74404d feat: dispatch registered workspaces independently 2026-08-20 17:28:14 +09:00
Hare a0e161c653 feat: integrate workspace-scoped resource references 2026-08-20 16:10:42 +09:00
Hare 614157424f fix: remove cargo check warnings 2026-08-20 15:16:29 +09:00
Hare f5f80fcd48 feat: add web console modes and run status 2026-08-20 15:02:24 +09:00
Hare 7dd4539f50 feat: add compact TUI activity overview 2026-08-20 15:02:03 +09:00
Hare e66876249e fix: remove redundant system reminder wrappers 2026-08-20 15:01:43 +09:00
Hare d39eb43419 fix: track retained assignment parents 2026-08-20 11:38:13 +09:00
Hare 674b897321 fix: validate assignment runtime snapshots 2026-08-20 11:28:41 +09:00
Hare d7e54ed181 fix: preserve retained assignment history 2026-08-20 11:21:31 +09:00
Hare 3e833b5295 fix: finalize stopped subworker sessions 2026-08-20 11:19:02 +09:00
Hare 9194f0a1ba test: complete ticket reference fixture 2026-08-20 11:19:02 +09:00
Hare 6945b7b3c3 fix: bind assignment events to tickets 2026-08-20 11:14:33 +09:00
Hare 560226dea2 fix: enforce assignment workspace references 2026-08-20 11:06:31 +09:00
Hare 4583b512b3 docs: add workspace schema migration runbook 2026-08-20 10:43:05 +09:00
Hare 223a6ed011 feat: enforce workspace-scoped resource references 2026-08-20 10:42:57 +09:00
Hare a82234a75e docs: report subworker feature installation failure 2026-08-20 10:33:12 +09:00
Hare 92594488da feat: stream workdir command output to consoles 2026-08-20 10:32:58 +09:00
Hare 2315c69f0a fix(worker-runtime): complete embedded store identity migration 2026-08-20 08:44:09 +09:00
Hare 9d003a5c98 fix: exclude stale worker sockets from migration 2026-08-20 07:51:34 +09:00
Hare 53ec914a52 docs: report subworker control dependency failure 2026-08-20 07:21:03 +09:00
Hare d052cedc7d fix: make worker identity migrations dry-runnable 2026-08-20 07:21:03 +09:00
Hare de72afd9a1 fix: clear stale internal worker in-flight state 2026-08-20 06:18:21 +09:00
Hare 80ffff642f fix: resolve ticket keys for nested merge request routes 2026-08-20 02:39:52 +09:00
Hare 97960d4e3f fix: resolve human keys at resource boundaries 2026-08-20 02:30:09 +09:00
Hare a96038d79f feat: add canonical human-key resource routes 2026-08-20 02:17:21 +09:00
Hare 1ca36d6b66 feat: add workspace resource human keys 2026-08-20 02:17:00 +09:00
Hare bb8eda379f fix: migrate all persisted Workspace Worker references 2026-08-20 00:49:21 +09:00
Hare 2858e8ceba fix: align Workdir occupancy UI with stable worker IDs 2026-08-19 23:15:34 +09:00
Hare e35b5797a3 feat: promote workers to Workspace-owned UUIDv7 identities 2026-08-19 23:04:02 +09:00
Hare 25baeedc03 Merge branch 'work/companion' into develop 2026-08-19 21:22:04 +09:00
Hare 17d81e29cc chore: merge authoritative develop into ticket source 2026-08-19 12:05:54 +09:00
Hare 08bce5b630 chore: merge current develop into ticket source 2026-08-19 11:54:35 +09:00
Hare 84f1b229ba fix: validate remote workdir grants before leasing 2026-08-19 11:42:49 +09:00
Hare 856ea7119a fix: clarify orchestrator branch integration 2026-08-19 11:24:55 +09:00
Hare 5f2798458e fix: align delegated paths with provider resolution 2026-08-19 11:22:56 +09:00
Hare af3decce51 fix: preserve nested workdir delegation chains 2026-08-19 11:04:40 +09:00
Hare 1cb6cd4e98 fix: enforce delegated workdir scope after resolution 2026-08-19 10:43:37 +09:00
Hare 21bd089a23 feat: delegate subworker access through workdir sessions 2026-08-19 09:45:56 +09:00
Hare 88f463e633 feat: add scoped workdir delegation sessions 2026-08-19 09:45:49 +09:00
Hare ce62e09919 feat: stream internal subworker output through parent 2026-08-19 09:24:14 +09:00
Hare fe74d7c4b8 chore: update ticket source from develop 2026-08-19 08:38:13 +09:00
Hare 73902b03b6 fix: preserve live errors across segment rotation 2026-08-19 08:29:36 +09:00
Hare 9aeaa52bdb fix: retain worker run errors in console history 2026-08-19 08:12:55 +09:00
Hare 89ee5e48a5 fix: use active prompt projection route 2026-08-19 07:03:15 +09:00
Hare 5b5396599d fix: restore pending workspace prompt catalog 2026-08-19 06:52:32 +09:00
Hare 1e33b2945c fix: requeue uncommitted notifications 2026-08-19 06:45:45 +09:00
Hare 50b05051bb feat: persist prompt render provenance 2026-08-19 06:40:29 +09:00
Hare 4208b6228e fix: fence prompt projection freshness 2026-08-19 06:22:41 +09:00
Hare bb558bad2b fix: share compiled prompt projection cache 2026-08-19 06:19:31 +09:00
Hare fcc7c49ff1 fix: enforce prompt projection workspace scope 2026-08-19 06:07:24 +09:00
Hare fb5f49d2a2 test: align pending orchestrator restore contract 2026-08-19 06:05:43 +09:00
Hare 82eaa986d8 fix: scope prompt projection cache fills 2026-08-19 06:03:18 +09:00
Hare 17d6789b41 feat: propagate workspace prompt revisions 2026-08-19 06:01:03 +09:00
Hare d24d50cac9 feat: refresh prompts at operation boundaries 2026-08-19 06:00:57 +09:00
Hare 44b3c78761 fix: reject unrecoverable pending worker restore 2026-08-19 05:02:50 +09:00
Hare 08daf782b9 fix: accept queued tickets after coder spawn 2026-08-19 04:55:29 +09:00
Hare d7e35ea9ee fix: keep restore independent of live prompts 2026-08-19 04:41:38 +09:00
Hare 39aa465a51 fix: keep config bundles transport-only 2026-08-19 04:36:38 +09:00
Hare 382b5e57f2 fix: carry prompt projection source identity 2026-08-19 04:30:00 +09:00
Hare 0d011ea0cd fix: fence prompt cache source revisions 2026-08-19 04:25:13 +09:00
Hare b740b2d1e2 fix: remove config bundle restore dependency 2026-08-19 04:23:37 +09:00
Hare c97bde9ee0 fix: isolate workspace profile launch projections 2026-08-18 22:47:34 +09:00
Hare bb742e253d feat: allow companion to manage workdirs 2026-08-18 10:47:31 +09:00
Hare a10507c54f merge: integrate orchestration
# Conflicts:
#	crates/flow/src/builtin.rs
#	crates/manifest/src/profile.rs
#	crates/worker/src/prompt/catalog.rs
#	crates/worker/src/prompt/system.rs
#	resources/flows/coder-review.dcdl
#	resources/prompts/role/coder.md
#	resources/prompts/role/orchestrator.md
#	web/workspace/src/lib/workspace/console/worker-console.ui.test.ts
#	web/workspace/src/lib/workspace/styles/tickets.css
#	web/workspace/src/routes/w/[workspaceId]/tickets/+page.svelte
#	web/workspace/src/routes/w/[workspaceId]/tickets/+page.ts
2026-08-18 09:55:27 +09:00
Hare 6a607ccbed feat: integrate bounded workspace query pagination 2026-08-18 09:03:59 +09:00
Hare 4ac79b3665 fix: publish coder revisions before review 2026-08-18 08:14:58 +09:00
Hare a4fdf9cc45 docs: record test code quality audit 2026-08-18 08:14:58 +09:00
Hare 981c422122 fix: preserve completed merge request replays 2026-08-18 08:14:43 +09:00
Hare ab0f57c00a fix: include incoming Ticket relation filters 2026-08-18 08:14:05 +09:00
Hare b723c64fa1 fix: preserve accepted Ticket query filters 2026-08-18 08:06:21 +09:00
Hare f86ae6d52f feat: connect selector-based merge request flow 2026-08-18 08:06:02 +09:00
Hare 9a548d2b5e fix: require observed merge target completion 2026-08-18 08:05:57 +09:00
Hare 4e738ac5eb fix: query authoritative merge request review events 2026-08-18 07:57:20 +09:00
Hare a6f3e30652 fix: preserve Ticket lane order across pages 2026-08-18 07:50:42 +09:00
Hare 6ca5dfbe11 feat: paginate Ticket board lanes independently 2026-08-18 03:08:39 +09:00
Hare bc835b8503 feat: add bounded Ticket and Objective query pages 2026-08-18 03:08:30 +09:00
Hare 46767daf49 test: remove duplicated resource content assertions 2026-08-18 02:20:32 +09:00
Hare 99170d47ab fix: delegate queued tickets through merge 2026-08-18 02:20:32 +09:00
Hare 796fa2ee85 feat: integrate ticket ready target guards 2026-08-18 01:12:32 +09:00
Hare 200c24bc00 fix: avoid unbounded ticket board queries 2026-08-18 00:46:31 +09:00
Hare 0a2b24bf5e fix: ignore transient vite config bundles 2026-08-17 23:33:12 +09:00
Hare eec2be87ad feat: paginate ticket workflow lanes 2026-08-17 23:33:12 +09:00
Hare 71cd58f868 feat: scope merge request tools by profile flags 2026-08-17 22:53:09 +09:00
Hare 58ed04ac59 Merge branch 'orchestration' into develop 2026-08-17 21:50:21 +09:00
Hare c6a476d65d feat: derive ticket readiness from merge requests 2026-08-17 21:26:42 +09:00
Hare 4c31ea2228 fix: check queue state before local readiness 2026-08-17 14:59:24 +09:00
Hare f9e5fca67d fix: preserve intake and companion ticket workflows 2026-08-17 14:44:59 +09:00
Hare a2cd860199 feat: gate ticket readiness on validated targets 2026-08-17 14:23:47 +09:00
Hare f5fdce2d07 fix: migrate legacy merge request schema marker 2026-08-17 11:54:24 +09:00
Hare 8c60921c99 chore: merge orchestration into develop 2026-08-17 11:02:47 +09:00
Hare 956b453e6a fix: preserve long-running workdir requests 2026-08-17 11:01:33 +09:00
Hare 063f203efe merge: integrate selector-thread merge request authority 2026-08-17 10:34:01 +09:00
Hare 5f44b10ff9 fix: revalidate merge authority in completion transaction 2026-08-17 08:15:13 +09:00
Hare e3dc8ee327 fix: validate merge authority before ref updates 2026-08-17 08:04:33 +09:00
Hare 645458498a fix: fence merge request approval and grant lifecycle 2026-08-17 07:57:23 +09:00
Hare 6c4119e2c6 fix: separate merge request authority from thread projection 2026-08-17 07:46:48 +09:00
Hare 7e9cae5f39 fix: bound merge request thread bodies 2026-08-17 07:44:08 +09:00
Hare 1fe1b7463f fix: align merge requests with selector thread contract 2026-08-17 07:41:03 +09:00
Hare 9e48cae759 feat: expose selector based merge request threads 2026-08-17 07:09:20 +09:00
Hare aeb2727bea feat: replace merge request revision authority 2026-08-17 07:09:10 +09:00
Hare 298c20012a fix: bind relation and event query evidence 2026-08-17 06:57:29 +09:00
Hare 7507412f1c fix: query authoritative Ticket content and relations 2026-08-17 06:46:43 +09:00
Hare 45b7d0764d fix: complete query and workflow alias cutover 2026-08-17 06:35:24 +09:00
Hare 7508d428b0 docs: report MR target discovery blocker 2026-08-17 05:39:18 +09:00
Hare 977c8e7b21 fix: align read projections with query contracts 2026-08-17 05:37:06 +09:00
Hare 4964583868 feat: cut over Ticket and Objective read tools 2026-08-17 05:18:38 +09:00
Hare 14aa1aabea feat: add bounded Ticket and Objective read APIs 2026-08-17 05:18:27 +09:00
Hare 76c427c887 fix: remove redundant merge request diff digest 2026-08-17 04:13:14 +09:00
Hare ff7d874138 fix: rebuild merge request schema authority 2026-08-17 02:51:53 +09:00
Hare e881c8fad8 fix: remove speculative worker control delegation 2026-08-17 02:51:18 +09:00
Hare 06cc6056e5 chore: merge orchestration into develop 2026-08-17 01:09:51 +09:00
Hare c15999b7a6 fix: classify commit messages by change type 2026-08-17 01:09:12 +09:00
Hare 0b954c1ab6 fix: scope merge request foreign key checks 2026-08-17 01:09:05 +09:00
Hare eb0dd67d16 server: recover completed Worker transfers 2026-08-17 00:48:37 +09:00
Hare 97828f8bd5 server: fence Worker control operation identity 2026-08-17 00:38:48 +09:00
Hare 8be2cfd2a3 worker: unify granted Worker control 2026-08-17 00:18:49 +09:00
Hare f41ab0e277 worker: persist known-worker control grants 2026-08-16 23:08:32 +09:00
Hare 46a44b232b merge-request: normalize target observation refs 2026-08-16 21:03:30 +09:00
Hare 2cf4c57813 merge-request: verify guarded target updates 2026-08-16 21:03:30 +09:00
Hare 41534b215a merge-request: harden target update recovery 2026-08-16 21:03:30 +09:00
Hare 5ea2792df7 merge-request: finalize one guarded merge outcome 2026-08-16 21:03:30 +09:00
Hare 1479148f84 merge-request: select one final integration result 2026-08-16 21:03:30 +09:00
Hare 7256d80514 merge-request: preserve migration foreign keys 2026-08-16 21:03:30 +09:00
Hare 8e73d755d3 merge-request: harden latest schema migration 2026-08-16 21:03:30 +09:00
Hare 027f60d262 merge-request: add target and merge result authority 2026-08-16 21:03:30 +09:00
Hare 4f042cae84 tui: scope composer history under client data 2026-08-16 18:24:34 +09:00
Hare 0b8924eda7 merge-request: checkpoint restartable migration 2026-08-15 21:26:02 +09:00
Hare eaaf2f6dcc workdir: display working directory status 2026-08-15 21:26:02 +09:00
Hare f5a0e14991 docs: require root cargo check 2026-08-15 21:26:02 +09:00
Hare 11e4d536c5 ticket: support relation removal 2026-08-15 17:05:47 +09:00
Hare 0fd2486baf Merge ticket 00001M00PZS9R paused Worker Resume 2026-08-15 03:55:20 +09:00
Hare 8294a476d2 runtime: allow safe paused resume on orchestration 2026-08-15 03:49:53 +09:00
Hare 9922b654d7 Merge ticket 00001KZVPX841 workspace Workdir contract 2026-08-15 03:38:24 +09:00
Hare b910efd945 workdir: centralize workspace inventory contract 2026-08-15 03:29:53 +09:00
Hare 20854edca2 Merge ticket 00001KZ9SR97B notification projection 2026-08-15 02:57:46 +09:00
Hare 2a23a5d574 server: minimize ticket notification context 2026-08-15 02:34:28 +09:00
Hare 4cf34375a8 config: commit without preview 2026-08-15 02:06:46 +09:00
Hare 404809ab6e config: format sources before commit 2026-08-15 01:28:25 +09:00
Hare c5c89795e1 config: require schema assertion on main 2026-08-15 00:21:46 +09:00
Hare 99b08e0f0c web: protect config schema wrapper 2026-08-14 23:38:51 +09:00
Hare 83a99541b2 web: repair config source editor 2026-08-14 23:28:14 +09:00
Hare 1ed835fb79 Merge branch 'orchestration' into develop
# Conflicts:
#	web/workspace/deno.json
2026-08-14 14:49:01 +09:00
Hare ace134e2f0 runtime: deliver immutable prompt bundle on initial spawn 2026-08-14 14:24:59 +09:00
Hare ecbd003579 worker: track work as natural task steps 2026-08-14 14:23:58 +09:00
Hare 93e784a3ed prompt: route source assertions through effective catalog 2026-08-14 14:02:01 +09:00
Hare a1f6a6bad5 prompt: close whitespace-control include validation gap 2026-08-14 13:58:11 +09:00
Hare a6f92104fa server: project Workspace prompts into Worker config bundles 2026-08-14 13:45:14 +09:00
Hare 0ad7d6d210 worker: replace filesystem prompts with effective DCDL catalog 2026-08-14 13:45:03 +09:00
Hare 48ff977d06 config-source: validate static template catalog projections 2026-08-14 13:44:51 +09:00
Hare 93eea24420 web: show Worker tasks in Console 2026-08-14 12:46:59 +09:00
Hare e582babae3 runtime: avoid duplicate Notify observations 2026-08-14 12:46:49 +09:00
Hare 46ffde19a6 config-source: bind import cache keys to content 2026-08-14 12:06:10 +09:00
Hare 6446eb1302 server: project Skills from active virtual config 2026-08-14 11:55:33 +09:00
Hare ad0f6c68d5 config-source: project Markdown imports as values 2026-08-14 11:55:10 +09:00
Hare 6bcd59fcc6 test: cover Decodal 0.4 parity contracts 2026-08-14 11:00:50 +09:00
Hare 1fad5fc8ed config: migrate workspace evaluation to Decodal 0.4 2026-08-14 10:53:22 +09:00
Hare 5c57e10de9 web: link profiles to shared config editor 2026-08-14 10:03:36 +09:00
Hare c0f4e80320 server: preserve profile config authority at spawn 2026-08-14 09:54:11 +09:00
Hare 4857910410 web: retire profile-specific editor 2026-08-14 09:19:13 +09:00
Hare c2510495ef server: derive profiles from virtual config 2026-08-14 09:19:04 +09:00
Hare f8baa1edb7 server: compose Workspace config schemas 2026-08-14 05:38:21 +09:00
Hare 7a8bd7717e server: require main config entrypoint 2026-08-14 04:36:26 +09:00
Hare c98048b97b Merge branch 'work/00001KY8KRJKK-virtual-config-tree' into develop 2026-08-14 03:20:59 +09:00
Hare 38dad4e865 server: authorize orchestrator MR completion 2026-08-14 03:14:08 +09:00
Hare d039359386 web: refine workspace sidebar navigation 2026-08-14 02:20:50 +09:00
Hare 8c68129d69 web: reapply original changes after config conflict 2026-08-14 01:48:36 +09:00
Hare 348ac51011 config: add revision reads and conflict recovery 2026-08-14 01:41:23 +09:00
Hare 544abbbf56 config: enforce browser preflight and generated DTOs 2026-08-14 01:27:29 +09:00
Hare fa9bd8207f config: complete virtual tree editor contract 2026-08-14 01:07:14 +09:00
Hare 0a7e67e373 config: validate every Decodal source before commit 2026-08-14 00:45:20 +09:00
Hare 9cd1c1c448 runtime: update Decodal import loader test 2026-08-14 00:40:39 +09:00
Hare dfea679f0b web: update Decodal CodeMirror baseline 2026-08-14 00:36:39 +09:00
Hare 0689116e4d server: update schema migration expectations 2026-08-14 00:33:00 +09:00
Hare 02a09ae2d7 test: verify browser WASM config parity 2026-08-14 00:31:22 +09:00
Hare f9d328f2db worker: add typed feature services for coder spawn 2026-08-14 00:02:13 +09:00
Hare 8c6dcb9483 web: edit virtual config sources with WASM core 2026-08-13 22:34:56 +09:00
Hare c8b57a6a5d server: persist evaluated virtual config trees 2026-08-13 22:26:11 +09:00
Hare 7aa4d3067e config: add canonical Decodal source core 2026-08-13 22:13:33 +09:00
Hare e47eca53a2 Merge branch 'orchestration' into develop 2026-08-13 17:50:33 +09:00
Hare 8d061a8734 fix: guard orchestrator Coder assignment spawn 2026-08-13 17:50:27 +09:00
Hare 9c8ab6441c Merge branch 'work/00001KZVN5J0S-ticket-list-bulk-projection' into orchestration 2026-08-13 05:23:19 +09:00
Hare dfede080d2 ticket: deduplicate bulk relation blockers 2026-08-13 04:56:52 +09:00
Hare cf32d871de server: bulk project ticket list 2026-08-13 04:21:10 +09:00
Hare fe373b5656 runtime: remove embedded worker socket transport 2026-08-13 03:25:57 +09:00
Hare a44a4bc4f8 docs: record ticket audit and restart failures 2026-08-13 02:01:23 +09:00
Hare cb683beef8 dev: gate dogfood restarts with isolated smoke 2026-08-13 02:01:17 +09:00
Hare 1d4ffa875a runtime: restore persisted workers without adapter panic 2026-08-13 02:01:13 +09:00
Hare 297a7ddd9d merge: integrate orchestration merge request lifecycle
# Conflicts:
#	resources/flows/coder-review.dcdl
2026-08-12 18:30:08 +09:00
Hare be698c2239 Merge branch 'work/00001KZPQW4GJ-worker-remove-v3' into orchestration-merge-request-domain-final 2026-08-12 17:49:35 +09:00
Hare e80581d139 worker: preserve retry cleanup stage 2026-08-12 17:40:11 +09:00
Hare 4e7eaac7d5 worker: retry attachment cleanup stages 2026-08-12 17:31:29 +09:00
Hare 92f7f3fca3 Merge branch 'work/00001KZPQW4GJ-worker-remove-v3' into orchestration-merge-request-domain 2026-08-12 17:18:04 +09:00
Hare 1e10cdecc8 docs: report stale Flow verifier capture 2026-08-12 17:16:57 +09:00
Hare ce6b8f65cc Merge branch 'work/00001KZPQW4GJ-worker-remove-v3' into orchestration-merge-request-domain 2026-08-12 17:10:29 +09:00
Hare f60c2d5834 worker: resume failed removal operation 2026-08-12 17:09:39 +09:00
Hare 795f26fb51 Merge branch 'work/00001KZPQW4GJ-worker-remove-v3' into orchestration-merge-request-domain 2026-08-12 17:01:24 +09:00
Hare 8ae930c5fc worker: add guarded WorkerRemove lifecycle 2026-08-12 17:00:32 +09:00
Hare ebe0f93744 Merge branch 'work/00001KZRWSNNE-runtime-worker-source' into orchestration-merge-request-domain 2026-08-12 04:11:22 +09:00
Hare 8cc0aaf8d2 runtime: prove Worker mutation source authority 2026-08-12 04:03:09 +09:00
Hare 86be3a6865 Merge branch 'work/00001KZPQSFQD-worker-retention' into orchestration-merge-request-domain 2026-08-12 00:47:46 +09:00
Hare 5e5ce73fd0 runtime: harden retention reconciliation and retry 2026-08-12 00:46:39 +09:00
Hare 01971807cb Merge branch 'work/00001KZPQSFQD-worker-retention' into orchestration-merge-request-domain 2026-08-11 23:59:19 +09:00
Hare da8313fa1a runtime: add revisioned worker retention authority 2026-08-11 23:57:37 +09:00
Hare 09fd17e38b Merge branch 'work/00001KZPS59RK-worker-aggregate' into orchestration-merge-request-domain 2026-08-11 22:39:30 +09:00
Hare 34f8949e85 runtime: canonicalize Worker aggregates 2026-08-11 22:38:29 +09:00
Hare 33d3d1a43f Merge branch 'work/00001KZNCCD9C-merge-request-domain' into orchestration-merge-request-domain 2026-08-11 21:17:35 +09:00
Hare 1814c35701 feat: add merge request review authority 2026-08-11 20:21:37 +09:00
Hare 6df5fe5b2a flow: require coder work branch commits 2026-08-11 19:39:56 +09:00
Hare c292c01da3 fix: keep active workers visible in sidebar 2026-08-11 15:32:50 +09:00
Hare 133fbbe038 fix: keep reviewer routing owned by coder 2026-08-11 15:02:13 +09:00
Hare 7f0d025312 server: scope repository identity by workspace 2026-08-11 05:44:48 +09:00
Hare 9dccf99c50 ticket: own typed schema migrations 2026-08-11 05:00:40 +09:00
Hare 1d498d13c3 fix: remove secure-context websocket id dependency 2026-08-11 04:58:47 +09:00
Hare e88b0cda18 fix: restore production orchestrator spawn 2026-08-11 04:58:34 +09:00
Hare 8d2b8b690f fix: make image tool results durably prunable 2026-08-11 02:44:37 +09:00
Hare 38b8f26a50 feat: add scoped multimodal image attachments 2026-08-10 21:49:39 +09:00
Hare 64ced7dbad worker: make coder review routing durable 2026-08-10 02:01:08 +09:00
Hare b9dadb6a08 worker: support typed initial submit on spawn 2026-08-09 23:19:29 +09:00
Hare 068ba9afa5 flow: own worker flow state in runtime sessions 2026-08-09 18:04:32 +09:00
Hare c0532fda4e runtime: project granted worker sessions 2026-08-07 16:31:30 +09:00
Hare ff50baec99 worker: split session capture observation features 2026-08-07 16:31:15 +09:00
Hare a9bb806387 subworker: harden internal session lifecycle 2026-08-07 13:36:44 +09:00
Hare 8fe0525295 worker: exercise project reviewer internal spawn 2026-08-07 02:20:52 +09:00
Hare e6703ed18a worker: preserve prompt overrides in internal children 2026-08-07 02:15:00 +09:00
Hare ee75272917 worker: materialize legacy child cleanup only when needed 2026-08-07 02:05:43 +09:00
Hare 620ecbafcb worker: cover legacy sub-worker restore cleanup 2026-08-07 02:04:42 +09:00
Hare cf394403a6 worker: retire process sub-worker registry authority 2026-08-07 02:03:09 +09:00
Hare 8f0d7fa3c0 worker: revoke parent writes before child run 2026-08-07 01:54:31 +09:00
Hare cc7266c801 worker: cover parent teardown scope reclaim 2026-08-07 01:52:07 +09:00
Hare e0ac732769 worker: verify internal sub-worker scope reclaim 2026-08-07 01:48:25 +09:00
Hare c79db24016 worker: run sub-workers as internal sessions 2026-08-07 01:44:04 +09:00
Hare 485918ebe3 worker: route sub-worker tools through internal sessions 2026-08-06 23:15:30 +09:00
Hare d9f399b97b worker: add internal worker session actor 2026-08-06 22:57:42 +09:00
Hare b8a5c60ff9 server: diagnose and fix worker spawn failures 2026-08-06 22:39:24 +09:00
Hare 2d4b93dde7 worker: cover cancelled memory extraction caller 2026-08-06 22:02:57 +09:00
Hare bd893f271a worker: treat rolled-back extraction as cancelled 2026-08-06 09:49:48 +09:00
Hare 2c8e617b2a worker: run internal extraction through Worker 2026-08-06 08:54:40 +09:00
Hare 8207e560e9 worker: compensate spawn finalize failures 2026-08-06 07:45:18 +09:00
Hare 22b6f4e71d worker: allow companion to manage workers 2026-08-05 23:20:38 +09:00
Hare 5c5921fcd2 docs: report LAN websocket UUID failure 2026-08-05 21:31:46 +09:00
Hare a2781f57e9 worker: structure runtime worker identities 2026-08-05 21:26:55 +09:00
Hare fd391ef705 fix: recover partial session log writes 2026-08-05 18:15:49 +09:00
Hare 36df79e561 runtime: allow cross-runtime workdir sessions 2026-08-05 16:02:16 +09:00
Hare 636dc14616 web: refresh worker sidebar snapshots 2026-08-05 05:46:06 +09:00
Hare fb115fbb7e worker: unify workdir attachments 2026-08-05 05:30:58 +09:00
Hare ba009c0a20 worker: separate subworkers from workspace workers 2026-08-05 03:36:59 +09:00
Hare 50726e4cf3 web: show system items in worker console 2026-08-05 03:36:50 +09:00
Hare f98a123e40 runtime: route notifications through worker inbox 2026-08-05 01:44:57 +09:00
Hare dd2ca54874 web: launch embedded workspace orchestrator 2026-08-04 19:52:54 +09:00
Hare da90ac74b4 worker: add workspace workdir management feature 2026-08-04 19:28:59 +09:00
Hare e6a2da548f fs: extract provider operations into shared crate 2026-08-04 02:03:22 +09:00
Hare e5f0c4168f workdir: add authenticated runtime session transport 2026-08-03 23:37:15 +09:00
Hare 05e8b00bf0 workdir: separate identity from worker session 2026-08-03 18:12:47 +09:00
Hare 0ffaa6c741 workspace: remove worker credential refresh flow 2026-08-03 17:08:23 +09:00
Hare ddadc830ac workdir: add network-capable operation boundary 2026-08-03 16:14:01 +09:00
Hare 0fa36395e7 web: show worker status in sidebar 2026-08-02 04:18:16 +09:00
Hare 606cd5fa31 web: subscribe console on route changes 2026-08-02 03:43:53 +09:00
Hare e5f3c20f64 server: restore weak workspace web access 2026-08-02 03:24:54 +09:00
Hare e530150e43 auth: bootstrap legacy workspace ownership 2026-08-02 00:26:28 +09:00
Hare 0f9f06048a runtime: remove legacy event polling authority 2026-08-01 22:55:58 +09:00
Hare 24f7267d55 web: share workspace multiplexer with console 2026-08-01 21:07:45 +09:00
Hare 11f26a1090 server: multiplex worker protocol subscriptions 2026-08-01 21:07:45 +09:00
Hare 72cef5ed9e web: subscribe sidebar to workspace workers 2026-08-01 20:12:27 +09:00
Hare b977c4cbad server: stream workspace worker subscriptions 2026-08-01 20:12:27 +09:00
Hare 5d4deb258a server: expose subscription runtime catalog 2026-08-01 19:34:50 +09:00
Hare f46c82d171 server: broker embedded runtime subscriptions 2026-08-01 19:23:49 +09:00
Hare 42c69f9f6c protocol: identify workspace subscription runtimes 2026-08-01 19:11:41 +09:00
Hare 9308f93de7 server: broker runtime event subscriptions 2026-08-01 19:04:05 +09:00
Hare ecd5751a67 docs: report spawn worker delegation scope 2026-08-01 18:34:32 +09:00
Hare ec262f0238 runtime: serve selective event subscriptions 2026-08-01 18:34:32 +09:00
Hare 21cd672f64 protocol: define multiplexer subscriptions 2026-08-01 18:34:32 +09:00
Hare 9dfcddf40b docs: report spawned worker launcher mismatch 2026-08-01 17:24:10 +09:00
Hare 81e631e640 auth: enforce workspace worker credentials over ticket REST 2026-08-01 17:23:59 +09:00
Hare 3412f1c0ed merge: integrate ticket assignment notifications
# Conflicts:
#	crates/workspace-server/src/store.rs
2026-07-31 23:59:09 +09:00
Hare 48556e1a2c feat: add workspace breadcrumbs 2026-07-31 23:48:46 +09:00
Hare 06a98fe30c workdir: report current selector and ref 2026-07-31 23:48:46 +09:00
Hare 4cf110b28e runtime: replay Worker creation before workdir conflicts 2026-07-31 23:28:07 +09:00
Hare df34d43a23 server: close Ticket lifecycle crash gaps 2026-07-31 23:12:05 +09:00
Hare e9a6269d9f server: address Ticket orchestration review 2026-07-31 22:15:55 +09:00
Hare 005f6cb498 server: route Ticket mutation notifications 2026-07-31 20:15:11 +09:00
Hare 32d3f8f75e Merge branch 'merge/00001KYRRDVH9-ticket-panel' into develop 2026-07-31 02:54:15 +09:00
Hare cb4b588598 fix: remove companion filter from worker list 2026-07-31 02:53:36 +09:00
Hare 20a0f7a454 merge: integrate ticket panel workflow 2026-07-31 02:22:49 +09:00
Hare e720af38a6 workspace: add ticket panel workflow 2026-07-31 01:12:10 +09:00
Hare 1c2d284578 workspace: add typed Ticket API and targets 2026-07-30 22:13:01 +09:00
Hare 3e217adc14 feat: profile解決とmodel catalogを更新 2026-07-30 22:12:25 +09:00
Hare d94ef81b43 runtime: bind workspaces to issuer 2026-07-30 13:42:53 +09:00
Hare ac6c8b275d runtime: require http auth 2026-07-30 13:05:57 +09:00
Hare 3dda06cbe3 runtime: scope worker access by workspace 2026-07-30 00:25:46 +09:00
Hare 0ff8a95da3 docs: mention trybuild policy 2026-07-29 23:18:09 +09:00
Hare be7a96a825 docs: add rust testing strategy 2026-07-29 23:05:10 +09:00
Hare 7265041e55 objective: add mutation tools 2026-07-29 21:58:01 +09:00
Hare 0b64eab148 build: enable runtime server features by default 2026-07-29 19:57:59 +09:00
Hare fb285b17e4 build: rename server runtime binaries 2026-07-29 19:36:05 +09:00
Hare 699290ccb1 cli: support panel restore list 2026-07-29 19:15:57 +09:00
Hare 406104babd cli: update yoi help 2026-07-29 18:44:08 +09:00
Hare 297c56c72d cli: configure target defaults 2026-07-29 18:26:22 +09:00
Hare 8ec940f624 merge: bound task tool output 2026-07-29 16:53:57 +09:00
Hare cbbc860366 cli: route worker lists through targets 2026-07-29 16:04:24 +09:00
Hare acc7281414 runtime: filter stopped workers 2026-07-29 04:27:04 +09:00
Hare bffbe6b551 fix: simplify task item output 2026-07-29 02:36:14 +09:00
Hare b6f83d81bb fix: bound task tool output 2026-07-29 02:29:15 +09:00
Hare 98c1599d1a cli: introduce connection target abstraction 2026-07-29 02:18:02 +09:00
Hare 450e0cddbd prompt: preserve feature instruction order 2026-07-28 22:00:16 +09:00
Hare 44e7014d83 prompt: derive guidance from features 2026-07-28 21:30:06 +09:00
Hare 9125cee6fd prompt: update ticket guidance 2026-07-28 20:58:19 +09:00
Hare 7a1b5e97c1 refactor: make runtime worker state authoritative 2026-07-28 19:21:09 +09:00
Hare 6114cc9018 fix: read secrets from legacy data dir 2026-07-28 04:12:26 +09:00
Hare 5d1950647e fix: keep in-flight cleanup internal 2026-07-27 16:38:47 +09:00
Hare 1dc6429b87 fix: clear stale in-flight state 2026-07-27 15:54:08 +09:00
Hare e20c8a1d0b docs: document runtime auth setup 2026-07-27 02:41:02 +09:00
Hare 3cb056c523 fmt: format runtime auth changes 2026-07-27 01:43:17 +09:00
Hare 55204478c6 fmt: format merged cli changes 2026-07-27 01:43:08 +09:00
Hare 0f2289c539 merge: ticket edit partial replacement 2026-07-27 01:40:54 +09:00
Hare 20dcf429d4 merge: runtime auth 2026-07-27 01:38:58 +09:00
Hare 9a14f1b6fc fix: require explicit runtime trust replacement 2026-07-26 23:18:51 +09:00
Hare 1378581940 ticket: add exact body replacement edits 2026-07-26 20:46:06 +09:00
Hare d994268a6b feat: add runtime trust capability auth 2026-07-26 20:45:52 +09:00
Hare 006762f900 worker: separate display metadata 2026-07-26 17:45:46 +09:00
Hare ff905d4a22 memory: reuse consolidation worker 2026-07-26 17:08:29 +09:00
Hare 3369dbd1eb web: add memory document view 2026-07-26 16:45:12 +09:00
Hare a5d207821d memory: simplify document consolidation tools 2026-07-26 16:18:07 +09:00
Hare e751a11a92 memory: route staging lifecycle through sqlite authority 2026-07-26 15:44:51 +09:00
Hare faaf258a96 merge: sqlite memory tools 2026-07-26 15:23:24 +09:00
Hare 23e47e6097 feat: connect memory tools to workspace authority 2026-07-26 15:17:48 +09:00
Hare 386152749a merge: sqlite memory authority 2026-07-26 14:29:28 +09:00
Hare 82ffc14d65 workspace: add sqlite memory authority 2026-07-26 14:21:27 +09:00
Hare 0eb840ab4b objective: remove one-shot import 2026-07-26 12:47:42 +09:00
Hare e653f8f08b workspace: introduce authority abstraction 2026-07-26 12:20:18 +09:00
Hare 5b1b0688bc objective: move records to sqlite authority 2026-07-26 11:10:00 +09:00
Hare 18b5cead7a objective: add read tools 2026-07-26 02:21:22 +09:00
Hare 2200f60b94 ticket: plan objective tools 2026-07-26 02:06:08 +09:00
Hare e997aa2fc6 memory: gate staging tools by profile 2026-07-25 10:56:27 +09:00
Hare a44673fa6b memory: consolidate staging through queue tools 2026-07-25 09:17:08 +09:00
Hare 4de801f8d0 runtime: avoid profile archive during restore 2026-07-24 21:04:12 +09:00
Hare 7caf6cd6e6 script: migrate workdir layout 2026-07-24 19:01:09 +09:00
Hare 1d64618b4a runtime: simplify workdir layout 2026-07-24 18:37:59 +09:00
Hare 6b824d9018 web: remove unused tailwind import 2026-07-24 18:16:51 +09:00
Hare b22f7d06e7 web: simplify font fallbacks 2026-07-24 18:07:31 +09:00
Hare 54bb7209a4 style: format web workspace 2026-07-24 17:54:16 +09:00
Hare 1c2cb01882 web: split app css by feature 2026-07-24 17:47:25 +09:00
Hare 51e2b721ff web: add ibm plex mono font 2026-07-24 16:14:35 +09:00
Hare 862f8f7f98 web: make running composer stoppable 2026-07-24 15:53:02 +09:00
Hare 342c3dabb7 web: use gen interface font 2026-07-24 15:28:31 +09:00
Hare f7482d6151 runtime: dry-check worker restore 2026-07-24 15:17:53 +09:00
Hare b8cc58ac29 web: expose memory staging view 2026-07-24 14:10:52 +09:00
Hare b9067a8110 web: align ticket table with panel order 2026-07-24 12:46:17 +09:00
Hare 7a28395d75 web: theme ticket table 2026-07-24 11:20:23 +09:00
Hare d3d2b28adc runtime: simplify worker lifecycle 2026-07-24 11:07:04 +09:00
Hare e0b092dbc8 workdir: project occupancy from links 2026-07-24 09:29:25 +09:00
Hare b1570aba63 web: add sortable ticket table 2026-07-24 08:56:36 +09:00
Hare 4ff599c011 server: use single XDG server database 2026-07-24 08:45:51 +09:00
Hare 19d5396897 migrate: move workspace data to XDG SQLite stores 2026-07-24 08:45:42 +09:00
Hare e975c648c2 web: move sidebar fold into frame 2026-07-23 21:59:47 +09:00
Hare 60460b23dc web: make sidebar fold button visible 2026-07-23 21:19:06 +09:00
Hare 62c1e4303b web: move sidebar chrome css out of app 2026-07-23 21:09:44 +09:00
Hare 97397a1c4d web: keep sidebar fold button visible 2026-07-23 20:57:02 +09:00
Hare 6e53df0303 web: rename sidebar collapse to fold 2026-07-23 20:50:30 +09:00
Hare f848a96343 web: keep sidebar collapse local 2026-07-23 20:45:58 +09:00
Hare fb4d3c3f1f web: register sidebar snippets from layouts 2026-07-23 20:01:54 +09:00
Hare b3854004a1 web: restore root sidebar chrome 2026-07-23 19:47:11 +09:00
Hare 308e1ffdbc web: add global sidebar fallback 2026-07-23 19:23:02 +09:00
Hare 2bd69f9403 web: scope sidebar to workspace routes 2026-07-23 19:12:50 +09:00
Hare 61b1735292 web: simplify header chrome 2026-07-23 18:49:36 +09:00
Hare 11663830e3 web: move account nav to header 2026-07-23 18:46:43 +09:00
Hare 2285277060 fix: align account UI actor shape 2026-07-23 18:35:04 +09:00
Hare cd6468bb92 fix: send browser origin for passkey options 2026-07-23 18:03:22 +09:00
Hare 28304f13c3 fix: honor browser origin for passkey ceremonies 2026-07-23 17:54:51 +09:00
Hare 7740191194 web: add account passkey login UI 2026-07-23 03:14:43 +09:00
Hare 7dda898830 web: add workspace ticket routes 2026-07-23 02:44:20 +09:00
Hare 681034db1e merge: account passkey login flow 2026-07-23 02:08:56 +09:00
Hare 554a784639 backend: verify passkey ceremonies 2026-07-23 02:01:28 +09:00
Hare 026e4cf90b docs: record backend auth model 2026-07-23 01:14:24 +09:00
Hare 4f8a2357a5 cli: add backend device login 2026-07-23 01:11:07 +09:00
Hare ba0289b820 backend: add passkey auth api 2026-07-23 01:05:40 +09:00
Hare ed8110ae45 backend: add account auth store schema 2026-07-23 00:57:45 +09:00
Hare 41da9c91b2 docs: record workspace runtime docker boundary 2026-07-23 00:03:46 +09:00
Hare 44deacb3f4 fix: remove workdir management kind 2026-07-22 20:52:09 +09:00
Hare fe2a39c12d fix: async workspace memory backend 2026-07-22 19:44:52 +09:00
Hare aa542b38d9 feat: add local image compose setup 2026-07-22 19:09:17 +09:00
Hare c1ee1ff9e9 feat: build docker images with nix 2026-07-22 18:43:35 +09:00
Hare a8236ff3b4 feat: add docker image targets 2026-07-22 18:03:03 +09:00
Hare c75baacd9b chore: untrack yoi tickets 2026-07-22 17:09:14 +09:00
Hare a8c27f5752 fix: remove console composer click shell 2026-07-22 16:55:28 +09:00
Hare 1ff02151b8 fix: relativize web console tool paths 2026-07-22 16:23:39 +09:00
Hare c7c838b4e5 fix: filter web timeline assistant marks 2026-07-22 16:08:45 +09:00
Hare ad93047a25 fix: handle web console segment rotation 2026-07-22 15:37:02 +09:00
Hare b9f4c06c68 fix: share protocol frame codec 2026-07-22 14:03:33 +09:00
Hare 945716d010 fix: share worker protocol session logic 2026-07-22 12:51:19 +09:00
Hare a164017432 fix: bridge worker log events to protocol 2026-07-22 11:54:44 +09:00
Hare fdf1f43281 fix: echo protocol run inputs 2026-07-22 11:11:53 +09:00
Hare 8aafd388fa fix: proxy backend protocol websocket frames 2026-07-21 20:42:49 +09:00
Hare 8841d063be fix: unify worker protocol websocket 2026-07-21 20:29:30 +09:00
Hare 70a26a3042 feat: route backend worker controls over protocol 2026-07-21 19:33:24 +09:00
Hare bfa9346de2 ticket: target protocol worker controls 2026-07-21 18:47:17 +09:00
Hare c9c1d0bb72 ticket: scope backend worker protocol controls 2026-07-21 18:42:25 +09:00
Hare 58e9fd17cc ticket: close backend worker picker 2026-07-21 18:16:38 +09:00
Hare 4a08b69b4c fix: align backend worker picker style 2026-07-21 18:12:33 +09:00
Hare 2e2d7b7290 fix: expose runtime worker list endpoint 2026-07-21 18:04:14 +09:00
Hare f79892baef feat: surface backend runtime workers in tui 2026-07-21 17:41:50 +09:00
Hare 2b307b8040 merge: worker workspace authority api 2026-07-21 15:45:01 +09:00
Hare 06d4adf198 Update AGENTS.md 2026-07-21 15:34:17 +09:00
Hare 00d6c3a7c4 fix: remove direct worker local workspace discovery 2026-07-21 12:07:38 +09:00
Hare 1251edae04 feat: route worker workspace access through backend authority 2026-07-21 11:21:13 +09:00
Hare 2572dde691 feat: add workspace memory backend for embedded workers 2026-07-21 09:27:28 +09:00
Hare 2e0cd3d161 Merge branch 'work/ticket-access-capabilities' into develop 2026-07-21 06:28:41 +09:00
Hare 8a3c7b4191 Update .gitignore 2026-07-21 06:25:37 +09:00
Hare 7f7d2fe7fc ticket: use boolean ticket capabilities 2026-07-21 06:13:26 +09:00
Hare 064965d350 ticket: collapse ticket access into one feature 2026-07-20 19:51:46 +09:00
Hare 2c01e7672b ticket: split ticket feature access presets 2026-07-20 19:05:55 +09:00
Hare a40d9c2027 ticket: share workspace actionable projection 2026-07-20 17:42:20 +09:00
Hare 556adb429c ticket: use list state tokens in query 2026-07-20 17:16:40 +09:00
Hare 39be7a5a0a ticket: merge TicketListQuery implementation 2026-07-20 17:09:17 +09:00
Hare 0a5270a2cc ticket: update list query semantics 2026-07-20 15:45:53 +09:00
Hare edc495ac01 merge: work/default-ticket-tools 2026-07-20 11:36:12 +09:00
Hare 156dbfda64 dev: harden workspace restart scheduling 2026-07-20 11:35:22 +09:00
Hare 18d9b96cac runtime: avoid ticket backend blocking panic 2026-07-20 09:45:39 +09:00
Hare 2b0901eb62 runtime: avoid websocket runtime drop panic 2026-07-20 08:45:13 +09:00
Hare 1173e3af38 runtime: report adapter task panics 2026-07-19 00:37:53 +09:00
Hare 23234b96ca profile: inherit ticket tools across roles 2026-07-18 21:59:58 +09:00
Hare 5f651755d8 runtime: preserve workdirs across worker deletion 2026-07-18 21:49:19 +09:00
Hare de3416cf3b dev: document workspace process switcher 2026-07-18 19:10:51 +09:00
Hare 76f35a7126 dev: detach workspace process actions 2026-07-18 17:41:09 +09:00
Hare 5e91f98ae0 dev: enable default ticket tools and workdir helpers 2026-07-18 17:32:46 +09:00
Hare 60410f29a1 ticket: plan backend runtime worker list 2026-07-18 11:46:39 +09:00
Hare 7e43c10e2d worker: implement session explore extract worker 2026-07-18 10:35:59 +09:00
Hare 92a825fd15 worker: reuse session reference for compaction reads 2026-07-18 09:03:06 +09:00
Hare 2dd9ef95dd worker: add session reference view 2026-07-18 08:27:42 +09:00
Hare 39fa8827da ticket: add session reference view 2026-07-18 08:15:05 +09:00
Hare 37c44a7942 Update workspace.toml 2026-07-18 07:49:35 +09:00
Hare 62dbed8075 worker: rename internal worker purpose to slug 2026-07-18 06:11:44 +09:00
Hare 88b91a2c55 worker: add internal worker runner 2026-07-18 05:59:02 +09:00
Hare ff04becfab ticket: add internal worker runner 2026-07-18 05:47:48 +09:00
Hare 2352f34c4e memory: implement flat extract staging 2026-07-18 05:46:56 +09:00
Hare 444e6bee42 ticket: define flat memory extract staging 2026-07-18 04:34:28 +09:00
Hare 7c1fb65947 Update AGENTS.md 2026-07-18 03:51:43 +09:00
Hare c5eb28af75 ticket: close staging source anchors work 2026-07-17 04:45:45 +09:00
Hare 9a1a75de48 merge: staging source anchors 2026-07-17 04:44:20 +09:00
Hare d0e514704e ticket: approve staging source anchors implementation 2026-07-17 04:44:11 +09:00
Hare c34a50f7c9 ticket: record staging source anchors implementation 2026-07-17 04:41:00 +09:00
Hare 31798fb285 feat: add staging entry source anchors 2026-07-17 04:39:43 +09:00
Hare 08c4547a2e ticket: accept staging source anchors work 2026-07-17 04:28:08 +09:00
Hare 5aa88f7d0d ticket: queue 00001KXNYXNM6 2026-07-17 04:26:52 +09:00
Hare a9c86297aa merge: sync orchestration before queue 00001KXNYXNM6 2026-07-17 04:26:52 +09:00
Hare 594e4140bf ticket: split memory extract implementation 2026-07-17 04:26:50 +09:00
Hare 65dc67a7a1 prompt: add progress message guidance 2026-07-17 01:49:10 +09:00
Hare 8163c54a44 ticket: plan memory extract improvements 2026-07-17 00:50:43 +09:00
Hare 57bd5a5902 ticket: close agent skills work 2026-07-16 09:15:13 +09:00
Hare 1611e04d17 merge: agent skills support 2026-07-16 09:11:07 +09:00
Hare 888ec11455 ticket: approve agent skills implementation 2026-07-16 09:11:00 +09:00
Hare 3d5c24cc4c ticket: record agent skills review fix 2026-07-16 09:07:45 +09:00
Hare 4ddfccee2d fix: reject unsupported skill fields 2026-07-16 09:06:45 +09:00
Hare 85153cf8a0 ticket: record agent skills review blockers 2026-07-16 08:53:18 +09:00
Hare a92457ea05 ticket: record agent skills implementation 2026-07-16 08:46:52 +09:00
Hare 62ef89a163 feat: add workspace-backed agent skills 2026-07-16 08:41:10 +09:00
Hare 1abf56dbc2 objective: revise memory knowledge skills architecture 2026-07-16 08:38:33 +09:00
Hare 9e0f8e9aad objective: draft memory architecture overview 2026-07-16 08:15:39 +09:00
Hare 05c50e32cf ticket: accept agent skills work 2026-07-16 08:01:35 +09:00
Hare 076e01adbb ticket: close knowledge removal work 2026-07-16 08:00:28 +09:00
Hare f279eb11e8 merge: remove knowledge support 2026-07-16 07:57:16 +09:00
Hare d4665ee8e5 ticket: approve knowledge removal implementation 2026-07-16 07:57:07 +09:00
Hare 8681cfa063 ticket: record knowledge docs fix 2026-07-16 07:55:27 +09:00
Hare 9f527f5ea2 fix: remove stale report knowledge wording 2026-07-16 07:54:35 +09:00
Hare fae9bbe84a ticket: record knowledge docs review blocker 2026-07-16 07:53:26 +09:00
Hare ff8e3c1114 ticket: record knowledge hash completion fix 2026-07-16 07:51:05 +09:00
Hare 20654f9c40 fix: disable hash console completions 2026-07-16 07:50:13 +09:00
Hare da912980fd objective: add sensemaking process reference 2026-07-16 07:47:00 +09:00
Hare 63676b9ae3 ticket: record knowledge hash completion blocker 2026-07-16 07:44:53 +09:00
Hare 4f5cc1e884 ticket: record knowledge guidance fix 2026-07-16 07:41:31 +09:00
Hare ad66650369 fix: remove stale knowledge guidance 2026-07-16 07:40:32 +09:00
Hare 09230633a5 ticket: record knowledge removal review blockers 2026-07-16 07:35:48 +09:00
Hare 149497b823 objective: align memory records with skills direction 2026-07-16 07:34:24 +09:00
Hare ca10a130a7 ticket: record knowledge removal implementation 2026-07-16 07:31:24 +09:00
Hare f786e01997 feat: remove active knowledge support 2026-07-16 07:30:00 +09:00
Hare f2106407be ticket: accept knowledge removal work 2026-07-16 06:40:32 +09:00
Hare 66b3a38f7d ticket: close workflow removal work 2026-07-16 06:39:31 +09:00
Hare 2f260029d4 merge: remove workflow machinery
# Conflicts:
#	.yoi/tickets/00001KXKJGYGD/item.md
#	.yoi/tickets/00001KXKJGYGD/thread.md
2026-07-16 06:35:48 +09:00
Hare 7cd5585a4e ticket: approve workflow removal implementation 2026-07-16 06:35:35 +09:00
Hare 9dc27a10bb ticket: record workflow tui test fix 2026-07-16 06:32:55 +09:00
Hare bc48094dde fix: update workflow-free tui tests 2026-07-16 06:32:07 +09:00
Hare ad1cbbc77f ticket: hold skills support for removal prerequisites 2026-07-16 06:27:03 +09:00
Hare e0f14d402e ticket: queue 00001KXKMX0QM 2026-07-16 06:26:15 +09:00
Hare d64a42125f merge: sync orchestration before queue 00001KXKMX0QM 2026-07-16 06:26:15 +09:00
Hare 5030888cb5 ticket: record workflow snapshot test blocker 2026-07-16 06:25:48 +09:00
Hare 2bd3ccd36c ticket: record workflow completion fix 2026-07-16 06:23:31 +09:00
Hare 0b56052a44 fix: remove workflow completion surface 2026-07-16 06:22:41 +09:00
Hare 0e51461ab6 ticket: ready agent skills support 2026-07-16 06:17:10 +09:00
Hare 5c79bc7609 ticket: record workflow completion review blocker 2026-07-16 06:10:20 +09:00
Hare 21296a10df ticket: add agent skills references 2026-07-16 06:08:16 +09:00
Hare f772977784 ticket: record workflow removal fix 2026-07-16 06:07:05 +09:00
Hare d30dca2d99 fix: remove remaining workflow invoke surfaces 2026-07-16 06:04:19 +09:00
Hare 7a71d9c114 ticket: require workspace skills api 2026-07-16 06:02:43 +09:00
Hare 6d9885aa5d ticket: record workflow removal review blockers 2026-07-16 05:53:09 +09:00
Hare 88f8796cdc ticket: record workflow removal implementation 2026-07-16 05:46:25 +09:00
Hare d801b2698b refactor: remove workflow machinery 2026-07-16 05:45:24 +09:00
Hare 1676018ce7 ticket: make workspace skills authority 2026-07-16 05:43:51 +09:00
Hare a8ac4cc56a ticket: hold knowledge removal for workflow cleanup 2026-07-16 05:27:58 +09:00
Hare 2417ac1960 ticket: queue 00001KXKP2A71 2026-07-16 05:27:03 +09:00
Hare 74f02a0e58 merge: sync orchestration before queue 00001KXKP2A71 2026-07-16 05:27:02 +09:00
Hare 2b73cbfbce ticket: plan knowledge removal before skills 2026-07-16 05:04:54 +09:00
Hare 724fc037ed ticket: require removing skill projection extensions 2026-07-16 04:58:46 +09:00
Hare 29db1b6270 ticket: record current skills support 2026-07-16 04:56:55 +09:00
Hare 83ad7506d7 ticket: accept workflow removal work 2026-07-16 04:55:47 +09:00
Hare 6ce8fdb578 ticket: queue 00001KXKJGYGD 2026-07-16 04:54:36 +09:00
Hare b62946845f ticket: implement skills 2026-07-16 04:54:33 +09:00
Hare e3f4fdb478 Create ticket.config.toml 2026-07-16 04:27:57 +09:00
Hare dec678e9b4 ticket: ready workflow removal skills migration 2026-07-16 04:27:18 +09:00
Hare f32496286e merge: workspace ticket settings 2026-07-16 04:03:53 +09:00
Hare a8f7ea9aed ticket: replace workflow tracking with skills 2026-07-16 04:03:06 +09:00
Hare 3679362f0f ticket: close workspace ticket settings work 2026-07-16 02:51:38 +09:00
Hare 45783b7488 merge: workspace ticket settings 2026-07-16 02:45:52 +09:00
Hare 05cf6e883f ticket: approve workspace ticket settings implementation 2026-07-16 02:45:40 +09:00
Hare 884ced7ecb ticket: record workspace ticket settings fix 2026-07-16 02:43:12 +09:00
Hare 40f2114541 tui: use configured ticket root for overlay 2026-07-16 02:42:29 +09:00
Hare f5c340a120 ticket: record workspace ticket settings review blocker 2026-07-16 02:26:32 +09:00
Hare 1473e874a8 ticket: record workspace ticket settings implementation 2026-07-16 02:20:11 +09:00
Hare b1e3a2ad33 ticket: move ticket settings into workspace config 2026-07-16 02:19:04 +09:00
Hare 7f9b6c01b5 build: update cargo hash after llm engine merge 2026-07-16 01:47:33 +09:00
Hare 88c2edefd4 merge: prepare llm engine for publish 2026-07-16 01:45:09 +09:00
Hare ed825db4e9 ticket: plan workspace orchestrator workdir tools 2026-07-16 01:31:01 +09:00
Hare c68ed1fdc5 ticket: accept workspace ticket settings work 2026-07-16 01:30:44 +09:00
Hare 5c8a7f363c ticket: close completed workspace cleanup items 2026-07-16 01:28:54 +09:00
Hare 16063c636d ticket: route workspace ticket settings work 2026-07-16 01:22:57 +09:00
Hare 7efe13747a ticket: queue 00001KXK9507N 2026-07-16 01:19:31 +09:00
Hare 724a5da67b ticket: plan workspace ticket settings consolidation 2026-07-16 01:19:19 +09:00
Hare 983ffe6017 feat: route ticket tools through workspace backend 2026-07-16 01:18:13 +09:00
Hare 66abd53e51 feat: refine workspace console ui 2026-07-15 22:43:56 +09:00
Hare f9f1f85b07 feat: add worker console timeline 2026-07-15 02:46:45 +09:00
Hare 839fc7b40c refactor: fold provider crate into engine 2026-07-15 00:58:29 +09:00
Hare e298856c85 feat: add web console commands 2026-07-14 07:55:51 +09:00
Hare 520c10d807 ui: refine worker console streaming 2026-07-14 04:54:23 +09:00
Hare 1505c5e8a3 docs: generalize llm-engine comments 2026-07-14 04:14:58 +09:00
Hare ddbcd595ef ticket: close runtime snapshot fix 2026-07-14 02:59:59 +09:00
Hare 6ca0d48327 fix: use live worker observation snapshots 2026-07-14 02:59:52 +09:00
Hare ec951ee5c0 ticket: start runtime snapshot fix 2026-07-14 02:48:47 +09:00
Hare de93d4c3b7 ticket: use live worker snapshots 2026-07-14 02:48:47 +09:00
Hare 1b99b3b4d2 chore: remove "nix build" instruction for development 2026-07-13 23:58:36 +09:00
Hare 1837865b33 runtime: restore from metadata snapshot 2026-07-13 23:56:16 +09:00
Hare bedf087455 ticket: start restore profile decoupling 2026-07-13 23:45:04 +09:00
Hare f93e734c57 ticket: restore without profile fetch 2026-07-13 23:45:03 +09:00
Hare 2e66655652 workspace: render console snapshot entries 2026-07-13 23:30:48 +09:00
Hare bbb79afdd8 ticket: start console snapshot rendering 2026-07-13 23:18:30 +09:00
Hare cdf46bd8eb ticket: render console snapshot entries 2026-07-13 23:18:30 +09:00
Hare 34856b9900 workspace: stop worker before cleanup delete 2026-07-13 23:05:46 +09:00
Hare f5b200d36b ticket: start worker cleanup stop 2026-07-13 22:58:54 +09:00
Hare 9c3677ff67 ticket: stop worker before cleanup delete 2026-07-13 22:58:54 +09:00
Hare 498337317c workspace: stabilize cleanup plan digest 2026-07-13 22:38:35 +09:00
Hare 655cdf9533 ticket: start cleanup plan stabilization 2026-07-13 22:30:39 +09:00
Hare 1b9d8c91c3 ticket: stabilize cleanup plan ordering 2026-07-13 22:30:39 +09:00
Hare 59524679c1 workspace: type workdir cleanup status 2026-07-13 21:57:20 +09:00
Hare daa06f98fb ticket: start typed workdir cleanup 2026-07-13 21:46:05 +09:00
Hare 2061c810db ticket: type workdir cleanup status 2026-07-13 21:46:05 +09:00
Hare 80a84b854c ticket: close completed runtime work 2026-07-13 21:45:11 +09:00
Hare f88ee692c9 workspace: allow not-found workdir cleanup 2026-07-13 20:54:33 +09:00
Hare b583af4dd3 ticket: start not-found workdir cleanup 2026-07-13 20:44:18 +09:00
Hare 81ceb1ceff ticket: allow not-found workdir cleanup 2026-07-13 20:44:18 +09:00
Hare da0fe7c81f runtime: preserve typed workdir errors 2026-07-13 20:17:09 +09:00
Hare 72c7beb9c7 ticket: start workdir error preservation 2026-07-13 19:59:02 +09:00
Hare 490d5ed674 ticket: preserve typed workdir errors 2026-07-13 19:59:02 +09:00
Hare 60c772ec38 workspace: show backend error details 2026-07-13 19:51:28 +09:00
Hare fb0d5aeaa9 ticket: start backend error details 2026-07-13 19:46:30 +09:00
Hare ec4b404580 ticket: show backend error details 2026-07-13 19:46:30 +09:00
Hare 6b91d83fe2 runtime: normalize filesystem options 2026-07-13 19:06:26 +09:00
Hare b82407816e runtime: remove workspace cwd options 2026-07-13 18:31:54 +09:00
Hare f54ba6950c ticket: start runtime option cleanup 2026-07-13 18:22:30 +09:00
Hare a5e38f5964 ticket: remove runtime workspace cwd options 2026-07-13 18:22:30 +09:00
Hare 49f085916e runtime: remove runtime-owned id 2026-07-13 17:38:09 +09:00
Hare 6fedf81785 ticket: start runtime id removal 2026-07-13 16:43:36 +09:00
Hare 6af7f61247 ticket: remove runtime-owned id 2026-07-13 16:43:36 +09:00
Hare 4a90267ebc workspace: remove input readiness capability 2026-07-12 23:43:44 +09:00
Hare c948b669c1 runtime: restore persisted worker execution 2026-07-12 23:38:56 +09:00
Hare c56b8c04ea ticket: start runtime worker restore 2026-07-12 23:16:14 +09:00
Hare 8b235b6cf5 ticket: add runtime worker restore plan 2026-07-12 23:16:05 +09:00
Hare 59b1b3df79 workspace: gate workdir assignment 2026-07-12 20:07:32 +09:00
Hare 21802d68f8 workspace: finalize workdir deletion flow 2026-07-12 16:33:14 +09:00
Hare 52cccc7f2f workspace: track workdir observation state 2026-07-12 12:32:24 +09:00
Hare 3009bb4ad9 workspace: delete workers through runtime 2026-07-12 09:06:59 +09:00
Hare d8c0853d55 workspace: refine runtime and cleanup lists 2026-07-12 06:57:10 +09:00
Hare c5aae4b234 workspace: use opaque numeric worker ids 2026-07-12 05:07:39 +09:00
Hare 664f8693a0 ticket: close worker display name preservation 2026-07-11 17:44:32 +09:00
Hare 88d819591e workspace: preserve worker display names 2026-07-11 17:44:23 +09:00
Hare 593d3309d9 ticket: preserve worker display names 2026-07-11 17:31:54 +09:00
Hare 32d1ae597e ticket: close archived worker console links 2026-07-11 16:01:41 +09:00
Hare 30d15daddf workspace: disable archived worker console links 2026-07-11 16:01:29 +09:00
Hare d8412d022b ticket: disable archived worker console links 2026-07-11 15:52:17 +09:00
Hare d53bfd8087 ticket: close worker status removal 2026-07-11 15:22:34 +09:00
Hare 2d2c29a775 workspace: remove worker status field 2026-07-11 15:22:23 +09:00
Hare 69560addf8 ticket: remove worker status field 2026-07-11 15:06:13 +09:00
Hare b6bb22f956 merge: orchestration 2026-07-11 13:44:15 +09:00
Hare 6823f0e72d ticket: close worker lifecycle state removal 2026-07-11 13:34:08 +09:00
Hare b877c92975 workspace: remove worker lifecycle state 2026-07-11 13:33:49 +09:00
Hare 13f9e0fab8 ticket: remove worker lifecycle state 2026-07-11 13:09:06 +09:00
Hare 7d3b364728 ticket: close workspace backend work 2026-07-11 10:10:05 +09:00
Hare 391f11fc23 merge: workspace backend worker context 2026-07-11 10:07:19 +09:00
Hare 5d4cb9b3fe ticket: approve workspace backend implementation 2026-07-11 10:07:12 +09:00
Hare 0736de6451 ticket: record workspace backend implementation 2026-07-11 10:00:03 +09:00
Hare 142b60e1b3 refactor: separate worker workspace identity 2026-07-11 09:58:20 +09:00
Hare a98e25eda8 ticket: close observation cursor removal 2026-07-11 09:31:57 +09:00
Hare 10762a3c8b workspace: remove observation cursor surface 2026-07-11 09:31:49 +09:00
Hare 74b07bd787 ticket: accept workspace backend work 2026-07-11 09:15:16 +09:00
Hare 14e704b858 ticket: close embedded no-workdir policy work 2026-07-11 09:13:58 +09:00
Hare 2f7b809401 merge: embedded no-workdir worker policy 2026-07-11 09:12:34 +09:00
Hare 50eec7885a ticket: approve embedded no-workdir policy 2026-07-11 09:12:29 +09:00
Hare 54eaa44681 ticket: remove observation cursor surface 2026-07-11 09:09:33 +09:00
Hare 7223cab0b2 ticket: record embedded no-workdir implementation 2026-07-11 09:01:00 +09:00
Hare 10267869ae feat: enforce embedded no-workdir worker policy 2026-07-11 08:59:19 +09:00
Hare 1d7765d9ee ticket: close observation replay removal 2026-07-11 08:50:55 +09:00
Hare 7d393f8c98 ticket: finish observation replay removal 2026-07-11 08:50:55 +09:00
Hare 8a3fca65f2 workspace: remove observation replay 2026-07-11 08:50:42 +09:00
Hare 83c9d8844d ticket: route embedded no-workdir worker work 2026-07-11 08:38:59 +09:00
Hare 3a0600be0f ticket: remove observation replay 2026-07-11 08:35:04 +09:00
Hare 0e01e5c84b workspace: align console colors with tui 2026-07-11 08:18:44 +09:00
Hare 69607d02bc workspace: remove console color rail 2026-07-11 08:05:28 +09:00
Hare 33ae73e7ee ticket: close rich console rendering 2026-07-11 07:46:12 +09:00
Hare db5c1d64d1 workspace: add rich console rendering 2026-07-11 07:46:03 +09:00
Hare 0f2d7263a8 ticket: close worker filesystem authority work 2026-07-11 07:45:08 +09:00
Hare c29e913511 merge: worker filesystem authority 2026-07-11 07:40:45 +09:00
Hare 19a52742a3 ticket: approve worker filesystem authority implementation 2026-07-11 07:40:38 +09:00
Hare 5d07e9b9d5 ticket: console rich rendering 2026-07-11 07:31:41 +09:00
Hare 44410a0fdd ticket: record worker filesystem authority implementation 2026-07-11 07:31:20 +09:00
Hare b50b94612a feat: add explicit worker filesystem authority 2026-07-11 07:30:17 +09:00
Hare 89ba205cac workspace: aggregate console read calls 2026-07-11 07:28:31 +09:00
Hare dbc223e9e0 ticket: close console tool call rendering 2026-07-11 07:17:10 +09:00
Hare 2a6930a946 workspace: group console tool calls 2026-07-11 07:17:03 +09:00
Hare a5417320eb ticket: console tool call rendering 2026-07-11 07:09:21 +09:00
Hare a38fcdf04d ticket: hold workspace backend work for authority base 2026-07-11 07:04:02 +09:00
Hare 4b2e03d7cc ticket: queue 00001KX6Y6ZEA 2026-07-11 07:03:28 +09:00
Hare 603a717e40 merge: sync orchestration before queue 00001KX6Y6ZEA 2026-07-11 07:03:27 +09:00
Hare e6b5013224 ticket: ready worker workspace backend 2026-07-11 07:01:46 +09:00
Hare 3ee9469c1a ticket: hold embedded no-workdir policy for authority base 2026-07-11 07:00:37 +09:00
Hare bbcc91db01 ticket: require workspace root removal 2026-07-11 07:00:25 +09:00
Hare 366af8c544 ticket: queue 00001KX6WVNPD 2026-07-11 07:00:07 +09:00
Hare 505bbd7cc9 merge: sync orchestration before queue 00001KX6WVNPD 2026-07-11 07:00:07 +09:00
Hare e4653f7a2d ticket: ready embedded no-workdir worker 2026-07-11 06:59:20 +09:00
Hare f7191056b7 ticket: align embedded policy with filesystem authority 2026-07-11 06:54:22 +09:00
Hare db3a7165f7 ticket: accept worker filesystem authority work 2026-07-11 06:51:37 +09:00
Hare 5c228a7fae ticket: queue 00001KX6Y2A9Q 2026-07-11 06:51:00 +09:00
Hare e40445b07a ticket: ready worker filesystem authority 2026-07-11 06:49:37 +09:00
Hare 3df1c2dcfa ticket: require cwd authority removal 2026-07-11 06:46:25 +09:00
Hare 6fa3d9d21f ticket: normalize worker authority priority 2026-07-11 06:34:18 +09:00
Hare 358fb32fe7 ticket: clarify worker workspace identity 2026-07-11 06:23:30 +09:00
Hare 632a3310ea ticket: worker workspace backend 2026-07-11 06:16:53 +09:00
Hare 9d6400cf2f ticket: worker filesystem authority 2026-07-11 06:14:22 +09:00
Hare c44bdb286a ticket: embedded no-workdir worker authority 2026-07-11 05:53:24 +09:00
Hare cab6a5300d merge: orchestration 2026-07-11 04:52:53 +09:00
Hare 254360f1ab profile: remove lua profile resolver 2026-07-11 04:44:32 +09:00
Hare 156f8ad044 runtime: remove worker transcript projection 2026-07-11 03:55:44 +09:00
Hare 1262b6022a ticket: close manual cleanup work 2026-07-11 03:37:44 +09:00
Hare 4970a58c5a merge: manual worker workdir cleanup
# Conflicts:
#	.yoi/tickets/00001KX6CRVBE/item.md
#	.yoi/tickets/00001KX6CRVBE/thread.md
2026-07-11 03:36:24 +09:00
Hare 1b4d336d80 ticket: approve manual cleanup implementation 2026-07-11 03:36:14 +09:00
Hare c961185635 ticket: record manual cleanup safety fix 2026-07-11 03:30:57 +09:00
Hare 361569a69e fix: require discard confirmation for unknown workdirs 2026-07-11 03:30:08 +09:00
Hare 29ddc168a3 ticket: record manual cleanup review blocker 2026-07-11 03:19:16 +09:00
Hare 85da6a6c33 ticket: record manual cleanup implementation evidence 2026-07-11 03:13:44 +09:00
Hare ba44391acf feat: add manual worker workdir cleanup 2026-07-11 03:12:51 +09:00
Hare 5f762a6ce3 ticket: accept manual cleanup work 2026-07-11 02:39:10 +09:00
Hare dcab396e69 ticket: close worker workdir registry work 2026-07-11 02:38:25 +09:00
Hare 03652f8210 merge: worker workdir registry
# Conflicts:
#	.yoi/tickets/00001KX6BPY7M/item.md
#	.yoi/tickets/00001KX6BPY7M/thread.md
2026-07-11 02:35:48 +09:00
Hare 763709fdf8 ticket: approve worker workdir registry implementation 2026-07-11 02:35:34 +09:00
Hare 26e4efc990 ticket: record unmanaged workdir fix pass 2026-07-11 02:32:07 +09:00
Hare 239f93b084 fix: keep unmanaged workdirs out of managed lists 2026-07-11 02:31:29 +09:00
Hare d9b3eb0e8b ticket: record unmanaged workdir review blocker 2026-07-11 02:22:18 +09:00
Hare e6b52b045a ticket: record worker workdir registry fix pass 2026-07-11 02:14:06 +09:00
Hare 8695089fba fix: sync backend worker registry projections 2026-07-11 02:13:00 +09:00
Hare 522c7043b1 ticket: record worker workdir registry review blockers 2026-07-11 01:52:34 +09:00
Hare 210f41e020 objective: clarify worker cleanup retention 2026-07-11 01:48:49 +09:00
Hare 1ed0501f8e ticket: hold cleanup work for registry review 2026-07-11 01:46:14 +09:00
Hare 234d62bbef ticket: queue 00001KX6CRVBE 2026-07-11 01:45:14 +09:00
Hare 5f669b90ef merge: sync orchestration before queue 00001KX6CRVBE 2026-07-11 01:45:14 +09:00
Hare db8cfa8142 ticket: ready manual worker workdir cleanup 2026-07-11 01:44:28 +09:00
Hare c949e1b4f2 ticket: simplify worker delete lifecycle 2026-07-11 01:43:46 +09:00
Hare c2afaefb5f ticket: record worker workdir registry implementation evidence 2026-07-11 01:40:24 +09:00
Hare 3e5546ea33 feat: add backend worker workdir registry 2026-07-11 01:38:23 +09:00
Hare c88283dbe5 ticket: include worker pinning in manual prune 2026-07-11 01:31:22 +09:00
Hare 1564d7e411 ticket: route worker workdir registry coder 2026-07-11 01:13:26 +09:00
Hare 452d07273c ticket: manual worker workdir prune 2026-07-11 01:12:43 +09:00
Hare 86f652a72f ticket: accept worker workdir registry work 2026-07-11 01:12:18 +09:00
Hare 651422e0c8 ticket: queue 00001KX6BPY7M 2026-07-11 01:10:57 +09:00
Hare fe66437589 ticket: ready backend worker workdir registry 2026-07-11 01:06:19 +09:00
Hare 04cb2f700d ticket: backend worker workdir registry 2026-07-11 00:54:35 +09:00
Hare 24156947ac ui: add runtime workdir pages 2026-07-11 00:15:49 +09:00
Hare 47e03bd54b ui: move workers list to page 2026-07-10 12:06:10 +09:00
Hare a3cb59af43 ui: move worker launch to page 2026-07-10 10:32:44 +09:00
Hare d149f7e936 runtime: namespace spawned worker names 2026-07-10 04:18:14 +09:00
Hare 611f1656a3 profile: inherit default model for roles 2026-07-10 03:58:45 +09:00
Hare 69fd11a233 runtime: use workspace id for profile archives 2026-07-10 03:14:15 +09:00
Hare 9f6abb675c runtime: tolerate corrupt worker snapshots 2026-07-10 02:51:55 +09:00
Hare c3afcc7491 runtime: fetch profile archives for remote workers 2026-07-10 01:32:26 +09:00
Hare ef0799c278 merge: orchestration 2026-07-09 19:24:12 +09:00
Hare d216b10100 runtime: default working directories to data dir 2026-07-09 19:24:04 +09:00
Hare fa233ba025 runtime: own working directories 2026-07-09 19:04:37 +09:00
Hare 36454e831b ticket: close profile source tree work 2026-07-09 18:18:57 +09:00
Hare 9a2e57fb0e merge: profile source tree editor
# Conflicts:
#	.yoi/tickets/00001KX1JNJ2Y/item.md
#	.yoi/tickets/00001KX1JNJ2Y/thread.md
2026-07-09 18:16:49 +09:00
Hare dccfe539ef ticket: approve profile source tree work 2026-07-09 18:16:38 +09:00
Hare ae227c7e4d ticket: record profile source tree symlink fix 2026-07-09 18:10:08 +09:00
Hare 13c6548b46 fix: reject profile source root symlinks 2026-07-09 18:08:31 +09:00
Hare 2dfad3500f ticket: record profile source tree symlink blocker 2026-07-09 17:57:33 +09:00
Hare c5a9f8a0ab ticket: record profile source tree review fixes 2026-07-09 17:52:24 +09:00
Hare 941b91261b fix: complete profile source tree review fixes 2026-07-09 17:47:19 +09:00
Hare 0458af721f ticket: record profile source tree review blockers 2026-07-09 17:32:43 +09:00
Hare 129079cad4 ticket: record profile source tree implementation evidence 2026-07-09 17:28:23 +09:00
Hare 81abfa630a feat: add profile source tree editor 2026-07-09 17:22:57 +09:00
Hare ce2ccce98e ticket: route profile source tree coder 2026-07-09 16:59:00 +09:00
Hare 7da14f1a8d ticket: accept profile source tree work 2026-07-09 16:58:08 +09:00
Hare afc43780a7 ticket: queue 00001KX1JNJ2Y 2026-07-09 16:56:07 +09:00
Hare b06e1b3dc2 ticket: ready profile source tree editor 2026-07-09 16:18:33 +09:00
Hare 23ab100d20 ticket: include decodal source editor 2026-07-09 04:21:52 +09:00
Hare 1400ebd2f1 ticket: profile source tree virtual fs 2026-07-09 04:19:30 +09:00
Hare 292ad2c202 ui: split workspace settings routes 2026-07-09 01:23:34 +09:00
Hare 981f0501a3 merge: backend resource and profile settings 2026-07-08 23:11:54 +09:00
Hare f3cd632b64 ticket: backend memory observation pipeline 2026-07-08 22:46:50 +09:00
Hare 5c862ca12a ticket: close workspace profile settings work 2026-07-08 22:20:36 +09:00
Hare 0bf3638c64 merge: workspace profile settings
# Conflicts:
#	.yoi/tickets/00001KX0DSMPT/item.md
#	.yoi/tickets/00001KX0DSMPT/thread.md
2026-07-08 22:19:14 +09:00
Hare 137234fae0 ticket: approve profile settings implementation 2026-07-08 22:19:04 +09:00
Hare bfba61cee6 ticket: record profile settings review fixes 2026-07-08 22:07:45 +09:00
Hare 0c2ca1eafb fix: harden profile settings validation 2026-07-08 22:06:12 +09:00
Hare 1a8824613b ticket: record profile settings review blockers 2026-07-08 21:49:19 +09:00
Hare e8048e6dc3 ticket: record profile settings implementation evidence 2026-07-08 21:40:15 +09:00
Hare 3eefd33334 feat: add workspace profile settings 2026-07-08 21:38:23 +09:00
Hare 950427a135 ticket: backend ticket objective api 2026-07-08 21:28:11 +09:00
Hare 3abaf51a66 ticket: record profile settings coder recovery 2026-07-08 21:03:33 +09:00
Hare 620e37da8b ticket: route workspace profile settings coder 2026-07-08 20:58:26 +09:00
Hare c903beee69 ticket: accept workspace profile settings work 2026-07-08 20:56:51 +09:00
Hare a645ee5b79 ticket: close backend resource fetch work 2026-07-08 20:55:03 +09:00
Hare 01f94b7591 merge: backend resource fetch api 2026-07-08 20:53:12 +09:00
Hare fd1ab4bad8 ticket: approve backend resource fetch work 2026-07-08 20:53:12 +09:00
Hare 237c75448c ticket: record backend resource fetch review fixes 2026-07-08 20:45:52 +09:00
Hare e716ae44f0 fix: harden backend resource handles 2026-07-08 20:44:04 +09:00
Hare a0ef9a9f82 ticket: record backend resource fetch review blockers 2026-07-08 20:27:33 +09:00
Hare 595da68751 ticket: record backend resource fetch implementation evidence 2026-07-08 20:20:32 +09:00
Hare 57e96d3be8 feat: add backend resource fetch api 2026-07-08 20:18:38 +09:00
Hare 352be1f4c7 ticket: hold profile settings for resource fetch 2026-07-08 19:45:57 +09:00
Hare 98f6bd14b3 ticket: queue 00001KX0DSMPT 2026-07-08 19:44:13 +09:00
Hare 813af7b4c4 merge: sync orchestration before queue 00001KX0DSMPT 2026-07-08 19:44:12 +09:00
Hare 92adee2ada ticket: route backend resource fetch coder 2026-07-08 19:40:33 +09:00
Hare 0c8b5b962c ticket: ready workspace profile settings 2026-07-08 19:40:06 +09:00
Hare 2109ad1021 ticket: use plain text profile editor 2026-07-08 19:39:46 +09:00
Hare 1a2097b10d ticket: accept backend resource fetch work 2026-07-08 19:39:25 +09:00
Hare ffc16deac2 ticket: close decodal profile archive work 2026-07-08 19:35:46 +09:00
Hare 0334c5725e merge: decodal profile archives
# Conflicts:
#	.yoi/tickets/00001KWZ5KERY/item.md
#	.yoi/tickets/00001KWZ5KERY/thread.md
2026-07-08 19:33:39 +09:00
Hare e17c7a5b82 ticket: approve decodal profile archive work 2026-07-08 19:33:27 +09:00
Hare 7f81c6cdf4 ticket: record decodal profile archive review fixes 2026-07-08 19:23:18 +09:00
Hare a2833dadca fix: reject unknown profile archive selectors 2026-07-08 19:21:52 +09:00
Hare 27fa1cc815 ticket: record decodal profile archive review blockers 2026-07-08 19:07:16 +09:00
Hare ab55238d29 ticket: hold backend resource fetch for decodal ordering 2026-07-08 19:05:49 +09:00
Hare 81cf73e452 ticket: queue 00001KX0G06VA 2026-07-08 19:04:10 +09:00
Hare 0dc5fc687f merge: sync orchestration before queue 00001KX0G06VA 2026-07-08 19:04:10 +09:00
Hare 89fdc6b443 ticket: record decodal profile archive implementation evidence 2026-07-08 18:59:39 +09:00
Hare a823d414d0 feat: add decodal profile archives 2026-07-08 18:57:54 +09:00
Hare 048b0af614 ticket: avoid changing active decodal work 2026-07-08 18:44:12 +09:00
Hare 461ae6a89e ticket: ready runtime backend resource rest api 2026-07-08 18:28:04 +09:00
Hare dccd8d03af ticket: route decodal profile archive coder 2026-07-08 18:14:34 +09:00
Hare 63f3129eb7 ticket: add runtime backend resource channel 2026-07-08 18:14:31 +09:00
Hare 56cac3c74a ticket: accept decodal profile archive work 2026-07-08 18:13:24 +09:00
Hare 190f6a2a8f ticket: queue 00001KWZ5KERY 2026-07-08 18:11:22 +09:00
Hare e5fb26ca74 ticket: ready decodal profile archive migration 2026-07-08 18:03:55 +09:00
Hare 1688f2a640 fix: separate profile base from working directory 2026-07-08 18:03:55 +09:00
Hare 061e52c35c ticket: profile source archive migration order 2026-07-08 18:01:34 +09:00
Hare bbe6694122 ticket: workspace profile settings api 2026-07-08 17:35:01 +09:00
Hare a84e968699 ticket: use event driven worker config bundle sync 2026-07-08 15:55:12 +09:00
Hare fb25f1a33d ticket: scope config bundle sync implementation 2026-07-08 06:05:47 +09:00
Hare ebc3804ebd ticket: design config bundle sync strategy 2026-07-08 05:52:40 +09:00
Hare 25900f31cf refactor: remove working directory allocation terminology 2026-07-08 04:56:22 +09:00
Hare 5c33b2f63d ticket: close runtime connection reload 2026-07-08 04:16:57 +09:00
Hare fa219e40b3 merge: browser working directory spawn 2026-07-08 02:27:53 +09:00
Hare 9745bf041c ui: show worker spawn diagnostics 2026-07-08 02:27:19 +09:00
Hare a6fe68301c Merge branch 'develop' into orchestration
# Conflicts:
#	.yoi/objectives/00001KVJPT2PP/item.md
#	.yoi/objectives/00001KWW44EXK/item.md
2026-07-08 01:15:07 +09:00
Hare 40463b6133 refactor: rename execution workspace to working directory 2026-07-08 01:14:14 +09:00
Hare 0cad2308cc ticket: close browser execution workspace work 2026-07-07 23:59:03 +09:00
Hare b52986e55a merge: browser execution workspaces 2026-07-07 23:57:00 +09:00
Hare 7acf06ad23 ticket: approve browser execution workspace work 2026-07-07 23:57:00 +09:00
Hare 55105564bf ticket: record browser execution workspace review fixes 2026-07-07 23:51:40 +09:00
Hare 9adb0fae82 fix: preserve execution workspace cwd diagnostics 2026-07-07 23:50:01 +09:00
Hare a6b93ceabc objective: clarify working directory terminology 2026-07-07 23:41:27 +09:00
Hare 05a592d80b ticket: record browser execution workspace review blocker 2026-07-07 23:37:08 +09:00
Hare 41cc66b11b ticket: record browser execution workspace implementation evidence 2026-07-07 23:23:35 +09:00
Hare 684b19e87c feat: add browser execution workspaces 2026-07-07 23:21:20 +09:00
Hare 57a5af8efd ticket: route browser execution workspace coder 2026-07-07 22:42:57 +09:00
Hare ecf10c72ab ticket: accept browser execution workspace work 2026-07-07 22:41:51 +09:00
Hare 9f1c17d4e9 ticket: queue 00001KWY8EHEJ 2026-07-07 22:40:23 +09:00
Hare 6db5751bbf ticket: ready browser execution workspace spawn 2026-07-07 21:26:40 +09:00
Hare ce773d0fb4 ticket: browser execution workspace spawn 2026-07-07 21:22:42 +09:00
Hare fbc9ba411e merge: workspace id route scoping
# Conflicts:
#	web/workspace/src/lib/workspace-sidebar/WorkspaceSidebar.svelte
2026-07-07 06:27:48 +09:00
Hare 7f6a057e22 ui: refine workspace sidebar controls 2026-07-07 06:19:08 +09:00
Hare 1d88b333a9 ticket: close workspace id route scoping 2026-07-07 05:53:50 +09:00
Hare 13e756e74f merge: workspace id route scoping 2026-07-07 05:52:46 +09:00
Hare f3fdc98319 ticket: approve workspace id route scoping 2026-07-07 05:52:46 +09:00
Hare 3315fa5458 ticket: record workspace id route review fixes 2026-07-07 05:45:40 +09:00
Hare 71340b8999 fix: redirect unscoped workspace routes 2026-07-07 05:44:22 +09:00
Hare a2f2e37585 ticket: record workspace id route review blockers 2026-07-07 05:36:54 +09:00
Hare 55f93fd987 ticket: record workspace id route implementation evidence 2026-07-07 05:27:20 +09:00
Hare f6ad9cfcd3 feat: scope workspace routes by id 2026-07-07 05:26:03 +09:00
Hare ab33c30d7c ticket: route workspace id scoping coder 2026-07-07 04:55:32 +09:00
Hare 34836d97ae ticket: accept workspace id route scoping 2026-07-07 04:54:37 +09:00
Hare 384d162b74 ticket: queue 00001KWWE8E04 2026-07-07 04:53:14 +09:00
Hare 76153b64c7 merge: sync orchestration before queue 00001KWWE8E04 2026-07-07 04:53:14 +09:00
Hare 72ace6e913 ticket: ready workspace scoped routes 2026-07-07 04:48:42 +09:00
Hare 376a43b8ae ticket: close execution workspace materializer 2026-07-07 04:24:31 +09:00
Hare c4cdf1c37e merge: execution workspace materializer 2026-07-07 04:23:08 +09:00
Hare ab19882b8e ticket: approve execution workspace materializer 2026-07-07 04:23:08 +09:00
Hare 673fbeed09 ticket: record execution workspace review fixes 2026-07-07 04:17:23 +09:00
Hare c90ebf2468 fix: keep execution workspace paths internal 2026-07-07 04:16:04 +09:00
Hare 6c4df18da1 ticket: record execution workspace review blocker 2026-07-07 04:06:30 +09:00
Hare 5ef8e4e8ba refactor: move workspace pages into routes 2026-07-07 04:04:37 +09:00
Hare 504090ac99 ticket: record execution workspace implementation evidence 2026-07-07 03:57:46 +09:00
Hare 8b7a5da031 feat: materialize execution workspaces 2026-07-07 03:56:32 +09:00
Hare 9a064117bd ticket: route execution workspace coder 2026-07-07 03:31:17 +09:00
Hare 50c80e7747 ticket: accept execution workspace materializer 2026-07-07 03:30:04 +09:00
Hare 4e72bc6be3 ticket: queue 00001KWW9DYH4 2026-07-07 03:28:26 +09:00
Hare 3cee4116d1 ticket: plan execution workspace materializer 2026-07-07 03:27:12 +09:00
Hare 1f69061956 fix: normalize runtime workspace bootstrap 2026-07-07 03:27:12 +09:00
Hare b6029220ff fix: refine workspace runtime UI 2026-07-06 22:51:25 +09:00
Hare 5279f8fc0d merge: repository registry 2026-07-05 23:51:54 +09:00
Hare 8528c9057a ticket: close repository registry work 2026-07-05 05:19:21 +09:00
Hare a786fd85a7 merge: repository registry implementation 2026-07-05 05:18:01 +09:00
Hare b0334e042b ticket: approve repository registry implementation 2026-07-05 05:18:01 +09:00
Hare 7163ba7197 ticket: record repository registry review fixes 2026-07-05 05:11:36 +09:00
Hare 14e63ca5b6 fix: derive repository UI from registry 2026-07-05 05:10:23 +09:00
Hare a62653e5bc ticket: record repository registry review blockers 2026-07-05 05:03:00 +09:00
Hare 6717ced46a ticket: record repository registry implementation evidence 2026-07-05 04:58:57 +09:00
Hare 2f0d1cee19 feat: add workspace repository registry 2026-07-05 04:57:52 +09:00
Hare 6c2f2e0df3 ticket: route repository registry coder 2026-07-05 04:37:01 +09:00
Hare 416d67ca06 ticket: accept repository registry work 2026-07-05 04:35:55 +09:00
Hare f4d7631f19 ticket: queue 00001KWPC13WQ 2026-07-05 04:34:04 +09:00
Hare 23d3782f38 ticket: ready repository registry 2026-07-04 19:59:11 +09:00
Hare 078f2137b3 docs: update workspace runtime objective 2026-07-04 19:58:50 +09:00
Hare 1ebdf7cf7a ticket: add repository registry work 2026-07-04 19:51:33 +09:00
Hare b3dac8ea68 feat: live reload runtime connections 2026-07-04 04:47:23 +09:00
Hare 296da3a440 ticket: add runtime registry reload 2026-07-04 01:00:28 +09:00
Hare da047d5686 merge: close runtime worker tickets 2026-07-03 03:24:57 +09:00
Hare f28d4d5d3a ticket: close runtime worker tickets 2026-07-03 03:24:57 +09:00
Hare 540e55d499 merge: runtime worker ticket records 2026-07-03 03:20:35 +09:00
Hare 4edaa73dde merge: runtime worker controls 2026-07-03 03:20:35 +09:00
Hare c2c594411d ticket: approve runtime worker implementation 2026-07-03 03:20:17 +09:00
Hare 50016b122c ticket: record runtime worker review fixes 2026-07-03 03:11:16 +09:00
Hare 47ed0ff825 fix: harden runtime and worker launch controls 2026-07-03 02:54:48 +09:00
Hare f28be76ab6 ticket: record runtime worker review blockers 2026-07-03 02:36:49 +09:00
Hare 64f1780ede ticket: record runtime worker implementation evidence 2026-07-03 02:29:39 +09:00
Hare f2fead7ebd feat: add workspace runtime and worker controls 2026-07-03 02:27:42 +09:00
Hare 4267084d5a ticket: record combined coder routing 2026-07-03 02:03:34 +09:00
Hare 2eb90470bb ticket: accept runtime and worker tickets 2026-07-03 02:01:21 +09:00
Hare 69563cc2f9 ticket: queue 00001KWHHRTM9 2026-07-03 01:45:19 +09:00
Hare dc1f68903d ticket: ready runtime connection management 2026-07-03 01:45:18 +09:00
Hare 9f2c9ac048 ticket: queue 00001KWHEM8YJ 2026-07-03 01:13:24 +09:00
Hare 73f76170ef merge: sync orchestration before queue 00001KWHEM8YJ 2026-07-03 01:13:24 +09:00
Hare d276e27e81 ticket: ready manual coding worker launch 2026-07-03 00:39:49 +09:00
Hare 578ea261a4 ticket: plan runtime connection negotiation 2026-07-03 00:29:58 +09:00
Hare d1e8333551 ticket: record settings admin shell cleanup 2026-07-02 23:39:08 +09:00
Hare 9f9c65bea6 ticket: close settings admin shell 2026-07-02 23:38:40 +09:00
Hare fdad94afbf merge: settings admin shell 2026-07-02 23:37:46 +09:00
Hare fca13aab7a ticket: approve settings admin shell 2026-07-02 23:37:35 +09:00
Hare 02fc884fad ticket: record settings reviewer spawn failure 2026-07-02 23:36:48 +09:00
Hare 9006eb8228 ticket: record settings admin shell implementation 2026-07-02 23:36:17 +09:00
Hare c0c6880b1a feat: add settings admin shell 2026-07-02 23:34:30 +09:00
Hare b2f8f16949 ticket: record settings coder spawn failure 2026-07-02 23:26:45 +09:00
Hare bcf71f588d ticket: accept settings admin shell 2026-07-02 23:25:53 +09:00
Hare fee175fc72 ticket: queue 00001KWHJ0XH6 2026-07-02 23:24:54 +09:00
Hare 109b74da42 ticket: ready settings admin shell 2026-07-02 23:18:50 +09:00
Hare 7a0eb1566a ticket: close worker console redesign 2026-07-02 21:16:11 +09:00
Hare 8e449acd59 feat: manage workspace backend local config 2026-07-02 21:02:45 +09:00
Hare da631029cb feat: add explicit workspace init 2026-07-02 18:20:38 +09:00
Hare 5002be498f ticket: plan workspace init command 2026-07-02 18:03:55 +09:00
Hare a123db83ad feat: install workspace backend config template 2026-07-02 01:38:47 +09:00
Hare 8b1e4b721f ticket: close workspace backend config schema 2026-07-02 00:48:28 +09:00
Hare 5a8d18ec27 feat: add workspace backend config schema 2026-07-02 00:48:17 +09:00
Hare 52b445e6bc ticket: define workspace backend config schema 2026-07-02 00:30:24 +09:00
Hare 9ae9b0a043 ui: filter worker console protocol noise 2026-07-01 23:32:39 +09:00
Hare 11d94d3866 merge: worker runtime orchestration 2026-06-29 11:53:52 +09:00
Hare 3a41581c5c ticket: record old pod crate cleanup cleanup 2026-06-29 05:10:57 +09:00
Hare 0bdb55e658 ticket: close old pod crate cleanup 2026-06-29 05:10:33 +09:00
Hare 83d433bf7e merge: old pod crate cleanup 2026-06-29 05:04:59 +09:00
Hare 9582a1761d ticket: approve old pod crate cleanup 2026-06-29 05:04:52 +09:00
Hare 9b0fe97cd9 ticket: record e2e worker metadata root fix 2026-06-29 05:02:34 +09:00
Hare fdd902d534 fix: align e2e worker metadata root 2026-06-29 05:01:56 +09:00
Hare c8a5b8d53d ticket: request e2e worker metadata root fix 2026-06-29 05:00:17 +09:00
Hare 95523dc66f ticket: record old pod cleanup wording fix 2026-06-29 04:55:15 +09:00
Hare c46e880b50 fix: finish worker wording cleanup 2026-06-29 04:54:33 +09:00
Hare 5e08d328d5 ticket: route old pod cleanup fixes 2026-06-29 04:51:41 +09:00
Hare 4f57beda7a ticket: request old pod cleanup wording fixes 2026-06-29 04:51:07 +09:00
Hare 094a728b8a ticket: start old pod crate cleanup review 2026-06-29 04:46:34 +09:00
Hare a5be6b758c ticket: record old pod crate cleanup implementation 2026-06-29 04:46:06 +09:00
Hare 17a9488a4a refactor: remove old pod crates 2026-06-29 04:44:55 +09:00
Hare 1fa85fb89c ticket: start old pod crate cleanup 2026-06-29 04:18:47 +09:00
Hare 0fd99075f0 ticket: accept old pod crate cleanup 2026-06-29 04:17:41 +09:00
Hare 9eda90067e ticket: record embedded runtime fs-store cleanup 2026-06-29 04:16:57 +09:00
Hare 44be40451b ticket: close embedded runtime fs-store 2026-06-29 04:16:35 +09:00
Hare 888e7b68e5 merge: embedded runtime fs-store 2026-06-29 04:15:25 +09:00
Hare ac42a6477b ticket: approve embedded runtime fs-store 2026-06-29 04:15:17 +09:00
Hare 24118a0f3c ticket: start embedded runtime fs-store review 2026-06-29 04:06:13 +09:00
Hare 6871c19f39 ticket: record embedded runtime fs-store implementation 2026-06-29 04:05:51 +09:00
Hare 736b05c670 feat: persist embedded workspace runtime in fs store 2026-06-29 04:05:02 +09:00
Hare 6a448de618 ticket: start embedded runtime fs-store 2026-06-29 03:41:03 +09:00
Hare e3ad8b6e08 ticket: accept embedded runtime fs-store 2026-06-29 03:40:26 +09:00
Hare d65bc9395e ticket: record runtime worker launch cleanup 2026-06-29 03:39:30 +09:00
Hare 88ef627b6b ticket: close runtime worker launch unification 2026-06-29 03:39:07 +09:00
Hare bdb339fab8 merge: runtime worker launch unification 2026-06-29 03:37:45 +09:00
Hare b246cd97f7 ticket: approve runtime worker launch unification 2026-06-29 03:37:41 +09:00
Hare 9546542c15 ticket: record remote runtime projection fix 2026-06-29 03:35:17 +09:00
Hare ba7f9d2ee8 workspace: respect remote execution projection 2026-06-29 03:34:16 +09:00
Hare 7f0255baf5 ticket: request remote runtime projection fix 2026-06-29 03:17:11 +09:00
Hare 4dfe2394c5 ticket: record runtime worker launch fix 2026-06-29 03:12:06 +09:00
Hare c29d10b67b runtime: persist execution binding projection 2026-06-29 03:11:16 +09:00
Hare f340c6badc ticket: request runtime worker launch changes 2026-06-29 02:51:17 +09:00
Hare ea9f637747 ticket: start runtime worker launch review 2026-06-29 02:46:36 +09:00
Hare c060f5fe50 ticket: record runtime worker launch implementation 2026-06-29 02:46:11 +09:00
Hare 14bb4934a6 runtime: unify worker creation path 2026-06-29 02:44:52 +09:00
Hare eaf17ecb1b ticket: block embedded runtime fs-store on launch unification 2026-06-29 02:12:45 +09:00
Hare 4df3585190 chore: ignore worktree directories 2026-06-29 02:12:29 +09:00
Hare 7d751abc0f ticket: queue 00001KW76E8EG 2026-06-29 02:12:16 +09:00
Hare df8ada7003 merge: sync orchestration before queue 00001KW76E8EG 2026-06-29 02:12:16 +09:00
Hare 300a032562 ticket: ready embedded runtime fs-store 2026-06-29 02:11:13 +09:00
Hare b34bbf6482 ticket: block old pod crate cleanup on launch unification 2026-06-29 01:51:26 +09:00
Hare 445a40d5e7 ticket: queue 00001KW7835H0 2026-06-29 01:51:00 +09:00
Hare 539ee7ef72 merge: sync orchestration before queue 00001KW7835H0 2026-06-29 01:51:00 +09:00
Hare c2941af88a ticket: start runtime worker launch unification 2026-06-29 01:49:14 +09:00
Hare 9c8fb7dea6 ticket: accept runtime worker launch unification 2026-06-29 01:48:30 +09:00
Hare 262fc7f257 ticket: ready remove old pod crates 2026-06-29 01:48:14 +09:00
Hare ecc876b6c1 ticket: queue 00001KW7726H9 2026-06-29 01:47:42 +09:00
Hare 91e5fb41b5 ticket: ready runtime worker startup path 2026-06-29 01:45:14 +09:00
Hare 0602efd3b7 ui: simplify worker console 2026-06-28 22:41:32 +09:00
Hare 05d39e05c7 test: align companion execution assertions 2026-06-28 16:55:34 +09:00
Hare e7d56bba73 merge: embedded worker execution 2026-06-28 16:47:39 +09:00
Hare e5b539faee ticket: record companion llm cleanup 2026-06-28 16:20:27 +09:00
Hare 9c54bfe997 ticket: close workspace companion llm worker 2026-06-28 16:19:54 +09:00
Hare eb06b8a923 merge: workspace companion llm worker 2026-06-28 16:18:48 +09:00
Hare a21a62301d ticket: approve workspace companion llm worker 2026-06-28 16:18:41 +09:00
Hare 169a8d501e ticket: record companion workspace status fix 2026-06-28 16:14:20 +09:00
Hare 3be193223c fix: report companion console runtime status 2026-06-28 16:13:33 +09:00
Hare f00252c8aa ticket: request companion workspace status fix 2026-06-28 16:05:58 +09:00
Hare d09a6f5da1 ticket: record companion llm implementation 2026-06-28 15:56:54 +09:00
Hare ee25cfbcfd fix: route workspace companion through worker runtime 2026-06-28 15:56:00 +09:00
Hare dc8d8a0df5 ticket: request companion llm changes 2026-06-28 15:27:12 +09:00
Hare 05f1e1ed39 ticket: start companion llm review 2026-06-28 15:21:04 +09:00
Hare b43e6b7eee ticket: record companion llm verification pass 2026-06-28 15:20:36 +09:00
Hare 865d1092a0 ticket: record companion coder context error 2026-06-28 15:09:58 +09:00
Hare d91168825c ticket: start workspace companion llm worker 2026-06-28 15:04:06 +09:00
Hare 0c5a769abb ticket: accept workspace companion llm worker 2026-06-28 15:02:59 +09:00
Hare 9c3347f0ec ticket: record worker adapter cleanup 2026-06-28 15:02:21 +09:00
Hare 235cd88db9 ticket: close worker adapter 2026-06-28 06:45:04 +09:00
Hare c3ed223dfd merge: worker runtime worker adapter 2026-06-28 06:42:32 +09:00
Hare 1ab270ba46 ticket: approve worker adapter 2026-06-28 06:42:27 +09:00
Hare a45797baff ticket: record worker adapter spawn failure fix 2026-06-28 06:39:58 +09:00
Hare 7e29ff5ec9 fix: reject embedded spawn execution failures 2026-06-28 06:39:03 +09:00
Hare d02007c993 ticket: request worker adapter spawn failure fix 2026-06-28 06:27:40 +09:00
Hare d549b4bd08 ticket: record worker adapter fix 2026-06-28 06:22:05 +09:00
Hare 9069b03504 fix: connect embedded runtime input lifecycle 2026-06-28 06:20:34 +09:00
Hare af1a1eb836 ticket: request worker adapter changes 2026-06-28 05:58:09 +09:00
Hare ca4498e001 ticket: start worker adapter review 2026-06-28 05:51:46 +09:00
Hare 2d275de3cc ticket: record worker adapter implementation 2026-06-28 05:51:18 +09:00
Hare 18526ee362 feat: connect runtime worker execution adapter 2026-06-28 05:50:11 +09:00
Hare 1c4e7e5198 ticket: start worker runtime worker adapter 2026-06-28 05:12:36 +09:00
Hare e1e9fcb326 ticket: accept worker runtime worker adapter 2026-06-28 05:11:47 +09:00
Hare 435863a07f ticket: record worker execution backend cleanup 2026-06-28 05:09:48 +09:00
Hare 655c0a3ec6 ticket: close worker execution backend 2026-06-28 04:49:51 +09:00
Hare 0753e155a5 merge: worker runtime execution backend 2026-06-28 04:48:38 +09:00
Hare d7d1fbbdcb ticket: approve worker execution backend 2026-06-28 04:48:34 +09:00
Hare f7448c832e ticket: record worker execution backend fix 2026-06-28 04:46:48 +09:00
Hare 761b60c857 fix: initialize restored worker observations 2026-06-28 04:46:08 +09:00
Hare b6bfad7f8b ticket: request worker execution backend changes 2026-06-28 04:41:14 +09:00
Hare 4240bd29bb ticket: start worker execution backend review 2026-06-28 04:36:16 +09:00
Hare c242841957 ticket: record worker execution backend implementation 2026-06-28 04:34:29 +09:00
Hare 2d59717384 feat: add worker execution backend boundary 2026-06-28 04:33:01 +09:00
Hare 5420265236 ticket: start worker runtime execution boundary 2026-06-28 04:09:48 +09:00
Hare 9929d1c704 ticket: accept worker runtime execution boundary 2026-06-28 04:08:53 +09:00
Hare 62ce777cf8 ticket: queue 00001KW55B33H 2026-06-28 04:06:32 +09:00
Hare 6bfeb6d945 ticket: queue 00001KW55B33B 2026-06-28 04:06:30 +09:00
Hare e1f14a920d ticket: queue 00001KW55B32Y 2026-06-28 04:06:28 +09:00
Hare 3836639825 ticket: ready embedded worker execution 2026-06-28 04:06:24 +09:00
Hare d86b1fb06d ticket: plan embedded worker execution 2026-06-28 03:29:57 +09:00
Hare 2fb7514daa runtime: remove fake companion responses 2026-06-28 03:06:12 +09:00
Hare 67df7d1a53 runtime: make worker console observation required 2026-06-28 02:11:43 +09:00
Hare 135667417b ui: remove legacy local worker projection 2026-06-27 18:31:17 +09:00
Hare 62420b7cc4 merge: worker console redesign
# Conflicts:
#	web/workspace/src/lib/workspace-sidebar/WorkersNavSection.svelte
2026-06-27 03:26:48 +09:00
Hare 7d90cb644d ui: compact workspace overview 2026-06-27 03:25:28 +09:00
Hare 18aa07446e ticket: record worker console cleanup 2026-06-27 03:22:58 +09:00
Hare 29d6209ea4 ticket: mark worker console redesign done 2026-06-27 03:22:17 +09:00
Hare 864efe32e4 merge: 00001KW2GCPYF worker console redesign 2026-06-27 03:21:24 +09:00
Hare 867a8ee55b ticket: approve worker console redesign 2026-06-27 03:21:24 +09:00
Hare 10322595c6 ticket: record worker console refresh fix 2026-06-27 03:19:21 +09:00
Hare a1083908b6 fix: stabilize worker console refresh 2026-06-27 03:18:26 +09:00
Hare f98dc7d7ca ticket: request worker console effect fix 2026-06-27 03:12:02 +09:00
Hare a342dfb9d2 ticket: record worker console implementation 2026-06-27 03:07:28 +09:00
Hare c3fed59109 feat: worker attach workspace console 2026-06-27 03:06:10 +09:00
Hare f070b9e56f ticket: start worker console redesign 2026-06-27 02:47:34 +09:00
Hare f64e11b854 ticket: accept worker console redesign 2026-06-27 02:46:44 +09:00
Hare 816c79290f ticket: close runtime migration batch 2026-06-27 02:46:11 +09:00
Hare 22a2350126 ticket: queue 00001KW2GCPYF 2026-06-27 02:45:40 +09:00
Hare 971d2f832f ticket: plan worker console redesign 2026-06-27 02:45:26 +09:00
Hare 390b914268 merge: runtime backend orchestration updates 2026-06-27 01:28:11 +09:00
Hare aaf3cc8391 ticket: record tui runtime migration cleanup 2026-06-26 17:55:36 +09:00
Hare 3f6d5f29b8 ticket: mark tui runtime migration done 2026-06-26 17:54:53 +09:00
Hare 0a683bb227 merge: 00001KW04A8K6 tui runtime migration 2026-06-26 17:52:55 +09:00
Hare bd211d55fd ticket: approve tui runtime migration 2026-06-26 17:52:55 +09:00
Hare 5cfe1d7f4b ticket: record tui runtime migration implementation 2026-06-26 17:44:01 +09:00
Hare 63ec9f9572 feat: add backend runtime console target 2026-06-26 17:42:21 +09:00
Hare 94a2c94cc4 ticket: start tui runtime migration 2026-06-26 17:11:25 +09:00
Hare 65efde7651 ticket: accept tui runtime migration 2026-06-26 17:10:27 +09:00
Hare 0ba188889a ticket: record web console cleanup 2026-06-26 17:09:15 +09:00
Hare d9e6913791 ticket: mark web console mvp done 2026-06-26 17:08:24 +09:00
Hare bf834e8352 merge: 00001KVZ9JGK0 web console mvp 2026-06-26 17:07:32 +09:00
Hare b94fb8167d ticket: approve web console mvp 2026-06-26 17:07:32 +09:00
Hare 95c992ddbd ticket: record web console implementation 2026-06-26 17:02:51 +09:00
Hare f3ad9c96b3 feat: add workspace companion console MVP 2026-06-26 17:01:30 +09:00
Hare d6fe8b8d8a ticket: start web console mvp 2026-06-26 16:43:19 +09:00
Hare f39036032b ticket: accept web console mvp 2026-06-26 16:42:20 +09:00
Hare 32e1360802 ticket: record runtime config bundle cleanup 2026-06-26 16:40:48 +09:00
Hare 2df7a98dbf ticket: mark runtime config bundle sync done 2026-06-26 16:39:56 +09:00
Hare 7e8a8cfa4b merge: 00001KVZQHPNY runtime config bundles 2026-06-26 16:38:34 +09:00
Hare d2dfc186b1 ticket: approve runtime config bundle sync 2026-06-26 16:38:34 +09:00
Hare b6d7a34677 ticket: record config bundle boundary fixes 2026-06-26 16:34:11 +09:00
Hare 4867ab21bf fix: harden runtime config bundle boundary 2026-06-26 16:32:50 +09:00
Hare 0f8c6b80e3 ticket: request config bundle boundary fixes 2026-06-26 16:18:58 +09:00
Hare be396e59d9 ticket: record runtime config bundle implementation 2026-06-26 16:08:39 +09:00
Hare abab1af2f0 feat: add runtime config bundle sync 2026-06-26 16:06:58 +09:00
Hare 0c83d57727 ticket: start runtime config bundle sync 2026-06-26 15:35:33 +09:00
Hare 9a09ebd9ac ticket: accept runtime config bundle sync 2026-06-26 15:34:24 +09:00
Hare 3e550874ac ticket: record remote runtime cleanup 2026-06-26 15:31:00 +09:00
Hare 6c03220c1c ticket: mark remote runtime registry done 2026-06-26 15:30:13 +09:00
Hare bbb5d68c4c merge: 00001KVZSGT14 remote runtime registry 2026-06-26 15:29:18 +09:00
Hare f19ed64feb ticket: approve remote runtime registry 2026-06-26 15:29:18 +09:00
Hare 2d263278e6 ticket: record remote runtime debug redaction fix 2026-06-26 15:27:57 +09:00
Hare 38ff7d8f80 fix: redact observation source debug output 2026-06-26 15:27:08 +09:00
Hare 1bdb8f8a73 ticket: request remote runtime debug redaction 2026-06-26 15:21:40 +09:00
Hare 11f53c197a ticket: record remote runtime implementation 2026-06-26 15:16:41 +09:00
Hare aeb12b3b8e feat: add remote runtime registry source 2026-06-26 15:15:29 +09:00
Hare 71198821ae ticket: start remote runtime registry 2026-06-26 14:50:34 +09:00
Hare ec4ada9464 ticket: accept remote runtime registry 2026-06-26 14:49:45 +09:00
Hare 815b169757 ticket: record embedded runtime cleanup 2026-06-26 14:48:02 +09:00
Hare 5c592938f4 ticket: mark embedded runtime registry done 2026-06-26 14:47:18 +09:00
Hare e0cc7acf13 merge: 00001KVZSGT0Q embedded runtime registry 2026-06-26 14:46:31 +09:00
Hare 3d03ebccf8 ticket: approve embedded runtime registry 2026-06-26 14:46:31 +09:00
Hare 4616eb7254 ticket: record embedded runtime implementation 2026-06-26 14:41:23 +09:00
Hare c820928592 feat: add embedded workspace runtime registry 2026-06-26 14:40:07 +09:00
Hare a533d15bc6 ticket: start embedded runtime registry 2026-06-26 14:19:39 +09:00
Hare 7f312f1f6e ticket: accept embedded runtime registry 2026-06-26 14:18:50 +09:00
Hare bb8e09afa1 ticket: record websocket observation cleanup 2026-06-26 14:16:59 +09:00
Hare 35a5cf2887 ticket: mark websocket observation proxy done 2026-06-26 14:16:19 +09:00
Hare ae0f0d1d96 merge: 00001KVZKSTJT websocket observation proxy 2026-06-26 14:15:11 +09:00
Hare 009d59b3ee ticket: approve websocket observation proxy 2026-06-26 14:15:11 +09:00
Hare 9eaaedd08c ticket: record websocket diagnostic fixes 2026-06-26 14:11:03 +09:00
Hare 8cc9a594f7 fix: preserve runtime websocket diagnostics 2026-06-26 14:10:08 +09:00
Hare e67d884d62 ticket: request websocket diagnostic mapping fixes 2026-06-26 14:02:52 +09:00
Hare 6aba7dbbe0 ticket: record websocket observation implementation 2026-06-26 13:56:13 +09:00
Hare 9807accaf0 feat: add worker observation websocket proxy 2026-06-26 13:54:55 +09:00
Hare d3c9995e25 ticket: start websocket observation proxy 2026-06-26 13:23:32 +09:00
Hare 0c6d603128 ticket: accept websocket observation proxy 2026-06-26 13:22:34 +09:00
Hare 5e7cd8f3a8 ticket: record rest server cleanup 2026-06-26 13:20:40 +09:00
Hare 82850c344a ticket: mark worker runtime rest server done 2026-06-26 12:27:28 +09:00
Hare 660b07e8d7 merge: 00001KVZKSTE2 worker runtime rest server 2026-06-26 12:24:04 +09:00
Hare 15b3f002a3 ticket: approve worker runtime rest server 2026-06-26 12:24:04 +09:00
Hare 336f607536 ticket: record rest server binary fix 2026-06-26 12:21:34 +09:00
Hare d0db32fa6a fix: add worker runtime REST process binary 2026-06-26 12:20:37 +09:00
Hare a9fe199510 ticket: request rest server process wrapper 2026-06-26 12:14:49 +09:00
Hare 526ef640f0 ticket: record worker runtime rest server implementation 2026-06-26 12:10:55 +09:00
Hare 5b0d6551fa ticket: record sequential cleanup 2026-06-26 12:09:07 +09:00
Hare f43a6b8401 feat: add worker runtime REST server 2026-06-26 05:48:23 +09:00
Hare 8f67bd4d3e ticket: mark runtime registry foundation done 2026-06-26 05:44:33 +09:00
Hare fb023aab53 merge: 00001KVZKSV6C runtime registry foundation 2026-06-26 05:41:15 +09:00
Hare 749fe5d090 ticket: approve runtime registry foundation 2026-06-26 05:41:15 +09:00
Hare 7ea5568114 ticket: record runtime registry authority fix 2026-06-26 05:38:38 +09:00
Hare 15c2c38710 ticket: start worker runtime rest server 2026-06-26 05:38:09 +09:00
Hare 523b04d391 ticket: route websocket runtime queue chain 2026-06-26 05:37:09 +09:00
Hare 75a458ddd9 ticket: queue 00001KW04A8K6 2026-06-26 05:34:42 +09:00
Hare 22733deb15 ticket: queue 00001KVZSGT14 2026-06-26 05:34:35 +09:00
Hare 3a76967365 ticket: queue 00001KVZ9JGK0 2026-06-26 05:34:27 +09:00
Hare 7803a170b5 ticket: queue 00001KVZKSTJT 2026-06-26 05:34:20 +09:00
Hare 52f0099f74 ticket: ready websocket proxy and web console 2026-06-26 05:30:38 +09:00
Hare ee8fa17abd merge: orchestration planning returns
# Conflicts:
#	.yoi/tickets/00001KVZKSTJT/item.md
#	.yoi/tickets/00001KVZKSTJT/thread.md
2026-06-26 05:28:20 +09:00
Hare 471dc5bc52 ticket: refine websocket proxy planning 2026-06-26 05:26:33 +09:00
Hare 127bc18bd7 ticket: return web console stream planning 2026-06-26 05:23:24 +09:00
Hare 51d558a7a5 ticket: return websocket stream planning 2026-06-26 05:21:48 +09:00
Hare 15abcf6782 merge: orchestration runtime updates 2026-06-26 05:10:58 +09:00
Hare 243fb40092 ticket: ready runtime websocket stream 2026-06-26 05:10:54 +09:00
Hare f89552cafd ticket: update runtime migration planning 2026-06-26 04:59:15 +09:00
Hare 7110e078cd ticket: mark worker runtime fs store done 2026-06-26 04:49:07 +09:00
Hare 36ff72385c merge: 00001KVZKST83 worker runtime fs store 2026-06-26 04:46:07 +09:00
Hare 8d7ab0c053 ticket: approve worker runtime fs store 2026-06-26 04:46:07 +09:00
Hare d7c4396cd3 fix: scope workspace worker lookup by runtime 2026-06-26 04:45:22 +09:00
Hare fb8dc9fe51 ticket: record worker runtime fs store implementation 2026-06-26 04:41:55 +09:00
Hare 4071343996 feat: add worker runtime fs store 2026-06-26 04:40:58 +09:00
Hare 150d5c49eb ticket: request runtime registry authority fix 2026-06-26 04:37:50 +09:00
Hare f6fe9fba7f ticket: record runtime registry implementation 2026-06-26 04:33:14 +09:00
Hare f6fd7b6323 feat: add workspace runtime registry source boundary 2026-06-26 04:31:59 +09:00
Hare 928074fd64 ticket: resume accepted worker runtime branches 2026-06-26 04:25:03 +09:00
Hare 7d9fed8144 ticket: record spawn launcher blocker 2026-06-26 01:58:53 +09:00
Hare 40d4138068 ticket: accept next worker runtime branches 2026-06-26 01:56:16 +09:00
Hare 07a913f51f ticket: record worker runtime core cleanup 2026-06-26 01:54:24 +09:00
Hare 31c8d99187 ticket: mark worker runtime core done 2026-06-26 01:53:52 +09:00
Hare 56bdf95580 merge: 00001KVZBCQH4 worker runtime core 2026-06-26 01:52:55 +09:00
Hare 138b1fd860 ticket: approve worker runtime core 2026-06-26 01:52:50 +09:00
Hare 6a17366fcf ticket: record worker runtime lifecycle fix 2026-06-26 01:50:53 +09:00
Hare fbd358a195 fix: keep worker terminal lifecycle stable 2026-06-26 01:50:11 +09:00
Hare 9877a20778 ticket: record worker runtime continuation authority 2026-06-26 01:49:58 +09:00
Hare 579ab635cd merge: runtime routing updates 2026-06-26 01:46:39 +09:00
Hare f6159dc16e ticket: return runtime websocket stream to planning 2026-06-26 01:46:39 +09:00
Hare fb6f0ce068 ticket: request worker runtime lifecycle fix 2026-06-26 01:46:23 +09:00
Hare f3538dcd1f ticket: route runtime bundle and console blockers 2026-06-26 01:45:30 +09:00
Hare 1245ce027e ticket: queue 00001KVZ9JGK0 2026-06-26 01:44:45 +09:00
Hare 37c96b6ebd ticket: queue 00001KVZQHPNY 2026-06-26 01:44:39 +09:00
Hare 76b6b1dc4f merge: sync orchestration before queue 00001KVZQHPNY 2026-06-26 01:44:39 +09:00
Hare be8d190138 ticket: route worker runtime feature blockers 2026-06-26 01:44:24 +09:00
Hare 313cbd8bd8 ticket: queue 00001KVZKSTE2 2026-06-26 01:39:39 +09:00
Hare ae6076a5aa ticket: queue 00001KVZKST83 2026-06-26 01:39:26 +09:00
Hare 750ed74106 merge: sync orchestration before queue 00001KVZKST83 2026-06-26 01:39:25 +09:00
Hare f858e015b1 ticket: ready worker runtime followups 2026-06-26 01:39:23 +09:00
Hare 02423dad01 ticket: record worker runtime packaging fix 2026-06-26 01:37:29 +09:00
Hare 593db95175 fix: update nix cargo hash 2026-06-26 01:36:57 +09:00
Hare fc4153ae54 ticket: route backend runtime queue blockers 2026-06-26 01:32:57 +09:00
Hare 1966ec614d ticket: queue 00001KVZSGT0Q 2026-06-26 01:31:30 +09:00
Hare 0b665cd176 ticket: queue 00001KVZKSV6C 2026-06-26 01:31:28 +09:00
Hare 1e9ca19313 merge: sync orchestration before queue 00001KVZKSV6C 2026-06-26 01:31:28 +09:00
Hare 9b2cae32ea feat: add memory worker runtime crate 2026-06-26 01:31:09 +09:00
Hare d6c240af35 ticket: split backend runtime registry integration 2026-06-26 01:30:43 +09:00
Hare e64deceac7 ticket: start worker runtime core implementation 2026-06-26 01:23:28 +09:00
Hare f8d3b1cca9 ticket: accept worker runtime core routing 2026-06-26 01:21:59 +09:00
Hare 30363e5ed9 ticket: queue 00001KVZBCQH4 2026-06-26 01:20:10 +09:00
Hare 53c6799d4d merge: sync orchestration before queue 00001KVZBCQH4 2026-06-26 01:20:09 +09:00
Hare 089840e707 ticket: mark worker crate rename done 2026-06-26 01:19:33 +09:00
Hare 5dceaf9a72 ticket: refine worker runtime core plan 2026-06-26 01:18:21 +09:00
Hare b3db803c73 ticket: record dashboard routing pause 2026-06-26 01:18:09 +09:00
Hare 2a7e877584 merge: 00001KVZG9BMS worker crate rename 2026-06-26 01:15:29 +09:00
Hare 21e8d99494 ticket: approve worker crate rename 2026-06-26 01:15:19 +09:00
Hare b5e5f73071 ticket: record worker wording cleanup 2026-06-26 01:13:47 +09:00
Hare 60dbd724c5 fix: clean remaining worker wording 2026-06-26 01:13:11 +09:00
Hare 712425e3fc ticket: request worker wording cleanup 2026-06-26 01:11:40 +09:00
Hare 0b7a3c2392 ticket: record final worker wording fixes 2026-06-26 01:07:35 +09:00
Hare cb0c52e787 fix: update remaining active worker wording 2026-06-26 01:06:20 +09:00
Hare f75052eb8e ticket: request final worker terminology fixes 2026-06-26 01:00:50 +09:00
Hare 8e8f4f5a6d ticket: record worker rename guidance fixes 2026-06-26 00:58:46 +09:00
Hare da96d06f25 fix: remove stale pod guidance references 2026-06-26 00:57:27 +09:00
Hare 638bd7bcd6 ticket: request worker rename guidance fixes 2026-06-26 00:46:49 +09:00
Hare 6e638d1035 ticket: record remaining worker rename fixes 2026-06-26 00:44:26 +09:00
Hare 94c7aa793a fix: clean remaining worker rename references 2026-06-26 00:43:16 +09:00
Hare 0d296c72a9 ticket: request remaining worker rename fixes 2026-06-26 00:29:35 +09:00
Hare 07b4cffc54 ticket: record worker rename followup fixes 2026-06-26 00:26:22 +09:00
Hare ebf50baa94 fix: align worker rename followups 2026-06-26 00:25:03 +09:00
Hare 47e555ba80 ticket: request worker rename fixes 2026-06-26 00:15:37 +09:00
Hare befbabe13a ticket: split worker runtime implementation 2026-06-26 00:12:00 +09:00
Hare 137673045f ticket: record worker crate implementation report 2026-06-26 00:07:24 +09:00
Hare 6c59fe927b refactor: rename pod crate to worker 2026-06-26 00:05:57 +09:00
Hare ed0c22f959 ticket: record worker crate coder start 2026-06-25 23:16:34 +09:00
Hare 4c677640f4 ticket: accept worker crate rename task 2026-06-25 23:15:27 +09:00
Hare 0bf5b117da ticket: route worker crate rename task 2026-06-25 23:15:08 +09:00
Hare d93dbc0533 ticket: close completed work 2026-06-25 23:14:05 +09:00
Hare 9ee77b44ae ticket: queue 00001KVZG9BMS 2026-06-25 23:13:35 +09:00
Hare 20cfcfaca3 merge: llm engine rename 2026-06-25 23:10:27 +09:00
Hare b367abd76a ticket: plan worker runtime transition 2026-06-25 23:09:25 +09:00
Hare 6ab0d64fcb ticket: mark llm engine rename done 2026-06-25 22:57:39 +09:00
Hare 254ecccba2 merge: 00001KVZD10ED llm engine rename 2026-06-25 22:54:25 +09:00
Hare 4d8e022465 ticket: approve llm engine rename 2026-06-25 22:54:25 +09:00
Hare 50e2754e5e ticket: record llm engine implementation report 2026-06-25 22:47:33 +09:00
Hare 292fc4ea5d refactor: rename llm worker crate to engine 2026-06-25 22:46:26 +09:00
Hare 230b379979 ticket: record llm engine coder start 2026-06-25 22:28:33 +09:00
Hare 22598710fd ticket: accept llm engine rename task 2026-06-25 22:27:24 +09:00
Hare 1d6125e57d ticket: route llm engine rename task 2026-06-25 22:26:27 +09:00
Hare 193c868146 ticket: queue 00001KVZD10ED 2026-06-25 22:24:26 +09:00
Hare 1aa3a409cd ticket: plan llm engine rename 2026-06-25 22:23:50 +09:00
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 6434df13aa ticket: plugin request/ws support 2026-06-21 16:15:36 +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
Hare 98c85a1d9e ticket: queue 00001KVMFFYVX 2026-06-21 16:11:58 +09:00
Hare 1f198ccb43 merge: sync orchestration before queue 00001KVMFFYVX 2026-06-21 16:11:58 +09:00
Hare 5fb8c393c5 ticket: bootstrap workspace web control plane 2026-06-21 15:58:18 +09:00
Hare 7c424e7d38 objective: defer memory redesign 2026-06-21 15:31:45 +09:00
Hare 5fa0846dcf ticket: record resume cli cleanup 2026-06-21 02:00:53 +09:00
Hare 19c3ec45eb ticket: complete resume cli command 2026-06-21 02:00:29 +09:00
Hare bdc11c771d merge: explicit resume command 2026-06-21 01:58:41 +09:00
Hare 35fba2b6fb ticket: approve resume cli changes 2026-06-21 01:58:34 +09:00
Hare bf4bf4da09 ticket: record resume guidance fix 2026-06-21 01:54:29 +09:00
Hare d25ca6ff3c fix: update resume guidance 2026-06-21 01:53:32 +09:00
Hare 79ee5c4388 ticket: request changes on resume cli guidance 2026-06-21 01:50:52 +09:00
Hare 2081fd5bda ticket: start resume cli review 2026-06-21 01:46:56 +09:00
Hare 8fcfa6e016 ticket: record resume cli implementation 2026-06-21 01:46:27 +09:00
Hare c14083a45a ticket: close completed audit items 2026-06-21 01:46:02 +09:00
Hare 861c351a96 feat: add explicit resume command 2026-06-21 01:45:28 +09:00
Hare 50b261e7e2 ticket: start resume cli implementation 2026-06-21 01:31:58 +09:00
Hare 54245e3292 ticket: close obsolete planning items 2026-06-21 01:31:34 +09:00
Hare a63b40f460 ticket: accept resume cli routing 2026-06-21 01:31:04 +09:00
Hare 8684344e92 ticket: queue 00001KVJX7VZT 2026-06-21 01:29:26 +09:00
Hare 5f52c72b45 records: add pending objective and ticket 2026-06-21 01:28:36 +09:00
Hare 839783b2e6 merge: integrate orchestration branch 2026-06-21 01:24:03 +09:00
Hare 717ff8db01 ticket: close stale notification guidance item 2026-06-21 01:23:54 +09:00
Hare 249b55ec3f objective: define team workspace roadmap 2026-06-21 01:16:36 +09:00
Hare 5885850726 ticket: record plugin lifecycle cleanup 2026-06-21 00:23:39 +09:00
Hare bc484338df ticket: complete plugin instance lifecycle 2026-06-21 00:23:17 +09:00
Hare 43c9216ef8 merge: plugin instance lifecycle surface 2026-06-21 00:18:43 +09:00
Hare ec3a1c621d ticket: approve plugin instance lifecycle 2026-06-21 00:18:40 +09:00
Hare 2edffafc2b ticket: record plugin static surface fix 2026-06-21 00:14:03 +09:00
Hare 627c8f36ff plugin: filter static enabled surfaces 2026-06-21 00:12:55 +09:00
Hare 01ba4c157a ticket: request changes on plugin surface inspection 2026-06-21 00:04:15 +09:00
Hare 6f790faed9 ticket: record plugin surface selection fix 2026-06-20 23:59:33 +09:00
Hare 79ca0f7f81 plugin: enforce enabled lifecycle surfaces 2026-06-20 23:58:16 +09:00
Hare 8fd75228e4 ticket: request changes on plugin surface selection 2026-06-20 23:50:29 +09:00
Hare dcbd04aacd ticket: record plugin instance lifecycle fixes 2026-06-20 23:43:52 +09:00
Hare 870bcc76a5 plugin: fix instance lifecycle blockers 2026-06-20 23:42:44 +09:00
Hare c383178f7f ticket: request changes on plugin instance lifecycle 2026-06-20 23:24:48 +09:00
Hare 97df2c8a28 ticket: dispatch plugin instance lifecycle review 2026-06-20 23:17:39 +09:00
Hare 6eda265bf2 ticket: record plugin instance lifecycle report 2026-06-20 23:16:51 +09:00
Hare 147a600577 plugin: add instance lifecycle surface 2026-06-20 23:15:47 +09:00
Hare 0dd5be8e7a ticket: close mcp cli inspection 2026-06-20 22:56:47 +09:00
Hare 8c42729e5b ticket: complete mcp cli inspection 2026-06-20 22:56:23 +09:00
Hare 5e0b023a7b merge: mcp cli inspection 2026-06-20 22:54:13 +09:00
Hare 09f0ec5ebf ticket: approve mcp cli inspection 2026-06-20 22:54:13 +09:00
Hare c326c45d70 ticket: dispatch mcp cli inspection review 2026-06-20 22:49:37 +09:00
Hare ebf6beaaf1 ticket: record mcp cli inspection implementation report 2026-06-20 22:48:46 +09:00
Hare c91f5fc9b8 mcp: add cli inspection 2026-06-20 22:47:41 +09:00
Hare 673c739909 chore: remove daemon crate 2026-06-20 22:41:24 +09:00
Hare 3bc0de1762 ticket: remove obsolete daemon crate 2026-06-20 22:36:51 +09:00
Hare 9af2ad7cd9 ticket: start mcp cli inspection worktree 2026-06-20 22:33:12 +09:00
Hare 12d7e69f07 ticket: accept mcp cli inspection 2026-06-20 22:32:24 +09:00
Hare 142fdffb00 ticket: queue 00001KVJKHAFE 2026-06-20 22:31:00 +09:00
Hare c4687b6816 merge: sync orchestration before queue 00001KVJKHAFE 2026-06-20 22:31:00 +09:00
Hare 9b161d251e ticket: start plugin instance lifecycle worktree 2026-06-20 22:30:49 +09:00
Hare a8f058c792 ticket: add mcp cli inspection 2026-06-20 22:30:19 +09:00
Hare 5ec8bae983 ticket: accept plugin instance lifecycle 2026-06-20 22:29:34 +09:00
Hare 7f06e6567a ticket: queue 00001KVJHYP4Q 2026-06-20 22:28:19 +09:00
Hare 3257cf799a ticket: redesign plugin instance runtime 2026-06-20 22:26:49 +09:00
Hare 70b8ed628d ticket: make plugin lifecycle instance-oriented 2026-06-20 22:18:53 +09:00
Hare aadc0329d2 ticket: clarify service-backed tool state 2026-06-20 22:15:09 +09:00
Hare 120044af80 ticket: plan plugin service ingress surface 2026-06-20 22:02:44 +09:00
Hare dfc5263eec merge: integrate orchestration branch 2026-06-20 21:42:13 +09:00
Hare 2646dfae7e ticket: close queue conflict ticket 2026-06-20 21:42:08 +09:00
Hare 7d087afbf6 ticket: close webfetch pdf text 2026-06-20 21:31:42 +09:00
Hare 59c59a6a70 ticket: complete webfetch pdf text 2026-06-20 21:31:15 +09:00
Hare 97edfe8ae7 merge: webfetch pdf text 2026-06-20 21:28:27 +09:00
Hare daf3ae68c3 ticket: approve webfetch pdf text 2026-06-20 21:28:27 +09:00
Hare df5d65dc2d ticket: dispatch webfetch pdf review 2026-06-20 21:24:51 +09:00
Hare 4887aa33d9 ticket: record webfetch pdf implementation report 2026-06-20 21:24:09 +09:00
Hare b1af95ad20 web: fetch pdf text by pages 2026-06-20 21:22:55 +09:00
Hare 865a11c628 ticket: close intake investigation gate 2026-06-20 21:20:21 +09:00
Hare 7c2c5319f4 ticket: complete intake investigation gate 2026-06-20 21:20:03 +09:00
Hare f62ed4db8a merge: intake investigation gate 2026-06-20 21:19:24 +09:00
Hare 556fc353a8 ticket: approve intake investigation gate 2026-06-20 21:19:24 +09:00
Hare 8fd3cb855f ticket: dispatch intake investigation gate review 2026-06-20 21:17:16 +09:00
Hare 448a24a975 merge: integrate orchestration branch 2026-06-20 21:16:54 +09:00
Hare d547198361 ticket: record intake investigation gate implementation report 2026-06-20 21:16:34 +09:00
Hare 1143ae1c5a workflow: add intake investigation gate 2026-06-20 21:15:18 +09:00
Hare 69c55a21a4 ticket: close profile override scope 2026-06-20 21:13:40 +09:00
Hare 22c631cf88 ticket: complete profile override scope 2026-06-20 21:13:19 +09:00
Hare a13868818c merge: profile override scope 2026-06-20 21:12:19 +09:00
Hare 203160db4f ticket: approve profile override scope 2026-06-20 21:12:19 +09:00
Hare 61ae37a752 ticket: start webfetch pdf and intake gate worktrees 2026-06-20 21:09:57 +09:00
Hare e752a7206a ticket: accept webfetch pdf and intake gate 2026-06-20 21:08:41 +09:00
Hare 36b9ed450f ticket: dispatch profile override scope review 2026-06-20 21:07:06 +09:00
Hare 75215bb143 ticket: queue 00001KVJDJD02 2026-06-20 21:06:37 +09:00
Hare 8e625344e6 ticket: queue 00001KVJA7V2R 2026-06-20 21:06:29 +09:00
Hare 3ecd86dbc2 merge: sync orchestration before queue 00001KVJA7V2R 2026-06-20 21:06:29 +09:00
Hare d95e044913 ticket: record profile override scope implementation report 2026-06-20 21:06:28 +09:00
Hare 0717aae341 pod: preserve profile override scope 2026-06-20 21:04:10 +09:00
Hare 054d44f737 ticket: start profile override scope worktree 2026-06-20 20:55:06 +09:00
Hare c04c8796f5 ticket: add pending work items 2026-06-20 20:53:58 +09:00
Hare 72e9f2f14e ticket: accept profile override scope launch 2026-06-20 20:53:58 +09:00
Hare 9e7c84a430 ticket: queue 00001KVJABS1A 2026-06-20 20:52:33 +09:00
Hare a04fe0a9dd merge: sync orchestration before queue 00001KVJABS1A 2026-06-20 20:52:33 +09:00
Hare 9fbe9e7aea ticket: track profile scope override bug 2026-06-20 19:49:37 +09:00
Hare 93bdad4c42 ticket: close mcp list changed handling 2026-06-20 19:33:08 +09:00
Hare 21008249ea ticket: complete mcp list changed handling 2026-06-20 19:32:43 +09:00
Hare ae5f3e425b merge: mcp list changed handling 2026-06-20 19:31:33 +09:00
Hare fccef54cd6 ticket: approve mcp list changed handling 2026-06-20 19:31:33 +09:00
Hare d67f4023e1 ticket: dispatch mcp list changed review 2026-06-20 19:27:00 +09:00
Hare 4caafe99d3 ticket: record mcp list changed implementation report 2026-06-20 19:26:21 +09:00
Hare e33dee192c mcp: handle list changed notifications 2026-06-20 19:24:59 +09:00
Hare 02cd596139 ticket: start mcp list changed worktree 2026-06-20 19:08:13 +09:00
Hare d31b89072d ticket: accept mcp list changed handling 2026-06-20 19:07:15 +09:00
Hare b11f83c8b3 ticket: close mcp resources prompts tools 2026-06-20 19:05:26 +09:00
Hare dbdae3c63f ticket: complete mcp resources prompts tools 2026-06-20 19:05:02 +09:00
Hare 4a4590f86b merge: mcp resources prompts tools 2026-06-20 19:03:32 +09:00
Hare 25e0ae7f0d ticket: approve mcp resources prompts tools 2026-06-20 19:03:32 +09:00
Hare baefa90df9 ticket: dispatch mcp resources prompts review 2026-06-20 18:58:05 +09:00
Hare c4f3c42957 ticket: record mcp resources prompts implementation report 2026-06-20 18:57:22 +09:00
Hare 3a22360a78 mcp: expose resources prompts tools 2026-06-20 18:56:14 +09:00
Hare e4be4944d8 ticket: start mcp resources prompts worktree 2026-06-20 18:38:20 +09:00
Hare b2b4764f36 ticket: accept mcp resources prompts tools 2026-06-20 18:37:30 +09:00
Hare 6ac916c785 ticket: close dashboard console tui refactor 2026-06-20 18:35:58 +09:00
Hare 831c8dc64e ticket: complete dashboard console tui refactor 2026-06-20 18:35:35 +09:00
Hare 23ec2bbd7e merge: dashboard console tui refactor 2026-06-20 18:33:22 +09:00
Hare 945a61c0ed ticket: approve dashboard console tui refactor 2026-06-20 18:33:22 +09:00
Hare 883badc1d8 ticket: record dashboard console tui state fix 2026-06-20 18:30:21 +09:00
Hare 135343a2e7 tui: preserve dashboard after console return 2026-06-20 18:29:10 +09:00
Hare ff3b779fa9 ticket: request changes on dashboard console tui 2026-06-20 18:22:32 +09:00
Hare 24c8297df1 ticket: close mcp tools call 2026-06-20 18:19:01 +09:00
Hare 656b0220c4 ticket: complete mcp tools call 2026-06-20 18:18:19 +09:00
Hare 399a9d43d3 merge: mcp tools call 2026-06-20 18:17:01 +09:00
Hare ee16a4debc ticket: approve mcp tools call 2026-06-20 18:17:01 +09:00
Hare 454d67d0a2 ticket: dispatch dashboard console tui review 2026-06-20 18:14:15 +09:00
Hare bf44d8124d ticket: record dashboard console tui implementation report 2026-06-20 18:13:29 +09:00
Hare 5415a9478d tui: introduce dashboard console boundaries 2026-06-20 18:12:18 +09:00
Hare 62dd661395 ticket: dispatch mcp tools call review 2026-06-20 18:09:57 +09:00
Hare e6b2144f74 ticket: record mcp tools call implementation report 2026-06-20 18:08:52 +09:00
Hare 9a2454037f mcp: execute stdio tool calls 2026-06-20 18:07:21 +09:00
Hare 2fc20adc23 docs: update plugin authoring guide 2026-06-20 18:00:44 +09:00
Hare ae5528b62f ticket: start mcp tools call worktree 2026-06-20 17:49:30 +09:00
Hare 92432ad750 ticket: accept mcp tools call 2026-06-20 17:48:39 +09:00
Hare 381db88e33 ticket: close mcp tool registration 2026-06-20 17:46:38 +09:00
Hare 7abe13f23d ticket: complete mcp tool registration 2026-06-20 17:46:17 +09:00
Hare a1f904b84d merge: mcp tool registration 2026-06-20 17:44:32 +09:00
Hare 3d147c9e01 ticket: approve mcp tool registration 2026-06-20 17:44:32 +09:00
Hare db23435337 ticket: start dashboard console tui worktree 2026-06-20 17:43:59 +09:00
Hare 7e35721a81 ticket: accept dashboard console tui refactor 2026-06-20 17:42:40 +09:00
Hare 8ce4fcdeba ticket: record mcp tool registration collision fix 2026-06-20 17:40:55 +09:00
Hare 0080c5b3d4 mcp: reject colliding tool names 2026-06-20 17:40:03 +09:00
Hare 865c3f01ba ticket: request changes on mcp tool registration 2026-06-20 17:35:19 +09:00
Hare 37d0105319 ticket: hold dashboard console refactor for capacity 2026-06-20 17:31:36 +09:00
Hare c5cd587780 ticket: queue 00001KVHX0WBE 2026-06-20 17:30:58 +09:00
Hare e881c47abf merge: sync orchestration before queue 00001KVHX0WBE 2026-06-20 17:30:58 +09:00
Hare 952020c8a5 ticket: dispatch mcp tool registration review 2026-06-20 17:30:28 +09:00
Hare db1f6fb6d1 ticket: record mcp tool registration implementation report 2026-06-20 17:29:31 +09:00
Hare 66fa9d55a1 mcp: register stdio server tools 2026-06-20 17:28:26 +09:00
Hare 50224326aa ticket: start mcp tool registration worktree 2026-06-20 17:01:54 +09:00
Hare a59e5c1ed3 ticket: accept mcp tool registration 2026-06-20 17:00:59 +09:00
Hare 5df7580a1e merge: integrate orchestration branch 2026-06-20 17:00:26 +09:00
Hare 96223148c0 ticket: clarify mcp runtime-discovered tools 2026-06-20 17:00:17 +09:00
Hare 68a8fc97d2 ticket: close mcp stdio lifecycle client 2026-06-20 16:59:37 +09:00
Hare ca28c927b2 ticket: complete mcp stdio lifecycle client 2026-06-20 16:59:17 +09:00
Hare 9cf5344fc5 merge: mcp stdio lifecycle client 2026-06-20 16:58:29 +09:00
Hare e5510620cc ticket: approve mcp stdio lifecycle client 2026-06-20 16:58:21 +09:00
Hare 8e6b440f9a ticket: record mcp stdio lifecycle redaction fix 2026-06-20 16:56:06 +09:00
Hare f396e1a253 mcp: redact stdio server spec debug 2026-06-20 16:54:48 +09:00
Hare 39b55fb6e8 ticket: request changes on mcp stdio lifecycle 2026-06-20 16:51:36 +09:00
Hare c91ed5600f ticket: dispatch mcp stdio lifecycle review 2026-06-20 16:46:44 +09:00
Hare 35e6533986 ticket: record mcp stdio lifecycle implementation report 2026-06-20 16:46:05 +09:00
Hare a114fa9d0a mcp: implement stdio lifecycle client 2026-06-20 16:45:05 +09:00
Hare 017c4471ed ticket: start mcp stdio lifecycle worktree 2026-06-20 16:31:10 +09:00
Hare c0e760d73e ticket: accept mcp stdio lifecycle client 2026-06-20 16:30:12 +09:00
Hare 8f5eef94e4 ticket: close mcp stdio config trust 2026-06-20 16:29:03 +09:00
Hare c4a7eb7a2e ticket: complete mcp stdio config trust 2026-06-20 16:28:39 +09:00
Hare 9b7c4e279d merge: mcp stdio config trust 2026-06-20 16:27:12 +09:00
Hare c6fa0b2d95 ticket: approve mcp stdio config trust 2026-06-20 16:27:07 +09:00
Hare a0cd3dd0e9 ticket: dispatch mcp stdio config review 2026-06-20 16:19:31 +09:00
Hare e578d888e3 ticket: record mcp stdio config implementation report 2026-06-20 16:18:46 +09:00
Hare e0680ccee0 mcp: add stdio server config 2026-06-20 16:17:38 +09:00
Hare 6cc8551a6c ticket: start mcp stdio config worktree 2026-06-20 15:57:19 +09:00
Hare b0225e48b8 ticket: accept mcp stdio config trust 2026-06-20 15:56:29 +09:00
Hare a5df9e3728 ticket: close plugin authoring cli 2026-06-20 15:55:14 +09:00
Hare ead96654be ticket: complete plugin authoring cli 2026-06-20 15:54:51 +09:00
Hare 0430ed982d merge: plugin authoring cli 2026-06-20 15:50:55 +09:00
Hare 52e40b2fdc ticket: approve plugin authoring cli 2026-06-20 15:50:48 +09:00
Hare 93265ae65c ticket: record plugin authoring cli hardening fix 2026-06-20 15:46:18 +09:00
Hare 699db538b6 plugin: harden authoring checks 2026-06-20 15:45:12 +09:00
Hare 9ac540f7cf ticket: request changes on plugin authoring cli 2026-06-20 15:36:56 +09:00
Hare 8206b5912d ticket: dispatch plugin authoring cli review 2026-06-20 15:26:33 +09:00
Hare 59d0a58e3a ticket: record plugin authoring cli implementation report 2026-06-20 15:25:47 +09:00
Hare 945ecdf64d plugin: add authoring cli 2026-06-20 15:24:35 +09:00
Hare e37a360d07 ticket: hold queued mcp chain for dependencies 2026-06-20 15:00:52 +09:00
Hare 9881a061fe ticket: queue 00001KVHR3WSW 2026-06-20 14:59:05 +09:00
Hare 76729c3377 ticket: queue 00001KVHR3WSD 2026-06-20 14:59:04 +09:00
Hare f880007639 ticket: queue 00001KVHR3WS6 2026-06-20 14:58:58 +09:00
Hare eee2ce00e2 ticket: queue 00001KVHR3WSN 2026-06-20 14:58:57 +09:00
Hare a729282cc1 ticket: queue 00001KVHR3WRY 2026-06-20 14:58:55 +09:00
Hare 061322d425 ticket: queue 00001KVHR3WRF 2026-06-20 14:58:46 +09:00
Hare 191e7999c0 merge: sync orchestration before queue 00001KVHR3WRF 2026-06-20 14:58:46 +09:00
Hare c0239684ed ticket: start plugin authoring cli worktree 2026-06-20 14:55:36 +09:00
Hare d1095f854a ticket: accept plugin authoring cli 2026-06-20 14:54:50 +09:00
Hare 902b383de7 ticket: close plugin rust pdk templates 2026-06-20 14:53:26 +09:00
Hare ab7ab69f20 ticket: complete plugin rust pdk templates 2026-06-20 14:51:47 +09:00
Hare edc53a6bc9 merge: plugin rust pdk templates 2026-06-20 14:47:33 +09:00
Hare 1f0766c1d7 ticket: approve plugin rust pdk templates 2026-06-20 14:47:25 +09:00
Hare 01f2e926b0 ticket: record plugin rust pdk template fix 2026-06-20 14:40:23 +09:00
Hare 0a9e585c1d plugin: fix rust pdk wit template probes 2026-06-20 14:39:10 +09:00
Hare 75e8103cdd ticket: split mcp stdio roadmap 2026-06-20 14:34:00 +09:00
Hare 356d06ef58 fix: allow queueing behind active blockers 2026-06-20 14:34:00 +09:00
Hare 730bc73975 ticket: hold plugin authoring cli for pdk dependency 2026-06-20 14:23:53 +09:00
Hare b4cb9fbc41 ticket: queue 00001KVHKWNQS 2026-06-20 14:23:14 +09:00
Hare 2c78428d9d merge: sync orchestration before queue 00001KVHKWNQS 2026-06-20 14:23:14 +09:00
Hare 88f4c7e104 ticket: request changes on plugin rust pdk 2026-06-20 14:21:54 +09:00
Hare 3fb3368272 ticket: dispatch plugin rust pdk review 2026-06-20 14:16:58 +09:00
Hare af435fa9bc ticket: record plugin rust pdk implementation report 2026-06-20 14:16:22 +09:00
Hare 06287aca40 plugin: add rust pdk template 2026-06-20 14:15:20 +09:00
Hare 6c04cb9a0b merge: sync orchestration before queue 00001KVHKWNQS 2026-06-20 14:12:46 +09:00
Hare b5e623e5a1 ticket: start plugin rust pdk worktree 2026-06-20 13:54:58 +09:00
Hare 5f7f81bdde ticket: accept plugin rust pdk templates 2026-06-20 13:54:09 +09:00
Hare 9ca2f85b08 ticket: queue 00001KVHKWNQA 2026-06-20 13:52:58 +09:00
Hare 8b42e319e2 ticket: add plugin authoring roadmap 2026-06-20 13:43:16 +09:00
Hare c8877b49a4 ticket: close plugin component model runtime 2026-06-20 02:23:35 +09:00
Hare 54a91f1b7e ticket: complete plugin component model runtime 2026-06-20 02:23:17 +09:00
Hare 63d7ad788d merge: plugin component model runtime 2026-06-20 02:20:03 +09:00
Hare e6619bc6c9 ticket: approve plugin component model runtime 2026-06-20 02:19:59 +09:00
Hare ac58bfdd63 ticket: record component runtime resource fix 2026-06-20 02:17:13 +09:00
Hare a705bb3bf2 plugin: bound component model runtime resources 2026-06-20 02:16:16 +09:00
Hare 30e49d806a ticket: request changes on component model runtime 2026-06-20 02:08:22 +09:00
Hare 5f00329d44 ticket: dispatch plugin component model review 2026-06-20 02:01:02 +09:00
Hare ed33a0b00f ticket: record plugin component model implementation report 2026-06-20 02:00:25 +09:00
Hare 57bbf14e1a plugin: implement component model runtime 2026-06-20 01:58:53 +09:00
Hare 02006fee2e ticket: update plugin component model work metadata 2026-06-20 01:25:34 +09:00
Hare 466e2bf927 ticket: start plugin component model runtime worktree 2026-06-20 01:25:27 +09:00
Hare 878517dcd2 ticket: accept plugin component model runtime 2026-06-20 01:22:02 +09:00
Hare b0ea9513e3 ticket: close plugin fs host api 2026-06-20 01:18:14 +09:00
Hare 817c335f30 ticket: approve plugin fs host api 2026-06-20 01:15:35 +09:00
Hare f8a1e9452e ticket: record plugin fs host api merge 2026-06-20 01:14:52 +09:00
Hare 1097f35ed8 ticket: approve plugin fs host api 2026-06-20 01:12:56 +09:00
Hare 3dac71d0a5 ticket: approve plugin fs host api 2026-06-20 01:12:06 +09:00
Hare 993e407df2 ticket: approve plugin fs host api 2026-06-20 01:11:11 +09:00
Hare c94e157b76 merge: plugin fs host api 2026-06-20 01:10:37 +09:00
Hare ca988ffc3a ticket: approve plugin fs host api 2026-06-20 01:10:37 +09:00
Hare 93bd6bdf01 ticket: dispatch plugin fs host api review 2026-06-20 01:02:48 +09:00
Hare ec600c8806 ticket: record plugin fs host api implementation 2026-06-20 01:01:52 +09:00
Hare 717c0999a5 plugin: implement fs host api 2026-06-20 00:58:44 +09:00
Hare c4d7ad8d0d ticket: record plugin fs host api coder start 2026-06-20 00:39:20 +09:00
Hare 6711bcf300 ticket: accept plugin fs host api work 2026-06-20 00:37:54 +09:00
Hare 838b273d9c ticket: close plugin https host api 2026-06-20 00:36:01 +09:00
Hare f64570ee84 ticket: record plugin https host api merge 2026-06-20 00:34:10 +09:00
Hare 94cb37075a ticket: approve plugin https host api 2026-06-20 00:32:31 +09:00
Hare 6beb8625bf merge: plugin https host api 2026-06-20 00:29:59 +09:00
Hare 998225eb4e ticket: approve plugin https host api 2026-06-20 00:29:59 +09:00
Hare 8de6b447ee ticket: record plugin https target hardening fix 2026-06-20 00:23:18 +09:00
Hare 85683f17c3 plugin: harden https target validation 2026-06-20 00:21:37 +09:00
Hare ffa8e2f25a ticket: dispatch plugin https host api fixes 2026-06-20 00:12:33 +09:00
Hare faadebc67a ticket: request plugin https host api changes 2026-06-20 00:10:49 +09:00
Hare 748074ba9f ticket: dispatch plugin https host api review 2026-06-20 00:05:11 +09:00
Hare 884accd976 ticket: record plugin https host api implementation 2026-06-20 00:04:16 +09:00
Hare 7377527f7c plugin: implement https host api 2026-06-20 00:02:24 +09:00
Hare e44827823a ticket: record plugin https host api coder start 2026-06-19 23:26:40 +09:00
Hare 1fdef32a4d ticket: accept plugin https host api work 2026-06-19 23:25:39 +09:00
Hare da2dbfb108 ticket: close plugin cli inspection 2026-06-19 23:23:00 +09:00
Hare f8230f9f59 ticket: record plugin cli inspection merge 2026-06-19 23:21:35 +09:00
Hare 71ca05c899 merge: plugin cli inspection 2026-06-19 23:18:51 +09:00
Hare 509ca60959 ticket: approve plugin cli inspection 2026-06-19 23:18:51 +09:00
Hare be91977725 ticket: dispatch plugin cli missing-diagnostic re-review 2026-06-19 23:11:31 +09:00
Hare 22be375f1b ticket: record plugin cli missing-diagnostic fix report 2026-06-19 23:10:41 +09:00
Hare 0142ef1d3f plugin: distinguish present invalid packages 2026-06-19 23:08:06 +09:00
Hare 6e4c49df61 ticket: dispatch plugin cli missing-diagnostic fixes 2026-06-19 23:03:41 +09:00
Hare 4bf6b1bf0f ticket: request plugin cli missing-diagnostic changes 2026-06-19 23:02:48 +09:00
Hare d2ee3bf379 ticket: dispatch plugin cli invalid package re-review 2026-06-19 22:55:02 +09:00
Hare f1c182072b ticket: record plugin cli invalid package fix report 2026-06-19 22:54:13 +09:00
Hare 877ec94fc9 ticket: dispatch plugin cli invalid package fixes 2026-06-19 22:53:10 +09:00
Hare a5709d8bfc ticket: request plugin cli invalid package changes 2026-06-19 22:52:00 +09:00
Hare a5f3b0b554 plugin: reject configured invalid packages 2026-06-19 22:51:02 +09:00
Hare 3a0fd1c219 ticket: dispatch plugin cli invalid package fixes 2026-06-19 22:45:54 +09:00
Hare 8e600311d0 ticket: request plugin cli invalid package changes 2026-06-19 22:45:09 +09:00
Hare ea6355a73d ticket: dispatch plugin cli schema re-review 2026-06-19 22:37:02 +09:00
Hare 3cfb3a647e ticket: record plugin cli schema fix report 2026-06-19 22:36:03 +09:00
Hare 22af7fd342 ticket: queue 00001KVG0HR96 2026-06-19 22:34:43 +09:00
Hare c0f70d1a88 merge: integrate orchestration branch 2026-06-19 22:33:30 +09:00
Hare 8b135cf47a ticket: close plugin design umbrella 2026-06-19 22:29:47 +09:00
Hare e5126321ad ticket: plan plugin component model migration 2026-06-19 22:21:31 +09:00
Hare 982a1b75ed plugin: validate inspected tool schemas 2026-06-19 20:47:11 +09:00
Hare 86c87ded89 ticket: dispatch plugin cli schema validation fixes 2026-06-19 20:42:31 +09:00
Hare 66821b30a7 ticket: request plugin cli schema validation changes 2026-06-19 20:41:32 +09:00
Hare ecd3f124be ticket: dispatch plugin cli metadata re-review 2026-06-19 20:34:35 +09:00
Hare 41db5a9bf9 ticket: record plugin cli metadata fix report 2026-06-19 20:33:55 +09:00
Hare dfa966dbfc plugin: report inspection package metadata 2026-06-19 20:31:26 +09:00
Hare 00a2459a86 ticket: dispatch plugin cli path api fixes 2026-06-19 20:24:14 +09:00
Hare d5b718b380 ticket: request plugin cli path api changes 2026-06-19 20:23:32 +09:00
Hare 9e08291579 ticket: dispatch plugin cli inspection re-review 2026-06-19 20:17:57 +09:00
Hare 075cdfc810 ticket: record plugin cli inspection fix report 2026-06-19 20:17:15 +09:00
Hare b5f10ab7dc plugin: align inspection statuses 2026-06-19 20:15:48 +09:00
Hare 71f4c11fea ticket: dispatch plugin cli inspection fixes 2026-06-19 20:08:47 +09:00
Hare 8a623394da ticket: request plugin cli inspection changes 2026-06-19 20:08:06 +09:00
Hare 349a55fa33 ticket: dispatch plugin cli inspection review 2026-06-19 20:03:57 +09:00
Hare 83699e2011 ticket: record plugin cli inspection implementation 2026-06-19 20:03:12 +09:00
Hare 462de32a5a plugin: add cli inspection 2026-06-19 19:58:10 +09:00
Hare 630548644d ticket: record plugin cli inspection coder start 2026-06-19 19:24:02 +09:00
Hare d51b610f97 ticket: record plugin host api waiting metadata 2026-06-19 19:23:07 +09:00
Hare aea2a8a45d ticket: accept plugin cli inspection work 2026-06-19 19:22:56 +09:00
Hare 3b026b2f5f ticket: queue 00001KVFDX9AF 2026-06-19 19:19:53 +09:00
Hare ecb23a1651 ticket: queue 00001KVFDX9AY 2026-06-19 19:19:52 +09:00
Hare d7f0a718c3 ticket: queue 00001KVFD3YSV 2026-06-19 19:19:28 +09:00
Hare f1876321c5 ticket: add plugin host api followups 2026-06-19 16:54:40 +09:00
Hare 8940262618 ticket: close panel startup e2e work 2026-06-19 14:44:18 +09:00
Hare 69ab9f7c22 fix: speed up panel startup pod probes 2026-06-19 13:19:49 +09:00
Hare caf18dbaab test: measure panel shell startup path 2026-06-19 13:04:45 +09:00
Hare 7593202492 test: align panel dashboard readiness fixture 2026-06-19 00:53:30 +09:00
Hare 63449a8c26 ticket: close panel workspace pod filter 2026-06-19 00:40:49 +09:00
Hare 0ef36b4e02 merge: panel workspace pod filter 2026-06-19 00:38:03 +09:00
Hare 8e8d95eba4 ticket: approve panel workspace pod filter 2026-06-19 00:38:03 +09:00
Hare 49cc0f2e80 ticket: dispatch panel workspace pod re-review 2026-06-19 00:29:55 +09:00
Hare f7179f7a99 ticket: record panel workspace pod fix report 2026-06-19 00:29:15 +09:00
Hare 160c96ad1e pod: persist metadata workspace root 2026-06-19 00:28:19 +09:00
Hare 86ce56b941 ticket: dispatch panel workspace pod fixes 2026-06-19 00:25:31 +09:00
Hare 6952b265b5 ticket: request panel workspace pod changes 2026-06-19 00:24:47 +09:00
Hare 38cc57e7fb ticket: dispatch panel workspace pod review 2026-06-19 00:16:52 +09:00
Hare 7b975aaf93 ticket: record panel workspace pod implementation 2026-06-19 00:16:04 +09:00
Hare 3b634d66ca tui: filter panel pods by workspace 2026-06-19 00:14:02 +09:00
Hare 6fe2dcdf8e ticket: record panel workspace pod coder start 2026-06-18 23:51:56 +09:00
Hare e2e76d3beb ticket: accept panel workspace pod filter 2026-06-18 23:51:03 +09:00
Hare 6cd2af7b72 ticket: close panel dashboard readiness 2026-06-18 23:48:59 +09:00
Hare 6d289a583a ticket: queue 00001KVDH2E06 2026-06-18 23:47:10 +09:00
Hare 667873bdbf merge: sync orchestration before queue 00001KVDH2E06 2026-06-18 23:47:10 +09:00
Hare 2d4d11e476 merge: panel dashboard readiness metric 2026-06-18 23:46:59 +09:00
Hare a92dff05f8 ticket: approve panel dashboard readiness 2026-06-18 23:46:59 +09:00
Hare cd07a9d846 ticket: dispatch panel dashboard re-review 2026-06-18 23:42:29 +09:00
Hare cd86cc533c fix: restore orchestrator companion notifications 2026-06-18 23:42:07 +09:00
Hare 656f3fb249 ticket: record panel dashboard fix report 2026-06-18 23:41:52 +09:00
Hare 5870251bdf tui: tighten panel dashboard readiness 2026-06-18 23:39:52 +09:00
Hare ef0c22eae9 ticket: close plugin permission grants 2026-06-18 23:24:50 +09:00
Hare 94aa3c1d3b merge: plugin permission grants 2026-06-18 23:22:49 +09:00
Hare a172d46c90 ticket: approve plugin grants implementation 2026-06-18 23:22:40 +09:00
Hare 486ee5f41e ticket: dispatch panel dashboard review fixes 2026-06-18 23:21:02 +09:00
Hare d98872af4c ticket: request panel dashboard review changes 2026-06-18 23:20:26 +09:00
Hare 20cc77573b ticket: dispatch reviewers for implementation branches 2026-06-18 23:16:32 +09:00
Hare 7ae725c95d ticket: record coder implementation reports 2026-06-18 23:15:32 +09:00
Hare b1ba15995f plugin: enforce permission grants 2026-06-18 23:13:40 +09:00
Hare fc1ee5bb55 tui: measure panel dashboard readiness 2026-06-18 23:13:06 +09:00
Hare 6c52e5dddf ticket: record panel dashboard coder start 2026-06-18 22:59:29 +09:00
Hare 3b4879446f ticket: accept panel dashboard latency work 2026-06-18 22:58:41 +09:00
Hare b5f0081566 ticket: record plugin grants coder resume 2026-06-18 22:57:43 +09:00
Hare dcbfb6314e ticket: queue 00001KVDETSN6 2026-06-18 22:55:08 +09:00
Hare d2833ffded merge: sync orchestration before queue 00001KVDETSN6 2026-06-18 22:55:08 +09:00
Hare 8cbade818f chore: record panel followups 2026-06-18 22:41:54 +09:00
Hare 9ca89250b4 ticket: record plugin grant spawn failure 2026-06-18 22:12:56 +09:00
Hare a984f5809f ticket: accept plugin permission grants 2026-06-18 22:12:03 +09:00
Hare b6685af3ae ticket: queue 00001KV5W3PJ3 2026-06-18 22:11:00 +09:00
Hare 63d864e1f0 merge: sync orchestration before queue 00001KV5W3PJ3 2026-06-18 22:11:00 +09:00
Hare 6641bf4860 ticket: complete plugin wasm runtime 2026-06-18 21:39:40 +09:00
Hare 05cd788c13 merge: plugin wasm tool runtime 2026-06-18 21:37:21 +09:00
Hare c05bfaa9c4 ticket: approve plugin wasm runtime 2026-06-18 21:37:21 +09:00
Hare f2d4194f37 ticket: record plugin wasm runtime implementation 2026-06-18 21:31:09 +09:00
Hare 10d12148dd feat: run plugin tools through wasm runtime 2026-06-18 21:29:41 +09:00
Hare ca29cd3b89 ticket: complete panel rows-ready e2e 2026-06-18 21:25:23 +09:00
Hare 226eca7a9d merge: panel rows-ready e2e 2026-06-18 21:24:10 +09:00
Hare 49db85c09a ticket: approve panel rows-ready e2e 2026-06-18 21:24:09 +09:00
Hare 4be925f56c ticket: close commit noise policy 2026-06-18 21:22:17 +09:00
Hare 7de73dbd33 ticket: record panel rows-ready implementation 2026-06-18 21:19:51 +09:00
Hare fffdfd2721 test: assert panel rows-ready fixture data 2026-06-18 21:17:51 +09:00
Hare 54cc87132e ticket: resume queued implementation pods 2026-06-18 21:06:11 +09:00
Hare 94f63b1324 merge: sync orchestration before queue 00001KV5W3PJ3 2026-06-18 20:20:44 +09:00
Hare e729e75aaa ticket: record spawn runtime failure 2026-06-17 18:51:03 +09:00
Hare d32fb3bc3c ticket: route wasm runtime and panel readiness e2e 2026-06-17 18:49:29 +09:00
Hare bcb8068ebd ticket: queue 00001KV5W3PHW 2026-06-17 18:46:10 +09:00
Hare a2583b8114 ticket: queue 00001KV62PF32 2026-06-17 18:46:03 +09:00
Hare 9d477f37e7 ticket: close plugin tool surface 2026-06-17 14:44:13 +09:00
Hare cce36419ac merge: integrate orchestration branch 2026-06-17 14:41:20 +09:00
Hare 05c6978d80 ticket: correct panel startup readiness metric 2026-06-17 14:41:15 +09:00
Hare 0da2b5db7b ticket: complete plugin tool surface 2026-06-16 01:40:07 +09:00
Hare 204d0d022f merge: plugin tool surface registration 2026-06-16 01:38:46 +09:00
Hare fb39bf38a1 ticket: approve plugin tool schema fix 2026-06-16 01:38:46 +09:00
Hare fb44159261 ticket: record plugin tool schema fix 2026-06-16 01:31:00 +09:00
Hare 3413bae7d7 fix: reject nested plugin tool schema errors 2026-06-16 01:30:00 +09:00
Hare d9b986853f ticket: request plugin tool schema changes 2026-06-16 01:26:44 +09:00
Hare f262815990 ticket: record plugin tool surface implementation 2026-06-16 01:20:13 +09:00
Hare 05a9c52217 feat: register plugin tool surfaces 2026-06-16 01:18:54 +09:00
Hare fcae886044 ticket: accept plugin tool surface work 2026-06-16 00:54:32 +09:00
Hare 1fdb4cd6f4 ticket: queue 00001KV5W3PHA 2026-06-16 00:53:32 +09:00
Hare 15e60dcbe6 merge: integrate orchestration branch 2026-06-16 00:50:08 +09:00
Hare a03b86e749 ticket: complete plugin resolver 2026-06-16 00:30:09 +09:00
Hare f678383aad merge: plugin package resolver 2026-06-16 00:27:15 +09:00
Hare 1337425504 ticket: approve plugin resolver restore fix 2026-06-16 00:27:15 +09:00
Hare 37e11e465f ticket: record plugin resolver restore fix 2026-06-16 00:16:22 +09:00
Hare 07978d2df5 fix: persist plugin snapshots for restore 2026-06-16 00:15:04 +09:00
Hare 65803c7868 ticket: close completed panel work 2026-06-16 00:09:02 +09:00
Hare a2b991adf8 ticket: request plugin resolver restore fixes 2026-06-16 00:06:02 +09:00
Hare f223bf44ce ticket: add plugin tool followups 2026-06-16 00:00:14 +09:00
Hare 60348708a1 ticket: record plugin resolver fixes 2026-06-15 23:53:30 +09:00
Hare ede7acfdf6 fix: pin plugin resolution metadata 2026-06-15 23:52:13 +09:00
Hare c29d378d4c ticket: request plugin resolver changes 2026-06-15 23:37:18 +09:00
Hare a89b7ac5de ticket: complete panel startup latency e2e 2026-06-15 23:31:36 +09:00
Hare 6f99ebedcc merge: panel startup latency e2e 2026-06-15 23:30:16 +09:00
Hare 77ace64f87 ticket: record plugin resolver implementation 2026-06-15 23:28:02 +09:00
Hare a03a9da64a feat: add plugin package resolver 2026-06-15 23:26:46 +09:00
Hare 9bad2745f7 fix: measure and defer panel startup reload 2026-06-15 23:24:16 +09:00
Hare 4772c4d6a5 ticket: route plugin and panel latency work 2026-06-15 23:01:29 +09:00
Hare 425a6c66a8 ticket: queue 00001KV5MRH6D 2026-06-15 22:59:47 +09:00
Hare d8300a0211 ticket: queue 00001KV5R5V2S 2026-06-15 22:59:47 +09:00
Hare 49abbd9519 ticket: add panel startup latency e2e 2026-06-15 22:50:38 +09:00
Hare 65fa4c06ce merge: integrate orchestration branch 2026-06-15 22:48:46 +09:00
Hare c3d1490443 ticket: add plugin package resolver 2026-06-15 22:48:26 +09:00
Hare 648422c966 ticket: complete panel orchestration overlay 2026-06-15 22:05:29 +09:00
Hare eeb6986f16 merge: panel orchestration overlay 2026-06-15 22:04:30 +09:00
Hare 3eef5fe1b5 ticket: approve panel orchestration overlay 2026-06-15 22:04:29 +09:00
Hare 01e8cd7fb0 ticket: record panel overlay implementation 2026-06-15 21:57:21 +09:00
Hare e0ddbed1eb feat: show orchestration ticket overlay in panel 2026-06-15 21:56:17 +09:00
Hare 95abdc8d94 ticket: accept panel orchestration overlay 2026-06-15 21:40:53 +09:00
Hare 318aa1912b ticket: queue 00001KV5D7MG5 2026-06-15 21:39:21 +09:00
Hare 6572791e50 merge: integrate orchestration branch 2026-06-15 19:48:59 +09:00
Hare 665c58deab ticket: add panel orchestration overlay 2026-06-15 19:48:49 +09:00
Hare c0d8badf55 ticket: complete single-pod text selection 2026-06-15 16:16:06 +09:00
Hare 3fa52f2c01 merge: single-pod text selection 2026-06-15 16:11:47 +09:00
Hare 73e26c41b5 ticket: approve single-pod selection 2026-06-15 16:11:47 +09:00
Hare 314e317a9a ticket: complete panel row hierarchy 2026-06-15 16:09:15 +09:00
Hare 8c00a6e98e merge: panel row hierarchy 2026-06-15 16:08:23 +09:00
Hare 09c7153a04 ticket: approve panel row hierarchy 2026-06-15 16:08:23 +09:00
Hare 10c29c5ae4 ticket: record panel row hierarchy implementation 2026-06-15 16:04:17 +09:00
Hare 2998f37b5a ticket: record single-pod selection implementation 2026-06-15 16:02:54 +09:00
Hare f3b435e724 fix: clarify panel ticket row hierarchy 2026-06-15 16:02:31 +09:00
Hare 09f5e9d51a feat: add single-pod text selection 2026-06-15 16:01:13 +09:00
Hare 79dda10da3 ticket: accept panel row hierarchy work 2026-06-15 15:52:29 +09:00
Hare 1d21aae32c ticket: complete panel alt-enter newline 2026-06-15 15:51:12 +09:00
Hare 0335cad9ff merge: panel alt-enter newline 2026-06-15 15:50:32 +09:00
Hare dba335f74a ticket: approve panel alt-enter fix 2026-06-15 15:50:32 +09:00
Hare 3001bc6873 ticket: record panel alt-enter implementation 2026-06-15 15:46:37 +09:00
Hare 5c33917753 fix: align panel alt-enter composer handling 2026-06-15 15:45:30 +09:00
Hare 368249d677 ticket: route queued tui panel work 2026-06-15 15:39:26 +09:00
Hare f0de841360 ticket: queue 00001KV4ZPAD3 2026-06-15 15:37:02 +09:00
Hare f205fb7540 ticket: queue 00001KV4ZDMV1 2026-06-15 15:37:01 +09:00
Hare ba5d0ee605 ticket: queue 00001KV4YAAVY 2026-06-15 15:37:00 +09:00
Hare 6d4b700181 ticket: record panel and plugin followups 2026-06-15 15:35:35 +09:00
Hare 169f29e960 merge: integrate orchestration branch 2026-06-15 02:24:46 +09:00
Hare 752cce3ffd ticket: refine plugin surface model 2026-06-15 02:24:23 +09:00
Hare 25a91d1cec ticket: complete panel e2e evidence 2026-06-15 01:54:10 +09:00
Hare b5e7ca98fb merge: panel e2e evidence 2026-06-15 01:52:37 +09:00
Hare 1f07e57a2c test: record panel tui e2e evidence 2026-06-15 01:46:43 +09:00
Hare 5e81bc38e6 ticket: accept panel e2e evidence work 2026-06-15 01:39:23 +09:00
Hare 765e6e8ebc ticket: complete invalid ticket panel tolerance 2026-06-15 01:38:06 +09:00
Hare 863b13b687 merge: tolerate invalid panel tickets 2026-06-15 01:37:21 +09:00
Hare 8af11be0f0 ticket: approve invalid ticket panel fixes 2026-06-15 01:37:21 +09:00
Hare 198d619358 ticket: record invalid ticket panel fixes 2026-06-15 01:30:59 +09:00
Hare 456722c339 fix: disable tickets with invalid detail records 2026-06-15 01:30:21 +09:00
Hare d81fced051 ticket: request invalid ticket panel changes 2026-06-15 01:27:24 +09:00
Hare 092fcd806d ticket: complete active workflow compaction 2026-06-15 01:26:06 +09:00
Hare 64d26f8490 merge: preserve active workflows across compaction 2026-06-15 01:25:09 +09:00
Hare 2f51cb6287 ticket: approve active workflow fixes 2026-06-15 01:25:05 +09:00
Hare b2c08d8043 ticket: record invalid ticket panel implementation 2026-06-15 01:21:54 +09:00
Hare b83b9e4e9e fix: tolerate invalid ticket rows in panel 2026-06-15 01:21:04 +09:00
Hare 30b22c1efc ticket: record active workflow fixes 2026-06-15 01:17:51 +09:00
Hare ff446052c7 fix: gate active workflow rehydration state 2026-06-15 01:16:54 +09:00
Hare 61473f6496 ticket: request active workflow changes 2026-06-15 00:58:53 +09:00
Hare a1c8264beb ticket: accept invalid ticket panel work 2026-06-15 00:57:54 +09:00
Hare 81667a9aca ticket: complete plugin package design 2026-06-15 00:56:49 +09:00
Hare 2b9dae4875 merge: plugin package design 2026-06-15 00:56:29 +09:00
Hare 8bcf833e2e ticket: record plugin package review 2026-06-15 00:56:29 +09:00
Hare b77ab0f424 ticket: complete panel intake pod rows 2026-06-15 00:55:41 +09:00
Hare 2fcbd6aefb merge: panel intake pod rows 2026-06-15 00:54:44 +09:00
Hare 48b0d34938 ticket: record panel intake pod review 2026-06-15 00:54:40 +09:00
Hare 01e643719d ticket: record plugin package implementation 2026-06-15 00:53:19 +09:00
Hare 3c674a7051 docs: propose plugin package distribution 2026-06-15 00:52:19 +09:00
Hare 24d0c2139f ticket: record active workflow implementation 2026-06-15 00:50:45 +09:00
Hare d73f748ee8 ticket: accept plugin package implementation 2026-06-15 00:49:44 +09:00
Hare 362fedfbe6 fix: preserve active workflows across compaction 2026-06-15 00:48:39 +09:00
Hare 80a9e40d3a ticket: record panel intake pod implementation 2026-06-15 00:48:17 +09:00
Hare 2664cdd992 feat: show ticket intake pods in panel 2026-06-15 00:47:08 +09:00
Hare e95af466ce ticket: defer plugin package routing for capacity 2026-06-15 00:40:56 +09:00
Hare 4be6c9662d ticket: queue 00001KT0Z4BK8 2026-06-15 00:40:15 +09:00
Hare a92fe5ca0a merge: sync orchestration before queue 00001KT0Z4BK8 2026-06-15 00:40:15 +09:00
Hare 61ed07f3b5 ticket: ready plugin package discovery 2026-06-15 00:37:35 +09:00
Hare d38828a2b3 ticket: defer conflicting queued panel work 2026-06-15 00:37:08 +09:00
Hare 28f3ed626b ticket: queue 00001KV3BQ7Q3 2026-06-15 00:35:57 +09:00
Hare c49d7f9d05 ticket: queue 00001KV3A5CNH 2026-06-15 00:35:56 +09:00
Hare cfbaad0abd merge: sync orchestration before queue 00001KV3A5CNH 2026-06-15 00:35:56 +09:00
Hare 71bf43224d ticket: add e2e evidence followup 2026-06-15 00:35:53 +09:00
Hare becb963bd0 ticket: add panel invalid ticket resilience 2026-06-15 00:35:16 +09:00
Hare 73d0a6a452 ticket: accept queued implementation work 2026-06-15 00:25:03 +09:00
Hare d311fe8f38 ticket: queue 00001KV09WYC6 2026-06-15 00:23:27 +09:00
Hare 392d4da3ad ticket: queue 00001KTFY8V80 2026-06-15 00:23:07 +09:00
Hare a64674e3ab ticket: ready plugin discovery package work 2026-06-15 00:00:04 +09:00
Hare d66dfbbbc2 chore: update orchestration and plugin tickets 2026-06-14 23:49:45 +09:00
Hare adebedc021 ticket: complete profile launch policy scope 2026-06-14 16:04:32 +09:00
Hare 2eaaac97f5 merge: profile launch policy scope 2026-06-14 16:01:26 +09:00
Hare dcbdf251d7 ticket: approve profile launch policy scope 2026-06-14 16:01:14 +09:00
Hare 77892b94f2 ticket: report 00001KV11DHGZ implementation 2026-06-14 15:53:42 +09:00
Hare 21bf009a3f feat: move profile scope to launch policy 2026-06-14 15:52:59 +09:00
Hare 4d626e9632 ticket: complete panel two-line rows 2026-06-14 15:42:18 +09:00
Hare 98357b8aa2 merge: panel ticket two-line rows 2026-06-14 15:40:45 +09:00
Hare e50e1a1a8c ticket: complete feature provider api 2026-06-14 15:40:10 +09:00
Hare f8daecccb3 merge: feature provider api 2026-06-14 15:38:40 +09:00
Hare 77e57cff5d ticket: approve panel two-line rows 2026-06-14 15:38:27 +09:00
Hare d0e8d79106 ticket: approve feature provider api 2026-06-14 15:38:27 +09:00
Hare cdb12af997 ticket: accept profile launch policy scope 2026-06-14 15:35:56 +09:00
Hare 69fc3675f0 ticket: complete profile extend removal 2026-06-14 15:34:47 +09:00
Hare 783c34e75b merge: profile extend removal 2026-06-14 15:32:49 +09:00
Hare c12fbd8eb7 ticket: approve profile extend removal 2026-06-14 15:32:06 +09:00
Hare 053a4f90dc feat: add protocol provider feature contributions 2026-06-14 15:31:19 +09:00
Hare 645d048df5 tui: render panel ticket rows on two lines 2026-06-14 15:28:53 +09:00
Hare 7c6070ef2f profile: remove extend profile composition 2026-06-14 15:24:41 +09:00
Hare f709fc1000 ticket: accept next queued batch 2026-06-14 15:12:46 +09:00
Hare 095331b06e ticket: queue 00001KV11DHGZ 2026-06-14 15:08:45 +09:00
Hare f6f938b5d3 ticket: queue 00001KV12W2RT 2026-06-14 15:08:41 +09:00
Hare 8ad04b2660 ticket: queue 00001KTZY8HK2 2026-06-14 15:08:28 +09:00
Hare 551ee1658c ticket: queue 00001KTR81P9X 2026-06-14 15:08:25 +09:00
Hare 0248db80e1 merge: integrate orchestration branch
# Conflicts:
#	.yoi/tickets/00001KV10SN02/item.md
#	.yoi/tickets/00001KV10SN02/thread.md
2026-06-14 15:08:02 +09:00
Hare 4d5c8b7f86 ticket: complete e2e critical path 2026-06-14 14:39:11 +09:00
Hare 2d9dd7d5e9 merge: e2e critical path
# Conflicts:
#	.yoi/tickets/00001KV10SN02/item.md
#	.yoi/tickets/00001KV10SN02/thread.md
2026-06-14 14:36:15 +09:00
Hare 86dc41ba7b ticket: record e2e critical recovery handoff 2026-06-14 14:35:16 +09:00
Hare bc1decb940 ticket: approve e2e critical path 2026-06-14 14:34:41 +09:00
Hare db95492a4f chore: record profile scope and restore diagnostics 2026-06-14 14:30:18 +09:00
Hare b6c6fc040d merge: sync e2e critical branch
# Conflicts:
#	.yoi/tickets/00001KV10SN02/item.md
#	.yoi/tickets/00001KV10SN02/thread.md
2026-06-14 14:26:50 +09:00
Hare 3de938b7a1 ticket: report e2e critical implementation 2026-06-14 14:24:52 +09:00
Hare b9f49eee1f test: cover critical tui e2e paths 2026-06-14 14:24:12 +09:00
Hare 8f210af72c ticket: complete panel return planning 2026-06-14 14:09:17 +09:00
Hare 7a6321d955 merge: panel return planning
# Conflicts:
#	.yoi/tickets/00001KV09X0XC/item.md
#	.yoi/tickets/00001KV09X0XC/thread.md
#	crates/tui/src/multi_pod.rs
2026-06-14 14:08:16 +09:00
Hare a389e30142 ticket: complete orchestration branch config 2026-06-14 14:06:06 +09:00
Hare 290c4230ac merge: orchestration branch config
# Conflicts:
#	.yoi/tickets/00001KV0X254D/item.md
#	.yoi/tickets/00001KV0X254D/thread.md
2026-06-14 14:04:50 +09:00
Hare 9d4abe5027 ticket: approve panel planning return 2026-06-14 14:03:44 +09:00
Hare 9ad87dda25 ticket: approve orchestration branch config 2026-06-14 14:03:44 +09:00
Hare c53625946e ticket: stop e2e critical path blocker 2026-06-14 04:05:01 +09:00
Hare cb565477a6 ticket: report panel planning return implementation 2026-06-14 04:02:24 +09:00
Hare a0df3279f5 ticket: complete host authority cleanup 2026-06-14 04:02:08 +09:00
Hare f74146c6b4 tui: return ready tickets to planning from panel 2026-06-14 04:00:29 +09:00
Hare 297e95ef4b merge: remove feature host authority
# Conflicts:
#	.yoi/tickets/00001KV0SP0TY/item.md
#	.yoi/tickets/00001KV0SP0TY/thread.md
2026-06-14 04:00:24 +09:00
Hare fc075bc69e ticket: report orchestration branch config 2026-06-14 03:59:48 +09:00
Hare 92e64bda5f ticket: approve host authority cleanup 2026-06-14 03:59:20 +09:00
Hare 1c54689edb tui: configure orchestration branch 2026-06-14 03:58:58 +09:00
Hare 3faf7d7bd1 ticket: report host authority cleanup 2026-06-14 03:53:11 +09:00
Hare 5549c50d86 feat: remove feature host authority API 2026-06-14 03:52:26 +09:00
Hare 144762023a ticket: record e2e critical acceptance 2026-06-14 03:43:37 +09:00
Hare 931f1a074c ticket: record queued coder handoffs 2026-06-14 03:42:53 +09:00
Hare 1abce888ae chore: capture current pod and panel followups 2026-06-14 03:41:40 +09:00
Hare c4465a04d8 ticket: accept queued implementation batch 2026-06-14 03:41:32 +09:00
Hare d15b0a99ea ticket: start e2e critical path 2026-06-14 03:40:06 +09:00
Hare 6cae63fc53 ticket: queue 00001KV10SN02 2026-06-14 02:51:04 +09:00
Hare fcebd4839b merge: integrate orchestration branch
# Conflicts:
#	.yoi/tickets/00001KV0TJVN5/item.md
#	.yoi/tickets/00001KV0TJVN5/thread.md
2026-06-14 02:50:53 +09:00
Hare d370b67dd7 ticket: add e2e and orchestrator scope followups 2026-06-14 02:47:27 +09:00
Hare 9be3f132ed fix: preserve pod restore manifest snapshot 2026-06-14 02:47:27 +09:00
Hare 6aa7c650e8 ticket: complete e2e tmp isolation 2026-06-14 02:34:03 +09:00
Hare 20184eeb1f merge: e2e tmp isolation
# Conflicts:
#	.yoi/tickets/00001KV0YK5S0/item.md
#	.yoi/tickets/00001KV0YK5S0/thread.md
2026-06-14 02:33:09 +09:00
Hare 39f5fffb2b ticket: approve e2e tmp isolation 2026-06-14 02:32:17 +09:00
Hare 07e754ce4b test: isolate e2e tmp runtime fixtures 2026-06-14 02:07:07 +09:00
Hare eb29b63aa1 ticket: accept e2e tmp isolation 2026-06-14 01:57:03 +09:00
Hare f467a77f6e ticket: create e2e tmp isolation followup 2026-06-14 01:56:31 +09:00
Hare d3ea48c87b ticket: note e2e runtime isolation concern 2026-06-14 01:55:52 +09:00
Hare b24aaaccae ticket: close done items 2026-06-14 01:34:18 +09:00
Hare 1df68c0e4a ticket: queue 00001KV0X254D 2026-06-14 01:33:27 +09:00
Hare f6b37f99b3 ticket: queue 00001KV09X0XC 2026-06-14 01:33:26 +09:00
Hare 4100de4b4d ticket: queue 00001KV0SP0TY 2026-06-14 01:33:15 +09:00
Hare 3003a4c7a4 chore: finalize orchestration merge 2026-06-14 01:31:49 +09:00
Hare 2b339247ed merge: integrate orchestration branch 2026-06-14 01:28:55 +09:00
Hare 0f7cac62ef ticket: refine plugin feature layering 2026-06-14 01:28:42 +09:00
Hare 7fe463af63 ticket: complete e2e binary provider 2026-06-14 01:09:41 +09:00
Hare 8abc2b7fa7 merge: e2e binary provider
# Conflicts:
#	.yoi/tickets/00001KV0TJVN5/item.md
#	.yoi/tickets/00001KV0TJVN5/thread.md
2026-06-14 01:08:49 +09:00
Hare d5782788d1 ticket: record e2e credential boundary 2026-06-14 01:08:08 +09:00
Hare 7e24a8df05 ticket: approve e2e binary provider 2026-06-14 01:07:38 +09:00
Hare 47efeb0143 test: isolate e2e yoi subprocess env 2026-06-14 01:02:19 +09:00
Hare 13d0053036 test: build e2e yoi binary provider 2026-06-14 00:54:41 +09:00
Hare a4df975415 ticket: accept e2e binary build followup 2026-06-14 00:47:10 +09:00
Hare 8fa5239102 ticket: note e2e binary build direction 2026-06-14 00:46:35 +09:00
Hare ceb34ba7f6 ticket: create e2e binary build followup 2026-06-14 00:46:29 +09:00
Hare bdc735b86f ticket: complete e2e harness 2026-06-14 00:23:49 +09:00
Hare b3bd6b114f merge: e2e harness
# Conflicts:
#	.yoi/tickets/00001KSKBP9YG/item.md
#	.yoi/tickets/00001KSKBP9YG/thread.md
2026-06-14 00:22:43 +09:00
Hare 04da452a9b ticket: approve e2e harness 2026-06-14 00:21:59 +09:00
Hare b30b43b989 test: cfg-gate e2e observer payloads 2026-06-14 00:18:33 +09:00
Hare 559adb9a3f ticket: request e2e harness changes 2026-06-14 00:06:43 +09:00
Hare 10a1c383c2 test: harden panel e2e harness 2026-06-14 00:00:41 +09:00
Hare 234ffbff2e ticket: add orchestration follow-up tickets 2026-06-13 23:56:32 +09:00
Hare 143cfde74e ticket: request e2e harness corrections 2026-06-13 23:40:48 +09:00
Hare 96561897ae test: add opt-in panel e2e harness 2026-06-13 23:38:51 +09:00
Hare a2084e881e ticket: record e2e coder handoff 2026-06-13 23:19:09 +09:00
Hare 134e8b8b57 ticket: accept e2e harness implementation 2026-06-13 23:17:46 +09:00
Hare 587a06fdad ticket: record e2e design direction 2026-06-13 23:15:54 +09:00
Hare d3d24a03a4 ticket: refine e2e harness scope 2026-06-13 22:56:44 +09:00
Hare 3a6461b6c5 ticket: record panel validation failures 2026-06-13 21:57:59 +09:00
Hare e5150aa9c9 ticket: complete panel quit latency 2026-06-13 20:41:30 +09:00
Hare db7bad7a64 merge: panel quit latency 2026-06-13 20:40:35 +09:00
Hare 2bb36cc40d ticket: approve panel quit latency 2026-06-13 20:40:31 +09:00
Hare 8de8283634 ticket: report panel quit latency fix 2026-06-13 20:35:35 +09:00
Hare cfe411e50d fix: avoid panel quit notice wait 2026-06-13 20:34:40 +09:00
Hare 9dacc90e66 ticket: accept panel quit latency 2026-06-13 20:27:42 +09:00
Hare 6c73b8e076 ticket: complete panel mouse selection 2026-06-13 20:26:34 +09:00
Hare 02311883f7 merge: panel mouse selection
# Conflicts:
#	.yoi/tickets/00001KV072V89/item.md
#	.yoi/tickets/00001KV072V89/thread.md
2026-06-13 20:25:52 +09:00
Hare 6c7385e5cc ticket: approve panel mouse selection 2026-06-13 20:25:03 +09:00
Hare 880cb2f418 ticket: complete rewind live refresh 2026-06-13 20:24:38 +09:00
Hare 802fa1f00f merge: rewind live refresh
# Conflicts:
#	.yoi/tickets/00001KV04NJ8D/item.md
#	.yoi/tickets/00001KV04NJ8D/thread.md
2026-06-13 20:23:46 +09:00
Hare 06a6e4ec57 ticket: approve rewind live refresh 2026-06-13 20:22:36 +09:00
Hare c96a6c465b ticket: report panel mouse implementation 2026-06-13 20:15:11 +09:00
Hare 3a7edbde52 ticket: record rewind live refresh report 2026-06-13 20:14:36 +09:00
Hare 452c9df178 tui: select panel rows by mouse 2026-06-13 20:14:32 +09:00
Hare 949ceb5a21 fix: refresh tui after rewind 2026-06-13 20:13:45 +09:00
Hare 6329e598ae ticket: retain panel quit queue 2026-06-13 20:00:48 +09:00
Hare 200f952228 ticket: refresh coder handoff timestamps 2026-06-13 19:59:51 +09:00
Hare 6f8d2c619f ticket: record coder handoffs 2026-06-13 19:59:41 +09:00
Hare 20daae0c59 ticket: accept panel mouse and rewind routing 2026-06-13 19:57:19 +09:00
Hare 68f1631672 ticket: queue 00001KV04NJ8D 2026-06-13 19:53:20 +09:00
Hare 2ca7c22f99 ticket: queue 00001KV0723PC 2026-06-13 19:53:17 +09:00
Hare 82ea738e4a ticket: queue 00001KV072V89 2026-06-13 19:53:16 +09:00
Hare 8e9855cf56 chore: record current yoi fixes 2026-06-13 19:51:15 +09:00
Hare ad4d0866ae merge: integrate orchestrator companion event notify 2026-06-13 15:03:11 +09:00
Hare 074f4b6ff9 ticket: close event companion notify 2026-06-13 13:22:26 +09:00
Hare ed639ac85f ticket: mark event companion notify done 2026-06-13 13:21:40 +09:00
Hare 2e5a60f4fc merge: companion ticket event notify 2026-06-13 13:20:30 +09:00
Hare 08baab8cbc ticket: record event companion review 2026-06-13 13:20:19 +09:00
Hare e9208295f1 ticket: record event companion implementation 2026-06-13 13:09:50 +09:00
Hare 6f8571f77f fix: render ticket event notice from prompt resource 2026-06-13 13:08:12 +09:00
Hare 465ef1004b feat: notify Companion on Orchestrator ticket events 2026-06-13 12:56:46 +09:00
Hare f58207d2da ticket: delegate event companion notify coder 2026-06-13 12:33:09 +09:00
Hare a3233f04b1 ticket: accept event companion notify 2026-06-13 12:32:03 +09:00
Hare 7ff2f8e3e8 fix: remove panel companion progress feed 2026-06-13 11:51:22 +09:00
Hare 2a7c96909c ticket: reopen companion notify 2026-06-13 11:38:08 +09:00
Hare 20ce1dcda9 merge: integrate orchestration branch 2026-06-13 10:53:20 +09:00
Hare 76ab8c3584 ui: allow panel queue with unrelated root dirt 2026-06-13 10:53:20 +09:00
Hare f235fd18b2 ticket: close idle queued attention 2026-06-13 01:13:08 +09:00
Hare 60cf2d9f09 ticket: mark idle queued done 2026-06-13 01:11:57 +09:00
Hare 9538feb1ce merge: idle queued orchestrator attention 2026-06-13 01:10:38 +09:00
Hare 255a212af9 ticket: record idle queued review 2026-06-13 01:10:31 +09:00
Hare 3005884032 ticket: delegate idle queued review 2026-06-13 01:05:16 +09:00
Hare 81e666d1ee ticket: record idle queued implementation 2026-06-13 01:04:26 +09:00
Hare d2fae81a36 tui: add idle queued orchestrator attention 2026-06-13 01:02:51 +09:00
Hare a85826e82d ticket: delegate idle queued coder 2026-06-13 00:47:58 +09:00
Hare 3b3e786a0b ticket: record idle queued worktree 2026-06-13 00:47:08 +09:00
Hare e72a4536b4 ticket: accept idle queued rekick 2026-06-13 00:46:37 +09:00
Hare 6a1d60f9a5 ticket: close companion notify 2026-06-13 00:44:49 +09:00
Hare 2b64f42854 ticket: mark companion notify done 2026-06-13 00:44:04 +09:00
Hare 56b10a2d6b merge: companion weak progress notify 2026-06-13 00:42:33 +09:00
Hare 85f4bafca6 ticket: approve companion notify review 2026-06-13 00:42:28 +09:00
Hare 40bdb90243 ticket: record companion notify fix 2026-06-13 00:40:21 +09:00
Hare 61e6c0683c fix: resource-back companion progress notice 2026-06-13 00:38:52 +09:00
Hare 042da1bcfd ticket: delegate companion notify fix 2026-06-13 00:31:08 +09:00
Hare 4ad7ae9b8f ticket: request companion notify changes 2026-06-13 00:30:37 +09:00
Hare 46da9523ed ticket: delegate companion notify review 2026-06-13 00:24:00 +09:00
Hare 839b241c2c ticket: record companion notify implementation 2026-06-13 00:23:08 +09:00
Hare 724b79f1c0 Merge branch 'orchestration/yoi-orchestrator' into ticket/orchestrator-progress-companion-notify 2026-06-13 00:21:06 +09:00
Hare 3bcf677768 ticket: close language guidance 2026-06-13 00:20:20 +09:00
Hare 2ba97b674e ticket: mark language guidance done 2026-06-13 00:19:35 +09:00
Hare a87d315471 feat: weak companion progress notify 2026-06-13 00:18:41 +09:00
Hare ec66cad8f8 merge: ticket language guidance for tool users 2026-06-13 00:17:10 +09:00
Hare e1a10e4af4 ticket: record language guidance review 2026-06-13 00:17:05 +09:00
Hare c400fd5062 ticket: delegate language guidance review 2026-06-13 00:11:32 +09:00
Hare 00127ceffa ticket: record language guidance implementation 2026-06-13 00:10:46 +09:00
Hare 2e7ed31f87 ticket: close panel focus model 2026-06-13 00:09:23 +09:00
Hare e330685ec3 ticket: mark panel focus done 2026-06-13 00:08:20 +09:00
Hare 92c4dee71a ticket: guide Ticket tool language universally 2026-06-13 00:08:01 +09:00
Hare d6166c7215 merge: panel focus composer row selection 2026-06-13 00:07:22 +09:00
Hare e9b73d987c ticket: record panel focus review 2026-06-13 00:07:17 +09:00
Hare 8928937942 ticket: delegate panel focus review 2026-06-13 00:02:02 +09:00
Hare 8acf6812a6 ticket: record panel focus implementation 2026-06-13 00:01:13 +09:00
Hare c5ef6f794f tui: clarify panel composer target and row selection 2026-06-12 23:59:05 +09:00
Hare 1ead5f2597 ticket: refresh idle rekick queue note 2026-06-12 23:56:30 +09:00
Hare a9b1ab302d ticket: defer idle rekick for capacity 2026-06-12 23:56:24 +09:00
Hare dcd61410ad ticket: delegate language guidance coder 2026-06-12 23:55:50 +09:00
Hare 97719f6c47 ticket: refresh language guidance state 2026-06-12 23:55:05 +09:00
Hare e34496ff05 ticket: record language guidance worktree 2026-06-12 23:54:54 +09:00
Hare 76d358e824 ticket: accept ticket language guidance 2026-06-12 23:54:31 +09:00
Hare 365051a440 ticket: delegate companion notify coder 2026-06-12 23:52:39 +09:00
Hare 3d3c6d6d45 ticket: refresh companion notify state 2026-06-12 23:51:45 +09:00
Hare 1f2bd8a840 ticket: record companion notify worktree 2026-06-12 23:51:37 +09:00
Hare 05fe1f6fb3 ticket: accept companion progress notify 2026-06-12 23:51:11 +09:00
Hare c3bf6f9a34 ticket: queue 00001KTJXS31R 2026-06-12 23:49:40 +09:00
Hare 25476f993d ticket: queue 00001KTVJGC0Y 2026-06-12 23:49:39 +09:00
Hare cf1e401df6 merge: sync orchestration before queue 00001KTVJGC0Y 2026-06-12 23:49:38 +09:00
Hare f7d5195a4d ticket: refresh panel focus state 2026-06-12 23:46:53 +09:00
Hare d9a5099944 ticket: delegate panel focus coder 2026-06-12 23:46:46 +09:00
Hare 2fa5c0ac7b ticket: record panel focus worktree 2026-06-12 23:46:06 +09:00
Hare f13ab29456 ticket: accept panel focus model 2026-06-12 23:45:46 +09:00
Hare 10e8c84e51 ticket: queue 00001KTVJFT6F 2026-06-12 23:44:16 +09:00
Hare 75d7470923 merge: sync orchestration before queue 00001KTVJFT6F 2026-06-12 23:44:16 +09:00
Hare 550d770fa6 ui: show panel diagnostics and preserve mouse selection 2026-06-12 23:00:31 +09:00
Hare af00af0366 ticket: close role launch split 2026-06-12 22:09:34 +09:00
Hare 9ad5ed6d86 ticket: mark role launch done 2026-06-12 22:08:17 +09:00
Hare bdbd955bc6 merge: ticket role launch input split 2026-06-12 22:07:07 +09:00
Hare 0ebe870658 ticket: record role launch review 2026-06-12 22:07:00 +09:00
Hare 4e8bf411d3 docs: relax nix build validation policy 2026-06-12 21:59:11 +09:00
Hare 2e1eabb186 ticket: delegate role launch review 2026-06-12 21:57:33 +09:00
Hare 57e8663f7e ticket: record role launch implementation 2026-06-12 21:56:53 +09:00
Hare 949531a07e client: shorten ticket role launch input 2026-06-12 21:53:18 +09:00
Hare 6e3970b7d1 ticket: delegate role launch coder 2026-06-12 21:34:25 +09:00
Hare 77a3043a73 ticket: record role launch worktree 2026-06-12 21:32:42 +09:00
Hare ae66c44728 ticket: accept role launch prompt split 2026-06-12 21:32:20 +09:00
Hare 9cc91eea75 ticket: queue 00001KTVPS6K3 2026-06-12 21:29:10 +09:00
Hare 370940a959 ticket: close panel queue orchestrator sync 2026-06-12 21:26:41 +09:00
Hare edb736f4ce merge: integrate orchestrator panel queue sync 2026-06-12 20:50:33 +09:00
Hare ba009b47b2 merge: integrate panel queue orchestrator sync 2026-06-12 20:50:24 +09:00
Hare 47c82103cd prompt: confine orchestrator integration to orchestration branch 2026-06-12 20:49:51 +09:00
Hare 0bcf90680c profile: enable local orchestration tools 2026-06-12 18:50:14 +09:00
Hare a010c8f94b docs: add crate test validity reports 2026-06-12 18:50:14 +09:00
Hare 74b655df0e ui: narrow panel ticket id column 2026-06-12 18:50:14 +09:00
Hare 870b6446b1 ticket: record panel queue sync dossier 2026-06-12 18:12:31 +09:00
Hare 2e29f91bd4 ticket: defer role launch input routing 2026-06-12 18:11:35 +09:00
Hare 190f596413 ticket: delegate panel queue sync review 2026-06-12 18:06:06 +09:00
Hare 28180cc337 ticket: record panel queue sync implementation 2026-06-12 18:05:38 +09:00
Hare 04a3c6e03c tui: make panel queue handoff durable 2026-06-12 18:02:35 +09:00
Hare 25487c9325 ticket: delegate panel queue sync coder 2026-06-12 17:47:26 +09:00
Hare 571b0ce53c ticket: update panel queue sync timestamp 2026-06-12 17:46:11 +09:00
Hare ae55260174 ticket: start panel queue sync implementation 2026-06-12 17:46:06 +09:00
Hare de0f533bc3 ticket: route panel queue sync 2026-06-12 17:45:39 +09:00
Hare 466f90bdd5 prompt: clarify orchestrator branch base 2026-06-12 17:16:01 +09:00
Hare 2ec96d0e47 ticket: start orchestrator branch base guidance 2026-06-12 17:11:52 +09:00
Hare b7e53a185c ticket: add orchestrator branch base guidance 2026-06-12 17:10:59 +09:00
Hare c04b1ca289 fix: validate spawn delegation authority 2026-06-12 17:10:59 +09:00
Hare ee508f707f ticket: accept companion progress work 2026-06-12 12:48:57 +09:00
Hare 3c36d1feb8 fix: use cwd for ticket backend 2026-06-12 11:45:20 +09:00
Hare 9dc78d38bf ticket: queue orchestrator worktree sync 2026-06-12 11:39:25 +09:00
Hare a111a91c83 ticket: record cwd workspace followups 2026-06-12 01:05:29 +09:00
Hare 7eff9301b9 fix: separate workspace root from cwd 2026-06-12 01:03:33 +09:00
Hare 23a5b53807 progress: prepare companion orchestration notifications 2026-06-11 23:12:14 +09:00
Hare e159e9d338 ticket: close builtin workflow resources 2026-06-11 17:52:36 +09:00
Hare ef2099c10a merge: builtin workflow knowledge resources 2026-06-11 17:50:54 +09:00
Hare fb772e29bd ticket: record builtin workflow review and companion progress intake 2026-06-11 17:50:54 +09:00
Hare 58666e3377 ticket: report builtin workflow resources 2026-06-11 17:46:50 +09:00
Hare 2418ad330e feat: add builtin workflow resources 2026-06-11 17:44:42 +09:00
Hare bf5b5bef48 ticket: accept builtin workflow knowledge resources 2026-06-11 17:30:48 +09:00
Hare cd831ec432 ticket: add companion progress notification planning 2026-06-11 17:30:12 +09:00
Hare ef1f5710b3 ticket: close panel orchestration worktree 2026-06-11 17:14:47 +09:00
Hare 735b0c048a merge: panel orchestration worktree 2026-06-11 17:13:14 +09:00
Hare d4dc41bb3f ticket: record panel orchestration review 2026-06-11 17:13:14 +09:00
Hare ab7ea17819 ticket: consolidate lifecycle commit policy 2026-06-11 17:11:22 +09:00
Hare f2938f4e2e ticket: record panel orchestration second fix 2026-06-11 17:10:54 +09:00
Hare 00e11b3df7 feat: launch orchestrator from worktree 2026-06-11 17:10:22 +09:00
Hare dcc87973bd ticket: refine builtin resource implementation 2026-06-11 17:05:24 +09:00
Hare 3b4bb0e62c ticket: record panel orchestration fix loop 2026-06-11 17:04:50 +09:00
Hare 831c59bd12 ticket: report panel orchestration worktree 2026-06-11 16:55:33 +09:00
Hare 02979cb76f ticket: accept panel orchestration worktree 2026-06-11 16:42:35 +09:00
Hare b75e131478 ticket: add orchestrator worktree auto-create 2026-06-11 16:28:38 +09:00
Hare 1810debb58 fix: inherit default role profile config 2026-06-11 16:28:38 +09:00
Hare 730dab65b8 ticket: close orchestrator worktree layout 2026-06-11 14:00:12 +09:00
Hare 5f7b301542 merge: orchestrator worktree layout 2026-06-11 13:59:08 +09:00
Hare 7775ed4184 ticket: record orchestrator worktree review 2026-06-11 13:59:08 +09:00
Hare 93d4053cf3 ticket: record orchestrator worktree fix loop 2026-06-11 13:56:57 +09:00
Hare e7c78f96df feat: track orchestration workspace roots 2026-06-11 13:56:28 +09:00
Hare 3a291439b5 ticket: report orchestrator worktree roots 2026-06-11 13:46:50 +09:00
Hare 95fb8340eb ticket: accept orchestrator worktree layout 2026-06-11 13:35:34 +09:00
Hare 53254ee1f8 ticket: refine orchestration worktree merge policy 2026-06-11 12:49:05 +09:00
Hare d900bdc234 ticket: close workflow split design 2026-06-11 12:48:48 +09:00
Hare af30d64152 ticket: add orchestration worktree planning 2026-06-11 12:48:00 +09:00
Hare 1c2cde51a4 merge: workflow public dogfood split 2026-06-11 12:47:27 +09:00
Hare 8789191787 ticket: add workflow split dossier 2026-06-11 11:33:40 +09:00
Hare 7265f4e7c2 ticket: record workflow split fix loop 2026-06-11 11:32:09 +09:00
Hare 21a25e127f docs: split public and dogfood workflows 2026-06-11 11:31:41 +09:00
Hare 28d6246979 ticket: report workflow split design 2026-06-11 11:27:36 +09:00
Hare 50d826b11a ticket: accept workflow split design 2026-06-11 11:24:33 +09:00
Hare b7a3dae543 ticket: close builtin role profiles 2026-06-11 09:05:29 +09:00
Hare 7daecca8c5 merge: builtin role profiles 2026-06-11 09:04:05 +09:00
Hare f8096bd306 ticket: add builtin role profile dossier 2026-06-11 00:26:39 +09:00
Hare 274e5d3dbf ticket: record builtin role profile fix loop 2026-06-11 00:24:04 +09:00
Hare 85c06dc62e feat: add builtin role profiles 2026-06-11 00:23:15 +09:00
Hare fc32c459bd ticket: report builtin role profiles 2026-06-11 00:15:42 +09:00
Hare a901ebeb4f ticket: accept builtin role profiles 2026-06-11 00:00:41 +09:00
Hare a0b688e29a ticket: record intake and companion closure 2026-06-11 00:00:02 +09:00
Hare 978d97a90a ticket: record builtin role profile routing wait 2026-06-10 20:17:47 +09:00
Hare e3a1292d75 ticket: close lua profile yoi api 2026-06-10 18:55:28 +09:00
Hare 15dc176e81 merge: lua profile yoi api 2026-06-10 18:53:17 +09:00
Hare c8d30df05d ticket: record lua profile api review 2026-06-10 18:53:17 +09:00
Hare e4dd08f8b6 ticket: close file mutation serialization 2026-06-10 18:40:43 +09:00
Hare 29960c1589 merge: serialize file mutations 2026-06-10 18:38:04 +09:00
Hare 05bb33ed8e ticket: record file mutation review 2026-06-10 18:38:04 +09:00
Hare 60e12a94d1 ticket: report lua profile api implementation 2026-06-10 18:37:07 +09:00
Hare 4e1a08c23d feat: add yoi profile lua api 2026-06-10 18:36:40 +09:00
Hare c88b8cccc0 ticket: accept lua profile yoi api 2026-06-10 18:32:32 +09:00
Hare 50f417593c ticket: close setup model wizard 2026-06-10 18:31:50 +09:00
Hare 791ebbf576 ticket: close pod fresh-start path 2026-06-10 18:31:20 +09:00
Hare 021661b568 merge: setup model wizard 2026-06-10 18:29:47 +09:00
Hare 710d962ffe ticket: record setup wizard review 2026-06-10 18:29:47 +09:00
Hare 15daadd015 ticket: report file mutation serialization 2026-06-10 18:29:12 +09:00
Hare c06817b48b fix: list setup command in help 2026-06-10 18:27:18 +09:00
Hare 66d6bf2e2a fix: update setup packaging 2026-06-10 18:27:02 +09:00
Hare 401301438d fix: serialize same-file mutations 2026-06-10 18:24:53 +09:00
Hare 536ff4dd57 ticket: accept file mutation serialization 2026-06-10 18:19:18 +09:00
Hare 5e716fb351 ticket: report setup wizard implementation 2026-06-10 18:17:10 +09:00
Hare 32be6075c1 feat: add setup model command 2026-06-10 18:16:23 +09:00
Hare 6bb023e9fe merge develop into setup wizard worktree 2026-06-10 18:12:31 +09:00
Hare 9309cef4fb ticket: record setup wizard routing blocker 2026-06-10 18:09:03 +09:00
Hare 6e0cff0830 ticket: close prompt resource centralization 2026-06-10 18:08:37 +09:00
Hare 9aaa3232ef merge: prompt resource centralization 2026-06-10 18:07:29 +09:00
Hare ed1b456284 ticket: add prompt resource merge dossier 2026-06-10 18:07:25 +09:00
Hare 41f7449008 ticket: record routing progress 2026-06-10 18:07:00 +09:00
Hare 16ceb3e22e ticket: record prompt resource implementation 2026-06-10 17:11:58 +09:00
Hare 2cedd97d25 ticket: record additional queue notifications 2026-06-10 17:11:28 +09:00
Hare 342d5cf8dd refactor: move ticket role prompts to resources 2026-06-10 17:10:47 +09:00
Hare 76165b47d6 ticket: accept wizard and prompt cleanup 2026-06-10 16:59:39 +09:00
Hare 095441dbd1 ticket: record new objectives and tickets 2026-06-10 16:58:12 +09:00
Hare 63524215f0 ticket: close base32 id migration 2026-06-09 22:26:03 +09:00
Hare 5f6c695b80 merge: unify project record ids 2026-06-09 22:24:40 +09:00
Hare 52c5c3afec ticket: approve base32 id migration 2026-06-09 22:24:40 +09:00
Hare bd9651bddd ticket: record base32 implementation report 2026-06-09 22:12:35 +09:00
Hare 4203988d74 ticket: use base32 project record ids 2026-06-09 22:10:47 +09:00
Hare 2bc299c5b1 ticket: route base32 id implementation 2026-06-09 21:48:05 +09:00
Hare 0803bc3725 ticket: accept base32 id migration 2026-06-09 21:46:51 +09:00
Hare 264dfce3c5 ticket: close profile feature flags 2026-06-09 21:46:13 +09:00
Hare c71a27275d merge: gate tool surfaces by profile features 2026-06-09 21:42:57 +09:00
Hare b43e6e8d72 ticket: approve profile feature flags 2026-06-09 21:42:49 +09:00
Hare 977313dd90 ticket: record project profile test fix 2026-06-09 21:38:35 +09:00
Hare 656048a0ad test: cover project role feature profiles 2026-06-09 21:38:12 +09:00
Hare 2a0911ec30 ticket: close action attention cleanup 2026-06-09 21:33:31 +09:00
Hare 1e534b954b merge: remove ticket attention fields 2026-06-09 21:32:36 +09:00
Hare 61c93990d1 ticket: record feature role fix and attention approval 2026-06-09 21:32:06 +09:00
Hare 507863f86a fix: lock project role feature surfaces 2026-06-09 21:31:33 +09:00
Hare 4eb3e117e3 ticket: record feature cleanup review fixes 2026-06-09 21:22:21 +09:00
Hare 2fd37afb9e fix: align pod feature flag naming 2026-06-09 21:21:40 +09:00
Hare 94db2dc8c9 fix: hide obsolete ticket fields in cli show 2026-06-09 21:19:42 +09:00
Hare 7f2a6568c3 ticket: route feature cleanup reviews 2026-06-09 21:10:26 +09:00
Hare 7b80a9b69c ticket: record coder reports and intake refinement 2026-06-09 21:08:31 +09:00
Hare 3afdd894d8 ticket: remove action attention fields 2026-06-09 21:05:48 +09:00
Hare f0f6cc92d8 feat: gate built-in tools by profile features 2026-06-09 21:05:38 +09:00
Hare 2bd4e43eaa ticket: record feature and attention handoffs 2026-06-09 20:32:02 +09:00
Hare 41133e0cd5 ticket: route feature flags and attention cleanup 2026-06-09 20:30:37 +09:00
Hare bebb0bd5da ticket: close panel composer keys 2026-06-09 20:28:55 +09:00
Hare 57ed405890 merge: improve panel composer keys 2026-06-09 20:26:09 +09:00
Hare bf701b9fed ticket: record panel composer review 2026-06-09 20:26:09 +09:00
Hare 1611f61675 ticket: record panel composer fix loop 2026-06-09 20:21:17 +09:00
Hare 573b02fbfc tui: clarify panel composer enter hints 2026-06-09 20:18:47 +09:00
Hare 774bb10c35 ticket: close analytics batching and record panel review 2026-06-09 20:07:52 +09:00
Hare c837fbceb5 merge: add session analytics response batching 2026-06-09 20:04:28 +09:00
Hare b2e1b91265 ticket: record analytics batching review 2026-06-09 20:04:28 +09:00
Hare c306339e0a ticket: record panel and analytics implementations 2026-06-09 19:55:50 +09:00
Hare 703176df7c ticket: close ticket list output slimming 2026-06-09 19:53:50 +09:00
Hare f2cdb6fd19 fix: align ticket list tests with tool context 2026-06-09 19:53:16 +09:00
Hare 963db29d96 analytics: add response batching metrics 2026-06-09 19:51:06 +09:00
Hare 20f06b3541 tui: clarify panel focus and composer keys 2026-06-09 19:49:26 +09:00
Hare b6ac36e65e merge: lighten ticket list output 2026-06-09 19:48:09 +09:00
Hare 81feb77433 ticket: close parallel queued routing 2026-06-09 19:47:56 +09:00
Hare ad5d3bad64 merge: prefer parallel queued routing 2026-06-09 19:47:28 +09:00
Hare c5a022bbdf ticket: close tool execution context 2026-06-09 19:47:01 +09:00
Hare 89e768a658 ticket: record tool context and parallel reviews 2026-06-09 19:46:29 +09:00
Hare 4744548d27 merge: add tool execution context 2026-06-09 19:43:53 +09:00
Hare a775a10d95 ticket: record tool context review and parallel guidance implementation 2026-06-09 19:43:13 +09:00
Hare 492fe06832 workflow: prefer parallel queued starts 2026-06-09 19:41:20 +09:00
Hare 762a18425f ticket: record ticketlist implementation 2026-06-09 19:39:46 +09:00
Hare 7368416e54 ticket: lighten ticket list output 2026-06-09 19:38:09 +09:00
Hare 65c47d6c38 ticket: record analytics and parallel handoffs 2026-06-09 19:36:54 +09:00
Hare 5d9e227823 ticket: route analytics batching and parallel guidance 2026-06-09 19:35:18 +09:00
Hare 28e7fe3890 ticket: record tool context implementation 2026-06-09 19:33:54 +09:00
Hare 5f0be7eaad ticket: record additional queued updates 2026-06-09 19:32:59 +09:00
Hare d8aed7befe tool: add execution context 2026-06-09 19:31:11 +09:00
Hare f7ff7e20f5 ticket: record panel ticket updates 2026-06-09 19:21:47 +09:00
Hare 873076e973 ticket: record parallel handoffs 2026-06-09 19:21:14 +09:00
Hare d95b3ffff6 ticket: route parallel ticketlist and panel work 2026-06-09 19:19:43 +09:00
Hare 949d6ee705 ticket: add parallel routing guidance 2026-06-09 19:18:50 +09:00
Hare 101061031c ticket: defer attention field cleanup routing 2026-06-09 19:12:32 +09:00
Hare 3c67ae5aa9 ticket: record tool execution context handoff 2026-06-09 19:05:13 +09:00
Hare b21fab82fc ticket: route tool execution context 2026-06-09 19:03:56 +09:00
Hare 5e7f1b921e ticket: record queued tool and panel updates 2026-06-09 19:02:50 +09:00
Hare 3b6a3da19f ticket: record tool analytics followups 2026-06-09 18:51:03 +09:00
Hare 7f4c78f1b6 ticket: close session analytics tooling 2026-06-09 16:41:14 +09:00
Hare 0d2a6a7bf3 merge: add session analytics tooling 2026-06-09 16:39:41 +09:00
Hare b9dda788f6 ticket: record session analytics review 2026-06-09 16:39:41 +09:00
Hare c7ce8d6dbb ticket: add base32 id unification 2026-06-09 16:39:41 +09:00
Hare 277cb547f5 objective: record e2e test strategy 2026-06-09 16:27:27 +09:00
Hare 32f4656b87 ticket: record session analytics implementation 2026-06-09 16:26:58 +09:00
Hare c1809b37b1 feat: add session analytics tooling 2026-06-09 16:24:55 +09:00
Hare fdf2efbd82 ticket: record session analytics handoff 2026-06-09 16:00:46 +09:00
Hare c166140660 ticket: route session analytics tooling 2026-06-09 15:59:29 +09:00
Hare bd4c3afb22 ticket: record session analytics queue 2026-06-09 15:58:15 +09:00
Hare 91c3763653 ticket: close objective records 2026-06-09 15:57:30 +09:00
Hare be69a8b06f merge: add objective records 2026-06-09 15:56:29 +09:00
Hare 8e17b00b51 ticket: record objective records review 2026-06-09 15:56:29 +09:00
Hare 5b92e1da12 ticket: record objective records implementation 2026-06-09 15:50:04 +09:00
Hare be12072547 objective: add lightweight records 2026-06-09 15:48:07 +09:00
Hare f2f4039389 ticket: record objective records handoff 2026-06-09 15:33:35 +09:00
Hare 4b3be3f0b3 ticket: route objective records 2026-06-09 15:32:34 +09:00
Hare 0fef311f75 ticket: close typed relation metadata 2026-06-09 15:31:27 +09:00
Hare 2225311d0b merge: add typed ticket relation metadata 2026-06-09 15:29:49 +09:00
Hare 8aaeb2d6f8 ticket: record relation metadata review 2026-06-09 15:29:49 +09:00
Hare 51c6176ce1 ticket: record relation metadata implementation 2026-06-09 15:19:43 +09:00
Hare 4601ad2b41 ticket: add typed relation metadata 2026-06-09 15:17:45 +09:00
Hare 02b0ec1e9a ticket: record relation metadata handoff 2026-06-09 14:43:53 +09:00
Hare 41a61d79d9 ticket: route typed relation metadata 2026-06-09 14:42:56 +09:00
Hare 7cfc108030 ticket: close identity simplification 2026-06-09 14:41:27 +09:00
Hare 634da5d769 merge: simplify ticket identity fields
# Conflicts:
#	.yoi/tickets/20260607-020215-001/item.md
#	.yoi/tickets/20260607-020215-001/thread.md
#	.yoi/tickets/20260608-072732-001/item.md
#	.yoi/tickets/20260608-110940-001/item.md
#	.yoi/tickets/20260608-125430-001/item.md
#	.yoi/tickets/closed/20260607-020215-workspace-panel-orchestrator-queue-automation/item.md
#	.yoi/tickets/closed/20260607-020215-workspace-panel-orchestrator-queue-automation/thread.md
#	.yoi/tickets/open/20260607-020215-workspace-panel-orchestrator-queue-automation/item.md
#	.yoi/tickets/open/20260607-020215-workspace-panel-orchestrator-queue-automation/thread.md
2026-06-09 14:13:30 +09:00
Hare 3b01c9b3b2 ticket: record pre-migration ticket updates 2026-06-09 14:06:28 +09:00
Hare 93648e6d50 ticket: record identity simplification approval 2026-06-09 14:05:01 +09:00
Hare b4f16592d3 ticket: record identity simplification fourth fix loop 2026-06-09 13:59:17 +09:00
Hare a6326a989e fix: align ticket intake state wording 2026-06-09 13:57:35 +09:00
Hare efad0e678e ticket: record identity simplification fourth review 2026-06-09 13:50:26 +09:00
Hare c8d2415989 ticket: record identity simplification third fix loop 2026-06-09 13:41:59 +09:00
Hare 6ca27f3663 fix: use flat ticket path in tui test 2026-06-09 13:40:41 +09:00
Hare dfe3749af9 ticket: record identity simplification third review 2026-06-09 13:36:05 +09:00
Hare 08ff812ce4 ticket: record identity simplification second fix loop 2026-06-09 13:28:28 +09:00
Hare 8fe4b822ee fix: align ticket flat-state surfaces 2026-06-09 13:27:02 +09:00
Hare e9e5caccd6 ticket: record identity simplification second review 2026-06-09 13:16:19 +09:00
Hare 61b8b67951 ticket: record identity simplification fix loop 2026-06-09 13:07:07 +09:00
Hare 21114fdd6f fix: remove stale ticket status surfaces 2026-06-09 13:04:57 +09:00
Hare 5d2290ac2d ticket: record identity simplification review changes 2026-06-09 12:27:23 +09:00
Hare 953f2917f7 ticket: record identity simplification implementation 2026-06-09 12:17:29 +09:00
Hare 591db3ff72 test: update ticket schema expectations 2026-06-09 12:15:58 +09:00
Hare 191a875f5a ticket: simplify ticket identity fields 2026-06-09 11:57:15 +09:00
Hare 06f08edecc ticket: defer relation and objective routing 2026-06-09 11:28:28 +09:00
Hare 48efcc7dfb ticket: route identity simplification 2026-06-09 11:14:41 +09:00
Hare 9d9baba969 ticket: record identity simplification queue 2026-06-09 11:13:57 +09:00
Hare 9bbbad5546 ticket: close umbrella deprecation 2026-06-09 11:04:52 +09:00
Hare ee41ed94d6 merge: deprecate umbrella tickets 2026-06-09 11:04:08 +09:00
Hare 340cf2c6ed ticket: record umbrella deprecation review dossier 2026-06-09 10:38:06 +09:00
Hare d5c04128b6 ticket: record umbrella deprecation implementation 2026-06-09 10:33:32 +09:00
Hare 1349a75350 ticket: deprecate umbrella containers 2026-06-09 10:31:58 +09:00
Hare 09afc812dd ticket: record umbrella deprecation handoff 2026-06-09 10:20:40 +09:00
Hare 8db8d7d926 ticket: route umbrella deprecation 2026-06-09 10:19:46 +09:00
Hare 832e01a0ab ticket: close return planning policy 2026-06-09 10:19:04 +09:00
Hare 5af58b5ad8 merge: tighten orchestrator planning return policy 2026-06-09 10:18:28 +09:00
Hare bcf9e2e58c ticket: defer umbrella deprecation routing 2026-06-09 10:14:57 +09:00
Hare d50e6236f8 ticket: record return planning review dossier 2026-06-09 09:24:35 +09:00
Hare 427a919077 ticket: record return planning implementation 2026-06-09 09:20:08 +09:00
Hare 03c3218dc7 ticket: record additional queued updates 2026-06-09 09:20:08 +09:00
Hare 8576615f2c workflow: tighten orchestrator planning return policy 2026-06-09 09:18:08 +09:00
Hare 2a3f744c26 ticket: record return planning handoff 2026-06-09 09:07:17 +09:00
Hare 9f35442a41 ticket: route return-to-planning policy 2026-06-09 09:06:32 +09:00
Hare 958b24133d ticket: close composer history persistence 2026-06-09 09:05:23 +09:00
Hare e6593d0549 ticket: record return planning queue 2026-06-09 09:04:54 +09:00
Hare b616420722 merge: persist tui composer history 2026-06-09 09:04:03 +09:00
Hare 2eafe24607 ticket: record composer history review dossier 2026-06-09 09:00:47 +09:00
Hare f37b341677 ticket: record composer history implementation 2026-06-09 08:55:33 +09:00
Hare 64b7ff7c7c tui: persist composer history 2026-06-09 08:54:15 +09:00
Hare 7af88483fc ticket: record composer history handoff 2026-06-09 08:39:02 +09:00
Hare ff5f985f70 ticket: route composer history persistence 2026-06-09 08:38:10 +09:00
Hare 208f7b3eaa ticket: close merged queued tickets 2026-06-09 08:37:01 +09:00
Hare e6bae0429f merge: render tui markdown tables 2026-06-09 08:34:14 +09:00
Hare b3eab44412 merge: add ticket orchestration plan tools 2026-06-09 08:34:10 +09:00
Hare 1cf54efd89 ticket: record tui table rendering review dossier 2026-06-08 22:29:35 +09:00
Hare 68b0156faa ticket: record tui table rendering implementation 2026-06-08 22:26:28 +09:00
Hare f767ec7a59 tui: render markdown pipe tables in chat 2026-06-08 22:25:29 +09:00
Hare 897835b678 ticket: record orchestration plan review dossier 2026-06-08 22:23:53 +09:00
Hare af13abdaa7 ticket: defer composer history routing 2026-06-08 22:19:39 +09:00
Hare 17bddbae20 ticket: record orchestration plan review handoff 2026-06-08 22:18:40 +09:00
Hare f264663367 ticket: record tui table rendering handoff 2026-06-08 22:17:05 +09:00
Hare 3f9d5448f8 ticket: record orchestration plan implementation report 2026-06-08 22:16:22 +09:00
Hare b28b7759f5 ticket: add orchestration plan tools 2026-06-08 22:16:08 +09:00
Hare 33467911ca ticket: record composer history readiness 2026-06-08 22:15:44 +09:00
Hare 60609ec326 ticket: route tui markdown table rendering 2026-06-08 22:15:21 +09:00
Hare 0ba56fdc37 project: record queued tickets and issue notes 2026-06-08 22:14:49 +09:00
Hare 0b9ce1e36b ticket: record orchestration plan tool handoff 2026-06-08 21:51:45 +09:00
Hare 68770a2b66 ticket: route orchestration plan tool 2026-06-08 21:50:55 +09:00
Hare 1d236de956 ticket: close legacy schema cleanup 2026-06-08 21:49:31 +09:00
Hare de8e973ce2 merge: remove legacy ticket schema fields
# Conflicts:
#	.yoi/tickets/open/20260608-103842-remove-legacy-ticket-schema-fields/item.md
#	.yoi/tickets/open/20260608-103842-remove-legacy-ticket-schema-fields/thread.md
2026-06-08 21:48:40 +09:00
Hare 242f9266d7 ticket: record legacy schema implementation report 2026-06-08 21:47:18 +09:00
Hare 934a4b5802 ticket: remove legacy schema fields 2026-06-08 21:36:56 +09:00
Hare 51adf011b6 ticket: authorize legacy ticket field removal 2026-06-08 21:17:56 +09:00
Hare 2a6b9162d4 ticket: record legacy schema cleanup block 2026-06-08 21:13:33 +09:00
Hare fdb9f50bd8 ticket: route queued schema cleanup 2026-06-08 21:10:39 +09:00
Hare 87d89bfa5c ticket: record queued intake updates 2026-06-08 21:09:58 +09:00
Hare 939ba16e8d ticket: close investigator role cleanup 2026-06-08 20:55:32 +09:00
Hare b552372d76 merge: remove fixed investigator ticket role 2026-06-08 20:54:46 +09:00
Hare 427a270722 ticket: remove fixed investigator role 2026-06-08 20:42:37 +09:00
Hare 5025ca9b36 ticket: record orchestration plan delegation block 2026-06-08 20:21:53 +09:00
Hare d7e2b6f628 ticket: record investigator role delegation block 2026-06-08 20:18:36 +09:00
Hare dc65b7d4a1 ticket: route investigator role cleanup 2026-06-08 20:17:15 +09:00
Hare c24b101ad2 ticket: remove legacy ticket schema fields 2026-06-08 19:56:08 +09:00
Hare 07f8b3cb8a ticket: migrate open tickets to planning state 2026-06-08 19:22:03 +09:00
Hare 603af8bd3b ticket: close planning workflow-state replacement 2026-06-08 18:19:29 +09:00
Hare 64466f2916 merge: replace intake state with planning 2026-06-08 18:17:52 +09:00
Hare f15ccf5e9e ticket: record planning state merge-ready dossier 2026-06-08 18:17:34 +09:00
Hare 212c38eb1b ticket: record planning state re-review 2026-06-08 18:15:08 +09:00
Hare eddb33cf83 docs: fix planning sync workflow references 2026-06-08 18:13:46 +09:00
Hare e8b463f82a ticket: record planning state review changes 2026-06-08 18:09:37 +09:00
Hare cbbccae7da ticket: record planning state review delegation 2026-06-08 18:02:28 +09:00
Hare ada6db99d8 feat: replace intake workflow state with planning 2026-06-08 18:00:23 +09:00
Hare 109e991ffb ticket: record planning state coder delegation 2026-06-08 17:38:47 +09:00
Hare cb234b86ad ticket: route planning workflow-state replacement 2026-06-08 17:37:32 +09:00
Hare 7e29c1ac4e ticket: record planning workflow followups 2026-06-08 17:22:18 +09:00
Hare af13a8bddb ticket: close ticket record language split 2026-06-08 17:22:05 +09:00
Hare a74e315bc3 merge: separate ticket record language 2026-06-08 17:19:10 +09:00
Hare ccea1e05a9 ticket: record ticket language merge-ready dossier 2026-06-08 17:18:55 +09:00
Hare 0b6f4a3b22 ticket: close spawnpod child cwd 2026-06-08 17:18:03 +09:00
Hare 05df656616 merge: allow SpawnPod child cwd
# Conflicts:
#	crates/pod/src/pod.rs
2026-06-08 17:15:05 +09:00
Hare 53c052578d ticket: record spawnpod cwd merge-ready dossier 2026-06-08 17:13:46 +09:00
Hare 2bd0789713 ticket: close intake idle-shutdown 2026-06-08 17:13:01 +09:00
Hare f7c50606e4 merge: shutdown intake after ready idle 2026-06-08 17:11:19 +09:00
Hare 4cb2235c91 ticket: record intake idle shutdown merge-ready dossier 2026-06-08 17:10:52 +09:00
Hare 885e493ba2 ticket: record spawnpod cwd re-review 2026-06-08 17:08:21 +09:00
Hare 248744f9cd fix: keep SpawnPod cwd separate 2026-06-08 17:06:50 +09:00
Hare b1346eeea3 ticket: record ticket language review delegation 2026-06-08 17:04:34 +09:00
Hare b662f84d41 ticket: record intake idle shutdown review delegation 2026-06-08 17:03:09 +09:00
Hare fb261bb4f6 feat: add ticket record language config 2026-06-08 17:02:16 +09:00
Hare 61c323189c pod: stop intake after ready idle 2026-06-08 17:00:37 +09:00
Hare a987250cd3 ticket: record ticket language coder delegation 2026-06-08 16:42:18 +09:00
Hare 17ac5b04f0 ticket: route ticket record language implementation 2026-06-08 16:41:20 +09:00
Hare 2f4addbfb9 ticket: record intake idle shutdown coder delegation 2026-06-08 16:38:32 +09:00
Hare 64318e8045 ticket: route intake idle shutdown implementation 2026-06-08 16:37:28 +09:00
Hare d380d20e84 ticket: record spawnpod cwd review changes 2026-06-08 16:32:13 +09:00
Hare a3edd11528 ticket: record spawnpod cwd review delegation 2026-06-08 16:25:13 +09:00
Hare 3dd77079f1 feat: add SpawnPod cwd 2026-06-08 16:23:37 +09:00
Hare 815213cb5c ticket: record spawnpod cwd coder delegation 2026-06-08 16:07:42 +09:00
Hare 15cf4a1332 ticket: route spawnpod cwd implementation 2026-06-08 16:06:37 +09:00
Hare 3db52a63ad ticket: close direct delegation authority split 2026-06-08 15:44:01 +09:00
Hare 92d1c0bb10 merge: split direct and delegation authority 2026-06-08 15:41:01 +09:00
Hare 4b84be4bb8 ticket: record direct delegation merge-ready dossier 2026-06-08 15:40:46 +09:00
Hare a255fe7231 ticket: record direct delegation re-review 2026-06-08 15:38:36 +09:00
Hare f43c8ac65c fix: validate delegation path sets exactly 2026-06-08 15:37:13 +09:00
Hare c835c16f1d ticket: refine orchestrator planning queue 2026-06-08 15:33:04 +09:00
Hare 6e77b1cccd ticket: record direct delegation review changes 2026-06-08 15:31:21 +09:00
Hare c8440d2078 ticket: record direct delegation review delegation 2026-06-08 15:24:53 +09:00
Hare a4a9b002c6 feat: split direct and delegation scope authority 2026-06-08 15:22:39 +09:00
Hare dfd155ab0f ticket: route intake idle-shutdown preflight 2026-06-08 15:21:15 +09:00
Hare 9129e81fbe ticket: close panel done-ticket action 2026-06-08 15:11:08 +09:00
Hare 24159561b6 merge: close done tickets from panel 2026-06-08 15:09:56 +09:00
Hare 78b4257f25 ticket: record panel close merge-ready dossier 2026-06-08 15:09:38 +09:00
Hare 59ebac76e0 ticket: record panel close review and language preflight 2026-06-08 15:03:51 +09:00
Hare 6d41ed31cf tui: close done tickets from panel 2026-06-08 15:01:09 +09:00
Hare b0e587cb8d ticket: record panel close coder delegation 2026-06-08 14:51:15 +09:00
Hare c6e8f6af8f ticket: route panel close done tickets 2026-06-08 14:50:18 +09:00
Hare 67519f5387 ticket: record direct delegation coder delegation 2026-06-08 14:48:26 +09:00
Hare fa39f921d5 ticket: route direct delegation authority split 2026-06-08 14:47:22 +09:00
Hare 776e7ca3e3 ticket: route pod archive fresh-start preflight 2026-06-08 12:49:22 +09:00
Hare 856de91c51 ticket: close intake claim timing fix 2026-06-08 12:33:01 +09:00
Hare 3bc4ab2840 merge: defer intake claims until launch success 2026-06-08 12:31:53 +09:00
Hare 2f62092413 ticket: record intake claim merge-ready dossier 2026-06-08 12:31:42 +09:00
Hare 731237ac8d config: set project role language 2026-06-08 12:30:50 +09:00
Hare 4b97a6a180 ticket: record intake claim review delegation 2026-06-08 12:24:23 +09:00
Hare 6797be30f0 fix: defer intake claim until launch acceptance 2026-06-08 12:23:06 +09:00
Hare 78a779e48d ticket: record intake claim coder delegation 2026-06-08 12:09:35 +09:00
Hare d2a040d77a ticket: route intake claim and spawn cwd tickets 2026-06-08 12:08:33 +09:00
Hare 50c5743fa0 ticket: close podclient reader cleanup 2026-06-08 11:54:41 +09:00
Hare b0f37b52eb merge: abort podclient reader task on drop 2026-06-08 11:53:18 +09:00
Hare 6864413456 ticket: record podclient reader merge-ready dossier 2026-06-08 11:52:58 +09:00
Hare ca9b5c69c0 ticket: record podclient reader review delegation 2026-06-08 11:50:49 +09:00
Hare aec75b3a35 fix: abort PodClient reader task on drop 2026-06-08 11:49:26 +09:00
Hare a6c3ef1a79 ticket: record podclient reader coder delegation 2026-06-08 11:43:00 +09:00
Hare 89b4369f2a ticket: route podclient reader cleanup 2026-06-08 11:42:09 +09:00
Hare 9b3041ec3a ticket: close workspace panel nonblocking transitions 2026-06-08 11:29:28 +09:00
Hare 86198d85c3 merge: workspace panel nonblocking transitions 2026-06-08 11:27:22 +09:00
Hare 99b24ffcec ticket: record workspace panel merge-ready dossier 2026-06-08 11:27:10 +09:00
Hare ebcc32ddb3 ticket: close workflow template non-goals cleanup 2026-06-08 11:23:30 +09:00
Hare c2d624569c merge: workflow template non-goals cleanup 2026-06-08 11:21:35 +09:00
Hare 45ee5d4fee ticket: record workflow template merge-ready dossier 2026-06-08 11:21:26 +09:00
Hare 2514b6f99e ticket: record workspace panel review delegation 2026-06-08 11:20:56 +09:00
Hare 12a4f39328 tui: make panel transitions nonblocking 2026-06-08 11:19:28 +09:00
Hare 18b6d8a620 ticket: record workspace panel coder delegation 2026-06-08 11:09:26 +09:00
Hare e3df2231cb ticket: route workspace panel nonblocking transitions 2026-06-08 11:08:27 +09:00
Hare df83d3f8cf ticket: record workflow template review delegation 2026-06-08 11:05:11 +09:00
Hare 783cd42638 workflow: replace non-goals template language 2026-06-08 11:03:56 +09:00
Hare d6f66dec01 ticket: close runtime workspace identity bundle 2026-06-08 11:00:39 +09:00
Hare b7a533f6cb merge: runtime workspace identity bundle 2026-06-08 10:57:47 +09:00
Hare 7729c83581 ticket: record runtime workspace merge-ready dossier 2026-06-08 10:54:18 +09:00
Hare 7eb0304ca2 ticket: record workflow template coder delegation 2026-06-08 10:51:26 +09:00
Hare b45d8f1f6e ticket: route workflow template non-goals cleanup 2026-06-08 10:50:39 +09:00
Hare 17248b5eca ticket: record runtime workspace re-review 2026-06-08 10:49:35 +09:00
Hare 15f54df0ba runtime: use pod flag for session identity 2026-06-08 10:48:00 +09:00
Hare 9a9c28bcc6 ticket: record runtime workspace review changes 2026-06-08 10:43:12 +09:00
Hare 8587f623f7 ticket: clarify panel and spawn authority tasks 2026-06-08 10:37:20 +09:00
Hare 0f8aede253 ticket: record runtime workspace review delegation 2026-06-08 10:36:06 +09:00
Hare b6af761da0 runtime: separate workspace pod and profile identity 2026-06-08 10:34:50 +09:00
Hare e210d76a82 ticket: record runtime workspace coder delegation 2026-06-08 10:04:52 +09:00
Hare d68e8d3f95 ticket: record runtime workspace delegation block 2026-06-08 09:59:55 +09:00
Hare 9df7f4eeb7 ticket: record workspace identity routing 2026-06-08 09:57:46 +09:00
Hare 992949e3b1 ticket: record pod identity boundary decision 2026-06-08 09:56:47 +09:00
Hare c6afb5004b ticket: add pod naming cleanup tasks 2026-06-08 09:07:29 +09:00
Hare 6903eea686 ticket: record yaml and planning merge completion 2026-06-08 08:38:45 +09:00
Hare 3079606054 merge: relax implementation planning readiness 2026-06-08 08:35:31 +09:00
Hare 10dc6da903 merge: parse ticket frontmatter as yaml 2026-06-08 08:35:31 +09:00
Hare 5b7c32ca4d ticket: record planning readiness dossier 2026-06-08 08:30:01 +09:00
Hare 54f227a9e1 ticket: record yaml and planning review progress 2026-06-08 08:25:55 +09:00
Hare 1e2d1d8545 docs: relax implementation readiness wording 2026-06-08 08:22:35 +09:00
Hare dbdccc50c7 ticket: quote frontmatter strings conservatively 2026-06-08 08:22:01 +09:00
Hare 10d7844fc8 ticket: parse item frontmatter as YAML 2026-06-08 08:13:19 +09:00
Hare aa61285dc3 ticket: delegate planning readiness coder 2026-06-08 08:10:26 +09:00
Hare c83fecd057 ticket: accept planning readiness implementation 2026-06-08 08:09:38 +09:00
Hare 2abc5df9ac ticket: add workflow policy cleanup tasks 2026-06-08 08:08:40 +09:00
Hare 4dbe029bd3 ticket: route planning readiness preflight 2026-06-08 08:04:05 +09:00
Hare 5944ec673a ticket: delegate yaml frontmatter coder 2026-06-08 07:59:49 +09:00
Hare de3a5569da ticket: accept yaml frontmatter implementation 2026-06-08 07:59:14 +09:00
Hare 1af710e998 ticket: route yaml frontmatter parsing preflight 2026-06-08 07:43:30 +09:00
Hare fd4c34b292 ticket: route panel nonblocking transitions preflight 2026-06-08 07:36:38 +09:00
Hare 906e46c8db ticket: add yaml frontmatter parsing task 2026-06-08 07:33:33 +09:00
Hare 58f770b626 ticket: record bare shortcut cleanup 2026-06-08 07:26:48 +09:00
Hare 8302cbb123 ticket: record bare shortcut merge completion 2026-06-08 07:26:10 +09:00
Hare b633319705 merge: remove workspace panel bare letter shortcuts 2026-06-08 07:24:56 +09:00
Hare a5fa3d840b fix: remove panel bare letter shortcuts 2026-06-08 07:14:23 +09:00
Hare 9341c8049e ticket: add ticket action commit policy task 2026-06-08 07:06:43 +09:00
Hare 696ef30d10 config: tune workspace profiles and codex models 2026-06-08 07:05:28 +09:00
Hare d406df3056 ticket: add intake claim timing bug 2026-06-08 07:04:58 +09:00
Hare b2f6a4b1db ticket: add panel shortcut removal task 2026-06-08 06:47:13 +09:00
Hare d17b44596e ticket: close companion pod lifecycle 2026-06-08 05:45:36 +09:00
Hare f7c5b56eb0 merge: companion pod lifecycle 2026-06-08 05:45:05 +09:00
Hare 9d030fbbc9 ticket: approve companion pod lifecycle 2026-06-08 05:45:05 +09:00
Hare 1c5c77bd08 ticket: report companion lifecycle implementation 2026-06-07 19:40:36 +09:00
Hare ba0c9d565a feat: wire panel companion lifecycle 2026-06-07 19:39:41 +09:00
Hare 2177dbf019 ticket: delegate companion pod lifecycle 2026-06-07 19:18:01 +09:00
Hare e418560a12 ticket: preflight companion pod lifecycle 2026-06-07 19:17:33 +09:00
Hare b453125870 ticket: close orchestrator diagnostic persistence 2026-06-07 19:16:08 +09:00
Hare c1be0a4ac1 merge: orchestrator diagnostic persistence 2026-06-07 19:15:40 +09:00
Hare 7511cd4ed4 ticket: approve orchestrator diagnostic persistence 2026-06-07 19:15:40 +09:00
Hare 817f53bf77 ticket: report orchestrator diagnostic implementation 2026-06-07 19:10:37 +09:00
Hare e15e9b7a47 fix: persist orchestrator lifecycle diagnostics 2026-06-07 19:09:01 +09:00
Hare a7683bda8e ticket: delegate orchestrator diagnostic persistence 2026-06-07 19:00:33 +09:00
Hare 7d9312d8a5 ticket: add orchestrator diagnostic persistence 2026-06-07 18:59:51 +09:00
Hare b5861e6bf2 config: add workspace role profiles 2026-06-07 17:44:58 +09:00
Hare 383b655072 ticket: close memory root marker 2026-06-07 16:59:18 +09:00
Hare 297b66838b merge: memory root marker 2026-06-07 16:58:25 +09:00
Hare 1838865507 ticket: approve memory root marker 2026-06-07 16:58:25 +09:00
Hare 084f051a4a ticket: review memory root marker 2026-06-07 16:53:50 +09:00
Hare 9ed6613a94 memory: resolve repo memory by memory marker 2026-06-07 16:52:19 +09:00
Hare 546c8c3ac1 ticket: delegate memory root marker 2026-06-07 16:46:05 +09:00
Hare afd683ac06 ticket: preflight memory root marker 2026-06-07 16:45:08 +09:00
Hare 94e028e807 ticket: close yoi worktree sparse exclusions 2026-06-07 16:38:37 +09:00
Hare d61fcc1249 merge: narrow yoi worktree sparse exclusions 2026-06-07 16:38:00 +09:00
Hare 4d5492c998 ticket: approve yoi worktree sparse exclusions 2026-06-07 16:38:00 +09:00
Hare 6f33275309 fixup! workflow: narrow yoi worktree sparse exclusions 2026-06-07 16:36:00 +09:00
Hare bfa728f7e5 ticket: add pod notification guidance task 2026-06-07 16:33:49 +09:00
Hare 7bf8f99a10 ticket: review yoi worktree sparse exclusions 2026-06-07 16:28:58 +09:00
Hare ee85b51e55 workflow: narrow yoi worktree sparse exclusions 2026-06-07 16:27:43 +09:00
Hare f6f10c7f9d ticket: delegate yoi worktree sparse exclusions 2026-06-07 16:15:42 +09:00
Hare 0cc81cfd4f ticket: preflight yoi worktree sparse exclusions 2026-06-07 16:14:53 +09:00
Hare 157fd8ff92 ticket: close orchestrator merge completion 2026-06-07 15:47:14 +09:00
Hare 81248b1c7f merge: orchestrator merge completion 2026-06-07 15:46:28 +09:00
Hare 6976243328 ticket: approve orchestrator merge completion 2026-06-07 15:46:16 +09:00
Hare 33abf3f960 fixup! orchestrator: add merge completion guidance 2026-06-07 15:43:44 +09:00
Hare e41401f31f ticket: review orchestrator merge completion 2026-06-07 15:38:25 +09:00
Hare 9b91e56fea ticket: add yoi worktree memory boundary tasks 2026-06-07 15:29:28 +09:00
Hare cb177288be orchestrator: add merge completion guidance 2026-06-07 15:20:17 +09:00
Hare 3a0ec9feb9 ticket: delegate orchestrator merge completion 2026-06-07 15:16:24 +09:00
Hare 8db57dd59a ticket: preflight orchestrator merge completion 2026-06-07 15:15:39 +09:00
Hare 7f1518382c ticket: close orchestrator agent routing 2026-06-07 14:56:04 +09:00
Hare 55f203710b merge: orchestrator agent routing 2026-06-07 14:55:20 +09:00
Hare 839b06cbaa ticket: approve orchestrator agent routing 2026-06-07 14:55:20 +09:00
Hare 6756cc3a69 ticket: review orchestrator agent routing 2026-06-07 14:50:08 +09:00
Hare c7d6bb84e5 orchestrator: add agent routing guidance 2026-06-07 14:48:43 +09:00
Hare 40d58a7090 ticket: delegate orchestrator agent routing 2026-06-07 14:40:45 +09:00
Hare f216601aba ticket: preflight orchestrator agent routing 2026-06-07 14:39:56 +09:00
Hare 42789b471c ticket: close queued ticket routing 2026-06-07 14:13:43 +09:00
Hare c1f3ba6b89 merge: queued ticket routing 2026-06-07 14:13:09 +09:00
Hare 3c0cf73141 ticket: approve queued ticket routing 2026-06-07 14:13:09 +09:00
Hare fd9613222e ticket: review queued routing implementation 2026-06-07 14:08:44 +09:00
Hare df6d7ee9c3 ticket: record queued routing implementation 2026-06-07 14:08:13 +09:00
Hare ccf43f8466 tui: update queued ticket routing notification 2026-06-07 14:04:08 +09:00
Hare 17c2f38a8f ticket: clarify orchestrator review git boundary 2026-06-07 14:00:41 +09:00
Hare a6cc7e6629 ticket: delegate queued ticket routing 2026-06-07 13:58:31 +09:00
Hare c049f9ba6d ticket: preflight queued ticket routing 2026-06-07 13:57:52 +09:00
Hare f952c1cfb4 ticket: close ticket init scaffold 2026-06-07 13:05:29 +09:00
Hare e592496c61 merge: ticket init scaffold 2026-06-07 13:04:23 +09:00
Hare a0c1408279 ticket: approve ticket init scaffold 2026-06-07 13:04:23 +09:00
Hare abbc8e16f0 ticket: close ticket lifecycle feature 2026-06-07 13:03:39 +09:00
Hare c0fb243760 merge: ticket lifecycle feature 2026-06-07 13:02:55 +09:00
Hare 28616777af ticket: approve ticket lifecycle feature 2026-06-07 13:02:55 +09:00
Hare e57e410c4d ticket: review ticket config and feature work 2026-06-07 12:58:44 +09:00
Hare 550e0159ed ticket: split orchestrator automation phases 2026-06-07 12:57:40 +09:00
Hare 3d662bc40e pod: split ticket feature access levels 2026-06-07 12:56:13 +09:00
Hare f265098eed ticket: add ticket config init scaffold 2026-06-07 12:52:18 +09:00
Hare 9aa6e7d1ab ticket: delegate ticket lifecycle feature 2026-06-07 12:49:00 +09:00
Hare 43f273de03 ticket: preflight ticket lifecycle feature 2026-06-07 12:48:02 +09:00
Hare 9e8d77fc70 ticket: delegate ticket init scaffold 2026-06-07 12:44:22 +09:00
Hare 716eb053d1 ticket: preflight ticket init scaffold 2026-06-07 12:43:43 +09:00
Hare 8f3f5bff2c ticket: close role launch config validation 2026-06-07 12:42:45 +09:00
Hare 3064c984b5 merge: role launch config validation 2026-06-07 12:42:12 +09:00
Hare 24a5bba852 ticket: approve role launch config validation 2026-06-07 12:42:12 +09:00
Hare 1cee15479d ticket: review role launch config validation 2026-06-07 12:38:30 +09:00
Hare 30a07b7f36 ticket: validate role launch config 2026-06-07 12:37:30 +09:00
Hare c57d13e61b ticket: split ticket lifecycle feature 2026-06-07 12:35:57 +09:00
Hare 24d6a62a54 ticket: delegate role launch config validation 2026-06-07 12:21:48 +09:00
Hare f2f74a8aab ticket: preflight role launch config validation 2026-06-07 12:20:56 +09:00
Hare c73690b38c ticket: update panel config planning 2026-06-07 12:14:56 +09:00
Hare 0dd8d268a6 ticket: lower companion panel priority 2026-06-07 12:13:12 +09:00
Hare 446134020f ticket: record companion bash policy 2026-06-07 12:07:51 +09:00
Hare 7a97a5fe9d ticket: expand orchestrator automation contract 2026-06-07 11:36:48 +09:00
Hare 4eefc0f87e ticket: record orchestrator inprogress contract 2026-06-07 11:35:26 +09:00
Hare b660e790c6 ticket: close panel role session registry 2026-06-07 11:34:55 +09:00
Hare 7e8e03d4a1 merge: panel role session registry 2026-06-07 11:34:21 +09:00
Hare 994ee5d918 ticket: approve panel role session registry 2026-06-07 11:34:14 +09:00
Hare 2f3f54b01a fixup! tui: add panel role session registry 2026-06-07 11:25:03 +09:00
Hare c119c426d3 ticket: add active workflow compaction task 2026-06-07 11:23:36 +09:00
Hare e0f0f3c8b3 ticket: record panel registry review changes 2026-06-07 11:18:29 +09:00
Hare f7141b85e0 ticket: delegate panel registry review 2026-06-07 11:04:29 +09:00
Hare 489059019d tui: add panel role session registry 2026-06-07 11:02:30 +09:00
Hare 3b4182cd08 ticket: add orchestrator queue automation task 2026-06-07 11:02:27 +09:00
Hare 32e93fe075 ticket: close remove direct pod send 2026-06-07 11:01:18 +09:00
Hare 3a35968338 merge: remove panel direct pod send 2026-06-07 11:00:18 +09:00
Hare 393cde9259 tui: remove panel direct pod send 2026-06-07 10:54:15 +09:00
Hare 52683a5646 config: remove workspace manifest 2026-06-07 10:48:20 +09:00
Hare 176e50450b ticket: delegate panel role session registry 2026-06-07 10:42:57 +09:00
Hare 5db02079d0 ticket: preflight panel role session registry 2026-06-07 10:42:17 +09:00
Hare 7f8f8ae656 ticket: delegate remove direct pod send 2026-06-07 10:33:31 +09:00
Hare 9717d64458 ticket: preflight remove direct pod send 2026-06-07 10:32:22 +09:00
Hare 1b7de88a59 ticket: add panel role session registry task 2026-06-07 10:22:18 +09:00
Hare 7f386f749e ticket: plan workspace companion interface 2026-06-07 09:18:58 +09:00
Hare f662ada9f6 ticket: close explicit workflow state 2026-06-07 09:08:04 +09:00
Hare 198708866a merge: explicit ticket workflow state 2026-06-07 09:06:42 +09:00
Hare 37c7f5b79c Merge branch 'develop' into work/explicit-ticket-workflow-state 2026-06-07 09:06:42 +09:00
Hare ab85388122 feat: add explicit ticket workflow state 2026-06-07 09:02:01 +09:00
Hare 7463f8ec53 ticket: add panel transition latency task 2026-06-07 08:36:10 +09:00
Hare eec805287b ticket: preflight explicit workflow state 2026-06-07 07:49:29 +09:00
Hare 733aa96c87 ticket: close typed ticket event log 2026-06-07 07:48:18 +09:00
Hare e5c95acd33 merge: typed ticket thread event log 2026-06-07 07:47:16 +09:00
Hare e87b14fa1e ticket: add typed thread transition events 2026-06-07 07:44:13 +09:00
Hare 2cc0ea9f31 ticket: preflight typed ticket event log 2026-06-07 07:16:04 +09:00
Hare 5fcdd2a3ed ticket: split ticket workflow event log 2026-06-07 07:14:29 +09:00
Hare dbc0ed2673 ticket: simplify panel state display requirements 2026-06-07 07:04:15 +09:00
Hare 02f61ca02f ticket: add explicit workflow state plan 2026-06-07 06:54:48 +09:00
Hare ff7814e3c6 ticket: close remove tui ticket commands 2026-06-07 06:28:39 +09:00
Hare 074105c37c merge: remove tui ticket commands 2026-06-07 06:26:41 +09:00
Hare ffd81de815 Merge branch 'develop' into work/remove-tui-ticket-commands 2026-06-07 06:26:41 +09:00
Hare 4ce4ee6532 tui: remove ticket role commands 2026-06-07 06:20:56 +09:00
Hare fe11d3691c ticket: close workspace panel layout tuning 2026-06-07 06:16:52 +09:00
Hare 5cca1692c9 merge: workspace panel layout tuning 2026-06-07 06:16:02 +09:00
Hare 609c2c4b42 Merge branch 'develop' into work/workspace-panel-layout-display-tuning 2026-06-07 06:16:02 +09:00
Hare 32f34f2fab tui: align workspace panel rows 2026-06-07 06:10:51 +09:00
Hare 5f59b0bf57 ticket: preflight remove tui ticket commands 2026-06-07 06:09:49 +09:00
Hare 66b7b97839 ticket: preflight workspace panel layout tuning 2026-06-06 18:32:01 +09:00
Hare 9a3693d2f0 ticket: require panel aligned columns 2026-06-06 17:36:49 +09:00
Hare 1de5a9aac4 ticket: plan workspace panel layout tuning 2026-06-06 15:06:30 +09:00
Hare 1c49ea3451 ticket: close workspace orchestration panel 2026-06-06 15:05:38 +09:00
Hare 6aeef2d76e ticket: close workspace panel action dispatch 2026-06-06 15:04:40 +09:00
Hare f4230c7386 merge: workspace panel ticket action dispatch 2026-06-06 15:03:48 +09:00
Hare 150e9fc1cd feat: dispatch workspace panel ticket actions 2026-06-06 15:00:45 +09:00
Hare 4f0513996a ticket: preflight workspace panel action dispatch 2026-06-06 14:30:26 +09:00
Hare ee6fbea177 ticket: add workspace panel action dispatch 2026-06-06 14:29:48 +09:00
Hare a06898ec92 ticket: close intake orchestrator handoff 2026-06-06 14:27:40 +09:00
Hare aaf8391a70 merge: ticket intake orchestrator handoff 2026-06-06 14:26:50 +09:00
Hare adbf3a1e34 feat: add ticket intake handoff 2026-06-06 14:21:37 +09:00
Hare f9745dd7a6 ticket: preflight intake orchestrator handoff 2026-06-06 13:49:16 +09:00
Hare c3cccd8a9d ticket: close workspace panel composer targets 2026-06-06 13:47:31 +09:00
Hare 24d977797d merge: workspace panel composer targets 2026-06-06 13:46:42 +09:00
Hare a7c155e5c3 feat: add workspace panel composer targets 2026-06-06 13:41:39 +09:00
Hare f23a4a29c6 ticket: preflight workspace panel composer targets 2026-06-06 13:24:53 +09:00
Hare 556fd42973 ticket: close workspace panel orchestrator lifecycle 2026-06-06 13:23:48 +09:00
Hare 891fe07c6a merge: workspace panel orchestrator lifecycle 2026-06-06 13:23:01 +09:00
Hare 7b29cd6817 feat: add workspace orchestrator panel lifecycle 2026-06-06 09:13:45 +09:00
Hare 17970feb21 ticket: preflight workspace panel orchestrator lifecycle 2026-06-06 08:32:34 +09:00
Hare 38bf4b0136 ticket: close workspace panel action model 2026-06-06 08:31:28 +09:00
Hare 0fce14bcfd merge: workspace panel action model 2026-06-06 08:30:42 +09:00
Hare 11d06df771 Merge branch 'develop' into work/workspace-panel-action-model 2026-06-06 08:30:25 +09:00
Hare cf1cc72255 feat: add workspace panel action model 2026-06-06 08:22:47 +09:00
Hare d5b664b7f4 ticket: remove multi in favor of panel 2026-06-06 08:13:39 +09:00
Hare 68e9f5254a ticket: decide workspace panel launch route 2026-06-06 08:08:49 +09:00
Hare 64ca7d7d4b ticket: unify multi under workspace panel 2026-06-06 08:05:06 +09:00
Hare 7965249e23 ticket: update tui composer history persistence 2026-06-06 08:01:38 +09:00
Hare a40627ab9f ticket: preflight workspace panel action model 2026-06-06 07:35:56 +09:00
Hare 5b705a3319 ticket: approve workspace panel design 2026-06-06 07:35:18 +09:00
Hare 018d01e90e ticket: simplify workspace panel view model 2026-06-06 07:29:53 +09:00
Hare a8b012f9e7 ticket: close yoi local backend migration 2026-06-06 07:13:53 +09:00
Hare 2eb396d22c ticket: close remove tickets shell shim 2026-06-06 07:13:36 +09:00
Hare da760e646d merge: remove tickets shell shim 2026-06-06 07:10:58 +09:00
Hare a9c5c3a821 ticket: remove tickets shell shim 2026-06-06 07:10:11 +09:00
Hare 8c6264d699 ticket: preflight remove tickets shell shim 2026-06-06 06:52:55 +09:00
Hare 22967b9a64 ticket: close yoi tickets storage migration 2026-06-06 06:52:03 +09:00
Hare 441f59d23b merge: migrate ticket storage to .yoi 2026-06-06 06:50:51 +09:00
Hare 9d142ec964 Merge branch 'develop' into work/migrate-ticket-storage-to-yoi-tickets 2026-06-06 06:45:25 +09:00
Hare da94b1ec50 ticket: move local storage to .yoi/tickets 2026-06-06 06:44:10 +09:00
Hare 92da1b4489 ticket: refine workspace panel tui design 2026-06-06 06:32:54 +09:00
Hare 749b3f3aee ticket: preflight yoi tickets storage migration 2026-06-06 06:28:37 +09:00
Hare 1ea10e02ce ticket: close builtin yoi local backend config 2026-06-06 06:26:56 +09:00
Hare 8c7e94f6fc merge: builtin yoi local backend config 2026-06-06 06:25:44 +09:00
Hare dd901b1f49 ticket: draft workspace panel ui design 2026-06-06 06:22:49 +09:00
Hare cd7e60a8dd ticket: add builtin yoi local backend provider 2026-06-06 06:19:30 +09:00
Hare 8f5a829833 ticket: preflight builtin yoi local backend 2026-06-06 06:10:33 +09:00
Hare a618a52d03 ticket: plan workspace orchestration panel 2026-06-06 06:09:27 +09:00
Hare ec525a3d70 ticket: close yoi ticket cli 2026-06-06 05:58:44 +09:00
Hare 4ba1b2fb95 merge: add yoi ticket cli 2026-06-06 05:57:14 +09:00
Hare 8f0b7064fc review: approve yoi ticket cli 2026-06-06 05:56:55 +09:00
Hare 4d5068ba3b feat: add yoi ticket CLI 2026-06-06 05:50:29 +09:00
Hare d725fb81d6 ticket: preflight yoi ticket cli 2026-06-06 05:34:39 +09:00
Hare 0b279ef6d8 ticket: plan yoi local ticket backend migration 2026-06-06 05:32:21 +09:00
Hare 2d7fc7a161 docs: document ticket development workflow 2026-06-06 05:23:48 +09:00
Hare bee9455935 ticket: close tui ticket role actions 2026-06-06 05:10:01 +09:00
Hare 5d3209d8e4 merge: add tui ticket role actions 2026-06-06 05:07:44 +09:00
Hare dab2478120 review: approve tui ticket role actions 2026-06-06 05:07:30 +09:00
Hare d288fa5901 fix: require TUI ticket intake context 2026-06-06 05:04:27 +09:00
Hare e125ebb374 feat: add TUI ticket role commands 2026-06-06 04:57:10 +09:00
Hare eb95722bd0 ticket: preflight tui ticket role actions 2026-06-06 04:36:53 +09:00
Hare 549cbabbb8 ticket: close ticket role launcher 2026-06-06 04:34:23 +09:00
Hare 3d6c1abf8c merge: add ticket role launcher 2026-06-06 04:33:16 +09:00
Hare 0407ad024e review: approve ticket role launcher 2026-06-06 04:33:03 +09:00
Hare dd70517f96 fix: harden ticket role launch execution 2026-06-06 04:29:47 +09:00
Hare 4bf0e2715c feat: add ticket role pod launcher 2026-06-06 04:18:36 +09:00
Hare ecd4a37d94 ticket: preflight ticket role launcher 2026-06-06 04:07:13 +09:00
Hare 3d4a76cda5 ticket: plan ticket role launcher ui 2026-06-06 04:06:26 +09:00
Hare e1215c79be ticket: close ticket config roles 2026-06-06 03:48:27 +09:00
Hare 9910df4e24 merge: add ticket config roles 2026-06-06 03:46:08 +09:00
Hare d704aea774 review: approve ticket config roles 2026-06-06 03:45:50 +09:00
Hare 8fab67b5fc ticket: reject nix profile selectors 2026-06-06 03:43:37 +09:00
Hare 767870a4fb ticket: add workspace ticket config 2026-06-06 03:33:40 +09:00
Hare 3edd68558f ticket: refine ticket config role prompts 2026-06-06 03:15:20 +09:00
Hare 956394b4ac ticket: plan ticket config roles 2026-06-06 02:35:34 +09:00
Hare 4fb6a3a688 workflow: retire auto maintain 2026-06-06 00:56:51 +09:00
Hare 44e6367a9c ticket: close ticket intake routing umbrella 2026-06-05 15:42:54 +09:00
Hare d02516d37d ticket: close ticket orchestrator routing 2026-06-05 15:42:12 +09:00
Hare af17f8b11d workflow: add ticket orchestrator routing 2026-06-05 15:41:46 +09:00
Hare afbfc21d57 ticket: close ticket intake workflow 2026-06-05 15:11:07 +09:00
Hare 12338332d6 workflow: add ticket intake 2026-06-05 15:10:42 +09:00
Hare 78120f5360 ticket: close ticket feature tools 2026-06-05 15:00:33 +09:00
Hare 4486a8133e merge: add ticket feature tools 2026-06-05 14:59:08 +09:00
Hare 8db9e2ebef review: approve ticket feature tools 2026-06-05 14:58:53 +09:00
Hare afd7f04ff6 feat: add built-in ticket tools 2026-06-05 14:52:39 +09:00
Hare a06d007202 ticket: preflight ticket feature tools 2026-06-05 14:37:54 +09:00
Hare 229b8e4ee0 docs: expand readme overview 2026-06-05 14:30:27 +09:00
Hare 03e04d5333 ticket: close feature authority separation 2026-06-05 14:12:06 +09:00
Hare b46ea65fdd merge: clarify feature host authorities 2026-06-05 14:09:52 +09:00
Hare b96df5ac21 review: approve feature authority separation 2026-06-05 14:09:44 +09:00
Hare 4fc361fba0 refactor: name feature host authorities explicitly 2026-06-05 14:03:37 +09:00
Hare 8202db1eb1 ticket: preflight feature authority separation 2026-06-05 13:54:42 +09:00
Hare d9003e525d ticket: close local ticket backend 2026-06-05 13:45:54 +09:00
Hare 1041cdb961 merge: add local ticket backend 2026-06-05 13:44:25 +09:00
Hare cbbf7e1535 review: approve local ticket backend 2026-06-05 13:44:15 +09:00
Hare 740b017d0c feat: add local ticket backend 2026-06-05 13:37:57 +09:00
Hare 5d71659bfa ticket: preflight local ticket backend 2026-06-05 13:24:31 +09:00
Hare 11daffcd27 ticket: split ticket intake routing 2026-06-05 13:04:57 +09:00
Hare 1bf212e225 ticket: close task domain move 2026-06-05 12:26:39 +09:00
Hare 61e9a18942 merge: move task domain into pod feature 2026-06-05 12:25:08 +09:00
Hare e25b31ecd8 report: task domain move implementation 2026-06-05 12:24:59 +09:00
Hare c2ed71a388 docs: update tui task snapshot comments 2026-06-05 12:23:12 +09:00
Hare bab30952b8 review: approve task domain move 2026-06-05 12:22:35 +09:00
Hare 5469335de9 refactor: move task feature into pod 2026-06-05 12:12:19 +09:00
Hare 7c604f37dd workflow: update yoi workspace paths 2026-06-05 11:59:23 +09:00
Hare 5de4156147 task: plan task domain move into pod 2026-06-05 11:53:19 +09:00
Hare 6cc2e9ade7 ticket: close task feature state move 2026-06-05 11:24:26 +09:00
Hare 9eceb189ba merge: move task state into feature 2026-06-05 11:23:22 +09:00
Hare 8f1cb1b8c2 review: approve task feature state move 2026-06-05 11:23:03 +09:00
Hare 960f2a305e fix: account hook system item appends 2026-06-05 11:17:16 +09:00
Hare 9b07cd21c0 review: request task reminder accounting fix 2026-06-05 11:00:49 +09:00
Hare c9cb2edc7e feature: move task reminders into builtin feature 2026-06-05 10:50:37 +09:00
Hare d92a29d63c task: plan task feature state ownership 2026-06-05 10:27:30 +09:00
Hare 52fa401725 ticket: close hook context sink 2026-06-05 10:26:09 +09:00
Hare 7d71507688 merge: add hook system item sink 2026-06-05 10:25:21 +09:00
Hare 9eee15ac3a review: approve hook context sink 2026-06-05 10:25:06 +09:00
Hare 04a4a730fb pod: add hook system item sink 2026-06-05 10:16:27 +09:00
Hare 3cc3134386 task: plan hook context sink implementation 2026-06-05 10:01:24 +09:00
Hare d5b919e0d6 task: plan hook task state ownership 2026-06-05 09:50:03 +09:00
Hare 4b90fe91bf ticket: close task tools module 2026-06-05 09:05:58 +09:00
Hare 6908bb5947 merge: extract task tools module 2026-06-05 09:05:20 +09:00
Hare 2b36c261b8 review: approve task tools module 2026-06-05 09:04:56 +09:00
Hare f394f15ba5 feat: extract task tools builtin module 2026-06-05 08:59:08 +09:00
Hare 9721c81eb0 task: plan task tools module extraction 2026-06-05 08:50:53 +09:00
Hare 06c5cb7652 task: split feature authority model 2026-06-05 08:50:18 +09:00
Hare d8ba6c39f7 task: add task tools plugin trial 2026-06-05 07:35:51 +09:00
Hare eea94ea4ba ticket: close feature registry slice 2026-06-05 07:26:40 +09:00
Hare e3cb29982f merge: add feature contribution registry slice 2026-06-05 07:25:41 +09:00
Hare c1c8a21f9a review: approve feature registry slice 2026-06-05 07:25:28 +09:00
Hare 6fa08f8917 fix: enforce feature descriptor contributions 2026-06-05 07:21:07 +09:00
Hare 6ed8af8764 review: request descriptor contribution checks 2026-06-05 07:11:04 +09:00
Hare 98bbd6f185 fix: align feature authority boundaries 2026-06-05 07:03:21 +09:00
Hare 5934d043ac task: narrow plugin authority model 2026-06-05 06:51:12 +09:00
Hare b1ebd77f8a review: request feature registry rereview changes 2026-06-05 06:46:07 +09:00
Hare 40701760eb fix: harden feature contribution gates 2026-06-05 06:41:06 +09:00
Hare 72c68dad84 review: request feature registry changes 2026-06-05 06:32:45 +09:00
Hare a8ae6ca2f8 feat: add pod feature registry slice 2026-06-05 06:25:54 +09:00
Hare cb642b0d37 task: plan feature registry implementation 2026-06-05 06:08:36 +09:00
Hare 0f2ec7c263 task: add plugin service boundary 2026-06-05 05:48:27 +09:00
Hare d7e416982f task: refine plugin notification boundary 2026-06-05 05:23:23 +09:00
Hare 9753b34fb9 ticket: close hook api hardening 2026-06-04 02:07:47 +09:00
Hare 7fff857b4c merge: harden public hook api 2026-06-04 02:05:55 +09:00
Hare 29468602b4 review: approve hook api hardening 2026-06-04 02:05:47 +09:00
Hare a4e30e292a fix: remove public hook skip action 2026-06-04 02:02:52 +09:00
Hare 64ca693fce review: request hook api changes 2026-06-04 01:58:52 +09:00
Hare 2f020ed0bb fix: harden public hook actions 2026-06-04 01:52:29 +09:00
Hare 3b2c35c9c4 task: add plugin pod api design 2026-06-04 01:44:08 +09:00
Hare 2d032b3360 task: plan plugin pod api design 2026-06-04 01:38:49 +09:00
Hare 21b6848e21 task: plan hook api hardening 2026-06-04 01:37:00 +09:00
Hare fb172b6049 task: split plugin feature registry tickets 2026-06-03 21:25:18 +09:00
Hare d9a88fbd88 ticket: close reasoning block lifecycle 2026-06-03 11:15:13 +09:00
Hare c94e3a01e1 merge: unify reasoning block lifecycle 2026-06-03 11:13:42 +09:00
Hare abb6adb5d2 fix: preserve openai reasoning live stops 2026-06-03 11:08:06 +09:00
Hare 42066f1e00 fix: unify reasoning block persistence 2026-06-03 10:11:59 +09:00
Hare 8135ff9006 task: plan reasoning block lifecycle implementation 2026-06-03 09:51:12 +09:00
Hare cc98c0eb28 fix: wire tui word navigation 2026-06-03 09:22:50 +09:00
Hare d0bdad58c2 task: add reasoning block lifecycle ticket 2026-06-03 09:12:23 +09:00
Hare ea2c7418f1 ticket: close peer pod handshake 2026-06-02 22:55:02 +09:00
Hare 3750a350fd merge: peer pod handshake command 2026-06-02 22:53:09 +09:00
Hare 057c2eff5f fix: harden peer pod registration 2026-06-02 22:23:13 +09:00
Hare 093a84fc83 feat: add peer pod handshake command 2026-06-02 19:43:20 +09:00
Hare b51c32401c task: plan peer pod handshake implementation 2026-06-02 19:17:45 +09:00
Hare 849af7a4d0 task: broaden peer pod command ticket 2026-06-02 19:16:31 +09:00
Hare 8072730e51 task: clarify known pod command ticket 2026-06-02 01:19:33 +09:00
Hare f30dc705c9 task: add tui pod connect command ticket 2026-06-01 22:31:45 +09:00
Hare 88cf6f366f Update README.md 2026-06-01 22:24:42 +09:00
Hare 8b46b72a17 ticket: close docs cleanup 2026-06-01 22:23:08 +09:00
Hare 5f8b3d9a57 ticket: close workspace override 2026-06-01 22:19:45 +09:00
Hare 9be37ea123 merge: workspace local manifest override 2026-06-01 22:16:59 +09:00
Hare 8f987857e8 test: cover nearest workspace override 2026-06-01 22:16:06 +09:00
Hare 4830c3aba1 task: add dependency version update scan 2026-06-01 22:09:12 +09:00
Hare 4beb1f61ea feat: add workspace local manifest override 2026-06-01 22:06:41 +09:00
Hare dd509d40c6 task: plan workspace override ticket 2026-06-01 21:54:00 +09:00
Hare bf6915b43b task: add dependency and override work items 2026-06-01 21:53:31 +09:00
Hare 7f62c457ad chore: fix package.nix 2026-06-01 21:37:04 +09:00
Hare 9dcbd4c3e0 docs: reorganize developer documentation 2026-06-01 20:59:32 +09:00
Hare e6c458021c rename: adopt yoi identity 2026-06-01 18:49:23 +09:00
Hare 6e133a7229 ticket: plan yoi rename 2026-06-01 17:29:58 +09:00
Hare 342f194c87 fix: avoid projecting token measurements past latest usage 2026-06-01 17:29:58 +09:00
Hare 28447466ca ticket: close profile authoring requirements sync 2026-06-01 16:02:52 +09:00
Hare b48483b7f1 ticket: add plugin distribution package task 2026-06-01 15:50:54 +09:00
Hare dba0bdcbdd Update package.nix 2026-06-01 15:02:52 +09:00
Hare 15fb1e5741 ticket: clarify WorkItem model 2026-06-01 14:26:57 +09:00
Hare dadf3ae7a3 ticket: add work item intake routing task 2026-06-01 12:13:38 +09:00
Hare 439bbab634 close: merge approved TUI fixes 2026-06-01 11:24:21 +09:00
Hare dbb47e0bef merge: keys inline viewport UI 2026-06-01 11:21:55 +09:00
Hare ff279177c4 merge: TUI first message display fix 2026-06-01 11:21:55 +09:00
Hare 5886f6ad08 fix: align keys UI with TUI viewport 2026-06-01 11:16:16 +09:00
Hare 501dcc916f fix: show initial TUI user message 2026-06-01 11:13:28 +09:00
Hare 9a5f44ff65 ticket: add composer history persistence task 2026-06-01 11:11:42 +09:00
Hare b6a57f75f6 Update default.lua 2026-06-01 11:08:34 +09:00
Hare f8143bffaf ticket: add keys inline viewport UI task 2026-06-01 11:02:44 +09:00
Hare c7c1a0a68a ticket: record TUI first message investigation 2026-06-01 11:00:44 +09:00
Hare bf887fca13 ticket: add TUI first message display bug 2026-06-01 10:32:07 +09:00
Hare f858f48c34 close: pod orchestration guidance 2026-06-01 10:24:59 +09:00
Hare b7cbf05305 merge: pod orchestration guidance 2026-06-01 10:24:33 +09:00
Hare d6e36a3268 review: approve pod orchestration guidance 2026-06-01 10:24:27 +09:00
Hare 6437580600 prompt: add pod orchestration guidance 2026-06-01 10:19:49 +09:00
Hare 5af9a5b1b6 ticket: refine pod orchestration guidance 2026-06-01 10:10:59 +09:00
Hare 623f45a254 close: prompt occupancy estimator 2026-06-01 10:10:17 +09:00
Hare e51944f045 merge: prompt occupancy estimator 2026-06-01 10:09:30 +09:00
Hare a40e45c90a review: approve prompt occupancy estimator 2026-06-01 09:59:20 +09:00
Hare 2d4ffe0bce ticket: supplement pod orchestration guidance 2026-06-01 09:57:09 +09:00
Hare 375d0216d1 fix: correct prompt occupancy extrapolation 2026-06-01 09:52:39 +09:00
Hare 3ea005822e ticket: prompt occupancy token estimator 2026-06-01 09:41:22 +09:00
Hare 231ab3a4bf close: memory prompt guidance 2026-06-01 07:52:47 +09:00
Hare bdb52b1ec7 merge: memory prompt guidance 2026-06-01 07:51:39 +09:00
Hare 62d88d919d review: approve memory prompt guidance 2026-06-01 07:51:36 +09:00
Hare 3a0c8e1597 memory: clean prompt helper warning 2026-06-01 07:50:27 +09:00
Hare 03256db913 memory: gate prompt guidance 2026-06-01 07:45:06 +09:00
Hare ccddab6425 close: bash tool editing guidance 2026-06-01 07:36:41 +09:00
Hare cff858ec23 ticket: add memory prompt thread files 2026-06-01 07:35:44 +09:00
Hare 6b48c4d3c5 ticket: memory prompt conditional lookup 2026-06-01 07:35:36 +09:00
Hare 681a37905c close: local secret store 2026-06-01 07:23:54 +09:00
Hare 629159a29f merge: local secret store 2026-06-01 07:21:26 +09:00
Hare c9e48b320d review: approve local secret store 2026-06-01 07:21:10 +09:00
Hare 7ddf74570a secrets: polish key manager and docs 2026-06-01 07:19:28 +09:00
Hare cc2c9a2973 secrets: add local key store 2026-06-01 07:07:39 +09:00
Hare 6e5ed683d6 decision: remove credential env compatibility 2026-06-01 06:23:48 +09:00
Hare faac237f0d plan: clarify phased secrets implementation 2026-06-01 06:19:31 +09:00
Hare 50ccf0f21b decision: simplify secret store model 2026-06-01 06:05:09 +09:00
Hare 9a00c91632 plan: detail encrypted secrets requirements 2026-06-01 05:58:02 +09:00
Hare 52d8807282 close: dev pod runtime env 2026-06-01 05:41:58 +09:00
Hare 32d20eea01 merge: dev pod runtime env 2026-06-01 05:41:36 +09:00
Hare 17e799a766 review: approve dev pod runtime env 2026-06-01 05:41:28 +09:00
Hare 0031953ed3 dev: add pod runtime command override 2026-06-01 05:37:17 +09:00
Hare ca9e1840cf close: tui runtime extraction 2026-05-31 22:57:04 +09:00
Hare a24d026b0e merge: tui runtime extraction 2026-05-31 22:56:39 +09:00
Hare 8ec398522e review: approve tui runtime extraction 2026-05-31 22:56:32 +09:00
Hare 4d897186c2 tui: extract single pod runtime 2026-05-31 22:51:21 +09:00
Hare c4cc93512f plan: rescope tui runtime extraction 2026-05-31 22:46:32 +09:00
Hare 0a538380a9 close: tui view mode state 2026-05-31 22:45:41 +09:00
Hare 9afe8a3243 merge: tui view mode state 2026-05-31 22:45:10 +09:00
Hare 72d6ac8719 review: approve tui view mode move 2026-05-31 22:45:04 +09:00
Hare bc31bfac58 tui: move view mode state 2026-05-31 22:41:38 +09:00
Hare 80a41d3264 close: tui cli parsing extraction 2026-05-31 22:38:32 +09:00
Hare 7141734f07 close: insomnia cli ownership 2026-05-31 22:20:05 +09:00
Hare 6b49be085d merge: insomnia cli ownership 2026-05-31 22:17:32 +09:00
Hare b12e3320a9 review: approve insomnia cli ownership 2026-05-31 22:17:15 +09:00
Hare 37281b64f2 cli: reject resume with pod selection 2026-05-31 22:15:12 +09:00
Hare 22d974a722 cli: move product entrypoint to insomnia 2026-05-31 22:07:52 +09:00
Hare 2deb93c7ce plan: preflight insomnia cli ownership 2026-05-31 21:42:24 +09:00
Hare 4c7088d757 ticket: add dev pod runtime command env 2026-05-31 21:41:24 +09:00
Hare f0efafbba9 close: single binary cli migration 2026-05-31 21:15:52 +09:00
Hare 5783503f74 docs: remove obsolete nix package doc 2026-05-31 21:11:48 +09:00
Hare 530c14e4b8 close: remove resource_dir 2026-05-31 20:58:30 +09:00
Hare f7293411cd merge: remove resource_dir 2026-05-31 20:54:37 +09:00
Hare 18ae9934e1 review: approve resource_dir removal 2026-05-31 20:54:28 +09:00
Hare 365ec8b7fa manifest: embed builtin resources 2026-05-31 20:47:06 +09:00
Hare 607923dfbd plan: preflight resource_dir removal 2026-05-31 20:28:43 +09:00
Hare f5c4943337 ticket: plan insomnia cli ownership 2026-05-31 20:20:34 +09:00
Hare 3a18842ac7 ticket: plan resource_dir removal 2026-05-31 20:09:12 +09:00
Hare 469410cbcf docs: prefer pure env fallback tests 2026-05-31 19:58:57 +09:00
Hare 813ff7e199 close: pure path fallback tests 2026-05-31 19:54:51 +09:00
Hare 7851fc0aac merge: pure path fallback tests 2026-05-31 19:54:24 +09:00
Hare 974dde3b88 review: approve pure path fallback tests 2026-05-31 19:54:18 +09:00
Hare e232f5468a test: make path fallback tests pure 2026-05-31 19:51:23 +09:00
Hare 6fa67097aa ticket: plan pure path fallback tests 2026-05-31 19:47:02 +09:00
Hare 506719796e docs: remove absent env surfaces 2026-05-31 19:31:33 +09:00
Hare 20f975c9b7 docs: simplify test env policy 2026-05-31 19:29:31 +09:00
Hare 1f29d1a39d docs: drop explicit test env name 2026-05-31 19:28:33 +09:00
Hare e605a5886f close: remove pod command env override 2026-05-31 19:12:05 +09:00
Hare 400cca9252 docs: drop pod command env reference 2026-05-31 19:11:50 +09:00
Hare 458a87e81a merge: remove pod command env override
# Conflicts:
#	docs/environment.md
2026-05-31 19:10:58 +09:00
Hare e8d8f139d0 review: approve pod command env removal 2026-05-31 19:09:52 +09:00
Hare e8e50bfa6b close: eliminate test-only env vars 2026-05-31 19:04:31 +09:00
Hare b61504e821 merge: eliminate test-only env vars 2026-05-31 19:04:04 +09:00
Hare fc3a0718a1 review: approve test env removal 2026-05-31 19:03:55 +09:00
Hare c618fa694c cli: remove pod command env override 2026-05-31 19:03:49 +09:00
Hare e64a559595 test: remove test-only env vars 2026-05-31 19:00:16 +09:00
Hare 44ff1411a3 docs: record env cleanup direction 2026-05-31 18:02:59 +09:00
Hare d06bb14e64 ticket: plan env var cleanup 2026-05-31 18:02:59 +09:00
Hare f186994c83 docs: clarify env path categories 2026-05-31 17:55:21 +09:00
Hare d1bc1d41b9 close: document env var policy 2026-05-31 17:49:34 +09:00
Hare 9bc7920ab5 docs: document environment variable policy 2026-05-31 17:29:29 +09:00
Hare 69cc4d38f0 docs: create env policy ticket 2026-05-31 17:29:23 +09:00
Hare 9b4b24c7ae ticket: plan tui module layout cleanup 2026-05-31 16:43:49 +09:00
Hare d56d3951d3 close: rename pod-command crate 2026-05-31 15:49:50 +09:00
Hare 9e886bc73e cli: rename pod command crate to insomnia 2026-05-31 15:49:14 +09:00
Hare 3a58ab7bb3 cli: create insomnia crate rename ticket 2026-05-31 15:49:03 +09:00
Hare b977bacb29 close: remove insomnia-pod binary 2026-05-31 15:10:45 +09:00
Hare 8560bd88a7 merge: remove insomnia-pod binary 2026-05-31 15:08:40 +09:00
Hare 7181afab40 review: approve insomnia-pod removal 2026-05-31 15:08:38 +09:00
Hare 0d7d3c7bf1 cli: remove insomnia-pod binary output 2026-05-31 14:59:22 +09:00
Hare fd32805c30 cli: create insomnia-pod removal ticket 2026-05-31 14:48:34 +09:00
Hare bd959ce25c close: spawn through insomnia pod 2026-05-31 14:27:15 +09:00
Hare cfbafbd67f merge: spawn through insomnia pod 2026-05-31 14:25:41 +09:00
Hare 582a2cd31f review: spawn through insomnia pod 2026-05-31 14:25:41 +09:00
Hare 4f622b8e32 cli: spawn pods through insomnia pod 2026-05-31 14:20:00 +09:00
Hare de3f64f41d cli: create insomnia pod spawn ticket 2026-05-31 13:51:24 +09:00
Hare c9b7e7f462 close: insomnia pod runtime entrypoint 2026-05-31 13:50:25 +09:00
Hare 898ff98761 merge: insomnia pod runtime entrypoint 2026-05-31 13:47:04 +09:00
Hare 07827f56ce review: insomnia pod runtime entrypoint 2026-05-31 13:47:04 +09:00
Hare 544257bfdd cli: add insomnia pod runtime entrypoint 2026-05-31 13:42:29 +09:00
Hare 0dd48f6152 cli: plan insomnia pod runtime entrypoint 2026-05-31 13:33:37 +09:00
Hare 74ac3b73cd chore: TODO.mdの削除 2026-05-31 12:30:23 +09:00
Hare ae6eb52f35 close: pod tool surface cleanup 2026-05-31 12:00:25 +09:00
Hare 97484091b6 merge: pod tool surface cleanup 2026-05-31 11:59:27 +09:00
Hare bca464cc73 review: pod tool surface cleanup 2026-05-31 11:59:27 +09:00
Hare 5472ceca48 pod: simplify pod tool surface 2026-05-31 11:50:41 +09:00
Hare 32ac0eee35 pod: create tool surface cleanup ticket 2026-05-31 11:29:28 +09:00
Hare 0764275b44 close: workspace memory lint cli 2026-05-31 11:15:38 +09:00
Hare 277f94885f merge: workspace memory lint cli 2026-05-31 11:14:38 +09:00
Hare 84819e2bf7 review: workspace memory lint cli 2026-05-31 11:14:38 +09:00
Hare 31f7db302d close: codex gpt55 context window 2026-05-31 10:58:32 +09:00
Hare 1c61cce2e7 merge: codex gpt55 context window 2026-05-31 10:57:55 +09:00
Hare 7c7e11d3aa review: codex gpt55 context window 2026-05-31 10:57:55 +09:00
Hare 7a717f2d25 cli: add workspace memory lint 2026-05-31 10:03:12 +09:00
Hare 1247cdabc1 plugin: create extension surface ticket 2026-05-31 10:01:20 +09:00
Hare 6812167422 cli: create single binary architecture ticket 2026-05-31 09:57:01 +09:00
Hare 30e9e65854 cli: define workspace memory lint ticket 2026-05-31 09:52:04 +09:00
Hare ed3e97c22a provider: use codex gpt55 effective context 2026-05-31 09:41:17 +09:00
Hare e0721c1dbc provider: create codex context window ticket 2026-05-31 09:38:32 +09:00
Hare 4302fbbf69 close: refresh builtin model catalog 2026-05-31 08:18:04 +09:00
Hare f6fbba4c48 provider: refresh builtin model catalog 2026-05-31 08:17:37 +09:00
Hare 164941f373 close: webfetch local reader markdown 2026-05-31 07:22:17 +09:00
Hare d5d7292bf7 merge: webfetch local reader markdown 2026-05-31 07:21:01 +09:00
Hare d2ad131eb2 review: webfetch local reader 2026-05-31 07:21:01 +09:00
Hare 44262c4236 web: harden reader navigation fallbacks 2026-05-31 07:19:08 +09:00
Hare 2a3208b96e web: render readable html as markdown 2026-05-31 07:11:31 +09:00
Hare aa81aa8c6f web: create local reader extractor ticket 2026-05-31 07:00:39 +09:00
Hare 5187a77dcd close: webfetch readable extraction 2026-05-31 05:55:56 +09:00
Hare c83bb9360f merge: webfetch readable extraction 2026-05-31 05:54:36 +09:00
Hare 1a33df4b6f review: webfetch readable extraction 2026-05-31 05:54:36 +09:00
Hare 7906ca5326 web: extract readable html content 2026-05-31 05:49:20 +09:00
Hare dc5ce2ba72 web: create readable extraction ticket 2026-05-31 05:41:29 +09:00
1207 changed files with 336327 additions and 67032 deletions
+4 -2
View File
@@ -1,5 +1,7 @@
/target /target
.direnv /result
/.direnv
/.yoi/dev
.worktree
*.local* *.local*
.env .env
.worktree
-1
View File
@@ -1 +0,0 @@
/memory/
-30
View File
@@ -1,30 +0,0 @@
[scope]
allow = [
{ target = ".", permission = "write", recursive = true },
]
[session]
record_event_trace = true
[worker]
reasoning = "high"
[model]
ref = "codex-oauth/gpt-5.5"
[compaction]
compact_threshold = 200000
compact_request_threshold = 240000
compact_worker_max_input_tokens = 100000
[memory]
extract_threshold = 50000
consolidation_threshold_files = 5
consolidation_threshold_bytes = 50000
[web]
enabled = true
[web.search]
provider = "brave"
api_key_env = "BRAVE_SEARCH_API_KEY"
-148
View File
@@ -1,148 +0,0 @@
---
description: TODO / tickets / docs / git history から次の作業候補を見繕い、課題発見や方針決定を半自動でイテレーションする WIP maintainer workflow
model_invokation: false
user_invocable: true
requires: []
---
# Auto Maintain Workflow (WIP)
insomnia を AI maintainer として運用するための半自動 loop。TODO / tickets から「今進められそうな作業」を選ぶだけでなく、課題の発見、設計判断の切り分け、次に人間へ戻すべき問いの整理までを扱う。
これは unattended 自動開発ではない。実装の並列委譲は `multi-agent-workflow`、worktree の機械的作成は `worktree-workflow` に任せる。本 Workflow はその前段として、何を進めるべきか、何をまだ決めるべきか、下位 orchestrator にどの intent packet を渡すべきかを整理する。
参照:
- `docs/plan/ai-maintainer.md`
- `tickets/auto-maintain-workflow.md`
## 位置づけ
AI maintainer の目的は、コードを書くこと自体ではなく、プロジェクト状態を前に進めることである。
この Workflow は WIP として、以下を行う。
- TODO / tickets / docs / git history を読んで現在地を把握する。
- 実装可能な ticket と、方針決定が必要な ticket を分ける。
- 小さく実装できる候補を提案する。
- 複数 ticket からなる作業群は、下位 orchestrator に任せる単位として整理する。
- 設計相談が必要な論点を人間に戻す。
- 運用上の問題や繰り返し発生する詰まりを report / ticket / workflow 改訂候補として整理する。
## 非目標
現時点では以下をしない。
- 常駐 scheduler として自動実行する。
- 人間の合意なしに新規 ticket を作る。
- 人間の合意なしに既存 ticket を大幅変更する。
- 人間の合意なしに ticket 完了削除を行う。
- push する。
- Workflow を自律生成・自律改訂する。
- scope / permission / history persistence / prompt context 加工原則に関わる判断を勝手に決める。
## 入力として読むもの
必要に応じて以下を読む。
1. `TODO.md`
2. `tickets/*.md`
3. `docs/plan/`
4. `docs/report/`
5. `git log --oneline` / ticket file の git history
6. 既存 worktree / branch 状態
7. 最近の失敗や通知、ユーザーからの観測
TODO と ticket の不整合を見つけたら、勝手に修正せず、まず報告する。ただしユーザーが明示的に「直して」と言った場合は Mode 1 として整理してよい。
## 分類
候補を以下に分ける。
### A. 実装委譲可能
- 要件と完了条件が具体的。
- 影響範囲が限定的。
- test / build で確認できる。
- 大きな設計判断が不要。
- scope を狭く切れる。
この場合は、人間に候補として提示する。人間が実行を許可したら `$user/multi-agent-workflow` に進む。複数 ticket や連続した作業群では、最上位 Pod が直接 coder を抱えず、下位 orchestrator に intent packet を渡して coder / reviewer sibling loop を管理させる。
### B. 方針決定が必要
- 複数の設計方針が自然に導ける。
- protocol / permission / scope / persistence / prompt context に触れる。
- UX の仕様が未確定。
- 既存 ticket の要件が古い。
この場合は、実装せず、決めるべき問いを短く提示する。
### C. ticket 整理が必要
- TODO にあるが ticket がない。
- ticket があるが TODO にない。
- 完了済みに見えるが残っている。
- ticket の前提が変わっている。
この場合は、不整合と修正案を提示する。修正は人間の許可後に行う。
### D. report / workflow 改善候補
- 同じ tool 問題が繰り返し出る。
- Workflow の指示が曖昧で実装 Pod が迷った。
- coder / reviewer / orchestrator の責務が混ざり、親 Pod が細かい code review に戻ってしまった。
- AI が過剰に Task tool を使うなど、運用上の癖が出た。
- 通知や Pod completion tracking など、開発基盤の不足が観測された。
この場合は、すぐ ticket 化するか、`docs/report/` に観測として残すか、人間に確認する。
## 半自動 iteration
1. 状態把握
- TODO / tickets / git status を読む。
- 最近完了した流れや未完了 branch を確認する。
2. 候補抽出
- 実装可能そうな ticket を 2〜5 件挙げる。
- correctness / developer experience / user-visible UX / cleanup で分類する。
3. 推奨順位
- blocking correctness を最優先。
- 実害が出ている運用問題を次点。
- 小さく完了できる UX / cleanup を次点。
- 大きな設計変更は方針相談に回す。
4. 人間への提示
- 「次に進めるなら X」を1つ推奨する。
- 理由を短く述べる。
- 実装委譲する場合の scope / test 方針を添える。
- 複数 ticket の作業群なら、下位 orchestrator に任せる単位として提示する。
5. 実行への接続
- 人間が「進めて」と言ったら `$user/multi-agent-workflow` に接続する。
- 単発 ticket か、下位 orchestrator に任せる ticket 群かを明示する。
- 下位 orchestrator に渡す intent / requirements / invariants / non-goals / escalation 条件を短くまとめる。
- worktree 作成は `$user/worktree-workflow` に従う。
## エスカレーション基準
以下では実装に進まず、人間へ戻す。
- ticket の要件から複数の設計方針が自然に導ける。
- 長期構造、crate boundary、protocol、permission、scope、history persistence に触れる。
- prompt context 加工原則に関わる。
- 新 ticket の作成、既存 ticket の大幅変更、ticket 完了削除について合意がない。
- test 不能、再現不能、または作業範囲外の不具合に遭遇した。
- WorkItem / Thread / Lease / maintainer state など、まだ設計中の概念が必要になる。
- 下位 orchestrator に委譲するには intent / invariant / escalation 条件が曖昧すぎる。
## まだ固定しないもの
以下は `docs/plan/ai-maintainer.md` の上位設計に残し、本 Workflow では詳細を固定しない。
- WorkItemStore / LeaseStore。
- operation inbox / trial log。
- QA feedback を ticket / review / report のどれに落とすか。
- AI 自身の feedback を Knowledge / report / ticket / workflow 改訂のどれにするか。
- maintainer doctor。
- reviewer Pod の評価基準の機械化。
-306
View File
@@ -1,306 +0,0 @@
---
description: worktree と sibling の coder / reviewer Pod を使い、下位 orchestrator が複数 ticket の実装・外部レビュー・修正・完了準備を管理する orchestration フロー
model_invokation: true
user_invocable: true
requires: ["ticket-preflight-workflow", "worktree-workflow"]
---
# Multi-agent Worktree Workflow
insomnia を insomnia で開発する際の、worktree + coder Pod + 外部 reviewer Pod + orchestrator Pod の標準フロー。これは **最上位 Pod が細かい code review を抱えず、下位 orchestrator が実装と外部レビューの loop を完了状態まで運ぶためのフロー** である。
worktree の機械的作成手順は `$user/worktree-workflow`、実装前の要件同期・反証 preflight は `$user/ticket-preflight-workflow`、ticket 候補選定や方針探索の半自動 loop は `$user/auto-maintain` に分ける。
この Workflow は、対象 ticket が implementation-ready であることを前提にする。設計境界・仕様・authority boundary が未同期の場合は、worktree 作成や coder Pod 起動の前に `ticket-preflight-workflow` を通す。
## 目的
- 実装差分を ticket ごとの child worktree に隔離する。
- coder Pod に narrow write scope を渡して実装させる。
- reviewer Pod を coder の子ではなく **同じ orchestrator 配下の sibling** として立て、外部レビューを行わせる。
- orchestrator は coder / reviewer のやり取り、修正 loop、validation、merge-ready dossier 作成に責任を持つ。
- 最上位 orchestrator は、コードを直接理解し切ることではなく、委譲した intent / 要件 / invariant に沿って下位 orchestrator が完了まで運んだかを acceptance する。
## 階層モデル
基本形は以下。
```text
最上位 orchestrator Pod
- 人間との会話相手
- intent / 要件 / invariant / escalation 条件を定義
- 複数の作業群を並列管理
- final merge / ticket close / main workspace validation を行う
- 原則として line-by-line code review を主業務にしない
下位 orchestrator Podarea / epic / ticket-group coordinator
- 連続した複数 ticket または大きめの ticket 群を完了状態まで運ぶ
- worktree / branch / coder / reviewer / validation / 修正 loop を管理する
- coder と reviewer を sibling として扱う
- 親には merge-ready dossier と残論点だけを返す
coder Pod
- 指定 worktree / branch に実装する
- ticket 外判断や設計衝突は orchestrator に戻す
- reviewer に直接反論・修正依頼を完結させず、orchestrator に報告する
reviewer Pod
- 原則 read-only
- ticket / intent packet / diff / validation 結果を読む
- 実際のコード変更が概念的に何を変えたかを説明する
- intent / 要件 / invariant に反する blocker を分類して返す
```
一段だけで足りる小さい ticket では、最上位 orchestrator が直接 coder / reviewer sibling を扱ってよい。複数 ticket や設計境界をまたぐ作業では、最上位の下に下位 orchestrator を挟む。
## 開始条件
以下が揃っている時に使う。
- 対象 ticket または ticket 群が決まっている。
- ticket の背景・要件・完了条件から実装方針が概ね導ける。
- worktree 作成と git 書き込み操作について、人間の許可がある。
- main workspace の unrelated dirty changes を把握している。
- 下位 orchestrator に渡す intent / invariant / non-goals / escalation 条件を短く書ける。
- 設計境界・仕様・authority boundary に不確定要素がある場合、`ticket-preflight-workflow` の結果が ticket thread に記録されている。
設計方針が複数自然に導ける場合、protocol / scope / permission / history persistence に触れる場合、ticket 自体の再定義が必要な場合は、実装委譲前に `ticket-preflight-workflow` を通し、必要なら人間へ戻す。ただし下位 orchestrator に探索だけを委譲することはできる。
## Intent packet
階層化すると人間の意図が劣化しやすい。下位 orchestrator や coder / reviewer へは、自然文の依頼だけでなく intent packet を渡す。
標準形:
```text
Intent:
- 何を実現するか。
Requirements:
- 完了時に満たすべき observable な要件。
Invariants:
- 壊してはいけない設計境界。
- 残してはいけない旧概念や互換層。
Non-goals:
- 今回やらないこと。
Escalate if:
- 親へ戻すべき判断条件。
Validation:
- 実行すべき format / build / test / doctor。
```
reviewer には coder の実装方針ではなく、この intent packet と diff を中心に読ませる。
## orchestrator の責務
下位 orchestrator を挟まない場合は、以下を最上位 orchestrator が行う。下位 orchestrator を挟む場合は、最上位は intent packet を渡し、以下の実務を下位に委譲する。
1. 状態確認
- `git status --short --branch`
- 対象 ticket / ticket 群
- 関連 TODO / docs / 既存 worktree
- preflight が必要な ticket では、`ticket-preflight-workflow` の分類・要件同期・critical risks
2. worktree 作成
- `$user/worktree-workflow` に従い `./.worktree/<task-name>` を作る。
- `.insomnia` を sparse checkout で除外する。
3. coder Pod spawn
- read scope: main workspace 全体。
- write scope: child worktree、または必要最小 directory。
- task には以下を明示する。
- child worktree path / branch
- 対象 ticket path
- intent packet
- Bash は必ず child worktree に `cd` すること
- main workspace の `TODO.md` / `tickets/` / `docs/report/` / `.insomnia` は編集しないこと
- 範囲外事項
- 実行すべき build / test / format
- 完了報告項目
4. coder 完了確認
- `ReadPodOutput` で報告を読む。
- 通知が来ない場合でも、worktree の `git status` / `git diff` / test で完了状態を確認する。
- coder が止まった場合、worktree 状態を見て再 spawn / rollback / 親 escalation を判断する。
5. reviewer Pod spawn
- reviewer は coder の子ではなく orchestrator 配下の sibling として立てる。
- 原則 read-only scope にする。
- reviewer に渡すもの:
- ticket / intent packet
- branch / commit / diff の読み方
- 実行済み validation
- blocker / non-blocker / acceptable の分類基準
- reviewer の主目的は「コードの詳細を親の代わりに説明し、intent / invariant 違反を見つけること」。
6. review → 修正 loop
- reviewer finding を orchestrator が読む。
- blocker は coder に修正依頼する。
- reviewer の指摘を却下する場合は、orchestrator が理由を dossier に残す。
- 修正後は focused validation を実行し、必要なら reviewer に再確認させる。
- reviewer の blocker が未解決のまま親に提出しない。
7. merge-ready dossier 作成
- 親がコードを直接理解しなくても判断できるよう、変更の概念的説明と evidence をまとめる。
8. merge / lifecycle
- 最上位 orchestrator または人間の許可を持つ orchestrator が main workspace へ merge する。
- `TODO.md` から該当行を削除し、ticket を完了処理して commit する。
- main workspace で必要な test / `cargo check --workspace` / `cargo fmt --check` を再実行する。
## coder Pod の責務
- child worktree 内でのみ実装する。
- main workspace の管理ファイルを書かない。
- intent / requirements / invariants / non-goals を読んでから実装する。
- 指定された build / test / format を実行する。
- ticket 要件外の設計変更、依存関係追加、scope / permission / history persistence / prompt context 加工原則に触れる変更が必要なら止めて orchestrator に報告する。
- 完了時に以下を報告する。
- worktree path / branch
- commit hashcommit した場合)
- 変更ファイル
- 実装概要
- 実行した build / test / format
- 未解決事項
- review に回せるか
## reviewer Pod の責務
reviewer は coder の subordinate ではない。orchestrator 配下の sibling として、実装 diff を外部から読む。
- 原則 read-only で作業する。
- ticket / intent packet / diff / validation 結果を読む。
- 実際のコード変更が概念的に何を変えたかを説明する。
- 親や上位 orchestrator が line-by-line diff を読まずに判断できるよう、以下を整理する。
- 変更の概念モデル
- intent / requirements との対応
- invariant 違反の有無
- 旧概念・禁止語彙・不要な互換層の残存
- validation の妥当性
- blocker / non-blocker / follow-up
- reviewer は直接 merge しない。
- reviewer は coder に直接作業指示を出さず、orchestrator に finding を返す。
## commit 方針
coder Pod には child worktree 内での commit を許可してよい。
- commit は ticket 内で意味のある粒度にする。
- 例: `feat: ...``fix: ...``test: ...``docs: ...`
- coder Pod は merge / push / branch deletion / worktree remove をしない。
- coder Pod は `TODO.md` / ticket の完了処理 commit をしない。
- orchestrator は review 時に commit 粒度も確認する。
- 必要な修正は、原則追加 commit として積む。履歴改変や squash は人間の明示指示がある時だけ行う。
## Review → 修正 → 完了の標準形
### Approve
1. coder Pod / reviewer Pod を停止し、scope を回収する。
2. orchestrator が merge-ready dossier を確認する。
3. 最上位 orchestrator が必要最小限の spot check を行う。
4. main workspace で `git merge --no-ff <branch>` する。
5. `TODO.md` と ticket を完了処理して commit する。
6. main workspace で検証コマンドを再実行する。
7. 変更内容・commit・検証結果・残 dirty changes を報告する。
### Request changes
1. reviewer finding または orchestrator finding を blocker / non-blocker に分ける。
2. blocker はファイル / 行 / 理由 / 修正方針つきで coder に戻す。
3. coder が停止済みなら、同じ worktree / branch / scope で再 spawn する。
4. 修正後に focused test と必要な broader test を再実行する。
5. 必要なら reviewer に再確認させる。
6. blocker が解消したら dossier を更新する。
### Non-blocking comments
- ticket 要件外の改善はその場で混ぜない。
- 必要なら後続 ticket / docs/report にする。
- non-blocking を理由に completion を遅らせない。
## 並列実装時の注意
- 1 ticket = 1 worktree = 1 branch を基本にする。
- 複数 Pod に同じ write scope を渡さない。
- parent / orchestrator は coder の write scope 配下を直接編集しない。
- reviewer は read-only を基本にする。review artifact を書かせる場合は ticket artifacts など限定 scope にする。
- 依存関係がある ticket は、土台 branch を merge してから次 worktree を切る。
- parallel に走らせた Pod の完了通知は取りこぼしうるため、`ReadPodOutput` と worktree 状態で確認する。
## merge-ready dossier の標準形
```text
Status:
- completed / blocked / needs parent decision
Scope:
- ticket(s): <path>
- branch: <name>
- commits:
- <hash> <subject>
Intent check:
- invariant 1: ok / violated / not applicable, evidence ...
- invariant 2: ok / violated / not applicable, evidence ...
Implementation summary:
- 変更の概念的説明: ...
- 主要変更ファイル: ...
- compatibility / migration: ...
Coder loop:
- coder pod: <name>
- produced commits: ...
- unresolved coder notes: ...
External review:
- reviewer pod: <name>
- blockers found: ...
- blockers fixed: ...
- rejected findings and reasons: ...
- non-blocking follow-ups: ...
Validation:
- cargo fmt --check
- cargo check --workspace
- cargo test ...
- ./tickets.sh doctor
Parent decision needed:
- none / specific question
Residual risk:
- ...
Dirty state:
- ...
```
## 最上位 orchestrator の acceptance
最上位 orchestrator は、下位 orchestrator の成果を code review するのではなく acceptance する。
確認するもの:
- intent packet が保持されているか。
- reviewer が coder と独立した sibling として機能したか。
- blocker が未解決のまま握りつぶされていないか。
- 変更の概念的説明が要件と対応しているか。
- validation が ticket のリスクに対して十分か。
- escalation すべき判断を下位が勝手に決めていないか。
必要なら spot check するが、常態的な line-by-line review に戻らない。
## この Workflow で扱わないもの
以下は `$user/auto-maintain` または別の設計相談で扱う。
- ticket 候補を見繕うこと。
- 新規 ticket 作成判断。
- QA feedback / AI feedback を ticket / report / workflow に落とす判断。
- 長期 maintainer loop / WorkItemStore / LeaseStore の設計。
- reviewer Pod の品質評価を機械的に採点する仕組み。
@@ -1,167 +0,0 @@
---
description: ticket を実装委譲する前に、要件・前提・設計境界・反証観点を同期し、tickets.sh に記録する preflight フロー
model_invokation: true
user_invocable: true
requires: []
---
# Ticket Preflight Workflow
insomnia プロジェクトで ticket を実装に渡す前に、要件・前提・設計境界・反証観点を同期するための Workflow。これは **実装前の gate** であり、worktree 作成や coder / reviewer Pod の起動は `multi-agent-workflow` / `worktree-workflow` 側で扱う。
目的は「ticket があるから実装する」状態を避け、ticket が **実装可能な仕様** なのか、**調査 ticket** なのか、**人間との仕様同期が必要な未決定 ticket** なのかを明確にすることである。
## 適用する場面
以下のいずれかに当てはまる ticket は、実装委譲前にこの Workflow を通す。
- profile / manifest / scope / permission / session / history / pod-store / prompt context など authority boundary に触れる。
- ticket の文面から複数の自然な設計方針が導ける。
- 「どう実装するか」以前に「何を仕様とするか」が曖昧である。
- 既存 implementation plan があるが、抽象化・責務境界・ユーザー体験に疑問がある。
- 過去 decision / memory / docs / ticket thread と矛盾しそうである。
- coder Pod に渡す intent packet を短く書けない。
小さなバグ修正や仕様が明確な局所変更では、この Workflow は省略してよい。ただし省略理由が曖昧な場合は preflight する。
## tickets.sh 運用方針
作業管理の authority は `work-items/``tickets.sh` である。preflight の結果は、口頭の会話だけで終わらせず、ticket の `thread.md` または `item.md` に残す。
- 新規の前提・要件・受け入れ条件は、必要に応じて `item.md` を更新する。
- 調査結果・実装前 plan は `./tickets.sh comment <ticket> --role plan --file <file>` で残す。
- 採用/却下した設計判断、実装停止判断、仕様同期の結論は `--role decision` で残す。
- 実装に入ってよい状態になったら、その根拠を intent packet として ticket thread に残す。
- 仕様が未決定なら、実装 ticket にせず requirements-sync / spike / design ticket として切り分ける。
- ticket の timestamp/frontmatter が更新される場合は、関連変更と一緒に commit する。
- ticket 作成・更新・レビュー・完了は git commit で記録する。push はしない。
## 手順
### 1. 状態確認
- `git status --short --branch`
- 対象 ticket の `item.md` / `thread.md` / artifacts
- 関連 ticket / docs / workflow / Knowledge / memory decision
- 既存 worktree / branch / running Pod の有無
この段階で unrelated dirty changes がある場合は、preflight の記録だけを行うか、人間に確認してから進める。
### 2. ticket の種類を分類する
以下のどれかに分類する。
```text
implementation-ready:
- 要件・受け入れ条件・invariant が明確で、実装方針が一意または十分絞れている。
requirements-sync-needed:
- ticket の目的は見えているが、仕様・用語・責務境界・ユーザー体験の同期が必要。
spike-needed:
- 技術的実現性・依存関係・ライセンス・性能・diagnostics などを先に調べる必要がある。
blocked-needs-human-decision:
- 複数方針があり、AI が勝手に決めると設計境界や product API を固定してしまう。
```
`implementation-ready` 以外は、coder Pod に実装を委譲しない。
### 3. 要件同期
最低限、以下を確認する。
- 完了時に observable に何が変わるか。
- ticket の主語は何か: user-facing behavior / internal architecture / cleanup / investigation。
- 用語が既存設計と一致しているか。
- 何をやらないか。
- 後方互換が必要か、不要な互換層を作ろうとしていないか。
- 既存の authority boundary を変えるか。
- runtime state / persisted state / config / profile / manifest / session log / pod metadata のどれが authority か。
必要なら ticket `item.md` の Background / Requirements / Acceptance criteria を更新する。
### 4. 現行コードと過去判断の map を作る
実装前に、少なくとも関連する current code paths を列挙する。
```text
Current code map:
- file/function: 現在の責務
- file/function: 変更候補
- file/function: 触ってはいけない境界
```
この map は簡潔でよい。目的は coder Pod が blind に探しながら設計を固定するのを防ぐこと。
### 5. 批判的 preflight
実装方針を一度疑う。以下の問いに答える。
- この ticket は本当に実装 ticket か、それとも仕様同期 ticket か。
- 最も自然に見える実装が失敗するとしたらどこか。
- 抽象化に失敗して「別名の同じもの」を作っていないか。
- runtime-bound な値を reusable config に混ぜていないか。
- profile / manifest / scope / session / pod-store などの authority を逆転させていないか。
- user-facing API を安易に public contract 化していないか。
- external dependency / license / portability / packaging の問題はないか。
- reviewer が diff だけ読んでも見落とす設計リスクは何か。
この問いへの答えを `plan` または `decision` として ticket thread に残す。
### 6. intent packet を作る
実装に入ってよい場合だけ、`multi-agent-workflow` に渡す intent packet を作る。
```text
Intent:
- 何を実現するか。
Requirements:
- observable な完了条件。
Invariants:
- 壊してはいけない authority boundary / design boundary。
Non-goals:
- 今回やらないこと。
Escalate if:
- 親/人間に戻す判断条件。
Validation:
- focused test / broader check / doctor / docs 更新。
Current code map:
- 実装対象と触ってはいけない場所。
Critical risks:
- reviewer にも見てほしい失敗パターン。
```
この intent packet が短く書けない場合は、実装委譲せず requirements-sync-needed とする。
## review への引き継ぎ
preflight で出た critical risks は reviewer Pod にも渡す。reviewer は diff だけでなく、ticket の前提・要件・invariant と preflight の反証観点を読む。
reviewer に期待すること:
- 実装が preflight の intent に対応しているか。
- 抽象化失敗や authority boundary 違反がないか。
- preflight で挙げた失敗パターンに落ちていないか。
- validation がリスクに対して十分か。
## 完了条件
この Workflow 自体の完了条件は、次のいずれかである。
- ticket が `implementation-ready` になり、intent packet が thread に記録されている。
- ticket が `requirements-sync-needed` / `spike-needed` / `blocked-needs-human-decision` として整理され、次に人間へ戻す問いまたは follow-up ticket が明確になっている。
- ticket 自体が不要/誤りと判断され、理由が decision として記録されている。
## この Workflow でしないこと
- worktree を作成しない。
- coder Pod に実装を委譲しない。
- merge / close しない。
- 仕様未決定のまま「小さく実装してみる」ことで public API を固定しない。
-119
View File
@@ -1,119 +0,0 @@
---
description: insomnia プロジェクトで child git worktree を作成・管理するための機械的手順。coder Pod に作らせず、orchestrator Pod が main workspace で実行する。
model_invokation: true
user_invocable: true
requires: []
---
# Worktree Workflow
insomnia プロジェクトで実装差分を main workspace から分離するため、`./.worktree/<task-name>` に child git worktree を作る。これは **worktree の扱い方だけ** を定める Workflow であり、ticket 選定、coder / reviewer sibling の起動、外部レビュー、merge の運用は `$user/multi-agent-workflow` 側で扱う。
insomnia では Pod の write scope が排他的に委譲されるため、child worktree に `.insomnia` を置かない。main workspace は orchestration / ticket / docs / memory / workflow 管理の場所として残し、child worktree はコード差分専用の作業面として扱う。
## 適用範囲
この Workflow は親 Pod / 下位 orchestrator が main workspace で実行する。
- coder Pod にこの Workflow を渡して worktree を作らせない。
- coder Pod は、orchestrator が作成済みの child worktree を受け取り、その中で実装・build・test・報告を行う。
- reviewer Pod は、coder Pod の子ではなく orchestrator 配下の sibling として、原則 read-only で main workspace と child worktree を読む。
- ticket 作成、TODO 更新、review artifact、docs/report は main workspace 側で扱う。
## 原則
- 1 ticket / 1 実装 task につき 1 worktree を作る。
- 複数 ticket を下位 orchestrator に任せる場合も、実装差分は ticket / bounded task ごとに worktree を分ける。
- worktree path は `./.worktree/<task-name>`
- branch 名は原則 `<task-name>` と同じ kebab-case。
- child worktree には `.insomnia` を出さない。
- child worktree は実装差分用。`TODO.md` / `tickets/` / `docs/report/` / workflow / memory は原則 main workspace 側で扱う。
- push はしない。
## 事前確認
作成前に以下を確認する。
1. 対象 ticket / task が決まっているか。
2. `<task-name>` が branch / path 名に使える kebab-case か。
3. `git worktree add` を実行してよい許可があるか。
4. main workspace に混ぜてはいけない未保存差分がないか。
5. 同名 branch / worktree が既に存在しないか。
6. coder / reviewer を sibling として扱う orchestrator が誰か明確か。
同名 branch がある場合は、既存 branch を使うか、人間に確認する。`git worktree add -b` で上書きしない。
## 作成手順
main workspace で実行する。
```bash
git worktree add .worktree/<task-name> -b <task-name>
git -C .worktree/<task-name> sparse-checkout init --no-cone
git -C .worktree/<task-name> sparse-checkout set --no-cone \
'/*' \
'!/.insomnia/' \
'!/.insomnia/**'
```
確認する。
```bash
git -C .worktree/<task-name> status --short --branch
test ! -e .worktree/<task-name>/.insomnia
```
失敗した場合は、worktree / branch / lock の状態を確認し、勝手に cleanup せず人間へ報告する。
## Pod へ渡す scope
Pod を使う場合、Pod の cwd は main workspace のままになる。必ず作業対象が child worktree であることを明示し、Bash 実行時は毎回 `cd <repo>/.worktree/<task-name> && ...` させる。
coder Pod 推奨 scope:
```text
read: <repo>
write: <repo>/.worktree/<task-name>
```
reviewer Pod 推奨 scope:
```text
read: <repo>
read: <repo>/.worktree/<task-name> # main workspace の read に含まれるなら別指定不要
```
reviewer は原則 write scope を持たない。review artifact を書かせる必要がある場合だけ、ticket artifacts など限定 directory を write scope として渡す。
より狭く切れる場合は、coder の write scope を変更対象 crate / directory まで狭めてよい。ただし build / test に必要な生成物を書けることを確認する。
## child worktree 内の禁止事項
- `.insomnia` を作らない / コピーしない。
- main workspace の `TODO.md` / `tickets/` / `docs/report/` を編集しない。
- merge / push / branch deletion / worktree remove をしない。
- scope / permission / history persistence / prompt context 加工原則に関わる設計変更を無断で行わない。
## 完了時の扱い
worktree 作成 Workflow としては、完了時に merge しない。merge、ticket 完了、TODO 削除は `$user/multi-agent-workflow` または人間の明示指示で行う。
coder Pod へ渡す完了報告項目の標準形:
- worktree path
- branch 名
- commit hashcoder Pod に commit を許可した場合)
- 変更ファイル
- 実装概要
- 実行した build / test / format
- 未解決事項
- review に回せるか
reviewer Pod へ渡す完了報告項目の標準形:
- 読んだ ticket / intent packet / diff
- 実際のコード変更の概念的説明
- intent / requirements / invariant との対応
- blocker / non-blocker / follow-up
- validation の妥当性
- 親または上位 orchestrator が判断すべき残論点
+4
View File
@@ -0,0 +1,4 @@
/memory/
tickets/.ticket-backend.lock
/workspace.db*
tickets
+60
View File
@@ -0,0 +1,60 @@
---
title: "E2E テスト戦略"
state: "active"
created_at: "2026-06-09T07:09:26Z"
updated_at: "2026-06-09T07:09:26Z"
linked_tickets: ["00001KSKBP9YG"]
---
## Goal
Yoi の実プロセス・実 socket・実 provider 境界をまたぐ振る舞いを、通常の crate 内 unit / integration test だけに頼らず検証できる E2E テスト戦略を確立する。
最初の到達点は、実 `pod` / product binary を spawn し、protocol 経由で最小シナリオを実行し、graceful shutdown まで確認できる opt-in E2E harness を持つこと。その上で、permission、resume/fork、spawned Pod、provider stream、TUI/Panel などの重要境界を段階的に増やせる状態にする。
## Motivation / background
現状のテストは crate 内の in-process coverage が厚い一方で、以下の性質は単体テストだけでは十分に確認しづらい。
- 実プロセス spawn と runtime dir / socket / env の相互作用。
- Pod controller / protocol client / session store / metadata / restore の統合挙動。
- provider endpoint、streaming、auth/token、tool call、continuation、retry の実接続に近い振る舞い。
- permission deny、scope、manifest/profile 解決、child Pod delegation など、複数 crate と実 runtime state をまたぐ policy。
- TUI / Panel が前提にする Pod lifecycle や Ticket orchestration の外形。
E2E は常時実行の軽いテストではなく、dogfooding 中に「この機能は実 runtime でも壊れていない」と確認するための opt-in 検証基盤として必要。
## Strategy / design direction
- E2E は通常の `cargo test --workspace` からは外し、明示 feature / 専用 package / 独立 job で opt-in 実行する。
- まずはワークスペース直下の専用 E2E package / harness として設計し、個別 crate の unit test に押し込めない。
- protocol を喋る側は TUI の PTY 操作ではなく、typed client / protocol client を使う方向を優先する。
- provider 依存は最初から全部を対象にしない。
- 最小 harness では canned / fixture / mock HTTP server を使う。
- provider 差分は代表 provider から段階的に増やす。
- env / runtime dir / socket path は test ごとに隔離し、並列実行方針を明示する。
- 必要なら最初は `--test-threads=1` 相当で安全側に倒す。
- 将来的には per-test runtime dir と typed launch config で並列性を上げる。
- E2E は「全シナリオを大量に持つ」より、重要な runtime seam ごとに少数の高価値 scenario を置く。
- 失敗時 diagnostics は、secret を出さずに process phase、socket path、session id、log path、provider fixture id を辿れる形にする。
- E2E harness 自体が flaky にならないよう、network / time / external auth への依存は明示 opt-in に分ける。
## Success criteria / exit conditions
- `cargo test --workspace` では E2E が走らず、通常開発の feedback loop を重くしない。
- 明示コマンドで E2E harness を実行できる。
- 例: `cargo test -p e2e --features e2e` または後続で決める同等コマンド。
- 最小 scenario が実 `pod` / product binary を spawn し、protocol 経由で 1 turn 実行し、graceful shutdown まで通る。
- E2E 実行は専用 runtime/data dir を使い、通常の user/workspace state を汚さない。
- fixture / mock provider の設計があり、少なくとも 1 provider 相当の canned response を実 HTTP 経由で返せる。
- failure diagnostics から、spawn 失敗・socket 接続失敗・provider fixture 失敗・protocol 失敗・shutdown 失敗を区別できる。
- 後続 Ticket が permission / resume / fork / spawned Pod / provider streaming / Panel などを追加できる harness boundary がある。
## Decision context
- linked Ticket `00001KSKBP9YG` は、E2E harness の最初の concrete implementation Ticket として扱う。
- この Objective は E2E 全体の中長期方針・判断軸を保持する。個別 scenario の実装や harness の細部は concrete Ticket に分ける。
- TUI を直接 PTY で叩く方針は初期 harness では避け、protocol/client 経由を優先する。
- provider 全対応は初期 scope にしない。fixture / mock HTTP server を基礎にし、代表 provider から段階的に広げる。
- E2E は flakiness と実行コストが高いため、既定 CI / 既定 workspace test には入れず、opt-in 検証として始める。
- Objective context は判断材料であり、実装 authority は各 Ticket の body/thread/artifacts と明示的な Ticket relation / OrchestrationPlan に置く。
+73
View File
@@ -0,0 +1,73 @@
---
title: "ネイティブGUIアプリケーション"
state: "active"
created_at: "2026-06-10T07:41:18Z"
updated_at: "2026-07-15T21:18:00Z"
linked_tickets: []
---
## Goal
Yoi の Pod / Ticket / Orchestrator / Skill・prompt resource 操作を、TUI だけでなくネイティブ GUI から扱えるようにする。
最初の到達点は、既存の runtime / Ticket backend / Pod protocol / Profile / Skill/prompt resource authority を再実装せずに、workspace の状態を視覚的に把握し、選択した Pod・Ticket・role action に対して安全に操作できる desktop GUI client を持つこと。GUI は core authority ではなく client surface とし、既存 CLI/TUI と同じ durable state・同じ protocol・同じ permission/prompt/resource 境界を使う。
## Motivation / background
現在の TUI / Panel は dogfooding 可能な状態まで進んでいるが、複数 Pod・複数 Ticket・Orchestrator 状態・session output・role launch・review/merge dossier を同時に扱うには、terminal UI の表示密度・視覚的状態表現・スクロール/選択/比較操作に限界が出ている。
ネイティブ GUI があると、以下をより自然に扱える。
- live / stored Pod、Ticket lane、Orchestrator progress、Companion/Intake 状態の同時表示。
- Ticket body/thread/artifacts、Pod output、validation evidence、diff/report の並列閲覧。
- composer target、role action、queue/routing/attach/restore の明確な affordance。
- long-running orchestration の通知、状態変化、失敗診断の視覚化。
- 将来的な review / merge-ready dossier / plan board / settings editor の専用 UI。
一方で、GUI を理由に runtime authority を分散させたり、Ticket/Pod state を独自 DB として二重管理したり、prompt/resource 文字列を GUI code に直書きしたりしてはいけない。
## Strategy / design direction
- GUI は Yoi core の上に乗る client として作る。
- Pod lifecycle、session/history、Ticket storage、Profile resolution、resource/prompt authority は既存 core を正とする。
- GUI 固有 state は selection、layout、local UI preference などに限定する。
- 最初に toolkit / architecture の小さな spike を置く。
- 評価軸は Rust code reuse、async/runtime 統合、native packaging、Linux dogfooding しやすさ、testability、accessibility、long-running log/output 表示、将来の cross-platform 余地。
- toolkit 選定は Objective では固定しない。候補比較と採用理由を Ticket に残す。
- 実装は段階的に進める。
1. read-only workspace dashboard: Pod / Ticket / Orchestrator 状態を既存 backend から表示する。
2. attach / restore / open など、既存 protocol に乗る低リスク操作を追加する。
3. composer と role action: Companion / Intake / Orchestrator / coder / reviewer launch を既存 launcher 経由で扱う。
4. Ticket body/thread/artifacts、Pod output、validation evidence、review report を閲覧しやすくする。
5. 必要に応じて settings/profile/config editor や merge-ready dossier UI を追加する。
- TUI は廃止前提にしない。
- GUI 導入後も CLI/TUI は fallback / automation / terminal-first operation flow として維持する。
- GUI で見つかった state model の改善は、TUI と共有できる pure data model / client API に寄せる。
- Prompt / resource / role guidance は GUI code に直書きしない。
- LLM-facing prompt は `resources/prompts` または `.yoi/skills` / configured resources を正とする。
- GUI は prompt 文言を所有せず、選択・起動・runtime context の入力面を担当する。
- Security / privacy / authority boundary を保つ。
- secret-like data は UI diagnostics / logs / model context に漏らさない。
- permission / scope / profile の authority は既存 resolver/policy に従う。
- GUI convenience action は durable Ticket/Pod state transition と対応付け、暗黙の side effect を避ける。
## Success criteria / exit conditions
- 明示コマンドまたは binary で native GUI を起動できる。
- GUI は既存 workspace config、Profile、Ticket backend、Pod registry/protocol を使い、独自の authority store を持たない。
- 最小 dashboard で live/stored Pod、Ticket lane/state、Orchestrator/role session の概況を確認できる。
- GUI から少なくとも attach/restore/open 相当の安全な Pod 操作ができる。
- GUI から Ticket Intake または既存 role launcher を使った role action を実行でき、既存の prompt/resource 境界を壊さない。
- Pod output / Ticket body/thread/artifacts を、TUI より見通しよく閲覧できる最小 UI がある。
- GUI 固有 state と core durable state の境界が文書化されている。
- toolkit / architecture 選定理由、採用しなかった選択肢、packaging 方針が Ticket artifact または design note として残っている。
- GUI で使う state transformation / action eligibility は pure model として test 可能で、主要な selection/action state の unit test がある。
- GUI 実装は CLI/TUI の既存 operation flow を破壊せず、必要な targeted validation が定義されている。
## Decision context
- この Objective は中長期の方向性・判断軸を保持する。具体的な toolkit 選定、crate 構成、初期 dashboard 実装、role action 実装、packaging は個別 Ticket に分ける。
- GUI は TUI の単純な置換ではなく、複数 Pod / Ticket / Orchestrator を扱う workspace cockpit として設計する。
- authority は既存 core に残す。GUI は client/view/controller surface であり、Pod/Ticket/resource/prompt の正本を所有しない。
- Prompt 直書き禁止方針を守る。GUI 実装中に LLM-facing 文言が必要になった場合は、`resources/prompts` または Skill/resource 側に置く。
- 初期 target は dogfooding しやすい desktop GUI とし、public release / cross-platform polish / installer は後続段階で扱う。
+111
View File
@@ -0,0 +1,111 @@
---
title: 'MCP local stdio integration roadmap'
state: 'active'
created_at: '2026-06-10T07:48:45Z'
updated_at: '2026-06-20T05:34:00Z'
linked_tickets: ['00001KTR81P9X', '00001KV0SP0TY', '00001KVHR3WRF', '00001KVHR3WRY', '00001KVHR3WS6', '00001KVHR3WSD', '00001KVHR3WSN', '00001KVHR3WSW']
---
## Goal
Add MCP local stdio integration to Yoi without weakening Worker history, prompt-context, scoped tool permission, or Plugin/Feature layering invariants.
MCP is a protocol-backed integration layer on top of `pod::feature`. `pod::feature` supplies contribution/lifecycle/runtime-discovered registration substrate; MCP owns its own enablement, local server trust model, command/env/secret policy, and MCP-specific permission decisions. MCP is not the Plugin model, and Plugin permission policy is not implemented by feature-layer authority grants.
## Motivation / background
Yoi needs to integrate with external capability providers without turning them into hidden context sources or bypassing ordinary Tool/Worker safety rules. MCP is useful because it can expose tools, resources, and prompts from local protocol servers, but those server-provided declarations and results are untrusted and must be normalized through Yoi's existing authority boundaries.
The first MCP slice should focus on local stdio servers because they are concrete enough to implement and debug while keeping remote auth, OAuth, Streamable HTTP, registry distribution, sampling, and elicitation out of the initial trust boundary.
A configured local MCP server runs as a local executable. Yoi feature authority does not sandbox that executable's OS-level side effects, so command/env/secret handling and explicit local trust policy are MCP-layer responsibilities rather than generic `pod::feature` grants.
## Strategy / design direction
- Baseline the initial implementation on MCP specification `2025-11-25`.
- Start with local stdio MCP servers only.
- Treat MCP server metadata, tools, resources, prompts, and results as untrusted content.
- Do not allow MCP resources/prompts to become hidden context injection.
- They must be explicit tool operations with history records.
- Use the normal Yoi ToolRegistry, PreToolCall permission, history, and bounded result paths.
- Do not add private MCP-only bypasses around Worker/tool invariants.
- Keep sampling and elicitation fail-closed initially.
- Keep Streamable HTTP, remote auth, OAuth, and MCP Registry/distribution out of the first slice.
- Treat local stdio server execution as an explicit MCP config/trust decision, not as a `pod::feature` authority grant.
- Document clearly that a configured local MCP server runs as a local executable; Yoi feature authority does not sandbox its OS-level side effects.
### Layering decisions
- `pod::feature` is an API/contribution substrate.
- It owns contribution declarations, provider/service lifecycle hooks, diagnostics, runtime-discovered registration plumbing, and integration with normal Worker/ToolRegistry paths.
- It does not own Plugin permission policy or MCP server trust policy.
- Plugin is a user-facing package/config/runtime layer over `pod::feature`.
- Plugin permissions are Plugin-layer policy.
- Plugin package discovery/enablement must not be conflated with MCP local server execution.
- MCP is a separate feature-backed integration layer.
- MCP enablement, command/env/secret handling, server trust, and MCP-specific permission decisions live in MCP config/implementation.
- MCP provider-discovered tools/resources/prompts are exposed through the feature API and ordinary Yoi tool paths.
### Concrete implementation tickets
Completed prerequisites:
- `00001KTR81P9X` — Extend `pod::feature` API for external protocol-backed capability providers.
- `00001KV0SP0TY` — Remove feature-layer HostAuthority model.
Concrete MCP implementation sequence:
1. `00001KVHR3WRF` — MCP local stdio server config and trust policy.
- explicit config, command/env/secret redaction, local executable trust boundary, no auto-start.
2. `00001KVHR3WRY` — MCP stdio JSON-RPC lifecycle client.
- subprocess lifecycle, initialize/capability negotiation, diagnostics, shutdown.
3. `00001KVHR3WS6` — MCP tools/list registration into ToolRegistry.
- provider-discovered tools, stable namespacing, schema validation, untrusted metadata normalization, no tools/call yet.
4. `00001KVHR3WSD` — MCP tools/call execution through ordinary Tool path.
- PreToolCall gate before server call, bounded result serialization, history path.
5. `00001KVHR3WSN` — MCP resources/prompts as explicit tool operations.
- resources/list/read and prompts/list/get without hidden context injection.
6. `00001KVHR3WSW` — MCP list_changed notification handling.
- deterministic safe refresh/diagnostic behavior without breaking tool schema or prompt-cache invariants.
The old broad implementation Ticket `00001KTR82RB7` is superseded by this sequence and should not be used as an implementation work item.
### Terminology
Use `runtime-discovered` or `provider-discovered` for MCP tools/resources/prompts discovered from `tools/list`, `resources/list`, or `prompts/list`. Avoid `dynamic tools` / `dynamic registry` in new MCP design prose because those phrases imply that model-visible tool schemas may change during an active LLM run.
The intended invariant is:
```text
provider-discovered at startup / provider initialization;
registered into the ordinary ToolRegistry before model exposure;
run-stable for the duration of a model request/run;
refreshed only at a safe boundary or reported as a diagnostic.
```
### Later follow-ups
- Richer MCP task/task-support integration if ordinary tool-call fallback is insufficient.
- Streamable HTTP transport.
- OAuth / remote auth.
- Registry/package distribution.
- Explicit MCP/Plugin bridge only if separately approved; do not conflate Plugin packages with MCP local server execution.
## Success criteria / exit conditions
- A local mock MCP server can be configured explicitly and initialized.
- Discovered MCP tools appear as ordinary Yoi tools with stable namespacing.
- Tool calls go through ordinary permission and history paths.
- MCP resources/prompts are explicit operations, not hidden context injections.
- MCP result forms are bounded and safely serialized.
- Secret values, command/env details, and server diagnostics are redacted where required.
- Local server trust boundary is documented: Yoi does not sandbox the configured executable through feature authority.
- Feature, Plugin, and MCP permission/trust responsibilities are documented as separate layers.
## Decision context
- MCP is not the Plugin model; it is a protocol-backed integration layer using `pod::feature` substrate.
- `pod::feature` should provide contribution/lifecycle/runtime-discovered registration plumbing, not MCP server trust policy or Plugin package permission policy.
- MCP resources and prompts must never be hidden context injection. They are explicit operations recorded through ordinary history/tool paths.
- Provider-discovered tools are discovered at startup/provider initialization and registered before model exposure; model-visible schemas remain run-stable during a request/run.
- Local stdio server execution is a user/config trust decision. Yoi does not sandbox the local executable merely because it is configured through MCP.
+101
View File
@@ -0,0 +1,101 @@
---
title: "Plugin platform roadmap"
state: "active"
created_at: "2026-06-19T13:18:58Z"
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
Build Yoi's Plugin platform as a coherent extension system: packages are discovered and inspected safely, enabled explicitly, registered through typed Plugin surfaces, executed in a sandboxed runtime, constrained by Plugin-layer grants, and authored through SDK/templates rather than raw runtime ABI details.
The long-term platform goal is not merely to run Wasm. It is to make Plugin packages a durable, inspectable, permissioned, and authorable extension layer for Tools first, then host APIs (`https`, `fs`), and later Service / Ingress surfaces when concrete needs justify them.
## Motivation / background
The current Plugin foundation is already substantial:
- package discovery and explicit enablement resolver;
- Tool surface registration through the ordinary ToolRegistry/model-visible schema path;
- minimal sandboxed WASM Tool execution;
- Plugin permission grant enforcement;
- follow-up Tickets for read-only inspection CLI, `https`, `fs`, and Component Model migration.
The remaining work must be kept as one roadmap because the pieces constrain each other:
- Plugin authoring needs an SDK/PDK and examples, not raw pointer/length Wasm ABI hand-coding.
- `https` and `fs` host APIs must be grant-gated and shaped so they can move cleanly to typed Component Model interfaces.
- Diagnostics (`yoi plugin list/show`) are needed before the system becomes harder to debug.
- Component Model adoption should guide new host API design before a custom raw ABI becomes entrenched.
- Service / Ingress are useful for bridge-style integrations, but should come after Tool runtime, diagnostics, and host API policy are stable.
Research of common Wasm extension systems points to the same pattern: mature systems combine a package manifest, explicit capabilities, a sandbox runtime, host-provided capability APIs, language SDK/PDK bindings, templates/examples, inspection/check tooling, and versioned interfaces.
## Strategy / design direction
- Keep Plugin as a user-facing package/config/runtime layer above lower-level `pod::feature` substrate.
- `pod::feature` provides contribution/registration substrate.
- Plugin owns package discovery, enablement, grant policy, runtime selection, authoring UX, and user-facing diagnostics.
- Preserve authority boundaries.
- Package discovery is read-only inventory.
- 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 active Plugin runtime shape before public release.
- New typed Plugin host APIs should be designed in WIT-compatible terms.
- `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.
3. Minimal WASM Tool execution. Completed foundation.
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. 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 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, 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 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 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.
+287
View File
@@ -0,0 +1,287 @@
---
title: "Team workspace control plane and runtime architecture"
state: "active"
created_at: "2026-06-20T14:26:29Z"
updated_at: "2026-07-15T21:18:00Z"
linked_tickets: ["00001KVMFFYVX", "00001KWMBAA6V"]
---
## Goal
Yoi を、単一のローカル開発ディレクトリで動くエージェント実行ツールから、チームで作業・判断・実行結果を管理できるワークスペース基盤へ発展させる。
この Objective の中心は、Web から扱える管理システムを作り、その管理システムにローカル Runtime・リモート Runtime・将来のクラウド Runtime を接続できるようにすることである。管理システムは Ticket、Objective、Memory、Skill catalog、Artifact、Policy、Actor、Repository、Runtime state の正本を持つ。Runtime はその管理システムから Worker launch request / config bundle / repository target / authority を受け取り、作業環境を用意して Worker を実行し、結果・イベント・証跡を返す。
この Objective は Git ホスティングサービスを作るものではない。Git は重要な Repository provider として扱うが、Yoi の Workspace は Git Repository root と同じものにしない。Yoi が作るべきものは、コード・ドキュメント・データ・成果物などの Repository と Runtime を接続しながら、人間とエージェントの作業、Ticket lifecycle、Memory、Skill catalog、検証証跡、実行環境配置を管理するチームワークスペースである。
## Glossary
この Objective では、以下の語をこの意味で使う。
- Workspace: チームまたはプロジェクトの管理単位。Ticket、Objective、Memory、Skill catalog、Artifact、Policy、Actor、Repository、Runtime state を持つ。Git Repository root ではない。
- Control plane: Workspace の正本を持ち、Web UI / API / CLI から操作される管理システム。
- Runtime: Worker 群を束ねる実行基盤。Worker lifecycle、sandbox、mount、cache、checkout/worktree/container filesystem などの working directory materialization、event/control plane を管理する。将来的には 1 つの Runtime が複数 Workspace / Repository の Worker を抱えられる。
- Worker: Runtime が管理する 1 つの agent/session/process。Runtime が用意した working directory と authority の中で動く。
- Repository: Workspace に接続される source/storage。コード、ドキュメント、local directory、object storage、artifact store、dataset などを含む。Git Repository も Repository の一種であり、基本的には filesystem path ではなく URI / URL で識別する。
- RepositoryId: Workspace 内でどの Repository を対象にするかを指す安定 identifier。Git hash、branch、path ではない。
- Repository provider: Repository の種類ごとの実装。Git、local filesystem、object store、artifact store、将来の non-Git VCS など。
- RepositorySelector: Repository provider に渡す未解決の地点指定。branch/tag/PR/revspec/bookmark/revset/path@revision/object version/latest など provider-specific な symbolic / mutable / query-like locator であり、それ自体は再現性の authority ではない。
- RepositoryPoint: RepositorySelector をある時点で解決した具体地点。Git commit/tree、Mercurial changeset、SVN revision、object store version/manifest digest、file snapshot など provider ごとの immutable / reproducible point を表し、Artifact/evidence に残す。
- working directory: Runtime が Worker のために作る作業環境。1 つ以上の RepositoryPoint から materialize される作業用ディレクトリ、container filesystem、sandbox mount の集合であり、Git worktree、clone、sparse checkout などはこれを作る手段である。Browser-facing UI/API では product `Workspace` と混同しないよう、この呼称に寄せる。`Volume` は storage backing の候補名に留め、作業領域そのものの呼称にはしない。
- Ticket: チームで扱う作業単位。目的、要件、判断、議論、完了条件、関係、証跡を持つ。
- Objective: 複数の Ticket を束ねる長期目標や設計方針。
- Artifact: Ticket や Worker 実行に紐づく成果物や証跡。diff、log、validation result、review result、report など。
- Memory: エージェントやユーザーが再利用するための要約された文脈。Ticket や Artifact の正本ではない。
- Skill catalog: `.yoi/skills` / builtin skills から Workspace backend が解決する procedural guidance catalog。外部状態 authority は持たず、Ticket / Worker / workdir などの操作は typed feature/tool surface が担う。
- Actor: 人間、エージェント、システム、外部サービスなど、Workspace 上で操作や発言を行う主体。
## Motivation / background
現在の Yoi は、ローカルの `.yoi` ディレクトリ、ローカルプロセス、Ticket ファイル、ワークツリー運用によって、自分自身の開発に使えるエージェント実行環境になっている。しかし、チーム利用、Web UI、リモート実行、クラウド実行、最終的な SaaS 提供を考えると、次の前提を変える必要がある。
- Workspace を Git Repository root と同一視しない。
- ローカル filesystem 上の `.yoi` を、長期的なチーム用正本 store にしない。
- Ticket をローカル作業メモではなく、チームの作業調整 record にする。
- 実行証跡は Ticket thread、Artifact、WorkerRef snapshot、Runtime event として扱い、独立した実行単位概念を先に増やさない。
- 管理システムと Runtime を分ける。
- まず Web から Ticket、Objective、Memory、Skill catalog、Artifact、Runtime / Worker state を見られるようにする。
- 最初はローカル Runtime を使い、後でリモート Runtime、クラウド Runtime、runtime pool、resource allocation、quota、billing、sandboxing に拡張する。
- Git ホスティング機能を取り込むのではなく、Git Repository / worktree / clone は Repository provider と working directory materialization の手段として扱う。
OSS として Control plane、Runtime、Web frontend、protocol を公開しつつ、managed service では hosted control plane、runtime fleet、リソース柔軟性、team auth、backup、audit、availability、multi-tenant operations で価値を出す。
## Strategy / design direction
### 1. Control plane を先に作る
Team Workspace の正本は server-side control plane に置く。`.yoi` は local backend、single-user/self-hosted compatibility、offline/export/import、local projection、migration bridge として残せるが、multi-user SaaS の正本とはみなさない。
Control plane は Ticket、Objective、Memory、Skill catalog、Artifact、Actor、Permission、Audit、Repository、Runtime / Worker state を管理する。Web UI、CLI、TUI、将来の desktop client は、この Control plane を操作する client であり、別の正本 store を持たない。
### 2. Workspace と Repository を同一視しない
Workspace はチームまたはプロジェクトの作業管理単位である。Repository は Workspace に接続される source/storage である。Git Repository は Repository の一種にすぎない。
1 つの Workspace は複数の Repository を持てる。Repository は filesystem path ではなく URI / URL で識別する。例として `git+https://...``file://...``s3://...``artifact://...`、将来の VCS provider URI などを扱えるようにする。
Ticket と Objective は Repository 配下に置かず、Workspace 配下に平たく持つ。Ticket は必要に応じて対象 RepositoryId、RepositorySelector、path scope、必要 capability を持つ。Objective は複数 Ticket にまたがる target default / scope hint を持てるが、Repository の所有物にはしない。
RepositorySelector は Git branch/tag の抽象化ではない。Selector は provider-specific な未解決 locator であり、Git provider なら branch/tag/ref/revspec/PR/commit、Mercurial provider なら bookmark/revset/changeset、SVN provider なら path/revision、object store provider なら prefix/version/latest などを解釈する。実行時には Control plane または Repository provider が Selector を RepositoryPoint に解決し、Runtime はその RepositoryPoint を materialize する。
Worker launch request は Ticket の target selector を concrete RepositoryPoint に解決し、その RepositoryPoint から Runtime が working directory を materialize する。Git worktree 相当の機能は、この working directory を作るための実装戦略として扱う。
Backend は cwd や `--workspace` を暗黙の Repository として扱わない。`--workspace` は当面 workspace config root / local descriptor root を指すだけであり、Repository registry は明示設定された Workspace config から構築する。短期的には `.yoi/workspace-backend.local.toml``[[repositories]]` を local descriptor として使い、`uri = "."` のような local repository も明示 entry として登録する。`./` を暗黙 Repository として自動採用しない。
`.yoi` は現在の local backend / fs-store / compatibility surface として残るが、long-term Backend store ではない。将来的には `~/.yoi` 側に Backend store と Workspace registry を置き、1 Backend process が複数 Workspace を扱える形へ移行する。`.yoi/workspace-backend.local.toml` はその移行までの workspace-local descriptor / override surface として扱う。
短期的には Git を主な Repository provider とする。ただし Yoi の authority model を Git object、Git branch、Git Repository root、worktree path に固定しない。Orchestration は Git そのものではなく、`resolve_ref``materialize``diff``patch``commit``merge` などの Repository capability に依存する。
### 3. Ticket を team coordination record にする
Ticket は実行そのものではない。Ticket は「何を、なぜ、どの条件で完了とみなすか」を持つ。Ticket は Workspace に平たく所属し、Repository には所属しない。コードやドキュメントを対象にする Ticket は、対象 Repository / ref selector / path / intent を target として持つ。
Ticket target は intent/selector であり、実行再現性のための immutable point ではない。Worker launch request が target selector を concrete RepositoryPoint に解決し、Runtime が実際にどの revision/snapshot を materialize したかを Artifact / evidence として記録する。
```text
Ticket
-> target selectors: Repository + ref selector + path + intent
-> resolved RepositoryPoint
-> working directory
-> WorkerRef / Artifact / Evidence
-> Review / Decision
-> Audit / Notification
```
Target 例:
```text
Ticket targets:
- repository: main-code
role: primary
ref: develop
paths: ["crates/pod/"]
intent: change
- repository: docs
role: related
ref: main
paths: ["docs/development/"]
intent: read
Worker launch materialization:
- repository: main-code
requested_ref: develop
resolved_point: git commit abc123
mount: /workspace/main-code
```
Ticket には次の概念が必要になる。
- Actor identity: human / agent / system / service account.
- Assignment / owner / reviewer / watcher.
- Typed thread events: comment, decision, plan, review, implementation report, state transition.
- Linked Objective / Artifact / WorkerRef / Repository / RepositoryPoint / working directory.
- Permission / visibility.
- Audit trail.
- Notification / mention.
- Board / queue / planning / review / done / archived views.
- Conflict handling and concurrent editing policy.
### 4. Memory / Skill catalog の本格再設計は後回しにする
Memory は Ticket / Artifact のコピーではない。再利用可能な文脈、方針、学習された制約を扱うが、Ticket や Artifact の authority を置き換えない。Skill catalog は procedural guidance の catalog であり、外部状態 authority を持たない。Knowledge record kind は削除方針なので、この Objective では separate Knowledge storage を新しい control plane entity として増やさない。
理由は、Memory と Skill catalog の正しい設計が Workspace control plane の record model、Actor / visibility / permission、Ticket、Artifact / evidence、RepositoryPoint、Runtime に渡す context の監査方法に依存するためである。これらが固まる前に Memory schema や Skill API だけを作ると、local `.yoi` 前提や現行 agent runtime 前提に引っ張られ、後で再設計が必要になる。
この Objective では、Memory / Skill catalog について以下の platform contract だけを維持する。
- Memory は Control plane が扱う record だが、Ticket / Artifact の authority を置き換えない。
- Skill catalog は Workspace backend が扱う prompt/resource catalog だが、Ticket / Worker / workdir / queue の authority を持たない。
- 将来、Memory と Skill catalog の canonical storage / API は Workspace control plane 側に置く。
- local `.yoi` memory と `.yoi/skills` は compatibility、offline/export/import、local projection、migration bridge として扱う。
- Personal Memory、Workspace Memory、Worker Summary、Skill catalog は分離が必要である。
- Generated Memory には provenance、visibility、approval、audit が必要である。
- Runtime / Worker に渡した Memory / Skill context は、将来 ContextPack などとして Artifact/evidence に記録できる必要がある。
本格的な Memory 再設計は、Memory の保存先を Workspace backend / control plane record に移すタイミングで回収する。それまでは低リスクな観察、問題例の収集、既存 local memory の互換維持に留める。
### 5. Control plane / Runtime を分離する
Control plane は正本と調整を持つ。Runtime は Worker 群と実行基盤を管理する。初期実装では local backend と runtime process が同じマシン上にあり、役割が近く見えるが、設計上は分ける。
初期形:
```text
Web UI / Control Plane
-> Runtime registry / local backend
-> Runtime process
-> Workers
-> Existing Yoi tools, working copy, build/test commands
```
この段階では、現在ローカル管理画面が行っている Ticket 選択、エージェント起動、レビュー起動、作業用 checkout 作成、検証実行、結果表示を、Web/control plane から local Runtime に対して実行できるようにする。
長期的には Runtime が作業環境の用意まで請け負う。Runtime は Worker launch request / config bundle / repository target / authority を受け取り、必要な checkout、worktree、container filesystem、sandbox mount、cache、secret boundary を準備して Worker を起動する。Runtime 起動時に特定 Workspace path を必須にする形は暫定であり、Workspace / Repository 情報は Runtime process 起動引数ではなく Worker launch request 側の入力に寄せる。
Sandbox と authority 分離が成立している前提では、1 つの Runtime が複数 Workspace / Repository の Worker を抱えられる。したがって Runtime identity は Git repository root や single workspace directory と同一視しない。Runtime は execution substrate、Workspace は作業管理 record の正本として扱う。
Worker の作業環境を用意する経路は次のようにまとめる。
```text
Ticket / user intent
-> RepositoryId + RepositorySelector + path scope + required authority
-> resolved RepositoryPoint
-> WorkerLaunchRequest / ConfigBundle / AuthorityBundle
-> Runtime WorkingDirectoryMaterializer
-> working directory allocation
-> Worker process
-> WorkerRef + Artifact/evidence
```
Control plane は Workspace authority、Ticket target、Repository registry、Actor permission、設定 bundle の正本を持つ。Control plane または Repository provider は RepositorySelector を RepositoryPoint に解決し、どの地点を対象にしたかを evidence に残す。Runtime は RepositoryPoint、materialization policy、sandbox policy、mount/cache/secret policy、Worker config を受け取り、Runtime-local な working directory を確保して Worker を起動する。
この境界では、Worker は host filesystem path や Repository credential を自分で発見しない。Worker は Runtime が materialize した working directory root、mount、環境変数、tool authority、config bundle だけを見る。Runtime は working directory の lifecycle、cleanup、cache reuse、namespace、quota、sandbox boundary、event collection を管理する。Control plane / Browser-facing API は raw host path、secret、socket、internal runtime path を authority-bearing internals として扱い、必要な evidence だけを Artifact として公開する。
v0 materializer は existing local root を明示的な working directory として返してよい。ただし型と呼び出し順序は、後で Git worktree、clone、sparse checkout、container filesystem、remote object snapshot、multi-repository mount に置き換えられる形にする。Runtime process 起動時の `--workspace` はこの v0 materializer の legacy bootstrap input であり、Runtime identity や long-term workspace binding ではない。
その後で、remote Runtime、self-hosted Runtime、hosted cloud runtime fleet、runtime pool、resource allocation、quota、billing、sandbox、network policy、secret distribution を追加する。
```text
Phase 1: Web control plane + local Runtime
Phase 2: Remote/self-hosted Runtime
Phase 3: Hosted cloud runtime fleet
Phase 4: Resource allocation / scheduling / quotas / billing / isolation
```
### 6. Web frontend を先に作る
Desktop app は対応コストが高いので、まず Web frontend を primary UI とする。
- Web: チームで使う主要 UI。
- CLI: automation、scripting、local operations。
- TUI/local panel: fallback、dogfooding surface。
- Future desktop: Web/control-plane model が安定した後に検討する optional client。
Web UI は Ticket、Objective、Memory、Skill catalog、Runtime、Worker、Artifact を扱う。UI の都合で正本を二重化しない。
### 7. 多重起動コストと runtime placement を見直す
Cloud/remote execution を成立させるには、多数のエージェント実行を安く管理できる必要がある。logical Worker session と Runtime process/resource placement を分ける。Runtime は Git Repository root や Workspace path に固定されず、request ごとに必要な working directory を materialize できる実行基盤として扱う。
初期 Workspace DB では、Worker を canonical table として永続化しない。Runtime / Worker 一覧は backend-local runtime inspection や将来の Runtime protocol から逐次取得する live view とし、Ticket に関わった Worker は Ticket thread events と WorkerRef snapshot / TicketWorkerLink として記録する。
Worker の一元管理、データ永続化、アーカイブは将来的には必要になる。これは Runtime protocol、remote/self-hosted/hosted runtime lifecycle、worker identity、retention policy、audit requirements が固まった後に、dedicated Worker registry / archive model として追加する。v0 で Pod metadata の代替として Worker table を作らない。
検討対象:
- Worker identity と Runtime process/resource placement の分離。
- 1 Runtime が複数 Workspace / Repository の Worker を抱える場合の namespace、quota、cleanup、audit boundary。
- Runtime-side working directory materialization、sandbox、mount、checkout/worktree/container filesystem の責務。
- Provider client、tool registry、resource cache の共有可能性。
- Prompt/resource/profile/config bundle resolution cache。
- Model call multiplexing and scheduling。
- Tool execution sandbox reuse。
- Plugin instance / Service runtime との統合。
- Session/event stream と runtime lifecycle の分離。
- Runtime-local cache、checkout reuse、build cache、dependency cache。
## Initial phases / candidate tickets
1. **Vocabulary / architecture record**
- Workspace / RepositoryId / RepositorySelector / RepositoryPoint / working directory / Runtime / Worker / Control Plane / Ticket / Memory の用語と境界を固める。
2. **Team-space canonical data model**
- Ticket / Objective / Target / Artifact / Actor / Permission / Audit / Memory の entity/event model を設計する。
3. **Ticket evidence model**
- Ticket lifecycle、WorkerRef、Artifact、validation evidence、review evidence、Ticket thread の責務を明確化する。
4. **Memory storage migration boundary**
- Memory の本格再設計は後回しにし、まずは Workspace backend に移す時の platform contract、compatibility/cache/export 方針、将来の provenance / visibility / approval 要件だけを固定する。
5. **Control plane backend architecture**
- local `.yoi` backend と server-side canonical backend の境界、migration/export/import、compatibility mode を設計する。
6. **Web control plane MVP design**
- read-only Ticket / Objective / Memory / Runtime / Worker state UI/API の範囲を決める。
7. **Local Runtime protocol design**
- Web/control plane から local Runtime に安全な操作を送り、Runtime が Worker lifecycle と working directory materialization を担う protocol と authority boundary を設計する。
8. **Repository and working directory materialization model**
- Repository URI、Repository provider capability、RepositorySelector resolution、RepositoryPoint evidence、Git worktree / clone / sparse checkout / future source backend を Runtime-side materialization strategy として抽象化する。
9. **Remote/hosted runtime foundation**
- runtime registration, heartbeat, capability advertisement, job assignment, logs/events, secrets, sandbox/resource policy を設計する。
## Non-goals
- Git hosting service を作ること。
- `.yoi` filesystem をそのまま SaaS canonical store にすること。
- 最初から full hosted cloud execution を作ること。
- local execution / CLI / TUI / local panel を捨てること。
- Ticket を単なる issue tracker clone にすること。
- Memory を Ticket/Artifact audit log の代替にすること。
- Web UI のために core authority を二重化すること。
- hidden server state を LLM context に直接注入すること。
- multi-tenant auth/billing/secret/security を shortcut して実装すること。
## Success criteria / exit conditions
- Workspace / RepositoryId / RepositorySelector / RepositoryPoint / working directory / Runtime / Worker / Control Plane / Ticket / Memory の境界が文書化されている。
- Ticket が team coordination record として、target selector / Artifact / Actor / Permission / Audit と分離された model を持つ。
- `.yoi` local backend は compatibility/local backend として整理され、server-side canonical backend の設計を阻害しない。
- Web UI/API が Ticket / Objective / Runtime / Worker state を中心とした read-only view を提供できる設計または MVP を持つ。Memory は既存 record の表示または将来 placeholder に留め、本格再設計をこの段階の必須条件にしない。
- Control plane から local Runtime に対して、現在のローカル管理画面相当の安全な操作を実行できる design/protocol がある。
- Runtime は single Workspace / Git repository root 専用 process ではなく、sandbox/authority が成立すれば複数 Workspace / Repository の Worker を抱えられる execution substrate として設計されている。
- Git Repository root に依存しない Workspace model があり、Git Repository は Repository provider の一種として扱われている。
- Ticket と Objective は Workspace 配下に平たく存在し、Repository への所属ではなく RepositoryId / RepositorySelector / path scope / intent で対象を表現する。
- Git worktree 相当は working directory materialization strategy として扱われ、Artifact/evidence が concrete RepositoryPoint を記録する。
- Memory は Ticket / Artifact の authority を置き換えない record として platform contract だけを持つ。本格的な意味論・抽出・承認・検索・staleness 処理は、Memory の保存先を Workspace backend / control plane record に移すタイミングで回収する。
- Hosted Runtime / resource allocation / SaaS offering に進むための後続 Ticket が切れる状態になっている。
- 既存 local dogfooding runtime を壊さず、local use と remote-capable architecture が両立している。
## Decision context
- Yoi は hosted Git tool ではなく、team workspace control plane + Runtime execution environment として設計する。
- Team-space の長期 canonical authority は server-side control plane に置く。local `.yoi` は互換/local/offline/export/import surface だが、multi-user SaaS の正本ではない。
- 実行環境と管理システムは弱結合にする。まず管理システムを独立させ、local Runtime を実行環境として接続する。その後に remote/self-hosted/hosted runtime fleet へ進む。
- Runtime は Worker 群を束ねる実行基盤であり、将来的には作業環境の用意、sandbox、mount、checkout/worktree/container filesystem、cache、secret boundary を Worker launch request ごとに準備する。Runtime process は single Workspace / Git repository root 専用に固定しない。RepositorySelector は provider-specific な未解決 locator、RepositoryPoint は解決済み evidence として扱う。
- 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 配下に平たく持つ。対象コードベースや地点指定は RepositoryId / RepositorySelector / path scope / intent として表現し、Worker launch materialization が concrete RepositoryPoint に解決する。
- Backend Repository は cwd inspection ではなく、Workspace config の明示 Repository registry から構築する。`--workspace` は Repository ではなく workspace config root / local descriptor root を指す。
- `./.yoi` は local descriptor / fs-store / compatibility surface であり、将来の Backend canonical store と Workspace registry は `~/.yoi` 側へ寄せる。
- Memory の本格再設計は後回しにする。先に Workspace / Ticket / Repository / Runtime/Worker live view / Control plane の基盤を固め、Memory の保存先を Workspace backend に移すタイミングで、意味論・抽出・承認・検索・staleness 処理をまとめて回収する。
- Worker の一元管理・データ永続化・アーカイブも後続設計に回す。初期 DB では Worker を Pod metadata の代替として永続化せず、live view と Ticket-linked WorkerRef 記録に留める。
+289
View File
@@ -0,0 +1,289 @@
---
title: "効果的な Memory システム設計・検証"
state: "active"
created_at: "2026-06-20T15:16:00Z"
updated_at: "2026-07-17T23:10:00Z"
linked_tickets: ["00001KSKBPHRG", "00001KT02TCCG", "00001KTGCAFXG", "00001KSKBPTHR", "00001KXMEZNYC", "00001KXMK7YMC", "00001KXNYXNM6", "00001KXRM6G0G", "00001KXS56AS5", "00001KXMK846H"]
---
## Goal
Yoi の Memory / Knowledge / Skills / generated context / resident context / retrieval / usage metrics を、実際の開発・設計・レビュー・オーケストレーションに効く sensemaking substrate として再設計・検証する。Memory は短期・変化前提の context、Knowledge は育てる long-term note、Skill は移植可能な workflow として分け、この Objective ではそれらと authority record / docs / typed tools の境界を再整理する。
この Objective でいう「効果的な Memory システム」は、単に多く保存する仕組みではなく、作業中の問いに対して relevant material を集め、根拠を検証可能にし、再表現・仮説形成・反証探索・意思決定・成果物への反映を低コストにする仕組みである。
暫定的な定義:
- foraging cost を下げる: Ticket / Objective / current question に対して、関連する memory / docs / tickets / session evidence / code references を探しやすい。
- evidence を失わない: Memory が authority そのものにならず、Ticket / docs / git history / session logs / user instruction への検証可能な入口になる。
- schema 化を支援する: raw summary ではなく、subsystem、invariant、risk、authority boundary、open question、rejected alternative、hypothesis など推論しやすい形へ再表現できる。
- hypothesis loop を支援する: 支持証拠だけでなく、代替仮説・棄却理由・反証 evidence・stale assumption を扱える。
- product に戻る: Memory に保存して終わりではなく、Ticket、review、docs、implementation、decision、report に影響を戻せる。
- stale / contradiction を扱う: 古い前提、矛盾、適用範囲外の memory を検出・降格・更新できる。
- usage を成果基準で測る: resident exposure や read count ではなく、判断・レビュー・実装・docs に効いたかを観測できる。
## Motivation / background
現在の Memory システムは「墓場化」している。保存された情報はあるが、後続の作業で自然に使われにくく、使われたとしても根拠・適用範囲・鮮度・反証可能性が弱い。結果として Memory は、作業場ではなく古い結論の倉庫になりやすい。
Pirolli & Card 2005 の sensemaking model では、分析作業は単なる保存ではなく、次の変換として捉えられる。
```text
external data sources
-> shoebox
-> evidence file
-> schema / representation
-> hypotheses
-> presentation / product
```
Yoi の現行 Memory は、この流れのうち「保存」と「一部の検索」には対応しているが、少なくとも以下が弱い。
- Ticket / task / question ごとの shoebox がない。
- shoebox から evidence snippets を切り出し、source / provenance / applicability / confidence と共に扱う evidence file がない。
- `summary`, `decision`, `request` は durable memory storage taxonomy であり、sensemaking 用 schema としては粗い。Knowledge は古い record kind をそのまま残すのではなく、育てる long-term note subsystem として再設計する。再利用可能な手順は Skill、保守された設計資料は Knowledge / docs / Ticket decisions に寄せる。
- decision は残るが、hypothesis space、alternative、rejected reason、disconfirming evidence が残りにくい。
- reviewer / orchestrator が confirmation bias を避けるための反証探索導線が弱い。関連する手順誘導は旧 Workflow ではなく Skill と role prompt / typed tools へ寄せる。
- resident exposure と explicit retrieval は観測できても、Memory が product に効いたかは測りにくい。
この Objective は、Memory 関連の設計・検証・検討・考察を一元化し、個別 Ticket がばらばらに storage、prompt、retrieval、metrics を改善して再び墓場を増やすことを防ぐための判断背景である。
## Strategy / design direction
Memory を「長期保存領域」ではなく、Yoi の multi-agent 開発における sensemaking loop の支援機構として設計する。
### 1. Pirolli & Card の stage に合わせて責務を分ける
- external data sources: Tickets、docs、git history、session logs、reports、code、user instructions。
- shoebox: 特定 Ticket / Objective / design question に対して関連しそうな材料を集めた task-bound working set。
- evidence file: shoebox から抜き出した根拠 snippet。source anchor、支持/反証、適用範囲、confidence、staleness を持つ。
- schema / representation: subsystem、invariant、risk、authority boundary、open question、hypothesis、alternative、contradiction など、推論しやすい再表現。
- hypotheses: 採用前の設計仮説、代替案、棄却条件、反証 evidence。
- product: Ticket、review、docs、implementation、decision、report、orchestration plan などの成果物。
### 2. 最初の重点は task-bound shoebox と evidence file
Memory 墓場化の最初の原因は、保存情報が現在の問いに集まらないことである。まずは Orchestrator / Intake / Reviewer が Ticket を扱う時に、関連 memory / docs / tickets / reports / prior decisions を shoebox として束ねる導線を作る。
この段階では大きな永続 schema 追加に飛びつかず、report / Ticket artifact / bounded generated context として検証してよい。
### 3. Session Overview を extract の足場にする
現在の extract は、tool call / tool result summary を含む flat slice から意味を復元しようとして断片化しやすい。改善方針は、main Worker が通常 Assistant Message として Progress message を残し、user messages + Assistant messages を Session Overview として先に読む形にする。
- Progress message は専用 Tool ではなく通常 Message とし、ユーザーへの進捗報告と extract 用 semantic summary を兼ねる。
- extract worker には専用の read-only evidence tools を渡し、Overview で重要そうに見えた箇所だけ session range / tool summaries / source anchors を探索させる。
- extract worker は Memory / Knowledge / Skill を直接更新しない。output は必ず staging を挟み、source / provenance を host 側で機械的に保持する。
- trigger は初期実装では現行通り Worker run cycle 完了後の threshold 判定にする。LLM call 単位や Run 中の Overview accumulation trigger は含めない。
### 4. Memory を authority にしない
Memory は Ticket、docs、git history、session logs、user instruction の代替ではない。Memory は authority record への evidence index / schema / reasoning aid として扱う。
したがって、改善案は次の性質を持つべきである。
- source / provenance を辿れる。
- stale / superseded / contradicted を扱える。
- Memory の断定をそのまま authority として使わない。
- Ticket body/thread/artifacts を読まずに Objective や Memory だけで実装判断できる状態を作らない。
### 5. 反証探索を first-class にする
より効果的な Memory は、過去方針を思い出すだけでなく、現在案を疑うために使える必要がある。
Reviewer / Orchestrator / Intake の導線では、次を探せるようにする。
- supporting evidence
- contradicting evidence
- stale decisions
- rejected alternatives
- unresolved questions
- authority boundary risks
- prior failures / reports
### 6. Metrics は exposure から product impact へ寄せる
Memory が prompt に入った、または query されたことは成功ではない。評価は次を区別する。
- resident exposure
- explicit retrieval
- cited in response
- cited in Ticket / review / report
- changed requirement
- changed implementation
- contradicted / invalidated
- led to docs or decision update
### 7. 後続 Ticket は concrete slice に分割する
この Objective は中期的な設計・検証の一元化 record であり、umbrella Ticket ではない。実装や調査は、単独で実装・レビュー・close できる concrete Ticket に分割する。
候補 slice:
- Memory sensemaking 分析 report を `docs/report/` に作る。
- Ticket routing 用 Memory shoebox artifact を試作する。
- evidence snippet schema / source resolver を設計する。
- hypothesis / rejected alternative / disconfirming evidence の表現を追加する。
- Reviewer Skill / review process に反証探索を入れる。
- Memory usage metrics を product impact oriented に拡張する。
- stale / contradiction / renewal の検出・表示を設計する。
- turn 中の Progress message を通常 Assistant Message として残す prompt/guidance を追加する (`00001KXMEZNYC`)。
- Session Overview + Evidence index を使う extract input を設計・実装する。
- extract worker 専用の read-only evidence search/read/source-anchor tools を設計する。
- extract output を staging に限定し、source range と output entry を結びつける schema を設計する。
## Success criteria / exit conditions
- Memory システムの目的が「保存」ではなく「sensemaking loop 支援」として project records / docs / prompts / Skills で一貫して説明されている。
- Pirolli & Card の `shoebox -> evidence file -> schema -> hypotheses -> product` に対応する Yoi 内の責務と非責務が整理されている。
- Ticket / Objective / docs / session logs / Memory / Skills の authority boundary が明確で、Memory が authority を僭称せず、Skill は手順資源として外部状態 authority を持たない。
- 少なくとも一つの実作業 routing / review / design analysis で、task-bound shoebox または evidence file が生成・利用され、作業品質にどう効いたかが確認されている。
- Memory records または関連 artifacts が source / provenance / applicability / staleness / supports-or-refutes のいずれかを扱えるようになっている。
- extract が User / Assistant messages 由来の Session Overview を primary input とし、tool logs を evidence として探索できる設計になっている。
- extract worker 専用の read-only evidence tools が設計され、main Worker の tool surface を増やさない方針になっている。
- extract output は direct Memory / Knowledge / Skill write ではなく staging を挟む方針になっている。
- Reviewer / Orchestrator が supporting evidence だけでなく、contradicting evidence / stale assumptions / rejected alternatives を探す導線を持っている。
- Memory usage metrics が resident exposure と product impact を区別している。
- 古い Memory が放置されるのではなく、stale / superseded / contradicted / needs-review として扱える方針がある。
- 後続の実装 Ticket が concrete slice として分割され、Objective が Ticket dependency や進捗 container として使われていない。
この Objective は、Memory が少なくとも一つの中規模設計・実装・レビュー作業で「関連情報を見つける」「根拠を確認する」「代替案/反証を検討する」「成果物へ反映する」流れを実証し、その設計方針が docs / Skills / metrics に反映された時点で `done` を検討できる。
## Decision context
- ユーザー指摘: 「Memoryシステムが完全に墓場化している」。これは保存量不足ではなく、保存情報が現在の問い・根拠・仮説・成果物に接続されない問題として扱う。
- ユーザー指示: Memory システムの設計・検証・検討・考察を Objective にまとめ、より効果的な Memory システムを作成する目標のもとで情報を一元化する。
- 「効果的」の定義は未確定だが、当面は Pirolli & Card の sensemaking process に沿って、foraging cost、evidence quality、schema usefulness、hypothesis/disconfirmation support、product impact、staleness handling を評価軸にする。
- Memory は durable project authority ではない。Ticket、docs、git history、session logs、明示 user instruction の代替として使わない。
- Objective context は判断背景であり、個別実装の authority は各 Ticket body/thread/artifacts と明示的な Ticket relations / OrchestrationPlan records にある。
- `history` に残らない context-only injection を改善案にしない。新しい context input は history に commit する原則を守る。
- Knowledge は古い unused record kind をそのまま残すのではなく、育てる long-term Markdown note subsystem として再設計する。再利用可能な手順・作法は Agent Skills (`.yoi/skills/<skill>/SKILL.md`) へ、durable policy/rationale は Knowledge / maintained docs / Ticket decisions へ、外部状態 authority は typed feature/tool surface へ分ける。
- Generated memory / Ticket / docs / report / Skill の境界を再定義する場合は、authority boundary と migration/staleness を明示する。
- 関連する既存 Ticket:
- `00001KSKBPHRG` — Prompt / Workflow 評価メトリクスと改善 Offer
- `00001KT02TCCG` — Memory prompt: conditional guidance and proactive lookup
- `00001KTGCAFXG` — Use .yoi/memory marker for repo-local memory root
- `00001KSKBPTHR` — ワークスペースのメモリーをLintするヘッドレスCLI
- `00001KXMEZNYC` — ターン中のProgress messageを残す指示を追加する
## Historical references / prior design sources
現在の Memory システムの初期設計時には、Codex Memories / Chronicle と HermesAgent を明示的な参考事例として調査していた。関連する調査・設計記録は、現在は主に以下に退避されている。
- `docs/.local/old-docs/ref/memory-systems.md`
- `docs/.local/old-docs/plan/memory.md`
- 初期設計 commit: `ca5a3d11``2026-04-21 メモリシステムの設計`
- 関連 commit:
- `0c1276b7``Memoryシステムの整理・Promptカタログチケット`
- `3d04f793``memoryを抽出する仕組みの実装`
- `f1b7af62``docs: memoryシステムの仕様変更と、動的Tool・VCSの話`
- `a2aecbf0``update: memoryシステムの"Phase"表記を撤廃`
### Codex Memories / Chronicle から得た設計要素
旧設計では、Codex Memories / Chronicle を `extract -> staging -> consolidation -> durable Markdown memory` の非同期パイプラインとして捉えていた。
主な参照点:
- extract と consolidation の 2 段構成。
- extract は JSON schema / structured output で分類ブレを抑える。
- consolidation は reasoning model / agentic rewrite によって、既存 memory と staging entries を統合・整理する。
- staging と durable memory を分ける。
- `MEMORY.md` は retrieval-oriented handbook として扱う。
- `memory_summary.md` は prompt-loaded high-signal context として扱う。
- `raw_memories.md` は routing layer / task inventory 的な中間層として扱う。
- workspace diff や usage 情報を使い、stale / deleted evidence / noisy entries を整理する。
- consolidation は append だけでなく、rewrite / merge / split / trim / drop / cleanup を担う。
Yoi 初期設計では、これを参考に以下を意図していた。
- activity token 閾値で extract を発火する。
- compact より前に session log range を抽出する。
- extract は `decisions`, `discussions`, `attempts`, `requests` などの候補を staging に保存する。
- 抽出時点では durable policy / Skill / docs へ早期分類せず、純粋な「起きたこと」に寄せる。
- consolidation が summary / decisions / requests と、必要に応じた docs / Skill / Ticket decision 更新候補を整理する。
- consolidation 入力に linter warnings / usage metrics / stale cleanup 候補を含める。
- stale / superseded / unused / noisy な情報を整理する。
この Objective での再解釈:
- Codex の `raw_memories.md` は、Pirolli & Card の sensemaking model では `shoebox` または `evidence file` に近い。
- Yoi は extract / consolidation という pipeline だけを継承しても不十分であり、task-bound shoebox / evidence file / hypothesis loop / product feedback がなければ Memory は再び墓場化する。
- 特に、staging を consolidation の一時入力としてだけ扱うと、後続 Ticket / Objective / review が使う探索入口にならない。
- Yoi では `raw memories` 相当の中間層を、現在の問いに紐づく working set / evidence index として再設計する必要がある。
### HermesAgent から得た設計要素
旧設計では、Nous Research HermesAgent を 3 層の memory system として整理していた。
- Persistent Memory:
- `MEMORY.md` / `USER.md`
- Markdown + SQLite / FTS5 session search
- 起動時 system prompt snapshot
- bounded character limits
- Skill Library:
- procedural memory
- `~/.hermes/skills/<name>/SKILL.md`
- `skill_manage` tool による agentic CRUD
- User Model / Honcho:
- dialectic user modeling
- 外部 service 連携
HermesAgent で特に重要だった点:
- memory / skill review は一定 turn / tool iteration ごとに background agent として起動する。
- 保存すべきものがなければ `Nothing to save.` で NOP として終了する。
- Yoi extract の「空配列許容」はこの設計からも影響を受けている。
- memory は session start 時の frozen snapshot として system prompt に入り、mid-session write で prompt cache を壊さない。
- persistent memory は bounded で、limit 超過時は deterministic eviction ではなく、agent に replace / remove を促す。
- procedural memory / skills は一般 memory から分離されている。
- SQLite FTS5 + LLM summarization による cross-session recall がある。
この Objective での再解釈:
- HermesAgent の `MEMORY.md` / `USER.md` / `skills` の分離は、Yoi の Memory / Knowledge / Skills / prompt resources / docs / Ticket decision / generated memory の責務再整理に使える。
- Yoi は foreground isolation 自体をすでに持つため、取り入れるべきなのは isolation そのものではなく、Overview を足場にした maintenance / extraction の質改善である。
- main Worker が通常 Assistant Message として残す Progress message は、人間向け進捗報告と machine-readable session overview を兼ねられる。
- extract worker は専用 read-only evidence tools で必要箇所だけ探索し、direct write ではなく staging に出力する。
- reusable procedure, reviewer focus, orchestration tactic, project preference, user preference, design invariant を同じ Memory bucket に入れると墓場化しやすい。
- `Nothing to save.` / empty extraction allowed は重要だが、保存抑制だけでは効果的な Memory にはならない。保存されたものが task-bound shoebox / evidence / schema / hypothesis / product に接続される必要がある。
- frozen snapshot / prompt cache 配慮は Yoi の history/context 加工原則と整合するが、それだけでは retrieval / resurfacing / disconfirmation は解決しない。
### Lessons for the next design iteration
Codex と HermesAgent の調査から、Yoi が継承すべきものと、継承するだけでは足りないものを分ける。
継承すべきもの:
- structured extract と agentic consolidation の分離。
- staging / raw memories / durable memory の分離。
- 保存対象がなければ NOP にする発火設計。
- prompt-loaded summary と durable retrieval-oriented memory の分離。
- stale / noisy / unused entries の cleanup。
- procedural memory と declarative memory の分離。
- session search / usage metrics / linter feedback を consolidation に入れる設計。
- user / Assistant messages から作る Session Overview を semantic guide にし、tool logs を evidence として探索する設計。
足りないもの:
- Pirolli & Card の sensemaking stage における各 record の役割定義。
- Ticket / Objective / current question に紐づく task-bound shoebox。
- authority record へ戻れる evidence file / provenance / source anchor。
- hypothesis, alternative hypothesis, rejected reason, disconfirming evidence の first-class 表現。
- reviewer / orchestrator が confirmation bias を避けるための反証探索導線。
- resident exposure や read count ではなく product impact を測る metrics。
- stale / contradiction / renewal を作業中に resurfacing する導線。
したがって、次の Memory 設計は Codex / HermesAgent の単純なコピーではなく、以下を満たす必要がある。
```text
external data / sessions / tickets / docs / code
-> task-bound shoebox
-> evidence file with provenance
-> schema / representation
-> hypotheses and disconfirmation
-> Ticket / review / docs / implementation / decision product
-> product impact and stale-feedback metrics
```
この Objective では、以後の Memory 関連 Ticket / report / implementation をこの historical reference と sensemaking model の両方に照らして判断する。
@@ -0,0 +1,916 @@
---
created_at: "2026-07-15T21:33:00Z"
updated_at: "2026-07-16T18:20:00Z"
objective: "00001KVJSMQXZ"
status: "architecture-draft"
notes: "Memory / Knowledge / Skills を別々の workspace resource として再設計するための draft architecture。この文書は Objective resource であり、実装 authority ではない。"
---
# Memory / Knowledge / Skills architecture overview
## 1. Position
Yoi は **Memory**、**Knowledge**、**Skills** を 1 つの汎用 record store に押し込めず、別々の resource class として扱う。
最初に固めるべきなのは、成果物が人間に読める形で成長できる workspace resource model である。Pirolli & Card の sensemaking process は有用な背景知識だが、storage taxonomy を shoebox / evidence / hypothesis として先に固定しない。sensemaking は Memory / Knowledge / Skills の上に乗る usage pattern として扱う。
Target split:
- **Memory**: 短期 fact、嗜好、現在の focus、進行中の context。変化する前提で書く。
- **Knowledge**: 長期的に育てる note。人間と agent が改訂し、相互リンクで mesh を形成し、durable project understanding として読めるもの。
- **Skill**: Agent Skills format に従う、移植可能で確立された手順・workflow。
この文書の中核は次の 2 つである。
1. resource class の境界を明確にする。
2. session から extract / staging / consolidation を経て resource に至る pipeline の責務を明確にする。
## 2. Design goals
- 人間が読め、成長できる artifact を作る。
- 一時的な model summary だけでは足りない。
- 有用な成果は Knowledge note、Skill、Ticket decision、doc、report に育てられるべき。
- 揮発的なものと durable なものを分ける。
- 短期 context が長期 note を汚染しないようにする。
- 長期 note が session extraction のたびに上書きされないようにする。
- 手順と note を分ける。
- 繰り返し使える作業方法は Knowledge note ではなく Skill にする。
- authority boundary を明示する。
- Ticket は work authority を定義する。
- docs と Objective resources は maintained design context を持つ。
- Knowledge notes は育てる project understanding を持つ。
- Skills は execution を guide する。
- Memory は変化する working context と preferences を追跡する。
- typed feature/tool surfaces が external state changes を所有する。
- 可能な限り Workspace backend を resource API の共有 authority にする。
- `WorkspaceClient::Http` が使えるときに、Worker ごとに local view が分岐してはいけない。
## 3. Resource model
### 3.1 Memory
Memory は、agent が作業を継続する助けになる volatile / short-to-medium-term な情報を扱う。長期的な project truth のふりはしない。
Memory record に入るもの:
- 現在の focus。
- user preferences。
- working assumptions。
- authority が別にある recent decisions の要約や pointer。
- 進行中の constraints。
- あとで Ticket / doc / session を再確認するための reminder。
- session から得た observations。
- 変化することが前提の personal / workspace context。
Memory は provisional に書く:
- いつ / なぜ learned したかを書く。
- どの前提で learned したかを必要な範囲で書く。
- staleness / supersession を許す。
- authoritative records を verbatim にコピーしない。
- 可能なら Tickets / docs / Knowledge notes への pointer を優先する。
Memory は resident context と lightweight lookup には有用だが、permanent note system として最適化しない。
#### 3.1.1 Memory storage profile: bounded H2 Markdown file
Memory の初期 storage profile は、bounded な single Markdown file にする。
Memory は Knowledge のような note bundle ではない。1〜3 行程度の short items を H2 section ごとに並べる resident context surface として扱う。
初期 filesystem shape:
```text
.yoi/memory/
memory.md
_staging/
_resolutions.jsonl
```
`memory.md` は H2 section を基本単位にする。
```md
# Workspace Memory
## Current focus
- Memory extract redesign is focused on Overview-first extraction and staging resolution.
Source: Objective 00001KVJSMQXZ. Stale when related tickets close.
## Preferences
- User prefers implementation Tickets, not design-only Tickets.
Source: 2026-07-16 session.
## Working assumptions
- Knowledge should be OKF-compatible, while volatile Memory and staging should not be OKF.
Source: architecture objective.
## Reminders
- Re-check extract/consolidation prompts after staging resolution is implemented.
```
Recommended H2 sections:
- `## Current focus`
- `## Preferences`
- `## Working assumptions`
- `## Constraints`
- `## Reminders`
- `## Stale or superseded`
Each item should stay short. When useful, include `Source` and `Stale when` inline. Long explanations, evidence-heavy analysis, durable rationale, citations, and cross-linked concepts should be routed to Knowledge rather than expanded inside Memory.
The single-file layout is an initial storage profile, not an API contract. Workers, Web, Runtime, and CLI should use the Workspace Memory API view rather than depending on the exact file layout, so storage can later split or evolve without changing the model-visible contract.
#### Memory examples
```text
User preference: prefers direct commits only when explicitly requested.
Source: repeated user corrections in sessions around git operations.
Staleness: revisit if user changes repo workflow.
```
```text
Current focus: web Workspace console and Workspace-backed Ticket/Skill authority.
Source: recent Tickets and Objective updates.
Expected to change after current milestone.
```
### 3.2 Knowledge
Knowledge は long-term note system。人間と agent が育て、改訂し、link し、split / merge しながら読むもの。抽出 snippet の山ではなく、project understanding の mesh を形成する。
Target Knowledge は、古い未使用の Knowledge feature をそのまま残すものではない。legacy implementation は先に削除してよい。置き換えは proper workspace note subsystem として設計する。
Knowledge notes の要件:
- Markdown-first で人間が読める。
- OKF-compatible な concept document として扱える。
- stable path / slug を持ち、OKF concept ID として参照できる。
- Yoi 内部で move / rename に強い identity が必要な場合は、extension frontmatter として `yoi_id` を持てる。
- bidirectional links / backlinks を support する。
- Obsidian-style wiki links (`[[slug]]`, `[[slug|label]]`) を support し、Knowledge mesh の authoring shorthand として使える。
- 必要なら tags や typed relations を support する。
- 重要な claim には provenance / citations を残す。
- Tickets、Objectives、docs、commits、reports、Skills、他 Knowledge notes に link できる。
- review / staleness / supersession を support する。
- 自動生成だけに頼らず、意図的に maintain される。
Knowledge は、長期 architecture note、conceptual model、subsystem explanation、decision context、recurring constraints、domain understanding を育てる場所である。
#### 3.2.1 Knowledge format profile: OKF-compatible bundle
Yoi Knowledge は、可能な限り Open Knowledge Format (OKF) compatible な bundle として設計する。
OKF から採用する baseline:
- Knowledge bundle は Markdown file tree とする。
- non-reserved `.md` file は concept document とする。
- concept document は YAML frontmatter + Markdown body とする。
- path without `.md` を OKF concept ID として扱う。
- `type` は required field とする。
- `title`, `description`, `resource`, `tags`, `timestamp` は recommended field とする。
- normal Markdown links を OKF-compatible graph edges として扱う。
- Obsidian-style wiki links (`[[slug]]`, `[[slug|label]]`) も graph edges として扱い、Markdown links へ解決・export できるようにする。
- `index.md` は progressive disclosure のための directory listing として使える。
- `log.md` は agent-readable update history として使える。
- `# Citations` section は external source / authority reference を示す convention として使う。
- consumers は unknown frontmatter fields、unknown `type`、broken links を tolerant に扱う。
Yoi は OKF に extension frontmatter を足してよい。候補:
```yaml
yoi_id: 00001...
status: draft | active | stale | superseded
source_refs: []
authority_refs: []
objective_refs: []
ticket_refs: []
skill_refs: []
reviewed_at: 2026-07-16T00:00:00Z
staleness: "Revisit when ..."
supersedes: []
superseded_by: null
```
Filesystem shape の例:
```text
.yoi/knowledge/
index.md
log.md
architecture/
index.md
memory-architecture.md
workspace-authority.md
references/
pirolli-card-2005-sensemaking.md
```
OKF compatibility は Knowledge の exchange / storage profile であり、Memory / staging / Skill の format ではない。
- Memory は短期・変化前提の resident context store なので OKF にしない。
- staging は extract / consolidation の審査キューなので OKF にしない。
- Skill は Agent Skills format を維持する。OKF `type: Playbook` に吸収しない。
#### Knowledge examples
- `workspace-authority-model`
- Workspace backend が Tickets / Skills / Runtime views の authority である理由を説明する。
- Ticket backend API design、Skill support ticket、Workspace control plane Objective に link する。
- `memory-knowledge-skill-boundary`
- Memory / Knowledge / Skills の boundary を定義する。
- この architecture resource と将来の implementation Tickets に link する。
- `ticket-lifecycle-authority`
- Ticket state authority と transition graph の rationale を説明する。
- 関連 decisions と code locations に link する。
### 3.3 Skill
Skill は、ある種類の task に対して確立された、portable な workflow / procedure。Agent Skills format に従う。
```text
.yoi/skills/<skill-name>/
SKILL.md
scripts/
references/
assets/
```
Skill は state machine ではなく、external authority も所有しない。agent が available tools を使って task をどう実行するかを示す prompt/resource guidance である。
Skill に含めるもの:
- いつその Skill を使うか。
- step-by-step procedure。
- expected inputs。
- expected outputs / report shape。
- examples。
- edge cases。
- optional references / scripts / assets。
Skill は、project-specific assumptions が少なく、別 workspace に移しても使えるとき portable と言える。
#### Skill examples
- `coder-review-cycle`
- Coder が実装、検証、review request、feedback 対応、dossier 作成をどう行うか。
- `ticket-intake`
- 曖昧な user request を accepted Ticket requirements に変換する方法。
- `architecture-review`
- design proposals、alternatives、authority boundaries を評価する方法。
## 4. Resource boundaries and authority
### 4.1 Memory vs Knowledge
Memory は provisional / change-oriented。Knowledge は maintained / growth-oriented。
Memory を使うべきとき:
- 情報が短命。
- preference や working assumption である。
- resident context として有用。
- 長期的な置き場所がまだ明確でない。
Knowledge を使うべきとき:
- 時間をかけて読み直し、改訂するべき情報。
- durable project concept を説明する情報。
- 複数の future tasks から link されるべき情報。
- backlinks / mesh structure が有用な note。
- 人間が project understanding として browse できるべきもの。
Promotion path:
```text
Memory observation -> candidate note/update -> Knowledge note / docs / Ticket decision
```
Promotion は明示的に行う。すべての Memory item が Knowledge になるわけではない。
### 4.2 Knowledge vs Docs
Docs は public / project-facing な maintained exposition。Knowledge は internal で、link され、発展する understanding。
Knowledge note は後で doc になり得るが、threshold は違う:
- Knowledge は uncertainty、partial models、evidence links を含められる。
- Docs は settled explanations または user/developer guidance を提示するべき。
### 4.3 Knowledge vs Ticket decisions
Ticket decisions は work item history と state の authority。Knowledge notes は複数 Ticket をまたいだ synthesis。
ある decision が Ticket の requirement、state、acceptance criteria を変えるなら、それは Ticket に記録する。Knowledge はそこに link し、より広い pattern を説明できる。
### 4.4 Skill vs Knowledge
Knowledge は「何が true か」「project をどう理解するか」を説明する。Skill は「recurring task をどう実行するか」を説明する。
Skill を使うべきとき:
- review process。
- implementation process。
- release checklist。
- architecture evaluation method。
Knowledge を使うべきとき:
- Workspace authority model。
- Memory architecture。
- Ticket lifecycle rationale。
### 4.5 Skill vs Feature/Plugin
Skill は prompt/resource guidance。Feature/Plugin は executable authority と tool surface。
Skill は「何をどう進めるか」を書けるが、Ticket、Workspace、Memory、外部状態を変更する権限そのものは持たない。その権限は Feature/Plugin や typed tool/API が持つ。
例: Skill は「review 前に Ticket shoebox を作る」と指示できる。実際に作成する authority は Workspace / Memory feature の typed tool/API が提供する。
## 5. Workspace API authority
Target architecture は Workspace-backed にする。
### 5.1 Memory API
Workspace backend が最終的に提供するもの:
- Memory list / search / read / write / edit / delete。
- resident memory summary の生成または取得。
- staleness / supersession markers。
- sessions や artifacts からの Memory candidate proposal。
- provenance と audit events。
- preference / current-focus surfaces。
移行期間中は local `.yoi/memory` を compatibility / offline storage として残してよい。初期 storage profile は H2 section ベースの bounded `.yoi/memory/memory.md` だが、これは API contract ではない。
### 5.2 Knowledge API
Workspace backend は、raw filesystem layout を唯一の interface にするのではなく、proper note API を提供する。
- Knowledge catalog / list / search。
- note read / write / edit / delete。
- OKF-compatible frontmatter validation / normalization。
- link / backlink extraction from Markdown links and wiki links (`[[slug]]`)。
- relation / tag metadata。
- staleness / supersession markers。
- note diagnostics / lint。
- source / provenance refs and citations。
- Markdown files からの import / export。
- OKF bundle import / export profile。
Filesystem representation は `.yoi/knowledge/` 配下の OKF-compatible bundle を第一候補にする。ただし Worker / Runtime / Web / CLI は、利用可能なら raw filesystem ではなく Workspace API view に収束する。
### 5.3 Skill API
Skill support は separate Skill Ticket の方針に従う。
- Workspace backend が discovery / lint / catalog / activation を所有する。
- `.yoi/skills/<skill>/SKILL.md` は workspace storage convention。
- `WorkspaceClient::Http` が使えるとき、Workers は Workspace API から Skill metadata / body を使う。
- Skill references / assets は backend-resolved authority または Skill resource APIs 経由で access する。
## 6. Session-to-resource pipeline
この章が extract 改善の中心である。`extract -> staging -> consolidate` の分割は維持する。3 つは同じ memory maintenance pipeline の一部だが、判断の種類が違う。
```text
Session history
-> Overview + Evidence index
-> extract
-> staging
-> consolidation
-> Memory / Knowledge candidate / Skill candidate / Ticket-doc candidate / discard
```
役割の要約:
- **extract**: session から候補を拾う。recall 寄り。Memory 化はしない。
- **staging**: provenance 付き候補キュー。まだ Memory ではない。
- **consolidation**: staging を審査・剪定・統合する。precision 寄り。Memory 肥大化と陳腐化を防ぐ。
### 6.1 Overview: transcript as semantic backbone
Overview は、committed history にある user messages と normal Assistant text outputs から作る。Assistant text outputs には、最終応答だけでなく、長い作業中の Progress message も含める。
Progress message は専用 Tool ではなく、ordinary user-visible prose response として残す。Tool surface を増やさず、ユーザーへの進捗報告と extract 用 semantic summary を兼ねるためである。
Overview に含めるもの:
- user requests / corrections / approvals。
- Assistant progress messages。
- Assistant final responses。
- parent delegation や Ticket context のように、history に commit された task context。
- tool evidence への bounded index。
Overview に含めないもの:
- raw reasoning / chain-of-thought。
- raw tool-result content 全文。
- secret-like data。
- history に commit されていない hidden context injection。
Overview の意図は、extract worker に「何のための探索だったか」「どの判断が節目だったか」「どこが未解決か」を伝えることである。Overview は authority ではない。durable output には evidence と source anchors が必要である。
### 6.2 Extract: candidate generation
Extract は candidate generation であり、Memory 化ではない。runtime 側の extract worker が Overview と session evidence を読んで、後で記憶化を検討すべき **flat candidate records** を staging に出す。
Extract の責務:
- Overview を読んで、記憶化を検討すべき candidate を見つける。
- 必要な箇所だけ evidence tools で確認する。
- candidate ごとに bounded evidence snippets / source anchors を選ぶ。
- candidate ごとに `stage_candidate` を呼び、1 candidate = 1 staging record として保存する。
- 最後に `finish_extraction` を呼び、staged count または NOP reason を残す。
Extract がしてはいけないこと:
- Memory / Knowledge / Skill / Ticket / docs を直接変更しない。
- batch payload として複数 candidate を 1 staging record にまとめない。
- tool result 全文や reasoning を無制限に取り込まない。
- local slice だけから根拠を推測しない。
- tool call chronology、generic progress、current focus update を抽出しない。
- 「進捗報告があった」こと自体を Memory 化しない。
Staging candidate は、Consolidation がそれ単体で discard / merge / promote / defer を判断できる最小単位にする。
`decisions` / `discussions` / `attempts` / `requests` batch schema は維持しなくてよい。互換性よりも、flat candidate records と clear responsibility を優先する。
#### 6.2.1 Extract candidate taxonomy
Extract が抽出する対象は activity log ではない。抽出対象は次の candidate kinds に絞る。
| kind | extract で見る観点 | consolidation での扱い |
| --- | --- | --- |
| `preference` | ユーザーまたは workspace の継続的な好み・作法。単発指示ではなく、今後の agent behavior に効くもの。 | Memory に短く merge / replace する候補。既存 preference と重複するなら統合。Ticket/docs の要件そのものなら mirror せず authority link へ。曖昧なら discard / defer。 |
| `working_assumption` | 現時点で仮に置いている設計・実装前提。future work に影響し、変更条件や反証条件があり得るもの。 | Memory に入れる場合は short-lived assumption として stale condition 必須。長期設計なら Knowledge candidate。すでに authority record に反映済みなら Memory には pointer だけ、または discard。 |
| `constraint` | 今後守るべき境界・禁止・invariant。実装や review でチェック可能なもの。 | active implementation に効くなら Memory。durable policy なら Ticket decision / Knowledge / docs candidate。破られた既存 Memory があれば mark_stale / replace。 |
| `decision` | alternatives / chosen / rationale がある判断。単なる事実確認や作業進行ではないもの。 | まず authority routing を判断する。Ticket 要件・state・acceptance に関係するなら Ticket decision/comment candidate。長期設計なら Knowledge/Objective candidate。短期実装判断だけ Memory に短く置く。会話中の一時結論なら discard。 |
| `open_question` | 未解決で後続作業に影響する問い。next action が書けるもの。単なる会話中の疑問ではない。 | Memory reminder にするか、Ticket follow-up / planning item に送る。解決済みなら discard。長く残る概念的問いなら Knowledge candidate。TTL / defer reason を持たせる。 |
| `lesson` | 検証・失敗・試行から得た再利用価値のある学び。同じ失敗を避ける、作業方法を改善する、Skill 化できる可能性があるもの。 | Memory に短く残すか、recurring / portable なら Skill candidate。単なる tool execution result は discard。validation evidence として Ticket/report に残すべきものは authority link。 |
抽出しないもの:
- `current_focus` update。これは resident summary surface であり、extract candidate kind ではない。
- tool call chronology。
- file read/write history。
- generic progress updates。
- one-off chit-chat。
- resolved local confusion。
- assistant self-corrections without durable consequence。
- authoritative Ticket/docs/git facts copied verbatim。
- validation results unless they imply a reusable lesson, active blocker, or authority evidence。
- implementation details that belong only in commit diff。
### 6.3 Extract worker tools
extract worker には `session-explore` feature の constrained tools だけを渡す。これは main Worker の tool 数を増やすものではない。
Tool surface:
- `search_evidence`: session snapshot / tool summaries / message index から query で候補 range を探す。
- `read_evidence`: bounded な session entry range、tool call/result summary、host が許す bounded excerpt を読む。
- `stage_candidate`: 1 candidate を staging record として保存する。
- `finish_extraction`: extract run を終了し、staged count または NOP reason を記録する。
`stage_candidate` は direct Memory write ではない。これは staging write だけを行う output tool である。
`stage_candidate` input の概念形:
```json
{
"kind": "decision",
"claim": "Overview is runtime-only extract projection, not staging data.",
"why_useful": "Clarifies extract/consolidate responsibility boundary.",
"staleness": "Revisit if Workspace can directly explore runtime sessions.",
"evidence_ids": ["E001", "E002"]
}
```
Host wrapper は `evidence_ids` を runtime reference environment から解決し、bounded evidence snippets と source anchors を staging record に機械的に付与する。LLM に自由な source anchor を書かせない。
`finish_extraction` の概念形:
```json
{
"staged_count": 0,
"reason": "Only local progress and tool chronology; no durable candidates."
}
```
候補が無い場合は `stage_candidate` を呼ばず、`finish_extraction` で NOP を明示する。tool call なし終了も host 側では NOP fallback として扱ってよいが、基本は `finish_extraction` を要求する。
制約:
- read-only evidence access。file write、Ticket mutation、Memory/Knowledge/Skill direct write は持たせない。
- bounded output。large tool result は summary / excerpt / pointer に留める。
- provenance first。extract worker が根拠を推測せず、読んだ evidence ids を `stage_candidate` に渡す。
### 6.4 Staging: flat provenance-backed candidate records
Staging は Memory ではない。Staging は、extract が切り出した candidate を provenance 付きで保管し、consolidation が後で審査できるようにする queue である。
Staging は flat records にする。
```text
1 extract run = 0..N staging records
1 staging record = 1 candidate = 1 consolidation decision unit
```
1 record の概念形:
```json
{
"schema_version": 2,
"id": "stg_...",
"extract_run_id": "er_...",
"source": {
"segment_id": "segment-1",
"range": [120, 180]
},
"kind": "constraint",
"claim": "Extract worker must not direct-write Memory/Knowledge/Skill; it only writes staging.",
"why_useful": "Preserves runtime/embedded responsibility boundary.",
"staleness": "Revisit if extract and consolidation move into the same Workspace execution context.",
"evidence": [
{
"id": "E001",
"kind": "message",
"entry_range": [132, 133],
"excerpt": "extract worker は Memory / Knowledge / Skill を直接更新しない",
"summary": "User and architecture discussion fixed staging-only extract boundary."
}
],
"source_refs": [
{
"evidence_id": "E001",
"evidence_kind": "message",
"entry_range": [132, 133]
}
]
}
```
Staging の責務:
- candidate kind / claim / hints を保持する。
- extract が選んだ bounded evidence snippets を保持する。
- source anchors を保持する。
- extract と consolidation を decouple する。
- duplicate / defer / discard / consumed の追跡対象になる。
- crash / cancel / long-running work の途中でも、後から審査できる候補を残す。
Staging がしてはいけないこと:
- Memory として resident context に直接入らない。
- Knowledge note の代替にならない。
- raw session log や Overview 全体の保存場所にならない。
- extract run 単位の batch file として複数 candidate を抱え込まない。
- staging entry をすべて Memory 化する前提にしない。
Pirolli & Card 的には、staging は shoebox / evidence file に近い。ただし Yoi の storage taxonomy そのものを shoebox にするのではなく、審査前の evidence-backed candidate queue として扱う。
### 6.5 Staging resolution: the important filter
Staging から Memory 化する段階が、Memory 肥大化と陳腐化を防ぐ中核 filter である。
Consolidation は staging entry ごとに resolution / disposition を決めるべきである。
Disposition action 候補:
- `discard`: 保存価値なし。discard reason を残す。
- `merge_memory`: 既存 Memory に統合する。
- `replace_memory`: 古い Memory を新しい内容で置換する。
- `mark_memory_stale`: 既存 Memory が古くなったことを記録する。
- `delete_memory`: 邪魔または誤った Memory を削除する。
- `defer`: 価値判断できないため短期保留する。TTL / defer reason を持つ。
- `promote_to_knowledge_candidate`: long-term note に育てる候補へ送る。
- `promote_to_skill_candidate`: recurring / portable procedure の候補へ送る。
- `link_to_authority`: Ticket / doc / commit / Objective への pointer だけ残す。
- `create_ticket_or_doc_candidate`: authority / public guidance にすべき候補として送る。
Resolution に残すべき情報:
- staging entry id。
- action。
- reason。
- source anchors。
- target record / candidate destination。
- consolidation run id / consumed_by。
- reviewed_at。
- discard / defer / stale reason。
Consumed staging を削除する場合も、resolution は残す。これにより「何を Memory にしなかったか」が改善材料として残る。
### 6.6 Consolidation: memoryization, routing, and gardening
Consolidation は precision-oriented pass である。staging を読んで、Memory にするか、別 resource candidate に送るか、捨てるかを決める。
Consolidation の責務:
- staging entry を candidate kind ごとの扱いに沿って評価する。
- Memory 化するなら usefulness / staleness / source を要求する。
- 既存 Memory と merge / replace / mark stale / delete する。
- decision / constraint / lesson などを authority / Knowledge / Skill / Ticket / docs candidate に routing する。
- discard reason / defer reason を残す。
- linter feedback / usage evidence / tidy hints を使う。
- Memory bloat と stale records を防ぐ。
Consolidation がしてはいけないこと:
- staging entry を無条件に append しない。
- Ticket / docs / git / session log の mirror を Memory に作らない。
- Knowledge / Skill / docs を background review だけで無制限に rewrite しない。
- source / provenance のない claim を durable Memory にしない。
Memory 化に必要な minimum fields / prose:
```text
content: 何を覚えるか
why_useful: 今後なぜ役立つか
source: staging / evidence anchor
staleness: 何が起きたら古くなるか
destination_reason: なぜ Knowledge / Skill / Ticket / docs ではなく Memory なのか
```
Consolidation は append worker ではなく garden worker である。新規作成より、既存 record の統合・置換・陳腐化・削除を優先する。
### 6.7 Trigger policy
発火単位は LLM call 単位にしない。LLM call 単位では文脈が薄く、断片的な extraction になりやすい。
初期方針:
- 現行通り、Worker run cycle が完了してから threshold を判定し、超えていれば extract を発火する。
- extract 開始時点で immutable snapshot / Overview projection / Evidence index を作る。
- LLM call ごとには発火しない。
- Run 中の Overview accumulation trigger / mid-run extract は初期実装に含めない。
- 将来 long-running 中に mid-run 発火を入れる場合も、direct update ではなく staging/checkpoint extraction に限定する。
この trigger は、まず既存の post-run memory job model を保ち、extract の入力品質と staging record 粒度の改善に集中する。
## 7. Sensemaking interpretation
Sensemaking は storage taxonomy ではなく、pipeline の見方として使う。
Pirolli & Card の flow を Yoi に対応させるとこうなる:
```text
External data sources
= session log, tool results, Tickets, docs, code, web refs
Shoebox
= Overview + Evidence index + selected candidate ranges
Evidence file
= source anchors 付き staging entries
Schemas / hypotheses
= Memory 化すべきか、Knowledge/Skill に送るべきか、stale かの判断
Product
= Memory update, Knowledge candidate, Skill candidate,
Ticket/doc update, review evidence, discard resolution
```
重要なのは、Memory 化を evidence から product へ進める審査の一形態として扱うこと。Memory record は「将来の作業に効く」という hypothesis なので、why_useful、staleness、source が必要である。
初期 sensemaking support は lightweight でよい:
- task-bound collected references as Ticket/Objective artifacts。
- provenance 付き evidence summaries。
- review Skills における explicit contradictory evidence sections。
- recurring patterns を synthesize する Knowledge notes。
- staging resolution に discard / defer / promote reason を残す。
## 8. Human-readable growth paths
中核要件は、有用な material が人間に読める形へ成長できること。
Typical paths:
```text
Session observation
-> staging candidate
-> Memory record
-> Knowledge note candidate
-> Knowledge note with links/backlinks
-> maintained doc or Ticket decision if it becomes authority
```
```text
Repeated successful procedure
-> staging candidate / Memory observation / Ticket comment
-> Skill candidate
-> `.yoi/skills/<skill>/SKILL.md`
-> builtin or shared Skill if portable
```
```text
Design discussion
-> Objective resource
-> Knowledge note synthesis
-> implementation Tickets
-> docs after stabilization
```
Architecture は、これらの promotion を explicit and reviewable にする。
## 9. External reference lessons
### 9.1 Current Yoi pipeline
現在の Yoi extraction は activity-log pipeline:
- `build_extract_input` が conversation slice を flat Markdown として render する。
- user / assistant text は保持する。
- tool-call names を含める。
- raw tool-result content ではなく tool-result summaries のみを含める。
- reasoning は落とす。
- extract worker の tool は `write_extracted` 1 つだけ。
- `write_extracted``decisions``discussions``attempts``requests` を持つ structured `ExtractedPayload` を 1 件受け取る。
- LLM は provenance を作らない。Worker が `StagingRecord` を書くときに `source` を機械的に付与する。
- empty payload は valid で、no-op として扱える。
- consolidation は後で staging entries、full current Memory records、usage evidence、tidy hints を consume する。
- consolidation は Memory tools 経由で write し、linter feedback に対応し、record を merge / replace し、outdated / superseded / unused / noisy records を clean up する。
残す価値がある点:
- foreground 応答生成から memory maintenance が隔離されている。
- provenance が host 側で機械付与される。
- extract が direct write せず staging を挟む。
- empty / no-op が許される。
- consolidation が linter feedback と tidy hints を使う。
変えるべき点:
- flat slice ではなく Overview-first / Evidence-index-second にする。
- extract worker に read-only evidence tools を持たせる。
- staging を一時バッファではなく審査キューとして扱う。
- consolidation に entry-level disposition / resolution を要求する。
- legacy Knowledge as generated memory 前提を外す。
### 9.2 HermesAgent
HermesAgent は background review により、conversation snapshot から Memory / Skill update を直接判断する。
参考になる点:
- maintenance を foreground interaction から隔離する。
- 保存すべきものがなければ NOP にする。
- Memory と Skill を分ける。
- prompt snapshot / drift / injection guard を重視する。
そのまま採用しない点:
- direct write-only review を主経路にしない。
- aggressive Skill update bias を避ける。
- `MEMORY.md` / `USER.md` two-file model を Yoi 全体の architecture にしない。
Yoi では、Hermes 的な direct maintenance は bounded Memory update lane では参考になるが、extract worker 自体は direct write しない。
### 9.3 Codex
Codex は session / rollout を durable source として扱い、background pipeline が後から claim / extract / consolidate する。
参考になる点:
- durable source。
- phase separation。
- claim / lease / retry / global lock。
- workspace diff / baseline guard。
- extraction と consolidation の分離。
Yoi では、Codex 的な durable job / phase pipeline は staging resolution と consolidation scheduling に取り入れる価値がある。ただし、この architecture phase ではまず Overview-first extract と staging resolution を優先する。
## 10. Implementation posture
現在の実装は redesign してよい。既存の Memory / Knowledge shape があるからという理由で残さない。
ただし big-bang rewrite は避ける。この architecture が accepted されてから分割する。
Recommended implementation sequence:
1. **Knowledge removal 後の current Memory を clarify する**
- short-term / resident Memory を維持する。
- Memory が Knowledge を代替しなければならない、という前提を外す。
- legacy `knowledge/*` を generated memory として扱う stale consolidation prompt language を削除する。
2. **Progress message guidance を追加する**
- 長い作業や tool loop の節目で、main Worker が ordinary user-visible prose response として短い Progress message を残す。
- 専用 Tool は追加しない。
- Progress message は public に見せられる作業状態、確認済み事実、判断、未解決点、次の作業に限定する。
3. **Overview-first extract input を実装する**
- user messages + Assistant text outputs を semantic Overview として優先する。
- tool calls / tool results は Evidence index として分離する。
- committed history だけから Overview を作り、hidden context injection を避ける。
4. **Extract worker 専用 evidence tools と staging output tools を実装する**
- extract worker に read-only Evidence search / Evidence read を渡す。
- main Worker の tool surface は増やさない。
- output tools は `stage_candidate` / `finish_extraction` にする。
- `stage_candidate` は 1 candidate = 1 flat staging record を書く。
- source range と candidate record を結びつけられる schema / staging format を実装する。
5. **Staging-first extract を維持する**
- extract worker は direct Memory / Knowledge / Skill write をしない。
- overview accumulation / evidence growth / run or task boundary で extract を予約する。
- mid-run 発火を入れる場合も staging/checkpoint extraction に限定する。
6. **Staging resolution / disposition を実装する**
- staging entry ごとに discard / merge / replace / stale / delete / defer / promote / link を記録する。
- consumed staging を削除する前に resolution log / archive を残す。
- discard reason と defer reason を extract prompt 改善に使えるようにする。
7. **Target Knowledge note model を設計する**
- OKF-compatible Markdown concept document / bundle profile。
- Yoi extension frontmatter。
- link / backlink model。
- provenance / citations / staleness metadata。
- Workspace API surface。
- reviewable Knowledge updates の candidate / staging format。
8. **Consolidation / tidy lane を更新する**
- staging entries、existing Memory、usage evidence、linter feedback、stale/noisy hints を統合する。
- legacy Knowledge as generated memory 前提を外す。
- Memory update、Knowledge candidate、Skill candidate を分けて扱う。
9. **Minimal Knowledge catalog/read/write を実装する**
- OKF-compatible Markdown files と Workspace API から始める。
- frontmatter validation / lint と backlinks を追加する。
- `index.md` progressive disclosure と `# Citations` の扱いを実装する。
10. **Skill support を別に実装する**
- Agent Skills standard と Workspace authority に従う。
- Skill と Knowledge note schema を混ぜない。
- automatic Skill modification は recurrence と portability で gate する。
11. **Promotion workflows/tools を追加する**
- Memory -> Knowledge candidate。
- Knowledge -> docs / Ticket decision candidate。
- repeated procedure -> Skill candidate。
12. **Resource classes が安定してから sensemaking helpers を追加する**
- collected refs。
- evidence extraction。
- contradiction / staleness views。
- product-impact metrics。
## 11. Non-goals
- Memory を唯一の long-term knowledge store として扱うこと。
- Knowledge を名前だけ変えた generated memory として扱うこと。
- Skill を Workflow tracker や state machine として扱うこと。
- Worker history / tool results の外で context injection を隠すこと。
- Knowledge notes を Tickets / docs / git history より authoritative にすること。
- review なしに Knowledge / Skills / docs を自動 rewrite すること。
- extract worker に direct resource mutation authority を持たせること。
- extract run 単位の batch staging record に複数 candidate を抱え込ませること。
- staging entry をすべて Memory 化すること。
- human-readable artifact model が安定する前に vector database を設計すること。
- volatile Memory や staging queue を OKF concept document として扱うこと。
- H2 Markdown single-file layout を Workspace Memory API の長期 contract として固定すること。
- Agent Skills format を OKF Playbook documents で置き換えること。
## 12. Open decisions
- Knowledge bundle の exact directory organization: flat files、nested directories、domain directories のどれを初期推奨にするか。
- Yoi extension frontmatter の exact fields。
- Yoi stable `yoi_id` を必須にするか optional にするか。
- OKF `type` values の初期 convention をどうするか。
- Link syntax は OKF-compatible Markdown links と Obsidian-style wiki links (`[[slug]]`, `[[slug|label]]`) を support する。canonical internal representation と export normalization をどうするか。
- Knowledge note IDs / slugs と titles の関係。
- Memory は local-first のままにするか、Knowledge と同じ phase で Workspace API-first にするか。
- Memory / Knowledge APIs は同じ crate にするか、別 domain crates にするか。
- Memory -> Knowledge の promotion UI/tool をどうするか。
- personal Memory と workspace Memory をどう区別するか。
- Knowledge drafts の auto-generation をどこまで許すか。
- extract worker 専用 evidence tools の exact API: search/read の引数、上限、evidence id format。
- `stage_candidate` / `finish_extraction` の exact tool schema。
- flat staging record の exact fields: `claim`, `why_useful`, `staleness`, `evidence`, `source_refs`, `extract_run_id` など。
- Overview trigger を overview token count、Assistant message count、evidence growth、run/task boundary のどれで制御するか。
- mid-run extract をどこまで許すか。初期は staging/checkpoint extraction に限定する方針。
- staging resolution log / archive の保持期間と compact policy。
- どの Memory sidecar writes を direct に許し、どれを staged proposals にするか。extract worker 自体は direct write しない。
- Skill sidecar output は patches/proposals だけから始めるか、low-risk Skill edits を auto-apply してよいか。
- Memory / Knowledge / Skill Workspace APIs をまたぐ sidecar audit events をどう表現するか。
- prompt-cache-aware sidecar input で full replay と digest-plus-tail をどう選ぶか。
## 13. Exit criteria for architecture phase
この architecture は、次が満たされたら Tickets に分割できる。
- Memory / Knowledge / Skill boundary が accepted される。
- OKF-compatible bundle / Markdown concept documents としての target Knowledge が accepted される。
- Memory / Knowledge / Skills の Workspace backend authority が accepted される。
- Overview-first extract、extract worker 専用 evidence tools、staging-first output の方針が accepted される。
- staging resolution / disposition と、staging -> Memory 化 filter の方針が accepted される。
- 最初の implementation slice が選ばれる。
- non-goals が accepted され、old Workflow tracking や old unused Knowledge をそのまま再作成しないことが確認される。
@@ -0,0 +1,137 @@
---
source_url: "https://andymatuschak.org/files/papers/Pirolli%2C%20Card%20-%202005%20-%20The%20sensemaking%20process%20and%20leverage%20points%20for%20analyst%20technology%20as.pdf"
fetched_at: "2026-07-15T21:24:00Z"
content_type: "application/pdf"
notes: "Untrusted external reference captured as local Objective resource for Memory sensemaking design. This is a summary/extraction for design discussion, not project authority."
---
# Pirolli & Card (2005): The sensemaking process and leverage points for analyst technology
## Citation / source
Peter Pirolli and Stuart Card, PARC. "The Sensemaking Process and Leverage Points for Analyst Technology as Identified Through Cognitive Task Analysis" (2005).
Source PDF: <https://andymatuschak.org/files/papers/Pirolli%2C%20Card%20-%202005%20-%20The%20sensemaking%20process%20and%20leverage%20points%20for%20analyst%20technology%20as.pdf>
## Core model
The paper frames intelligence analysis as a sensemaking task:
```text
Information -> Schema -> Insight -> Product
```
The analyst transforms raw data into progressively more structured representations so expertise can apply and so results can be communicated.
The paper's notional data flow is especially relevant to Yoi Memory design:
```text
External data sources
-> shoebox
-> evidence file
-> schemas
-> hypotheses
-> presentation / work product
```
- **External data sources**: raw material, mostly text in the studied setting.
- **Shoebox**: the smaller subset collected as relevant for the task.
- **Evidence file**: extracted snippets / nuggets from the shoebox, plus low-level inferences.
- **Schemas**: re-representations that organize information for analysis.
- **Hypotheses**: tentative conclusions with supporting or disconfirming evidence.
- **Product**: report / presentation / action suited for communication.
## Two major loops
The process has two interacting loops rather than a simple linear pipeline.
### Foraging loop
Activities aimed at finding and selecting information:
- search and filter external data sources;
- collect potentially relevant material into a shoebox;
- read and extract evidence snippets;
- follow up on questions generated by extracted evidence.
The paper highlights the exploration / enrichment / exploitation tradeoff:
- **Exploration**: monitor or search more of the information space; increases recall.
- **Enrichment**: narrow the collected set into smaller, higher-precision subsets.
- **Exploitation**: read/extract/analyze the chosen material more thoroughly.
Analyst tooling can help by changing the cost structure of search, scanning, assessment, selection, attention shifting, and follow-up searches.
### Sensemaking loop
Activities aimed at structuring and reasoning:
- schematize evidence;
- build a case;
- generate / manage hypotheses;
- marshal evidence for and against hypotheses;
- tell a story / produce a report;
- re-evaluate based on feedback or new evidence.
The paper emphasizes opportunistic mixing of bottom-up and top-down processing:
- **Bottom-up**: data triggers schemas, relations, hypotheses, and products.
- **Top-down**: hypotheses / client feedback trigger new searches, re-reading, and re-organization.
## Leverage points
### Foraging loop leverage
- Cost structure of exploration / enrichment / exploitation.
- Cost structure of scanning, recognizing, and selecting items for attention.
- Cost of shifting attentional control to a new domain or task.
- Cost of follow-up searches generated by extracted information.
- Broad-band low-fidelity assessment plus narrow-band high-fidelity processing is a useful design pattern.
### Sensemaking loop leverage
- Span of attention for evidence, hypotheses, and evidentiary relations.
- Generation of alternative hypotheses.
- Confirmation bias and failure to seek disconfirming evidence.
- External representations can expand working memory for evidence/hypothesis structures.
- Tools should help distribute attention toward diagnostic evidence and disconfirming relations.
## Implications for Yoi Memory Objective
This paper directly supports the Objective's direction that effective Memory is not just durable storage or retrieval count.
Useful design implications:
1. **Task-bound shoebox**
- For each Ticket / Objective / question, provide a bounded collection of potentially relevant materials.
- Include provenance and why each item was collected.
2. **Evidence file**
- Extract snippets from source material with source, applicability, confidence, and context.
- Evidence should be usable for support and disconfirmation, not only recall.
3. **Schema / representation layer**
- The system should help create intermediate structures: timelines, entity/relation maps, alternatives, checklists, hypothesis spaces, decision tables.
- These are separate from raw Memory records.
4. **Hypotheses and alternatives**
- Record competing explanations, rejected alternatives, open questions, and evidence gaps.
- Avoid only storing final decisions.
5. **Disconfirming evidence**
- Reviewer / Orchestrator support should explicitly search for contradiction and diagnostic evidence.
- This belongs in Skill guidance and typed review tooling, not in a separate Knowledge store.
6. **Metrics**
- Measure whether Memory changes product quality, review quality, decision quality, or time-to-evidence.
- Avoid treating exposure/retrieval counts alone as success.
7. **Product connection**
- The loop should end in a product: Ticket decision, implementation report, review, design doc, Skill update, or validated artifact.
- Memory that never reaches a product is likely a graveyard.
## Boundary with current Yoi direction
- Knowledge as a separate record kind is being removed; this paper's reusable representations should map to Memory artifacts, Ticket artifacts, maintained docs, or Skills depending on authority.
- Workflow tracking is being removed; procedural guidance such as "generate alternatives" or "seek disconfirming evidence" should live in Skills / role prompts and be enforced by typed tools where authority is needed.
- Workspace backend should eventually be the authority for task-bound shoebox / evidence artifacts when Memory moves from local compatibility storage to control-plane records.
+343
View File
@@ -0,0 +1,343 @@
---
title: "Runtime working directory materialization and sandboxed agent environments"
state: "active"
created_at: "2026-07-06T16:28:12Z"
updated_at: "2026-07-10T16:50:00Z"
linked_tickets: ["00001KWPC13WQ", "00001KWMBAA6V", "00001KX6BPY7M", "00001KX6CRVBE"]
---
## Goal
Runtime が Worker ごとに安全で安価な作業環境を用意できるようにする。Yoi の Runtime は、単に既存ディレクトリで Worker process を起動する launcher ではなく、RepositoryPoint から working directory を materialize し、sandbox / mount / cache / cleanup / evidence を管理する実行基盤になる。
この Objective の中心は、Worker 用 working directory の materialization、Repository cache、working directory allocation、sandboxed agent environment の境界を設計し、将来的に 1 つの Runtime が複数 Workspace / Repository の Worker を抱えられるようにすることである。
初期実装では Git/local repository を主対象にしてよい。ただし設計は Git worktree 固定にしない。Git worktree、bare object cache、sparse checkout、copy-on-write snapshot、reflink copy、APFS clonefile、btrfs snapshot、overlay filesystem、container filesystem、remote object snapshot は、すべて working directory materialization strategy の候補として扱う。
## Motivation / background
現在の Runtime は `--workspace` で与えられた単一 root を Worker の workspace scope として使う。この形では次の問題がある。
- 複数 Worker が同じ repository root を scope として要求すると allocation conflict が起きる。
- Runtime が single Workspace / Git repository root 専用 process になってしまう。
- Worker が source repository root を直接触るため、sandbox / cleanup / quota / evidence の境界が曖昧になる。
- Worker ごとに full clone すると容量と時間のコストが大きすぎる。
- `.yoi` / Backend fs-store / Workspace descriptor と、Worker 実行用 checkout / scratch / build output の lifecycle が混ざりやすい。
Yoi は Workspace / Repository / Runtime を分ける方針になっている。Backend は Repository registry、RepositorySelector、RepositoryPoint、Ticket/Artifact evidence の authority を持つ。一方 Runtime は RepositoryPoint を受け取り、Worker が使う working directory を用意する責務を持つべきである。
したがって、Repository を持ってくる実体ディレクトリは Backend / Workspace store ではなく Runtime 管理領域に置く。`./.yoi` は local descriptor / compatibility / project record surface であり、Worker ごとの checkout、worktree、snapshot、sandbox root、build cache、dependency cache を置く場所ではない。
参考になる方向性として、Rift のような copy-on-write workspace snapshot / reflink / btrfs snapshot / APFS clonefile による安価な workspace creation がある。ただし Yoi は Rift を Git worktree 代替 CLI として直接前提にするのではなく、Runtime materializer backend の一候補として扱う。
## Glossary
- Runtime root: Runtime が自身の store、cache、Worker metadata、working directory allocation を管理する root。長期的には `~/.yoi/runtimes/<runtime-id>/` 配下など、Workspace backend store とは別に置く。
- Repository cache: Runtime-local の共有 source/cache。Git なら bare mirror / object cache / packfile cache など。重く、長寿命で、複数 Worker allocation から共有される。
- working directory: Worker ごとの作業環境。短寿命で、Worker が読み書きする root / mounts / scratch / overlay を含む。Browser-facing UI では `workspace` と混同しないよう `workdir` と表示してよい。`Volume` は storage backing の候補名であり、この作業領域そのものの呼称にはしない。
- Worker record: 作業単位として保存する record。profile、Runtime、RepositoryPoint / workdir evidence、session/transcript refs、status、diagnostics、summary、pinned flag を束ねる。Session 単体ではなく Worker を保存・削除の単位にする。
- Materialization strategy: RepositoryPoint から working directory を作る実装戦略。Git detached worktree、sparse checkout、CoW snapshot、reflink copy、overlay、container filesystem など。
- WorkingDirectoryAllocation: Runtime が払い出した作業環境の record。allocation id、worker id、workspace id、repository point、materializer kind、root、mounts、cleanup policy、status を持つ。
- Sandbox policy: Worker が見られる filesystem、network、process、secret、tool authority の境界を表す policy。
- Dirty state policy: local uncommitted changes を Worker environment に含めるかどうかの方針。clean point only、patch artifact apply、snapshot current worktree など。
## Strategy / design direction
### 1. Backend store と Runtime execution storage を分ける
Workspace/backend store は canonical or local descriptor records を扱う。
```text
Backend / Control plane store
- Workspace registry
- Repository registry
- Ticket / Objective
- Artifact metadata / evidence
- Actor / Permission / Audit
- Runtime registry / observed state
```
Runtime execution storage は Worker 実行のための materialized filesystem と cache を扱う。
```text
Runtime root
- runtime catalog / runtime-local DB
- config bundles
- worker metadata / transcript references
- repository-cache
- working-directories
- sandbox state
- build/dependency cache
- cleanup ledger
```
この 2 つを混ぜない。特に `.yoi` や workspace config root に Worker ごとの checkout/worktree/sandbox root を置かない。
推奨配置の方向:
```text
~/.yoi/
workspace-server/
backend.db
workspaces/
<workspace-id>/
workspace.db
artifacts/
runtimes/
<runtime-id>/
runtime.db
config-bundles/
workers/
<worker-id>/
metadata/
repository-cache/
git/
<repository-cache-key>/
bare.git
working-directories/
<allocation-id>/
root/
mounts/
scratch/
materialization.json
build-cache/
tmp/
```
### 2. clone ではなく materialize と呼ぶ
Runtime は Repository を毎回 clone するのではない。Runtime は RepositoryPoint を Worker 用の working directory として materialize する。
```text
RepositoryId + RepositorySelector
-> resolved RepositoryPoint
-> Runtime repository-cache
-> WorkingDirectoryMaterializer
-> WorkingDirectoryAllocation
-> Worker process
```
Git の場合でも materialization strategy は複数あり得る。
- shared bare cache + detached Git worktree
- sparse checkout
- partial clone / blob filter
- reflink copy
- btrfs writable snapshot
- APFS clonefile
- overlay filesystem
- external tool backed snapshot, e.g. Rift-like CoW workspace creation
### 3. Repository cache と Worker working directory を分離する
full clone を Worker ごとに作らない。重い source/object data は Runtime-local repository cache に集約し、Worker ごとの working directory は cheap allocation にする。
Git v0 の方向:
```text
repository-cache/git/<repo-key>/bare.git
working-directories/<allocation-id>/root/<repository-id>/
```
初回:
```text
git clone --mirror <uri> repository-cache/git/<repo-key>/bare.git
```
次回以降:
```text
git -C repository-cache/git/<repo-key>/bare.git fetch --prune
```
Worker allocation:
```text
git --git-dir=<bare.git> worktree add --detach <execution-root>/<repository-id> <commit>
```
Git branch 名を直接 checkout しない。Git worktree は同一 branch を複数 worktree に checkout しづらいため、RepositorySelector を RepositoryPoint に解決し、resolved commit を detached worktree として materialize する。Worker が branch を必要とする場合は Worker/Task ごとの synthetic branch を別途作る。
### 4. Dirty state を明示 policy にする
local dirty changes を暗黙に Worker に見せない。
可能な policy:
- `clean_point_only`: dirty workspace は materialization 拒否。再現性が高く v0 の default 候補。
- `patch_artifact`: clean RepositoryPoint を materialize し、Backend が保存した dirty diff artifact を apply する。
- `current_worktree_snapshot`: CoW/reflink/Rift-like snapshot で現在の working tree を snapshot として materialize する。便利だが evidence と cleanup の扱いを明示する必要がある。
- `direct_legacy_mount`: 既存 root をそのまま渡す。debug/legacy only。通常 Worker creation の default にしない。
Dirty state を含める場合、Artifact/evidence には source RepositoryPoint、patch/snapshot digest、created_at、materializer kind を残す。
### 5. Sandbox を materialization と同じ境界で扱う
working directory は単なる directory path ではなく、Worker が見てよい filesystem view である。Runtime は working directory allocation と同時に sandbox/mount/authority を構築する。
Worker に渡すもの:
- workspace root
- repository mounts
- scratch/cache dirs
- tool authority
- env vars
- config bundle
- secret handles, not raw secrets
Worker が自分で発見してはいけないもの:
- host repository root
- Backend store path
- `.yoi` authority-bearing internals
- raw credentials
- Runtime socket/store/cache internals
- sibling Worker working directories
Sandbox v0 は strong isolation でなくてもよい。ただし型と lifecycle は、後で container sandbox、namespace, mount filtering, network policy, secret boundary に拡張できる形にする。
### 6. working directory registry を持つ
Runtime は materialized workspace を filesystem だけでなく registry でも管理する。
必要な record:
```text
WorkingDirectoryAllocation
id
runtime_id
worker_id
workspace_id
repository_points[]
materializer_kind
root
mounts[]
scratch
source_cache_refs[]
sandbox_policy
dirty_state_policy
cleanup_policy
status: active | stopped | cleanup_pending | removed | failed
created_at
stopped_at
diagnostics[]
```
この registry は Runtime root 側に置く。Backend は必要な evidence と summary だけを受け取る。Browser-facing API は raw host paths を原則漏らさない。
### 7. Heavy regenerable artifacts は policy で除外または cache 化する
Worker working directory creation では、`node_modules`, `target`, `.venv`, framework cache, dist, build, coverage などを無条件に full copy しない。
Materialization policy は以下を持てるようにする。
- exclude regenerable artifacts
- include manifests / lockfiles
- share dependency cache
- use build cache
- path scope / sparse checkout
- per-repository materialization options
Rift の filtered CoW creation のように、重い artifacts を除外しながら source tree を高速に用意できる strategy を将来取り込めるようにする。
## Initial implementation phases
### Phase 1: Materialization boundary and legacy allocation record
- `CreateWorkerRequest` に working directory request / target placeholder を追加する。
- `WorkingDirectoryMaterializer` trait を `worker-runtime` に追加する。
- `WorkerRuntimeExecutionBackend` が Worker spawn 前に materializer を呼ぶ順序にする。
- v0 materializer は existing local root を explicit allocation として返してよいが、`direct_legacy_mount` として明示し、通常設計の final form と混同しない。
- Allocation record / cleanup policy / diagnostics の型を先に作る。
- Worker が source repository root を直接 scope として要求する経路を deprecated/legacy に閉じ込める。
### Phase 2: Runtime root and working directory storage
- `--runtime-root` を導入し、Runtime state / repository-cache / working-directories / worker metadata / worker runtime dirs を Runtime root 配下へ寄せる。
- `--workspace` は legacy bootstrap input としてだけ扱い、Runtime identity / long-term workspace binding から外す。
- Runtime root default は user data 配下にする。
- working directory allocation registry を Runtime root に保存する。
### Phase 3: Git cached detached worktree materializer
- Git repository cache を Runtime root に作る。
- RepositorySelector を RepositoryPoint に解決する呼び出し境界を作る。
- resolved commit/tree を evidence として残す。
- Worker ごとに detached worktree を `working-directories/<allocation-id>/root/<repository-id>` に作る。
- Worker stop / cleanup 時に `git worktree remove` と registry cleanup を行う。
- dirty state は v0 では `clean_point_only` を default にし、dirty local workspace は明示 diagnostic で拒否する。
### Phase 4: Path scope / sparse checkout / cache policies
- Ticket target / Worker launch request の path scope を materialization に渡す。
- Git sparse checkout を materializer strategy として追加する。
- heavy artifact exclude / dependency cache / build cache policy を導入する。
### Phase 5: CoW / snapshot materializer
- btrfs snapshot、Linux reflink、macOS APFS clonefile、Rift-like snapshot backend を materializer strategy として検討・実装する。
- `current_worktree_snapshot` policy を evidence と cleanup 付きで扱う。
- source root と generated workspace の registry / ancestor / cleanup model を設計する。
### Phase 6: Strong sandbox and remote Runtime support
- container filesystem / mount namespace / network policy / secret handle / tool authority を Runtime allocation と統合する。
- Runtime が複数 Workspace / Repository の Worker を同時に抱える場合の namespace、quota、cleanup、audit boundary を固める。
- remote/self-hosted/hosted Runtime fleet で repository cache と working directory storage をどう扱うかを設計する。
### 7. Worker / Session / workdir retention and cleanup policy
- Worker を保存・削除単位にする。Session / transcript は Worker に内包または参照される履歴として扱い、Session 単体を長期保存 authority にしない。
- Worker lifecycle は `running -> stopped -> delete` を基本にする。`archived` を lifecycle state として導入しない。
- Worker には `pinned` flag を持たせる。Pinned Worker は manual delete / cleanup / future automatic prune から守られる。
- Worker delete は Worker record と内包する Session / transcript history の削除を意味する。Workdir files は自動削除しない。
- Session / transcript は削除可能にする。圧縮 archive storage や高度な summarized retention は必要になった時点で別の storage policy として設計する。
- Workdir 実ファイルは durable history ではなく再現可能 cache として扱う。RepositoryPoint / resolved commit から再現でき、dirty/uncommitted state が無いなら、running Worker に紐づかない workdir files は manual cleanup eligible とする。
- Dirty Workdir は活動中または要判断状態として扱う。削除は可能だが、changes ごと消す explicit confirmation を要求する。Dirty orphan は recovery Worker 起動または explicit discard の判断対象であり、通常の clean cleanup と区別する。
- Workdir record は materialization evidence として扱う。実ファイルが削除済みなら `removed`、外部要因で欠落しているなら stale/missing materialization として診断可能にする。
- Worker と Workdir の関係は Backend registry の link table を authority にする。Worker record は最後に活動した RepositoryPoint / resolved commit / workdir binding summary を保持し、Stopped Worker + Removed Workdir でも必要に応じて再 materialize できるようにする。
- Cleanup/delete は当面 manual-first にする。削除前に対象、理由、削除される bytes、blocking conditionsrunning Worker、pinned Worker、dirty state、unreachable commit など)を plan として提示する。
- 将来的には容量/期限ベースの automatic prune を設定可能にする予定。ただし automatic prune は user-configured policy と pinned protection を前提にし、初期の manual cleanup/delete とは別段階で扱う。
- UI 表示は `workdir` に寄せる。内部型/API の互換名 `working_directory` は移行中に残ってよいが、Browser-facing navigation では Runtime 管理配下の `Workdirs` として扱う。
## Non-goals
- v0 で完全な container sandbox を実装すること。
- Worker ごとに full clone すること。
- `.yoi` や Backend workspace store に Worker working directory を置くこと。
- Git worktree を唯一の materialization strategy として固定すること。
- Dirty local changes を暗黙に Worker に渡すこと。
- Browser-facing API に raw host path、secret、Runtime internal store path を公開すること。
- Repository credential / secret distribution の本格設計をこの Objective だけで完了させること。
## Success criteria / exit conditions
- Runtime root、Repository cache、working directory、Backend/Workspace store の境界が文書化されている。
- Runtime が Worker spawn 前に working directory materializer を呼ぶ型と順序を持つ。
- Worker は source repository root ではなく materialized working directory を scope として起動する。
- working directory allocation が Runtime registry に記録され、cleanup policy を持つ。
- Git/local repository の v0 materializer が full clone 連発ではなく shared cache / detached worktree / cheap allocation の方向に進んでいる。
- dirty state policy が明示され、clean point、patch artifact、snapshot のどれを使ったか evidence に残せる。
- Runtime process 起動時の `--workspace` は legacy bootstrap input として隔離され、Runtime identity や single workspace binding とみなされない。
- Worker ごとの scope allocation conflict が、同一 source root を直接渡す設計ではなく materialized workspace allocation によって解消される。
- Sandbox / mount / cache / secret boundary を後続実装で強化できる model になっている。
- Worker record が Session / transcript refs と pinned flag を束ね、`pinned` Worker を cleanup/delete/future automatic prune から守れる。
- Workdir 実ファイルは再現可能 cache として manual cleanup/delete でき、削除前に plan-first で linked Worker、session retention、commit reachability、dirty/missing 状態を確認できる。
- 将来的に容量/期限ベースの automatic prune を user-configured policy として追加できる設計余地がある。
## References
- [Rift: Worktree alternative for fast copy-on-write workspaces](https://github.com/anomalyco/rift) — CoW snapshot / reflink / btrfs snapshot / APFS clonefile による高速 workspace creation、heavy regenerable artifacts の除外、workspace registry などを Runtime materializer backend 設計の参考にする。
## Decision context
- Runtime は Worker 群を束ねる実行基盤であり、Worker 用の作業環境を用意する責務を持つ。
- Repository は clone されるものではなく、RepositoryPoint から Worker 用 working directory として materialize される。
- Runtime execution storage は Backend/Workspace store と分離する。`.yoi` は Worker working directory 置き場ではない。
- full clone を Worker ごとに作らない。Runtime-local repository cache と Worker-local cheap workspace allocation を分ける。
- Git detached worktree は v0 materialization strategy として有力だが、Git worktree 固定の設計にはしない。
- CoW snapshot / reflink / btrfs snapshot / APFS clonefile / Rift-like workspace creation は、将来の materializer backend として検討する。
- Dirty local state は暗黙に渡さず、policy と evidence を持って扱う。
- Sandbox は後付けの別機能ではなく、working directory allocation と同じ境界で扱う。
+3
View File
@@ -0,0 +1,3 @@
default = "builtin:companion"
[profile]
+329
View File
@@ -0,0 +1,329 @@
---
description: worktree と sibling の coder / reviewer Pod を使い、下位 orchestrator が concrete Ticket 群の実装・外部レビュー・修正・完了準備を管理する orchestration フロー
model_invokation: true
user_invocable: true
requires: []
---
# Multi-agent Worktree Workflow
yoi を yoi で開発する際の、worktree + coder Pod + 外部 reviewer Pod + orchestrator Pod の標準フロー。これは **最上位 Pod が細かい code review を抱えず、下位 orchestrator が実装と外部レビューの loop を完了状態まで運ぶためのフロー** である。
worktree の機械的作成手順は `$user/worktree-workflow`、ユーザー依頼の Ticket 化は `$user/ticket-intake-workflow`、Ticket の next action 分類は `$user/ticket-orchestrator-routing`、実装前の planning/requirements sync は compatibility canonical id `$user/ticket-preflight-workflow` に分ける。
この Workflow は、対象 ticket が implementation-ready であることを前提にする。implementation-ready は full implementation plan ではなく、recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions に基づいて coder が bounded investigation を進め、reviewer が判断できる状態を指す。設計境界・仕様・authority boundary が未同期の場合は、worktree 作成や coder Pod 起動の前に planning/requirements sync 互換入口として `ticket-preflight-workflow` を通す。
## 目的
- 実装差分を ticket ごとの child worktree に隔離する。
- coder Pod に narrow write scope を渡して実装させる。
- reviewer Pod を coder の子ではなく **同じ orchestrator 配下の sibling** として立て、外部レビューを行わせる。
- orchestrator は coder / reviewer のやり取り、修正 loop、orchestration branch への integration、validation、Ticket 記録、child worktree cleanup に責任を持つ。
- 最上位 orchestrator は、コードを直接理解し切ることではなく、委譲した intent / 要件 / invariant に沿って下位 orchestrator が完了まで運んだかを acceptance する。
## Pod coordination model
基本形は以下。
```text
最上位 orchestrator Pod
- 人間との会話相手
- intent / 要件 / invariant / escalation 条件を定義
- 複数の作業群を並列管理
- root/original workspace での read/write/validation/cleanup/git 操作を行う
- 原則として line-by-line code review を主業務にしない
下位 orchestrator Podarea / concrete-ticket-set coordinator
- 連続した複数 concrete Ticket または大きめの concrete Ticket を完了状態まで運ぶ
- worktree / branch / coder / reviewer / validation / 修正 loop を管理する
- coder と reviewer を sibling として扱う
- orchestration branch 上の integration 結果と残論点だけを返す
coder Pod
- 指定 worktree / branch に実装する
- ticket 外判断や設計衝突は orchestrator に戻す
- reviewer に直接反論・修正依頼を完結させず、orchestrator に報告する
reviewer Pod
- 原則 read-only
- ticket / intent packet / diff / validation 結果を読む
- 実際のコード変更が概念的に何を変えたかを説明する
- intent / 要件 / invariant に反する blocker を分類して返す
```
一段だけで足りる小さい concrete Ticket では、最上位 orchestrator が直接 coder / reviewer sibling を扱ってよい。複数 concrete Ticket や設計境界をまたぐ作業では、最上位の下に下位 orchestrator を挟む。
この Pod coordination model は runtime delegation の形であり、Ticket hierarchy を作る根拠ではない。複数 Ticket を扱う場合も各 Ticket は concrete work item として独立に実装・レビュー・検証・close できる必要がある。broad effort の進捗コンテナとして umbrella Ticket、parent/child Ticket、sub-ticket、part-of、contains などを作らない。中期的な目的や戦略は Objective context に置き、typed Ticket relations が利用可能な場合も dependency / related / blocking / replacement などの非階層メタデータに限る。
明示的な queue review や routing kick の中で、独立した queued Ticket が複数あり coder/reviewer capacity が残っているなら、最初の Ticket の完了を待つことを default にしない。Orchestrator は各 Ticket の relation metadata、OrchestrationPlan records、Ticket thread、workspace/worktree dirty state、visible Pods、既存 branch、conflict notes を確認し、blocking relation や `do_not_parallelize` がなく、write surface が disjoint または conflict risk が小さく機械的に処理できるものを、別 worktree・別 branch・別 narrow write scope で並列開始する。これは background scheduler や queue drain loop ではなく、人間が queued にした Ticket だけを、その場の明示的な acceptance 判断で `queued -> inprogress` に進める運用である。
## 開始条件
以下が揃っている時に使う。
- 対象 concrete Ticket または concrete Ticket 群が決まっている。
- Ticket lifecycle を使う場合、対象はすでに `inprogress` であるか、worktree 作成・Pod spawn・coder routing の前に Orchestrator が個別に `queued -> inprogress` acceptance を記録できる `queued` Ticket に限る。unqueued Ticket は capacity 埋めの対象にしない。
- ticket の背景・意図・制約・受け入れ条件から、実装調査と局所 tactic 選択を coder に委ねても product / API / UX / authority / design-boundary decision を silently 固定しないと判断できる。
- worktree 作成と git 書き込み操作について、人間の許可がある。
- 下位 orchestrator に渡す binding decisions / invariants、implementation latitude、escalation conditions を短く書ける。
- 設計境界・仕様・authority boundary に不確定要素があり、bounded project-context checks 後も concrete missing decision / information が残る場合、planning/requirements sync 互換入口 `ticket-preflight-workflow` の結果が ticket thread に記録されている。
product / API / UX / authority / design-boundary 方針が複数自然に導ける場合、ticket 自体の再定義が必要な場合、または protocol / scope / permission / history persistence に触れる作業で bounded project-context checks 後も concrete missing decision / information が残る場合は、実装委譲前に planning/requirements sync 互換入口 `ticket-preflight-workflow` を通し、必要なら人間へ戻す。scope / Pod / permission / persistence のような authority-adjacent domain は reviewer focus と context lookup の signal であり、intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が明確なら coder に委ねてよい。実装ファイルの探索、既存コード読解、局所的な構成選択のような bounded implementation uncertainty も同様に coder に委ねてよい。
## Intent packet
階層化すると人間の意図が劣化しやすい。下位 orchestrator や coder / reviewer へは、自然文の依頼だけでなく intent packet を渡す。
標準形:
```text
Intent:
- 何を実現するか。
Binding decisions / invariants:
- 人間/Orchestrator/Ticket に記録済みで coder / reviewer が従うべき decision。
- 壊してはいけない設計境界、authority boundary、明示制約。
- 残してはいけない旧概念や互換層。
Requirements / acceptance criteria:
- 完了時に満たすべき observable な要件と reviewer が判断できる基準。
Implementation latitude:
- Coder が調査しながら選んでよい local tactic / file-local organization / bounded uncertainty。
Escalate if:
- 親へ戻すべき判断条件。特に product / API / UX / authority boundary / explicit design constraint を変える必要が出た場合。
Validation:
- 実行すべき format / build / test / doctor。
Reviewer focus:
- reviewer が確認すべき critical risks。
```
reviewer には coder の実装方針ではなく、この intent packet と diff を中心に読ませる。reviewer は recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / explicit escalation conditions に照らして判断し、不記録の preferred tactic を基準にしない。
## orchestrator の責務
下位 orchestrator を挟まない場合は、以下を最上位 orchestrator が行う。下位 orchestrator を挟む場合は、最上位は intent packet を渡し、以下の実務を下位に委譲する。
1. 状態確認
- `git status --short --branch`
- 対象 ticket / ticket 群
- relation metadata / OrchestrationPlan records / do_not_parallelize / conflict or dependency notes
- visible Pods、既存 worktree/branch、coder/reviewer follow-up capacity
- 関連 TODO / docs / 既存 worktree
- planning sync が必要な ticket では、互換入口 `ticket-preflight-workflow` の分類・要件同期・critical risks
2. worktree 作成
- 対象 Ticket が `queued` なら、この step の前に typed Ticket backend/tool path で `queued -> inprogress` を記録する。これより前に branch 作成、worktree 作成、Pod spawn、実装調査依頼などの implementation side effect を行わない。
- Orchestrator が dedicated orchestration worktree で動く場合、作業対象は Orchestrator workspace/orchestration branch と child implementation worktree に限定する。root/original workspace は read/write/validation/cleanup/git 操作の対象ではない。
- implementation worktree は記録済み implementation worktree root の `.worktree` 配下に置く。root/original workspace は配置基準としてだけ扱い、作業対象にしない。
- implementation branch は Orchestrator workspace の current HEAD/orchestration branch HEAD から作り、reviewer approve 後は orchestration branch へ自動 integration する。
- `.yoi` 自体は除外しない。tracked project records は child worktree に存在してよく、`.yoi/memory` と local/runtime/log/lock/secret-like paths だけを sparse checkout で除外する。
3. coder Pod spawn
- read scope: original workspace root 全体、または実装に必要な bounded read scope。
- write scope: child worktree、または必要最小 directory。
- task には以下を明示する。
- child worktree path / branch
- 対象 ticket path
- intent packet
- SpawnPod の `cwd` は child worktree に設定すること(`cwd` は process/tool default cwd であり、scope/authority ではない)
- Orchestrator workspace / recorded Ticket backend の `TODO.md` / Ticket records / `docs/report/` / `.yoi` は編集しないこと
- child worktree 内の tracked `.yoi` project records は実装対象に必要な branch-local artifacts/dossiers として編集してよいが、`.yoi/memory` や local/runtime/secret-like files は作らないこと
- active orchestration progress、review、integration、Ticket lifecycle update は Orchestrator workspace または recorded Ticket backend の責任として残すこと
- 遵守すべき binding decisions / invariants と escalation conditions
- 実行すべき build / test / format
- 完了報告項目
4. coder 完了確認
- `ReadPodOutput` で報告を読む。
- 通知が来ない場合でも、worktree の `git status` / `git diff` / test で完了状態を確認する。
- coder が止まった場合、worktree 状態を見て再 spawn / rollback / 親 escalation を判断する。
5. reviewer Pod spawn
- reviewer は coder の子ではなく orchestrator 配下の sibling として立てる。
- 原則 read-only scope にする。
- reviewer に渡すもの:
- ticket / intent packet
- branch / commit / diff の読み方
- 実行済み validation
- blocker / non-blocker / acceptable の分類基準
- reviewer の主目的は「コードの詳細を親の代わりに説明し、intent / invariant 違反を見つけること」。
6. review → 修正 loop
- reviewer finding を orchestrator が読む。
- blocker は coder に修正依頼する。
- reviewer の指摘を却下する場合は、orchestrator が理由を dossier に残す。
- 修正後は focused validation を実行し、必要なら reviewer に再確認させる。
- reviewer の blocker が未解決のまま親に提出しない。
7. orchestration branch integration
- 親がコードを直接理解しなくても判断できるよう、変更の概念的説明と evidence をまとめる。
8. integration / lifecycle
- reviewer approve と blocker 解消を確認し、implementation branch を Orchestrator workspace の orchestration branch へ integration する。
- Orchestrator workspace で必要な validation を実行し、Ticket thread に integration と validation の結果を記録する。
- Ticket を完了処理して commit する。TODO cleanup が対象 Ticket の明示要件なら child implementation worktree/branch に限定して行う。root/original workspace は触らない。
## coder Pod の責務
- child worktree 内でのみ実装する。
- root/original workspace の管理ファイルを読まない・書かない。
- child worktree 内の tracked `.yoi` project records は ticket 要件に必要な branch-local artifact/dossier として扱ってよい。
- `.yoi/memory`、local/runtime state、logs、locks、secret-like files を child worktree に作らない。
- intent / requirements / acceptance criteria / binding decisions / invariants / implementation latitude / escalation conditions を読んでから実装する。
- 実装ファイルの探索、既存コード読解、局所的な tactic 選択は、intent packet の implementation latitude 内で行ってよい。
- 指定された build / test / format を実行する。
- ticket 要件外または binding decisions/invariants 外の設計変更、依存関係追加、scope / permission / history persistence / prompt context 加工原則に触れる変更が必要なら止めて orchestrator に報告する。
- 完了時に以下を報告する。
- worktree path / branch
- commit hashcommit した場合)
- 変更ファイル
- 実装概要
- 実行した build / test / format
- 未解決事項
- review に回せるか
## reviewer Pod の責務
reviewer は coder の subordinate ではない。orchestrator 配下の sibling として、実装 diff を外部から読む。
- 原則 read-only で作業する。
- ticket / intent packet / diff / validation 結果を読む。
- 実際のコード変更が概念的に何を変えたかを説明する。
- 親や上位 orchestrator が line-by-line diff を読まずに判断できるよう、以下を整理する。
- 変更の概念モデル
- recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / explicit escalation conditions との対応
- binding decisions / invariants 違反の有無
- 旧概念・禁止語彙・不要な互換層の残存
- validation の妥当性
- blocker / non-blocker / follow-up
- reviewer は直接 merge しない。
- reviewer は coder に直接作業指示を出さず、orchestrator に finding を返す。
## commit 方針
coder Pod には child worktree 内での commit を許可してよい。
- commit は ticket 内で意味のある粒度にする。
- 例: `feat: ...``fix: ...``test: ...``docs: ...`
- coder Pod は merge / push / branch deletion / worktree remove をしない。
- coder Pod は recorded Ticket backend の Ticket 完了処理 commit、最終 review/approval/close をしない。child worktree 側には branch-local dossier や実装証跡を残してよい。
- orchestrator は review 時に commit 粒度も確認する。
- 必要な修正は、原則追加 commit として積む。履歴改変や squash は人間の明示指示がある時だけ行う。
## Review → 修正 → 完了の標準形
### Approve
reviewer が approve し blocker が残っていない場合、Orchestrator workspace の orchestration branch への integration、validation、Ticket 記録、child worktree cleanup まで自動的に進める。root/original workspace への read/write/validation/cleanup/git 操作は行わない。
1. coder Pod / reviewer Pod を停止し、scope を回収する。
2. orchestrator が Ticket、child worktree/branch、commits、reviewer verdict、validation evidence を確認する。
3. 最上位 orchestrator が必要最小限の spot check を行う。
4. Orchestrator workspace の orchestration branch で implementation branch を merge または project-agreed method で integration する。
5. Ticket を完了処理して commit する。TODO cleanup が対象 Ticket の明示要件なら child implementation worktree/branch に限定して行う。
6. Orchestrator workspace/orchestration branch で検証コマンドを再実行する。root/original workspace では実行しない。
7. 変更内容・commit・検証結果・残 dirty changes を報告する。
### Request changes
1. reviewer finding または orchestrator finding を blocker / non-blocker に分ける。
2. blocker はファイル / 行 / 理由 / 修正方針つきで coder に戻す。
3. coder が停止済みなら、同じ worktree / branch / scope で再 spawn する。
4. 修正後に focused test と必要な broader test を再実行する。
5. 必要なら reviewer に再確認させる。
6. blocker が解消したら dossier を更新する。
### Non-blocking comments
- ticket 要件外の改善はその場で混ぜない。
- 必要なら後続 ticket / docs/report にする。
- non-blocking を理由に completion を遅らせない。
## 並列実装時の注意
- 1 ticket = 1 worktree = 1 branch を基本にする。
- 複数 Pod に同じ write scope を渡さない。parallel Coder Pod は別 worktree と narrow write scope を持つ。
- parent / orchestrator は coder の write scope 配下を直接編集しない。
- reviewer は read-only を基本にする。明示的に別 scope を与える判断がない限り、review artifact を書かせる場合も ticket artifacts など限定 scope にする。
- independent queued Ticket は、blocking relation/dependency がなく、`do_not_parallelize` や relevant `conflicts_with` がなく、source/write surface が disjoint または conflict risk が小さく機械的で、coder/reviewer follow-up capacity があり、workspace records を side effect 前に commit でき、別 worktree/branch/scope を切れる場合に並列開始を優先する。
- 依存関係がある ticket、同一 migration boundary や同一 schema/tool/panel surface を大きく触る ticket、または reviewer/coder bottleneck がある ticket は、土台 branch を merge してから次 worktree を切るか、bounded defer reason を記録して idle にする。
- capacity が見えるのに queued Ticket を開始しない場合、dependency / conflict / capacity / missing planning decision / dirty workspace / reviewer-coder bottleneck / migration boundary / human gate のいずれかを bounded reason として Ticket thread または `TicketOrchestrationPlanRecord` に残す。
- parallel に走らせた Pod の完了通知は取りこぼしうるため、`ReadPodOutput` と worktree 状態で確認する。
- この節は自動 scheduler、background runner、resource graph solver、automatic queue drain loop を導入しない。parallel start は明示的な routing/acceptance の結果であり、unqueued Ticket を開始する根拠ではない。
## orchestration integration dossier の標準形
```text
Status:
- completed / blocked / needs parent decision
Scope:
- ticket(s): <path>
- branch: <name>
- commits:
- <hash> <subject>
Intent check:
- invariant 1: ok / violated / not applicable, evidence ...
- invariant 2: ok / violated / not applicable, evidence ...
Implementation summary:
- 変更の概念的説明: ...
- 主要変更ファイル: ...
- compatibility / migration: ...
Coder loop:
- coder pod: <name>
- produced commits: ...
- unresolved coder notes: ...
External review:
- reviewer pod: <name>
- blockers found: ...
- blockers fixed: ...
- rejected findings and reasons: ...
- non-blocking follow-ups: ...
Validation:
- cargo fmt --check
- cargo check --workspace
- cargo test ...
- yoi ticket doctor
Parent decision needed:
- none / specific question
Residual risk:
- ...
Dirty state:
- ...
```
## 最上位 orchestrator の acceptance
最上位 orchestrator は、下位 orchestrator の成果を code review するのではなく acceptance する。
確認するもの:
- intent packet が保持されているか。
- reviewer が coder と独立した sibling として機能したか。
- blocker が未解決のまま握りつぶされていないか。
- 変更の概念的説明が要件と対応しているか。
- validation が ticket のリスクに対して十分か。
- escalation すべき判断を下位が勝手に決めていないか。
必要なら spot check するが、常態的な line-by-line review に戻らない。
## この Workflow で扱わないもの
以下は `$user/ticket-intake-workflow``$user/ticket-orchestrator-routing`、または別の設計相談で扱う。
- ユーザー依頼を Ticket 化すること。
- Ticket の next action を分類すること。
- QA feedback / AI feedback を Ticket / report / workflow に落とす判断。
- 長期 maintainer loop / scheduler / LeaseStore の設計。
- reviewer Pod の品質評価を機械的に採点する仕組み。
+350
View File
@@ -0,0 +1,350 @@
---
description: ユーザーの曖昧な依頼を要件同期し、合意済みの Ticket として作成・更新する Intake workflow
model_invokation: true
user_invocable: true
requires: []
---
# Ticket Intake Workflow
Yoi の multi-agent 運用で、ユーザーの依頼をいきなり実装委譲せず、まず **合意済み Ticket** または「まだ Ticket 化しない」判断に変換するための Workflow。
この workspace workflow は bundled `resources/workflows/ticket-intake-workflow.md` を dogfooding 用に詳述した override である。Objective / split policy / local Ticket 運用の説明を追加するが、bundled workflow の調査ゲート、Ticket 作成前の user agreement、Intake の非 scheduler 境界を弱めてはならない。
Intake の目的は、ユーザーの意図・要件・制約・受け入れ条件・未決定点を明確にし、Orchestrator が次の routing を判断できる Ticket を作ることである。Intake は scheduler ではなく、coder / reviewer / read-only investigation helper Pod を起動しない。
## 位置づけ
```text
User request / conversation
-> Ticket Intake Workflow
-> TicketCreate / TicketComment
-> Orchestrator routing
-> planning sync / spike / implementation / review / blocked / close
```
- `Ticket` は durable orchestration record。
- `Objective` は medium-term goal / motivation / strategy / success criteria / decision context の project record。Objective context は判断背景であり、Ticket body/thread/artifacts を読む代替ではない。
- `Task` は session-local progress tracking。
- `Assignment` は Orchestrator から coder / reviewer Pod、または task-specific helper Pod への具体的委譲。
- `IntentPacket` は Ticket から抽出して Assignment に渡す短い実装・レビュー契約。
Intake は、要件同期と Ticket 化を担当する。実装の起動・worktree 作成・review 委譲・merge 判断は Orchestrator 側の責務である。`ready` は Orchestrator が routing できる状態を意味し、実装戦術がすべて事前固定されていることを意味しない。
Ticket に残す内容は、binding decisions / invariants、implementation latitude、escalation conditions を区別する。Coder が調査しながら局所的な実装手段を選べる余地は残してよいが、product / API / UX / authority boundary / explicit design constraint を silently 決める余地を残してはならない。
## Intake の責務
Intake は以下を行う。
- ユーザー依頼の主語と目的を確認する。
- 既存 Ticket を確認し、duplicate / related work を探す。
- 曖昧な依頼、現在挙動への claim、authority boundary、workflow/source-of-truth 変更では、Ticket 化前の最小調査ゲートとして関連 docs / code / workflow / history を読む。
- 不足している要件を質問する。
- 作成または refinement する Ticket が、実装・レビュー・検証・完了判断を単独で行える concrete work item であるか確認する。
- 広い依頼を分割する場合は、進捗コンテナとしての umbrella Ticket ではなく、concrete Ticket / Objective context / split decision record に責務を分ける。
- Objective-to-Ticket links を提案する場合は canonical opaque Ticket ID だけを使い、dependency / blocking / ordering relation として扱わない。
- Ticket の title / body/request snapshot / acceptance criteria / priority / readiness / risk flags を、現在の要件として意味がある範囲で提案する。
- canonical ID は Ticket 作成/storage が opaque な path-derived value として割り当てるため、Intake はユーザー向け metadata として提案しない。
- ユーザー主張、Intake が確認した事実、未確認仮説、未決定点を分けて整理する。
- background / requirements / acceptance criteria / escalation conditions を整理する。
- binding decisions / invariants と implementation latitude を分けて書く。
- 具体的な除外や触れてはいけない境界が binding decision である場合は、generic な除外リストではなく invariant / escalation condition として明記する。
- readiness / open questions / risk flags を明示する。
- ユーザー合意後にだけ official Ticket を作成する。
- 既存 Ticket の refinement を求められた場合は、TicketComment で経緯を残す。
## Intake がしないこと
- coder / reviewer Pod や read-only investigation helper Pod を起動しない。
- worktree を作らない。
- merge / close / branch cleanup をしない。
- implementation-ready でない Ticket を実装に投げない。
- unattended scheduler として自動実行しない。
- ユーザー合意なしに official Ticket を作らない。
- broad effort の進捗を保持するためだけの long-lived umbrella / progress-container Ticket を作らない。
- parent/child、sub-ticket、umbrella、part-of、contains などの hierarchy/container relation を split の代替として提案しない。
- secrets / private context を Ticket body / thread / artifacts / diagnostics に保存しない。
- arbitrary filesystem write で `work-items/` を編集しない。Ticket 操作は Ticket tools を使う。
## 使用する Ticket tools
利用可能なら、以下の typed Ticket tools を使う。
- `QueryTicket`: 既存 Ticket の一覧・重複確認。
- `ShowTicket`: 関連 Ticket の詳細確認。
- `TicketCreate`: 合意済み Ticket の作成。
- `TicketComment`: 既存 Ticket refinement / decision / plan の記録。
Intake は `MergeRequest*`, `TicketWorkflowState`, `TicketClose` を通常使わない。review authority は assigned Coder が起動した read-only direct-child Reviewer の immutable Merge Request attempt に属し、completion / merge / close は各guarded workflowの責務である。
Ticket tools が利用できない環境では、勝手に file write で代替しない。ユーザーまたは Orchestrator に「Ticket tools がないため materialize できない」と報告し、必要なら `yoi ticket` を使える人間/親 workflow に戻す。
## 手順
### 1. 依頼を受け取る
ユーザー依頼を短く言い換え、以下を分ける。
- 何を変えたいか。
- なぜ必要か。
- 影響を受けるユーザー / Pod / workflow / crate / docs。
- 既に決まっていること。
- まだ未決定のこと。
この段階では Ticket を作らない。ユーザー発話は request snapshot / claim として扱い、確認済み requirements と混同しない。
### 2. 既存 Ticket を確認する
`QueryTicket` / `ShowTicket` で duplicate / related work を探す。
確認観点:
- 同じ目的の未完了 Ticket がないか。
- closed Ticket の判断・resolution と矛盾しないか。
- 既存の umbrella/progress-container Ticket が、superseded/decomposed として退役できる状態か。
- 既存 concrete follow-up Ticket や Objective context で足りるか、新規 concrete Ticket が必要か。
既存 Ticket の更新で足りる場合、新規 Ticket を作らず、ユーザーに更新案を提示する。
### 2.1. Ticket 化前の最小調査ゲート
`TicketCreate` または material な `TicketComment` の前に、以下の gate を通す。
必ず行うこと:
- duplicate / related / blocking-looking Ticket を確認する。
- 既存 Ticket を更新するなら、その Ticket の item/thread/artifacts を読む。
- ユーザー claim と、Intake が読んで確認した fact を分ける。
次のいずれかに当たる場合は、Ticket 作成前に関連 docs / code / workflow / prompt / config / history を読む。
- 依頼が曖昧、または複数の concrete work item を含む。
- 「現在の挙動」「既存仕様」「壊れている」「既にある」など、事実確認を要する claim がある。
- scope / permission / history / prompt context / persistence / public API など authority boundary に触れる。
- prompt / workflow resource、Ticket schema、source-of-truth 境界の変更に触れる。
- 既存実装の map がないと requirements / acceptance criteria を誤って固定しそうである。
Gate output は draft に以下を分けて残す。
- User claims / request snapshot: ユーザーが述べたこと。
- Confirmed facts / sources: Intake が読んで確認したことと source。
- Unverified hypotheses: ありそうだが未確認の推測。
- Undecided points / open questions: ユーザーまたは Orchestrator の判断が必要なこと。
調査が大きい、current-code map がない、または仕様同期が足りない場合は、official Ticket を作らず draft で止める。readiness は `spike_needed` / `requirements_sync_needed` / `blocked` のいずれかを付け、次に必要な調査や質問を報告する。確認できない claim を requirements / acceptance criteria として保存しない。
### 2.5. Broad request の split policy
1つの依頼が複数の implementable work item を含む場合、Intake は以下を提案する。
- broad effort を表す umbrella/progress-container Ticket は新規作成しない。
- concrete slice ごとに、単独で実装・レビュー・検証・close できる Ticket を作る。
- split した理由と残した範囲は、関連 Ticket の thread、必要なら Objective context に記録する。
- Objective は中期的な目的・方針・success criteria を保持するために使う。Objective record の実装や schema 追加はこの workflow の責務ではない。
- typed Ticket relation が利用可能になった場合も、dependency / related / blocking / replacement / supersedes などの非階層メタデータに限る。
- parent/child、sub-ticket、part-of、contains のような hierarchy/container relation を作らない。
ユーザーが「まず調査 Ticket」「設計 Ticket」「計画 Ticket」を concrete work item として求める場合は作成してよい。禁止されるのは、他の concrete Ticket の進捗を持つためだけに長期 open となる container Ticket である。
### 3. 要件を同期する
最低限、以下を確認する。
- ユーザー claim のうち、どれが確認済み fact で、どれが未確認仮説か。
- observable な完了条件は何か。
- 作業の種類・影響範囲は prose として body に書けばよいが、current Ticket core metadata として扱わない。
- 受け入れ条件は何か。
- binding decision として残す具体的な除外・authority boundary はあるか。
- 後方互換が必要か。
- authority boundary / scope / permission / history / prompt context に触れるか。
- validation は何で確認できるか。
- 人間判断が必要な論点は何か。
不足がある場合は、Ticket 作成前に質問する。質問は多すぎず、Ticket 作成に必要な最小限に絞る。調査が先に必要な場合は `spike_needed`、仕様同期が先に必要な場合は `requirements_sync_needed` として draft に留める。
### 4. readiness を分類する
Ticket 作成または更新前に、readiness を明示する。
```text
implementation_ready:
- 意図・受け入れ条件・binding decisions / invariants / implementation latitude が明確。
- Reviewer が判断できる基準と escalation conditions が明確。
- 実装調査や局所的な tactic 選択は残っていてよいが、product / API / UX / authority boundary / explicit design constraint を coder が silently 決める余地はない。
- validation が書ける。
requirements_sync_needed:
- 目的は見えているが、仕様・用語・UX・責務境界・受け入れ条件が未同期。
- ユーザー claim を requirements として固定するには合意や確認が足りない。
spike_needed:
- 技術調査、依存関係、性能、license、diagnostics、現在コード map が先に必要。
- どの files/workflows/Tickets を読むべきかは見えているが、Intake の最小調査では実装可能な要件まで確定できない。
blocked:
- 人間判断、外部イベント、別 Ticket の完了が必要。
unspecified:
- どうしても分類不能な時だけ使う。理由を Ticket に書く。
```
### 5. open questions / risk flags を付ける
以下に触れる Ticket は risk flags と reviewer/orchestrator focus を Ticket body に短く明記する。これは stop gate ではない。具体的な未決定 decision / information がある場合だけ、blocking open question として記録する。
- profile / manifest / scope / permission。
- session / history / Pod metadata / persistence。
- prompt context 加工原則。
- public API / plugin / feature boundary。
- security / secret / credential handling。
- storage migration / backward compatibility。
- 複数の自然な設計方針があるもの。
- reviewer が diff だけでは見落としやすい設計リスク。
risk flags は短い語でよい。missing boundary がすでに人間/Orchestrator の Ticket-recorded decision で補われている場合は、その decision を根拠に Orchestrator が routing できる。単に risk があるだけなら Orchestrator は Ticket を戻さず、IntentPacket に escalation / reviewer focus を明記して進める。
例:
```text
risk_flags: [authority-boundary, persistence, prompt-context, public-api]
```
### 6. Ticket draft を提示する
ユーザーに作成前 draft を提示する。
標準 draft:
```text
Title:
Priority:
Readiness:
Next Ticket operation: draft_only | create_after_user_agreement | update_existing_after_user_agreement | no_ticket
Risk flags:
User claims / request snapshot:
Confirmed facts / sources:
Unverified hypotheses:
Undecided points / open questions:
Background:
Requirements:
Acceptance criteria:
Binding decisions / invariants:
Implementation latitude:
Escalation conditions:
Validation:
Related tickets/docs/files:
```
canonical ID は作成時に storage が opaque/path-derived value として割り当てるため、draft では提案しない。
この時点ではまだ Ticket を作らない。`Next Ticket operation``draft_only` / `no_ticket` の場合は、ユーザー合意があっても `TicketCreate` ではなく追加同期または調査へ戻す。
### 7. ユーザー合意を取る
以下のどちらかがあるまで official Ticket を作らない。
- ユーザーが draft を明示的に承認する。
- ユーザーが「作って」「切って」「記録して」など、作成を明示する。
未決定のまま記録する場合は、`requirements_sync_needed` / `spike_needed` / `blocked` として未決定点を明示する。ユーザー合意は「この未決定状態で記録する」ことへの合意であり、未確認仮説を requirements 化する許可ではない。
### 8. Ticket を作成または更新する
新規 Ticket の場合:
- `TicketCreate` を使う。
- title / priority / body と、必要な readiness / risk flags を指定する。canonical ID は storage が割り当てる。
- body に readiness / open questions / risk flags と、binding decisions / invariants、implementation latitude、escalation conditions を Markdown で明記する。
- user claims、confirmed facts、unverified hypotheses、undecided points / open questions を分けて書き、未確認 claim を requirements / acceptance criteria として保存しない。
既存 Ticket refinement の場合:
- `TicketComment` を使う。
- role は内容に応じて `comment`, `plan`, `decision` を選ぶ。
- 既存 `item.md` の大幅変更が必要なら、Orchestrator / maintainer に戻す。
### 9. 作成後の報告
ユーザーへ以下を返す。
- 作成/更新した Ticket の system-assigned id / title。
- readiness。
- open questions / risk flags。
- 次に Orchestrator が取るべき routing 候補。
- 未決定点があれば、そのまま明示する。
Intake はここで止まる。implementation / worktree / coder / reviewer 起動は Orchestrator routing の責務である。
## Ticket body の推奨形
```markdown
## User claims / request snapshot
## Confirmed facts / sources
## Unverified hypotheses
## Undecided points / open questions
## Background
## Requirements
## Acceptance criteria
## Binding decisions / invariants
## Implementation latitude
## Readiness
- readiness: implementation_ready | requirements_sync_needed | spike_needed | blocked | unspecified
- risk_flags: [...]
## Escalation conditions
## Validation
## Related work
```
Ticket の body は Markdown/freeform を維持する。すべてを strict schema に押し込まない。
## secret / private context policy
以下は Ticket に保存しない。
- API keys / tokens / credentials。
- secret file contents。
- private prompts / model responses that should not become project records。
- user private context not needed for project history。
- raw logs containing secrets。
必要なら、保存せずに「secret/config が必要」とだけ書く。
## 完了条件
この Workflow の完了条件は次のいずれかである。
- ユーザー合意済みの新規 Ticket が作成され、Orchestrator が routing できる情報が揃っている。
- 既存 Ticket に refinement / decision / plan が記録され、次の routing が明確である。
- Ticket 化しない判断がユーザーに説明され、未決定の問いまたは関連 Ticket が明確になっている。
## 他 Workflow への接続
- `ticket-preflight-workflow`: legacy compatibility planning/requirements sync 入口。新規 routing は standalone preflight ではなく planning return/requirements sync として扱う。
- `multi-agent-workflow`: Orchestrator が implementation_ready と判断した後に接続する。
- `ticket-orchestrator-routing`: この Workflow が作った Ticket を routing する後続 Workflow。
@@ -0,0 +1,419 @@
---
description: Ticket を読み、Orchestrator が planning return / spike / implementation / review / blocked / close へ明示的に routing する workflow
model_invokation: true
user_invocable: true
requires: []
---
# Ticket Orchestrator Routing Workflow
Yoi の multi-agent 運用で、Intake や人間が作成した Ticket を Orchestrator が読み、次に取るべき action を明示的に分類・記録するための Workflow。
これは scheduler ではない。目的は、Ticket の fields / body / thread / artifacts / 現在の repository/Pod 状態を明示的に確認し、隠れた会話状態ではなく Ticket に基づいて routing 判断を残すことである。
Panel Queue / queued notification は、人間が Orchestrator に routing を開始してよいと許可した signal であり、unattended scheduler ではない。implementation side effect に進む場合は、Orchestrator が Ticket と workspace state を再確認し、unblocked と判断してから `queued -> inprogress` を記録する必要がある。明示的な routing / queue review / panel kick の中で、独立した queued Ticket と coder/reviewer capacity が複数あるなら、1件ずつ完了を待つことを default にせず、安全確認を満たす範囲で追加 Ticket の並列開始を優先する。
`ready` は Orchestrator routing に十分な状態であり、実装戦術が事前にすべて固定されている状態ではない。Orchestrator は、recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / escalation conditions が揃っていれば、bounded implementation uncertainty を残したまま implementation-ready と判断してよい。
`ready` / `queued``planning` に戻す判断は、Ticket text や risk flags だけで決めない。Orchestrator は、Ticket thread/artifacts、関連 Ticket / orchestration plan、関連 workflow/docs/code、durable project context、現在の repository/Pod/worktree 状態のうち relevant なものを bounded に確認し、実装前に必要な concrete missing decision / information が残っている場合だけ planning return とする。risk flags と risky domain は context lookup と reviewer focus の signal であり、automatic stop gate ではない。
## 位置づけ
```text
TicketCreate / TicketComment
-> Ticket Orchestrator Routing Workflow
-> planning return / requirements sync / spike / implementation / review / blocked / close
-> 必要に応じて他 Workflow へ接続
```
- Intake は Ticket の materialization と planning/clarification を担当する role であり、state 名ではない。
- state は `planning -> ready -> queued -> inprogress -> done` を基本遷移とする。
- `ticket-preflight-workflow` は legacy canonical id 互換の planning/requirements sync entry であり、`preflight` を独立 state / lane / long-lived operation として扱わない。
- `ready -> queued` は人間が Orchestrator routing を許可した状態であり、worktree 作成や Pod 起動の許可そのものではない。
- `multi-agent-workflow` は coder / reviewer Pod と worktree を使う実装・レビュー loop。
- この Workflow は自動 scheduler / lease / unattended maintainer ではない。
## Orchestrator の責務
Orchestrator は以下を行う。
- Ticket を `ShowTicket` で読む。
- 必要に応じて関連 Ticket を `QueryTicket` / `ShowTicket` で確認する。
- Ticket body / thread / artifacts / resolution / review / implementation report を読む。
- Ticket が Objective context と結びついている場合は、Objective を medium-term goal / motivation / strategy / success criteria / decision context として読む。ただし Objective context は判断背景であり、Ticket body/thread/artifacts や explicit Ticket relations / OrchestrationPlan records を読む代替ではない。
- repository 状態、関連 docs/code、既存 worktree、visible Pods を必要に応じて明示的に確認する。
- queued notification を受けた場合も、Ticket と workspace state を再確認してから routing する。
- next action を routing classification として決める。
- routing decision を `TicketComment` で Ticket thread に記録する。
- broad request や split/refinement では、long-lived umbrella/progress-container Ticket ではなく concrete implementable Ticket、Objective context、split decision record を使う。
- Objective-to-Ticket links は canonical opaque Ticket ID による non-blocking context link として扱い、dependency / blocking / ordering / ownership / scheduling relation と解釈しない。
- 既存 umbrella/progress-container Ticket が concrete follow-up Ticket / Objective context で置き換え済みなら、superseded/decomposed として退役・close する routing を検討する。
- implementation-ready の場合は `multi-agent-workflow` に渡す `IntentPacket` を作る。
- implementation-ready かつ Ticket が `queued` の場合は、worktree 作成 / implementation Pod `SpawnPod` / coder routing などの side effect の前に、既存の typed Ticket backend/tool path で `queued -> inprogress` を記録する。
- 人間による `ready -> queued` は、記録済み Ticket scopeについて、実装、current MRのguarded merge、completion記録、Ticket closeまでをWorkspace Orchestratorへ委任するdurable gateである。Orchestratorは`queued -> inprogress`を受理した後、current-ref approval、repository evidence、blocking relations、merge CASを確認して完了まで進め、別のmerge確認を待たない。Ticketがseparate approval gateを明記する場合、またはqueued scope外の新しい判断が必要な場合だけ停止する。
- 明示的な queue review 中に、他にも queued Ticket が見え、capacity が空いている場合は、各 Ticket について relation / orchestration-plan / dirty state / visible Pods / worktree / conflict risk を確認し、独立して受理できるものを同じ routing pass で追加の `queued -> inprogress` 候補にする。
- queued Ticket を capacity が見える状態で idle のまま残す場合は、dependency / conflict / capacity / missing planning decision / dirty workspace / reviewer-coder bottleneck / migration boundary / human gate のいずれかに絞った bounded reason を Ticket thread または `TicketOrchestrationPlanRecord` に残す。
- `ready` または `queued` に concrete missing decision / information がある場合だけ、typed state-change/routing event 付きで `planning` に戻す。その event/comment には missing item、checked context、implementation latitude では足りない理由、次の planning question/action を含める。
## Orchestrator がしないこと
- 自動 scheduler として unattended に実行しない。
- Panel Queue / queued notification だけを unattended scheduler trigger として扱わない。
- `queued -> inprogress` acceptance なしに worktree 作成、implementation Pod `SpawnPod`、coder/reviewer routing を行わない。
- 人間/上位 Orchestrator の許可または明示的な routing acceptance なしに coder / reviewer Pod や read-only investigation helper Pod を起動しない。
- unqueued Ticket を capacity 埋めのために開始しない。parallel start の候補は、個別に `queued` であり、人間が routing を許可済みの Ticket に限る。
- 設計境界の未決定を勝手に implementation-ready として固定しない。
- Ticketが`ready -> queued`されておらず完了権限を委任されていない場合、またはTicketがseparate approval gateを明記する場合に、勝手にmerge / close / cleanupしない。queued delegationとguarded completion evidenceが揃っている場合は、追加のhuman gateを作らず完了まで進める。
- Ticket tools があるからといって arbitrary filesystem write を行わない。
- broad multi-Ticket effort のために新しい umbrella/progress-container Ticket を作らない。
- parent/child、sub-ticket、umbrella、part-of、contains などの hierarchy/container relation を split/refinement の代替として扱わない。
- Notification だけを完了証拠にしない。Pod output / diff / validation / Ticket evidence を確認する。
- 具体的な不足項目を言語化できない場合に、単に risky という理由だけで `planning` に戻さない。その場合は IntentPacket に escalation / reviewer focus を明記して進める。
- risk flags / risky domain / authority-adjacent domain を automatic stop gate として扱わない。これらは bounded context lookup、IntentPacket invariant、reviewer focus、escalation condition に反映する signal である。
## 使用する Ticket tools
利用可能なら、以下を使う。
- `QueryTicket`: routing 候補、関連 Ticket、project-level forward relation (`depends_on` / `blocks` / `related` / `supersedes` / `duplicate_of`) と derived blocker summary を bounded filter/projection で確認する。`depends_on` と incoming unresolved `blocks` は queue/acceptance blocker であり、`related` は blocker ではない。`supersedes` / `duplicate_of` は visible diagnostic として扱い、自動的な lifecycle 変更や scheduler 判断にはしない。
- `ShowTicket`: 対象 Ticket の body / thread / artifacts / resolution / typed relation metadata、linked Objective、assignment、implementation/review evidence を確認する。
- `TicketComment`: routing decision / intent packet / blocked reason / next question の記録。
- `TicketWorkflowState`: `queued -> inprogress` acceptance、`inprogress -> done`、または concrete missing decision/information reason を伴う `ready|queued -> planning` に使う。
- `TicketDependencyCheck`: queue/acceptance 直前の typed dependency readiness guard に使う。
- `TicketRelationRecord` / `TicketRelationRemove`: ユーザー合意済みの durable project relation を明示的に更新する場合だけ使う。
- `TicketOrchestrationPlanQuery`: 対象 Ticket や関連 Ticket の ordering / blocker / conflict / waiting-capacity / accepted-plan 記録を読む。queued acceptance 前に必ず確認する。
- `TicketOrchestrationPlanRecord`: Orchestrator が routing 中に project-relevant な ordering / dependency / conflict / capacity/waiting / accepted-plan decision を残す。これは queue reorder、自動起動、state 変更ではない。
- `TicketClose`: 完了権限と resolution が揃っている場合だけ使う。
`TicketCreate` は通常 Intake の責務だが、routing 中に follow-up Ticket が必要だと判断した場合は、ユーザー/上位 Orchestrator の合意後にだけ使う。
## Queued acceptance contract
- `queued -> inprogress` acceptance の直前に `ShowTicket` / `QueryTicket` の relation blocker projection を再確認する。unresolved `depends_on` や incoming unresolved `blocks` が残る場合は implementation side effect を始めず、理由を thread に残して `planning` へ戻すか blocked diagnostic として停止する。
- Relation metadata は project-level constraint であり、OrchestrationPlan は runtime ordering/capacity decision である。relation を OrchestrationPlan で代替しないし、OrchestrationPlan を durable dependency authority として扱わない。
`state = queued` は、Ticket が routing 対象として人間により Orchestrator へ渡された状態である。Orchestrator は queued notification を受けたら、Ticket、workspace state、対象 Ticket の `TicketOrchestrationPlanQuery` 記録、risk domain に応じた bounded project context を読んで、次のどちらかを行う。
- unblocked と判断する場合: `queued -> inprogress` を記録してから worktree 作成、implementation/review Pod spawn、その他の implementation side effect に進む。
- `before` / `after` / `blocked_by` / `blocks` / `conflicts_with` / `do_not_parallelize` / waiting-capacity 記録がある場合、それを acceptance 判断の入力にする。記録は自動 scheduler ではないため、実際に進めるかどうかは Orchestrator が読んだうえで明示的に決める。
- risk flags / risky domain がある場合は、IntentPacket に invariants / reviewer focus / escalation conditions を入れる。risk flag だけを `queued -> planning` の理由にしない。
- concrete missing decision / information がある場合: `TicketWorkflowState``queued -> planning` を記録し、reason/body と `TicketComment` に不足項目、checked context、なぜ coder の implementation latitude では解決できないか、次の planning question/action を残す。既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。
- external action 待ちなど planning では解決しない blocker の場合: concise な理由を Ticket thread に記録し、必要に応じて attention / action-required frontmatter や `TicketOrchestrationPlanRecord` の blocker/waiting-capacity 記録で明示する。lifecycle 外の storage bucket を routing target にしない。
Parallel acceptance pass:
- 明示的な queue review 中に複数の queued Ticket が見える場合、Orchestrator は最初の1件の完了待ちを default にしない。各 Ticket について Ticket body/thread/artifacts、QueryTicket の relation/blocker projection、TicketOrchestrationPlanQuery、workspace/worktree dirty state、visible Pods、既存 branches、conflict/dependency notes を確認する。
- 追加で開始してよいのは、blocking relation/dependency がなく、`do_not_parallelize` または applicable conflict record がなく、source/write surfaces が disjoint または conflict risk が小さく機械的で、coder/reviewer follow-up capacity があり、acceptance basis となる Ticket thread/plan/workspace records を side effect 前に記録・commit でき、別 worktree/branch/scope を切れる Ticket だけである。
- capacity が見えるのに queued Ticket を idle にする場合は、dependency / conflict / capacity / missing planning decision / dirty workspace / reviewer-coder bottleneck / migration boundary / human gate のいずれかの bounded reason を記録する。
- この pass は scheduler、background runner、resource graph solver、automatic queue drain loop ではない。unqueued Ticket を開始せず、各 Ticket の `queued -> inprogress` acceptance を個別に記録する。
Invariant:
- `queued -> inprogress` は Orchestrator acceptance marker であり、coder Pod が既に動いていることの後追い記録ではない。
- `queued -> inprogress` に失敗した場合、implementation/review Pod を spawn しない。
- `inprogress` acceptance 後に worktree/spawn/first-run が失敗した場合は、queued に黙って戻さず、in-progress Ticket に failure/block/recovery note を記録する。
- Queue notification だけを根拠に blind spawn しない。必ず Ticket と workspace state を再確認する。
## Routing classification
Orchestrator は対象 Ticket を以下のいずれかに分類する。複数に見える場合は、次に必要な action が最も早いものを選ぶ。
### `requirements_sync_needed`
まだ `planning` に留めるべき、または `planning -> ready` に進める前に clarification が必要な状態。
条件:
- Ticket の目的は見えるが、observable な完了条件が書けない。
- ユーザー判断がないと product/API/UX を固定してしまう。
- acceptance criteria、binding decisions / invariants、または escalation conditions が不足している。
- existing decisions / docs / closed Tickets と矛盾する可能性がある。
Action:
- Intake / human / Planning sync に戻す。
- `TicketComment` で不足情報と質問を記録する。
- coder Pod は起動しない。
### `return_to_planning`
`ready` または `queued` とされているが、bounded project-context checks の後でも、実装 side effect 前に解決すべき concrete missing decision / information が残っている状態。
条件:
- product / API / UX / authority boundary / storage migration / security / secrets などについて、実装前に決めなければならない具体項目がある。
- 複数の自然な方針があり、human / Orchestrator decision なしでは固定できない。
- acceptance criteria、binding decisions、または escalation conditions に、実装可否を左右する具体的欠落がある。
- Ticket text / risk flags だけではなく、関連 Ticket/thread/artifacts、orchestration plan、関連 workflow/docs/code、durable project context、現在の workspace evidence の relevant subset を確認しても、既存 recorded decision が見つからない。
- その不足は coder の bounded implementation latitude / local tactic selection では安全に解消できない。
Action:
- `TicketWorkflowState``ready -> planning` または `queued -> planning` を記録する。
- reason/body と `TicketComment` に以下を明記する。
- concrete missing decision / information。
- context checkedTicket thread/artifacts、関連 Ticket/plan、docs/workflow/code/durable context/workspace state のうち実際に確認したもの)。
- why implementation latitude is insufficient(なぜ coder/reviewer の local tactic や escalation condition では足りないか)。
- next planning question/action。
- risk flag / risky domain だけを return reason にしない。
- 既存の claimed live/restorable Intake/Planning Pod があり、既存通知経路が使える場合は同じ理由を通知する。実用的な経路がない場合は follow-up として report する。
- planning が再度 `ready` にするまで coder Pod は起動しない。
### `spike_needed`
実装前に read-only 調査が必要。
条件:
- 技術的実現性が不明。
- dependency / license / packaging / portability / performance / diagnostics の確認が必要。
- current code map が不足している。
- bug の再現条件や観測 evidence が不足している。
Action:
- read-only investigation を提案する。
- 許可があれば task-specific read-only helper Pod を普通の scoped Pod として起動できる。
- `TicketComment` に調査問い・scope・完了条件を記録する。
- 実装 worktree はまだ作らない。
### `implementation_ready`
既存 multi-agent workflow に渡せる状態。
条件:
- intent / binding decisions / invariants / implementation latitude / acceptance criteria が明確。
- binding decisions / invariants と implementation latitude が区別されている。
- reviewer が判断する basis と escalation conditions が明確。
- validation が書ける。
- design / authority boundary の未決定がない、または planning return / human decision で補われている。
- risk flags / risky domain は context lookup と reviewer focus に反映済みで、bounded context check 後に concrete missing decision / information が残っていない。
- 残る不確実性が bounded implementation investigation / local tactic selection に閉じている。
- IntentPacket を短く書ける。
Action:
- `IntentPacket` を作る。risky-but-specified Ticket では、risk を stop reason にせず、binding invariants / implementation latitude / escalation conditions / Critical risks / reviewer focus として記録する。
- project-relevant な ordering / blocker / conflict / capacity decision や accepted work plan がある場合は、`TicketOrchestrationPlanRecord` に bounded typed record として残す。local session/socket/raw model output は入れない。
- `TicketComment` に routing decision と IntentPacket を記録する。
- 許可があれば `multi-agent-workflow` に接続し、worktree + coder/reviewer sibling loop に進む。
### `review_needed`
実装はあるが、review / acceptance が未完了。
条件:
- implementation report / branch / commit / diff がある。
- external review がない、または reviewer blocker が未解決。
- validation evidence が足りない。
Action:
- reviewer Pod 起動または追加 validation を提案する。
- reviewer は recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / explicit escalation conditions に照らして判断する。不記録の好みや Orchestrator の未共有 preferred tactic を基準にしない。
- `TicketComment` に review target と確認観点を記録する。
- blocker 未解決のまま merge-ready としない。
### `blocked_by_dependency_or_missing_authority`
人間判断または外部イベント待ち。
条件:
- design/product/security 判断が必要だが、planning で同期すれば進められる種類ではない。
- credential / secret / environment / external service が必要。
- 別 Ticket / branch / upstream change の完了待ち。
- scope/permission が不足している。
Action:
- 必要な判断・外部 action を短く書く。
- `TicketComment` に blocked reason と next question を記録する。
- 必要に応じて typed relation metadata や orchestration plan の blocker/waiting-capacity 記録で、待ち理由を current state とは別に表す。lifecycle 外の storage bucket へ移す route は使わない。
### `close_ready`
完了処理に進める状態。
条件:
- requirements / acceptance criteria が満たされている。
- review / validation / merge / cleanup evidence が揃っている。
- resolution を書ける。
- close 権限がある。
- 既存 umbrella/progress-container Ticket については、concrete follow-up Ticket と必要な Objective context が存在し、container role を superseded/decomposed として退役できる。
Action:
- `TicketClose` または既存 close workflow で resolution を記録する。
- umbrella/progress-container Ticket を退役する close resolution では、関連作業がすべて完了したという意味ではなく container role を retired したことを明記し、完了済み concrete Ticket と残る follow-up Ticket / Objective を列挙する。
- close 権限がない場合は merge-ready / close-ready dossier を親/人間に提出する。
### `closed_or_noop`
routing 不要。
条件:
- closed Ticket。
- duplicate として既存 Ticket に統合済み。
- Ticket 自体が不要と判断済み。
Action:
- 追加 action なし。
- 必要なら related Ticket へ comment する。
## Routing 手順
### 1. 状態確認
- `git state --short --branch`
- `ShowTicket <target>`
- 関連 Ticket の `QueryTicket` / `ShowTicket`
- 必要に応じて docs/code/workflow/history
- 必要に応じて visible Pods / worktrees / branches
この段階で unrelated dirty changes がある場合、実装/merge には進まず、routing decision の記録だけに留めるかユーザーに確認する。
### 2. Ticket evidence を読む
最低限、以下を確認する。
- Background
- Requirements
- Acceptance criteria
- Binding decisions / invariants
- Implementation latitude
- Readiness / open questions / risk flags
- Escalation conditions
- Validation
- Thread の plan / decision / implementation_report / review
- Artifacts / branch / commit references
- risk flags が示す domainauthority-boundary / scope / permission / Pod / persistence / prompt-context / public-api など)
### 3. Bounded project-context checks を行う
Ticket evidence だけで planning return を決めない。risk flags や risky domain がある場合は、必要な最小限の project context を確認する。
代表的な確認先:
- Ticket thread/artifacts/resolution と関連 Ticket。
- `TicketOrchestrationPlanQuery` の accepted-plan / ordering / blocker / conflict 記録。
- 関連 workflow/docs/design/development docs。
- 現在の code map や既存 implementation pattern。
- durable memory/Knowledge/project decisions(利用可能で、判断に関係する場合)。
- repository / branch / worktree / visible Pod state。
目的は broad repository archaeology ではなく、以下を区別できるだけの bounded check である。
- genuinely missing binding decision / requirement / invariant / acceptance criterion。
- Ticket thread、関連 Ticket、docs/workflows/code、durable context にすでに記録された decision。
- coder が implementation latitude の中で選べる local tactic / bounded investigation。
### 4. Classification を決める
例:
- implementation-ready に見えるが authority boundary の explicit decision がなく、bounded context check でも recorded decision がない → concrete missing decision として `return_to_planning`; routing record に missing item / checked context / implementation latitude では足りない理由 / next question を書く。
- implementation-ready に見えるが単に risk が高い → `implementation_ready` とし、IntentPacket に escalation / reviewer focus を明記する。
- `allow-spawnpod-child-workspace-cwd` のように scope / Pod / authority-adjacent domain に触れるが、intent、authority invariants、implementation latitude、escalation conditions が指定済み → `implementation_ready`。context check で既存 SpawnPod scope/cwd policy と workflow invariants を確認し、reviewer focus に authority leakage / workspace-cwd separation / delegation-scope preservation を入れる。risk domain だけを理由に `planning` へ戻さない。
- 実装済みだが review がない → `review_needed`
- 要件が曖昧で spike も必要そう → `requirements_sync_needed` を優先し、調査問いを明確化する
- 完了しているが close 権限がない → `close_ready` として dossier を返す
### 5. Routing decision を Ticket に記録する
`TicketComment` の role は通常 `decision` または `plan` を使う。
標準形:
```markdown
Routing decision: <classification>
Reason:
- ...
Evidence checked:
- Ticket body / thread / artifacts
- related Ticket(s) / orchestration plan records
- code/docs/workflow paths
- branch/worktree/Pod state if relevant
If returning to planning:
- Missing decision/information: ...
- Context checked: summarize the relevant subset from Evidence checked above
- Why implementation latitude is insufficient: ...
- Next planning question/action: ...
Next action:
- ...
Escalate if:
- ...
```
### 6. IntentPacket を作る(implementation_ready の場合)
`multi-agent-workflow` に渡す前に、以下を短くまとめる。
```text
Intent:
- 何を実現するか。
Binding decisions / invariants:
- 人間/Orchestrator/Ticket に記録済みで coder / reviewer が従うべき decision と、壊してはいけない design / authority boundary。
- 具体的な除外・触れてはいけない場所が binding decision である場合はここに書く。
Requirements / acceptance criteria:
- 完了時に満たす observable な要件と reviewer が判断できる基準。
Implementation latitude:
- Coder が調査しながら選んでよい local tactic / file-local organization / bounded uncertainty。
Escalate if:
- 親/人間に戻す判断条件。特に product / API / UX / authority boundary / explicit design constraint を変える必要が出た場合。
Validation:
- 実行すべき format / build / test / doctor。
Current code map:
- 実装対象と触ってはいけない場所。
Critical risks / reviewer focus:
- reviewer にも見てほしい失敗パターン。reviewer は recorded intent / binding decisions / invariants / implementation latitude / acceptance criteria / explicit escalation conditions に照らして判断し、不記録の preferred tactic を基準にしない。
```
IntentPacket が短く書けない場合、`implementation_ready` ではなく `return_to_planning` または `requirements_sync_needed` に戻す。
### 7. 後続 Workflow へ接続する
- `requirements_sync_needed``ticket-intake-workflow` / human / planning sync
- `return_to_planning``ticket-preflight-workflow`legacy compatibility canonical id の planning sync entry
- `spike_needed` → read-only investigation plan / Pod(許可後)
- `implementation_ready``multi-agent-workflow`
- `review_needed` → reviewer Pod / review workflow
- concrete blocker / missing decision → human / parent Orchestrator
- `close_ready` → close workflow / maintainer decision
## 完了条件
この Workflow の完了条件は次のいずれかである。
- routing decision が Ticket に記録され、次に接続する Workflow / human action が明確である。
- `ready` / `queued``planning` に戻した場合、typed state-change/routing event に concrete missing decision / information、checked context、implementation latitude では足りない理由、次の planning question/action が残っている。
- implementation-ready Ticket について IntentPacket が Ticket に記録され、`multi-agent-workflow` に渡せる。
- requirements-sync / planning return / spike / blocked / review / close-ready の理由と次 action が Ticket に記録されている。
- routing 不要と判断され、その理由が明確である。
## この Workflow で固定しないもの
- unattended scheduler。
- LeaseStore / queue persistence。
- queue/dashboard UI。
- automatic Pod spawning policy。
- TicketUpdate tool の導入。
- external tracker integration。
これらは routing decision を人間/Orchestrator が明示的に扱えるようになった後の follow-up とする。
@@ -0,0 +1,89 @@
---
description: 互換 canonical id を残した Ticket planning / requirements sync workflow。preflight を独立 lane や state として扱わない。
model_invokation: true
user_invocable: true
requires: []
---
# Ticket Planning / Requirements Sync Workflow
このファイル名は既存の workflow discovery / durable references 互換のために残す。新しい概念としての `preflight` state / lane / long-lived operation は作らない。ここで扱う作業は、Ticket を `planning` に戻して不足している決定・情報・受け入れ条件を同期するための planning activity である。
## 目的
実装に入る前または Orchestrator routing 中に、bounded project-context checks 後も concrete missing decision / information / acceptance condition が残る Ticket を planning に戻し、Ticket thread に監査可能な形で同期内容を残す。
この workflow は次をしてはいけない。
- `preflight` を state として扱う。
- `preflight` vocabulary を current Ticket metadata として新規に書く。
- 「リスクがある」だけで Ticket を戻す。
- broad effort の進捗を保持するためだけの umbrella/progress-container Ticket を作る。
- parent/child、sub-ticket、part-of、contains などの hierarchy/container relation を split/refinement の代替として設計する。
- Coder / Reviewer / worktree mechanics を再設計する。
## 適用条件
次のいずれかを満たす場合に使う。
- `planning` Ticket の要件・受け入れ条件・制約を明確化する。
- ユーザーが concrete work item として求めた initial planning / design / investigation Ticket の scope と acceptance criteria を明確化する。
- `ready` または `queued` Ticket について、Orchestrator が Ticket/thread/artifacts、関連 Ticket/plan、関連 workflow/docs/code、durable project context、workspace evidence の relevant subset を bounded に確認したうえで、実装開始前に concrete missing decision / information を特定した。
- 既存 Ticket に obsolete state vocabulary が残っており、planning terminology へ整理する必要がある。
適用しない条件:
- Orchestrator が具体的な不足項目、checked context、implementation latitude では足りない理由を言語化できない。
- 単に変更範囲が広い、リスクが高い、またはレビュー観点が多いだけである。
- すでに `queued -> inprogress` が記録され、実装 side effect が始まっている。
この場合は Ticket を戻さず、IntentPacket に escalation / reviewer focus を明記して進める。
## 手順
1. Ticket の current frontmatter と recent thread を読む。
2. `ready` / `queued` から planning に戻す場合は、関連 Ticket/plan、docs/workflow/code、durable project context、workspace state の relevant subset を bounded に確認する。
3. 不足している decision / information / acceptance condition を箇条書きで特定し、なぜ coder/reviewer の implementation latitude や escalation condition では足りないかを書く。
4. `ready` または `queued` から戻す場合は、typed state change で `to = planning` を記録する。reason/body には concrete missing item、checked context、implementation latitude では足りない理由、次の planning question/action を含める。
5. 既存の claimed live/restorable Intake/Planning Pod があり、利用可能な通知経路がある場合は、その Pod に同じ不足理由を通知する。実用的な経路が無い場合は follow-up として report する。
6. Ticket body または thread に requirements sync 結果を残す。広い依頼を分割する場合は、concrete follow-up Ticket / Objective context / split decision record へ責務を分け、umbrella container や hierarchy relation を作らないことを記録する。
7. Ticket が queue 可能になったら `planning -> ready` を typed state change / `TicketIntakeReady` で記録する。
## 記録テンプレート
```markdown
## Planning sync
Missing decisions / information:
- ...
Context checked:
- Ticket/thread/artifacts: ...
- related Ticket/plan: ...
- docs/workflow/code/durable/workspace context: ...
Why implementation latitude is insufficient:
- ...
Next planning question/action:
- ...
Decisions made:
- ...
Acceptance criteria changes:
- ...
Risk / reviewer focus:
- ...
Readiness:
- Keep in planning because ...
- or mark ready because ...
```
## 完了条件
- Ticket に具体的な不足項目または解決済み decision が記録されている。
- `planning` に戻した場合、state_changed event または thread に concrete missing decision / information、checked context、implementation latitude では足りない理由、次の planning question/action が残っている。
- `ready` に進める場合、未解決の blocking attention/action が残っていない。
+171
View File
@@ -0,0 +1,171 @@
---
description: yoi プロジェクトで child git worktree を作成・管理するための機械的手順。coder Pod に作らせず、orchestrator Pod が Orchestrator workspace/orchestration branch から実行する。
model_invokation: true
user_invocable: true
requires: []
---
# Worktree Workflow
yoi プロジェクトで実装差分を root/original workspace から分離するため、記録済み implementation worktree root の `.worktree/<task-name>` に child git worktree を作る。これは **worktree の扱い方だけ** を定める Workflow であり、ticket 選定、coder / reviewer sibling の起動、外部レビュー、orchestration branch への integration は `/multi-agent-workflow` 側で扱う。
yoi では Pod の write scope が排他的に委譲されるため、child Pod の write scope は child worktree に限定する。child worktree は Yoi project records marker として tracked `.yoi` records を含んでよいが、generated/personal memory root `.yoi/memory`、local override、runtime state、logs、locks、secret-like files は出さない。Orchestrator workspace or recorded Ticket backend remains the place for active orchestration progress, review evidence, integration records, and Ticket lifecycle updates.
## 適用範囲
この Workflow は親 Pod / 下位 orchestrator が Orchestrator workspace/orchestration branch から実行する。root/original workspace は read/write/validation/cleanup/git 操作の対象にしない。implementation worktree は記録済み implementation worktree root 配下に作る。
- coder Pod にこの Workflow を渡して worktree を作らせない。
- coder Pod は、orchestrator が作成済みの child worktree を受け取り、その中で実装・build・test・報告を行う。
- reviewer Pod は、coder Pod の子ではなく orchestrator 配下の sibling として、原則 read-only で child worktree と Orchestrator workspace の Ticket/context を読む。
- ticket 作成、active orchestration progress、review evidence、integration、Ticket lifecycle update は Orchestrator workspace または記録済み Ticket backend 側で扱う。
- branch-local artifacts / dossiers / docs/report / tracked `.yoi` project records は、実装対象に必要なら child worktree 内で扱ってよい。
## 原則
- 1 ticket / 1 実装 task につき 1 worktree を作る。
- 複数 ticket を下位 orchestrator に任せる場合も、実装差分は ticket / bounded task ごとに worktree を分ける。
- worktree path は `<implementation-worktree-root>/.worktree/<task-name>`
- branch 名は原則 `<task-name>` と同じ kebab-case。
- child worktree には `.yoi` project records を出してよい。
- child worktree では `.yoi/memory`、local/runtime/log/lock/secret-like paths を sparse checkout で除外する。
- active orchestration progress、review evidence、integration、Ticket lifecycle update は Orchestrator workspace または記録済み Ticket backend 側で扱う。branch-local artifacts/dossiers は child worktree 内に置いてよい。
- push はしない。
## 事前確認
作成前に以下を確認する。
1. 対象 ticket / task が決まっているか。
2. `<task-name>` が branch / path 名に使える kebab-case か。
3. `git worktree add` を実行してよい許可があるか。
4. root/original workspace で実行しようとしていないか。
5. 同名 branch / worktree が既に存在しないか。
6. coder / reviewer を sibling として扱う orchestrator が誰か明確か。
同名 branch がある場合は、既存 branch を使うか、人間に確認する。`git worktree add -b` で上書きしない。
## 作成手順
Orchestrator workspace で実行する。root/original workspace では実行しない。
```bash
git -C <orchestrator-workspace-root> worktree add <implementation-worktree-root>/.worktree/<task-name> -b <task-name> HEAD
git -C <implementation-worktree-root>/.worktree/<task-name> sparse-checkout init --no-cone
git -C <implementation-worktree-root>/.worktree/<task-name> sparse-checkout set --no-cone \
'/*' \
'!/.yoi/memory/' \
'!/.yoi/memory/**' \
'!/.yoi/logs/' \
'!/.yoi/logs/**' \
'!/.yoi/_logs/' \
'!/.yoi/_logs/**' \
'!/.yoi/**/_logs/' \
'!/.yoi/**/_logs/**' \
'!/.yoi/locks/' \
'!/.yoi/locks/**' \
'!/.yoi/**/*.log' \
'!/.yoi/**/*.lock' \
'!/.yoi/**/.lock' \
'!/.yoi/override.local.toml' \
'!/.yoi/**/*.local' \
'!/.yoi/**/*.local.*' \
'!/.yoi/local/' \
'!/.yoi/local/**' \
'!/.yoi/runtime/' \
'!/.yoi/runtime/**' \
'!/.yoi/pods/' \
'!/.yoi/pods/**' \
'!/.yoi/sessions/' \
'!/.yoi/sessions/**' \
'!/.yoi/sockets/' \
'!/.yoi/sockets/**' \
'!/.yoi/tmp/' \
'!/.yoi/tmp/**' \
'!/.yoi/cache/' \
'!/.yoi/cache/**' \
'!/.yoi/secrets/' \
'!/.yoi/secrets/**' \
'!/.yoi/**/*.secret' \
'!/.yoi/**/*.secret.*'
```
この sparse-checkout は `.yoi` 自体を除外しない。`.yoi/memory` は generated/personal memory marker として child worktree から外し、generated log trees は root `_logs` だけでなく recursive `.yoi/**/_logs/**` も外す。memory root detection の実装変更はこの Workflow では扱わない。
確認する。
```bash
git -C <implementation-worktree-root>/.worktree/<task-name> status --short --branch
test ! -e <implementation-worktree-root>/.worktree/<task-name>/.yoi/memory
if test -d <implementation-worktree-root>/.worktree/<task-name>/.yoi; then
test ! -e <implementation-worktree-root>/.worktree/<task-name>/.yoi/override.local.toml
test -z "$(find <implementation-worktree-root>/.worktree/<task-name>/.yoi \
\( -path '*/_logs' -o -path '*/logs' -o -path '*/locks' \
-o -path '*/local' -o -path '*/runtime' -o -path '*/pods' \
-o -path '*/sessions' -o -path '*/sockets' -o -path '*/tmp' \
-o -path '*/cache' -o -path '*/secrets' -o -name '*.log' \
-o -name '*.lock' -o -name '.lock' -o -name '*.local' \
-o -name '*.local.*' -o -name '*.secret' -o -name '*.secret.*' \) \
-print -quit)"
fi
```
この確認は `.yoi` project records の存在を失敗扱いしない。`.yoi/memory` と local/runtime/log/lock/secret-like paths が出ていないことを確認する。
失敗した場合は、worktree / branch / lock の状態を確認し、勝手に cleanup せず人間へ報告する。
## Pod へ渡す scope
Pod を使う場合、coder Pod の SpawnPod `cwd` は child worktree に設定する。`cwd` は child process/tool default cwd だけを変え、runtime workspace root・project record root・scope/authority は変えないため、下の明示 scope は別途渡す。
coder Pod 推奨 scope:
```text
read: <implementation-worktree-root>/.worktree/<task-name>
write: <implementation-worktree-root>/.worktree/<task-name>
```
reviewer Pod 推奨 scope:
```text
read: <implementation-worktree-root>/.worktree/<task-name>
read: <orchestrator-workspace-root> # Ticket/intent/review context が必要な範囲に限定する
```
reviewer は原則 write scope を持たない。review artifact を書かせる必要がある場合だけ、ticket artifacts など限定 directory を write scope として渡す。
より狭く切れる場合は、coder の write scope を変更対象 crate / directory まで狭めてよい。ただし build / test に必要な生成物を書けることを確認する。
## child worktree 内の禁止事項
- `.yoi/memory` を作らない / コピーしない / 復元しない。
- local overrides、runtime sockets/state、Pod session mirrors、cache/tmp、logs、locks、secret-like files を作らない / コピーしない / commit しない。
- root/original workspace の `TODO.md` / `tickets/` / `docs/report/` / `.yoi` を読まない・編集しない。
- active orchestration progress、review evidence、integration、Ticket lifecycle update を child worktree 内だけで完結させない。
- 実装対象に必要な tracked `.yoi` project records、branch-local artifacts / dossiers / docs/report は child worktree 内で扱ってよい。
- merge / push / branch deletion / worktree remove をしない。
- scope / permission / history persistence / prompt context 加工原則に関わる設計変更を無断で行わない。
## 完了時の扱い
worktree 作成 Workflow としては、完了時に integration しない。orchestration branch への integration、Ticket 完了、child worktree cleanup は `/multi-agent-workflow` 側で Orchestrator workspace に対して行う。root/original workspace は対象にしない。
coder Pod へ渡す完了報告項目の標準形:
- worktree path
- branch 名
- commit hashcoder Pod に commit を許可した場合)
- 変更ファイル
- 実装概要
- 実行した build / test / format
- 未解決事項
- review に回せるか
reviewer Pod へ渡す完了報告項目の標準形:
- 読んだ ticket / intent packet / diff
- 実際のコード変更の概念的説明
- intent / requirements / invariant との対応
- blocker / non-blocker / follow-up
- validation の妥当性
- 親または上位 orchestrator が判断すべき残論点
+22
View File
@@ -0,0 +1,22 @@
workspace_id = "0197a949-4b6b-7f2a-9d9a-1f87e3a4c5b6"
created_at = "2026-06-23T00:00:00Z"
display_name = "yoi"
[ticket]
language = "Japanese"
[ticket.backend]
provider = "builtin:yoi_local"
root = ".yoi/tickets"
[ticket.roles.intake]
profile = "builtin:intake"
[ticket.roles.orchestrator]
profile = "builtin:orchestrator"
[ticket.roles.coder]
profile = "builtin:coder"
[ticket.roles.reviewer]
profile = "builtin:reviewer"
+42 -53
View File
@@ -1,77 +1,66 @@
すでにシステムのドッグフーディングに成功しており、改善・機能追加のフェーズになっている。 すでにシステムのドッグフーディングに成功しており、ブラウザ/TUI Client/backend/runtimeの分離とチームスペースとしてのworkspaceの実装を進めている。
随所の細かい仕様を詰めながら実装を進めている。
## このシステムに置ける設計要旨 ## このシステムに置ける設計要旨
- プロンプトはすべて resources/promptsに集約している。管理効率の向上と同時に、ユーザーがオーバーライドする形式でもある。 - プロンプトはすべて`resources/prompts`に集約している。管理効率の向上のためであると同時に、ユーザーがオーバーライドする形式でもある。
- E2E(実プロセスをスポーンさせてのテスト)は未設計。
- 変更量を最小にするために設計を歪めたり、設計問題に対して不必要な後方互換性を作らない。長期的なメンテナンスと型安全性を追求すること。 - 変更量を最小にするために設計を歪めたり、設計問題に対して不必要な後方互換性を作らない。長期的なメンテナンスと型安全性を追求すること。
### LLM コンテキストの加工原則 ### LLM コンテキストの加工原則
LLM に投げる context への割り込みは、大きく2種類に分かれる。**前者は許されるが、後者は禁止** LLM に投げる context はappend-onlyが基本であり、またその永続化形式からAPIコールの形式を純粋に再現可能である必要が有る
Podの状態から純粋に再現可能で、且つ揮発性の無い操作であることが望ましい。(pruning、tool result の content 切り詰め、prompt cache anchor の付与等) 一時的にメッセージを差し込む等の、揮発性の有るコンテキストの改変や、過去のメッセージを改ざんすることは基本的に禁止されている
原則として、コンテキストは積み重ねるものであり、一時的にメッセージを差し込むことや、過去のメッセージを改ざんすることはKVキャッシュのヒット率を下げる。 これを行うと、 LLM はそのコンテキストに基づいて生成を行う一方、次以降のターンでhistoryに残らないため、「自分がなぜその発言/tool call をしたか」の根拠が消えるうえ、prompt cache のヒット率も低下させることになる。
**禁止**: ターンを跨ぐことができない情報に基づいて、history に記録せずに context だけにコンテンツを差し込むこと。これをやると LLM はそれに反応して生成を行う一方、次以降のターンでhistoryに残らないため、「自分がなぜその発言/tool call をしたか」の根拠が消えるうえ、prompt cache のヒット率も低下させることになる。 過去のコンテキストの圧縮は、キャッシュ破壊とトークン消費のトレードオフであり、必要であれば行っている。
しかし、キャッシュを破壊するタイミングと頻度は正確にコントロールされる必要があり、実際のセッションデータの解析に基づいて慎重に設計されるべきである。
新しい input を context に乗せたいなら、必ず先に `worker.history` に append して commit すること。`history.json` への永続化はそこから自動的についてくる。Notify / PodEvent / `<system-reminder>` 系はこの原則で扱う。
また、キャッシュを破壊するタイミングは正確にコントロールされる必要があり、キャッシュ破壊とトークン消費のトレードオフに基づいて慎重に設計されるべきである。
--- ---
## 実際のセッションを読んでデバッグする ## 検証
`~/.insomnia/sessions`にすべてのセッションがある。jsonlなので、いい感じにBashで読むこと 開発中は、変更した契約を証明する最小の target / filter から実行する
```sh
cargo test -p <crate> --lib <test-or-module-filter>
cargo test -p <crate> --test <test-target> <test-filter>
```
完了前には、workspace rootで必ず`cargo check`を実行する。rootの`cargo check`
`default-members`に含まれるTUIやServerを含む通常のcompile closureを確認するため、公開型の
変更ごとにLLMがreverse dependencyを推測して`-p`を列挙する運用にはしない。
```sh
cargo check
cargo test -p <changed-crate>
cargo fmt --all -- --check
git diff --check HEAD
```
変更したcrate全体のtestに加え、影響するfeature構成やtest-only targetがある場合は、その検証を
追加する。`cargo check`はtestを実行せず、通常有効でないfeatureまでは確認しないため、semanticな
証明とfeature境界の検証はtargeted test/checkで補う。
workspace全体のtest、`--all-targets`、E2E、Nix/Docker buildなどの重い検証は、変更した境界を
通常のroot checkと狭い検証では証明できない場合や、明示的に要求された場合に選ぶ。実行した検証が
何を証明するのかを意識し、広い検証を形式的に回すだけにしない。
--- ---
## Git操作 ## ドッグフーディング時の Ticket 境界
明示的に指示されない限り、読み取り以外の操作は控えること。 Yoi Worker で作業する場合、Ticket の authority・ライフサイクル・操作方法は Yoi
基本はworktree上の一時的なブランチでコミットを重ね、メインブランチに取り込む運用をしている system instructions と、その Worker に提供された typed Ticket tools に従うこと
コミットメッセージは適当に`<prefix>: *簡潔な1行*`で書いている。
外部の参考プロジェクトは必要に応じてローカルの外部 checkout からReadすること。 Codex など typed Ticket tools が提供されていないクライアントでは、`yoi ticket`
CLI や保存先の直接操作で Ticket tools を代替しないこと。Ticket の作成・更新は
Yoi Worker に委ねる。
--- ---
## Work item / Ticket の運用について YoiでYoiを開発している際、AI自身のフィードバックを元に改善を回すために `docs/report/`ディレクトリに感じた障壁や改善案等を書き残す形にした。 明確に力不足な点/ツールの問題があった場合や、ユーザーからの指示があった際に作ること。
作業管理は `work-items/``tickets.sh` を正とする。時系列・状態遷移の最終的な根拠は git history なので、work item の作成・更新・レビュー・完了はファイル操作と commit で表現する。
### 基本コマンド
- 新規作成: `./tickets.sh create --title "..." [--slug slug] [--kind task] [--priority P2] [--label a,b]`
- 一覧: `./tickets.sh list [--status open|pending|closed|all]`
- 詳細: `./tickets.sh show <id-or-slug>`
- コメント / 計画 / 判断 / 実装報告: `./tickets.sh comment <id-or-slug> [--role comment|plan|decision|implementation_report] [--file path]`
- レビュー記録: `./tickets.sh review <id-or-slug> --approve|--request-changes [--file path]`
- 状態変更: `./tickets.sh status <id-or-slug> open|pending|closed`
- 完了: `./tickets.sh close <id-or-slug> [--resolution text|--file path]`
- 整合性確認: `./tickets.sh doctor`
`tickets.sh``work-items/{open,pending,closed}/<id>/` 配下の `item.md``thread.md``artifacts/` を扱う。完了時は `resolution.md` も作られる。手でファイルを作るより、原則としてスクリプトを使うこと。
### Work item の粒度
- 1 work item = 完了時点で、実装が仕様または機能として説明できる粒度。
- 作成時は背景・要件・受け入れ条件を明確にする。実装手順やコード詳細は、必要になるまで増やしすぎない。
- チケット内の Phase / Step は実装順序であり、外部の依存関係管理として扱わない。
- ビルドが通り、その機能に限り「まだ動作できない」と明示できている場合を除き、全体として動作可能な状態を保つ。
### ライフサイクル
- 作成: `./tickets.sh create ...``work-items/open/...` を作成し、必要な前提を書いて commit する。
- 詳細化・前提変更: `item.md` を更新し、必要に応じて `./tickets.sh comment``thread.md` に経緯を残して commit する。
- レビュー: `./tickets.sh review <id-or-slug> --approve|--request-changes``thread.md` にレビュー結果を追記して commit する。
- 完了: `./tickets.sh close <id-or-slug>``work-items/closed/...` に移動し、`resolution.md` と完了状態を commit する。
worktree と併用して作業を進める場合、必ずブランチを切る前に対象 work item を作成・詳細化して commit してから切ること。
レビューは diff の確認だけでなく、work item の前提・要件・受け入れ条件が提出された実装で満たされているかを確認する。常に、その実装で良いのか、コードベースを歪めていないか、不必要な実装ではないかを確認すること。
--- ---
insomniaでinsomniaを開発している際、AI自身のフィードバックを元に改善を回すために `docs/report/`ディレクトリに感じた障壁や改善案等を書き残す形にした。 明確に力不足な点/ツールの問題があった場合や、ユーザーからの指示があった際に作ること。 絶対に自身が動作しているプロセスを止めないこと。
マージ後のドッグフーディング環境の更新は必ずユーザーの操作で行う。
-75
View File
@@ -1,75 +0,0 @@
全体設計が概ね固まり、随所の細かい仕様を詰めながら実装を進めている。
## このシステムに置ける設計要旨
- プロンプトはすべて resources/promptsに集約している。管理効率の工場と同時に、ユーザーがオーバーライドする形式でもある。
- E2E(実プロセスをスポーンさせてのテスト)は未設計。
- 変更量を最小にするために設計を歪めたり、設計問題に対して不必要な後方互換性を作らない。長期的なメンテナンスと型安全性を追求すること。
### LLM コンテキストの加工原則
LLM に投げる context への割り込みは、大きく2種類に分かれる。**前者は許されるが、後者は禁止**。
Podの状態から純粋に再現可能で、且つ揮発性の無い操作であることが望ましい。(pruning、tool result の content 切り詰め、prompt cache anchor の付与等)。
原則として、コンテキストは積み重ねるものであり、一時的にメッセージを差し込むことや、過去のメッセージを改ざんすることはKVキャッシュのヒット率を下げる。
**禁止**: ターンを跨ぐことができない情報に基づいて、history に記録せずに context だけにコンテンツを差し込むこと。これをやると LLM はそれに反応して生成を行う一方、次以降のターンでhistoryに残らないため、「自分がなぜその発言/tool call をしたか」の根拠が消えるうえ、prompt cache のヒット率も低下させることになる。
新しい input を context に乗せたいなら、必ず先に `worker.history` に append して commit すること。`history.json` への永続化はそこから自動的についてくる。Notify / PodEvent / `<system-reminder>` 系はこの原則で扱う(→ `tickets/notify-history-persist.md`)。
また、キャッシュを破壊するタイミングは正確にコントロールされる必要があり、キャッシュ破壊とトークン消費のトレードオフに基づいて慎重に設計されるべきである。
---
## 実際のセッションを読んでデバッグする
`~/.insomnia/sessions`にすべてのセッションがある。jsonlなので、いい感じにBashで読むこと。
---
## Git操作
workflowで明示されない限り、読み取り以外の操作は控えること。
基本はworktree上の一時的なブランチでコミットを重ね、メインブランチに取り込む運用をしている。
コミットメッセージは適当に`<prefix>: *簡潔な1行*`で書いている。
外部の参考プロジェクトは必要に応じてローカルの外部 checkout からReadすること。
---
## Ticketの運用について
`TODO.md``tickets/`はgitで管理されていて、時系列の管理はgitを参照して把握すること。
### TODO.md
- 1チケット = 1行。未完了のみ記載し、完了したら行ごと削除する(履歴はgitで追える)
- ネストは同一領域のグルーピング(表示用)にのみ使う。実装上の依存関係はネストで表現しない
- 完了した子は削除し、親は未完了の子がある限り残す。最後の子が完了したら親ごと削除
- Ticketを追加する際は、合わせてTODOも書くこと
### Ticket の粒度
- 1チケット = 完了時点で、実装が仕様又は機能として説明できる粒度。
- 作成時、背景や要件を前提として書き、実装の方針やコードの詳細は不必要に増やさない。
- チケット内のステップ(Phase 1, 2, ...)は実装順序であり、TODO等、外に出さない
- ビルドが通り、その機能に限り,まだ動作できないと明示出来ている場合を除いて全体を通して動作させられる状態である必要がある。
### Ticket のライフサイクル
gitがタイムラインの単一の情報源。ファイル操作とcommitで状態遷移を表現する。
a. 作成: `tickets/foo.md` を作成してcommit
b. 詳細化や前提の変化: `tickets/foo.md` を更新してcommit
c. レビュー: `tickets/foo.md` にレビュー状態を追記 + `tickets/foo.review.md` を作成してcommit
d. 完了: `tickets/foo.md``tickets/foo.review.md` を両方削除してcommit
worktreeと併用して作業を進める場合、必ずブランチを切る前に対象のチケットをコミットしてから切ること。
TODO.mdのリンクは完了後に切れるが、そのリンクを元にgitで消されたファイルを読み、内容を把握できる。
`.review.md` にはレビューの指摘事項と判断結果を記載する。
レビューはdiffの確認だけでなく、チケットはどのような前提・要件であり、それが達成されたかの確認まで含めて行う。
常に、提出された実装で良いのか、コードベースを歪めていないか、不必要な実装ではないかを確認すること。
---
insomniaでinsomniaを開発している際、AI自身のフィードバックを元に改善を回すために `docs/report/`ディレクトリに感じた障壁や改善案等を書き残す形にした。 明確に力不足な点/ツールの問題があった場合や、ユーザーからの指示があった際に作ること。
Generated
+2001 -302
View File
File diff suppressed because it is too large Load Diff
+93 -13
View File
@@ -2,58 +2,138 @@
resolver = "2" resolver = "2"
members = [ members = [
"crates/client", "crates/client",
"crates/daemon", "crates/agen",
"crates/llm-worker", "crates/agen-macros",
"crates/llm-worker-macros",
"crates/session-store", "crates/session-store",
"crates/standalone",
"crates/secrets",
"crates/manifest", "crates/manifest",
"crates/pod", "crates/mcp",
"crates/pod-store", "crates/worker",
"crates/worker-runtime",
"crates/plugin-pdk",
"crates/yoi",
"crates/protocol", "crates/protocol",
"crates/provider",
"crates/pod-registry",
"crates/session-metrics", "crates/session-metrics",
"crates/session-analytics",
"crates/lint-common", "crates/lint-common",
"crates/tools", "crates/tools",
"crates/fs-operation",
"crates/flow",
"crates/config-source",
"crates/config-source-wasm",
"crates/workdir",
"crates/tui", "crates/tui",
"crates/memory", "crates/memory",
"crates/workflow", "crates/ticket",
"crates/merge-request",
"crates/project-record",
"crates/workspace-api",
"crates/workspace-server",
"tests/e2e",
]
default-members = [
"crates/client",
"crates/agen",
"crates/agen-macros",
"crates/session-store",
"crates/standalone",
"crates/secrets",
"crates/manifest",
"crates/mcp",
"crates/worker",
"crates/worker-runtime",
"crates/plugin-pdk",
"crates/yoi",
"crates/protocol",
"crates/session-metrics",
"crates/session-analytics",
"crates/lint-common",
"crates/tools",
"crates/fs-operation",
"crates/flow",
"crates/config-source",
"crates/config-source-wasm",
"crates/workdir",
"crates/tui",
"crates/memory",
"crates/ticket",
"crates/merge-request",
"crates/project-record",
"crates/workspace-api",
"crates/workspace-server",
] ]
[workspace.package] [workspace.package]
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
[profile.dev]
debug = "line-tables-only"
[profile.dev.package."*"]
debug = false
[workspace.dependencies] [workspace.dependencies]
# Internal crates # Internal crates
client = { path = "crates/client" } client = { path = "crates/client" }
llm-worker = { path = "crates/llm-worker", version = "0.2" } agen = { path = "crates/agen", version = "0.2" }
llm-worker-macros = { path = "crates/llm-worker-macros", version = "0.2" } agen-macros = { path = "crates/agen-macros", version = "0.2" }
manifest = { path = "crates/manifest" } manifest = { path = "crates/manifest" }
mcp = { path = "crates/mcp" }
lint-common = { path = "crates/lint-common" } lint-common = { path = "crates/lint-common" }
memory = { path = "crates/memory" } memory = { path = "crates/memory" }
pod-registry = { path = "crates/pod-registry" } merge-request = { path = "crates/merge-request" }
pod-store = { path = "crates/pod-store" } ticket = { path = "crates/ticket" }
project-record = { path = "crates/project-record" }
worker = { path = "crates/worker" }
worker-runtime = { path = "crates/worker-runtime" }
workspace-api = { path = "crates/workspace-api" }
yoi-plugin-pdk = { path = "crates/plugin-pdk" }
yoi = { path = "crates/yoi" }
protocol = { path = "crates/protocol" } protocol = { path = "crates/protocol" }
provider = { path = "crates/provider" }
session-metrics = { path = "crates/session-metrics" } session-metrics = { path = "crates/session-metrics" }
session-analytics = { path = "crates/session-analytics" }
session-store = { path = "crates/session-store" } session-store = { path = "crates/session-store" }
standalone = { path = "crates/standalone" }
secrets = { path = "crates/secrets" }
tools = { path = "crates/tools" } tools = { path = "crates/tools" }
config-source = { path = "crates/config-source" }
fs-operation = { path = "crates/fs-operation" }
workdir = { path = "crates/workdir" }
tui = { path = "crates/tui" }
yoi-workspace-server = { path = "crates/workspace-server" }
# External # External
# Note: `reqwest` and `chrono` are not aggregated here because some crates # Note: `reqwest` and `chrono` are not aggregated here because some crates
# need `default-features = false`, which workspace inheritance cannot override. # need `default-features = false`, which workspace inheritance cannot override.
async-trait = "0.1" async-trait = "0.1"
axum = "0.8"
base64 = "0.22.1"
decodal = "0.4.0"
decodal-language-service = "0.4.0"
decodal-language-tools = "0.4.0"
fs4 = "0.13" fs4 = "0.13"
futures = "0.3" futures = "0.3"
libc = "0.2" libc = "0.2"
schemars = "1.2" schemars = "1.2"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_yaml = "0.9.34"
tar = "0.4"
rusqlite = { version = "0.37", features = ["backup", "bundled"] }
ring = "0.17.14"
sha2 = "0.11" sha2 = "0.11"
ssh-key = { version = "0.6.7", features = ["ed25519", "encryption"] }
tempfile = "3.27" tempfile = "3.27"
thiserror = "2.0" thiserror = "2.0"
tokio = "1.52" tokio = "1.52"
tokio-tungstenite = "0.29"
tower = "0.5"
toml = "1.1" toml = "1.1"
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
url = "2.5"
uuid = "1.23" uuid = "1.23"
zeroize = "1"
webauthn-rs = { version = "0.5.2", features = ["danger-allow-state-serialisation", "danger-credential-internals"] }
+3 -13
View File
@@ -2,17 +2,7 @@
Ticket を切るほどではないが、次に近所を触るときに合わせて拾いたい小粒な所見の置き場。 Ticket を切るほどではないが、次に近所を触るときに合わせて拾いたい小粒な所見の置き場。
## 運用 - `crates/worker/src/controller.rs:1453-1461``worker_error_code``WorkerError::WorkflowResolve(_) => InvalidRequest` が post-commit な resolve エラー (`KnowledgeNotFound` 等) にも適用される。意味論的には妥当方向だが、resolve 系のエラー粒度を分けたくなったタイミングで再評価。
- 1 項目 = 出典 (file:line) + 症状 (一文) + トリガー (いつ拾うか、一文)
- 関連 ticket があれば `→ [tickets/foo.md]` でリンク
- 修正したら同じコミットで該当エントリを削除する (履歴は git)
- ここに溜める基準: 「ticket は重い」「だが忘れたら次の触り手が踏む」もの。明確に作業すべきものは ticket 化する
## エントリ
- `crates/pod/src/controller.rs:703-718` / `crates/tui/src/app.rs:837-845` — bad workflow slug を含む `Method::Run` 送信時、`Event::UserMessage` の早期 broadcast で `turn_index += 1` されターンヘッダだけ残る ("ghost turn header")。次に TUI のターンヘッダ / エラー表示周りを触るときに整理。
- `crates/pod/src/controller.rs:1256-1265``worker_error_code``PodError::WorkflowResolve(_) => InvalidRequest` が post-commit な resolve エラー (`KnowledgeNotFound` 等) にも適用される。意味論的には妥当方向だが、resolve 系のエラー粒度を分けたくなったタイミングで再評価。
- `crates/session-store/src/fs_store.rs:200-210``FsStore::read_entry_count``fs::read_to_string` で全文ロードしてから行数カウントするため O(n)。`ensure_head_or_fork` は run-start でしか呼ばれず現状は許容範囲だが、長期セッションが普通になった時点で `\n` バイト数の cheap count か末尾 seek に置き換える。 - `crates/session-store/src/fs_store.rs:200-210``FsStore::read_entry_count``fs::read_to_string` で全文ロードしてから行数カウントするため O(n)。`ensure_head_or_fork` は run-start でしか呼ばれず現状は許容範囲だが、長期セッションが普通になった時点で `\n` バイト数の cheap count か末尾 seek に置き換える。
- `crates/session-store/src/segment.rs:143-172` `ensure_head_or_fork` (free fn, test 専用・本番 caller ゼロ) と `crates/pod/src/pod.rs:1943-2006` `Pod::ensure_segment_head` (本番 inline) に live auto-fork の検知 + forked_from 記録が二重実装されている。entry-hash-abolish 以前からの重複で、両方独立にテスト済みだが drift 必至。session-store 側を本番から呼ぶ形に寄せるか free fn を畳むかは要設計判断。Pod state / fork 周辺を次に触るときに統合を検討。 - `crates/session-store/src/segment.rs:143-172` `ensure_head_or_fork` (free fn, test 専用・本番 caller ゼロ) と `crates/worker/src/worker.rs:2032` `Worker::ensure_segment_head` (本番 inline) に live auto-fork の検知 + forked_from 記録が二重実装されている。entry-hash-abolish 以前からの重複で、両方独立にテスト済みだが drift 必至。session-store 側を本番から呼ぶ形に寄せるか free fn を畳むかは要設計判断。Worker state / fork 周辺を次に触るときに統合を検討。
- `crates/pod/src/pod.rs:4074` / `crates/pod/src/spawn/registry.rs:83` — restore 時の spawned child prune/reclaim が Pod restore path と spawned registry load path の両方に残っている。現状は安全側の重複チェックだが、Pod state / spawned registry 周辺を次に触るときに責務境界を再整理。 - `crates/worker/src/worker.rs` / `crates/worker/src/spawn/registry.rs:84-174` — restore 時の spawned child prune/reclaim が Worker restore path と spawned registry load path の両方に残っている。現状は安全側の重複チェックだが、Worker state / spawned registry 周辺を次に触るときに責務境界を再整理。
+83 -3
View File
@@ -1,5 +1,85 @@
# INSOMNIA # 夜居 / Yoi agent
insomnia(i6a)は不休のエージェントループを回すためのエージェントプラットフォーム。 Yoi is an agent runtime for building, running, and orchestrating LLM Workers while preserving explicit history, scoped capabilities, and developer-controlled workflows.
ワークフローを統括し、四六時中電力を消費し、イテレーションします。 ## 1. Yoi agent
Yoi focuses on long-running agent operation rather than one-off prompt execution. A named Worker can keep durable session history, run with explicit tool and filesystem authority, delegate bounded work to child Workers, and be inspected or restored through CLI/TUI surfaces.
Main highlights:
- Named long-running **Workers** with durable session and metadata records.
- Explicit tool permissions and filesystem scopes.
- Multi-agent orchestration with scoped coder/reviewer Workers.
- Profile, Manifest, and prompt-based runtime configuration.
- Local Tickets and workflow files for auditable project coordination.
- TUI and CLI entry points, including the `yoi panel` workspace Dashboard and single-Worker Console.
Yoi is actively dogfooded in this repository. Public APIs, configuration formats, and workflows may still change.
## 2. Quick Install
From source:
```sh
cargo build --release -p yoi
./target/release/yoi --help
```
With Nix:
```sh
nix build .#yoi
./result/bin/yoi --help
```
## 3. Getting Started
```sh
yoi --help
yoi
yoi panel
yoi --worker <name>
yoi worker --help
```
Typical flow:
1. Configure providers, models, profiles, prompts, and scopes.
2. Start or attach to a named Worker in the Console, or inspect workspace activity in the Dashboard.
3. Use explicit tools and scoped delegation for multi-agent work.
4. Record project work through Tickets, workflow files, and git history.
Runtime surfaces use `yoi`, `.yoi`, `~/.yoi`, and `YOI_*`.
## 4. Documentation
Start with [`docs/README.md`](docs/README.md).
Key docs:
- [`docs/design/overview.md`](docs/design/overview.md) — architecture and crate ownership map.
- [`docs/design/context-history.md`](docs/design/context-history.md) — history/context invariants.
- [`docs/design/worker-session-state.md`](docs/design/worker-session-state.md) — Worker identity, metadata, and session logs.
- [`docs/design/profiles-manifests-prompts.md`](docs/design/profiles-manifests-prompts.md) — Profiles, Manifests, and prompt resources.
- [`docs/design/tool-permissions-scope.md`](docs/design/tool-permissions-scope.md) — tool policy and filesystem scope.
- [`docs/development/work-items.md`](docs/development/work-items.md) — Ticket workflow and project records.
- [`docs/development/validation.md`](docs/development/validation.md) — validation expectations.
## 5. Development
This repository dogfoods Yoi to develop Yoi. Work is tracked through `.yoi/tickets/` and `yoi ticket ...`; git history plus Ticket files are the authoritative project record.
Common checks:
```sh
yoi ticket doctor
git diff --check
cargo fmt --check
cargo check --workspace --all-targets
cargo test --workspace
```
Real-process E2E testing is opt-in. Do not design or implement E2E coverage unless the work explicitly requires E2E; otherwise protect the narrower parser, API, protocol, authority, or runtime boundary.
License: MIT. See [`LICENSE`](LICENSE).
-5
View File
@@ -1,5 +0,0 @@
# TODO legacy notice
Active repository work items have been migrated to `work-items/`.
Use `./tickets.sh list --status all` for the generated/current view and `./tickets.sh doctor` to validate the migration state.
+38
View File
@@ -0,0 +1,38 @@
name: yoi
services:
runtime:
image: yoi-runtime:latest
pull_policy: never
restart: unless-stopped
expose:
- "38800"
volumes:
- runtime-data:/runtime-data
- runtime-workdirs:/workdirs
server:
image: yoi-server:latest
pull_policy: never
restart: unless-stopped
depends_on:
- runtime
expose:
- "8787"
volumes:
- server-data:/server-data
- /etc/yoi/server.toml:/server-config/server.toml:ro
webui:
image: yoi-webui:latest
pull_policy: never
restart: unless-stopped
depends_on:
- server
ports:
- "${YOI_WEBUI_PORT:-8080}:80"
volumes:
runtime-data:
runtime-workdirs:
server-data:
+25
View File
@@ -0,0 +1,25 @@
[package]
name = "agen-macros"
description = "Procedural macros for declaring agen tools"
version = "0.2.0"
edition.workspace = true
rust-version = "1.85"
license.workspace = true
readme = "README.md"
repository = "https://gitea.hareworks.net/Hare/yoi"
homepage = "https://gitea.hareworks.net/Hare/yoi"
documentation = "https://docs.rs/agen-macros"
keywords = ["llm", "agent", "tools", "macros"]
categories = ["development-tools::procedural-macro-helpers"]
include = ["src/**", "README.md", "LICENSE"]
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }
[package.metadata.docs.rs]
all-features = true
+7
View File
@@ -0,0 +1,7 @@
Copyright 2026 Hare
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+32
View File
@@ -0,0 +1,32 @@
# agen-macros
Procedural macros used by [`agen`](https://crates.io/crates/agen) to declare LLM tools from Rust methods.
Applications should normally depend only on `agen` and import its re-exports:
```rust
use agen::tool_registry;
#[derive(Clone)]
struct Tools;
#[tool_registry]
impl Tools {
/// Returns the supplied text.
#[tool]
async fn echo(
&self,
#[description = "Text to return"] text: String,
) -> Result<String, std::io::Error> {
Ok(text)
}
}
```
`#[tool_registry]` generates the argument schema, a `Tool` implementation, and an `<method>_definition` constructor. It rejects arguments of its own, duplicate `#[tool]` markers, malformed or duplicate `#[description = "..."]` attributes, and non-identifier argument patterns.
Generated code targets the canonical `::agen` path and uses implementation dependencies re-exported by `agen`; consumers do not need direct `serde`, `schemars`, `serde_json`, or `async-trait` dependencies. Renaming the `agen` dependency in `Cargo.toml` is not currently supported.
This companion package is published before the matching `agen` release. Its public contract is the generated API consumed by `agen`, and its minor version compatibility follows the `agen` 0.2 series.
Licensed under the [MIT License](https://gitea.hareworks.net/Hare/yoi/src/branch/develop/LICENSE).
+482
View File
@@ -0,0 +1,482 @@
//! Procedural macros for declaring [`agen`](https://docs.rs/agen) tools.
//!
//! [`tool_registry`] expands methods marked with `#[tool]` into `agen::tool::Tool`
//! implementations and tool definitions. Applications normally use the re-exports from
//! `agen`; this companion crate exists so those macros can be published and versioned
//! independently.
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{
Attribute, FnArg, ImplItem, ItemImpl, Lit, Meta, Pat, ReturnType, Type, parse_macro_input,
spanned::Spanned,
};
/// Generates tools for methods marked with `#[tool]` in an `impl` block.
///
/// Method doc comments become the tool description. An argument can use
/// `#[description = "..."]` to supply its JSON Schema description.
///
/// ```ignore
/// #[derive(Clone)]
/// struct MyApp;
///
/// #[agen::tool_registry]
/// impl MyApp {
/// /// Retrieves a user by ID.
/// #[tool]
/// async fn get_user(
/// &self,
/// #[description = "The user ID"] user_id: String,
/// ) -> Result<String, std::io::Error> {
/// todo!()
/// }
/// }
/// ```
///
/// This generates a `ToolGetUser` wrapper, a `GetUserArgs` schema type, and
/// `MyApp::get_user_definition()`.
#[proc_macro_attribute]
pub fn tool_registry(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = proc_macro2::TokenStream::from(attr);
let impl_block = parse_macro_input!(item as ItemImpl);
expand_tool_registry(attr, impl_block)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
fn expand_tool_registry(
attr: proc_macro2::TokenStream,
mut impl_block: ItemImpl,
) -> syn::Result<proc_macro2::TokenStream> {
if !attr.is_empty() {
return Err(syn::Error::new(
attr.span(),
"tool_registry does not accept arguments",
));
}
let self_ty = impl_block.self_ty.as_ref().clone();
let mut generated_items = Vec::new();
for item in &mut impl_block.items {
let ImplItem::Fn(method) = item else {
continue;
};
let tool_attrs: Vec<_> = method
.attrs
.iter()
.filter(|attr| attr.path().is_ident("tool"))
.collect();
if tool_attrs.len() > 1 {
return Err(syn::Error::new_spanned(
tool_attrs[1],
"duplicate #[tool] attribute",
));
}
let Some(tool_attr) = tool_attrs.first() else {
continue;
};
if !matches!(tool_attr.meta, Meta::Path(_)) {
return Err(syn::Error::new_spanned(
tool_attr,
"#[tool] does not accept arguments",
));
}
method.attrs.retain(|attr| !attr.path().is_ident("tool"));
generated_items.push(generate_tool_impl(&self_ty, method)?);
for input in &mut method.sig.inputs {
if let FnArg::Typed(pat_type) = input {
pat_type
.attrs
.retain(|attr| !attr.path().is_ident("description"));
}
}
}
Ok(quote! {
#impl_block
#(#generated_items)*
})
}
fn extract_doc_comment(attrs: &[Attribute]) -> String {
let mut lines = Vec::new();
for attr in attrs {
if attr.path().is_ident("doc")
&& let Meta::NameValue(meta) = &attr.meta
&& let syn::Expr::Lit(expr_lit) = &meta.value
&& let Lit::Str(lit_str) = &expr_lit.lit
{
let line = lit_str.value();
let trimmed = line.strip_prefix(' ').unwrap_or(&line);
lines.push(trimmed.to_string());
}
}
lines.join("\n")
}
fn extract_description_attr(attrs: &[Attribute]) -> syn::Result<Option<String>> {
let mut description = None;
for attr in attrs
.iter()
.filter(|attr| attr.path().is_ident("description"))
{
let value = match &attr.meta {
Meta::NameValue(meta) => match &meta.value {
syn::Expr::Lit(expr_lit) => match &expr_lit.lit {
Lit::Str(value) => value.value(),
_ => {
return Err(syn::Error::new_spanned(
attr,
"description must be a string literal",
));
}
},
_ => {
return Err(syn::Error::new_spanned(
attr,
"description must be a string literal",
));
}
},
_ => {
return Err(syn::Error::new_spanned(
attr,
"expected #[description = \"...\"]",
));
}
};
if description.replace(value).is_some() {
return Err(syn::Error::new_spanned(
attr,
"duplicate #[description] attribute",
));
}
}
Ok(description)
}
fn argument_ident(pat: &Pat) -> syn::Result<&syn::Ident> {
match pat {
Pat::Ident(pat_ident) => Ok(&pat_ident.ident),
_ => Err(syn::Error::new_spanned(
pat,
"tool arguments must use simple identifier patterns",
)),
}
}
fn is_tool_execution_context_type(ty: &Type) -> bool {
let Type::Path(path) = ty else {
return false;
};
path.path
.segments
.last()
.is_some_and(|segment| segment.ident == "ToolExecutionContext")
}
fn generate_tool_impl(
self_ty: &Type,
method: &syn::ImplItemFn,
) -> syn::Result<proc_macro2::TokenStream> {
let sig = &method.sig;
let method_name = &sig.ident;
let tool_name = method_name.to_string();
let pascal_name = to_pascal_case(&method_name.to_string());
let tool_struct_name = format_ident!("Tool{}", pascal_name);
let args_struct_name = format_ident!("{}Args", pascal_name);
let definition_name = format_ident!("{}_definition", method_name);
let description = extract_doc_comment(&method.attrs);
let description = if description.is_empty() {
format!("Tool: {}", tool_name)
} else {
description
};
let method_args: Vec<_> = sig
.inputs
.iter()
.filter_map(|arg| match arg {
FnArg::Typed(pat_type) => Some(pat_type),
FnArg::Receiver(_) => None,
})
.collect();
let json_args: Vec<_> = method_args
.iter()
.copied()
.filter(|pat_type| !is_tool_execution_context_type(pat_type.ty.as_ref()))
.collect();
let arg_fields: Vec<_> = json_args
.iter()
.map(|pat_type| {
let field_name = argument_ident(pat_type.pat.as_ref())?;
let ty = &pat_type.ty;
let description = extract_description_attr(&pat_type.attrs)?;
Ok(if let Some(description) = description {
quote! {
#[schemars(description = #description)]
pub #field_name: #ty
}
} else {
quote! {
pub #field_name: #ty
}
})
})
.collect::<syn::Result<_>>()?;
let call_args: Vec<_> = method_args
.iter()
.map(|pat_type| {
if is_tool_execution_context_type(pat_type.ty.as_ref()) {
Ok(quote! { ctx.clone() })
} else {
let ident = argument_ident(pat_type.pat.as_ref())?;
Ok(quote! { args.#ident })
}
})
.collect::<syn::Result<_>>()?;
let method_call = if call_args.is_empty() {
quote! { self.ctx.#method_name() }
} else {
quote! { self.ctx.#method_name(#(#call_args),*) }
};
let awaiter = if sig.asyncness.is_some() {
quote! { .await }
} else {
quote! {}
};
let result_handling = if is_result_type(&sig.output) {
quote! {
match result {
Ok(val) => Ok(format!("{:?}", val).into()),
Err(error) => Err(::agen::tool::ToolError::ExecutionFailed(format!("{}", error))),
}
}
} else {
quote! {
Ok(format!("{:?}", result).into())
}
};
let args_struct_def = quote! {
#[derive(
::agen::__private::serde::Deserialize,
::agen::__private::schemars::JsonSchema,
)]
#[serde(crate = "::agen::__private::serde")]
#[schemars(crate = "::agen::__private::schemars")]
struct #args_struct_name {
#(#arg_fields),*
}
};
let execute_body = if json_args.is_empty() {
quote! {
let _: #args_struct_name = ::agen::__private::serde_json::from_str(input_json)
.unwrap_or(#args_struct_name {});
let result = #method_call #awaiter;
#result_handling
}
} else {
quote! {
let args: #args_struct_name = ::agen::__private::serde_json::from_str(input_json)
.map_err(|error| ::agen::tool::ToolError::InvalidArgument(error.to_string()))?;
let result = #method_call #awaiter;
#result_handling
}
};
Ok(quote! {
#args_struct_def
#[derive(Clone)]
pub struct #tool_struct_name {
ctx: #self_ty,
}
#[::agen::__private::async_trait::async_trait]
impl ::agen::tool::Tool for #tool_struct_name {
async fn execute(
&self,
input_json: &str,
ctx: ::agen::tool::ToolExecutionContext,
) -> Result<::agen::tool::ToolOutput, ::agen::tool::ToolError> {
let _ = &ctx;
#execute_body
}
}
impl #self_ty {
/// Returns a tool definition for registration with an `agen::Engine`.
pub fn #definition_name(&self) -> ::agen::tool::ToolDefinition {
let ctx = self.clone();
::std::sync::Arc::new(move || {
let schema = ::agen::__private::schemars::schema_for!(#args_struct_name);
let meta = ::agen::tool::ToolMeta::new(#tool_name)
.description(#description)
.input_schema(
::agen::__private::serde_json::to_value(schema)
.unwrap_or_else(|_| ::agen::__private::serde_json::json!({})),
);
let tool: ::std::sync::Arc<dyn ::agen::tool::Tool> =
::std::sync::Arc::new(#tool_struct_name { ctx: ctx.clone() });
(meta, tool)
})
}
}
})
}
fn is_result_type(return_type: &ReturnType) -> bool {
match return_type {
ReturnType::Default => false,
ReturnType::Type(_, ty) => {
if let Type::Path(type_path) = ty.as_ref()
&& let Some(segment) = type_path.path.segments.last()
{
return segment.ident == "Result";
}
false
}
}
}
fn to_pascal_case(s: &str) -> String {
s.split('_')
.map(|part| {
let mut chars = part.chars();
match chars.next() {
None => String::new(),
Some(first) => first.to_uppercase().chain(chars).collect(),
}
})
.collect()
}
/// Marker attribute interpreted by [`tool_registry`].
#[proc_macro_attribute]
pub fn tool(attr: TokenStream, item: TokenStream) -> TokenStream {
marker_attribute("tool", attr, item)
}
/// Argument description marker interpreted by [`tool_registry`].
///
/// Use it as `#[description = "The argument description"]` on a tool method argument.
#[proc_macro_attribute]
pub fn description(attr: TokenStream, item: TokenStream) -> TokenStream {
marker_attribute("description", attr, item)
}
fn marker_attribute(name: &str, attr: TokenStream, item: TokenStream) -> TokenStream {
if attr.is_empty() {
item
} else {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("{name} is a marker interpreted by #[tool_registry]"),
)
.into_compile_error()
.into()
}
}
#[cfg(test)]
mod tests {
use super::*;
use quote::quote;
use syn::parse_quote;
#[test]
fn rejects_tool_registry_arguments() {
let implementation: ItemImpl = parse_quote!(impl Registry {});
let error = expand_tool_registry(quote!(unexpected), implementation).unwrap_err();
assert!(error.to_string().contains("does not accept arguments"));
}
#[test]
fn rejects_duplicate_tool_markers() {
let implementation: ItemImpl = parse_quote! {
impl Registry {
#[tool]
#[tool]
fn inspect(&self) {}
}
};
let error = expand_tool_registry(quote!(), implementation).unwrap_err();
assert!(error.to_string().contains("duplicate #[tool]"));
}
#[test]
fn rejects_invalid_description_attributes() {
let implementation: ItemImpl = parse_quote! {
impl Registry {
#[tool]
fn inspect(&self, #[description] input: String) {}
}
};
let error = expand_tool_registry(quote!(), implementation).unwrap_err();
assert!(error.to_string().contains("expected #[description"));
}
#[test]
fn rejects_duplicate_description_attributes() {
let implementation: ItemImpl = parse_quote! {
impl Registry {
#[tool]
fn inspect(
&self,
#[description = "first"]
#[description = "second"]
input: String,
) {}
}
};
let error = expand_tool_registry(quote!(), implementation).unwrap_err();
assert!(error.to_string().contains("duplicate #[description]"));
}
#[test]
fn generated_code_uses_only_agen_runtime_paths() {
let implementation: ItemImpl = parse_quote! {
impl Registry {
#[tool]
fn inspect(&self, input: String) -> Result<String, Error> {
unreachable!()
}
}
};
let expanded = expand_tool_registry(quote!(), implementation)
.unwrap()
.to_string();
assert!(expanded.contains(":: agen :: tool :: Tool"));
assert!(expanded.contains(":: agen :: __private :: serde_json"));
assert!(expanded.contains(":: agen :: __private :: serde"));
assert!(expanded.contains(":: agen :: __private :: schemars"));
}
}
+55
View File
@@ -0,0 +1,55 @@
[package]
name = "agen"
description = "Provider-neutral orchestration for tool-using LLM applications"
version = "0.2.1"
edition.workspace = true
rust-version = "1.86"
license.workspace = true
readme = "README.md"
repository = "https://gitea.hareworks.net/Hare/yoi"
homepage = "https://gitea.hareworks.net/Hare/yoi"
documentation = "https://docs.rs/agen"
keywords = ["llm", "agent", "tools", "streaming", "orchestration"]
categories = ["api-bindings", "asynchronous"]
include = ["src/**", "tests/**", "examples/*.rs", "docs/**", "README.md", "LICENSE"]
autoexamples = false
[features]
default = []
codex = ["dep:chrono"]
[dependencies]
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
schemars = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
async-trait = { workspace = true }
futures = { workspace = true }
tokio = { workspace = true, features = ["fs", "macros", "rt-multi-thread", "sync", "time"] }
tokio-util = "0.7"
reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "native-tls", "http2"] }
eventsource-stream = "0.2"
zstd = "0.13"
base64 = "0.22.1"
chrono = { version = "0.4", default-features = false, features = ["serde", "clock"], optional = true }
agen-macros = { workspace = true }
[dev-dependencies]
clap = { version = "4.5", features = ["derive", "env"] }
tempfile = { workspace = true }
dotenv = "0.15"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
trybuild = "1.0.116"
wiremock = "0.6.5"
[[example]]
name = "engine_cancel_demo"
path = "examples/engine_cancel_demo.rs"
[[example]]
name = "engine_cli"
path = "examples/engine_cli.rs"
[package.metadata.docs.rs]
all-features = true
+7
View File
@@ -0,0 +1,7 @@
Copyright 2026 Hare
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+91
View File
@@ -0,0 +1,91 @@
# agen
`agen` is a provider-neutral Rust engine for streaming LLM applications that use tools. It owns the turn loop, typed conversation history, provider wire-format adapters, tool execution, interceptors, usage accounting, and cache-aware state transitions.
> `agen` is pre-1.0. Public APIs may change between minor releases.
## Installation
```toml
[dependencies]
agen = "0.2.1"
```
The default feature set is intentionally empty. Enable the experimental Codex/ChatGPT authentication adapter when needed:
```toml
agen = { version = "0.2.1", features = ["codex"] }
```
`agen` requires Rust 1.86 or newer. The companion `agen-macros` package requires Rust 1.85 or newer.
## Quick start
Supply an implementation of [`LlmClient`](https://docs.rs/agen/latest/agen/llm_client/trait.LlmClient.html), keep conversation history in your application, then run a turn. The first call consumes the mutable engine and returns a cache-locked engine for later turns.
```no_run
use agen::{Engine, EngineError, History};
use agen::llm_client::LlmClient;
async fn conversation<C: LlmClient>(client: C) -> Result<(), EngineError> {
let mut history = History::new();
let output = Engine::new(client)
.system_prompt("You are a concise assistant.")
.run(&mut history, "Explain typed state in one sentence.")
.await;
let mut engine = output.engine;
let _result = engine.run(&mut history, "Give a Rust example.").await;
Ok(())
}
```
## Declaring tools
The tool macros are re-exported by `agen`; applications do not need direct dependencies on `serde`, `schemars`, `serde_json`, or `async-trait` for generated code.
```rust
use agen::tool_registry;
#[derive(Clone)]
struct Tools;
#[tool_registry]
impl Tools {
/// Returns the supplied text.
#[tool]
async fn echo(
&self,
#[description = "Text to return"] text: String,
) -> Result<String, std::io::Error> {
Ok(text)
}
}
let definition = Tools.echo_definition();
assert_eq!(definition().0.name, "echo");
```
The generated API uses the canonical crate name `agen`. Renaming the `agen` dependency in `Cargo.toml` is not currently supported by these macros.
## Features
| Feature | Default | Adds |
|---|---:|---|
| `codex` | No | Experimental Codex/ChatGPT auth-file loading and token refresh support |
The base crate includes provider-neutral transport and Anthropic, OpenAI-compatible, Gemini, and Ollama wire-format schemes. See [`llm_client`](https://docs.rs/agen/latest/agen/llm_client/) for the client boundary.
## Architecture and API scope
The current public modules cover the engine, typed history, client transport/schemes, timeline events, tools, interceptors, pruning, token estimation, and usage records. Their relationships are described in [Architecture](https://gitea.hareworks.net/Hare/yoi/src/branch/develop/crates/agen/docs/architecture.md); behavioral requirements are summarized in [Requirements](https://gitea.hareworks.net/Hare/yoi/src/branch/develop/crates/agen/docs/requirements.md).
Low-level modules remain public in the 0.2 series because downstream Yoi components implement custom clients, event handlers, pruning policies, and tool registries against them. This surface is versioned as pre-1.0 API rather than declared stable.
## Packaging and security
The published package contains source, public documentation, curated examples, and deterministic tests/fixtures. Credentialed fixture-recording utilities are intentionally excluded. Examples that contact a provider read credentials from environment variables and never embed production credentials.
## License
Licensed under the [MIT License](https://gitea.hareworks.net/Hare/yoi/src/branch/develop/LICENSE).
+62
View File
@@ -0,0 +1,62 @@
# agen architecture
`agen` separates orchestration, event projection, and provider transport so applications can replace an LLM client without changing the turn loop or tool model.
```text
┌────────────────────────────────────────────┐
│ Engine │
│ turn loop · interceptors · tool execution │
│ typed state: Mutable → Locked → Mutable │
└─────────────────────┬──────────────────────┘
┌─────────────────────▼──────────────────────┐
│ Timeline │
│ event dispatch · block collectors │
└─────────────────────┬──────────────────────┘
┌─────────────────────▼──────────────────────┐
│ LlmClient │
│ transport · provider wire-format schemes │
└────────────────────────────────────────────┘
```
## Main modules
| Module | Responsibility |
|---|---|
| `engine` | Turn execution, pause/resume, retries, tool integration, and callbacks |
| `state` | Sealed `Mutable` and `Locked` type-state markers |
| `interceptor` | Application-owned control decisions at orchestration boundaries |
| `tool` / `tool_server` | Tool metadata, registration, execution, and bounded output |
| `timeline` | Streaming event dispatch, handlers, and block assembly |
| `llm_client` | Provider-neutral request, response, auth, transport, and scheme contracts |
| `providers` | Optional higher-level provider adapters such as the `codex` feature |
| `prune` / `token_counter` | Cache-aware history reduction and token estimation |
| `usage_record` | Request and token usage accounting |
## Request flow
```text
Engine history
→ provider-neutral Request
→ Scheme::build_request
→ Provider transport
```
## Response flow
```text
streaming response bytes
→ Scheme event parsing
→ unified Event values
→ Timeline handlers and collectors
→ Engine history/tool decisions
```
## Type state and cache protection
`Engine<C, Mutable>` permits configuration and history editing. `Engine::run` or `Engine::lock` commits the current prefix and produces `Engine<C, Locked>`. The locked engine may append turns without mutating the committed prefix. `Engine::unlock` explicitly returns to mutable state when an application accepts losing that cache guarantee.
## Public surface
The 0.2 series exposes the low-level client, timeline, tool, pruning, and usage modules because custom clients and orchestration hosts build directly on them. These APIs are intentionally provider-neutral but remain pre-1.0 and may change in later minor releases.
+39
View File
@@ -0,0 +1,39 @@
# agen requirements
## R1: Turn execution and continuation
- `Engine::run` starts a turn and loops through provider output and tool calls.
- An `Interceptor` may continue, cancel, or pause work at defined orchestration boundaries.
- `Engine::resume` continues paused generation without fabricating another user message.
- Cancellation and provider errors are represented as typed `EngineError` values.
## R2: Explicit cache-preserving state
- `Engine<C, Mutable>` permits configuration and history edits.
- `Engine::run` or `Engine::lock` transitions to `Engine<C, Locked>` and records the committed prefix.
- A locked engine appends turns but cannot mutate that prefix through mutable-only APIs.
- `Engine::unlock` explicitly abandons the lock before configuration or history changes.
## R3: Tool declarations and execution
- `#[tool_registry]` generates a schema and `Tool` implementation for methods marked `#[tool]`.
- `#[description = "..."]` supplies argument descriptions in generated JSON Schema.
- Generated code resolves its runtime and helper dependencies through `::agen`.
- Invalid and duplicate marker attributes produce compile errors rather than panics.
- Tools execute through `ToolServer` with typed context, errors, and output limits.
## R4: Provider-neutral orchestration
- `LlmClient` is the boundary between the engine and provider-specific transport.
- Request/response schemes translate provider wire formats into shared request and event types.
- Interceptors, tool execution, timeline collection, and pruning stay above the provider transport.
- Provider-specific capabilities are optional features when they require additional policy or dependencies.
## R5: Publication quality
- crates.io metadata includes license, repository, documentation, README, categories, keywords, and MSRV.
- The default feature set and each optional feature compile and test independently.
- Macro expansion compiles in a downstream-style integration test without direct helper dependencies.
- rustdoc builds without dependency documentation.
- Package contents are explicitly bounded and exclude credentialed fixture-recording utilities.
- `cargo package` and `cargo publish --dry-run` are run for `agen-macros` before `agen` because the main package depends on its companion package.
@@ -1,10 +1,10 @@
//! Worker cancellation demo //! Engine cancellation demo
//! //!
//! Example of cancelling from another thread during streaming //! Example of cancelling from another thread during streaming
use llm_worker::llm_client::scheme::{Scheme, anthropic::AnthropicScheme}; use agen::llm_client::scheme::{Scheme, anthropic::AnthropicScheme};
use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth}; use agen::llm_client::transport::{HttpTransport, ResolvedAuth};
use llm_worker::{Worker, WorkerResult}; use agen::{Engine, EngineRunExit, RunInterruptionReason};
use std::time::Duration; use std::time::Duration;
#[tokio::main] #[tokio::main]
@@ -28,33 +28,33 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cap = scheme.default_capability(); let cap = scheme.default_capability();
let base_url = scheme.default_base_url().to_string(); let base_url = scheme.default_base_url().to_string();
let client = HttpTransport::new(scheme, model, base_url, ResolvedAuth::ApiKey(api_key), cap); let client = HttpTransport::new(scheme, model, base_url, ResolvedAuth::ApiKey(api_key), cap);
let worker = Worker::new(client); let engine = Engine::new(client);
let mut history = agen::History::new();
println!("🚀 Starting Worker..."); println!("🚀 Starting Engine...");
println!("💡 Will cancel after 2 seconds\n"); println!("💡 Will cancel after 2 seconds\n");
// Get cancel sender before run (Mutable state) // Get cancel sender before run (Mutable state)
let cancel_tx = worker.cancel_sender(); let cancel_tx = engine.cancel_sender();
// Task: Cancel after 2 seconds // Task: Cancel after 2 seconds
tokio::spawn(async move { tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(2)).await; tokio::time::sleep(Duration::from_secs(2)).await;
println!("\n🛑 Cancelling worker..."); println!("\n🛑 Cancelling engine...");
let _ = cancel_tx.send(()).await; let _ = cancel_tx.send(()).await;
}); });
println!("📡 Sending request to LLM..."); println!("📡 Sending request to LLM...");
match worker.run("Tell me a very long story about a brave knight. Make it as detailed as possible with many paragraphs.").await { let output = engine.run(&mut history, "Tell me a very long story about a brave knight. Make it as detailed as possible with many paragraphs.").await;
Ok(out) => match out.result { match output.result {
WorkerResult::Finished => println!("✅ Task completed normally"), EngineRunExit::Finished => println!("✅ Task completed normally"),
WorkerResult::Paused => println!("⏸️ Task paused"), EngineRunExit::Paused => println!("⏸️ Task paused"),
WorkerResult::LimitReached => println!("🔒 Turn limit reached"), EngineRunExit::Yielded => println!("↩️ Task yielded"),
WorkerResult::Yielded => println!("↩️ Task yielded"), EngineRunExit::Interrupted(RunInterruptionReason::LimitReached) => {
}, println!("🔒 Turn limit reached")
Err(e) => {
println!("❌ Task error: {}", e);
} }
EngineRunExit::Interrupted(reason) => println!("❌ Task interrupted: {reason:?}"),
} }
println!("\n✨ Demo complete!"); println!("\n✨ Demo complete!");
@@ -1,4 +1,4 @@
//! Interactive CLI client using Worker //! Interactive CLI client using Engine
//! //!
//! A CLI application for interacting with multiple LLM providers (Anthropic, Gemini, OpenAI, Ollama). //! A CLI application for interacting with multiple LLM providers (Anthropic, Gemini, OpenAI, Ollama).
//! Demonstrates tool registration and execution, and streaming response display. //! Demonstrates tool registration and execution, and streaming response display.
@@ -12,22 +12,22 @@
//! echo "OPENAI_API_KEY=your-api-key" >> .env //! echo "OPENAI_API_KEY=your-api-key" >> .env
//! //!
//! # Anthropic (default) //! # Anthropic (default)
//! cargo run --example worker_cli //! cargo run --example engine_cli
//! //!
//! # Gemini //! # Gemini
//! cargo run --example worker_cli -- --provider gemini //! cargo run --example engine_cli -- --provider gemini
//! //!
//! # OpenAI //! # OpenAI
//! cargo run --example worker_cli -- --provider openai --model gpt-4o //! cargo run --example engine_cli -- --provider openai --model gpt-4o
//! //!
//! # Ollama (local) //! # Ollama (local)
//! cargo run --example worker_cli -- --provider ollama --model llama3.2 //! cargo run --example engine_cli -- --provider ollama --model llama3.2
//! //!
//! # With options //! # With options
//! cargo run --example worker_cli -- --provider anthropic --model claude-3-haiku-20240307 --system "You are a helpful assistant." //! cargo run --example engine_cli -- --provider anthropic --model claude-3-haiku-20240307 --system "You are a helpful assistant."
//! //!
//! # Show help //! # Show help
//! cargo run --example worker_cli -- --help //! cargo run --example engine_cli -- --help
//! ``` //! ```
use std::collections::HashMap; use std::collections::HashMap;
@@ -38,10 +38,9 @@ use async_trait::async_trait;
use tracing::info; use tracing::info;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use clap::{Parser, ValueEnum}; use agen::{
use llm_worker::{ Engine, EngineRunExit, RunInterruptionReason,
Worker, interceptor::{Interceptor, InterceptorResult, PostToolAction, ToolResultInfo},
interceptor::{Interceptor, PostToolAction, ToolResultInfo},
llm_client::{ llm_client::{
LlmClient, LlmClient,
capability::{CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport}, capability::{CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport},
@@ -51,12 +50,9 @@ use llm_worker::{
transport::{HttpTransport, ResolvedAuth}, transport::{HttpTransport, ResolvedAuth},
}, },
timeline::{Handler, TextBlockEvent, TextBlockKind, ToolUseBlockEvent, ToolUseBlockKind}, timeline::{Handler, TextBlockEvent, TextBlockKind, ToolUseBlockEvent, ToolUseBlockKind},
tool_registry,
}; };
use llm_worker_macros::tool_registry; use clap::{Parser, ValueEnum};
// Required imports for macro expansion
use schemars;
use serde;
// ============================================================================= // =============================================================================
// Provider Definition // Provider Definition
@@ -114,8 +110,8 @@ impl Provider {
/// Interactive CLI client supporting multiple LLM providers /// Interactive CLI client supporting multiple LLM providers
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "worker-cli")] #[command(name = "engine-cli")]
#[command(about = "Interactive CLI client for multiple LLM providers using Worker")] #[command(about = "Interactive CLI client for multiple LLM providers using Engine")]
#[command(version)] #[command(version)]
struct Args { struct Args {
/// Provider to use /// Provider to use
@@ -284,7 +280,10 @@ impl ToolResultPrinterPolicy {
#[async_trait] #[async_trait]
impl Interceptor for ToolResultPrinterPolicy { impl Interceptor for ToolResultPrinterPolicy {
async fn post_tool_call(&self, info: &mut ToolResultInfo) -> PostToolAction { async fn post_tool_call(
&self,
info: &ToolResultInfo<'_, ()>,
) -> InterceptorResult<PostToolAction> {
let name = self let name = self
.call_names .call_names
.lock() .lock()
@@ -298,7 +297,7 @@ impl Interceptor for ToolResultPrinterPolicy {
println!(" Result ({}): ✅ {}", name, info.result.summary); println!(" Result ({}): ✅ {}", name, info.result.summary);
} }
PostToolAction::Continue Ok(PostToolAction::Continue)
} }
} }
@@ -393,7 +392,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv().ok(); dotenv::dotenv().ok();
// Initialize logging // Initialize logging
// Use RUST_LOG=debug cargo run --example worker_cli ... for detailed logs // Use RUST_LOG=debug cargo run --example engine_cli ... for detailed logs
// Default is warn level, can be overridden with RUST_LOG environment variable // Default is warn level, can be overridden with RUST_LOG environment variable
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn")); let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
@@ -408,7 +407,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
info!( info!(
provider = ?args.provider, provider = ?args.provider,
model = ?args.model, model = ?args.model,
"Starting worker CLI" "Starting engine CLI"
); );
// Interactive mode or one-shot mode // Interactive mode or one-shot mode
@@ -421,7 +420,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.unwrap_or_else(|| args.provider.default_model().to_string()); .unwrap_or_else(|| args.provider.default_model().to_string());
if is_interactive { if is_interactive {
let title = format!("Worker CLI - {}", args.provider.display_name()); let title = format!("Engine CLI - {}", args.provider.display_name());
let border_len = title.len() + 6; let border_len = title.len() + 6;
println!("{}", "".repeat(border_len)); println!("{}", "".repeat(border_len));
println!("{}", title); println!("{}", title);
@@ -453,39 +452,38 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}; };
// Create Worker // Create Engine
let mut worker = Worker::new(client); let mut engine = Engine::new(client);
let mut history = agen::History::new();
let tool_call_names = Arc::new(Mutex::new(HashMap::new())); let tool_call_names = Arc::new(Mutex::new(HashMap::new()));
// Set system prompt // Set system prompt
if let Some(ref system_prompt) = args.system { if let Some(ref system_prompt) = args.system {
worker.set_system_prompt(system_prompt); engine.set_system_prompt(system_prompt);
} }
// Register tools (unless --no-tools) // Register tools (unless --no-tools)
if !args.no_tools { if !args.no_tools {
let app = AppContext; let app = AppContext;
worker.register_tool(app.get_current_time_definition()); engine.register_tool(app.get_current_time_definition());
worker.register_tool(app.calculate_definition()); engine.register_tool(app.calculate_definition());
} }
// Register streaming display handlers // Register streaming display handlers
worker engine
.timeline_mut() .timeline_mut()
.on_text_block(StreamingPrinter::new()) .on_text_block(StreamingPrinter::new())
.on_tool_use_block(ToolCallPrinter::new(tool_call_names.clone())); .on_tool_use_block(ToolCallPrinter::new(tool_call_names.clone()));
worker.set_interceptor(ToolResultPrinterPolicy::new(tool_call_names)); engine.set_interceptor(ToolResultPrinterPolicy::new(tool_call_names));
// One-shot mode // One-shot mode
if let Some(prompt) = args.prompt { if let Some(prompt) = args.prompt {
match worker.run(&prompt).await { let output = engine.run(&mut history, &prompt).await;
Ok(_) => {} if let EngineRunExit::Interrupted(RunInterruptionReason::Unexpected(error)) = output.result
Err(e) => { {
eprintln!("\n❌ Error: {}", e); eprintln!("\n❌ Error: {error}");
std::process::exit(1);
}
} }
return Ok(()); return Ok(());
@@ -504,13 +502,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(()); return Ok(());
} }
let mut locked = match worker.run(first_input).await { let output = engine.run(&mut history, first_input).await;
Ok(out) => out.worker, let mut locked = output.engine;
Err(e) => {
eprintln!("\n❌ Error: {}", e);
return Ok(());
}
};
loop { loop {
print!("\n👤 You: "); print!("\n👤 You: ");
@@ -529,11 +522,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
break; break;
} }
match locked.run(input).await { if let EngineRunExit::Interrupted(RunInterruptionReason::Unexpected(error)) =
Ok(_) => {} locked.run(&mut history, input).await
Err(e) => { {
eprintln!("\n❌ Error: {}", e); eprintln!("\n❌ Error: {error}");
}
} }
} }
@@ -19,11 +19,11 @@
mod recorder; mod recorder;
mod scenarios; mod scenarios;
use clap::{Parser, ValueEnum}; use agen::llm_client::scheme::{
use llm_worker::llm_client::scheme::{
Scheme, anthropic::AnthropicScheme, gemini::GeminiScheme, openai_chat::OpenAIScheme, Scheme, anthropic::AnthropicScheme, gemini::GeminiScheme, openai_chat::OpenAIScheme,
}; };
use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth}; use agen::llm_client::transport::{HttpTransport, ResolvedAuth};
use clap::{Parser, ValueEnum};
fn make_transport<S: Scheme>(scheme: S, model: &str, auth: ResolvedAuth) -> HttpTransport<S> { fn make_transport<S: Scheme>(scheme: S, model: &str, auth: ResolvedAuth) -> HttpTransport<S> {
let cap = scheme.default_capability(); let cap = scheme.default_capability();
@@ -225,7 +225,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
println!("\n✅ Done!"); println!("\n✅ Done!");
println!("Run tests with: cargo test -p worker"); println!("Run tests with: cargo test -p engine");
Ok(()) Ok(())
} }
@@ -7,8 +7,8 @@ use std::io::{BufWriter, Write};
use std::path::Path; use std::path::Path;
use std::time::{Instant, SystemTime, UNIX_EPOCH}; use std::time::{Instant, SystemTime, UNIX_EPOCH};
use agen::llm_client::{LlmClient, Request};
use futures::StreamExt; use futures::StreamExt;
use llm_worker::llm_client::{LlmClient, Request};
/// Recorded event /// Recorded event
#[derive(Debug, serde::Serialize, serde::Deserialize)] #[derive(Debug, serde::Serialize, serde::Deserialize)]
@@ -79,7 +79,7 @@ pub async fn record_request<C: LlmClient>(
} }
// Save // Save
let fixtures_dir = Path::new("worker/tests/fixtures").join(subdir); let fixtures_dir = Path::new("engine/tests/fixtures").join(subdir);
fs::create_dir_all(&fixtures_dir)?; fs::create_dir_all(&fixtures_dir)?;
let filepath = fixtures_dir.join(format!("{}.jsonl", output_name)); let filepath = fixtures_dir.join(format!("{}.jsonl", output_name));
@@ -2,7 +2,7 @@
//! //!
//! Defines requests and output file names for each scenario //! Defines requests and output file names for each scenario
use llm_worker::llm_client::{Request, ToolDefinition}; use agen::llm_client::{Request, ToolDefinition};
/// Test scenario /// Test scenario
pub struct TestScenario { pub struct TestScenario {
@@ -1,7 +1,7 @@
//! Closure-based event callback API //! Closure-based event callback API
//! //!
//! Provides a closure-based alternative to implementing `Handler<K>` directly. //! Provides a closure-based alternative to implementing `Handler<K>` directly.
//! Register callbacks on `Worker` via `on_text_block()`, `on_tool_use_block()`, //! Register callbacks on `Engine` via `on_text_block()`, `on_tool_use_block()`,
//! `on_usage()`, etc. //! `on_usage()`, etc.
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -18,13 +18,13 @@ use crate::tool::ToolCall;
/// Callback scope for a text block. /// Callback scope for a text block.
/// ///
/// Passed to the setup closure registered with `Worker::on_text_block()`. /// Passed to the setup closure registered with `Engine::on_text_block()`.
/// Register per-block callbacks via `on_delta()` and `on_stop()`. /// Register per-block callbacks via `on_delta()` and `on_stop()`.
/// ///
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// worker.on_text_block(|block| { /// engine.on_text_block(|block| {
/// block.on_delta(|text| print!("{}", text)); /// block.on_delta(|text| print!("{}", text));
/// block.on_stop(|full_text| println!("\n--- {} chars ---", full_text.len())); /// block.on_stop(|full_text| println!("\n--- {} chars ---", full_text.len()));
/// }); /// });
@@ -176,13 +176,13 @@ impl Handler<ThinkingBlockKind> for ClosureThinkingBlockHandler {
/// Callback scope for a tool use block. /// Callback scope for a tool use block.
/// ///
/// Passed to the setup closure registered with `Worker::on_tool_use_block()`. /// Passed to the setup closure registered with `Engine::on_tool_use_block()`.
/// The setup closure also receives `&ToolUseBlockStart` with `id` and `name`. /// The setup closure also receives `&ToolUseBlockStart` with `id` and `name`.
/// ///
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// worker.on_tool_use_block(|start, block| { /// engine.on_tool_use_block(|start, block| {
/// println!("Tool: {} ({})", start.name, start.id); /// println!("Tool: {} ({})", start.name, start.id);
/// block.on_delta(|json| { /* streaming JSON fragment */ }); /// block.on_delta(|json| { /* streaming JSON fragment */ });
/// block.on_stop(|call| println!("Done: {}", call.name)); /// block.on_stop(|call| println!("Done: {}", call.name));
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
//! Public event types for Worker layer //! Public event types for Engine layer
//! //!
//! Re-exports from the canonical event definitions in llm_client. //! Re-exports from the canonical event definitions in llm_client.
@@ -32,7 +32,7 @@ pub trait Kind {
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use llm_worker::timeline::{Handler, TextBlockEvent, TextBlockKind}; /// use agen::timeline::{Handler, TextBlockEvent, TextBlockKind};
/// ///
/// struct TextCollector { /// struct TextCollector {
/// texts: Vec<String>, /// texts: Vec<String>,
@@ -91,16 +91,6 @@ impl Kind for ErrorKind {
type Event = ErrorEvent; type Event = ErrorEvent;
} }
/// Reasoning item Kind - 完成済み reasoning item の永続化用
///
/// 1 reasoning item につき 1 度だけ発火する。Worker は
/// `ReasoningItemCollector` 経由で受け取り、ターン終了時に
/// `Item::Reasoning` として history に append する。
pub struct ReasoningItemKind;
impl Kind for ReasoningItemKind {
type Event = ReasoningItemEvent;
}
// ============================================================================= // =============================================================================
// Block Kind Definitions // Block Kind Definitions
// ============================================================================= // =============================================================================
@@ -152,6 +142,7 @@ pub struct ThinkingBlockStart {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ThinkingBlockStop { pub struct ThinkingBlockStop {
pub index: usize, pub index: usize,
pub reasoning: Option<ReasoningBlockData>,
} }
/// ToolUseBlock Kind - for tool use blocks /// ToolUseBlock Kind - for tool use blocks
+199
View File
@@ -0,0 +1,199 @@
//! Typed conversation history containers.
//!
//! Agen keeps provider-visible [`Item`](crate::Item) values separate from any
//! host-domain provenance. The host chooses the annotation type `A`, while Agen
//! preserves each item and annotation as one entry for clone/truncate/restore
//! style history operations.
use serde::{Deserialize, Serialize};
use crate::Item;
/// One conversation-history entry with host-owned annotation.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct HistoryEntry<A = ()> {
/// Provider/model-visible conversation item.
pub item: Item,
/// Host-domain metadata kept with the item and never projected to providers.
pub annotation: A,
}
impl<A> HistoryEntry<A> {
/// Build an entry from an item and its annotation.
pub fn new(item: Item, annotation: A) -> Self {
Self { item, annotation }
}
/// Split the entry into its item and annotation.
pub fn into_parts(self) -> (Item, A) {
(self.item, self.annotation)
}
}
impl HistoryEntry<()> {
/// Build a unit-annotated entry.
pub fn from_item(item: Item) -> Self {
Self {
item,
annotation: (),
}
}
}
/// Conversation history with one annotation per item.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct History<A = ()> {
entries: Vec<HistoryEntry<A>>,
}
impl<A> History<A> {
/// Create an empty history.
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
/// Build history from already annotated entries, preserving order.
pub fn from_entries(entries: Vec<HistoryEntry<A>>) -> Self {
Self { entries }
}
/// Replace all entries as one restore/rebuild operation and return the old entries.
pub fn replace_entries(&mut self, entries: Vec<HistoryEntry<A>>) -> Vec<HistoryEntry<A>> {
std::mem::replace(&mut self.entries, entries)
}
/// Borrow annotated entries.
pub fn entries(&self) -> &[HistoryEntry<A>] {
&self.entries
}
/// Mutably borrow annotated entries for host-owned rebuild operations.
pub fn entries_mut(&mut self) -> &mut [HistoryEntry<A>] {
&mut self.entries
}
/// Consume the history into annotated entries.
pub fn into_entries(self) -> Vec<HistoryEntry<A>> {
self.entries
}
/// Number of entries.
pub fn len(&self) -> usize {
self.entries.len()
}
/// Whether the history is empty.
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
/// Iterate over annotated entries.
pub fn iter(&self) -> impl ExactSizeIterator<Item = &HistoryEntry<A>> {
self.entries.iter()
}
/// Iterate over provider-visible items only.
pub fn items(&self) -> impl ExactSizeIterator<Item = &Item> {
self.entries.iter().map(|entry| &entry.item)
}
/// Clone provider-visible items into a request-local projection.
pub fn items_cloned(&self) -> Vec<Item> {
self.items().cloned().collect()
}
/// Append an already annotated entry.
pub fn push_entry(&mut self, entry: HistoryEntry<A>) {
self.entries.push(entry);
}
/// Append many already annotated entries.
pub fn extend_entries(&mut self, entries: impl IntoIterator<Item = HistoryEntry<A>>) {
self.entries.extend(entries);
}
/// Commit one item through a trusted annotation callback before it becomes live.
///
/// The callback may durably persist the item and returns the annotation that
/// must be stored with it. If the callback fails, the history is left unchanged.
pub fn append_with(
&mut self,
item: Item,
annotate: &mut impl FnMut(&Item) -> Result<A, String>,
) -> Result<(), String> {
let annotation = annotate(&item)?;
self.entries.push(HistoryEntry { item, annotation });
Ok(())
}
/// Commit items through a trusted annotation callback before they become live.
///
/// Items before a failure remain appended; the failing item and later items do
/// not enter history. This mirrors append-only durable logs where each accepted
/// item is already committed before the next item is attempted.
pub fn extend_with(
&mut self,
items: impl IntoIterator<Item = Item>,
annotate: &mut impl FnMut(&Item) -> Result<A, String>,
) -> Result<(), String> {
for item in items {
self.append_with(item, annotate)?;
}
Ok(())
}
/// Truncate entries, preserving item+annotation pairing for retained entries.
pub fn truncate(&mut self, len: usize) {
self.entries.truncate(len);
}
/// Clear all entries.
pub fn clear(&mut self) {
self.entries.clear();
}
}
impl History<()> {
/// Build unit-annotated history from provider-visible items.
pub fn from_items(items: Vec<Item>) -> Self {
Self {
entries: items.into_iter().map(HistoryEntry::from_item).collect(),
}
}
/// Replace history from provider-visible items using unit annotations.
pub fn replace_items(&mut self, items: Vec<Item>) -> Vec<HistoryEntry<()>> {
self.replace_entries(items.into_iter().map(HistoryEntry::from_item).collect())
}
/// Append one item with unit annotation.
pub fn push(&mut self, item: Item) {
self.entries.push(HistoryEntry::from_item(item));
}
/// Append items with unit annotations.
pub fn extend_items(&mut self, items: impl IntoIterator<Item = Item>) {
self.entries
.extend(items.into_iter().map(HistoryEntry::from_item));
}
}
impl<A> IntoIterator for History<A> {
type Item = HistoryEntry<A>;
type IntoIter = std::vec::IntoIter<HistoryEntry<A>>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl<'a, A> IntoIterator for &'a History<A> {
type Item = &'a HistoryEntry<A>;
type IntoIter = std::slice::Iter<'a, HistoryEntry<A>>;
fn into_iter(self) -> Self::IntoIter {
self.entries.iter()
}
}
+423
View File
@@ -0,0 +1,423 @@
//! Interceptor - control flow delegation for the Engine execution loop
//!
//! Defines the [`Interceptor`] trait that callers implement to inject
//! orchestration decisions (approval, skip, pause, abort) into the Engine's
//! turn loop without the Engine knowing about host-application concepts.
use std::sync::Arc;
use async_trait::async_trait;
use crate::Item;
use crate::engine::EngineRunExit;
use crate::history::HistoryEntry;
use crate::tool::{Tool, ToolCall, ToolExecutionContext, ToolMeta, ToolResult};
// =============================================================================
// Typed lifecycle metadata and failures
// =============================================================================
/// Maximum UTF-8 byte length retained for interceptor diagnostics.
pub const MAX_INTERCEPTOR_DIAGNOSTIC_BYTES: usize = 1024;
/// Stable category for the source of an interceptor failure.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InterceptorErrorCategory {
Policy,
Dependency,
ContractViolation,
Internal,
}
impl std::fmt::Display for InterceptorErrorCategory {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(match self {
Self::Policy => "policy",
Self::Dependency => "dependency",
Self::ContractViolation => "contract_violation",
Self::Internal => "internal",
})
}
}
/// A typed, bounded failure returned by an [`Interceptor`] implementation.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{category}: {diagnostic}")]
pub struct InterceptorError {
category: InterceptorErrorCategory,
diagnostic: String,
}
impl InterceptorError {
pub fn new(category: InterceptorErrorCategory, diagnostic: impl Into<String>) -> Self {
let mut diagnostic = diagnostic.into();
if diagnostic.len() > MAX_INTERCEPTOR_DIAGNOSTIC_BYTES {
let mut end = MAX_INTERCEPTOR_DIAGNOSTIC_BYTES;
while !diagnostic.is_char_boundary(end) {
end -= 1;
}
diagnostic.truncate(end);
}
Self {
category,
diagnostic,
}
}
pub fn category(&self) -> InterceptorErrorCategory {
self.category
}
pub fn diagnostic(&self) -> &str {
&self.diagnostic
}
}
/// The lifecycle phase at which an interceptor callback executes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum InterceptorPhase {
#[default]
PromptSubmit,
PendingHistoryAppends,
PreLlmRequest,
PreToolCall,
PostToolCall,
AssistantTurnEnd,
RunExit,
}
impl std::fmt::Display for InterceptorPhase {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(match self {
Self::PromptSubmit => "prompt_submit",
Self::PendingHistoryAppends => "pending_history_appends",
Self::PreLlmRequest => "pre_llm_request",
Self::PreToolCall => "pre_tool_call",
Self::PostToolCall => "post_tool_call",
Self::AssistantTurnEnd => "assistant_turn_end",
Self::RunExit => "run_exit",
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct InterceptorRunId(pub u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InterceptorTurnId(pub u64);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum InterceptorCallId {
Llm(u64),
Tool(String),
}
/// Saturating public counter used by interceptor contexts.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct InterceptorCounter(u32);
impl InterceptorCounter {
pub fn from_usize(value: usize) -> Self {
Self(u32::try_from(value).unwrap_or(u32::MAX))
}
pub fn get(self) -> u32 {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct InterceptorCounters {
pub invocation: InterceptorCounter,
pub engine_turn: InterceptorCounter,
pub run_turn: InterceptorCounter,
pub llm_call: InterceptorCounter,
pub tool_batch: InterceptorCounter,
pub tool_call: InterceptorCounter,
}
/// Identity, phase, and bounded counters common to every lifecycle callback.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct InterceptorInvocation {
pub run_id: InterceptorRunId,
pub turn_id: Option<InterceptorTurnId>,
pub call_id: Option<InterceptorCallId>,
pub phase: InterceptorPhase,
pub counters: InterceptorCounters,
}
/// An interceptor failure bound to the exact Engine lifecycle phase that ran it.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{phase} interceptor failed: {error}")]
pub struct InterceptorFailure {
phase: InterceptorPhase,
#[source]
error: InterceptorError,
}
impl InterceptorFailure {
pub(crate) fn new(phase: InterceptorPhase, error: InterceptorError) -> Self {
Self { phase, error }
}
pub fn phase(&self) -> InterceptorPhase {
self.phase
}
pub fn error(&self) -> &InterceptorError {
&self.error
}
}
pub type InterceptorResult<T> = Result<T, InterceptorError>;
// =============================================================================
// Lifecycle Contexts
// =============================================================================
pub struct PromptSubmitContext<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub item: &'a mut Item,
pub history: &'a [HistoryEntry<A>],
}
pub struct PendingHistoryAppendsContext<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub history: &'a [HistoryEntry<A>],
}
pub struct PreLlmRequestContext<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub items: &'a mut Vec<Item>,
pub history: &'a [HistoryEntry<A>],
}
pub struct AssistantTurnEndContext<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub assistant_entries: &'a [HistoryEntry<A>],
pub history: &'a [HistoryEntry<A>],
pub tool_calls: &'a [ToolCall],
}
pub struct RunExitContext<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub exit: &'a EngineRunExit,
pub history: &'a [HistoryEntry<A>],
}
// =============================================================================
// Action Enums
// =============================================================================
/// Action after prompt submission.
#[derive(Debug, Clone, PartialEq)]
pub enum PromptAction {
/// Proceed normally.
Continue,
/// Cancel with a reason.
Cancel(String),
/// Proceed, and append these items to history right after the user
/// message. Mirrors [`TurnEndAction::ContinueWithMessages`] for the
/// submit edge: lets the upper layer attach resolver-produced
/// system messages (e.g. `@<path>` file content) so they sit
/// adjacent to the user message that referenced them.
ContinueWith(Vec<Item>),
}
/// Action before an LLM request.
#[derive(Debug, Clone, PartialEq)]
pub enum PreRequestAction {
/// Proceed normally.
Continue,
/// Proceed after appending these items to durable engine history.
///
/// This is for upper-layer budget/status nudges that the model may react
/// to: the items are committed before the request so later turns can see
/// why the engine changed course.
ContinueWith(Vec<Item>),
/// Yield after appending these items to durable engine history.
///
/// This is for host-mediated pre-request appends that must be visible to
/// usage accounting and compaction checks before the current LLM request is
/// allowed to proceed.
YieldWith(Vec<Item>),
/// Cancel with a reason (treated as an error).
Cancel(String),
/// Yield control to the caller for external processing.
///
/// The Engine exits the turn loop cleanly with `EngineResult::Yielded`.
/// The caller is expected to resume execution later.
Yield,
}
/// Action before a tool call.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PreToolAction {
/// Proceed with execution.
Continue,
/// Skip this tool call (do not execute).
Skip,
/// Do not execute the tool call; commit this synthetic result instead.
///
/// This preserves provider-visible `tool_use` / `tool_result` pairing
/// without aborting the whole turn.
SyntheticResult(ToolResult),
/// Abort the entire run.
Abort(String),
/// Pause execution (can be resumed later).
Pause,
}
/// Action after a tool call.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PostToolAction {
/// Proceed normally.
Continue,
/// Abort the entire run.
Abort(String),
}
/// Action at the end of a turn (when LLM produces no tool calls).
#[derive(Debug, Clone)]
pub enum TurnEndAction {
/// Accept the Engine's natural next phase: execute tools, or finish when none exist.
Finish,
/// Commit additional messages, then continue through the natural next phase.
ContinueWithMessages(Vec<Item>),
/// Pause execution (can be resumed later).
Pause,
}
// =============================================================================
// Context Types
// =============================================================================
/// Context for pre-tool-call decisions.
pub struct ToolCallInfo<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub history: &'a [HistoryEntry<A>],
pub call: ToolCall,
/// Tool meta information.
pub meta: ToolMeta,
/// Tool instance (for state access).
pub tool: Arc<dyn Tool>,
/// Response-local execution context for this call.
pub context: ToolExecutionContext,
}
/// Context for post-tool-call decisions.
pub struct ToolResultInfo<'a, A = ()> {
pub invocation: InterceptorInvocation,
pub history: &'a [HistoryEntry<A>],
pub call: ToolCall,
/// Committed terminal tool execution result.
pub result: ToolResult,
/// Tool meta information.
pub meta: ToolMeta,
/// Tool instance (for state access).
pub tool: Arc<dyn Tool>,
/// Response-local execution context for this call.
pub context: ToolExecutionContext,
}
// =============================================================================
// Interceptor Trait
// =============================================================================
/// Intercepts the Engine execution loop at key decision points.
///
/// Every lifecycle method is asynchronous and returns [`InterceptorResult`],
/// keeping implementation failure separate from the method's control-flow
/// action. The Engine reports a failure as a typed run interruption annotated
/// with the exact [`InterceptorPhase`] that failed.
///
/// All methods have default implementations that let the Engine proceed
/// without intervention. Callers provide richer implementations for approval
/// flows, permission checks, and other trusted host adaptation.
#[async_trait]
pub trait Interceptor<A: Send + Sync = ()>: Send + Sync {
/// Called after receiving user input, before adding it to Engine history.
async fn on_prompt_submit(
&self,
_context: PromptSubmitContext<'_, A>,
) -> InterceptorResult<PromptAction> {
Ok(PromptAction::Continue)
}
/// Items that should be **committed to `engine.history`** just
/// before the next LLM request. Returned items are `extend`ed into
/// the persistent history (and therefore picked up by the per-turn
/// clone that backs the LLM request, plus the usual
/// history-persistence path).
///
/// Use this for inputs that arrive from outside the LLM and need
/// to be reflected in the on-disk history — notifications,
/// external events, system reminders. Do **not** use
/// [`Self::pre_llm_request`] for that purpose: it mutates a
/// per-request clone, so any committed assistant response that
/// reacts to the injection would have no visible trigger on the
/// next turn (or after resume / compaction).
///
/// `pre_llm_request` remains the right place for purely
/// reproducible per-request transformations (pruning, content
/// trimming, cache anchors) that depend only on the existing
/// history.
async fn pending_history_appends(
&self,
_context: PendingHistoryAppendsContext<'_, A>,
) -> InterceptorResult<Vec<Item>> {
Ok(Vec::new())
}
/// Called before each LLM request. The context starts as a clone
/// of `engine.history` (after `pending_history_appends` and the
/// Engine's own prune projection have been applied).
///
/// Direct mutations to `context` remain request-local and are not persisted.
/// If an interceptor derives a human/model-visible nudge from the current
/// request context, return [`PreRequestAction::ContinueWith`] so the Engine
/// commits it to history before the request is sent.
async fn pre_llm_request(
&self,
_context: PreLlmRequestContext<'_, A>,
) -> InterceptorResult<PreRequestAction> {
Ok(PreRequestAction::Continue)
}
/// Called before each tool is executed.
async fn pre_tool_call(
&self,
_info: &mut ToolCallInfo<'_, A>,
) -> InterceptorResult<PreToolAction> {
Ok(PreToolAction::Continue)
}
/// Called after each tool reaches one terminal result and that result is committed.
async fn post_tool_call(
&self,
_info: &ToolResultInfo<'_, A>,
) -> InterceptorResult<PostToolAction> {
Ok(PostToolAction::Continue)
}
/// Called after every terminal assistant response is committed and before
/// the Engine decides whether to execute tools, continue, or finish.
async fn on_assistant_turn_end(
&self,
_context: AssistantTurnEndContext<'_, A>,
) -> InterceptorResult<TurnEndAction> {
Ok(TurnEndAction::Finish)
}
/// Called once for the terminal outcome of each public run or resume call.
async fn on_run_exit(&self, _context: RunExitContext<'_, A>) -> InterceptorResult<()> {
Ok(())
}
}
/// Default interceptor: no intervention. Engine proceeds through the loop
/// without any external control flow decisions.
pub(crate) struct DefaultInterceptor;
#[async_trait]
impl<A: Send + Sync> Interceptor<A> for DefaultInterceptor {}
+54
View File
@@ -0,0 +1,54 @@
#![doc = include_str!("../README.md")]
mod engine;
mod handler;
mod history;
mod message;
pub(crate) mod callback;
pub mod event;
pub mod interceptor;
pub mod llm_client;
pub mod providers;
pub mod prune;
pub mod state;
pub mod timeline;
pub mod token_counter;
pub mod tool;
pub mod tool_server;
pub mod usage_record;
pub use agen_macros::{description, tool, tool_registry};
pub use callback::{TextBlockScope, ThinkingBlockScope, ToolUseBlockScope};
pub use engine::{
Engine, EngineConfig, EngineError, EngineResult, EngineRunExit, EngineRunOutput,
LlmRetryNotice, RunInterruptionReason, ToolRegistryError,
};
pub use handler::ToolUseBlockStart;
pub use history::{History, HistoryEntry};
pub use interceptor::{
AssistantTurnEndContext, Interceptor, InterceptorCallId, InterceptorCounter,
InterceptorCounters, InterceptorError, InterceptorErrorCategory, InterceptorFailure,
InterceptorInvocation, InterceptorPhase, InterceptorResult, InterceptorRunId,
InterceptorTurnId, MAX_INTERCEPTOR_DIAGNOSTIC_BYTES, PendingHistoryAppendsContext,
PreLlmRequestContext, PromptSubmitContext, RunExitContext,
};
pub use message::{ContentPart, Item, Message, Role};
pub use tool::{
ToolCall, ToolExecutionContext, ToolExecutionHandle, ToolExecutionPolicy,
ToolExecutionTerminal, ToolExecutionTerminalFuture, ToolOutputLimits, ToolResult,
ToolResultDisposition,
};
pub use usage_record::UsageRecord;
/// Implementation dependencies used by code generated from `agen` macros.
///
/// This module is not a stable user-facing API. It is public only because macro expansion
/// happens in the downstream crate.
#[doc(hidden)]
pub mod __private {
pub use async_trait;
pub use schemars;
pub use serde;
pub use serde_json;
}
@@ -1,15 +1,11 @@
//! `Scheme` 実装と通信層が要求する認証要件、および動的認証プロバイダ。 //! `Scheme` 実装と通信層が要求する認証要件、および動的認証プロバイダ。
//! //!
//! マニフェスト側の型(`ModelConfig` / `SchemeKind` / `AuthRef`)は
//! `crates/manifest` に置き、llm-worker はそれを知らずに済む。
//! `AuthRequirement` は scheme が宣言する「この scheme はどんな認証を //! `AuthRequirement` は scheme が宣言する「この scheme はどんな認証を
//! 期待するか」のランタイム記述で、manifest 側の `AuthRef` との //! 期待するか」のランタイム記述で、設定ファイルや環境変数などから
//! 照合(`AuthRef → ResolvedAuth` 変換の適否)は `crates/provider` //! [`super::transport::ResolvedAuth`] を組み立てる責務は呼び出し側にある。
//! で行う。
//! //!
//! Codex OAuth のようにリクエスト毎にトークンが変わり得る認証は //! リクエスト毎にトークンが変わり得る認証は [`AuthProvider`] trait を
//! [`AuthProvider`] trait を `crates/provider` 側で実装し、 //! 実装し、[`super::transport::ResolvedAuth::Custom`] 経由で transport に渡す。
//! [`super::transport::ResolvedAuth::Custom`] 経由で transport に渡す。
use async_trait::async_trait; use async_trait::async_trait;
use reqwest::header::{HeaderName, HeaderValue}; use reqwest::header::{HeaderName, HeaderValue};
@@ -27,16 +23,15 @@ pub enum AuthRequirement {
XApiKey, XApiKey,
/// クエリパラメータ `?<name>=<token>`Gemini 形式) /// クエリパラメータ `?<name>=<token>`Gemini 形式)
QueryParam { name: &'static str }, QueryParam { name: &'static str },
/// 複合ヘッダ(Codex OAuth 等、`crates/provider` で解決) /// 複合ヘッダ(呼び出し側が [`AuthProvider`] で解決)
Custom, Custom,
} }
/// リクエスト毎に認証ヘッダを動的に組み立てるプロバイダ。 /// リクエスト毎に認証ヘッダを動的に組み立てるプロバイダ。
/// ///
/// Codex OAuth のように access_token が refresh で更新されたり、 /// access token が refresh で更新されたり、複数ヘッダを同時に注入する
/// `ChatGPT-Account-Id` / `X-OpenAI-Fedramp` のような複数ヘッダを /// 必要があるケースで使う。実体は呼び出し側に置き、agen は
/// 同時に注入する必要があるケースで使う。実体は `crates/provider` /// trait を知るだけ。
/// 側に置き、llm-worker は trait を知るだけ。
/// ///
/// 返したヘッダはそのまま `HeaderMap` に挿入される。`Authorization` /// 返したヘッダはそのまま `HeaderMap` に挿入される。`Authorization`
/// 含む scheme 既定の認証ヘッダは送出されないので、必要なら /// 含む scheme 既定の認証ヘッダは送出されないので、必要なら
@@ -45,13 +40,4 @@ pub enum AuthRequirement {
pub trait AuthProvider: Send + Sync + std::fmt::Debug { pub trait AuthProvider: Send + Sync + std::fmt::Debug {
/// 1 リクエスト分の認証ヘッダを返す。refresh が必要なら内部で行う。 /// 1 リクエスト分の認証ヘッダを返す。refresh が必要なら内部で行う。
async fn headers(&self) -> Result<Vec<(HeaderName, HeaderValue)>, ClientError>; async fn headers(&self) -> Result<Vec<(HeaderName, HeaderValue)>, ClientError>;
/// ChatGPT Codex backend 向けの複合認証かどうか。
///
/// transport は provider crate の具象型を知らないため、この hook だけで
/// Codex CLI 互換の wire behaviorconversation header / request compression 等)
/// を切り替える。
fn is_codex_backend(&self) -> bool {
false
}
} }
@@ -81,7 +81,7 @@ impl Clone for Box<dyn LlmClient> {
/// `Box<dyn LlmClient>` に対する `LlmClient` の実装 /// `Box<dyn LlmClient>` に対する `LlmClient` の実装
/// ///
/// これにより、動的ディスパッチを使用するクライアントも `Worker` で利用可能になる。 /// これにより、動的ディスパッチを使用するクライアントも `Engine` で利用可能になる。
#[async_trait] #[async_trait]
impl LlmClient for Box<dyn LlmClient> { impl LlmClient for Box<dyn LlmClient> {
async fn stream(&self, request: Request) -> Result<ResponseStream, ClientError> { async fn stream(&self, request: Request) -> Result<ResponseStream, ClientError> {
@@ -18,6 +18,9 @@ pub enum ClientError {
message: String, message: String,
retry_after: Option<Duration>, retry_after: Option<Duration>,
}, },
/// The provider rejected the request because it exceeded the model context window.
/// Classified only from a structured provider error code, never message text.
ContextWindowExceeded,
/// A request lifecycle phase exceeded its hard timeout. /// A request lifecycle phase exceeded its hard timeout.
Timeout { Timeout {
phase: &'static str, phase: &'static str,
@@ -48,6 +51,7 @@ impl fmt::Display for ClientError {
} }
write!(f, ": {}", message) write!(f, ": {}", message)
} }
ClientError::ContextWindowExceeded => write!(f, "Model context window reached"),
ClientError::Timeout { phase, timeout } => { ClientError::Timeout { phase, timeout } => {
write!(f, "{phase} timed out after {}s", timeout.as_secs()) write!(f, "{phase} timed out after {}s", timeout.as_secs())
} }
@@ -112,7 +116,10 @@ pub fn is_retryable(error: &ClientError) -> bool {
ClientError::Api { status: None, .. } => false, ClientError::Api { status: None, .. } => false,
ClientError::Timeout { .. } => true, ClientError::Timeout { .. } => true,
ClientError::Http(e) => e.is_connect() || e.is_timeout(), ClientError::Http(e) => e.is_connect() || e.is_timeout(),
ClientError::Json(_) | ClientError::Sse(_) | ClientError::Config(_) => false, ClientError::ContextWindowExceeded
| ClientError::Json(_)
| ClientError::Sse(_)
| ClientError::Config(_) => false,
} }
} }
@@ -17,14 +17,12 @@ use serde::{Deserialize, Serialize};
/// ///
/// - **メタイベント**: `Ping`, `Usage`, `Status`, `Error`, `UnhandledSse` /// - **メタイベント**: `Ping`, `Usage`, `Status`, `Error`, `UnhandledSse`
/// - **ブロックイベント**: `BlockStart`, `BlockDelta`, `BlockStop`, `BlockAbort` /// - **ブロックイベント**: `BlockStart`, `BlockDelta`, `BlockStop`, `BlockAbort`
/// - **永続化イベント**: `ReasoningItem` (history に commit すべき完成済み
/// reasoning item。streaming 表示用の Thinking BlockStart/Delta/Stop と
/// は別経路で発火する)
/// ///
/// # ブロックのライフサイクル /// # ブロックのライフサイクル
/// ///
/// テキストツール呼び出しは、`BlockStart` → `BlockDelta`(複数) → `BlockStop` /// テキスト、thinking、ツール呼び出しは、`BlockStart` → `BlockDelta`(複数) → `BlockStop`
/// の順序でイベントが発生します。 /// の順序でイベントが発生します。thinking の round-trip metadata は
/// `BlockStop.reasoning` に載ります。
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Event { pub enum Event {
/// ハートビート /// ハートビート
@@ -48,18 +46,6 @@ pub enum Event {
BlockStop(BlockStop), BlockStop(BlockStop),
/// ブロック中断 /// ブロック中断
BlockAbort(BlockAbort), BlockAbort(BlockAbort),
/// Reasoning item の完成。scheme が「次の request に送り返すための
/// reasoning material が揃った」点で 1 度だけ発火する。
///
/// - Anthropic: 1 つの `thinking` content_block 完了ごと
/// - OpenAI Responses: 1 つの reasoning output_item 完了ごと
///
/// 上位層(Worker / ReasoningItemCollector)はこれを `Item::Reasoning`
/// として `worker.history` に append する。streaming 表示用の
/// `BlockStart(Thinking)` / `BlockDelta(Thinking)` / `BlockStop(Thinking)`
/// は依然として並行発火する(live display と round-trip persist の責務分離)。
ReasoningItem(ReasoningItemEvent),
} }
// ============================================================================= // =============================================================================
@@ -218,6 +204,12 @@ pub struct BlockStop {
pub block_type: BlockType, pub block_type: BlockType,
/// 停止理由 /// 停止理由
pub stop_reason: Option<StopReason>, pub stop_reason: Option<StopReason>,
/// Thinking block の停止時に確定した reasoning round-trip metadata。
///
/// `None` の Thinking block は live streaming / trace 用で、history に
/// `Item::Reasoning` として永続化しない。`Some` の場合は block lifecycle
/// が永続化の authoritative source になる。
pub reasoning: Option<ReasoningBlockData>,
} }
impl BlockStop { impl BlockStop {
@@ -243,22 +235,17 @@ impl BlockAbort {
} }
} }
// ============================================================================= /// Thinking block stop で確定した reasoning material。
// Reasoning Item Event
// =============================================================================
/// 完成済み reasoning item。scheme が round-trip に必要なすべての
/// materialtext, summary, encrypted_content, signature, id)を揃えて
/// 1 度だけ発火する。
/// ///
/// `Item::Reasoning` のフィールドを 1:1 に持つ /// `Item::Reasoning` の round-trip に必要な provider material を保持する
/// `text` は deltas から収集した本文を上書きするために使う(metadata-only
/// reasoning block や provider completion event で全文が届くケース)。
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct ReasoningItemEvent { pub struct ReasoningBlockData {
/// scheme 側で観測した item idOpenAI Responses の `id`)。 /// scheme 側で観測した item idOpenAI Responses の `id`)。
pub id: Option<String>, pub id: Option<String>,
/// reasoning 本体テキスト。Anthropic は `thinking` 累積、OpenAI は /// reasoning 本体テキスト。`None` の場合は block delta 収集結果を使う。
/// `reasoning_text` 累積。redacted_thinking では空。 pub text: Option<String>,
pub text: String,
/// summary (OpenAI Responses の `summary_text[]`)。他 scheme は空。 /// summary (OpenAI Responses の `summary_text[]`)。他 scheme は空。
pub summary: Vec<String>, pub summary: Vec<String>,
/// 暗号化された opaque blobAnthropic `redacted_thinking.data` / /// 暗号化された opaque blobAnthropic `redacted_thinking.data` /
@@ -309,6 +296,7 @@ impl Event {
index, index,
block_type: BlockType::Text, block_type: BlockType::Text,
stop_reason, stop_reason,
reasoning: None,
}) })
} }
@@ -338,6 +326,7 @@ impl Event {
index, index,
block_type: BlockType::ToolUse, block_type: BlockType::ToolUse,
stop_reason: Some(StopReason::ToolUse), stop_reason: Some(StopReason::ToolUse),
reasoning: None,
}) })
} }
@@ -1,15 +1,15 @@
//! LLM response stream を開く前の transient error 向けリトライポリシー。 //! LLM response stream を開く前の transient error 向けリトライポリシー。
//! //!
//! Worker が `LlmClient::stream` の open error に対して `is_retryable` を見て //! `LlmClient::stream` の open error に対して `is_retryable` を見て
//! retry / backoff / TUI event / cancellation をまとめて管理する。 //! retry / backoff / cancellation をまとめて管理する。
//! SSE 読み出し開始後の失敗は対象外。 //! SSE 読み出し開始後の失敗は対象外。
use std::time::Duration; use std::time::Duration;
/// 指数バックオフ + ジッター + 累積タイムアウトを表すポリシー。 /// 指数バックオフ + ジッター + 累積タイムアウトを表すポリシー。
/// ///
/// `Default` は llm-worker 全体の固定値を返す。manifest 経由の上書きが /// `Default` は agen 全体の固定値を返す。呼び出し側からの上書きが
/// 必要になったら拡張する(現状は不要 → `tickets/llm-worker-transient-retry.md` /// 必要になったら拡張する。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RetryPolicy { pub struct RetryPolicy {
/// 指数の基準値。`base * 2^attempt` を `cap` で頭打ちにした上限から /// 指数の基準値。`base * 2^attempt` を `cap` で頭打ちにした上限から
@@ -1,7 +1,7 @@
//! Anthropic scheme の wire-level 既定 capability。 //! Anthropic scheme の wire-level 既定 capability。
//! //!
//! モデル ID 固有のテーブル(`claude-*` など)は高レベル構築層 //! モデル ID 固有のテーブル(`claude-*` など)は client construction layer
//! (`provider::capability`)の責務。ここでは未知モデルでも「この wire で //! の責務。ここでは未知モデルでも「この wire で
//! 安全に送れる最小共通項」を返すだけに留める。 //! 安全に送れる最小共通項」を返すだけに留める。
use crate::llm_client::capability::{ use crate::llm_client::capability::{
@@ -216,6 +216,7 @@ impl AnthropicScheme {
index: event.index, index: event.index,
block_type: BlockType::Text, // Timeline層で上書きされる block_type: BlockType::Text, // Timeline層で上書きされる
stop_reason: None, stop_reason: None,
reasoning: None,
}))) })))
} }
AnthropicEventType::MessageDelta => { AnthropicEventType::MessageDelta => {
@@ -286,9 +287,9 @@ impl AnthropicScheme {
/// `parse_event` の単発 Event に加えて、以下を行う: /// `parse_event` の単発 Event に加えて、以下を行う:
/// - `content_block_stop` の `block_type` を直前の Start 値で書き戻す /// - `content_block_stop` の `block_type` を直前の Start 値で書き戻す
/// - `thinking` / `redacted_thinking` ブロックの本体・signature・data を /// - `thinking` / `redacted_thinking` ブロックの本体・signature・data を
/// `state.pending_thinking` に蓄積し、`content_block_stop` /// `state.pending_thinking` に蓄積し、`content_block_stop` の Thinking
/// `Event::ReasoningItem` を追加発火す /// BlockStop metadata に載せ
/// - `signature_delta` を蓄積(Stream channel には流さず、reasoning event /// - `signature_delta` を蓄積(Stream channel には流さず、reasoning metadata
/// にだけ反映する) /// にだけ反映する)
pub(crate) fn parse_with_state( pub(crate) fn parse_with_state(
&self, &self,
@@ -374,16 +375,21 @@ impl AnthropicScheme {
AnthropicEventType::ContentBlockStop => { AnthropicEventType::ContentBlockStop => {
let raw: ContentBlockStopEvent = serde_json::from_str(data)?; let raw: ContentBlockStopEvent = serde_json::from_str(data)?;
let block_type = state.current_block_type.take().unwrap_or(BlockType::Text); let block_type = state.current_block_type.take().unwrap_or(BlockType::Text);
let reasoning = if matches!(block_type, BlockType::Thinking) {
state
.pending_thinking
.take()
.map(PendingThinking::into_reasoning)
} else {
state.pending_thinking.take();
None
};
emitted.push(Event::BlockStop(BlockStop { emitted.push(Event::BlockStop(BlockStop {
index: raw.index, index: raw.index,
block_type, block_type,
stop_reason: None, stop_reason: None,
reasoning,
})); }));
if matches!(block_type, BlockType::Thinking) {
if let Some(pending) = state.pending_thinking.take() {
emitted.push(Event::ReasoningItem(pending.into_event()));
}
}
} }
// 残りは state を必要としない。既存 parse_event に委譲。 // 残りは state を必要としない。既存 parse_event に委譲。
_ => { _ => {
@@ -524,8 +530,8 @@ mod tests {
} }
#[test] #[test]
fn thinking_block_emits_reasoning_item_with_signature() { fn thinking_block_stop_carries_reasoning_with_signature() {
// thinking ブロックが完了したら ReasoningItem に text+signature が乗ること // thinking ブロックが完了したら reasoning metadata に text+signature が乗ること
let scheme = AnthropicScheme::new(); let scheme = AnthropicScheme::new();
let mut state = AnthropicState::default(); let mut state = AnthropicState::default();
@@ -567,18 +573,18 @@ mod tests {
&mut state, &mut state,
) )
.unwrap(); .unwrap();
// BlockStop と ReasoningItem の 2 件が並ぶ assert_eq!(stop_evs.len(), 1);
assert!(matches!(stop_evs[0], Event::BlockStop(_))); let Event::BlockStop(stop) = &stop_evs[0] else {
let Event::ReasoningItem(reasoning) = &stop_evs[1] else { panic!("expected BlockStop, got {:?}", stop_evs[0]);
panic!("expected ReasoningItem, got {:?}", stop_evs[1]);
}; };
assert_eq!(reasoning.text, "hello world"); let reasoning = stop.reasoning.as_ref().expect("reasoning metadata");
assert_eq!(reasoning.text.as_deref(), Some("hello world"));
assert_eq!(reasoning.signature.as_deref(), Some("SIG-XYZ")); assert_eq!(reasoning.signature.as_deref(), Some("SIG-XYZ"));
assert!(reasoning.encrypted_content.is_none()); assert!(reasoning.encrypted_content.is_none());
} }
#[test] #[test]
fn redacted_thinking_emits_reasoning_item_with_data() { fn redacted_thinking_stop_carries_reasoning_with_data() {
let scheme = AnthropicScheme::new(); let scheme = AnthropicScheme::new();
let mut state = AnthropicState::default(); let mut state = AnthropicState::default();
@@ -596,16 +602,18 @@ mod tests {
&mut state, &mut state,
) )
.unwrap(); .unwrap();
let Event::ReasoningItem(reasoning) = &stop_evs[1] else { assert_eq!(stop_evs.len(), 1);
panic!("expected ReasoningItem"); let Event::BlockStop(stop) = &stop_evs[0] else {
panic!("expected BlockStop");
}; };
assert!(reasoning.text.is_empty()); let reasoning = stop.reasoning.as_ref().expect("reasoning metadata");
assert_eq!(reasoning.text.as_deref(), Some(""));
assert!(reasoning.signature.is_none()); assert!(reasoning.signature.is_none());
assert_eq!(reasoning.encrypted_content.as_deref(), Some("opaque-blob")); assert_eq!(reasoning.encrypted_content.as_deref(), Some("opaque-blob"));
} }
#[test] #[test]
fn text_block_does_not_emit_reasoning_item() { fn text_block_stop_has_no_reasoning_metadata() {
let scheme = AnthropicScheme::new(); let scheme = AnthropicScheme::new();
let mut state = AnthropicState::default(); let mut state = AnthropicState::default();
@@ -631,7 +639,10 @@ mod tests {
) )
.unwrap(); .unwrap();
assert_eq!(stop_evs.len(), 1); assert_eq!(stop_evs.len(), 1);
assert!(matches!(stop_evs[0], Event::BlockStop(_))); let Event::BlockStop(stop) = &stop_evs[0] else {
panic!("expected BlockStop");
};
assert!(stop.reasoning.is_none());
} }
#[test] #[test]
@@ -9,7 +9,7 @@ use crate::llm_client::{
ClientError, ClientError,
auth::AuthRequirement, auth::AuthRequirement,
capability::ModelCapability, capability::ModelCapability,
event::{BlockType, Event, ReasoningItemEvent}, event::{BlockType, Event, ReasoningBlockData},
scheme::Scheme, scheme::Scheme,
types::Request, types::Request,
}; };
@@ -23,7 +23,7 @@ use super::AnthropicScheme;
/// `BlockStop` に書き戻す。 /// `BlockStop` に書き戻す。
/// 2. `thinking` ブロック中の `thinking_delta` テキストと `signature_delta` /// 2. `thinking` ブロック中の `thinking_delta` テキストと `signature_delta`
/// 署名、および `redacted_thinking` ブロックの `data` を蓄積し、 /// 署名、および `redacted_thinking` ブロックの `data` を蓄積し、
/// `content_block_stop` で `Event::ReasoningItem` を発火する /// `content_block_stop` の Thinking block metadata として返す
/// round-trip 永続化のため)。 /// round-trip 永続化のため)。
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct AnthropicState { pub struct AnthropicState {
@@ -40,10 +40,10 @@ pub(crate) struct PendingThinking {
} }
impl PendingThinking { impl PendingThinking {
pub(crate) fn into_event(self) -> ReasoningItemEvent { pub(crate) fn into_reasoning(self) -> ReasoningBlockData {
ReasoningItemEvent { ReasoningBlockData {
id: None, id: None,
text: self.text, text: Some(self.text),
summary: Vec::new(), summary: Vec::new(),
encrypted_content: self.redacted_data, encrypted_content: self.redacted_data,
signature: self.signature, signature: self.signature,
@@ -1,7 +1,7 @@
//! Gemini scheme の wire-level 既定 capability。 //! Gemini scheme の wire-level 既定 capability。
//! //!
//! モデル ID 固有のテーブル(`gemini-*` バージョン別の reasoning 有無)は //! モデル ID 固有のテーブル(`gemini-*` バージョン別の reasoning 有無)は
//! 高レベル構築層(`provider::capability`)の責務。ここでは wire の //! client construction layer の責務。ここでは wire の
//! 保守的 default のみ。 //! 保守的 default のみ。
use crate::llm_client::capability::{ use crate::llm_client::capability::{
@@ -205,6 +205,7 @@ impl GeminiScheme {
index: candidate_index, index: candidate_index,
block_type: BlockType::Text, block_type: BlockType::Text,
stop_reason, stop_reason,
reasoning: None,
})); }));
} }
} }
@@ -45,8 +45,8 @@ pub trait Scheme: Clone + Send + Sync + 'static {
/// プロバイダもあるため、モデル ID を受け取る。 /// プロバイダもあるため、モデル ID を受け取る。
fn path(&self, model_id: &str) -> String; fn path(&self, model_id: &str) -> String;
/// この scheme が要求する認証形式。`build_client` 時に /// この scheme が要求する認証形式。呼び出し側は client 構築時に
/// `manifest::AuthRef` と照合する。 /// 設定された認証情報と照合する。
fn required_auth(&self) -> AuthRequirement; fn required_auth(&self) -> AuthRequirement;
/// `Content-Type` 以外の追加ヘッダ。`anthropic-version` / `anthropic-beta` 等。 /// `Content-Type` 以外の追加ヘッダ。`anthropic-version` / `anthropic-beta` 等。
@@ -78,8 +78,7 @@ pub trait Scheme: Clone + Send + Sync + 'static {
/// scheme 既定の capability。モデル ID に関係なく、この wire で /// scheme 既定の capability。モデル ID に関係なく、この wire で
/// 安全に送れる最小共通項を返す。既知モデル ID の能力テーブルは /// 安全に送れる最小共通項を返す。既知モデル ID の能力テーブルは
/// `provider::capability::lookup` 側(高レベル構築層)の責務で、 /// 高レベルの client 構築層の責務で、scheme はここには関与しない。
/// scheme はここには関与しない。
fn default_capability(&self) -> ModelCapability; fn default_capability(&self) -> ModelCapability;
/// scheme 側でサポートしていない `RequestConfig` フィールドを /// scheme 側でサポートしていない `RequestConfig` フィールドを
@@ -1,7 +1,7 @@
//! OpenAI Chat Completions scheme の wire-level 既定 capability。 //! OpenAI Chat Completions scheme の wire-level 既定 capability。
//! //!
//! モデル ID 固有のテーブル(`gpt-5` 系など)は高レベル構築層 //! モデル ID 固有のテーブル(`gpt-5` 系など)は client construction layer
//! (`provider::capability`)の責務。ここでは wire の保守的 default のみ。 //! の責務。ここでは wire の保守的 default のみ。
use crate::llm_client::capability::{ use crate::llm_client::capability::{
CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport, CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport,
@@ -5,10 +5,13 @@
use serde::Serialize; use serde::Serialize;
use serde_json::Value; use serde_json::Value;
use crate::llm_client::{ use crate::{
Request, llm_client::{
capability::{ModelCapability, ReasoningControl, ReasoningSupport}, Request,
types::{Item, Role, ToolDefinition, parse_tool_arguments}, capability::{ModelCapability, ReasoningControl, ReasoningSupport},
types::{ContentPart, Item, Role, ToolDefinition, image_data_url, parse_tool_arguments},
},
tool::Attachment,
}; };
use super::OpenAIScheme; use super::OpenAIScheme;
@@ -134,7 +137,7 @@ impl OpenAIScheme {
} }
// Convert items to messages // Convert items to messages
messages.extend(self.convert_items_to_messages(&request.items)); messages.extend(self.convert_items_to_messages(&request.items, capability.vision));
let tools = request.tools.iter().map(|t| self.convert_tool(t)).collect(); let tools = request.tools.iter().map(|t| self.convert_tool(t)).collect();
@@ -185,12 +188,38 @@ impl OpenAIScheme {
/// - Assistant messages have role "assistant" /// - Assistant messages have role "assistant"
/// - Tool calls are within assistant messages as tool_calls array /// - Tool calls are within assistant messages as tool_calls array
/// - Tool results have role "tool" with tool_call_id /// - Tool results have role "tool" with tool_call_id
fn convert_items_to_messages(&self, items: &[Item]) -> Vec<OpenAIMessage> { fn flush_pending_tool_result_images(
messages: &mut Vec<OpenAIMessage>,
pending_images: &mut Vec<OpenAIContentPart>,
) {
if !pending_images.is_empty() {
messages.push(OpenAIMessage {
role: "user".to_string(),
content: Some(OpenAIContent::Parts(std::mem::take(pending_images))),
tool_calls: vec![],
tool_call_id: None,
name: None,
});
}
}
fn convert_items_to_messages(
&self,
items: &[Item],
supports_images: bool,
) -> Vec<OpenAIMessage> {
let mut messages = Vec::new(); let mut messages = Vec::new();
let mut pending_tool_calls: Vec<OpenAIToolCall> = Vec::new(); let mut pending_tool_calls: Vec<OpenAIToolCall> = Vec::new();
let mut pending_assistant_text: Option<String> = None; let mut pending_assistant_text: Option<String> = None;
let mut pending_tool_result_images: Vec<OpenAIContentPart> = Vec::new();
for item in items { for item in items {
if !matches!(item, Item::ToolResult { .. }) {
Self::flush_pending_tool_result_images(
&mut messages,
&mut pending_tool_result_images,
);
}
match item { match item {
Item::Message { role, content, .. } => { Item::Message { role, content, .. } => {
// Flush pending tool calls // Flush pending tool calls
@@ -205,16 +234,17 @@ impl OpenAIScheme {
Role::Assistant => "assistant", Role::Assistant => "assistant",
Role::System => "system", Role::System => "system",
}; };
let message_content = OpenAIContent::Text(
let text_content: String = content content
.iter() .iter()
.map(|p| p.as_text()) .map(ContentPart::as_text)
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(""); .join(""),
);
messages.push(OpenAIMessage { messages.push(OpenAIMessage {
role: openai_role.to_string(), role: openai_role.to_string(),
content: Some(OpenAIContent::Text(text_content)), content: Some(message_content),
tool_calls: vec![], tool_calls: vec![],
tool_call_id: None, tool_call_id: None,
name: None, name: None,
@@ -244,19 +274,35 @@ impl OpenAIScheme {
call_id, call_id,
summary, summary,
content, content,
attachments,
.. ..
} => { } => {
// Flush pending tool calls before tool result // OpenAI requires every parallel tool result before a new user message.
self.flush_pending_assistant( self.flush_pending_assistant(
&mut messages, &mut messages,
&mut pending_tool_calls, &mut pending_tool_calls,
&mut pending_assistant_text, &mut pending_assistant_text,
); );
let text = match content { let mut text = match content {
Some(c) => format!("{summary}\n{c}"), Some(c) => format!("{summary}\n{c}"),
None => summary.clone(), None => summary.clone(),
}; };
if supports_images {
pending_tool_result_images.extend(attachments.iter().map(|attachment| {
let Attachment::Image(image) = attachment;
OpenAIContentPart::ImageUrl {
image_url: ImageUrl {
url: image_data_url(image.mime_type(), image.data()),
},
}
}));
} else if !attachments.is_empty() {
text.push_str(&format!(
"\n[{} image attachment(s) omitted: model does not support images]",
attachments.len()
));
}
messages.push(OpenAIMessage { messages.push(OpenAIMessage {
role: "tool".to_string(), role: "tool".to_string(),
content: Some(OpenAIContent::Text(text)), content: Some(OpenAIContent::Text(text)),
@@ -284,6 +330,7 @@ impl OpenAIScheme {
&mut pending_tool_calls, &mut pending_tool_calls,
&mut pending_assistant_text, &mut pending_assistant_text,
); );
Self::flush_pending_tool_result_images(&mut messages, &mut pending_tool_result_images);
messages messages
} }
@@ -334,6 +381,13 @@ mod tests {
} }
} }
fn vision_cap() -> ModelCapability {
ModelCapability {
vision: true,
..cap()
}
}
#[test] #[test]
fn test_build_simple_request() { fn test_build_simple_request() {
let scheme = OpenAIScheme::new(); let scheme = OpenAIScheme::new();
@@ -439,4 +493,94 @@ mod tests {
assert_eq!(body.messages[1].tool_calls.len(), 1); assert_eq!(body.messages[1].tool_calls.len(), 1);
assert_eq!(body.messages[2].role, "tool"); assert_eq!(body.messages[2].role, "tool");
} }
#[test]
fn parallel_tool_results_precede_durable_image_projection() {
let scheme = OpenAIScheme::new();
let image = std::sync::Arc::<[u8]>::from(&b"\x89PNG\r\n\x1a\nbody"[..]);
let request = Request::new()
.item(Item::tool_call("call_image", "ViewImage", "{}"))
.item(Item::tool_call("call_text", "Read", "{}"))
.item(Item::tool_result_item_with_attachments(
"call_image",
"Attached image",
None,
false,
vec![crate::tool::Attachment::Image(
crate::tool::ImageAttachment::new("image/png", image),
)],
))
.item(Item::tool_result_item(
"call_text",
"Read text",
None,
false,
));
let json = serde_json::to_value(
&scheme
.build_request("gpt-4o", &request, &vision_cap())
.messages,
)
.unwrap();
assert_eq!(json[0]["role"], "assistant");
assert_eq!(json[1]["role"], "tool");
assert_eq!(json[2]["role"], "tool");
assert_eq!(json[3]["role"], "user");
assert_eq!(json[3]["content"][0]["type"], "image_url");
}
#[test]
fn durable_tool_image_is_deterministically_lowered_to_following_user_content() {
let scheme = OpenAIScheme::new();
let image = std::sync::Arc::<[u8]>::from(&b"\x89PNG\r\n\x1a\nbody"[..]);
let attachment = crate::tool::Attachment::Image(crate::tool::ImageAttachment::new(
"image/png",
image.clone(),
));
let item = Item::tool_result_item_with_attachments(
"call_image",
"Attached image",
None,
false,
vec![attachment],
);
let persisted = serde_json::to_string(&item).unwrap();
assert!(persisted.contains("attachments"));
let restored: Item = serde_json::from_str(&persisted).unwrap();
let request = Request::new()
.item(Item::tool_call(
"call_image",
"ViewImage",
r#"{"path":"a.png"}"#,
))
.item(restored);
let body = scheme.build_request("gpt-4o", &request, &vision_cap());
let json = serde_json::to_value(&body.messages).unwrap();
let rebuilt = serde_json::to_value(
&scheme
.build_request("gpt-4o", &request, &vision_cap())
.messages,
)
.unwrap();
assert_eq!(rebuilt, json);
assert_eq!(json[0]["role"], "assistant");
assert_eq!(json[1]["role"], "tool");
assert_eq!(json[2]["role"], "user");
assert_eq!(json[2]["content"][0]["type"], "image_url");
assert!(
json[2]["content"][0]["image_url"]["url"]
.as_str()
.unwrap()
.starts_with("data:image/png;base64,")
);
let mut no_vision = cap();
no_vision.vision = false;
let disabled =
serde_json::to_string(&scheme.build_request("gpt-4o", &request, &no_vision)).unwrap();
assert!(!disabled.contains("data:image"));
}
} }
@@ -1,7 +1,7 @@
//! OpenAI Responses scheme の wire-level 既定 capability。 //! OpenAI Responses scheme の wire-level 既定 capability。
//! //!
//! モデル ID 固有のテーブル(`gpt-5` / `codex-` 系など)は高レベル構築層 //! モデル ID 固有の能力テーブルは高レベルの client 構築層の責務。
//! (`provider::capability`)の責務。ここでは wire の保守的 default のみ。 //! ここでは wire の保守的 default のみ。
use crate::llm_client::capability::{ use crate::llm_client::capability::{
CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport, CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport,
@@ -2,7 +2,7 @@
//! //!
//! `response.*` 名前空間の SSE を共通の [`Event`](crate::llm_client::event::Event) //! `response.*` 名前空間の SSE を共通の [`Event`](crate::llm_client::event::Event)
//! に変換する。Responses の (output_index, content_index) 2 次元座標と //! に変換する。Responses の (output_index, content_index) 2 次元座標と
//! insomnia 側 1 次元 `BlockStart/Delta/Stop::index` のマッピングは //! この crate の 1 次元 `BlockStart/Delta/Stop::index` のマッピングは
//! [`OpenAIResponsesState`] が保持する。 //! [`OpenAIResponsesState`] が保持する。
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
@@ -14,7 +14,7 @@ use crate::llm_client::{
ClientError, ClientError,
event::{ event::{
BlockDelta, BlockMetadata, BlockStart, BlockStop, BlockType, DeltaContent, ErrorEvent, BlockDelta, BlockMetadata, BlockStart, BlockStop, BlockType, DeltaContent, ErrorEvent,
Event, ReasoningItemEvent, ResponseStatus, StatusEvent, UnhandledSseEvent, UsageEvent, Event, ReasoningBlockData, ResponseStatus, StatusEvent, UnhandledSseEvent, UsageEvent,
}, },
}; };
@@ -25,8 +25,8 @@ pub struct OpenAIResponsesState {
next_index: usize, next_index: usize,
/// 蓄積中の reasoning output_item。`output_item.added`(Reasoning) で /// 蓄積中の reasoning output_item。`output_item.added`(Reasoning) で
/// 確保し、`reasoning_text.delta` / `reasoning_summary_text.delta` で /// 確保し、`reasoning_text.delta` / `reasoning_summary_text.delta` で
/// 蓄積、`output_item.done`(Reasoning) で `Event::ReasoningItem` を /// 蓄積、`output_item.done`(Reasoning) で既存 reasoning_text block または
/// 発火してエントリを除去する。 /// metadata-only Thinking block に reasoning persistence material を載せる。
pending_reasoning: HashMap<usize, PendingReasoning>, pending_reasoning: HashMap<usize, PendingReasoning>,
} }
@@ -38,6 +38,24 @@ struct PendingReasoning {
text: String, text: String,
/// `reasoning_summary_text.delta` を summary_index 順に蓄積。 /// `reasoning_summary_text.delta` を summary_index 順に蓄積。
summary: Vec<String>, summary: Vec<String>,
/// `response.content_part.done` が先に到着した reasoning/thinking block。
///
/// `response.output_item.done` まで待たないと encrypted_content や最終
/// summary が揃わないため、live-visible な余分な synthetic Thinking block
/// を作らず、既存 block の stop に persistence metadata を載せる。
deferred_thinking_stops: Vec<SlotInfo>,
}
impl PendingReasoning {
fn into_reasoning_data(self, encrypted_content: Option<String>) -> ReasoningBlockData {
ReasoningBlockData {
id: self.id,
text: Some(self.text),
summary: self.summary.into_iter().filter(|s| !s.is_empty()).collect(),
encrypted_content,
signature: None,
}
}
} }
impl OpenAIResponsesState { impl OpenAIResponsesState {
@@ -73,6 +91,31 @@ impl OpenAIResponsesState {
} }
entry.summary[summary_index].push_str(text); entry.summary[summary_index].push_str(text);
} }
fn defer_reasoning_stop(&mut self, output_index: usize, info: SlotInfo) {
self.ensure_reasoning(output_index)
.deferred_thinking_stops
.push(info);
}
fn take_active_reasoning_slots(&mut self, output_index: usize) -> Vec<SlotInfo> {
let mut keys: Vec<_> = self
.slots
.iter()
.filter_map(|(key, info)| match key {
SlotKey::ContentPart { output, content }
if *output == output_index && info.block_type == BlockType::Thinking =>
{
Some((*content, *key))
}
_ => None,
})
.collect();
keys.sort_by_key(|(content, _)| *content);
keys.into_iter()
.filter_map(|(_, key)| self.slots.remove(&key))
.collect()
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -380,9 +423,10 @@ pub(crate) fn parse_sse(
"response.output_item.done" => { "response.output_item.done" => {
let ev: OutputItemDone = from_json(data)?; let ev: OutputItemDone = from_json(data)?;
// Reasoning wrapper の done で蓄積分を ReasoningItem として発火。 // Reasoning wrapper の done で蓄積分を既存 reasoning_text block の
// これは `slots` の OutputItem slot とは独立している // stop に載せる。content_part.done が先に来た場合は stop を defer
// (FunctionCall は slots、Reasoning は pending_reasoning) // しておき、ここで encrypted_content / summary と一緒に完了させる
// reasoning_text が無い metadata-only item だけ synthetic block を作る。
if let OutputItem::Reasoning { if let OutputItem::Reasoning {
id, id,
encrypted_content, encrypted_content,
@@ -396,23 +440,50 @@ pub(crate) fn parse_sse(
if pending.id.is_none() { if pending.id.is_none() {
pending.id = id; pending.id = id;
} }
return Ok(vec![Event::ReasoningItem(ReasoningItemEvent {
id: pending.id, let mut stop_blocks = std::mem::take(&mut pending.deferred_thinking_stops);
text: pending.text, stop_blocks.extend(state.take_active_reasoning_slots(ev.output_index));
summary: pending let reasoning = pending.into_reasoning_data(encrypted_content);
.summary
.into_iter() if stop_blocks.is_empty() {
.filter(|s| !s.is_empty()) let info =
.collect(), state.allocate(SlotKey::OutputItem(ev.output_index), BlockType::Thinking);
encrypted_content, state.slots.remove(&SlotKey::OutputItem(ev.output_index));
signature: None, return Ok(vec![
})]); Event::BlockStart(BlockStart {
index: info.flat_index,
block_type: BlockType::Thinking,
metadata: BlockMetadata::Thinking,
}),
Event::BlockStop(BlockStop {
index: info.flat_index,
block_type: BlockType::Thinking,
stop_reason: None,
reasoning: Some(reasoning),
}),
]);
}
let last = stop_blocks.len() - 1;
return Ok(stop_blocks
.into_iter()
.enumerate()
.map(|(idx, info)| {
Event::BlockStop(BlockStop {
index: info.flat_index,
block_type: info.block_type,
stop_reason: None,
reasoning: (idx == last).then(|| reasoning.clone()),
})
})
.collect());
} }
if let Some(info) = state.slots.remove(&SlotKey::OutputItem(ev.output_index)) { if let Some(info) = state.slots.remove(&SlotKey::OutputItem(ev.output_index)) {
Ok(vec![Event::BlockStop(BlockStop { Ok(vec![Event::BlockStop(BlockStop {
index: info.flat_index, index: info.flat_index,
block_type: info.block_type, block_type: info.block_type,
stop_reason: None, stop_reason: None,
reasoning: None,
})]) })])
} else { } else {
Ok(Vec::new()) Ok(Vec::new())
@@ -446,11 +517,19 @@ pub(crate) fn parse_sse(
output: ev.output_index, output: ev.output_index,
content: ev.content_index, content: ev.content_index,
}) { }) {
Ok(vec![Event::BlockStop(BlockStop { if matches!(ev.part, ContentPart::ReasoningText { .. })
index: info.flat_index, || info.block_type == BlockType::Thinking
block_type: info.block_type, {
stop_reason: None, state.defer_reasoning_stop(ev.output_index, info);
})]) Ok(Vec::new())
} else {
Ok(vec![Event::BlockStop(BlockStop {
index: info.flat_index,
block_type: info.block_type,
stop_reason: None,
reasoning: None,
})])
}
} else { } else {
Ok(Vec::new()) Ok(Vec::new())
} }
@@ -531,6 +610,7 @@ pub(crate) fn parse_sse(
index: info.flat_index, index: info.flat_index,
block_type: info.block_type, block_type: info.block_type,
stop_reason: None, stop_reason: None,
reasoning: None,
})]) })])
} else { } else {
Ok(Vec::new()) Ok(Vec::new())
@@ -1116,9 +1196,9 @@ mod tests {
} }
#[test] #[test]
fn reasoning_output_item_emits_reasoning_item_with_text_summary_encrypted() { fn reasoning_output_item_completes_metadata_thinking_block_with_text_summary_encrypted() {
// 完成済み reasoning wrapper が text + summary[] + encrypted_content を持って // 完成済み reasoning wrapper が text + summary[] + encrypted_content を持って
// ReasoningItem として届くこと。 // Thinking BlockStop metadata として届くこと。
let mut state = OpenAIResponsesState::default(); let mut state = OpenAIResponsesState::default();
// wrapper added (id だけ持つ) // wrapper added (id だけ持つ)
@@ -1128,11 +1208,15 @@ mod tests {
r#"{"output_index":0,"item":{"type":"reasoning","id":"r1"}}"#, r#"{"output_index":0,"item":{"type":"reasoning","id":"r1"}}"#,
); );
// 内側の reasoning_text 用 content_part // 内側の reasoning_text 用 content_part
with( let start = with(
&mut state, &mut state,
"response.content_part.added", "response.content_part.added",
r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":""}}"#, r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":""}}"#,
); );
let start_index = match start.as_slice() {
[Event::BlockStart(start)] => start.index,
other => panic!("expected one BlockStart, got {other:?}"),
};
with( with(
&mut state, &mut state,
"response.reasoning_text.delta", "response.reasoning_text.delta",
@@ -1143,11 +1227,12 @@ mod tests {
"response.reasoning_text.delta", "response.reasoning_text.delta",
r#"{"output_index":0,"content_index":0,"item_id":"r1","delta":"world"}"#, r#"{"output_index":0,"content_index":0,"item_id":"r1","delta":"world"}"#,
); );
with( let part_done = with(
&mut state, &mut state,
"response.content_part.done", "response.content_part.done",
r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":"hello world"}}"#, r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":"hello world"}}"#,
); );
assert!(part_done.is_empty());
// summary 1 件 // summary 1 件
with( with(
&mut state, &mut state,
@@ -1172,11 +1257,13 @@ mod tests {
r#"{"output_index":0,"item":{"type":"reasoning","id":"r1","encrypted_content":"ENC-XYZ"}}"#, r#"{"output_index":0,"item":{"type":"reasoning","id":"r1","encrypted_content":"ENC-XYZ"}}"#,
); );
assert_eq!(evs.len(), 1); assert_eq!(evs.len(), 1);
let Event::ReasoningItem(reasoning) = &evs[0] else { let Event::BlockStop(stop) = &evs[0] else {
panic!("expected ReasoningItem, got {:?}", evs[0]); panic!("expected BlockStop, got {:?}", evs[0]);
}; };
assert_eq!(stop.index, start_index);
let reasoning = stop.reasoning.as_ref().expect("reasoning metadata");
assert_eq!(reasoning.id.as_deref(), Some("r1")); assert_eq!(reasoning.id.as_deref(), Some("r1"));
assert_eq!(reasoning.text, "hello world"); assert_eq!(reasoning.text.as_deref(), Some("hello world"));
assert_eq!(reasoning.summary, vec!["sum-A".to_string()]); assert_eq!(reasoning.summary, vec!["sum-A".to_string()]);
assert_eq!(reasoning.encrypted_content.as_deref(), Some("ENC-XYZ")); assert_eq!(reasoning.encrypted_content.as_deref(), Some("ENC-XYZ"));
assert!(reasoning.signature.is_none()); assert!(reasoning.signature.is_none());
@@ -1184,10 +1271,94 @@ mod tests {
assert!(state.pending_reasoning.is_empty()); assert!(state.pending_reasoning.is_empty());
} }
#[test]
fn reasoning_text_done_then_output_done_emits_single_existing_block_stop() {
let mut state = OpenAIResponsesState::default();
with(
&mut state,
"response.output_item.added",
r#"{"output_index":0,"item":{"type":"reasoning","id":"r1"}}"#,
);
let mut lifecycle = Vec::new();
lifecycle.extend(with(
&mut state,
"response.content_part.added",
r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":""}}"#,
));
lifecycle.extend(with(
&mut state,
"response.reasoning_text.delta",
r#"{"output_index":0,"content_index":0,"item_id":"r1","delta":"think"}"#,
));
lifecycle.extend(with(
&mut state,
"response.content_part.done",
r#"{"output_index":0,"content_index":0,"item_id":"r1","part":{"type":"reasoning_text","text":"think"}}"#,
));
lifecycle.extend(with(
&mut state,
"response.output_item.done",
r#"{"output_index":0,"item":{"type":"reasoning","id":"r1","encrypted_content":"ENC"}}"#,
));
let starts: Vec<_> = lifecycle
.iter()
.filter_map(|event| match event {
Event::BlockStart(start) => Some(start.index),
_ => None,
})
.collect();
let stops: Vec<_> = lifecycle
.iter()
.filter_map(|event| match event {
Event::BlockStop(stop) => Some(stop),
_ => None,
})
.collect();
assert_eq!(starts.len(), 1, "no synthetic second Thinking start");
assert_eq!(stops.len(), 1, "no duplicate empty Thinking stop");
assert_eq!(stops[0].index, starts[0]);
let reasoning = stops[0].reasoning.as_ref().expect("reasoning metadata");
assert_eq!(reasoning.text.as_deref(), Some("think"));
assert_eq!(reasoning.encrypted_content.as_deref(), Some("ENC"));
struct StopRecorder(std::sync::Arc<std::sync::Mutex<Vec<(usize, String, bool)>>>);
impl crate::handler::Handler<crate::handler::ThinkingBlockKind> for StopRecorder {
type Scope = String;
fn on_event(
&mut self,
scope: &mut Self::Scope,
event: &crate::handler::ThinkingBlockEvent,
) {
match event {
crate::handler::ThinkingBlockEvent::Start(_) => scope.clear(),
crate::handler::ThinkingBlockEvent::Delta(delta) => scope.push_str(delta),
crate::handler::ThinkingBlockEvent::Stop(stop) => self
.0
.lock()
.unwrap()
.push((stop.index, scope.clone(), stop.reasoning.is_some())),
}
}
}
let stops = std::sync::Arc::new(std::sync::Mutex::new(Vec::new()));
let mut timeline = crate::timeline::Timeline::new();
timeline.on_thinking_block(StopRecorder(stops.clone()));
for event in &lifecycle {
timeline.dispatch(event);
}
let stops = stops.lock().unwrap().clone();
assert_eq!(stops, vec![(starts[0], "think".to_string(), true)]);
}
#[test] #[test]
fn reasoning_wrapper_without_inner_content_emits_empty_text() { fn reasoning_wrapper_without_inner_content_emits_empty_text() {
// encrypted_content だけ届く(reasoning_text 無し)ケースでも // encrypted_content だけ届く(reasoning_text 無し)ケースでも
// ReasoningItem は発火する // reasoning metadata は届く
let mut state = OpenAIResponsesState::default(); let mut state = OpenAIResponsesState::default();
with( with(
&mut state, &mut state,
@@ -1199,10 +1370,13 @@ mod tests {
"response.output_item.done", "response.output_item.done",
r#"{"output_index":2,"item":{"type":"reasoning","id":"r9","encrypted_content":"BLOB"}}"#, r#"{"output_index":2,"item":{"type":"reasoning","id":"r9","encrypted_content":"BLOB"}}"#,
); );
let Event::ReasoningItem(r) = &evs[0] else { assert_eq!(evs.len(), 2);
panic!() assert!(matches!(evs[0], Event::BlockStart(_)));
let Event::BlockStop(stop) = &evs[1] else {
panic!("expected BlockStop")
}; };
assert!(r.text.is_empty()); let r = stop.reasoning.as_ref().expect("reasoning metadata");
assert_eq!(r.text.as_deref(), Some(""));
assert!(r.summary.is_empty()); assert!(r.summary.is_empty());
assert_eq!(r.encrypted_content.as_deref(), Some("BLOB")); assert_eq!(r.encrypted_content.as_deref(), Some("BLOB"));
} }
@@ -2,10 +2,10 @@
//! //!
//! Chat Completions とは別物の item-based wire format。reasoning item と //! Chat Completions とは別物の item-based wire format。reasoning item と
//! function_call item が first-class で、SSE イベントも `response.*` 名前空間で //! function_call item が first-class で、SSE イベントも `response.*` 名前空間で
//! 流れる。ChatGPT OAuth 経路 (codex) は本 scheme 必須。 //! 流れる。
//! //!
//! - リクエスト JSON 生成: [`request`] //! - リクエスト JSON 生成: `request`
//! - SSE イベントパース → [`Event`](crate::llm_client::event::Event) 変換: [`events`] //! - SSE イベントパース → [`Event`](crate::llm_client::event::Event) 変換: `events`
mod capability; mod capability;
mod events; mod events;
@@ -19,10 +19,10 @@ pub use scheme_impl::OpenAIResponsesState;
/// `store` / `include_encrypted_content` / `send_max_output_tokens` / /// `store` / `include_encrypted_content` / `send_max_output_tokens` /
/// `send_sampling_params` は scheme 固定の wire 設定で、デフォルトは /// `send_sampling_params` は scheme 固定の wire 設定で、デフォルトは
/// 公式 OpenAI Responses API 向け (stateless + ZDR + `max_output_tokens` /// 公式 OpenAI Responses API 向け (stateless + ZDR + `max_output_tokens`
/// / `temperature` / `top_p` 送出可)。ChatGPT backend (codex-oauth) /// / `temperature` / `top_p` 送出可)。受理パラメータが subset
/// ように受理パラメータが subset の経路では provider 層で /// 互換 backend では client 構築層で `send_max_output_tokens=false` /
/// `send_max_output_tokens=false` / `send_sampling_params=false` に /// `send_sampling_params=false` に上書きする。`ModelCapability` には
/// 上書きする。`ModelCapability` には入れない(モデル能力ではなく wire policy)。 /// 入れない(モデル能力ではなく wire policy)。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OpenAIResponsesScheme { pub struct OpenAIResponsesScheme {
/// サーバ側に response を保存するか。ZDR/stateless 運用では `false`。 /// サーバ側に response を保存するか。ZDR/stateless 運用では `false`。
@@ -31,12 +31,12 @@ pub struct OpenAIResponsesScheme {
/// `store=false` で reasoning を使うなら必須。 /// `store=false` で reasoning を使うなら必須。
pub include_encrypted_content: bool, pub include_encrypted_content: bool,
/// `max_output_tokens` を body に載せるか。公式 OpenAI Responses API は /// `max_output_tokens` を body に載せるか。公式 OpenAI Responses API は
/// 受理するが、ChatGPT backend (codex-oauth) は `Unsupported parameter` /// 受理するが、互換 backend によっては `Unsupported parameter`
/// 400 を返すため、その経路では `false` にする。 /// 400 を返すため、その経路では `false` にする。
pub send_max_output_tokens: bool, pub send_max_output_tokens: bool,
/// `temperature` / `top_p` を body に載せるか。公式 OpenAI Responses API /// `temperature` / `top_p` を body に載せるか。公式 OpenAI Responses API
/// は受理するが、ChatGPT backend (codex-oauth) は `Unsupported parameter` /// は受理するが、互換 backend によっては `Unsupported parameter`
/// 400 を返すため、その経路では `false` にする。 /// 400 を返すため、その経路では `false` にする。
pub send_sampling_params: bool, pub send_sampling_params: bool,
} }
@@ -7,14 +7,31 @@
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use serde_json::Value; use serde_json::Value;
use crate::llm_client::{ use crate::{
Request, llm_client::{
capability::{ModelCapability, ReasoningControl, ReasoningSupport}, Request,
types::{ContentPart, Item, Role, ToolDefinition, parse_tool_arguments}, capability::{ModelCapability, ReasoningControl, ReasoningSupport},
types::{ContentPart, Item, Role, ToolDefinition, image_data_url, parse_tool_arguments},
},
tool::Attachment,
}; };
use super::OpenAIResponsesScheme; use super::OpenAIResponsesScheme;
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub(crate) enum FunctionCallOutputBody {
Text(String),
ContentItems(Vec<FunctionCallOutputContentItem>),
}
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub(crate) enum FunctionCallOutputContentItem {
InputText { text: String },
InputImage { image_url: String },
}
/// `/v1/responses` のリクエスト body。 /// `/v1/responses` のリクエスト body。
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct ResponsesRequest { pub(crate) struct ResponsesRequest {
@@ -38,21 +55,21 @@ pub(crate) struct ResponsesRequest {
/// `["reasoning.encrypted_content"]` 等。 /// `["reasoning.encrypted_content"]` 等。
#[serde(skip_serializing_if = "Vec::is_empty")] #[serde(skip_serializing_if = "Vec::is_empty")]
pub include: Vec<&'static str>, pub include: Vec<&'static str>,
/// 公式 OpenAI Responses API では受理されるが、ChatGPT backend /// 公式 OpenAI Responses API では受理されるが、互換 backend によっては
/// (codex-oauth) は 400 で弾く。scheme の `send_max_output_tokens` /// 400 で弾く。scheme の `send_max_output_tokens` が `false` のときは
/// が `false` のときは `None` のまま送る (skip_serializing_if で除外)。 /// `None` のまま送る (skip_serializing_if で除外)。
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<u32>, pub max_output_tokens: Option<u32>,
/// 公式 OpenAI Responses API では受理されるが、ChatGPT backend /// 公式 OpenAI Responses API では受理されるが、互換 backend によっては
/// (codex-oauth) は `temperature` / `top_p` を 400 で弾く。scheme の /// `temperature` / `top_p` を 400 で弾く。scheme の
/// `send_sampling_params` が `false` のときは `None` のまま送る。 /// `send_sampling_params` が `false` のときは `None` のまま送る。
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>, pub temperature: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f32>, pub top_p: Option<f32>,
/// 会話単位の安定キー。ChatGPT backend (codex-oauth) は明示キーが /// 会話単位の安定キー。明示キーを必要とする backend では、
/// 無いとプロンプトキャッシュがほぼ効かない。pod 側は `SegmentId` /// 呼び出し側が安定した conversation identifier を渡す。
/// を渡す。`Request::cache_key` が `None` のときはキー自体を送らない。 /// `Request::cache_key` が `None` のときはキー自体を送らない。
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub prompt_cache_key: Option<String>, pub prompt_cache_key: Option<String>,
} }
@@ -74,10 +91,9 @@ pub(crate) struct ReasoningConfig {
#[serde(tag = "type", rename_all = "snake_case")] #[serde(tag = "type", rename_all = "snake_case")]
pub(crate) enum InputItem { pub(crate) enum InputItem {
/// 会話メッセージ。user / assistant / developer のいずれか。 /// 会話メッセージ。user / assistant / developer のいずれか。
/// `Role::System` items は `developer` として投影するChatGPT /// `Role::System` items は `developer` として投影する。OpenAI
/// backend `role: "system"` を拒否するため。Codex CLI も /// Responses 互換 backend の一部は `role: "system"` を拒否するため
/// system 相当の挿入には DeveloperInstructions = `role: "developer"` /// system 相当の挿入には `role: "developer"` を使う。
/// を使う)。
Message { Message {
role: &'static str, role: &'static str,
content: Vec<InputContent>, content: Vec<InputContent>,
@@ -92,9 +108,7 @@ pub(crate) enum InputItem {
/// function tool の結果(user 側)。 /// function tool の結果(user 側)。
FunctionCallOutput { FunctionCallOutput {
call_id: String, call_id: String,
/// Responses は文字列 or 構造化 output を許すが、ここでは output: FunctionCallOutputBody,
/// `summary` + `content` を改行連結した文字列で送る。
output: String,
}, },
/// reasoning item。`encrypted_content` があれば必ず添える。 /// reasoning item。`encrypted_content` があれば必ず添える。
Reasoning { Reasoning {
@@ -119,6 +133,7 @@ pub(crate) enum InputItem {
pub(crate) enum InputContent { pub(crate) enum InputContent {
/// user / developer 側のテキスト /// user / developer 側のテキスト
InputText { text: String }, InputText { text: String },
/// user 側の画像
/// assistant 側のテキスト /// assistant 側のテキスト
OutputText { text: String }, OutputText { text: String },
} }
@@ -174,7 +189,7 @@ impl OpenAIResponsesScheme {
request: &Request, request: &Request,
capability: &ModelCapability, capability: &ModelCapability,
) -> ResponsesRequest { ) -> ResponsesRequest {
let input = convert_items_to_input(&request.items); let input = convert_items_to_input(&request.items, capability.vision);
let tools = request.tools.iter().map(convert_tool).collect(); let tools = request.tools.iter().map(convert_tool).collect();
// Reasoning 投影: capability が Effort / Both をサポートし、かつ // Reasoning 投影: capability が Effort / Both をサポートし、かつ
@@ -235,7 +250,7 @@ impl OpenAIResponsesScheme {
} }
/// `Item` 列を `input[]` に変換する。 /// `Item` 列を `input[]` に変換する。
fn convert_items_to_input(items: &[Item]) -> Vec<InputItem> { fn convert_items_to_input(items: &[Item], supports_images: bool) -> Vec<InputItem> {
let mut out = Vec::with_capacity(items.len()); let mut out = Vec::with_capacity(items.len());
for item in items { for item in items {
match item { match item {
@@ -248,7 +263,7 @@ fn convert_items_to_input(items: &[Item]) -> Vec<InputItem> {
}; };
let parts: Vec<InputContent> = content let parts: Vec<InputContent> = content
.iter() .iter()
.map(|p| match p { .map(|part| match part {
ContentPart::Text { text } => text_variant(text.clone()), ContentPart::Text { text } => text_variant(text.clone()),
ContentPart::Refusal { refusal } => text_variant(refusal.clone()), ContentPart::Refusal { refusal } => text_variant(refusal.clone()),
}) })
@@ -276,15 +291,33 @@ fn convert_items_to_input(items: &[Item]) -> Vec<InputItem> {
call_id, call_id,
summary, summary,
content, content,
attachments,
.. ..
} => { } => {
let text = match content { let text = match content {
Some(c) => format!("{summary}\n{c}"), Some(c) => format!("{summary}\n{c}"),
None => summary.clone(), None => summary.clone(),
}; };
let output = if attachments.is_empty() {
FunctionCallOutputBody::Text(text)
} else if supports_images {
let mut parts = vec![FunctionCallOutputContentItem::InputText { text }];
parts.extend(attachments.iter().map(|attachment| {
let Attachment::Image(image) = attachment;
FunctionCallOutputContentItem::InputImage {
image_url: image_data_url(image.mime_type(), image.data()),
}
}));
FunctionCallOutputBody::ContentItems(parts)
} else {
FunctionCallOutputBody::Text(format!(
"{text}\n[{} image attachment(s) omitted: model does not support images]",
attachments.len()
))
};
out.push(InputItem::FunctionCallOutput { out.push(InputItem::FunctionCallOutput {
call_id: call_id.clone(), call_id: call_id.clone(),
output: text, output,
}); });
} }
Item::Reasoning { Item::Reasoning {
@@ -403,10 +436,9 @@ mod tests {
#[test] #[test]
fn system_role_item_is_projected_as_developer() { fn system_role_item_is_projected_as_developer() {
// ChatGPT backend (codex-oauth) は input[] の `role: "system"` // Some compatible backends reject `role: "system"` in input[].
// "System messages are not allowed" で 400 拒否する。in-conversation // Project in-conversation system notes as `role: "developer"` so
// な system note (notify / fs_view auto-read / compaction summary) は // both official and compatible backends can accept them.
// `role: "developer"` として投影し、両 backend で受理されるようにする。
let scheme = OpenAIResponsesScheme::new(); let scheme = OpenAIResponsesScheme::new();
let req = Request::new() let req = Request::new()
.user("hi") .user("hi")
@@ -523,11 +555,9 @@ mod tests {
fn reasoning_summary_field_is_always_serialized() { fn reasoning_summary_field_is_always_serialized() {
// Responses API は reasoning item に `summary` を必須で要求する。 // Responses API は reasoning item に `summary` を必須で要求する。
// summary が空でも wire 上に `summary: []` として残らないと、 // summary が空でも wire 上に `summary: []` として残らないと、
// ChatGPT backend (codex-oauth) が // backend によっては missing required parameter として拒否される。
// 400 invalid_request_error: Missing required parameter: // reasoning effort 未指定のターンでは summary text が付かないことが
// 'input[N].summary'. // あるため、空のままでも skip しないこと。
// で弾く。GPT-5 + reasoning effort 未指定のターンでは summary text
// が付かないことがあるため、空のままでも skip しないこと。
let scheme = OpenAIResponsesScheme::new(); let scheme = OpenAIResponsesScheme::new();
let item = Item::reasoning("").with_encrypted_content("ENC"); let item = Item::reasoning("").with_encrypted_content("ENC");
let req = Request::new().user("hi").item(item); let req = Request::new().user("hi").item(item);
@@ -694,4 +724,51 @@ mod tests {
assert_eq!(json["tools"][0]["type"], "function"); assert_eq!(json["tools"][0]["type"], "function");
assert_eq!(json["tools"][0]["name"], "t"); assert_eq!(json["tools"][0]["name"], "t");
} }
#[test]
fn durable_tool_image_uses_function_call_output_content_items() {
let scheme = OpenAIResponsesScheme::new();
let image = std::sync::Arc::<[u8]>::from(&b"\x89PNG\r\n\x1a\nbody"[..]);
let item = Item::tool_result_item_with_attachments(
"call_image",
"Attached image",
None,
false,
vec![crate::tool::Attachment::Image(
crate::tool::ImageAttachment::new("image/png", image),
)],
);
let persisted = serde_json::to_string(&item).unwrap();
let restored: Item = serde_json::from_str(&persisted).unwrap();
let req = Request::new()
.item(Item::tool_call(
"call_image",
"ViewImage",
r#"{"path":"a.png"}"#,
))
.item(restored);
let body = scheme.build_request("gpt-5", &req, &cap_with_reasoning());
let json = serde_json::to_value(&body).unwrap();
assert_eq!(json["input"][1]["type"], "function_call_output");
assert_eq!(json["input"].as_array().unwrap().len(), 2);
assert_eq!(json["input"][1]["output"][0]["type"], "input_text");
assert_eq!(json["input"][1]["output"][1]["type"], "input_image");
assert!(
json["input"][1]["output"][1]["image_url"]
.as_str()
.unwrap()
.starts_with("data:image/png;base64,")
);
let rebuilt =
serde_json::to_value(scheme.build_request("gpt-5", &req, &cap_with_reasoning()))
.unwrap();
assert_eq!(rebuilt["input"], json["input"]);
let mut no_vision = cap_with_reasoning();
no_vision.vision = false;
let disabled =
serde_json::to_string(&scheme.build_request("gpt-5", &req, &no_vision)).unwrap();
assert!(!disabled.contains("data:image"));
}
} }
@@ -20,9 +20,8 @@ impl Scheme for OpenAIResponsesScheme {
type State = OpenAIResponsesState; type State = OpenAIResponsesState;
fn default_base_url(&self) -> &'static str { fn default_base_url(&self) -> &'static str {
// `/v1` は base_url 側に寄せる。ChatGPT OAuth 経由のときは // `/v1` は base_url 側に寄せる。互換 backend を使う場合も、
// `https://chatgpt.com/backend-api/codex` を base にすれば同じ // base URL を差し替えるだけで同じ `/responses` path を使える。
// `/responses` path で両系統を吸収できる(Codex CLI 準拠)。
"https://api.openai.com/v1" "https://api.openai.com/v1"
} }
@@ -59,27 +58,29 @@ impl Scheme for OpenAIResponsesScheme {
fn validate_config(&self, config: &RequestConfig) -> Vec<ConfigWarning> { fn validate_config(&self, config: &RequestConfig) -> Vec<ConfigWarning> {
let mut warnings = Vec::new(); let mut warnings = Vec::new();
// ChatGPT backend (codex-oauth) は `max_output_tokens` を 400 で弾く。 // Some compatible backends reject `max_output_tokens` with HTTP 400.
// scheme 構築時に `send_max_output_tokens=false` で組まれていれば // If the scheme was built with `send_max_output_tokens=false`, body
// body 投影は止まっているので、ユーザの意図が落ちることだけを通知する。 // projection is already disabled; only notify that the user's intent
// was dropped.
if !self.send_max_output_tokens && config.max_tokens.is_some() { if !self.send_max_output_tokens && config.max_tokens.is_some() {
warnings.push(ConfigWarning::unsupported( warnings.push(ConfigWarning::unsupported(
"max_tokens", "max_tokens",
"OpenAI Responses (ChatGPT backend)", "OpenAI Responses compatible backend",
)); ));
} }
// 同上、`temperature` / `top_p` も ChatGPT backend では 400 で弾かれる。 // Same for `temperature` / `top_p` on compatible backends that
// reject unsupported sampling parameters.
if !self.send_sampling_params { if !self.send_sampling_params {
if config.temperature.is_some() { if config.temperature.is_some() {
warnings.push(ConfigWarning::unsupported( warnings.push(ConfigWarning::unsupported(
"temperature", "temperature",
"OpenAI Responses (ChatGPT backend)", "OpenAI Responses compatible backend",
)); ));
} }
if config.top_p.is_some() { if config.top_p.is_some() {
warnings.push(ConfigWarning::unsupported( warnings.push(ConfigWarning::unsupported(
"top_p", "top_p",
"OpenAI Responses (ChatGPT backend)", "OpenAI Responses compatible backend",
)); ));
} }
} }
@@ -1,8 +1,8 @@
//! `HttpTransport<S: Scheme>`: すべての LLM wire scheme を共通の 1 本の //! `HttpTransport<S: Scheme>`: すべての LLM wire scheme を共通の 1 本の
//! HTTP クライアントで扱う。 //! HTTP クライアントで扱う。
//! //!
//! 旧 `providers/{anthropic,openai,gemini,ollama}.rs` を置き換える。 //! scheme 固有の差分は [`Scheme`] trait 実装に委譲し、backend 固有の
//! scheme 固有の差分は [`Scheme`] trait 実装に委譲する //! HTTP policy は [`TransportPolicy`] で明示的に差し込む
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
@@ -12,7 +12,8 @@ use async_trait::async_trait;
use eventsource_stream::Eventsource; use eventsource_stream::Eventsource;
use futures::{Stream, StreamExt, TryStreamExt}; use futures::{Stream, StreamExt, TryStreamExt};
use reqwest::header::{ use reqwest::header::{
ACCEPT, CONTENT_ENCODING, CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, RETRY_AFTER, ACCEPT, CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue,
RETRY_AFTER, TRANSFER_ENCODING,
}; };
use serde_json::{Map, Value, json}; use serde_json::{Map, Value, json};
@@ -27,11 +28,11 @@ use super::types::{Request, RequestConfig};
pub const DEFAULT_STREAM_OPEN_TIMEOUT: Duration = Duration::from_secs(20); pub const DEFAULT_STREAM_OPEN_TIMEOUT: Duration = Duration::from_secs(20);
pub const DEFAULT_FIRST_STREAM_EVENT_TIMEOUT: Duration = Duration::from_secs(30); pub const DEFAULT_FIRST_STREAM_EVENT_TIMEOUT: Duration = Duration::from_secs(30);
/// `AuthRef` を解決したランタイム表現。`crates/provider` が構築する /// 認証設定をリクエスト時に使える形へ解決したランタイム表現
/// ///
/// - `None`: 認証ヘッダを送らない(Ollama 等の opt-out /// - `None`: 認証ヘッダを送らない(Ollama 等の opt-out
/// - `ApiKey`: 静的な API key 文字列 /// - `ApiKey`: 静的な API key 文字列
/// - `Custom`: リクエスト毎に動的にヘッダを組み立てるCodex OAuth 等) /// - `Custom`: リクエスト毎に動的にヘッダを組み立てる
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ResolvedAuth { pub enum ResolvedAuth {
None, None,
@@ -62,6 +63,120 @@ impl ResolvedAuth {
} }
} }
/// Request body encoding policy used by [`HttpTransport`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RequestBodyEncoding {
/// Send the request body as plain JSON.
Json,
/// Send the request body as zstd-compressed JSON with `Content-Encoding: zstd`.
ZstdJson,
}
impl Default for RequestBodyEncoding {
fn default() -> Self {
Self::Json
}
}
/// Conversation header policy used by [`HttpTransport`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConversationHeaderPolicy {
/// Do not derive any transport headers from [`Request::cache_key`].
None,
/// Send OpenAI-compatible conversation headers from [`Request::cache_key`].
OpenAiCompatible {
/// Send the legacy `session_id` header in addition to `session-id`.
include_legacy_session_id: bool,
/// Send `thread-id` with the same value as `session-id`.
include_thread_id: bool,
/// Send `x-client-request-id` with the same value as `session-id`.
include_client_request_id: bool,
},
}
impl Default for ConversationHeaderPolicy {
fn default() -> Self {
Self::None
}
}
/// Backend-specific HTTP transport policy.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TransportPolicy {
/// How to serialize and encode the HTTP request body.
pub request_body_encoding: RequestBodyEncoding,
/// Optional backend-specific conversation headers derived from request metadata.
pub conversation_headers: ConversationHeaderPolicy,
}
impl TransportPolicy {
/// Plain JSON requests with no derived conversation headers.
pub fn standard() -> Self {
Self::default()
}
/// OpenAI-compatible backend profile that uses zstd JSON bodies and
/// conversation headers derived from [`Request::cache_key`].
pub fn openai_compatible_zstd() -> Self {
Self {
request_body_encoding: RequestBodyEncoding::ZstdJson,
conversation_headers: ConversationHeaderPolicy::OpenAiCompatible {
include_legacy_session_id: true,
include_thread_id: true,
include_client_request_id: true,
},
}
}
}
fn header_value_for_diagnostics(headers: &HeaderMap, name: &str) -> Option<String> {
headers
.get(name)
.and_then(|value| value.to_str().ok())
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned)
}
fn response_header_diagnostics(headers: &HeaderMap) -> serde_json::Value {
serde_json::json!({
"content_type": header_value_for_diagnostics(headers, CONTENT_TYPE.as_str()),
"content_encoding": header_value_for_diagnostics(headers, CONTENT_ENCODING.as_str()),
"transfer_encoding": header_value_for_diagnostics(headers, TRANSFER_ENCODING.as_str()),
"content_length": header_value_for_diagnostics(headers, CONTENT_LENGTH.as_str()),
})
}
fn request_header_diagnostics(headers: &HeaderMap) -> serde_json::Value {
serde_json::json!({
"content_type": header_value_for_diagnostics(headers, CONTENT_TYPE.as_str()),
"content_encoding": header_value_for_diagnostics(headers, CONTENT_ENCODING.as_str()),
"accept": header_value_for_diagnostics(headers, ACCEPT.as_str()),
"openai_beta": header_value_for_diagnostics(headers, "openai-beta"),
"session_id_present": headers.contains_key("session-id"),
"thread_id_present": headers.contains_key("thread-id"),
"legacy_session_id_present": headers.contains_key("session_id"),
"legacy_thread_id_present": headers.contains_key("thread_id"),
"x_client_request_id_present": headers.contains_key("x-client-request-id"),
"chatgpt_account_id_present": headers.contains_key("chatgpt-account-id"),
})
}
fn sse_error_context(status: u16, headers: &serde_json::Value, source: &str) -> String {
let field = |name: &str| {
headers
.get(name)
.and_then(serde_json::Value::as_str)
.unwrap_or("<none>")
};
format!(
"SSE stream parse failed after HTTP {status}: {source}; content-type={}, content-encoding={}, transfer-encoding={}, content-length={}",
field("content_type"),
field("content_encoding"),
field("transfer_encoding"),
field("content_length")
)
}
/// scheme 共通の HTTP 通信層。 /// scheme 共通の HTTP 通信層。
pub struct HttpTransport<S: Scheme> { pub struct HttpTransport<S: Scheme> {
http_client: reqwest::Client, http_client: reqwest::Client,
@@ -70,6 +185,7 @@ pub struct HttpTransport<S: Scheme> {
base_url: String, base_url: String,
auth: ResolvedAuth, auth: ResolvedAuth,
capability: ModelCapability, capability: ModelCapability,
policy: TransportPolicy,
} }
impl<S: Scheme> HttpTransport<S> { impl<S: Scheme> HttpTransport<S> {
@@ -91,9 +207,16 @@ impl<S: Scheme> HttpTransport<S> {
base_url, base_url,
auth, auth,
capability, capability,
policy: TransportPolicy::default(),
} }
} }
/// Set a backend-specific HTTP transport policy.
pub fn with_transport_policy(mut self, policy: TransportPolicy) -> Self {
self.policy = policy;
self
}
/// カスタム HTTP クライアントを差し込む(テスト等)。 /// カスタム HTTP クライアントを差し込む(テスト等)。
pub fn with_http_client(mut self, client: reqwest::Client) -> Self { pub fn with_http_client(mut self, client: reqwest::Client) -> Self {
self.http_client = client; self.http_client = client;
@@ -156,13 +279,6 @@ impl<S: Scheme> HttpTransport<S> {
Ok(headers) Ok(headers)
} }
fn is_codex_backend(&self) -> bool {
match &self.auth {
ResolvedAuth::Custom(provider) => provider.is_codex_backend(),
_ => false,
}
}
fn apply_stream_headers( fn apply_stream_headers(
&self, &self,
headers: &mut HeaderMap, headers: &mut HeaderMap,
@@ -170,14 +286,26 @@ impl<S: Scheme> HttpTransport<S> {
) -> Result<(), ClientError> { ) -> Result<(), ClientError> {
headers.insert(ACCEPT, HeaderValue::from_static("text/event-stream")); headers.insert(ACCEPT, HeaderValue::from_static("text/event-stream"));
if self.is_codex_backend() if let ConversationHeaderPolicy::OpenAiCompatible {
include_legacy_session_id,
include_thread_id,
include_client_request_id,
} = self.policy.conversation_headers
&& let Some(cache_key) = request.cache_key.as_deref() && let Some(cache_key) = request.cache_key.as_deref()
{ {
let value = HeaderValue::from_str(cache_key).map_err(|e| { let value = HeaderValue::from_str(cache_key).map_err(|e| {
ClientError::Config(format!("invalid Codex conversation header: {e}")) ClientError::Config(format!("invalid conversation header value: {e}"))
})?; })?;
headers.insert(HeaderName::from_static("session_id"), value.clone()); headers.insert(HeaderName::from_static("session-id"), value.clone());
headers.insert(HeaderName::from_static("x-client-request-id"), value); if include_thread_id {
headers.insert(HeaderName::from_static("thread-id"), value.clone());
}
if include_legacy_session_id {
headers.insert(HeaderName::from_static("session_id"), value.clone());
}
if include_client_request_id {
headers.insert(HeaderName::from_static("x-client-request-id"), value);
}
} }
Ok(()) Ok(())
@@ -188,19 +316,22 @@ impl<S: Scheme> HttpTransport<S> {
body: &serde_json::Value, body: &serde_json::Value,
headers: &mut HeaderMap, headers: &mut HeaderMap,
) -> Result<RequestBody, ClientError> { ) -> Result<RequestBody, ClientError> {
if !self.is_codex_backend() { match self.policy.request_body_encoding {
return Ok(RequestBody::Json(body.clone())); RequestBodyEncoding::Json => Ok(RequestBody::Json(body.clone())),
RequestBodyEncoding::ZstdJson => {
let raw = serde_json::to_vec(body)?;
let raw_json_bytes = raw.len();
let compressed =
zstd::stream::encode_all(std::io::Cursor::new(raw), 3).map_err(|e| {
ClientError::Config(format!("failed to zstd-compress request: {e}"))
})?;
headers.insert(CONTENT_ENCODING, HeaderValue::from_static("zstd"));
Ok(RequestBody::CompressedJson {
bytes: compressed,
raw_json_bytes,
})
}
} }
let raw = serde_json::to_vec(body)?;
let raw_json_bytes = raw.len();
let compressed = zstd::stream::encode_all(std::io::Cursor::new(raw), 3)
.map_err(|e| ClientError::Config(format!("failed to zstd-compress request: {e}")))?;
headers.insert(CONTENT_ENCODING, HeaderValue::from_static("zstd"));
Ok(RequestBody::CompressedJson {
bytes: compressed,
raw_json_bytes,
})
} }
} }
@@ -300,13 +431,7 @@ fn api_error_code(error: &ClientError) -> Option<&str> {
} }
fn is_context_length_exceeded(error: &ClientError) -> bool { fn is_context_length_exceeded(error: &ClientError) -> bool {
match error { matches!(error, ClientError::ContextWindowExceeded)
ClientError::Api { code, message, .. } => {
code.as_deref() == Some("context_length_exceeded")
|| message.contains("context_length_exceeded")
}
_ => false,
}
} }
async fn response_with_timeout( async fn response_with_timeout(
@@ -329,6 +454,7 @@ impl<S: Scheme + Clone> Clone for HttpTransport<S> {
base_url: self.base_url.clone(), base_url: self.base_url.clone(),
auth: self.auth.clone(), auth: self.auth.clone(),
capability: self.capability.clone(), capability: self.capability.clone(),
policy: self.policy.clone(),
} }
} }
} }
@@ -355,6 +481,9 @@ async fn classify_error_response(resp: reqwest::Response) -> ClientError {
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.unwrap_or(&text) .unwrap_or(&text)
.to_string(); .to_string();
if code.as_deref() == Some("context_length_exceeded") {
return ClientError::ContextWindowExceeded;
}
ClientError::Api { ClientError::Api {
status: Some(status), status: Some(status),
code, code,
@@ -392,7 +521,8 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
"path": path, "path": path,
"auth_kind": auth_kind(&self.auth), "auth_kind": auth_kind(&self.auth),
"required_auth": format!("{:?}", self.scheme.required_auth()), "required_auth": format!("{:?}", self.scheme.required_auth()),
"codex_backend": self.is_codex_backend(), "request_body_encoding": format!("{:?}", self.policy.request_body_encoding),
"conversation_headers": format!("{:?}", self.policy.conversation_headers),
"cache_key_present": request.cache_key.is_some(), "cache_key_present": request.cache_key.is_some(),
"stream_open_timeout_ms": DEFAULT_STREAM_OPEN_TIMEOUT.as_millis() as u64, "stream_open_timeout_ms": DEFAULT_STREAM_OPEN_TIMEOUT.as_millis() as u64,
}), }),
@@ -416,6 +546,7 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
json!({ json!({
"elapsed_ms": headers_started.elapsed().as_millis() as u64, "elapsed_ms": headers_started.elapsed().as_millis() as u64,
"headers_len": headers.len(), "headers_len": headers.len(),
"headers": request_header_diagnostics(&headers),
}), }),
); );
headers headers
@@ -451,6 +582,7 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
json!({ json!({
"elapsed_ms": stream_headers_started.elapsed().as_millis() as u64, "elapsed_ms": stream_headers_started.elapsed().as_millis() as u64,
"headers_len": headers.len(), "headers_len": headers.len(),
"headers": request_header_diagnostics(&headers),
}), }),
); );
@@ -485,15 +617,19 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
return Err(error); return Err(error);
} }
}; };
let final_request_headers = request_header_diagnostics(&headers);
let body_compression = request_body.encoding().to_string();
emit_transport_trace( emit_transport_trace(
&request, &request,
"transport_body_encode_done", "transport_body_encode_done",
json!({ json!({
"elapsed_ms": encode_started.elapsed().as_millis() as u64, "elapsed_ms": encode_started.elapsed().as_millis() as u64,
"encoding": request_body.encoding(), "encoding": body_compression.as_str(),
"body_compression": body_compression.as_str(),
"raw_json_bytes": request_body.raw_json_bytes(), "raw_json_bytes": request_body.raw_json_bytes(),
"wire_bytes": request_body.wire_bytes(), "wire_bytes": request_body.wire_bytes(),
"request_shape": body_shape.clone(), "request_shape": body_shape.clone(),
"headers": final_request_headers.clone(),
}), }),
); );
@@ -510,6 +646,7 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
.await .await
{ {
Ok(response) => { Ok(response) => {
let response_headers = response_header_diagnostics(response.headers());
emit_transport_trace( emit_transport_trace(
&request, &request,
"transport_http_headers_received", "transport_http_headers_received",
@@ -517,6 +654,7 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
"elapsed_ms": send_started.elapsed().as_millis() as u64, "elapsed_ms": send_started.elapsed().as_millis() as u64,
"status": response.status().as_u16(), "status": response.status().as_u16(),
"success": response.status().is_success(), "success": response.status().is_success(),
"headers": response_headers,
}), }),
); );
response response
@@ -549,6 +687,8 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
"context_length_exceeded": context_length_exceeded, "context_length_exceeded": context_length_exceeded,
"provider_usage_absent": context_length_exceeded, "provider_usage_absent": context_length_exceeded,
"request_shape": body_shape.clone(), "request_shape": body_shape.clone(),
"request_headers": final_request_headers.clone(),
"body_compression": body_compression.as_str(),
}), }),
); );
return Err(error); return Err(error);
@@ -563,6 +703,9 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
); );
let scheme = self.scheme.clone(); let scheme = self.scheme.clone();
let status = response.status().as_u16();
let response_headers = response_header_diagnostics(response.headers());
let transport_trace = request.transport_trace.clone();
let byte_stream = response.bytes_stream().map_err(std::io::Error::other); let byte_stream = response.bytes_stream().map_err(std::io::Error::other);
let event_stream = byte_stream.eventsource(); let event_stream = byte_stream.eventsource();
@@ -575,7 +718,21 @@ impl<S: Scheme + Clone + 'static> LlmClient for HttpTransport<S> {
Ok(events) => Ok(events), Ok(events) => Ok(events),
Err(e) => Err(e), Err(e) => Err(e),
}, },
Err(e) => Err(ClientError::Sse(e.to_string())), Err(e) => {
let source = e.to_string();
let message = sse_error_context(status, &response_headers, &source);
if let Some(trace) = &transport_trace {
trace.emit(
"transport_sse_parse_error",
json!({
"status": status,
"headers": response_headers.clone(),
"error": source,
}),
);
}
Err(ClientError::Sse(message))
}
}) })
.map(|res| { .map(|res| {
let s: Pin<Box<dyn Stream<Item = Result<Event, ClientError>> + Send>> = match res { let s: Pin<Box<dyn Stream<Item = Result<Event, ClientError>> + Send>> = match res {
@@ -596,9 +753,7 @@ mod tests {
use serde_json::json; use serde_json::json;
#[derive(Debug)] #[derive(Debug)]
struct TestAuthProvider { struct TestAuthProvider;
codex: bool,
}
#[async_trait] #[async_trait]
impl AuthProvider for TestAuthProvider { impl AuthProvider for TestAuthProvider {
@@ -614,10 +769,6 @@ mod tests {
), ),
]) ])
} }
fn is_codex_backend(&self) -> bool {
self.codex
}
} }
#[derive(Clone)] #[derive(Clone)]
@@ -675,6 +826,39 @@ mod tests {
) )
} }
#[test]
fn sse_error_context_includes_response_headers() {
let headers = json!({
"content_type": "application/octet-stream",
"content_encoding": "gzip",
"transfer_encoding": "chunked",
"content_length": "123",
});
let message = sse_error_context(200, &headers, "stream did not contain valid UTF-8");
assert!(message.contains("HTTP 200"));
assert!(message.contains("stream did not contain valid UTF-8"));
assert!(message.contains("content-type=application/octet-stream"));
assert!(message.contains("content-encoding=gzip"));
assert!(message.contains("transfer-encoding=chunked"));
assert!(message.contains("content-length=123"));
}
#[test]
fn response_header_diagnostics_redacts_to_safe_header_subset() {
let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("text/event-stream"));
headers.insert(CONTENT_ENCODING, HeaderValue::from_static("identity"));
headers.insert("authorization", HeaderValue::from_static("Bearer secret"));
let diagnostics = response_header_diagnostics(&headers);
assert_eq!(diagnostics["content_type"], "text/event-stream");
assert_eq!(diagnostics["content_encoding"], "identity");
assert!(diagnostics.get("authorization").is_none());
}
#[test] #[test]
fn request_body_shape_counts_reasoning_encrypted_content() { fn request_body_shape_counts_reasoning_encrypted_content() {
let payload = request_body_shape_payload(&json!({ let payload = request_body_shape_payload(&json!({
@@ -713,10 +897,9 @@ mod tests {
} }
#[tokio::test] #[tokio::test]
async fn codex_backend_adds_conversation_headers_and_zstd_body() { async fn transport_policy_adds_conversation_headers_and_zstd_body() {
let transport = transport(ResolvedAuth::Custom(Arc::new(TestAuthProvider { let transport = transport(ResolvedAuth::Custom(Arc::new(TestAuthProvider)))
codex: true, .with_transport_policy(TransportPolicy::openai_compatible_zstd());
})));
let request = Request::new().user("hello").cache_key("segment-123"); let request = Request::new().user("hello").cache_key("segment-123");
let mut headers = transport.build_headers().await.unwrap(); let mut headers = transport.build_headers().await.unwrap();
transport transport
@@ -730,16 +913,32 @@ mod tests {
let encoded = transport.encode_request_body(&body, &mut headers).unwrap(); let encoded = transport.encode_request_body(&body, &mut headers).unwrap();
assert_eq!(headers.get(ACCEPT).unwrap(), "text/event-stream"); assert_eq!(headers.get(ACCEPT).unwrap(), "text/event-stream");
assert_eq!(headers.get("session-id").unwrap(), "segment-123");
assert_eq!(headers.get("thread-id").unwrap(), "segment-123");
assert_eq!(headers.get("session_id").unwrap(), "segment-123"); assert_eq!(headers.get("session_id").unwrap(), "segment-123");
assert_eq!(headers.get("x-client-request-id").unwrap(), "segment-123"); assert_eq!(headers.get("x-client-request-id").unwrap(), "segment-123");
assert_eq!(headers.get(CONTENT_ENCODING).unwrap(), "zstd"); assert_eq!(headers.get(CONTENT_ENCODING).unwrap(), "zstd");
let diagnostics = request_header_diagnostics(&headers);
assert_eq!(diagnostics["content_type"], "application/json");
assert_eq!(diagnostics["content_encoding"], "zstd");
assert_eq!(diagnostics["accept"], "text/event-stream");
assert!(diagnostics["session_id_present"].as_bool().unwrap());
assert!(diagnostics["thread_id_present"].as_bool().unwrap());
assert!(diagnostics["legacy_session_id_present"].as_bool().unwrap());
assert!(
diagnostics["x_client_request_id_present"]
.as_bool()
.unwrap()
);
assert!(diagnostics["chatgpt_account_id_present"].as_bool().unwrap());
let RequestBody::CompressedJson { let RequestBody::CompressedJson {
bytes: compressed, bytes: compressed,
raw_json_bytes, raw_json_bytes,
} = encoded } = encoded
else { else {
panic!("Codex backend request body must be zstd-compressed"); panic!("transport policy should zstd-compress request body");
}; };
assert!(raw_json_bytes > 0); assert!(raw_json_bytes > 0);
let decoded = zstd::stream::decode_all(std::io::Cursor::new(compressed)).unwrap(); let decoded = zstd::stream::decode_all(std::io::Cursor::new(compressed)).unwrap();
@@ -748,7 +947,7 @@ mod tests {
} }
#[tokio::test] #[tokio::test]
async fn non_codex_request_does_not_get_codex_only_headers_or_compression() { async fn standard_policy_does_not_get_conversation_headers_or_compression() {
let transport = transport(ResolvedAuth::ApiKey("api-key".to_string())); let transport = transport(ResolvedAuth::ApiKey("api-key".to_string()));
let request = Request::new().user("hello").cache_key("segment-123"); let request = Request::new().user("hello").cache_key("segment-123");
let mut headers = transport.build_headers().await.unwrap(); let mut headers = transport.build_headers().await.unwrap();
@@ -763,12 +962,14 @@ mod tests {
let encoded = transport.encode_request_body(&body, &mut headers).unwrap(); let encoded = transport.encode_request_body(&body, &mut headers).unwrap();
assert_eq!(headers.get(ACCEPT).unwrap(), "text/event-stream"); assert_eq!(headers.get(ACCEPT).unwrap(), "text/event-stream");
assert!(headers.get("session-id").is_none());
assert!(headers.get("thread-id").is_none());
assert!(headers.get("session_id").is_none()); assert!(headers.get("session_id").is_none());
assert!(headers.get("x-client-request-id").is_none()); assert!(headers.get("x-client-request-id").is_none());
assert!(headers.get(CONTENT_ENCODING).is_none()); assert!(headers.get(CONTENT_ENCODING).is_none());
let RequestBody::Json(decoded) = encoded else { let RequestBody::Json(decoded) = encoded else {
panic!("non-Codex request body must remain normal JSON"); panic!("standard transport policy should keep request body as JSON");
}; };
assert_eq!(decoded["prompt_cache_key"], "segment-123"); assert_eq!(decoded["prompt_cache_key"], "segment-123");
} }
@@ -1,6 +1,6 @@
//! LLM Client Common Types //! LLM Client Common Types
//! //!
//! Core conversation types for insomnia's LLM interaction model. //! Core conversation types for LLM interaction.
//! The core abstraction is `Item` which represents different types of conversation elements: //! The core abstraction is `Item` which represents different types of conversation elements:
//! - Message items (user/assistant messages with content parts) //! - Message items (user/assistant messages with content parts)
//! - ToolCall items (tool invocations) //! - ToolCall items (tool invocations)
@@ -9,12 +9,19 @@
use std::{fmt, sync::Arc}; use std::{fmt, sync::Arc};
use crate::tool::{Attachment, ToolResultDisposition};
use base64::Engine as _;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
fn is_false(value: &bool) -> bool { fn is_false(value: &bool) -> bool {
!*value !*value
} }
pub(crate) fn image_data_url(media_type: &str, data: &[u8]) -> String {
let encoded = base64::engine::general_purpose::STANDARD.encode(data);
format!("data:{media_type};base64,{encoded}")
}
// ============================================================================ // ============================================================================
// Item - The core unit of conversation // Item - The core unit of conversation
// ============================================================================ // ============================================================================
@@ -62,7 +69,7 @@ impl fmt::Debug for RequestTrace {
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use llm_worker::Item; /// use agen::Item;
/// ///
/// let user = Item::user_message("Hello!"); /// let user = Item::user_message("Hello!");
/// let assistant = Item::assistant_message("Hi there!"); /// let assistant = Item::assistant_message("Hi there!");
@@ -114,9 +121,15 @@ pub enum Item {
/// Detailed output (removed by pruning when old enough) /// Detailed output (removed by pruning when old enough)
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
content: Option<String>, content: Option<String>,
/// Typed terminal state used for replay and recovery.
#[serde(default, skip_serializing_if = "ToolResultDisposition::is_success")]
disposition: ToolResultDisposition,
/// Whether the tool result represents an execution error. /// Whether the tool result represents an execution error.
#[serde(default, skip_serializing_if = "is_false")] #[serde(default, skip_serializing_if = "is_false")]
is_error: bool, is_error: bool,
/// Durable binary details (removed with `content` by normal pruning).
#[serde(default, skip_serializing_if = "Vec::is_empty")]
attachments: Vec<Attachment>,
}, },
/// Reasoning/thinking item /// Reasoning/thinking item
@@ -251,12 +264,56 @@ impl Item {
content: Option<String>, content: Option<String>,
is_error: bool, is_error: bool,
) -> Self { ) -> Self {
Self::tool_result_item_with_disposition_and_attachments(
call_id,
summary,
content,
if is_error {
ToolResultDisposition::Error
} else {
ToolResultDisposition::Success
},
Vec::new(),
)
}
/// Create a tool result item with durable, prunable structured attachments.
pub fn tool_result_item_with_attachments(
call_id: impl Into<String>,
summary: impl Into<String>,
content: Option<String>,
is_error: bool,
attachments: Vec<Attachment>,
) -> Self {
Self::tool_result_item_with_disposition_and_attachments(
call_id,
summary,
content,
if is_error {
ToolResultDisposition::Error
} else {
ToolResultDisposition::Success
},
attachments,
)
}
pub fn tool_result_item_with_disposition_and_attachments(
call_id: impl Into<String>,
summary: impl Into<String>,
content: Option<String>,
disposition: ToolResultDisposition,
attachments: Vec<Attachment>,
) -> Self {
let is_error = !disposition.is_success();
Self::ToolResult { Self::ToolResult {
id: None, id: None,
call_id: call_id.into(), call_id: call_id.into(),
summary: summary.into(), summary: summary.into(),
content, content,
disposition,
is_error, is_error,
attachments,
} }
} }
@@ -461,7 +518,7 @@ impl ContentPart {
} }
} }
/// Get the text content regardless of type /// Get a textual projection of the content part.
pub fn as_text(&self) -> &str { pub fn as_text(&self) -> &str {
match self { match self {
Self::Text { text } => text, Self::Text { text } => text,
@@ -521,9 +578,8 @@ pub struct Request {
/// Providers without prompt caching ignore the field. /// Providers without prompt caching ignore the field.
pub cache_anchor: Option<usize>, pub cache_anchor: Option<usize>,
/// 会話単位の安定キー。`prompt_cache_key` として送られる /// 会話単位の安定キー。`prompt_cache_key` として送られる
/// (OpenAI Responses)。ChatGPT backend (codex-oauth) は明示キーが /// (OpenAI Responses)。明示キーを必要とする backend では、
/// 無いと org/project ハッシュ衝突でプロンプトキャッシュが /// 呼び出し側が安定した conversation identifier を渡す。
/// ほぼヒットしないため、pod 側で `SegmentId` を渡す運用を想定。
/// `cache_anchor` と違い名前空間キーであり、`prefix anchor` とは /// `cache_anchor` と違い名前空間キーであり、`prefix anchor` とは
/// 別の概念。`cache_anchor` を読まない provider と同じく、 /// 別の概念。`cache_anchor` を読まない provider と同じく、
/// `prompt_cache_key` を持たない provider は無視する。 /// `prompt_cache_key` を持たない provider は無視する。
@@ -1,7 +1,7 @@
//! `~/.codex/auth.json` の読み書き。 //! `~/.codex/auth.json` の読み書き。
//! //!
//! Codex CLI と schema を共有するが、insomnia は知らないフィールドを //! Codex CLI と schema を共有するが、知らないフィールドを失わないよう
//! 失わないようファイル全体を `serde_json::Value` で保持し、必要箇所 //! ファイル全体を `serde_json::Value` で保持し、必要箇所
//! のみアクセスする。書込は `mode 0o600` を再設定(Codex CLI 同様)、 //! のみアクセスする。書込は `mode 0o600` を再設定(Codex CLI 同様)、
//! ファイルロックは取らない(manager 側で guarded reload)。 //! ファイルロックは取らない(manager 側で guarded reload)。
@@ -106,7 +106,7 @@ pub async fn load(path: &Path) -> Result<AuthSnapshot, CodexAuthError> {
/// 既存ファイルを再読込し、`tokens.{id_token,access_token,refresh_token}` と /// 既存ファイルを再読込し、`tokens.{id_token,access_token,refresh_token}` と
/// `last_refresh` を更新して書き戻す。Codex CLI の `persist_tokens` 相当。 /// `last_refresh` を更新して書き戻す。Codex CLI の `persist_tokens` 相当。
/// ///
/// 並行する Codex CLI / 別 insomnia プロセスが先に refresh していた場合の /// 並行する Codex CLI / 別プロセスが先に refresh していた場合の
/// fields を保護するため、書込前に再 load して merge する。 /// fields を保護するため、書込前に再 load して merge する。
pub async fn persist_refreshed( pub async fn persist_refreshed(
path: &Path, path: &Path,
@@ -6,7 +6,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use llm_worker::llm_client::ClientError; use crate::llm_client::ClientError;
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@@ -4,11 +4,11 @@
//! //!
//! 設計: //! 設計:
//! //!
//! - llm-worker は [`AuthProvider`] trait しか知らず、実体である //! - HTTP transport は [`AuthProvider`] trait だけを見て、実体である
//! [`CodexAuthProvider`] はこのクレートに置く(feedback_llm_worker_scope //! [`CodexAuthProvider`] はこの optional module に置く
//! - access_token JWT の `exp` を読み、`now` 以下で proactive refresh //! - access_token JWT の `exp` を読み、`now` 以下で proactive refresh
//! Codex CLI と同じバッファなし) //! Codex CLI と同じバッファなし)
//! - 並行する Codex CLI / 別 insomnia の refresh と取り違えないよう、 //! - 並行する Codex CLI / 別プロセスの refresh と取り違えないよう、
//! refresh 直前に再 load して account_id 一致を確認(guarded reload //! refresh 直前に再 load して account_id 一致を確認(guarded reload
//! - ファイルロックは取らず、書込前に再 load + diff merge で吸収 //! - ファイルロックは取らず、書込前に再 load + diff merge で吸収
//! - Codex の Keyring storage は対象外。auth.json 不在ならエラーで案内 //! - Codex の Keyring storage は対象外。auth.json 不在ならエラーで案内
@@ -21,9 +21,9 @@ mod refresh;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use crate::llm_client::{ClientError, auth::AuthProvider};
use async_trait::async_trait; use async_trait::async_trait;
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use llm_worker::llm_client::{ClientError, auth::AuthProvider};
use reqwest::header::{HeaderName, HeaderValue}; use reqwest::header::{HeaderName, HeaderValue};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@@ -152,7 +152,7 @@ impl CodexAuthProvider {
.map_err(|e| CodexAuthError::InvalidHeader(format!("ChatGPT-Account-Id: {e}")))?; .map_err(|e| CodexAuthError::InvalidHeader(format!("ChatGPT-Account-Id: {e}")))?;
out.push((HeaderName::from_static("chatgpt-account-id"), acc_val)); out.push((HeaderName::from_static("chatgpt-account-id"), acc_val));
// Cloudflare WAF は ChatGPT backend アクセス元を `originator` / // Cloudflare WAF は互換 backend アクセス元を `originator` /
// `User-Agent` で識別する。Codex CLI が送る固定値を流用しないと // `User-Agent` で識別する。Codex CLI が送る固定値を流用しないと
// HTML challenge (403) を返されて SSE に到達できない。 // HTML challenge (403) を返されて SSE に到達できない。
out.push(( out.push((
@@ -188,10 +188,6 @@ impl AuthProvider for CodexAuthProvider {
.map_err(CodexAuthError::to_client_error)?; .map_err(CodexAuthError::to_client_error)?;
Self::build_headers(&snap).map_err(CodexAuthError::to_client_error) Self::build_headers(&snap).map_err(CodexAuthError::to_client_error)
} }
fn is_codex_backend(&self) -> bool {
true
}
} }
/// `access_token` の JWT `exp` を見て、期限切れなら true。 /// `access_token` の JWT `exp` を見て、期限切れなら true。
@@ -80,7 +80,7 @@ async fn response_with_timeout(
.await .await
.map_err(|_| { .map_err(|_| {
CodexAuthError::RefreshTransient(format!( CodexAuthError::RefreshTransient(format!(
"codex_oauth_refresh timed out after {}s", "oauth_token_refresh timed out after {}s",
timeout.as_secs() timeout.as_secs()
)) ))
})? })?
+4
View File
@@ -0,0 +1,4 @@
//! Optional built-in provider/backend helpers.
#[cfg(feature = "codex")]
pub mod codex;
@@ -8,8 +8,8 @@
//! //!
//! Prune は **コンテキスト射影** であり、history の変換ではない。 //! Prune は **コンテキスト射影** であり、history の変換ではない。
//! この crate が提供するのは pure な候補抽出 [`prunable_indices`] のみで、 //! この crate が提供するのは pure な候補抽出 [`prunable_indices`] のみで、
//! 射影の適用は上位層(`pod::prune_hook` 等)が LLM に送る一時コンテキスト //! 射影の適用は LLM に送る一時コンテキストに対してだけ行う。
//! に対してだけ行う。Worker の永続履歴は決して変更されない。 //! Engine の永続履歴は決して変更されない。
//! //!
//! 保護境界は末尾 token budget で決めるが、この crate は usage 履歴を //! 保護境界は末尾 token budget で決めるが、この crate は usage 履歴を
//! 所有しない。prefix ごとの token 推定値と savings 推定は上位層から //! 所有しない。prefix ごとの token 推定値と savings 推定は上位層から
@@ -32,8 +32,8 @@ pub type TokenEstimator = Box<dyn Fn(&[Item]) -> Vec<TokenEstimate> + Send + Syn
/// Callback that estimates the token savings for projecting the /// Callback that estimates the token savings for projecting the
/// `ToolResult.content` out of `history[i]` for each `i` in `indices`. /// `ToolResult.content` out of `history[i]` for each `i` in `indices`.
/// ///
/// Injected into [`crate::Worker`] via `set_savings_estimator` so the /// Injected into [`crate::Engine`] via `set_savings_estimator` so the
/// Worker can make `min_savings` decisions without knowing about usage /// Engine can make `min_savings` decisions without knowing about usage
/// measurement sources. Return `0` to signal "no data / refuse to prune". /// measurement sources. Return `0` to signal "no data / refuse to prune".
/// ///
/// 推定対象は「drop する範囲全体」ではなく「content を None にする差分」 /// 推定対象は「drop する範囲全体」ではなく「content を None にする差分」
@@ -44,7 +44,7 @@ pub type SavingsEstimator = Box<dyn Fn(&[Item], &[usize]) -> u64 + Send + Sync>;
/// Result of one prune evaluation pass, surfaced to the optional /// Result of one prune evaluation pass, surfaced to the optional
/// [`PruneObserver`] for instrumentation. /// [`PruneObserver`] for instrumentation.
/// ///
/// Worker は LLM リクエストごとに 1 回 prune の評価をし、その結果を /// Engine は LLM リクエストごとに 1 回 prune の評価をし、その結果を
/// (observer が登録されていれば)この値で通知する。fire/skip の判定 /// (observer が登録されていれば)この値で通知する。fire/skip の判定
/// 結果と、判定材料になった候補数 / 推定 savings / 保護領域の先頭 index を持つ。 /// 結果と、判定材料になった候補数 / 推定 savings / 保護領域の先頭 index を持つ。
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -61,7 +61,7 @@ pub struct PruneEvaluation {
} }
/// Outcome of one prune evaluation. Each variant is one branch of the /// Outcome of one prune evaluation. Each variant is one branch of the
/// "fire vs skip" decision tree the Worker walks before each LLM request. /// "fire vs skip" decision tree the Engine walks before each LLM request.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum PruneDecision { pub enum PruneDecision {
/// `prunable_indices` が空 → 何もしない。 /// `prunable_indices` が空 → 何もしない。
@@ -75,7 +75,7 @@ pub enum PruneDecision {
} }
/// Optional observer invoked after each prune evaluation, regardless of /// Optional observer invoked after each prune evaluation, regardless of
/// branch. Pod 等の上位層が install して metrics を発行する。 /// branch. Callers can install this to publish metrics or traces.
pub type PruneObserver = Box<dyn Fn(&PruneEvaluation) + Send + Sync>; pub type PruneObserver = Box<dyn Fn(&PruneEvaluation) + Send + Sync>;
/// Configuration for the Prune algorithm. /// Configuration for the Prune algorithm.
@@ -110,25 +110,30 @@ impl Default for PruneConfig {
} }
} }
/// Set `content = None` on each `Item::ToolResult` at the given indices. /// Remove detailed text and attachments from each `Item::ToolResult` at the given indices.
/// ///
/// Returns the number of items that were actually modified — items that /// The mandatory summary remains. Returns the number of items that were actually
/// are already content-less are counted as 0. Intended for use on a /// modified — results that already contain no detail are counted as 0. Intended
/// request-context clone (never on a persistent history). /// for use on a request-context clone (never on a persistent history).
pub fn project(items: &mut [Item], indices: &[usize]) -> usize { pub fn project(items: &mut [Item], indices: &[usize]) -> usize {
let mut count = 0; let mut count = 0;
for &i in indices { for &i in indices {
if let Item::ToolResult { content, .. } = &mut items[i] if let Item::ToolResult {
&& content.is_some() content,
attachments,
..
} = &mut items[i]
&& (content.is_some() || !attachments.is_empty())
{ {
*content = None; *content = None;
attachments.clear();
count += 1; count += 1;
} }
} }
count count
} }
/// Indices of `Item::ToolResult { content: Some(_), .. }` that lie before /// Indices of detailed `Item::ToolResult` values that lie before
/// the suffix protected by `protected_tokens`. Pure: does not mutate `items`. /// the suffix protected by `protected_tokens`. Pure: does not mutate `items`.
/// ///
/// Returns an empty vector when token estimates are unavailable (`NoData`) or /// Returns an empty vector when token estimates are unavailable (`NoData`) or
@@ -159,8 +164,10 @@ pub fn evaluate_candidates(
.enumerate() .enumerate()
.filter_map(|(i, item)| match item { .filter_map(|(i, item)| match item {
Item::ToolResult { Item::ToolResult {
content: Some(_), .. content,
} => Some(i), attachments,
..
} if content.is_some() || !attachments.is_empty() => Some(i),
_ => None, _ => None,
}) })
.collect(); .collect();
@@ -373,6 +380,38 @@ mod tests {
} }
} }
#[test]
fn project_drops_image_detail_but_keeps_summary_and_persistent_source() {
let original = vec![Item::tool_result_item_with_attachments(
"call_image",
"Attached image/png image (12 bytes)",
None,
false,
vec![crate::tool::Attachment::Image(
crate::tool::ImageAttachment::new("image/png", b"image-body".to_vec()),
)],
)];
let mut request_context = original.clone();
let estimates = uniform_estimates(&original, 100);
assert_eq!(prunable_indices(&original, 0, &estimates), vec![0]);
assert_eq!(project(&mut request_context, &[0]), 1);
assert!(matches!(
&request_context[0],
Item::ToolResult {
summary,
content: None,
attachments,
..
} if summary == "Attached image/png image (12 bytes)" && attachments.is_empty()
));
assert!(matches!(
&original[0],
Item::ToolResult { attachments, .. } if attachments.len() == 1
));
}
#[test] #[test]
fn project_skips_already_pruned_items() { fn project_skips_already_pruned_items() {
// indices points at an item whose content is already None. // indices points at an item whose content is already None.
@@ -1,12 +1,12 @@
//! Worker State //! Engine State
//! //!
//! State marker types for cache protection using the Type-state pattern. //! State marker types for cache protection using the Type-state pattern.
//! Worker has state transitions from `Mutable` → `Locked`. //! Engine has state transitions from `Mutable` → `Locked`.
/// Marker trait representing Worker state /// Marker trait representing Engine state
/// ///
/// This trait is sealed and cannot be implemented externally. /// This trait is sealed and cannot be implemented externally.
pub trait WorkerState: private::Sealed + Send + Sync + 'static {} pub trait EngineState: private::Sealed + Send + Sync + 'static {}
mod private { mod private {
pub trait Sealed {} pub trait Sealed {}
@@ -19,28 +19,28 @@ mod private {
/// - Editing message history (add, delete, clear) /// - Editing message history (add, delete, clear)
/// - Registering tools and hooks /// - Registering tools and hooks
/// ///
/// Can transition to [`Locked`] state via `Worker::lock()`. /// Can transition to [`Locked`] state via `Engine::lock(&history)`.
/// ///
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use llm_worker::Worker; /// use agen::Engine;
/// ///
/// let mut worker = Worker::new(client) /// let mut engine = Engine::new(client)
/// .system_prompt("You are helpful."); /// .system_prompt("You are helpful.");
/// ///
/// // History can be edited /// // History can be edited
/// worker.push_message(Message::user("Hello")); /// engine.push_message(Message::user("Hello"));
/// worker.clear_history(); /// engine.clear_history();
/// ///
/// // Lock to protected state /// // Lock to protected state
/// let locked = worker.lock(); /// let locked = engine.lock();
/// ``` /// ```
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Mutable; pub struct Mutable;
impl private::Sealed for Mutable {} impl private::Sealed for Mutable {}
impl WorkerState for Mutable {} impl EngineState for Mutable {}
/// Cache locked state (cache protected) /// Cache locked state (cache protected)
/// ///
@@ -51,10 +51,10 @@ impl WorkerState for Mutable {}
/// To ensure LLM API KV cache hits, /// To ensure LLM API KV cache hits,
/// using this state during execution is recommended. /// using this state during execution is recommended.
/// ///
/// Can return to [`Mutable`] state via `Worker::unlock()`, /// Can return to [`Mutable`] state via `Engine::unlock()`,
/// but note that cache protection will be released. /// but note that cache protection will be released.
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Locked; pub struct Locked;
impl private::Sealed for Locked {} impl private::Sealed for Locked {}
impl WorkerState for Locked {} impl EngineState for Locked {}
@@ -7,18 +7,19 @@
//! - [`Timeline`] - イベントストリームの管理とディスパッチ //! - [`Timeline`] - イベントストリームの管理とディスパッチ
//! - [`Handler`] - イベントを処理するトレイト //! - [`Handler`] - イベントを処理するトレイト
//! - [`TextBlockCollector`] - テキストブロックを収集するHandler //! - [`TextBlockCollector`] - テキストブロックを収集するHandler
//! - [`ThinkingBlockCollector`] - reasoning material を Thinking block から収集するHandler
//! - [`ToolCallCollector`] - ツール呼び出しを収集するHandler //! - [`ToolCallCollector`] - ツール呼び出しを収集するHandler
pub mod event; pub mod event;
mod reasoning_item_collector;
mod text_block_collector; mod text_block_collector;
mod thinking_block_collector;
mod timeline; mod timeline;
mod tool_call_collector; mod tool_call_collector;
// 公開API // 公開API
pub use event::*; pub use event::*;
pub use reasoning_item_collector::ReasoningItemCollector;
pub use text_block_collector::TextBlockCollector; pub use text_block_collector::TextBlockCollector;
pub use thinking_block_collector::ThinkingBlockCollector;
pub use timeline::Timeline; pub use timeline::Timeline;
pub use tool_call_collector::ToolCallCollector; pub use tool_call_collector::ToolCallCollector;
@@ -30,7 +31,6 @@ pub use crate::handler::{
Handler, Handler,
Kind, Kind,
PingKind, PingKind,
ReasoningItemKind,
StatusKind, StatusKind,
// Block Events // Block Events
TextBlockEvent, TextBlockEvent,
@@ -0,0 +1,138 @@
//! `ThinkingBlockCollector` - reasoning material from Thinking block lifecycle.
//!
//! Scheme implementations emit Thinking BlockStart/Delta/Stop events for live
//! streaming. A Thinking block stop with `ReasoningBlockData` is also the single
//! authoritative persistence signal for `Item::Reasoning` round-trip material.
use std::sync::{Arc, Mutex};
use crate::handler::{Handler, ThinkingBlockEvent, ThinkingBlockKind};
use crate::llm_client::event::ReasoningBlockData;
/// Reasoning material collected from completed Thinking blocks.
#[derive(Clone, Default)]
pub struct ThinkingBlockCollector {
collected: Arc<Mutex<Vec<ReasoningBlockData>>>,
}
impl ThinkingBlockCollector {
pub fn new() -> Self {
Self::default()
}
/// 収集済み item を取り出してクリア
pub fn take_collected(&self) -> Vec<ReasoningBlockData> {
let mut guard = self.collected.lock().unwrap();
std::mem::take(&mut *guard)
}
/// 収集をクリア
pub fn clear(&self) {
self.collected.lock().unwrap().clear();
}
}
impl Handler<ThinkingBlockKind> for ThinkingBlockCollector {
type Scope = String;
fn on_event(&mut self, scope: &mut Self::Scope, event: &ThinkingBlockEvent) {
match event {
ThinkingBlockEvent::Start(_) => scope.clear(),
ThinkingBlockEvent::Delta(text) => scope.push_str(text),
ThinkingBlockEvent::Stop(stop) => {
if let Some(mut reasoning) = stop.reasoning.clone() {
if reasoning.text.is_none() {
reasoning.text = Some(scope.clone());
}
self.collected.lock().unwrap().push(reasoning);
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::llm_client::event::{
BlockMetadata, BlockStart, BlockStop, BlockType, DeltaContent, Event, ReasoningBlockData,
};
use crate::timeline::Timeline;
#[test]
fn collects_in_order_from_thinking_block_stops() {
let collector = ThinkingBlockCollector::new();
let mut timeline = Timeline::new();
timeline.on_thinking_block(collector.clone());
timeline.dispatch(&Event::BlockStart(BlockStart {
index: 0,
block_type: BlockType::Thinking,
metadata: BlockMetadata::Thinking,
}));
timeline.dispatch(&Event::BlockDelta(crate::llm_client::event::BlockDelta {
index: 0,
delta: DeltaContent::Thinking("first".into()),
}));
timeline.dispatch(&Event::BlockStop(BlockStop {
index: 0,
block_type: BlockType::Thinking,
stop_reason: None,
reasoning: Some(ReasoningBlockData {
id: Some("r1".into()),
signature: Some("sig1".into()),
..Default::default()
}),
}));
timeline.dispatch(&Event::BlockStart(BlockStart {
index: 1,
block_type: BlockType::Thinking,
metadata: BlockMetadata::Thinking,
}));
timeline.dispatch(&Event::BlockStop(BlockStop {
index: 1,
block_type: BlockType::Thinking,
stop_reason: None,
reasoning: Some(ReasoningBlockData {
id: Some("r2".into()),
text: Some("second".into()),
..Default::default()
}),
}));
let items = collector.take_collected();
assert_eq!(items.len(), 2);
assert_eq!(items[0].text.as_deref(), Some("first"));
assert_eq!(items[0].signature.as_deref(), Some("sig1"));
assert_eq!(items[1].text.as_deref(), Some("second"));
// take は drain なので 2 度目は空
assert!(collector.take_collected().is_empty());
}
#[test]
fn ignores_streaming_only_thinking_blocks() {
let collector = ThinkingBlockCollector::new();
let mut timeline = Timeline::new();
timeline.on_thinking_block(collector.clone());
timeline.dispatch(&Event::BlockStart(BlockStart {
index: 0,
block_type: BlockType::Thinking,
metadata: BlockMetadata::Thinking,
}));
timeline.dispatch(&Event::BlockDelta(crate::llm_client::event::BlockDelta {
index: 0,
delta: DeltaContent::Thinking("live only".into()),
}));
timeline.dispatch(&Event::BlockStop(BlockStop {
index: 0,
block_type: BlockType::Thinking,
stop_reason: None,
reasoning: None,
}));
assert!(collector.take_collected().is_empty());
}
}
@@ -1,9 +1,9 @@
//! Timeline層 //! Timeline層
//! //!
//! LLMからのイベントストリームを受信し、登録されたHandlerにディスパッチします。 //! LLMからのイベントストリームを受信し、登録されたHandlerにディスパッチします。
//! 通常はWorker経由で使用しますが、直接使用することも可能です。 //! 通常はEngine経由で使用しますが、直接使用することも可能です。
use std::marker::PhantomData; use std::{collections::HashMap, marker::PhantomData};
use super::event::*; use super::event::*;
use crate::handler::*; use crate::handler::*;
@@ -47,10 +47,8 @@ fn merge_usage(acc: &mut UsageEvent, new: &UsageEvent) {
pub trait ErasedHandler<K: Kind>: Send + Sync { pub trait ErasedHandler<K: Kind>: Send + Sync {
/// イベントをディスパッチ /// イベントをディスパッチ
fn dispatch(&mut self, event: &K::Event); fn dispatch(&mut self, event: &K::Event);
/// スコープを開始Block開始時) /// スコープを開始
fn start_scope(&mut self); fn start_scope(&mut self);
/// スコープを終了(Block終了時)
fn end_scope(&mut self);
} }
/// `Handler<K>`を`ErasedHandler<K>`として扱うためのラッパー /// `Handler<K>`を`ErasedHandler<K>`として扱うためのラッパー
@@ -94,10 +92,6 @@ where
fn start_scope(&mut self) { fn start_scope(&mut self) {
self.scope = Some(H::Scope::default()); self.scope = Some(H::Scope::default());
} }
fn end_scope(&mut self) {
self.scope = None;
}
} }
// ============================================================================= // =============================================================================
@@ -195,7 +189,7 @@ where
H: Handler<ThinkingBlockKind>, H: Handler<ThinkingBlockKind>,
{ {
handler: H, handler: H,
scope: Option<H::Scope>, scopes: HashMap<usize, H::Scope>,
} }
impl<H> ThinkingBlockHandlerWrapper<H> impl<H> ThinkingBlockHandlerWrapper<H>
@@ -205,7 +199,7 @@ where
fn new(handler: H) -> Self { fn new(handler: H) -> Self {
Self { Self {
handler, handler,
scope: None, scopes: HashMap::new(),
} }
} }
} }
@@ -216,44 +210,43 @@ where
H::Scope: Send + Sync, H::Scope: Send + Sync,
{ {
fn dispatch_start(&mut self, start: &BlockStart) { fn dispatch_start(&mut self, start: &BlockStart) {
if let Some(scope) = &mut self.scope { let scope = self.scopes.entry(start.index).or_default();
self.handler.on_event( self.handler.on_event(
scope, scope,
&ThinkingBlockEvent::Start(ThinkingBlockStart { index: start.index }), &ThinkingBlockEvent::Start(ThinkingBlockStart { index: start.index }),
); );
}
} }
fn dispatch_delta(&mut self, delta: &BlockDelta) { fn dispatch_delta(&mut self, delta: &BlockDelta) {
if let Some(scope) = &mut self.scope { if let DeltaContent::Thinking(text) = &delta.delta {
if let DeltaContent::Thinking(text) = &delta.delta { let scope = self.scopes.entry(delta.index).or_default();
self.handler self.handler
.on_event(scope, &ThinkingBlockEvent::Delta(text.clone())); .on_event(scope, &ThinkingBlockEvent::Delta(text.clone()));
}
} }
} }
fn dispatch_stop(&mut self, stop: &BlockStop) { fn dispatch_stop(&mut self, stop: &BlockStop) {
if let Some(scope) = &mut self.scope { if let Some(mut scope) = self.scopes.remove(&stop.index) {
self.handler.on_event( self.handler.on_event(
scope, &mut scope,
&ThinkingBlockEvent::Stop(ThinkingBlockStop { index: stop.index }), &ThinkingBlockEvent::Stop(ThinkingBlockStop {
index: stop.index,
reasoning: stop.reasoning.clone(),
}),
); );
} }
} }
fn dispatch_abort(&mut self, _abort: &BlockAbort) {} fn dispatch_abort(&mut self, _abort: &BlockAbort) {
self.scopes.clear();
fn start_scope(&mut self) {
self.scope = Some(H::Scope::default());
} }
fn end_scope(&mut self) { fn start_scope(&mut self) {}
self.scope = None;
} fn end_scope(&mut self) {}
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
self.scope.is_some() !self.scopes.is_empty()
} }
} }
@@ -355,7 +348,7 @@ where
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use llm_worker::{Timeline, Handler, TextBlockKind, TextBlockEvent}; /// use agen::{Timeline, Handler, TextBlockKind, TextBlockEvent};
/// ///
/// struct MyHandler; /// struct MyHandler;
/// impl Handler<TextBlockKind> for MyHandler { /// impl Handler<TextBlockKind> for MyHandler {
@@ -381,8 +374,6 @@ pub struct Timeline {
ping_handlers: Vec<Box<dyn ErasedHandler<PingKind>>>, ping_handlers: Vec<Box<dyn ErasedHandler<PingKind>>>,
status_handlers: Vec<Box<dyn ErasedHandler<StatusKind>>>, status_handlers: Vec<Box<dyn ErasedHandler<StatusKind>>>,
error_handlers: Vec<Box<dyn ErasedHandler<ErrorKind>>>, error_handlers: Vec<Box<dyn ErasedHandler<ErrorKind>>>,
reasoning_item_handlers: Vec<Box<dyn ErasedHandler<ReasoningItemKind>>>,
// Block系ハンドラー(BlockTypeごとにグループ化) // Block系ハンドラー(BlockTypeごとにグループ化)
text_block_handlers: Vec<Box<dyn ErasedBlockHandler>>, text_block_handlers: Vec<Box<dyn ErasedBlockHandler>>,
thinking_block_handlers: Vec<Box<dyn ErasedBlockHandler>>, thinking_block_handlers: Vec<Box<dyn ErasedBlockHandler>>,
@@ -411,7 +402,6 @@ impl Timeline {
ping_handlers: Vec::new(), ping_handlers: Vec::new(),
status_handlers: Vec::new(), status_handlers: Vec::new(),
error_handlers: Vec::new(), error_handlers: Vec::new(),
reasoning_item_handlers: Vec::new(),
text_block_handlers: Vec::new(), text_block_handlers: Vec::new(),
thinking_block_handlers: Vec::new(), thinking_block_handlers: Vec::new(),
tool_use_block_handlers: Vec::new(), tool_use_block_handlers: Vec::new(),
@@ -473,18 +463,6 @@ impl Timeline {
self self
} }
/// `ReasoningItemKind` 用 Handler を登録
pub fn on_reasoning_item<H>(&mut self, handler: H) -> &mut Self
where
H: Handler<ReasoningItemKind> + Send + Sync + 'static,
H::Scope: Send + Sync,
{
let mut wrapper = HandlerWrapper::new(handler);
wrapper.start_scope();
self.reasoning_item_handlers.push(Box::new(wrapper));
self
}
/// TextBlockKind用のHandlerを登録 /// TextBlockKind用のHandlerを登録
pub fn on_text_block<H>(&mut self, handler: H) -> &mut Self pub fn on_text_block<H>(&mut self, handler: H) -> &mut Self
where where
@@ -538,9 +516,6 @@ impl Timeline {
Event::BlockDelta(d) => self.handle_block_delta(d), Event::BlockDelta(d) => self.handle_block_delta(d),
Event::BlockStop(s) => self.handle_block_stop(s), Event::BlockStop(s) => self.handle_block_stop(s),
Event::BlockAbort(a) => self.handle_block_abort(a), Event::BlockAbort(a) => self.handle_block_abort(a),
// 完成済み reasoning item: 即時ディスパッチ
Event::ReasoningItem(r) => self.dispatch_reasoning_item(r),
} }
} }
@@ -583,12 +558,6 @@ impl Timeline {
} }
} }
fn dispatch_reasoning_item(&mut self, event: &ReasoningItemEvent) {
for handler in &mut self.reasoning_item_handlers {
handler.dispatch(event);
}
}
fn handle_block_start(&mut self, start: &BlockStart) { fn handle_block_start(&mut self, start: &BlockStart) {
self.current_block = Some(start.block_type); self.current_block = Some(start.block_type);
@@ -130,13 +130,13 @@ mod tests {
let mut timeline = Timeline::new(); let mut timeline = Timeline::new();
timeline.on_tool_use_block(collector.clone()); timeline.on_tool_use_block(collector.clone());
timeline.dispatch(&Event::tool_use_start(0, "tool_empty", "ListPods")); timeline.dispatch(&Event::tool_use_start(0, "tool_empty", "ListItems"));
timeline.dispatch(&Event::tool_use_stop(0)); timeline.dispatch(&Event::tool_use_stop(0));
let calls = collector.take_collected(); let calls = collector.take_collected();
assert_eq!(calls.len(), 1); assert_eq!(calls.len(), 1);
assert_eq!(calls[0].id, "tool_empty"); assert_eq!(calls[0].id, "tool_empty");
assert_eq!(calls[0].name, "ListPods"); assert_eq!(calls[0].name, "ListItems");
assert!(calls[0].input.is_object()); assert!(calls[0].input.is_object());
assert_eq!( assert_eq!(
calls[0].input, calls[0].input,
@@ -6,7 +6,8 @@
//! # 方針 //! # 方針
//! //!
//! - ローカルトークナイザは持たない。実測値があればそれを採用し、 //! - ローカルトークナイザは持たない。実測値があればそれを採用し、
//! measurement 間はバイト数で按分、最新 measurement より先は最終 rate で外挿する //! measurement 間はバイト数で按分、最新 measurement より先は byte/4
//! fallback で外挿する
//! - 推定の出どころは [`EstimateSource`] で呼び出し側に明示する。 //! - 推定の出どころは [`EstimateSource`] で呼び出し側に明示する。
//! 課金判断には使えないが、compact / prune / memory extract trigger 等の //! 課金判断には使えないが、compact / prune / memory extract trigger 等の
//! 閾値判定には十分な精度 //! 閾値判定には十分な精度
@@ -21,7 +22,7 @@ pub enum EstimateSource {
Measured, Measured,
/// 連続する 2 つの measurement の間をバイト按分で計算 /// 連続する 2 つの measurement の間をバイト按分で計算
Interpolated, Interpolated,
/// 最後の measurement より新しい区間を最終 rate で外挿 /// 最後の measurement より新しい区間を byte/4 fallback で外挿
Extrapolated, Extrapolated,
/// measurement が 1 件も無く、バイト数のみのフォールバック /// measurement が 1 件も無く、バイト数のみのフォールバック
NoData, NoData,
@@ -119,17 +120,10 @@ pub fn tokens_at(
(Some(lo), None) => { (Some(lo), None) => {
let lo_bytes = prefix[lo.history_len.min(cap)]; let lo_bytes = prefix[lo.history_len.min(cap)];
let at_bytes = prefix[index]; let at_bytes = prefix[index];
if lo_bytes == 0 || lo.input_total_tokens == 0 {
return TokenEstimate {
tokens: lo.input_total_tokens,
source: EstimateSource::Extrapolated,
};
}
let delta_bytes = at_bytes.saturating_sub(lo_bytes); let delta_bytes = at_bytes.saturating_sub(lo_bytes);
let delta_tokens =
(delta_bytes as u128 * lo.input_total_tokens as u128 / lo_bytes as u128) as u64;
TokenEstimate { TokenEstimate {
tokens: lo.input_total_tokens + delta_tokens, tokens: lo.input_total_tokens.saturating_add(delta_bytes / 4),
source: EstimateSource::Extrapolated, source: EstimateSource::Extrapolated,
} }
} }
@@ -214,6 +208,63 @@ mod tests {
assert!(est.tokens > 100); assert!(est.tokens > 100);
} }
#[test]
fn extrapolation_after_single_measurement_uses_byte_fallback_not_total_prompt_rate() {
let history = vec![msg("first"), msg(&"tool output ".repeat(400))];
let records = vec![record(1, 11_124)];
let prefix = prefix_bytes(&history);
let delta_bytes = prefix[2].saturating_sub(prefix[1]);
let est = total_tokens(&history, &records);
assert_eq!(est.source, EstimateSource::Extrapolated);
assert_eq!(est.tokens, 11_124 + delta_bytes / 4);
let old_projection =
11_124 + (delta_bytes as u128 * 11_124_u128 / prefix[1] as u128) as u64;
assert!(
old_projection > est.tokens.saturating_mul(10),
"old_projection={old_projection}, corrected={}",
est.tokens
);
}
#[test]
fn extrapolation_after_multiple_measurements_uses_byte_fallback_for_unmeasured_delta() {
let history = vec![
msg("first"),
msg(&"measured increment ".repeat(20)),
msg(&"unmeasured increment ".repeat(30)),
];
let records = vec![record(1, 10_000), record(2, 10_200)];
let prefix = prefix_bytes(&history);
let delta_bytes = prefix[3].saturating_sub(prefix[2]);
let est = total_tokens(&history, &records);
assert_eq!(est.source, EstimateSource::Extrapolated);
assert_eq!(est.tokens, 10_200 + delta_bytes / 4);
}
#[test]
fn extrapolation_does_not_reuse_measured_rate_after_context_projection() {
let compacted_span = msg("x");
let projected = vec![
msg("first"),
msg("summary only"),
compacted_span,
msg("new user input"),
];
let records = vec![record(1, 10_000), record(3, 30_000)];
let prefix = prefix_bytes(&projected);
let delta_bytes = prefix[4].saturating_sub(prefix[3]);
let est = total_tokens(&projected, &records);
assert_eq!(est.source, EstimateSource::Extrapolated);
assert_eq!(est.tokens, 30_000 + delta_bytes / 4);
}
#[test] #[test]
fn total_zero_history_is_zero() { fn total_zero_history_is_zero() {
let est = total_tokens(&[], &[]); let est = total_tokens(&[], &[]);
+753
View File
@@ -0,0 +1,753 @@
//! Tool Definition
//!
//! Traits for defining tools callable by LLM.
//! Usually auto-implemented using the `#[tool]` macro.
use std::{
collections::HashMap,
fmt,
future::Future,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use async_trait::async_trait;
use base64::{Engine as _, engine::general_purpose::STANDARD};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
use serde_json::Value;
use thiserror::Error;
/// Error during tool execution
#[derive(Debug, Error)]
pub enum ToolError {
/// Invalid argument
#[error("Invalid argument: {0}")]
InvalidArgument(String),
/// Execution failed
#[error("Execution failed: {0}")]
ExecutionFailed(String),
/// Internal error
#[error("Internal error: {0}")]
Internal(String),
/// Cooperative cancellation completed with bounded terminal output.
#[error("Tool execution cancelled")]
Cancelled(ToolOutput),
/// Execution was interrupted with a confirmed bounded terminal output.
#[error("Tool execution interrupted")]
Interrupted(ToolOutput),
}
// =============================================================================
// ToolOutput - Tool execution result with summary + content
// =============================================================================
/// Threshold below which tool output is treated as summary-only (no content).
/// Outputs this small don't benefit from pruning.
pub const SUMMARY_THRESHOLD: usize = 200;
/// Byte-size caps applied to tool execution `content` at the Engine's
/// tool-execution boundary, before results enter conversation history.
///
/// Exists so a single oversized tool result (e.g. a wide `Glob` scan)
/// cannot blow past the provider's per-minute input-token rate limit.
/// Individual tools are not trusted to self-limit — this is the single
/// chokepoint.
///
/// The unit is bytes rather than tokens because accurate pre-send token
/// estimation is not available. The limits can be migrated to token
/// units later without changing callers.
#[derive(Debug, Clone)]
pub struct ToolOutputLimits {
/// Cap applied to any tool not listed in `per_tool`.
pub default_max_bytes: usize,
/// Per-tool overrides, keyed by tool registration name.
pub per_tool: HashMap<String, usize>,
}
impl ToolOutputLimits {
/// Resolve the cap for a given tool name.
pub fn limit_for(&self, tool_name: &str) -> usize {
self.per_tool
.get(tool_name)
.copied()
.unwrap_or(self.default_max_bytes)
}
}
/// Truncate `content` in-place if it exceeds `limit` bytes, replacing
/// the dropped tail with a short human- and LLM-readable marker so the
/// model can self-correct by narrowing its query.
///
/// The cut point is walked back to the nearest UTF-8 char boundary so
/// multibyte characters are never split.
pub(crate) fn truncate_content(content: &mut String, limit: usize) {
let original_len = content.len();
if original_len <= limit {
return;
}
let suffix_template = "\n\n[truncated: %BYTES% bytes dropped, refine your query]";
// Reserve enough headroom for the suffix (upper bound on the byte length
// of the number substitution). usize::MAX fits in 20 digits.
let reserved = suffix_template.len() + 20 - "%BYTES%".len();
let body_budget = limit.saturating_sub(reserved);
let mut cut = body_budget.min(original_len);
while cut > 0 && !content.is_char_boundary(cut) {
cut -= 1;
}
content.truncate(cut);
let dropped = original_len - cut;
content.push_str(&suffix_template.replace("%BYTES%", &dropped.to_string()));
}
#[derive(Clone, PartialEq, Eq)]
pub struct ImageAttachment {
mime_type: String,
data: Arc<[u8]>,
}
impl ImageAttachment {
pub fn new(mime_type: impl Into<String>, data: impl Into<Arc<[u8]>>) -> Self {
Self {
mime_type: mime_type.into(),
data: data.into(),
}
}
pub fn mime_type(&self) -> &str {
&self.mime_type
}
pub fn data(&self) -> &[u8] {
&self.data
}
}
impl fmt::Debug for ImageAttachment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ImageAttachment")
.field("mime_type", &self.mime_type)
.field("bytes", &self.data.len())
.finish()
}
}
#[derive(Serialize, Deserialize)]
struct ImageAttachmentWire {
mime_type: String,
data: String,
}
impl Serialize for ImageAttachment {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
ImageAttachmentWire {
mime_type: self.mime_type.clone(),
data: STANDARD.encode(self.data.as_ref()),
}
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ImageAttachment {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let wire = ImageAttachmentWire::deserialize(deserializer)?;
let data = STANDARD.decode(wire.data).map_err(D::Error::custom)?;
Ok(Self::new(wire.mime_type, data))
}
}
/// Durable binary detail emitted by a tool and handled by normal ToolResult pruning.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
pub enum Attachment {
Image(ImageAttachment),
}
/// Terminal disposition of one started tool call.
///
/// `Cancelled` means the tool confirmed cancellation. `OutcomeUnknown` means
/// execution stopped without confirmation, so neither completion nor side
/// effects may be inferred.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum ToolResultDisposition {
#[default]
Success,
Error,
Interrupted,
Cancelled,
OutcomeUnknown,
}
impl ToolResultDisposition {
pub const fn is_success(&self) -> bool {
matches!(self, Self::Success)
}
}
/// Tool execution result.
///
/// Every output has a mandatory `summary` (1-2 lines) that persists in
/// conversation history even after pruning. Optional text and binary details are
/// committed to history and may later be omitted only by normal ToolResult pruning.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolOutput {
/// Short summary (1-2 lines). Always remains in history.
pub summary: String,
/// Detailed text output. Removed by Prune when old enough.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
/// Durable binary details handled by the same pruning lifecycle as `content`.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attachments: Vec<Attachment>,
}
impl From<String> for ToolOutput {
fn from(s: String) -> Self {
if s.len() <= SUMMARY_THRESHOLD {
ToolOutput {
summary: s,
content: None,
attachments: Vec::new(),
}
} else {
let lines = s.lines().count();
let first_line: String = s.lines().next().unwrap_or("").chars().take(80).collect();
let summary = format!("{lines} lines | {first_line}");
ToolOutput {
summary,
content: Some(s),
attachments: Vec::new(),
}
}
}
}
// =============================================================================
// ToolMeta - Immutable Meta Information
// =============================================================================
/// Origin metadata for a registered tool.
///
/// This metadata is intentionally not part of the provider-facing tool schema.
/// It lets host layers audit where a model-visible tool definition came from
/// while keeping execution and permission semantics in the normal Engine path.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ToolOrigin {
/// Origin kind, for example `plugin` or `builtin`.
pub kind: String,
/// Package-local plugin id.
pub plugin_id: String,
/// Source-qualified plugin/package reference when `kind == "plugin"`.
pub plugin_ref: String,
/// Plugin source such as `user`, `project`, or `builtin`.
pub source: String,
/// Resolved package digest.
pub digest: String,
/// Resolved package version.
pub package_version: String,
/// Plugin API/schema version declared by the package.
pub package_api_version: u32,
/// Surface that contributed this tool. Plugin tools use `tool`.
pub surface: String,
}
/// Tool meta information (fixed at registration, immutable)
///
/// Generated from `ToolDefinition` factory and does not change after registration with Engine.
/// Used for sending tool definitions to LLM.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolMeta {
/// Tool name (used by LLM for identification)
pub name: String,
/// Tool description (included in prompt to LLM)
pub description: String,
/// JSON Schema for arguments
pub input_schema: Value,
/// Optional host-side origin metadata. This is not exposed to the LLM.
pub origin: Option<ToolOrigin>,
}
impl ToolMeta {
/// Create a new ToolMeta
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
description: String::new(),
input_schema: Value::Object(Default::default()),
origin: None,
}
}
/// Set the description
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = desc.into();
self
}
/// Set the argument schema
pub fn input_schema(mut self, schema: Value) -> Self {
self.input_schema = schema;
self
}
/// Set host-side origin metadata.
pub fn origin(mut self, origin: ToolOrigin) -> Self {
self.origin = Some(origin);
self
}
}
// =============================================================================
// ToolDefinition - Factory Type
// =============================================================================
/// Tool definition factory
///
/// When called, returns `(ToolMeta, Arc<dyn Tool>)`.
/// Called once during Engine registration, and the meta information and instance
/// are cached at session scope.
///
/// # Examples
///
/// ```ignore
/// let def: ToolDefinition = Arc::new(|| {
/// (
/// ToolMeta::new("my_tool")
/// .description("My tool description")
/// .input_schema(json!({"type": "object"})),
/// Arc::new(MyToolImpl { state: 0 }) as Arc<dyn Tool>,
/// )
/// });
/// engine.register_tool(def)?;
/// ```
pub type ToolDefinition = Arc<dyn Fn() -> (ToolMeta, Arc<dyn Tool>) + Send + Sync>;
/// Per-call context supplied by the engine when executing a tool call.
///
/// The context identifies a tool call within one assistant response's tool-call
/// batch without imposing any scheduling policy on the engine. Tool
/// implementations may use it for response-local ordering, diagnostics, or
/// correlation, but it is intentionally not a handle to engine state, history,
/// or session mutation.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolExecutionContext {
/// Provider/tool-call id for the call being executed.
pub call_id: String,
/// Engine-local identity shared by all tool calls from one execution batch.
pub batch_id: String,
/// Zero-based order of this call in the model-returned tool-call list.
pub call_index: usize,
}
impl ToolExecutionContext {
pub fn new(call_id: impl Into<String>, batch_id: impl Into<String>, call_index: usize) -> Self {
Self {
call_id: call_id.into(),
batch_id: batch_id.into(),
call_index,
}
}
/// Identifies one live execution attempt without making the batch id a durable
/// replay or idempotency authority.
pub fn execution_id(&self) -> String {
format!("{}:{}", self.batch_id, self.call_id)
}
/// Context for direct, non-engine calls in unit tests and low-level callers.
pub fn direct() -> Self {
Self::new("direct", "direct", 0)
}
}
impl Default for ToolExecutionContext {
fn default() -> Self {
Self::direct()
}
}
/// The provider-confirmed terminal result of one started tool execution.
///
/// `OutcomeUnknown` is reserved for an execution task that had to be force-closed
/// or failed before the provider could confirm its terminal result.
#[derive(Debug)]
pub enum ToolExecutionTerminal {
Confirmed(Result<ToolOutput, ToolError>),
OutcomeUnknown,
}
/// The completion future paired with a [`ToolExecutionHandle`]. Dropping this
/// future does not drop the provider execution: the spawned execution remains
/// owned by its handle until it completes or is explicitly force-closed.
pub struct ToolExecutionTerminalFuture {
task: tokio::task::JoinHandle<Result<ToolOutput, ToolError>>,
}
impl Future for ToolExecutionTerminalFuture {
type Output = ToolExecutionTerminal;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match Pin::new(&mut self.task).poll(cx) {
Poll::Ready(Ok(result)) => Poll::Ready(ToolExecutionTerminal::Confirmed(result)),
Poll::Ready(Err(_)) => Poll::Ready(ToolExecutionTerminal::OutcomeUnknown),
Poll::Pending => Poll::Pending,
}
}
}
/// Live ownership and control for one started tool execution.
///
/// Execution, cancellation, and terminal confirmation remain provider-owned:
/// this handle starts `Tool::execute`, delegates cooperative cancellation to
/// `Tool::cancel_execution`, and treats execution-future completion as the
/// provider's terminal confirmation. Agen may force-close only after its caller's
/// deadline expires, at which point the outcome is necessarily unknown.
#[derive(Clone)]
pub struct ToolExecutionHandle {
inner: Arc<ToolExecutionHandleInner>,
}
struct ToolExecutionHandleInner {
tool: Arc<dyn Tool>,
context: ToolExecutionContext,
abort: tokio::task::AbortHandle,
}
impl Drop for ToolExecutionHandleInner {
fn drop(&mut self) {
// Losing the final live owner is an explicit forced close, never a
// best-effort detached provider future.
self.abort.abort();
}
}
impl fmt::Debug for ToolExecutionHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ToolExecutionHandle")
.field("call_id", &self.inner.context.call_id)
.field("batch_id", &self.inner.context.batch_id)
.finish_non_exhaustive()
}
}
impl ToolExecutionHandle {
pub fn start(
tool: Arc<dyn Tool>,
input_json: String,
context: ToolExecutionContext,
) -> (Self, ToolExecutionTerminalFuture) {
let execution_tool = Arc::clone(&tool);
let execution_context = context.clone();
let task =
tokio::spawn(
async move { execution_tool.execute(&input_json, execution_context).await },
);
let abort = task.abort_handle();
(
Self {
inner: Arc::new(ToolExecutionHandleInner {
tool,
context,
abort,
}),
},
ToolExecutionTerminalFuture { task },
)
}
pub fn context(&self) -> &ToolExecutionContext {
&self.inner.context
}
pub async fn cancel_before(&self, deadline: tokio::time::Instant) -> Result<(), ToolError> {
match tokio::time::timeout_at(
deadline,
self.inner.tool.cancel_execution(&self.inner.context),
)
.await
{
Ok(result) => result,
Err(_) => Err(ToolError::Internal(format!(
"tool cancellation request exceeded its deadline for call {}",
self.inner.context.call_id
))),
}
}
pub fn force_close(&self) {
self.inner.abort.abort();
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ToolExecutionPolicy {
/// Time a pause waits for already-started providers to reach a natural safe
/// boundary before escalating to explicit cooperative cancellation.
pub pause_safe_boundary_timeout: std::time::Duration,
/// Maximum time allowed for a provider to accept one cooperative
/// cancellation request.
pub cancellation_request_timeout: std::time::Duration,
/// Maximum time allowed for all providers to confirm terminal results after
/// cancellation has been requested.
pub terminal_confirmation_timeout: std::time::Duration,
}
impl Default for ToolExecutionPolicy {
fn default() -> Self {
Self {
pause_safe_boundary_timeout: std::time::Duration::from_millis(100),
cancellation_request_timeout: std::time::Duration::from_millis(100),
terminal_confirmation_timeout: std::time::Duration::from_millis(500),
}
}
}
// =============================================================================
// Tool trait
// =============================================================================
/// Trait for defining tools callable by LLM
///
/// Tools are used by LLM to access external resources
/// or execute computations.
/// Can maintain state during the session.
///
/// # How to Implement
///
/// Usually auto-implemented using the `#[tool_registry]` macro:
///
/// ```ignore
/// #[tool_registry]
/// impl MyApp {
/// #[tool]
/// async fn search(&self, query: String) -> String {
/// format!("Results for: {}", query)
/// }
/// }
///
/// // Register
/// engine.register_tool(app.search_definition())?;
/// ```
///
/// # Manual Implementation
///
/// ```ignore
/// use agen::tool::{Tool, ToolError, ToolExecutionContext, ToolMeta, ToolDefinition, ToolOutput};
/// use std::sync::Arc;
///
/// struct MyTool { counter: std::sync::atomic::AtomicUsize }
///
/// #[async_trait::async_trait]
/// impl Tool for MyTool {
/// async fn execute(&self, input: &str, ctx: ToolExecutionContext) -> Result<ToolOutput, ToolError> {
/// self.counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
/// Ok(format!("call {}: {}", ctx.call_index, input).into())
/// }
/// }
///
/// let def: ToolDefinition = Arc::new(|| {
/// (
/// ToolMeta::new("my_tool")
/// .description("My custom tool")
/// .input_schema(serde_json::json!({"type": "object"})),
/// Arc::new(MyTool { counter: Default::default() }) as Arc<dyn Tool>,
/// )
/// });
/// ```
#[async_trait]
pub trait Tool: Send + Sync {
/// Execute the tool.
///
/// # Arguments
/// * `input_json` - JSON-formatted arguments generated by LLM
/// * `ctx` - response-local call identity and ordering context
///
/// # Returns
/// A [`ToolOutput`] with summary and optional detailed content.
/// For simple cases, use `From<String>`: `Ok("done".to_string().into())`
async fn execute(
&self,
input_json: &str,
ctx: ToolExecutionContext,
) -> Result<ToolOutput, ToolError>;
/// Request cooperative cancellation for one started call.
///
/// Implementations that own cancellable provider operations should signal
/// every live execution identified by `call_id`, then let `execute` return
/// the confirmed bounded terminal output. Direct callers may use this
/// compatibility surface; Agen uses [`Tool::cancel_execution`] so providers
/// can bind cancellation to one exact live attempt.
async fn cancel(&self, _call_id: &str) -> Result<(), ToolError> {
Ok(())
}
/// Request cooperative cancellation for one exact started execution.
///
/// The default preserves existing tools by delegating to `cancel(call_id)`.
/// Providers with their own execution registry should override this method
/// and key cancellation by [`ToolExecutionContext::execution_id`].
async fn cancel_execution(&self, ctx: &ToolExecutionContext) -> Result<(), ToolError> {
self.cancel(&ctx.call_id).await
}
}
// =============================================================================
// Tool Call / Result Types
// =============================================================================
/// Tool call information
///
/// Represents a ToolUse block from LLM.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCall {
/// Tool call ID (used for linking with response)
pub id: String,
/// Tool name
pub name: String,
/// Input arguments (JSON)
pub input: Value,
}
/// Tool execution result
///
/// Intermediate representation between tool execution and history.
/// Carries `summary` + optional `content` from [`ToolOutput`].
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ToolResult {
/// Corresponding tool call ID
pub tool_use_id: String,
/// Typed terminal state.
#[serde(default, skip_serializing_if = "ToolResultDisposition::is_success")]
pub disposition: ToolResultDisposition,
/// Short summary (always kept in history)
pub summary: String,
/// Detailed output (prunable)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
/// Whether this is an error
#[serde(default)]
pub is_error: bool,
/// Durable binary details (prunable with `content`).
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attachments: Vec<Attachment>,
}
impl ToolResult {
/// Create a success result from a [`ToolOutput`].
pub fn from_output(tool_use_id: impl Into<String>, output: ToolOutput) -> Self {
Self::from_output_with_disposition(tool_use_id, output, ToolResultDisposition::Success)
}
pub fn from_output_with_disposition(
tool_use_id: impl Into<String>,
output: ToolOutput,
disposition: ToolResultDisposition,
) -> Self {
Self {
tool_use_id: tool_use_id.into(),
disposition,
summary: output.summary,
content: output.content,
is_error: !disposition.is_success(),
attachments: output.attachments,
}
}
/// Create an error result.
pub fn error(tool_use_id: impl Into<String>, message: impl Into<String>) -> Self {
Self {
tool_use_id: tool_use_id.into(),
disposition: ToolResultDisposition::Error,
summary: message.into(),
content: None,
is_error: true,
attachments: Vec::new(),
}
}
/// Close an execution whose completion and side effects cannot be confirmed.
pub fn outcome_unknown(tool_use_id: impl Into<String>) -> Self {
Self {
tool_use_id: tool_use_id.into(),
disposition: ToolResultDisposition::OutcomeUnknown,
summary: "Tool execution outcome unknown".to_string(),
content: Some(
"Execution was interrupted before completion could be confirmed. Completion and side effects are unknown."
.to_string(),
),
is_error: true,
attachments: Vec::new(),
}
}
}
#[cfg(test)]
mod truncate_tests {
use super::*;
#[test]
fn noop_when_within_limit() {
let mut s = "hello world".to_string();
truncate_content(&mut s, 1024);
assert_eq!(s, "hello world");
}
#[test]
fn noop_at_exact_limit() {
let mut s = "a".repeat(100);
truncate_content(&mut s, 100);
assert_eq!(s.len(), 100);
}
#[test]
fn truncates_oversized_ascii_with_marker() {
let mut s = "a".repeat(1000);
truncate_content(&mut s, 200);
assert!(s.contains("[truncated:"));
assert!(s.contains("refine your query"));
assert!(s.len() <= 200, "result was {} bytes", s.len());
let dropped: usize = s
.split("[truncated: ")
.nth(1)
.unwrap()
.split(' ')
.next()
.unwrap()
.parse()
.unwrap();
let body_len = s.find("\n\n[truncated:").unwrap();
assert_eq!(body_len + dropped, 1000);
}
#[test]
fn respects_utf8_char_boundaries() {
// 100 copies of "あ" (3 bytes each) = 300 bytes.
let mut s = "".repeat(100);
truncate_content(&mut s, 120);
// Truncation must not split a multibyte character.
assert!(s.is_char_boundary(s.find("\n\n[truncated:").unwrap_or(s.len())));
// And the result must still be valid UTF-8 (implicitly true for String).
assert!(s.contains("[truncated:"));
}
#[test]
fn limits_per_tool_override() {
let mut limits = ToolOutputLimits {
default_max_bytes: 1024,
per_tool: HashMap::new(),
};
limits.per_tool.insert("Read".to_string(), 4096);
assert_eq!(limits.limit_for("Read"), 4096);
assert_eq!(limits.limit_for("Grep"), 1024);
}
}

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