{"record":{"id":"d7da0f60882d820f","repo":"Hmbown/CodeWhale","slug":"push-is-never-automatic-re-run-with-dry-run-to","errorCode":null,"errorMessage":"Push is never automatic; re-run with --dry-run to preview, then confirm explicitly","messagePattern":"Push is never automatic; re-run with --dry-run to preview, then confirm explicitly","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/cloud.rs","lineNumber":938,"sourceCode":"            writeln!(out, \"Account settings (pull --dry-run):\")?;\n            writeln!(out, \"Account ID: {}\", printable(&user.id))?;\n            writeln!(out, \"Profile: {}\", printable(profile))?;\n            writeln!(out, \"API: {api_base}\")?;\n            writeln!(\n                out,\n                \"dry-run: remote settings import is not available; local config unchanged\"\n            )?;\n            // Show the invariant: Bearer custody stays in the OS keyring, never in config.toml.\n            writeln!(\n                out,\n                \"Secure custody: Bearer tokens remain in the OS keyring\"\n            )?;\n            Ok(())\n        }\n        CloudCommand::Push(args) => {\n            let user = client.me()?;\n            if !args.dry_run {\n                bail!(\n                    \"Push is never automatic; re-run with --dry-run to preview, then confirm explicitly\"\n                );\n            }\n            writeln!(out, \"Account settings (push --dry-run):\")?;\n            writeln!(out, \"Account ID: {}\", printable(&user.id))?;\n            writeln!(out, \"Profile: {}\", printable(profile))?;\n            writeln!(out, \"API: {api_base}\")?;\n            writeln!(\n                out,\n                \"dry-run: would PATCH /api/me/preferences with If-Match revision check (412 on conflict)\"\n            )?;\n            writeln!(\n                out,\n                \"No credentials, paths, or env are copied; only explicit fields (field-level last-writer-wins)\"\n            )?;\n            Ok(())\n        }\n    }","sourceCodeStart":920,"sourceCodeEnd":956,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/cloud.rs#L920-L956","documentation":"`codewhale account push` is preview-only by design: it never writes to the server automatically. Without `--dry-run` the command bails after only the me() identity check, forcing an explicit preview-then-confirm flow.","triggerScenarios":"Running `codewhale account push` without `--dry-run`.","commonSituations":"Users expecting push to upload local settings in one shot; scripts assuming push is the write side of pull; CI automation calling push non-interactively.","solutions":["Re-run with `--dry-run`: `codewhale account push --dry-run` to see what would be pushed.","Follow any explicit confirm flow the dry-run output describes.","Since automatic push is intentionally unsupported, script only the dry-run form; no apply path exists yet."],"exampleFix":"// before\ncodewhale account push\n// after\ncodewhale account push --dry-run","handlingStrategy":"validation","validationCode":"// Guard automation: push is preview-only\nlet args: Vec<String> = std::env::args().collect();\nassert!(args.iter().any(|a| a == \"--dry-run\"), \"push requires --dry-run\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run `codewhale account push --dry-run` first.","Never assume push applies changes — it is intentionally manual.","In CI, invoke only the dry-run form.","Design scripts around the preview; expect the flag to remain mandatory."],"tags":["cli","safety","dry-run"],"backgroundTag":"feature-not-enabled","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}