refactor: rename RoleDefinition fields for clarity

- identity → goal
- prepare → capabilities (string[])
- execute → procedure
- report → output
- outputSchema → meta

Fixes #364
This commit is contained in:
2026-05-22 00:46:06 +00:00
parent fe035c065d
commit c60c310074
13 changed files with 187 additions and 129 deletions
@@ -1,54 +1,71 @@
import { describe, expect, test } from "vitest";
import type { RoleDefinition } from "@uncaged/workflow-protocol";
import { describe, expect, test } from "vitest";
import { buildRolePrompt } from "../src/build-role-prompt.js";
describe("buildRolePrompt", () => {
test("all fields present", () => {
const role: RoleDefinition = {
description: "A coder",
identity: "You are a senior developer.",
prepare: "Load cursor-agent skill.",
execute: "Implement the feature.",
report: "Summarize changes.",
outputSchema: "placeholder00000" as string,
goal: "You are a senior developer.",
capabilities: ["cursor-agent", "file-edit"],
procedure: "Implement the feature.",
output: "Summarize changes.",
meta: "placeholder00000" as string,
};
const result = buildRolePrompt(role);
expect(result).toContain("## Identity");
expect(result).toContain("## Goal");
expect(result).toContain("You are a senior developer.");
expect(result).toContain("## Prepare");
expect(result).toContain("Load cursor-agent skill.");
expect(result).toContain("## Execute");
expect(result).toContain("## Capabilities");
expect(result).toContain("- cursor-agent");
expect(result).toContain("- file-edit");
expect(result).toContain("## Procedure");
expect(result).toContain("Implement the feature.");
expect(result).toContain("## Report");
expect(result).toContain("## Output");
expect(result).toContain("Summarize changes.");
});
test("empty fields are omitted", () => {
const role: RoleDefinition = {
description: "A reviewer",
identity: "You are a code reviewer.",
prepare: "",
execute: "Review the PR diff carefully.",
report: "",
outputSchema: "placeholder00000" as string,
goal: "You are a code reviewer.",
capabilities: [],
procedure: "Review the PR diff carefully.",
output: "",
meta: "placeholder00000" as string,
};
const result = buildRolePrompt(role);
expect(result).toContain("## Identity");
expect(result).toContain("## Execute");
expect(result).not.toContain("## Prepare");
expect(result).not.toContain("## Report");
expect(result).toContain("## Goal");
expect(result).toContain("## Procedure");
expect(result).not.toContain("## Capabilities");
expect(result).not.toContain("## Output");
});
test("all empty returns empty string", () => {
const role: RoleDefinition = {
description: "Minimal",
identity: "",
prepare: "",
execute: "",
report: "",
outputSchema: "placeholder00000" as string,
goal: "",
capabilities: [],
procedure: "",
output: "",
meta: "placeholder00000" as string,
};
const result = buildRolePrompt(role);
expect(result).toBe("");
});
test("capabilities rendered as bullet list", () => {
const role: RoleDefinition = {
description: "Agent",
goal: "",
capabilities: ["search", "code", "browse"],
procedure: "",
output: "",
meta: "placeholder00000" as string,
};
const result = buildRolePrompt(role);
expect(result).toContain("## Capabilities");
expect(result).toContain("- search");
expect(result).toContain("- code");
expect(result).toContain("- browse");
});
});
@@ -3,26 +3,27 @@ import type { RoleDefinition } from "@uncaged/workflow-protocol";
/**
* Build the role prompt from a RoleDefinition.
*
* Assembles structured sections: Identity, Prepare, Execute, Report.
* Empty strings are omitted from the output.
* Assembles structured sections: Goal, Capabilities, Procedure, Output.
* Empty strings and empty arrays are omitted from the output.
*/
export function buildRolePrompt(role: RoleDefinition): string {
const sections: string[] = [];
if (role.identity !== "") {
sections.push(`## Identity\n\n${role.identity}`);
if (role.goal !== "") {
sections.push(`## Goal\n\n${role.goal}`);
}
if (role.prepare !== "") {
sections.push(`## Prepare\n\n${role.prepare}`);
if (role.capabilities.length > 0) {
const list = role.capabilities.map((c) => `- ${c}`).join("\n");
sections.push(`## Capabilities\n\n${list}`);
}
if (role.execute !== "") {
sections.push(`## Execute\n\n${role.execute}`);
if (role.procedure !== "") {
sections.push(`## Procedure\n\n${role.procedure}`);
}
if (role.report !== "") {
sections.push(`## Report\n\n${role.report}`);
if (role.output !== "") {
sections.push(`## Output\n\n${role.output}`);
}
return sections.join("\n\n");
+4 -4
View File
@@ -131,13 +131,13 @@ export function createAgent(options: AgentOptions): () => Promise<void> {
fail(`unknown role: ${role}`);
}
const outputSchema = getSchema(ctx.meta.store, roleDef.outputSchema);
if (outputSchema !== null) {
ctx.outputFormatInstruction = buildOutputFormatInstruction(outputSchema);
const metaSchema = getSchema(ctx.meta.store, roleDef.meta);
if (metaSchema !== null) {
ctx.outputFormatInstruction = buildOutputFormatInstruction(metaSchema);
}
const agentResult = await runAgent(options, ctx);
const outputHash = await extractOutput(agentResult.output, roleDef.outputSchema, storageRoot, ctx);
const outputHash = await extractOutput(agentResult.output, roleDef.meta, storageRoot, ctx);
const stepHash = await persistStep({
ctx,
outputHash,