@ycodium-ai/plugin-team 0.2.3635 → 0.2.3671

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/dist/index.js CHANGED
@@ -9301,12 +9301,31 @@ var remotePrincipalOf = (identity2) => typeof identity2 === "object" && identity
9301
9301
 
9302
9302
  // src/domain/defaultModel.ts
9303
9303
  var isSelectionUnavailable = isTagged("ProviderSelectionError");
9304
- async function resolveModel(ctx, base) {
9305
- const selection = await ctx.providers.selection.resolve({ base }).catch((error) => {
9306
- if (isSelectionUnavailable(error)) return null;
9304
+ var MODEL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
9305
+ "instance-not-found",
9306
+ "instance-unavailable",
9307
+ "model-not-in-catalog"
9308
+ ]);
9309
+ var UNAVAILABLE_MESSAGE_KEYS = {
9310
+ "instance-not-found": "instanceNotFound",
9311
+ "instance-unavailable": "instanceUnavailable",
9312
+ "model-not-in-catalog": "modelNotInCatalog"
9313
+ };
9314
+ var unavailableFrom = (error) => {
9315
+ const reason = Reflect.get(error, "reason");
9316
+ return typeof reason === "string" && MODEL_UNAVAILABLE_REASONS.has(reason) ? { code: "model-unavailable", reason } : { code: "model-unavailable" };
9317
+ };
9318
+ async function resolveModel(ctx, base, named = false) {
9319
+ try {
9320
+ return {
9321
+ selection: await ctx.providers.selection.resolve(
9322
+ named && base !== null ? { base, instanceId: base.instanceId, model: base.model } : { base }
9323
+ )
9324
+ };
9325
+ } catch (error) {
9326
+ if (isSelectionUnavailable(error)) return unavailableFrom(error);
9307
9327
  throw error;
9308
- });
9309
- return selection === null ? { code: "model-unavailable" } : { selection };
9328
+ }
9310
9329
  }
