{"record":{"id":"131c98b34f0c4918","repo":"Yeachan-Heo/oh-my-codex","slug":"autoresearch-reset-requires-clean-worktree","errorCode":"autoresearch_reset_requires_clean_worktree","errorMessage":"autoresearch_reset_requires_clean_worktree:${worktreePath}:${blocking.join(' | ')}","messagePattern":"autoresearch_reset_requires_clean_worktree:(.+?):(.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/autoresearch/runtime.ts","lineNumber":262,"sourceCode":"    .split(/\\r?\\n/)\n    .map((line) => line.trimEnd())\n    .filter(Boolean);\n}\n\nfunction isAllowedRuntimeDirtyLine(line: string): boolean {\n  const trimmed = line.trim();\n  if (trimmed.length < 4) return false;\n  const path = trimmed.slice(3).trim();\n  return trimmed.startsWith('?? ') && AUTORESEARCH_WORKTREE_EXCLUDES.some((exclude) => exclude.endsWith('/')\n    ? path.startsWith(exclude) || path === exclude.slice(0, -1)\n    : path === exclude);\n}\n\nexport function assertResetSafeWorktree(worktreePath: string): void {\n  const lines = gitStatusLines(worktreePath);\n  const blocking = lines.filter((line) => !isAllowedRuntimeDirtyLine(line));\n  if (blocking.length === 0) return;\n  throw new Error(`autoresearch_reset_requires_clean_worktree:${worktreePath}:${blocking.join(' | ')}`);\n}\n\nasync function ensureParentDir(filePath: string): Promise<void> {\n  await mkdir(dirname(filePath), { recursive: true });\n}\n\nasync function writeJsonFile(filePath: string, value: unknown): Promise<void> {\n  await ensureParentDir(filePath);\n  await writeFile(filePath, `${JSON.stringify(value, null, 2)}\\n`, 'utf-8');\n}\n\nasync function readJsonFile<T>(filePath: string): Promise<T> {\n  return JSON.parse(await readFile(filePath, 'utf-8')) as T;\n}\n\nasync function readActiveRunState(projectRoot: string): Promise<AutoresearchActiveRunState | null> {\n  const file = activeRunStateFile(projectRoot);\n  if (!existsSync(file)) return null;","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/autoresearch/runtime.ts#L244-L280","documentation":"assertResetSafeWorktree throws (code autoresearch_reset_requires_clean_worktree) when `git status --porcelain` in the worktree shows dirty entries that are not on the allowlist (isAllowedRuntimeDirtyLine). The runtime refuses to reset a worktree that contains uncommitted user changes, because a reset would destroy them.","triggerScenarios":"Calling prepareAutoresearchRuntime, resumeAutoresearchRuntime, resetToLastKeptCommit, or recordNonEvaluatedCandidateStatus while the worktree has modified/untracked files beyond the runtime's own allowed artifacts (e.g. .omx logs or exclusions).","commonSituations":"A developer manually edited files inside the autoresearch worktree, a crashed run left partial changes, editors creating temp/untracked files, or a previous run's artifacts not covered by the allowlist.","solutions":["Inspect the blocking entries listed in the message and commit, stash, or remove them inside the worktree","If the changes are disposable, `git checkout -- . && git clean -fd` in the worktree path","If they are valuable, commit them to a branch or copy them out before resuming/resetting","Report/extend isAllowedRuntimeDirtyLine if a legitimate runtime artifact is wrongly flagged"],"exampleFix":"# before\n# worktree has modified src/foo.ts\nresumeAutoresearchRuntime(repoRoot, runId); // throws autoresearch_reset_requires_clean_worktree\n# after\ngit -C /path/to/worktree stash --include-untracked\nresumeAutoresearchRuntime(repoRoot, runId);","handlingStrategy":"validation","validationCode":"import { spawnSync } from 'node:child_process';\nfunction isClean(worktreePath: string): boolean {\n  const r = spawnSync('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: worktreePath, encoding: 'utf-8' });\n  return r.status === 0 && (r.stdout ?? '').trim() === '';\n}","typeGuard":null,"tryCatchPattern":"try { await resumeAutoresearchRuntime(repoRoot, runId); }\ncatch (e) { if (e instanceof Error && e.message.startsWith('autoresearch_reset_requires_clean_worktree')) { const dirty = e.message.split(':').pop(); /* stash/commit those paths, then retry */ } throw e; }","preventionTips":["Never manually edit files inside an autoresearch worktree","Clean or stash worktree changes before prepare/resume/reset","Treat the blocking entries in the message as the authoritative list of files to handle"],"tags":["git","worktree","dirty-state","reset-safety"],"backgroundTag":"dirty-working-tree","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}