@qilin-agent/experimental-agent-team 3.1.5 → 3.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -3,77 +3,77 @@
3
3
  # After editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/experimental/agent-team/README.md
5
5
  /:
6
- en: 6dbca19f6b32549f
7
- zh: dae9c49eab8f6fee
6
+ en: 8b11ad84b831ec01
7
+ zh: 01acc9f40e64b8d4
8
8
  /qilin-agent-experimental-agent-team:
9
9
  en: 4402b42eb6f211c1
10
10
  zh: 8ac92563ac79d88a
11
11
  /qilin-agent-experimental-agent-team/summary:
12
- en: 287cc2a4386252f2
13
- zh: 25729a2ac8565d15
12
+ en: 93089ec3250c740b
13
+ zh: ac1f8c50602fd5ef
14
14
  /qilin-agent-experimental-agent-team/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /qilin-agent-experimental-agent-team/use-this-package:
18
- en: dd1424b30f3cfb4e
19
- zh: 184ef8c784fbb2ca
18
+ en: bf566e925ea847da
19
+ zh: 7a88fd5fbc13bf14
20
20
  /qilin-agent-experimental-agent-team/use-this-package/when-to-choose-it:
21
- en: 8da318ac2f4343d7
22
- zh: b31a399d6e3fd64e
21
+ en: fc789f82c1b86394
22
+ zh: c6dff674d537dc26
23
23
  /qilin-agent-experimental-agent-team/use-this-package/smallest-working-setup:
24
24
  en: 067776ea2c4f9776
25
25
  zh: 4a73fe617591dd61
26
26
  /qilin-agent-experimental-agent-team/use-this-package/teammates:
27
- en: 93bba70f00d8015a
28
- zh: b66c4c2b1a91facf
27
+ en: 5a314d1f80ecd31b
28
+ zh: c34e6a93dd1e2045
29
29
  /qilin-agent-experimental-agent-team/use-this-package/messages-between-teammates:
30
- en: 14ae48980c5e7fd0
31
- zh: dc40cb0c15789d14
30
+ en: 3f98b1feabc09b11
31
+ zh: c83ad4de36021fb5
32
32
  /qilin-agent-experimental-agent-team/use-this-package/shared-task-board:
33
33
  en: 73682f0d2001b517
34
34
  zh: 3744d82eb3b7fcb9
35
35
  /qilin-agent-experimental-agent-team/use-this-package/waiting-and-interruption:
36
- en: 42c6d6e7175a930f
37
- zh: eb077879ea52bd97
36
+ en: f8e38ccf6295b375
37
+ zh: 44f008e23613c0af
38
38
  /qilin-agent-experimental-agent-team/use-this-package/what-success-and-failure-look-like:
39
- en: a14116e6ef3b90fc
40
- zh: 9b1984cfcb4501d6
39
+ en: cfcb985f5628e427
40
+ zh: a455c63b9813a06f
41
41
  /qilin-agent-experimental-agent-team/understand-the-implementation:
42
42
  en: 6a18034f1ccc247a
43
43
  zh: e08b0eb0ccb41ea8
44
44
  /qilin-agent-experimental-agent-team/understand-the-implementation/design-philosophy:
45
- en: 5ed15e91ee5575cb
46
- zh: e34618a49056b439
45
+ en: 0b6c6a1f5e069abb
46
+ zh: 0cdca2d88bd25993
47
47
  /qilin-agent-experimental-agent-team/understand-the-implementation/source-map:
48
48
  en: b4617379acb1800c
49
- zh: d0b2846a7117cdbd
49
+ zh: bdb67fae4e5b4c53
50
50
  /qilin-agent-experimental-agent-team/understand-the-implementation/team-identity-and-roster:
51
- en: 85f97723e45e43de
52
- zh: def66721e21339cc
53
- /qilin-agent-experimental-agent-team/understand-the-implementation/direct-steering:
54
- en: bc66f052a2290fe1
55
- zh: 2deb7e0847349f3c
51
+ en: 2389048c1a494ed3
52
+ zh: 7e72acd6b83ea248
53
+ /qilin-agent-experimental-agent-team/understand-the-implementation/direct-messages-and-historical-compatibility:
54
+ en: 60d5c54d032ec106
55
+ zh: efdf8a7dcd4e8e1e
56
56
  /qilin-agent-experimental-agent-team/understand-the-implementation/shared-task-board:
57
57
  en: 2dc37ba97a8a7178
58
58
  zh: 96bd24033030e19d
59
59
  /qilin-agent-experimental-agent-team/understand-the-implementation/waiting-and-interruption:
60
- en: 94e09c51cec44b0c
61
- zh: dbbead1b8de96a3a
60
+ en: 29eebf85f25d8d8b
61
+ zh: 6976a482f65b4989
62
62
  /qilin-agent-experimental-agent-team/understand-the-implementation/durability-model:
63
- en: 40cdf38b158a6a99
64
- zh: 78b6a0a9cf9dda25
63
+ en: 16e982658c04aa80
64
+ zh: 3c75e95bb6d7b8bd
65
65
  /qilin-agent-experimental-agent-team/understand-the-implementation/disposal:
66
- en: 47588f975c83fe96
67
- zh: fd25c61a7dcc9b01
66
+ en: a12fb358183cc6d8
67
+ zh: 7fdb0434d3c407fe
68
68
  /qilin-agent-experimental-agent-team/further-exploration:
69
- en: 7bf1185e46e3afc7
70
- zh: 99ffb9a0e8997b2f
69
+ en: a74b13081f4198df
70
+ zh: 364d6ac92f0380c0
71
71
  /qilin-agent-experimental-agent-team/further-exploration/browser-projection:
72
- en: 96186095e80f835f
73
- zh: 2f6d699872a07730
72
+ en: 33ad8d459cf2ba34
73
+ zh: f5c9b92a5ccbb52a
74
74
  /qilin-agent-experimental-agent-team/further-exploration/browser-write-bridge:
75
- en: af8b1417a9566469
76
- zh: b9ddc7d585d34be5
75
+ en: 0b80f4c679480592
76
+ zh: 85725998a7d68604
77
77
  /qilin-agent-experimental-agent-team/model-experience:
78
78
  en: 215e7ba838619b7b
79
79
  zh: a311da3843709f90
@@ -81,17 +81,17 @@
81
81
  en: 7a72088145dd45ec
82
82
  zh: 6763071c604c2edd
