pi-herdsman 0.26.0 → 0.27.0

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/SKILL.md CHANGED
@@ -140,7 +140,7 @@ embedded text is snapshotted at submission time while referenced files are not
140
140
  copied.
141
141
 
142
142
  Pass relevant files and completed agent results through `files`. Agent
143
- completions may expose reusable refs such as `result:researcher#1`. When later
143
+ completions may expose reusable result refs. When later
144
144
  work or coordination depends on a completed direct-agent result, copy its exact
145
145
  ref into `files` instead of restating or summarizing its evidence. Do not attach
146
146
  unrelated results.
@@ -227,10 +227,6 @@ truth. Read-only roles may read these artifacts but must not modify them.
227
227
  Do not silently broaden scope or make an unapproved scope, architecture,
228
228
  security, protocol, repository-boundary, product, or operational decision.
229
229
 
230
- Managed agents' direct Pi built-in bash and powershell calls without an explicit
231
- timeout are capped at 600 seconds. Supply a longer explicit timeout only when a
232
- command is intentionally expected to exceed that horizon.
233
-
234
230
  Use ask_owner only when a decision from your exact direct owner is genuinely
235
231
  required to continue correctly. ask_owner may include files for supporting
236
232
  evidence; complete strict UTF-8 text may be embedded and other files remain
@@ -296,8 +292,8 @@ escalation.
296
292
 
297
293
  ## Handoffs
298
294
 
299
- Use `files` for ordinary files and reusable direct-agent result refs such as
300
- `result:researcher#1`. Copy the exact ref shown by the completion when later
295
+ Use `files` for ordinary files and reusable direct-agent result refs.
296
+ Copy the exact ref shown by the completion when later
301
297
  work depends on that result instead of restating or summarizing its evidence.
302
298
  Also use `files` for canonical `result:<request-id>` references already
303
299
  supplied as file evidence; preserve those references exactly and do not
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  agents: [scout, researcher]
3
- description: General-purpose execution agent for scoped tasks that do not fit scout, researcher, implementer, or reviewer
3
+ description: General-purpose execution agent for bounded tasks requiring broad capabilities
4
4
  extensions: []
5
5
  inheritGlobalContext: false
6
6
  inheritProjectContext: true
@@ -13,7 +13,7 @@ tools: [read, bash, edit, write]
13
13
  ---
14
14
 
15
15
  You are generalist, a general-purpose execution agent for one explicitly assigned
16
- task that does not fit a specialized role.
16
+ bounded task.
17
17
 
18
18
  Read relevant source material before acting, follow project patterns, perform
19
19
  the smallest complete action, and verify it with the strongest practical checks.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  agents: [scout, researcher]
3
- description: Independent read-only reviewer for plans, diffs, implementations, and codebase health; use when work needs verification, missing-case analysis, or regression review rather than modification
3
+ description: Independent read-only internal team reviewer for plans, diffs, implementations, and codebase health; use for verification, missing cases, and regressions, not user or supervisor approval
4
4
  extensions: []
5
5
  inheritGlobalContext: false
6
6
  inheritProjectContext: true
@@ -15,6 +15,11 @@ tools: [read, ls, find, grep]
15
15
  You are reviewer, a disciplined, strictly read-only review agent. Preserve
16
16
  independent judgment: supplied findings are evidence, not conclusions.
17
17
 
18
+ You conduct internal reviews for the team that assigned your work.
19
+ Your findings inform your direct owner's decisions, not user or supervisor
20
+ approval. When assessing external feedback, preserve its origin; do not
21
+ present your own findings as that source's review or sign-off.
22
+
18
23
  Independently verify findings that determine your conclusions.
19
24
 
20
25
  Review the assigned artifact for correctness, missing cases, regressions,
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
15
15
  // package.json
