pi-cohort 5.1.1 → 5.1.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,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.1.3] - 2026-08-18
4
+
5
+ ### Fixed
6
+
7
+ - Foreground control notices are steered to a turn boundary while the session
8
+ is streaming instead of splicing into an open tool cycle (which corrupted
9
+ the session with a duplicated `tool_use_id`); idle delivery still appends
10
+ without triggering a turn. (#7)
11
+
12
+ ### Changed
13
+
14
+ - `dir` no longer advertised by the subagent tool schema (follows `runId`,
15
+ #5) - still accepted at runtime for async status/resume, `id` preferred.
16
+
17
+ ## [5.1.2] - 2026-08-07
18
+
19
+ ### Changed
20
+
21
+ - Schema diet round three (subagent tool schema 9,483 -> 8,246 bytes serialized):
22
+ `tasks[]` items collapsed to the round-two stub form (overrides pass through,
23
+ documented in the pi-cohort skill), `ChainItem` allOf conditionals removed
24
+ (runtime-enforced at chain parse), and `runId` no longer advertised by the
25
+ tool schema - still accepted at runtime, `id` preferred.
26
+
3
27
  ## [5.1.1] - 2026-08-07
4
28
 
5
29
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cohort",
3
- "version": "5.1.1",
3
+ "version": "5.1.3",
4
4
  "description": "Delegate Pi work to focused child agents: code review, scouting, implementation, parallel audits, saved chains, and background jobs.",
5
5
  "author": "Jacek Juraszek",
6
6
  "license": "MIT",
@@ -36,8 +36,8 @@
36
36
  "scripts": {
37
37
  "check:agents-core": "node scripts/check-agents-core.mjs",
38
38
  "test": "npm run test:unit",
39
- "test:unit": "node --experimental-strip-types --test test/unit/*.test.ts",
40
- "test:integration": "node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/integration/*.test.ts",
39
+ "test:unit": "node --test test/unit/*.test.ts",
40
+ "test:integration": "node --import ./test/support/register-loader.mjs --test test/integration/*.test.ts",
41
41
  "test:all": "npm run check:agents-core && npm run test:unit && npm run test:integration"
42
42
  },
43
43
  "pi": {
@@ -39,6 +39,7 @@ function deliverControlNotice(input: {
39
39
  pi: Pick<ExtensionAPI, "sendMessage">;
40
40
  visibleControlNotices: Set<string>;
41
41
  details: SubagentControlMessageDetails;
42
+ isIdle: () => boolean;
42
43
  }): void {
43
44
  const childIntercomTarget = controlNoticeTarget(input.details);
44
45
  const key = controlNotificationKey(input.details.event, childIntercomTarget);
@@ -52,7 +53,7 @@ function deliverControlNotice(input: {
52
53
  display: true,
53
54
  details: { ...input.details, childIntercomTarget, noticeText },
54
55
  },
55
- { triggerTurn: input.details.source !== "foreground" },
56
+ { triggerTurn: input.details.source !== "foreground" || !input.isIdle() },
56
57
  );
57
58
  }
58
59
 
@@ -72,8 +73,9 @@ export function handleSubagentControlNotice(input: {
72
73
  foregroundDelayMs?: number;
73
74
  }): void {
74
75
  if (!input.details?.event || input.details.event.type === "active_long_running") return;
76
+ const isIdle = () => input.state.lastUiContext?.isIdle() ?? false;
75
77
  if (input.details.source !== "foreground") {
76
- deliverControlNotice(input);
78
+ deliverControlNotice({ ...input, isIdle });
77
79
  return;
78
80
  }
79
81
 
@@ -85,7 +87,7 @@ export function handleSubagentControlNotice(input: {
85
87
  const timer = setTimeout(() => {
86
88
  pending.delete(timerKey);
87
89
  if (!isForegroundNoticeStillActionable(input.state, input.details)) return;
88
- deliverControlNotice(input);
90
+ deliverControlNotice({ ...input, isIdle });
89
91
  }, input.foregroundDelayMs ?? 1000);
90
92
  timer.unref?.();
91
93
  pending.set(timerKey, timer);
@@ -183,10 +183,13 @@ function parseSubagentNotifyContent(content: string): SubagentNotifyDetails | un
183
183
  }
184
184
 
185
185
  class SubagentControlNoticeComponent implements Component {
186
- constructor(
187
- private readonly details: SubagentControlMessageDetails,
188
- private readonly theme: ExtensionContext["ui"]["theme"],
189
- ) {}
186
+ private readonly details: SubagentControlMessageDetails;
187
+ private readonly theme: ExtensionContext["ui"]["theme"];
188
+
189
+ constructor(details: SubagentControlMessageDetails, theme: ExtensionContext["ui"]["theme"]) {
190
+ this.details = details;
191
+ this.theme = theme;
192
+ }
190
193
 
191
194
  invalidate(): void {}
192
195
 
@@ -441,7 +444,7 @@ Example: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {agent:"agent-b", t
441
444
 
442
445
  MANAGEMENT: action=list/get/create/update/delete (chainName for chains; packaged agents use dotted names); config fields: pi-cohort skill reference/config-fields.md.
443
446
 
444
- CONTROL: action=status/interrupt/resume (id/runId, message, index); details: pi-cohort skill.
447
+ CONTROL: action=status/interrupt/resume (id, message, index); details: pi-cohort skill.
445
448
 
446
449
  DIAGNOSTICS:
447
450
  • { action: "doctor" } - read-only report for runtime paths, discovery, sessions, and intercom`,
@@ -137,18 +137,22 @@ const AcceptanceOverrideStub = Type.Unsafe({
137
137
  description: "Acceptance override; same shape as top-level acceptance.",
138
138
  });
139
139
 
140
- const TaskItem = Type.Object({
141
- agent: Type.String(),
142
- task: Type.String(),
143
- cwd: Type.Optional(Type.String()),
144
- count: Type.Optional(Type.Integer({ minimum: 1, description: "Repeat N times (same settings)." })),
145
- output: Type.Optional(brief(OutputOverride, "Output file path, or false.")),
146
- outputMode: Type.Optional(brief(OutputModeOverride, "Default: inline.")),
147
- reads: Type.Optional(ReadsOverride),
148
- progress: Type.Optional(Type.Boolean({ description: "true enables progress.md tracking; omit or false disables." })),
149
- model: Type.Optional(Type.String()),
150
- skill: Type.Optional(brief(SkillOverride, "Skill override.")),
151
- acceptance: Type.Optional(AcceptanceOverrideStub),
140
+ // tasks[] stub (round three): same treatment as ParallelTaskSchema below; structural keys
141
+ // stay explicit (agent/task required, count = arity); every per-task override (model, output,
142
+ // outputMode, reads, progress, skill, cwd, acceptance) passes through additionalProperties
143
+ // and is documented in the pi-cohort skill. No `as` (no {outputs.name} wiring here) and no
144
+ // `label` (TaskParam has no such field at this position). Widening-only: unknown keys were
145
+ // already ignored at runtime.
146
+ const TaskItem = Type.Unsafe({
147
+ type: "object",
148
+ additionalProperties: true,
149
+ required: ["agent", "task"],
150
+ properties: {
151
+ agent: { type: "string" },
152
+ task: { type: "string" },
153
+ count: { type: "integer", minimum: 1, description: "Repeat N times (same settings)." },
154
+ },
155
+ description: "Per-task overrides (model, output, reads, skill, ...): pi-cohort skill.",
152
156
  });
153
157
 
154
158
  // Parallel-item stubs (round two): structural/wiring keys stay explicit (agent/task,
@@ -232,11 +236,6 @@ const ChainItem = Type.Object({
232
236
  }, {
233
237
  description: "{agent,task?} seq; {parallel:[..]} concurrent; {expand,parallel,collect} fanout.",
234
238
  additionalProperties: false,
235
- allOf: [
236
- { if: { required: ["expand"] }, then: { required: ["parallel", "collect"], properties: { parallel: { type: "object" } } } },
237
- { if: { required: ["collect"] }, then: { required: ["expand", "parallel"], properties: { parallel: { type: "object" } } } },
238
- { not: { required: ["expand"], properties: { parallel: { type: "array", items: {} } } } },
239
- ],
240
239
  });
241
240
 
242
241
  // Control stub (round two): 10 fields collapsed; the full table lives in the pi-cohort
@@ -260,12 +259,6 @@ export const SubagentParams = Type.Object({
260
259
  id: Type.Optional(Type.String({
261
260
  description: "Run id/prefix for status/interrupt/resume."
262
261
  })),
263
- runId: Type.Optional(Type.String({
264
- description: "Run ID (interrupt/resume); defaults to latest. Prefer id."
265
- })),
266
- dir: Type.Optional(Type.String({
267
- description: "Async run dir for status/resume."
268
- })),
269
262
  index: Type.Optional(Type.Integer({ minimum: 0, description: "Zero-based index for per-child actions." })),
270
263
  message: Type.Optional(Type.String({ description: "Follow-up message for resume." })),
271
264
  // Chain identifier for management (can't reuse 'chain' — that's the execution array)