From 3d2caceb7f7e36832f743bc5330d1002add0932a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 17:44:23 +0200 Subject: [PATCH] Reconcile PR 61 standards deltas onto main docs structure --- src/docs/Modules/Module-Types.md | 47 +++++-------- src/docs/Modules/Repository-Defaults.md | 34 ++++----- src/docs/Modules/Standards.md | 93 ++++++++++++++++++------- 3 files changed, 103 insertions(+), 71 deletions(-) diff --git a/src/docs/Modules/Module-Types.md b/src/docs/Modules/Module-Types.md index be97843..3466465 100644 --- a/src/docs/Modules/Module-Types.md +++ b/src/docs/Modules/Module-Types.md @@ -1,7 +1,7 @@ # Module types Most PSModule modules fall into one of a few archetypes. The general rules in -[PowerShell module standard](Standards.md) and [PowerShell Standards](../PowerShell/Standard/index.md) always apply; this +[PowerShell module standard](Standards.md) and the [PowerShell style guide](../Style-Guides/PowerShell.md) always apply; this page adds the conventions that are specific to a module's type so that modules of the same kind feel the same to use. @@ -32,40 +32,28 @@ the HTTP method or the endpoint path. Map REST methods to verbs: | `DELETE` | `Remove-` | `Remove-GitHubRepository` | | Non-CRUD action | Approved verb for the intent | `Invoke-`, `Start-`, `Stop-`, `Enable-`, ... | -Prefix the noun with the service's term of art (`GitHubRepository`, not `Repository`). +Prefix the noun with the service's term of art (`GitHubRepository`, not `Repository`). See the +[PowerShell style guide](../Style-Guides/PowerShell.md) for naming guidance. -### Transport abstraction +### Transport stays private -Lower-level helpers own the concrete `Invoke-RestMethod` / GraphQL / HTTP calls. How you expose -or hide this abstraction is a design choice: - -- **Private transport** (common): Keep REST, GraphQL, and HTTP helpers private. Public functions - accept resolved inputs and typed objects. This follows the Dependency Inversion rule from - [Standards](Standards.md#solid-applied) applied to the network boundary. -- **Public transport**: Expose REST or GraphQL functions publicly for power users or module - composition. -- **Public Context**: Expose the `Context` module as public so users can configure and manage - module state, secrets, and settings directly. - -Choose the strategy that best serves your module's audience. +Public functions accept resolved inputs and typed objects; private helpers own the concrete +`Invoke-RestMethod` / GraphQL / HTTP calls. This is the Dependency Inversion rule from +[Standards](Standards.md#solid-applied) applied to the network boundary. ### Use Context for user and module settings Integration modules persist state with the [`Context`](https://github.com/PSModule/Context) module -rather than inventing bespoke storage. Context provides on-disk storage for user data and secrets, -organized by context and environment. Two kinds of state are both standard: +rather than inventing bespoke storage. Two kinds of state are both standard: -- **User settings and secrets**: accounts, tokens, sessions, and per-user configuration. Store these +- **User settings and secrets** — accounts, tokens, sessions, and per-user configuration. Store these in a per-user context. `Context` encrypts secrets at rest (via `Sodium`), so a user can resume work without reconfiguring or logging in again when the service supports session refresh. -- **Module settings**: module-wide defaults, endpoints, and feature flags that are not tied to a +- **Module settings** — module-wide defaults, endpoints, and feature flags that are not tied to a single user. Store these in a module-scoped context. -Your module must expose functions and object types so users can target specific contexts and -environments. Users need to be able to read from, write to, and manage contexts programmatically, -selecting which environment or context their functions operate against. Persisting both through -`Context` gives every integration module the same, discoverable settings model and keeps secrets -out of source, logs, and plain files. +Persisting both through `Context` gives every integration module the same, discoverable settings +model, and keeps secrets out of source, logs, and plain files. ## Data modules @@ -80,14 +68,14 @@ format-specific representation into an object; `ConvertTo-` renders an o format. Converting through the object as a common pivot means any format interoperates with any other, instead of writing a direct converter for every pair. -Always ship both directions so data can round-trip between the format and the object model. +Always ship **both** directions so data can round-trip between the format and the object model. ### Verb vocabulary | Verb pattern | Purpose | | ------------ | ------- | | `ConvertFrom-` | Format-specific text/representation → `[PSCustomObject]` / `[hashtable]` | -| `ConvertTo-` | `[PSCustomObject]` / `[hashtable]` → format-specific text/representation | +| `ConvertTo-` | Object → format-specific text/representation | | `Import-` | Read from a file or store into objects | | `Export-` | Write objects to a file or store | | `Format-` | Produce a normalized or pretty rendering | @@ -98,9 +86,10 @@ Always ship both directions so data can round-trip between the format and the ob The `Hashtable` module demonstrates the full set: `ConvertFrom-Hashtable`, `ConvertTo-Hashtable`, `Import-Hashtable`, `Export-Hashtable`, `Format-Hashtable`, `Merge-Hashtable`, and -`Remove-HashtableEntry`. +`Remove-HashtableEntry`. See the [PowerShell style guide](../Style-Guides/PowerShell.md) for naming guidance. ## Where this connects -- [PowerShell module standard](Standards.md): layout, private functions, and the mandatory context parameter. -- [Repository Defaults](Repository-Defaults.md): repository files, README shape, and agent onboarding. +- [PowerShell style guide](../Style-Guides/PowerShell.md) — the concrete verb rules for both types. +- [PowerShell module standard](Standards.md) — layout, private functions, and the mandatory context parameter. +- [Repository Defaults](Repository-Defaults.md) — repository files, README shape, and agent onboarding. diff --git a/src/docs/Modules/Repository-Defaults.md b/src/docs/Modules/Repository-Defaults.md index f26135e..215bdd6 100644 --- a/src/docs/Modules/Repository-Defaults.md +++ b/src/docs/Modules/Repository-Defaults.md @@ -68,7 +68,7 @@ Module repositories use the PSModule framework layout: | `SECURITY.md` | Security support policy and private vulnerability reporting instructions. | | `SUPPORT.md` | Support expectations and where users ask for help. | | `CODE_OF_CONDUCT.md` | Community conduct expectations. | -| `AGENTS.md` | Agent onboarding entry point. Points agents to the canonical guidance in `PSModule/docs`. | +| `AGENTS.md` | Agent onboarding entry point. Points agents to the PSModule and MSX documentation for the why, how, and what. | | `CLAUDE.md` | Claude Code entry point. Imports `AGENTS.md` so Claude reads the same instructions. | | `.github/copilot-instructions.md` | VS Code and GitHub Copilot repository instructions. Points to the same documentation. | | `.github/PSModule.yml` | Module workflow configuration overrides. | @@ -111,7 +111,7 @@ Required baseline files for module repositories: | `SECURITY.md` | Private vulnerability reporting and latest-version support policy. | | `SUPPORT.md` | Support channel and issue-routing expectations. | | `CODE_OF_CONDUCT.md` | Community participation rules. | -| `AGENTS.md` | Cross-tool agent instructions pointing to the canonical guidance in `PSModule/docs`. | +| `AGENTS.md` | Cross-tool agent instructions pointing to the PSModule and MSX documentation. | | `CLAUDE.md` | Claude Code entry point that imports `AGENTS.md`. | | `.github/copilot-instructions.md` | VS Code and GitHub Copilot repository instructions pointing to the documentation. | | `.github/dependabot.yml` | Supply-chain maintenance for GitHub Actions and PowerShell dependencies. | @@ -130,11 +130,11 @@ Each repository must stand on its own. It carries its own copy of every file abo ## Agent onboarding files -Every repository must be usable by an agent that has never seen it before, without special configuration. Each repository carries its own agent entry points that point to the authoritative documentation instead of restating it: +Every repository must be usable by an agent that has never seen it before, without special configuration. Each repository carries its own agent entry points that *point to* the authoritative documentation instead of restating it: -- `AGENTS.md`: the cross-tool entry point, read by the GitHub Copilot coding agent, VS Code, and other AGENTS.md-aware tools. It names what the repository is in a line or two and points to the canonical agent guidance in [`PSModule/docs`](https://github.com/PSModule/docs). -- `CLAUDE.md`: a thin file that imports `AGENTS.md` with `@AGENTS.md` so Claude Code reads the same instructions. Claude-specific notes, if any, go below the import. -- `.github/copilot-instructions.md`: repository instructions for VS Code and GitHub Copilot that point to the same documentation. +- `AGENTS.md` — the cross-tool entry point, read by the GitHub Copilot coding agent, VS Code, and other AGENTS.md-aware tools. It names what the repository is in a line or two and points to the PSModule documentation (`https://psmodule.io`, source in [`PSModule/docs`](https://github.com/PSModule/docs)) for the module's why/how/what, and to the MSX documentation (`https://msxorg.github.io/docs`, source in [`MSXOrg/docs`](https://github.com/MSXOrg/docs)) for organization-level principles and ways of working. +- `CLAUDE.md` — a thin file that imports `AGENTS.md` with `@AGENTS.md` so Claude Code reads the same instructions. Claude-specific notes, if any, go below the import. +- `.github/copilot-instructions.md` — repository instructions for VS Code and GitHub Copilot that point to the same documentation. These files are the agent equivalent of the README: pointers, not copies. Keep them short so the linked documentation stays the single source of truth. Like the other governance files, they live in the repository itself so it can stand on its own. @@ -199,7 +199,7 @@ Dependabot PRs still go through normal review. Automated dependency updates are A module README is a start page, not the command reference or full manual. It brings a reader in, answers the first questions, and sends them to the right documentation surface. -Making the README shorter must not delete unique information. The README is published as the module's landing page on the documentation site (for example `psmodule.io/`); the per-command reference is generated separately from comment-based help. So the README is often the only published home for prerequisites, platform and dependency notes, authentication and setup guidance, operational behavior such as caching, state, or update and versioning semantics, and upstream attribution. Trimming the README must preserve that content: keep it on the landing page, or move it only to another surface that also publishes (a command group's overview page under `src/functions/public//.md`, comment-based help, or published documentation in `docs/`). Only remove content that is genuinely duplicated by the generated command reference. +Making the README shorter must not delete unique information. The README is published as the module's landing page on the documentation site (for example `psmodule.io/`); the per-command reference is generated separately from comment-based help. So the README is often the only published home for prerequisites, platform and dependency notes, authentication and setup guidance, operational behavior such as caching, state, or update and versioning semantics, and upstream attribution. Trimming the README must preserve that content: keep it on the landing page, or move it only to another surface that also publishes (a command group's overview page under `src/functions/public//.md`, or comment-based help). Only remove content that is genuinely duplicated by the generated command reference. The README answers these questions, in this order: @@ -208,7 +208,7 @@ The README answers these questions, in this order: | What is it? | Name the module and define its scope in one short paragraph. | | Why should I care? | State the value or kind of task the module makes easier. | | How do I get it? | Show the PowerShell Gallery install and import commands. | -| How does it work? | Show one to three representative capabilities or usage examples. | +| How does it work? | Show one to three representative usage examples. | | How do I get more info? | Link to generated module documentation and PowerShell help. | Module installation examples must use PSResourceGet: @@ -235,11 +235,11 @@ Install-PSResource -Name Import-Module -Name ``` -## Capabilities +## Usage -Use this section as a short showcase and introduction to how the module works. Show the most important things the module makes possible with one to three realistic examples. +Use this section as a short showcase and introduction to how the module works. Show the most important things the module makes possible with one to three realistic examples; `### Example: ` subsections are fine when you have more than one. -The goal is discovery and marketing, not exhaustive command documentation. A reader should understand why the module exists and what kind of tasks it helps with. +The goal is discovery, not exhaustive command documentation. A reader should understand why the module exists and what kind of tasks it helps with. ```powershell # Replace this with a real example that demonstrates the module's value. @@ -260,19 +260,19 @@ Get-Help -Name -Examples In the documentation examples, replace `` with a real command exported by the module, for example `Get-Help -Name Get-GitHubRepository -Examples`, so the snippet runs as written. Do not ship placeholder tokens such as `'CommandName'` or `` as if they were runnable commands. -Implemented modules must include the capabilities or usage showcase before the documentation link. Keep it focused on discovery: show one to three representative outcomes, not every command, parameter, or edge case. A landing page with only an installation snippet and a documentation link is not enough for a module that has working commands. +Implemented modules must include the `## Usage` showcase before the documentation link. Keep it focused on discovery: show one to three representative outcomes, not every command, parameter, or edge case. A landing page with only an installation snippet and a documentation link is not enough for a module that has working commands. Do not title this section `## Capabilities`; use `## Usage` (or `## Examples`). Keep, trim, or relocate content — do not delete it: -- **Keep on the landing page:** the overview, prerequisites and requirements (PowerShell version, supported platforms, module or native dependencies), installation, the capabilities showcase, and the short operational notes a reader needs before first use. +- **Keep on the landing page:** the overview, prerequisites and requirements (PowerShell version, supported platforms, module or native dependencies), installation, the usage showcase, and the short operational notes a reader needs before first use. - **Trim:** exhaustive command inventories, parameter tables, and repetitive examples that differ only by a parameter. These come from comment-based help — point to `Get-Help` and the documentation site instead of restating them. -- **Relocate only to a published home — never drop:** long-form guides and unique conceptual content (authentication and setup walkthroughs, deep operational detail, end-to-end scenarios) may move out of the README only into a surface that is actually published: a command group's overview page under `src/functions/public//.md`, comment-based help, or published documentation in `docs/` or `examples/`. Only relocate to unpublished areas if there is no published home for it yet; keep the full content in the README to ensure it reaches users. A longer landing page is acceptable and expected for feature-rich modules; do not shorten by deleting. +- **Relocate only to a published home — never drop:** long-form guides and unique conceptual content (authentication and setup walkthroughs, deep operational detail, end-to-end scenarios) may move out of the README only into a surface that is actually published: a command group's overview page under `src/functions/public//.md`, or comment-based help. A bare top-level `docs/` folder is not published by the current docs build, so moving content there drops it from the site. When there is no published home for it yet, keep the full content in the README. A longer landing page is acceptable and expected for feature-rich modules; do not shorten by deleting. Retain upstream attribution and licensing context. Credit, acknowledgements, donation notes, and third-party license notices for wrapped or bundled work must stay in the README, or move to a clearly linked place. The rule below about community and policy sections does not apply to attribution the project is expected to carry. README pages should not duplicate generated command documentation. Do not add full command inventories, parameter tables, or long reference sections when those details are already produced from comment-based help. -Do not add a community-file or policy link section by default. Readers can find standard repository files such as `LICENSE`, `CONTRIBUTING.md`, `SECURITY.md`, and `CODE_OF_CONDUCT.md` through GitHub conventions and the repository file tree. Link them only when the module has an unusual rule the user must know before using it, or when it carries required upstream attribution. +Do not add a community-file, policy, or Contributing link section to the README by default, and do not add a `## Contributing` section. Each repository carries its own `CONTRIBUTING.md`, `SECURITY.md`, `SUPPORT.md`, and `CODE_OF_CONDUCT.md`; readers and tools find them through the repository file tree and GitHub renders them in its UI. The README links or restates them only when the module has an unusual rule the user must know before using it, or when it carries required upstream attribution. ## Placeholder and in-progress repositories @@ -307,7 +307,7 @@ Before opening a README-only PR, check that the README follows the default and d ```powershell Select-String -Path README.md -SimpleMatch -Pattern 'Greet-Entity', 'PSModuleTemplate', 'YourModuleName' Select-String -Path README.md -SimpleMatch -Pattern '{{ NAME }}', '{{ DESCRIPTION }}' -Select-String -Path README.md -SimpleMatch -Pattern '', '', "-Name 'CommandName'" +Select-String -Path README.md -SimpleMatch -Pattern "-Name 'CommandName'", '' Select-String -Path README.md -Pattern '^## (Commands|Capabilities)$' Select-String -Path README.md -Pattern '^Install-Module\b' git diff --check -- README.md @@ -315,7 +315,7 @@ git diff --check -- README.md `Template-PSModule` is the exception: it intentionally keeps `{{ NAME }}` and `{{ DESCRIPTION }}` tokens because those are template inputs. -For an implemented module, also confirm the README keeps a capabilities or usage showcase and that any unique content removed from the previous version — prerequisites, setup or authentication guidance, operational notes, or upstream attribution — was relocated to `docs/`, `examples/`, or comment-based help rather than deleted. +For an implemented module, also confirm the README keeps a `## Usage` showcase and that any unique content removed from the previous version — prerequisites, setup or authentication guidance, operational notes, or upstream attribution — was kept on the landing page or relocated to a published home (`src/functions/public//.md` or comment-based help) rather than deleted. Repository-only locations such as `examples/` are not published on their own, so content moved there must still be linked from the README. ## Documentation ownership diff --git a/src/docs/Modules/Standards.md b/src/docs/Modules/Standards.md index 8b72597..ce86224 100644 --- a/src/docs/Modules/Standards.md +++ b/src/docs/Modules/Standards.md @@ -114,32 +114,77 @@ For large work, open a release branch and target it from feature branches. Apply ## CI/CD pipeline -The [Process-PSModule](https://github.com/PSModule/Process-PSModule) workflow orchestrates the full lifecycle. Every PR triggers a **Plan** job that resolves configuration and version, then conditionally runs build, test, lint, and publish stages. - -### Pipeline stages +The [Process-PSModule](https://github.com/PSModule/Process-PSModule) workflow orchestrates the full lifecycle. The repository entry workflow starts the **Plan** job, `Plan` loads `.github/PSModule.yml`, and `Plan` then conditionally starts the build, test, lint, docs, and publish sub-jobs. ```mermaid graph LR - Plan --> Lint-Repository - Plan --> Build-Module - Plan --> Test-SourceCode - Plan --> Lint-SourceCode - Build-Module --> Test-Module - Build-Module --> BeforeAll-ModuleLocal - BeforeAll-ModuleLocal --> Test-ModuleLocal - Test-ModuleLocal --> AfterAll-ModuleLocal - Test-SourceCode --> Get-TestResults - Test-Module --> Get-TestResults - Test-ModuleLocal --> Get-TestResults - Test-Module --> Get-CodeCoverage - Test-ModuleLocal --> Get-CodeCoverage - Get-TestResults --> Publish-Module - Get-CodeCoverage --> Publish-Module - Build-Module --> Build-Docs - Build-Docs --> Build-Site - Build-Site --> Publish-Site + subgraph Inputs + Workflow[workflow.yml] + PSModule[.github/PSModule.yml] + end + + subgraph Planning + Plan + end + + subgraph Validation + Lint-Repository + Build-Module + Test-SourceCode + Lint-SourceCode + Test-Module + BeforeAll-ModuleLocal + Test-ModuleLocal + AfterAll-ModuleLocal + Get-TestResults + Get-CodeCoverage + end + + subgraph Documentation + Build-Docs + Build-Site + Publish-Site + end + + subgraph Release + Publish-Module + end + + Workflow --> Plan + PSModule --> Plan + Plan --> Lint-Repository + Plan --> Build-Module + Plan --> Test-SourceCode + Plan --> Lint-SourceCode + Build-Module --> Test-Module + Build-Module --> BeforeAll-ModuleLocal + BeforeAll-ModuleLocal --> Test-ModuleLocal + Test-ModuleLocal --> AfterAll-ModuleLocal + Test-SourceCode --> Get-TestResults + Test-Module --> Get-TestResults + Test-ModuleLocal --> Get-TestResults + Test-Module --> Get-CodeCoverage + Test-ModuleLocal --> Get-CodeCoverage + Get-TestResults --> Publish-Module + Get-CodeCoverage --> Publish-Module + Build-Module --> Build-Docs + Build-Docs --> Build-Site + Build-Site --> Publish-Site ``` +Read the workflow as one flow from left to right: + +1. **The entry workflow and module settings feed Plan first.** `workflow.yml` invokes the Process-PSModule workflow, `Plan` loads `.github/PSModule.yml`, evaluates changed files against `ImportantFilePatterns`, determines `ReleaseType` from PR labels, and resolves the next semantic version before any child job starts. +2. **Non-impacting changes stop here.** If no changed file matches the important patterns, the workflow resolves `ReleaseType: None` and skips build, test, and publish work. +3. **Repository lint runs for PR hygiene.** `Lint-Repository` checks the repo-level files such as Markdown, YAML, and other non-module assets. +4. **Module build creates the release candidate artifact.** `Build-Module` compiles the module and stamps the resolved version into the manifest so the artifact under test is the same version that would later be published. +5. **Source and module tests fan out from the build plan.** `Test-SourceCode` validates raw source files, `Test-Module` validates the built artifact, and the local test path runs `BeforeAll-ModuleLocal`, `Test-ModuleLocal`, and `AfterAll-ModuleLocal` across the OS matrix. +6. **Lint and reporting run alongside tests.** `Lint-SourceCode` analyzes `src/`, `Get-TestResults` aggregates all test output, and `Get-CodeCoverage` calculates coverage from the module test stages. +7. **Docs build from the same change set.** `Build-Docs` generates command and doc content, `Build-Site` prepares the static site, and `Publish-Site` deploys it for merged PRs. +8. **Publish only happens after a releasable merge.** `Publish-Module` runs for merged PRs, or for preview builds when the PR carries `Prerelease`, and reads the already-stamped manifest version rather than recalculating it. + +Stage reference: + | Stage | Runs on | Purpose | | ----- | ------- | ------- | | **Plan** | All events | Loads `.github/PSModule.yml`, resolves version from PR labels, produces the Settings JSON | @@ -157,16 +202,14 @@ graph LR | **Build-Docs / Build-Site** | Open/Updated PR, Merged PR, Manual | Generates documentation site from source | | **Publish-Site** | Merged PR | Deploys documentation site to GitHub Pages | -### Important file patterns - -The workflow only triggers build, test, and publish stages when changed files match the `ImportantFilePatterns` setting. The default patterns are: +Default important file patterns: ```text ^src/ ^README\.md$ ``` -Changes that do not match any pattern result in `ReleaseType: None` — the pipeline skips build, test, and publish entirely. Override in `.github/PSModule.yml`: +Override them in `.github/PSModule.yml` when other files should trigger the full module lifecycle: ```yaml ImportantFilePatterns: