fix(squads): align parent issue status with agent-managed model (MUL-5156) (#5758)

* fix(squads): align parent issue status ownership with agent-managed model

Squad leaders now open assigned parents to in_progress on first dispatch, keep them there while members work, and only move to in_review when overall completion is confirmed—matching ordinary agent status semantics without server auto-flips.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(squads): scope leader parent-status ownership to squad-assigned issues

Review follow-up on the parent-status alignment change. Two boundaries were
left ambiguous, both of which the change's own premise ("don't make the model
resolve a contradiction in the prompt") argues should be closed in-place.

1. Status ownership was granted too widely. The leader briefing is injected on
   every leader path, keyed off is_leader_task — including the MUL-3724 case
   where an issue is assigned to a plain agent and a squad was merely
   @mentioned for help. The unqualified "Own the parent issue status"
   responsibility therefore also reached guest leaders, who could push another
   assignee's in-flight issue to in_review.

   buildSquadLeaderBriefing now takes ownsIssueStatus and selects between two
   variants of responsibility 6: the grant only when the issue's assignee is
   this squad, otherwise an explicit "do NOT change this issue's status".
   Quick-create passes false — no issue exists on that turn. Everything else in
   the protocol (roster, delegation, evaluation) is unchanged for both.

2. The comment-triggered path still contradicted itself. The runtime brief says
   "do not change status unless the comment explicitly asks", and a member's
   delivery comment never asks. Squads that dispatch by @mention create no
   child issues, so no child-done system comment exists to carry the explicit
   ask either — that parent would sit in in_progress indefinitely.
   writeWorkflowComment now names the protocol responsibility as the one
   exception for squad leaders. It is safe to state unconditionally because the
   grant is only present in the instructions when the server decided this squad
   owns the issue; for a guest leader the sentence has nothing to activate.

Tests: two composition tests assemble both halves (server-side briefing +
daemon-side CLAUDE.md) for one real scenario each, since asserting each half
alone is how the original contradiction shipped. Plus execenv coverage that the
carve-out appears only for leaders and the ordinary-agent rule stays absolute.

Docs and the multica-squads skill / source map record the narrower contract.

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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: J <j@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
YikaJ
2026-07-22 20:33:15 +08:00
committed by GitHub
parent dd45f30553
commit fcb370edfd
18 changed files with 487 additions and 42 deletions

View File

@@ -50,7 +50,9 @@ When a non-Backlog issue is assigned to an agent, Multica immediately does the f
1. Enqueues a `queued` `task` with priority inherited from the issue, routed to the runtime where the agent lives.
2. The agent's daemon picks up the `task` on its next poll and transitions it to `dispatched`.
3. The agent starts working and the `task` moves to `running`; on completion it becomes `completed` or `failed`.
4. During execution the agent can change the issue's status, post comments, and edit fields — these actions appear under the agent's identity.
4. During execution the agent is expected to manage the issue's status (typically `todo` → `in_progress`, then `in_review` when it has delivered), post comments, and edit fields — these actions appear under the agent's identity. Task lifecycle and issue status are separate: completing a `task` does not by itself change the issue status.
The same status expectations apply when the assignee is a [squad](/squads): Multica enqueues the **leader**, who should move the parent issue to `in_progress` on the first turn and keep it there while members work. The leader only moves the parent to `in_review` once the overall goal is met — a successful first dispatch is not completion.
**If the agent is offline**, the `task` waits in the queue — **it times out and fails after 5 minutes** with reason `runtime_offline`. For retryable sources (assign, @-mention, chat), Multica automatically re-enqueues it. See [**Tasks**](/tasks) for the full retry rules.

View File

@@ -50,7 +50,9 @@ multica issue assign MUL-42 --unassign
1. 入队一个 `queued` 状态的 `task`,优先级继承自 issue路由到该智能体所在的运行时
2. 该智能体的守护进程下次轮询时把 `task` 领走,状态变成 `dispatched`
3. 智能体开始执行,`task` 转成 `running`;完成后转成 `completed` / `failed`
4. 执行过程中智能体可以改 issue 状态、发评论、改字段——这些动作以智能体的身份出现
4. 执行过程中智能体应按约定管理 issue 状态(通常是 `todo` → `in_progress`,交付后再到 `in_review`)、发评论、改字段——这些动作以智能体的身份出现。`task` 生命周期和 issue 状态是分开的:`task` 完成本身不会自动改 issue 状态
当 assignee 是 [小队](/squads) 时同样的状态约定适用Multica 入队的是**队长**,队长首次接单时应把父 issue 推到 `in_progress`,并在成员干活期间保持该状态。只有整体目标达成后,队长才把父 issue 推到 `in_review`——第一次成功分发不等于完成。
**如果智能体离线**`task` 会在队列里等——**5 分钟没被领走就超时失败**,失败原因 `runtime_offline`。对可重试的来源(分配、@ 提及、对话Multica 会自动重新排队;完整重试规则见 [**执行任务**](/tasks)。

View File

@@ -11,7 +11,7 @@ An issue is a self-contained unit of work in Multica — a bug, a new feature, a
## Assigning an issue to an agent
[Assigning](/assigning-issues) an issue to an agent hands that work over to it. The agent **starts automatically** — executing within seconds, reporting progress in comments, and flipping the status to done when finished. The only difference from handing work to a teammate is that an agent doesn't go offline, doesn't need reminders, and is available 24/7.
[Assigning](/assigning-issues) an issue to an agent hands that work over to it. The agent **starts automatically** — Multica enqueues a `task` within seconds, the agent reports progress in comments, and during the run it is expected to update the issue status (typically `todo` → `in_progress` → `in_review`). The only difference from handing work to a teammate is that an agent doesn't go offline, doesn't need reminders, and is available 24/7.
<Callout type="info">
For agent identity, configuration, and where they run, see [Agents](/agents).
@@ -33,7 +33,7 @@ Multica has seven statuses. **Any status can move directly to any other** — Mu
| `blocked` | Stuck on an external factor |
| `cancelled` | Cancelled |
Once an issue is assigned to an agent, the agent automatically moves the status from `backlog` / `todo` to `in_progress`, then to `done` on completion. You can also change it manually at any time.
Once an issue is assigned to an agent, the agent is expected to move the status from `backlog` / `todo` to `in_progress` when it starts, then to `in_review` when it has delivered the work. Status updates are made by the agent through the Multica CLI during the run — the server does **not** flip issue status when a `task` starts or completes. `done` is usually a human confirmation or an integration (for example a PR with close intent that merges). You can also change status manually at any time.
## Priority

View File

@@ -11,7 +11,7 @@ Issue工作项是 Multica 里一个独立工作的单位——一条 bug
## 把 issue 分配给智能体
把 issue [分配](/assigning-issues) 给某个智能体等于把这项工作交给它。智能体会**自动开工**——在几秒内开始执行、在评论里汇报进展、完成后把状态改到 done。和给同事派活的区别只在于它不下线、不需要你提醒、7×24 可用。
把 issue [分配](/assigning-issues) 给某个智能体等于把这项工作交给它。智能体会**自动开工**——Multica 在几秒内入队一个 `task`,智能体在评论里汇报进展,并在执行过程中按约定更新 issue 状态(通常是 `todo` → `in_progress` → `in_review`。和给同事派活的区别只在于它不下线、不需要你提醒、7×24 可用。
<Callout type="info">
智能体的身份、配置、运行位置详见 [智能体](/agents)。
@@ -33,7 +33,7 @@ Multica 提供七种状态。**任何状态可以直接改到任何状态**—
| `blocked` | 被外部因素卡住 |
| `cancelled` | 已取消 |
把 issue 分配给智能体后,智能体会自动把状态从 `backlog` / `todo` 推到 `in_progress`完成后推到 `done`。你也可以随时手动改。
把 issue 分配给智能体后,智能体开工时应把状态从 `backlog` / `todo` 推到 `in_progress`交付工作后再推到 `in_review`。这些状态变更由智能体在运行中通过 Multica CLI 显式写入——`task` 开始或完成时,服务端**不会**自动改 issue 状态。`done` 通常留给人工确认,或由集成完成(例如带 close intent 的 PR merge。你也可以随时手动改。
## 优先级

View File

@@ -62,9 +62,10 @@ When a non-Backlog issue is assigned to a squad, Multica immediately enqueues a
1. **Leader claims the task.** The agent runtime picks up the task on its next poll, same as any other agent assignment.
2. **Leader is briefed.** On claim, Multica appends three sections to the leader's system prompt — see [What the leader sees on every turn](#what-the-leader-sees-on-every-turn) below.
3. **Leader posts one delegation comment.** The comment `@`-mentions the chosen member(s) using the exact mention markdown from the roster — that mention triggers a new `task` for each mentioned agent.
4. **Leader records its evaluation** via `multica squad activity <issue-id> action --reason "..."`. This writes an entry to the issue's activity timeline so humans can see the leader actually evaluated the trigger.
5. **Leader stops.** The leader does not do the implementation itself. When the delegated member posts back, the leader is re-triggered to read the update and either delegate the next step, escalate, or stay silent.
3. **Leader moves the parent to `in_progress`.** Same agent-managed status contract as a direct agent assignment: the first turn should leave `todo` / leave `backlog`-promoted work as `in_progress`. Dispatching members is not completion — the parent stays `in_progress` while the squad works.
4. **Leader posts one delegation comment.** The comment `@`-mentions the chosen member(s) using the exact mention markdown from the roster — that mention triggers a new `task` for each mentioned agent.
5. **Leader records its evaluation** via `multica squad activity <issue-id> action --reason "..."`. This writes an entry to the issue's activity timeline so humans can see the leader actually evaluated the trigger.
6. **Leader stops.** The leader does not do the implementation itself. When the delegated member posts back — or when a sub-issue / stage barrier closes — the leader is re-triggered to read the update and either delegate the next step, escalate, move the parent to `in_review` once the overall goal is met, or stay silent. `done` is left to a human reviewer or existing integrations (for example a PR with close intent that merges).
If the issue is in **Backlog**, the leader is not triggered — Backlog is a parking lot, same rule as for direct agent assignment.
@@ -72,7 +73,9 @@ If the issue is in **Backlog**, the leader is not triggered — Backlog is a par
On each squad-leader run, three blocks are appended to the leader's instructions:
- **Squad Operating Protocol** — a hard-coded rule set: read the issue, delegate by `@`-mention, be terse (don't restate the issue body — the assignee can read it), record an evaluation every turn, and **stop after dispatching**. This protocol is system-managed and not editable.
- **Squad Operating Protocol** — a hard-coded rule set: read the issue, move the parent to `in_progress` on the first turn, delegate by `@`-mention, be terse (don't restate the issue body — the assignee can read it), record an evaluation every turn, **stop after dispatching**, and only move the parent to `in_review` once the overall goal is met. This protocol is system-managed and not editable.
The status half of that protocol is **scoped to issues actually assigned to this squad**. A leader woken by an `@squad` mention on someone else's issue gets the same roster and delegation rules, but is told explicitly **not** to touch that issue's status — status stays with the issue's own assignee.
- **Squad Roster** — the leader's self-row plus one row per non-archived member. Each row carries the exact mention markdown (`[@Name](mention://agent/<uuid>)` or `[@Name](mention://member/<uuid>)`) the leader should paste — typing a plain `@name` won't trigger anyone.
- **Squad Instructions** — your custom guidance for this squad (set on the squad detail page or via `multica squad update --instructions`). Use this for routing rules ("send DB work to Alice, frontend to Bob"), escalation policies, or anything else the leader needs to know that isn't already in the issue.

View File

@@ -62,9 +62,10 @@ multica squad member add <squad-id> --member-id <agent-or-user-uuid> --type agen
1. **队长领走 task。** 队长所在的 daemon 在下次轮询时把 task 领走,和普通智能体的分配流程一样。
2. **队长拿到 briefing。** 领走的瞬间Multica 会在队长的系统提示后面追加三段内容——详见下文 [队长每次执行看到的内容](#队长每次执行看到的内容)。
3. **队长发一条"派活"评论。** 评论里用 roster 里给好的 mention markdown `@` 选中的成员——这个 `@` 会触发被派的成员入队新 `task`。
4. **队长记录 evaluation** `multica squad activity <issue-id> action --reason "..."`。这一行会写进 issue 的 activity 时间线,方便人类回溯队长确实评估过这一次触发
5. **队长停下。** 派完活,队长**不动手干活**。当被派的成员有回复时,队长会被自动唤醒,决定下一步:继续派活、上抛给人类、还是保持沉默
3. **队长把父 issue 推到 `in_progress`。** 和直接分配给智能体同一套 Agent-managed 状态约定:首次接单应离开 `todo`(或从 backlog 提升后的状态),进入 `in_progress`。分发成员不等于完成——小队干活期间父 issue 保持 `in_progress`。
4. **队长发一条"派活"评论。** 评论里用 roster 里给好的 mention markdown `@` 选中的成员——这个 `@` 会触发被派的成员入队新 `task`
5. **队长记录 evaluation** `multica squad activity <issue-id> action --reason "..."`。这一行会写进 issue 的 activity 时间线,方便人类回溯队长确实评估过这一次触发
6. **队长停下。** 派完活,队长**不动手干活**。当被派的成员有回复——或子 issue / stage 屏障关闭——时,队长会被自动唤醒,决定下一步:继续派活、上抛给人类、在整体目标达成后把父 issue 推到 `in_review`、还是保持沉默。`done` 留给人工确认或既有集成(例如带 close intent 的 PR merge
如果 issue 是 **Backlog** 状态队长不会被触发——Backlog 是停泊场,规则和直接分配给智能体一样。
@@ -72,7 +73,9 @@ multica squad member add <squad-id> --member-id <agent-or-user-uuid> --type agen
每次队长被触发,三段内容会被附加到它的 instructions 上:
- **Squad Operating Protocol小队工作规范** —— 一段硬编码的规则集:读 issue → 用 `@` 派活 → 简洁(**不要**复述 issue 内容,被派的成员自己能读)→ 每次都记 evaluation → **派完就停**。这段是系统管理的,不可编辑。
- **Squad Operating Protocol小队工作规范** —— 一段硬编码的规则集:读 issue → 首次接单把父 issue 推到 `in_progress` → 用 `@` 派活 → 简洁(**不要**复述 issue 内容,被派的成员自己能读)→ 每次都记 evaluation → **派完就停** → 只有整体目标达成后才把父 issue 推到 `in_review`。这段是系统管理的,不可编辑。
其中**状态那一半只对「确实分配给本小队」的 issue 生效**。如果队长是被别人 issue 里的 `@squad` 喊醒的,他照样拿到花名册和派活规则,但会被明确告知**不要碰那个 issue 的状态**——状态仍归该 issue 自己的 assignee。
- **Squad Roster小队花名册** —— 队长自己一行 + 每个未归档成员一行。每一行带上**确切可用**的 mention markdown`[@Name](mention://agent/<uuid>)` 或 `[@Name](mention://member/<uuid>)`)让队长直接复制——纯文本 `@name` 是**不会**触发任何人的。
- **Squad Instructions小队自定义指令** —— 你为这个小队写的私货(在详情页里编辑,或用 `multica squad update --instructions`)。用来写路由规则("DB 相关派给 Alice前端派给 Bob")、上报策略,或者任何 issue 本身不会有的背景。