diff --git a/docs/reference/steps.md b/docs/reference/steps.md index f19961cf..cb287dba 100644 --- a/docs/reference/steps.md +++ b/docs/reference/steps.md @@ -9,10 +9,10 @@ This page documents built-in IdLE steps discovered from `Invoke-IdleStep*` funct ## EmitEvent -- **Step Name**: $stepType -- **Implementation**: $commandName -- **Idempotent**: $idempotent -- **Contracts**: $contracts +- **Step Name**: `EmitEvent` +- **Implementation**: `Invoke-IdleStepEmitEvent` +- **Idempotent**: `Unknown` +- **Contracts**: `Unknown` - **Events**: Unknown **Synopsis** @@ -33,10 +33,10 @@ _Unknown (not detected automatically). Document required With.* keys in the step ## EnsureAttribute -- **Step Name**: $stepType -- **Implementation**: $commandName -- **Idempotent**: $idempotent -- **Contracts**: $contracts +- **Step Name**: `EnsureAttribute` +- **Implementation**: `Invoke-IdleStepEnsureAttribute` +- **Idempotent**: `Yes` +- **Contracts**: `Provider must implement method: EnsureAttribute` - **Events**: Unknown **Synopsis** @@ -64,10 +64,10 @@ The step is idempotent by design: it converges state to the desired value. ## EnsureEntitlement -- **Step Name**: $stepType -- **Implementation**: $commandName -- **Idempotent**: $idempotent -- **Contracts**: $contracts +- **Step Name**: `EnsureEntitlement` +- **Implementation**: `Invoke-IdleStepEnsureEntitlement` +- **Idempotent**: `Yes` +- **Contracts**: `Unknown` - **Events**: Unknown **Synopsis** @@ -79,6 +79,7 @@ Ensures that an entitlement assignment is present or absent for an identity. This provider-agnostic step uses entitlement provider contracts to converge an assignment to the desired state. The host must supply a provider instance via `Context.Providers[]` that implements: + - ListEntitlements(identityKey) - GrantEntitlement(identityKey, entitlement) - RevokeEntitlement(identityKey, entitlement) diff --git a/src/IdLE.Core/Private/Copy-IdleRedactedObject.ps1 b/src/IdLE.Core/Private/Copy-IdleRedactedObject.ps1 index 0b2022e7..6c5b1e3a 100644 --- a/src/IdLE.Core/Private/Copy-IdleRedactedObject.ps1 +++ b/src/IdLE.Core/Private/Copy-IdleRedactedObject.ps1 @@ -1,5 +1,6 @@ function Copy-IdleRedactedObject { [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'RedactionMarker', Justification = 'Used within nested helper functions for redaction output.')] param( [Parameter()] [AllowNull()] diff --git a/src/IdLE.Core/Private/Invoke-IdleWithRetry.ps1 b/src/IdLE.Core/Private/Invoke-IdleWithRetry.ps1 index 5d99745b..7a8c44da 100644 --- a/src/IdLE.Core/Private/Invoke-IdleWithRetry.ps1 +++ b/src/IdLE.Core/Private/Invoke-IdleWithRetry.ps1 @@ -174,7 +174,8 @@ function Invoke-IdleWithRetry { ) } catch { - # Intentionally ignored. + # Intentionally ignored, but surfaced for diagnostics. + Write-Verbose "EventSink.WriteEvent failed: $($_.Exception.Message)" } } diff --git a/src/IdLE.Core/Private/New-IdleEventSink.ps1 b/src/IdLE.Core/Private/New-IdleEventSink.ps1 index 532133c6..961e3d24 100644 --- a/src/IdLE.Core/Private/New-IdleEventSink.ps1 +++ b/src/IdLE.Core/Private/New-IdleEventSink.ps1 @@ -1,5 +1,6 @@ function New-IdleEventSink { [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'EventBuffer', Justification = 'Passed to Write-IdleEvent via closure.')] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] diff --git a/src/IdLE.Core/Private/Test-IdleCondition.ps1 b/src/IdLE.Core/Private/Test-IdleCondition.ps1 index af6c60c5..9708a514 100644 --- a/src/IdLE.Core/Private/Test-IdleCondition.ps1 +++ b/src/IdLE.Core/Private/Test-IdleCondition.ps1 @@ -1,5 +1,6 @@ function Test-IdleCondition { [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Context', Justification = 'Used for path resolution within nested helper functions.')] param( [Parameter(Mandatory)] [ValidateNotNull()] diff --git a/src/IdLE.Core/Private/Write-IdleEvent.ps1 b/src/IdLE.Core/Private/Write-IdleEvent.ps1 index 3bcb0fe7..0c845c86 100644 --- a/src/IdLE.Core/Private/Write-IdleEvent.ps1 +++ b/src/IdLE.Core/Private/Write-IdleEvent.ps1 @@ -20,7 +20,7 @@ function Write-IdleEvent { # # We never mutate the original event object. We emit a redacted copy. $shouldEmitToSink = ($null -ne $EventSink) - $shouldBuffer = ($null -ne $EventBuffer) + $shouldBuffer = ($null -ne $EventBuffer) $eventToEmit = $Event if ($shouldEmitToSink -or $shouldBuffer) { diff --git a/src/IdLE.Core/Public/Invoke-IdlePlanObject.ps1 b/src/IdLE.Core/Public/Invoke-IdlePlanObject.ps1 index 7ef5b630..e3409041 100644 --- a/src/IdLE.Core/Public/Invoke-IdlePlanObject.ps1 +++ b/src/IdLE.Core/Public/Invoke-IdlePlanObject.ps1 @@ -316,11 +316,16 @@ function Invoke-IdlePlanObject { } } - $context.EventSink.WriteEvent('RunStarted', 'Plan execution started.', $null, @{ - CorrelationId = $corr - Actor = $actor - StepCount = @($Plan.Steps).Count - }) + $context.EventSink.WriteEvent( + 'RunStarted', + 'Plan execution started.', + $null, + @{ + CorrelationId = $corr + Actor = $actor + StepCount = @($Plan.Steps).Count + } + ) $failed = $false $stepResults = @() @@ -351,19 +356,29 @@ function Invoke-IdlePlanObject { Attempts = 1 } - $context.EventSink.WriteEvent('StepNotApplicable', "Step '$stepName' not applicable (condition not met).", $stepName, @{ - StepType = $stepType - Index = $i - }) + $context.EventSink.WriteEvent( + 'StepNotApplicable', + "Step '$stepName' not applicable (condition not met).", + $stepName, + @{ + StepType = $stepType + Index = $i + } + ) $i++ continue } - $context.EventSink.WriteEvent('StepStarted', "Step '$stepName' started.", $stepName, @{ - StepType = $stepType - Index = $i - }) + $context.EventSink.WriteEvent( + 'StepStarted', + "Step '$stepName' started.", + $stepName, + @{ + StepType = $stepType + Index = $i + } + ) try { $impl = Resolve-IdleStepHandler -StepType ([string]$stepType) -StepRegistry $stepRegistry @@ -415,19 +430,29 @@ function Invoke-IdlePlanObject { if ($result.Status -eq 'Failed') { $failed = $true - $context.EventSink.WriteEvent('StepFailed', "Step '$stepName' failed.", $stepName, @{ - StepType = $stepType - Index = $i - Error = $result.Error - }) + $context.EventSink.WriteEvent( + 'StepFailed', + "Step '$stepName' failed.", + $stepName, + @{ + StepType = $stepType + Index = $i + Error = $result.Error + } + ) break } - $context.EventSink.WriteEvent('StepCompleted', "Step '$stepName' completed.", $stepName, @{ - StepType = $stepType - Index = $i - }) + $context.EventSink.WriteEvent( + 'StepCompleted', + "Step '$stepName' completed.", + $stepName, + @{ + StepType = $stepType + Index = $i + } + ) } catch { $failed = $true @@ -442,11 +467,16 @@ function Invoke-IdlePlanObject { Attempts = 1 } - $context.EventSink.WriteEvent('StepFailed', "Step '$stepName' failed.", $stepName, @{ - StepType = $stepType - Index = $i - Error = $err.Exception.Message - }) + $context.EventSink.WriteEvent( + 'StepFailed', + "Step '$stepName' failed.", + $stepName, + @{ + StepType = $stepType + Index = $i + Error = $err.Exception.Message + } + ) break } @@ -470,9 +500,14 @@ function Invoke-IdlePlanObject { } if ($failed -and @($planOnFailureSteps).Count -gt 0) { - $context.EventSink.WriteEvent('OnFailureStarted', 'Executing OnFailureSteps (best effort).', $null, @{ - OnFailureStepCount = @($planOnFailureSteps).Count - }) + $context.EventSink.WriteEvent( + 'OnFailureStarted', + 'Executing OnFailureSteps (best effort).', + $null, + @{ + OnFailureStepCount = @($planOnFailureSteps).Count + } + ) $onFailureHadFailures = $false $onFailureStepResults = @() @@ -502,19 +537,29 @@ function Invoke-IdlePlanObject { Attempts = 1 } - $context.EventSink.WriteEvent('OnFailureStepNotApplicable', "OnFailure step '$ofName' not applicable (condition not met).", $ofName, @{ - StepType = $ofType - Index = $j - }) + $context.EventSink.WriteEvent( + 'OnFailureStepNotApplicable', + "OnFailure step '$ofName' not applicable (condition not met).", + $ofName, + @{ + StepType = $ofType + Index = $j + } + ) $j++ continue } - $context.EventSink.WriteEvent('OnFailureStepStarted', "OnFailure step '$ofName' started.", $ofName, @{ - StepType = $ofType - Index = $j - }) + $context.EventSink.WriteEvent( + 'OnFailureStepStarted', + "OnFailure step '$ofName' started.", + $ofName, + @{ + StepType = $ofType + Index = $j + } + ) try { $impl = Resolve-IdleStepHandler -StepType ([string]$ofType) -StepRegistry $stepRegistry @@ -564,17 +609,27 @@ function Invoke-IdlePlanObject { if ($result.Status -eq 'Failed') { $onFailureHadFailures = $true - $context.EventSink.WriteEvent('OnFailureStepFailed', "OnFailure step '$ofName' failed.", $ofName, @{ - StepType = $ofType - Index = $j - Error = $result.Error - }) + $context.EventSink.WriteEvent( + 'OnFailureStepFailed', + "OnFailure step '$ofName' failed.", + $ofName, + @{ + StepType = $ofType + Index = $j + Error = $result.Error + } + ) } else { - $context.EventSink.WriteEvent('OnFailureStepCompleted', "OnFailure step '$ofName' completed.", $ofName, @{ - StepType = $ofType - Index = $j - }) + $context.EventSink.WriteEvent( + 'OnFailureStepCompleted', + "OnFailure step '$ofName' completed.", + $ofName, + @{ + StepType = $ofType + Index = $j + } + ) } } catch { @@ -590,11 +645,16 @@ function Invoke-IdlePlanObject { Attempts = 1 } - $context.EventSink.WriteEvent('OnFailureStepFailed', "OnFailure step '$ofName' failed.", $ofName, @{ - StepType = $ofType - Index = $j - Error = $err.Exception.Message - }) + $context.EventSink.WriteEvent( + 'OnFailureStepFailed', + "OnFailure step '$ofName' failed.", + $ofName, + @{ + StepType = $ofType + Index = $j + Error = $err.Exception.Message + } + ) } $j++ @@ -608,17 +668,27 @@ function Invoke-IdlePlanObject { Steps = @($onFailureStepResults) } - $context.EventSink.WriteEvent('OnFailureCompleted', "OnFailureSteps finished (status: $onFailureStatus).", $null, @{ - Status = $onFailureStatus - StepCount = @($planOnFailureSteps).Count - }) + $context.EventSink.WriteEvent( + 'OnFailureCompleted', + "OnFailureSteps finished (status: $onFailureStatus).", + $null, + @{ + Status = $onFailureStatus + StepCount = @($planOnFailureSteps).Count + } + ) } # RunCompleted should always be the last event for deterministic event order. - $context.EventSink.WriteEvent('RunCompleted', "Plan execution finished (status: $runStatus).", $null, @{ - Status = $runStatus - StepCount = @($Plan.Steps).Count - }) + $context.EventSink.WriteEvent( + 'RunCompleted', + "Plan execution finished (status: $runStatus).", + $null, + @{ + Status = $runStatus + StepCount = @($Plan.Steps).Count + } + ) # Issue #48: # Redact provider configuration/state at the output boundary (execution result). diff --git a/src/IdLE.Core/Public/New-IdlePlanObject.ps1 b/src/IdLE.Core/Public/New-IdlePlanObject.ps1 index 73b56bf4..8014d4e2 100644 --- a/src/IdLE.Core/Public/New-IdlePlanObject.ps1 +++ b/src/IdLE.Core/Public/New-IdlePlanObject.ps1 @@ -94,7 +94,7 @@ function New-IdlePlanObject { return $null } - $m = $Object | Get-Member -Name $Name -MemberType NoteProperty,Property -ErrorAction SilentlyContinue + $m = $Object | Get-Member -Name $Name -MemberType NoteProperty, Property -ErrorAction SilentlyContinue if ($null -eq $m) { return $null } @@ -378,7 +378,7 @@ function New-IdlePlanObject { return $Step.ContainsKey($Key) } - $m = $Step | Get-Member -Name $Key -MemberType NoteProperty,Property -ErrorAction SilentlyContinue + $m = $Step | Get-Member -Name $Key -MemberType NoteProperty, Property -ErrorAction SilentlyContinue return ($null -ne $m) } diff --git a/src/IdLE.Steps.Common/Public/Invoke-IdleStepEnsureEntitlement.ps1 b/src/IdLE.Steps.Common/Public/Invoke-IdleStepEnsureEntitlement.ps1 index cc51c7ad..39a2a9a5 100644 --- a/src/IdLE.Steps.Common/Public/Invoke-IdleStepEnsureEntitlement.ps1 +++ b/src/IdLE.Steps.Common/Public/Invoke-IdleStepEnsureEntitlement.ps1 @@ -7,6 +7,7 @@ function Invoke-IdleStepEnsureEntitlement { This provider-agnostic step uses entitlement provider contracts to converge an assignment to the desired state. The host must supply a provider instance via `Context.Providers[]` that implements: + - ListEntitlements(identityKey) - GrantEntitlement(identityKey, entitlement) - RevokeEntitlement(identityKey, entitlement) diff --git a/src/IdLE/IdLE.psm1 b/src/IdLE/IdLE.psm1 index ae87fe5a..b3c51e68 100644 --- a/src/IdLE/IdLE.psm1 +++ b/src/IdLE/IdLE.psm1 @@ -24,6 +24,7 @@ function Import-IdleCoreModule { } catch { # Continue with local fallback + Write-Verbose "Failed to import '$($script:IdleCoreModuleName)' from PSModulePath: $($_.Exception.Message)" } # 2) Fallback: repo clone layout (IdLE and IdLE.Core side-by-side under /src) @@ -59,6 +60,7 @@ function Import-IdleBuiltInStepsModule { } catch { # Continue with local fallback + Write-Verbose "Failed to import '$($script:IdleBuiltInStepsModuleName)' from PSModulePath: $($_.Exception.Message)" } # 2) Fallback: repo clone layout (IdLE and packs side-by-side under /src) diff --git a/tools/Generate-IdleCmdletReference.ps1 b/tools/Generate-IdleCmdletReference.ps1 index e1d8a0c7..935e9799 100644 --- a/tools/Generate-IdleCmdletReference.ps1 +++ b/tools/Generate-IdleCmdletReference.ps1 @@ -117,8 +117,7 @@ function Get-IdleCmdletMetadata { [string[]] $Exclude = @() ) - $cmds = - Get-Command -Module $ModuleName -CommandType Function, Cmdlet -ErrorAction Stop | + $cmds = Get-Command -Module $ModuleName -CommandType Function, Cmdlet -ErrorAction Stop | Where-Object { $_.Name -and $_.Name -notin $Exclude } | Sort-Object -Property Name -Unique @@ -129,6 +128,7 @@ function Get-IdleCmdletMetadata { } catch { # Missing help should not fail generation; we reflect it in the synopsis. + Write-Verbose "Help not available for '$($cmd.Name)': $($_.Exception.Message)" } $synopsis = '' diff --git a/tools/Generate-IdleStepReference.ps1 b/tools/Generate-IdleStepReference.ps1 index a58ccbfb..f09e57dd 100644 --- a/tools/Generate-IdleStepReference.ps1 +++ b/tools/Generate-IdleStepReference.ps1 @@ -201,16 +201,16 @@ function ConvertTo-IdleStepMarkdownSection { } $providerMethod = Get-IdleProviderMethodHintFromDescription -DescriptionText $description - $contracts = if ($providerMethod) { "Provider must implement method: `$providerMethod" } else { 'Unknown' } + $contracts = if ($providerMethod) { "Provider must implement method: $providerMethod" } else { 'Unknown' } $sb = New-Object System.Text.StringBuilder [void]$sb.AppendLine("## $stepType") [void]$sb.AppendLine() - [void]$sb.AppendLine(("- **Step Name**: `$stepType")) - [void]$sb.AppendLine(("- **Implementation**: `$commandName")) - [void]$sb.AppendLine(("- **Idempotent**: `$idempotent")) - [void]$sb.AppendLine(("- **Contracts**: `$contracts")) + [void]$sb.AppendLine(("- **Step Name**: ``{0}``" -f $stepType)) + [void]$sb.AppendLine(("- **Implementation**: ``{0}``" -f $commandName)) + [void]$sb.AppendLine(("- **Idempotent**: ``{0}``" -f $idempotent)) + [void]$sb.AppendLine(("- **Contracts**: ``{0}``" -f $contracts)) [void]$sb.AppendLine(("- **Events**: Unknown")) [void]$sb.AppendLine() [void]$sb.AppendLine("**Synopsis**") @@ -295,14 +295,12 @@ foreach ($m in $StepModules) { } # Discover step commands from the configured step modules. -$stepCommands = - foreach ($m in $StepModules) { - Get-Command -Module $m -CommandType Function -ErrorAction SilentlyContinue | - Where-Object { $_.Name -like 'Invoke-IdleStep*' } - } +$stepCommands = foreach ($m in $StepModules) { + Get-Command -Module $m -CommandType Function -ErrorAction SilentlyContinue | + Where-Object { $_.Name -like 'Invoke-IdleStep*' } +} -$stepCommands = - $stepCommands | +$stepCommands = $stepCommands | Where-Object { $_.Name -and $_.Name -notin $ExcludeCommands } | Sort-Object -Property Name -Unique diff --git a/tools/Set-IdleModuleVersion.ps1 b/tools/Set-IdleModuleVersion.ps1 index 9ee4a236..4f71aafc 100644 --- a/tools/Set-IdleModuleVersion.ps1 +++ b/tools/Set-IdleModuleVersion.ps1 @@ -99,9 +99,7 @@ function Get-ManifestModuleInfo { $content = Get-Content -Path $ManifestPath -Raw - $moduleVersion = - if ($content -match "(?m)^\s*ModuleVersion\s*=\s*'([^']+)'") { $Matches[1] } - else { $null } + $moduleVersion = if ($content -match "(?m)^\s*ModuleVersion\s*=\s*'([^']+)'") { $Matches[1] } else { $null } $moduleName = Split-Path -Path (Split-Path -Path $ManifestPath -Parent) -Leaf