@ferris1225/pi-subagents 4.1.23 → 4.2.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.
@@ -1,39 +0,0 @@
1
- ---
2
- name: synthesizer
3
- description: "Read-only merge of many long inputs (result artifacts, reports, docs) into one deduplicated, attributed brief; conflicts and gaps stay explicit."
4
- tools: read, grep, find, ls, bash
5
- # The shell slot follows the parent and parent-active plugin tools are appended;
6
- # listed non-shell Pi built-ins are the permission boundary.
7
- thinking: low
8
- ---
9
-
10
- You are a synthesizer agent: a read-only specialist that merges several long inputs into one integrated brief so the caller never has to read them all itself. You have NOT got the caller's conversation history; the task brief names your inputs — result artifact files from earlier sub-agent runs, reports, documents, diffs, or logs — and they are your complete source material.
11
-
12
- ## Hard constraints
13
-
14
- - You are READ-ONLY. Never create, edit, or delete files; never run mutating commands. Read inputs with your `read` tool, not a shell command — the shell you were given may be POSIX or PowerShell, and `read` is identical everywhere. Keep shell use to read-only inspection (`git log/show/diff/status`).
15
- - Stay within the named inputs. Short verification reads of files those inputs cite are allowed; broad codebase exploration is `explorer` work — if the inputs cannot answer the brief, report that as a gap instead of searching for more.
16
- - Preserve attribution: every merged claim keeps a pointer to its source (file/section, or `path:line` when the source cites code).
17
- - Conflicts between sources are findings. Report them side by side with both attributions; never average them away or silently pick a winner.
18
-
19
- ## Workflow
20
-
21
- 1. Read every named input fully before writing anything.
22
- 2. Deduplicate: collapse restatements of the same fact into one entry with all sources attached.
23
- 3. Reconcile: where sources disagree, check whether a cited file settles it with a short verification read; otherwise record the conflict.
24
- 4. Rank what remains by relevance to the brief's question — the caller reads your brief instead of the inputs, so anything omitted is invisible to it.
25
-
26
- ## Final response
27
-
28
- Return one integrated brief:
29
-
30
- ```text
31
- ## Brief
32
- - merged, deduplicated findings in priority order, each with source attribution
33
- ## Conflicts
34
- - source A says X; source B says Y (omit this section when none)
35
- ## Gaps
36
- - questions the inputs cannot answer (omit this section when none)
37
- ```
38
-
39
- Do not repeat the task brief, quote long passages when a pointer suffices, or narrate which input you read when. Keep the final response comfortably below the 40-line delivery cap unless the requested synthesis genuinely requires more.
package/agents/worker.md DELETED
@@ -1,43 +0,0 @@
1
- ---
2
- name: worker
3
- description: Default route for any non-trivial, self-contained code change — implement, fix, refactor, or test, then verify and hand off.
4
- thinking: high
5
- # No `tools` field => inherits all tools (full capability).
6
- ---
7
-
8
- You are a worker agent with full capabilities in an isolated context window. You own a delegated, self-contained task end to end so the main conversation stays clean. You have NOT got the caller's conversation history — the task brief is your source of truth.
9
-
10
- ## Procedure
11
-
12
- 1. **Context.** Read the brief fully. Read referenced files — and referenced images (screenshots, mockups) when the model supports vision — before editing. If critical context is missing, state what an `explorer` should retrieve rather than guessing.
13
- 2. **Plan.** Inspect existing code and conventions first; form the smallest coherent root-cause change that satisfies the brief. Prefer the design that deletes complexity rather than rearranges it, and decompose rather than push a file toward ~1000 lines. For a large task, note files, order, and risks before editing. No unrelated refactors or standalone docs work unless the brief asks.
14
- 3. **Implement.** Preserve the user's work; limit edits to the request plus required validation. Follow the project's error handling, naming, and style. Synchronize existing README/docs/examples/comments directly affected by your change; do not defer obvious drift.
15
- 4. **Verify.** Run the project's format/build/tests when they exist (e.g. `tsc --noEmit`, the test runner). NEVER report an unrun check as passed — report it as unavailable or a pre-existing failure, with the exact error.
16
- 5. **Handoff.** Return only the concrete outcome. Do not repeat the task brief, plan, root-cause investigation, or tool chronology; report only unresolved blockers and checks that remain failed.
17
-
18
- ## Boundaries
19
-
20
- - Never commit, push, publish, tag, release, or bump a package version. The parent workflow owns the independent review gate and every release action — even when repository instructions normally automate release after green checks.
21
- - Children are leaf processes: you cannot dispatch sub-agents.
22
- - When your brief carries reviewer findings, apply their fix instructions: implement each when it is sound; when it is wrong, out of scope, or a sounder fix exists, ship your fix and push back in your report — cite the finding, refute the instruction's reasoning, and describe what you shipped instead. A deviation without reasoning will be re-opened.
23
- - Do not ask the caller to duplicate downstream roles, and never treat your own verification as the final gate.
24
-
25
- ## Output format
26
-
27
- ## Completed
28
-
29
- What was done, in a few lines.
30
-
31
- ## Files Changed
32
-
33
- - `path/to/file.ts` — what changed.
34
-
35
- ## Verification
36
-
37
- Which checks you ACTUALLY ran and their result (e.g. `tsc --noEmit` clean; `vitest` 12 passed). State explicitly anything you could not run and why.
38
-
39
- ## Notes (only when material)
40
-
41
- Unresolved blockers, rejected requirements, or decisions the caller must know. For a reviewer handoff: exact paths changed and the key functions/types touched. Omit when nothing actionable.
42
-
43
- Keep the final response comfortably below the 40-line delivery cap unless the result genuinely requires more.
package/src/workflow.ts DELETED
@@ -1,215 +0,0 @@
1
- /**
2
- * Managed workflow policy and handoff formatting.
3
- *
4
- * Successful top-level worker/cleaner runs continue through one independent
5
- * code review gate. A failing managed gate continues into the reviewer fix
6
- * stage: the same retained reviewer session gets write access and applies its
7
- * own fix instructions, so nobody outside the gate has to guess what satisfies
8
- * it. Direct reviewer results never chain — a failing direct gate returns its
9
- * findings to the main agent, which owns that fix decision. Documentation
10
- * drift is an ordinary gate finding; dispatching a documenter stays the main
11
- * agent's call. Internal steps are launched by dispatch directly, so they
12
- * never re-enter this policy or wake the main agent mid-chain.
13
- */
14
-
15
- import { isWriteCapableAgent, type AgentConfig } from "./agents.ts";
16
- import { getResultOutput, isFailedResult, reviewVerdict, type SingleResult } from "./spawn.ts";
17
- import { formatUsageCompact, sumUsage } from "./monitor.ts";
18
-
19
- export interface WorkflowAgentAvailability {
20
- reviewer: boolean;
21
- writer: boolean;
22
- }
23
-
24
- export function workflowAgentAvailability(
25
- agents: readonly Pick<AgentConfig, "name" | "tools">[],
26
- ): WorkflowAgentAvailability {
27
- const names = new Set(agents.map((agent) => agent.name));
28
- return {
29
- reviewer: names.has("reviewer"),
30
- writer: agents.some(isWriteCapableAgent),
31
- };
32
- }
33
-
34
- export interface ManagedWorkflowPlan {
35
- initialRelation: string;
36
- }
37
-
38
- /** Dispatch-time gate intensity for one worker/cleaner task. "gate" (default)
39
- * keeps the automatic post-writer reviewer; "none" skips it so a mechanical,
40
- * low-risk edit does not pay for a full adversarial review — the dispatching
41
- * model owns that proportionality call because it knows the task's risk. */
42
- export type ReviewMode = "gate" | "none";
43
-
44
- /** Fixed cap on reviewer fix → re-review rounds inside one managed workflow.
45
- * Re-reviews converge by construction (they verify fixes and fix regressions
46
- * instead of re-scanning the whole surface); the cap only stops pathological
47
- * burn and hands the still-failing gate back to the main agent. */
48
- export const MAX_REVIEW_FIX_ROUNDS = 2;
49
-
50
- /** Conservative pre-run check used to reserve one shared-repository lane
51
- * around a complete writer workflow or a reviewer that needs a stable diff. */
52
- export function canStartManagedWorkflow(
53
- agent: Pick<AgentConfig, "name" | "tools">,
54
- availability: WorkflowAgentAvailability,
55
- ): boolean {
56
- // Every shared write-capable role—including custom agents—owns the repository
57
- // lane even when no downstream role is enabled. Otherwise its edits can race
58
- // a managed writer's pending diff.
59
- if (isWriteCapableAgent(agent)) return true;
60
- if (agent.name === "reviewer") {
61
- // Hold a stable diff snapshot against every discoverable writer even when
62
- // this review is advisory: a gate over a moving diff is unsound.
63
- return availability.writer;
64
- }
65
- return false;
66
- }
67
-
68
- /** Classify only healthy top-level writer results; everything else delivers
69
- * directly, including every reviewer result — a direct reviewer dispatch never
70
- * starts another child. A failing managed gate is expanded by the workflow
71
- * itself into the reviewer fix stage. A dispatch that opted out of the gate
72
- * (review: "none") delivers directly too.
73
- *
74
- * `changedWorkspace: false` also delivers directly. A gate reviews a pending
75
- * diff, so a run that produced none — a cleaner that found no safe cut, a worker
76
- * that concluded there was nothing to do, both explicitly valid outcomes — has
77
- * nothing to review, and spending a reviewer on an empty diff buys nothing.
78
- * Only a proven absence of changes skips: `undefined` keeps the gate. */
79
- export function getManagedWorkflowPlan(
80
- result: SingleResult,
81
- availability: WorkflowAgentAvailability,
82
- review: ReviewMode = "gate",
83
- changedWorkspace?: boolean,
84
- ): ManagedWorkflowPlan | undefined {
85
- if (review === "none") return undefined;
86
- if (changedWorkspace === false) return undefined;
87
- if (result.dispatchFailed || isFailedResult(result)) return undefined;
88
- if (result.agent === "worker" || result.agent === "cleaner") {
89
- if (!availability.reviewer) return undefined;
90
- return {
91
- initialRelation: result.agent === "cleaner" ? "initial cleanup" : "initial implementation",
92
- };
93
- }
94
- return undefined;
95
- }
96
-
97
- /** Build the code gate that runs directly after a top-level writer. Reports
98
- * carry intent; the actual pending diff remains authoritative. */
99
- export function buildFinalReviewBrief(initialResult: SingleResult): string {
100
- return [
101
- `Fresh code gate for a managed ${initialResult.agent} workflow.`,
102
- ``,
103
- `The top-level ${initialResult.agent}'s full report:`,
104
- `---`,
105
- getResultOutput(initialResult),
106
- `---`,
107
- ``,
108
- `Run \`git status\` and \`git diff\` and judge the actual pending code; the report is context, not proof.`,
109
- `Scale the gate to the change: a small, contained diff gets a fast, focused review of its correctness,`,
110
- `regressions, and blast radius — not a whole-surface audit or a redesign of surrounding code it merely touches.`,
111
- `Remain read-only. Attach a concrete fix instruction to EVERY gate finding — including documentation drift —:`,
112
- `what to change, where, and how to verify it. A failing gate continues into your own write-enabled fix stage,`,
113
- `so make every instruction executable exactly as written.`,
114
- `End with exactly one standalone machine verdict line:`,
115
- `VERDICT: REVIEW_PASS when no finding remains, otherwise VERDICT: REVIEW_FAIL.`,
116
- ].join("\n");
117
- }
118
-
119
- /** Build the follow-up brief for the reviewer fix stage: the same retained
120
- * reviewer session continues with its read-only boundary lifted and applies
121
- * its own fix instructions. The workflow continues with a converging re-review. */
122
- export function buildReviewerFixBrief(gateOutput: string): string {
123
- return [
124
- `Fix stage: your gate review returned REVIEW_FAIL. You now have full write access in this same session.`,
125
- `Apply every one of your own fix instructions now — exactly the changes you specified, nothing broader.`,
126
- `Then re-check the code your fixes touch, so the next scan does not open with your own regression, and run`,
127
- `the narrowest decisive checks (type check, focused tests) to verify.`,
128
- ``,
129
- `Your gate review:`,
130
- `---`,
131
- gateOutput,
132
- `---`,
133
- ``,
134
- `Report:`,
135
- `## Fixed`,
136
- `- each finding → the exact fix applied (path + what changed)`,
137
- `## Verification`,
138
- `- checks actually run and their results`,
139
- `Do not emit another VERDICT; a converging gate re-reviews the diff after you.`,
140
- ].join("\n");
141
- }
142
-
143
- /** Fresh gate over the updated diff after a fix round. The re-review runs in a
144
- * brand-new context but with a converging contract: verify the recorded fixes
145
- * landed and hunt regressions the fixes introduced. It must not reopen new
146
- * structural or style findings — the initial gate owned those — or every fresh
147
- * scan would surface fresh nits forever and the loop would never end. */
148
- export function buildReReviewBrief(fixResult: SingleResult, round: number): string {
149
- return [
150
- `Re-review after fix round ${round}. This gate CONVERGES: it verifies fixes, it does not re-scan the whole surface.`,
151
- ``,
152
- `The fix stage reported:`,
153
- `---`,
154
- getResultOutput(fixResult),
155
- `---`,
156
- ``,
157
- `Verify every recorded fix actually landed in the code, and hunt regressions the fixes introduced in the touched`,
158
- `code and its direct blast radius (\`git status\` + \`git diff\`). Do NOT open new structural, style, or pre-existing`,
159
- `findings — the initial gate owned those; a remaining earlier finding counts only if its fix failed to land.`,
160
- `Remain read-only. Attach a concrete fix instruction to every finding you do report.`,
161
- `End with exactly one standalone machine verdict line:`,
162
- `VERDICT: REVIEW_PASS when nothing remains, otherwise VERDICT: REVIEW_FAIL.`,
163
- ].join("\n");
164
- }
165
-
166
- /**
167
- * One step of a managed workflow as delivered: the run id (the stable handle
168
- * for resume/stop), the result, and the human-readable role within the
169
- * workflow ("initial implementation", "final review"). runId is optional only
170
- * for synthetic steps that never spawned a child.
171
- */
172
- export interface ChainStep {
173
- runId?: number;
174
- result: SingleResult;
175
- relation: string;
176
- }
177
-
178
- export interface ManagedWorkflowOutcome {
179
- steps: ChainStep[];
180
- }
181
-
182
- function workflowResultStatus(result: SingleResult, relation?: string): string {
183
- if (isFailedResult(result)) return "failed";
184
- // The fix stage is reviewer-named writer work: judge it by outcome, not by
185
- // the verdict contract its review stage was held to.
186
- if (relation === "review fix") return "completed";
187
- if (result.agent === "reviewer") {
188
- const verdict = reviewVerdict(getResultOutput(result));
189
- return verdict ? verdict.toUpperCase() : "NO_VERDICT";
190
- }
191
- return "completed";
192
- }
193
-
194
- function workflowStepLine(step: ChainStep): string {
195
- const id = step.runId !== undefined ? `#${step.runId} ` : "";
196
- return `- ${id}${step.result.agent} · ${step.relation} · ${workflowResultStatus(step.result, step.relation)}`;
197
- }
198
-
199
- function appendWorkflowFooter(lines: string[], steps: readonly ChainStep[]): void {
200
- const total = sumUsage(steps.map((step) => step.result.usage));
201
- const usage = formatUsageCompact(total);
202
- lines.push("", `Totals: ${steps.length} run${steps.length === 1 ? "" : "s"}${usage ? ` · ${usage}` : ""}`);
203
- }
204
-
205
- /** One clear final delivery for managed writer → gate workflows. */
206
- export function formatManagedWorkflowSummary(
207
- steps: readonly ChainStep[],
208
- terminalResult: SingleResult = steps[steps.length - 1]!.result,
209
- terminalRelation: string = steps[steps.length - 1]!.relation,
210
- ): string {
211
- const route = steps.map((step) => step.result.agent).join(" → ");
212
- const lines = [`## Managed workflow: ${route} — final ${workflowResultStatus(terminalResult, terminalRelation)}`, "", ...steps.map(workflowStepLine)];
213
- appendWorkflowFooter(lines, steps);
214
- return lines.join("\n");
215
- }