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
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
98f799b6-9a79-465d-bfa9-b04ce4f36e79; scoped-context persistence must use this authoritative thread contract.Acceptance criteria
Verification
cwd: .
timeout: 25m
codeBlocks: [test, lint]
ai: {}
verify:
scope: diff
threshold: 80
Thread and provider-session identity tests
Chat client thread-switching tests
Changed-code lint