83
83
  /qilin-agent-experimental-agent-team/model-experience/peer-messages/what-the-model-sees:
84
- en: 4f9110ba058f25cd
85
- zh: cf820293929ea993
84
+ en: 03d122c94d97375c
85
+ zh: e05915f33dedbdc1
86
86
  /qilin-agent-experimental-agent-team/model-experience/peer-messages/token-effect:
87
- en: deacf0f9e654cff5
88
- zh: 2a30a685b2e3a04f
87
+ en: 9e0eca38b2fc9327
88
+ zh: 99462fd765390ed6
89
89
  /qilin-agent-experimental-agent-team/model-experience/peer-messages/kv-cache-effect:
90
- en: ff845d434b857afe
91
- zh: 04479bddf7650ede
90
+ en: af2993419835b838
91
+ zh: b2a4fea055d5cdf4
92
92
  /qilin-agent-experimental-agent-team/known-limitations-and-deferred-work:
93
- en: 016afbeb35dd7448
94
- zh: 909b7ae6796314b0
93
+ en: 2b6bbe3e4242d932
94
+ zh: c1b33474c62f9674
95
95
  /qilin-agent-experimental-agent-team/known-limitations-and-deferred-work/dev-note:
96
96
  en: 498e4cf9fe5741a7
97
97
  zh: 9d2bab630e655c99
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Run a small team of named agents in one session: durable messages between members and a shared task board, for deployments composing the experimental Team plugins."
2
+ description: "Run named teammates with direct inbox messages and a durable shared task board in experimental Team compositions."
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- `qilin-experimental-agent-team` turns one coding session into a small working team: the session's agent becomes the Lead, creates named teammates for delegated work, exchanges durable messages with them, and tracks shared tasks on a common board. Messages and task state survive crashes, reloads, and interruptions: a message steered at an offline teammate cold-resumes it. It provides no tools of its own — mount the sibling `qilin-experimental-tool-agent-team` so the model can create teammates, message them, and use the task board. It is published under its experimental name, carries no stability promise, and needs durable session storage to activate.
12
+ `qilin-experimental-agent-team` gives one session a Lead, named teammates, direct messages, and a durable shared task board. Sends use each target Agent’s inbox and can cold-resume stored teammates. Team retains roster and task state; message persistence follows the target Agent’s normal policy. Mount `qilin-experimental-tool-agent-team` for model tools. The package is experimental and requires durable session storage.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -25,11 +25,11 @@ English | [中文](README.zh.md)
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
- Add this package to a composition when one agent should run a small team of named helpers in its own working directory, with messages and task state that survive crashes and restarts. It ships no tools of its own: mount it together with `@qilin-agent/experimental-tool-agent-team` so the model can create teammates, message them, and use the task board.
28
+ Add this package when one agent needs named helpers in a shared working directory, direct peer messages, and durable roster and task state. Mount it with `@qilin-agent/experimental-tool-agent-team` to expose the model tools.
29
29
 
30
30
  ### When to choose it
31
31
 
32
- Choose it when several agents must cooperate on one shared workspace and their roster, messages, and task state must survive crashes and restarts. Avoid it when teammates need separate working directories, when several processes must coordinate over one team, or when a task owner should be released automatically — none of those are supported. The team features need durable session storage to activate.
32
+ Choose it for cooperation in one shared workspace with durable roster and task state. Separate working directories, coordination across processes, and automatic task-owner release are unsupported. Durable session storage is required.
33
33
 
34
34
  ### Smallest working setup
35
35
 
@@ -59,15 +59,15 @@ The generated [configuration catalog](../../../docs/config-catalog.md#qilin-agen
59
59
 
60
60
  Ask the Lead to create a teammate: give it a unique lowercase name such as `reviewer` and describe its job. A teammate starts fresh with no memory of the Lead's conversation, or as a fork that inherits the Lead's completed turns; the creation request chooses which. Teammate names are permanent — even a teammate whose creation failed keeps its name, and no name is ever reused.
61
61
 
62
- The roster shows every member with its role (`lead` or `teammate`) and current status: `running`, `idle`, `inactive` (a member that exists but is not loaded), `provisioning`, or `failed`. A member that is not loaded receives its messages when it wakes.
62
+ The roster shows every member with its role (`lead` or `teammate`) and current status: `running`, `inactive` (no turn is executing, whether loaded or stored), `provisioning`, or `failed`. A member that is not loaded receives its messages when it wakes.
63
63
 
64
64
  Only the Lead can create teammates or interrupt them.
65
65
 
66
66
  ### Messages between teammates
67
67
 
68
- Any member can send a message to any other member or to the Lead. A live member receives it at its next step boundary; an idle or inactive member is started or cold-resumed so the message still arrives. The message becomes durable in the target's own Session log, so it survives a crash between delivery and model processing.
68
+ Any member can send to another member or the Lead. Each attempt either returns the Team message identity carried by the accepted delivery source or throws. Team does not retain unaccepted send intent, retry new messages after restart, or deduplicate explicit resends.
69
69
 
70
- Every message uses Steer: a running target receives it at the nearest step boundary, an idle target starts a turn, and an inactive teammate cold-resumes. The sender either sees the accepted message id or one specific rejection: an unknown target name, a self-addressed message, an oversized message, or cancellation before acceptance. A successful send is already durable, so it must never be resent.
70
+ Steer gives a running target the message at its nearest step boundary and starts or cold-resumes an inactive target. Success means inbox acceptance, not model processing or a separate synchronous storage flush. Accepted messages follow ordinary Agent persistence and inbox recovery.
71
71
 
72
72
  ### Shared task board
73
73
 
@@ -81,11 +81,11 @@ File hints produce warnings when two in-progress tasks plan to touch overlapping
81
81
 
82
82
  A member can wait for the next team change — a teammate's status, an incoming message, or a task update — instead of polling repeatedly; the wait reports only whether it timed out, and the caller re-reads the current state afterward.
83
83
 
84
- The Lead can stop a teammate's current turn without deleting messages already in its inbox; task ownership is unchanged.
84
+ The Lead can stop a teammate's current turn without deleting its queued messages; task ownership is unchanged.
85
85
 
86
86
  ### What success and failure look like
87
87
 
88
- Success looks like a teammate appearing in the roster, a message reporting its accepted id, and task revisions advancing with each change. Likely failures are reported as specific errors instead of silently corrupting state: sending to a name that is not a member, claiming a task that is not ready, editing with an outdated revision, or creating a teammate beyond the member limit.
88
+ Success returns a teammate roster row, an accepted Team message id, or an updated task revision. Invalid member names, unready tasks, stale revisions, exhausted limits, and failed message admission report errors.
89
89
 
90
90
  -----
91
91
 
@@ -101,12 +101,12 @@ This section explains the design decisions behind the service and points at the
101
101
 
102
102
  The service is built on one separation and three commitments:
103
103
 
104
- - **Durable log, derived state.** The Lead Session log is the single source of truth; roster, message, and task state are replayed from it on every read.
105
- - **Process-local ownership.** All coordination lives in one process; the guarantee is retry plus de-duplication, never cross-process consensus.
104
+ - **Durable log, derived state.** The Lead log owns roster and tasks; each target Agent owns its accepted messages.
105
+ - **Process-local ownership.** Continuation delivery owns target locking, cold recovery, and lifecycle authorization.
106
106
  - **Explicit authority.** Every service method takes the exact live calling `Agent`; only the Lead spawns, reassigns, or interrupts.
107
107
  - **Bounds that fail loud.** Every limit is a validated deployment value, and exhaustion reports a typed error instead of reusing an id or name.
108
108
 
109
- The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) owns the identity, mailbox, task, and shared-checkout decisions.
109
+ The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) owns the roster, mailbox, task, and shared-checkout decisions. Model-facing identity is a required runtime-context contribution from the [tool package](../tool-agent-team/README.md).
110
110
 
