GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat(site/src): move chats between projects from the chat menu by ibetitsmike · Pull Request #30895 · coder/coder

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Oct 16, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

The chat menu in the sidebar, the top bar and the project page gets a Move to project submenu. It lists the projects of the chat's organization, marks the current one with a check mark and aria-current, and ends with Remove from project.

Stack (moving chats between projects, bottom first):

  1. feat: move a chat family between projects in chatd #30893: the move in chatd
  2. feat: move chats between projects through the chat update API #30894: the chat update API takes project_id
  3. This PR: Move to project in the chat menu
  4. feat(site): drag chats onto project folders in the sidebar #30795: drag a chat onto a project folder in the sidebar

Why: this is the first way for a user to move a chat, through the API from #30894.

  • The submenu shows only for the owner of a root chat that is not archived, with the chat-projects experiment. While the chat or a subagent runs, it looks disabled and does not open, as the API would return 409. It stays keyboard focusable, so keyboard and screen reader users reach the Archive agent hint it names.
  • moveChatToProject updates the cached lists and the chat entity at once. Its rollback restores only project_id, so it keeps the fields that watch events wrote while the request ran. A refused move shows the server message in a toast, even after the menu closes.
  • Other tabs follow the project_change watch event. A move keeps updated_at, so project_id comes only from that event, and the open chat refetches so the last event cannot win over the committed project. First list fetches that started before the move restart.
  • The project page hides a chat that moved away. The composer's project picker no longer says "Can't move to a project later".

What to scrutinize: the project_change branch in AgentsPageLayout.tsx and mergeWatchedChatSummary() in api/queries/chats.ts.

Move to project submenu Move is off while the chat runs Project page after the move
The Move to project submenu shows the current project Launch with a check mark, then Billing and Remove from project Move to project and Archive agent are disabled, with the hint to interrupt or wait for the agent The Billing project page lists the moved chat

Pixel: new ChatTopBar submenu stories, ProjectPage ChatMovedToAnotherProject, and the ChatsSidebar menus without Move to project (archived, shared, subagent) and MoveToProjectOffWhileSubagentRuns, which focuses the blocked item. The open CompactProjectSelector stories lose the hint.

Testing

  • make pre-commit passes. Vitest passes on the 5 touched specs (437 tests), and the Storybook tests of the 4 touched story files pass (134).
  • The open chat in AgentsPageLayout.test.tsx ends on the older project when two moves arrive in reverse order and it does not refetch. The resetUnloadedChatLists tests fail when the project list family or the unloaded-only check is removed.
  • A blocked Move to project takes keyboard focus, has the hint as its description and does not open. The test fails when the trigger is disabled or the open guard is removed.
  • Untested: aria-current on the current project, which site/AGENTS.md leaves to the stories.
  • Codex: the keyboard reach of a blocked Move to project is fixed. Seven other findings are declined in their threads: client race and cache sync hardening, and story and doc nits on patterns or text this PR keeps from main.

Xum opened this PR on behalf of @ibetitsmike.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
ibetitsmike added 3 commits October 16, 2026 12:29
@ibetitsmike
feat: move a chat family between projects in chatd
b06cf6d
chatd gains MoveChatToProject, which sets the project of a root chat.
Its subagent chats follow because they use the project of the root.

The chatstate machine gets a SetProject transition, allowed only from
W, E0 and E1, like SetArchived. SetFamilyProject locks the root row
before its subagents, in the same order as archiving, so a busy family
gets ErrTransitionNotAllowed and a move never overlaps a step. A move to
the project the chat is already in changes nothing, even while the chat
runs. After the commit, chatd publishes a project_change watch event for
each chat of the family.

A root chat outside a project now has an empty memory index, so a chat
that leaves its project, or whose project is deleted, gets the memories
it saw removed at its next turn start.
@ibetitsmike
feat: move chats between projects through the chat update API
15a49ca
PATCH /api/v2/chats/{chat} now accepts project_id. A UUID moves an idle
root chat into a project of its owner and organization; uuid.Nil removes
it from its project. The project checks are the ones of chat creation,
now shared by validateChatProjectSelection.

