Skip to main content

Directory Inspection

Run inspection without generating output:

$inspection = Get-PSModuleInspection `
-Specification ./PSModule/PSModule.psd1

$inspection.Data
$inspection | Get-PSModuleDiagnostic -Detailed

Inspector output is an ordered dictionary. Missing artifact types normally produce an empty collection or an unconfigured object.

Common Exclusions

Recursive inspectors skip paths containing these segments:

  • .git
  • node_modules
  • artifacts
  • bin
  • obj

They also skip nested directories containing their own .git marker and the current generation output directory. Root-only inspectors do not recurse.

Every check compares the candidate's real location, not its lexical one: a symlink or junction is resolved before any exclusion or containment check runs, so a linked file cannot present content from outside the repository root by way of a path that merely looks like it belongs inside. A resolution that cycles back on itself is rejected rather than followed indefinitely. Path comparisons are case-insensitive on Windows and macOS and case-sensitive on Linux, matching each platform's filesystem.

Within one inspector's own traversal, the same real file reached through two different admitted paths — for example two links pointing at the same target — is only inspected once. This deduplication is scoped to a single inspector's own scan; it does not suppress a different inspector, or a later independent check within the same inspector, from reading the same file for an unrelated purpose.

Dockerfiles

Inputs: root Dockerfile, Dockerfile.*, and *.Dockerfile.

Supported subset: single-line FROM with optional --platform, image, and optional AS alias.

Dockerfiles[]:
Path
Stages[]:
Image
Alias
Platform

Continuations and build-argument expansion in FROM are not interpreted in the current Version 1 parser.

Docker Compose

Inputs: root compose.yaml, compose.yml, docker-compose.yaml, and docker-compose.yml.

Supported subset:

  • top-level services;
  • service names;
  • scalar image;
  • scalar build;
  • nested build.context;
  • nested build.dockerfile; and
  • list-form ports.
ComposeFiles[]:
Path
Services[]:
Name
Image
Build:
Context
Dockerfile
Ports[]

This is a line-oriented subset, not a complete YAML or Compose implementation. Anchors, aliases, flow mappings, interpolation semantics, merged configuration, and extended forms are not resolved.

.NET Projects

Inputs: recursive *.csproj.

DotNetProjects[]:
Path
Name
Sdk
TargetFrameworks[]
OutputType
IsExecutable
IsTestProject
AssemblyName
PackageId
NukeRootDirectory
NukeScriptDirectory
PackageReferences[]:
Name
Version
ProjectReferences[]:
Path
Aliases[]

The first matching property group supplies scalar properties. Package references support a Version attribute or nested Version element. Name uses AssemblyName when authored and otherwise uses the project filename. IsExecutable recognizes Exe and WinExe; IsTestProject recognizes the corresponding MSBuild property or a Microsoft.NET.Test.Sdk package reference. Project-reference paths are resolved relative to the declaring project and then normalized relative to the directory.

Malformed project XML currently terminates inspection.

Node Projects

Inputs: recursive package.json.

NodeProjects[]:
Path
Name
Version
Private
PackageManager
Scripts[]
Dependencies[]
DevDependencies[]

Only property names are retained for scripts and dependencies. Lists are sorted ordinally. Malformed JSON currently terminates inspection.

README

Inputs: root README with no extension or .md, .markdown, or .txt, matched without regard to case.

Readmes[]:
Path
Title
Headings[]:
Level
Text
CodeLanguages[]

Markdown headings inside fenced code are ignored. Fence languages are recorded in declaration order. For text READMEs, the first non-empty line is the title.

PowerShell

Inputs: recursive .ps1, .psm1, and .psd1 under scripts only.

PowerShellFiles[]:
Path
Type
IsCommandCandidate
SuggestedCommandName
Parameters[]:
Name
Type
Mandatory
Functions[]
Classes[]
ParseErrors[]

Only .ps1 files are direct command candidates. This inspection data is also used by initial specification inference.

GitHub Actions

Inputs: root .github/workflows/*.yml and *.yaml.

Supported subset:

  • top-level workflow name;
  • inline on: [push, pull_request];
  • mapping keys immediately beneath on; and
  • job IDs immediately beneath jobs.
GitHubActions[]:
Path
Name
Triggers[]
Jobs[]

The parser is line-oriented and does not evaluate reusable workflows, expressions, anchors, or complete YAML semantics.

NUKE

Inputs:

  • .nuke directory;
  • .nuke/build.schema.json;
  • .nuke/parameters.json;
  • .NET projects referencing Nuke.Common; and
  • recursive build.ps1.
Nuke:
IsConfigured
SchemaPath
ParameterNames[]
ConfiguredParameterNames[]
Parameters[]:
Name
Type
Description
Enum[]
ItemType
ItemEnum[]
Default
Targets[]
ProjectPaths[]
BuildScripts[]

When build.schema.json exists, ParameterNames and Parameters describe its resolved allOf properties, including local #/definitions/... references. Executable targets come from the ExecutableTarget definition. parameters.json is treated as configured values: metadata properties beginning with $, including $schema, are excluded from ConfiguredParameterNames. When no build schema exists, those configured names remain the backward-compatible ParameterNames fallback.

This parser resolves only local definition references and does not evaluate external JSON Schema references or arbitrary composition keywords. Malformed NUKE JSON currently terminates inspection.

Configuration Schemas

Inputs: recursive *.schema.json and JSON documents containing $schema.

ConfigurationSchemas[]:
Path
Schema
Id
Title
Type
Required[]
Properties[]

Malformed files explicitly named *.schema.json terminate inspection because their names declare them authoritative. Other malformed JSON files are skipped. Only top-level schema identity, type, required names, and property names are retained.

OpenAPI

Inputs: recursive JSON or YAML files whose names begin with openapi or swagger, without regard to case.

OpenApiDocuments[]:
Path
SpecificationVersion
Title
ApiVersion
Paths[]

JSON documents read openapi or swagger, info.title, info.version, and top-level path names.

The YAML subset reads scalar openapi or swagger, info.title, info.version, and direct keys under paths. It does not implement full YAML semantics.

Malformed OpenAPI JSON currently terminates inspection.

Diagnostics

Each plugin execution record contains:

Stage
ExecutionOrder
Plugin
Path
StartedAt
Duration
Succeeded
Error

Use the concise view in CI logs and -Detailed during troubleshooting.

Issues

Plugin execution diagnostics describe whether a plugin ran; issues describe problems with the source data a plugin read. Get-PSModuleInspection returns them separately as Issues, without changing the shape of Data or PluginExecutions. Each issue contains:

Severity
Code
Inspector
Path
Message
ExceptionType
Details

Severity is Warning or Error. Code is a stable, machine-readable identifier; messages may improve without changing what a code means. Issues are ordered by inspector execution order, then repository-relative path, then code.

Get-PSModuleDiagnostic keeps its current default output. Pass -IncludeIssues to also emit issue records, typed SubZeroDev.PSGenerator.InspectionIssueDiagnostic, after every plugin-execution record in the same stream. The two record types share no position guarantee relative to one another beyond that ordering, so distinguish them by type rather than by index.

An authoritative input that fails inspection still throws. A caller that only wants the message keeps working unchanged; a caller that wants the structured detail behind the failure reads it from the caught exception:

try {
Get-PSModuleInspection -Specification ./PSModule/PSModule.psd1
}
catch {
$issues = $_.Exception.Data['PSModule.InspectionIssues']
}

Issues is never populated on that exception directly, because Get-PSModuleInspection never returns a result for a failed inspection; reading $_.Exception.Data['PSModule.InspectionIssues'] is the documented way to reach the same typed records Issues would have held on success, including every issue recorded before the fatal one.