refactor: rename status to $status, default to _ when absent

- evaluate() reads $status instead of status, defaults to _ when missing
- Update all YAML examples and .workflows to use $status
- Update cli-workflow resolveEvaluateArgs to use $status
- 10 moderator tests pass including new default _ test
- Single-exit roles no longer need to declare status field

Phase 1 of #499 (closes #500)
This commit is contained in:
2026-05-25 06:22:53 +00:00
parent 298b944169
commit 7a19ceca89
8 changed files with 64 additions and 46 deletions
@@ -81,7 +81,7 @@ describe("solve-issue workflow: tea pr create worktree fix", () => {
expect(workflow.roles.committer?.frontmatter).toBeDefined();
});
test("committer frontmatter schema should require status field", async () => {
test("committer frontmatter schema should require $status field", async () => {
const yamlContent = await readFile(workflowPath, "utf-8");
// Parse as any to access the raw YAML structure (frontmatter is inline JSON Schema in YAML)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -90,8 +90,8 @@ describe("solve-issue workflow: tea pr create worktree fix", () => {
const frontmatter = workflow.roles.committer?.frontmatter;
expect(frontmatter).toBeDefined();
expect(frontmatter?.type).toBe("object");
expect(frontmatter?.properties?.status).toBeDefined();
expect(frontmatter?.properties?.status?.enum).toContain("committed");
expect(frontmatter?.required).toContain("status");
expect(frontmatter?.properties?.["$status"]).toBeDefined();
expect(frontmatter?.properties?.["$status"]?.enum).toContain("committed");
expect(frontmatter?.required).toContain("$status");
});
});
+5 -4
View File
@@ -669,14 +669,16 @@ function formatThreadReadMarkdown(options: {
return parts.join("\n\n---\n\n");
}
type EvaluateLastOutput = Record<string, unknown> & { status: string };
type EvaluateLastOutput = Record<string, unknown>;
const STATUS_KEY = "$status";
function resolveEvaluateArgs(
uwf: UwfStore,
chain: ChainState,
): { lastRole: string; lastOutput: EvaluateLastOutput } {
if (chain.headIsStart) {
return { lastRole: START_ROLE, lastOutput: { status: "_" } };
return { lastRole: START_ROLE, lastOutput: { [STATUS_KEY]: "_" } };
}
const lastStep = chain.stepsNewestFirst[0];
@@ -689,11 +691,10 @@ function resolveEvaluateArgs(
typeof raw === "object" && raw !== null && !Array.isArray(raw)
? (raw as Record<string, unknown>)
: {};
const status = typeof base.status === "string" ? base.status : "_";
return {
lastRole: lastStep.role,
lastOutput: { ...base, status },
lastOutput: base,
};
}