Repository navigation
feat(server): thread groups live on the server with agent tools - #1840
Conversation
Fork-Domain: thread-ordering Fork-Tier: qol
Fork-Domain: thread-ordering Fork-Tier: qol
Fork-Domain: thread-ordering Fork-Tier: qol
🧩 Effect Service Conventions
|
| Head | Result | Time | Check |
|---|---|---|---|
fbd537a |
✅ clear | 2 min | run |
6908994 |
✅ clear | 2 min | run |
24ce29b |
✅ clear | 1 min | run |
81ca197 |
✅ clear · 3 fixed | 2 min | run |
dd19a24 |
🔴 3 open · 4 fixed · 1 held · 2 new | 3 min | run |
5e008e3 |
🔴 5 open · 5 new | 3 min | run |
🩺 Aftercare
|
| Head | Result | Time | Check |
|---|---|---|---|
fbd537a |
✅ clear · 1 fixed | 3 min | run |
6908994 |
🟡 1 open · 3 fixed · 1 new | 5 min | run |
24ce29b |
🔴 3 open · 1 fixed · 2 held · 1 new | 7 min | run |
81ca197 |
🔴 3 open · 5 fixed · 2 held · 1 new | 5 min | run |
5e008e3 |
🔴 9 open · 9 new | 9 min | run |
Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
A9: b The maintainer scoped launch placement as "in its group; another group; or in no group". A3: drop require-dependency part; each accepted child now joins as it is accepted (dd19a24), but |
Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
Fixed in 81ca197:
|
Requested a rerun for one exact failed or cancelled CI job on the unchanged pull-request head. GitHub may also rerun dependent jobs.
|
… unavailable Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
Fixed in 24ce29b:
A10: drop test part: only the upstream |
Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
… grouping is unavailable Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
|
Requested a rerun for one exact failed or cancelled CI job on the unchanged pull-request head. GitHub may also rerun dependent jobs. |
…onment Fork-Domain: thread-ordering Fork-Tier: qol Fork-Upstreamable: no
A12:
|
Requested a rerun for one exact failed or cancelled CI job on the unchanged pull-request head. GitHub may also rerun dependent jobs.
|
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
## Problem
Sidebar thread groups live only in each browser's local storage.
- **Agents:** cannot read or edit groups
- **Launches:** children land outside the group
- **Clients:** a second browser or device sees none
## Change
Groups now live per environment on the server.
- **Server:** `ThreadGroupsServiceFork`
- Table: `fork_thread_groups`
- **RPCs:**
- `threadGroups.subscribeFork`
- `threadGroups.mutateFork`
- **Capability:** optional `threadGroupsFork`
- Upstream web and mobile clients ignore it
- **Reducer:** one, shared in contracts
- **MCP tools:**
- `t3_thread_group_list`
- `t3_thread_group_update`
- **Launch:** joins the caller's group by default
- `group`: an existing `{groupId}`, or `"none"`
- New groups: `t3_thread_group_update`
- Batch launches place each accepted thread
- **Web:** follows the server, optimistic edits
- Pending edits replay over newer snapshots
- Replies older than the held revision drop
- **Collapsed state:** stays per client
- **Legacy:** local groups import once
- A failed import retries
Known gap: launched threads still get `parentThreadId: null`; lineage is a separate follow-up.
## Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
## Verification
Isolated dev server on a seeded worktree `.t3` home.
Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
1. Agent (GPT-6-Astra via Codex) groups 3 threads
2. "Agent group" appears live on both clients
3. Agent launches a child with no `group` option
4. Child joins: "Agent group (4)" on both clients
https://github.com/user-attachments/assets/80208be1-44dd-4918-84ce-e3f11fef4a00
**Host Chrome**

**VM Firefox**

