{"record":{"id":"e0f17824d504bbb2","repo":"nikivdev/code","slug":"refusing-doc-commit-because-unrelated-changes-are","errorCode":null,"errorMessage":"refusing doc commit because unrelated changes are present: {}","messagePattern":"refusing doc commit because unrelated changes are present: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/codex_session_docs.rs","lineNumber":575,"sourceCode":"    }\n\n    let mut allowed_paths = BTreeSet::new();\n    let mut session_keys = Vec::new();\n    for index in &candidate_indexes {\n        let entry = &entries[*index];\n        session_keys.push(entry.session_key.clone());\n        for path in allowed_commit_paths(project_root, entry) {\n            allowed_paths.insert(path);\n        }\n    }\n\n    let unexpected = changed_paths\n        .iter()\n        .filter(|path| !allowed_paths.contains(path.as_str()))\n        .cloned()\n        .collect::<Vec<_>>();\n    if !unexpected.is_empty() {\n        bail!(\n            \"refusing doc commit because unrelated changes are present: {}\",\n            unexpected.join(\", \")\n        );\n    }\n\n    let files = changed_paths\n        .into_iter()\n        .filter(|path| allowed_paths.contains(path.as_str()))\n        .collect::<Vec<_>>();\n    if files.is_empty() {\n        return Ok(None);\n    }\n\n    let commit_message = build_doc_commit_message(&entries, &candidate_indexes);\n    let plan = CommitPendingPlan {\n        session_keys: session_keys.clone(),\n        files: files.clone(),\n        commit_message: commit_message.clone(),","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/codex_session_docs.rs#L557-L593","documentation":"Before committing documentation changes the library snapshots the git working tree and allows only a whitelisted set of paths (the doc files it manages). If any other modified/untracked file is present, the whole doc commit is refused so unrelated work is never swept into the commit.","triggerScenarios":"Invoking the doc commit path while `git status --porcelain` shows changed paths outside `allowed_paths` — e.g. hand-edited source files, build artifacts, or unrelated untracked files in the repo.","commonSituations":"Developers promoting docs mid-feature with dirty working trees; leftover untracked scratch files; CI runners that checked out a tree with local modifications.","solutions":["Commit, stash, or remove unrelated changes before running the doc commit","Restrict the doc command to a clean checkout dedicated to doc updates","Compare against `git status --porcelain` to identify and clean the offending paths"],"exampleFix":"// before\nrun_doc_commit(); // fails when repo is dirty with unrelated files\n// after\nlet unexpected: Vec<_> = changed_paths.iter().filter(|p| !ALLOWED.contains(&p.as_str())).collect();\nif unexpected.is_empty() {\n    run_doc_commit();\n} else {\n    eprintln!(\"clean or commit these first: {:?}\", unexpected);\n}","handlingStrategy":"validation","validationCode":"let status = Command::new(\"git\").args([\"status\", \"--porcelain\", \"--untracked-files=all\"]).output()?;\nlet changed: Vec<&str> = String::from_utf8_lossy(&status.stdout).lines().filter_map(|l| l.get(3..)).collect();\nlet unexpected: Vec<_> = changed.iter().filter(|p| !ALLOWED_PATHS.contains(p)).collect();\nif !unexpected.is_empty() {\n    anyhow::bail!(\"clean unrelated changes first: {:?}\", unexpected);\n}","typeGuard":"fn tree_is_clean_for_paths(changed: &[String], allowed: &[&str]) -> bool {\n    changed.iter().all(|p| allowed.contains(&p.as_str()))\n}","tryCatchPattern":"match commit_docs() {\n    Err(e) if e.to_string().starts_with(\"refusing doc commit\") => {\n        eprintln!(\"{}\\nstash/commit unrelated work, then retry\", e);\n    }\n    other => other?,\n}","preventionTips":["Run doc commits from a clean working tree or a dedicated checkout","Add scratch/artifact paths to .gitignore so untracked files never appear","Avoid mixing manual edits with automated doc promotion in the same tree"],"tags":["git","commit","working-tree","safety-guard"],"backgroundTag":"dirty-working-tree","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}