@sebastienrousseau/dotfiles 0.2.499 → 0.2.501

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (567) hide show
  1. package/CHANGELOG.md +452 -0
  2. package/LICENSE +1283 -0
  3. package/README.md +322 -0
  4. package/docs/.vitepress/reports/localization-readability-audit.md +73 -0
  5. package/docs/AI.md +108 -0
  6. package/docs/CNAME +1 -0
  7. package/docs/COPYRIGHT +4 -3
  8. package/docs/NAMING_CONVENTIONS.md +102 -0
  9. package/docs/README.md +82 -0
  10. package/docs/_config.yml +59 -0
  11. package/docs/adr/ADR-001-ci-cd-pipeline.md +118 -0
  12. package/docs/adr/ADR-002-shell-performance.md +130 -0
  13. package/docs/adr/ADR-003-security-first.md +158 -0
  14. package/docs/adr/ADR-004-cli-architecture.md +171 -0
  15. package/docs/adr/ADR-005-chezmoi-choice.md +99 -0
  16. package/docs/adr/ADR-006-shell-selection.md +124 -0
  17. package/docs/adr/ADR-007-multi-shell-parity.md +62 -0
  18. package/docs/adr/ADR-008-alias-system-architecture.md +95 -0
  19. package/docs/adr/ADR-009-wallpaper-driven-theming.md +131 -0
  20. package/docs/adr/ADR-010-starship-transient-prompt.md +144 -0
  21. package/docs/adr/ADR-011-nushell-tier3-keep.md +144 -0
  22. package/docs/adr/README.md +39 -0
  23. package/docs/architecture/ARCHITECTURE.md +117 -0
  24. package/docs/architecture/INTEROP.md +44 -0
  25. package/docs/architecture/REPO_LAYOUT.md +241 -0
  26. package/docs/architecture/WALKTHROUGH.md +86 -0
  27. package/docs/architecture/fleet-deployment.md +77 -0
  28. package/docs/archive/EUXIS_2026_REVIEW.md +127 -0
  29. package/docs/archive/LEGACY_ROADMAP.md +160 -0
  30. package/docs/archive/MILESTONE_v0.2.493.md +47 -0
  31. package/docs/{PLAN.md → archive/PLAN.md} +50 -12
  32. package/docs/archive/REPO_AUDIT.md +31 -0
  33. package/docs/guides/INSTALL.md +144 -0
  34. package/docs/guides/NEOVIM_IDE_GUIDE.md +61 -0
  35. package/docs/guides/THEMING.md +230 -0
  36. package/docs/guides/TROUBLESHOOTING.md +176 -0
  37. package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +792 -0
  38. package/docs/index.md +43 -0
  39. package/docs/interop/A2A.md +39 -0
  40. package/docs/interop/POWERSHELL.md +102 -0
  41. package/docs/manual/00-introduction.md +89 -0
  42. package/docs/manual/01-concepts/01-architecture.md +138 -0
  43. package/docs/manual/01-concepts/02-trust-model.md +182 -0
  44. package/docs/manual/01-concepts/03-theme-engine.md +186 -0
  45. package/docs/manual/01-concepts/04-fleet.md +148 -0
  46. package/docs/manual/01-concepts/05-self-healing.md +204 -0
  47. package/docs/manual/02-tutorials/01-first-install.md +197 -0
  48. package/docs/manual/02-tutorials/02-add-wallpaper.md +216 -0
  49. package/docs/manual/02-tutorials/03-create-profile.md +244 -0
  50. package/docs/manual/02-tutorials/04-encrypt-secret.md +281 -0
  51. package/docs/manual/02-tutorials/05-deploy-fleet.md +283 -0
  52. package/docs/manual/03-reference/01-dot-cli.md +417 -0
  53. package/docs/manual/03-reference/02-config-files.md +265 -0
  54. package/docs/manual/03-reference/03-environment.md +124 -0
  55. package/docs/manual/03-reference/04-templates.md +190 -0
  56. package/docs/manual/03-reference/05-feature-flags.md +128 -0
  57. package/docs/manual/04-cookbook/01-recipes.md +285 -0
  58. package/docs/manual/04-cookbook/02-troubleshooting.md +351 -0
  59. package/docs/manual/04-cookbook/03-faq.md +175 -0
  60. package/docs/manual/05-appendices/A-platform-matrix.md +101 -0
  61. package/docs/manual/05-appendices/B-security-checklist.md +84 -0
  62. package/docs/manual/05-appendices/C-glossary.md +40 -0
  63. package/docs/manual/05-appendices/D-bibliography.md +58 -0
  64. package/docs/manual/05-appendices/E-license.md +38 -0
  65. package/docs/manual/_toc.yml +58 -0
  66. package/docs/manual/command-index.md +62 -0
  67. package/docs/manual/concept-index.md +168 -0
  68. package/docs/operations/ATTESTATION.md +44 -0
  69. package/docs/operations/CI_CADENCE.md +107 -0
  70. package/docs/operations/CI_COMPOSITES.md +156 -0
  71. package/docs/operations/COMPLETIONS.md +123 -0
  72. package/docs/operations/COVERAGE.md +148 -0
  73. package/docs/operations/DRIFT.md +107 -0
  74. package/docs/operations/MAINTENANCE.md +63 -0
  75. package/docs/operations/MIGRATION.md +109 -0
  76. package/docs/operations/OPERATIONS.md +188 -0
  77. package/docs/operations/PERFORMANCE.md +133 -0
  78. package/docs/operations/RELIABILITY.md +122 -0
  79. package/docs/{ROADMAP.md → operations/ROADMAP.md} +57 -39
  80. package/docs/operations/TESTING.md +199 -0
  81. package/docs/operations/TRACEABILITY.md +35 -0
  82. package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +65 -0
  83. package/docs/operations/VERSION_SYNC.md +393 -0
  84. package/docs/reference/ALIASES.md +131 -0
  85. package/docs/reference/ALIASES_CHEATSHEET.md +32 -0
  86. package/docs/reference/ALIASES_DEPRECATIONS.md +13 -0
  87. package/docs/reference/FEATURES.md +66 -0
  88. package/docs/reference/FONTS.md +112 -0
  89. package/docs/reference/PROFILES.md +69 -0
  90. package/docs/reference/SCREENSHOTS.md +121 -0
  91. package/docs/reference/SCRIPTS.md +71 -0
  92. package/docs/reference/SUPPORT_MATRIX.md +80 -0
  93. package/docs/reference/THEMES.md +117 -0
  94. package/docs/reference/TOOLS.md +109 -0
  95. package/docs/reference/UTILS.md +155 -0
  96. package/docs/security/AI_ACT_COMPLIANCE.md +94 -0
  97. package/docs/security/AUDIT_BYPASS.md +103 -0
  98. package/docs/security/AUTOMATION_SECRETS.md +26 -0
  99. package/docs/security/CI_EGRESS_ALLOWLIST.md +127 -0
  100. package/docs/security/COMPLIANCE.md +458 -0
  101. package/docs/security/DEPS_DEV_EXCEPTIONS.md +86 -0
  102. package/docs/security/ENCRYPTION.md +57 -0
  103. package/docs/security/FMEA.md +159 -0
  104. package/docs/security/HISTORY_FILTERING.md +132 -0
  105. package/docs/security/INCIDENT_RESPONSE.md +579 -0
  106. package/docs/security/INSTALL_VERIFICATION.md +122 -0
  107. package/docs/security/KEYS.md +49 -0
  108. package/docs/security/KEY_ROTATION.md +223 -0
  109. package/docs/security/MCP_POLICY.md +78 -0
  110. package/docs/security/POLICY_RELEASES.md +37 -0
  111. package/docs/security/README.md +28 -0
  112. package/docs/security/SCORECARD.md +80 -0
  113. package/docs/security/SECRETS.md +158 -0
  114. package/docs/security/SECURITY.md +45 -0
  115. package/docs/security/SECURITY_CHECKLIST.md +55 -0
  116. package/docs/security/SHELL_EXEMPTIONS.md +145 -0
  117. package/docs/security/SOUP_REGISTER.md +36 -0
  118. package/docs/security/THREAT_MODEL.md +130 -0
  119. package/docs/security/VERIFICATION_VALIDATION.md +228 -0
  120. package/docs/themes/README.md +10 -0
  121. package/docs/themes/VISUAL_INTEGRITY_REPORT.md +30 -0
  122. package/docs/themes/hero-shot.svg +78 -0
  123. package/dot_config/.module-manifest.json +69 -0
  124. package/dot_config/ai/identity.md +23 -0
  125. package/dot_config/ai/patterns/architect.md +16 -0
  126. package/dot_config/ai/patterns/hardener.md +15 -0
  127. package/dot_config/ai/patterns/refactor.md +15 -0
  128. package/dot_config/aider/aider.conf.yml +32 -0
  129. package/dot_config/alacritty/alacritty.toml.tmpl +55 -0
  130. package/dot_config/ansible/ansible.cfg +11 -0
  131. package/dot_config/atuin/config.toml.tmpl +47 -0
  132. package/dot_config/bat/config +23 -0
  133. package/dot_config/brave-flags.conf.tmpl +7 -0
  134. package/dot_config/btop/btop.conf +16 -0
  135. package/dot_config/btop/themes/tokyonight.theme +34 -0
  136. package/dot_config/bun/bunfig.toml.tmpl +33 -0
  137. package/dot_config/claude/mcp_servers.json +20 -0
  138. package/dot_config/containers/containers.conf +14 -0
  139. package/dot_config/curl/dot_curlrc +18 -0
  140. package/dot_config/dlv/config.yml +39 -0
  141. package/dot_config/docker/config.json +15 -0
  142. package/dot_config/dotfiles/agent-card.json +29 -0
  143. package/dot_config/dotfiles/agent-profiles.json +92 -0
  144. package/dot_config/dotfiles/boot/README.md +13 -0
  145. package/dot_config/dotfiles/grub/README.md +13 -0
  146. package/dot_config/dotfiles/lock/README.md +13 -0
  147. package/dot_config/dotfiles/mcp-lock.json +33 -0
  148. package/dot_config/dotfiles/mcp-policy.json +52 -0
  149. package/dot_config/dotfiles/mcp-registry.json +47 -0
  150. package/dot_config/dotfiles/model-registry.json +20 -0
  151. package/dot_config/dotfiles/policy-bundles.json +38 -0
  152. package/dot_config/dotfiles/prompt-registry.json +16 -0
  153. package/dot_config/dotfiles/versions.env +18 -0
  154. package/dot_config/duf/duf.conf +6 -0
  155. package/dot_config/duti/defaults.duti +5 -0
  156. package/dot_config/emoji/emoji.txt +34 -0
  157. package/dot_config/environment.d/50-ssh-agent.conf +2 -0
  158. package/dot_config/environment.d/90-wayland.conf +19 -0
  159. package/dot_config/fastfetch/config.jsonc +28 -0
  160. package/dot_config/firefox/user.js.tmpl +58 -0
  161. package/dot_config/fish/completions/dot-theme-sync.fish.tmpl +9 -0
  162. package/dot_config/fish/completions/dot.fish.tmpl +115 -0
  163. package/dot_config/fish/conf.d/000-perf-cache.fish +56 -0
  164. package/dot_config/fish/conf.d/aliases.fish.tmpl +77 -0
  165. package/dot_config/fish/conf.d/env.fish.tmpl +48 -0
  166. package/dot_config/fish/conf.d/functions.fish.tmpl +22 -0
  167. package/dot_config/fish/conf.d/init.fish.tmpl +172 -0
  168. package/dot_config/fish/config.fish.tmpl +44 -0
  169. package/dot_config/fish/fish_plugins +1 -0
  170. package/dot_config/fish/functions/_.fish +3 -0
  171. package/dot_config/fish/functions/_cached_eval.fish +131 -0
  172. package/dot_config/fish/functions/_cached_eval_clear.fish +17 -0
  173. package/dot_config/fish/functions/als.fish +46 -0
  174. package/dot_config/fish/functions/bg-upgrade.fish +7 -0
  175. package/dot_config/fish/functions/c.fish +3 -0
  176. package/dot_config/fish/functions/cat.fish +9 -0
  177. package/dot_config/fish/functions/d.fish +7 -0
  178. package/dot_config/fish/functions/dot.fish +34 -0
  179. package/dot_config/fish/functions/h.fish +3 -0
  180. package/dot_config/fish/functions/l.fish +7 -0
  181. package/dot_config/fish/functions/la.fish +7 -0
  182. package/dot_config/fish/functions/ll.fish +7 -0
  183. package/dot_config/fish/functions/log_error.fish +13 -0
  184. package/dot_config/fish/functions/log_info.fish +13 -0
  185. package/dot_config/fish/functions/lr.fish +7 -0
  186. package/dot_config/fish/functions/lra.fish +7 -0
  187. package/dot_config/fish/functions/ls.fish +7 -0
  188. package/dot_config/fish/functions/lt.fish +7 -0
  189. package/dot_config/fish/functions/lta.fish +7 -0
  190. package/dot_config/fish/functions/notify-run.fish +11 -0
  191. package/dot_config/fish/functions/q.fish +3 -0
  192. package/dot_config/fish/functions/silent-run.fish +7 -0
  193. package/dot_config/fish/functions/yy.fish +8 -0
  194. package/dot_config/flatpak/flatpak.list +4 -0
  195. package/dot_config/fontconfig/fonts.conf.tmpl +57 -0
  196. package/dot_config/foot/foot.ini.tmpl +33 -0
  197. package/dot_config/fuzzel/fuzzel.ini.tmpl +18 -0
  198. package/dot_config/fzf/fzf.zsh +48 -0
  199. package/dot_config/gem/gemrc +9 -0
  200. package/dot_config/gh/config.yml +12 -0
  201. package/dot_config/ghostty/config.tmpl +165 -0
  202. package/dot_config/git/allowed_signers.tmpl +18 -0
  203. package/dot_config/git/attributes +12 -0
  204. package/dot_config/git/commit-template +10 -0
  205. package/dot_config/git/hooks/executable_commit-msg +146 -0
  206. package/dot_config/git/ignore +27 -0
  207. package/dot_config/gnupg/gpg-agent.conf +11 -0
  208. package/dot_config/go/golangci.yml +118 -0
  209. package/dot_config/go/gopls.json +30 -0
  210. package/dot_config/goose/config.yaml +29 -0
  211. package/dot_config/gtk-3.0/gtk.css.tmpl +184 -0
  212. package/dot_config/gtk-3.0/settings.ini.tmpl +27 -0
  213. package/dot_config/gtk-4.0/gtk.css.tmpl +252 -0
  214. package/dot_config/gtk-4.0/settings.ini.tmpl +18 -0
  215. package/dot_config/htop/htoprc +20 -0
  216. package/dot_config/inputrc +2 -0
  217. package/dot_config/ipython/profile_default/ipython_config.py +19 -0
  218. package/dot_config/just/justfile +122 -0
  219. package/dot_config/k9s/config.yaml +65 -0
  220. package/dot_config/k9s/skins/catppuccin-mocha.yaml +116 -0
  221. package/dot_config/kanshi/config.tmpl +22 -0
  222. package/dot_config/karabiner/karabiner.json +14 -0
  223. package/dot_config/kitty/kitty.conf.tmpl +53 -0
  224. package/dot_config/lazydocker/config.yml +186 -0
  225. package/dot_config/lazygit/config.yml +35 -0
  226. package/dot_config/mako/config +47 -0
  227. package/dot_config/mas/masapps.txt +5 -0
  228. package/dot_config/micro/settings.json +3 -0
  229. package/dot_config/mimeapps.list +77 -0
  230. package/dot_config/minikube/config.json +13 -0
  231. package/dot_config/mise/config.toml +99 -0
  232. package/dot_config/mongosh/mongoshrc.js +68 -0
  233. package/dot_config/mpv/input.conf +47 -0
  234. package/dot_config/mpv/mpv.conf +47 -0
  235. package/dot_config/mycli/myclirc +67 -0
  236. package/dot_config/nano/nanorc +28 -0
  237. package/dot_config/ncdu/config +12 -0
  238. package/dot_config/niri/config.kdl.tmpl +327 -0
  239. package/dot_config/nushell/aliases.nu +18 -0
  240. package/dot_config/nushell/cached_eval.nu +80 -0
  241. package/dot_config/nushell/completions.nu.tmpl +52 -0
  242. package/dot_config/nushell/config.nu.tmpl +86 -0
  243. package/dot_config/nushell/env.nu.tmpl +102 -0
  244. package/dot_config/nushell/functions.nu.tmpl +17 -0
  245. package/dot_config/nvim/init.lua +18 -0
  246. package/dot_config/nvim/lazy-lock.json +58 -0
  247. package/dot_config/nvim/lua/config/autocmds.lua +107 -0
  248. package/dot_config/nvim/lua/config/keymaps.lua +92 -0
  249. package/dot_config/nvim/lua/config/lazy.lua +44 -0
  250. package/dot_config/nvim/lua/config/options.lua +49 -0
  251. package/dot_config/nvim/lua/plugins/ai.lua +75 -0
  252. package/dot_config/nvim/lua/plugins/coding.lua +216 -0
  253. package/dot_config/nvim/lua/plugins/completion.lua +60 -0
  254. package/dot_config/nvim/lua/plugins/dap.lua +412 -0
  255. package/dot_config/nvim/lua/plugins/editor.lua +55 -0
  256. package/dot_config/nvim/lua/plugins/git.lua +10 -0
  257. package/dot_config/nvim/lua/plugins/lsp.lua +156 -0
  258. package/dot_config/nvim/lua/plugins/markdown.lua +18 -0
  259. package/dot_config/nvim/lua/plugins/rust.lua +34 -0
  260. package/dot_config/nvim/lua/plugins/sessions.lua +33 -0
  261. package/dot_config/nvim/lua/plugins/ui.lua +509 -0
  262. package/dot_config/paru/paru.conf +10 -0
  263. package/dot_config/pip/pip.conf.tmpl +32 -0
  264. package/dot_config/powershell/Microsoft.PowerShell_profile.ps1.tmpl +81 -0
  265. package/dot_config/pueue/pueue.yml +34 -0
  266. package/dot_config/pypoetry/config.toml +6 -0
  267. package/dot_config/pyrightconfig.json +5 -0
  268. package/dot_config/raycast/README.md +13 -0
  269. package/dot_config/redis/redisclirc +41 -0
  270. package/dot_config/ripgrep/ripgreprc +21 -0
  271. package/dot_config/shell/00-core-paths.sh.tmpl +134 -0
  272. package/dot_config/shell/05-core-safety.sh +48 -0
  273. package/dot_config/shell/10-secrets.sh +41 -0
  274. package/dot_config/shell/40-fzf-defaults.sh.tmpl +17 -0
  275. package/dot_config/shell/40-ls-colors.sh +49 -0
  276. package/dot_config/shell/50-logic-functions-core.sh.tmpl +11 -0
  277. package/dot_config/shell/50-logic-functions.sh.tmpl +11 -0
  278. package/dot_config/shell/51-logic-functions-extra.sh.tmpl +65 -0
  279. package/dot_config/shell/90-ux-aliases.sh.tmpl +121 -0
  280. package/dot_config/shell/91-ux-aliases-lazy.sh.tmpl +55 -0
  281. package/dot_config/shell/Brewfile +207 -0
  282. package/dot_config/shell/Brewfile.cask +92 -0
  283. package/dot_config/shell/Brewfile.cli +127 -0
  284. package/dot_config/shell/README.md +284 -0
  285. package/dot_config/shell/als_data.txt.tmpl +65 -0
  286. package/dot_config/shell/custom/auto_ls.zsh +20 -0
  287. package/dot_config/shell/custom/context_suggest.zsh +68 -0
  288. package/dot_config/shell/custom/error_analysis.zsh +45 -0
  289. package/dot_config/sops/dot_sops.yaml +23 -0
  290. package/dot_config/starship.toml.tmpl +202 -0
  291. package/dot_config/swaylock/config +43 -0
  292. package/dot_config/systemd/user/dotfiles-maintenance.service +8 -0
  293. package/dot_config/systemd/user/dotfiles-maintenance.timer +11 -0
  294. package/dot_config/systemd/user/pueued.service +12 -0
  295. package/dot_config/systemd/user/ssh-agent.service +12 -0
  296. package/dot_config/task/Taskfile.yml +86 -0
  297. package/dot_config/tflint/tflint.hcl +9 -0
  298. package/dot_config/tmux/tmux.conf.tmpl +223 -0
  299. package/dot_config/topgrade.toml.tmpl +54 -0
  300. package/dot_config/user-dirs.dirs +10 -0
  301. package/dot_config/vscode/extensions.txt +11 -0
  302. package/dot_config/vscode/settings.json.tmpl +82 -0
  303. package/dot_config/waybar/config.jsonc.tmpl +90 -0
  304. package/dot_config/waybar/style.css.tmpl +211 -0
  305. package/dot_config/wezterm/wezterm.lua.tmpl +64 -0
  306. package/dot_config/wget/wgetrc +12 -0
  307. package/dot_config/xdg-desktop-portal/niri-portals.conf +5 -0
  308. package/dot_config/yarn/yarnrc.yml +36 -0
  309. package/dot_config/yazi/keymap.toml +67 -0
  310. package/dot_config/yazi/theme.toml +102 -0
  311. package/dot_config/yazi/yazi.toml +40 -0
  312. package/dot_config/zathura/zathurarc +52 -0
  313. package/dot_config/zellij/config.kdl.tmpl +79 -0
  314. package/dot_config/zsh/dot_zprofile +7 -0
  315. package/dot_config/zsh/dot_zshenv +5 -0
  316. package/dot_config/zsh/dot_zshrc.tmpl +635 -0
  317. package/dot_config/zsh/rc.d/00-alias-shims.zsh +99 -0
  318. package/dot_config/zsh/rc.d/05-ssh-agent.zsh +18 -0
  319. package/dot_config/zsh/rc.d/10-env.zsh.tmpl +28 -0
  320. package/dot_config/zsh/rc.d/20-zinit.zsh +65 -0
  321. package/dot_config/zsh/rc.d/30-options.zsh.tmpl +214 -0
  322. package/dot_config/zsh/rc.d/40-bell.zsh +20 -0
  323. package/dot_config/zsh/rc.d/50-login-fortune.zsh +9 -0
  324. package/dot_config/zsh/rc.d/99-alias-wrapper.zsh +32 -0
  325. package/dot_local/bin/executable_ai-update +195 -0
  326. package/dot_local/bin/executable_ai_core +152 -0
  327. package/dot_local/bin/executable_antigravity +11 -0
  328. package/dot_local/bin/executable_b64 +84 -0
  329. package/dot_local/bin/executable_bm +79 -0
  330. package/dot_local/bin/executable_cb +39 -0
  331. package/dot_local/bin/executable_dot +596 -0
  332. package/dot_local/bin/executable_dot-ai +36 -0
  333. package/dot_local/bin/executable_dot-bootstrap +77 -0
  334. package/dot_local/bin/executable_dot-launch-or-focus +52 -0
  335. package/dot_local/bin/executable_dot-load-benchmark +31 -0
  336. package/dot_local/bin/executable_dot-load-benchmark-pty +77 -0
  337. package/dot_local/bin/executable_dot-theme-sync +952 -0
  338. package/dot_local/bin/executable_dot_completion +57 -0
  339. package/dot_local/bin/executable_dtags +28 -0
  340. package/dot_local/bin/executable_epoch +67 -0
  341. package/dot_local/bin/executable_extract +41 -0
  342. package/dot_local/bin/executable_gbd +52 -0
  343. package/dot_local/bin/executable_gd +42 -0
  344. package/dot_local/bin/executable_git-ai-commit +175 -0
  345. package/dot_local/bin/executable_git-ai-diff +169 -0
  346. package/dot_local/bin/executable_gl +101 -0
  347. package/dot_local/bin/executable_hash +161 -0
  348. package/dot_local/bin/executable_hashsum +160 -0
  349. package/dot_local/bin/executable_hex +115 -0
  350. package/dot_local/bin/executable_jsonv +78 -0
  351. package/dot_local/bin/executable_jwt +94 -0
  352. package/dot_local/bin/executable_kill-port +75 -0
  353. package/dot_local/bin/executable_lorem +118 -0
  354. package/dot_local/bin/executable_mkscript +35 -0
  355. package/dot_local/bin/executable_monitor +56 -0
  356. package/dot_local/bin/executable_myip +51 -0
  357. package/dot_local/bin/executable_notify +24 -0
  358. package/dot_local/bin/executable_open +38 -0
  359. package/dot_local/bin/executable_pw +27 -0
  360. package/dot_local/bin/executable_rec-start +46 -0
  361. package/dot_local/bin/executable_rec-stop +35 -0
  362. package/dot_local/bin/executable_regex +132 -0
  363. package/dot_local/bin/executable_start-niri +8 -0
  364. package/dot_local/bin/executable_tmux-sessionizer +314 -0
  365. package/dot_local/bin/executable_tour +177 -0
  366. package/dot_local/bin/executable_up +23 -0
  367. package/dot_local/bin/executable_update +142 -0
  368. package/dot_local/bin/executable_uuid +87 -0
  369. package/dot_local/bin/executable_win +32 -0
  370. package/dot_local/bin/executable_yamlv +57 -0
  371. package/dot_local/share/bash-completion/completions/dot +72 -0
  372. package/dot_local/share/icons/hicolor/128x128/apps/rousseau.png +0 -0
  373. package/dot_local/share/icons/hicolor/16x16/apps/rousseau.png +0 -0
  374. package/dot_local/share/icons/hicolor/24x24/apps/rousseau.png +0 -0
  375. package/dot_local/share/icons/hicolor/256x256/apps/rousseau.png +0 -0
  376. package/dot_local/share/icons/hicolor/32x32/apps/rousseau.png +0 -0
  377. package/dot_local/share/icons/hicolor/48x48/apps/rousseau.png +0 -0
  378. package/dot_local/share/icons/hicolor/512x512/apps/rousseau.png +0 -0
  379. package/dot_local/share/icons/hicolor/64x64/apps/rousseau.png +0 -0
  380. package/dot_local/share/icons/hicolor/96x96/apps/rousseau.png +0 -0
  381. package/dot_local/share/icons/hicolor/scalable/apps/rousseau.png +0 -0
  382. package/dot_local/share/man/man1/dot.1 +149 -0
  383. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_download +64 -0
  384. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_install +18 -0
  385. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_list-all +13 -0
  386. package/dot_local/share/wayland-sessions/niri.desktop.tmpl +6 -0
  387. package/dot_local/share/zsh/completions/.keep +0 -0
  388. package/dot_local/share/zsh/completions/_dot +283 -0
  389. package/install.sh +350 -0
  390. package/package.json +1 -1
  391. package/scripts/ci/check-copyright-headers.sh +96 -0
  392. package/scripts/ci/check-dangerous-chmod.sh +19 -0
  393. package/scripts/ci/check-deps-dev.sh +236 -0
  394. package/scripts/ci/check-insecure-tls.sh +61 -0
  395. package/scripts/ci/check-regression-traceability.sh +67 -0
  396. package/scripts/ci/check-shell-preamble.sh +106 -0
  397. package/scripts/ci/guard-gitleaks-checkout.sh +57 -0
  398. package/scripts/ci/install-chezmoi-verified.sh +64 -0
  399. package/scripts/ci/run-coverage.sh +362 -0
  400. package/scripts/ci/validate-chezmoidata.sh +25 -0
  401. package/scripts/ci/validate-ci-config.sh +224 -0
  402. package/scripts/demo/record.sh +42 -0
  403. package/scripts/diagnostics/a2a-conformance.sh +162 -0
  404. package/scripts/diagnostics/alias-governance.sh +137 -0
  405. package/scripts/diagnostics/aliases-cheatsheet.sh +73 -0
  406. package/scripts/diagnostics/aliases-manifest.sh +31 -0
  407. package/scripts/diagnostics/benchmark.sh +381 -0
  408. package/scripts/diagnostics/conflicts.sh +72 -0
  409. package/scripts/diagnostics/doctor-unified.sh +38 -0
  410. package/scripts/diagnostics/doctor.sh +709 -0
  411. package/scripts/diagnostics/drift-dashboard.sh +201 -0
  412. package/scripts/diagnostics/health.sh +614 -0
  413. package/scripts/diagnostics/history-analysis.sh +85 -0
  414. package/scripts/diagnostics/mcp-doctor.sh +575 -0
  415. package/scripts/diagnostics/perf.sh +452 -0
  416. package/scripts/diagnostics/scorecard.sh +118 -0
  417. package/scripts/diagnostics/secret-governance.sh +58 -0
  418. package/scripts/diagnostics/security-score.sh +438 -0
  419. package/scripts/diagnostics/smoke-test.sh +87 -0
  420. package/scripts/diagnostics/snapshot.sh +89 -0
  421. package/scripts/diagnostics/verify.sh +107 -0
  422. package/scripts/{verify_state.sh → diagnostics/verify_state.sh} +22 -22
  423. package/scripts/diagnostics/version-locks.sh +79 -0
  424. package/scripts/diagnostics/workstation-attestation.sh +186 -0
  425. package/scripts/docs/build-manual.sh +883 -0
  426. package/scripts/docs/check-manual.sh +213 -0
  427. package/scripts/dot/commands/agent.sh +474 -0
  428. package/scripts/dot/commands/ai.sh +481 -0
  429. package/scripts/dot/commands/aliases.sh +250 -0
  430. package/scripts/dot/commands/appearance.sh +80 -0
  431. package/scripts/dot/commands/core.sh +185 -0
  432. package/scripts/dot/commands/diagnostics.sh +229 -0
  433. package/scripts/dot/commands/fleet.sh +399 -0
  434. package/scripts/dot/commands/lint.sh +177 -0
  435. package/scripts/dot/commands/manual.sh +168 -0
  436. package/scripts/dot/commands/meta.sh +248 -0
  437. package/scripts/dot/commands/patterns.sh +54 -0
  438. package/scripts/dot/commands/restore.sh +231 -0
  439. package/scripts/dot/commands/secrets.sh +223 -0
  440. package/scripts/dot/commands/security.sh +76 -0
  441. package/scripts/dot/commands/tools.sh +469 -0
  442. package/scripts/dot/data/alias-deprecations.tsv +2 -0
  443. package/scripts/dot/lib/bento.sh +50 -0
  444. package/scripts/dot/lib/log.sh +200 -0
  445. package/scripts/dot/lib/platform.sh +99 -0
  446. package/scripts/dot/lib/ui.sh +518 -0
  447. package/scripts/dot/lib/utils.sh +377 -0
  448. package/scripts/fonts/install-nerd-fonts.sh +68 -0
  449. package/scripts/fonts/patch-fonts.sh +35 -0
  450. package/scripts/git-hooks/install.sh +11 -0
  451. package/scripts/git-hooks/pre-commit +12 -0
  452. package/scripts/git-hooks/pre-commit-audit.sh +145 -0
  453. package/scripts/git-hooks/pre-push +92 -0
  454. package/scripts/git-hooks/prepare-commit-msg +29 -0
  455. package/scripts/lib/secrets_provider.sh +158 -0
  456. package/scripts/maintenance/check-updates.sh +131 -0
  457. package/scripts/ops/ai-setup.sh +55 -0
  458. package/scripts/ops/bundle.sh +77 -0
  459. package/scripts/ops/chaos.sh +49 -0
  460. package/scripts/ops/chezmoi-apply.sh +270 -0
  461. package/scripts/ops/chezmoi-diff.sh +15 -0
  462. package/scripts/ops/chezmoi-remove.sh +45 -0
  463. package/scripts/ops/chezmoi-update.sh +48 -0
  464. package/scripts/ops/heal-chezmoi.sh +86 -0
  465. package/scripts/ops/heal-system.sh +128 -0
  466. package/scripts/ops/heal-tools.sh +340 -0
  467. package/scripts/ops/heal.sh +222 -0
  468. package/scripts/ops/post-apply-repair.sh +106 -0
  469. package/scripts/ops/prewarm.sh +127 -0
  470. package/scripts/ops/release.sh +252 -0
  471. package/scripts/ops/rollback.sh +589 -0
  472. package/scripts/ops/setup.sh +137 -0
  473. package/scripts/ops/teleport.sh +33 -0
  474. package/scripts/qa/coverage-baseline.sh +60 -0
  475. package/scripts/qa/docs-coverage.sh +111 -0
  476. package/scripts/qa/powershell-contract.ps1 +95 -0
  477. package/scripts/qa/reliability-audit.sh +138 -0
  478. package/scripts/qa/traceability-coverage.sh +116 -0
  479. package/scripts/qa/validate-examples.sh +26 -0
  480. package/scripts/qa/wsl-contract.sh +11 -0
  481. package/scripts/release/package-policy-bundles.sh +125 -0
  482. package/scripts/secrets/age-init.sh +70 -0
  483. package/scripts/secrets/create-secrets-file.sh +45 -0
  484. package/scripts/secrets/encrypt-ssh-key.sh +43 -0
  485. package/scripts/security/backup.sh +57 -0
  486. package/scripts/security/dns-doh.sh +51 -0
  487. package/scripts/security/encryption-check.sh +54 -0
  488. package/scripts/security/enforce-policies.sh +334 -0
  489. package/scripts/security/firewall.sh +90 -0
  490. package/scripts/security/lock-configs.sh +57 -0
  491. package/scripts/security/lock-screen.sh +55 -0
  492. package/scripts/security/manage-secrets.sh +428 -0
  493. package/scripts/security/ssh-cert.sh +203 -0
  494. package/scripts/security/telemetry-kill.sh +50 -0
  495. package/scripts/security/usb-safety.sh +51 -0
  496. package/scripts/theme/apply-gnome-theme.sh +328 -0
  497. package/scripts/theme/extract-theme.py +677 -0
  498. package/scripts/theme/install-boot-logo.sh +62 -0
  499. package/scripts/theme/install-catppuccin-themes.sh +370 -0
  500. package/scripts/theme/install-cursors.sh +25 -0
  501. package/scripts/theme/install-file-icons.sh +26 -0
  502. package/scripts/theme/install-grub-theme.sh +61 -0
  503. package/scripts/theme/install-lock-icon.sh +30 -0
  504. package/scripts/theme/merge-wallpaper.sh +145 -0
  505. package/scripts/theme/rebuild-themes.sh +309 -0
  506. package/scripts/theme/switch.sh +431 -0
  507. package/scripts/theme/wallpaper-rotate.sh +136 -0
  508. package/scripts/theme/wallpaper-sync.sh +397 -0
  509. package/scripts/tools/cmatrix.sh +21 -0
  510. package/scripts/{detect-collisions.py → tools/detect-collisions.py} +2 -2
  511. package/scripts/tools/emoji-picker.sh +48 -0
  512. package/scripts/tools/figlet-banner.sh +18 -0
  513. package/scripts/tools/log-rotate.sh +30 -0
  514. package/scripts/tools/lolcat-wrap.sh +19 -0
  515. package/scripts/tools/pipes.sh +48 -0
  516. package/scripts/tuning/linux.sh +185 -0
  517. package/scripts/tuning/macos.sh +55 -0
  518. package/scripts/uninstall.sh +85 -0
  519. package/scripts/version-sync.sh +487 -0
  520. package/templates/chezmoi-data/geekom-a9.toml.example +21 -0
  521. package/templates/chezmoi-data/mac-m1.toml.example +16 -0
  522. package/templates/chezmoi-data/mac-t2-linux.toml.example +21 -0
  523. package/templates/chezmoi-data/surface-pro-7p.toml.example +21 -0
  524. package/templates/projects/go/.github/workflows/ci.yml +31 -0
  525. package/templates/projects/go/README.md +4 -0
  526. package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +1 -0
  527. package/templates/projects/go/go.sum +0 -0
  528. package/templates/projects/molecule/README.md +7 -0
  529. package/templates/projects/molecule/converge.yml +7 -0
  530. package/templates/projects/molecule/molecule.yml +16 -0
  531. package/templates/projects/node/.github/workflows/ci.yml +30 -0
  532. package/templates/projects/node/README.md +4 -0
  533. package/templates/projects/node/package-lock.json +12 -0
  534. package/templates/projects/node/src/index.js +1 -0
  535. package/templates/projects/packer/README.md +15 -0
  536. package/templates/projects/packer/main.pkr.hcl +15 -0
  537. package/templates/projects/python/.github/workflows/ci.yml +34 -0
  538. package/templates/projects/python/README.md +4 -0
  539. package/templates/projects/python/pyproject.toml +15 -0
  540. package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +1 -0
  541. package/templates/projects/python/tests/test_basic.py +1 -0
  542. package/docs/ARCHITECTURE.md +0 -62
  543. package/docs/COMPLIANCE.md +0 -47
  544. package/docs/OPERATIONS.md +0 -103
  545. package/docs/PR_DESCRIPTION.md +0 -150
  546. package/docs/ROADMAP_legacy.md +0 -556
  547. package/docs/SECURITY_CHECKLIST.md +0 -25
  548. package/docs/TASK.md +0 -99
  549. package/docs/WALKTHROUGH.md +0 -46
  550. package/scripts/backup.sh +0 -142
  551. package/scripts/banner.sh +0 -20
  552. package/scripts/benchmark.sh +0 -20
  553. package/scripts/build.sh +0 -41
  554. package/scripts/clean.sh +0 -31
  555. package/scripts/compile.sh +0 -54
  556. package/scripts/copy.sh +0 -108
  557. package/scripts/doctor.sh +0 -79
  558. package/scripts/dotfiles.sh +0 -63
  559. package/scripts/download.sh +0 -35
  560. package/scripts/help.sh +0 -57
  561. package/scripts/lock-configs.sh +0 -57
  562. package/scripts/package.sh +0 -46
  563. package/scripts/ssh.sh +0 -55
  564. package/scripts/teleport.sh +0 -23
  565. package/scripts/test-aliases.sh +0 -25
  566. package/scripts/test_smoke.sh +0 -88
  567. package/scripts/unpack.sh +0 -28
