chore: normalize to bun monorepo conventions
CI / check (push) Successful in 1m41s

- Enhanced Biome config with test file override for noConsole
- Applied Biome auto-fixes (8 files: formatting, template literals, optional chains)
- Updated all package repository URLs to git.shazhou.work/uncaged/workflow.git
- Added workflow-agent-claude-code to publish order in scripts/publish-all.mjs
- Added --ignore-scripts flag to publish command to bypass prepublishOnly guard
- Installed vitest in root devDependencies for test infrastructure
- Created vitest.config.ts for all 8 packages with passWithNoTests: true
- Fixed 3 test files to use vitest imports instead of bun:test
- Added test and test:ci scripts to packages missing them
- Added missing build step to .gitea/workflows/ci.yml
- Renamed CI job from 'test' to 'check' for clarity
- Created workflows/solve-issue.yaml with TDD-driven issue resolution workflow
- Registered solve-issue workflow with uwf (hash: 084YVM60BR8G6)
- Added packageManager: bun@1.3.14 to root package.json
- Added preinstall guard to block npm/pnpm/yarn
- Added prepublishOnly guard to root and all 7 public packages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 08:01:41 +00:00
parent 512a3f8653
commit 3a927de63f
30 changed files with 329 additions and 59 deletions
+7 -6
View File
@@ -7,18 +7,19 @@ on:
branches: [main]
jobs:
test:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun install
- run: bun install
- name: Check
- name: Build
run: bun run build
- name: Lint
run: bun run check
- name: Test
+2 -1
View File
@@ -39,7 +39,8 @@
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
"noExplicitAny": "off",
"noConsole": "off"
},
"style": {
"noNonNullAssertion": "off"
+6 -1
View File
@@ -1,11 +1,14 @@
{
"name": "@uncaged/workflow-monorepo",
"private": true,
"packageManager": "bun@1.3.14",
"workspaces": [
"packages/*"
],
"scripts": {
"uwf": "bun packages/cli-workflow/src/cli.ts",
"preinstall": "npx only-allow bun",
"prepublishOnly": "echo 'Use bun run release instead' && exit 1",
"build": "bunx tsc --build",
"check": "bunx tsc --build && biome check . && bash scripts/lint-log-tags.sh",
"typecheck": "bunx tsc --build",
@@ -23,7 +26,9 @@
"@types/node": "^25.7.0",
"@types/xxhashjs": "^0.2.4",
"@uncaged/workflow-agent-hermes": "workspace:*",
"bun-types": "^1.3.13"
"bun-types": "^1.3.13",
"typescript": "^5.8.3",
"vitest": "^4.1.7"
},
"repository": {
"type": "git",
+4 -3
View File
@@ -22,6 +22,7 @@
"yaml": "^2.8.4"
},
"scripts": {
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
@@ -34,12 +35,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/cli-workflow"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -98,7 +98,7 @@ describe("solve-issue workflow: tea pr create worktree fix", () => {
expect(frontmatter).toBeDefined();
expect(frontmatter?.oneOf).toBeDefined();
const committedVariant = frontmatter.oneOf.find(
(v: any) => v.properties?.["$status"]?.const === "committed",
(v: any) => v.properties?.$status?.const === "committed",
);
expect(committedVariant).toBeDefined();
expect(committedVariant.required).toContain("$status");
@@ -56,7 +56,7 @@ const VALID_OUTPUT: AdapterOutput = {
describe("spawnAgent JSON parsing", () => {
test("B1. parses valid JSON from agent stdout", () => {
const stdout = JSON.stringify(VALID_OUTPUT) + "\n";
const stdout = `${JSON.stringify(VALID_OUTPUT)}\n`;
const result = parseAgentStdout(stdout);
expect(result.stepHash).toBe("0123456789ABC");
expect(result.detailHash).toBe("DEFGH12345678");
@@ -68,7 +68,7 @@ describe("spawnAgent JSON parsing", () => {
});
test("B2. extracts stepHash for head pointer", () => {
const stdout = JSON.stringify(VALID_OUTPUT) + "\n";
const stdout = `${JSON.stringify(VALID_OUTPUT)}\n`;
const result = parseAgentStdout(stdout);
expect(result.stepHash).toBe("0123456789ABC");
expect(isCasRef(result.stepHash)).toBe(true);
@@ -76,7 +76,7 @@ describe("spawnAgent JSON parsing", () => {
test("B3. handles debug lines before JSON", () => {
const debugLines = "[debug] loading context...\n[debug] running agent...\n";
const stdout = debugLines + JSON.stringify(VALID_OUTPUT) + "\n";
const stdout = `${debugLines + JSON.stringify(VALID_OUTPUT)}\n`;
const result = parseAgentStdout(stdout);
expect(result.stepHash).toBe("0123456789ABC");
});
@@ -88,13 +88,13 @@ describe("spawnAgent JSON parsing", () => {
test("B5. rejects JSON missing stepHash", () => {
const incomplete = { detailHash: "DEFGH12345678", role: "planner" };
const stdout = JSON.stringify(incomplete) + "\n";
const stdout = `${JSON.stringify(incomplete)}\n`;
expect(() => parseAgentStdout(stdout)).toThrow("missing valid stepHash");
});
test("B6. rejects JSON with invalid stepHash", () => {
const bad = { ...VALID_OUTPUT, stepHash: "not-a-hash" };
const stdout = JSON.stringify(bad) + "\n";
const stdout = `${JSON.stringify(bad)}\n`;
expect(() => parseAgentStdout(stdout)).toThrow("missing valid stepHash");
});
});
+1 -6
View File
@@ -5,12 +5,7 @@ export {
generateUserReference as cmdSkillUser,
} from "@uncaged/workflow-util";
const SKILL_NAMES = [
"user",
"author",
"developer",
"adapter",
] as const;
const SKILL_NAMES = ["user", "author", "developer", "adapter"] as const;
export function cmdSkillList(): ReadonlyArray<string> {
return [...SKILL_NAMES];
+1
View File
@@ -3,5 +3,6 @@ import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+6 -5
View File
@@ -18,8 +18,9 @@
}
},
"scripts": {
"test": "bun test",
"test:ci": "bun test"
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@uncaged/json-cas": "^0.5.3",
@@ -34,12 +35,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-agent-builtin"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
@@ -18,8 +18,9 @@
}
},
"scripts": {
"test": "bun test",
"test:ci": "bun test"
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@uncaged/json-cas": "^0.5.3",
@@ -34,12 +35,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-agent-claude-code"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -152,9 +152,7 @@ async function runClaudeCode(ctx: AgentContext): Promise<AgentRunResult> {
} catch (err) {
log(
"5VKR8N3Q",
"resume failed for session %s, falling back to fresh run: %s",
cachedSessionId,
err,
`resume failed for session ${cachedSessionId}, falling back to fresh run: ${err}`,
);
}
}
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+6 -5
View File
@@ -18,8 +18,9 @@
}
},
"scripts": {
"test": "bun test",
"test:ci": "bun test __tests__/*.test.ts"
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@uncaged/json-cas": "^0.5.3",
@@ -35,12 +36,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-agent-hermes"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"engines": {
"bun": ">= 1.0.0"
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+3 -1
View File
@@ -5,7 +5,9 @@
"type": "module",
"scripts": {
"dev": "bun server.ts",
"build": "vite build"
"build": "vite build",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@base-ui/react": "^1.5.0",
+8 -3
View File
@@ -14,6 +14,11 @@
"import": "./dist/index.js"
}
},
"scripts": {
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@uncaged/json-cas": "^0.5.3",
"@uncaged/json-cas-fs": "^0.5.3"
@@ -26,12 +31,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-protocol"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -1,4 +1,4 @@
import { describe, expect, test } from "bun:test";
import { describe, expect, test } from "vitest";
import type { StartNodePayload, StepRecord, Target } from "../types.js";
describe("Protocol types for thread/edge location", () => {
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+6 -5
View File
@@ -15,8 +15,9 @@
}
},
"scripts": {
"test": "bun test",
"test:ci": "bun test"
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {
"@uncaged/json-cas": "^0.5.3",
@@ -34,12 +35,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-util-agent"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { afterEach, beforeEach, describe, expect, test } from "vitest";
describe("parseArgv empty prompt error message", () => {
let stderrOutput: string;
@@ -214,7 +214,7 @@ function getConstValue(propSchema: JSONSchema): string {
function buildVariantBlock(variant: JSONSchema, discriminant: string): string {
const props = extractSchemaProperties(variant);
const value = getConstValue(
((variant.properties as Record<string, JSONSchema>) ?? {})[discriminant] ?? {},
(variant.properties as Record<string, JSONSchema>)?.[discriminant] ?? {},
);
const yamlExample = buildYamlExampleBlock(props);
const fieldList = buildFieldList(props);
+1 -1
View File
@@ -5,5 +5,5 @@
"outDir": "dist"
},
"include": ["src"],
"references": [{ "path": "../workflow-protocol" }]
"references": [{ "path": "../workflow-protocol" }, { "path": "../workflow-util" }]
}
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+8 -3
View File
@@ -14,6 +14,11 @@
"import": "./dist/index.js"
}
},
"scripts": {
"prepublishOnly": "echo 'Use bun run release from repo root' && exit 1",
"test": "vitest run",
"test:ci": "vitest run"
},
"dependencies": {},
"devDependencies": {
"typescript": "^5.8.3"
@@ -23,12 +28,12 @@
},
"repository": {
"type": "git",
"url": "https://github.com/shazhou-ww/uncaged-workflow.git",
"url": "https://git.shazhou.work/uncaged/workflow.git",
"directory": "packages/workflow-util"
},
"homepage": "https://github.com/shazhou-ww/uncaged-workflow#readme",
"homepage": "https://git.shazhou.work/uncaged/workflow#readme",
"bugs": {
"url": "https://github.com/shazhou-ww/uncaged-workflow/issues"
"url": "https://git.shazhou.work/uncaged/workflow/issues"
},
"license": "MIT"
}
@@ -1,4 +1,4 @@
import { describe, expect, it } from "bun:test";
import { describe, expect, it } from "vitest";
import { extractUlidTimestamp, generateUlid } from "../ulid.js";
describe("extractUlidTimestamp", () => {
+8
View File
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/__tests__/**/*.test.ts"],
passWithNoTests: true,
},
});
+2 -1
View File
@@ -21,6 +21,7 @@ const publishOrder = [
"workflow-util-agent",
"workflow-agent-hermes",
"workflow-agent-builtin",
"workflow-agent-claude-code",
"cli-workflow",
];
@@ -59,7 +60,7 @@ let failed = false;
for (const name of publishOrder) {
const pkgDir = join(root, "packages", name);
const tagFlag = tag ? `--tag ${tag}` : "";
const cmd = `npm publish --access public ${tagFlag}`;
const cmd = `npm publish --access public --ignore-scripts ${tagFlag}`;
console.log(`📦 ${name}...`);
+1
View File
@@ -23,6 +23,7 @@
{ "path": "packages/workflow-util-agent" },
{ "path": "packages/workflow-agent-hermes" },
{ "path": "packages/workflow-agent-builtin" },
{ "path": "packages/workflow-agent-claude-code" },
{ "path": "packages/cli-workflow" }
]
}
+202
View File
@@ -0,0 +1,202 @@
name: "solve-issue"
description: "TDD-driven issue resolution adapted for the workflow monorepo with bun + vitest"
roles:
planner:
description: "Analyzes issue and outputs a TDD test spec"
goal: "You are a planning agent. You analyze Gitea issues and produce a TDD test specification that downstream roles will implement and verify."
capabilities:
- issue-analysis
- planning
procedure: |
On first run (no previous steps):
1. Read the issue and all comments from Gitea using `tea issues <number> -r <owner/repo>`
2. Look for project conventions files (CLAUDE.md, CONTRIBUTING.md) in the repo
3. Assess whether the issue has enough information to produce a test spec
4. If insufficient info: comment on the issue via `echo "..." | tea comment <number> -r <owner/repo>` (skip if you already commented), then output $status=insufficient_info
5. If sufficient: produce a detailed TDD test spec in markdown covering all scenarios
On subsequent runs (bounced back by tester with fix_spec):
1. Read the tester's output from the previous step to understand what's wrong with the spec
2. Revise the test spec accordingly
After producing the test spec:
1. Store it via `uwf cas put-text "<markdown content>"` and capture the returned hash
2. Put the hash in frontmatter.plan (required when $status=ready)
3. Set repoPath to the absolute path of the repository root
output: "Output a brief summary of the test spec. Set $status to ready (with plan hash and repoPath) or insufficient_info."
frontmatter:
oneOf:
- properties:
$status: { const: "ready" }
plan: { type: string }
repoPath: { type: string }
required: [$status, plan, repoPath]
- properties:
$status: { const: "insufficient_info" }
required: [$status]
developer:
description: "TDD implementation per test spec"
goal: "You are a developer agent. You implement code changes following TDD — write tests first, then implementation."
capabilities:
- coding
procedure: |
IMPORTANT: Always work in a git worktree, NEVER modify the main working directory directly.
The repo path and other details are provided in your task prompt.
Before starting any work, set up an isolated worktree:
1. cd into the repo path provided in your task prompt
2. `git fetch origin` to get latest refs
3. First time (no existing branch):
- `git worktree add .worktrees/fix/<issue-number>-<short-slug> -b fix/<issue-number>-<short-slug> origin/main`
- `cd .worktrees/fix/<issue-number>-<short-slug> && bun install`
4. If bounced back from reviewer or tester (branch already exists):
- cd into the existing worktree under `.worktrees/fix/<issue-number>-<short-slug>`
- `git fetch origin && git rebase origin/main`
5. ALL subsequent work must happen inside the worktree directory.
Then implement TDD:
6. Read the test spec from CAS: `uwf cas get <plan hash>` (find the hash from the planner's output in your task prompt)
7. If bounced back from reviewer or tester: read the previous role's feedback in your task prompt
8. Write tests first based on the spec (use vitest)
9. Implement the code to make tests pass
10. Ensure `bun run build` passes with no errors
11. Run `bun test` to verify all tests pass
If you cannot complete the implementation (e.g. the issue is too complex, blocked by external factors,
or repeated attempts fail), set $status=failed with a reason.
output: "List all files changed and provide a summary. Set $status to done (with branch/worktree), or failed (with reason)."
frontmatter:
oneOf:
- properties:
$status: { const: "done" }
branch: { type: string }
worktree: { type: string }
required: [$status, branch, worktree]
- properties:
$status: { const: "failed" }
reason: { type: string }
required: [$status, reason]
reviewer:
description: "Code standards compliance check"
goal: "You are a code reviewer. You verify code standards compliance — NOT functionality (that's the tester's job)."
capabilities:
- code-review
- static-analysis
procedure: |
The worktree path is provided in your task prompt. cd into it first.
Before reviewing, verify the git branch:
1. Run `git branch --show-current` — confirm the branch name references the issue number being worked on
2. If the branch doesn't correspond to the issue, flag it in your output and reject
Then perform code review:
Hard checks (must all pass):
3. `bun run build` — no build errors
4. `bunx biome check` — no lint violations
5. TypeScript strict mode — no type errors
Soft checks (review against project conventions from CLAUDE.md):
- Functional-first: functions + types, no classes (except for errors or third-party requirements)
- Named exports only, no default exports
- No optional properties (use `T | null` instead of `?:`)
- Folder module discipline: index.ts only re-exports, types in types.ts
- Crockford Base32 log tags (8-char, unique per call site)
- No `console.log` in production code (use createLogger from @uncaged/workflow-util)
- No dynamic imports in production code
Only review standards compliance. Do NOT test functionality.
If rejecting, you MUST explain the specific reason in your output.
output: "Explain your decision with specific file/line references. Set $status to approved (with branch/worktree) or rejected (with comments)."
frontmatter:
oneOf:
- properties:
$status: { const: "approved" }
branch: { type: string }
worktree: { type: string }
required: [$status, branch, worktree]
- properties:
$status: { const: "rejected" }
comments: { type: string }
worktree: { type: string }
required: [$status, comments, worktree]
tester:
description: "Functional correctness verification"
goal: "You are a tester agent. You verify that the implementation correctly satisfies every scenario in the test spec."
capabilities:
- testing
procedure: |
The worktree path is provided in your task prompt. cd into it first.
1. Run `bun test` for automated test verification
2. Read the test spec from CAS: `uwf cas get <plan hash>` (find the hash from the planner step in the thread history)
3. Verify each scenario in the spec is covered and passing
4. Determine outcome:
- passed: all scenarios verified, tests pass
- fix_code: tests fail or implementation doesn't match spec → send back to developer
- fix_spec: the spec itself is wrong or incomplete → send back to planner
output: "Report test results per scenario. Set $status to passed (with branch/worktree), fix_code (with report), or fix_spec (with report)."
frontmatter:
oneOf:
- properties:
$status: { const: "passed" }
branch: { type: string }
worktree: { type: string }
required: [$status, branch, worktree]
- properties:
$status: { const: "fix_code" }
report: { type: string }
required: [$status, report]
- properties:
$status: { const: "fix_spec" }
report: { type: string }
required: [$status, report]
committer:
description: "Commits and creates PR"
goal: "You are a committer agent. You create a clean commit and push a PR linking the original issue."
capabilities: []
procedure: |
The worktree path, branch name, and repo info are provided in your task prompt.
cd into the worktree first.
Note: You inherit the developer's worktree and branch. Do NOT create a new branch.
1. Stage all changes: `git add -A`
2. Commit with a descriptive message referencing the issue: `git commit -m "type: description\n\nFixes #N"`
3. Push the branch: `git push -u origin <branch-name>`
- If push hook fails: capture the error log in your output, mark hook_failed
4. On push success: create a PR via `tea pr create --repo <owner/repo> --title "..." --description "..."`
- Extract owner/repo from: `git remote get-url origin | sed 's/.*[:/]\([^/]*\/[^.]*\).*/\1/'`
- PR description must include: What / Why / Changes / Ref sections, with `Fixes #N` in Ref
- On tea failure: capture stderr/stdout, include PR details for manual creation, mark hook_failed
5. After PR creation, clean up the worktree:
- cd to the repo root (parent of .worktrees)
- `git worktree remove <worktree-path>`
output: "Include PR URL on success or error log on failure. Set $status to committed (with prUrl) or hook_failed (with error)."
frontmatter:
oneOf:
- properties:
$status: { const: "committed" }
prUrl: { type: string }
required: [$status, prUrl]
- properties:
$status: { const: "hook_failed" }
error: { type: string }
required: [$status, error]
graph:
$START:
_: { role: "planner", prompt: "Analyze the issue and produce an implementation plan." }
planner:
insufficient_info: { role: "$END", prompt: "Insufficient information to proceed; end the workflow." }
ready: { role: "developer", prompt: "Implement the TDD test spec (CAS hash: {{{plan}}}) in repo {{{repoPath}}}." }
developer:
done: { role: "reviewer", prompt: "Review branch {{{branch}}} at {{{worktree}}} for code standards compliance." }
failed: { role: "$END", prompt: "Developer failed: {{{reason}}}. Ending workflow." }
reviewer:
rejected: { role: "developer", prompt: "Reviewer rejected: {{{comments}}}. Fix the issues in repo {{{worktree}}}." }
approved: { role: "tester", prompt: "Review passed. Run tests on branch {{{branch}}} at {{{worktree}}}." }
tester:
fix_code: { role: "developer", prompt: "Tests found code issues: {{{report}}}. Fix and re-submit." }
fix_spec: { role: "planner", prompt: "Tests found spec issues: {{{report}}}. Revise the test spec." }
passed: { role: "committer", prompt: "All tests passed. Commit and push branch {{{branch}}} from {{{worktree}}}." }
committer:
hook_failed: { role: "developer", prompt: "Push hook failed: {{{error}}}. Fix and re-submit." }
committed: { role: "$END", prompt: "PR created: {{{prUrl}}}. Workflow complete." }