mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-17 07:03:28 +00:00
move pi-mono into companion-cloud as apps/companion-os
- Copy all pi-mono source into apps/companion-os/ - Update Dockerfile to COPY pre-built binary instead of downloading from GitHub Releases - Update deploy-staging.yml to build pi from source (bun compile) before Docker build - Add apps/companion-os/** to path triggers - No more cross-repo dispatch needed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
0250f72976
579 changed files with 206942 additions and 0 deletions
|
|
@ -0,0 +1,283 @@
|
|||
# pi-teams Core Features Implementation Plan
|
||||
|
||||
> **REQUIRED SUB-SKILL:** Use the executing-plans skill to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Implement Plan Approval Mode, Broadcast Messaging, and Quality Gate Hooks for the `pi-teams` repository to achieve functional parity with Claude Code Agent Teams.
|
||||
|
||||
**Architecture:**
|
||||
|
||||
- **Plan Approval**: Add a `planning` status to `TaskFile.status`. Create `task_submit_plan` and `task_evaluate_plan` tools. Lead can approve/reject.
|
||||
- **Broadcast Messaging**: Add a `broadcast_message` tool that iterates through the team roster in `config.json` and sends messages to all active members.
|
||||
- **Quality Gate Hooks**: Introduce a simple hook system that triggers on `task_update` (specifically when status becomes `completed`). For now, it will look for a `.pi/team-hooks/task_completed.sh` or similar.
|
||||
|
||||
**Tech Stack:** Node.js, TypeScript, Vitest
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Plan Approval Mode
|
||||
|
||||
### Task 1: Update Task Models and Statuses
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/utils/models.ts`
|
||||
|
||||
**Step 1: Add `planning` to `TaskFile.status` and add `plan` field**
|
||||
|
||||
```typescript
|
||||
export interface TaskFile {
|
||||
id: string;
|
||||
subject: string;
|
||||
description: string;
|
||||
activeForm?: string;
|
||||
status: "pending" | "in_progress" | "planning" | "completed" | "deleted";
|
||||
blocks: string[];
|
||||
blockedBy: string[];
|
||||
owner?: string;
|
||||
plan?: string;
|
||||
planFeedback?: string;
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add src/utils/models.ts
|
||||
git commit -m "feat: add planning status to TaskFile"
|
||||
```
|
||||
|
||||
### Task 2: Implement Plan Submission Tool
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/utils/tasks.ts`
|
||||
- Test: `src/utils/tasks.test.ts`
|
||||
|
||||
**Step 1: Write test for `submitPlan`**
|
||||
|
||||
```typescript
|
||||
it("should update task status to planning and save plan", async () => {
|
||||
const task = await createTask("test-team", "Task 1", "Desc");
|
||||
const updated = await submitPlan("test-team", task.id, "My Plan");
|
||||
expect(updated.status).toBe("planning");
|
||||
expect(updated.plan).toBe("My Plan");
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Implement `submitPlan` in `tasks.ts`**
|
||||
|
||||
```typescript
|
||||
export async function submitPlan(
|
||||
teamName: string,
|
||||
taskId: string,
|
||||
plan: string,
|
||||
): Promise<TaskFile> {
|
||||
return await updateTask(teamName, taskId, { status: "planning", plan });
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Run tests**
|
||||
|
||||
```bash
|
||||
npx vitest run src/utils/tasks.test.ts
|
||||
```
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add src/utils/tasks.ts src/utils/tasks.test.ts
|
||||
git commit -m "feat: implement submitPlan tool"
|
||||
```
|
||||
|
||||
### Task 3: Implement Plan Evaluation Tool (Approve/Reject)
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/utils/tasks.ts`
|
||||
- Test: `src/utils/tasks.test.ts`
|
||||
|
||||
**Step 1: Write test for `evaluatePlan`**
|
||||
|
||||
```typescript
|
||||
it("should set status to in_progress on approval", async () => {
|
||||
const task = await createTask("test-team", "Task 1", "Desc");
|
||||
await submitPlan("test-team", task.id, "My Plan");
|
||||
const approved = await evaluatePlan("test-team", task.id, "approve");
|
||||
expect(approved.status).toBe("in_progress");
|
||||
});
|
||||
|
||||
it("should set status back to in_progress or pending on reject with feedback", async () => {
|
||||
const task = await createTask("test-team", "Task 1", "Desc");
|
||||
await submitPlan("test-team", task.id, "My Plan");
|
||||
const rejected = await evaluatePlan(
|
||||
"test-team",
|
||||
task.id,
|
||||
"reject",
|
||||
"More detail needed",
|
||||
);
|
||||
expect(rejected.status).toBe("in_progress"); // Teammate stays in implementation but needs to revise
|
||||
expect(rejected.planFeedback).toBe("More detail needed");
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Implement `evaluatePlan` in `tasks.ts`**
|
||||
|
||||
```typescript
|
||||
export async function evaluatePlan(
|
||||
teamName: string,
|
||||
taskId: string,
|
||||
action: "approve" | "reject",
|
||||
feedback?: string,
|
||||
): Promise<TaskFile> {
|
||||
const status = action === "approve" ? "in_progress" : "in_progress"; // Simplified for now
|
||||
return await updateTask(teamName, taskId, { status, planFeedback: feedback });
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Run tests and commit**
|
||||
|
||||
```bash
|
||||
npx vitest run src/utils/tasks.test.ts
|
||||
git add src/utils/tasks.ts
|
||||
git commit -m "feat: implement evaluatePlan tool"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Broadcast Messaging
|
||||
|
||||
### Task 4: Implement Broadcast Messaging Tool
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/utils/messaging.ts`
|
||||
- Test: `src/utils/messaging.test.ts`
|
||||
|
||||
**Step 1: Write test for `broadcastMessage`**
|
||||
|
||||
```typescript
|
||||
it("should send message to all team members except sender", async () => {
|
||||
// setup team with lead, m1, m2
|
||||
await broadcastMessage(
|
||||
"test-team",
|
||||
"team-lead",
|
||||
"Hello everyone!",
|
||||
"Broadcast",
|
||||
);
|
||||
// verify m1 and m2 inboxes have the message
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: Implement `broadcastMessage`**
|
||||
|
||||
```typescript
|
||||
import { readConfig } from "./teams";
|
||||
|
||||
export async function broadcastMessage(
|
||||
teamName: string,
|
||||
fromName: string,
|
||||
text: string,
|
||||
summary: string,
|
||||
color?: string,
|
||||
) {
|
||||
const config = await readConfig(teamName);
|
||||
for (const member of config.members) {
|
||||
if (member.name !== fromName) {
|
||||
await sendPlainMessage(
|
||||
teamName,
|
||||
fromName,
|
||||
member.name,
|
||||
text,
|
||||
summary,
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Run tests and commit**
|
||||
|
||||
```bash
|
||||
npx vitest run src/utils/messaging.test.ts
|
||||
git add src/utils/messaging.ts
|
||||
git commit -m "feat: implement broadcastMessage tool"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Quality Gate Hooks
|
||||
|
||||
### Task 5: Implement Simple Hook System for Task Completion
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `src/utils/tasks.ts`
|
||||
- Create: `src/utils/hooks.ts`
|
||||
- Test: `src/utils/hooks.test.ts`
|
||||
|
||||
**Step 1: Create `hooks.ts` to run local hook scripts**
|
||||
|
||||
```typescript
|
||||
import { execSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
export function runHook(
|
||||
teamName: string,
|
||||
hookName: string,
|
||||
payload: any,
|
||||
): boolean {
|
||||
const hookPath = path.join(
|
||||
process.cwd(),
|
||||
".pi",
|
||||
"team-hooks",
|
||||
`${hookName}.sh`,
|
||||
);
|
||||
if (!fs.existsSync(hookPath)) return true; // No hook, success
|
||||
|
||||
try {
|
||||
const payloadStr = JSON.stringify(payload);
|
||||
execSync(`sh ${hookPath} '${payloadStr}'`, { stdio: "inherit" });
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`Hook ${hookName} failed`, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Modify `updateTask` in `tasks.ts` to trigger hook**
|
||||
|
||||
```typescript
|
||||
// in updateTask, after saving:
|
||||
if (updates.status === "completed") {
|
||||
const success = runHook(teamName, "task_completed", updated);
|
||||
if (!success) {
|
||||
// Optionally revert or mark as failed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Write test and verify**
|
||||
|
||||
```bash
|
||||
npx vitest run src/utils/hooks.test.ts
|
||||
git add src/utils/tasks.ts src/utils/hooks.ts
|
||||
git commit -m "feat: implement basic hook system for task completion"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Expose New Tools to Agents
|
||||
|
||||
### Task 6: Expose Tools in extensions/index.ts
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `extensions/index.ts`
|
||||
|
||||
**Step 1: Add `broadcast_message`, `task_submit_plan`, and `task_evaluate_plan` tools**
|
||||
**Step 2: Update `spawn_teammate` to include `plan_mode_required`**
|
||||
**Step 3: Update `task_update` to allow `planning` status**
|
||||
Loading…
Add table
Add a link
Reference in a new issue