From 02f7f0b70828ee1f94ead156fef6c80c26f57efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 06:04:45 +0000 Subject: [PATCH] =?UTF-8?q?refactor!:=20rename=20RoleDefinition.meta=20?= =?UTF-8?q?=E2=86=92=20frontmatter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: All workflow YAML files must use 'frontmatter' instead of 'meta'. - workflow-protocol: RoleDefinition.meta → frontmatter, schema updated - cli-workflow: validate.ts, workflow.ts — resolveMetaRef → resolveFrontmatterRef - workflow-agent-kit: run.ts — metaSchema → frontmatterSchema - All YAML files updated (examples/, .workflows/) Fixes #374 --- .workflows/solve-issue.yaml | 10 ++++----- examples/analyze-topic.yaml | 2 +- examples/solve-issue.yaml | 6 +++--- .../cli-workflow/src/commands/workflow.ts | 21 +++++++++++++------ packages/cli-workflow/src/validate.ts | 6 +++--- packages/workflow-agent-kit/src/run.ts | 13 ++++++++---- packages/workflow-protocol/src/schemas.ts | 4 ++-- packages/workflow-protocol/src/types.ts | 2 +- 8 files changed, 39 insertions(+), 25 deletions(-) diff --git a/.workflows/solve-issue.yaml b/.workflows/solve-issue.yaml index aa09753..fddb1e1 100644 --- a/.workflows/solve-issue.yaml +++ b/.workflows/solve-issue.yaml @@ -23,7 +23,7 @@ roles: 1. Store it via `uwf cas put ""` and capture the returned hash 2. Put the hash in meta.plan (required when status=ready) output: "Output a brief summary of the test spec. Frontmatter must include: status (ready or insufficient_info) and plan (CAS hash of the test spec, required when status=ready)." - meta: + frontmatter: type: object properties: status: @@ -45,7 +45,7 @@ roles: 5. Ensure `bun run build` passes with no errors 6. Run `bun test` to verify all tests pass output: "List all files changed and provide a summary. Frontmatter must include: status (done or failed)." - meta: + frontmatter: type: object properties: status: @@ -75,7 +75,7 @@ roles: 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. Frontmatter must include: approved (true or false)." - meta: + frontmatter: type: object properties: approved: @@ -95,7 +95,7 @@ roles: - 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. Frontmatter must include: status (passed, fix_code, or fix_spec)." - meta: + frontmatter: type: object properties: status: @@ -115,7 +115,7 @@ roles: 4. On push success: create a PR via `tea pr create --title "..." --description "..."` - PR description must follow the project template: What / Why / Changes / Ref sections, with `Fixes #N` in Ref output: "Include PR URL on success or error log on failure. Frontmatter must include: success (true or false)." - meta: + frontmatter: type: object properties: success: diff --git a/examples/analyze-topic.yaml b/examples/analyze-topic.yaml index 585b32b..9ddb143 100644 --- a/examples/analyze-topic.yaml +++ b/examples/analyze-topic.yaml @@ -19,7 +19,7 @@ roles: output: | Provide your analysis as markdown under the frontmatter. The frontmatter must include your structured findings. - meta: + frontmatter: type: object properties: thesis: diff --git a/examples/solve-issue.yaml b/examples/solve-issue.yaml index 34302ac..299b572 100644 --- a/examples/solve-issue.yaml +++ b/examples/solve-issue.yaml @@ -9,7 +9,7 @@ roles: - planning procedure: "Analyze the issue and create a detailed, actionable implementation plan." output: "Output the plan summary and list of concrete steps." - meta: + frontmatter: type: object properties: plan: @@ -28,7 +28,7 @@ roles: - testing procedure: "Implement the plan. Write code, tests, and ensure existing tests pass." output: "List all files changed and provide a summary of the implementation." - meta: + frontmatter: type: object properties: filesChanged: @@ -46,7 +46,7 @@ roles: - static-analysis procedure: "Review the implementation against the plan. Check for bugs, edge cases, and style." output: "Approve or reject with detailed comments explaining your decision." - meta: + frontmatter: type: object properties: approved: diff --git a/packages/cli-workflow/src/commands/workflow.ts b/packages/cli-workflow/src/commands/workflow.ts index 2618481..8bc1f84 100644 --- a/packages/cli-workflow/src/commands/workflow.ts +++ b/packages/cli-workflow/src/commands/workflow.ts @@ -46,11 +46,16 @@ function isJsonSchema(value: unknown): value is JSONSchema { return typeof value === "object" && value !== null && !Array.isArray(value); } -async function resolveMetaRef(uwf: UwfStore, roleName: string, meta: unknown): Promise { - if (!isJsonSchema(meta)) { - fail(`role "${roleName}": meta must be a JSON Schema object`); +async function resolveFrontmatterRef( + uwf: UwfStore, + roleName: string, + frontmatter: unknown, +): Promise { + if (!isJsonSchema(frontmatter)) { + fail(`role "${roleName}": frontmatter must be a JSON Schema object`); } - const schema: JSONSchema = meta.title === undefined ? { ...meta, title: roleName } : meta; + const schema: JSONSchema = + frontmatter.title === undefined ? { ...frontmatter, title: roleName } : frontmatter; return putSchema(uwf.store, schema); } @@ -60,14 +65,18 @@ export async function materializeWorkflowPayload( ): Promise { const roles: Record = {}; for (const [roleName, role] of Object.entries(raw.roles)) { - const meta = await resolveMetaRef(uwf, `${raw.name}.${roleName}`, role.meta); + const frontmatter = await resolveFrontmatterRef( + uwf, + `${raw.name}.${roleName}`, + role.frontmatter, + ); roles[roleName] = { description: role.description, goal: role.goal, capabilities: role.capabilities, procedure: role.procedure, output: role.output, - meta, + frontmatter, }; } return { diff --git a/packages/cli-workflow/src/validate.ts b/packages/cli-workflow/src/validate.ts index a7a3edb..5a3a5cc 100644 --- a/packages/cli-workflow/src/validate.ts +++ b/packages/cli-workflow/src/validate.ts @@ -15,8 +15,8 @@ function isRoleDefinition(value: unknown): boolean { if (!isRecord(value)) { return false; } - const meta = value.meta; - const metaOk = isRecord(meta) && typeof meta.type === "string"; + const frontmatter = value.frontmatter; + const frontmatterOk = isRecord(frontmatter) && typeof frontmatter.type === "string"; const capabilities = value.capabilities; const capabilitiesOk = Array.isArray(capabilities) && capabilities.every((c) => typeof c === "string"); @@ -26,7 +26,7 @@ function isRoleDefinition(value: unknown): boolean { capabilitiesOk && typeof value.procedure === "string" && typeof value.output === "string" && - metaOk + frontmatterOk ); } diff --git a/packages/workflow-agent-kit/src/run.ts b/packages/workflow-agent-kit/src/run.ts index 23d2bad..f6ba1ab 100644 --- a/packages/workflow-agent-kit/src/run.ts +++ b/packages/workflow-agent-kit/src/run.ts @@ -130,13 +130,18 @@ export function createAgent(options: AgentOptions): () => Promise { fail(`unknown role: ${role}`); } - const metaSchema = getSchema(ctx.meta.store, roleDef.meta); - if (metaSchema !== null) { - ctx.outputFormatInstruction = buildOutputFormatInstruction(metaSchema); + const frontmatterSchema = getSchema(ctx.meta.store, roleDef.frontmatter); + if (frontmatterSchema !== null) { + ctx.outputFormatInstruction = buildOutputFormatInstruction(frontmatterSchema); } const agentResult = await runAgent(options, ctx); - const outputHash = await extractOutput(agentResult.output, roleDef.meta, storageRoot, ctx); + const outputHash = await extractOutput( + agentResult.output, + roleDef.frontmatter, + storageRoot, + ctx, + ); const stepHash = await persistStep({ ctx, outputHash, diff --git a/packages/workflow-protocol/src/schemas.ts b/packages/workflow-protocol/src/schemas.ts index fd85793..cb28471 100644 --- a/packages/workflow-protocol/src/schemas.ts +++ b/packages/workflow-protocol/src/schemas.ts @@ -2,14 +2,14 @@ import type { JSONSchema } from "@uncaged/json-cas"; const ROLE_DEFINITION: JSONSchema = { type: "object", - required: ["description", "goal", "capabilities", "procedure", "output", "meta"], + required: ["description", "goal", "capabilities", "procedure", "output", "frontmatter"], properties: { description: { type: "string" }, goal: { type: "string" }, capabilities: { type: "array", items: { type: "string" } }, procedure: { type: "string" }, output: { type: "string" }, - meta: { type: "string", format: "cas_ref" }, + frontmatter: { type: "string", format: "cas_ref" }, }, additionalProperties: false, }; diff --git a/packages/workflow-protocol/src/types.ts b/packages/workflow-protocol/src/types.ts index 4f063eb..8960f0c 100644 --- a/packages/workflow-protocol/src/types.ts +++ b/packages/workflow-protocol/src/types.ts @@ -22,7 +22,7 @@ export type RoleDefinition = { capabilities: string[]; procedure: string; output: string; - meta: CasRef; + frontmatter: CasRef; }; export type Transition = {