@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.
|
package/docs/orchestration.md
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
116
|
-
2. resolves its route and named Skills from the latest effective Pi context
|
|
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}`);
|
package/extensions/subagent.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
@@ -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.
|
|
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
|
|