@henryqw/pi-subagent 15.1.1 → 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,19 @@ 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
|
+
|
|
87
|
+
Before delegating:
|
|
88
|
+
|
|
89
|
+
- Find concrete outcomes that can ship on their own.
|
|
90
|
+
- Split only those outcomes. Give each one owner and a focused check.
|
|
91
|
+
- Run independent work in parallel.
|
|
92
|
+
- Prefer parallel delegation when at least two outcomes are independent.
|
|
93
|
+
- For naturally multi-part work, roughly three to five useful units can help.
|
|
94
|
+
- This is a guide, not a quota. Never create units just to reach it.
|
|
95
|
+
|
|
83
96
|
Its ordinary review loop is optional. Use it only when the caller or repository policy explicitly requires judgment review.
|
|
84
97
|
|
|
85
98
|
- Call `delegate_task` with `role: "reviewer"` to select the effective `reviewer` Role.
|
|
@@ -92,7 +105,9 @@ Flow is separate. It owns exact review evidence, exact `PASS` approval, validati
|
|
|
92
105
|
|
|
93
106
|
## Flow
|
|
94
107
|
|
|
95
|
-
Flow requires a clean Main worktree on an attached branch with a committed `HEAD`. Use it only for independent Git changes that can merge in any order.
|
|
108
|
+
Flow requires a clean Main worktree on an attached branch with a committed `HEAD`. Use it only for independent Git changes that can merge in any order.
|
|
109
|
+
|
|
110
|
+
Keep work together or run it in order when a split divides an invariant or adds coordination. Do not split units with overlapping mutable ownership. Do not split units that overlap files, APIs, schemas, generated output, package metadata, lockfiles, or invariants.
|
|
96
111
|
|
|
97
112
|
One Implementer launch must plausibly finish before the configured maximum runtime. Cohesion is not enough when work has several preservable, separately verifiable milestones. Split oversized dependent work into serial one-unit Flows after each milestone integrates. Units in one Flow stay independent and commuting.
|
|
98
113
|
|
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}`);
|
|
@@ -770,7 +770,7 @@ export function registerDelegateFlow(pi: ExtensionAPI, runtime: DelegateFlowRunt
|
|
|
770
770
|
description: "Run 1–8 independent Implementers in isolated Unit Worktrees, validate and serially fast-forward each tip, with exact review only for units that declare a judgment criterion.",
|
|
771
771
|
promptSnippet: "Run a deterministic parallel-implementation, serial-verification Flow",
|
|
772
772
|
promptGuidelines: [
|
|
773
|
-
"Use delegate_flow only for cohesive units expected to commute:
|
|
773
|
+
"Use delegate_flow only for cohesive units expected to commute: make independent commuting outcomes separate units rather than combining them merely to reduce Implementer count; sequence dependent work outside delegate_flow. On naturally multi-part work, actively look for roughly 3–5 useful units, but never manufacture units, split one invariant across multiple units, assign overlapping mutable ownership, or use a quota. Combine work that overlaps files, APIs, schemas, generated output, package metadata, lockfiles, or invariants.",
|
|
774
774
|
`${TASK_NAME_CONTRACT.promptGuidance} Each delegate_flow unit must own one concrete outcome with one focused validation story: include explicit bounded requirements and its authoritative direct command/argument validation gate. If the affected flow or scope is not yet known, perform bounded read-only discovery first. Add review only for an explicit judgment that validation cannot establish.`,
|
|
775
775
|
`For each delegate_flow unit, ${MODEL_CLASS_GUIDANCE}`,
|
|
776
776
|
"If a Flow blocks, inspect its classification and call delegate_flow_continue once with explicit repair guidance; modelClass may replace that one repair's current class.",
|
package/extensions/subagent.ts
CHANGED
|
@@ -596,10 +596,10 @@ export default function subagentExtension(
|
|
|
596
596
|
description: `Delegate one selected single, parallel, or chain workflow of bounded tasks to isolated Pi Subagents. Roles: ${roleSummary()}.`,
|
|
597
597
|
promptSnippet: "Delegate one bounded single, parallel, or chain workflow to isolated roles",
|
|
598
598
|
promptGuidelines: [
|
|
599
|
-
"Call delegate_task with exactly one mode: role+name+task for one task, tasks for 1–8 independent parallel tasks, or chain for 1–8 dependent sequential tasks using {previous} for the immediately preceding assistant output;
|
|
600
|
-
`${TASK_NAME_CONTRACT.promptGuidance} Every delegate_task entry must own one concrete outcome with one focused validation story: state its objective, exact scope and exclusions, relevant context and constraints, expected deliverable, and validation; if the affected flow or scope is not yet known, perform bounded read-only discovery first; never pass the parent request unchanged.`,
|
|
599
|
+
"Call delegate_task with exactly one mode: role+name+task in single mode for one atomic task, tasks for 1–8 independent parallel tasks, or chain for 1–8 dependent sequential tasks using {previous} for the immediately preceding assistant output; prefer parallel mode whenever at least two independent outcomes exist and each is independently deliverable and independently verifiable; do not combine independent outcomes merely to reduce child count. Sequence dependent work in chain entries, and never divide one invariant across multiple entries.",
|
|
600
|
+
`${TASK_NAME_CONTRACT.promptGuidance} Every delegate_task entry must own one concrete outcome with one focused validation story: state its objective, exact scope and exclusions, relevant context and constraints, expected deliverable, and validation; if the affected flow or scope is not yet known, perform bounded read-only discovery first; never pass the parent request unchanged. For naturally multi-part delegate_task work, you may look for roughly 3–5 useful entries, but do not manufacture entries or enforce a quota.`,
|
|
601
601
|
`For each delegate_task entry, ${MODEL_CLASS_GUIDANCE} A direct model replaces only the selected route's model; its thinking level stays unchanged.`,
|
|
602
|
-
"Parallel delegate_task entries must own non-overlapping files. Keep integration and cross-cutting decisions in Main
|
|
602
|
+
"Parallel mutating delegate_task entries must own non-overlapping files and changes. Read-only delegate_task entries may inspect overlapping sources when their questions and deliverables differ. Keep integration and cross-cutting decisions in Main.",
|
|
603
603
|
"delegate_task background applies to the whole selected workflow and returns before results exist; use it only when the user explicitly asks for non-blocking work.",
|
|
604
604
|
],
|
|
605
605
|
parameters: WorkflowSchema,
|
|
@@ -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
|
@@ -11,11 +11,13 @@ You are Main, the planner/orchestrator: slice work and choose `delegate_flow` or
|
|
|
11
11
|
|
|
12
12
|
Before slicing, identify applicable repository prohibitions. If the request or plan conflicts with them, stop and resolve the conflict before delegation. Copy them into every affected task and into `review` when automated validation cannot establish compliance; never replace repository policy with generic preservation or migration assumptions. When compatibility is disallowed, require deletion of replaced paths and forbid legacy readers, aliases, adapters, dual schemas, deprecation paths, and compatibility fallbacks.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Run a concise decomposition pass. Identify independently deliverable concrete outcomes. Maximize safe parallelism at those boundaries: give each outcome focused validation and clear ownership, and parallelize commuting work. Prefer parallel delegation when at least two independent outcomes exist. For naturally multi-part work, roughly 3–5 useful units is a guide, not a quota. Never manufacture units.
|
|
15
|
+
|
|
16
|
+
Before selecting a Flow unit, require that one Implementer launch can plausibly finish before the configured maximum runtime. Cohesion alone is not enough when work has multiple preservable, separately verifiable milestones. Use `delegate_flow` for independent units expected to commute. Keep work together or sequence it when splitting would divide an invariant, overlap mutable ownership, or create coordination. Combine or sequence work that overlaps files, APIs, schemas, generated output, package metadata, lockfiles, or invariants. Units inside one Flow remain independent and commuting. Dependent work remains outside Flow. Split oversized dependent work into serial one-unit Flows after each milestone integrates; otherwise sequence it in one task or ordinary caller-controlled sequencing.
|
|
15
17
|
|
|
16
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.
|
|
17
19
|
|
|
18
|
-
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.
|
|
19
21
|
|
|
20
22
|
## Runtime Flow
|
|
21
23
|
|
|
@@ -35,7 +37,7 @@ A cleanup warning does not undo successful integration. Report a cleanup warning
|
|
|
35
37
|
|
|
36
38
|
## Ordinary delegation
|
|
37
39
|
|
|
38
|
-
Use `delegate_task` for a single bounded task, independent parallel tasks, or dependent chain work that is not a Flow. Give each entry its objective, exact scope and exclusions, relevant context and constraints, expected deliverable, and focused validation. Choose `modelClass` according to the delegation tool's guidance. A direct `model` replaces only the selected route's model. The route keeps its thinking level. Keep integration and cross-cutting decisions in Main
|
|
40
|
+
Use `delegate_task` for a single bounded task, independent parallel tasks, or dependent chain work that is not a Flow. Give each entry its objective, exact scope and exclusions, relevant context and constraints, expected deliverable, and focused validation. Choose `modelClass` according to the delegation tool's guidance. A direct `model` replaces only the selected route's model. The route keeps its thinking level. Keep integration and cross-cutting decisions in Main.
|
|
39
41
|
|
|
40
42
|
### Optional evidence loop for implementation
|
|
41
43
|
|