### Fixed
- `.gitattributes` — `*.ps1 text eol=crlf` rule ensures PowerShell scripts are always
  checked out / packaged with CRLF line endings; `powershell.exe` v5.1 fails to parse
  here-strings with LF-only line endings (closes #9).
- `phases.py` — `_exec_copy_scripts` now normalises deployed `.ps1` files to CRLF on
  Windows as a safety net for users with existing LF-only installs.
- `chief-install.ps1` — `Run` helper: replaced invalid `@Command[1..]` splatting-with-
  index syntax with destructuring assignment (`$exe, $rest = $Command; & $exe @rest`);
  `$key:` in a double-quoted string now written as `${key}:` to avoid the colon being
  parsed as a scope qualifier. Both were parse errors under `pwsh` 7+.
- `chief-install.ps1` — `Invoke-Install`: replaced `Invoke-Expression $cmd` (unsafe
  string eval, security finding) with `$exe, $rest = $cmd -split '\s+'; & $exe @rest`,
  consistent with the `Run` helper pattern.
- `chief-install.ps1` — `Invoke-Log`: renamed `param([string[]]$Args)` to
  `param([string[]]$Pairs = @())` — `$Args`/`$args` is a PowerShell automatic variable;
  using it as a named parameter under `Set-StrictMode -Version Latest` caused the
  parameter to appear null, so zero-arg validation silently short-circuited. Changed the
  zero-arg guard to `-not $Pairs` to handle the null-vs-empty-array distinction correctly.
- `chief-install.ps1` — `Miss` and `Err` helpers: replaced `Write-Error` with
  `$host.UI.WriteErrorLine()`. With `$ErrorActionPreference = 'Stop'` at the top of the
  script, `Write-Error` throws a terminating exception before any subsequent `exit N` or
  `$fail = 1` line can execute, causing `check bogus-framework` to exit 1 instead of 2
  and prereq-miss paths to exit 1 before setting `$fail`. `$host.UI.WriteErrorLine()`
  writes to stderr without throwing, so explicit exit codes are correctly honoured.

---