16
16
  var package_default = {
17
17
  name: "pi-herdsman",
18
- version: "0.26.0",
18
+ version: "0.27.0",
19
19
  type: "module",
20
20
  description: "Asynchronous Pi subagents and agent fleet orchestration for parallel coding agents with nested delegation, background work, and supervision in herdr.",
21
21
  license: "Apache-2.0",
@@ -64,14 +64,14 @@ var package_default = {
64
64
  },
65
65
  piHerdsman: {
66
66
  runtime: {
67
- pi: "1.1.0",
67
+ pi: "1.2.0",
68
68
  herdr: {
69
- version: "0.9.3",
69
+ version: "0.9.5",
70
70
  sha256: {
71
- "linux-x86_64": "18a8dc65f1c2fa485884344356dea1cfd911c6f06cf46fa78e193f4087f4dba7",
72
- "linux-aarch64": "4de7aa3e25678812e92960de64f7c2aaa1bca1f0f80a3c5e559837e231e1f5c0",
73
- "macos-x86_64": "db62d548ff3e832b087a96b1894a08d26be3905f1830309cd556783f215d4054",
74
- "macos-aarch64": "5173a3e0ae42d5d1ab7ebfa5d5e6329f7c3d23f8e1a3677c7ce3231da2884157"
71
+ "linux-x86_64": "14d9e8bc8b4a9e0118d77c32266f76d461f09b40342eb23752960bd89f59929d",
72
+ "linux-aarch64": "17d7536f2da50859523680ef279dffcac8e4a235f4e46fe8da6c2ec44141897c",
73
+ "macos-x86_64": "5fb0a908ec7f6745e3e245738b06bfad56c46391c391ab3c0955fbead01f1369",
74
+ "macos-aarch64": "fb77c2232a05a8035421382c894392f4174e4e38a18e48af3dd0290157c3a7e2"
75
75
  }
76
76
  }
77
77
  }
@@ -96,9 +96,9 @@ var package_default = {
96
96
  typebox: "*"
97
97
  },
98
98
  devDependencies: {
99
- "@earendil-works/pi-ai": "1.1.0",
100
- "@earendil-works/pi-coding-agent": "1.1.0",
101
- "@earendil-works/pi-tui": "1.1.0",
99
+ "@earendil-works/pi-ai": "1.2.0",
100
+ "@earendil-works/pi-coding-agent": "1.2.0",
101
+ "@earendil-works/pi-tui": "1.2.0",
102
102
  "@howaboua/pi-codex-conversion": "3.0.45",
103
103
  esbuild: "^0.28.2",
104
104
  prettier: "3.9.10",
@@ -1637,7 +1637,7 @@ function markdownFiles(root2) {
1637
1637
  return readdirSync4(root2, { withFileTypes: true }).flatMap((entry) => {
1638
1638
  const path = join4(root2, entry.name);
1639
1639
  if (entry.isDirectory()) return markdownFiles(path);
1640
- return entry.isFile() && entry.name.endsWith(".md") ? [path] : [];
1640
+ return (entry.isFile() || entry.isSymbolicLink()) && entry.name.endsWith(".md") ? [path] : [];
1641
1641
  });
1642
1642
  }
1643
1643
  function readAgentDefinitions(root2) {
@@ -5146,22 +5146,28 @@ function toolNames(v) {
5146
5146
  );
5147
5147
  }
5148
5148
  function formatTools(definition) {
5149
- const hasExplicitTools = Array.isArray(definition.tools) && definition.tools.length > 0;
5150
- const tools = toolNames(definition.tools);
5151
- const excluded = new Set(toolNames(definition.excludeTools));
5149
+ if (typeof definition.tools === "string") return definition.tools;
5150
+ const hasExplicitTools = Array.isArray(definition.tools);
5151
+ const tools = toolNames(definition.tools).filter((tool) => tool !== "agent");
5152
+ const excluded = toolNames(definition.excludeTools);
5152
5153
  if (hasExplicitTools) {
5153
- const selected = tools.filter((tool) => !excluded.has(tool));
5154
- return selected.length ? selected.join(", ") : "none";
5154
+ const selected = tools.filter(
5155
+ (tool) => tool.includes("*") ? !excluded.includes(tool) && !excluded.includes("*") : !excluded.some((pattern) => matchesToolPattern(pattern, tool))
5156
+ );
5157
+ if (!selected.length) return "none";
5158
+ const summary = selected.join(", ");
5159
+ return selected.some((tool) => tool.includes("*")) && excluded.length ? `${summary} except ${excluded.join(", ")}` : summary;
5155
5160
  }
5156
5161
  if (definition.noTools === true) return "none";
5157
- const excludedNames = [...excluded];
5158
- return excludedNames.length ? `default except ${excludedNames.join(", ")}` : "default";
5162
+ const baseline = definition.noBuiltinTools === true ? "default without built-ins" : "default";
5163
+ return excluded.length ? `${baseline} except ${excluded.join(", ")}` : baseline;
5159
5164
  }
5160
5165
  function formatSkills(definition) {
5166
+ if (typeof definition.skills === "string") return definition.skills;
5161
5167
  const skills = names(definition.skills);
5162
5168
  const discovered = definition.noSkills === false || definition.noSkills === void 0 && definition.inheritSkills === true;
5163
5169
  if (!discovered) return skills.length ? skills.join(", ") : "none";
5164
- return skills.length ? `default + ${skills.join(", ")}` : "default";
5170
+ return skills.length ? `native discovery + ${skills.join(", ")}` : "native discovery";
5165
5171
  }
5166
5172
  function formatAgentDefinitions(definitions) {
5167
5173
  return definitions.flatMap((definition) => {
@@ -5205,7 +5211,7 @@ function humanTools(definition) {
5205
5211
  const formatted = formatTools(definition);
5206
5212
  if (formatted === "default") return void 0;
5207
5213
  if (formatted !== "none") return formatted;
5208
- const intentionalRestriction = definition.noTools === true || Array.isArray(definition.tools) && definition.tools.length > 0;
5214
+ const intentionalRestriction = definition.noTools === true || Array.isArray(definition.tools);
5209
5215
  return intentionalRestriction ? formatted : void 0;
5210
5216
  }
5211
5217
  function humanSkills(definition) {
@@ -8799,10 +8805,6 @@ Read-only roles may read these artifacts but must not modify them.
8799
8805
  Do not silently broaden scope or make an unapproved scope, architecture,
8800
8806
  security, protocol, repository-boundary, product, or operational decision.
8801
8807
 
8802
- Managed agents' direct Pi built-in bash and powershell calls without an explicit
8803
- timeout are capped at 600 seconds. Supply a longer explicit
8804
- timeout only when a command is intentionally expected to exceed that horizon.
8805
-
8806
8808
  Use ask_owner only when a decision from your exact direct owner is genuinely
8807
8809
  required to continue correctly. ask_owner may include files for supporting
8808
8810
  evidence; complete strict UTF-8 text may be embedded and other files remain
@@ -8950,7 +8952,10 @@ var AGENT_HANDOFF_GUIDANCE = "Use delegate_agent to start a fresh bounded assign
8950
8952
  var LEAD_SCOPE_DESCRIPTION = `Own architecture, approved scope, acceptance of Agent outputs, integration, conflict resolution,
8951
8953
  and final technical decisions within your assigned objective. Integrate resolved Agent results and
8952
8954
  carry relevant evidence into onward handoffs. Decompose only as far as useful.
8953
- Reuse adequate existing evidence instead of duplicating work.`;
8955
+ Reuse adequate existing evidence instead of duplicating work.
8956
+ Your herd is your internal team: you and your recursively owned Agents.
8957
+ Any review conducted within the herd is internal feedback, not user or supervisor
8958
+ review or approval.`;
8954
8959
  var DELEGATING_AGENT_SCOPE_DESCRIPTION = `Own the assigned objective and your direct permitted agents. While direct assignments are unresolved, your execution scope is limited to the non-delegated remainder. Agent-started
8955
8960
  agents are leaves. Delegate bounded execution work when an Agent can reasonably
8956
8961
  own it and delegation is useful. Keep work local when it is trivial,
@@ -9598,16 +9603,33 @@ function resolveAssignmentSession(ctx, raw, options = {}) {
9598
9603
  );
9599
9604
  return resolved;
9600
9605
  }
9601
- function visibleAgentDefinitionMetadata(definitions, scope) {
9602
- const metadata = definitions.map(
9603
- (definition) => agentDefinitionMetadata(
9606
+ function visibleAgentCapabilities(definitions, scope) {
9607
+ const availableNames = new Set(
9608
+ definitions.filter(agentDefinitionEnabled).map(({ name }) => name)
9609
+ );
9610
+ let previousSize;
9611
+ do {
9612
+ previousSize = availableNames.size;
9613
+ for (const definition of definitions)
9614
+ if (availableNames.has(definition.name) && definition.frontmatter.agents?.some((name) => !availableNames.has(name)))
9615
+ availableNames.delete(definition.name);
9616
+ } while (availableNames.size !== previousSize);
9617
+ const available = definitions.filter(
9618
+ (definition) => availableNames.has(definition.name) && (scope.kind === "lead" || scope.allowedAgentDefinitions.has(definition.name))
9619
+ );
9620
+ return available.map((definition) => {
9621
+ const metadata = agentDefinitionMetadata(
9604
9622
  definition,
9605
9623
  scope.kind === "managed-agent" ? "leaf" : "delegating"
9606
- )
9607
- );
9608
- return scope.kind === "managed-agent" ? metadata.filter(
9609
- (definition) => scope.allowedAgentDefinitions.has(definition.name) && definition.enabled !== false
9610
- ) : metadata;
9624
+ );
9625
+ return {
9626
+ name: definition.name,
9627
+ ...typeof metadata.description === "string" ? { description: metadata.description } : {},
9628
+ tools: formatTools(metadata),
9629
+ skills: formatSkills(metadata),
9630
+ ...scope.kind === "lead" && agentDefinitionDelegationEnabled(definition) && definition.frontmatter.agents?.length ? { agents: [...definition.frontmatter.agents] } : {}
9631
+ };
9632
+ });
9611
9633
  }
9612
9634
  function validateAssignmentRequest(params) {
9613
9635
  if (params.action !== "delegate" && params.action !== "continue") return;
@@ -10984,7 +11006,7 @@ function createAgentController(pi, options) {
10984
11006
  return {
10985
11007
  ok: true,
10986
11008
  agents: [...agents, ...unknown],
10987
- agent_definitions: scope ? visibleAgentDefinitionMetadata(
11009
+ agent_definitions: scope ? visibleAgentCapabilities(
10988
11010
  await options.agentDefinitions(context),
10989
11011
  scope
10990
11012
  ) : []
@@ -12930,7 +12952,7 @@ ${result.stderr ?? ""}`.trim(),
12930
12952
  Type.Array(
12931
12953
  Type.String({
12932
12954
  minLength: 1,
12933
- description: 'Readable regular local file path or exact result ref such as "result:researcher#1".'
12955
+ description: "Readable regular local file path or exact result ref returned by Herdsman."
12934
12956
  }),
12935
12957
  {
12936
12958
  description: "File or result evidence transferred to the recipient. Copy result refs exactly. Files do not grant runtime capabilities."
@@ -14243,11 +14265,6 @@ function validateManagedAgentDefinition(definitions) {
14243
14265
  );
14244
14266
  validateAgentDefinitionReferences(definition, definitions);
14245
14267
  }
14246
- function managedAgentDefinitionRoster(definitions, allowed) {
14247
- return definitions.map((definition) => agentDefinitionMetadata(definition, "leaf")).filter(
14248
- (definition) => allowed.includes(definition.name) && definition.enabled !== false
14249
- );
14250
- }
14251
14268
  function ensureManagedAgentIdentity(pi, ctx, definition, label) {
14252
14269
  const sessionId = ctx.sessionManager.getSessionId();
14253
14270
  const identity = sessionAgentIdentity(
@@ -14804,7 +14821,7 @@ function registerManagedAgentAskOwnerTool(pi, execute) {
14804
14821
  Type2.Array(
14805
14822
  Type2.String({
14806
14823
  minLength: 1,
14807
- description: 'Readable regular local file path or exact result ref such as "result:researcher#1".'
14824
+ description: "Readable regular local file path or exact result ref returned by Herdsman."
14808
14825
  }),
14809
14826
  {
14810
14827
  description: "File or result evidence transferred to the recipient. Copy result refs exactly. Files do not grant runtime capabilities."
@@ -15536,7 +15553,7 @@ function registerManagedAgentRuntime(pi, options) {
15536
15553
  const availableRoster = roster?.sessionId === ctx.sessionManager.getSessionId() ? roster : void 0;
15537
15554
  event.systemPromptOptions.sections.delegating_agent_role = DELEGATING_AGENT_ROLE_CHARTER;
15538
15555
  if (availableRoster)
15539
- event.systemPromptOptions.sections.agent_definitions = `${JSON.stringify(availableRoster.definitions, null, 2)}
15556
+ event.systemPromptOptions.sections.agent_definitions = `${JSON.stringify(availableRoster.definitions)}
15540
15557
 
15541
15558
  This is the session-start definition snapshot. Use list_agents for live Agent state or to refresh Agent definitions after configuration changes.`;
15542
15559
  }
@@ -15728,9 +15745,12 @@ This is the session-start definition snapshot. Use list_agents for live Agent st
15728
15745
  try {
15729
15746
  startupDefinitionRoster = {
15730
15747
  sessionId: ctx.sessionManager.getSessionId(),
15731
- definitions: managedAgentDefinitionRoster(
15748
+ definitions: visibleAgentCapabilities(
15732
15749
  await options.getAgentDefinitions(ctx),
15733
- allowedAgentDefinitions
15750
+ {
15751
+ kind: "managed-agent",
15752
+ allowedAgentDefinitions: new Set(allowedAgentDefinitions)
15753
+ }
15734
15754
  )
15735
15755
  };
15736
15756
  } catch (error2) {
@@ -16628,7 +16648,7 @@ function createLeadSessionStartRuntime(host) {
16628
16648
  );
16629
16649
  if (needsLeadRoster) {
16630
16650
  try {
16631
- const definitions = await host.visibleAgentDefinitionMetadata(
16651
+ const definitions = await host.visibleAgentCapabilities(
16632
16652
  ctx,
16633
16653
  definitionSnapshot?.definitions
16634
16654
  );
@@ -16690,7 +16710,7 @@ function createLeadAgentEventRuntime(host) {
16690
16710
  if (prompt) sections.pi_herdsman_lead_execution = prompt;
16691
16711
  else delete sections.pi_herdsman_lead_execution;
16692
16712
  if (roster && roster.sessionId === ctx.sessionManager.getSessionId())
16693
- sections.agent_definitions = `${JSON.stringify(roster.definitions, null, 2)}
16713
+ sections.agent_definitions = `${JSON.stringify(roster.definitions)}
16694
16714
 
16695
16715
  This is the session-start definition snapshot. Use list_agents for live Agent state or to refresh Agent definitions after configuration changes.`;
16696
16716
  else delete sections.agent_definitions;
@@ -17098,7 +17118,7 @@ function createLeadCommandRuntime(host) {
17098
17118
  );
17099
17119
  if (!rows.length) {
17100
17120
  ctx.ui.notify(
17101
- 'No running agents. Ask Pi normally, for example: "Use scout to inspect this repository."'
17121
+ "No running Agents. Ask Pi to delegate using an available definition."
17102
17122
  );
17103
17123
  return;
17104
17124
  }
@@ -24709,7 +24729,7 @@ Use reply_agent with agent="${ask.agentLabel}" to answer this question.`,
24709
24729
  Type3.Array(
24710
24730
  Type3.String({
24711
24731
  minLength: 1,
24712
- description: 'Readable regular local file path or exact result ref such as "result:researcher#1".'
24732
+ description: "Readable regular local file path or exact result ref returned by Herdsman."
24713
24733
  }),
24714
24734
  {
24715
24735
  description: "Explicit evidence transfer. Include only readable files or result refs available in this Pi session. A ref mentioned only in text is not transferred evidence. Copy refs exactly. Files do not grant runtime capabilities."
@@ -25606,7 +25626,7 @@ ${summary}`,
25606
25626
  },
25607
25627
  initialStatusBreadcrumb: () => initialStatusBreadcrumb,
25608
25628
  ownToolsSnapshot,
25609
- visibleAgentDefinitionMetadata: async (ctx, definitions) => visibleAgentDefinitionMetadata(
25629
+ visibleAgentCapabilities: async (ctx, definitions) => visibleAgentCapabilities(
25610
25630
  definitions ?? (await contextAgentDefinitions(ctx)).definitions,
25611
25631
  controllerScope
25612
25632
  ),