From 174df68368c789aadd6bd9a3503d5fc7a82e7d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Wed, 29 Apr 2026 14:18:12 +0000 Subject: [PATCH] refactor: use @uncaged/nerve-role-committer package, delete _shared/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - develop-sense/develop-workflow committer → re-export from package - solve-issue committer → uses decorateRole chain (custom prompt stays) - Delete _shared/workspace-committer.ts and _shared/ directory RFC-004 Phase 1 complete --- package.json | 8 ++- pnpm-lock.yaml | 4 ++ workflows/_shared/workspace-committer.ts | 65 ------------------- workflows/develop-sense/roles/committer.ts | 4 +- workflows/develop-workflow/roles/committer.ts | 4 +- .../solve-issue/roles/committer/index.ts | 28 ++------ 6 files changed, 20 insertions(+), 93 deletions(-) delete mode 100644 workflows/_shared/workspace-committer.ts diff --git a/package.json b/package.json index ff09808..a452eb1 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "@uncaged/nerve-daemon": "link:../repos/nerve/packages/daemon", "@uncaged/nerve-workflow-utils": "link:../repos/nerve/packages/workflow-utils", "drizzle-orm": "latest", - "zod": "^4.3.6" + "zod": "^4.3.6", + "@uncaged/nerve-role-committer": "link:../repos/nerve/packages/role-committer" }, "devDependencies": { "drizzle-kit": "latest" @@ -27,7 +28,8 @@ "@uncaged/nerve-adapter-hermes": "link:../repos/nerve/packages/adapter-hermes", "@uncaged/nerve-daemon": "link:../repos/nerve/packages/daemon", "@uncaged/nerve-core": "link:../repos/nerve/packages/core", - "@uncaged/nerve-workflow-utils": "link:../repos/nerve/packages/workflow-utils" + "@uncaged/nerve-workflow-utils": "link:../repos/nerve/packages/workflow-utils", + "@uncaged/nerve-role-committer": "link:../repos/nerve/packages/role-committer" } } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62f66df..68c1cbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ overrides: '@uncaged/nerve-daemon': link:../repos/nerve/packages/daemon '@uncaged/nerve-core': link:../repos/nerve/packages/core '@uncaged/nerve-workflow-utils': link:../repos/nerve/packages/workflow-utils + '@uncaged/nerve-role-committer': link:../repos/nerve/packages/role-committer importers: @@ -27,6 +28,9 @@ importers: '@uncaged/nerve-daemon': specifier: link:../repos/nerve/packages/daemon version: link:../repos/nerve/packages/daemon + '@uncaged/nerve-role-committer': + specifier: link:../repos/nerve/packages/role-committer + version: link:../repos/nerve/packages/role-committer '@uncaged/nerve-workflow-utils': specifier: link:../repos/nerve/packages/workflow-utils version: link:../repos/nerve/packages/workflow-utils diff --git a/workflows/_shared/workspace-committer.ts b/workflows/_shared/workspace-committer.ts deleted file mode 100644 index 94ca540..0000000 --- a/workflows/_shared/workspace-committer.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { AgentFn, Role, RoleResult, StartStep } from "@uncaged/nerve-core"; -import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils"; -import { createRole, isDryRun } from "@uncaged/nerve-workflow-utils"; -import { z } from "zod"; - -export const committerMetaSchema = z.object({ - committed: z - .boolean() - .describe("true if branch created, changes committed, and pushed successfully"), -}); -export type CommitterMeta = z.infer; - -function workspaceCommitterPrompt(threadId: string): string { - return `You are the committer agent. The coder finished with a passing build; your job is to branch, commit, and push. - -1. Read the workflow thread: \`nerve thread show ${threadId}\` — understand what was planned, coded, and reviewed. -2. Run \`git status\`. If nothing to commit, set committed=false. -3. Create a feature branch: infer a good \`fix/\` or \`feat/\` name from the thread context. -4. \`git add -A\` -5. Write a conventional commit message based on the thread context. -6. \`git commit -m ""\` — do NOT pass \`--author\`, use repo git config. -7. \`git push -u origin \` - -**committed=true** only if branch was created, commit succeeded, and **push** succeeded. - -End your reply with a JSON line: -\`\`\`json -{ "committed": true } -\`\`\` -or -\`\`\`json -{ "committed": false } -\`\`\``; -} - -export function createWorkspaceCommitterRole( - adapter: AgentFn, - extract: LlmExtractorConfig, -): Role { - const innerRole = createRole( - adapter, - async (start: StartStep) => workspaceCommitterPrompt(start.meta.threadId), - committerMetaSchema, - extract, - ); - - return async (start, _messages): Promise> => { - if (isDryRun(start)) { - return { - content: "[dry-run] committer skipped (no git branch/commit/push)", - meta: { committed: true }, - }; - } - - try { - return await innerRole(start, _messages); - } catch (e) { - const msg = e instanceof Error ? e.message : String(e); - return { - content: `committer failed: ${msg}`, - meta: { committed: false }, - }; - } - }; -} diff --git a/workflows/develop-sense/roles/committer.ts b/workflows/develop-sense/roles/committer.ts index c303dba..3b21db1 100644 --- a/workflows/develop-sense/roles/committer.ts +++ b/workflows/develop-sense/roles/committer.ts @@ -1,5 +1,5 @@ export { - createWorkspaceCommitterRole, + createCommitterRole as createWorkspaceCommitterRole, committerMetaSchema, type CommitterMeta, -} from "../../_shared/workspace-committer.js"; +} from "@uncaged/nerve-role-committer"; diff --git a/workflows/develop-workflow/roles/committer.ts b/workflows/develop-workflow/roles/committer.ts index c303dba..3b21db1 100644 --- a/workflows/develop-workflow/roles/committer.ts +++ b/workflows/develop-workflow/roles/committer.ts @@ -1,5 +1,5 @@ export { - createWorkspaceCommitterRole, + createCommitterRole as createWorkspaceCommitterRole, committerMetaSchema, type CommitterMeta, -} from "../../_shared/workspace-committer.js"; +} from "@uncaged/nerve-role-committer"; diff --git a/workflows/solve-issue/roles/committer/index.ts b/workflows/solve-issue/roles/committer/index.ts index fd0ecb9..4f70a9a 100644 --- a/workflows/solve-issue/roles/committer/index.ts +++ b/workflows/solve-issue/roles/committer/index.ts @@ -1,6 +1,6 @@ -import type { AgentFn, Role, RoleResult, StartStep, WorkflowMessage } from "@uncaged/nerve-core"; +import type { AgentFn, Role, StartStep } from "@uncaged/nerve-core"; import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils"; -import { createRole, isDryRun } from "@uncaged/nerve-workflow-utils"; +import { createRole, decorateRole, withDryRun, onFail } from "@uncaged/nerve-workflow-utils"; import { z } from "zod"; import { committerPrompt } from "./prompt.js"; @@ -16,29 +16,15 @@ export function createCommitterRole( adapter: AgentFn, extract: LlmExtractorConfig, ): Role { - const innerRole = createRole( + const inner = createRole( adapter, async (start: StartStep) => committerPrompt({ threadId: start.meta.threadId }), committerMetaSchema, extract, ); - return async (start: StartStep, messages: WorkflowMessage[]): Promise> => { - if (isDryRun(start)) { - return { - content: "[dry-run] committer skipped (no git branch/commit/push)", - meta: { committed: true }, - }; - } - - try { - return await innerRole(start, messages); - } catch (e) { - const msg = e instanceof Error ? e.message : String(e); - return { - content: `committer failed: ${msg}`, - meta: { committed: false }, - }; - } - }; + return decorateRole(inner, [ + withDryRun({ label: "committer", meta: { committed: true } as CommitterMeta }), + onFail({ label: "committer", meta: { committed: false } as CommitterMeta }), + ]) as Role; } -- 2.43.0