111
111
  ### Source map
112
112
 
@@ -124,13 +124,13 @@ The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-
124
124
 
125
125
  ### Team identity and roster
126
126
 
127
- Every ordinary runtime root is the implicit Lead of a Team whose `TeamId` equals its `SessionId`; there is no creation event, and durable state begins with the first member, message, or task record. `spawnTeammate()` first appends and flushes a `provisioning` member record, then asks the configured provider to create the reserved child; a provider failure appends a durable `failed` member. A fresh child starts with no Lead history; a fork child captures the Lead's completed-turn prefix once. Recovery reconciles an unterminated provisioning record against the child's independently persisted Session: a matching direct-parent and continuable descriptor plus a recorded initial user message produces `active`, and anything else produces `failed`. If recovery wins a same-process race, the creator accepts the terminal state or reports `TEAM_PROVISIONING_CONFLICT` and drains the child. Names are reserved by the first provisioning record and never reused.
127
+ Every ordinary runtime root is the implicit Lead of a Team whose `TeamId` equals its `SessionId`; there is no creation event, and durable Team state begins with the first member or task record. `spawnTeammate()` first appends and flushes a `provisioning` member record, then asks the configured provider to create the reserved child; a provider failure appends a durable `failed` member. A fresh child starts with no Lead history; a fork child captures the Lead's completed-turn prefix once. Recovery reconciles an unterminated provisioning record against the child's independently persisted Session: a matching direct-parent and continuable descriptor plus a recorded initial user message produces `active`, and anything else produces `failed`. If recovery wins a same-process race, the creator accepts the terminal state or reports `TEAM_PROVISIONING_CONFLICT` and drains the child. Names are reserved by the first provisioning record and never reused.
128
128
 
129
- ### Direct steering
129
+ ### Direct messages and historical compatibility
130
130
 
131
- `sendMessage()` validates peer membership, resolves the target, mints the message identity, and measures the framed content against `maxMessageBytes` before anything is delivered. The target message begins with `Team message <id> from <name>:` and keeps the same id and sender in `TeamMessageSource`, so the receiving model and the durable log agree on the sender's identity. Lead delivery calls `Agent.steer()` directly; teammate delivery uses the continuation owner's host-only Steer path, which authorizes the Lead-to-child edge and cold-resumes inactive targets. A send that cannot be admitted fails with its own error instead of being retained, so the sender never has to reason about a retry queue.
131
+ `sendMessage()` checks exact caller membership, rejects self-messaging, and bounds the complete sender-framed UTF-8 content. It mints one `TeamMessageId`, returns it after acceptance, and emits Team activity only after acceptance. The target stores `team-message` source carrying that id, the Team id, and the sender's identity; the first content block is `Team message <id> from <name>:`. No new `team/message/queued` or `team/message/delivered` records are written for these sends. Team adds no per-target send ordering; delivery order belongs to the target inbox. The Web client presents these messages with the Team title and icon.
132
132
 
133
- Sibling messages never impersonate the Lead through the public adjacent-Agent messaging operation.
133
+ Lead delivery calls `Agent.steer()` directly. Teammate delivery uses the continuation owner's host-only Steer path, which preserves the Team sender source while authorizing the Lead-to-child edge and cold-resuming inactive targets. Sibling messages never impersonate the Lead through the public adjacent-Agent messaging operation.
134
134
 
135
135
  ### Shared task board
136
136
 
