{"record":{"id":"cc85e78d3dd39284","repo":"can1357/oh-my-pi","slug":"security-remediation-refuses-a-dirty-working-tree","errorCode":null,"errorMessage":"Security remediation refuses a dirty working tree (${dirty.join(\", \")}). Commit or stash the changes before creating an isolated remediation workspace.","messagePattern":"Security remediation refuses a dirty working tree \\((.+?)\\)\\. Commit or stash the changes before creating an isolated remediation workspace\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/remediation.ts","lineNumber":57,"sourceCode":"\tif (baseline.root.unstaged.trim()) dirty.push(\"unstaged changes\");\n\tif (baseline.root.untracked.length > 0 || baseline.root.untrackedPatch.trim()) dirty.push(\"untracked files\");\n\tfor (const nested of baseline.nested) {\n\t\tif (\n\t\t\tnested.baseline.staged.trim() ||\n\t\t\tnested.baseline.unstaged.trim() ||\n\t\t\tnested.baseline.untracked.length > 0 ||\n\t\t\tnested.baseline.untrackedPatch.trim()\n\t\t) {\n\t\t\tdirty.push(`dirty nested repository ${nested.relativePath}`);\n\t\t}\n\t}\n\treturn dirty;\n}\n\nexport function assertSecurityRemediationBaselineClean(baseline: WorktreeBaseline): void {\n\tconst dirty = repoBaselineDirty(baseline);\n\tif (dirty.length === 0) return;\n\tthrow new Error(\n\t\t[\n\t\t\t`Security remediation refuses a dirty working tree (${dirty.join(\", \")}).`,\n\t\t\t\"Commit or stash the changes before creating an isolated remediation workspace.\",\n\t\t].join(\" \"),\n\t);\n}\n\nexport async function prepareSecurityRemediationWorkspace(\n\trequest: SecurityRemediationRequest,\n\tdependencies: SecurityRemediationDependencies = {},\n): Promise<SecurityRemediationWorkspace> {\n\tconst findingIds = [...new Set(request.findingIds.map(id => id.trim()).filter(Boolean))];\n\tif (findingIds.length === 0) throw new Error(\"Security remediation requires at least one finding id\");\n\tconst prepareContext = dependencies.prepareContext ?? prepareIsolationContext;\n\tconst createIsolation = dependencies.createIsolation ?? ensureIsolation;\n\tconst disposeIsolation = dependencies.cleanupIsolation ?? cleanupIsolation;\n\tconst context = await prepareContext(request.cwd);\n\tassertSecurityRemediationBaselineClean(context.baseline);","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/remediation.ts#L39-L75","documentation":"assertSecurityRemediationBaselineClean inspects the WorktreeBaseline of the project and refuses to create an isolated remediation worktree when the working tree has uncommitted changes. Remediation needs a pristine baseline so generated fixes can be isolated and reviewed as a clean diff.","triggerScenarios":"Calling prepareSecurityRemediationWorkspace (directly or via the workspace command) while `git status` shows modified, staged, untracked, or conflicting files in the repo.","commonSituations":"Developer had local edits/WIP in the repo when starting remediation, untracked build artifacts or config files, leftovers from a previous failed remediation, or a dirty checkout on CI.","solutions":["Commit the pending changes with `git commit -am \"wip\"` before creating the remediation workspace","Stash them with `git stash -u` (including untracked files), run remediation, then `git stash pop`","Clean untracked artifacts with `git clean -n` (review) then `git clean -fd` if safe","Check `git status --porcelain` first to see exactly which paths are dirty"],"exampleFix":"// before\nawait prepareSecurityRemediationWorkspace({ cwd, findingIds });\n// after\nawait $`git -C ${cwd} stash -u`;\nawait prepareSecurityRemediationWorkspace({ cwd, findingIds });\nawait $`git -C ${cwd} stash pop`;","handlingStrategy":"validation","validationCode":"if ((await $`git -C ${cwd} status --porcelain`.text()).trim()) throw new Error(\"dirty tree\");","typeGuard":"null","tryCatchPattern":"try { await prepare(request); } catch (e) { if (String(e.message).includes(\"dirty working tree\")) { await $`git stash -u`; } else throw e; }","preventionTips":["Require clean `git status --porcelain` preflight","Stash with -u to include untracked files"],"tags":["git","dirty-worktree","precondition"],"backgroundTag":"dirty-working-tree","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}