Summary
"Reply in side chat" displays the selected source message under "Replying to", but the explicit agent-only reply anchor is omitted from the first provider turn. The forked provider session inherits conversation history, but it does not receive the text that identifies which earlier message the user selected.
Versions and environment
- bb from source at
7e10ea4b3742f3d14bde086c2963118238fec3ab, current origin/main
- bb CLI 0.39.0
- macOS 26.3, Node v24.6.0
- Codex CLI 0.149.0
- Local reused-workspace fork
Steps to reproduce
- Create an idle fork through
POST /api/v1/threads/fork with an agentContextSeed containing Replying to the selected earlier message and workspace: "reuse".
- Complete the queued zero-input
thread.start, returning a provider thread id.
- Send the first user message to the fork through
POST /api/v1/threads/:id/send with Explain that quoted message.
- Inspect the queued
turn.submit.input sent to the host daemon.
Minimal regression assertion run on main:
expect(firstTurn.command.input).toEqual([seed, firstReply]);
Expected vs actual
Expected turn.submit.input:
[
{
"type": "text",
"text": "Replying to the selected earlier message",
"mentions": [],
"visibility": "agent-only"
},
{
"type": "text",
"text": "Explain that quoted message",
"mentions": []
}
]
Actual turn.submit.input:
[
{
"type": "text",
"text": "Explain that quoted message",
"mentions": []
}
]
Vitest reports:
AssertionError: expected [ { type: 'text', …(2) } ] to deeply equal [ { type: 'text', …(3) }, …(1) ]
Evidence and root cause
The side-chat plugin builds an agentContextSeed for an earlier-message anchor and passes it to threads.fork: plugins/side-chat/server.ts.
The server combines that seed into the fork's persisted input, but for a seed-only idle fork it separately sets providerInput: []: apps/server/src/services/threads/thread-fork.ts.
Provisioning persists args.input in client/turn/requested, while args.providerInput ?? args.input becomes the daemon-facing input. The explicit empty providerInput therefore removes the seed from the zero-turn provider fork: apps/server/src/services/threads/thread-provisioning.ts.
The first subsequent send builds turn.submit from only the new request input. It does not recover the persisted seed: apps/server/src/services/threads/thread-send.ts.
The current test covers only persistence plus the intentionally empty initial provider input; it does not exercise the first user turn: apps/server/test/public/public-thread-fork.test.ts.
Investigation thread: thr_93njf8in3x.
What was ruled out
- Still reproduces on current
origin/main at 7e10ea4b3742f3d14bde086c2963118238fec3ab.
- The panel UI does retain and render the anchor; the loss occurs between persisted fork input and provider input.
- Searches across open and closed issues for side-chat seed, reply anchor, and reply context found no duplicate.
AGENT GENERATED
Summary
"Reply in side chat" displays the selected source message under "Replying to", but the explicit agent-only reply anchor is omitted from the first provider turn. The forked provider session inherits conversation history, but it does not receive the text that identifies which earlier message the user selected.
Versions and environment
7e10ea4b3742f3d14bde086c2963118238fec3ab, currentorigin/mainSteps to reproduce
POST /api/v1/threads/forkwith anagentContextSeedcontainingReplying to the selected earlier messageandworkspace: "reuse".thread.start, returning a provider thread id.POST /api/v1/threads/:id/sendwithExplain that quoted message.turn.submit.inputsent to the host daemon.Minimal regression assertion run on
main:Expected vs actual
Vitest reports:
Evidence and root cause
The side-chat plugin builds an
agentContextSeedfor an earlier-message anchor and passes it tothreads.fork: plugins/side-chat/server.ts.The server combines that seed into the fork's persisted input, but for a seed-only idle fork it separately sets
providerInput: []: apps/server/src/services/threads/thread-fork.ts.Provisioning persists
args.inputinclient/turn/requested, whileargs.providerInput ?? args.inputbecomes the daemon-facing input. The explicit emptyproviderInputtherefore removes the seed from the zero-turn provider fork: apps/server/src/services/threads/thread-provisioning.ts.The first subsequent send builds
turn.submitfrom only the new request input. It does not recover the persisted seed: apps/server/src/services/threads/thread-send.ts.The current test covers only persistence plus the intentionally empty initial provider input; it does not exercise the first user turn: apps/server/test/public/public-thread-fork.test.ts.
Investigation thread: thr_93njf8in3x.
What was ruled out
origin/mainat7e10ea4b3742f3d14bde086c2963118238fec3ab.