@@ -138,15 +138,19 @@ Tasks are complete versioned snapshots; every mutation carries `expectedRevision
138
138
 
139
139
  ### Waiting and interruption
140
140
 
141
- `waitForChange()` waits for one roster, task, message, or live-status edge that occurs after registration, from ten seconds through one hour, and reports only whether it timed out; runtime disposal releases current waits. Cancellation preserves an Error reason or reports a non-Error reason through `TEAM_WAIT_ABORTED`. `interrupt()` is Lead-only and delegates to the continuable-subagent interrupt path, which cancels only a live teammate's current turn with `keepInbox`; it neither releases task ownership nor deletes durable mail.
141
+ `waitForChange()` waits for one roster, task, message-acceptance, or live-status edge that occurs after registration, from ten seconds through one hour, and reports only whether it timed out; runtime disposal releases current waits. Cancellation preserves an Error reason or reports a non-Error reason through `TEAM_WAIT_ABORTED`. `interrupt()` is Lead-only and delegates to the continuable-subagent interrupt path, which cancels only a live teammate's current turn with `keepInbox`; it neither releases task ownership nor deletes durable mail.
142
142
 
143
143
  ### Durability model
144
144
 
145
- Team events are appended to the exact live Lead Session and flushed before the operation reports success or wakes waiters. `team/member` and `team/task` are log-only, and the historical `team/message/queued` and `team/message/delivered` records stay readable: none of them enters the conversation surface, so derived model history is untouched by coordination records. Session event `seq` and `time` own ordering and timing; snapshots do not duplicate them.
145
+ Roster and task mutations append `team/member` and `team/task` to the exact live Lead Session and flush before reporting success or waking waiters. Historical `team/message/queued` and `team/message/delivered` records remain readable; Team writes neither. All four event types are log-only: they never enter the conversation surface, so derived model history is untouched by coordination records. Session event `seq` and `time` own ordering and timing; snapshots do not duplicate them.
146
+
147
+ Historical mailbox events remain readable, and `team-message` sources attribute both new peer deliveries and historical ones. The projection still reports queued-minus-delivered records, but Team never delivers or acknowledges them: a historical message that its target had not recorded stays undelivered.
148
+
149
+ Mailbox projection and checkpoint admission preserve every decoded JSON field of accepted content outside the locally declared validators, including an own `__proto__` key. Local field checks cover `text`, `reasoning`, `image`, and `tool-call`; accepted unknown tags remain opaque. Team projection cache version 4 rebuilds checkpoints from earlier cache versions from the Session log; the Session format version is unchanged.
146
150
 
147
151
  ### Disposal
148
152
 
149
- Disposal closes admission, aborts and awaits admitted send and creation transactions, then asks the continuation owner to release the roster's exact live direct children and their descendants; non-Team continuable children of the Lead remain untouched. Cleanup failures make disposal fail visibly, bounded by `disposalTimeoutMs`.
153
+ The runtime lifecycle tracks sends and complete creation transactions in one operation set. Disposal closes admission, aborts and awaits those operations, then releases the roster’s live children and descendants. Non-Team children remain untouched. Admitted operations share one `disposalTimeoutMs` settlement deadline; each subsequent Team child drain has its own deadline. This value is not a whole-service shutdown bound. Cleanup failures are reported.
150
154
 
151
155
  </details>
152
156
 
@@ -159,8 +163,8 @@ Read these pages when the package-level contract is not enough. They move from t
159
163
 
160
164
  - [Agent Teams subsystem](../../../docs/subsystems/agent-team.md) — durable Team types and the `ctx.agentTeams` service API.
161
165
  - [tool-agent-team package](../tool-agent-team/README.md) — the tools that let the model create, message, and coordinate teammates.
162
- - [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) — identity, mailbox, task, and shared-checkout decisions.
163
- - [Experimental package decision](../../../.agents/notes/implemented/architecture/2026-08-18-experimental-agent-teams-packages.md) — placement, publication, and dependency isolation.
166
+ - [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) — roster, mailbox, task, and shared-checkout decisions.
167
+ - [Experimental package reference](../AGENTS.md) — placement, publication, and dependency isolation.
164
168
 
165
169
  -----
166
170
 
@@ -170,11 +174,11 @@ Read these pages when the package-level contract is not enough. They move from t
170
174
 
171
175
  The `agentTeam` Session projection publishes the Lead Session's durable roster identities and phases, member errors, non-deleted task views, and any `failure` beside the last valid state. Its `apply` replaces only the touched collection; mailbox-only changes retain the client view reference and produce no frame. The [subsystem reference](../../../docs/subsystems/agent-team.md#web-projection) defines the wire types.
172
176
 
173
- The [Web UI](../client-ui-agent-team/README.md) reads the shared Session projections and overlays activity from Session status. The `./client` export supplies browser-safe roster, task, and projection types.
177
+ The [Web UI](../client-ui-agent-team/README.md) reads the shared Session projections and overlays activity from Session status. Task creation and updates travel through both the service and model tools and the browser write bridge below. The `./client` export supplies browser-safe roster, task, and projection types.
174
178
 
175
179
  ### Browser write bridge
176
180
 
177
- The service exposes two wire methods on the `agentTeams` Typert namespace — `createTask` and `updateTask` — the direct wire face of the same-named service operations. `updateTask` carries every board mutation the browser offers as a typed action: `edit`, `complete`, `reopen`, `delete`, `reassign`, and `set_dependencies`. The wire caller is the exact live conversation agent; because the Web conversation prompt path runs as the Lead, the browser always writes with Lead authority, and a teammate conversation resolves its writes to the Lead before calling. Domain refusals map onto the shared Remote vocabulary through `src/remote.ts`: `TEAM_TASK_STALE_REVISION` becomes `agent-team/stale-revision`, a non-member caller becomes `agent-team/not-a-member`, and every other Team error becomes `agent-team/rejected` carrying the originating Team code in its details. The same file augments `RemoteErrorDetailsMap` with the Team codes so browser consumers branch on them type-safely. Read paths stay on the `agentTeam` projection; the bridge adds no model-visible input.
181
+ The service exposes two wire methods on the `agentTeams` Typert namespace — `createTask` and `updateTask` — the direct wire face of the same-named service operations. `updateTask` carries every board mutation the browser offers as a typed action: `edit`, `complete`, `reopen`, `delete`, `reassign`, and `set_dependencies`. The wire caller is the exact live conversation agent; because the Web conversation prompt path runs as the Lead, the browser always writes with Lead authority, and a teammate conversation resolves its writes to the Lead before calling. Domain refusals map onto the shared Remote failure vocabulary through `src/remote.ts`: `TEAM_TASK_STALE_REVISION` becomes `agent-team/stale-revision`, a non-member caller becomes `agent-team/not-a-member`, and every other Team error becomes `agent-team/rejected` carrying the originating Team code in its details. The same file augments `RemoteErrorDetailsMap` with the Team codes so browser consumers branch on them type-safely. Read paths stay on the `agentTeam` projection; the bridge adds no model-visible input.
178
182
 
179
183
  ## Model Experience
180
184
 
@@ -182,15 +186,15 @@ The service exposes two wire methods on the `agentTeams` Typert namespace — `c
182
186
 
183
187
  #### What the model sees
184
188
 
185
- Each delivered peer message is a user-role message. A short first text block names its stable message id and sender; the sender's original content blocks follow unchanged. Roster, task, and mailbox records are log-only and never enter derived model history.
189
+ Each peer message is a user-role message whose first text block names the stable Team message id and sender, followed by the original content blocks. Roster, task, and historical mailbox records remain log-only.
186
190
 
187
191
  #### Token effect
188
192
 
189
- Each peer delivery adds the sender prefix plus message content to the target history. Task and roster mutations add no model tokens; their model-facing representation belongs to `@qilin-agent/experimental-tool-agent-team` results.
193
+ Each peer delivery adds the sender prefix plus message content to the target history; the stable id appears in the prefix and in the delivery source. Task and roster mutations add no model tokens; their model-facing representation belongs to `@qilin-agent/experimental-tool-agent-team` results.
190
194
 
