Skip to content

Commit 5b81056

Browse files
WilliamBerryiiiBill Berry
andauthored
feat(scripts)(settings): add ADR consistency lint infrastructure (#1552)
## Description Added a PowerShell-based linter that enforces structural consistency between Architecture Decision Record frontmatter and body sections in *docs/planning/adrs/*. The linter is shipped as two reusable modules, a CLI entry script, a JSON rule registry, and three Draft-07 JSON Schemas, with editor schema bindings, a markdownlint exclusion for fixture corpora, an `npm run lint:adr-consistency` entry, and a Pester 5.x test suite covering all nine rules through a paired pass/fail fixture pattern. The change is additive. No existing linter was modified except a one-line tolerance added to **skill structure validation** so skills can carry a *templates/* subdirectory without warning. The new `lint:adr-consistency` script is invokable on its own and is **not** wired into the `lint:all` chain in this PR. ### Linter core * Added [scripts/linting/Modules/AdrConsistency.psm1](scripts/linting/Modules/AdrConsistency.psm1) (857 lines) with the public `Invoke-AdrConsistencyValidation` dispatcher and nine private `Test-*` rule functions covering `ADR-CONSISTENCY-001` through `ADR-CONSISTENCY-009`. The module declares `#Requires -Version 7.0` and pins `PowerShell-Yaml` to version `0.4.7`, loads `../rules/adr-consistency-rules.json` into `$script:RuleRegistry` keyed by rule id, and routes all violation construction through a single `New-AdrViolation` factory that owns rule lookup, `{token}` substitution, and severity assignment. * Added [scripts/linting/Modules/AdrBodyParser.psm1](scripts/linting/Modules/AdrBodyParser.psm1) (445 lines) with the public `Get-AdrBodySections` parser. The parser splits an ADR body into structured sections — *AffectedComponents*, *DecisionDrivers*, *DecisionOutcomeMatrixDrivers*, *BadConsequences*, *RisksAndMitigationsRisks*, *Confirmation*, and three path-token sets — and exposes only the parser; helpers like `Get-AdrH2Section`, `Get-AdrH3SectionInH2` (for MADR v4 `### Consequences` under `## Decision Outcome`), `Get-AdrTableRows`, `Get-AdrPathTokens`, `Get-AdrBadConsequenceBullets`, and a stateful `Remove-AdrFencedCodeBlocks` walker remain private. * Added [scripts/linting/Validate-AdrConsistency.ps1](scripts/linting/Validate-AdrConsistency.ps1) as the CLI entry script. Parameters cover `-Paths`, `-Files`, `-ExcludePaths`, `-WarningsAsErrors`, `-ChangedFilesOnly`, `-BaseBranch`, and `-OutputPath` (defaulting to *logs/adr-consistency-results.json*). The script imports `Modules/AdrConsistency.psm1`, `Modules/LintingHelpers.psm1`, and `../lib/Modules/CIHelpers.psm1`; resolves the repo root via `git rev-parse --show-toplevel` with a `$PSScriptRoot` fallback; and uses an ordinal-ignore-case `StartsWith` boundary check to reject paths that escape the repository. Each violation prints to host output, and on CI the script also emits `Write-CIAnnotation` per finding plus a single `Write-CIStepSummary`. Exit code is `1` when error count is non-zero, or when `-WarningsAsErrors` is set and warning count is non-zero. ### Rule registry, schemas, and editor integration * Added [scripts/linting/rules/adr-consistency-rules.json](scripts/linting/rules/adr-consistency-rules.json) declaring all nine rules with `id`, `severity`, `scope`, `check`, `message`, and `description` fields. Eight rules are `error` severity and one (`ADR-CONSISTENCY-007`, *numeric-claim-generalized*) is `warn`. Scopes split as `frontmatter` (002, 008), `body` (003, 004, 005, 006, 007), and `cross-region` (001, 009). The kebab-case `check` slug maps mechanically to the `Test-<PascalCase>` PowerShell function name. * Added [scripts/linting/schemas/adr-consistency-rules.schema.json](scripts/linting/schemas/adr-consistency-rules.schema.json) as a Draft-07 schema for the rule registry. It requires `rules` with `minItems: 1`, pins `id` to `^ADR-CONSISTENCY-\d{3}$`, restricts `severity` to `error|warn` and `scope` to `frontmatter|body|cross-region`, and requires `check` to be kebab-case. * Added [scripts/linting/schemas/adr-frontmatter.schema.json](scripts/linting/schemas/adr-frontmatter.schema.json) as a Draft-07 schema for `docs/planning/adrs/NNNN-{kebab-case}.md` frontmatter. Required fields are `id`, `title`, `status`, `proposed_date`, `deciders`, and `affected_components`. The schema models the six-value status taxonomy (`proposed`, `accepted`, `rejected`, `deprecated`, `superseded`, `withdrawn`), constrains `effort` to `S|M|L|XL`, models `success_criteria` items with `metric`/`target`/`measurement_window`/`source`, models `related` items as `path`/`relation` pairs (with relation enum `informational|influenced-by|influences`), pairs each `asr_triggers` item with required `evidence`, and adds an `allOf` conditional that requires `accepted_date` when `status` is `accepted`. * Added [scripts/linting/schemas/adr-config.schema.json](scripts/linting/schemas/adr-config.schema.json) as a Draft-07 schema for `docs/planning/adrs/.adr-config.yml`. Required keys are `project_slug`, `owner`, `default_status`, `decision_id_format`, `template_source`, and `last_decision_id`. `decision_id_format` is constrained to the literal `NNNN`; `last_decision_id` is pinned to `^\d{4}$`. * Modified [scripts/linting/schemas/schema-mapping.json](scripts/linting/schemas/schema-mapping.json) to register two new entries: ADR markdown files via the glob `docs/planning/adrs/[0-9][0-9][0-9][0-9]-*.md` against the *adr-frontmatter* schema, and the rule registry against the *adr-consistency-rules* schema. * Modified [.vscode/settings.json](.vscode/settings.json) to register `./scripts/linting/schemas/adr-config.schema.json` against `**/.adr-config.yml` and `**/.adr-config.yaml` under `yaml.schemas` so editor validation matches the file-on-disk checker. ### Tests and fixtures * Added [scripts/tests/linting/AdrConsistency.Tests.ps1](scripts/tests/linting/AdrConsistency.Tests.ps1) as a Pester 5.x suite tagged `Unit`. A `BeforeDiscovery` block declares a nine-element `$RuleCases` array mapping each rule id to its fixture directory; three `Describe` blocks then run data-driven `It -ForEach` iterations over the cases, asserting that each `pass.md` produces zero violations, each `fail.md` fires its target rule, no violation message contains an unsubstituted `{token}` template, and the validator's return shape exposes `File`/`Violations` properties with consistent fields. The `BeforeAll` block force-imports the consistency module and mocks `Write-Host`; the `AfterAll` block tears down both *AdrConsistency* and its *AdrBodyParser* dependency. * Added 18 fixture files under [scripts/tests/linting/fixtures/adr-consistency/](scripts/tests/linting/fixtures/adr-consistency/) — one folder per rule, each with `pass.md` and `fail.md`. All fixtures derive from a single canonical 76-line *Fixture base ADR 9999* baseline that follows MADR v4 layout: `## Context`, `## Decision Drivers`, `## Considered Options`, `## Decision Outcome` (with a driver matrix and an H3 *Consequences* block split into Good/Bad/Neutral H4 subsections), `## Risks and Mitigations`, `## Confirmation`, `## More Information`, and `## Affected Components`. Each `fail.md` mutates the baseline along exactly one axis to trigger a single target rule (for example, *risks-consequences-pairing/fail.md* swaps the Bad consequence to a risk-shaped statement absent from the Risks and Mitigations table). * Modified [.markdownlint-cli2.jsonc](.markdownlint-cli2.jsonc) to add `scripts/tests/linting/fixtures/**` to the markdownlint `ignores` list so the deliberately defective fail-fixture markdown does not trip project-wide linting. ### Configuration touches * Modified [package.json](package.json) to register `lint:adr-consistency` (`pwsh -NoProfile -File scripts/linting/Validate-AdrConsistency.ps1 -Paths docs/planning/adrs`) between `lint:frontmatter` and `lint:collections-metadata`. The script is **not** added to the `lint:all` chain in this PR. * Modified [scripts/linting/Validate-SkillStructure.ps1](scripts/linting/Validate-SkillStructure.ps1) to add `'templates'` to `$script:RecognizedSubdirectories` alongside the existing `scripts`, `references`, `assets`, `examples`, and `tests` entries. ## Related Issue(s) Closes #1551. ## Type of Change Select all that apply: **Code & Documentation:** * [ ] Bug fix (non-breaking change fixing an issue) * [x] New feature (non-breaking change adding functionality) * [ ] Breaking change (fix or feature causing existing functionality to change) * [ ] Documentation update **Infrastructure & Configuration:** * [ ] GitHub Actions workflow * [x] Linting configuration (markdown, PowerShell, etc.) * [ ] Security configuration * [ ] DevContainer configuration * [ ] Dependency update **AI Artifacts:** * [ ] Reviewed contribution with `prompt-builder` agent and addressed all feedback * [ ] Copilot instructions (`.github/instructions/*.instructions.md`) * [ ] Copilot prompt (`.github/prompts/*.prompt.md`) * [ ] Copilot agent (`.github/agents/*.agent.md`) * [ ] Copilot skill (`.github/skills/*/SKILL.md`) > Note for AI Artifact Contributors: > > * Agents: Research, indexing/referencing other project (using standard VS Code GitHub Copilot/MCP tools), planning, and general implementation agents likely already exist. Review `.github/agents/` before creating new ones. > * Skills: Must include both bash and PowerShell scripts. See [Skills](../docs/contributing/skills.md). > * Model Versions: Only contributions targeting the **latest Anthropic and OpenAI models** will be accepted. Older model versions (e.g., GPT-3.5, Claude 3) will be rejected. > * See [Agents Not Accepted](../docs/contributing/custom-agents.md#agents-not-accepted) and [Model Version Requirements](../docs/contributing/ai-artifacts-common.md#model-version-requirements). **Other:** * [x] Script/automation (`.ps1`, `.sh`, `.py`) * [ ] Other (please describe): ## Sample Prompts (for AI Artifact Contributions) <!-- Not applicable: this PR contains no AI artifacts. --> For detailed contribution requirements, see: * Common Standards: [docs/contributing/ai-artifacts-common.md](../docs/contributing/ai-artifacts-common.md) - Shared standards for XML blocks, markdown quality, RFC 2119, validation, and testing * Agents: [docs/contributing/custom-agents.md](../docs/contributing/custom-agents.md) - Agent configurations with tools and behavior patterns * Prompts: [docs/contributing/prompts.md](../docs/contributing/prompts.md) - Workflow-specific guidance with template variables * Instructions: [docs/contributing/instructions.md](../docs/contributing/instructions.md) - Technology-specific standards with glob patterns * Skills: [docs/contributing/skills.md](../docs/contributing/skills.md) - Task execution utilities with cross-platform scripts ## Testing Ran `npm run lint:adr-consistency` against the working tree. The validator discovered the existing *.adr-config.yml* style entries under *docs/planning/adrs/* and reported `ADR consistency: 1 file(s) | 0 error(s) | 0 warning(s)` with exit code `0`. The Pester suite at *scripts/tests/linting/AdrConsistency.Tests.ps1* exercises all nine rules through paired pass/fail fixtures, validates the validator's return contract, and asserts that no rule message contains an unsubstituted `{token}` placeholder. ## Checklist ### Required Checks * [x] Documentation is updated (if applicable) * [x] Files follow existing naming conventions * [x] Changes are backwards compatible (if applicable) * [x] Tests added for new functionality (if applicable) ### AI Artifact Contributions * [ ] Used `/prompt-analyze` to review contribution * [ ] Addressed all feedback from `prompt-builder` review * [ ] Verified contribution follows common standards and type-specific requirements ### Required Automated Checks The following validation commands must pass before merging: * [x] Markdown linting: `npm run lint:md` * [x] Spell checking: `npm run spell-check` * [x] Frontmatter validation: `npm run lint:frontmatter` * [x] Skill structure validation: `npm run validate:skills` * [x] Link validation: `npm run lint:md-links` — 7 pre-existing baseline failures on `main` not introduced by this PR (`.github/skills/security/secure-by-design/SKILL.md`, `docs/agents/code-review/README.md`, `docs/agents/rai-planning/agent-overview.md`, `docs/agents/rai-planning/phase-reference.md`, `docs/architecture/README.md`, `docs/getting-started/collections.md`, `docs/getting-started/mcp-configuration.md`) * [x] PowerShell analysis: `npm run lint:ps` * [x] Plugin freshness: `npm run plugin:generate` * [x] Docusaurus tests: `npm run docs:test` ## Security Considerations * [x] This PR does not contain any sensitive or NDA information * [x] Any new dependencies have been reviewed for security issues * [x] Security-related scripts follow the principle of least privilege ## Additional Notes The new `lint:adr-consistency` script is intentionally not wired into `lint:all` in this PR. The `docs/planning/adrs/` corpus does not yet contain ADR markdown files, so the linter is a no-op against the current tree. A follow-up PR will introduce the ADR Planner upgrade that produces ADR documents and enable the linter as part of `lint:all`. The `Validate-SkillStructure.ps1` change adds `templates` to `$script:RecognizedSubdirectories`, allowing skills that ship author-facing templates to validate without warnings. No existing skill relies on a `templates/` directory being rejected. --------- Co-authored-by: Bill Berry <wbery@microsoft.com>
1 parent f5e8513 commit 5b81056

38 files changed

Lines changed: 4273 additions & 25 deletions

File tree

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"skillmd",
8181
"smol",
8282
"subcat",
83+
"uncited",
8384
"vally",
8485
"whiteboarding",
8586
"ˈpræksɪs",
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
name: ADR Consistency Validation
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
soft-fail:
7+
description: 'Whether to continue on ADR consistency violations'
8+
required: false
9+
type: boolean
10+
default: false
11+
changed-files-only:
12+
description: 'Only run validation when ADR markdown files changed'
13+
required: false
14+
type: boolean
15+
default: false
16+
upload-sarif:
17+
description: 'Whether to upload SARIF results to Security tab'
18+
required: false
19+
type: boolean
20+
default: false
21+
upload-artifact:
22+
description: 'Whether to upload validation results as artifact'
23+
required: false
24+
type: boolean
25+
default: true
26+
27+
permissions:
28+
contents: read
29+
30+
jobs:
31+
detect-changes:
32+
name: Detect ADR Changes
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
outputs:
37+
has-adr-changes: ${{ steps.detect.outputs.has-adr-changes }}
38+
steps:
39+
- name: Checkout code
40+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
41+
with:
42+
persist-credentials: false
43+
fetch-depth: 0
44+
45+
- name: Check ADR changes
46+
id: detect
47+
shell: pwsh
48+
run: |
49+
if ('${{ inputs.changed-files-only }}' -ne 'true') {
50+
'has-adr-changes=true' >> $env:GITHUB_OUTPUT
51+
Write-Output 'ADR validation requested for all configured ADR files.'
52+
} else {
53+
$baseRef = if ($env:GITHUB_BASE_REF) { $env:GITHUB_BASE_REF } else { 'main' }
54+
$changed = @(git diff --name-only --diff-filter=ACMR "origin/$baseRef...HEAD" -- docs/planning/adrs |
55+
Where-Object { $_ -match '^docs/planning/adrs/.+\.md$' })
56+
57+
if ($changed.Count -gt 0) {
58+
'has-adr-changes=true' >> $env:GITHUB_OUTPUT
59+
Write-Output "Detected $($changed.Count) changed ADR file(s)"
60+
$changed | ForEach-Object { Write-Output "- $_" }
61+
} else {
62+
'has-adr-changes=false' >> $env:GITHUB_OUTPUT
63+
Write-Output 'No ADR markdown changes detected under docs/planning/adrs'
64+
}
65+
}
66+
67+
report-skipped:
68+
name: Report Skipped ADR Validation
69+
runs-on: ubuntu-latest
70+
needs: detect-changes
71+
if: inputs.changed-files-only && needs.detect-changes.outputs.has-adr-changes != 'true'
72+
permissions:
73+
contents: read
74+
steps:
75+
- name: Report skipped validation
76+
shell: pwsh
77+
run: |
78+
@(
79+
'## ADR Consistency Validation',
80+
'',
81+
'No ADR markdown changes detected under docs/planning/adrs. Validation skipped.'
82+
) -join "`n" >> $env:GITHUB_STEP_SUMMARY
83+
84+
validate:
85+
name: Validate ADR Consistency
86+
runs-on: ubuntu-latest
87+
needs: detect-changes
88+
if: needs.detect-changes.outputs.has-adr-changes == 'true'
89+
permissions:
90+
contents: read
91+
steps:
92+
- name: Checkout code
93+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
94+
with:
95+
persist-credentials: false
96+
fetch-depth: 0
97+
98+
- name: Run ADR consistency validation
99+
shell: pwsh
100+
continue-on-error: ${{ inputs.soft-fail }}
101+
run: |
102+
New-Item -ItemType Directory -Force -Path logs | Out-Null
103+
$baseBranch = if ($env:GITHUB_BASE_REF) { "origin/$env:GITHUB_BASE_REF" } else { 'origin/main' }
104+
$params = @{
105+
Paths = @('docs/planning/adrs')
106+
BaseBranch = $baseBranch
107+
OutputPath = 'logs/adr-consistency-results.json'
108+
}
109+
110+
if ('${{ inputs.changed-files-only }}' -eq 'true') {
111+
$params['ChangedFilesOnly'] = $true
112+
}
113+
114+
if ('${{ inputs.upload-sarif }}' -eq 'true') {
115+
$params['SarifOutputPath'] = 'logs/adr-consistency-results.sarif'
116+
}
117+
118+
& scripts/linting/Validate-AdrConsistency.ps1 @params
119+
120+
- name: Upload SARIF handoff
121+
if: inputs.upload-sarif && always()
122+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
123+
with:
124+
name: adr-consistency-sarif
125+
path: logs/adr-consistency-results.sarif
126+
retention-days: 1
127+
if-no-files-found: ignore
128+
129+
- name: Upload validation report
130+
if: inputs.upload-artifact && always()
131+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
132+
with:
133+
name: adr-consistency-results
134+
path: |
135+
logs/adr-consistency-results.json
136+
logs/adr-consistency-results.sarif
137+
retention-days: 90
138+
if-no-files-found: ignore
139+
140+
upload-sarif:
141+
name: Upload ADR SARIF
142+
runs-on: ubuntu-latest
143+
needs: validate
144+
if: inputs.upload-sarif && always() && needs.validate.result != 'skipped'
145+
permissions:
146+
contents: read
147+
security-events: write # Required for SARIF upload to Security tab
148+
steps:
149+
- name: Download SARIF handoff
150+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v6.0.0
151+
with:
152+
name: adr-consistency-sarif
153+
path: logs
154+
155+
- name: Upload SARIF to Security tab
156+
uses: github/codeql-action/upload-sarif@ce729e4d353d580e6cacd6a8cf2921b72e5e310a # v3.27.0
157+
with:
158+
sarif_file: logs/adr-consistency-results.sarif
159+
category: adr-consistency
160+
continue-on-error: true

.github/workflows/pr-validation.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ jobs:
196196
skip-footer-validation: false
197197
warnings-as-errors: true
198198

199+
adr-consistency-validation:
200+
name: ADR Consistency Validation
201+
uses: ./.github/workflows/adr-consistency-validation.yml
202+
permissions:
203+
contents: read
204+
security-events: write # Required for SARIF upload to Security tab
205+
with:
206+
soft-fail: false
207+
changed-files-only: true
208+
upload-sarif: true
209+
upload-artifact: false
210+
199211
ai-artifact-validation:
200212
name: AI Artifact Validation
201213
uses: ./.github/workflows/ai-artifact-validation.yml

.markdownlint-cli2.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"logs/**",
77
"venv/**",
88
"scripts/tests/Fixtures/**",
9+
"scripts/tests/linting/fixtures/**",
910
"extension/README.md",
1011
"extension/README.*.md",
1112
"extension/CHANGELOG.md",

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
],
1919
"./scripts/linting/schemas/docs-frontmatter.schema.json": [
2020
"docs/**/*.md"
21+
],
22+
"./scripts/linting/schemas/adr-config.schema.json": [
23+
"**/.adr-config.yml",
24+
"**/.adr-config.yaml"
2125
]
2226
},
2327
"json.schemas": [

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"lint:links": "pwsh -NoProfile -Command \"& scripts/linting/Invoke-LinkLanguageCheck.ps1 -ExcludePaths 'scripts/tests/**'\"",
1515
"lint:md-links": "pwsh -File scripts/linting/Markdown-Link-Check.ps1",
1616
"lint:frontmatter": "pwsh -NoProfile -Command \"& './scripts/linting/Validate-MarkdownFrontmatter.ps1' -WarningsAsErrors -EnableSchemaValidation\"",
17+
"lint:adr-consistency": "pwsh -NoProfile -File scripts/linting/Validate-AdrConsistency.ps1 -Paths docs/planning/adrs",
1718
"lint:collections-metadata": "pwsh -NoProfile -Command \"./scripts/collections/Validate-Collections.ps1 -OutputPath logs/collection-validation-results.json\"",
1819
"lint:marketplace": "pwsh -File scripts/plugins/Validate-Marketplace.ps1 -OutputPath logs/marketplace-validation-results.json",
1920
"lint:version-consistency": "pwsh -NoProfile -Command \"./scripts/security/Test-ActionVersionConsistency.ps1 -FailOnMismatch -Format Json -OutputPath logs/action-version-consistency-results.json\"",

scripts/linting/Invoke-PSScriptAnalyzer.ps1

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,45 @@ Import-Module (Join-Path $PSScriptRoot "../lib/Modules/CIHelpers.psm1") -Force
3232

3333
#region Functions
3434

35+
function Invoke-ScriptAnalyzerIsolated {
36+
[CmdletBinding()]
37+
[OutputType([System.Object[]])]
38+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseUsingScopeModifierInNewRunspaces', '', Justification = 'Variables are passed into the Start-Job script block via param() and -ArgumentList, so the $using: modifier does not apply.')]
39+
param(
40+
[Parameter(Mandatory = $true)]
41+
[string]$Path,
42+
43+
[Parameter(Mandatory = $true)]
44+
[string]$SettingsPath
45+
)
46+
47+
# Analyze each file in its own child process so every file compiles into a
48+
# fresh dynamic assembly. On Linux/CoreCLR a process permits only one dynamic
49+
# module per dynamic assembly, so analyzing multiple module files in a shared
50+
# runspace throws "more than one dynamic module" on the second .psm1 file.
51+
$job = Start-Job -ScriptBlock {
52+
param($FilePath, $ConfigPath)
53+
Import-Module PSScriptAnalyzer -RequiredVersion 1.25.0
54+
Invoke-ScriptAnalyzer -Path $FilePath -Settings $ConfigPath | ForEach-Object {
55+
[pscustomobject]@{
56+
RuleName = $_.RuleName
57+
Message = $_.Message
58+
Severity = $_.Severity.ToString()
59+
Line = $_.Line
60+
Column = $_.Column
61+
}
62+
}
63+
} -ArgumentList $Path, $SettingsPath
64+
65+
try {
66+
$null = Wait-Job -Job $job
67+
return @(Receive-Job -Job $job)
68+
}
69+
finally {
70+
Remove-Job -Job $job -Force
71+
}
72+
}
73+
3574
function Invoke-PSScriptAnalyzerCore {
3675
[CmdletBinding()]
3776
[OutputType([void])]
@@ -85,12 +124,15 @@ function Invoke-PSScriptAnalyzerCore {
85124
$allResults = @()
86125
$hasErrors = $false
87126

127+
$resolvedConfigPath = (Resolve-Path -LiteralPath $ConfigPath).Path
128+
88129
foreach ($file in $filesToAnalyze) {
89130
$filePath = if ($file -is [System.IO.FileInfo]) { $file.FullName } else { $file }
90131
Write-Host "`n📄 Analyzing: $filePath" -ForegroundColor Cyan
91-
92-
$results = Invoke-ScriptAnalyzer -Path $filePath -Settings $ConfigPath
93-
132+
133+
$resolvedFilePath = (Resolve-Path -LiteralPath $filePath).Path
134+
$results = @(Invoke-ScriptAnalyzerIsolated -Path $resolvedFilePath -SettingsPath $resolvedConfigPath)
135+
94136
if ($results) {
95137
$allResults += $results
96138

0 commit comments

Comments
 (0)