A project that the chat's owner does not own gives 404 even for an
admin, so an admin cannot put a member's chat into another user's
project and expose its memory. A child chat, an archived chat or a
disabled experiment gives 400, and a busy family gives 409. The move is
the last write of the request, so a refused move keeps the earlier
writes, as a refused archive does.
@ibetitsmike
feat(site/src): move chats between projects from the chat menu
eab509f
The chat menu (sidebar, top bar, project page) gets a Move to project
submenu with the projects of the chat's organization, a check mark and
aria-current on the current one, and Remove from project. It shows only
for the owner of a root chat that is not archived, with the
chat-projects experiment, and it is off with the Archive agent hint
while the chat or a subagent runs.

moveChatToProject updates the cached chat lists and the chat entity
optimistically, and its rollback restores only project_id. Other tabs
follow project_change watch events: a move keeps updated_at, so
project_id is taken only from that kind, and the open chat refetches.
The project page drops a chat that moved away. The composer's project
picker no longer says "Can't move to a project later".
@ibetitsmike
ibetitsmike added this pull request to stack #30896 October 16, 2026 12:42
@github-actions github-actions Bot assigned ibetitsmike Oct 16, 2026
This was referenced Oct 16, 2026
feat: move a chat family between projects in chatd #30893
Merged
feat: move chats between projects through the chat update API #30894
Merged
feat(site): drag chats onto project folders in the sidebar #30795
Merged
@ibetitsmike
ibetitsmike marked this pull request as ready for review October 16, 2026 14:00
@ibetitsmike
ibetitsmike requested a review from a team as a code owner October 16, 2026 14:00
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T21:26:14.839491Z 96bcfd3 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

chatgpt-codex-connector[bot]
chatgpt-codex-connector Bot reviewed Oct 16, 2026
View reviewed changes

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eab509f362

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread site/src/pages/AgentsPage/components/MoveToProjectMenuItems.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/pages/AgentsPage/components/ChatElements/CompactProjectSelector.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

@pr-queue-manager
pr-queue-manager Bot requested a review from jaaydenh October 16, 2026 14:24
@ibetitsmike
fix(site/src/pages/AgentsPage/components): keep a blocked move to pro…
96bcfd3
…ject item keyboard reachable

Radix keeps disabled menu items out of keyboard focus, so while the chat
or a subagent ran, keyboard and screen reader users could not reach
"Move to project" or the hint its aria-describedby names. The trigger now
only looks disabled and its submenu refuses to open while blocked.
@ibetitsmike

ibetitsmike commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

chatgpt-codex-connector[bot]
chatgpt-codex-connector Bot reviewed Oct 16, 2026
View reviewed changes

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 96bcfd3375

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread site/src/pages/AgentsPage/components/MoveToProjectMenuItems.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/api/queries/chats.ts Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/api/queries/chats.ts Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/pages/AgentsPage/components/ChatsSidebar/ChatsSidebar.stories.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread site/src/pages/AgentsPage/components/ProjectPage/ProjectPage.stories.tsx Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ibetitsmike

ibetitsmike commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 96bcfd3375

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jaaydenh
jaaydenh reviewed Oct 18, 2026
View reviewed changes
Comment thread site/src/api/queries/chatProjects.ts Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ibetitsmike
refactor(site/src): filter projects by organization in the move to pr…
74f7e9e
…oject menu

