@sebastienrousseau/dotfiles 0.2.519 → 0.2.521

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 (306) hide show
  1. package/CHANGELOG.md +200 -0
  2. package/LICENSE-APACHE +190 -0
  3. package/{LICENSE → LICENSE-MIT} +1 -1
  4. package/README.md +1172 -166
  5. package/install.sh +77 -11
  6. package/package.json +8 -8
  7. package/tools/README.md +49 -0
  8. package/tools/ci/install-chezmoi-verified.sh +68 -0
  9. package/docs/.vitepress/reports/localization-readability-audit.md +0 -73
  10. package/docs/AI.md +0 -179
  11. package/docs/CNAME +0 -1
  12. package/docs/CONFIG_STRATEGY.md +0 -124
  13. package/docs/COPYRIGHT +0 -7
  14. package/docs/GOVERNANCE.md +0 -98
  15. package/docs/MAINTAINERS.md +0 -41
  16. package/docs/NAMING_CONVENTIONS.md +0 -102
  17. package/docs/OPENCODE.md +0 -127
  18. package/docs/README.md +0 -84
  19. package/docs/STRUCTURE.md +0 -102
  20. package/docs/adr/ADR-001-ci-cd-pipeline.md +0 -118
  21. package/docs/adr/ADR-002-shell-performance.md +0 -130
  22. package/docs/adr/ADR-003-security-first.md +0 -158
  23. package/docs/adr/ADR-004-cli-architecture.md +0 -171
  24. package/docs/adr/ADR-005-chezmoi-choice.md +0 -99
  25. package/docs/adr/ADR-006-shell-selection.md +0 -124
  26. package/docs/adr/ADR-007-multi-shell-parity.md +0 -62
  27. package/docs/adr/ADR-008-alias-system-architecture.md +0 -95
  28. package/docs/adr/ADR-009-wallpaper-driven-theming.md +0 -131
  29. package/docs/adr/ADR-010-starship-transient-prompt.md +0 -144
  30. package/docs/adr/ADR-011-nushell-tier3-keep.md +0 -144
  31. package/docs/adr/ADR-012-ai-fleet-local-proxy.md +0 -79
  32. package/docs/adr/README.md +0 -40
  33. package/docs/architecture/AI_COST_OPTIMIZATION.md +0 -144
  34. package/docs/architecture/ARCHITECTURE.md +0 -117
  35. package/docs/architecture/INTEROP.md +0 -44
  36. package/docs/architecture/REPO_LAYOUT.md +0 -241
  37. package/docs/architecture/WALKTHROUGH.md +0 -86
  38. package/docs/architecture/fleet-deployment.md +0 -77
  39. package/docs/archive/EUXIS_2026_REVIEW.md +0 -127
  40. package/docs/archive/LEGACY_ROADMAP.md +0 -6
  41. package/docs/archive/MILESTONE_v0.2.493.md +0 -47
  42. package/docs/archive/PLAN.md +0 -199
  43. package/docs/archive/REPO_AUDIT.md +0 -31
  44. package/docs/articles/.pages +0 -6
  45. package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +0 -216
  46. package/docs/articles/2026-07-05-fish-startup-abbr.md +0 -153
  47. package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +0 -128
  48. package/docs/articles/index.md +0 -36
  49. package/docs/guides/INSTALL.md +0 -144
  50. package/docs/guides/NEOVIM_IDE_GUIDE.md +0 -61
  51. package/docs/guides/THEMING.md +0 -230
  52. package/docs/guides/TROUBLESHOOTING.md +0 -176
  53. package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +0 -792
  54. package/docs/index.md +0 -132
  55. package/docs/interop/A2A.md +0 -39
  56. package/docs/interop/POWERSHELL.md +0 -102
  57. package/docs/manual/00-introduction.md +0 -89
  58. package/docs/manual/01-concepts/01-architecture.md +0 -138
  59. package/docs/manual/01-concepts/02-trust-model.md +0 -183
  60. package/docs/manual/01-concepts/03-theme-engine.md +0 -186
  61. package/docs/manual/01-concepts/04-fleet.md +0 -148
  62. package/docs/manual/01-concepts/05-self-healing.md +0 -204
  63. package/docs/manual/02-tutorials/01-first-install.md +0 -197
  64. package/docs/manual/02-tutorials/02-add-wallpaper.md +0 -216
  65. package/docs/manual/02-tutorials/03-create-profile.md +0 -244
  66. package/docs/manual/02-tutorials/04-encrypt-secret.md +0 -281
  67. package/docs/manual/02-tutorials/05-deploy-fleet.md +0 -283
  68. package/docs/manual/03-reference/01-dot-cli.md +0 -450
  69. package/docs/manual/03-reference/02-config-files.md +0 -265
  70. package/docs/manual/03-reference/03-environment.md +0 -124
  71. package/docs/manual/03-reference/04-templates.md +0 -190
  72. package/docs/manual/03-reference/05-feature-flags.md +0 -187
  73. package/docs/manual/04-cookbook/01-recipes.md +0 -285
  74. package/docs/manual/04-cookbook/02-troubleshooting.md +0 -351
  75. package/docs/manual/04-cookbook/03-faq.md +0 -175
  76. package/docs/manual/05-appendices/A-platform-matrix.md +0 -101
  77. package/docs/manual/05-appendices/B-security-checklist.md +0 -85
  78. package/docs/manual/05-appendices/C-glossary.md +0 -40
  79. package/docs/manual/05-appendices/D-bibliography.md +0 -58
  80. package/docs/manual/05-appendices/E-license.md +0 -38
  81. package/docs/manual/_toc.yml +0 -58
  82. package/docs/manual/command-index.md +0 -155
  83. package/docs/manual/concept-index.md +0 -168
  84. package/docs/manual/index.md +0 -66
  85. package/docs/operations/ARCHITECTURE_ROADMAP.md +0 -7
  86. package/docs/operations/ATTESTATION.md +0 -44
  87. package/docs/operations/CI_CADENCE.md +0 -107
  88. package/docs/operations/CI_COMPOSITES.md +0 -156
  89. package/docs/operations/COMPLETIONS.md +0 -123
  90. package/docs/operations/COVERAGE.md +0 -204
  91. package/docs/operations/DRIFT.md +0 -107
  92. package/docs/operations/HARD_AUDIT_2026.md +0 -631
  93. package/docs/operations/MAINTENANCE.md +0 -63
  94. package/docs/operations/MANIFEST.md +0 -127
  95. package/docs/operations/MIGRATION.md +0 -109
  96. package/docs/operations/OPERATIONS.md +0 -188
  97. package/docs/operations/PERFORMANCE.md +0 -133
  98. package/docs/operations/REGISTRY.md +0 -90
  99. package/docs/operations/RELEASE_PIPELINE.md +0 -128
  100. package/docs/operations/RELIABILITY.md +0 -122
  101. package/docs/operations/RFC_v0_2_503_reorganization.md +0 -280
  102. package/docs/operations/ROADMAP.md +0 -10
  103. package/docs/operations/ROADMAP_2026.md +0 -7
  104. package/docs/operations/ROADMAP_V0_2_503.md +0 -10
  105. package/docs/operations/TESTING.md +0 -216
  106. package/docs/operations/TRACEABILITY.md +0 -43
  107. package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +0 -65
  108. package/docs/operations/VERSION_SYNC.md +0 -393
  109. package/docs/reference/ALIASES.md +0 -131
  110. package/docs/reference/ALIASES_CHEATSHEET.md +0 -32
  111. package/docs/reference/ALIASES_DEPRECATIONS.md +0 -13
  112. package/docs/reference/FEATURES.md +0 -66
  113. package/docs/reference/FONTS.md +0 -112
  114. package/docs/reference/POWERSHELL_PARITY.md +0 -82
  115. package/docs/reference/PROFILES.md +0 -69
  116. package/docs/reference/SCREENSHOTS.md +0 -121
  117. package/docs/reference/SCRIPTS.md +0 -71
  118. package/docs/reference/SUPPORT_MATRIX.md +0 -80
  119. package/docs/reference/THEMES.md +0 -117
  120. package/docs/reference/TOOLS.md +0 -110
  121. package/docs/reference/UTILS.md +0 -242
  122. package/docs/registry.json +0 -6
  123. package/docs/schema/dot-env-v1.json +0 -110
  124. package/docs/schema/dot-registry-v1.json +0 -33
  125. package/docs/security/AI_ACT_COMPLIANCE.md +0 -94
  126. package/docs/security/AUDIT_BYPASS.md +0 -103
  127. package/docs/security/AUTOMATION_SECRETS.md +0 -26
  128. package/docs/security/CI_EGRESS_ALLOWLIST.md +0 -127
  129. package/docs/security/CI_PINNING.md +0 -129
  130. package/docs/security/COMMIT_SIGNING.md +0 -138
  131. package/docs/security/COMPLIANCE.md +0 -458
  132. package/docs/security/DEPS_DEV_EXCEPTIONS.md +0 -86
  133. package/docs/security/DISCLOSURE.md +0 -130
  134. package/docs/security/ENCRYPTION.md +0 -57
  135. package/docs/security/FMEA.md +0 -159
  136. package/docs/security/FUZZING.md +0 -114
  137. package/docs/security/HISTORY_FILTERING.md +0 -132
  138. package/docs/security/INCIDENT_RESPONSE.md +0 -579
  139. package/docs/security/INSTALL_VERIFICATION.md +0 -122
  140. package/docs/security/KEYS.md +0 -49
  141. package/docs/security/KEY_ROTATION.md +0 -303
  142. package/docs/security/MCP_POLICY.md +0 -78
  143. package/docs/security/POLICY_RELEASES.md +0 -37
  144. package/docs/security/README.md +0 -28
  145. package/docs/security/SCORECARD.md +0 -195
  146. package/docs/security/SECRETS.md +0 -158
  147. package/docs/security/SECURITY.md +0 -45
  148. package/docs/security/SECURITY_CHECKLIST.md +0 -55
  149. package/docs/security/SHELL_EXEMPTIONS.md +0 -145
  150. package/docs/security/SOUP_REGISTER.md +0 -36
  151. package/docs/security/THREAT_MODEL.md +0 -130
  152. package/docs/security/VERIFICATION_VALIDATION.md +0 -228
  153. package/docs/security/VERIFY_RELEASE.md +0 -201
  154. package/docs/security/security-pubkey.asc +0 -15
  155. package/docs/stylesheets/extra.css +0 -444
  156. package/docs/themes/README.md +0 -10
  157. package/docs/themes/VISUAL_INTEGRITY_REPORT.md +0 -30
  158. package/docs/themes/hero-shot.svg +0 -78
  159. package/scripts/README.md +0 -123
  160. package/scripts/ci/check-copyright-headers.sh +0 -8
  161. package/scripts/ci/check-shell-preamble.sh +0 -8
  162. package/scripts/ci/guard-gitleaks-checkout.sh +0 -8
  163. package/scripts/demo/record.sh +0 -43
  164. package/scripts/diagnostics/a2a-conformance.sh +0 -163
  165. package/scripts/diagnostics/alias-governance.sh +0 -138
  166. package/scripts/diagnostics/aliases-cheatsheet.sh +0 -74
  167. package/scripts/diagnostics/aliases-manifest.sh +0 -77
  168. package/scripts/diagnostics/benchmark.sh +0 -408
  169. package/scripts/diagnostics/conflicts.sh +0 -73
  170. package/scripts/diagnostics/doctor-unified.sh +0 -39
  171. package/scripts/diagnostics/doctor.sh +0 -751
  172. package/scripts/diagnostics/drift-dashboard.sh +0 -202
  173. package/scripts/diagnostics/health.sh +0 -623
  174. package/scripts/diagnostics/history-analysis.sh +0 -86
  175. package/scripts/diagnostics/mcp-doctor.sh +0 -582
  176. package/scripts/diagnostics/perf.sh +0 -453
  177. package/scripts/diagnostics/scorecard.sh +0 -119
  178. package/scripts/diagnostics/secret-governance.sh +0 -65
  179. package/scripts/diagnostics/security-score.sh +0 -467
  180. package/scripts/diagnostics/smoke-test.sh +0 -88
  181. package/scripts/diagnostics/snapshot.sh +0 -90
  182. package/scripts/diagnostics/verify.sh +0 -108
  183. package/scripts/diagnostics/verify_state.sh +0 -73
  184. package/scripts/diagnostics/version-locks.sh +0 -94
  185. package/scripts/diagnostics/workstation-attestation.sh +0 -187
  186. package/scripts/dot/commands/agent.sh +0 -485
  187. package/scripts/dot/commands/agents.sh +0 -336
  188. package/scripts/dot/commands/ai.sh +0 -587
  189. package/scripts/dot/commands/aliases.sh +0 -277
  190. package/scripts/dot/commands/appearance.sh +0 -110
  191. package/scripts/dot/commands/completion.sh +0 -134
  192. package/scripts/dot/commands/core.sh +0 -217
  193. package/scripts/dot/commands/diagnostics.sh +0 -265
  194. package/scripts/dot/commands/env-emit.sh +0 -203
  195. package/scripts/dot/commands/fleet.sh +0 -688
  196. package/scripts/dot/commands/init.sh +0 -185
  197. package/scripts/dot/commands/lint.sh +0 -208
  198. package/scripts/dot/commands/manual.sh +0 -169
  199. package/scripts/dot/commands/meta.sh +0 -333
  200. package/scripts/dot/commands/patterns.sh +0 -55
  201. package/scripts/dot/commands/registry.sh +0 -419
  202. package/scripts/dot/commands/restore.sh +0 -232
  203. package/scripts/dot/commands/secrets.sh +0 -296
  204. package/scripts/dot/commands/security.sh +0 -102
  205. package/scripts/dot/commands/tools.sh +0 -556
  206. package/scripts/dot/data/alias-deprecations.tsv +0 -2
  207. package/scripts/dot/powershell/Dot.psm1 +0 -319
  208. package/scripts/fonts/install-nerd-fonts.sh +0 -75
  209. package/scripts/fonts/patch-fonts.sh +0 -36
  210. package/scripts/git-hooks/install.sh +0 -12
  211. package/scripts/git-hooks/pre-commit +0 -12
  212. package/scripts/git-hooks/pre-commit-audit.sh +0 -146
  213. package/scripts/git-hooks/pre-push +0 -105
  214. package/scripts/git-hooks/prepare-commit-msg +0 -29
  215. package/scripts/lib/secrets_provider.sh +0 -185
  216. package/scripts/ops/ai-setup.sh +0 -71
  217. package/scripts/ops/bundle.sh +0 -104
  218. package/scripts/ops/chaos.sh +0 -50
  219. package/scripts/ops/chezmoi-apply.sh +0 -333
  220. package/scripts/ops/chezmoi-diff.sh +0 -16
  221. package/scripts/ops/chezmoi-remove.sh +0 -46
  222. package/scripts/ops/chezmoi-update.sh +0 -63
  223. package/scripts/ops/heal-chezmoi.sh +0 -87
  224. package/scripts/ops/heal-system.sh +0 -129
  225. package/scripts/ops/heal-tools.sh +0 -297
  226. package/scripts/ops/heal.sh +0 -223
  227. package/scripts/ops/post-apply-repair.sh +0 -107
  228. package/scripts/ops/prewarm.sh +0 -128
  229. package/scripts/ops/release.sh +0 -262
  230. package/scripts/ops/rollback.sh +0 -604
  231. package/scripts/ops/setup.sh +0 -138
  232. package/scripts/ops/teleport.sh +0 -34
  233. package/scripts/qa/check-version-consistency.sh +0 -124
  234. package/scripts/qa/coverage-baseline.sh +0 -61
  235. package/scripts/qa/docs-coverage.sh +0 -112
  236. package/scripts/qa/examples-coverage.sh +0 -94
  237. package/scripts/qa/powershell-contract.ps1 +0 -95
  238. package/scripts/qa/reliability-audit.sh +0 -139
  239. package/scripts/qa/scorecard-snapshot.sh +0 -128
  240. package/scripts/qa/traceability-coverage.sh +0 -117
  241. package/scripts/qa/validate-examples.sh +0 -27
  242. package/scripts/qa/wsl-contract.sh +0 -12
  243. package/scripts/secrets/age-init.sh +0 -82
  244. package/scripts/secrets/create-secrets-file.sh +0 -46
  245. package/scripts/secrets/encrypt-ssh-key.sh +0 -44
  246. package/scripts/security/backup.sh +0 -58
  247. package/scripts/security/check-disclosure-key-expiry.sh +0 -111
  248. package/scripts/security/dns-doh.sh +0 -52
  249. package/scripts/security/encryption-check.sh +0 -55
  250. package/scripts/security/enforce-policies.sh +0 -335
  251. package/scripts/security/firewall.sh +0 -91
  252. package/scripts/security/lock-configs.sh +0 -67
  253. package/scripts/security/lock-screen.sh +0 -56
  254. package/scripts/security/manage-secrets.sh +0 -429
  255. package/scripts/security/ssh-cert.sh +0 -204
  256. package/scripts/security/telemetry-kill.sh +0 -51
  257. package/scripts/security/usb-safety.sh +0 -52
  258. package/scripts/theme/apply-gnome-theme.sh +0 -333
  259. package/scripts/theme/extract-heic-frames.sh +0 -115
  260. package/scripts/theme/extract-theme.py +0 -742
  261. package/scripts/theme/install-boot-logo.sh +0 -63
  262. package/scripts/theme/install-catppuccin-themes.sh +0 -371
  263. package/scripts/theme/install-cursors.sh +0 -26
  264. package/scripts/theme/install-file-icons.sh +0 -27
  265. package/scripts/theme/install-grub-theme.sh +0 -62
  266. package/scripts/theme/install-lock-icon.sh +0 -31
  267. package/scripts/theme/merge-wallpaper.sh +0 -146
  268. package/scripts/theme/rebuild-themes.sh +0 -544
  269. package/scripts/theme/switch.sh +0 -449
  270. package/scripts/theme/wallpaper-rotate.sh +0 -137
  271. package/scripts/theme/wallpaper-sync.sh +0 -690
  272. package/scripts/tools/cmatrix.sh +0 -22
  273. package/scripts/tools/detect-collisions.py +0 -103
  274. package/scripts/tools/emoji-picker.sh +0 -49
  275. package/scripts/tools/figlet-banner.sh +0 -19
  276. package/scripts/tools/log-rotate.sh +0 -31
  277. package/scripts/tools/lolcat-wrap.sh +0 -20
  278. package/scripts/tools/pipes.sh +0 -49
  279. package/scripts/tuning/linux.sh +0 -186
  280. package/scripts/tuning/macos.sh +0 -56
  281. package/scripts/uninstall.sh +0 -86
  282. package/scripts/version-sync.sh +0 -654
  283. package/templates/chezmoi-data/geekom-a9.toml.example +0 -21
  284. package/templates/chezmoi-data/mac-m1.toml.example +0 -16
  285. package/templates/chezmoi-data/mac-t2-linux.toml.example +0 -21
  286. package/templates/chezmoi-data/surface-pro-7p.toml.example +0 -21
  287. package/templates/projects/go/.github/workflows/ci.yml +0 -31
  288. package/templates/projects/go/README.md +0 -7
  289. package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +0 -8
  290. package/templates/projects/go/go.mod +0 -3
  291. package/templates/projects/go/go.sum +0 -0
  292. package/templates/projects/molecule/README.md +0 -7
  293. package/templates/projects/molecule/converge.yml +0 -7
  294. package/templates/projects/molecule/molecule.yml +0 -16
  295. package/templates/projects/node/.github/workflows/ci.yml +0 -30
  296. package/templates/projects/node/README.md +0 -7
  297. package/templates/projects/node/package-lock.json +0 -12
  298. package/templates/projects/node/package.json +0 -10
  299. package/templates/projects/node/src/index.js +0 -3
  300. package/templates/projects/packer/README.md +0 -15
  301. package/templates/projects/packer/main.pkr.hcl +0 -15
  302. package/templates/projects/python/.github/workflows/ci.yml +0 -34
  303. package/templates/projects/python/README.md +0 -7
  304. package/templates/projects/python/pyproject.toml +0 -25
  305. package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +0 -2
  306. package/templates/projects/python/tests/test_basic.py +0 -3
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- # Interactive setup for dotfiles preferences
5
- # Usage: dot setup
6
-
7
- set -euo pipefail
8
-
9
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
- # shellcheck source=../../lib/dot/ui.sh
11
- # shellcheck disable=SC1091
12
- source "$SCRIPT_DIR/../../lib/dot/ui.sh"
13
-
14
- ui_init
15
-
16
- CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi"
17
- CONFIG_FILE="$CONFIG_DIR/chezmoi.toml"
18
- BACKUP_FILE="$CONFIG_DIR/chezmoi.toml.bak.$(date +%Y%m%d_%H%M%S)"
19
- mkdir -p "$CONFIG_DIR"
20
-
21
- choose() {
22
- local prompt="$1"
23
- shift
24
- if command -v gum >/dev/null 2>&1; then
25
- gum choose --cursor.foreground=212 --selected.foreground=212 --header "$prompt" "$@"
26
- else
27
- echo "$prompt"
28
- select opt in "$@"; do
29
- echo "$opt"
30
- return
31
- done
32
- fi
33
- }
34
-
35
- confirm() {
36
- local prompt="$1"
37
- if command -v gum >/dev/null 2>&1; then
38
- gum confirm "$prompt"
39
- else
40
- read -r -p "$prompt [y/N]: " ans
41
- [[ "$ans" =~ ^[Yy]$ ]]
42
- fi
43
- }
44
-
45
- ui_header "Dotfiles Setup"
46
-
47
- profile=$(choose "Select profile" laptop desktop server minimal)
48
-
49
- feature_zsh=true
50
- feature_nvim=true
51
- feature_tmux=true
52
- feature_gui=true
53
- feature_secrets=true
54
-
55
- confirm "Enable Zsh config?" || feature_zsh=false
56
- confirm "Enable Neovim config?" || feature_nvim=false
57
- confirm "Enable tmux config?" || feature_tmux=false
58
- confirm "Enable GUI extras (fonts/themes)?" || feature_gui=false
59
- confirm "Enable secrets integration?" || feature_secrets=false
60
-
61
- alias_profile=$(choose "Alias profile" standard minimal)
62
- strict_mode=false
63
- confirm "Enable strict alias governance?" && strict_mode=true
64
-
65
- secrets_provider=$(choose "Secrets provider" auto sops onepassword bitwarden)
66
-
67
- theme_choices=(
68
- macos-ai-dark macos-ai-light
69
- macos-bigsur-dark macos-bigsur-light
70
- macos-blue-dark macos-blue-light
71
- macos-blush-dark macos-blush-light
72
- macos-citrus-dark macos-citrus-light
73
- macos-green-dark macos-green-light
74
- macos-gridgreen-dark macos-gridgreen-light
75
- macos-heatmap-dark macos-heatmap-light
76
- macos-indigo-dark macos-indigo-light
77
- macos-miami-dark macos-miami-light
78
- macos-mojave-dark macos-mojave-light
79
- macos-monterey-dark macos-monterey-light
80
- macos-nova-dark macos-nova-light
81
- macos-orange-dark macos-orange-light
82
- macos-pink-dark macos-pink-light
83
- macos-purple-dark macos-purple-light
84
- macos-sequoia-dark macos-sequoia-light
85
- macos-silver-dark macos-silver-light
86
- macos-sonoma-dark macos-sonoma-light
87
- macos-tahoe-dark macos-tahoe-light
88
- macos-valentine-dark macos-valentine-light
89
- macos-ventura-dark macos-ventura-light
90
- macos-wave-dark macos-wave-light
91
- macos-yellow-dark macos-yellow-light
92
- )
93
- theme=$(choose "Theme" "${theme_choices[@]}")
94
-
95
- if [[ -f "$CONFIG_FILE" ]]; then
96
- cp "$CONFIG_FILE" "$BACKUP_FILE"
97
- ui_info "Backup" "$BACKUP_FILE"
98
- fi
99
-
100
- cat >"$CONFIG_FILE" <<TOML
101
- [data]
102
- profile = "$profile"
103
- theme = "$theme"
104
-
105
- [data.features]
106
- zsh = ${feature_zsh}
107
- nvim = ${feature_nvim}
108
- tmux = ${feature_tmux}
109
- gui = ${feature_gui}
110
- secrets = ${feature_secrets}
111
-
112
- [data.aliases]
113
- profile = "$alias_profile"
114
-
115
- [data.aliases.policy]
116
- strict_mode = ${strict_mode}
117
-
118
- [data.aliases.buckets]
119
- system = true
120
- svn = true
121
-
122
- [data.secrets]
123
-
124
- [data.secrets.policy]
125
- provider = "$secrets_provider"
126
- auto_load = true
127
- TOML
128
-
129
- ui_ok "Config" "Updated $CONFIG_FILE"
130
-
131
- if confirm "Apply dotfiles now?"; then
132
- if command -v chezmoi >/dev/null 2>&1; then
133
- chezmoi apply
134
- ui_ok "Apply" "Complete"
135
- else
136
- ui_warn "chezmoi" "Not installed"
137
- fi
138
- fi
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- # Script: teleport.sh
5
- # Description: Deploys dotfiles to a remote host ephemerally.
6
- # Usage: ./teleport.sh user@hostname
7
-
8
- set -euo pipefail
9
-
10
- TARGET="${1:-}"
11
-
12
- if [[ -z "$TARGET" ]]; then
13
- echo "Usage: dot teleport user@host"
14
- exit 1
15
- fi
16
-
17
- # Validate SSH target: must be user@host format, no shell metacharacters
18
- if [[ ! "$TARGET" =~ ^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+$ ]]; then
19
- echo "Invalid SSH target: $TARGET" >&2
20
- echo "Expected format: user@hostname (alphanumeric, dots, hyphens, underscores only)" >&2
21
- exit 1
22
- fi
23
-
24
- echo " Teleporting dotfiles to ${TARGET}..."
25
-
26
- # 1. Archive the current state
27
- # 2. Pipe to SSH
28
- # 3. Extract in remote home directory with safety flags
29
- # --no-same-owner: don't try to preserve owner (non-root)
30
- # --strip-components=0: don't strip path components
31
- chezmoi archive | ssh "$TARGET" 'tar xz -C "$HOME" --no-same-owner'
32
-
33
- echo " Teleport successful!"
34
- echo " Note: Changes are applied to files, but shell may need restart or sourcing."
@@ -1,124 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- #
5
- # Verify that every "live" version reference matches the canonical
6
- # version in .chezmoidata.toml. The intent is to catch drift between
7
- # the source-of-truth and the human-visible surfaces (CLI banner, man
8
- # page, badge URL, etc.) BEFORE it ships.
9
- #
10
- # Historical references (CHANGELOG entries, audit-doc closed-cycle
11
- # tables, roadmap docs that mention previous versions) are NOT
12
- # checked — they are intentionally pinned to the version they
13
- # describe.
14
- #
15
- # Usage:
16
- # scripts/qa/check-version-consistency.sh # verify
17
- # scripts/qa/check-version-consistency.sh --fix # auto-fix
18
- # scripts/qa/check-version-consistency.sh --quiet # rc-only
19
- #
20
- # Exit codes:
21
- # 0 every live reference matches
22
- # 1 drift detected (with diff printed unless --quiet)
23
- # 2 bad usage / missing canonical version
24
-
25
- set -euo pipefail
26
-
27
- REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
28
- cd "$REPO_ROOT"
29
-
30
- # ── Parse flags ─────────────────────────────────────────────────────────
31
- fix=0
32
- quiet=0
33
- for arg in "$@"; do
34
- case "$arg" in
35
- --fix) fix=1 ;;
36
- --quiet | -q) quiet=1 ;;
37
- -h | --help)
38
- sed -n '2,21p' "$0"
39
- exit 0
40
- ;;
41
- *)
42
- echo "unknown flag: $arg" >&2
43
- exit 2
44
- ;;
45
- esac
46
- done
47
-
48
- _log() { ((quiet)) || printf '%s\n' "$*"; }
49
- _err() { printf 'check-version-consistency: %s\n' "$*" >&2; }
50
-
51
- # ── Canonical version ──────────────────────────────────────────────────
52
- canonical="$(grep -E '^dotfiles_version[[:space:]]*=' defaults/.chezmoidata.toml |
53
- head -1 | sed -E 's/.*"([^"]+)".*/\1/')"
54
-
55
- if [[ -z "$canonical" ]]; then
56
- _err 'failed to read dotfiles_version from defaults/.chezmoidata.toml'
57
- exit 2
58
- fi
59
- _log "canonical: $canonical (defaults/.chezmoidata.toml)"
60
-
61
- # ── Per-file expected-substring map ────────────────────────────────────
62
- # Each entry: PATH|MATCH_PATTERN|EXPECTED_STRING
63
- # MATCH_PATTERN is a fixed substring to grep for on the file to
64
- # locate the version-bearing line; we then verify it contains the
65
- # expected substring rendered with $canonical. version-sync.sh
66
- # already handles many files (it reads package.json as source);
67
- # this list captures the surfaces version-sync.sh historically
68
- # missed — bento.sh banner, man-page header, dispatcher header.
69
- specs=(
70
- "package.json|\"version\"|\"version\": \"${canonical}\""
71
- "bin/dot|^VERSION=|VERSION=\"${canonical}\""
72
- "bin/dot|^# Dotfiles CLI Entry Point - v|# Dotfiles CLI Entry Point - v${canonical}"
73
- "share/man/man1/dot.1|^.TH DOT 1|dotfiles v${canonical}"
74
- "lib/dot/bento.sh|D O T F I L E S|[v${canonical}]"
75
- "README.md|img.shields.io/badge/Version|Version-v${canonical}-blue"
76
- "CLAUDE.md|^Chezmoi-managed dotfiles|Version \`${canonical}\`"
77
- "AGENTS.md|^Chezmoi-managed dotfiles|Version \`${canonical}\`"
78
- )
79
-
80
- drift=0
81
- for spec in "${specs[@]}"; do
82
- IFS='|' read -r path pattern expected <<<"$spec"
83
- if [[ ! -f "$path" ]]; then
84
- _err "MISSING: $path (declared in spec list)"
85
- drift=$((drift + 1))
86
- continue
87
- fi
88
- line="$(grep -E "$pattern" "$path" | head -1 || true)"
89
- if [[ -z "$line" ]]; then
90
- _err "PATTERN NOT FOUND: '$pattern' in $path"
91
- drift=$((drift + 1))
92
- continue
93
- fi
94
- if [[ "$line" != *"$expected"* ]]; then
95
- _err "DRIFT in $path"
96
- _err " found: $line"
97
- _err " expected: contains '$expected'"
98
- drift=$((drift + 1))
99
- if ((fix)); then
100
- # Auto-fix: only safe when the file contains a previous v0.X.YYY
101
- # we can sed-replace. Skip otherwise.
102
- old="$(printf '%s' "$line" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
103
- if [[ -n "$old" ]] && [[ "$old" != "v${canonical}" ]]; then
104
- sed -i.bak "s|${old}|v${canonical}|g" "$path" && rm -f "$path.bak"
105
- _log " fixed: $path ($old → v${canonical})"
106
- fi
107
- fi
108
- fi
109
- done
110
-
111
- if ((drift > 0)); then
112
- if ((fix)); then
113
- _log ""
114
- _log "Auto-fixed where safe. Re-run without --fix to verify."
115
- else
116
- _log ""
117
- _log "Tip: rerun with --fix to auto-correct (only safe substitutions)."
118
- _log " For non-trivial drift, edit the file manually then re-run."
119
- fi
120
- exit 1
121
- fi
122
-
123
- _log "all $((${#specs[@]})) live version surfaces match $canonical"
124
- exit 0
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8
-
9
- include_module_coverage=0
10
-
11
- usage() {
12
- cat <<'EOF'
13
- Coverage Baseline
14
-
15
- Usage:
16
- coverage-baseline.sh [--with-module-coverage]
17
-
18
- Options:
19
- --with-module-coverage Run tests/framework/module_coverage.sh and include the result
20
- -h, --help Show this help
21
- EOF
22
- }
23
-
24
- while [ "$#" -gt 0 ]; do
25
- case "$1" in
26
- --with-module-coverage)
27
- include_module_coverage=1
28
- ;;
29
- -h | --help)
30
- usage
31
- exit 0
32
- ;;
33
- *)
34
- printf 'Unknown option: %s\n' "$1" >&2
35
- usage >&2
36
- exit 1
37
- ;;
38
- esac
39
- shift
40
- done
41
-
42
- unit_tests="$(find "$REPO_ROOT/tests/unit" -name 'test_*.sh' | wc -l | tr -d ' ')"
43
- integration_tests="$(find "$REPO_ROOT/tests/integration" -name 'test_*.sh' | wc -l | tr -d ' ')"
44
- total_tests="$(find "$REPO_ROOT/tests" -path '*/framework/*' -prune -o -name 'test_*.sh' -print | wc -l | tr -d ' ')"
45
- named_tests="$(rg -o '\btest_start\b' "$REPO_ROOT/tests/unit" "$REPO_ROOT/tests/integration" -g 'test_*.sh' | wc -l | tr -d ' ')"
46
- docs_files="$(find "$REPO_ROOT/docs" -type f \( -name '*.md' -o -name '*.md.tmpl' \) | wc -l | tr -d ' ')"
47
- shell_surfaces="$(find "$REPO_ROOT/scripts" "$REPO_ROOT/defaults/dot_local/bin" "$REPO_ROOT/defaults/.chezmoitemplates/functions" -type f \( -name '*.sh' -o -name 'executable_*' \) | wc -l | tr -d ' ')"
48
-
49
- printf 'Coverage Baseline\n'
50
- printf 'Repository: %s\n' "$REPO_ROOT"
51
- printf 'Documentation files: %s\n' "$docs_files"
52
- printf 'Executable shell surfaces: %s\n' "$shell_surfaces"
53
- printf 'Unit test files: %s\n' "$unit_tests"
54
- printf 'Integration test files: %s\n' "$integration_tests"
55
- printf 'Total test files: %s\n' "$total_tests"
56
- printf 'Named tests: %s\n' "$named_tests"
57
-
58
- if [ "$include_module_coverage" -eq 1 ]; then
59
- printf '\n'
60
- (cd "$REPO_ROOT" && bash ./tests/framework/module_coverage.sh)
61
- fi
@@ -1,112 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8
-
9
- DOT_CLI="$REPO_ROOT/bin/dot"
10
- UTILS_DOC="$REPO_ROOT/docs/reference/UTILS.md"
11
- AI_DOC="$REPO_ROOT/docs/AI.md"
12
- SCRIPTS_DOC="$REPO_ROOT/docs/reference/SCRIPTS.md"
13
- ARCH_DOC="$REPO_ROOT/docs/architecture/ARCHITECTURE.md"
14
- FUNCTION_GROUPS_JSON="$REPO_ROOT/defaults/.chezmoitemplates/functions/groups.json"
15
- MIN_DOCS_COVERAGE="${MIN_DOCS_COVERAGE:-100}"
16
-
17
- TOTAL_CHECKS=0
18
- COVERED_CHECKS=0
19
-
20
- record_doc_check() {
21
- local label="$1"
22
- local needle="$2"
23
- local file="$3"
24
-
25
- TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
26
- if grep -Fq "$needle" "$file"; then
27
- COVERED_CHECKS=$((COVERED_CHECKS + 1))
28
- else
29
- printf 'Missing documentation: %s\n' "$label" >&2
30
- fi
31
- }
32
-
33
- extract_public_commands() {
34
- awk '
35
- /_dot_help_specs\(\)/ { in_func=1; next }
36
- in_func && /cat <<'\''EOF'\''/ { in_block=1; next }
37
- in_block && /^EOF$/ { exit }
38
- in_block && /\|/ {
39
- split($0, parts, /\|/)
40
- print parts[2]
41
- }
42
- ' "$DOT_CLI"
43
- }
44
-
45
- check_dot_command_docs() {
46
- local command=""
47
-
48
- while IFS= read -r command; do
49
- [ -n "$command" ] || continue
50
- record_doc_check "dot $command in UTILS.md" "\`dot $command" "$UTILS_DOC"
51
- done < <(extract_public_commands)
52
- }
53
-
54
- check_ai_provider_docs() {
55
- local provider=""
56
-
57
- for provider in cl copilot kimi agy kiro sgpt ollama opencode aider; do
58
- record_doc_check "dot $provider in AI.md" "\`dot $provider\`" "$AI_DOC"
59
- done
60
- }
61
-
62
- check_utility_docs() {
63
- local utility=""
64
-
65
- for utility in \
66
- ai-update ai_core antigravity b64 bm cb dot dot-ai dot-bootstrap dot-launch-or-focus \
67
- dot-load-benchmark dot-load-benchmark-pty dot-theme-sync dtags epoch extract gbd gd \
68
- git-ai-commit git-ai-diff gl hash hashsum hex jsonv jwt kill-port lorem monitor myip \
69
- notify open pw rec-start rec-stop regex start-niri tmux-sessionizer tour up update uuid \
70
- win yamlv; do
71
- record_doc_check "$utility in SCRIPTS.md" "\`$utility\`" "$SCRIPTS_DOC"
72
- done
73
- }
74
-
75
- check_function_group_docs() {
76
- local group=""
77
-
78
- for group in $(
79
- FUNCTION_GROUPS_JSON="$FUNCTION_GROUPS_JSON" python3 - <<'PY'
80
- import json
81
- import os
82
- from pathlib import Path
83
- path = Path(os.environ["FUNCTION_GROUPS_JSON"])
84
- for key in json.loads(path.read_text()).keys():
85
- print(key)
86
- PY
87
- ); do
88
- record_doc_check "function group $group in ARCHITECTURE.md" "\`$group\`" "$ARCH_DOC"
89
- done
90
- }
91
-
92
- report_coverage() {
93
- local pct
94
- pct="$(awk -v c="$COVERED_CHECKS" -v t="$TOTAL_CHECKS" 'BEGIN{if(t==0){print "0.00"}else{printf "%.2f", (100*c/t)}}')"
95
-
96
- printf 'Docs coverage: %s/%s (%s%%)\n' "$COVERED_CHECKS" "$TOTAL_CHECKS" "$pct"
97
- printf 'Threshold: %s%%\n' "$MIN_DOCS_COVERAGE"
98
-
99
- awk -v p="$pct" -v min="$MIN_DOCS_COVERAGE" 'BEGIN{exit !(p+0 >= min+0)}'
100
- }
101
-
102
- main() {
103
- check_dot_command_docs
104
- check_ai_provider_docs
105
- check_utility_docs
106
- check_function_group_docs
107
- report_coverage
108
-
109
- printf 'PASS: public dot commands, utility entrypoints, AI providers, and function groups are documented at or above the required threshold\n'
110
- }
111
-
112
- main "$@"
@@ -1,94 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- # =============================================================================
5
- # examples-coverage.sh — enforce that every core feature domain ships a
6
- # runnable example under examples/. Mirrors scripts/qa/docs-coverage.sh:
7
- # it is a *coverage contract*, not a linter. Threshold defaults to 100%.
8
- #
9
- # A feature domain is "covered" when examples/example-<domain>.sh exists.
10
- # Keep REQUIRED_AREAS in lockstep with the feature surface — adding a major
11
- # user-facing capability (a new `dot` subsystem) means adding its example.
12
- # =============================================================================
13
- set -euo pipefail
14
-
15
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
- REPO_ROOT="${REPO_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
17
- EXAMPLES_DIR="$REPO_ROOT/examples"
18
- DOT_CLI="$REPO_ROOT/bin/dot"
19
- MIN_EXAMPLES_COVERAGE="${MIN_EXAMPLES_COVERAGE:-100}"
20
-
21
- # Public commands/subcommands, extracted from bin/dot's _dot_help_specs — the
22
- # same source scripts/qa/docs-coverage.sh uses, so docs and examples stay in
23
- # lockstep at the command granularity.
24
- extract_public_commands() {
25
- awk -F'|' '
26
- /_dot_help_specs\(\)/ { in_func=1; next }
27
- in_func && /cat <<'\''EOF'\''/ { in_block=1; next }
28
- in_block && /^EOF$/ { exit }
29
- in_block && NF>=2 { print $2 }
30
- ' "$DOT_CLI"
31
- }
32
-
33
- # Core feature domains that must each have examples/example-<area>.sh.
34
- REQUIRED_AREAS=(
35
- ai-patterns
36
- cli-utilities
37
- coverage-gate
38
- diagnostics
39
- dot-commands
40
- functions
41
- fleet
42
- git-hooks
43
- install-uninstall
44
- ops
45
- platform-contract
46
- qa
47
- secrets
48
- security
49
- test-suite
50
- testing-framework
51
- theme
52
- )
53
-
54
- total=0
55
- covered=0
56
- missing=()
57
-
58
- # --- Check 1: every feature domain has a dedicated example file. ---
59
- for area in "${REQUIRED_AREAS[@]}"; do
60
- total=$((total + 1))
61
- if [ -f "$EXAMPLES_DIR/example-$area.sh" ]; then
62
- covered=$((covered + 1))
63
- else
64
- missing+=("domain:$area")
65
- fi
66
- done
67
-
68
- # --- Check 2: every public command/subcommand is referenced in an example. ---
69
- while IFS= read -r cmd; do
70
- [ -n "$cmd" ] || continue
71
- total=$((total + 1))
72
- # "dot <cmd>" followed by a non-identifier char (or EOL) — avoids matching
73
- # `dot ai` against `dot ai-query`, and matches printf '...\n'-terminated refs.
74
- if grep -rqE "dot ${cmd}([^A-Za-z0-9_-]|\$)" "$EXAMPLES_DIR" 2>/dev/null; then
75
- covered=$((covered + 1))
76
- else
77
- missing+=("cmd:$cmd")
78
- fi
79
- done < <(extract_public_commands | sort -u)
80
-
81
- pct="$(awk -v c="$covered" -v t="$total" \
82
- 'BEGIN{if(t==0){print "0.00"}else{printf "%.2f", (100*c/t)}}')"
83
- printf 'Examples coverage: %s/%s (%s%%)\n' "$covered" "$total" "$pct"
84
- printf 'Threshold: %s%%\n' "$MIN_EXAMPLES_COVERAGE"
85
- if [ "${#missing[@]}" -gt 0 ]; then
86
- printf 'Missing coverage for: %s\n' "${missing[*]}" >&2
87
- fi
88
-
89
- if awk -v p="$pct" -v min="$MIN_EXAMPLES_COVERAGE" 'BEGIN{exit !(p+0 >= min+0)}'; then
90
- printf 'PASS: every feature domain and every public command has an example.\n'
91
- exit 0
92
- fi
93
- printf 'FAIL: examples coverage %s%% is below the %s%% threshold.\n' "$pct" "$MIN_EXAMPLES_COVERAGE" >&2
94
- exit 1
@@ -1,95 +0,0 @@
1
- # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
- #
3
- # PowerShell parity contract — smoke test for the dotfiles PowerShell
4
- # profile. Run by the windows-latest CI job (#860). Asserts that:
5
- #
6
- # 1. The profile parses + loads without throwing.
7
- # 2. Core function shims (`dot`, `ll`, `la`, `cat`) are defined.
8
- # 3. PSScriptAnalyzer reports no errors against the profile (warnings
9
- # surface but don't fail the gate; tighten later).
10
- #
11
- # Exit codes:
12
- # 0 contract intact.
13
- # 1 any check failed; details printed to host.
14
-
15
- $ErrorActionPreference = 'Stop'
16
- $Failures = New-Object System.Collections.Generic.List[string]
17
-
18
- $RepoRoot = if ($env:GITHUB_WORKSPACE) { $env:GITHUB_WORKSPACE } else { (Get-Location).Path }
19
- $ProfileSrc = Join-Path $RepoRoot 'defaults/dot_config/powershell/Microsoft.PowerShell_profile.ps1.tmpl'
20
-
21
- if (-not (Test-Path $ProfileSrc)) {
22
- Write-Output "FAIL: profile source not found at $ProfileSrc"
23
- exit 1
24
- }
25
-
26
- # Step 1 — chezmoi-render the template into a real .ps1 we can dot-source.
27
- # In CI, chezmoi is on PATH (installed by setup-chezmoi composite).
28
- $Rendered = Join-Path $env:TEMP 'Microsoft.PowerShell_profile.ps1'
29
- if (Get-Command chezmoi -ErrorAction SilentlyContinue) {
30
- & chezmoi execute-template --init --promptString version=0.2.501 `
31
- --in $ProfileSrc | Set-Content -Path $Rendered -NoNewline
32
- } else {
33
- # Fallback: strip chezmoi template syntax with a simple regex so the
34
- # contract still runs locally without chezmoi installed.
35
- (Get-Content $ProfileSrc -Raw) -replace '\{\{[^}]+\}\}', '0.0.0-fallback' |
36
- Set-Content -Path $Rendered -NoNewline
37
- }
38
-
39
- if (-not (Test-Path $Rendered)) {
40
- $Failures.Add("profile template did not render to $Rendered")
41
- }
42
-
43
- # Step 2 — dot-source the rendered profile and verify it didn't throw.
44
- $loadOk = $false
45
- try {
46
- . $Rendered
47
- $loadOk = $true
48
- Write-Output "OK: profile dot-sourced"
49
- } catch {
50
- Write-Output "FAIL: profile threw during load: $_"
51
- $Failures.Add("profile load: $_")
52
- }
53
-
54
- # Step 3 — verify required function shims are defined.
55
- $RequiredFunctions = @('dot', 'd', 'll', 'la', 'cat')
56
- foreach ($fn in $RequiredFunctions) {
57
- if (Get-Command $fn -CommandType Function -ErrorAction SilentlyContinue) {
58
- Write-Output "OK: function $fn defined"
59
- } else {
60
- Write-Output "FAIL: function $fn not defined"
61
- $Failures.Add("missing function: $fn")
62
- }
63
- }
64
-
65
- # Step 4 — PSScriptAnalyzer (static analysis). Pre-installed on the
66
- # windows-latest GitHub-hosted runner; install on demand if missing.
67
- if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) {
68
- Write-Output "Installing PSScriptAnalyzer..."
69
- Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -ErrorAction SilentlyContinue | Out-Null
70
- }
71
-
72
- if (Get-Module -ListAvailable -Name PSScriptAnalyzer) {
73
- Import-Module PSScriptAnalyzer -Force
74
- $Findings = Invoke-ScriptAnalyzer -Path $Rendered -Severity 'Error' -ErrorAction SilentlyContinue
75
- if ($Findings) {
76
- foreach ($f in $Findings) {
77
- Write-Output "FAIL: PSScriptAnalyzer error: $($f.RuleName) at line $($f.Line): $($f.Message)"
78
- $Failures.Add("PSScriptAnalyzer error: $($f.RuleName)")
79
- }
80
- } else {
81
- Write-Output "OK: PSScriptAnalyzer clean (Error severity)"
82
- }
83
- } else {
84
- Write-Output "WARN: PSScriptAnalyzer not available — static analysis skipped"
85
- }
86
-
87
- Write-Output ""
88
- if ($Failures.Count -eq 0) {
89
- Write-Output "PowerShell contract: PASS"
90
- exit 0
91
- } else {
92
- Write-Output "PowerShell contract: FAIL ($($Failures.Count) issue(s))"
93
- foreach ($f in $Failures) { Write-Output " - $f" }
94
- exit 1
95
- }