mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
feat(desktop): auto-update bundled skills on app launch
Skills installed via Paseo desktop never updated after first run, so users were stuck on already-fixed skill content. On every launch, if the paseo base skill is present in `~/.agents/skills/`, sync each bundled skill (incl. `references/`) into agents, claude (via symlink/ junction), and codex — overwriting only files whose content differs. Files on disk that are not in the bundle are left alone; deprecation goes through tombstones (e.g. `paseo-orchestrate` redirects to `paseo-epic`). Also refreshes the bundled skill set: drops `paseo-chat`, adds `paseo-advisor` and `paseo-epic`, and turns `paseo-orchestrate` into a tombstone redirecting to `paseo-epic`. Adds a desktop test job to CI on Ubuntu and Windows so the junction/symlink path is exercised on both platforms.
This commit is contained in:
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@@ -137,6 +137,26 @@ jobs:
|
||||
src/server/persisted-config.test.ts
|
||||
src/server/bootstrap-provider-availability.test.ts
|
||||
|
||||
desktop-tests:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run desktop tests
|
||||
run: npm run test --workspace=@getpaseo/desktop
|
||||
|
||||
app-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -4,6 +4,7 @@ import os from "node:os";
|
||||
import { app } from "electron";
|
||||
import log from "electron-log/main";
|
||||
import { resolveCliInstallSourcePath } from "./cli-install-path.js";
|
||||
import { syncSkills } from "./skill-sync.js";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -19,11 +20,12 @@ interface InstallStatus {
|
||||
|
||||
const SKILL_NAMES = [
|
||||
"paseo",
|
||||
"paseo-loop",
|
||||
"paseo-handoff",
|
||||
"paseo-orchestrator",
|
||||
"paseo-chat",
|
||||
"paseo-advisor",
|
||||
"paseo-committee",
|
||||
"paseo-epic",
|
||||
"paseo-handoff",
|
||||
"paseo-loop",
|
||||
"paseo-orchestrate",
|
||||
];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -238,60 +240,70 @@ export async function getCliInstallStatus(): Promise<InstallStatus> {
|
||||
// Skills Installation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function copySkillFile(
|
||||
sourceFile: string,
|
||||
destDir: string,
|
||||
skillName: string,
|
||||
): Promise<void> {
|
||||
const destSkillDir = path.join(destDir, skillName);
|
||||
await fs.mkdir(destSkillDir, { recursive: true });
|
||||
await fs.copyFile(sourceFile, path.join(destSkillDir, "SKILL.md"));
|
||||
}
|
||||
|
||||
async function symlinkSkillDir(
|
||||
skillName: string,
|
||||
targetDir: string,
|
||||
linkParentDir: string,
|
||||
): Promise<void> {
|
||||
await fs.mkdir(linkParentDir, { recursive: true });
|
||||
const target = path.join(targetDir, skillName);
|
||||
const linkPath = path.join(linkParentDir, skillName);
|
||||
|
||||
if (await pathOrSymlinkExists(linkPath)) {
|
||||
await fs.rm(linkPath, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
try {
|
||||
await fs.symlink(target, linkPath, "junction");
|
||||
} catch {
|
||||
await copySkillFile(path.join(target, "SKILL.md"), linkParentDir, skillName);
|
||||
}
|
||||
} else {
|
||||
await fs.symlink(target, linkPath);
|
||||
}
|
||||
function getSkillSyncTargets(): {
|
||||
sourceDir: string;
|
||||
agentsDir: string;
|
||||
claudeDir: string;
|
||||
codexDir: string;
|
||||
} {
|
||||
return {
|
||||
sourceDir: getBundledSkillsDir(),
|
||||
agentsDir: getAgentsSkillsDir(),
|
||||
claudeDir: getClaudeSkillsDir(),
|
||||
codexDir: getCodexSkillsDir(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function installSkills(): Promise<InstallStatus> {
|
||||
const sourceDir = getBundledSkillsDir();
|
||||
const agentsDir = getAgentsSkillsDir();
|
||||
const claudeDir = getClaudeSkillsDir();
|
||||
const codexDir = getCodexSkillsDir();
|
||||
const targets = getSkillSyncTargets();
|
||||
log.info("[integrations] installSkills", targets);
|
||||
|
||||
log.info("[integrations] installSkills", { sourceDir, agentsDir, claudeDir, codexDir });
|
||||
|
||||
await Promise.all(
|
||||
SKILL_NAMES.map(async (skillName) => {
|
||||
const sourceFile = path.join(sourceDir, skillName, "SKILL.md");
|
||||
await copySkillFile(sourceFile, agentsDir, skillName);
|
||||
await symlinkSkillDir(skillName, agentsDir, claudeDir);
|
||||
await copySkillFile(sourceFile, codexDir, skillName);
|
||||
}),
|
||||
);
|
||||
const result = await syncSkills({
|
||||
...targets,
|
||||
skillNames: SKILL_NAMES,
|
||||
onSkillError: (skillName, error) => {
|
||||
log.warn("[integrations] skill install failed", { skillName, error });
|
||||
},
|
||||
});
|
||||
|
||||
log.info("[integrations] installSkills done", result);
|
||||
return getSkillsInstallStatus();
|
||||
}
|
||||
|
||||
export async function autoUpdateSkillsIfInstalled(): Promise<{
|
||||
ran: boolean;
|
||||
changedFiles: number;
|
||||
processedSkills: number;
|
||||
}> {
|
||||
const targets = getSkillSyncTargets();
|
||||
const installedMarker = path.join(targets.agentsDir, "paseo", "SKILL.md");
|
||||
|
||||
try {
|
||||
await fs.access(installedMarker);
|
||||
} catch {
|
||||
return { ran: false, changedFiles: 0, processedSkills: 0 };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await syncSkills({
|
||||
...targets,
|
||||
skillNames: SKILL_NAMES,
|
||||
onSkillError: (skillName, error) => {
|
||||
log.warn("[integrations] skill auto-update failed", { skillName, error });
|
||||
},
|
||||
});
|
||||
if (result.changedFiles > 0) {
|
||||
log.info("[integrations] auto-updated paseo skills", result);
|
||||
} else {
|
||||
log.info("[integrations] paseo skills already up to date", result);
|
||||
}
|
||||
return { ran: true, ...result };
|
||||
} catch (error) {
|
||||
log.warn("[integrations] auto-update skills aborted", { error });
|
||||
return { ran: false, changedFiles: 0, processedSkills: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSkillsInstallStatus(): Promise<InstallStatus> {
|
||||
const claudeDir = getClaudeSkillsDir();
|
||||
const accessResults = await Promise.all(
|
||||
|
||||
256
packages/desktop/src/integrations/skill-sync.test.ts
Normal file
256
packages/desktop/src/integrations/skill-sync.test.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
import { promises as fs } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { syncSkills } from "./skill-sync";
|
||||
|
||||
interface Sandbox {
|
||||
root: string;
|
||||
sourceDir: string;
|
||||
agentsDir: string;
|
||||
claudeDir: string;
|
||||
codexDir: string;
|
||||
}
|
||||
|
||||
async function makeSandbox(): Promise<Sandbox> {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), "paseo-skill-sync-"));
|
||||
const sourceDir = path.join(root, "bundle");
|
||||
const agentsDir = path.join(root, "home", ".agents", "skills");
|
||||
const claudeDir = path.join(root, "home", ".claude", "skills");
|
||||
const codexDir = path.join(root, "home", ".codex", "skills");
|
||||
await fs.mkdir(sourceDir, { recursive: true });
|
||||
return { root, sourceDir, agentsDir, claudeDir, codexDir };
|
||||
}
|
||||
|
||||
async function writeBundleSkill(
|
||||
sourceDir: string,
|
||||
name: string,
|
||||
files: Record<string, string>,
|
||||
): Promise<void> {
|
||||
const skillDir = path.join(sourceDir, name);
|
||||
await fs.mkdir(skillDir, { recursive: true });
|
||||
for (const [rel, content] of Object.entries(files)) {
|
||||
const full = path.join(skillDir, rel);
|
||||
await fs.mkdir(path.dirname(full), { recursive: true });
|
||||
await fs.writeFile(full, content);
|
||||
}
|
||||
}
|
||||
|
||||
describe("syncSkills", () => {
|
||||
let sandbox: Sandbox;
|
||||
|
||||
beforeEach(async () => {
|
||||
sandbox = await makeSandbox();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await fs.rm(sandbox.root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("overwrites on-disk skill content when the bundle differs", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", {
|
||||
"SKILL.md": "new paseo content",
|
||||
});
|
||||
const onDiskSkill = path.join(sandbox.agentsDir, "paseo");
|
||||
await fs.mkdir(onDiskSkill, { recursive: true });
|
||||
await fs.writeFile(path.join(onDiskSkill, "SKILL.md"), "old paseo content");
|
||||
|
||||
const result = await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
});
|
||||
|
||||
expect(result.processedSkills).toBe(1);
|
||||
expect(result.changedFiles).toBeGreaterThan(0);
|
||||
const agentsContent = await fs.readFile(
|
||||
path.join(sandbox.agentsDir, "paseo", "SKILL.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(agentsContent).toBe("new paseo content");
|
||||
const codexContent = await fs.readFile(
|
||||
path.join(sandbox.codexDir, "paseo", "SKILL.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(codexContent).toBe("new paseo content");
|
||||
});
|
||||
|
||||
it("installs new bundled skills, including references/, when not present on disk", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo-epic", {
|
||||
"SKILL.md": "epic content",
|
||||
"references/roles.md": "roles content",
|
||||
});
|
||||
|
||||
await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo-epic"],
|
||||
});
|
||||
|
||||
expect(await fs.readFile(path.join(sandbox.agentsDir, "paseo-epic", "SKILL.md"), "utf-8")).toBe(
|
||||
"epic content",
|
||||
);
|
||||
expect(
|
||||
await fs.readFile(
|
||||
path.join(sandbox.agentsDir, "paseo-epic", "references", "roles.md"),
|
||||
"utf-8",
|
||||
),
|
||||
).toBe("roles content");
|
||||
expect(
|
||||
await fs.readFile(
|
||||
path.join(sandbox.codexDir, "paseo-epic", "references", "roles.md"),
|
||||
"utf-8",
|
||||
),
|
||||
).toBe("roles content");
|
||||
|
||||
const claudeLink = path.join(sandbox.claudeDir, "paseo-epic");
|
||||
const lstat = await fs.lstat(claudeLink);
|
||||
expect(lstat.isSymbolicLink()).toBe(true);
|
||||
expect(await fs.readFile(path.join(claudeLink, "references", "roles.md"), "utf-8")).toBe(
|
||||
"roles content",
|
||||
);
|
||||
});
|
||||
|
||||
it("leaves on-disk skills not in the bundle untouched", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", { "SKILL.md": "new" });
|
||||
const customSkill = path.join(sandbox.agentsDir, "user-custom-skill");
|
||||
await fs.mkdir(customSkill, { recursive: true });
|
||||
await fs.writeFile(path.join(customSkill, "SKILL.md"), "user content");
|
||||
|
||||
await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
});
|
||||
|
||||
expect(await fs.readFile(path.join(customSkill, "SKILL.md"), "utf-8")).toBe("user content");
|
||||
});
|
||||
|
||||
it("does not delete files on disk that are no longer in the bundle", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", { "SKILL.md": "new" });
|
||||
const onDiskSkill = path.join(sandbox.agentsDir, "paseo");
|
||||
await fs.mkdir(path.join(onDiskSkill, "references"), { recursive: true });
|
||||
await fs.writeFile(path.join(onDiskSkill, "SKILL.md"), "old");
|
||||
await fs.writeFile(path.join(onDiskSkill, "references", "stale.md"), "stale");
|
||||
|
||||
await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
});
|
||||
|
||||
expect(await fs.readFile(path.join(onDiskSkill, "SKILL.md"), "utf-8")).toBe("new");
|
||||
expect(await fs.readFile(path.join(onDiskSkill, "references", "stale.md"), "utf-8")).toBe(
|
||||
"stale",
|
||||
);
|
||||
});
|
||||
|
||||
it("reports zero changed files on a no-op resync", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", {
|
||||
"SKILL.md": "content",
|
||||
"references/extra.md": "ref",
|
||||
});
|
||||
|
||||
const first = await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
});
|
||||
expect(first.changedFiles).toBeGreaterThan(0);
|
||||
|
||||
const second = await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
});
|
||||
expect(second.changedFiles).toBe(0);
|
||||
});
|
||||
|
||||
it("skips skills listed in skillNames that are missing from the bundle without raising", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", { "SKILL.md": "content" });
|
||||
// "paseo-removed" is in skillNames but not in the bundle on disk.
|
||||
|
||||
const errors: Array<{ name: string; error: unknown }> = [];
|
||||
const result = await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo", "paseo-removed"],
|
||||
onSkillError: (name, error) => errors.push({ name, error }),
|
||||
});
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(result.processedSkills).toBe(1);
|
||||
expect(await fs.readFile(path.join(sandbox.agentsDir, "paseo", "SKILL.md"), "utf-8")).toBe(
|
||||
"content",
|
||||
);
|
||||
await expect(fs.access(path.join(sandbox.agentsDir, "paseo-removed"))).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("leaves on-disk skill content alone when the skill has been removed from the bundle", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", { "SKILL.md": "current" });
|
||||
const deprecatedDir = path.join(sandbox.agentsDir, "paseo-deprecated");
|
||||
await fs.mkdir(deprecatedDir, { recursive: true });
|
||||
await fs.writeFile(path.join(deprecatedDir, "SKILL.md"), "old content");
|
||||
|
||||
await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo", "paseo-deprecated"],
|
||||
});
|
||||
|
||||
expect(await fs.readFile(path.join(deprecatedDir, "SKILL.md"), "utf-8")).toBe("old content");
|
||||
});
|
||||
|
||||
it("does not crash when the source bundle directory is missing", async () => {
|
||||
const missingSourceDir = path.join(sandbox.root, "no-bundle-here");
|
||||
|
||||
const errors: string[] = [];
|
||||
const result = await syncSkills({
|
||||
sourceDir: missingSourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
onSkillError: (skillName) => errors.push(skillName),
|
||||
});
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(result).toEqual({ changedFiles: 0, processedSkills: 0 });
|
||||
});
|
||||
|
||||
it("reports per-skill errors via onSkillError without throwing", async () => {
|
||||
await writeBundleSkill(sandbox.sourceDir, "paseo", { "SKILL.md": "content" });
|
||||
// Make agents skill path a file (not a directory) to force a write error
|
||||
await fs.mkdir(sandbox.agentsDir, { recursive: true });
|
||||
await fs.writeFile(path.join(sandbox.agentsDir, "paseo"), "blocking file");
|
||||
|
||||
const errors: string[] = [];
|
||||
const result = await syncSkills({
|
||||
sourceDir: sandbox.sourceDir,
|
||||
agentsDir: sandbox.agentsDir,
|
||||
claudeDir: sandbox.claudeDir,
|
||||
codexDir: sandbox.codexDir,
|
||||
skillNames: ["paseo"],
|
||||
onSkillError: (skillName) => errors.push(skillName),
|
||||
});
|
||||
|
||||
expect(errors).toContain("paseo");
|
||||
expect(result.processedSkills).toBe(0);
|
||||
});
|
||||
});
|
||||
122
packages/desktop/src/integrations/skill-sync.ts
Normal file
122
packages/desktop/src/integrations/skill-sync.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { promises as fs } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
export interface SkillSyncOptions {
|
||||
sourceDir: string;
|
||||
agentsDir: string;
|
||||
claudeDir: string;
|
||||
codexDir: string;
|
||||
skillNames: readonly string[];
|
||||
platform?: NodeJS.Platform;
|
||||
onSkillError?: (skillName: string, error: unknown) => void;
|
||||
}
|
||||
|
||||
export interface SkillSyncResult {
|
||||
changedFiles: number;
|
||||
processedSkills: number;
|
||||
}
|
||||
|
||||
async function writeFileIfChanged(srcPath: string, dstPath: string): Promise<boolean> {
|
||||
const src = await fs.readFile(srcPath);
|
||||
const dst = await fs.readFile(dstPath).catch(() => null);
|
||||
if (dst && src.equals(dst)) return false;
|
||||
await fs.mkdir(path.dirname(dstPath), { recursive: true });
|
||||
await fs.writeFile(dstPath, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
async function listFilesRecursive(rootDir: string): Promise<string[]> {
|
||||
const out: string[] = [];
|
||||
async function walk(dir: string): Promise<void> {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await walk(full);
|
||||
} else if (entry.isFile()) {
|
||||
out.push(path.relative(rootDir, full));
|
||||
}
|
||||
}
|
||||
}
|
||||
await walk(rootDir);
|
||||
return out;
|
||||
}
|
||||
|
||||
async function syncDirectoryFiles(srcDir: string, dstDir: string): Promise<number> {
|
||||
const files = await listFilesRecursive(srcDir);
|
||||
let changed = 0;
|
||||
for (const rel of files) {
|
||||
if (await writeFileIfChanged(path.join(srcDir, rel), path.join(dstDir, rel))) {
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
async function ensureClaudeSkillLink(
|
||||
skillName: string,
|
||||
agentsDir: string,
|
||||
claudeDir: string,
|
||||
platform: NodeJS.Platform,
|
||||
): Promise<number> {
|
||||
await fs.mkdir(claudeDir, { recursive: true });
|
||||
const target = path.join(agentsDir, skillName);
|
||||
const linkPath = path.join(claudeDir, skillName);
|
||||
|
||||
// Always rebuild the link rather than diffing it. fs.rm with force: true is
|
||||
// a no-op when nothing is there, and matches existing install behavior.
|
||||
// On Windows, `fs.rm` does not follow junctions, so the agents-side content
|
||||
// is preserved.
|
||||
await fs.rm(linkPath, { recursive: true, force: true });
|
||||
|
||||
if (platform === "win32") {
|
||||
try {
|
||||
// Junctions don't require Developer Mode / admin like regular symlinks do.
|
||||
await fs.symlink(target, linkPath, "junction");
|
||||
return 0;
|
||||
} catch {
|
||||
return await syncDirectoryFiles(target, linkPath);
|
||||
}
|
||||
}
|
||||
|
||||
await fs.symlink(target, linkPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
export async function syncSkills(options: SkillSyncOptions): Promise<SkillSyncResult> {
|
||||
const platform = options.platform ?? process.platform;
|
||||
let changedFiles = 0;
|
||||
let processedSkills = 0;
|
||||
|
||||
for (const skillName of options.skillNames) {
|
||||
const bundleSkillDir = path.join(options.sourceDir, skillName);
|
||||
|
||||
const bundleStat = await fs.stat(bundleSkillDir).catch(() => null);
|
||||
if (!bundleStat?.isDirectory()) continue;
|
||||
|
||||
try {
|
||||
changedFiles += await syncDirectoryFiles(
|
||||
bundleSkillDir,
|
||||
path.join(options.agentsDir, skillName),
|
||||
);
|
||||
|
||||
changedFiles += await ensureClaudeSkillLink(
|
||||
skillName,
|
||||
options.agentsDir,
|
||||
options.claudeDir,
|
||||
platform,
|
||||
);
|
||||
|
||||
changedFiles += await syncDirectoryFiles(
|
||||
bundleSkillDir,
|
||||
path.join(options.codexDir, skillName),
|
||||
);
|
||||
|
||||
processedSkills++;
|
||||
} catch (error) {
|
||||
options.onSkillError?.(skillName, error);
|
||||
}
|
||||
}
|
||||
|
||||
return { changedFiles, processedSkills };
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
createBeforeQuitHandler,
|
||||
stopDesktopManagedDaemonOnQuitIfNeeded,
|
||||
} from "./daemon/quit-lifecycle.js";
|
||||
import { autoUpdateSkillsIfInstalled } from "./integrations/integrations-manager.js";
|
||||
|
||||
const DEV_SERVER_URL = process.env.EXPO_DEV_URL ?? "http://localhost:8081";
|
||||
const APP_SCHEME = "paseo";
|
||||
@@ -392,6 +393,11 @@ async function bootstrap(): Promise<void> {
|
||||
registerDialogHandlers();
|
||||
registerNotificationHandlers();
|
||||
registerOpenerHandlers();
|
||||
|
||||
void autoUpdateSkillsIfInstalled().catch((error) => {
|
||||
log.warn("[integrations] auto-update skills failed", error);
|
||||
});
|
||||
|
||||
await createMainWindow();
|
||||
|
||||
app.on("activate", async () => {
|
||||
|
||||
48
skills/paseo-advisor/SKILL.md
Normal file
48
skills/paseo-advisor/SKILL.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: paseo-advisor
|
||||
description: Spin up a single agent as an advisor — second opinion on the current task. Use when the user says "advisor", "second opinion", "what does X think", or wants an outside take without delegating the work itself.
|
||||
user-invocable: true
|
||||
argument-hint: "[--provider <name>] <question or topic>"
|
||||
---
|
||||
|
||||
# Paseo Advisor
|
||||
|
||||
Single agent. Reads the situation you're in. Gives a judgment. You decide what to do — the advisor doesn't drive the work.
|
||||
|
||||
**User's request:** $ARGUMENTS
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Read the **paseo** skill — provider for the advisor comes from orchestration preferences unless the user names one.
|
||||
|
||||
## Picking the advisor
|
||||
|
||||
1. **User named one** (`--provider claude/opus`) → use it.
|
||||
2. **Otherwise** resolve from preferences — pick the category that matches the question:
|
||||
- Design / approach question → `planning`
|
||||
- "Did I miss something" review → `audit`
|
||||
- "Is this even right" → `research`
|
||||
3. **Contrast helps.** If your own provider matches what preferences would pick, swap to a different family on purpose — fresh perspective is the point.
|
||||
|
||||
## The briefing
|
||||
|
||||
The advisor has zero context. Make it self-contained:
|
||||
|
||||
- The question, sharply.
|
||||
- What you've considered and what you've ruled out.
|
||||
- Relevant files by path (don't paste — let the agent read).
|
||||
- Explicit ask: "give me a recommendation, with reasoning."
|
||||
|
||||
End with the no-edits suffix:
|
||||
|
||||
```
|
||||
This is analysis only. Do NOT edit, create, or delete any files. Do NOT write code.
|
||||
```
|
||||
|
||||
## Launch and synthesize
|
||||
|
||||
Create the advisor agent via Paseo with a `[Advisor] <topic>` title and the briefing as the initial prompt. Wait for it to finish. Read its response. Synthesize for the user — the advisor's verdict + your recommendation.
|
||||
|
||||
## Persistent advisor
|
||||
|
||||
If the user wants ongoing input ("keep this advisor for the next few decisions"), don't archive after the first reply. Send follow-ups when you need another take. Archive when the user says they're done, or when the topic shifts and a fresh context would serve better.
|
||||
@@ -1,134 +0,0 @@
|
||||
---
|
||||
name: paseo-chat
|
||||
description: Use chat rooms through the Paseo CLI. Use when the user says "chat room", "room", "coordinate through chat", "shared mailbox", or wants agents to communicate asynchronously.
|
||||
user-invocable: true
|
||||
---
|
||||
|
||||
# Paseo Chat Skill
|
||||
|
||||
This skill teaches how to use chat rooms for agent coordination via the Paseo CLI.
|
||||
|
||||
**User's arguments:** $ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Load the **Paseo skill** first if you need CLI guidance for launching or messaging agents.
|
||||
|
||||
## Rules
|
||||
|
||||
When using chat:
|
||||
|
||||
- create a room with `paseo chat create` if you need a new room
|
||||
- inspect available rooms with `paseo chat ls` and `paseo chat inspect`
|
||||
- post with `paseo chat post`
|
||||
- read with `paseo chat read`
|
||||
- keep reads bounded, usually `--limit 10` or `--limit 20`
|
||||
- check chat often while working
|
||||
|
||||
Mentions are active:
|
||||
|
||||
- write mentions inline in the message body as `@<agent-id>` to notify a specific agent immediately
|
||||
- use `@everyone` to notify all non-archived, non-internal agents
|
||||
- notifications are sent to the target agent without blocking the chat post
|
||||
- if a normal post is enough and no one needs to act right now, skip the mention
|
||||
|
||||
## Command Surface
|
||||
|
||||
### Create a room
|
||||
|
||||
```bash
|
||||
paseo chat create issue-456 --purpose "Coordinate implementation and review"
|
||||
```
|
||||
|
||||
### List rooms
|
||||
|
||||
```bash
|
||||
paseo chat ls
|
||||
```
|
||||
|
||||
### Inspect room details
|
||||
|
||||
```bash
|
||||
paseo chat inspect issue-456
|
||||
```
|
||||
|
||||
### Post a message
|
||||
|
||||
```bash
|
||||
paseo chat post issue-456 "I traced the failure to relay auth. Investigating config loading now."
|
||||
```
|
||||
|
||||
With a reply:
|
||||
|
||||
```bash
|
||||
paseo chat post issue-456 "I can take that next." --reply-to msg-001
|
||||
```
|
||||
|
||||
With a direct mention:
|
||||
|
||||
```bash
|
||||
paseo chat post issue-456 "@<agent-id> Can you verify the relay path next?"
|
||||
```
|
||||
|
||||
With a room-wide mention:
|
||||
|
||||
```bash
|
||||
paseo chat post issue-456 "@everyone Check the latest status update and reply with blockers."
|
||||
```
|
||||
|
||||
### Read recent messages
|
||||
|
||||
```bash
|
||||
paseo chat read issue-456 --limit 10
|
||||
```
|
||||
|
||||
### Filter reads
|
||||
|
||||
```bash
|
||||
paseo chat read issue-456 --agent <agent-id>
|
||||
paseo chat read issue-456 --since 5m
|
||||
paseo chat read issue-456 --since 2026-03-24T10:00:00Z
|
||||
```
|
||||
|
||||
### Wait for new messages
|
||||
|
||||
```bash
|
||||
paseo chat wait issue-456 --timeout 60s
|
||||
```
|
||||
|
||||
## Defaults
|
||||
|
||||
When creating a room:
|
||||
|
||||
- choose a short slug: `issue-456`, `pr-143-review`, `relay-cleanup`
|
||||
- give it a clear purpose
|
||||
|
||||
When using a room:
|
||||
|
||||
- read only a bounded window before acting
|
||||
- post updates when they would help another agent or your future self
|
||||
- use `--reply-to` when responding to a specific message
|
||||
- use inline `@<agent-id>` mentions when you want to get a specific agent's attention
|
||||
- use `@everyone` when the whole active team needs to react now
|
||||
- check chat frequently enough that shared coordination actually works
|
||||
- your own agent ID is available via `$PASEO_AGENT_ID`
|
||||
|
||||
Typical things to post:
|
||||
|
||||
- status updates
|
||||
- blockers
|
||||
- handoffs
|
||||
- review findings
|
||||
- important context another agent may need later
|
||||
|
||||
## Your Job
|
||||
|
||||
1. Understand whether you should use an existing room or create a new one
|
||||
2. Create the room with `paseo chat create` if needed
|
||||
3. Read the room with bounded history
|
||||
4. Post clearly
|
||||
5. Use `--reply-to` when replying to a specific message
|
||||
6. Use inline `@<agent-id>` mentions when you want to notify someone directly
|
||||
7. Use `@everyone` when you need to notify all active non-archived agents
|
||||
@@ -6,154 +6,76 @@ user-invocable: true
|
||||
|
||||
# Committee Skill
|
||||
|
||||
You are forming a committee to step back from the current problem and get fresh perspective.
|
||||
Two agents from contrasting providers, fresh context, planning a solution in parallel. They stay alive for review after implementation.
|
||||
|
||||
The purpose is to step back, not double down. The committee may propose a completely different approach.
|
||||
|
||||
**User's additional context:** $ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Load the **Paseo skill** first — it contains the CLI reference for all agent commands and waiting guidelines.
|
||||
Read the **paseo** skill. Contrast is the point of a committee, so pick across providers deliberately rather than using whatever the default category would resolve to.
|
||||
|
||||
## What Is a Committee
|
||||
## Composition
|
||||
|
||||
Two agents — **Opus 4.6** (`--thinking on`) and **GPT 5.4** (`--thinking medium`) — launched in parallel to plan a solution. Fresh context, no implementation baggage, proper root cause analysis.
|
||||
Two members with different reasoning styles:
|
||||
|
||||
They stay alive after planning for Phase 3 review — they hold only the plan, so they catch implementation drift.
|
||||
- **Claude Opus** with extended thinking on
|
||||
- **Codex GPT-5.4** with thinking on
|
||||
|
||||
**The purpose is to step back, not to double down.** The committee may propose a completely different approach.
|
||||
Override only when the user explicitly asks for different members.
|
||||
|
||||
## Your Role
|
||||
## Hard rules
|
||||
|
||||
You drive the full lifecycle: plan → implement → review. You are a middleman between the user and the committee. Do not yield back to the user until the cycle is complete. If the user needs to weigh in on a divergence, ask them — but don't stop the process.
|
||||
- **No edits.** Every prompt to a committee member ends with the no-edits suffix:
|
||||
|
||||
## No Anxiety
|
||||
```
|
||||
This is analysis only. Do NOT edit, create, or delete any files. Do NOT write code.
|
||||
```
|
||||
|
||||
**Once you call `paseo wait`, trust the wait.** Do not poll logs, read output early, send hurry-up messages, interrupt deep analysis, or give up because it's taking long.
|
||||
- **Trust the wait.** Do not poll, send hurry-ups, or interrupt. GPT-5.4 can reason 15–30 minutes; Opus does extended thinking. Long waits mean it found something worth thinking about.
|
||||
- **You are the middleman.** Drive plan → implement → review without yielding to the user, except for divergences that need their call.
|
||||
|
||||
GPT 5.4 can reason for 15–30 minutes. Opus does extended thinking. Long waits mean the agent found something worth thinking about. Let it finish.
|
||||
## Phase 1: Plan
|
||||
|
||||
If the CLI has a bug, the user will tell you.
|
||||
|
||||
## No-Edits Suffix
|
||||
|
||||
Every prompt to a committee member — initial, follow-up, or review — **must** end with this suffix. They will start editing code if you don't.
|
||||
|
||||
```
|
||||
NO_EDITS="This is analysis only. Do NOT edit, create, or delete any files. Do NOT write code."
|
||||
```
|
||||
|
||||
All example prompts below include `$NO_EDITS` — always expand it.
|
||||
|
||||
## Phase 1: Get a Plan
|
||||
|
||||
### Write the prompt
|
||||
|
||||
Describe the **overall problem**, not just the immediate symptom:
|
||||
Write a problem-level prompt:
|
||||
|
||||
- High-level goal and acceptance criteria
|
||||
- Constraints
|
||||
- Symptoms (if a bug)
|
||||
- What you've tried and why it failed
|
||||
- Explicitly ask for root cause analysis
|
||||
- What you tried and why it failed
|
||||
- Explicit: "do root cause analysis"
|
||||
- Explicit: "use think-harder — state assumptions, ask why three levels deep, check whether you're patching a symptom or removing the problem"
|
||||
|
||||
```bash
|
||||
prompt="We're trying to [high-level goal]. Constraints: [X, Y, Z]. Acceptance criteria: [A, B, C].
|
||||
Create both agents in parallel via Paseo with `[Committee] <task>` titles and the same prompt. Wait for both — not just whichever finishes first.
|
||||
|
||||
We've been stuck on this. Here's what we've tried and why it didn't work:
|
||||
- [approach 1] — failed because [reason]
|
||||
- [approach 2] — partially worked but [issue]
|
||||
Read both responses. Challenge them — do not accept at face value:
|
||||
|
||||
Step back from these attempts. Do root cause analysis — the fix might not be for [immediate symptom] at all, it might be structural.
|
||||
- "Why does <underlying thing> happen? Symptom or cause?"
|
||||
- Verify any assumption the plan makes about the code.
|
||||
- "What did you considered and reject?"
|
||||
|
||||
Use the think-harder approach: state your assumptions, ask why at least 3 levels deep for each, and check whether you're patching a symptom or removing the problem. What's the right approach?
|
||||
Send follow-ups until the plan addresses root cause.
|
||||
|
||||
$NO_EDITS"
|
||||
```
|
||||
Synthesize:
|
||||
|
||||
### Launch both members
|
||||
|
||||
Same prompt to both, `[Committee]` prefix for identification:
|
||||
|
||||
```bash
|
||||
opus_id=$(paseo run -d --mode bypassPermissions --provider claude/opus --thinking on --name "[Committee] Task description" "$prompt" -q)
|
||||
gpt_id=$(paseo run -d --mode full-access --provider codex/gpt-5.4 --thinking medium --name "[Committee] Task description" "$prompt" -q)
|
||||
```
|
||||
|
||||
### Wait for both
|
||||
|
||||
Wait for **both** agents — not just the first one that finishes.
|
||||
|
||||
```bash
|
||||
paseo wait "$opus_id"
|
||||
paseo wait "$gpt_id"
|
||||
```
|
||||
|
||||
### Read and challenge
|
||||
|
||||
```bash
|
||||
paseo logs "$opus_id"
|
||||
paseo logs "$gpt_id"
|
||||
```
|
||||
|
||||
**Do not accept output at face value.** Use the **think-harder** framework to challenge their output. Before synthesizing:
|
||||
|
||||
1. **Ask "why" 2–3 levels deep.** "Fix X because Y is broken" — why is Y broken? Is Y a root cause or a consequence?
|
||||
2. **Challenge assumptions.** If the plan assumes something about the code, make the agent verify it.
|
||||
3. **Symptom vs cause.** "Are we fixing the consequence or the cause?"
|
||||
4. **Probe alternatives.** "What did you consider and reject?"
|
||||
|
||||
```bash
|
||||
paseo send "$opus_id" "You said [X]. Why does [underlying thing] happen in the first place? Are we patching a symptom? $NO_EDITS"
|
||||
paseo wait "$opus_id"
|
||||
paseo logs "$opus_id"
|
||||
```
|
||||
|
||||
Keep pushing until the plan addresses the root cause.
|
||||
|
||||
### Synthesize and confirm
|
||||
|
||||
- Convergence → merge into unified plan.
|
||||
- Convergence → unified plan.
|
||||
- Significant divergence → involve the user.
|
||||
|
||||
Send the merged plan back for confirmation. Multi-turn if needed — keep going until consensus.
|
||||
|
||||
```bash
|
||||
paseo send "$opus_id" "Merged plan: [plan]. Concerns? $NO_EDITS"
|
||||
paseo send "$gpt_id" "Merged plan: [plan]. Concerns? $NO_EDITS"
|
||||
```
|
||||
Confirm the merged plan with both members. Multi-turn until consensus.
|
||||
|
||||
## Phase 2: Implement
|
||||
|
||||
Implement the plan yourself — unless the user said **"delegate"**, in which case launch an implementer:
|
||||
Default: implement yourself. If the user said **"delegate"**, launch one impl agent and pass the merged plan.
|
||||
|
||||
```bash
|
||||
impl_id=$(paseo run -d --mode full-access --provider codex/gpt-5.4 --name "[Impl] Task description" "Implement the following plan end-to-end. [plan]" -q)
|
||||
paseo wait "$impl_id"
|
||||
```
|
||||
|
||||
Committee agents stay clean — not involved in implementation.
|
||||
The committee stays clean — not involved in implementation.
|
||||
|
||||
## Phase 3: Review
|
||||
|
||||
Send the committee the changes for review. They anchor against the plan and catch drift.
|
||||
Send the diff to the committee:
|
||||
|
||||
```bash
|
||||
review_prompt="Implementation is done. Review changes against the plan. Flag drift or missing pieces. $NO_EDITS"
|
||||
> Implementation is done. Review changes against the plan. Flag drift or missing pieces. <no-edits suffix>
|
||||
|
||||
paseo send "$opus_id" "$review_prompt"
|
||||
paseo send "$gpt_id" "$review_prompt"
|
||||
Apply feedback yourself, or send to the impl agent. Repeat 2 → 3 until consensus.
|
||||
|
||||
paseo wait "$opus_id"
|
||||
paseo wait "$gpt_id"
|
||||
|
||||
paseo logs "$opus_id"
|
||||
paseo logs "$gpt_id"
|
||||
```
|
||||
|
||||
### Iterate
|
||||
|
||||
Send committee feedback to the implementer (or apply yourself). Repeat Phase 2 → 3 until the committee confirms the implementation matches the plan.
|
||||
|
||||
After ~10 iterations without convergence, start a fresh committee with full context of what was tried — the current committee's context may have drifted too far.
|
||||
After ~10 iterations without convergence, start a fresh committee with the full history of what was tried — the current committee's context may have drifted too far.
|
||||
|
||||
285
skills/paseo-epic/SKILL.md
Normal file
285
skills/paseo-epic/SKILL.md
Normal file
@@ -0,0 +1,285 @@
|
||||
---
|
||||
name: paseo-epic
|
||||
description: Heavy-ceremony orchestration for big work — research, planning, adversarial review, phased implementation, audit, delivery. Use when the user says "epic", "long task", "build this end to end", or wants a feature that runs all night.
|
||||
user-invocable: true
|
||||
argument-hint: "[--autopilot] [--worktree] [--no-grill] <task>"
|
||||
---
|
||||
|
||||
# Paseo Epic
|
||||
|
||||
Heavy-ceremony orchestrator. Runs research → plan → implement → deliver as one resumable flow. The plan file at `~/.paseo/plans/<slug>.md` is the source of truth and survives compaction.
|
||||
|
||||
**User's request:** $ARGUMENTS
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Read the **paseo** skill — it carries the surface (worktrees, agents, waiting, scheduling, preferences). Every agent you spawn reads it too.
|
||||
|
||||
The role and phase-type vocabulary lives in the roles reference shipped with this skill (`references/roles.md`).
|
||||
|
||||
## Modes
|
||||
|
||||
- **Default**: conversational. Grills, gates between phases, ask before deliver.
|
||||
- `--autopilot`: no grills, no gates, run through deliver. For all-night work.
|
||||
- `--worktree`: isolate the work in a new worktree.
|
||||
- `--no-grill`: skip clarifying questions; keep gates.
|
||||
|
||||
## Hard rules
|
||||
|
||||
- **The plan file is the source of truth.** Re-read before every phase.
|
||||
- **You are the only writer to the plan file.** Agents don't touch it.
|
||||
- **Provider for every agent comes from orchestration preferences** — match the role's category.
|
||||
- **Worktrees only via Paseo.** Never run `git worktree add` yourself.
|
||||
- **Agents do not commit.** Delivery happens in the deliver phase.
|
||||
- **Describe problems, not solutions.** Tell agents what's broken or needed; let them decide how. No specific line numbers or code snippets in prompts.
|
||||
- **One agent per phase.** If a phase needs two, the planner split it wrong.
|
||||
- **Don't poll agents.** Wait for them properly.
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
[Worktree] → Research → [Grill] → Plan → Adversarial review → [Confirm] → Implement → Deliver
|
||||
^^^^^^^ ^^^^^^^^^
|
||||
default mode default mode
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Research yourself
|
||||
|
||||
Read the code first. Grep the relevant area, read 2–4 key files, understand the current shape.
|
||||
|
||||
For ≥3 packages or architectural change, spawn one or two **researcher** agents — each scoped to one area. Provider from the `research` preference. Tell each researcher to read the roles reference for its mandate, read the area you've assigned, and report files / types / patterns / gotchas. No solutions. No edits.
|
||||
|
||||
State your own understanding to the user in 2–3 sentences.
|
||||
|
||||
## 2. Worktree (if `--worktree`)
|
||||
|
||||
Create a worktree via Paseo. Record the returned path and branch — they go into the plan frontmatter.
|
||||
|
||||
## 3. Grill (unless `--no-grill` or `--autopilot`)
|
||||
|
||||
Use `AskUserQuestion`. One at a time, recommended option stated, branches resolved depth-first. Never ask code-answerable questions. Every 3–4 questions, summarize resolved decisions.
|
||||
|
||||
Stop when branches are resolved or the user says "go".
|
||||
|
||||
## 4. Plan with adversarial review
|
||||
|
||||
### Spawn a planner
|
||||
|
||||
Persistent — keep iterating, do not archive after the first response. Provider from the `planning` preference.
|
||||
|
||||
Prompt it to:
|
||||
|
||||
- Read the roles reference for vocabulary.
|
||||
- Take the objective and resolved decisions from grill as input.
|
||||
- Think refactor-first: if existing code doesn't accommodate the change, plan the reshape before the feature. Phases like "wire up", "glue", "integrate" usually mean an upstream refactor was missed.
|
||||
- Reply terse, one line per phase, in chat — not to disk.
|
||||
|
||||
### Challenge it
|
||||
|
||||
Send follow-ups. Push on edge cases, alternative orderings, smallest shippable slice, bolt-on phases that should be a refactor instead. Iterate until the plan is sharp.
|
||||
|
||||
### Spawn a plan-reviewer
|
||||
|
||||
Provider from the `planning` preference. Prompt it to:
|
||||
|
||||
- Read the roles reference.
|
||||
- Read the planner's draft.
|
||||
- Challenge it: bolt-ons, missing edge cases, over-engineering, wrong ordering, hidden dependencies. Push for alternatives. Force tradeoffs.
|
||||
|
||||
### Surface tradeoffs to the user
|
||||
|
||||
Never present raw planner output. Surface the choice:
|
||||
|
||||
> Planner wants A → B → C (working slice fastest, defers refactor).
|
||||
> Reviewer argued for B → A → C (refactor first, slower but cleaner).
|
||||
> Which?
|
||||
|
||||
Use `AskUserQuestion`. Iterate the planner if the user picks differently.
|
||||
|
||||
Archive the planner and plan-reviewer once the plan is locked.
|
||||
|
||||
## 5. Write the plan
|
||||
|
||||
Persist to `~/.paseo/plans/<slug>.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
task: <slug>
|
||||
status: not-started
|
||||
worktree: <abs path or null>
|
||||
branch: <branch or null>
|
||||
pr: null
|
||||
created: <ISO>
|
||||
updated: <ISO>
|
||||
---
|
||||
|
||||
# <Title>
|
||||
|
||||
## Objective
|
||||
|
||||
<one paragraph>
|
||||
|
||||
## Notes
|
||||
|
||||
- <ISO> orchestrator: <freeform>
|
||||
|
||||
## Phases
|
||||
|
||||
- [ ] **Phase 1** · <type> · <short name>
|
||||
Acceptance: <one line>
|
||||
|
||||
- [ ] **Phase N** · gate · user smoke test
|
||||
|
||||
- [ ] **Phase N+1** · deliver · <commit | PR + merge | cherry-pick>
|
||||
```
|
||||
|
||||
Phase types: `refactor`, `implement`, `verify`, `gate`, `deliver`. Verify variants written inline: `verify · unslop`, `verify · qa`, `verify · spec`, `verify · review`. See the roles reference.
|
||||
|
||||
Status markers: `[ ]` not started, `[~]` in progress, `[x]` done, `[!]` blocked.
|
||||
|
||||
## 6. Confirm (default mode)
|
||||
|
||||
Show the phase list (not the file contents — they'll read it). 2–3 sentences. Wait.
|
||||
|
||||
If `--autopilot`: skip.
|
||||
|
||||
---
|
||||
|
||||
## 7. Implement
|
||||
|
||||
Loop: find next undone phase → mark `[~]` → dispatch by type → wait → verify → mark `[x]` → repeat.
|
||||
|
||||
Stop when: a `gate` phase is reached, all phases `[x]`, or a phase is `[!]` blocked and you can't unblock it.
|
||||
|
||||
### Dispatch by phase type
|
||||
|
||||
#### refactor
|
||||
|
||||
Spawn a refactorer. Provider from `impl` (or `ui` for styling-only reshapes). cwd = the worktree path if set. Tell it to:
|
||||
|
||||
- Read the roles reference and load the skills it names.
|
||||
- Read the plan file. Scope is Phase N; acceptance is pinned there.
|
||||
- Reshape, not feature: behavior identical before and after. Existing tests stay green. Add a parity test if missing.
|
||||
- When done: typecheck pass + relevant tests green. Do not commit. Do not update the plan.
|
||||
|
||||
#### implement
|
||||
|
||||
Spawn an impl agent. Provider from `impl` (or `ui` for styling-only). cwd = the worktree path if set. Tell it to:
|
||||
|
||||
- Read the roles reference and load the skills it names.
|
||||
- Read the plan file. Scope is Phase N.
|
||||
- Read any plan-relevant repo docs by path.
|
||||
- TDD: failing test first, then make it pass.
|
||||
- If the existing shape doesn't accommodate the change, push back instead of bolting on — a refactor phase should have come first.
|
||||
- When done: typecheck + every test it touched green. Do not commit. Do not update the plan.
|
||||
|
||||
#### verify
|
||||
|
||||
Spawn an auditor matching the variant after `verify ·`. Provider from `audit`. The roles reference's variant table tells the auditor what to load and what to output. Read-only — no edits.
|
||||
|
||||
#### gate
|
||||
|
||||
No agent. Yield to the user.
|
||||
|
||||
1. Mark this phase `[x]`.
|
||||
2. Compose handoff: worktree path (if set), what to test (next phase's acceptance, or this phase's Notes), how to resume (`/epic <slug>` once satisfied, or edit the plan first).
|
||||
3. Exit cleanly. Don't launch the next phase. Don't poll.
|
||||
|
||||
#### deliver
|
||||
|
||||
Inline — see Section 8.
|
||||
|
||||
### Verifying agent output
|
||||
|
||||
For `refactor` and `implement`:
|
||||
|
||||
1. Read the agent's final activity.
|
||||
2. Confirm acceptance: typecheck + tests green, what was touched matches the phase.
|
||||
3. Wrong → send a follow-up to the same agent. Don't launch a new one for course-corrections.
|
||||
4. OK → archive.
|
||||
|
||||
For `verify`:
|
||||
|
||||
- Green → mark the audited phase `[x]`, advance.
|
||||
- Issues → append findings to Notes. Do not mark the phase done. Either send the impl agent the findings as new acceptance, or surface to the user if ambiguous.
|
||||
|
||||
### When the user interjects
|
||||
|
||||
- Feedback on a running agent → forward to it.
|
||||
- Plan change → edit the plan file (add/remove/reorder), tell them what changed, continue.
|
||||
- "Stop" / "kill" → archive running agents, summarize state, wait.
|
||||
- New question → answer briefly, continue.
|
||||
|
||||
The plan file lets a fresh orchestrator pick up if the user kills you and reinvokes — write everything important to Notes immediately.
|
||||
|
||||
---
|
||||
|
||||
## 8. Deliver
|
||||
|
||||
Read frontmatter to choose mode:
|
||||
|
||||
```
|
||||
worktree: null → Mode A: main commit
|
||||
worktree: <path> → Mode B (PR) or Mode C (cherry-pick); ask if not specified
|
||||
```
|
||||
|
||||
Never push to main directly. Never force-push without explicit permission. Never merge before CI is green. Archive worktrees via Paseo, never `git worktree remove`.
|
||||
|
||||
### Mode A — main commit
|
||||
|
||||
1. `git status` — confirm related changes.
|
||||
2. `git diff` — review.
|
||||
3. Draft a commit message: title <70 chars imperative; body 1–3 sentences why; match repo style (`git log --oneline -20`).
|
||||
4. `git add <specific files>` — never `-A` or `.`.
|
||||
5. `git commit -m "..."` (HEREDOC).
|
||||
6. Update plan: `status: delivered`. Append a Notes line.
|
||||
7. Tell user: hash + summary. Ask about push.
|
||||
|
||||
### Mode B — worktree → PR + merge
|
||||
|
||||
1. **Commit cleanly in the worktree.** One tidy commit per logical change. Match repo style.
|
||||
2. **Rebase if behind main.** Spawn an agent that loads the rebase skill. Provider from `impl`. Tell it to rebase onto origin/main, resolve conflicts by intent (never blanket-accept one side), confirm typecheck and tests still pass, do not push.
|
||||
3. **Push the branch** — `git -C <worktree> push -u origin <branch-from-frontmatter>`.
|
||||
4. **Open the PR** — `gh pr create` with summary from plan Objective + Phases and test plan from acceptance lines. Capture URL → frontmatter `pr:`. Status → `pr-open`.
|
||||
5. **Monitor CI.** Either watch directly (`gh pr checks <n> --watch`), or spawn a fix-build agent that loads the fix-build skill. Provider from `impl`. Tell it to drive the PR to green: when checks fail, read failure logs, fix, push, repeat. Don't merge — your call.
|
||||
When green: append Notes, frontmatter `status: ready-to-merge`.
|
||||
6. **Merge** when green — ask the user (`AskUserQuestion`: squash / rebase / merge / wait). Read repo convention from recent merged PRs (`gh pr list --state merged -L 5 --json mergeCommit,title`).
|
||||
```bash
|
||||
gh pr merge <n> --squash --delete-branch
|
||||
```
|
||||
7. **Archive the worktree** via Paseo. Frontmatter: `status: delivered`, `worktree: null`. Append a Notes line.
|
||||
|
||||
### Mode C — worktree → cherry-pick
|
||||
|
||||
1. Commit cleanly in the worktree (single clean commit per logical change).
|
||||
2. From the main checkout (don't `cd`): `git cherry-pick <sha>`. For multiple: `git cherry-pick <oldest>..<newest>`.
|
||||
3. Conflicts → stop, tell the user. Don't auto-resolve.
|
||||
4. Archive the worktree via Paseo. Frontmatter: `status: delivered`, `worktree: null`. Ask about push.
|
||||
|
||||
---
|
||||
|
||||
## Resumability
|
||||
|
||||
The user can interrupt or kill at any phase. New invocation:
|
||||
|
||||
1. Find the plan by slug (or most recently updated).
|
||||
2. Read frontmatter `status` and the first non-done phase.
|
||||
3. Resume from the matching phase.
|
||||
|
||||
Mid-deliver resumption:
|
||||
|
||||
- `status: pr-open` + `pr: <url>` → resume CI monitoring.
|
||||
- `status: ready-to-merge` → ask the user to merge again.
|
||||
- `status: delivered` + `worktree: <path>` → worktree wasn't archived, do that.
|
||||
|
||||
## Failure modes
|
||||
|
||||
- Treating phases as a checklist to grind through. They're gates. Verify before advancing.
|
||||
- Forgetting to set the agent's cwd to the worktree path in worktree mode.
|
||||
- Re-explaining the plan to the user. They wrote it with you. Reference phases by number.
|
||||
- Polling agents instead of waiting properly.
|
||||
- Editing code yourself. You orchestrate. Agents implement.
|
||||
- Marking `status: delivered` before the worktree is actually archived.
|
||||
- Pushing to main directly.
|
||||
120
skills/paseo-epic/references/roles.md
Normal file
120
skills/paseo-epic/references/roles.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Roles and phase types
|
||||
|
||||
Shared vocabulary for `paseo-epic`. The plan file format and the implement-phase dispatch logic both depend on these definitions. Agents launched by the epic skill read this file to know their role.
|
||||
|
||||
## Phase types — vocabulary used in the plan file
|
||||
|
||||
Each phase line has exactly one type after the `·`. The type tells the orchestrator which role to dispatch and which provider category to use.
|
||||
|
||||
| Type | What the phase does | Role dispatched | Provider category |
|
||||
| ----------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------- |
|
||||
| `refactor` | Reshape existing code so the upcoming change slots in. Behavior-preserving. | `refactorer` | `impl` (or `ui` if the reshape is purely styling) |
|
||||
| `implement` | Build the slice. Default = vertical slice. May be interface-first when the work calls for it. | `impl` (or `ui-impl` for styling-only passes) | `impl` (or `ui`) |
|
||||
| `verify` | Read-only gate. Variant after the `·` selects the auditor: `spec` / `unslop` / `qa` / `review`. | `auditor` | `audit` |
|
||||
| `gate` | Human-in-the-loop. Orchestrator yields. | none | none |
|
||||
| `deliver` | Ship: commit / PR / cherry-pick. | handled inline | `impl` (for rebase / fix-build agents) |
|
||||
|
||||
## Agent roles
|
||||
|
||||
These are the agent identities the epic skill launches. They're not visible in the plan file (the plan only uses phase types) — they're the dispatcher's vocabulary.
|
||||
|
||||
### researcher (read-only)
|
||||
|
||||
Used during initial research for genuinely large tasks (≥3 packages or architectural change). Skipped for small tasks where the orchestrator can read the code directly.
|
||||
|
||||
- Provider: `research`
|
||||
- Edits: no
|
||||
- Loads: nothing by default; specific repo docs by path if relevant
|
||||
- Done: returns a structured summary in chat
|
||||
- Mandate: "Report files, types, patterns, gotchas. Do not suggest solutions. Do not edit."
|
||||
|
||||
### planner (read-only, persistent)
|
||||
|
||||
Drafts phase lists. Always followed by adversarial review before the plan is accepted.
|
||||
|
||||
- Provider: `planning`
|
||||
- Edits: no
|
||||
- Persistent: yes — orchestrator iterates with the planner over multiple turns. Do not archive after first response.
|
||||
- Loads: this `roles.md`
|
||||
- Done: a phase list the orchestrator and user agree on
|
||||
- Mandate: "Draft phases using the role vocabulary. Refactor-first. Be terse. One line per phase."
|
||||
|
||||
### plan-reviewer (read-only, adversarial)
|
||||
|
||||
Challenges a planner's draft.
|
||||
|
||||
- Provider: `planning`
|
||||
- Edits: no
|
||||
- Loads: this `roles.md`
|
||||
- Mandate: "Challenge: bolt-ons, missing edge cases, over-engineering, wrong phase ordering, hidden dependencies. Push for alternatives. Force tradeoffs."
|
||||
|
||||
### refactorer (writes code)
|
||||
|
||||
Dispatched for `refactor` phases.
|
||||
|
||||
- Provider: `impl` (or `ui` if the reshape is purely styling)
|
||||
- Edits: yes
|
||||
- Loads: the **unslop** skill (focus on bolt-on, structure, module, and tests categories)
|
||||
- Behavior: behavior-preserving. Existing tests stay green. Add a parity test if missing.
|
||||
- Done: typecheck pass + relevant tests green; **does not commit; does not update the plan file**.
|
||||
|
||||
### impl (writes code)
|
||||
|
||||
Dispatched for `implement` phases. Default unit of work is a vertical slice.
|
||||
|
||||
- Provider: `impl`
|
||||
- Edits: yes
|
||||
- Loads:
|
||||
- The **unslop** skill (will be audited)
|
||||
- The **e2e-playwright** skill if frontend/E2E
|
||||
- Any repo docs the plan or user names — given by path, never inlined
|
||||
- Behavior: TDD. Failing test first, then make it pass. All relevant tests green when done.
|
||||
- Push-back: if the existing shape doesn't accommodate the change, push back to the orchestrator instead of bolting on. A refactor phase should have come first.
|
||||
- Done: typecheck pass + every test the agent touched is green; **does not commit; does not update the plan file**.
|
||||
|
||||
### ui-impl (writes code, styling only)
|
||||
|
||||
Dispatched for `implement` phases that are explicitly styling/layout passes. Per user preference, "UI" means styling and layout only — not React logic.
|
||||
|
||||
- Provider: `ui`
|
||||
- Edits: yes (styles, layout, copy)
|
||||
- Loads:
|
||||
- The **unslop** skill
|
||||
- The **e2e-playwright** skill (visual test discipline)
|
||||
- The repo's design system doc by path if one exists
|
||||
- Behavior: study existing components in adjacent screens, follow conventions exactly, no new patterns, design minimal and consistent.
|
||||
- Done: typecheck pass; **does not commit; does not update the plan file**.
|
||||
|
||||
### auditor (read-only)
|
||||
|
||||
Dispatched for `verify` phases. The variant selects the audit type.
|
||||
|
||||
- Provider: `audit`
|
||||
- Edits: no
|
||||
|
||||
| Variant | Loads | Output |
|
||||
| -------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| `spec` | nothing | YES/NO per acceptance criterion in Phase N, with evidence (file/line/test) |
|
||||
| `unslop` | the **unslop** skill in `--report-only` mode | Findings by category and severity from the diff |
|
||||
| `qa` | the **e2e-playwright** skill | Walkthrough of user flows with screenshots |
|
||||
| `review` | nothing | Adversarial concerns: edge cases, failure modes, alternatives the impl agent didn't consider |
|
||||
|
||||
## Hard rules across roles
|
||||
|
||||
- **Pass-through, never paraphrase.** When an agent should use a skill or doc, give the path. Never inline content.
|
||||
- **One agent per phase.** If a phase needs two impl agents, the planner split it wrong — fix the plan instead of launching a second.
|
||||
- **Agents do not commit.** Delivery happens in the deliver phase.
|
||||
- **Agents do not update the plan file.** The orchestrator is the only writer.
|
||||
- **All agents in worktree mode get cwd set to the worktree path.** No exceptions.
|
||||
- **Don't poll.** Wait properly.
|
||||
|
||||
## Plan file phase line — canonical format
|
||||
|
||||
```
|
||||
- [<status>] **Phase <N>** · <type> · <short name>
|
||||
Acceptance: <one line>
|
||||
```
|
||||
|
||||
Status markers: `[ ]` not started, `[~]` in progress, `[x]` done, `[!]` blocked.
|
||||
|
||||
Notes are freeform timestamped lines under the Notes section, not under the phase.
|
||||
@@ -1,144 +1,59 @@
|
||||
---
|
||||
name: paseo-handoff
|
||||
description: Hand off the current task to another agent with full context. Use when the user says "handoff", "hand off", "hand this to", or wants to pass work to another agent (Codex or Claude).
|
||||
description: Hand off the current task to another agent with full context. Use when the user says "handoff", "hand off", "hand this to", or wants to pass work to another agent.
|
||||
user-invocable: true
|
||||
---
|
||||
|
||||
# Handoff Skill
|
||||
|
||||
You are handing off the current task to another agent. Your job is to write a comprehensive handoff prompt and launch the agent via Paseo CLI.
|
||||
Transfer the current task — context, decisions, failed attempts, constraints — to a fresh agent. The receiving agent starts with **zero context**, so the handoff prompt must be a self-contained briefing.
|
||||
|
||||
**User's arguments:** $ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Load the **Paseo skill** first — it contains the CLI reference for all agent commands.
|
||||
Read the **paseo** skill — provider for the receiving agent comes from orchestration preferences unless the user names one.
|
||||
|
||||
## What Is a Handoff
|
||||
## Parsing arguments
|
||||
|
||||
A handoff transfers your current task — including all context, decisions, failed attempts, and constraints — to a fresh agent that will carry it to completion. The handoff prompt is the most important part: the receiving agent starts with **zero context**, so everything it needs must be in the prompt.
|
||||
1. **Provider** — explicit user request first; otherwise resolve from `impl` preference (or `ui` if the task is styling-only).
|
||||
2. **Worktree** — "in a worktree" / "worktree" → create a worktree via Paseo with a short branch name derived from the task, based on the current branch.
|
||||
3. **Task description** — anything else the user said.
|
||||
|
||||
## Parsing Arguments
|
||||
## The handoff prompt
|
||||
|
||||
Parse `$ARGUMENTS` to determine:
|
||||
|
||||
1. **Provider and model** — who to hand off to
|
||||
2. **Worktree** — whether to run in an isolated git worktree
|
||||
3. **Task description** — any additional context the user provided
|
||||
|
||||
### Provider Resolution
|
||||
|
||||
| User says | --provider | Mode |
|
||||
| ----------- | --------------- | ------------- |
|
||||
| _(nothing)_ | `codex/gpt-5.4` | `full-access` |
|
||||
| `codex` | `codex/gpt-5.4` | `full-access` |
|
||||
| `claude` | `claude/opus` | `bypass` |
|
||||
| `opus` | `claude/opus` | `bypass` |
|
||||
| `sonnet` | `claude/sonnet` | `bypass` |
|
||||
|
||||
Default is **Codex** with `gpt-5.4`.
|
||||
|
||||
### Worktree Resolution
|
||||
|
||||
If the user says "in a worktree" or "worktree", add `--worktree` with a short descriptive branch name derived from the task. Worktrees require a `--base` branch — use the current branch in the working directory (run `git branch --show-current` to get it).
|
||||
|
||||
## Writing the Handoff Prompt
|
||||
|
||||
This is the critical step. The receiving agent has **zero context** about your conversation. The handoff prompt must be a self-contained briefing document.
|
||||
|
||||
### Must Include
|
||||
|
||||
1. **Task description** — What needs to be done, in clear imperative language
|
||||
2. **Task qualifiers** — Preserve the semantics of what the user asked for:
|
||||
- If the user asked to **investigate without editing**, say "DO NOT edit any files"
|
||||
- If the user asked to **fix**, say "implement the fix"
|
||||
- If the user asked to **refactor**, say "refactor" not "rewrite"
|
||||
- Carry forward the exact intent
|
||||
3. **Relevant files** — List every file path that matters, with brief descriptions of what each contains
|
||||
4. **Current state** — What has been done so far, what's working, what's not
|
||||
5. **What was tried** — Any approaches attempted and why they failed or were abandoned
|
||||
6. **Decisions made** — Anything you and the user agreed on (design choices, constraints, trade-offs)
|
||||
7. **Acceptance criteria** — How the agent knows it's done
|
||||
8. **Constraints** — Anything the agent must NOT do
|
||||
|
||||
### Template
|
||||
The receiving agent has zero context. Include:
|
||||
|
||||
```
|
||||
## Task
|
||||
|
||||
[Clear, imperative description of what to do]
|
||||
[Imperative description.]
|
||||
|
||||
## Context
|
||||
[Why this task exists, background needed.]
|
||||
|
||||
[Why this task exists, background the agent needs]
|
||||
## Relevant files
|
||||
- `path/to/file.ts` — [what it is and why it matters]
|
||||
|
||||
## Relevant Files
|
||||
## Current state
|
||||
[What's done, what works, what doesn't.]
|
||||
|
||||
- `path/to/file.ts` — [what it does and why it matters]
|
||||
- `path/to/other.ts` — [what it does and why it matters]
|
||||
|
||||
## Current State
|
||||
|
||||
[What's been done, what works, what doesn't]
|
||||
|
||||
## What Was Tried
|
||||
|
||||
- [Approach 1] — [why it failed/was abandoned]
|
||||
- [Approach 2] — [partial success, but...]
|
||||
## What was tried
|
||||
- [Approach] — [why it failed or was abandoned]
|
||||
|
||||
## Decisions
|
||||
- [Decision — rationale]
|
||||
|
||||
- [Decision 1 — rationale]
|
||||
- [Decision 2 — rationale]
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] [Criterion 1]
|
||||
- [ ] [Criterion 2]
|
||||
## Acceptance criteria
|
||||
- [ ] [Criterion]
|
||||
|
||||
## Constraints
|
||||
|
||||
- [Do not do X]
|
||||
- [Must preserve Y]
|
||||
- [Must-not / must-preserve]
|
||||
```
|
||||
|
||||
## Launching the Agent
|
||||
**Preserve task semantics.** Investigate-only → "DO NOT edit files." Fix → "implement the fix." Refactor → "refactor, not rewrite." Carry the user's exact intent.
|
||||
|
||||
### Default (Codex, no worktree)
|
||||
## Launch
|
||||
|
||||
```bash
|
||||
paseo run -d --mode full-access --provider codex/gpt-5.4 --name "[Handoff] Task description" "$prompt"
|
||||
```
|
||||
Create the agent via Paseo with a `[Handoff] <task>` title, the briefing as initial prompt, and cwd set to the worktree path if `--worktree`.
|
||||
|
||||
### Claude (Opus, no worktree)
|
||||
|
||||
```bash
|
||||
paseo run -d --mode bypassPermissions --provider claude/opus --name "[Handoff] Task description" "$prompt"
|
||||
```
|
||||
|
||||
### Codex in a worktree
|
||||
|
||||
```bash
|
||||
base=$(git branch --show-current)
|
||||
paseo run -d --mode full-access --provider codex/gpt-5.4 --worktree task-branch-name --base "$base" --name "[Handoff] Task description" "$prompt"
|
||||
```
|
||||
|
||||
### Claude in a worktree
|
||||
|
||||
```bash
|
||||
base=$(git branch --show-current)
|
||||
paseo run -d --mode bypass --provider claude/opus --worktree task-branch-name --base "$base" --name "[Handoff] Task description" "$prompt"
|
||||
```
|
||||
|
||||
## After Launch
|
||||
|
||||
1. Print the agent ID and the command to follow along:
|
||||
```
|
||||
Handed off to [provider] ([model]). Agent ID: <id>
|
||||
Follow along: paseo logs <id> -f
|
||||
Wait for completion: paseo wait <id>
|
||||
```
|
||||
2. Do **not** wait for the agent by default — the user can choose to wait or move on.
|
||||
3. If the user wants to wait, run `paseo wait <id>` and then `paseo logs <id>` when done.
|
||||
Don't wait by default — the user decides whether to follow along or move on. Tell them the agent ID and how to follow along (the paseo skill explains).
|
||||
|
||||
@@ -6,117 +6,40 @@ user-invocable: true
|
||||
|
||||
# Paseo Loop Skill
|
||||
|
||||
You are setting up a loop — an iterative worker/verifier cycle managed by the Paseo daemon.
|
||||
A loop is a worker/verifier cycle: launch a worker → check verification → repeat until done or limits hit. Use for "keep trying", "babysit", or "watch this until X."
|
||||
|
||||
**User's arguments:** $ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Load the **Paseo skill** first. It contains the CLI reference for `paseo loop` and related commands.
|
||||
Read the **paseo** skill for orchestration preferences — worker and verifier providers come from preferences unless the user names them.
|
||||
|
||||
## Core Model
|
||||
Loops are a CLI primitive: `paseo loop run`. Manage with `paseo loop ls`, `paseo loop inspect <id>`, `paseo loop logs <id>`, `paseo loop stop <id>`.
|
||||
|
||||
A loop repeats: launch a worker → verify → repeat until done or limits hit.
|
||||
## Your job
|
||||
|
||||
1. **Worker prompt**: what the worker does each iteration
|
||||
2. **Verification**: verifier prompt and/or shell checks that judge success
|
||||
3. **Sleep**: optional pause between iterations
|
||||
4. **Stop conditions**: max iterations and/or max total runtime
|
||||
5. **Model selection**: different providers/models for worker vs verifier
|
||||
6. **Archive**: optionally preserve agent history after each iteration
|
||||
1. Understand the user's intent from `$ARGUMENTS` and the conversation.
|
||||
2. **Worker prompt** — self-contained, concrete about what to do this iteration, explicit about what counts as progress.
|
||||
3. **Verification** — pick the right shape:
|
||||
- Shell check (`--verify-check`) for objective criteria a command can answer (`gh pr checks --fail-fast`, `npm test`).
|
||||
- Verifier prompt (`--verify`) for judgment ("Return done=true only if all tests pass and the changed files are coherent. Cite the command and the outcome.").
|
||||
- Both, when shell rules out the obvious failures and the verifier judges the rest.
|
||||
4. **Providers** — `--provider` for the worker, `--verify-provider` for the verifier. From preferences unless the user named them. For implementation loops, pair worker and verifier on different providers — each catches the other's blind spots.
|
||||
5. **Sleep** — `--sleep` only when polling something external. Otherwise let it run as fast as the loop completes.
|
||||
6. **Stops** — set a sensible `--max-iterations` and/or `--max-time`. Open-ended loops are how runaways happen.
|
||||
7. **Archive** — `--archive` keeps agents after each iteration for inspection.
|
||||
8. Launch with `paseo loop run`.
|
||||
|
||||
## Verification
|
||||
## Common shapes
|
||||
|
||||
Every loop needs at least one form of verification:
|
||||
**Babysit a PR** — worker checks PR state and fixes issues; shell check is `gh pr checks <n> --fail-fast`; sleep 2m; max-time 1h.
|
||||
|
||||
- `--verify "<prompt>"` — a verifier agent judges the worker's output
|
||||
- `--verify-check "<command>"` — a shell command that must exit 0 (repeatable)
|
||||
- Both can be combined: shell checks run first, then the verifier prompt
|
||||
**Drive tests to green** — worker investigates failures and fixes code; shell check is the test command; verifier confirms all tests pass; max-iterations 10.
|
||||
|
||||
## Model Selection
|
||||
**Cross-provider implementation** — worker on `impl` provider, verifier on a different provider; verifier checks changed files, runs typecheck and tests; max-iterations and max-time both bounded; archive on so iterations can be inspected.
|
||||
|
||||
Choose the right provider/model for worker and verifier independently:
|
||||
## Prompt rules
|
||||
|
||||
- `--provider <provider/model>` — sets the worker (e.g. `codex/gpt-5.4`)
|
||||
- `--verify-provider <provider/model>` — sets the verifier (e.g. `claude/opus`)
|
||||
**Worker** — self-contained, concrete (commands, files, branches, tests, PRs, systems), explicit about what counts as progress this iteration.
|
||||
|
||||
Default: both use Claude/sonnet. For implementation loops, use Codex for the worker and Claude for the verifier — each catches the other's blind spots.
|
||||
|
||||
## Archive
|
||||
|
||||
`--archive` preserves worker and verifier agents after each iteration instead of destroying them. Use this when you need to inspect conversation history for debugging.
|
||||
|
||||
## Defaults by User Intent
|
||||
|
||||
### Babysit / watch / check every X
|
||||
|
||||
```bash
|
||||
paseo loop run "Check PR #42. Review CI, comments, and branch status. Fix issues as they arise." \
|
||||
--verify-check "gh pr checks 42 --fail-fast" \
|
||||
--sleep 2m \
|
||||
--max-time 1h \
|
||||
--name babysit-pr-42
|
||||
```
|
||||
|
||||
### Keep trying until tests pass
|
||||
|
||||
```bash
|
||||
paseo loop run "Run the test suite, investigate failures, and fix the code." \
|
||||
--provider codex/gpt-5.4 \
|
||||
--verify "Run the test suite. Return done=true only if all tests pass. Cite the exact command and outcome." \
|
||||
--verify-check "npm test" \
|
||||
--max-iterations 10 \
|
||||
--name fix-tests
|
||||
```
|
||||
|
||||
### Implementation loop with cross-provider review
|
||||
|
||||
```bash
|
||||
paseo loop run "Implement issue #456. Make incremental progress each iteration." \
|
||||
--provider codex/gpt-5.4 \
|
||||
--verify "Verify issue #456 is complete. Check changed files, run typecheck and tests." \
|
||||
--verify-provider claude/sonnet \
|
||||
--max-iterations 8 \
|
||||
--max-time 2h \
|
||||
--archive \
|
||||
--name issue-456
|
||||
```
|
||||
|
||||
## Managing Loops
|
||||
|
||||
```bash
|
||||
paseo loop ls # List all loops
|
||||
paseo loop inspect <id> # Show details and iteration history
|
||||
paseo loop logs <id> # Stream logs
|
||||
paseo loop stop <id> # Stop a running loop
|
||||
```
|
||||
|
||||
## Your Job
|
||||
|
||||
1. Understand the user's intent from the conversation and `$ARGUMENTS`
|
||||
2. Decide the worker prompt — self-contained, concrete about what to do
|
||||
3. Decide verification — shell checks for objective criteria, verifier prompt for judgment
|
||||
4. Choose providers/models for worker and verifier
|
||||
5. Choose sleep only when the task is polling or waiting on an external system
|
||||
6. Add sensible stop conditions
|
||||
7. Run `paseo loop run` with the final arguments
|
||||
|
||||
## Prompt Writing Rules
|
||||
|
||||
### Worker prompt
|
||||
|
||||
The worker prompt must be:
|
||||
|
||||
- self-contained
|
||||
- concrete about commands, files, branches, tests, PRs, or systems to inspect
|
||||
- explicit about what counts as progress this iteration
|
||||
|
||||
### Verifier prompt
|
||||
|
||||
The verifier prompt should:
|
||||
|
||||
- check facts, not offer fixes
|
||||
- cite commands, outputs, or file evidence
|
||||
- be specific about what "done" means
|
||||
**Verifier** — checks facts, doesn't suggest fixes, cites commands/outputs/file evidence, specific about what "done" means.
|
||||
|
||||
@@ -1,879 +1,12 @@
|
||||
---
|
||||
name: paseo-orchestrate
|
||||
description: End-to-end implementation orchestrator. Use when the user says "orchestrate", "implement this end to end", "build this", or wants a full feature/fix implemented through a team of agents with planning, implementation, review, and QA phases.
|
||||
description: Deprecated. Renamed to paseo-epic. Loading this skill redirects to paseo-epic and tells the user.
|
||||
user-invocable: true
|
||||
argument-hint: "[--auto] [--worktree] <task description>"
|
||||
allowed-tools: Bash Read Grep Glob Skill
|
||||
---
|
||||
|
||||
# Orchestrate
|
||||
# Deprecated — use `paseo-epic`
|
||||
|
||||
You are an end-to-end implementation orchestrator. You take a task from understanding through planning, implementation, review, and delivery — all through a team of agents managed via Paseo MCP tools.
|
||||
This skill has been renamed to `paseo-epic`.
|
||||
|
||||
**User's request:** $ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Load these skills before proceeding:
|
||||
|
||||
1. **e2e-playwright** — if the task involves frontend/UI work
|
||||
|
||||
## Guard
|
||||
|
||||
Before anything else, verify you have access to Paseo MCP tools by calling the Paseo **list agents** tool. If the tool is not available or errors, stop immediately. Tell the user: "The orchestrate skill requires Paseo MCP tools. These should be available in any Paseo-managed agent."
|
||||
|
||||
## Parse Arguments
|
||||
|
||||
Check `$ARGUMENTS` for flags:
|
||||
|
||||
- `--auto` — fully autonomous mode. No grill, no approval gates. Fire and forget.
|
||||
- `--worktree` — work in an isolated git worktree instead of the current directory.
|
||||
- Everything else is the task description.
|
||||
|
||||
If no `--auto` flag, you're in **default mode** — conversational with grill and approval gates.
|
||||
|
||||
## Load Preferences
|
||||
|
||||
Read user preferences:
|
||||
|
||||
```bash
|
||||
cat ~/.paseo/orchestrate.json 2>/dev/null || echo '{}'
|
||||
```
|
||||
|
||||
Merge with defaults for any missing fields. The file maps role categories to `<agent-type>/<model>` strings:
|
||||
|
||||
- The part before `/` is the `agentType` (e.g., `codex`, `claude`, `opencode`)
|
||||
- The part after `/` is the `model` (e.g., `gpt-5.4`, `opus`)
|
||||
|
||||
| Category | Roles covered | Default |
|
||||
| ---------- | --------------------------------- | --------------- |
|
||||
| `impl` | impl, tester, refactorer | `codex/gpt-5.4` |
|
||||
| `ui` | impl agents doing UI/styling work | `claude/opus` |
|
||||
| `research` | researcher | `codex/gpt-5.4` |
|
||||
| `planning` | planner, plan-reviewer | `codex/gpt-5.4` |
|
||||
| `audit` | auditor, qa | `codex/gpt-5.4` |
|
||||
|
||||
The file also has a `preferences` array of freeform natural language strings. Read these at startup and weave them into your behavior contextually. When the user says "store my preference: X", update the file.
|
||||
|
||||
## Hard Rules
|
||||
|
||||
- **You are the orchestrator.** You do NOT edit code, write code, or implement anything yourself.
|
||||
- **You may only:** run git commands, run tests/typecheck, and use Paseo MCP tools.
|
||||
- **Always TDD.** Every feature phase starts with a failing test. Not optional, not configurable.
|
||||
- **Always archive.** Archive every agent as soon as its role is done. No exceptions.
|
||||
- **Work in the current directory by default.** If `--worktree` is set, create an isolated worktree and run ALL agents there. Never mix — every agent, terminal, and command targets the worktree path, never the main checkout.
|
||||
- **Do NOT commit or push unless the user says to.** Ask at the end.
|
||||
- **Never stop to ask the user during implementation.** Once past the approval gate, you are fully autonomous. Hit a blocker? Solve it — spin up agents, investigate, fix.
|
||||
- **Never trust implementation agents at face value.** Always verify with separate auditor agents.
|
||||
- **Never classify failures as "pre-existing."** If a test is failing, fix it or delete it.
|
||||
- **The plan file on disk is the source of truth.** Re-read `~/.paseo/plans/<task-slug>.md` before every verification and QA phase. It survives compaction.
|
||||
- **Never micromanage agents.** Describe the **problem** (what's broken, how it fails, the error output), not the **solution** (which line to change, what to change it to). Agents are smart — give them context and let them figure out the fix. If you find yourself writing specific line numbers or code snippets in an agent prompt, you're doing it wrong. Say "this test fails with this error" not "change line 47 to use X instead of Y."
|
||||
- **Any task that touches tests MUST run those tests.** This is non-negotiable. If an agent modifies, fixes, or writes a test file, the prompt MUST explicitly say "run the test(s) and confirm they pass." Typecheck alone is never sufficient for test changes. An agent that changes a test without running it has not completed its task.
|
||||
|
||||
## Launching Agents
|
||||
|
||||
All agents are launched via the Paseo **create agent** tool. The standard pattern:
|
||||
|
||||
- `background: true` — don't block waiting for the agent.
|
||||
- `notifyOnFinish: true` — **always set this.** Paseo will notify you when the agent finishes, errors, or needs permission. You do NOT need to poll, loop, or check on agents anxiously. Launch the agent, move on to other work, and wait for the notification. Polling wastes your context and slows everything down.
|
||||
- Set `title` to the role-scope name (e.g., `"impl-checkout-phase1"`).
|
||||
- Set `agentType` based on the provider category from preferences (e.g., `"codex"` or `"claude"`).
|
||||
- Set `model` based on the provider category from preferences (e.g., `"gpt-5.4"` or `"opus"`). MUST BE REFERENCED.
|
||||
- **If in worktree mode:** set `cwd` to the worktree path for EVERY agent. No exceptions. Agents that run in the main checkout will corrupt the orchestration.
|
||||
|
||||
**Do NOT poll agents.** After launching an agent with `notifyOnFinish: true`, do not call **get agent status** or **wait for agent** in a loop. Paseo delivers a notification to your conversation when the agent completes — just wait for it. The only reasons to check on an agent manually are: (1) the heartbeat fires and you're doing a periodic status review, or (2) you need to read the agent's activity to extract findings after it finishes.
|
||||
|
||||
To send follow-up instructions: Paseo **send agent prompt**.
|
||||
To archive: Paseo **archive agent**.
|
||||
|
||||
### How to Write Agent Prompts
|
||||
|
||||
**Describe the problem, not the solution.** Your prompt should tell the agent:
|
||||
|
||||
- What's wrong or what needs to be built (the goal)
|
||||
- How it currently fails (error output, test output, user-visible behavior)
|
||||
- The acceptance criteria (what "done" looks like)
|
||||
|
||||
**Do NOT tell the agent:**
|
||||
|
||||
- Which specific lines to change
|
||||
- What code to write
|
||||
- Which functions to call or which patterns to use
|
||||
|
||||
The agent reads the plan and the code. It will figure out the implementation. If you're writing specific line numbers or code snippets in the prompt, you're micromanaging and it will backfire — the agent takes you literally and skips its own judgment.
|
||||
|
||||
Bad: "In `new-workspace.spec.ts` at line 164, change the tab assertion from `getByText('New Agent')` to `getByTestId(/workspace-tab-agent_/)`"
|
||||
|
||||
Good: "The new-workspace E2E test is failing. The test creates a workspace via empty submit, but then the tab assertion fails because it looks for text 'New Agent' which doesn't match the actual tab label. Here's the error output: [paste error]. Fix the test and run it to confirm it passes."
|
||||
|
||||
---
|
||||
|
||||
## Worktree Mode
|
||||
|
||||
If `--worktree` is set, create an isolated git worktree with the Paseo skill.
|
||||
|
||||
**You (the orchestrator) stay in the main checkout.** You do not `cd` into the worktree. You only ensure that all agents, terminals, and commands target the worktree path via `cwd`.
|
||||
|
||||
If `--worktree` is NOT set, skip this — work in the current directory as normal.
|
||||
|
||||
## The Flow
|
||||
|
||||
```
|
||||
[Worktree Setup] -> Guard -> Triage -> [Grill] -> Research -> Plan -> [Approve] -> Implement -> Verify -> Cleanup -> Final QA -> Deliver
|
||||
^^^^^^ ^^^^^^^
|
||||
default mode only default mode only
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Triage
|
||||
|
||||
Triage is fast and cheap. You do it yourself — no agents. The goal is to assess complexity order, which determines how many agents to deploy at each phase.
|
||||
|
||||
1. Read the task description
|
||||
2. Grep the codebase for relevant files, types, and functions
|
||||
3. Identify how many packages/modules are touched
|
||||
4. Identify whether it's a new feature, refactor, bug fix, or architectural change
|
||||
5. Assign a complexity order
|
||||
|
||||
State the order and briefly why: "Order 3 — touches server session management and the app's git status display across two packages."
|
||||
|
||||
### Complexity Orders
|
||||
|
||||
**Order 1 — Single file, single concern.** A contained change: fix a bug in one function, add a field to one type, update one component.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ----------------------------- |
|
||||
| Research | 1 researcher |
|
||||
| Planning | 0 — orchestrator plans inline |
|
||||
| Implement | 1 impl |
|
||||
| Verify | 1-2 auditors |
|
||||
| Cleanup | 0-1 refactorer |
|
||||
|
||||
**Order 2 — Single module, few files.** A feature or fix within one package that touches 3-8 files.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ---------------- |
|
||||
| Research | 2 researchers |
|
||||
| Planning | 1 planner |
|
||||
| Implement | 1 impl per phase |
|
||||
| Verify | 2-3 auditors |
|
||||
| Cleanup | 1 refactorer |
|
||||
|
||||
**Order 3 — Cross-module, multiple packages.** A feature that spans packages.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ---------------------------- |
|
||||
| Research | 3-4 researchers |
|
||||
| Planning | 2 planners + 1 plan-reviewer |
|
||||
| Implement | 1-2 impl agents per phase |
|
||||
| Verify | 3-4 auditors |
|
||||
| Cleanup | 1-2 refactorers |
|
||||
|
||||
**Order 4 — Architectural, system-wide.** A new subsystem, major refactor, or system-wide change.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ------------------------------ |
|
||||
| Research | 5+ researchers |
|
||||
| Planning | 2+ planners + 2 plan-reviewers |
|
||||
| Implement | 2+ impl agents per phase |
|
||||
| Verify | Full auditor suite per phase |
|
||||
| Cleanup | 2+ refactorers |
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Grill (default mode only)
|
||||
|
||||
Skipped in `--auto` mode.
|
||||
|
||||
### Protocol: Research First, Grill Second
|
||||
|
||||
Before asking the user anything:
|
||||
|
||||
1. Read the task description
|
||||
2. Grep relevant files, types, functions
|
||||
3. Read key files to understand the current state
|
||||
4. Form your own understanding of the problem space
|
||||
|
||||
Then ask the user ONLY about things the code cannot answer: intent, scope boundaries, UX preferences, tradeoffs, priorities, acceptance criteria. Never ask a question the codebase could answer.
|
||||
|
||||
### Questioning Approach
|
||||
|
||||
Treat the task as a decision tree. Each design choice branches into sub-decisions, constraints, and consequences.
|
||||
|
||||
- Ask one question at a time
|
||||
- Wait for the answer before moving on
|
||||
- Drill depth-first into each branch until it's resolved or explicitly deferred
|
||||
- For each question, state your recommended answer based on what you've learned from the code — the user can confirm or override
|
||||
- Cycle through question types: feasibility, dependency, edge case, alternative, scope, ordering, failure mode
|
||||
|
||||
Every 3-4 questions, summarize: resolved decisions, open branches, current focus.
|
||||
|
||||
Stop grilling when all branches are resolved, the user signals they're done, or no meaningful questions remain. Conclude with a final summary of all resolved decisions.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Research
|
||||
|
||||
Deploy researchers to gather information before planning. Each researcher gets a narrow mandate — one area of the codebase, one external doc source, one reference project.
|
||||
|
||||
### Launching Researchers
|
||||
|
||||
```
|
||||
title: "researcher-<scope>"
|
||||
agentType: <resolved from providers.research>
|
||||
model: <resolved from providers.research>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a researcher.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for the objective.
|
||||
|
||||
<specific research mandate>
|
||||
|
||||
Include in your findings: relevant files, types, interfaces, patterns, gotchas, and anything surprising. Do NOT suggest solutions or edit files."
|
||||
```
|
||||
|
||||
Wait for all researchers to complete (you'll be notified). Use Paseo **get agent activity** to read their findings. Synthesize into a research summary that feeds the planning phase.
|
||||
|
||||
If findings raise new questions (default mode), go back and ask the user.
|
||||
|
||||
Archive all researchers when done.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Plan
|
||||
|
||||
Deploy planners to create an implementation plan informed by research findings.
|
||||
|
||||
### Refactor-First Thinking
|
||||
|
||||
Every planner prompt must emphasize this: the default agent instinct is to bolt new code on top of existing code. Resist this.
|
||||
|
||||
The right approach:
|
||||
|
||||
1. Study the existing code — understand why it's shaped the way it is
|
||||
2. Design the target shape — what would the code look like if this feature had always existed?
|
||||
3. Identify the refactoring gap — what needs to change so the new feature slots in cleanly?
|
||||
4. Plan refactor phases before feature phases
|
||||
|
||||
If the plan has a phase called "wire up" or "connect" or "integrate," a refactor phase could probably eliminate the need for it.
|
||||
|
||||
### Launching Planners
|
||||
|
||||
```
|
||||
title: "planner-<scope>"
|
||||
agentType: <resolved from providers.planning>
|
||||
model: <resolved from providers.planning>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a planner.
|
||||
|
||||
Read the research findings provided below and the objective.
|
||||
|
||||
<paste synthesized research findings and objective>
|
||||
|
||||
Draft a phased implementation plan. Think refactor-first: before planning the feature, identify what existing code needs to be reshaped so the feature slots in naturally.
|
||||
|
||||
For each phase, specify:
|
||||
- What changes and why
|
||||
- Files involved
|
||||
- Types and interfaces affected
|
||||
- Tests to write (failing test first — TDD)
|
||||
- Acceptance criteria for the phase
|
||||
|
||||
Write the plan to ~/.paseo/plans/<task-slug>.md"
|
||||
```
|
||||
|
||||
### Launching Plan-Reviewers
|
||||
|
||||
```
|
||||
title: "plan-reviewer-<scope>"
|
||||
agentType: <resolved from providers.planning>
|
||||
model: <resolved from providers.planning>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a plan-reviewer.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md.
|
||||
|
||||
Challenge the plan:
|
||||
- Is it bolting new code on top, or reshaping existing code first?
|
||||
- Are there coordination/glue/bridge layers that a better refactor would eliminate?
|
||||
- What edge cases are missing? What will break?
|
||||
- What's over-engineered? What's under-specified?
|
||||
- Is the phase ordering correct? Are there hidden dependencies?"
|
||||
```
|
||||
|
||||
For Order 3+, deploy multiple planners (one per area) + plan-reviewers. Iterate until the plan-reviewer's only feedback is minor.
|
||||
|
||||
### Plan Structure
|
||||
|
||||
The final plan must follow:
|
||||
|
||||
```
|
||||
# <Task Title>
|
||||
|
||||
## Objective
|
||||
<one-paragraph summary>
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] <criterion 1>
|
||||
- [ ] <criterion 2>
|
||||
|
||||
## Plan
|
||||
### Phase 1: <name>
|
||||
<description, files, types, tests, acceptance criteria>
|
||||
|
||||
### Phase 2: <name>
|
||||
...
|
||||
```
|
||||
|
||||
Persist to `~/.paseo/plans/<task-slug>.md`. Archive all planners and plan-reviewers.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Approve (default mode only)
|
||||
|
||||
Skipped in `--auto` mode.
|
||||
|
||||
Present the plan to the user. Wait for explicit confirmation before proceeding.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Set Up
|
||||
|
||||
Persist the plan to disk and set up the heartbeat:
|
||||
|
||||
Use the Paseo **create schedule** tool with:
|
||||
|
||||
- `name`: `"heartbeat-<task-slug>"`
|
||||
- `target`: `"self"`
|
||||
- `every`: `"5m"`
|
||||
- `expiresIn`: `"4h"`
|
||||
- `prompt`: (see heartbeat prompt below)
|
||||
|
||||
### Heartbeat prompt
|
||||
|
||||
```
|
||||
HEARTBEAT — periodic self-check.
|
||||
|
||||
Do the following steps in order:
|
||||
|
||||
1. Re-read the plan:
|
||||
cat ~/.paseo/plans/<task-slug>.md
|
||||
|
||||
2. WORKTREE CHECK (if in worktree mode):
|
||||
⚠️ REMINDER: You are orchestrating in worktree mode.
|
||||
Worktree path: <worktree-path>
|
||||
Branch: orchestrate/<task-slug>
|
||||
ALL agents MUST have cwd set to the worktree path.
|
||||
Do NOT launch any agents or terminals in the main checkout.
|
||||
Verify: ls <worktree-path>/.git (confirm worktree still exists)
|
||||
|
||||
3. List all your active agents using the Paseo **list agents** tool.
|
||||
|
||||
4. For each active agent, check its status using the Paseo **get agent status** tool.
|
||||
- If in worktree mode, confirm each agent's cwd points to the worktree path.
|
||||
|
||||
5. Compare progress against the plan:
|
||||
- Which phases are complete?
|
||||
- Which agents are still running?
|
||||
- Is anyone stuck or errored?
|
||||
|
||||
6. Course-correct:
|
||||
- If an agent errored, investigate and relaunch.
|
||||
- If an agent is stuck, send it a nudge or archive and replace it.
|
||||
- If a phase is done but the next hasn't started, start it.
|
||||
- If in worktree mode and any agent is NOT in the worktree, archive it and relaunch with the correct cwd.
|
||||
|
||||
7. If ALL acceptance criteria are met:
|
||||
- Proceed to delivery.
|
||||
- Do NOT delete this schedule yet — if the user requests a PR, the heartbeat transitions to CI monitoring mode. Only delete it once CI is fully green (or if the user declines a PR).
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Implement
|
||||
|
||||
Execute phases from the plan sequentially. For each phase:
|
||||
|
||||
1. Launch impl agent(s) with `background: true, notifyOnFinish: true`
|
||||
2. Wait for notification
|
||||
3. Verify (Phase 8)
|
||||
4. Fix any issues
|
||||
5. Re-verify
|
||||
6. Proceed to next phase
|
||||
|
||||
UI passes use `providers.ui` from preferences. All other impl work uses `providers.impl`.
|
||||
|
||||
### TDD — Not Optional
|
||||
|
||||
Every impl agent works TDD:
|
||||
|
||||
1. Write a failing test that defines the expected behavior
|
||||
2. Make it pass
|
||||
3. Refactor if needed
|
||||
4. All tests green — not just new ones, the full relevant suite
|
||||
|
||||
If an impl agent finds a broken test, it fixes it. No "pre-existing failures." No exceptions.
|
||||
|
||||
### Impl Agent Prompt Template
|
||||
|
||||
```
|
||||
title: "impl-<scope>-<phase>"
|
||||
agentType: <resolved from providers.impl>
|
||||
model: <resolved from providers.impl>
|
||||
cwd: <worktree-path if worktree mode, omit otherwise>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are an implementation engineer. [Load the e2e-playwright skill if frontend/E2E work.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md to understand the objective and your specific phase.
|
||||
|
||||
Do not bolt new code on top of existing code. If the existing code isn't shaped to accommodate your work, reshape it first. The goal is code that looks like this feature always existed.
|
||||
|
||||
Work TDD: write a failing test first, then make it pass. All tests must be green when done — not just your new ones, the full relevant suite. If you find a broken test, fix it.
|
||||
|
||||
<describe the problem and acceptance criteria — NOT the solution>
|
||||
|
||||
When done: run typecheck AND run any tests you modified or that cover your changes. Both must pass. Do NOT commit."
|
||||
```
|
||||
|
||||
### UI Agent Prompt Template
|
||||
|
||||
```
|
||||
title: "impl-<scope>-ui"
|
||||
agentType: <resolved from providers.ui>
|
||||
model: <resolved from providers.ui>
|
||||
cwd: <worktree-path if worktree mode, omit otherwise>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a UI engineer. [Load the e2e-playwright skill.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
The functionality is implemented. Your job is the styling pass:
|
||||
- Study existing components and styles in nearby screens
|
||||
- Follow existing conventions exactly — no new patterns
|
||||
- Keep design minimal and consistent with the rest of the app
|
||||
- Think carefully about spacing, alignment, and visual hierarchy
|
||||
|
||||
<describe the specific UI work>
|
||||
|
||||
Run typecheck when done. Do NOT commit."
|
||||
```
|
||||
|
||||
### Handling Blockers
|
||||
|
||||
If an impl agent reports a blocker:
|
||||
|
||||
- Do NOT ask the user (in either mode)
|
||||
- Spin up a researcher to investigate
|
||||
- Spin up an impl agent to fix it
|
||||
- The scope of work is unlimited — touching other files, packages, or systems is fine
|
||||
|
||||
Archive every impl agent as soon as its phase is verified.
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Verify
|
||||
|
||||
After every implementation phase, deploy auditors to verify the work. Auditors are read-only — they check, they don't fix. Each auditor has a single specialization.
|
||||
|
||||
### Which Auditors to Deploy
|
||||
|
||||
| Phase type | Auditors |
|
||||
| ------------------ | ------------------------------------------------------ |
|
||||
| Refactor | `parity`, `regression`, `types` |
|
||||
| Feature (backend) | `overeng`, `tests`, `regression`, `types` |
|
||||
| Feature (frontend) | `overeng`, `tests`, `types`, `browser` (if applicable) |
|
||||
| UI pass | `overeng`, `browser` (if applicable) |
|
||||
| Test-only | `regression` |
|
||||
|
||||
Deploy all relevant auditors in parallel — they're read-only so they don't conflict.
|
||||
|
||||
### Auditor Prompts
|
||||
|
||||
All auditors are launched via the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`.
|
||||
|
||||
#### overeng (anti-over-engineering)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-overeng"
|
||||
initialPrompt: "You are an anti-over-engineering auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check the recent changes (use git diff) for:
|
||||
- Unnecessary abstractions, helpers, or utility functions
|
||||
- Defensive code for scenarios that can't happen
|
||||
- Event emitters, observers, or pub/sub where a direct call would do
|
||||
- Coordination/glue/bridge layers between old and new code
|
||||
- Flag parameters or special-case branches
|
||||
- Weird or overly literal naming
|
||||
|
||||
For each issue: file, line, what's wrong, what it should be instead.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
#### dry (DRY violations)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-dry"
|
||||
initialPrompt: "You are a DRY auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check the recent changes (use git diff) for:
|
||||
- Duplicated logic across files
|
||||
- Copy-pasted code with minor variations
|
||||
- Types that repeat fields from other types instead of deriving
|
||||
- Constants or strings repeated instead of extracted
|
||||
|
||||
For each issue: the duplicated code locations and a brief note on how to consolidate.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
#### tests (test coverage)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-tests"
|
||||
initialPrompt: "You are a test coverage auditor. [Load the e2e-playwright skill if E2E tests are in scope.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check:
|
||||
- Does every new behavior have a test?
|
||||
- Do tests verify behavior, not implementation details?
|
||||
- Are tests asserting real outcomes or just mocks?
|
||||
- Are there edge cases without test coverage?
|
||||
- Do E2E tests follow DSL-style helpers and ARIA role selectors (if applicable)?
|
||||
|
||||
Run the full relevant test suite and report output.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
#### regression
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-regression"
|
||||
initialPrompt: "You are a regression auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Run the full test suite. Report:
|
||||
- Total tests, passed, failed, skipped
|
||||
- Any failures with full error output
|
||||
- Whether failures are in new tests or existing tests
|
||||
|
||||
If ANY test fails, this phase is not done.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
#### types
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-types"
|
||||
initialPrompt: "You are a type auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Run typecheck (npm run typecheck). Report:
|
||||
- Pass/fail
|
||||
- All type errors with file, line, and error message
|
||||
- Any use of 'any', type assertions, or @ts-ignore in the changes
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
#### browser
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-browser"
|
||||
initialPrompt: "You are a browser QA auditor. Load the e2e-playwright skill.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Test the affected user flows in a browser:
|
||||
- Navigate to the relevant screens
|
||||
- Exercise the new/changed functionality
|
||||
- Check for visual regressions, broken layouts, missing states
|
||||
- Take screenshots of results
|
||||
|
||||
Report what works and what doesn't with evidence. Do NOT edit files."
|
||||
```
|
||||
|
||||
#### parity (for refactors)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-parity"
|
||||
initialPrompt: "You are a parity auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
This was a refactoring phase — behavior must be identical before and after. Check:
|
||||
- All existing tests still pass (run them)
|
||||
- No behavioral changes were introduced
|
||||
- Public APIs and interfaces are unchanged
|
||||
- No removed functionality unless explicitly planned
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### Interpreting Findings
|
||||
|
||||
If any auditor reports issues:
|
||||
|
||||
1. Check the auditor's activity with Paseo **get agent activity** for details
|
||||
2. Direct the impl agent to fix them via Paseo **send agent prompt**, or launch a new impl agent if the old one is stale
|
||||
3. Re-deploy the same auditor after fixes
|
||||
4. Do not proceed to the next phase until all auditors pass
|
||||
|
||||
Archive every auditor as soon as its report is reviewed.
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Cleanup
|
||||
|
||||
After all implementation phases are verified, deploy refactorer agents for targeted cleanup. Each refactorer has a single specialization.
|
||||
|
||||
### Refactorer Prompts
|
||||
|
||||
All refactorers launched via the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`.
|
||||
|
||||
#### dry (consolidate duplication)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-dry"
|
||||
initialPrompt: "You are a cleanup engineer specializing in DRY.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at the full diff of changes in this task (use git diff). Consolidate:
|
||||
- Duplicated logic — extract shared functions or reuse existing ones
|
||||
- Repeated types — derive with Pick, Omit, or extend instead of redefining
|
||||
- Repeated constants or strings — extract to a single source
|
||||
|
||||
Only fix genuine duplication. Three similar lines is fine — don't create premature abstractions. Run typecheck and any tests you touch when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
#### dead-code (remove unused code)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-dead-code"
|
||||
initialPrompt: "You are a cleanup engineer specializing in dead code.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at the full diff of changes (use git diff). Remove:
|
||||
- Unused imports
|
||||
- Unused variables, functions, or types introduced by this task
|
||||
- Commented-out code
|
||||
- Backwards-compatibility shims or renamed _vars that serve no purpose
|
||||
|
||||
Do NOT remove code that predates this task unless it was made dead by this task's changes. Run typecheck and any tests you touch when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
#### naming (fix unclear names)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-naming"
|
||||
initialPrompt: "You are a cleanup engineer specializing in naming.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at all new names introduced by this task (functions, variables, types, files). Fix:
|
||||
- Overly literal or verbose names
|
||||
- Inconsistent naming relative to surrounding code conventions
|
||||
- Unclear abbreviations
|
||||
- Names that describe implementation instead of intent
|
||||
|
||||
Only rename things introduced or modified by this task. Run typecheck and any tests you touch when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
Deploy refactorers in parallel. After cleanup, run a regression auditor to confirm nothing broke.
|
||||
|
||||
Archive every refactorer as soon as verified.
|
||||
|
||||
---
|
||||
|
||||
## Phase 10: Final QA
|
||||
|
||||
After all phases are implemented, verified, and cleaned up, run one final pass.
|
||||
|
||||
### 1. Re-read the plan
|
||||
|
||||
```bash
|
||||
cat ~/.paseo/plans/<task-slug>.md
|
||||
```
|
||||
|
||||
### 2. Run typecheck yourself
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
Must pass. No exceptions.
|
||||
|
||||
### 3. Run the full test suite yourself
|
||||
|
||||
Run all relevant tests. Must be 100% green. No skipped tests, no "known failures."
|
||||
|
||||
### 4. Final review agent
|
||||
|
||||
```
|
||||
title: "qa-<scope>-review"
|
||||
initialPrompt: "You are a final reviewer.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for the objective and acceptance criteria.
|
||||
|
||||
Review the entire git diff for this task. For each acceptance criterion, report:
|
||||
- YES — met, with evidence (file, line, test that proves it)
|
||||
- NO — not met, with explanation of what's missing
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### 5. Final anti-over-engineering agent
|
||||
|
||||
```
|
||||
title: "qa-<scope>-overeng"
|
||||
initialPrompt: "You are a final quality auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Audit the entire git diff for this task:
|
||||
- Unnecessary abstractions or helpers
|
||||
- Code that's clever instead of clear
|
||||
- Missing error handling at system boundaries
|
||||
- Excessive error handling for internal code
|
||||
- Any code that doesn't serve the acceptance criteria
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### 6. Browser QA (if applicable)
|
||||
|
||||
If the task involves UI changes:
|
||||
|
||||
```
|
||||
title: "qa-<scope>-browser"
|
||||
initialPrompt: "You are a QA engineer. Load the e2e-playwright skill.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Test all affected user flows end-to-end in the browser. For each flow:
|
||||
- What you tested
|
||||
- What you expected
|
||||
- What actually happened
|
||||
- Screenshot evidence
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
If any final QA agent reports issues, launch an impl or refactorer to fix, then re-run the specific check. Do not deliver with any failing checks.
|
||||
|
||||
Archive all QA agents once reports are reviewed.
|
||||
|
||||
---
|
||||
|
||||
## Phase 11: Deliver
|
||||
|
||||
1. Archive any remaining implementation/QA agents
|
||||
2. **If in worktree mode:**
|
||||
- Report the worktree path and branch name
|
||||
- Ask: "The work is in worktree `<worktree-path>` on branch `orchestrate/<task-slug>`. Should I merge it into your current branch, create a PR, or leave the worktree for you to review?"
|
||||
- Do NOT remove the worktree automatically
|
||||
3. **If NOT in worktree mode:**
|
||||
- Report: what was done (high-level), what files changed, verification results
|
||||
- Ask: "Should I commit this? Create a PR? Or leave it uncommitted for you to review?"
|
||||
|
||||
Wait for the user's instruction.
|
||||
|
||||
**When the user asks for a PR, the job is NOT done when the PR is created.** The objective is: PR created AND all CI checks passing. After creating the PR:
|
||||
|
||||
1. Keep the heartbeat schedule running — do NOT delete it yet.
|
||||
2. Update the heartbeat prompt to CI monitoring mode (below).
|
||||
3. Monitor CI status via `gh pr checks <pr-number> --watch` or `gh pr checks <pr-number>`.
|
||||
4. If any check fails:
|
||||
- Read the failure logs (`gh run view <run-id> --log-failed`).
|
||||
- Launch a fix agent targeting the failure.
|
||||
- Push the fix. CI will re-run automatically.
|
||||
- Continue monitoring.
|
||||
5. Only when ALL checks are green:
|
||||
- Delete the heartbeat schedule.
|
||||
- Report to the user with the full PR URL.
|
||||
|
||||
### Post-PR heartbeat prompt
|
||||
|
||||
```
|
||||
HEARTBEAT — CI monitoring for PR #<pr-number>.
|
||||
|
||||
Do the following steps in order:
|
||||
|
||||
1. Check CI status:
|
||||
gh pr checks <pr-number>
|
||||
|
||||
2. If all checks passed:
|
||||
- Delete this schedule.
|
||||
- Tell the user the PR is ready with the full PR URL (use `gh pr view <pr-number> --json url -q .url` to get it).
|
||||
|
||||
3. If any check failed:
|
||||
- Get the failed run logs: gh run view <run-id> --log-failed
|
||||
- Diagnose the failure.
|
||||
- Launch a fix agent to address it (background: true, notifyOnFinish: true).
|
||||
- After the fix agent completes, push the fix.
|
||||
- Continue monitoring on next heartbeat.
|
||||
|
||||
4. If checks are still running:
|
||||
- Do nothing. Wait for the next heartbeat.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Roles Reference
|
||||
|
||||
Every agent has exactly one role. The role determines what the agent does, whether it can edit files, and how it's named.
|
||||
|
||||
**Naming:** `<role>-<scope>[-<specialization>]` in kebab-case.
|
||||
|
||||
| Role | Job | Edits? | Prompt emphasis |
|
||||
| --------------- | ------------------------------------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `researcher` | Gathers info: codebase, docs, web, scripts | No | "Report what you find. Do not suggest solutions. Do not edit files." |
|
||||
| `planner` | Creates implementation plan from research | No | "Think refactor-first. Design the target shape, not the steps." |
|
||||
| `plan-reviewer` | Adversarially challenges a plan | No | "Challenge the plan. Find what's wrong, missing, or over-engineered." |
|
||||
| `impl` | Writes code, works TDD | Yes | "Work TDD. Reshape existing code. Run typecheck AND run any tests you modified. Both must pass. Do NOT commit." |
|
||||
| `tester` | Writes/fixes tests | Yes | "Verify behavior, not implementation. Run every test you modified and confirm it passes. A test change without running the test is not done." |
|
||||
| `auditor` | Read-only verification | No | "Check [specialization]. Report YES/NO with evidence. Do NOT edit files." |
|
||||
| `refactorer` | Targeted cleanup | Yes | "Fix [specialization] only. Run typecheck and any tests you touch. Do NOT commit." |
|
||||
| `qa` | End-to-end QA, browser testing | No | "Test the actual user experience. Report with evidence." |
|
||||
|
||||
Auditor specializations: `overeng`, `dry`, `tests`, `regression`, `types`, `browser`, `parity`
|
||||
Refactorer specializations: `dry`, `dead-code`, `naming`
|
||||
|
||||
---
|
||||
|
||||
## Principles
|
||||
|
||||
- **Reshape, then fill in.** Don't append new code on top. Refactor so the feature has a natural home.
|
||||
- **If it's not tested, it doesn't work.** TDD — failing test first, always.
|
||||
- **Green means done. Red means not done.** All tests pass after every phase.
|
||||
- **Simple beats clever.** The simplest solution that meets requirements wins.
|
||||
- **Narrow agents are honest agents.** Ask one thing, get one answer.
|
||||
- **The plan file is the shared context.** Every agent reads the plan from disk.
|
||||
- **Archive aggressively.** Done agents clutter the UI.
|
||||
- **Trust but verify.** Always verify with separate agents. Never take an impl agent's word for it.
|
||||
- **Describe problems, not solutions.** Tell agents what's wrong, not what to type.
|
||||
1. Load the `paseo-epic` skill and follow it.
|
||||
2. Tell the user, in one sentence: `paseo-orchestrate` is deprecated — using `paseo-epic` instead.
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
# Cleanup
|
||||
|
||||
After all implementation phases are verified, deploy refactorer agents for targeted cleanup. Each refactorer has a single specialization.
|
||||
|
||||
## When to Clean Up
|
||||
|
||||
Run cleanup after all feature work is done and verified — not between phases. Cleanup is a sweep across the entire diff.
|
||||
|
||||
## Refactorer Prompts
|
||||
|
||||
All refactorers are launched via the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`.
|
||||
|
||||
### dry (consolidate duplication)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-dry"
|
||||
initialPrompt: "You are a cleanup engineer specializing in DRY.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at the full diff of changes in this task (use git diff). Consolidate:
|
||||
- Duplicated logic — extract shared functions or reuse existing ones
|
||||
- Repeated types — derive with Pick, Omit, or extend instead of redefining
|
||||
- Repeated constants or strings — extract to a single source
|
||||
|
||||
Only fix genuine duplication. Three similar lines is fine — don't create premature abstractions. Run typecheck and tests when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
### dead-code (remove unused code)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-dead-code"
|
||||
initialPrompt: "You are a cleanup engineer specializing in dead code.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at the full diff of changes (use git diff). Remove:
|
||||
- Unused imports
|
||||
- Unused variables, functions, or types introduced by this task
|
||||
- Commented-out code
|
||||
- Backwards-compatibility shims or renamed _vars that serve no purpose
|
||||
|
||||
Do NOT remove code that predates this task unless it was made dead by this task's changes. Run typecheck and tests when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
### naming (fix unclear names)
|
||||
|
||||
```
|
||||
title: "refactorer-<scope>-naming"
|
||||
initialPrompt: "You are a cleanup engineer specializing in naming.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Look at all new names introduced by this task (functions, variables, types, files). Fix:
|
||||
- Overly literal or verbose names (e.g., handleOnClickButtonSubmit -> submitForm)
|
||||
- Inconsistent naming relative to surrounding code conventions
|
||||
- Unclear abbreviations
|
||||
- Names that describe implementation instead of intent
|
||||
|
||||
Only rename things introduced or modified by this task. Run typecheck and tests when done.
|
||||
|
||||
Do NOT commit."
|
||||
```
|
||||
|
||||
## Deploy in Parallel
|
||||
|
||||
All refactorers read the same diff but touch different concerns, so they can run in parallel. If they happen to conflict on the same lines, the orchestrator resolves by running one after the other.
|
||||
|
||||
## Verify After Cleanup
|
||||
|
||||
After cleanup, run a regression auditor to confirm nothing broke. The cleanup should be behavior-preserving.
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive every refactorer as soon as verified.
|
||||
@@ -1,93 +0,0 @@
|
||||
# Final QA
|
||||
|
||||
After all phases are implemented, verified, and cleaned up, run one final pass across the entire change.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Re-read the plan
|
||||
|
||||
```bash
|
||||
cat ~/.paseo/plans/<task-slug>.md
|
||||
```
|
||||
|
||||
Re-ground yourself in the acceptance criteria. This is what you're checking against.
|
||||
|
||||
### 2. Run typecheck yourself
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
Must pass. No exceptions.
|
||||
|
||||
### 3. Run the full test suite yourself
|
||||
|
||||
Run all relevant tests. Must be 100% green. No skipped tests, no "known failures."
|
||||
|
||||
### 4. Final review agent
|
||||
|
||||
One agent reviews the entire diff against the acceptance criteria. Launch via the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`:
|
||||
|
||||
```
|
||||
title: "qa-<scope>-review"
|
||||
initialPrompt: "You are a final reviewer.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for the objective and acceptance criteria.
|
||||
|
||||
Review the entire git diff for this task. For each acceptance criterion, report:
|
||||
- YES — met, with evidence (file, line, test that proves it)
|
||||
- NO — not met, with explanation of what's missing
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### 5. Final anti-over-engineering agent
|
||||
|
||||
```
|
||||
title: "qa-<scope>-overeng"
|
||||
initialPrompt: "You are a final quality auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Audit the entire git diff for this task:
|
||||
- Unnecessary abstractions or helpers
|
||||
- Code that's clever instead of clear
|
||||
- Missing error handling at system boundaries
|
||||
- Excessive error handling for internal code
|
||||
- Any code that doesn't serve the acceptance criteria
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### 6. Browser QA (if applicable)
|
||||
|
||||
If the task involves UI changes, deploy a browser QA agent:
|
||||
|
||||
```
|
||||
title: "qa-<scope>-browser"
|
||||
initialPrompt: "You are a QA engineer. Load the e2e-playwright skill.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Test all affected user flows end-to-end in the browser. For each flow:
|
||||
- What you tested
|
||||
- What you expected
|
||||
- What actually happened
|
||||
- Screenshot evidence
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
## If Issues Are Found
|
||||
|
||||
If any final QA agent reports issues:
|
||||
|
||||
1. Launch an impl or refactorer agent to fix them
|
||||
2. Re-run the specific QA check that failed
|
||||
3. Repeat until all checks pass
|
||||
|
||||
Do not deliver with any failing checks.
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive all QA agents once their reports are reviewed.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Grill
|
||||
|
||||
The grill phase extracts clarity from the user through structured questioning. It runs in default mode only — skipped in `--auto`.
|
||||
|
||||
## Protocol: Research First, Grill Second
|
||||
|
||||
Before asking the user anything:
|
||||
|
||||
1. Read the task description
|
||||
2. Grep relevant files, types, functions
|
||||
3. Read key files to understand the current state
|
||||
4. Form your own understanding of the problem space
|
||||
|
||||
Then ask the user ONLY about things the code cannot answer: intent, scope boundaries, UX preferences, tradeoffs, priorities, acceptance criteria.
|
||||
|
||||
Never ask a question the codebase could answer. That wastes the user's time.
|
||||
|
||||
## Questioning Approach
|
||||
|
||||
Treat the task as a decision tree. Each design choice branches into sub-decisions, constraints, and consequences.
|
||||
|
||||
- Ask one question at a time
|
||||
- Wait for the answer before moving on
|
||||
- Drill depth-first into each branch until it's resolved or explicitly deferred
|
||||
- For each question, state your recommended answer based on what you've learned from the code — the user can confirm or override
|
||||
- Cycle through question types as appropriate:
|
||||
- **Feasibility** — can this actually work given the current architecture?
|
||||
- **Dependency** — what needs to happen first? What blocks what?
|
||||
- **Edge case** — what happens when X is empty, null, concurrent, offline?
|
||||
- **Alternative** — is there a simpler way to achieve this?
|
||||
- **Scope** — is this in or out? Where's the boundary?
|
||||
- **Ordering** — does the sequence matter? What's the critical path?
|
||||
- **Failure mode** — what happens when this breaks? How do we recover?
|
||||
|
||||
## Summaries
|
||||
|
||||
Every 3-4 questions, pause and summarize:
|
||||
|
||||
- **Resolved decisions** — what's been decided
|
||||
- **Open branches** — what still needs discussion
|
||||
- **Current focus** — what you're drilling into next
|
||||
|
||||
## Termination
|
||||
|
||||
Stop grilling when:
|
||||
|
||||
- All branches of the decision tree are resolved or explicitly deferred
|
||||
- The user signals they're done ("go", "that's enough", "just build it")
|
||||
- No meaningful questions remain
|
||||
|
||||
Conclude with a final summary of all resolved decisions and any deferred items. This summary feeds directly into the planning phase.
|
||||
@@ -1,110 +0,0 @@
|
||||
# Implementation Phase
|
||||
|
||||
Deploy impl agents to execute the plan phase by phase. Each phase is independently verifiable.
|
||||
|
||||
## TDD — Not Optional
|
||||
|
||||
Every impl agent works TDD:
|
||||
|
||||
1. Write a failing test that defines the expected behavior
|
||||
2. Make it pass
|
||||
3. Refactor if needed
|
||||
4. All tests green — not just new ones, the full relevant suite
|
||||
|
||||
If an impl agent finds a broken test, it fixes it. No "pre-existing failures." No exceptions.
|
||||
|
||||
## Phase Sequencing
|
||||
|
||||
Execute phases sequentially from the plan. Refactoring phases first, then feature phases, then UI passes.
|
||||
|
||||
After each phase:
|
||||
|
||||
1. Verify (see verification.md)
|
||||
2. Fix any issues found
|
||||
3. Re-verify
|
||||
4. Only then proceed to the next phase
|
||||
|
||||
## Launching Impl Agents
|
||||
|
||||
Use the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`. **If in worktree mode, always set `cwd` to the worktree path.**
|
||||
|
||||
### How to describe the work
|
||||
|
||||
**Describe the problem, not the solution.** Your prompt should tell the agent:
|
||||
|
||||
- What's wrong or what needs to be built (the goal)
|
||||
- How it currently fails (error output, test output, user-visible behavior)
|
||||
- The acceptance criteria (what "done" looks like)
|
||||
|
||||
**Do NOT tell the agent:**
|
||||
|
||||
- Which specific lines to change
|
||||
- What code to write
|
||||
- Which functions to call or which patterns to use
|
||||
|
||||
The agent reads the plan and the code. It will figure out the implementation. If you're writing specific line numbers or code snippets in the prompt, you're micromanaging and it will backfire — the agent takes you literally and skips its own judgment.
|
||||
|
||||
Bad: "In `new-workspace.spec.ts` at line 164, change the tab assertion from `getByText('New Agent')` to `getByTestId(/workspace-tab-agent_/)`"
|
||||
|
||||
Good: "The new-workspace E2E test is failing. The test creates a workspace via empty submit, but then the tab assertion fails because it looks for text 'New Agent' which doesn't match the actual tab label. Here's the error output: [paste error]. Fix the test and run it to confirm it passes."
|
||||
|
||||
### Prompt template
|
||||
|
||||
```
|
||||
title: "impl-<scope>-<phase>"
|
||||
agentType: <resolved from providers.impl>
|
||||
model: <resolved from providers.impl>
|
||||
cwd: <worktree-path if worktree mode, omit otherwise>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are an implementation engineer. [Load the e2e-playwright skill if frontend/E2E work.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md to understand the objective and your specific phase.
|
||||
|
||||
Do not bolt new code on top of existing code. If the existing code isn't shaped to accommodate your work, reshape it first. The goal is code that looks like this feature always existed.
|
||||
|
||||
Work TDD: write a failing test first, then make it pass. All tests must be green when done — not just your new ones, the full relevant suite. If you find a broken test, fix it.
|
||||
|
||||
<describe the problem and acceptance criteria — NOT the solution>
|
||||
|
||||
When done: run typecheck AND run any tests you modified or that cover your changes. Both must pass. Do NOT commit."
|
||||
```
|
||||
|
||||
## UI Passes
|
||||
|
||||
UI/styling work uses a different provider (from `providers.ui` in preferences). The orchestrator launches UI agents after the functionality is verified:
|
||||
|
||||
```
|
||||
title: "impl-<scope>-ui"
|
||||
agentType: <resolved from providers.ui>
|
||||
model: <resolved from providers.ui>
|
||||
cwd: <worktree-path if worktree mode, omit otherwise>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a UI engineer. [Load the e2e-playwright skill.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
The functionality is implemented. Your job is the styling pass:
|
||||
- Study existing components and styles in nearby screens
|
||||
- Follow existing conventions exactly — no new patterns
|
||||
- Keep design minimal and consistent with the rest of the app
|
||||
- Think carefully about spacing, alignment, and visual hierarchy
|
||||
|
||||
<describe the specific UI work>
|
||||
|
||||
Run typecheck when done. Do NOT commit."
|
||||
```
|
||||
|
||||
## Handling Blockers
|
||||
|
||||
If an impl agent reports a blocker:
|
||||
|
||||
- Do NOT ask the user (in either mode)
|
||||
- Spin up a researcher to investigate
|
||||
- Spin up an impl agent to fix it
|
||||
- The scope of work is unlimited — touching other files, packages, or systems is fine
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive every impl agent as soon as its phase is verified.
|
||||
@@ -1,122 +0,0 @@
|
||||
# Planning Phase
|
||||
|
||||
Deploy planners to create an implementation plan informed by research findings. The number of planners and plan-reviewers scales with complexity order (see triage.md).
|
||||
|
||||
## Refactor-First Thinking
|
||||
|
||||
Every planner prompt must emphasize this: the default agent instinct is to bolt new code on top of existing code. Resist this.
|
||||
|
||||
The right approach:
|
||||
|
||||
1. Study the existing code — understand why it's shaped the way it is
|
||||
2. Design the target shape — what would the code look like if this feature had always existed?
|
||||
3. Identify the refactoring gap — what needs to change so the new feature slots in cleanly?
|
||||
4. Plan refactor phases before feature phases — lay the groundwork first
|
||||
|
||||
If the plan has a phase called "wire up" or "connect" or "integrate," a refactor phase could probably eliminate the need for it.
|
||||
|
||||
## Launching Planners
|
||||
|
||||
Use the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`:
|
||||
|
||||
```
|
||||
title: "planner-<scope>"
|
||||
agentType: <resolved from providers.planning>
|
||||
model: <resolved from providers.planning>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a planner.
|
||||
|
||||
Read the research findings provided below and the objective.
|
||||
|
||||
<paste synthesized research findings and objective>
|
||||
|
||||
Draft a phased implementation plan. Think refactor-first: before planning the feature, identify what existing code needs to be reshaped so the feature slots in naturally.
|
||||
|
||||
For each phase, specify:
|
||||
- What changes and why
|
||||
- Files involved
|
||||
- Types and interfaces affected
|
||||
- Tests to write (failing test first — TDD)
|
||||
- Acceptance criteria for the phase
|
||||
|
||||
Write the plan to ~/.paseo/plans/<task-slug>.md"
|
||||
```
|
||||
|
||||
## Launching Plan-Reviewers
|
||||
|
||||
```
|
||||
title: "plan-reviewer-<scope>"
|
||||
agentType: <resolved from providers.planning>
|
||||
model: <resolved from providers.planning>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a plan-reviewer.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md.
|
||||
|
||||
Challenge the plan:
|
||||
- Is it bolting new code on top, or reshaping existing code first?
|
||||
- Are there coordination/glue/bridge layers that a better refactor would eliminate?
|
||||
- What edge cases are missing? What will break?
|
||||
- What's over-engineered? What's under-specified?
|
||||
- Is the phase ordering correct? Are there hidden dependencies?"
|
||||
```
|
||||
|
||||
## Multiple Planners (Order 3+)
|
||||
|
||||
For cross-module tasks, deploy planners focusing on different slices:
|
||||
|
||||
- One for backend phases
|
||||
- One for frontend phases
|
||||
- One for test strategy
|
||||
|
||||
Then deploy a plan-reviewer to challenge the combined plan.
|
||||
|
||||
## Iteration
|
||||
|
||||
If the plan-reviewer finds significant issues, either:
|
||||
|
||||
1. Send follow-up instructions via the Paseo **send agent prompt** tool to the planner
|
||||
2. Launch a new planner if the original is stale
|
||||
|
||||
Iterate until the plan-reviewer's only feedback is minor. Then synthesize the final plan.
|
||||
|
||||
## Plan Structure
|
||||
|
||||
The final plan must follow this structure:
|
||||
|
||||
```
|
||||
# <Task Title>
|
||||
|
||||
## Objective
|
||||
<one-paragraph summary>
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] <criterion 1>
|
||||
- [ ] <criterion 2>
|
||||
|
||||
## Plan
|
||||
### Phase 1: <name>
|
||||
<description, files, types, tests, acceptance criteria>
|
||||
|
||||
### Phase 2: <name>
|
||||
...
|
||||
```
|
||||
|
||||
## Persisting the Plan
|
||||
|
||||
Save the final plan to disk:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.paseo/plans
|
||||
cat > ~/.paseo/plans/<task-slug>.md << 'PLAN'
|
||||
<plan content>
|
||||
PLAN
|
||||
```
|
||||
|
||||
This file is the durable reference. Re-read it before every verification, review, or QA phase. It survives context compaction.
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive all planners and plan-reviewers once the final plan is settled.
|
||||
@@ -1,73 +0,0 @@
|
||||
# Preferences
|
||||
|
||||
The orchestrator reads user preferences from `~/.paseo/orchestrate.json` at startup. If the file doesn't exist, use the defaults below.
|
||||
|
||||
## Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"providers": {
|
||||
"impl": "codex/gpt-5.4",
|
||||
"ui": "claude/opus",
|
||||
"research": "codex/gpt-5.4",
|
||||
"planning": "codex/gpt-5.4",
|
||||
"audit": "codex/gpt-5.4"
|
||||
},
|
||||
"preferences": []
|
||||
}
|
||||
```
|
||||
|
||||
### providers
|
||||
|
||||
Maps role categories to `<agent-type>/<model>` strings. These map directly to the Paseo **create agent** tool parameters:
|
||||
|
||||
- The part before `/` is the `agentType` (e.g., `codex`, `claude`, `opencode`)
|
||||
- The part after `/` is the `model` (e.g., `gpt-5.4`, `opus`)
|
||||
|
||||
| Category | Roles covered |
|
||||
| ---------- | --------------------------------- |
|
||||
| `impl` | impl, tester, refactorer |
|
||||
| `ui` | impl agents doing UI/styling work |
|
||||
| `research` | researcher |
|
||||
| `planning` | planner, plan-reviewer |
|
||||
| `audit` | auditor, qa |
|
||||
|
||||
If a category is missing, use these defaults:
|
||||
|
||||
- `impl` -> `codex/gpt-5.4`
|
||||
- `ui` -> `claude/opus`
|
||||
- `research` -> `codex/gpt-5.4`
|
||||
- `planning` -> `codex/gpt-5.4`
|
||||
- `audit` -> `codex/gpt-5.4`
|
||||
|
||||
### preferences
|
||||
|
||||
Freeform array of natural language strings. The user states preferences and the orchestrator appends them here. Read these at startup and weave them into your behavior contextually.
|
||||
|
||||
Examples:
|
||||
|
||||
- "Prefer small, focused PRs over large bundled ones"
|
||||
- "Run E2E tests with Maestro, not Playwright"
|
||||
- "Always check mobile responsiveness"
|
||||
- "Use French for commit messages"
|
||||
|
||||
## Reading Preferences
|
||||
|
||||
At the start of every orchestration:
|
||||
|
||||
```bash
|
||||
cat ~/.paseo/orchestrate.json 2>/dev/null || echo '{}'
|
||||
```
|
||||
|
||||
Parse the JSON. Merge with defaults for any missing fields.
|
||||
|
||||
## Writing Preferences
|
||||
|
||||
When the user says "store my preference: X" or "remember that I prefer X":
|
||||
|
||||
1. Read the current file
|
||||
2. If it's a provider change (e.g., "use Claude for implementation"), update `providers`
|
||||
3. If it's anything else, append to `preferences`
|
||||
4. Write the file back
|
||||
|
||||
Never remove preferences unless the user explicitly asks.
|
||||
@@ -1,43 +0,0 @@
|
||||
# Research Phase
|
||||
|
||||
Deploy researchers to gather information before planning. The number and focus of researchers scales with complexity order (see triage.md).
|
||||
|
||||
## Researcher Deployment
|
||||
|
||||
Each researcher gets a narrow mandate. Examples:
|
||||
|
||||
- **Codebase area:** "Read all files in `packages/server/src/server/session/`. Map the types, interfaces, and data flow. Report what you find."
|
||||
- **Test coverage:** "Read all test files related to X. What's tested? What's not? What patterns do the tests follow?"
|
||||
- **External docs:** "Search the Expo docs for Y. Find the recommended approach. Report back."
|
||||
- **Reference implementation:** "Read the cmux project at ~/dev/cmux. How does it handle Z? Report the pattern."
|
||||
- **Web research:** "Search for how other projects solve X. Find 2-3 reference implementations. Summarize the approaches."
|
||||
- **Scripts/probing:** "Write and run a small script to test whether X behaves as expected. Report the results."
|
||||
|
||||
## Launching Researchers
|
||||
|
||||
Use the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`:
|
||||
|
||||
```
|
||||
title: "researcher-<scope>"
|
||||
agentType: <resolved from providers.research>
|
||||
model: <resolved from providers.research>
|
||||
background: true
|
||||
notifyOnFinish: true
|
||||
initialPrompt: "You are a researcher.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for the objective.
|
||||
|
||||
<specific research mandate>
|
||||
|
||||
Include in your findings: relevant files, types, interfaces, patterns, gotchas, and anything surprising. Do NOT suggest solutions or edit files."
|
||||
```
|
||||
|
||||
## Collecting Findings
|
||||
|
||||
Wait for all researchers to complete (you'll be notified). Use the Paseo **get agent activity** tool to read their findings. Synthesize into a research summary that feeds the planning phase.
|
||||
|
||||
If a researcher's findings raise new questions (in default mode), go back and ask the user before proceeding to planning.
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive every researcher as soon as its findings are collected.
|
||||
@@ -1,83 +0,0 @@
|
||||
# Roles
|
||||
|
||||
Every agent launched by the orchestrator has exactly one role. The role determines what the agent does, whether it can edit files, and how it's named.
|
||||
|
||||
## Naming Convention
|
||||
|
||||
`<role>-<scope>[-<specialization>]` in kebab-case.
|
||||
|
||||
- `<role>` — one of the roles below
|
||||
- `<scope>` — what area of the codebase or task (e.g., `server-session`, `app-checkout`, `auth-refactor`)
|
||||
- `<specialization>` — optional narrowing (e.g., `overeng`, `dry`, `tests`)
|
||||
|
||||
Examples: `researcher-server-session`, `planner-background-fetch`, `impl-checkout-phase1`, `auditor-checkout-overeng`, `refactorer-checkout-dry`
|
||||
|
||||
## Role Definitions
|
||||
|
||||
### researcher
|
||||
|
||||
Gathers information. Can explore the codebase, read files, trace dependencies, search the web, read docs, check other projects for reference implementations, run scripts to test hypotheses, read tests, run tests.
|
||||
|
||||
- **Edits files:** No
|
||||
- **Prompt emphasis:** "Report what you find. Do not suggest solutions. Do not edit files."
|
||||
|
||||
### planner
|
||||
|
||||
Synthesizes research findings into a phased implementation plan. Identifies what existing code needs to be reshaped, defines interfaces and types, sequences phases.
|
||||
|
||||
- **Edits files:** No
|
||||
- **Prompt emphasis:** "Think refactor-first. Design the target shape, not the steps."
|
||||
|
||||
### plan-reviewer
|
||||
|
||||
Adversarially challenges a plan. Looks for: bolted-on code vs natural fit, missing edge cases, over-engineering, under-specification, wrong phase ordering, scope creep.
|
||||
|
||||
- **Edits files:** No
|
||||
- **Prompt emphasis:** "Challenge the plan. Find what's wrong, missing, or over-engineered. Do not suggest an alternative plan — identify problems."
|
||||
|
||||
### impl
|
||||
|
||||
Writes code. Works TDD: failing test first, then make it pass. Runs typecheck and all modified/related tests when done.
|
||||
|
||||
- **Edits files:** Yes
|
||||
- **Prompt emphasis:** "Work TDD. Do not bolt new code on top — reshape existing code so the feature slots in naturally. Run typecheck AND run any tests you modified or that cover your changes when done. Both must pass. Do NOT commit."
|
||||
|
||||
### tester
|
||||
|
||||
Writes or fixes tests specifically. Used when test work is substantial enough to warrant a dedicated agent separate from impl.
|
||||
|
||||
- **Edits files:** Yes
|
||||
- **Prompt emphasis:** "Write tests that verify behavior, not implementation details. Run every test you modified and confirm it passes. A test change without running the test is not done."
|
||||
|
||||
### auditor
|
||||
|
||||
Read-only verification. Each auditor has a specialization — it checks exactly one thing.
|
||||
|
||||
- **Edits files:** No
|
||||
- **Specializations:**
|
||||
- `overeng` — unnecessary abstractions, helpers, defensive code, coordination/glue layers
|
||||
- `dry` — duplicated logic, copy-pasted code
|
||||
- `tests` — test coverage gaps, test quality, tests that assert mocks instead of behavior
|
||||
- `regression` — runs full test suite, checks for breakage
|
||||
- `types` — runs typecheck, checks type hygiene
|
||||
- `browser` — QA with browser (Maestro or Playwright)
|
||||
- `parity` — for refactors, verifies behavior is identical before/after
|
||||
- **Prompt emphasis:** "Check [specialization]. Report YES/NO with evidence. Do NOT edit files."
|
||||
|
||||
### refactorer
|
||||
|
||||
Targeted cleanup. Each refactorer has a specialization.
|
||||
|
||||
- **Edits files:** Yes
|
||||
- **Specializations:**
|
||||
- `dry` — consolidate duplicated logic
|
||||
- `dead-code` — remove unused code, unused imports, unused types
|
||||
- `naming` — fix unclear or unconventional names
|
||||
- **Prompt emphasis:** "Fix [specialization] only. Do not refactor anything else. Run typecheck and tests when done. Do NOT commit."
|
||||
|
||||
### qa
|
||||
|
||||
End-to-end quality assurance. Can use browser automation, run the app, test user flows.
|
||||
|
||||
- **Edits files:** No
|
||||
- **Prompt emphasis:** "Test the actual user experience. Report what works and what doesn't with evidence (screenshots, logs, error messages)."
|
||||
@@ -1,63 +0,0 @@
|
||||
# Triage
|
||||
|
||||
Triage is fast and cheap. The orchestrator does it itself — no agents. The goal is to assess complexity order, which determines how many agents to deploy at each phase.
|
||||
|
||||
## How to Assess
|
||||
|
||||
1. Read the task description
|
||||
2. Grep the codebase for relevant files, types, and functions
|
||||
3. Identify how many packages/modules are touched
|
||||
4. Identify whether it's a new feature, refactor, bug fix, or architectural change
|
||||
5. Assign a complexity order
|
||||
|
||||
State the order and briefly why: "Order 3 — touches server session management and the app's git status display across two packages."
|
||||
|
||||
## Complexity Orders
|
||||
|
||||
### Order 1 — Single file, single concern
|
||||
|
||||
A contained change: fix a bug in one function, add a field to one type, update one component.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ----------------------------- |
|
||||
| Research | 1 researcher |
|
||||
| Planning | 0 — orchestrator plans inline |
|
||||
| Implement | 1 impl |
|
||||
| Verify | 1-2 auditors |
|
||||
| Cleanup | 0-1 refactorer |
|
||||
|
||||
### Order 2 — Single module, few files
|
||||
|
||||
A feature or fix within one package that touches 3-8 files. Might involve new types, new tests, a few component changes.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ---------------- |
|
||||
| Research | 2 researchers |
|
||||
| Planning | 1 planner |
|
||||
| Implement | 1 impl per phase |
|
||||
| Verify | 2-3 auditors |
|
||||
| Cleanup | 1 refactorer |
|
||||
|
||||
### Order 3 — Cross-module, multiple packages
|
||||
|
||||
A feature that spans packages (e.g., server + app, or CLI + server). Multiple concerns, multiple file groups, likely needs interface changes between layers.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | ----------------------------------------------------------------------- |
|
||||
| Research | 3-4 researchers (one per area: backend, frontend, tests, external docs) |
|
||||
| Planning | 2 planners + 1 plan-reviewer |
|
||||
| Implement | 1-2 impl agents per phase |
|
||||
| Verify | 3-4 auditors (overeng, tests, regression, types) |
|
||||
| Cleanup | 1-2 refactorers |
|
||||
|
||||
### Order 4 — Architectural, system-wide
|
||||
|
||||
A new subsystem, major refactor, or change that touches most of the codebase. New abstractions, new patterns, potentially breaking changes that need migration.
|
||||
|
||||
| Phase | Agents |
|
||||
| --------- | --------------------------------------------------- |
|
||||
| Research | 5+ researchers across all relevant areas |
|
||||
| Planning | 2+ planners (one per major area) + 2 plan-reviewers |
|
||||
| Implement | 2+ impl agents per phase, sequenced carefully |
|
||||
| Verify | Full auditor suite per phase |
|
||||
| Cleanup | 2+ refactorers with different specializations |
|
||||
@@ -1,162 +0,0 @@
|
||||
# Verification
|
||||
|
||||
After every implementation phase, deploy auditors to verify the work. Auditors are read-only — they check, they don't fix. Each auditor has a single specialization.
|
||||
|
||||
## Which Auditors to Deploy
|
||||
|
||||
Not every phase needs every auditor. Match auditors to the work:
|
||||
|
||||
| Phase type | Auditors |
|
||||
| ------------------ | ------------------------------------------------------ |
|
||||
| Refactor | `parity`, `regression`, `types` |
|
||||
| Feature (backend) | `overeng`, `tests`, `regression`, `types` |
|
||||
| Feature (frontend) | `overeng`, `tests`, `types`, `browser` (if applicable) |
|
||||
| UI pass | `overeng`, `browser` (if applicable) |
|
||||
| Test-only | `regression` |
|
||||
|
||||
Deploy all relevant auditors in parallel — they're read-only so they don't conflict.
|
||||
|
||||
## Auditor Prompts
|
||||
|
||||
All auditors are launched via the Paseo **create agent** tool with `background: true` and `notifyOnFinish: true`.
|
||||
|
||||
### overeng (anti-over-engineering)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-overeng"
|
||||
initialPrompt: "You are an anti-over-engineering auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check the recent changes (use git diff) for:
|
||||
- Unnecessary abstractions, helpers, or utility functions
|
||||
- Defensive code for scenarios that can't happen
|
||||
- Event emitters, observers, or pub/sub where a direct call would do
|
||||
- Coordination/glue/bridge layers between old and new code
|
||||
- Flag parameters or special-case branches
|
||||
- Weird or overly literal naming
|
||||
|
||||
For each issue: file, line, what's wrong, what it should be instead.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### dry (DRY violations)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-dry"
|
||||
initialPrompt: "You are a DRY auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check the recent changes (use git diff) for:
|
||||
- Duplicated logic across files
|
||||
- Copy-pasted code with minor variations
|
||||
- Types that repeat fields from other types instead of deriving
|
||||
- Constants or strings repeated instead of extracted
|
||||
|
||||
For each issue: the duplicated code locations and a brief note on how to consolidate.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### tests (test coverage)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-tests"
|
||||
initialPrompt: "You are a test coverage auditor. [Load the e2e-playwright skill if E2E tests are in scope.]
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Check:
|
||||
- Does every new behavior have a test?
|
||||
- Do tests verify behavior, not implementation details?
|
||||
- Are tests asserting real outcomes or just mocks?
|
||||
- Are there edge cases without test coverage?
|
||||
- Do E2E tests follow DSL-style helpers and ARIA role selectors (if applicable)?
|
||||
|
||||
Run the full relevant test suite and report output.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### regression
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-regression"
|
||||
initialPrompt: "You are a regression auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Run the full test suite. Report:
|
||||
- Total tests, passed, failed, skipped
|
||||
- Any failures with full error output
|
||||
- Whether failures are in new tests or existing tests
|
||||
|
||||
If ANY test fails, this phase is not done.
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### types
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-types"
|
||||
initialPrompt: "You are a type auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Run typecheck (npm run typecheck). Report:
|
||||
- Pass/fail
|
||||
- All type errors with file, line, and error message
|
||||
- Any use of 'any', type assertions, or @ts-ignore in the changes
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
### browser
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-browser"
|
||||
initialPrompt: "You are a browser QA auditor. Load the e2e-playwright skill.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
Test the affected user flows in a browser:
|
||||
- Navigate to the relevant screens
|
||||
- Exercise the new/changed functionality
|
||||
- Check for visual regressions, broken layouts, missing states
|
||||
- Take screenshots of results
|
||||
|
||||
Report what works and what doesn't with evidence. Do NOT edit files."
|
||||
```
|
||||
|
||||
### parity (for refactors)
|
||||
|
||||
```
|
||||
title: "auditor-<scope>-parity"
|
||||
initialPrompt: "You are a parity auditor.
|
||||
|
||||
Read the plan at ~/.paseo/plans/<task-slug>.md for context.
|
||||
|
||||
This was a refactoring phase — behavior must be identical before and after. Check:
|
||||
- All existing tests still pass (run them)
|
||||
- No behavioral changes were introduced
|
||||
- Public APIs and interfaces are unchanged
|
||||
- No removed functionality unless explicitly planned
|
||||
|
||||
Do NOT edit files."
|
||||
```
|
||||
|
||||
## Interpreting Findings
|
||||
|
||||
If any auditor reports issues:
|
||||
|
||||
1. Check the auditor's activity with the Paseo **get agent activity** tool for details
|
||||
2. Direct the impl agent to fix them via the Paseo **send agent prompt** tool, or launch a new impl agent if the old one is stale
|
||||
3. Re-deploy the same auditor after fixes
|
||||
4. Do not proceed to the next phase until all auditors pass
|
||||
|
||||
## Always Archive
|
||||
|
||||
Archive every auditor as soon as its report is reviewed.
|
||||
@@ -38,6 +38,34 @@ Compose: call `create_worktree` first, then `create_agent` with `cwd` set to the
|
||||
|
||||
`claude/sonnet` (default), `claude/opus` (harder reasoning), `codex/gpt-5.4` (frontier coding), `claude/haiku` (tests only).
|
||||
|
||||
## Orchestration preferences
|
||||
|
||||
User-specific configuration at `~/.paseo/orchestration-preferences.json`. **Any paseo skill that picks an agent reads this file.** Never hardcode a provider string in another skill — resolve through this file.
|
||||
|
||||
Two parts:
|
||||
|
||||
- `providers` — map of role categories to provider strings. Pass straight to `create_agent`'s `provider` field.
|
||||
- `preferences` — freeform string array. Read on startup; weave into agent prompts contextually.
|
||||
|
||||
Categories: `impl`, `ui`, `research`, `planning`, `audit`. Skills pick the category that matches the role they're launching.
|
||||
|
||||
```json
|
||||
{
|
||||
"providers": {
|
||||
"impl": "codex/gpt-5.4",
|
||||
"ui": "claude/opus",
|
||||
"research": "codex/gpt-5.4",
|
||||
"planning": "codex/gpt-5.4",
|
||||
"audit": "codex/gpt-5.4"
|
||||
},
|
||||
"preferences": [
|
||||
"Claude Opus is the right choice for anything artistic or human-skill-oriented: copywriting, naming, UX copy, visual design, styling. Codex is the workhorse for mechanical work."
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If the file is missing, use sensible defaults and tell the user once.
|
||||
|
||||
## Waiting
|
||||
|
||||
`create_agent` and `send_agent_prompt` block by default — trust them. Real tasks take 10–30+ minutes routinely. Don't poll `list_agents` or `get_agent_status` to "check on" a blocking call. To work in parallel, pass `background: true` and call `wait_for_agent` later.
|
||||
|
||||
Reference in New Issue
Block a user