9311
9330
  async function resolveDefaultSelection(ctx, projectId) {
9312
9331
  const project2 = await ctx.projects.get({ projectId });
@@ -9365,6 +9384,9 @@ var en_default = {
9365
9384
  memberNotFound: "There is no member {{memberId}} in this project. List the members with team_roster_overview.",
9366
9385
  memberRemoved: "Member {{memberId}} was removed from the project. Restore them first with team_restore_member.",
9367
9386
  modelUnavailable: "The model chosen for member {{memberId}} is not available on this machine. Check list_providers and list_models, then change it with team_update_member.",
9387
+ instanceNotFound: "The provider instance chosen for member {{memberId}} does not exist on this machine. Check list_providers, then change it with team_update_member.",
9388
+ instanceUnavailable: "The provider instance chosen for member {{memberId}} is turned off or cannot run on this machine. Check list_providers, then change it with team_update_member.",
9389
+ modelNotInCatalog: "The model chosen for member {{memberId}} is not in that provider instance's model list. Check list_models, then change it with team_update_member.",
9368
9390
  noDefaultModel: "Member {{memberId}} has no model of its own and the project has no default model. Give them one with team_update_member.",
9369
9391
  duplicateTeamName: "A team named {{name}} already exists in this project. Choose another name and use a new requestId.",
9370
9392
  leadOnly: "Only the lead conversation of a team can change its members.",
@@ -9384,6 +9406,9 @@ var en_default = {
9384
9406
  requestVoided: "This requestId was abandoned before the change reached the engine. Use a new requestId.",
9385
9407
  invalidAgent: "Give both instanceId and model, or neither.",
9386
9408
  modelUnavailable: "That provider instance or model is not available on this machine. Check list_providers and list_models, then try again.",
9409
+ instanceNotFound: "That provider instance does not exist on this machine. Check list_providers, then try again.",
9410
+ instanceUnavailable: "That provider instance is turned off or cannot run on this machine. Check list_providers, then try again.",
9411
+ modelNotInCatalog: "That model is not in the provider instance's model list. Check list_models, then try again.",
9387
9412
  noDefaultModel: "The project has no default model. Give instanceId and model.",
9388
9413
  notAgentMember: "Only agent members can be changed with this tool.",
9389
9414
  memberInOtherTeam: "Another team is using this member. You can only change or remove members who are on no team, or only on yours. See which teams each member is on with team_roster_overview.",
@@ -9615,6 +9640,9 @@ var en_default = {
9615
9640
  invalidPayload: "Check the member fields and try again.",
9616
9641
  noDefaultModel: "This project has no default model. Choose one in the project settings under New threads \u2192 Model, then try again.",
9617
9642
  modelUnavailable: "The project's default model isn't available on this machine. Check the provider, or choose another model in the project settings under New threads \u2192 Model.",
9643
+ instanceNotFound: "The project's default model belongs to a provider instance that does not exist on this machine. Choose another model in the project settings under New threads \u2192 Model.",
9644
+ instanceUnavailable: "The provider instance of the project's default model is turned off or cannot run on this machine. Check the provider, or choose another model in the project settings under New threads \u2192 Model.",
9645
+ modelNotInCatalog: "The project's default model is not in its provider instance's model list. Choose another model in the project settings under New threads \u2192 Model.",
9618
9646
  duplicateMember: "Another member already has this name or remote agent. Rename or remove that member first.",
9619
9647
  alreadyYou: "You are already {{name}} on this roster. Clear \u201CThis is me\u201D on {{name}} first.",
9620
9648
  staleVersion: "This member was changed elsewhere and has been reloaded. Review it and save again.",
@@ -10481,10 +10509,12 @@ var GUARD_MESSAGES = {
10481
10509
  "model-unavailable": "modelUnavailable",
10482
10510
  "no-default-model": "noDefaultModel"
10483
10511
  };
10484
- var refuse = (code) => ({
10512
+ var refuse = (code, reason) => ({
10485
10513
  status: "rejected",
10486
10514
  code,
10487
- detail: coordinatorMessage(GUARD_MESSAGES[code])
10515
+ detail: coordinatorMessage(
10516
+ code === "model-unavailable" && reason !== void 0 ? UNAVAILABLE_MESSAGE_KEYS[reason] : GUARD_MESSAGES[code]
10517
+ )
10488
10518
  });
10489
10519
  function terminalRefusal(error) {
10490
10520
  const refusal = memberRefusal(error);
@@ -10605,14 +10635,14 @@ function startCoordinatorRuntime(ctx, deps) {
10605
10635
  if (instanceId === void 0 && model === void 0) {
10606
10636
  if (change.op === "update") return {};
10607
10637
  const fallback = await defaultAgent(ctx, projectId);
10608
- return "code" in fallback ? refuse(fallback.code) : { agent: fallback.agent };
10638
+ return "code" in fallback ? refuse(fallback.code, "reason" in fallback ? fallback.reason : void 0) : { agent: fallback.agent };
10609
10639
  }
10610
10640
  if (instanceId === void 0 || model === void 0) return refuse("invalid-agent");
10611
10641
  const environmentId = target?.agent?.environmentId ?? ctx.environment.id;
10612
10642
  if (environmentId !== ctx.environment.id)
10613
10643
  return { agent: { environmentId, modelSelection: { instanceId, model } } };
10614
- const resolved = await resolveModel(ctx, { instanceId, model });
10615
- return "code" in resolved ? refuse(resolved.code) : { agent: { environmentId, modelSelection: resolved.selection.modelSelection } };
10644
+ const resolved = await resolveModel(ctx, { instanceId, model }, true);
10645
+ return "code" in resolved ? refuse(resolved.code, "reason" in resolved ? resolved.reason : void 0) : { agent: { environmentId, modelSelection: resolved.selection.modelSelection } };
10616
10646
  };
10617
10647
  const plan = async (change, requestId, projectId, target) => {
10618
10648
  if (change.op === "create") {
@@ -11179,6 +11209,11 @@ var toEngineAgent = (agent) => ({
11179
11209
  environmentId: agent.environmentId,
11180
11210
  modelSelection: agent.modelSelection
11181
11211
  });
11212
+ var rejectDefault = (commandType, refusal) => rejectMember(
11213
+ commandType,
11214
+ refusal.code,
11215
+ "reason" in refusal && refusal.reason !== void 0 ? { reason: refusal.reason } : void 0
11216
+ );
11182
11217
  async function refused(commandType, run2) {
11183
11218
  try {
11184
11219
  return await run2();
@@ -11219,7 +11254,7 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11219
11254
  agent = toEngineAgent(input.agent);
11220
11255
  } else {
11221
11256
  const fallback = await defaultAgent(ctx, input.projectId);
11222
- if ("code" in fallback) return rejectMember("createMember", fallback.code);
11257
+ if ("code" in fallback) return rejectDefault("createMember", fallback);
11223
11258
  agent = fallback.agent;
11224
11259
  }
11225
11260
  }
@@ -11317,7 +11352,7 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11317
11352
  let local;
11318
11353
  if (missing2.some(({ member }) => member.principal === void 0)) {
11319
11354
  const fallback = await defaultAgent(ctx, projectId);
11320
- if ("code" in fallback) return rejectMember("importRoster", fallback.code);
11355
+ if ("code" in fallback) return rejectDefault("importRoster", fallback);
11321
11356
  local = fallback;
11322
11357
  }
11323
11358
  for (const { member, memberId } of missing2) {
@@ -11642,6 +11677,33 @@ function startCommentMentionRuntime(ctx, goals) {
11642
11677
  ctx.reactor({ name: "team-comment-mentions", events: ["work.comment-posted"], handle });
11643
11678
  }
11644
11679
 
11680
+ // src/runtime/dispatchClaim.ts
11681
+ var allow = { allowed: true };
11682
+ var claim = (detail) => ({ allowed: false, detail });
11683
+ function registerDispatchClaim(ctx, wakes) {
11684
+ const check = async (input) => {
11685
+ const project2 = readFact(
11686
+ await wakes.get({ throughSequence: input.throughSequence }),
11687
+ input.projectId
11688
+ );
11689
+ if (project2 === null) return allow;
11690
+ if (input.workLineId !== null && project2.lineScopes?.[input.workLineId] !== void 0)
11691
+ return claim("the team on this work line dispatches its members");
11692
+ if (project2.goalId === void 0) return allow;
11693
+ if (readFact(project2.bindings ?? {}, input.memberId) !== null)
11694
+ return claim("the project's team goal dispatches this member");
11695
+ if (isClosed(readFact(project2.items, teamGoalItemId(input.projectId, project2.goalId))))
11696
+ return allow;
11697
+ const lines = await ctx.work.lines.list({
11698
+ projectId: input.projectId,
11699
+ includeArchived: true,
11700
+ limit: 1
11701
+ });
11702
+ return lines.items.length === 0 ? claim("the project's team goal takes this member in and dispatches it") : allow;
11703
+ };
11704
+ return ctx.operations.guard({ operations: ["work.dispatch"], check });
11705
+ }
11706
+
11645
11707
  // src/runtime/deliveryPacing.ts
11646
11708
  function foldProgress(state, event) {
11647
11709
  const decoded = decodeWorkEvent(event);
@@ -11823,6 +11885,8 @@ function startGroupDeliveryRuntime(ctx, wakes, now3 = () => runPromise2(map5(now
11823
11885
  events: [
11824
11886
  "communication.group-message-sent",
11825
11887
  "work.line-restored",
11888
+ // 线或成员恢复:暂停期间没绑的目标补扫出去。
11889
+ "work.line-resumed",
11826
11890
  "plugin.event-appended",
11827
11891
  "member.created",
11828
11892
  "member.updated",
@@ -12846,9 +12910,63 @@ function memberStarter(previous, settled, moved) {
12846
12910
  return threadId !== void 0 && Object.values(settled.memberThreads ?? {}).includes(threadId) ? threadId : void 0;
12847
12911
  }
12848
12912
 
12913
+ // src/runtime/linePauseFold.ts
12914
+ var EnginePause = Struct({
12915
+ projectId: String4,
12916
+ workLineId: String4,
12917
+ memberId: optionalKey2(String4)
12918
+ });
12919
+ var decodeEnginePause = decodeUnknownOption2(EnginePause);
12920
+ var pauseOfEngineEvent = (event) => {
12921
+ if (event.type !== "work.line-paused" && event.type !== "work.line-resumed") return null;
12922
+ const decoded = decodeEnginePause(event.payload);
12923
+ if (isNone2(decoded)) return null;
12924
+ return { ...decoded.value, paused: event.type === "work.line-paused" };
12925
+ };
12926
+ function applyPause(project2, change) {
12927
+ const { workLineId, memberId, paused } = change;
12928
+ if (memberId === void 0) {
12929
+ const known = project2.linePauses ?? {};
12930
+ if (paused === (known[workLineId] === true)) return project2;
12931
+ return {
12932
+ ...project2,
12933
+ linePauses: paused ? { ...known, [workLineId]: true } : without(known, workLineId)
12934
+ };
12935
+ }
12936
+ const list = project2.pausedMembers?.[workLineId] ?? [];
12937
+ if (paused === list.includes(memberId)) return project2;
12938
+ const remaining = paused ? [...list, memberId] : list.filter((id) => id !== memberId);
12939
+ const pausedMembers = { ...project2.pausedMembers };
12940
+ if (remaining.length === 0) delete pausedMembers[workLineId];
12941
+ else pausedMembers[workLineId] = remaining;
12942
+ return { ...project2, pausedMembers };
12943
+ }
12944
+ var legacyPauseId = (project2, workLineId, memberId) => memberId === void 0 ? project2.legacyLinePauses?.[workLineId] : project2.legacyMemberPauses?.[workLineId]?.[memberId];
12945
+ function withPause(project2, change, legacyEventId) {
12946
+ const { workLineId, memberId, paused } = change;
12947
+ const previous = legacyPauseId(project2, workLineId, memberId);
12948
+ if (!paused && legacyEventId !== void 0 && previous === void 0) return project2;
12949
+ const next = applyPause(project2, change);
12950
+ const legacy = paused ? legacyEventId : void 0;
12951
+ if (legacy === previous) return next;
12952
+ if (memberId === void 0) {
12953
+ const known2 = project2.legacyLinePauses ?? {};
12954
+ return {
12955
+ ...next,
12956
+ legacyLinePauses: legacy === void 0 ? without(known2, workLineId) : { ...known2, [workLineId]: legacy }
12957
+ };
12958
+ }
12959
+ const known = project2.legacyMemberPauses?.[workLineId] ?? {};
12960
+ const members = legacy === void 0 ? without(known, memberId) : { ...known, [memberId]: legacy };
12961
+ const legacyMemberPauses = { ...project2.legacyMemberPauses };
12962
+ if (Object.keys(members).length === 0) delete legacyMemberPauses[workLineId];
12963
+ else legacyMemberPauses[workLineId] = members;
12964
+ return { ...next, legacyMemberPauses };
12965
+ }
12966
+
12849
12967
  // src/runtime/wakeState.ts
12850
12968
  var WAKE_STATE_KEY = "wakes";
12851
- var WAKE_STATE_VERSION = 8;
12969
+ var WAKE_STATE_VERSION = 9;
12852
12970
  var WAKE_EVENTS = [
12853
12971
  "work.item-created",
12854
12972
  "work.item-updated",
@@ -12858,6 +12976,9 @@ var WAKE_EVENTS = [
12858
12976
  "work.comment-posted",
12859
12977
  "plugin.event-appended",
12860
12978
  "thread.session-set",
12979
+ // 线与线上成员的暂停:引擎的看板事实,派发闸读它(见 `linePauses` / `pausedMembers`)。
12980
+ "work.line-paused",
12981
+ "work.line-resumed",
12861
12982
  // 团队的线归档、恢复,负责人会话被删:这个团队停工(见 `lineStops`)。
12862
12983
  "work.line-archived",
12863
12984
  "work.line-restored",
@@ -12994,28 +13115,17 @@ function foldWorkWakes(state, event) {
12994
13115
  if (fact.name === "team/line-paused" || fact.name === "team/line-member-paused") {
12995
13116
  const { projectId: projectId3, workLineId, status } = fact.data;
12996
13117
  const project4 = readFact(state, projectId3) ?? emptyProject();
12997
- const paused = status === "paused";
12998
- if (fact.name === "team/line-paused") {
12999
- const known = project4.linePauses ?? {};
13000
- if (paused === (known[workLineId] === true)) return state;
13001
- return {
13002
- ...state,
13003
- [projectId3]: {
13004
- ...project4,
13005
- linePauses: paused ? { ...known, [workLineId]: true } : without(known, workLineId)
13006
- }
13007
- };
13008
- }
13009
- const list = project4.pausedMembers?.[workLineId] ?? [];
13010
- if (paused === list.includes(fact.data.memberId)) return state;
13011
- const remaining = paused ? [...list, fact.data.memberId] : list.filter((memberId) => memberId !== fact.data.memberId);
13012
- const pausedMembers = { ...project4.pausedMembers };
13013
- if (remaining.length === 0) delete pausedMembers[workLineId];
13014
- else pausedMembers[workLineId] = remaining;
13015
- return {
13016
- ...state,
13017
- [projectId3]: { ...project4, pausedMembers }
13018
- };
13118
+ const next2 = withPause(
13119
+ project4,
13120
+ {
13121
+ projectId: projectId3,
13122
+ workLineId,
13123
+ ...fact.name === "team/line-member-paused" ? { memberId: fact.data.memberId } : {},
13124
+ paused: status === "paused"
13125
+ },
13126
+ event.eventId
13127
+ );
13128
+ return next2 === project4 ? state : { ...state, [projectId3]: next2 };
13019
13129
  }
13020
13130
  if (fact.name === COMMENT_MENTIONS_EVENT) {
13021
13131
  const { projectId: projectId3, workItemId: workItemId2, commentId, recipients } = fact.data;
@@ -13283,7 +13393,16 @@ function foldLineStops(state, event) {
13283
13393
  }
13284
13394
  return next;
13285
13395
  }
13396
+ function foldEnginePause(state, event) {
13397
+ const change = pauseOfEngineEvent(event);
13398
+ if (change === null) return state;
13399
+ const project2 = readFact(state, change.projectId) ?? emptyProject();
13400
+ const next = withPause(project2, change);
13401
+ return next === project2 ? state : { ...state, [change.projectId]: next };
13402
+ }
13286
13403
  function foldWakes(state, event) {
13404
+ if (event.type === "work.line-paused" || event.type === "work.line-resumed")
13405
+ return foldEnginePause(state, event);
13287
13406
  return foldRecovery(
13288
13407
  pruneReviews(state, foldLineStops(foldWorkWakes(state, event), event)),
13289
13408
  event,
@@ -13692,7 +13811,9 @@ function startRecoveryRuntime(ctx, goals, state, worktrees) {
13692
13811
  "thread.turn-intent-transitioned",
13693
13812
  "thread.turn-queue-updated",
13694
13813
  "thread.request-resolved",
13695
- "thread.user-input-pending"
13814
+ "thread.user-input-pending",
13815
+ // 线或成员恢复:暂停期间扣下的恢复计划补发。
13816
+ "work.line-resumed"
13696
13817
  ],
13697
13818
  handle: (event) => flush(recoveryEventScopeOf(event))
13698
13819
  });
@@ -14492,7 +14613,7 @@ function startHandbookRuntime(ctx, worktrees) {
14492
14613
  const flush = () => serial(execute);
14493
14614
  ctx.reactor({
14494
14615
  name: "team-handbook",
14495
- events: [...HANDBOOK_EVENTS2, "work.item-updated"],
14616
+ events: [...HANDBOOK_EVENTS2, "work.item-updated", "work.line-resumed"],
14496
14617
  handle: () => flush()
14497
14618
  });
14498
14619
  ctx.onDispose(queue.close);
@@ -15447,7 +15568,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15447
15568
  throw new TeamRuleError(
15448
15569
  resolved.code,
15449
15570
  teamMessage(
15450
- resolved.code === "no-default-model" ? "noDefaultModel" : "modelUnavailable",
15571
+ resolved.code === "no-default-model" ? "noDefaultModel" : resolved.reason === void 0 ? "modelUnavailable" : UNAVAILABLE_MESSAGE_KEYS[resolved.reason],
15451
15572
  { memberId: row.memberId }
15452
15573
  )
15453
15574
  );
@@ -15649,13 +15770,11 @@ var MEMBER_LIMIT = 500;
15649
15770
  var TEAM_LIMIT = 200;
15650
15771
  function createTeamOverview(ctx, deps) {
15651
15772
  return async (projectId) => {
15652
- const [members, lines, trials2, wakes] = await Promise.all([
15773
+ const [members, lines, trials2] = await Promise.all([
15653
15774
  readPages(MEMBER_LIMIT, (page) => ctx.members.list({ projectId, ...page })),
15654
15775
  readPages(TEAM_LIMIT, (page) => ctx.work.lines.list({ projectId, ...page })),
15655
- deps.trials.get(),
15656
- deps.wakes.get()
15776
+ deps.trials.get()
15657
15777
  ]);
15658
- const paused = wakes[projectId] ?? {};
15659
15778
  const teamsOf = (memberId) => lines.items.flatMap(
15660
15779
  (line) => line.memberIds.includes(memberId) ? [
15661
15780
  {
@@ -15682,9 +15801,9 @@ function createTeamOverview(ctx, deps) {
15682
15801
  trial: member.kind === "human" ? "none" : trial === null ? principalId === null ? "none" : "unverified" : trial.evidence === "invoked" ? "invoked" : trial.status === "failed" ? "failed" : trial.status === "passed" || trial.status === "overridden" ? "ready" : "pending",
15683
15802
  trialFailure: trial?.failure?.category ?? null,
15684
15803
  teams: teamsOf(member.memberId),
15685
- // 这名成员被暂停的团队:整线暂停,或它在这条线上被单独暂停(ADR-0027:371);判定与派发闸同一份。
15804
+ // 这名成员被暂停的团队:整线暂停,或它在这条线上被单独暂停(ADR-0027:371);读线上的引擎事实。
15686
15805
  pausedOnLines: lines.items.filter(
15687
- (line) => line.memberIds.includes(member.memberId) && (isLinePaused(paused, line.workLineId) || isMemberPausedOnLine(paused, line.workLineId, member.memberId))
15806
+ (line) => line.memberIds.includes(member.memberId) && (line.pause !== void 0 || (line.memberPauses ?? []).some((pause) => pause.memberId === member.memberId))
15688
15807
  ).map((line) => line.workLineId)
15689
15808
  };
15690
15809
  }),
@@ -15694,7 +15813,7 @@ function createTeamOverview(ctx, deps) {
15694
15813
  leadMemberId: line.leadMemberId,
15695
15814
  memberCount: line.memberIds.length,
15696
15815
  conversation: line.threadId,
15697
- paused: isLinePaused(paused, line.workLineId)
15816
+ paused: line.pause !== void 0
15698
15817
  })),
15699
15818
  truncated: members.truncated || lines.truncated
15700
15819
  };
@@ -15890,96 +16009,134 @@ var LineMemberPauseInput = Struct({
15890
16009
  memberId: String4
15891
16010
  });
15892
16011
  var decodeLine = decodeUnknownSync(LinePauseInput);
16012
+ var decodeRestored = decodeUnknownOption2(
16013
+ Struct({ projectId: String4, workLineId: String4 })
16014
+ );
15893
16015
  var decodeMember = decodeUnknownSync(LineMemberPauseInput);
15894
- var appendOf = (name, key) => ({
15895
- commandId: `team-${name}:${stableHash(JSON.stringify([...key]))}`,
15896
- name
15897
- });
15898
- function registerPauseCommands(ctx) {
15899
- const asPerson = (run2) => async (payload, invocation) => {
16016
+ var engineRequestId = (status, target, requestId) => `team-pause:${stableHash(JSON.stringify([status, target.projectId, target.workLineId, target.memberId ?? null, requestId]))}`;
16017
+ function registerPauseCommands(ctx, deps) {
16018
+ const write = async (invocation, status, target, requestId) => {
16019
+ const lines = invocation.asPerson.work.lines;
16020
+ const input = { ...target, requestId: engineRequestId(status, target, requestId) };
16021
+ try {
16022
+ await (status === "paused" ? lines.pause(input) : lines.resume(input));
16023
+ } catch (error) {
16024
+ const code = hostRefusalCode(error);
16025
+ if (code === "not-permitted")
16026
+ throw new Error("This team is archived; restore it instead of pausing", { cause: error });
16027
+ if (code === "invalid-input")
16028
+ throw new Error("This member is not on that team's work line", { cause: error });
16029
+ throw error;
16030
+ }
16031
+ };
16032
+ const handler = (status, withMember) => async (payload, invocation) => {
15900
16033
  if (invocation.asPerson === void 0)
15901
16034
  throw Object.assign(new Error("Only a person can pause or resume a team"), {
15902
16035
  code: "needs-person"
15903
16036
  });
15904
- return run2(payload);
15905
- };
15906
- const setLinePaused = async (input, paused) => {
15907
- const { line } = await ctx.work.lines.get({
15908
- projectId: input.projectId,
15909
- workLineId: input.workLineId
15910
- });
15911
- if (line.archivedAt !== null)
15912
- throw new Error("This team is archived; restore it instead of pausing");
15913
- await ctx.events.append({
15914
- ...appendOf("line-paused", [input.projectId, input.workLineId, input.requestId]),
15915
- aggregate: { kind: "project", id: input.projectId },
15916
- data: {
15917
- version: 1,
15918
- status: paused ? "paused" : "resumed",
15919
- projectId: input.projectId,
15920
- workLineId: input.workLineId
15921
- }
15922
- });
15923
- return {
15924
- projectId: input.projectId,
15925
- workLineId: input.workLineId,
15926
- status: paused ? "paused" : "resumed"
15927
- };
15928
- };
15929
- const setLineMemberPaused = async (input, paused) => {
15930
- const { line } = await ctx.work.lines.get({
15931
- projectId: input.projectId,
15932
- workLineId: input.workLineId
16037
+ const { requestId, ...target } = withMember ? decodeMember(payload) : decodeLine(payload);
16038
+ await deps.queue.run(async () => {
16039
+ await backfillLine(ctx, deps.wakes, target.projectId, target.workLineId);
16040
+ await write(invocation, status, target, requestId);
16041
+ if (status === "resumed") await releaseLegacyLeftover(ctx, deps.wakes, target, requestId);
15933
16042
  });
15934
- if (!line.memberIds.includes(input.memberId))
15935
- throw new Error("This member is not on that team's work line");
15936
- await ctx.events.append({
15937
- ...appendOf("line-member-paused", [
15938
- input.projectId,
15939
- input.workLineId,
15940
- input.memberId,
15941
- input.requestId
15942
- ]),
15943
- aggregate: { kind: "project", id: input.projectId },
15944
- data: {
15945
- version: 1,
15946
- status: paused ? "paused" : "resumed",
15947
- projectId: input.projectId,
15948
- workLineId: input.workLineId,
15949
- memberId: input.memberId
15950
- }
15951
- });
15952
- return {
15953
- projectId: input.projectId,
15954
- workLineId: input.workLineId,
15955
- memberId: input.memberId,
15956
- status: paused ? "paused" : "resumed"
15957
- };
16043
+ return { ...target, status };
15958
16044
  };
15959
16045
  ctx.command({
15960
16046
  name: "pauseLine",
15961
16047
  scope: "operate",
15962
16048
  payloadSchema: payloadSchemaOf(LinePauseInput),
15963
- handle: asPerson((input) => setLinePaused(decodeLine(input), true))
16049
+ handle: handler("paused", false)
15964
16050
  });
15965
16051
  ctx.command({
15966
16052
  name: "resumeLine",
15967
16053
  scope: "operate",
15968
16054
  payloadSchema: payloadSchemaOf(LinePauseInput),
15969
- handle: asPerson((input) => setLinePaused(decodeLine(input), false))
16055
+ handle: handler("resumed", false)
15970
16056
  });
15971
16057
  ctx.command({
15972
16058
  name: "pauseLineMember",
15973
16059
  scope: "operate",
15974
16060
  payloadSchema: payloadSchemaOf(LineMemberPauseInput),
15975
- handle: asPerson((input) => setLineMemberPaused(decodeMember(input), true))
16061
+ handle: handler("paused", true)
15976
16062
  });
15977
16063
  ctx.command({
15978
16064
  name: "resumeLineMember",
15979
16065
  scope: "operate",
15980
16066
  payloadSchema: payloadSchemaOf(LineMemberPauseInput),
15981
- handle: asPerson((input) => setLineMemberPaused(decodeMember(input), false))
16067
+ handle: handler("resumed", true)
16068
+ });
16069
+ ctx.reactor({
16070
+ name: "team-pause-backfill",
16071
+ events: ["work.line-restored"],
16072
+ handle: (event) => match(decodeRestored(event.payload), {
16073
+ onNone: () => Promise.resolve(),
16074
+ onSome: ({ projectId, workLineId }) => deps.queue.run(() => backfillLine(ctx, deps.wakes, projectId, workLineId))
16075
+ })
15982
16076
  });
16077
+ const ready = deps.queue.run(() => backfillLegacyPauses(ctx, deps.wakes));
16078
+ void ready.catch((error) => ctx.log.warn("team pause backfill failed", { error }));
16079
+ return { ready };
16080
+ }
16081
+ async function backfillLine(ctx, wakes, projectId, workLineId) {
16082
+ try {
16083
+ const { line, snapshotSequence } = await ctx.work.lines.get({ projectId, workLineId });
16084
+ if (line.archivedAt !== null) return;
16085
+ const caught = readFact(await wakes.get({ throughSequence: snapshotSequence }), projectId);
16086
+ if (caught === null) return;
16087
+ const targets = [
16088
+ ...isLinePaused(caught, workLineId) && line.pause === void 0 ? [{ projectId, workLineId }] : [],
16089
+ ...(caught.pausedMembers?.[workLineId] ?? []).filter(
16090
+ (memberId) => isMemberPausedOnLine(caught, workLineId, memberId) && line.memberIds.includes(memberId) && !(line.memberPauses ?? []).some((pause) => pause.memberId === memberId)
16091
+ ).map((memberId) => ({ projectId, workLineId, memberId }))
16092
+ ];
16093
+ for (const target of targets)
16094
+ await ctx.work.lines.pause({
16095
+ ...target,
16096
+ requestId: `team-pause-backfill:${stableHash(JSON.stringify([target.workLineId, target.memberId ?? null, line.version]))}`
16097
+ });
16098
+ } catch (error) {
16099
+ ctx.log.warn("team pause could not be recorded on the work line", {
16100
+ projectId,
16101
+ workLineId,
16102
+ error
16103
+ });
16104
+ }
16105
+ }
16106
+ async function backfillLegacyPauses(ctx, wakes) {
16107
+ const state = await wakes.get();
16108
+ for (const [projectId, project2] of Object.entries(state)) {
16109
+ const lineIds = /* @__PURE__ */ new Set([
16110
+ ...Object.keys(project2.linePauses ?? {}),
16111
+ ...Object.keys(project2.pausedMembers ?? {})
16112
+ ]);
16113
+ for (const workLineId of lineIds) await backfillLine(ctx, wakes, projectId, workLineId);
16114
+ }
16115
+ }
16116
+ async function releaseLegacyLeftover(ctx, wakes, target, requestId) {
16117
+ const { line, snapshotSequence } = await ctx.work.lines.get({
16118
+ projectId: target.projectId,
16119
+ workLineId: target.workLineId
16120
+ });
16121
+ const engineHolds = target.memberId === void 0 ? line.pause !== void 0 : (line.memberPauses ?? []).some((pause) => pause.memberId === target.memberId);
16122
+ if (engineHolds) return;
16123
+ const caught = readFact(await wakes.get({ throughSequence: snapshotSequence }), target.projectId);
16124
+ if (caught === null) return;
16125
+ if (legacyPauseId(caught, target.workLineId, target.memberId) === void 0) return;
16126
+ const name = target.memberId === void 0 ? "line-paused" : "line-member-paused";
16127
+ const receipt = await ctx.events.append({
16128
+ commandId: `team-${name}:${stableHash(JSON.stringify([target, requestId]))}`,
16129
+ name,
16130
+ aggregate: { kind: "project", id: target.projectId },
16131
+ data: {
16132
+ version: 1,
16133
+ status: "resumed",
16134
+ projectId: target.projectId,
16135
+ workLineId: target.workLineId,
16136
+ ...target.memberId === void 0 ? {} : { memberId: target.memberId }
16137
+ }
16138
+ });
16139
+ await wakes.get({ throughSequence: receipt.sequence });
15983
16140
  }
15984
16141
 
15985
16142
  // src/team/waiting.ts
@@ -16262,6 +16419,9 @@ var zh_CN_default = {
16262
16419
  memberNotFound: "\u8FD9\u4E2A\u9879\u76EE\u91CC\u6CA1\u6709\u6210\u5458 {{memberId}}\u3002\u7528 team_roster_overview \u5217\u51FA\u6210\u5458\u3002",
16263
16420
  memberRemoved: "\u6210\u5458 {{memberId}} \u5DF2\u4ECE\u9879\u76EE\u91CC\u79FB\u9664\u3002\u5148\u7528 team_restore_member \u628A\u5B83\u8BF7\u56DE\u6765\u3002",
16264
16421
  modelUnavailable: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684\u6A21\u578B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u4E0D\u4E86\u3002\u67E5 list_providers \u548C list_models\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16422
+ instanceNotFound: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684 provider \u5B9E\u4F8B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u4E0D\u5B58\u5728\u3002\u67E5 list_providers\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16423
+ instanceUnavailable: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684 provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u67E5 list_providers\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16424
+ modelNotInCatalog: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684\u6A21\u578B\u4E0D\u5728\u8BE5 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u67E5 list_models\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16265
16425
  noDefaultModel: "\u6210\u5458 {{memberId}} \u6CA1\u6709\u81EA\u5DF1\u7684\u6A21\u578B\uFF0C\u9879\u76EE\u4E5F\u6CA1\u6709\u9ED8\u8BA4\u6A21\u578B\u3002\u7528 team_update_member \u7ED9\u5B83\u4E00\u4E2A\u3002",
16266
16426
  duplicateTeamName: "\u8FD9\u4E2A\u9879\u76EE\u91CC\u5DF2\u7ECF\u6709\u540D\u4E3A {{name}} \u7684\u56E2\u961F\u3002\u6362\u4E2A\u540D\u5B57\uFF0C\u5E76\u7528\u65B0\u7684 requestId\u3002",
16267
16427
  leadOnly: "\u53EA\u6709\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\u4F1A\u8BDD\u80FD\u6539\u5B83\u7684\u6210\u5458\u3002",
@@ -16281,6 +16441,9 @@ var zh_CN_default = {
16281
16441
  requestVoided: "\u8FD9\u4E2A requestId \u5728\u6539\u52A8\u5230\u8FBE\u5F15\u64CE\u4E4B\u524D\u5C31\u4F5C\u5E9F\u4E86\u3002\u8BF7\u6362\u4E00\u4E2A\u65B0\u7684 requestId\u3002",
16282
16442
  invalidAgent: "instanceId \u548C model \u8981\u4E48\u90FD\u7ED9\uFF0C\u8981\u4E48\u90FD\u4E0D\u7ED9\u3002",
16283
16443
  modelUnavailable: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u8FD9\u4E2A provider \u5B9E\u4F8B\u6216\u6A21\u578B\u3002\u5148\u770B list_providers \u548C list_models\uFF0C\u518D\u91CD\u8BD5\u3002",
16444
+ instanceNotFound: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u8FD9\u4E2A provider \u5B9E\u4F8B\u3002\u5148\u770B list_providers\uFF0C\u518D\u91CD\u8BD5\u3002",
16445
+ instanceUnavailable: "\u8FD9\u4E2A provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u5148\u770B list_providers\uFF0C\u518D\u91CD\u8BD5\u3002",
16446
+ modelNotInCatalog: "\u8FD9\u4E2A\u6A21\u578B\u4E0D\u5728\u8BE5 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u5148\u770B list_models\uFF0C\u518D\u91CD\u8BD5\u3002",
16284
16447
  noDefaultModel: "\u9879\u76EE\u6CA1\u6709\u8BBE\u9ED8\u8BA4\u6A21\u578B\uFF0C\u8BF7\u7ED9\u51FA instanceId \u548C model\u3002",
16285
16448
  memberInOtherTeam: "\u8FD9\u4E2A\u6210\u5458\u5DF2\u5728\u522B\u7684\u56E2\u961F\u91CC\u3002\u4F60\u53EA\u80FD\u4FEE\u6539\u6216\u79FB\u9664\u4E0D\u5728\u4EFB\u4F55\u56E2\u961F\u3001\u6216\u53EA\u5728\u4F60\u8FD9\u4E2A\u56E2\u961F\u91CC\u7684\u6210\u5458\u3002\u7528 team_roster_overview \u770B\u6BCF\u4E2A\u6210\u5458\u5728\u54EA\u4E2A\u56E2\u961F\u3002",
16286
16449
  notAgentMember: "\u8FD9\u4E2A\u5DE5\u5177\u53EA\u80FD\u6539 agent \u6210\u5458\u3002",
@@ -16512,6 +16675,9 @@ var zh_CN_default = {
16512
16675
  invalidPayload: "\u8BF7\u68C0\u67E5\u6210\u5458\u5B57\u6BB5\u540E\u91CD\u8BD5\u3002",
16513
16676
  noDefaultModel: "\u8FD9\u4E2A\u9879\u76EE\u6CA1\u8BBE\u9ED8\u8BA4\u6A21\u578B\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u9009\u4E00\u4E2A\uFF0C\u518D\u91CD\u8BD5\u3002",
16514
16677
  modelUnavailable: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u4E0D\u4E86\u3002\u68C0\u67E5\u4E00\u4E0B provider\uFF0C\u6216\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16678
+ instanceNotFound: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u6240\u5C5E\u7684 provider \u5B9E\u4F8B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u4E0D\u5B58\u5728\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16679
+ instanceUnavailable: "\u8FD9\u4E2A\u9879\u76EE\u9ED8\u8BA4\u6A21\u578B\u6240\u5C5E\u7684 provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u68C0\u67E5\u4E00\u4E0B provider\uFF0C\u6216\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16680
+ modelNotInCatalog: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u4E0D\u5728\u5176 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16515
16681
  duplicateMember: "\u5DF2\u6709\u6210\u5458\u7528\u4E86\u8FD9\u4E2A\u540D\u5B57\u6216\u8FD9\u4E2A\u8FDC\u7AEF agent\uFF0C\u8BF7\u5148\u6539\u540D\u6216\u79FB\u9664\u5B83\u3002",
16516
16682
  alreadyYou: "\u4F60\u5728\u540D\u518C\u4E0A\u5DF2\u7ECF\u662F\u300C{{name}}\u300D\u4E86\uFF0C\u8BF7\u5148\u5728\u300C{{name}}\u300D\u90A3\u91CC\u53D6\u6D88\u300C\u8FD9\u662F\u6211\u300D\u3002",
16517
16683
  staleVersion: "\u8FD9\u540D\u6210\u5458\u5DF2\u88AB\u522B\u5904\u6539\u8FC7\uFF0C\u5DF2\u91CD\u65B0\u8F7D\u5165\u3002\u8BF7\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002",
@@ -16783,6 +16949,107 @@ function registerTrial(ctx, runtime) {
16783
16949
  });
16784
16950
  }
16785
16951
 
16952
+ // src/trial/mirror.ts
16953
+ var SUMMARY_MAX = 500;
16954
+ var MEMBER_LIMIT2 = 500;
16955
+ var RECONCILE_MS2 = 12e4;
16956
+ var cut = (text) => text.length > SUMMARY_MAX ? `${text.slice(0, SUMMARY_MAX - 1)}\u2026` : text;
16957
+ var desiredTrialOf = (view) => {
16958
+ if (view === null) return null;
16959
+ switch (view.status) {
16960
+ case "passed":
16961
+ return {
16962
+ outcome: "passed",
16963
+ summary: view.evidence === "remote" ? "Remote connection verified" : view.evidence === "invoked" ? "Proved by the conversation that opened the team" : "Passed in a local session"
16964
+ };
16965
+ case "overridden":
16966
+ return { outcome: "skipped", summary: "Skipped by a person" };
16967
+ case "failed":
16968
+ return {
16969
+ outcome: "failed",
16970
+ summary: cut(
16971
+ view.failure === null ? "Failed" : `${view.failure.category}: ${view.failure.reason.replace(/\s+/g, " ").trim()}`
16972
+ )
16973
+ };
16974
+ case "pending":
16975
+ return { outcome: "not-run", summary: "Waiting to run" };
16976
+ case "waiting":
16977
+ return { outcome: "not-run", summary: "Sent to the remote agent" };
16978
+ case "running":
16979
+ return { outcome: "not-run", summary: "Running" };
16980
+ }
16981
+ };
16982
+ var TRIAL_FACT = /^team\/member-trial-/u;
16983
+ var isTrialTrigger = (event) => event.type !== "plugin.event-appended" || TRIAL_FACT.test(String(event.payload?.name ?? ""));
16984
+ function startTrialMirror(ctx, deps) {
16985
+ const queue = createSerial("team-trial-mirror-closed");
16986
+ ctx.onDispose(queue.close);
16987
+ const reconcile = async (onlyProjectId, throughSequence) => {
16988
+ const state = await deps.state.get(
16989
+ throughSequence === void 0 ? void 0 : { throughSequence }
16990
+ );
16991
+ const projects = /* @__PURE__ */ new Map();
16992
+ for (const record2 of Object.values(state.members)) {
16993
+ if (onlyProjectId !== void 0 && record2.projectId !== onlyProjectId) continue;
16994
+ const desired = desiredTrialOf(trialViewOf(record2));
16995
+ if (desired === null) continue;
16996
+ const rows = projects.get(record2.projectId) ?? [];
16997
+ rows.push({
16998
+ memberId: record2.memberId,
16999
+ desired,
17000
+ key: JSON.stringify([record2.specKey, record2.attempt])
17001
+ });
17002
+ projects.set(record2.projectId, rows);
17003
+ }
17004
+ for (const [projectId, rows] of projects) {
17005
+ try {
17006
+ const members = await readPages(
17007
+ MEMBER_LIMIT2,
17008
+ (page) => ctx.members.list({ projectId, ...page })
17009
+ );
17010
+ const recorded = new Map(members.items.map((member) => [member.memberId, member]));
17011
+ for (const row of rows) {
17012
+ const member = recorded.get(row.memberId);
17013
+ if (member === void 0 || member.removedAt !== null || member.kind !== "agent")
17014
+ continue;
17015
+ if (member.trial?.outcome === row.desired.outcome && (member.trial.summary ?? "") === row.desired.summary)
17016
+ continue;
17017
+ await ctx.members.trial.record({
17018
+ projectId,
17019
+ memberId: row.memberId,
17020
+ outcome: row.desired.outcome,
17021
+ summary: row.desired.summary,
17022
+ requestId: `team-trial-record:${stableHash(
17023
+ JSON.stringify([projectId, row.memberId, row.key, row.desired])
17024
+ )}`
17025
+ }).catch(
17026
+ (error) => ctx.log.warn("team trial result could not be recorded on the member", {
17027
+ projectId,
17028
+ memberId: row.memberId,
17029
+ error
17030
+ })
17031
+ );
17032
+ }
17033
+ } catch (error) {
17034
+ ctx.log.warn("team trial results could not be compared with the members", {
17035
+ projectId,
17036
+ error
17037
+ });
17038
+ }
17039
+ }
17040
+ };
17041
+ const flush = (onlyProjectId, throughSequence) => queue.run(() => reconcile(onlyProjectId, throughSequence));
17042
+ ctx.reactor({
17043
+ name: "team-trial-mirror",
17044
+ events: ["plugin.event-appended", "member.created", "member.updated", "member.restored"],
17045
+ handle: (event) => isTrialTrigger(event) ? flush(event.aggregateKind === "project" ? event.aggregateId : void 0, event.sequence) : Promise.resolve()
17046
+ });
17047
+ ctx.interval({ name: "team-trial-mirror", everyMs: RECONCILE_MS2, handle: () => flush() });
17048
+ const ready = flush();
17049
+ void ready.catch((error) => ctx.log.warn("team trial mirror catch-up failed", { error }));
17050
+ return { ready, flush };
17051
+ }
17052
+
16786
17053
  // src/trial/env.ts
16787
17054
  var factKey = (record2) => ({
16788
17055
  version: 1,
@@ -17134,7 +17401,7 @@ var decodeHuman2 = decodeUnknownOption2(HumanPrincipal);
17134
17401
  var decodeFactName = decodeUnknownOption2(
17135
17402
  Struct({ pluginId: Literal2("team"), name: String4 })
17136
17403
  );
17137
- var isTrialTrigger = (event) => {
17404
+ var isTrialTrigger2 = (event) => {
17138
17405
  if (event.type.startsWith("member.")) return true;
17139
17406
  if (event.type !== "plugin.event-appended") return false;
17140
17407
  const fact = decodeFactName(event.payload);
@@ -17321,7 +17588,7 @@ function startTrialRuntime(ctx, deps, options = {}) {
17321
17588
  const threadId = event.payload?.threadId;
17322
17589
  return typeof threadId === "string" && threadId.startsWith("team-trial:") ? failOnSessionError(event).then(() => flush()) : Promise.resolve();
17323
17590
  }
17324
- return isTrialTrigger(event) ? flush() : Promise.resolve();
17591
+ return isTrialTrigger2(event) ? flush() : Promise.resolve();
17325
17592
  }
17326
17593
  });
17327
17594
  ctx.interval({ name: "team-trial", everyMs: options.tickMs ?? TICK_MS2, handle: () => flush() });
@@ -17452,7 +17719,7 @@ function startTrialRuntime(ctx, deps, options = {}) {
17452
17719
  // src/index.ts
17453
17720
  var index_default = definePlugin({
17454
17721
  id: "team",
17455
- apiVersion: 50,
17722
+ apiVersion: 51,
17456
17723
  activate(ctx) {
17457
17724
  const trialState = ctx.derivedState(trialStateDefinition);
17458
17725
  const rosters = createRosterService(ctx);
@@ -17484,7 +17751,8 @@ var index_default = definePlugin({
17484
17751
  },
17485
17752
  memberQueue
17486
17753
  );
17487
- registerPauseCommands(ctx);
17754
+ registerDispatchClaim(ctx, wakes.state);
17755
+ registerPauseCommands(ctx, { wakes: wakes.state, queue: memberQueue });
17488
17756
  startArchiveMirror(
17489
17757
  ctx,
17490
17758
  { state: ctx.derivedState(archiveStateDefinition), wakes: wakes.state },
@@ -17512,6 +17780,7 @@ var index_default = definePlugin({
17512
17780
  handbookRelease: async (projectId) => (await handbook.read(projectId)).currentRelease
17513
17781
  });
17514
17782
  registerTrial(ctx, trials2);
17783
+ startTrialMirror(ctx, { state: trialState });
17515
17784
  }
17516
17785
  });
17517
17786
  export {