fix: CRLF-safe typos directive, non-silent analyzer hook, accurate config pointers - #77
Conversation
…rors Two adopted configs silently did the wrong thing: - modules/typos/_typos.toml: the `spellchecker:ignore-next-line` directive regex used a bare `\n`, so on a CRLF-terminated file the `\r` before the newline was never matched and the pragma silently suppressed nothing (its siblings are CRLF-aware via (?Rm)/(?s)). Add `\r?` so it works on both line endings. Verified with typos against a CRLF fixture: the next line is now suppressed, an unprotected line still flags. - modules/lefthook/psscriptanalyzer-staged.ps1: `ErrorAction = 'SilentlyContinue'` swallowed EVERY non-terminating analyzer error, not just the one benign PSUseCompatibleSyntax NRE its comment justified - so a malformed PSScriptAnalyzerSettings.psd1 (or a rule that failed to load) would make the hook report clean while running unruled. Now: validate the settings file parses (fail loud if not), capture errors via -ErrorVariable, drop only the benign "Object reference not set" NRE, and re-surface anything else as a failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JLR9bgyuhEX6YUUkAhkhy5
Cosmetic comment fixes so the adopted copies read correctly downstream: - .editorconfig: the header claimed to cover only "Markdown, shell, PowerShell" plus batch, but the file also carries config/serialization (JSON/YAML/TOML), JS/TS, git config, and lockfile sections; broaden the header to match. Name the Biome config's home explicitly as the standards repo's modules/typescript so a consumer's copied file does not read it as a dangling local path. - .shellcheckrc (root + modules/shellcheck): likewise qualify "its canonical home is modules/shellcheck/" as the standards repo's path, so the pointer doesn't dangle once copied into a consumer with no modules/ tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JLR9bgyuhEX6YUUkAhkhy5
|
Claude finished @kyle-sexton's task in 3m 3s —— View job PR Review
Overall this is a well-reasoned fix PR. The substantive changes address real bugs with correct logic; the cosmetic changes improve accuracy for downstream consumers. A couple of minor observations below.
|
| Area | Finding | Severity |
|---|---|---|
_typos.toml CRLF fix |
Correct; comment accurate | ✅ |
.psd1 parse guard |
Correct; improves failure visibility | ✅ |
| Error accumulation | Correct; minor comment imprecision | Nit |
| NRE filter breadth | Slightly wider than justified; low risk | Minor |
.editorconfig header |
Accurate; Biome path clarified | ✅ |
.shellcheckrc pointers |
Accurate; same-SHA sync correct | ✅ |
No blocking issues. The two minor points (comment imprecision on accumulation, NRE filter breadth) are worth considering but don't change the correctness of the behavior.
|
Claude finished @kyle-sexton's task in 2m 11s —— View job PR Review
Bug confirmed: false hook failure on clean scanCursor Bugbot's High Severity finding is correct. Root cause — $findings = foreach ($file in $targets) {
Invoke-ScriptAnalyzer ... # produces no output when the file is clean
}
$findings = @($findings) # @($null) → Count = 1 ← bugWhen all staged files pass, Fix — filter nulls before wrapping: -$findings = @($findings)
+$findings = @($findings | Where-Object { $_ })
Remaining observations from the prior reviewThe previous review's two minor notes stand — neither blocks merge, but worth considering alongside the bug fix:
The |
There was a problem hiding this comment.
Stale comment
Risk: medium. Cursor Bugbot completed with a skipped check and reported one unresolved high-severity finding in the staged analyzer hook. Human review is needed before merge; no reviewers were assigned because the only maintainer is the PR author.
Sent by Cursor Approval Agent: Pull Request Router and Approver
There was a problem hiding this comment.
Stale comment
Risk: medium. Not approving: Cursor Bugbot reported 1 unresolved high-severity finding in
psscriptanalyzer-staged.ps1, and the Bugbot check completed as skipped. Human review is needed before merge; no reviewers were assigned because the only repo contributor is the PR author.Sent by Cursor Approval Agent: Pull Request Router and Approver
|
Claude finished @kyle-sexton's task in 1m 21s —— View job PR Review
|
| File | Finding | Status |
|---|---|---|
psscriptanalyzer-staged.ps1:55 |
@($null) false-failure fix via Where-Object { $_ } |
✅ Fixed in 89d1ed1 |
psscriptanalyzer-staged.ps1:35–43 |
.psd1 parse guard — Import-PowerShellDataFile -ErrorAction Stop |
✅ Correct |
psscriptanalyzer-staged.ps1:51–54 |
Error accumulation via AddRange in foreach loop |
✅ Correct |
psscriptanalyzer-staged.ps1:59 |
NRE filter slightly broader than PSUseCompatibleSyntax only |
Minor / awareness |
psscriptanalyzer-staged.ps1:49 |
Comment says foreach causes accumulation; it's actually AddRange |
Nit |
modules/typos/_typos.toml:14 |
\r?\n CRLF-safe fix; comment is accurate |
✅ Correct |
.editorconfig:1–11 |
Broadened header; Biome path qualified to standards repo | ✅ Correct |
.shellcheckrc / modules/shellcheck/.shellcheckrc |
"standards repo's" qualification; same SHA (correct sync) | ✅ Correct |
No blocking issues. The critical false-failure bug is resolved. The two remaining minor points don't change correctness and are fine to carry forward.
…yntax only The staged-file analyzer hook tolerated a benign NullReferenceException from PSUseCompatibleSyntax by filtering on the substring "Object reference not set". That message match was too broad: it dropped EVERY analyzer error carrying that message, including an NRE thrown by a consumer's custom/broken rule - silently turning a broken ruleset into a green scan and defeating the hook's purpose. The analyzer's ErrorRecord does not embed the rule name for built-in-rule failures, so the NRE cannot be attributed to PSUseCompatibleSyntax by field alone. Narrow the ignore as tightly as the data allows: tolerate the NRE only when all hold - the message is the NRE signature, PSUseCompatibleSyntax is actually effective for the scan (it ships enabled and is only skipped when the consumer's settings exclude it), and the error did not originate from an external/custom rule (those run via a distinct engine path - GetExternalRecord, RuntimeException, error id 80131501, targeting the analyzer engine object). Every other analyzer error, including any custom-rule NRE, now surfaces. Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 56s —— View job PR Review
Latest commit —
|
| File | Finding | Status |
|---|---|---|
psscriptanalyzer-staged.ps1:50–57 |
$compatSyntaxEffective tracking — ExcludeRules, IncludeRules, and no-settings-file all handled correctly |
✅ |
psscriptanalyzer-staged.ps1:81–88 |
NRE filter narrowed to PSUseCompatibleSyntax only via 3-condition guard | ✅ |
psscriptanalyzer-staged.ps1:69 |
@($null) false-failure fixed via Where-Object { $_ } |
✅ |
psscriptanalyzer-staged.ps1:35–43 |
.psd1 parse guard — hard fail on malformed settings |
✅ |
psscriptanalyzer-staged.ps1:63 |
Comment says foreach causes accumulation; it's actually AddRange |
Nit |
modules/typos/_typos.toml:17 |
\r?\n CRLF-safe fix; comment accurate |
✅ |
.editorconfig:1–11 |
Broadened header; Biome path qualified to standards repo | ✅ |
.shellcheckrc / modules/shellcheck/.shellcheckrc |
"standards repo's" qualification; same SHA (correct sync) | ✅ |
No blocking issues. The NRE narrowing is well-implemented and resolves the last substantive concern from the prior review passes. The one remaining nit (comment imprecision on foreach vs AddRange) doesn't affect correctness.
There was a problem hiding this comment.
Stale comment
Risk: medium. Not approving: Cursor Bugbot completed as skipped and reported 1 unresolved finding in
psscriptanalyzer-staged.ps1on the latest commit. Human review is needed; no reviewers assigned because the only contributor is the PR author.Sent by Cursor Approval Agent: Pull Request Router and Approver
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af814209a1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… hook The repo's CI PSScriptAnalyzer settings (modules/powershell/PSScriptAnalyzerSettings.psd1) enable PSAvoidLongLines (120) and PSUseConsistentIndentation, which the prior commit's module-default local run did not exercise. Hoist the analyzer engine type name and the error's TargetObject into locals so no line exceeds 120 chars, and align the multi-line boolean continuation to the block's indentation. Logic is unchanged; verified 0 findings under the CI settings. Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 41s —— View job PR Review
Latest commit (
|
| File | Finding | Status |
|---|---|---|
psscriptanalyzer-staged.ps1 |
Latest commit wraps long lines + fixes indentation only; 0 logic changes | ✅ Style fix |
psscriptanalyzer-staged.ps1:52–56 |
Rules.X.Enable = $false not checked — NRE from non-compat-syntax rule could be silently dropped |
Medium — fix above |
psscriptanalyzer-staged.ps1:55–56 |
-contains misses wildcard IncludeRules/ExcludeRules patterns |
Low-Medium — fix above |
psscriptanalyzer-staged.ps1:63 |
Comment conflates foreach scope with accumulation (from AddRange) |
Nit |
psscriptanalyzer-staged.ps1:69 |
@($null) false-failure fixed |
✅ |
psscriptanalyzer-staged.ps1:35–43 |
.psd1 parse guard — hard fail on malformed settings |
✅ |
psscriptanalyzer-staged.ps1:82–89 |
NRE narrowed to PSUseCompatibleSyntax via 3-condition guard | ✅ |
modules/typos/_typos.toml:17 |
\r?\n CRLF-safe fix |
✅ |
.editorconfig:1–11 |
Broadened header; Biome path qualified | ✅ |
.shellcheckrc / modules/shellcheck/.shellcheckrc |
Standards-repo path qualification | ✅ |
The Rules.X.Enable = $false gap is the most actionable of the two new findings given that the repo's own settings template uses this form. Both are worth addressing; neither changes the fundamental correctness of the PR's core fixes.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c6e0a702ad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Stale comment
Risk: medium. Not approving: Cursor Bugbot completed as skipped and still has an unresolved medium-severity finding in
psscriptanalyzer-staged.ps1on the latest commit. Human review is needed; no reviewers assigned because the only repo contributor is the PR author.Sent by Cursor Approval Agent: Pull Request Router and Approver
…e and wildcard-aware $compatSyntaxEffective decided whether the benign PSUseCompatibleSyntax NRE is tolerable, but it only inspected ExcludeRules/IncludeRules by exact match. Two gaps let it misjudge whether the rule actually runs: - Rules.PSUseCompatibleSyntax.Enable = $false disables the rule, yet the check ignored the Rules table and still treated an NRE from another rule as benign. - IncludeRules/ExcludeRules accept wildcards, so IncludeRules = 'PSUseCompatible*' runs the rule but exact match set effective=false, treating its benign NRE as real and blocking every staged PowerShell commit in such repos. Compute effectiveness across all three signals - Rules.<name>.Enable=$false, wildcard-aware ExcludeRules, wildcard-aware IncludeRules - defaulting to effective (the rule ships enabled) only when nothing disables or omits it. Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 28s —— View job PR Review
Latest commit (
|
| Check | Location | Status |
|---|---|---|
@($null) false-failure via Where-Object { $_ } |
line 79 | ✅ |
.psd1 parse guard — hard fail on malformed settings |
lines 37–43 | ✅ |
Error accumulation via AddRange in foreach loop |
lines 75–78 | ✅ |
| NRE narrowed to PSUseCompatibleSyntax via 3-condition guard | lines 92–99 | ✅ |
Remaining nit (carried across all review passes — still present)
Comment inaccuracy (line 73)
"a foreach statement (not ForEach-Object) keeps them in this scope so they accumulate"
The accumulation is from the explicit $saErrors.AddRange(@($err)) call (line 77), not from foreach itself. foreach matters because it runs in the enclosing scope rather than a child scriptblock scope (as ForEach-Object would), making $err readable immediately after each Invoke-ScriptAnalyzer call — but foreach does not accumulate anything automatically. A future reader might conclude the keyword is doing the accumulation work. Fix this →
Not a blocker — doesn't affect correctness.
All files — final summary
| File | Finding | Status |
|---|---|---|
psscriptanalyzer-staged.ps1:56–58 |
Rules.X.Enable = $false check — Bugbot Medium resolved |
✅ |
psscriptanalyzer-staged.ps1:61, 64 |
Wildcard -like matching — Codex P2 resolved |
✅ |
psscriptanalyzer-staged.ps1:79 |
@($null) false-failure fixed |
✅ |
psscriptanalyzer-staged.ps1:37–43 |
.psd1 parse guard |
✅ |
psscriptanalyzer-staged.ps1:92–99 |
NRE triage — 3-condition guard | ✅ |
psscriptanalyzer-staged.ps1:73 |
Comment conflates foreach scope with accumulation (from AddRange) |
Nit |
modules/typos/_typos.toml:17 |
\r?\n CRLF-safe fix |
✅ |
.editorconfig:1–11 |
Broadened header; Biome path qualified to standards repo | ✅ |
.shellcheckrc / modules/shellcheck/.shellcheckrc |
"standards repo's" qualification; same-SHA sync | ✅ |
No blocking issues. All substantive findings from prior review passes are resolved. The PR is in good shape to merge.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit decebb1. Configure here.
There was a problem hiding this comment.
Stale comment
Risk: medium. Not approving: Cursor Bugbot completed as skipped and reported 1 unresolved finding in
psscriptanalyzer-staged.ps1on the latest commit. Human review is needed; no reviewers assigned because the only repo contributor is the PR author.Sent by Cursor Approval Agent: Pull Request Router and Approver
…urface all analyzer errors The staged-file hook tolerated a benign PSUseCompatibleSyntax NullReferenceException by inferring whether that rule was "effective" for the scan. That inference drew a stream of valid edge-case findings (default Enable=$false, scalar vs array settings, wildcard include/exclude) - accidental complexity in service of suppressing one benign error. Remove the whole surface instead: exclude PSUseCompatibleSyntax from this fast lane via -ExcludeRule so the rule never runs and its benign NRE never arises, then surface EVERY analyzer/engine error with no message-based suppression. This is strictly non-silent - a rule that fails to load or a broken ruleset now always fails the hook, the PR's stated intent. The rule remains enforced authoritatively in CI (the gate). Tradeoff: a consumer that explicitly enabled PSUseCompatibleSyntax loses it in the fast pre-commit lane but still gets it in CI. Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 44s —— View job PR Review
Latest commit (
|
| File | Finding | Status |
|---|---|---|
psscriptanalyzer-staged.ps1 |
Refactor: exclude PSUseCompatibleSyntax rather than infer its state — eliminates problem class | ✅ |
psscriptanalyzer-staged.ps1:50 |
-ExcludeRule alongside -Settings — correct, exclusions additive |
✅ |
psscriptanalyzer-staged.ps1:55–59 |
Error accumulation via AddRange in foreach — correct |
✅ |
psscriptanalyzer-staged.ps1:60 |
@($null) false-failure guard preserved |
✅ |
psscriptanalyzer-staged.ps1:62–68 |
All errors surfaced, no suppression | ✅ |
| Bugbot Low: scalar rules string enumeration | Obsolete — relevant code deleted | ✅ |
modules/typos/_typos.toml:17 |
\r?\n CRLF-safe fix |
✅ |
.editorconfig:1–11 |
Broadened header; Biome path qualified to standards repo | ✅ |
.shellcheckrc / modules/shellcheck/.shellcheckrc |
"standards repo's" qualification; same-SHA sync | ✅ |
No blocking issues. The refactor is architecturally sounder than the approach it replaced — the complexity budget was being spent on inference logic that is simply unnecessary when the rule can be excluded outright. All substantive findings from prior review passes are resolved. Ready to merge.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 36313ecc7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
## Summary - add a centralized GitHub Actions runner policy that enforces approved selector routing, public/hosted boundaries, explicit read-only permissions, cancellation-safe literal hosted fallback, and machine-readable hosted exceptions - derive the required literal fallback from the governed policy default, so changing an approved hosted image is a policy/configuration change rather than parser-code surgery - route Standards' 28 eligible private Linux workloads through the governed selector while retaining exact hosted exceptions for policy and control-plane boundaries - recursively validate repository-local reusable workflows and caller/callee permission narrowing without allowing arbitrary secrets, tokens, inputs, labels, or runner expressions - distribute the locked policy runtime and Node version to six enrolled private consumers from one deterministic manifest - harden staged .NET formatting and PSScriptAnalyzer adapters with deterministic cross-platform path semantics and per-target no-profile PowerShell isolation - keep the complete .NET-format named job managed by Standards while each consumer owns only strict data in `.lefthook/dotnet-format.json` - preserve executable source and consumer index modes through distribution - pin every production selector/reusable and Actionlint parity reference to merged `ci-workflows/main` commit `99ac2f8c5b09dbb785d4eaf18465cbd96c30290c` ## Dependencies The final routing contract is the immutable squash merge from melodic-software/ci-workflows#74 (including stacked #76/#77): - `99ac2f8c5b09dbb785d4eaf18465cbd96c30290c` ## Reviewed head `0795d22c89cb8fae11642ede9757e7b43fd5d546` ## Validation Independent author, reviewer, recheck, and integration-review gates all PASS with no findings. - runner-policy adversarial suite: 83/83, including alternate configured hosted-default proof - Standards private self-audit: PASS - .NET/Lefthook adapter: 12/12 - pinned Lefthook 2.1.9 validate, dump, and actual job execution: PASS - independent argv probe: spaces, semicolons, and `$()` remain inert data with `shell:false` - production distribution suite: 114/114 under checksum-pinned yq 4.53.3 in author native Linux and hosted Linux - independent reviewer inspected the exact-head hosted log and confirmed assertions 1 through 114 - exact executable-bit gate: PASS; both source CLIs are index mode `100755` - routing graph: 28 selectors, 28 workloads, 31 actual `ci-status` gates, zero selector gates - final pin proof: exactly 46 merged-main references, zero stale full/short feature-stack references, and 25 preserved transitional compatibility references - all eight changed files reconstruct byte-for-byte from only the two intended SHA/comment substitutions - Actionlint 1.7.12 plus hosted checksum-verified ShellCheck 0.11.0: PASS - all 10 uniquely referenced workflow/action paths exist at the immutable ci-workflows commit - six workflow schemas, Zizmor medium/high, Biome, Markdown, ShellCheck, Gitleaks, full Lefthook, and diff checks: PASS - signed final pin commit: `0795d22c89cb8fae11642ede9757e7b43fd5d546` All 63 hosted checks pass on this exact head. ## Authoritative basis - GitHub Actions workflow syntax and runner routing: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax - Node cross-platform path semantics: https://nodejs.org/api/path.html#pathwin32 - Lefthook v2.1.9 named-job merge contract: https://github.com/evilmartians/lefthook/blob/v2.1.9/docs/configuration/jobs.md - Lefthook v2.1.9 job templates: https://github.com/evilmartians/lefthook/blob/v2.1.9/docs/configuration/templates.md ## Rollout safety This PR does not change GitHub variables, secrets, runners, repository settings, or live infrastructure. Production routing remains hosted until the IaC and physical canary gates are applied later. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Large CI workflow refactor with secrets/vars for runner selection and a new security gate; misconfiguration could break merges or route jobs incorrectly until fleet is live. > > **Overview** > Introduces a **YAML-aware runner policy** (`components/runner-policy`, `.github/runner-policy.json`, `policy.json`) and a hosted **Runner policy** CI lane that tests and enforces it against workflow inventory and repository visibility. > > **CI routing** shifts eligible lint/contract jobs from fixed `ubuntu-latest` to paired `select-runner` + workload jobs using `needs.select-*.outputs.runner || 'ubuntu-24.04'`, `if: ${{ !cancelled() }}`, and `merge_group` support. Control-plane jobs (runner-policy gate, ci-status, zizmor, osv-scanner) stay on explicit hosted runners with documented exceptions. `ci-status` now requires `runner-policy`, treats only `success` as pass (not `skipped`), and pins several workflows to `ci-workflows@99ac2f8`. > > **Local hooks:** Lefthook .NET formatting moves to a consumer-owned `.lefthook/dotnet-format.json` and `dotnet-format-staged.mjs` (shell-less `dotnet format whitespace`). PSScriptAnalyzer staged checks run **one target per fresh `pwsh` worker**; `PSUseCorrectCasing` is removed from settings. Dependabot gains an npm root for `components/runner-policy`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0795d22. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->



Config-hygiene fixes surfaced by a downstream code-review pass (kyle-sexton/provisioning). All are in the Track-B source configs; consumers pick them up via the sync manifest (
_typos.toml,.editorconfig,.shellcheckrc), except the lefthook runner which is manually adopted.Substantive (silent-wrong-behavior bugs)
modules/typos/_typos.toml— thespellchecker:ignore-next-linedirective regex used a bare\n, so on a CRLF file the\rwas never matched and the pragma silently suppressed nothing (siblings are CRLF-aware via(?Rm)/(?s)). Added\r?. Verified withtyposon a CRLF fixture: the next line is now suppressed; an unprotected line still flags.modules/lefthook/psscriptanalyzer-staged.ps1—ErrorAction = 'SilentlyContinue'swallowed every non-terminating analyzer error, not just the one benignPSUseCompatibleSyntaxNRE its comment justified. A malformedPSScriptAnalyzerSettings.psd1(or a rule that failed to load) would make the hook report clean while running unruled. Now: validate the settings parse (fail loud otherwise), capture errors via-ErrorVariable, drop only the benignObject reference not setNRE, and re-surface anything else. Logic verified locally (parse-guard, error triage, loop accumulation); PSScriptAnalyzer clean.Cosmetic (pointer/header accuracy so copies read right downstream)
.editorconfig— header claimed only Markdown/shell/PowerShell+batch, but the file also carries JSON/YAML/TOML, JS/TS, git-config, and lockfile sections; broadened. Named Biome's config home as the standards repo'smodules/typescriptso a consumer's copy doesn't read it as a dangling local path..shellcheckrc(root +modules/shellcheck) — qualified "its canonical home ismodules/shellcheck/" as the standards repo's path, same reason.Verified: PSScriptAnalyzer 0, editorconfig-checker clean,
_typos.tomlvalid TOML, lefthook pre-commit green.🤖 Generated with Claude Code
https://claude.ai/code/session_01JLR9bgyuhEX6YUUkAhkhy5
Note
Medium Risk
Changes pre-commit PowerShell lint behavior (stricter failures on bad settings or analyzer errors); typos and comment edits are low impact but the hook affects every staged PS commit using Lefthook.
Overview
Fixes silent-wrong behavior in synced Track-B configs and the Lefthook PowerShell lane.
modules/typos/_typos.toml— thespellchecker:ignore-next-lineignore regex now uses\r?\nso CRLF files actually honor the pragma (a bare\nleft the next line unprotected).modules/lefthook/psscriptanalyzer-staged.ps1— pre-commit no longer runs withSilentlyContinueon the whole analyzer pass. It parsesPSScriptAnalyzerSettings.psd1up front and exits on failure, excludesPSUseCompatibleSyntaxin this fast lane (CI still enforces it), and fails on any captured analyzer/engine errors instead of reporting clean while unruled..editorconfigand.shellcheckrc(root +modules/shellcheck) — comment-only updates: broader file-class coverage in the header and explicit “standards repo” paths so synced copies don’t read like broken local references.Reviewed by Cursor Bugbot for commit 36313ec. Bugbot is set up for automated code reviews on this repo. Configure here.