@@ -0,0 +1,589 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
3
+ # shellcheck disable=SC2034
4
+ # =============================================================================
5
+ # Dotfiles Rollback Script - Self-Healing Configuration Recovery
6
+ # Safely reverts failed dotfile applications with automatic backup
7
+ # Usage: ./scripts/ops/rollback.sh [OPTIONS]
8
+ # =============================================================================
9
+
10
+ set -euo pipefail
11
+
12
+ _cleanup_files=()
13
+ trap 'set +u; rm -f "${_cleanup_files[@]}" 2>/dev/null; set -u' EXIT
14
+
15
+ # Configuration
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ # shellcheck source=../dot/lib/ui.sh
18
+ # shellcheck disable=SC1091
19
+ source "$SCRIPT_DIR/../dot/lib/ui.sh"
20
+ # shellcheck source=../dot/lib/log.sh
21
+ # shellcheck disable=SC1091
22
+ source "$SCRIPT_DIR/../dot/lib/log.sh"
23
+ export DOT_COMMAND="rollback"
24
+ REPO_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
25
+ # Resolve symlinks for consistent path handling
26
+ if command -v realpath >/dev/null 2>&1; then
27
+ DOTFILES_SOURCE="$(realpath "${HOME}/.dotfiles" 2>/dev/null || echo "${HOME}/.dotfiles")"
28
+ elif command -v readlink >/dev/null 2>&1; then
29
+ DOTFILES_SOURCE="$(readlink -f "${HOME}/.dotfiles" 2>/dev/null || echo "${HOME}/.dotfiles")"
30
+ else
31
+ DOTFILES_SOURCE="${HOME}/.dotfiles"
32
+ fi
33
+ BACKUP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/dotfiles/backups"
34
+ STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/dotfiles"
35
+ ROLLBACK_LOG="$STATE_DIR/rollback.log"
36
+ MAX_BACKUPS=10
37
+
38
+ # Logging — delegates to shared ui.sh primitives
39
+ ui_init
40
+ log() { printf '%b\n' "$*"; }
41
+ log_info() { ui_info "$@"; }
42
+ log_success() { ui_ok "$@"; }
43
+ log_warn() { ui_warn "$@"; }
44
+ log_error() { ui_err "$@"; }
45
+ log_step() {
46
+ echo ""
47
+ ui_section "$*"
48
+ }
49
+
50
+ # Persistent logging
51
+ persist_log() {
52
+ mkdir -p "$STATE_DIR"
53
+ echo "[$(date -Iseconds)] $*" >>"$ROLLBACK_LOG"
54
+ }
55
+
56
+ usage() {
57
+ cat <<EOF
58
+ Dotfiles Rollback & Recovery Tool
59
+
60
+ Usage: $(basename "$0") [COMMAND] [OPTIONS]
61
+
62
+ Commands:
63
+ status Show current state and available backups
64
+ backup Create a manual backup of current dotfiles
65
+ rollback Rollback to the previous backup
66
+ rollback-to N Rollback to specific backup number (from status list)
67
+ git-reset Reset to last known good git commit
68
+ restore FILE Restore a specific file from backup
69
+ clean Remove old backups (keeps last $MAX_BACKUPS)
70
+
71
+ Options:
72
+ -f, --force Skip confirmation prompts
73
+ -n, --dry-run Show what would be done without making changes
74
+ -v, --verbose Show detailed output
75
+ -h, --help Show this help message
76
+
77
+ Examples:
78
+ $(basename "$0") status # List available backups
79
+ $(basename "$0") backup # Create manual backup
80
+ $(basename "$0") rollback # Rollback to previous state
81
+ $(basename "$0") rollback-to 3 # Rollback to backup #3
82
+ $(basename "$0") git-reset # Reset to last good commit
83
+ $(basename "$0") restore .bashrc # Restore specific file
84
+
85
+ EOF
86
+ }
87
+
88
+ # Ensure directories exist
89
+ ensure_dirs() {
90
+ mkdir -p "$BACKUP_DIR" "$STATE_DIR"
91
+ }
92
+
93
+ # List available backups
94
+ list_backups() {
95
+ local backups=()
96
+ local i=1
97
+
98
+ if [[ ! -d "$BACKUP_DIR" ]]; then
99
+ log_warn "No backup directory found"
100
+ return 1
101
+ fi
102
+
103
+ log_step "Available Backups"
104
+ echo ""
105
+
106
+ while IFS= read -r backup; do
107
+ if [[ -d "$backup" ]]; then
108
+ local name timestamp size
109
+ name=$(basename "$backup")
110
+ timestamp=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$backup" 2>/dev/null || stat -c "%y" "$backup" 2>/dev/null | cut -d'.' -f1)
111
+ size=$(du -sh "$backup" 2>/dev/null | cut -f1)
112
+ printf " %2d. %-30s %s %s\n" "$i" "$name" "$timestamp" "$size"
113
+ ((i++)) || true
114
+ fi
115
+ done < <(find "$BACKUP_DIR" -maxdepth 1 -type d -name "backup_*" | sort -r)
116
+
117
+ if [[ $i -eq 1 ]]; then
118
+ log_warn "No backups found"
119
+ return 1
120
+ fi
121
+ echo ""
122
+ }
123
+
124
+ # Create a backup
125
+ create_backup() {
126
+ local reason="${1:-manual}"
127
+ local timestamp
128
+ timestamp=$(date +"%Y%m%d_%H%M%S")
129
+ local backup_name="backup_${timestamp}_${reason}"
130
+ local backup_path="$BACKUP_DIR/$backup_name"
131
+
132
+ log_step "Creating Backup: $backup_name"
133
+ ensure_dirs
134
+
135
+ mkdir -p "$backup_path"
136
+
137
+ # List of files/directories to backup
138
+ local targets=(
139
+ "$HOME/.bashrc"
140
+ "$HOME/.zshrc"
141
+ "$HOME/.zshenv"
142
+ "$HOME/.profile"
143
+ "$HOME/.inputrc"
144
+ "$HOME/.vimrc"
145
+ "$HOME/.gitconfig"
146
+ "$HOME/.config/shell"
147
+ "$HOME/.config/nvim"
148
+ "$HOME/.config/git"
149
+ "$HOME/.config/tmux"
150
+ "$HOME/.config/chezmoi"
151
+ )
152
+
153
+ local backed_up=0
154
+ for target in "${targets[@]}"; do
155
+ if [[ -e "$target" ]]; then
156
+ local rel_path="${target#"$HOME"/}"
157
+ local dest_dir
158
+ dest_dir=$(dirname "$backup_path/$rel_path")
159
+ mkdir -p "$dest_dir"
160
+ cp -a "$target" "$backup_path/$rel_path" 2>/dev/null || true
161
+ ((backed_up++)) || true
162
+ [[ "$VERBOSE" == "1" ]] && log_info "Backed up: $rel_path"
163
+ fi
164
+ done
165
+
166
+ local git_commit="unknown"
167
+ if cd "$DOTFILES_SOURCE" 2>/dev/null; then
168
+ git_commit=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
169
+ fi
170
+
171
+ # Record metadata
172
+ cat >"$backup_path/.backup_meta" <<EOF
173
+ timestamp=$timestamp
174
+ reason=$reason
175
+ chezmoi_version=$(chezmoi --version 2>/dev/null || echo "unknown")
176
+ git_commit=$git_commit
177
+ files_backed_up=$backed_up
178
+ EOF
179
+
180
+ log_success "Backup created: $backup_path ($backed_up items)"
181
+ persist_log "BACKUP_CREATED: $backup_name ($backed_up items)"
182
+
183
+ # Cleanup old backups
184
+ cleanup_old_backups
185
+ }
186
+
187
+ # Cleanup old backups, keeping only MAX_BACKUPS
188
+ cleanup_old_backups() {
189
+ local count
190
+ count=$(find "$BACKUP_DIR" -maxdepth 1 -type d -name "backup_*" 2>/dev/null | wc -l | tr -d ' ')
191
+
192
+ if [[ $count -gt $MAX_BACKUPS ]]; then
193
+ local to_delete=$((count - MAX_BACKUPS))
194
+ log_info "Cleaning up $to_delete old backup(s)..."
195
+
196
+ find "$BACKUP_DIR" -maxdepth 1 -type d -name "backup_*" | sort | head -n "$to_delete" | while read -r old; do
197
+ rm -rf "$old"
198
+ [[ "$VERBOSE" == "1" ]] && log_info "Removed: $(basename "$old")"
199
+ done
200
+ fi
201
+ }
202
+
203
+ # Get the most recent backup
204
+ get_latest_backup() {
205
+ find "$BACKUP_DIR" -maxdepth 1 -type d -name "backup_*" 2>/dev/null | sort -r | head -1
206
+ }
207
+
208
+ # Get backup by index (1-based)
209
+ get_backup_by_index() {
210
+ local index="$1"
211
+ find "$BACKUP_DIR" -maxdepth 1 -type d -name "backup_*" | sort -r | sed -n "${index}p"
212
+ }
213
+
214
+ # Rollback to a specific backup
215
+ perform_rollback() {
216
+ local backup_path="$1"
217
+ local dry_run="${2:-0}"
218
+
219
+ if [[ ! -d "$backup_path" ]]; then
220
+ log_error "Backup not found: $backup_path"
221
+ return 1
222
+ fi
223
+
224
+ log_step "Rollback from: $(basename "$backup_path")"
225
+
226
+ # First, create a safety backup of current state
227
+ if [[ "$dry_run" != "1" ]]; then
228
+ create_backup "pre_rollback"
229
+ fi
230
+
231
+ # Restore files
232
+ local restored=0
233
+ while IFS= read -r -d '' file; do
234
+ local rel_path="${file#"$backup_path"/}"
235
+ local dest="$HOME/$rel_path"
236
+
237
+ # Skip metadata file
238
+ [[ "$rel_path" == ".backup_meta" ]] && continue
239
+
240
+ if [[ "$dry_run" == "1" ]]; then
241
+ log_info "[DRY-RUN] Would restore: $rel_path"
242
+ else
243
+ local dest_dir
244
+ dest_dir=$(dirname "$dest")
245
+ mkdir -p "$dest_dir"
246
+ cp -a "$file" "$dest"
247
+ ((restored++)) || true
248
+ [[ "$VERBOSE" == "1" ]] && log_info "Restored: $rel_path"
249
+ fi
250
+ done < <(find "$backup_path" -type f -print0)
251
+
252
+ if [[ "$dry_run" != "1" ]]; then
253
+ log_success "Rollback complete: $restored file(s) restored"
254
+ persist_log "ROLLBACK: from $(basename "$backup_path"), $restored files restored"
255
+ dot_log info "rollback_end" "files=$restored" "backup=$(basename "$backup_path")"
256
+
257
+ # AI-Driven Analysis of the failure
258
+ if command -v dot >/dev/null 2>&1 && [[ "${DOTFILES_AI:-0}" == "1" ]]; then
259
+ log_step "AI Root-Cause Analysis"
260
+ local drift
261
+ drift=$(chezmoi status 2>/dev/null || true)
262
+ local last_log=""
263
+ if cd "$DOTFILES_SOURCE" 2>/dev/null; then
264
+ last_log=$(git log -n 5 --oneline 2>/dev/null || true)
265
+ fi
266
+
267
+ local ai_prompt
268
+ ai_prompt="System rollback was triggered from $(basename "$backup_path").
269
+ Recent Git History:
270
+ $last_log
271
+
272
+ Current Drift after rollback:
273
+ $drift
274
+
275
+ Analyze why the environment may have reached a state requiring rollback and suggest architectural hardening steps."
276
+
277
+ dot cl --pattern hardener "$ai_prompt" || true
278
+ fi
279
+ fi
280
+ }
281
+
282
+ # Git-based rollback
283
+ git_reset() {
284
+ local dry_run="${1:-0}"
285
+
286
+ if [[ ! -d "$DOTFILES_SOURCE/.git" ]]; then
287
+ log_error "Not a git repository: $DOTFILES_SOURCE"
288
+ return 1
289
+ fi
290
+
291
+ log_step "Git Reset Recovery"
292
+
293
+ cd "$DOTFILES_SOURCE"
294
+
295
+ # Show recent commits
296
+ log_info "Recent commits:"
297
+ git log --oneline -5
298
+ echo ""
299
+
300
+ # Check for uncommitted changes
301
+ if [[ -n "$(git status --porcelain)" ]]; then
302
+ log_warn "Uncommitted changes detected"
303
+ if [[ "$FORCE" == "1" ]]; then
304
+ git stash push -m "Auto-stash before rollback $(date +%Y%m%d_%H%M%S)"
305
+ log_success "Changes auto-stashed (use 'git stash pop' to recover)"
306
+ else
307
+ read -t 30 -rp "Stash changes? [y/N] " response || response="N"
308
+ if [[ "$response" =~ ^[Yy]$ ]]; then
309
+ git stash push -m "Auto-stash before rollback $(date +%Y%m%d_%H%M%S)"
310
+ log_success "Changes stashed"
311
+ fi
312
+ fi
313
+ fi
314
+
315
+ # Find last good commit (last tag or HEAD~1)
316
+ local target_commit
317
+ target_commit=$(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~1")
318
+
319
+ log_info "Reset target: $target_commit"
320
+
321
+ if [[ "$dry_run" == "1" ]]; then
322
+ log_info "[DRY-RUN] Would reset to: $target_commit"
323
+ git diff --stat HEAD "$target_commit"
324
+ else
325
+ # Create backup first
326
+ create_backup "pre_git_reset"
327
+
328
+ git reset --hard "$target_commit"
329
+ log_success "Git reset to: $target_commit"
330
+
331
+ # Re-apply chezmoi
332
+ if command -v chezmoi >/dev/null 2>&1; then
333
+ log_info "Re-applying chezmoi..."
334
+ chezmoi apply --force --exclude=scripts
335
+ log_success "Chezmoi re-applied"
336
+ fi
337
+
338
+ persist_log "GIT_RESET: to $target_commit"
339
+ fi
340
+ }
341
+
342
+ # Restore a specific file from the latest backup
343
+ restore_file() {
344
+ local file_path="$1"
345
+ local dry_run="${2:-0}"
346
+
347
+ # Normalize path
348
+ file_path="${file_path#"$HOME"/}"
349
+ file_path="${file_path#./}"
350
+ file_path="${file_path#~/}"
351
+
352
+ # Validate against path traversal (e.g., "../../etc/passwd")
353
+ # Reject paths containing ".." components
354
+ if [[ "$file_path" == *".."* ]]; then
355
+ log_error "Path traversal detected in file path: $file_path"
356
+ return 1
357
+ fi
358
+
359
+ local backup
360
+ backup=$(get_latest_backup)
361
+
362
+ if [[ -z "$backup" ]]; then
363
+ log_error "No backups available"
364
+ return 1
365
+ fi
366
+
367
+ local source_file="$backup/$file_path"
368
+
369
+ # shellcheck disable=SC1091
370
+ # Verify resolved source path stays within the backup directory
371
+ local resolved_source
372
+ resolved_source="$(cd "$(dirname "$source_file")" 2>/dev/null && pwd)/$(basename "$source_file")" || {
373
+ # shellcheck disable=SC1091
374
+ log_error "Cannot resolve source path: $source_file"
375
+ return 1
376
+ }
377
+ if [[ "$resolved_source" != "$backup/"* ]]; then
378
+ log_error "Path traversal detected: resolved path escapes backup directory"
379
+ return 1
380
+ fi
381
+
382
+ # Verify resolved destination stays within HOME
383
+ local resolved_dest_dir
384
+ resolved_dest_dir="$(cd "$(dirname "$HOME/$file_path")" 2>/dev/null && pwd)" || {
385
+ log_error "Cannot resolve destination directory for: $file_path"
386
+ return 1
387
+ }
388
+ if [[ "$resolved_dest_dir" != "$HOME"* ]]; then
389
+ log_error "Path traversal detected: destination escapes HOME directory"
390
+ return 1
391
+ fi
392
+
393
+ if [[ ! -f "$source_file" ]]; then
394
+ log_error "File not found in backup: $file_path"
395
+ log_info "Available files in backup:"
396
+ find "$backup" -type f -name "*.backup_meta" -prune -o -type f -print | sed "s|$backup/||" | head -20
397
+ return 1
398
+ fi
399
+
400
+ local dest="$HOME/$file_path"
401
+
402
+ if [[ "$dry_run" == "1" ]]; then
403
+ log_info "[DRY-RUN] Would restore: $file_path"
404
+ log_info "From: $source_file"
405
+ log_info "To: $dest"
406
+ else
407
+ # Backup current version
408
+ if [[ -f "$dest" ]]; then
409
+ cp "$dest" "${dest}.rollback.$(date +%Y%m%d_%H%M%S)"
410
+ fi
411
+
412
+ local dest_dir
413
+ dest_dir=$(dirname "$dest")
414
+ mkdir -p "$dest_dir"
415
+ cp -a "$source_file" "$dest"
416
+ log_success "Restored: $file_path"
417
+ persist_log "RESTORE_FILE: $file_path"
418
+ fi
419
+ }
420
+
421
+ # Show current status
422
+ show_status() {
423
+ log_step "Dotfiles Rollback Status"
424
+ echo ""
425
+
426
+ # Chezmoi status
427
+ if command -v chezmoi >/dev/null 2>&1; then
428
+ log_info "Chezmoi version: $(chezmoi --version | head -1)"
429
+ local status
430
+ status=$(chezmoi status 2>/dev/null || echo "")
431
+ if [[ -z "$status" ]]; then
432
+ log_success "Chezmoi: All files in sync"
433
+ else
434
+ log_warn "Chezmoi: $(echo "$status" | wc -l | tr -d ' ') file(s) out of sync"
435
+ fi
436
+ fi
437
+
438
+ # Git status
439
+ if [[ -d "$DOTFILES_SOURCE/.git" ]]; then
440
+ cd "$DOTFILES_SOURCE"
441
+ log_info "Git commit: $(git rev-parse --short HEAD)"
442
+ log_info "Git branch: $(git branch --show-current)"
443
+ local changes
444
+ changes=$(git status --porcelain | wc -l | tr -d ' ')
445
+ if [[ "$changes" -eq 0 ]]; then
446
+ log_success "Git: Working tree clean"
447
+ else
448
+ log_warn "Git: $changes uncommitted change(s)"
449
+ fi
450
+ fi
451
+
452
+ # List backups
453
+ echo ""
454
+ list_backups || true
455
+
456
+ # Recent rollback log
457
+ if [[ -f "$ROLLBACK_LOG" ]]; then
458
+ echo ""
459
+ log_info "Recent rollback activity:"
460
+ tail -5 "$ROLLBACK_LOG" | while read -r line; do
461
+ echo " $line"
462
+ done
463
+ fi
464
+ }
465
+
466
+ # =============================================================================
467
+ # Main
468
+ # =============================================================================
469
+
470
+ FORCE=0
471
+ DRY_RUN=0
472
+ VERBOSE=0
473
+
474
+ main() {
475
+ local command="${1:-status}"
476
+ shift || true
477
+
478
+ if [[ "$command" == "help" ]]; then
479
+ usage
480
+ exit 0
481
+ fi
482
+
483
+ # Parse global options
484
+ while [[ $# -gt 0 ]]; do
485
+ case "$1" in
486
+ -f | --force)
487
+ FORCE=1
488
+ shift
489
+ ;;
490
+ -n | --dry-run)
491
+ DRY_RUN=1
492
+ shift
493
+ ;;
494
+ -v | --verbose)
495
+ VERBOSE=1
496
+ shift
497
+ ;;
498
+ -h | --help)
499
+ usage
500
+ exit 0
501
+ ;;
502
+ *) break ;;
503
+ esac
504
+ done
505
+
506
+ ensure_dirs
507
+
508
+ # Concurrency guard
509
+ LOCK_FILE="${XDG_RUNTIME_DIR:-/tmp}/dotfiles-rollback.lock"
510
+ if command -v flock >/dev/null 2>&1; then
511
+ exec 9>"$LOCK_FILE"
512
+ if ! flock -n 9; then
513
+ ui_warn "Already running" "Another rollback instance is active"
514
+ exit 0
515
+ fi
516
+ fi
517
+
518
+ dot_log info "rollback_start" "command=$command"
519
+
520
+ case "$command" in
521
+ status)
522
+ show_status
523
+ ;;
524
+ backup)
525
+ create_backup "manual"
526
+ ;;
527
+ rollback)
528
+ local latest
529
+ latest=$(get_latest_backup)
530
+ if [[ -z "$latest" ]]; then
531
+ log_error "No backups available for rollback"
532
+ exit 1
533
+ fi
534
+ if [[ "$FORCE" != "1" ]] && [[ "$DRY_RUN" != "1" ]]; then
535
+ read -t 30 -rp "Rollback to $(basename "$latest")? [y/N] " response || response="N"
536
+ [[ ! "$response" =~ ^[Yy]$ ]] && exit 0
537
+ fi
538
+ perform_rollback "$latest" "$DRY_RUN"
539
+ ;;
540
+ rollback-to)
541
+ local index="${1:-}"
542
+ if [[ -z "$index" ]] || ! [[ "$index" =~ ^[0-9]+$ ]]; then
543
+ log_error "Please specify a backup number (see 'status' command)"
544
+ exit 1
545
+ fi
546
+ local backup
547
+ backup=$(get_backup_by_index "$index")
548
+ if [[ -z "$backup" ]]; then
549
+ log_error "Backup #$index not found"
550
+ exit 1
551
+ fi
552
+ if [[ "$FORCE" != "1" ]] && [[ "$DRY_RUN" != "1" ]]; then
553
+ read -t 30 -rp "Rollback to $(basename "$backup")? [y/N] " response || response="N"
554
+ [[ ! "$response" =~ ^[Yy]$ ]] && exit 0
555
+ fi
556
+ perform_rollback "$backup" "$DRY_RUN"
557
+ ;;
558
+ git-reset)
559
+ if [[ "$FORCE" != "1" ]] && [[ "$DRY_RUN" != "1" ]]; then
560
+ read -t 30 -rp "Reset to last known good commit? [y/N] " response || response="N"
561
+ [[ ! "$response" =~ ^[Yy]$ ]] && exit 0
562
+ fi
563
+ git_reset "$DRY_RUN"
564
+ ;;
565
+ restore)
566
+ local file="${1:-}"
567
+ if [[ -z "$file" ]]; then
568
+ log_error "Please specify a file to restore"
569
+ exit 1
570
+ fi
571
+ restore_file "$file" "$DRY_RUN"
572
+ ;;
573
+ clean)
574
+ log_info "Cleaning old backups (keeping last $MAX_BACKUPS)..."
575
+ cleanup_old_backups
576
+ log_success "Cleanup complete"
577
+ ;;
578
+ -h | --help | help)
579
+ usage
580
+ ;;
581
+ *)
582
+ log_error "Unknown command: $command"
583
+ usage
584
+ exit 1
585
+ ;;
586
+ esac
587
+ }
588
+
589
+ main "$@"