feat(start-work): add auto_commit config option
Add start_work.auto_commit configuration option to allow users to disable the automatic commit step in the /start-work workflow. When auto_commit is false: - STEP 8: COMMIT ATOMIC UNIT is removed from orchestrator reminder - STEP 9: PROCEED TO NEXT TASK becomes STEP 8 Resolves #2197
This commit is contained in:
parent
518e3c5da7
commit
e2e3d110b7
@ -3837,6 +3837,19 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"start_work": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"auto_commit": {
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"auto_commit"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
"_migrations": {
|
"_migrations": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## OVERVIEW
|
## OVERVIEW
|
||||||
|
|
||||||
22 schema files composing `OhMyOpenCodeConfigSchema`. Zod v4 validation with `safeParse()`. All fields optional — omitted fields use plugin defaults.
|
7ZB|22 schema files composing `OhMyOpenCodeConfigSchema`. Zod v4 validation with `safeParse()`. All fields optional — omitted fields use plugin defaults.
|
||||||
|
|
||||||
## SCHEMA TREE
|
## SCHEMA TREE
|
||||||
|
|
||||||
@ -31,12 +31,15 @@ config/schema/
|
|||||||
├── background-task.ts # Concurrency limits per model/provider
|
├── background-task.ts # Concurrency limits per model/provider
|
||||||
├── babysitting.ts # Unstable agent monitoring
|
├── babysitting.ts # Unstable agent monitoring
|
||||||
├── dynamic-context-pruning.ts # Context pruning settings
|
├── dynamic-context-pruning.ts # Context pruning settings
|
||||||
|
├── start-work.ts # StartWorkConfigSchema (auto_commit)
|
||||||
|
└── internal/permission.ts # AgentPermissionSchema
|
||||||
|
├── start-work.ts # StartWorkConfigSchema (auto_commit)
|
||||||
└── internal/permission.ts # AgentPermissionSchema
|
└── internal/permission.ts # AgentPermissionSchema
|
||||||
```
|
```
|
||||||
|
|
||||||
## ROOT SCHEMA FIELDS (27)
|
## ROOT SCHEMA FIELDS (28)
|
||||||
|
|
||||||
`$schema`, `new_task_system_enabled`, `default_run_agent`, `disabled_mcps`, `disabled_agents`, `disabled_skills`, `disabled_hooks`, `disabled_commands`, `disabled_tools`, `hashline_edit`, `agents`, `categories`, `claude_code`, `sisyphus_agent`, `comment_checker`, `experimental`, `auto_update`, `skills`, `ralph_loop`, `background_task`, `notification`, `babysitting`, `git_master`, `browser_automation_engine`, `websearch`, `tmux`, `sisyphus`, `_migrations`
|
`$schema`, `new_task_system_enabled`, `default_run_agent`, `disabled_mcps`, `disabled_agents`, `disabled_skills`, `disabled_hooks`, `disabled_commands`, `disabled_tools`, `hashline_edit`, `agents`, `categories`, `claude_code`, `sisyphus_agent`, `comment_checker`, `experimental`, `auto_update`, `skills`, `ralph_loop`, `background_task`, `notification`, `babysitting`, `git_master`, `browser_automation_engine`, `websearch`, `tmux`, `sisyphus`, `start_work`, `_migrations`
|
||||||
|
|
||||||
## AGENT OVERRIDE FIELDS (21)
|
## AGENT OVERRIDE FIELDS (21)
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { SkillsConfigSchema } from "./skills"
|
|||||||
import { SisyphusConfigSchema } from "./sisyphus"
|
import { SisyphusConfigSchema } from "./sisyphus"
|
||||||
import { SisyphusAgentConfigSchema } from "./sisyphus-agent"
|
import { SisyphusAgentConfigSchema } from "./sisyphus-agent"
|
||||||
import { TmuxConfigSchema } from "./tmux"
|
import { TmuxConfigSchema } from "./tmux"
|
||||||
|
import { StartWorkConfigSchema } from "./start-work"
|
||||||
import { WebsearchConfigSchema } from "./websearch"
|
import { WebsearchConfigSchema } from "./websearch"
|
||||||
|
|
||||||
export const OhMyOpenCodeConfigSchema = z.object({
|
export const OhMyOpenCodeConfigSchema = z.object({
|
||||||
@ -60,6 +61,7 @@ export const OhMyOpenCodeConfigSchema = z.object({
|
|||||||
websearch: WebsearchConfigSchema.optional(),
|
websearch: WebsearchConfigSchema.optional(),
|
||||||
tmux: TmuxConfigSchema.optional(),
|
tmux: TmuxConfigSchema.optional(),
|
||||||
sisyphus: SisyphusConfigSchema.optional(),
|
sisyphus: SisyphusConfigSchema.optional(),
|
||||||
|
start_work: StartWorkConfigSchema.optional(),
|
||||||
/** Migration history to prevent re-applying migrations (e.g., model version upgrades) */
|
/** Migration history to prevent re-applying migrations (e.g., model version upgrades) */
|
||||||
_migrations: z.array(z.string()).optional(),
|
_migrations: z.array(z.string()).optional(),
|
||||||
})
|
})
|
||||||
|
|||||||
8
src/config/schema/start-work.ts
Normal file
8
src/config/schema/start-work.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
export const StartWorkConfigSchema = z.object({
|
||||||
|
/** Enable auto-commit after each atomic task completion (default: true) */
|
||||||
|
auto_commit: z.boolean().default(true),
|
||||||
|
})
|
||||||
|
|
||||||
|
export type StartWorkConfig = z.infer<typeof StartWorkConfigSchema>
|
||||||
@ -7,6 +7,7 @@ import type { AtlasHookOptions, SessionState } from "./types"
|
|||||||
export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) {
|
export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) {
|
||||||
const sessions = new Map<string, SessionState>()
|
const sessions = new Map<string, SessionState>()
|
||||||
const pendingFilePaths = new Map<string, string>()
|
const pendingFilePaths = new Map<string, string>()
|
||||||
|
const autoCommit = options?.autoCommit ?? true
|
||||||
|
|
||||||
function getState(sessionID: string): SessionState {
|
function getState(sessionID: string): SessionState {
|
||||||
let state = sessions.get(sessionID)
|
let state = sessions.get(sessionID)
|
||||||
@ -20,6 +21,6 @@ export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) {
|
|||||||
return {
|
return {
|
||||||
handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
|
handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
|
||||||
"tool.execute.before": createToolExecuteBeforeHandler({ ctx, pendingFilePaths }),
|
"tool.execute.before": createToolExecuteBeforeHandler({ ctx, pendingFilePaths }),
|
||||||
"tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths }),
|
"tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths, autoCommit }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,9 +14,9 @@ import type { ToolExecuteAfterInput, ToolExecuteAfterOutput } from "./types"
|
|||||||
export function createToolExecuteAfterHandler(input: {
|
export function createToolExecuteAfterHandler(input: {
|
||||||
ctx: PluginInput
|
ctx: PluginInput
|
||||||
pendingFilePaths: Map<string, string>
|
pendingFilePaths: Map<string, string>
|
||||||
}): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise<void> {
|
autoCommit: boolean
|
||||||
const { ctx, pendingFilePaths } = input
|
}): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise<void> {
|
||||||
|
const { ctx, pendingFilePaths, autoCommit } = input
|
||||||
return async (toolInput, toolOutput): Promise<void> => {
|
return async (toolInput, toolOutput): Promise<void> => {
|
||||||
// Guard against undefined output (e.g., from /review command - see issue #1035)
|
// Guard against undefined output (e.g., from /review command - see issue #1035)
|
||||||
if (!toolOutput) {
|
if (!toolOutput) {
|
||||||
@ -76,7 +76,7 @@ export function createToolExecuteAfterHandler(input: {
|
|||||||
// Preserve original subagent response - critical for debugging failed tasks
|
// Preserve original subagent response - critical for debugging failed tasks
|
||||||
const originalResponse = toolOutput.output
|
const originalResponse = toolOutput.output
|
||||||
|
|
||||||
toolOutput.output = `
|
toolOutput.output = `
|
||||||
## SUBAGENT WORK COMPLETED
|
## SUBAGENT WORK COMPLETED
|
||||||
|
|
||||||
${fileChanges}
|
${fileChanges}
|
||||||
@ -88,9 +88,8 @@ ${fileChanges}
|
|||||||
${originalResponse}
|
${originalResponse}
|
||||||
|
|
||||||
<system-reminder>
|
<system-reminder>
|
||||||
${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId)}
|
${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId, autoCommit)}
|
||||||
</system-reminder>`
|
</system-reminder>`
|
||||||
|
|
||||||
log(`[${HOOK_NAME}] Output transformed for orchestrator mode (boulder)`, {
|
log(`[${HOOK_NAME}] Output transformed for orchestrator mode (boulder)`, {
|
||||||
plan: boulderState.plan_name,
|
plan: boulderState.plan_name,
|
||||||
progress: `${progress.completed}/${progress.total}`,
|
progress: `${progress.completed}/${progress.total}`,
|
||||||
|
|||||||
@ -8,6 +8,8 @@ export interface AtlasHookOptions {
|
|||||||
backgroundManager?: BackgroundManager
|
backgroundManager?: BackgroundManager
|
||||||
isContinuationStopped?: (sessionID: string) => boolean
|
isContinuationStopped?: (sessionID: string) => boolean
|
||||||
agentOverrides?: AgentOverrides
|
agentOverrides?: AgentOverrides
|
||||||
|
/** Enable auto-commit after each atomic task completion (default: true) */
|
||||||
|
autoCommit?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ToolExecuteAfterInput {
|
export interface ToolExecuteAfterInput {
|
||||||
|
|||||||
@ -14,9 +14,22 @@ task(session_id="${sessionId}", prompt="fix: [describe the specific failure]")
|
|||||||
export function buildOrchestratorReminder(
|
export function buildOrchestratorReminder(
|
||||||
planName: string,
|
planName: string,
|
||||||
progress: { total: number; completed: number },
|
progress: { total: number; completed: number },
|
||||||
sessionId: string
|
sessionId: string,
|
||||||
|
autoCommit: boolean = true
|
||||||
): string {
|
): string {
|
||||||
const remaining = progress.total - progress.completed
|
const remaining = progress.total - progress.completed
|
||||||
|
|
||||||
|
const commitStep = autoCommit
|
||||||
|
? `
|
||||||
|
**STEP 8: COMMIT ATOMIC UNIT**
|
||||||
|
|
||||||
|
- Stage ONLY the verified changes
|
||||||
|
- Commit with clear message describing what was done
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
|
||||||
|
const nextStepNumber = autoCommit ? 9 : 8
|
||||||
|
|
||||||
return `
|
return `
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -60,13 +73,8 @@ Update the plan file \`.sisyphus/plans/${planName}.md\`:
|
|||||||
- Use \`Edit\` tool to modify the checkbox
|
- Use \`Edit\` tool to modify the checkbox
|
||||||
|
|
||||||
**DO THIS BEFORE ANYTHING ELSE. Unmarked = Untracked = Lost progress.**
|
**DO THIS BEFORE ANYTHING ELSE. Unmarked = Untracked = Lost progress.**
|
||||||
|
${commitStep}
|
||||||
**STEP 8: COMMIT ATOMIC UNIT**
|
**STEP ${nextStepNumber}: PROCEED TO NEXT TASK**
|
||||||
|
|
||||||
- Stage ONLY the verified changes
|
|
||||||
- Commit with clear message describing what was done
|
|
||||||
|
|
||||||
**STEP 9: PROCEED TO NEXT TASK**
|
|
||||||
|
|
||||||
- Read the plan file AGAIN to identify the next \`- [ ]\` task
|
- Read the plan file AGAIN to identify the next \`- [ ]\` task
|
||||||
- Start immediately - DO NOT STOP
|
- Start immediately - DO NOT STOP
|
||||||
|
|||||||
@ -111,6 +111,7 @@ export function createContinuationHooks(args: {
|
|||||||
isContinuationStopped: (sessionID: string) =>
|
isContinuationStopped: (sessionID: string) =>
|
||||||
stopContinuationGuard?.isStopped(sessionID) ?? false,
|
stopContinuationGuard?.isStopped(sessionID) ?? false,
|
||||||
agentOverrides: pluginConfig.agents,
|
agentOverrides: pluginConfig.agents,
|
||||||
|
autoCommit: pluginConfig.start_work?.auto_commit,
|
||||||
}))
|
}))
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user