Compare commits
No commits in common. "f6e29a5cae57b24cdf28f2db454e0d8b610467ae" and "85fac3158d84809a66ce013477bf90e54d851436" have entirely different histories.
f6e29a5cae
...
85fac3158d
@ -1,109 +0,0 @@
|
||||
import type { Role, RoleResult, StartStep } from "@uncaged/nerve-core";
|
||||
import { hermesAdapter } from "@uncaged/nerve-adapter-hermes";
|
||||
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<typeof committerMetaSchema>;
|
||||
|
||||
export type BuildWorkspaceCommitterDeps = {
|
||||
extract: LlmExtractorConfig;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
conventionalCommitScopeHint: string;
|
||||
branchCheckoutExample: string;
|
||||
};
|
||||
|
||||
function workspaceCommitterPrompt({
|
||||
threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
conventionalCommitScopeHint,
|
||||
branchCheckoutExample,
|
||||
}: {
|
||||
threadId: string;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
conventionalCommitScopeHint: string;
|
||||
branchCheckoutExample: string;
|
||||
}): string {
|
||||
return `You are the **committer** agent (Hermes) for the **${workflowName}** workflow. The coder finished with a passing build; you branch, commit, and push workspace changes.
|
||||
|
||||
## Context
|
||||
|
||||
1. Read the workflow thread: \`nerve thread show ${threadId}\`
|
||||
2. Your git repository root is: \`${nerveRoot}\` — \`cd\` there for all git commands.
|
||||
|
||||
## Steps (in order)
|
||||
|
||||
1. Run \`git status\`. There should be uncommitted changes from the coder. If there is nothing to commit, set **committed** to false and explain.
|
||||
2. Create a short-lived branch (do not commit directly on the default branch if it would mix unrelated work):
|
||||
- Prefer \`fix/<short-slug>\` or \`feat/<short-slug>\` with a lowercase hyphenated slug from the thread (planner/coder context).
|
||||
- Example: \`${branchCheckoutExample}\`
|
||||
3. \`git add -A\`
|
||||
4. Write a **conventional commit** message summarizing what changed and why (scope may be \`${conventionalCommitScopeHint}\` or similar).
|
||||
5. \`git commit -m "<message>"\` (use multiple \`-m\` if you need a body).
|
||||
6. \`git push -u origin <branch-name>\`
|
||||
|
||||
**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 buildWorkspaceCommitterRole({
|
||||
extract,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
conventionalCommitScopeHint,
|
||||
branchCheckoutExample,
|
||||
}: BuildWorkspaceCommitterDeps): Role<CommitterMeta> {
|
||||
const innerRole = createRole(
|
||||
hermesAdapter,
|
||||
async (start: StartStep) =>
|
||||
workspaceCommitterPrompt({
|
||||
threadId: start.meta.threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
conventionalCommitScopeHint,
|
||||
branchCheckoutExample,
|
||||
}),
|
||||
committerMetaSchema,
|
||||
extract,
|
||||
);
|
||||
|
||||
return async (start, _messages): Promise<RoleResult<CommitterMeta>> => {
|
||||
if (isDryRun(start)) {
|
||||
return {
|
||||
content: "[dry-run] committer skipped (no git branch/commit/push)",
|
||||
meta: { committed: true },
|
||||
};
|
||||
}
|
||||
|
||||
const innerStart = {
|
||||
...start,
|
||||
meta: { ...start.meta, workdir: nerveRoot },
|
||||
} as StartStep;
|
||||
|
||||
try {
|
||||
return await innerRole(innerStart, _messages);
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : String(e);
|
||||
return {
|
||||
content: `committer failed: ${msg}`,
|
||||
meta: { committed: false },
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -63,8 +63,6 @@ export function buildDevelopSenseWorkflow({
|
||||
extract,
|
||||
nerveRoot: cwd,
|
||||
workflowName: "develop-sense",
|
||||
conventionalCommitScopeHint: "sense",
|
||||
branchCheckoutExample: "git checkout -b fix/sense-export-path",
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,62 @@
|
||||
export {
|
||||
buildWorkspaceCommitterRole,
|
||||
committerMetaSchema,
|
||||
type BuildWorkspaceCommitterDeps,
|
||||
type CommitterMeta,
|
||||
} from "../../../_shared/workspace-committer.js";
|
||||
import type { Role, RoleResult, StartStep } from "@uncaged/nerve-core";
|
||||
import { hermesAdapter } from "@uncaged/nerve-adapter-hermes";
|
||||
import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils";
|
||||
import { createRole, isDryRun } from "@uncaged/nerve-workflow-utils";
|
||||
import { z } from "zod";
|
||||
|
||||
import { workspaceCommitterPrompt } from "./prompt.js";
|
||||
|
||||
export const committerMetaSchema = z.object({
|
||||
committed: z
|
||||
.boolean()
|
||||
.describe("true if branch created, changes committed, and pushed successfully"),
|
||||
});
|
||||
export type CommitterMeta = z.infer<typeof committerMetaSchema>;
|
||||
|
||||
export type BuildWorkspaceCommitterDeps = {
|
||||
extract: LlmExtractorConfig;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
};
|
||||
|
||||
export function buildWorkspaceCommitterRole({
|
||||
extract,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}: BuildWorkspaceCommitterDeps): Role<CommitterMeta> {
|
||||
const innerRole = createRole(
|
||||
hermesAdapter,
|
||||
async (start: StartStep) =>
|
||||
workspaceCommitterPrompt({
|
||||
threadId: start.meta.threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}),
|
||||
committerMetaSchema,
|
||||
extract,
|
||||
);
|
||||
|
||||
return async (start, _messages): Promise<RoleResult<CommitterMeta>> => {
|
||||
if (isDryRun(start)) {
|
||||
return {
|
||||
content: "[dry-run] committer skipped (no git branch/commit/push)",
|
||||
meta: { committed: true },
|
||||
};
|
||||
}
|
||||
|
||||
const innerStart = {
|
||||
...start,
|
||||
meta: { ...start.meta, workdir: nerveRoot },
|
||||
} as StartStep;
|
||||
|
||||
try {
|
||||
return await innerRole(innerStart, _messages);
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : String(e);
|
||||
return {
|
||||
content: `committer failed: ${msg}`,
|
||||
meta: { committed: false },
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
38
workflows/develop-sense/roles/committer/prompt.ts
Normal file
38
workflows/develop-sense/roles/committer/prompt.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export function workspaceCommitterPrompt({
|
||||
threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}: {
|
||||
threadId: string;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
}): string {
|
||||
return `You are the **committer** agent (Hermes) for the **${workflowName}** workflow. The coder finished with a passing build; you branch, commit, and push workspace changes.
|
||||
|
||||
## Context
|
||||
|
||||
1. Read the workflow thread: \`nerve thread show ${threadId}\`
|
||||
2. Your git repository root is: \`${nerveRoot}\` — \`cd\` there for all git commands.
|
||||
|
||||
## Steps (in order)
|
||||
|
||||
1. Run \`git status\`. There should be uncommitted changes from the coder. If there is nothing to commit, set **committed** to false and explain.
|
||||
2. Create a short-lived branch (do not commit directly on the default branch if it would mix unrelated work):
|
||||
- Prefer \`fix/<short-slug>\` or \`feat/<short-slug>\` with a lowercase hyphenated slug from the thread (planner/coder context).
|
||||
- Example: \`git checkout -b fix/sense-export-path\`
|
||||
3. \`git add -A\`
|
||||
4. Write a **conventional commit** message summarizing what changed and why (scope may be \`sense\` or similar).
|
||||
5. \`git commit -m "<message>"\` (use multiple \`-m\` if you need a body).
|
||||
6. \`git push -u origin <branch-name>\`
|
||||
|
||||
**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 }
|
||||
\`\`\``;
|
||||
}
|
||||
@ -10,5 +10,5 @@
|
||||
"declaration": false,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["./**/*.ts", "../_shared/**/*.ts"]
|
||||
"include": ["./**/*.ts"]
|
||||
}
|
||||
|
||||
@ -63,8 +63,6 @@ export function buildDevelopWorkflow({
|
||||
extract,
|
||||
nerveRoot,
|
||||
workflowName: "develop-workflow",
|
||||
conventionalCommitScopeHint: "workflow",
|
||||
branchCheckoutExample: "git checkout -b feat/workflow-new-step",
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,62 @@
|
||||
export {
|
||||
buildWorkspaceCommitterRole,
|
||||
committerMetaSchema,
|
||||
type BuildWorkspaceCommitterDeps,
|
||||
type CommitterMeta,
|
||||
} from "../../../_shared/workspace-committer.js";
|
||||
import type { Role, RoleResult, StartStep } from "@uncaged/nerve-core";
|
||||
import { hermesAdapter } from "@uncaged/nerve-adapter-hermes";
|
||||
import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils";
|
||||
import { createRole, isDryRun } from "@uncaged/nerve-workflow-utils";
|
||||
import { z } from "zod";
|
||||
|
||||
import { workspaceCommitterPrompt } from "./prompt.js";
|
||||
|
||||
export const committerMetaSchema = z.object({
|
||||
committed: z
|
||||
.boolean()
|
||||
.describe("true if branch created, changes committed, and pushed successfully"),
|
||||
});
|
||||
export type CommitterMeta = z.infer<typeof committerMetaSchema>;
|
||||
|
||||
export type BuildWorkspaceCommitterDeps = {
|
||||
extract: LlmExtractorConfig;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
};
|
||||
|
||||
export function buildWorkspaceCommitterRole({
|
||||
extract,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}: BuildWorkspaceCommitterDeps): Role<CommitterMeta> {
|
||||
const innerRole = createRole(
|
||||
hermesAdapter,
|
||||
async (start: StartStep) =>
|
||||
workspaceCommitterPrompt({
|
||||
threadId: start.meta.threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}),
|
||||
committerMetaSchema,
|
||||
extract,
|
||||
);
|
||||
|
||||
return async (start, _messages): Promise<RoleResult<CommitterMeta>> => {
|
||||
if (isDryRun(start)) {
|
||||
return {
|
||||
content: "[dry-run] committer skipped (no git branch/commit/push)",
|
||||
meta: { committed: true },
|
||||
};
|
||||
}
|
||||
|
||||
const innerStart = {
|
||||
...start,
|
||||
meta: { ...start.meta, workdir: nerveRoot },
|
||||
} as StartStep;
|
||||
|
||||
try {
|
||||
return await innerRole(innerStart, _messages);
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : String(e);
|
||||
return {
|
||||
content: `committer failed: ${msg}`,
|
||||
meta: { committed: false },
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
38
workflows/develop-workflow/roles/committer/prompt.ts
Normal file
38
workflows/develop-workflow/roles/committer/prompt.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export function workspaceCommitterPrompt({
|
||||
threadId,
|
||||
nerveRoot,
|
||||
workflowName,
|
||||
}: {
|
||||
threadId: string;
|
||||
nerveRoot: string;
|
||||
workflowName: string;
|
||||
}): string {
|
||||
return `You are the **committer** agent (Hermes) for the **${workflowName}** workflow. The coder finished with a passing build; you branch, commit, and push workspace changes.
|
||||
|
||||
## Context
|
||||
|
||||
1. Read the workflow thread: \`nerve thread show ${threadId}\`
|
||||
2. Your git repository root is: \`${nerveRoot}\` — \`cd\` there for all git commands.
|
||||
|
||||
## Steps (in order)
|
||||
|
||||
1. Run \`git status\`. There should be uncommitted changes from the coder. If there is nothing to commit, set **committed** to false and explain.
|
||||
2. Create a short-lived branch (do not commit directly on the default branch if it would mix unrelated work):
|
||||
- Prefer \`fix/<short-slug>\` or \`feat/<short-slug>\` with a lowercase hyphenated slug from the thread (planner/coder context).
|
||||
- Example: \`git checkout -b feat/workflow-new-step\`
|
||||
3. \`git add -A\`
|
||||
4. Write a **conventional commit** message summarizing what changed and why (scope may be \`workflow\` or similar).
|
||||
5. \`git commit -m "<message>"\` (use multiple \`-m\` if you need a body).
|
||||
6. \`git push -u origin <branch-name>\`
|
||||
|
||||
**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 }
|
||||
\`\`\``;
|
||||
}
|
||||
@ -9,5 +9,5 @@
|
||||
"noEmit": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["./**/*.ts", "../_shared/**/*.ts"]
|
||||
"include": ["./**/*.ts"]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user