Skip to content

Make Captain chat threads and provider sessions authoritative #54

Description

@moshloop

Problem

Captain aichat does not have one authoritative identity contract across the UI thread, Captain session, provider session, backend, model, and AI SDK message lifecycle. Thread switching can retain stale messages, provider sessions can be resumed under a different runtime, regeneration metadata is ignored, and concurrent turns can overwrite persisted thread state.

Required implementation

  • Create, hydrate, switch, and reset chat threads explicitly; never combine messages from two thread identities.
  • Keep Captain session ID, provider session ID, thread ID, backend, runtime, and model as distinct typed fields. Bind immutable runtime identity when the provider session is first observed and reject incompatible resume attempts.
  • Make the server authoritative for thread/session identity and return the resolved values to the client.
  • Honor AI SDK trigger, message ID, and regeneration semantics without duplicate assistant IDs or duplicate persisted turns.
  • Serialize turns per thread or use optimistic versioning so concurrent windows cannot silently overwrite messages, scopes, or provider-session state.
  • Return bounded thread summaries from list endpoints and hydrate full history from a detail endpoint.
  • Coordinate with Xero TODO 98f799b6-9a79-465d-bfa9-b04ce4f36e79; scoped-context persistence must use this authoritative thread contract.

Acceptance criteria

  • Switching threads replaces visible and submitted history rather than appending stale messages.
  • A provider session cannot resume under a different backend, runtime, or model.
  • Regeneration replaces the intended assistant turn and remains stable after reload.
  • Concurrent turns have deterministic ordering or fail with an actionable version conflict.
  • Focused store, HTTP, AI SDK, and UI integration tests cover creation, hydration, switching, regeneration, resume rejection, and concurrency.

Verification


cwd: .
timeout: 25m
codeBlocks: [test, lint]
ai: {}
verify:
scope: diff
threshold: 80

Thread and provider-session identity tests

paths: [./pkg/aichat/..., ./pkg/session/..., ./pkg/database/...]
framework: [go, ginkgo]
test-timeout: 18m
show-passed: true

Chat client thread-switching tests

paths: [./pkg/cli/webapp]
framework: [vitest]
test-timeout: 8m

Changed-code lint

changed: true
fix: false
timeout: 5m

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions