Skip to content

feat(coderd/x/chatd/chatstate): add hook-aware transitions and queued policy#27428

Open
ibetitsmike wants to merge 1 commit into
mike/chat-hooks/backendfrom
mike/chat-hooks/chatstate
Open

feat(coderd/x/chatd/chatstate): add hook-aware transitions and queued policy#27428
ibetitsmike wants to merge 1 commit into
mike/chat-hooks/backendfrom
mike/chat-hooks/chatstate

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Stack Context

Chat lifecycle hooks stack: #27427 (DB schema) -> #27401 (dispatch backend) -> #27428 (this) -> #27429 (chatd wiring) -> #27430 (API + UI).

What

State-machine primitives that hook responses need, with no hook dispatch here:

  • Queued prompts persist hook_prefix and hook_allowed_tools so hook effects apply at promotion time, not queue time; policies can only narrow on promotion.
  • NarrowHookAllowedTools: intersection semantics for allowed-tools policies (NULL means unrestricted).
  • Turn ID threading on messages, prefix message insertion on transitions, and batch tool-cancellation synthesis for edits that cut off in-flight tool calls.
  • FailIdle for idle-chat error termination.

Why

These transitions are pure state-machine mechanics, testable without any hook plumbing (see the transition matrix tests). Keeping them below #27429 makes the chatd diff reviewable as "dispatch + response application" only.

This PR was prepared by Mux (AI agent) on Mike's behalf.

Copy link
Copy Markdown
Collaborator Author

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

Copy link
Copy Markdown

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: 9fefafe6dc

ℹ️ 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".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
Comment thread coderd/x/chatd/chatstate/transition.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/backend branch from fb591a8 to cdabebf Compare July 22, 2026 19:59
@ibetitsmike
ibetitsmike requested a review from Emyrk as a code owner July 22, 2026 19:59
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 9fefafe to e0b7344 Compare July 22, 2026 19:59
@ibetitsmike ibetitsmike changed the title feat(coderd/x/chatd/chatstate): add hook transitions and end-chat family orchestration feat(coderd/x/chatd/chatstate): add hook-aware transitions and queued policy Jul 22, 2026
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: e0b7344a0f

ℹ️ 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".

Comment thread coderd/x/chatd/chatstate/transition.go
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from e0b7344 to a05cf3c Compare July 22, 2026 20:12
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: a05cf3ceb6

ℹ️ 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".

Comment thread coderd/x/chatd/chatstate/transitions.go
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/backend branch from cdabebf to fb7db50 Compare July 22, 2026 20:24
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from a05cf3c to 841eefb Compare July 22, 2026 20:24
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: 841eefb780

ℹ️ 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".

Comment thread coderd/x/chatd/chatstate/transitions.go
… policy

Threads hook effects through chat state transitions: prefix messages and
narrowed tool policies persist with queued prompts and apply at promotion,
messages carry turn IDs, CreateChatWithID supports caller-minted chat IDs
with an initial hook tool policy, CompleteRequiresAction accepts suffix
messages, and FailIdle moves a waiting chat to the error state when a hook
dispatch fails outside an owned run.
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 841eefb to e08f7af Compare July 22, 2026 20:51
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: e08f7affcd

ℹ️ 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".

return EditMessageResult{}, err
}
cancellationMessages, err := tx.insertMessages(cancels)
cancellationMessages, err := tx.insertMessages(append(cancels, input.PrefixMessages...))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stamp prefix messages with the edited turn ID

When EditMessage is called with hook PrefixMessages that do not already carry input.TurnID, these rows are inserted with a NULL or stale turn_id; the next edit only removes stale prefixes by matching the target message's TurnID above, so old hook context can remain in the model prompt next to the replacement. The queued-promotion path explicitly stamps prefixes with the queued prompt's turn ID for this reason, so the edit path, and the analogous direct-send path, should stamp prefixes before insertion.

Useful? React with 👍 / 👎.

- `Interrupt(reason)` requests cancellation of an active generation or closes pending dynamic-tool action. It preserves queued backlog.
- `CompleteRequiresAction(results)` inserts submitted tool-result messages, clears `requires_action_deadline_at`, and lands in `running`. It preserves queued messages.
- `RequestCompaction` records a manual compaction request on an idle chat by setting `compaction_requested_at` and landing in `running` without inserting any message. The chat worker picks the chat up like any other running chat and consumes the request. See [Manual compaction](#manual-compaction).
- `FailIdle(err)` moves a waiting chat to `error` and persists `last_error = err` without requiring runner ownership. Used when a blocking lifecycle hook dispatch fails while handling `SendMessage` or `EditMessage`, before any generation starts.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Document the new hook state in the architecture guide

This architecture update only adds FailIdle, but the commit also makes turn_id, queued hook_prefix, and hook_allowed_tools part of promotion, edit cleanup, and policy narrowing semantics. Leaving those fields out of the state-machine spec means future chatd work will still read that queued execution state is only position and created_by, with no mention of deferred hook context or tool-policy narrowing. Please update the architecture doc for those state changes too.

AGENTS.md reference: AGENTS.md:L90-L93

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant