mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-10 18:36:45 +08:00
* feat(cli): expose active and cross-issue agent runs on `issue runs` An agent could already read one issue's task runs, but only as the full execution history — every past run, hydrated with attribution and token usage — with no way to ask the one question coordination actually needs: who is working right now. And nothing at all could answer it across a parent's sub-issues, which is the case #7768 describes: several agents claim sibling children in parallel and each starts overlapping work without knowing the others exist. The claim-time `## Active sibling runs` block does not cover this. It is scoped by agent_id — your OWN other in-flight tasks — so a different agent running on a sibling issue is invisible, and it is a snapshot taken before the turn started. Two query params on the existing task-runs endpoint, and the flags that drive them: multica issue runs <id> --active # in-flight runs on this issue multica issue runs <id> --siblings # ...and across the sub-issue family `--siblings` roots at the issue's parent, or at the issue itself when it has none. One rule covers both directions: a child sees its siblings, a parent sees its children, a standalone issue degenerates to its own active runs — so a caller does not have to know an issue's shape before choosing a flag. Rows carry the issue they belong to, ordered running-first and bounded, because a parent that fanned out hundreds of children must not turn an advisory read into an unbounded response. Both reads are advisory. Nothing here reserves an issue or serialises anything; they tell a run whom to coordinate with, and coordination still happens in comments. With neither param the response is byte-identical to before, which the issue-detail execution log and the CLI's short-task-ID resolver both depend on. Co-authored-by: multica-agent <[email protected]> * fix(cli): address review on active/sibling run reads Four fixes from review, all on the same theme: a coordination read has to be cheap and has to be honest about what it did not tell you. - `--active` no longer hydrates usage. ListIssueTaskUsage returns a row per (task, provider, model) for every task the issue ever ran, so the active path was still paying the full-history cost the filter exists to remove — for a column that is near-empty on runs that have not finished. The execution log keeps it. - An invalid `active` value is a 400 instead of a silent fallback. `active=tru` used to answer "who is here now?" with the whole history under a 200, and a pile of finished runs reads as the live ones. Same reason the unknown-scope check already existed, same shape as the comment-list boolean params. - The 50-row family cap now announces itself. The query asks for one row past the cap and sets X-Active-Runs-Truncated when it comes back; the CLI warns on stderr. Without it, "the answer was cut off" and "no run on that sibling" are the same response, and an agent reads the second. The cap is also documented in the flag help, the skill and CLI_AND_DAEMON.md, along with the ordering it depends on. - The skill's new agent-facing contract is pinned in builtin_skills_test.go: that the claim-time block is same-agent only, the `--siblings` command itself, the cap disclosure, and the advisory/no-lock boundary — the last a negative anchor, because an agent that reads these as a lock skips the coordination they exist to prompt. Also reuses service.IssueIdentifier instead of re-deriving the format. Co-authored-by: multica-agent <[email protected]> * fix(server): expose the truncation header to CORS, correct the cap rationale Both from re-review, and both about the cap telling the truth. - HeaderActiveRunsTruncated was missing from corsExposedHeaders. No browser client requests scope=family today, so nothing is broken right now — but a custom response header that is not exposed is unreadable from JS, which is the exact silent-truncation failure the header was added to remove. The registry and its guard test exist because this drifted once already (MUL-5492); completing both is two lines. - The comment justifying 50 was wrong. It claimed real family concurrency is bounded far below the cap so 50 sits above any legitimate answer. It does not: agentconfig.MaxMaxConcurrentTasks lets ONE agent run 50 concurrent tasks, this feature exists for the case where several agents work a family at once, and the returned set includes queued / dispatched / waiting rows that no execution slot bounds at all — a parent that fans out 200 children can have 200 enqueued. So 50 is a response-size budget and nothing more, truncation is an ordinary outcome rather than a pathological one, and that is precisely why it has to be reported. Comment and PR body now say that. Co-authored-by: multica-agent <[email protected]> * refactor(cli): give the family read its own compact row, cap at 20 The family read was reusing AgentTaskResponse — the execution log's row. Measured against real data that is ~1645 bytes per run, of which the caller reads almost nothing: attribution (625 bytes, and its own extra query), result, work_dir, relative_work_dir, trigger_summary, coalesced comment ids. An agent asking "is anyone working next to me?" was spending ~20k tokens of its own context on the answer. ActiveRunSummary carries what the question needs and nothing else: task, issue, agent, status, and timestamps. 367 bytes per row. It is a separate type on purpose — not AgentTaskResponse, and not ActiveSiblingRunData (the claim payload's row, which has no agent field because those runs all belong to the claiming agent by construction). Reusing either would mean an optional field only one caller ever sets, which is the shape this commit removes from AgentTaskResponse. The query now names its columns instead of embedding the task row, so Postgres stops detoasting the JSONB blobs too, and the handler drops attribution hydration along with the field. Cap goes 50 -> 20 (maintainer call): a handful of runs is the normal case, so the budget is set to the normal case. Truncation was already reported and still is, which is what makes a small cap safe. Worst-case response: 80 KB / ~20k tokens -> 7 KB / ~1.8k tokens. The CLI's family table drops COMPLETED and ERROR, which are empty on every row of a read that only returns work still in flight. Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: J <[email protected]> Co-authored-by: multica-agent <[email protected]>