diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index 16114f11..025ec186 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -3837,6 +3837,19 @@ }, "additionalProperties": false }, + "start_work": { + "type": "object", + "properties": { + "auto_commit": { + "default": true, + "type": "boolean" + } + }, + "required": [ + "auto_commit" + ], + "additionalProperties": false + }, "_migrations": { "type": "array", "items": { diff --git a/src/config/AGENTS.md b/src/config/AGENTS.md index 83a8830a..8838e91e 100644 --- a/src/config/AGENTS.md +++ b/src/config/AGENTS.md @@ -4,7 +4,7 @@ ## 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 @@ -31,12 +31,15 @@ config/schema/ ├── background-task.ts # Concurrency limits per model/provider ├── babysitting.ts # Unstable agent monitoring ├── 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 ``` -## 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) diff --git a/src/config/schema/oh-my-opencode-config.ts b/src/config/schema/oh-my-opencode-config.ts index 52e7d461..cf98ccf1 100644 --- a/src/config/schema/oh-my-opencode-config.ts +++ b/src/config/schema/oh-my-opencode-config.ts @@ -18,6 +18,7 @@ import { SkillsConfigSchema } from "./skills" import { SisyphusConfigSchema } from "./sisyphus" import { SisyphusAgentConfigSchema } from "./sisyphus-agent" import { TmuxConfigSchema } from "./tmux" +import { StartWorkConfigSchema } from "./start-work" import { WebsearchConfigSchema } from "./websearch" export const OhMyOpenCodeConfigSchema = z.object({ @@ -60,6 +61,7 @@ export const OhMyOpenCodeConfigSchema = z.object({ websearch: WebsearchConfigSchema.optional(), tmux: TmuxConfigSchema.optional(), sisyphus: SisyphusConfigSchema.optional(), + start_work: StartWorkConfigSchema.optional(), /** Migration history to prevent re-applying migrations (e.g., model version upgrades) */ _migrations: z.array(z.string()).optional(), }) diff --git a/src/config/schema/start-work.ts b/src/config/schema/start-work.ts new file mode 100644 index 00000000..7daae0c3 --- /dev/null +++ b/src/config/schema/start-work.ts @@ -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 diff --git a/src/hooks/atlas/atlas-hook.ts b/src/hooks/atlas/atlas-hook.ts index 94a6470e..97d0842d 100644 --- a/src/hooks/atlas/atlas-hook.ts +++ b/src/hooks/atlas/atlas-hook.ts @@ -7,6 +7,7 @@ import type { AtlasHookOptions, SessionState } from "./types" export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) { const sessions = new Map() const pendingFilePaths = new Map() + const autoCommit = options?.autoCommit ?? true function getState(sessionID: string): SessionState { let state = sessions.get(sessionID) @@ -20,6 +21,6 @@ export function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) { return { handler: createAtlasEventHandler({ ctx, options, sessions, getState }), "tool.execute.before": createToolExecuteBeforeHandler({ ctx, pendingFilePaths }), - "tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths }), + "tool.execute.after": createToolExecuteAfterHandler({ ctx, pendingFilePaths, autoCommit }), } } diff --git a/src/hooks/atlas/tool-execute-after.ts b/src/hooks/atlas/tool-execute-after.ts index 8a7240c4..818fdb73 100644 --- a/src/hooks/atlas/tool-execute-after.ts +++ b/src/hooks/atlas/tool-execute-after.ts @@ -14,9 +14,9 @@ import type { ToolExecuteAfterInput, ToolExecuteAfterOutput } from "./types" export function createToolExecuteAfterHandler(input: { ctx: PluginInput pendingFilePaths: Map -}): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise { - const { ctx, pendingFilePaths } = input - + autoCommit: boolean + }): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise { + const { ctx, pendingFilePaths, autoCommit } = input return async (toolInput, toolOutput): Promise => { // Guard against undefined output (e.g., from /review command - see issue #1035) if (!toolOutput) { @@ -76,7 +76,7 @@ export function createToolExecuteAfterHandler(input: { // Preserve original subagent response - critical for debugging failed tasks const originalResponse = toolOutput.output - toolOutput.output = ` +toolOutput.output = ` ## SUBAGENT WORK COMPLETED ${fileChanges} @@ -88,9 +88,8 @@ ${fileChanges} ${originalResponse} -${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId)} +${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId, autoCommit)} ` - log(`[${HOOK_NAME}] Output transformed for orchestrator mode (boulder)`, { plan: boulderState.plan_name, progress: `${progress.completed}/${progress.total}`, diff --git a/src/hooks/atlas/types.ts b/src/hooks/atlas/types.ts index 7302f830..73436a01 100644 --- a/src/hooks/atlas/types.ts +++ b/src/hooks/atlas/types.ts @@ -8,6 +8,8 @@ export interface AtlasHookOptions { backgroundManager?: BackgroundManager isContinuationStopped?: (sessionID: string) => boolean agentOverrides?: AgentOverrides + /** Enable auto-commit after each atomic task completion (default: true) */ + autoCommit?: boolean } export interface ToolExecuteAfterInput { diff --git a/src/hooks/atlas/verification-reminders.ts b/src/hooks/atlas/verification-reminders.ts index f0c24c54..1955dde3 100644 --- a/src/hooks/atlas/verification-reminders.ts +++ b/src/hooks/atlas/verification-reminders.ts @@ -14,9 +14,22 @@ task(session_id="${sessionId}", prompt="fix: [describe the specific failure]") export function buildOrchestratorReminder( planName: string, progress: { total: number; completed: number }, - sessionId: string + sessionId: string, + autoCommit: boolean = true ): string { 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 ` --- @@ -60,13 +73,8 @@ Update the plan file \`.sisyphus/plans/${planName}.md\`: - Use \`Edit\` tool to modify the checkbox **DO THIS BEFORE ANYTHING ELSE. Unmarked = Untracked = Lost progress.** - -**STEP 8: COMMIT ATOMIC UNIT** - -- Stage ONLY the verified changes -- Commit with clear message describing what was done - -**STEP 9: PROCEED TO NEXT TASK** +${commitStep} +**STEP ${nextStepNumber}: PROCEED TO NEXT TASK** - Read the plan file AGAIN to identify the next \`- [ ]\` task - Start immediately - DO NOT STOP diff --git a/src/plugin/hooks/create-continuation-hooks.ts b/src/plugin/hooks/create-continuation-hooks.ts index da453f58..9cedce21 100644 --- a/src/plugin/hooks/create-continuation-hooks.ts +++ b/src/plugin/hooks/create-continuation-hooks.ts @@ -111,6 +111,7 @@ export function createContinuationHooks(args: { isContinuationStopped: (sessionID: string) => stopContinuationGuard?.isStopped(sessionID) ?? false, agentOverrides: pluginConfig.agents, + autoCommit: pluginConfig.start_work?.auto_commit, })) : null