clanker-agent/packages/clanker-teams/docs/plans/2026-02-22-pi-teams-core-features.md
Harivansh Rathi 67168d8289 chore: rebrand companion-os to clanker-agent
- Rename all package names from companion-* to clanker-*
- Update npm scopes from @mariozechner to @harivansh-afk
- Rename config directories .companion -> .clanker
- Rename environment variables COMPANION_* -> CLANKER_*
- Update all documentation, README files, and install scripts
- Rename package directories (companion-channels, companion-grind, companion-teams)
- Update GitHub URLs to harivansh-afk/clanker-agent
- Preserve full git history from companion-cloud monorepo
2026-03-26 16:22:52 -04:00

6.8 KiB

clanker-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 clanker-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 .clanker/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

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

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

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

export async function submitPlan(
  teamName: string,
  taskId: string,
  plan: string,
): Promise<TaskFile> {
  return await updateTask(teamName, taskId, { status: "planning", plan });
}

Step 3: Run tests

npx vitest run src/utils/tasks.test.ts

Step 4: Commit

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

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

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

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

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

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

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

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(),
    ".clanker",
    "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

// 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

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