Skip to content

Duplicate-thread review and merge API

The dashboard's Possible overlap review helps you compare threads that may describe the same outcome. Similar wording alone never authorizes a merge. See Dashboard for the user interface and Return-cue coaching for help recording a restart step.

Suggestions

REST routes require your existing bearer token or browser session. HTTP MCP uses authenticated /mcp; local stdio exposes the same tools.

Operation MCP tool REST
Check a planned task check_overlap(query, limit=5) GET /api/overlap?q=…&limit=5
Review an existing thread suggest_duplicate_threads(thread_id, limit=5) GET /api/threads/{id}/duplicates?limit=5
Queue a merge for review request_thread_merge(source_thread_id, target_thread_id) POST /api/threads/{source_id}/merge
Read retained history thread_merge_history(thread_id, limit=50) GET /api/threads/{id}/merge-history?limit=50

Each suggestion includes the thread, score and reason, plus an outcome (same_outcome, related or uncertain), evidence and merge_allowed. Suggestion limits are 1–50. Reads do not change threads or queue actions. The planned-task check always returns merge_allowed: false because a query does not establish which two threads belong together.

Human-confirmed merge

Only two different unfinished local threads in the same project with the same nonempty normalized goal can be merged. Forge-backed or imported work stays review-only. Before confirming, check that both goals represent one independently finishable outcome.

Queue the direction with POST /api/threads/source/merge and {"target_thread_id":"target"}, or the corresponding MCP tool. The source is the duplicate; the target is the active thread you keep. Queueing changes neither thread. Review both goals, continuity states and source identities:

  • The target keeps its focus, next steps, resume cue and pause state.
  • The source is locally dismissed with merged_into pointing to the target.
  • The source's original fields, notes and events remain in retained history.
  • No remote issue is changed.

After a person confirms the preview, an integration can approve with POST /api/pending-actions/{action_id}/approve and {"confirm_merge":true}. Agents must not confirm on the person's behalf. Reject through POST /api/pending-actions/{action_id}/reject; rejection changes neither thread. If the preview becomes stale, reject it and request a fresh review.

Refusals and retained history

Unsafe queue requests return pending: false, merge_allowed: false, a reason and review alternatives. Typical reasons include different projects, missing goals, distinct outcomes, finished threads or forge authority. Keep those outcomes separate or add an ordinary progress note linking them.

Unsafe or stale approval returns 409; missing threads or actions return 404. A merged source is read-only: update its active target instead.

History includes each retained thread's original fields, notes and events, including descendants from earlier merges. The history limit is 1–500 per thread. Read the history endpoint to see source notes that do not appear in the target's ordinary context view.

Cursor fixtures and checks

For response examples, refusal codes, transaction guarantees and maintainer fixtures, see the merge implementation contract.