@tmustier/pi-agent-teams 0.5.2 → 0.5.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.3
4
+
5
+ ### Fixes
6
+
7
+ - **Inherited parent-team attach warnings** — forked/branched child sessions now silently detach back to their own session team when they briefly inherit a parent team id without any attach claim. This removes the noisy warning seen in subagent-style flows while preserving normal `not_owner` warnings for real claim conflicts.
8
+
3
9
  ## 0.5.2
4
10
 
5
11
  ### Fixes
@@ -33,6 +33,7 @@ import {
33
33
  } from "./hooks.js";
34
34
  import { handleTeamCommand } from "./leader-team-command.js";
35
35
  import { registerTeamsTool } from "./leader-teams-tool.js";
36
+ import { getParentSessionId, shouldSilenceInheritedParentAttachClaimWarning } from "./session-parent.js";
36
37
  import type { ContextMode, SpawnTeammateFn, SpawnTeammateResult, WorkspaceMode } from "./spawn-types.js";
37
38
 
38
39
  function getTeamsExtensionEntryPath(): string | null {
@@ -155,6 +156,7 @@ export function runLeader(pi: ExtensionAPI): void {
155
156
  let delegateMode = process.env.PI_TEAMS_DELEGATE_MODE === "1";
156
157
  let style: TeamsStyle = getTeamsStyleFromEnv();
157
158
  let lastAttachClaimHeartbeatMs = 0;
159
+ let inheritedParentTeamId: string | null = null;
158
160
 
159
161
  const stopLoops = () => {
160
162
  if (refreshTimer) clearInterval(refreshTimer);
@@ -180,13 +182,22 @@ export function runLeader(pi: ExtensionAPI): void {
180
182
  const result = await heartbeatTeamAttachClaim(getTeamDir(currentTeamId), sessionTeamId);
181
183
  if (result === "updated") return;
182
184
 
183
- ctx.ui.notify(
184
- `Attach claim for team ${currentTeamId} is no longer owned by this session; detaching to session team.`,
185
- "warning",
186
- );
185
+ const lostTeamId = currentTeamId;
186
+ const shouldSilenceWarning = shouldSilenceInheritedParentAttachClaimWarning({
187
+ currentTeamId: lostTeamId,
188
+ parentSessionId: inheritedParentTeamId,
189
+ result,
190
+ });
191
+ inheritedParentTeamId = null;
187
192
  currentTeamId = sessionTeamId;
188
193
  taskListId = sessionTeamId;
189
194
  delegationTracker.clear();
195
+ if (!shouldSilenceWarning) {
196
+ ctx.ui.notify(
197
+ `Attach claim for team ${lostTeamId} is no longer owned by this session; detaching to session team.`,
198
+ "warning",
199
+ );
200
+ }
190
201
  await refreshTasks();
191
202
  renderWidget();
192
203
  };
@@ -709,6 +720,7 @@ export function runLeader(pi: ExtensionAPI): void {
709
720
  pi.on("session_start", async (_event, ctx) => {
710
721
  currentCtx = ctx;
711
722
  currentTeamId = currentCtx.sessionManager.getSessionId();
723
+ inheritedParentTeamId = getParentSessionId(currentCtx.sessionManager);
712
724
  // Keep the task list aligned with the active session. If you want a shared namespace,
713
725
  // use `/team task use <taskListId>` after switching.
714
726
  taskListId = currentTeamId;
@@ -792,6 +804,7 @@ export function runLeader(pi: ExtensionAPI): void {
792
804
 
793
805
  currentCtx = ctx;
794
806
  currentTeamId = currentCtx.sessionManager.getSessionId();
807
+ inheritedParentTeamId = getParentSessionId(currentCtx.sessionManager);
795
808
  // Keep the task list aligned with the active session. If you want a shared namespace,
796
809
  // use `/team task use <taskListId>` after switching.
797
810
  taskListId = currentTeamId;
@@ -1072,6 +1085,7 @@ export function runLeader(pi: ExtensionAPI): void {
1072
1085
  getActiveTeamId: () => currentTeamId ?? ctx.sessionManager.getSessionId(),
1073
1086
  setActiveTeamId: (teamId) => {
1074
1087
  currentTeamId = teamId;
1088
+ inheritedParentTeamId = null;
1075
1089
  delegationTracker.clear();
1076
1090
  },
1077
1091
  pendingPlanApprovals,
@@ -0,0 +1,24 @@
1
+ import { SessionManager } from "@mariozechner/pi-coding-agent";
2
+ import type { TeamAttachClaimHeartbeatResult } from "./team-attach-claim.js";
3
+
4
+ interface SessionManagerWithHeader {
5
+ getHeader(): { parentSession?: string } | null;
6
+ }
7
+
8
+ export function getParentSessionId(sessionManager: SessionManagerWithHeader): string | null {
9
+ const parentSessionPath = sessionManager.getHeader()?.parentSession;
10
+ if (!parentSessionPath) return null;
11
+ try {
12
+ return SessionManager.open(parentSessionPath).getSessionId();
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+
18
+ export function shouldSilenceInheritedParentAttachClaimWarning(opts: {
19
+ currentTeamId: string;
20
+ parentSessionId: string | null;
21
+ result: TeamAttachClaimHeartbeatResult;
22
+ }): boolean {
23
+ return opts.result === "missing" && opts.parentSessionId !== null && opts.currentTeamId === opts.parentSessionId;
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmustier/pi-agent-teams",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Claude Code agent teams style workflow for Pi.",
5
5
  "license": "MIT",
6
6
  "author": "Thomas Mustier",
@@ -70,7 +70,9 @@ import {
70
70
  isPlanRejectedMessage,
71
71
  } from "../extensions/teams/protocol.js";
72
72
  import { pollLeaderInbox } from "../extensions/teams/leader-inbox.js";
73
- import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
73
+ import { getParentSessionId, shouldSilenceInheritedParentAttachClaimWarning } from "../extensions/teams/session-parent.js";
74
+ import { SessionManager, type ExtensionContext } from "@mariozechner/pi-coding-agent";
75
+ import type { AssistantMessage } from "@mariozechner/pi-ai";
74
76
 
75
77
  // ── helpers ──────────────────────────────────────────────────────────
76
78
  let passed = 0;
@@ -845,6 +847,67 @@ console.log("\n10. team discovery + attach claims");
845
847
  }
846
848
  }
847
849
 
850
+ // ── 10b. branched sessions + inherited attach claims ────────────────
851
+ console.log("\n10b. branched sessions + inherited attach claims");
852
+ {
853
+ const sessionsDir = path.join(tmpRoot, "branch-session-test");
854
+ const parent = SessionManager.create(tmpRoot, sessionsDir);
855
+ const assistantMessage: AssistantMessage = {
856
+ role: "assistant",
857
+ content: [{ type: "text", text: "ok" }],
858
+ api: "test",
859
+ provider: "test",
860
+ model: "test",
861
+ usage: {
862
+ input: 0,
863
+ output: 0,
864
+ cacheRead: 0,
865
+ cacheWrite: 0,
866
+ totalTokens: 0,
867
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
868
+ },
869
+ stopReason: "stop",
870
+ timestamp: Date.now(),
871
+ };
872
+ parent.appendMessage(assistantMessage);
873
+ const parentLeafId = parent.getLeafId();
874
+ const originalParentSessionId = parent.getSessionId();
875
+ assert(parentLeafId !== null, "branch test parent has a leaf entry");
876
+ if (parentLeafId) {
877
+ const branchedPath = parent.createBranchedSession(parentLeafId);
878
+ assert(branchedPath !== null, "createBranchedSession returns child session path");
879
+ if (branchedPath) {
880
+ const child = SessionManager.open(branchedPath, sessionsDir);
881
+ const parentSessionId = getParentSessionId(child);
882
+ assertEq(parentSessionId, originalParentSessionId, "getParentSessionId resolves branch parent session id");
883
+ assert(
884
+ shouldSilenceInheritedParentAttachClaimWarning({
885
+ currentTeamId: originalParentSessionId,
886
+ parentSessionId,
887
+ result: "missing",
888
+ }),
889
+ "silences missing inherited parent-team claim warnings",
890
+ );
891
+ assert(
892
+ !shouldSilenceInheritedParentAttachClaimWarning({
893
+ currentTeamId: originalParentSessionId,
894
+ parentSessionId,
895
+ result: "not_owner",
896
+ }),
897
+ "keeps non-owner inherited parent-team warnings visible",
898
+ );
899
+ assert(
900
+ !shouldSilenceInheritedParentAttachClaimWarning({
901
+ currentTeamId: child.getSessionId(),
902
+ parentSessionId,
903
+ result: "missing",
904
+ }),
905
+ "does not silence unrelated missing-claim warnings",
906
+ );
907
+ }
908
+ }
909
+ }
910
+
848
911
  // ── 11. /team done (end-of-run cleanup) ──────────────────────────────
849
912
  console.log("\n11. /team done (end-of-run)");
850
913
  {