@fradser/pi-agent-teams 0.5.3 → 0.7.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/.memory/MEMORY.md +3 -1
- package/.memory/node-terminal-followups.md +3 -2
- package/.memory/team-centric-design.md +21 -0
- package/README.md +103 -63
- package/package.json +4 -4
- package/references/agent-roles.md +77 -0
- package/src/activity.ts +86 -0
- package/src/agents.ts +93 -24
- package/src/follow-up-queue.ts +94 -26
- package/src/guidance.ts +96 -61
- package/src/index.ts +114 -28
- package/src/spawner.ts +194 -350
- package/src/state.ts +252 -565
- package/src/statefile.ts +209 -46
- package/src/team-machine.ts +968 -0
- package/src/tools.ts +160 -175
- package/src/types.ts +153 -189
- package/src/ui.ts +459 -226
- package/src/worker.ts +174 -34
- package/src/worktree.ts +20 -8
- package/.memory/run-centric-design.md +0 -22
- package/agents/observer.md +0 -10
- package/agents/reviewer.md +0 -11
- package/agents/specialist.md +0 -10
- package/agents/worker.md +0 -11
- package/src/run-machine.ts +0 -606
- package/src/terminal.ts +0 -34
package/src/worker.ts
CHANGED
|
@@ -1,59 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Teammate capabilities. A single addressed send_message primitive covers
|
|
3
|
+
* leader reports and peer mail. Task-list registration is shared by leader
|
|
4
|
+
* and worker processes; claiming and submitting remain worker-only.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
+
import * as path from "node:path";
|
|
2
9
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
10
|
+
import { livingTeammates, listTasks } from "./state.ts";
|
|
11
|
+
import { appendInboxMessage, appendWorkerEvent, createTaskIntent, readBoardFile, readRoster } from "./statefile.ts";
|
|
12
|
+
import {
|
|
13
|
+
LEADER_RECIPIENT,
|
|
14
|
+
messageTitle,
|
|
15
|
+
SendMessageParams,
|
|
16
|
+
TaskClaimParams,
|
|
17
|
+
TaskListParams,
|
|
18
|
+
TaskSubmitParams,
|
|
19
|
+
type BoardTask,
|
|
20
|
+
} from "./types.ts";
|
|
5
21
|
|
|
6
22
|
export interface WorkerBinding {
|
|
7
23
|
worker: string;
|
|
8
|
-
taskId: string;
|
|
9
24
|
spawnId: string;
|
|
10
25
|
outbox: string;
|
|
26
|
+
inbox: string;
|
|
27
|
+
rosterFile: string;
|
|
28
|
+
boardFile: string;
|
|
29
|
+
claimsDir: string;
|
|
30
|
+
submissionsDir: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const REQUIRED_ENV = [
|
|
34
|
+
"PI_TEAMMATE_WORKER_NAME",
|
|
35
|
+
"PI_TEAMMATE_SPAWN_ID",
|
|
36
|
+
"PI_TEAMMATE_OUTBOX_FILE",
|
|
37
|
+
"PI_TEAMMATE_INBOX_FILE",
|
|
38
|
+
"PI_TEAMMATE_ROSTER_FILE",
|
|
39
|
+
"PI_TEAMMATE_BOARD_FILE",
|
|
40
|
+
"PI_TEAMMATE_CLAIMS_DIR",
|
|
41
|
+
"PI_TEAMMATE_SUBMISSIONS_DIR",
|
|
42
|
+
] as const;
|
|
43
|
+
|
|
44
|
+
export function workerBinding(): WorkerBinding | undefined {
|
|
45
|
+
const values = REQUIRED_ENV.map((name) => process.env[name]);
|
|
46
|
+
if (values.some((value) => !value)) return undefined;
|
|
47
|
+
const [worker, spawnId, outbox, inbox, rosterFile, boardFile, claimsDir, submissionsDir] = values as string[];
|
|
48
|
+
return { worker, spawnId, outbox, inbox, rosterFile, boardFile, claimsDir, submissionsDir };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function livingRecipients(binding: WorkerBinding): Set<string> {
|
|
52
|
+
return new Set(readRoster(binding.rosterFile)
|
|
53
|
+
.filter((entry) => entry.status !== "stopped")
|
|
54
|
+
.map((entry) => entry.name));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadBoardTasks(binding: WorkerBinding): BoardTask[] {
|
|
58
|
+
const board = readBoardFile(binding.boardFile);
|
|
59
|
+
return Object.values(board?.tasks ?? {}).sort((a, b) => a.id.localeCompare(b.id));
|
|
11
60
|
}
|
|
12
61
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const taskId = process.env.PI_TEAMMATE_TASK_ID;
|
|
16
|
-
const spawnId = process.env.PI_TEAMMATE_SPAWN_ID;
|
|
17
|
-
const outbox = process.env.PI_TEAMMATE_OUTBOX_FILE;
|
|
18
|
-
return worker && taskId && spawnId && outbox ? { worker, taskId, spawnId, outbox } : undefined;
|
|
62
|
+
function dependenciesMet(task: BoardTask, tasks: Map<string, BoardTask>): boolean {
|
|
63
|
+
return task.dependsOn.every((dep) => tasks.get(dep)?.status === "completed");
|
|
19
64
|
}
|
|
20
65
|
|
|
21
|
-
export function
|
|
22
|
-
if (
|
|
23
|
-
const
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
66
|
+
export function renderTaskBoard(tasks: BoardTask[]): string {
|
|
67
|
+
if (tasks.length === 0) return "(the task board is empty)";
|
|
68
|
+
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
69
|
+
return tasks.map((task) => {
|
|
70
|
+
const deps = task.dependsOn.length > 0
|
|
71
|
+
? ` | depends on ${task.dependsOn.join(", ")} (${dependenciesMet(task, byId) ? "met" : "unmet"})`
|
|
72
|
+
: "";
|
|
73
|
+
const holder = task.claimedBy ? ` by @${task.claimedBy}` : "";
|
|
74
|
+
const verify = task.verify ? ` | verify: ${task.verify}` : "";
|
|
75
|
+
const description = task.description ? `\n ${task.description.slice(0, 2000)}` : "";
|
|
76
|
+
return `- [${task.id}] ${task.status}${holder}: ${task.subject}${deps}${verify}${description}`;
|
|
77
|
+
}).join("\n");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** One registration shared by leader and worker; binding chooses the data source. */
|
|
81
|
+
export function registerTaskListTool(pi: ExtensionAPI): void {
|
|
82
|
+
pi.registerTool({
|
|
83
|
+
name: "task_list",
|
|
84
|
+
promptSnippet: "Read the shared task board",
|
|
85
|
+
label: "Task Board",
|
|
86
|
+
description: "Read board tasks with status, dependencies, and verify gates. Pending tasks with met dependencies are claimable.",
|
|
87
|
+
parameters: TaskListParams,
|
|
88
|
+
async execute() {
|
|
89
|
+
const binding = workerBinding();
|
|
90
|
+
const tasks = binding ? loadBoardTasks(binding) : listTasks();
|
|
91
|
+
// Both sides get a roster tail: peer discovery is zero-cost for workers.
|
|
92
|
+
const roster = binding
|
|
93
|
+
? readRoster(binding.rosterFile)
|
|
94
|
+
.filter((entry) => entry.status !== "stopped")
|
|
95
|
+
.map((entry) => `@${entry.name} (${entry.agent}, ${entry.status})`)
|
|
96
|
+
.join("\n")
|
|
97
|
+
: livingTeammates().map((t) => `@${t.name} (${t.agent}, ${t.status}${t.currentTaskId ? `, task ${t.currentTaskId}` : ""})`).join("\n");
|
|
98
|
+
return { content: [{ type: "text", text: `${renderTaskBoard(tasks)}\n\nRoster:\n${roster || "(none)"}` }], details: {} };
|
|
99
|
+
},
|
|
100
|
+
});
|
|
33
101
|
}
|
|
34
102
|
|
|
35
103
|
export function registerWorkerCapabilities(pi: ExtensionAPI): void {
|
|
36
104
|
pi.registerTool({
|
|
37
|
-
name: "
|
|
38
|
-
promptSnippet: "
|
|
39
|
-
label: "
|
|
40
|
-
description: "
|
|
41
|
-
parameters:
|
|
105
|
+
name: "send_message",
|
|
106
|
+
promptSnippet: "Send a message to the leader or a teammate",
|
|
107
|
+
label: "Send Message",
|
|
108
|
+
description: "The only messaging primitive. Use to=\"leader\" for reports; use a teammate name for direct peer mail. status is valid only for leader reports.",
|
|
109
|
+
parameters: SendMessageParams,
|
|
42
110
|
async execute(_toolCallId, params) {
|
|
43
|
-
const binding =
|
|
111
|
+
const binding = workerBinding();
|
|
44
112
|
if (!binding) throw new Error("This capability is available only inside a spawned teammate.");
|
|
45
|
-
|
|
113
|
+
if (params.to === LEADER_RECIPIENT) {
|
|
114
|
+
appendWorkerEvent(binding.outbox, {
|
|
115
|
+
id: randomUUID(),
|
|
116
|
+
type: "message",
|
|
117
|
+
worker: binding.worker,
|
|
118
|
+
spawnId: binding.spawnId,
|
|
119
|
+
body: params.message,
|
|
120
|
+
status: params.status,
|
|
121
|
+
});
|
|
122
|
+
return { content: [{ type: "text", text: params.status
|
|
123
|
+
? "Queued message to leader."
|
|
124
|
+
: 'Queued message to leader. Note: without status="completed" or status="failed" this report does not end your assignment.' }], details: {} };
|
|
125
|
+
}
|
|
126
|
+
if (params.status) throw new Error('status is valid only when to="leader".');
|
|
127
|
+
if (params.to === binding.worker) throw new Error("You are already the recipient — no need to message yourself.");
|
|
128
|
+
if (!livingRecipients(binding).has(params.to)) {
|
|
129
|
+
throw new Error(`No living teammate named "${params.to}". Check the roster or ask the leader.`);
|
|
130
|
+
}
|
|
131
|
+
const recipientInbox = path.join(path.dirname(binding.inbox), `inbox-${encodeURIComponent(params.to)}.jsonl`);
|
|
132
|
+
appendInboxMessage(recipientInbox, {
|
|
46
133
|
id: randomUUID(),
|
|
47
|
-
|
|
134
|
+
from: binding.worker,
|
|
135
|
+
subject: messageTitle(params.message),
|
|
136
|
+
body: params.message,
|
|
137
|
+
});
|
|
138
|
+
return { content: [{ type: "text", text: `Delivered to @${params.to}'s inbox.` }], details: {} };
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
registerTaskListTool(pi);
|
|
143
|
+
|
|
144
|
+
pi.registerTool({
|
|
145
|
+
name: "task_claim",
|
|
146
|
+
promptSnippet: "Self-claim a pending board task",
|
|
147
|
+
label: "Claim Task",
|
|
148
|
+
description: "Atomically claim a pending task whose dependencies are met. Omit taskId to claim the first claimable task.",
|
|
149
|
+
parameters: TaskClaimParams,
|
|
150
|
+
async execute(_toolCallId, params) {
|
|
151
|
+
const binding = workerBinding();
|
|
152
|
+
if (!binding) throw new Error("This capability is available only inside a spawned teammate.");
|
|
153
|
+
const tasks = loadBoardTasks(binding);
|
|
154
|
+
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
155
|
+
const candidates = params.taskId
|
|
156
|
+
? tasks.filter((task) => task.id === params.taskId)
|
|
157
|
+
: tasks.filter((task) => task.status === "pending" && dependenciesMet(task, byId));
|
|
158
|
+
if (candidates.length === 0) {
|
|
159
|
+
throw new Error(params.taskId ? `Task "${params.taskId}" was not found on the board.` : "No claimable task right now.");
|
|
160
|
+
}
|
|
161
|
+
for (const task of candidates) {
|
|
162
|
+
if (task.status !== "pending" || !dependenciesMet(task, byId)) continue;
|
|
163
|
+
const won = createTaskIntent(binding.claimsDir, task.id, {
|
|
164
|
+
taskId: task.id,
|
|
165
|
+
worker: binding.worker,
|
|
166
|
+
spawnId: binding.spawnId,
|
|
167
|
+
timestamp: Date.now(),
|
|
168
|
+
});
|
|
169
|
+
if (won) {
|
|
170
|
+
return { content: [{ type: "text", text: `You won [${task.id}] "${task.subject}". Submit with task_submit.` }], details: {} };
|
|
171
|
+
}
|
|
172
|
+
if (params.taskId) throw new Error(`Task "${task.id}" was claimed by someone else first.`);
|
|
173
|
+
}
|
|
174
|
+
throw new Error("All candidate tasks were claimed in the race. Check the board again.");
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
pi.registerTool({
|
|
179
|
+
name: "task_submit",
|
|
180
|
+
promptSnippet: "Submit a claimed task outcome",
|
|
181
|
+
label: "Submit Task",
|
|
182
|
+
description: "Submit a task you claimed. completed runs its verify gate; failed releases the task back to the board.",
|
|
183
|
+
parameters: TaskSubmitParams,
|
|
184
|
+
async execute(_toolCallId, params) {
|
|
185
|
+
const binding = workerBinding();
|
|
186
|
+
if (!binding) throw new Error("This capability is available only inside a spawned teammate.");
|
|
187
|
+
const won = createTaskIntent(binding.submissionsDir, params.taskId, {
|
|
188
|
+
taskId: params.taskId,
|
|
48
189
|
worker: binding.worker,
|
|
49
190
|
spawnId: binding.spawnId,
|
|
50
|
-
subject: params.subject,
|
|
51
|
-
body: params.body,
|
|
52
191
|
status: params.status,
|
|
53
|
-
|
|
192
|
+
result: params.result,
|
|
193
|
+
timestamp: Date.now(),
|
|
54
194
|
});
|
|
55
|
-
|
|
56
|
-
return { content: [{ type: "text", text: `
|
|
195
|
+
if (!won) throw new Error(`A submission for "${params.taskId}" is already pending.`);
|
|
196
|
+
return { content: [{ type: "text", text: `Submitted ${params.status} for [${params.taskId}].` }], details: {} };
|
|
57
197
|
},
|
|
58
198
|
});
|
|
59
199
|
}
|
package/src/worktree.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface WorktreeDiff {
|
|
|
27
27
|
diffStat: string;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export type WorktreeDiffResult = { ok: true; diff: WorktreeDiff } | { ok: false; error: string };
|
|
31
|
+
|
|
30
32
|
function runGit(cwd: string, args: string[]): { status: number | null; stdout: string; stderr: string } {
|
|
31
33
|
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8" });
|
|
32
34
|
return {
|
|
@@ -81,14 +83,24 @@ export function createWorktree(
|
|
|
81
83
|
* Capture the worker's changes in the worktree as a patch against the base
|
|
82
84
|
* commit. The worktree is left untouched; call cleanupWorktree afterwards.
|
|
83
85
|
*/
|
|
84
|
-
export function captureWorktreeDiff(setup: WorktreeSetup):
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
export function captureWorktreeDiff(setup: WorktreeSetup): WorktreeDiffResult {
|
|
87
|
+
try {
|
|
88
|
+
execFileSync("git", ["-C", setup.path, "add", "-A"], { stdio: "ignore" });
|
|
89
|
+
const stat = runGit(setup.path, ["diff", "--cached", "--stat", setup.baseCommit]);
|
|
90
|
+
const patch = runGit(setup.path, ["diff", "--cached", setup.baseCommit]);
|
|
91
|
+
if (stat.status !== 0 || patch.status !== 0) {
|
|
92
|
+
return { ok: false, error: patch.stderr.trim() || stat.stderr.trim() || "git diff failed" };
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
ok: true,
|
|
96
|
+
diff: {
|
|
97
|
+
patch: patch.stdout ?? "",
|
|
98
|
+
diffStat: stat.stdout?.trim() ?? "",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
103
|
+
}
|
|
92
104
|
}
|
|
93
105
|
|
|
94
106
|
/**
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: teammate-autonomous-and-tui
|
|
3
|
-
description: Agent Teams (packages/agent-teams) — run-centric: declarative agent files, single-call DAG dispatch, bounded child-process nodes, one-way leader inbox reports, session-wide worker cap, per-spawn identity validation
|
|
4
|
-
type: project
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
`packages/agent-teams` (0.3.0) is a run-centric multi-agent system: the Pi session is the leader; agents are declarative Markdown files; each run is a dependency-aware task graph dispatched in one call, where each node is a bounded child Pi process and a session-wide cap limits total workers to 8.
|
|
8
|
-
|
|
9
|
-
**Why:**
|
|
10
|
-
The teammate-registry model (runtime `teammate_register`/`create_task`/`start_task` ceremony, session-scoped identities, read receipts) was replaced after a design review. The ceremony critique: a one-off delegation cost 4 tool calls (list/register/create/start), identities were session-ephemeral so registration cost was paid per session, and both competitor packages (pi-maestro-teammate, @gcoder1991/pi-mesh) proved single-call DAG dispatch + declarative markdown agents. The later simplification removed the remaining half-channels: workers report only to the leader, upstream DAG results replace peer delivery, and live run status is not injected into every system prompt.
|
|
11
|
-
|
|
12
|
-
**How to apply:**
|
|
13
|
-
1. **Agents are declarative files** (`src/agents.ts`): frontmatter `name`/`description`/`tools`/`model` (inline `#` comments stripped), body = role prompt. Discovery precedence per name: project `.pi/agents/` > user `~/.pi/agent/agents/` > bundled `agents/`. Bundled: worker/reviewer/specialist/observer.
|
|
14
|
-
2. **Single-call DAG dispatch** (`teammate_run`): `tasks` with `id`/`agent`/`prompt`/`paths`/`access` (default read)/`dependsOn`/`model`/`timeoutMs`, plus `concurrency` (default 4), `worktree`, `background`, `timeoutMs`, `summarize`, and `summaryAgent`. Validates dup ids, unknown dependsOn, cycles, bad paths before any spawn. Root nodes start immediately; `scheduleRun` auto-starts dependents on completion; write nodes with overlapping paths are deferred across all runs in the session unless worktree-isolated (`findSharedWorkspaceWriteConflict`).
|
|
15
|
-
3. **Leader tools (3)**: `teammate_run`, `teammate_cancel` (run or `nodeId` node-level cancel; marks cancelled BEFORE terminating workers; SIGTERM→SIGKILL; console `x` reuses `cancelNodeAndTerminate`), and `teammate_retry` (retries failed/cancelled nodes without re-running completed ones). No leader message tool exists.
|
|
16
|
-
4. **Worker protocol (1 capability tool)**: worker-only `teammate_message` has only `subject`/`body`/optional `status` and always reports to the leader. Per-spawn identity: `PI_TEAMMATE_WORKER_NAME` = `runId:nodeId`, `PI_TEAMMATE_SPAWN_ID` = fresh UUID; `applyWorkerEvents` rejects stale-spawn events. Reports enter one leader inbox; there are no peer mailboxes, worker inboxes, or leader broadcasts. Upstream DAG results are injected into downstream prompts (`=== UPSTREAM HANDOFF ===`).
|
|
17
|
-
|
|
18
|
-
5. **Outcomes authoritative & non-polling leader**: workers message `team-leader` (`teammate_message`) with their deliverables upon completion, delivered automatically as a follow-up turn. The team leader does not sleep while tasks execute. One canonical terminal result per node built by the harness after child close; reported completion + SIGTERM close stays completed; failed node cancels its transitive pending dependents (`cancelBlockedDependents`) and fails the run. Worktree per node (`createWorktree(run.cwd, "${runId}-${nodeId}")`), diff captured for integration review. State snapshots are dirty-gated and worker task temp files are removed after close. Background runs deliver one run-completion follow-up; foreground gather (`background: false`) blocks the tool call (detaches after 5 min so turn is never hung).
|
|
19
|
-
6. **UI**: passive widget (display-only) + `/teammate` full-screen console (owns input via `ctx.ui.custom`, no global interception) — rows are nodes, detail = node lifecycle + leader reports, live activity streams tool calls and thinking deltas, SGR mouse-wheel scrolling. Follows `@packages/btw` style language.
|
|
20
|
-
7. **Testing**: BDD in `features/agent-teams.feature`, package tests in `tests/test_teammate_package.py` including node-eval runtime tests of state.ts/spawner.ts; typecheck via `npx tsc --noEmit --strict ... src/*.ts`.
|
|
21
|
-
|
|
22
|
-
**Related:** [[pi-cli-print-json-usage]] [[no-global-input-interception]] [[pi-kitty-csi-u-keys]] [[pi-custom-component-rendering]] [[pi-package-conventions]]
|
package/agents/observer.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: observer
|
|
3
|
-
description: Read-only monitor of activity, logs, or processes; use when the task is to observe, watch, or report state rather than change it
|
|
4
|
-
tools: read
|
|
5
|
-
---
|
|
6
|
-
You are an observer agent. Observe and report on the assigned scope without
|
|
7
|
-
changing anything. Take the required snapshots or readings, summarize what you
|
|
8
|
-
observed, and report notable events or anomalies with timestamps and evidence
|
|
9
|
-
via teammate_message to team-leader with status="completed". You have no edit,
|
|
10
|
-
write, or command tools.
|
package/agents/reviewer.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: reviewer
|
|
3
|
-
description: Read-only code or content reviewer; use after implementation or plan changes to check for correctness, regressions, and security
|
|
4
|
-
tools: read,bash
|
|
5
|
-
---
|
|
6
|
-
You are a reviewer agent. Read the relevant code and tests first, then review
|
|
7
|
-
the assigned scope for correctness, regressions, and security problems. Do not
|
|
8
|
-
edit files. Report only confirmed findings with severity, evidence, exact
|
|
9
|
-
paths, and a minimal fix recommendation via teammate_message to team-leader with
|
|
10
|
-
status="completed". When no issue is confirmed, say so and list the checks
|
|
11
|
-
you performed.
|
package/agents/specialist.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: specialist
|
|
3
|
-
description: Read-only domain expert for a specific technical area (security, performance, data, platform); use when a task needs deep domain judgment rather than broad implementation
|
|
4
|
-
tools: read,bash
|
|
5
|
-
---
|
|
6
|
-
You are a specialist agent. Apply deep domain judgment to the assigned scope:
|
|
7
|
-
investigate, analyze, and produce findings or recommendations with evidence via
|
|
8
|
-
teammate_message to team-leader with status="completed". Do not edit files.
|
|
9
|
-
State your assumptions, the evidence you used, and the bounds of your expertise
|
|
10
|
-
for this task.
|
package/agents/worker.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: worker
|
|
3
|
-
description: General executor that implements changes and verifies them; use when a task needs code or file modifications, or when no more specific agent fits
|
|
4
|
-
tools: read,bash,edit,write
|
|
5
|
-
---
|
|
6
|
-
You are a worker agent. Implement the assigned task end to end within the
|
|
7
|
-
declared paths and access scope, then verify your own work by running the
|
|
8
|
-
relevant tests or commands. Follow the task's ordered procedure. Report what
|
|
9
|
-
you changed, what you verified, and any risks or follow-up work via
|
|
10
|
-
teammate_message to team-leader with status="completed". Do not touch
|
|
11
|
-
files outside the assigned scope.
|