{"record":{"id":"e9401357a14d5b2e","repo":"xai-org/grok-build","slug":"local-workspace-ack-required","errorCode":null,"errorMessage":"{LOCAL_WORKSPACE_ACK_REQUIRED}","messagePattern":"\\{LOCAL_WORKSPACE_ACK_REQUIRED\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/app/session_startup.rs","lineNumber":554,"sourceCode":"/// Testable UX gate: `stdin_is_terminal` is injected.\n#[cfg(feature = \"local-workspace\")]\npub fn emit_local_workspace_startup_ux_with(\n    cfg: &LocalWorkspaceConfig,\n    stdin_is_terminal: bool,\n) -> anyhow::Result<()> {\n    let cwd_display = cfg\n        .cwd\n        .as_ref()\n        .map(|p| p.display().to_string())\n        .unwrap_or_else(|| \"<session cwd>\".to_string());\n    let banner = LOCAL_WORKSPACE_BANNER.replace(\"<cwd>\", &cwd_display);\n    eprintln!(\"{banner}\");\n    eprintln!(\"{LOCAL_WORKSPACE_HITL_HINT}\");\n    if local_workspace_ack_satisfied() {\n        return Ok(());\n    }\n    if !stdin_is_terminal {\n        anyhow::bail!(\"{LOCAL_WORKSPACE_ACK_REQUIRED}\");\n    }\n    eprint!(\"Continue with local workspace on this machine? [y/N] \");\n    use std::io::Write;\n    let _ = std::io::stderr().flush();\n    let mut line = String::new();\n    std::io::stdin().read_line(&mut line)?;\n    let ok = matches!(line.trim(), \"y\" | \"Y\" | \"yes\" | \"YES\");\n    if !ok {\n        anyhow::bail!(\"local workspace cancelled\");\n    }\n    write_local_workspace_ack();\n    Ok(())\n}\n/// True when ACK env or ack file already authorizes local workspace.\n#[cfg(feature = \"local-workspace\")]\npub fn local_workspace_ack_satisfied() -> bool {\n    if env_truthy(GROK_CHAT_LOCAL_WORKSPACE_ACK_ENV) {\n        return true;","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/app/session_startup.rs#L536-L572","documentation":"Local workspace activation is gated by a human-in-the-loop acknowledgement. `emit_local_workspace_startup_ux_with` prints a banner, and if no prior ACK exists (GROK_CHAT_LOCAL_WORKSPACE_ACK truthy or ack file present) and stdin is not a terminal, it fails closed with `LOCAL_WORKSPACE_ACK_REQUIRED` (session_startup.rs:554) rather than proceeding without consent.","triggerScenarios":"Running the chat CLI with a local workspace enabled in non-interactive contexts: CI jobs, piped/redirected stdin, `nohup`, systemd services, docker exec without -t, when neither the ACK env var nor the ack file exists.","commonSituations":"First local-workspace run inside CI; scheduling the tool where stdin is /dev/null; running via a wrapper that detaches the TTY before the interactive confirm could be answered.","solutions":["Set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 in the environment for non-interactive runs","Answer the interactive `Continue with local workspace? [y/N]` prompt once in a TTY so the ack file persists","Run interactively in a terminal for the first activation","Pre-create the ack file at the path `local_workspace_ack_path()` expects"],"exampleFix":"// before\ngrok-pager --chat --local-workspace-own < input.txt\n// after\nGROK_CHAT_LOCAL_WORKSPACE_ACK=1 grok-pager --chat --local-workspace-own < input.txt","handlingStrategy":"fallback","validationCode":"fn ack_ready() -> bool {\n    std::env::var(\"GROK_CHAT_LOCAL_WORKSPACE_ACK\").ok().as_deref() == Some(\"1\")\n        || std::path::Path::new(&ack_file_path()).is_file()\n}","typeGuard":null,"tryCatchPattern":"match run_with_local_workspace(args) {\n    Err(e) if e.to_string().contains(\"ACK\") => {\n        eprintln!(\"non-interactive run: set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 after reviewing the banner: {e}\");\n        std::process::exit(2);\n    }\n    other => other?,\n}","preventionTips":["Answer the interactive [y/N] prompt once in a TTY to persist the ack file","Set GROK_CHAT_LOCAL_WORKSPACE_ACK=1 in CI/job environments that need local workspace","Avoid detaching the TTY (nohup, systemd) before first activation","Only set the ACK env after reviewing the local-workspace banner"],"tags":["local-workspace","ack","non-interactive","human-in-the-loop"],"backgroundTag":"missing-ack-confirmation","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}