191
195
  #### KV Cache effect
192
196
 
193
- Peer messages append after the target's reusable history prefix. Cold resume reuses the persisted conversation before appending a previously undelivered item.
197
+ Peer messages append after the target's reusable history prefix. Cold resume reuses the persisted conversation before appending the new message.
194
198
 
195
199
  ## Known Limitations and Deferred Work
196
200
 
@@ -204,8 +208,8 @@ These limits describe what a team cannot do yet or what needs special operationa
204
208
  - **One process and one shared checkout** — members share cwd and observe edits immediately; this package provides no worktree, remote member, merge, or filesystem lock.
205
209
  - **Advisory write scopes** — Bash, formatters, code generators, and direct external writers can bypass filesystem version checks; Leads must coordinate ownership and review the final diff.
206
210
  - **Flat immutable roster** — only the Lead creates direct teammates; there is no nested Team, rename, deletion, or name reuse.
207
- - **No automatic ownership release** — idle, interruption, process exit, and failed work do not release a task owner.
208
- - **Mailbox is not cross-process exactly-once** — concurrent harness processes over one Team are unsupported.
211
+ - **No automatic ownership release** — inactivity, interruption, process exit, and failed work do not release a task owner.
212
+ - **No send retry guarantee** — Team does not retain or deduplicate new attempts; concurrent processes over one Team are unsupported. Historical queued messages that never reached their target are not delivered.
209
213
 
210
214
  <a id="dev-note"></a>
211
215
  ### Dev Note
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "在一个会话中运行一个小型具名 agent(智能体)团队:成员之间的持久消息与共享任务板,用于组合实验性 Team 插件的部署。"
2
+ description: "在实验性 Team 组合中运行具名 teammate,使用直接 inbox 消息和持久共享任务板。"
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- `qilin-experimental-agent-team` 把一个编码会话变成一个小型工作团队:会话中的 agent 成为 Lead,创建具名 teammate 处理委派的工作,与它们交换持久消息,并在公共任务板上跟踪共享任务。消息与任务状态能挺过崩溃、reload 与中断:发给离线 teammate 的消息会把它冷恢复。它本身不提供任何工具——请挂载兄弟包 `qilin-experimental-tool-agent-team`,让模型能够创建 teammate、给它们发消息并使用任务板。它以实验性名称公开发布、不承诺稳定性,并且需要持久会话存储才能激活。
12
+ `qilin-experimental-agent-team` 为一个会话提供 Lead、具名 teammate、直接消息和持久共享任务板。发送使用目标 agent(智能体)的 inbox,并可冷恢复已存储的 teammate。Team 保留 roster 与任务状态,消息持久化遵循目标 Agent 的常规策略。挂载 `qilin-experimental-tool-agent-team` 可提供模型工具。本包为实验性功能,需要持久会话存储。
13
13
 
14
14
  ## 目录
15
15
 
@@ -25,11 +25,11 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 当一个 agent 应该在自己的工作目录中运行一支小型具名助手团队、且消息与任务状态需要挺过崩溃与重启时,把本包加入组合。它本身不带工具:请与 `@qilin-agent/experimental-tool-agent-team` 一起挂载,让模型能够创建 teammate、给它们发消息并使用任务板。
28
+ 当一个 agent 需要共享工作目录中的具名助手、直接 peer 消息以及持久 roster 与任务状态时,加入本包。与 `@qilin-agent/experimental-tool-agent-team` 一起挂载可提供模型工具。
29
29
 
30
30
  ### 何时选择
31
31
 
32
- 当多个 agent 必须在同一个共享工作区协作、且 roster、消息与任务状态需要挺过崩溃与重启时,选择它。当 teammate 需要独立工作目录、多个进程需要协调同一支团队、或任务 owner 需要自动释放时,请不要选择——这些都不受支持。团队功能需要持久会话存储才能激活。
32
+ 适用于在同一共享工作区协作并保留持久 roster 和任务状态。不支持独立工作目录、跨进程协调和自动释放任务 owner。需要持久会话存储。
33
33
 
34
34
  ### 最小工作配置
35
35
 
@@ -59,15 +59,15 @@ kind: "package-reference"
59
59
 
60
60
  请 Lead 创建 teammate:给它一个唯一的小写名字(例如 `reviewer`)并描述其职责。teammate 可以 fresh 启动(不携带 Lead 对话的任何记忆),也可以作为 fork 启动(继承 Lead 已完成的轮次);创建请求决定用哪种。teammate 名字是永久的——即使创建失败的 teammate 也保留其名字,任何名字都不会被复用。
61
61
 
62
- roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`running`、`idle`、`inactive`(存在但未加载的成员)、`provisioning` 或 `failed`。未加载的成员会在唤醒后收到其消息。
62
+ roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`running`、`inactive`(当前没有执行轮次,包括已加载和仅存储的成员)、`provisioning` 或 `failed`。未加载的成员会在唤醒后收到其消息。
63
63
 
64
64
  只有 Lead 可以创建 teammate 或中断它们。
65
65
 
66
66
  ### teammate 之间的消息
67
67
 
68
- 任何成员都可以向任何其他成员或 Lead 发送消息。live 成员会在下一个步骤边界收到;idle 或离线的成员会被启动或冷恢复,消息照常到达。消息落地在目标自己的会话日志里,因此在投递与模型处理之间发生崩溃也不会丢失。
68
+ 任何成员都可向其他成员或 Lead 发送消息。每次尝试要么返回获准投递 source 所携带的 Team 消息身份,要么抛出错误。Team 不保留尚未接收的发送意图,不在重启后重试新消息,也不对显式重发去重。
69
69
 
70
- 每条消息都使用 Steer:running target 在最近的步骤边界收到消息,idle target 启动一个轮次,inactive teammate 则冷恢复。发送方要么拿到已接受的消息 id,要么拿到一个明确的拒绝:目标名不存在、给自己发消息、消息超出字节上限,或在接受前被取消。发送成功即已落库,因此绝不能重发。
70
+ Steer 让 running target 在最近的步骤边界接收消息,并启动或冷恢复 inactive target。成功表示 inbox 接收,不表示模型已处理或已完成单独的同步存储 flush。获准消息遵循普通 Agent 的持久化和 inbox 恢复策略。
71
71
 
72
72
  ### 共享任务板
73
73
 
