Files
multica/server/internal
Bohan Jiang 459dd90f82 fix(daemon): stop the coalesced-comment fallback from pulling the whole issue history (MUL-5442) (#6309)
* fix(daemon): stop the coalesced-comment fallback from pulling the whole issue history (MUL-5442)

When a run covers comments that arrived before it started and the server sent
only their ids (no bodies), the prompt told the agent to find them by running
`multica issue comment list <issue> --recent 30`.

`--recent N` caps THREADS, not comments, and every returned thread carries all
of its descendants. On an issue with fewer than 30 root threads that is the
entire comment history — measured on a live 3-thread issue: 88,301 bytes
(~22k tokens) to locate two ids. It also contradicted the runtime brief's own
catch-up step, which tells the agent to read in two bounded steps and never
make one bulk pull (MUL-5372): the platform was recommending the exact shape
it forbids elsewhere.

Those comments all arrived between the agent's previous run and this one, so
when the server supplied that anchor `--since` returns precisely them in one
bounded read — 17,376 bytes on the same issue. When there is no anchor (no
prior run on this issue, so the server sends none) the fallback now uses the
same scan-then-expand pair the brief teaches instead of a bulk pull.

Also drops the "--full if a thread is folded" note: per `comment list --help`,
`--since`, `--tail` and `--roots-only` reads are never folded, so it was
advice that could not apply to either replacement read.

This was the last place the platform steered agents onto `--recent`. The flag
and its saturation warning stay documented in Available Commands, since an
agent can still choose it.

MUL-5442

Co-authored-by: multica-agent <github@multica.ai>

* fix(daemon): make the coalesced-id lookup deterministic, not window-dependent (MUL-5442)

Review found the previous version could still drop a user instruction.

`--since` is not a reliable lower bound for these ids. A retry inherits the
previous attempt's coalesced_comment_ids verbatim (queries/agent.sql RetryTask)
while the anchor is recomputed from the last STARTED task's started_at
(GetLastTaskStartedAtForIssueAndAgent), so an inherited id can predate the
anchor. If any unrelated comment lands after the anchor, NewCommentsSince is
populated, the prompt sent the agent at the window, and the inherited id was
simply not in the result. It was not a precise fetch in the other direction
either -- the window also carries the trigger comment and unrelated comments.

Replace the window-or-heuristic pair with one deterministic contract:
`--thread` accepts ANY comment id, reply or root, and the server resolves it to
the containing thread. So every id is fetchable directly and bounded, with
`--before`/`--before-id` paging when it is older than the tail window. That
pass now runs unconditionally; `--since` is demoted to an optional prefetch,
described as a candidate window rather than an exact fetch.

This also removes the anchorless branch's "expand the threads whose
last_activity_at is recent" heuristic. Completeness of user instructions is not
a good place for the agent to guess.

Tests assert the contract rather than the command spelling: the per-id lookup,
the reply-id capability, cursor paging and the "account for every id" rule are
required in both shapes; the anchored shape must not overpromise the window;
the anchorless shape must carry no --since and no recency heuristic.

MUL-5442

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: Bohan-J <bohan@devv.ai>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-03 19:00:09 +08:00
..