**Checks**
- [x] `apps/server: vp run typecheck` → exit 0
- [x] `vp run fork:ci` → exit 0
- [x] `apps/server: vp run build:bundle` → exit 0
- [x] `apps/web: vp run build` → exit 0
- [x] MCP registration test fails on old params
- [ ] `vp run check:changed` → exit 1
- 5005/5006 pass
- Fails: GitManager "includes CLAUDE.md"
- Cause: local global git config
- Passes with `GIT_CONFIG_GLOBAL=/dev/null`
Claude Opus 5.5 via Claude Code in T3 Code.
## Fork trailers
Squashes:
- 01547bb feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- a4b48f8 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 50aba4d feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ef3cc72 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- ad6dbd0 feat(server): thread groups live on the server with agent tools (#1840) (#1840)
- 32d73f7 fixup! feat(server): thread groups live on the server with agent tools (#1840) (#1840)
Fork-Domain: thread-ordering
Fork-Tier: qol
Co-authored-by: donjor <[email protected]>
## Problem A group with a parent thread showed its title as a section header above the parent, detached from it. Collapse lived in two places: the header chevron, and an `8 threads` fold strip under the parent. ## Change - **Title tab:** joined to the parent card - **One control:** the tab toggles the children - **Collapsed:** urgent-first status dots, max 6 plus `+N` - **Tab tooltip:** every child's status; opens on focus - **Count:** children only - **Fold strip:** deleted, with drag hook and test - **Parentless groups:** header unchanged - **Cross-project:** cards keep their project line **Fork isolation:** the header lives in `SidebarThreadGroup.tsx`; upstream files carry `fork-hook` lines only. ## Scope and approval The human picked concept A (Tab) from four captured concepts, relayed by the orchestrator thread. Follows #1829 and #1840. ## Verification Real Chrome, seeded dev data: a cross-project parent group (8 children, 6 projects) and a parentless group (3). - Tab click flips `aria-expanded`; 6 dots plus `+2` - Keyboard focus on the tab opens the status list - Enter on the focused tab toggles; focus stays - Double-click opens rename; hover menu opens - Parentless header toggles as before - Light theme and active parent checked - No new console errors | State | Before | After | | --- | --- | --- | | Expanded |  |  | | Collapsed |  |  | **Active parent:**  **Checks:** - `vp run typecheck` (apps/web) → exit 0 - `vp run check:changed` → exit 1 on the last commit, from the unrelated `markdownPipeline.browser.test.ts`; it passes alone (exit 0 on earlier commits) - `vp run fork:ci` → exit 0 Claude Opus 5.5, Claude Code in T3 Code. ## Fork trailers Squashes: - 11840c4 feat(web): group title becomes a tab on its parent thread (#1878) (#1878) - 960f0b5 fixup! feat(web): group title becomes a tab on its parent thread (#1878) (#1878) Fork-Domain: thread-ordering Fork-Tier: qol Co-authored-by: donjor <[email protected]>
Problem
Sidebar thread groups live only in each browser's local storage.
Change
Groups now live per environment on the server.
ThreadGroupsServiceForkfork_thread_groupsthreadGroups.subscribeForkthreadGroups.mutateForkthreadGroupsForkt3_thread_group_listt3_thread_group_updategroup: an existing{groupId}, or"none"t3_thread_group_updateKnown gap: launched threads still get
parentThreadId: null; lineage is a separate follow-up.Scope and approval
Fork-only feature, scoped by the maintainer in the T3 thread: per-environment groups, launch auto-join with opt-out, per-client collapse.
Verification
Isolated dev server on a seeded worktree
.t3home.Client 1 is host Chrome; client 2 is Firefox in a QA VM over an SSH tunnel.
groupoptionthread-groups-two-clients.mp4
Host Chrome
VM Firefox
Checks
apps/server: vp run typecheck→ exit 0vp run fork:ci→ exit 0apps/server: vp run build:bundle→ exit 0apps/web: vp run build→ exit 0vp run check:changed→ exit 1GIT_CONFIG_GLOBAL=/dev/nullClaude Opus 5.5 via Claude Code in T3 Code.
Fork trailers
Fork-Domain: thread-ordering
Fork-Tier: qol