@henryqw/pi-subagent 15.1.2 → 15.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/README.md CHANGED
@@ -80,6 +80,10 @@ See the [orchestration guide](./docs/orchestration.md) for full delegation, tran
80
80
 
81
81
  The bundled [`pi-subagent-delegated-development`](./skills/pi-subagent-delegated-development/SKILL.md) Skill guides Main's planning and orchestration. It adds no runtime code, config, or Role installation.
82
82
 
83
+ Implementers remove only task-created temporary, generated, or ignored artifacts. Required deliverables and unrelated files stay intact. They never use `git clean` or blanket deletion, and unclear paths block.
84
+
85
+ For known regressions with a runner that supports test-name filtering, use a test-name filter. Keep broad package or workspace checks to one caller-owned final validation after relevant units integrate. Flow itself does not run that check.
86
+
83
87
  Before delegating:
84
88
 
85
89
  - Find concrete outcomes that can ship on their own.
@@ -110,12 +110,12 @@ Flow has no dependency graph, saved state, automatic retry, aggregate review, or
110
110
 
111
111
  ## Per-delegation resources and isolation
112
112
 
113
- For `delegate_task`, every single entry, parallel sibling, and chain step independently:
113
+ `delegate_task` first preflights every requested Role name, so an initially unknown Role starts no sibling. Then, after receiving an executor permit, every single entry, parallel sibling, and chain step independently:
114
114
 
115
- 1. loads its selected Role;
116
- 2. resolves its route and named Skills from the latest effective Pi context after receiving an executor permit;
115
+ 1. reloads its effective Role by requested name;
116
+ 2. resolves its route and named Skills from the latest effective Pi context;
117
117
  3. creates its Role launch policy; and
118
- 4. when the Role requests `isolation: worktree`, creates a worktree identified by the tool call, mode, and input index.
118
+ 4. when the reloaded Role requests `isolation: worktree`, creates a worktree identified by the tool call, mode, and input index.
119
119
 
120
120
  Separate deterministic identities produce separate worktree paths and branches. Parallel siblings cannot collide, and a chain does not base one step's worktree on the preceding step's branch. `{previous}` passes text only. There is no implicit shared worktree or hidden workflow state.
121
121
 
@@ -16,7 +16,7 @@ isolation: worktree
16
16
 
17
17
  Implement the bounded outcome, not a preassigned file list. Work in the assigned cwd. Read applicable repository instructions and domain context first; inspect the relevant flow, callers, and tests before editing. Preserve unrelated work. Fix the root cause with the smallest complete diff, reusing existing patterns and dependencies. Do not add speculative work. Stop when the outcome is complete or blocked.
18
18
 
19
- For ordinary delegation, run focused validation needed to establish correctness. For Flow, the declared validation gate is authoritative: run only narrow development checks while implementing and do not duplicate that final gate.
19
+ For ordinary delegation, run focused validation needed to establish correctness. For Flow, the declared validation gate is authoritative: run only narrow development checks while implementing and do not duplicate that final gate. Before reporting ordinary or Flow completion, remove only task-created non-deliverable temporary, generated, or ignored artifacts. Preserve required deliverables, unrelated files, pre-existing files, and user data. Never use `git clean` or blanket deletion. If a path's ownership or necessity is uncertain, report its exact path as a blocker.
20
20
 
21
21
  Do not access credentials, use the network, generate artifacts, or broaden scope unless the task explicitly requires it. Never invoke external LLM APIs, SDKs, agent harnesses, or model CLIs.
22
22
 