@@ -81,11 +81,11 @@ roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`
81
81
 
82
82
  成员可以等待下一次团队变化——teammate 的状态、新消息或任务更新——而不必反复轮询;等待只报告是否超时,调用方随后重新读取当前状态。
83
83
 
84
- Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有的消息;任务归属不变。
84
+ Lead 可以停止 teammate 的当前轮次,而不会删除其排队的消息;任务归属不变。
85
85
 
86
86
  ### 成功与失败的表现
87
87
 
88
- 成功的表现是:teammate 出现在 roster 中、消息报告其被接受的 id、任务 revision 随每次变更递增。可能的失败会以具体错误报告,而不会悄悄破坏状态:发给不存在的成员名字、claim 尚未就绪的任务、用过期 revision 编辑、或超出成员上限创建 teammate。
88
+ 成功会返回 teammate roster 行、获准的 Team 消息 id 或更新后的任务 revision。无效成员名称、未就绪任务、过期 revision、上限耗尽和消息准入失败均报告错误。
89
89
 
90
90
  -----
91
91
 
@@ -101,12 +101,12 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
101
101
 
102
102
  本服务建立在一个分离与三项承诺之上:
103
103
 
104
- - **持久日志,派生状态。** Lead 会话日志是唯一真源;roster、消息与任务状态每次读取都从中回放。
105
- - **进程内归属。** 所有协作都位于单一进程;保证是重试加去重,绝不是跨进程共识。
104
+ - **持久日志,派生状态。** Lead 日志拥有 roster 与任务,各目标 Agent 拥有其接收的消息。
105
+ - **进程内归属。** Continuation 投递拥有目标锁、冷恢复和生命周期授权。
106
106
  - **显式权限。** 每个服务方法都接收确切的实时调用方 `Agent`;只有 Lead 可以 spawn、reassign 或 interrupt。
107
107
  - **超出上限时明确失败。** 每个限制都是经过校验的部署值,耗尽时报告类型化错误,而不是复用 id 或名字。
108
108
 
109
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)负责身份、mailbox、任务与共享 checkout 决策。
109
+ [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)负责 roster、mailbox、任务与共享 checkout 决策。面向模型的身份由 [tool 包](../tool-agent-team/README.zh.md) 以 required runtime context 贡献。
110
110
 
111
111
  ### 源码地图
112
112
 
@@ -117,18 +117,18 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
117
117
  | [`src/task-board.ts`](src/task-board.ts) | 任务 CAS 命令、DAG 校验与派生视图 |
118
118
  | [`src/journal.ts`](src/journal.ts) | 串行化的 Lead 日志事务与提交通知 |
119
119
  | [`src/projection.ts`](src/projection.ts) | 解码并校验 Team 事件、发布 `agentTeam` 客户端视图的严格回放投影 |
120
- | [`src/remote.ts`](src/remote.ts) | 浏览器写入桥 face:wire 错误映射与 `RemoteErrorDetailsMap` 的 Team 扩充 |
120
+ | [`src/remote.ts`](src/remote.ts) | 浏览器写面:wire 错误映射与 `RemoteErrorDetailsMap` 的 Team 扩展 |
121
121
  | [`src/task-view.ts`](src/task-view.ts) | 任务板与客户端视图共用的纯任务派生:就绪状态、owner 名称与写入范围重叠 |
122
122
  | [`src/activity.ts`](src/activity.ts) | 一次性变更等待者与 dispose(资源释放)时的等待解除 |
123
123
  | [`src/lifecycle.ts`](src/lifecycle.ts) | 共享准入截止与有界结算 |
124
124
 
125
125
  ### Team 身份与 roster
126
126
 
127
- 每个普通运行时 root 都是一个隐式 Team 的 Lead,其 `TeamId` 等于 `SessionId`;不存在创建事件,持久状态从第一条成员、消息或任务记录开始。`spawnTeammate()` 先追加并 flush 一条 `provisioning` 成员记录,再要求配置的提供方创建预留 child;提供方失败会追加一条持久的 `failed` 成员。fresh child 不携带 Lead 历史;fork child 只捕获一次 Lead 的已完成 turn 前缀。恢复把未终结的 provisioning 记录对照 child 独立持久化的会话进行对账:直接 parent 与 continuable descriptor 匹配、且初始用户消息已记录则产生 `active`,其他任何情况都产生 `failed`。如果恢复在同进程竞争中先完成,creator 会接受终态,或报告 `TEAM_PROVISIONING_CONFLICT` 并 drain 该 child。名字由第一条 provisioning 记录保留,且永不复用。
127
+ 每个普通运行时 root 都是一个隐式 Team 的 Lead,其 `TeamId` 等于 `SessionId`;不存在创建事件,持久 Team 状态从第一条成员或任务记录开始。`spawnTeammate()` 先追加并 flush 一条 `provisioning` 成员记录,再要求配置的提供方创建预留 child;提供方失败会追加一条持久的 `failed` 成员。fresh child 不携带 Lead 历史;fork child 只捕获一次 Lead 的已完成 turn 前缀。恢复把未终结的 provisioning 记录对照 child 独立持久化的会话进行对账:直接 parent 与 continuable descriptor 匹配、且初始用户消息已记录则产生 `active`,其他任何情况都产生 `failed`。如果恢复在同进程竞争中先完成,creator 会接受终态,或报告 `TEAM_PROVISIONING_CONFLICT` 并 drain 该 child。名字由第一条 provisioning 记录保留,且永不复用。
128
128
 
129
- ### 直接 steering
129
+ ### 直接消息与历史兼容
130
130
 
131
- `sendMessage()` 校验 peer 成员关系、解析目标、铸出消息身份,并在投递任何内容之前按 `maxMessageBytes` 量取封帧后的内容。目标消息以 `Team message <id> from <name>:` 开头,并在 `TeamMessageSource` 中保留同一 id 与发送者,因此接收模型与持久日志对发送者身份的认定一致。发往 Lead 时直接调用 `Agent.steer()`;发往 teammate 时走 continuation owner 的 host-only Steer 路径,它授权 Lead→子代这条边并冷恢复非活跃目标。无法准入的发送以自己的错误失败而不是被保留,因此发送方无需推理重试队列。
131
+ `sendMessage()` 检查确切调用方的成员身份,拒绝自发消息,并限制包含发送者前缀的完整 UTF-8 内容大小。它铸出一个 `TeamMessageId`,在接收后返回该 id,并仅在接收后发出 Team activity。目标保存 `team-message` source,携带该 id、Team id 与发送者身份;首个内容块为 `Team message <id> from <name>:`。这些发送不写入新的 `team/message/queued` 或 `team/message/delivered` 记录。Team 不额外保证同目标发送顺序;投递顺序由目标 inbox 管理。Web 客户端使用 Team 标题和图标展示这些消息。
132
132
 
133
133
  投递给 Lead 时直接调用 `Agent.steer()`。投递给 teammate 时使用 continuation owner 的 host-only Steer 路径;该路径会保留 Team 发送者 source,同时授权 Lead-to-child edge 并冷恢复 inactive target。sibling 消息绝不会通过公开的相邻 Agent 消息操作伪装成 Lead。
134
134
 
@@ -138,15 +138,19 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
138
138
 
139
139
  ### 等待与中断
140
140
 
141
- `waitForChange()` 等待注册之后发生的下一条 roster、task、消息或实时状态边,时长从 10 秒到 1 小时,并且只报告是否超时;运行时 dispose 会释放当前等待。取消会保留 Error reason;非 Error reason 则通过 `TEAM_WAIT_ABORTED` 报告。`interrupt()` 仅限 Lead,委托 continuable-subagent 的 interrupt 路径,以 `keepInbox` 只取消 live teammate 的当前 turn;它既不释放任务 owner,也不删除持久 mail。
141
+ `waitForChange()` 等待注册之后发生的下一条 roster、task、消息接收或实时状态边,时长从 10 秒到 1 小时,并且只报告是否超时;运行时 dispose 会释放当前等待。取消会保留 Error reason;非 Error reason 则通过 `TEAM_WAIT_ABORTED` 报告。`interrupt()` 仅限 Lead,委托 continuable-subagent 的 interrupt 路径,以 `keepInbox` 只取消 live teammate 的当前 turn;它既不释放任务 owner,也不删除持久 mail。
142
142
 
143
143
  ### 持久性模型
144
144
 
145
- Team 事件追加到精确的 live Lead 会话,并在操作报告成功或唤醒等待者之前 flush。`team/member` 与 `team/task` 仅存在于日志,历史的 `team/message/queued` 与 `team/message/delivered` 记录保持可读:它们都不进入会话表面,因此派生模型历史不受协作记录影响。顺序与时间由会话事件的 `seq` 与 `time` 负责,快照不重复保存。
145
+ roster 与任务变更将 `team/member` 和 `team/task` 追加到精确的 live Lead 会话,并在报告成功或唤醒等待者之前 flush。历史 `team/message/queued` 与 `team/message/delivered` 记录仍可读取;Team 不再写入这两种记录。这四种事件仅存在于日志:它们从不进入会话表面,因此派生模型历史不受协作记录影响。顺序与时间由会话事件的 `seq` 与 `time` 负责,快照不重复保存。
146
+
147
+ 历史 mailbox 事件仍可读取;`team-message` source 同时归属新的 peer 投递与历史投递。投影仍报告 queued-minus-delivered 记录,但 Team 不会投递或确认这些记录:目标尚未记录的历史消息保持未投递。
148
+
149
+ Mailbox 投影与 checkpoint 准入保留本地声明的校验器之外获准内容中全部已解码 JSON 字段,包括自有 `__proto__` 键。本地字段检查覆盖 `text`、`reasoning`、`image` 和 `tool-call`;获准的未知标签保持不透明。Team 投影缓存版本 4 从 Session 日志重建较早缓存版本的 checkpoint;Session 格式版本保持不变。
146
150
 
147
151
  ### Dispose
148
152
 
149
- dispose 会关闭准入、中止并等待已获准的发送与创建事务,再让 continuation owner 释放 roster 中确切的 live direct child 及其后代;Lead 的非 Team continuable child 不受影响。cleanup 失败会让 dispose 明确失败,并以 `disposalTimeoutMs` 为上限。
153
+ 运行时生命周期用同一个操作集合跟踪发送和完整创建事务。dispose 关闭准入,中止并等待这些操作,然后释放 roster 中的 live child 及其后代。非 Team child 不受影响。已获准操作共享一个 `disposalTimeoutMs` 等待期限;随后每个 Team 的 child drain 各有独立期限。此值不是整个服务关闭的总时限。清理失败会明确报告。
150
154
 
151
155
  </details>
152
156
 
@@ -159,8 +163,8 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
159
163
 
160
164
  - [Agent Teams 子系统](../../../docs/subsystems/agent-team.zh.md)——持久 Team 类型与 `ctx.agentTeams` 服务 API。
161
165
  - [tool-agent-team 包](../tool-agent-team/README.zh.md)——让模型创建 teammate、向其发送消息并进行协调的工具。
162
- - [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)——身份、mailbox、任务与共享 checkout 决策。
163
- - [实验包决策](../../../.agents/notes/implemented/architecture/2026-08-18-experimental-agent-teams-packages.zh.md)——位置、公开发布与依赖隔离。
166
+ - [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)——roster、mailbox、任务与共享 checkout 决策。
167
+ - [实验包参考](../AGENTS.md)——位置、公开发布与依赖隔离。
164
168
 
165
169
  -----
166
170
 
@@ -170,11 +174,11 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
170
174
 
171
175
  `agentTeam` Session 投影发布 Lead Session 的持久成员身份与阶段、成员错误、未删除任务视图,以及最后有效状态旁的 `failure`。其 `apply` 只替换被触及的集合;仅邮箱的变化保留客户端视图引用,不产生 frame。[子系统参考](../../../docs/subsystems/agent-team.zh.md#web-projection) 定义传输类型。
172
176
 
173
- [Web UI](../client-ui-agent-team/README.zh.md) 读取共享 Session 投影,并从 Session 状态叠加活动信息。`./client` 导出可供浏览器使用的 roster、任务与投影类型。
177
+ [Web UI](../client-ui-agent-team/README.zh.md) 读取共享 Session 投影,并从 Session 状态叠加活动信息。任务创建与更新既可以通过服务和模型工具完成,也可以通过下文的浏览器写面完成。`./client` 导出可供浏览器使用的 roster、任务与投影类型。
174
178
 
175
- ### 浏览器写入桥
179
+ ### 浏览器写面
176
180
 
177
- 服务在 `agentTeams` Typert namespace 上暴露两个 wire 方法——`createTask` 与 `updateTask`——它们是同名服务操作的直接 wire face。`updateTask` 以类型化 action 承载浏览器提供的全部任务板变更:`edit`、`complete`、`reopen`、`delete`、`reassign` 与 `set_dependencies`。wire 调用方是当前活跃的会话 agent;由于 Web 会话提示词路径以 Lead 身份运行,浏览器始终以 Lead 权限写入,teammate 会话会在调用前把写入解析到 Lead。领域拒绝经 `src/remote.ts` 映射到共享 Remote 词汇:`TEAM_TASK_STALE_REVISION` 变为 `agent-team/stale-revision`,非成员调用方变为 `agent-team/not-a-member`,其余 Team 错误变为 `agent-team/rejected` 并在 details 中携带原始 Team code。同一文件还以 Team code 扩充 `RemoteErrorDetailsMap`,让浏览器消费者以类型安全方式分支。读取路径仍走 `agentTeam` 投影;该桥不新增模型可见输入。
181
+ 服务在 `agentTeams` Typert 命名空间上暴露两个 wire 方法——`createTask` 与 `updateTask`——它们与同名服务操作直接对应。`updateTask` 以类型化 action 承载浏览器提供的所有看板变更:`edit`、`complete`、`reopen`、`delete`、`reassign` 与 `set_dependencies`。wire 调用方是确切的实时会话 agent;由于 Web 会话的提示词路径以 Lead 身份运行,浏览器始终以 Lead 权限写入,而 teammate 会话会在调用前把写入解析到 Lead。领域拒绝通过 `src/remote.ts` 映射到共享 Remote 失败词汇:`TEAM_TASK_STALE_REVISION` 变为 `agent-team/stale-revision`,非成员调用方变为 `agent-team/not-a-member`,其他 Team 错误变为 `agent-team/rejected` 并在 details 中携带原始 Team 错误码。同一文件为 `RemoteErrorDetailsMap` 扩展 Team 错误码,使浏览器消费方可以类型安全地分支。读取路径仍走 `agentTeam` 投影;写面不增加模型可见输入。
178
182
 
179
183
  ## 模型体验
180
184
 
@@ -182,15 +186,15 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
182
186
 
183
187
  #### 模型看到什么
184
188
 
185
- 每条已投递 peer 消息都是用户角色消息。第一个短文本块包含稳定消息 id 与发送者,之后原样附加发送者的内容块。roster、task 与 mailbox 记录仅存在于日志,绝不进入派生模型历史。
189
+ 每条 peer 消息都是用户角色消息:首个文本块给出稳定的 Team 消息 id 与发送者,随后是原始内容块。roster、task 和历史 mailbox 记录仍仅存在于日志。
186
190
 
187
191
  #### Token 影响
188
192
 
189
- 每次 peer 投递都会把发送者前缀与消息内容加入 target 历史。任务与 roster 变更不增加模型 token;其面向模型的呈现属于 `@qilin-agent/experimental-tool-agent-team` 结果。
193
+ 每次 peer 投递都会把发送者前缀与消息内容加入 target 历史;稳定 id 同时出现在前缀与投递 source 中。任务与 roster 变更不增加模型 token;其面向模型的呈现属于 `@qilin-agent/experimental-tool-agent-team` 结果。
190
194
 
191
195
  #### KV Cache 影响
192
196
 
193
- Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用持久对话,再追加尚未投递的消息。
197
+ Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用持久对话,再追加新消息。
194
198
 
195
199
  ## 已知限制与延期工作
196
200
 
@@ -204,8 +208,8 @@ Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用
204
208
  - **单进程、共享 checkout**——成员共享 cwd,修改立即可见;本包不提供 worktree、远端成员、merge 或文件锁。
205
209
  - **write scope 仅作提示**——Bash、formatter、代码生成器与直接外部写入可以绕过文件版本检查;Lead 必须协调 owner 并检查最终 diff。
206
210
  - **扁平且不可变的 roster**——只有 Lead 可以创建直接 teammate;不支持嵌套 Team、重命名、删除或名字复用。
207
- - **不会自动释放 owner**——idle、interrupt、进程退出与工作失败都不会释放任务 owner。
208
- - **mailbox 不保证跨进程 exactly-once**——不支持多个 harness 进程并发操作同一 Team。
211
+ - **不会自动释放 owner**——成员不活动、interrupt、进程退出与工作失败都不会释放任务 owner。
212
+ - **无发送重试保证**——Team 不保留新尝试,也不对其去重;不支持多个进程同时操作一个 Team。从未到达目标的历史排队消息不会被投递。
209
213
 
210
214
  <a id="dev-note"></a>
211
215
  ### 开发备注
package/lib/index.js CHANGED
@@ -777,7 +777,7 @@ async function readPersistedSession(persistence, id, signal) {
777
777
  }
778
778
  //#endregion
779
779
  //#region lib/types/session-message.js
780
- /** Durable Session-message acceptance checks shared by provisioning and mailbox recovery. */
780
+ /** Durable Session-message acceptance checks for teammate provisioning. */
781
781
  /** Fold the durable inbox suffix into the messages still awaiting a claim. */
782
782
  function pendingInboxMessages(events) {
783
783
  const inbox = {
@@ -1749,20 +1749,16 @@ let TeamService = (() => {
1749
1749
  tryMembership(agent) {
1750
1750
  return this.roster.tryMembership(agent);
1751
1751
  }
1752
- /** Queue one contained recovery pass after publication has unwound. */
1752
+ /** Queue one contained provisioning reconciliation after publication has unwound. */
1753
1753
  scheduleRecovery(agent) {
1754
1754
  queueMicrotask(() => {
1755
1755
  if (this.lifecycle.disposed) return;
1756
- this.recoverFor(agent).catch((error) => {
1756
+ this.roster.recoverFor(agent, this.lifecycle.signal).catch((error) => {
1757
1757
  if (this.lifecycle.disposed) return;
1758
1758
  this.ctx.logger.warn(`Agent Teams recovery for "${agent.id}" failed: ${errorMessage(error)}`);
1759
1759
  });
1760
1760
  });
1761
1761
  }
1762
- /** Reconcile roster provisioning when one Team member Session starts. */
1763
- async recoverFor(agent) {
1764
- await this.roster.recoverFor(agent, this.lifecycle.signal);
1765
- }
1766
1762
  /** Stop Team-owned live branches and release every waiter before service disposal completes. */
1767
1763
  async disposeRuntime() {
1768
1764
  this.lifecycle.close();