mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-26 04:25:46 +02:00
* fix(agent/comments): re-emit trigger comment id every turn + server-side parent_id guard Resumed Claude sessions keep prior turns' tool calls in context, so a comment-triggered task could reuse the PREVIOUS turn's --parent UUID instead of the current trigger's. The reply landed in the wrong thread (MUL-1125): backend stored exactly what the agent sent, but the agent pulled a stale UUID from its own conversation memory. Two layers of defense: 1. Extract BuildCommentReplyInstructions so daemon.buildCommentPrompt and execenv.InjectRuntimeConfig emit the same "use this exact --parent, do not reuse values from previous turns" block. The per-turn prompt now carries the current TriggerCommentID, which it previously relied on CLAUDE.md for (and CLAUDE.md isn't re-read mid-session). 2. Handler-side guard in CreateComment: when an agent posts from inside a comment-triggered task (X-Agent-ID + X-Task-ID, task has TriggerCommentID), require parent_id == task.TriggerCommentID or return 409. Assignment-triggered tasks are untouched. * fix(agent/comments): scope parent_id guard to the task's own issue Two issues from CI + GPT-Boy's review: 1. Guard was too broad: the CLI stamps X-Task-ID on every request, so an agent legitimately commenting on a different issue while its current task was comment-triggered would get 409'd with the wrong issue's trigger comment id. Narrow the guard to fire only when the request's issue matches the task's own issue — cross-issue agent activity stays unblocked. 2. The integration test tried to insert a second queued task for the same (agent, issue), which hits the idx_one_pending_task_per_issue_agent unique index. Replace the assignment-triggered-task sub-case with a cross-issue regression test (the scenario we now need to cover anyway): post on issue B while X-Task-ID points at a comment-triggered task on issue A, expect 201.
25 lines
989 B
Go
25 lines
989 B
Go
package execenv
|
|
|
|
import "fmt"
|
|
|
|
// BuildCommentReplyInstructions returns the canonical block telling an agent
|
|
// how to post its reply for a comment-triggered task. Both the per-turn
|
|
// prompt (daemon.buildCommentPrompt) and the CLAUDE.md workflow
|
|
// (InjectRuntimeConfig) call this so the trigger comment ID and the
|
|
// --parent value cannot drift between surfaces.
|
|
//
|
|
// The explicit "do not reuse --parent from previous turns" wording exists
|
|
// because resumed Claude sessions keep prior turns' tool calls in context
|
|
// and will otherwise copy the old --parent UUID forward.
|
|
func BuildCommentReplyInstructions(issueID, triggerCommentID string) string {
|
|
if triggerCommentID == "" {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf(
|
|
"Reply by running exactly this command — always use the trigger comment ID below, "+
|
|
"do NOT reuse --parent values from previous turns in this session:\n\n"+
|
|
" multica issue comment add %s --parent %s --content \"...\"\n",
|
|
issueID, triggerCommentID,
|
|
)
|
|
}
|