@@ -550,7 +550,7 @@ export function registerDelegateFlow(pi: ExtensionAPI, runtime: DelegateFlowRunt
550
550
  const tip = oid(tipResult.stdout, "Unit HEAD");
551
551
  const branchTip = oid(await requireGit(["rev-parse", "--verify", `refs/heads/${unit.worktree.branch}^{commit}`], unit.worktree.cwd, signal), "Unit branch tip");
552
552
  if (tip !== branchTip) return { block: `Unit ${JSON.stringify(unit.request.id)} branch no longer names its checked-out HEAD.` };
553
- const status = await requireGit(["status", "--porcelain=v1", "--untracked-files=all"], unit.worktree.cwd, signal);
553
+ const status = await requireGit(["status", "--porcelain=v1", "--untracked-files=all", "--ignore-submodules=none"], unit.worktree.cwd, signal);
554
554
  if (status) return { block: `Unit Worktree is dirty:\n${capOutput(status)}` };
555
555
  const flags = await inspectIndexFlags(unit.worktree.cwd, git, signal);
556
556
  if (flags.failure) throw new Error(`Unit index inspection failed: ${flags.failure}`);
@@ -619,10 +619,9 @@ export default function subagentExtension(
619
619
  };
620
620
  throwIfAborted();
621
621
  let workflow: ParsedWorkflow;
622
- let roles: Role[];
623
622
  try {
624
623
  workflow = parseWorkflow(params);
625
- roles = loadRoles();
624
+ const roles = loadRoles();
626
625
  const knownRoles = new Set(roles.map(({ name }) => name));
627
626
  for (const { role } of workflow.delegations) {
628
627
  if (!knownRoles.has(role)) {
@@ -633,7 +632,22 @@ export default function subagentExtension(
633
632
  throw boundedError(error);
634
633
  }
635
634
  throwIfAborted();
636
- const rolesByName = new Map(roles.map((role) => [role.name, role]));
635
+ const reloadRole = (name: string): Role => {
636
+ let freshRoles: Role[];
637
+ try {
638
+ freshRoles = loadRoles();
639
+ } catch (error) {
640
+ throw boundedError(new Error(
641
+ `Couldn't reload Subagent role ${JSON.stringify(name)} after it waited for an executor permit. Fix the Role configuration and retry: ${error instanceof Error ? error.message : String(error)}`,
642
+ { cause: error },
643
+ ));
644
+ }
645
+ const role = freshRoles.find((candidate) => candidate.name === name);
646
+ if (role) return role;
647
+ throw boundedError(new Error(
648
+ `Subagent role ${JSON.stringify(name)} disappeared while waiting for an executor permit. Restore it and retry. Available roles: ${freshRoles.map(({ name: available }) => available).join(", ") || "none"}.`,
649
+ ));
650
+ };
637
651
 
638
652
  // Resolve against the latest known session context after each FIFO permit.
639
653
  const launchCtx = () => latestCtx ?? ctx;
@@ -681,7 +695,6 @@ export default function subagentExtension(
681
695
  const runWorkflow = async (workflowSignal: AbortSignal | undefined, emitToolUpdates: boolean) => {
682
696
  try {
683
697
  return await runForegroundWorkflow<EphemeralSubagentResult>(toolCallId, foregroundWorkflow, async (entry: WorkflowEntry) => {
684
- const role = rolesByName.get(entry.delegation.role)!;
685
698
  let model: string | undefined;
686
699
  let thinkingLevel: string | undefined;
687
700
  let worktree: WorktreeInfo | undefined;
@@ -701,7 +714,7 @@ export default function subagentExtension(
701
714
  id: entry.id,
702
715
  index: entry.index,
703
716
  name: entry.delegation.name,
704
- role: role.name,
717
+ role: entry.delegation.role,
705
718
  ...(model === undefined ? {} : { model }),
706
719
  ...(thinkingLevel === undefined ? {} : { thinkingLevel }),
707
720
  ...(worktreePayload === undefined ? {} : { worktreePayload }),
@@ -723,6 +736,7 @@ export default function subagentExtension(
723
736
  prepare: async () => {
724
737
  // Route and effective Role resources resolve only after this entry's
725
738
  // shared executor permit, before isolated state is created.
739
+ const role = reloadRole(entry.delegation.role);
726
740
  const launch = resolveLaunch(role, entry.delegation);
727
741
  notifyMissingSkills(role, launch);
728
742
  model = modelReference(launch.model);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-subagent",
3
- "version": "15.1.2",
3
+ "version": "15.1.3",
4
4
  "description": "Delegate bounded single, parallel, or chained tasks to isolated Pi roles.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -17,7 +17,7 @@ Before selecting a Flow unit, require that one Implementer launch can plausibly
17
17
 
18
18
  Give every unit a bounded objective, owned scope and exclusions, and its direct validation command/argument array. Each task packet must name the neighboring behavior that must stay unchanged. Include the exact test name or error when known CI evidence exists. Never claim a validation command matches unknown CI.
19
19
 
20
- Each delegation must own one concrete outcome with one focused validation story. Order declared validation from the cheapest focused check to broader required checks. If the affected flow or scope is not yet known, perform bounded read-only discovery first. Do not pass the parent request unchanged. Choose `modelClass` according to the delegation tool's guidance. Add non-empty `review` only for an explicit judgment that automated validation cannot establish. Call `delegate_flow` with 1–8 units; the runtime always supplies the effective Implementer and supplies the Reviewer only when a unit needs review.
20
+ Each delegation must own one concrete outcome with one focused validation story. When a known regression exists and the runner supports test-name filtering, require its exact test-name filter for that unit; for Node, use `node --test --test-name-pattern "exact test name" test/example.test.ts`. Keep each unit's declared validation focused on that unit's outcome; do not include a broad package or workspace suite. Its declared Flow validation remains authoritative for that outcome. Reserve required broad package or cross-unit checks for one distinct caller-owned final integration validation after relevant units integrate. Do not duplicate checks against the same state. Flow itself has no post-merge validation. If the affected flow or scope is not yet known, perform bounded read-only discovery first. Do not pass the parent request unchanged. Choose `modelClass` according to the delegation tool's guidance. Add non-empty `review` only for an explicit judgment that automated validation cannot establish. Call `delegate_flow` with 1–8 units; the runtime always supplies the effective Implementer and supplies the Reviewer only when a unit needs review.
21
21
 
22
22
  ## Runtime Flow
23
23