The menu reads one organization's projects, so a filter in the
component replaces the grouping selector and its lodash import.
@ibetitsmike
ibetitsmike requested a review from jaaydenh October 18, 2026 15:19
jaaydenh
jaaydenh approved these changes Oct 19, 2026
View reviewed changes
ibetitsmike added 8 commits October 19, 2026 11:11
@ibetitsmike
docs(coderd/x/chatd): describe moving chats between projects
9f84197
Add the SetProject transition to the transition list and the execution
state diagram, note that a root chat's project can change after
creation, and describe how a moved chat's memory index is brought up to
date at its next turn.
@ibetitsmike
Merge branch 'mike/move-chats-chatd' into mike/move-chats-api
6d26347
@ibetitsmike
docs(coderd/x/chatd): describe project moves in the chat update endpoint
a57182f
The PATCH /api/v2/chats/{chat} section said the endpoint emits no state
transitions unless the request changes archived. A project_id change now
applies SetProject to the chat family, so list its supported states and
refusals.
@ibetitsmike
Merge branch 'mike/move-chats-api' into mike/move-chats-menu
9197d76
@ibetitsmike
Merge origin/main into mike/move-chats-chatd
f83d0f0
@ibetitsmike
Merge the updated layer below into mike/move-chats-api
0093b17
Brings in origin/main through mike/move-chats-chatd. Chat creation on
main now checks project access with chatd.ChatProjectUsableBy, so
validateChatProjectSelection uses that check for both creation and
moves.
@ibetitsmike
test: cover moving a chat into a project shared with its owner
de152c0
A move accepts the same projects as chat creation, which now include
projects shared with the chat's owner. Extend the owner-check test to
share the project and move the chat, and describe the rule on
UpdateChatRequest.ProjectID.
@ibetitsmike
Merge the updated layer below into mike/move-chats-menu
6ee95a9
ibetitsmike added a commit that referenced this pull request Oct 19, 2026
@ibetitsmike
feat: move a chat family between projects in chatd (#30893)
0968f97
chatd can now move a root chat, together with its subagent chats, into a
project, to another project, or out of its project. Nothing calls this
yet. #30894 adds the API.

**Stack** (moving chats between projects, bottom first):
1. **This PR**: the move in chatd
2. #30894: `PATCH /api/v2/chats/{chat}` takes `project_id`
3. #30895: **Move to project** in the chat menu
4. #30795: drag a chat onto a project folder in the sidebar

**Why:** today a chat keeps the project it was created with. A move must
follow the family rules of archiving, because a step that runs during a
move would still have the memory tools of the old project.

- `chatstate.Tx.SetProject` runs only from W, E0 and E1, like
`SetArchived`. `SetFamilyProject()` locks the root row before its
subagents, in the same order as archiving, so a busy family gets
`ErrTransitionNotAllowed` and nothing changes.
- A move to the project the chat is already in changes nothing, even
while the chat runs. The check reads the locked root row, so it waits
for a move that is still in flight.
- Only the root row stores `project_id`, and subagents use the project
of the root. After the commit, chatd publishes a new `project_change`
watch event for each chat of the family. The move keeps `updated_at`, so
lists keep their order.
- A root chat outside a project now has an empty memory index. When a
chat leaves its project, or its project is deleted, its next turn start
commits one memory index update that removes the memories the model saw
there.

**What to scrutinize:** the lock order and the same-project check under
the lock in `SetFamilyProject()` (`chatstate/family.go`), the turn-start
condition in `memoryIndexMessage()` (`memory.go`), and whether the
`ARCHITECTURE.md` text matches them.

**Generated** (`make gen`): `queries.sql.go`, `querier.go`, `dbmock` and
`dbmetrics` come from `queries/chats.sql`. `coderd/apidoc`,
`docs/reference/api/schemas.md` and `typesGenerated.ts` come from the
new watch event kind, which is also why two `chats.test.ts` fixtures
gain `project_change: false`.

**Architecture doc:** `coderd/x/chatd/ARCHITECTURE.md` lists
`SetProject` among the transitions and in the execution state diagram
(W, E0 and E1 back to themselves). It also says that a root chat's
project can change after creation, and that a moved chat's next turn
starts with a memory index update from the old project to the new one.

## Testing

- `make pre-commit` passes. `go test` passes for
`coderd/x/chatd/chatstate`, `coderd/database/dbauthz`
(`TestMethodTestSuite`) and the chatd memory tests.
- `TestSetFamilyProjectLocksRootFirst` fails with 55P03 when a subagent
row is locked first. `TestSetFamilyProjectKeepsTheCurrentProject` covers
the same-project move during a run. The transition matrix test gains
`SetProject` cases for W, E0 and E1.
- `TestMovedChatUsesNewProject` runs two real turns around a move: the
second turn uses the instructions and memories of the new project, and
`OutOfProject` fails without the memory index removal.

> Xum opened this PR on behalf of @ibetitsmike.
Base automatically changed from mike/move-chats-api to main October 19, 2026 14:01
@ibetitsmike
ibetitsmike requested a review from nickvigilante as a code owner October 19, 2026 14:01
ibetitsmike added a commit that referenced this pull request Oct 19, 2026
@ibetitsmike
feat: move chats between projects through the chat update API (#30894)
dfdd6a5
`PATCH /api/v2/chats/{chat}` now takes `project_id`. A project ID moves
the chat into that project, and `uuid.Nil` removes it from its project.

**Stack** (moving chats between projects, bottom first):
1. #30893: the move in chatd
2. **This PR**: the chat update API takes `project_id`
3. #30895: **Move to project** in the chat menu
4. #30795: drag a chat onto a project folder in the sidebar

**Why:** #30893 can move a chat family, and the UI layers above need an
endpoint to call.

- A move accepts the same projects as chat creation, through
`validateChatProjectSelection()`, which this PR extracts from
`postChats()` without a change in behavior.
- A project that the chat's owner cannot use gives 404, even for an
admin. The owner must own the project or hold a grant on it
(`chatd.ChatProjectUsableBy`, the check that chat creation uses since
#30439). So an admin cannot put a member's chat into a project that the
member has no access to and expose its memory.
- A child chat, an archived chat or a disabled `chat-projects`
experiment gives 400. A family that is not idle gives 409 ("Cannot move
an active chat. Interrupt or wait for the chat to finish first."). A
project deleted between the check and the move gives 404.
- The move is the last write in `patchChat()`, so a refused move keeps
the earlier writes of the same request, as a refused archive does.

**What to scrutinize:** the access check in
`validateChatProjectSelection()` and the order of the refusals in
`patchChat()` (`coderd/exp_chats.go`).

**Architecture doc:** the `PATCH /api/v2/chats/{chat}` section of
`coderd/x/chatd/ARCHITECTURE.md` lists the `SetProject` states of a move
and its refusals, and no longer says that only an `archived` change
emits transitions.

**Generated** (`make gen`): `coderd/apidoc`,
`docs/reference/api/chats.md`, `docs/reference/api/schemas.md` and
`typesGenerated.ts` come from `UpdateChatRequest.ProjectID` in
`codersdk/chats.go`.

## Testing

- `make pre-commit` passes, and so does `go test ./coderd -run
TestPatchChatProject` (14 subtests).
- `TestPatchChatProject/AnotherOwnersProject` gets 404 for another
user's project, then moves the chat after the project is shared with the
chat's owner. It fails without the access check, and also with an
owner-only check. `MoveBackWaitsForAPendingMove` ends in the wrong
project when the handler skips the move before the lock.
`ActiveFamilyReturnsConflict` checks the 409 for a running, interrupting
or action-waiting root and for a running subagent.
`PublishesProjectChange` and `AuditsTheMove` cover the watch event and
the audit entry.
- Untested: the 404 when the project is deleted between the check and
the move.

> Xum opened this PR on behalf of @ibetitsmike.
@ibetitsmike
Merge main into mike/move-chats-menu
f63c468
@ibetitsmike
ibetitsmike merged commit 2cade24 into main Oct 19, 2026
27 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@ibetitsmike
ibetitsmike deleted the mike/move-chats-menu branch October 19, 2026 14:22
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@chatgpt-codex-connector chatgpt-codex-connector[bot] chatgpt-codex-connector[bot] left review comments
@jaaydenh jaaydenh jaaydenh approved these changes
@nickvigilante nickvigilante Awaiting requested review from nickvigilante

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@ibetitsmike ibetitsmike

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@ibetitsmike @jaaydenh
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.