From 517b20b6d4e25037ff9da39e820cc3cf59bb5a92 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 13:28:17 +0200 Subject: [PATCH 01/10] Add repository agent onboarding defaults --- .github/copilot-instructions.md | 1 + AGENTS.md | 19 +++++++++++++++++++ CLAUDE.md | 1 + src/docs/Modules/Repository-Defaults.md | 24 ++++++++++++++++++++++-- 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..3884664 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1 @@ +Follow the instructions in [AGENTS.md](../AGENTS.md). diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8402301 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +# Agents + +This repository holds the source for the [PSModule](https://psmodule.io) documentation, published at [psmodule.io/docs](https://psmodule.io/docs). Everything an agent needs to work here is documentation — read it the same way a new contributor would. + +## Start here + +1. Read this file, then the [README](README.md) for what this repository is and how it builds. +2. Read the [PSModule documentation](https://psmodule.io/docs) for the framework's why, how, and what — its standards, conventions, and style guides. The source for those pages lives under `src/docs/` in this repository. +3. Read the [MSX documentation](https://msxorg.github.io/docs) for the organization-level principles and ways of working that sit above any single repository. + +## Working in this repository + +- Documentation pages live under `src/docs/`; the published site navigation is defined in `src/zensical.toml`. Add a new page to both. +- The PowerShell standards and style guides under `src/docs/` are the source of truth for content changes — follow the page you are changing. +- Keep each page the single source of truth: link to the canonical page instead of restating its content elsewhere. + +## The rule + +This file points; it never defines. Standards and process live in the documentation and are referenced by their canonical location — never copied here. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/src/docs/Modules/Repository-Defaults.md b/src/docs/Modules/Repository-Defaults.md index 7ce6b66..62f4165 100644 --- a/src/docs/Modules/Repository-Defaults.md +++ b/src/docs/Modules/Repository-Defaults.md @@ -15,6 +15,8 @@ They do not apply directly to: - Template repositories other than `Template-PSModule`. - Test, archive, service, or infrastructure repositories that are not published as module artifacts. +Two baseline expectations still apply to every PSModule repository, including the types listed above. Each repository stands on its own: it carries its own governance and community files instead of relying on the organization `.github` fallback, and each repository ships the [agent onboarding files](#agent-onboarding-files) so an agent can work in it without prior context. What differs by type is the concrete file set and layout: the required files, README shape, and framework wiring on the rest of this page are module defaults, and non-module repositories keep only the equivalent baseline appropriate to their own type. This repository, `PSModule/docs`, follows those two baseline expectations itself. + Each initiative should keep its own repository standards in its central documentation repository. For the PSModule organization, this repository is the source of truth. ## Repository creation @@ -62,10 +64,13 @@ Module repositories use the PSModule framework layout: | ---- | --------------- | | `README.md` | Concise start page for the module. | | `LICENSE` | Repository license. PSModule module repositories default to MIT unless a different license is explicitly decided. | -| `CONTRIBUTING.md` | Contribution workflow or a repository-level pointer to the organization contribution guide. | +| `CONTRIBUTING.md` | Self-contained contribution workflow for this repository. Does not rely on an organization-level fallback. | | `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 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. | | `.github/workflows/workflow.yml` | Reusable Process-PSModule workflow entry point. | | `.github/dependabot.yml` | Dependency and supply-chain update configuration. | @@ -102,10 +107,13 @@ Required baseline files for module repositories: | ---- | ------------------ | | `README.md` | Repository landing page and evergreen context for humans and agents. | | `LICENSE` | Clear legal terms for reuse, packaging, and redistribution. | -| `CONTRIBUTING.md` | Shared contribution workflow and expectations. | +| `CONTRIBUTING.md` | Self-contained contribution workflow and expectations for this repository. | | `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 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. | | `.github/CODEOWNERS` | Review routing for source, docs, and GitHub workflow files. | | `.github/pull_request_template.md` | Consistent PR Manager-style PR descriptions and change classification. | @@ -118,6 +126,18 @@ Required baseline files for module repositories: Repositories can add local files, but they should not remove these baseline files unless the repository is explicitly outside the module standard. +Each repository must stand on its own. It carries its own copy of every file above and does not depend on the organization `.github` fallback: that fallback is only surfaced in GitHub's web UI, and agents, linters, and local tooling do not read it. + +## 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: + +- `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. + ## Managed file distribution Shared files should be treated as managed files. The current distribution service is [`PSModule/Distributor`](https://github.com/PSModule/Distributor). It keeps source file sets under `Repos/{Type}/{Selection}/` and syncs those files into repositories through pull requests. From 6bb4a81dd23b2c1c1ad95485f273ff4b35a7204d Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 13:51:07 +0200 Subject: [PATCH 02/10] Handle missing docs paths in update-index action --- .github/actions/update-index/src/Helper.psm1 | 37 +++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 30ed03a..20d469a 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -92,22 +92,51 @@ function Update-MDSection { # The new content to insert between the section markers. [Parameter()] - [string] $Content + [string] $Content, + + # Skip update when the target file or section markers are missing. + [Parameter()] + [switch] $SkipIfMissing ) $startSegment = "" $endSegment = "" + + if (-not (Test-Path -Path $Path)) { + if ($SkipIfMissing) { + Write-Warning "[$Name] Skipping update because target file was not found: $Path" + return + } + + throw "[$Name] Target file was not found: $Path" + } + $currentContent = Get-Content -Path $Path $startIndex = $currentContent.IndexOf($startSegment) $endIndex = $currentContent.IndexOf($endSegment) if ($startIndex -lt 0) { + if ($SkipIfMissing) { + Write-Warning "[$Name] Skipping update because the start marker was not found in: $Path" + return + } + throw "[$Name] The start comment segment was not found in the file." } if ($endIndex -lt 0) { + if ($SkipIfMissing) { + Write-Warning "[$Name] Skipping update because the end marker was not found in: $Path" + return + } + throw "[$Name] The end comment segment was not found in the file." } if ($endIndex -lt $startIndex) { + if ($SkipIfMissing) { + Write-Warning "[$Name] Skipping update because marker order is invalid in: $Path" + return + } + throw "[$Name] The end comment segment was found before the start comment segment." } @@ -173,7 +202,7 @@ function Update-ActionList { $actionTableRows "@ - Update-MDSection -Path '.\src\docs\GitHub-Actions\index.md' -Name 'ACTION_LIST' -Content $actionTable + Update-MDSection -Path '.\src\docs\GitHub-Actions\index.md' -Name 'ACTION_LIST' -Content $actionTable -SkipIfMissing } function Update-ModuleList { @@ -229,7 +258,7 @@ $moduleTableRows "@ - Update-MDSection -Path '.\src\docs\PowerShell\Modules\index.md' -Name 'MODULE_LIST' -Content $moduleTable + Update-MDSection -Path '.\src\docs\PowerShell\Modules\index.md' -Name 'MODULE_LIST' -Content $moduleTable -SkipIfMissing } function Update-FunctionAppList { @@ -289,5 +318,5 @@ $functionAppTableRows "@ - Update-MDSection -Path '.\src\docs\PowerShell\FunctionApps\index.md' -Name 'FUNCTIONAPP_LIST' -Content $functionAppTable + Update-MDSection -Path '.\src\docs\PowerShell\FunctionApps\index.md' -Name 'FUNCTIONAPP_LIST' -Content $functionAppTable -SkipIfMissing } From 9b0984e117bdcbc4cd1fc0feb66f28d86512533e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 13:51:59 +0200 Subject: [PATCH 03/10] Align lint rules with docs headings and format JS override --- .github/linters/.markdown-lint.yml | 1 + src/docs/Style-Guides/index.md | 2 +- .../javascripts/abbreviation-preview.js | 156 +++++++++--------- 3 files changed, 82 insertions(+), 77 deletions(-) diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index 7d96392..b1b1250 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -13,6 +13,7 @@ MD007: indent: 2 # Unordered list indentation MD013: line_length: 3000 # Line length +MD025: false # Allow front-matter title + visible H1 on docs pages MD026: punctuation: ".,;:!。,;:" # List of not allowed MD029: false # Ordered list item prefix diff --git a/src/docs/Style-Guides/index.md b/src/docs/Style-Guides/index.md index c2d817d..b874da8 100644 --- a/src/docs/Style-Guides/index.md +++ b/src/docs/Style-Guides/index.md @@ -5,7 +5,7 @@ description: Coding style guidelines for PSModule repositories. # Style Guides (Moved) -Style-guide content is now canonical in MSXOrg/docs. +Style guide content is now canonical in MSXOrg/docs. Use: diff --git a/src/overrides/assets/javascripts/abbreviation-preview.js b/src/overrides/assets/javascripts/abbreviation-preview.js index e397ba0..1db79df 100644 --- a/src/overrides/assets/javascripts/abbreviation-preview.js +++ b/src/overrides/assets/javascripts/abbreviation-preview.js @@ -1,94 +1,98 @@ /* global document$ */ (function () { - "use strict"; + "use strict"; - // Map abbreviations to glossary pages. Add entries as glossary coverage expands. - var ABBR_TO_PAGE = { - API: "Dictionary/api/", - "CI/CD": "Dictionary/ci-cd/", - CI: "Dictionary/ci-cd/", - CD: "Dictionary/ci-cd/", - GH: "Dictionary/github/", - GitHub: "Dictionary/github/", - Git: "Dictionary/git/", - LTS: "Dictionary/lts/", - MkDocs: "Dictionary/mkdocs/", - REST: "Dictionary/rest-api/", - "REST API": "Dictionary/rest-api/", - YAML: "Dictionary/yaml/" - }; + // Map abbreviations to glossary pages. Add entries as glossary coverage expands. + var ABBR_TO_PAGE = { + API: "Dictionary/api/", + "CI/CD": "Dictionary/ci-cd/", + CI: "Dictionary/ci-cd/", + CD: "Dictionary/ci-cd/", + GH: "Dictionary/github/", + GitHub: "Dictionary/github/", + Git: "Dictionary/git/", + LTS: "Dictionary/lts/", + MkDocs: "Dictionary/mkdocs/", + REST: "Dictionary/rest-api/", + "REST API": "Dictionary/rest-api/", + YAML: "Dictionary/yaml/", + }; - function titleCase(value) { - return value - .toLowerCase() - .split(/\s+/) - .filter(Boolean) - .map(function (part) { - return part.charAt(0).toUpperCase() + part.slice(1); - }) - .join(" "); - } - - function getAbbreviationText(node) { - return (node.textContent || "").trim(); - } + function titleCase(value) { + return value + .toLowerCase() + .split(/\s+/) + .filter(Boolean) + .map(function (part) { + return part.charAt(0).toUpperCase() + part.slice(1); + }) + .join(" "); + } - function toAbsoluteHref(path) { - var scopeBase = "/"; - if (typeof window !== "undefined" && window.__md_scope && window.__md_scope.base) { - scopeBase = window.__md_scope.base; - } + function getAbbreviationText(node) { + return (node.textContent || "").trim(); + } - if (!scopeBase.endsWith("/")) { - scopeBase += "/"; - } - - return scopeBase + path; + function toAbsoluteHref(path) { + var scopeBase = "/"; + if ( + typeof window !== "undefined" && + window.__md_scope && + window.__md_scope.base + ) { + scopeBase = window.__md_scope.base; } - function upgradeAbbreviation(node) { - if (!node || node.dataset.abbrLinked === "true") { - return; - } - - var key = getAbbreviationText(node); - var target = ABBR_TO_PAGE[key]; - if (!target) { - return; - } - - var link = document.createElement("a"); - link.href = toAbsoluteHref(target); - link.className = "abbr-preview-link"; - link.innerHTML = node.innerHTML; + if (!scopeBase.endsWith("/")) { + scopeBase += "/"; + } - // Keep native tooltip text as fallback while enabling preview-on-hover for links. - if (node.hasAttribute("title")) { - link.setAttribute("title", node.getAttribute("title")); - } else { - link.setAttribute("title", titleCase(key)); - } + return scopeBase + path; + } - // Mark transformed to avoid repeated wrapping on instant navigation reloads. - link.dataset.abbrLinked = "true"; - node.replaceWith(link); + function upgradeAbbreviation(node) { + if (!node || node.dataset.abbrLinked === "true") { + return; } - function enhanceAbbreviations() { - var nodes = document.querySelectorAll("abbr"); - nodes.forEach(upgradeAbbreviation); + var key = getAbbreviationText(node); + var target = ABBR_TO_PAGE[key]; + if (!target) { + return; } - if (typeof document$ !== "undefined" && document$.subscribe) { - document$.subscribe(function () { - enhanceAbbreviations(); - }); - return; - } + var link = document.createElement("a"); + link.href = toAbsoluteHref(target); + link.className = "abbr-preview-link"; + link.innerHTML = node.innerHTML; - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", enhanceAbbreviations); + // Keep native tooltip text as fallback while enabling preview-on-hover for links. + if (node.hasAttribute("title")) { + link.setAttribute("title", node.getAttribute("title")); } else { - enhanceAbbreviations(); + link.setAttribute("title", titleCase(key)); } + + // Mark transformed to avoid repeated wrapping on instant navigation reloads. + link.dataset.abbrLinked = "true"; + node.replaceWith(link); + } + + function enhanceAbbreviations() { + var nodes = document.querySelectorAll("abbr"); + nodes.forEach(upgradeAbbreviation); + } + + if (typeof document$ !== "undefined" && document$.subscribe) { + document$.subscribe(function () { + enhanceAbbreviations(); + }); + return; + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", enhanceAbbreviations); + } else { + enhanceAbbreviations(); + } })(); From 80b2ab285b12bcee5a005dad3191a8f5c6a4893f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:17:01 +0200 Subject: [PATCH 04/10] Refactor agent onboarding documentation and clarify managed file distribution process --- AGENTS.md | 32 ++++++++++++++++--------- src/docs/Modules/Repository-Defaults.md | 30 ++++++++++++++--------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8402301..aca5719 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,19 +1,29 @@ # Agents -This repository holds the source for the [PSModule](https://psmodule.io) documentation, published at [psmodule.io/docs](https://psmodule.io/docs). Everything an agent needs to work here is documentation — read it the same way a new contributor would. +## Main directive -## Start here +Everything is a work in progress and can be updated and improved. +If you find a problem, fix it if it's small; otherwise, register it as an issue in the respective repo. -1. Read this file, then the [README](README.md) for what this repository is and how it builds. -2. Read the [PSModule documentation](https://psmodule.io/docs) for the framework's why, how, and what — its standards, conventions, and style guides. The source for those pages lives under `src/docs/` in this repository. -3. Read the [MSX documentation](https://msxorg.github.io/docs) for the organization-level principles and ways of working that sit above any single repository. +## Install the ecosystem -## Working in this repository +1. Create a folder in the home directory called `.msx/PSModule`: +2. Clone the ecosystem locally: + 1. — requires PRs to be updated. + - Clone as bare and use worktrees. + - Create a worktree for all branches - worktree = name of the branch. + 2. — work directly towards main. + - Simple clone, only main. -- Documentation pages live under `src/docs/`; the published site navigation is defined in `src/zensical.toml`. Add a new page to both. -- The PowerShell standards and style guides under `src/docs/` are the source of truth for content changes — follow the page you are changing. -- Keep each page the single source of truth: link to the canonical page instead of restating its content elsewhere. +To install: + Clone the repos in the users home folder under a sub-folder named `.msx/PSModule`. +- Set configs locally to each of these repos using the github username and email. -## The rule +## Working with the ecosystem -This file points; it never defines. Standards and process live in the documentation and are referenced by their canonical location — never copied here. +1. Get to know this repo first: + - [README](README.md) for what this repository is and how it builds. + - [CONTRIBUTING](CONTRIBUTING.md) for how to contribute and the review process. +2. Read the `.msx/PSModule/main/docs` - start with the index to get an overview of what is here. +3. Read the `.msx/PSModule/memory` - start with the index to get an overview of what is here. Use this while working - commit your memories here for work inside the PSModule organization. +4. While working with the code, do small micro commits and push on every commit. This will make it easier to review and merge your changes. diff --git a/src/docs/Modules/Repository-Defaults.md b/src/docs/Modules/Repository-Defaults.md index 62f4165..d8eb4a1 100644 --- a/src/docs/Modules/Repository-Defaults.md +++ b/src/docs/Modules/Repository-Defaults.md @@ -140,22 +140,30 @@ These files are the agent equivalent of the README: pointers, not copies. Keep t ## Managed file distribution -Shared files should be treated as managed files. The current distribution service is [`PSModule/Distributor`](https://github.com/PSModule/Distributor). It keeps source file sets under `Repos/{Type}/{Selection}/` and syncs those files into repositories through pull requests. +Shared repository files are managed through [`PSModule/Distributor`](https://github.com/PSModule/Distributor). Distributor is the source of truth for managed file content and file-set membership. -The current Distributor model is subscription-based: +Managed-file distribution follows this contract: -- `Type` is an organization repository custom property that maps a repository to a type folder such as `Module` or `Action`. -- `SubscribeTo` is an organization repository custom property that selects file sets such as `dependabot.yml`, `Linter Settings`, `PSModule Settings`, `CODEOWNERS`, `License`, `.gitattributes`, and `.gitignore`. -- Sync changes are delivered through a `managed-files/update` branch and a `⚙️ [Maintenance]: Sync managed files` pull request. -- Managed files are overwritten by the source file set. Local edits to managed files should be made in Distributor, not directly in the receiving repository. -- Removing a file from a Distributor file set does not delete the previously distributed file from target repositories; cleanup is explicit. +- `Type` maps a repository to its file-set root (for example `Module` or `Action`). +- `SubscribeTo` declares which optional managed file sets the repository receives. +- Organization-wide mandatory file sets define non-optional governance and supply-chain files for each applicable repository type. +- Distributor delivers changes through a `managed-files/update` branch and a `⚙️ [Maintenance]: Sync managed files` pull request. +- Receiving repositories treat managed files as generated artifacts from Distributor. Local edits in the receiving repository are replaced on the next sync and must be made in Distributor instead. +- Removing a file from a file set does not implicitly delete previously synced copies; deletion is an explicit managed change. -Two follow-up Distributor capabilities define the desired direction: +This page defines what files must exist in repositories. Distributor defines how those files are distributed and kept aligned. -- **Global file sets** should allow common file sets such as `.gitattributes`, `.gitignore`, and `License` to be defined once and made available to all repository types while still requiring subscription. -- **Mandatory file sets** should allow organization-critical files such as `SECURITY.md`, `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md`, and supply-chain configuration to be pushed to applicable repositories without each repository having to subscribe manually. +### Migration for existing repositories -Until mandatory file sets exist, repository owners are still responsible for ensuring the required common files exist. Distributor is the preferred implementation mechanism; this document is the standard that says what must exist and why. +Repositories that still reflect older distribution behavior should be aligned to this contract: + +1. Set or correct repository `Type` and `SubscribeTo` properties. +2. Ensure mandatory governance and supply-chain files from this standard exist in the repository. +3. Move any intended local edits in managed files into Distributor source file sets. +4. Sync from Distributor and merge the `managed-files/update` pull request. +5. Remove unmanaged duplicates or stale files explicitly when they are no longer part of an active file set. + +After migration, the repository keeps the required files from this standard, and managed-file content changes are made through Distributor-first updates. ## Supply-chain defaults From d6cda493ec49c0f296eafe41d452e9d6ef0814ef Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:22:13 +0200 Subject: [PATCH 05/10] Refactor Update-MDSection to simplify warning handling and remove SkipIfMissing parameter; update markdown lint rules for clarity; delete unused abbreviation-preview.js script --- .github/actions/update-index/src/Helper.psm1 | 51 ++++------ .github/linters/.markdown-lint.yml | 20 ++-- .../javascripts/abbreviation-preview.js | 98 ------------------- 3 files changed, 30 insertions(+), 139 deletions(-) delete mode 100644 src/overrides/assets/javascripts/abbreviation-preview.js diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 20d469a..ff76cdd 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -92,23 +92,24 @@ function Update-MDSection { # The new content to insert between the section markers. [Parameter()] - [string] $Content, - - # Skip update when the target file or section markers are missing. - [Parameter()] - [switch] $SkipIfMissing + [string] $Content ) $startSegment = "" $endSegment = "" - if (-not (Test-Path -Path $Path)) { - if ($SkipIfMissing) { - Write-Warning "[$Name] Skipping update because target file was not found: $Path" - return + function Write-UpdateWarning { + param([string] $Message) + + Write-Warning $Message + if ($env:GITHUB_ACTIONS -eq 'true') { + Write-Output "::warning::$Message" } + } - throw "[$Name] Target file was not found: $Path" + if (-not (Test-Path -Path $Path)) { + Write-UpdateWarning "[$Name] Skipping update because target file was not found: $Path" + return } $currentContent = Get-Content -Path $Path @@ -116,28 +117,16 @@ function Update-MDSection { $endIndex = $currentContent.IndexOf($endSegment) if ($startIndex -lt 0) { - if ($SkipIfMissing) { - Write-Warning "[$Name] Skipping update because the start marker was not found in: $Path" - return - } - - throw "[$Name] The start comment segment was not found in the file." + Write-UpdateWarning "[$Name] Skipping update because the start marker was not found in: $Path" + return } if ($endIndex -lt 0) { - if ($SkipIfMissing) { - Write-Warning "[$Name] Skipping update because the end marker was not found in: $Path" - return - } - - throw "[$Name] The end comment segment was not found in the file." + Write-UpdateWarning "[$Name] Skipping update because the end marker was not found in: $Path" + return } if ($endIndex -lt $startIndex) { - if ($SkipIfMissing) { - Write-Warning "[$Name] Skipping update because marker order is invalid in: $Path" - return - } - - throw "[$Name] The end comment segment was found before the start comment segment." + Write-UpdateWarning "[$Name] Skipping update because marker order is invalid in: $Path" + return } $updatedContent = $currentContent[0..$startIndex] + $Content + $currentContent[($endIndex)..($currentContent.Length - 1)] @@ -202,7 +191,7 @@ function Update-ActionList { $actionTableRows "@ - Update-MDSection -Path '.\src\docs\GitHub-Actions\index.md' -Name 'ACTION_LIST' -Content $actionTable -SkipIfMissing + Update-MDSection -Path '.\src\docs\GitHub-Actions\index.md' -Name 'ACTION_LIST' -Content $actionTable } function Update-ModuleList { @@ -258,7 +247,7 @@ $moduleTableRows "@ - Update-MDSection -Path '.\src\docs\PowerShell\Modules\index.md' -Name 'MODULE_LIST' -Content $moduleTable -SkipIfMissing + Update-MDSection -Path '.\src\docs\PowerShell\Modules\index.md' -Name 'MODULE_LIST' -Content $moduleTable } function Update-FunctionAppList { @@ -318,5 +307,5 @@ $functionAppTableRows "@ - Update-MDSection -Path '.\src\docs\PowerShell\FunctionApps\index.md' -Name 'FUNCTIONAPP_LIST' -Content $functionAppTable -SkipIfMissing + Update-MDSection -Path '.\src\docs\PowerShell\FunctionApps\index.md' -Name 'FUNCTIONAPP_LIST' -Content $functionAppTable } diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index b1b1250..db8977f 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -8,20 +8,20 @@ ############### # Rules by id # ############### -MD004: false # Unordered list style +MD004: false # Unordered list style MD007: - indent: 2 # Unordered list indentation + indent: 2 # Unordered list indentation MD013: - line_length: 3000 # Line length -MD025: false # Allow front-matter title + visible H1 on docs pages + line_length: 3000 # Line length +MD025: false # Allow front-matter title + visible H1 on docs pages MD026: - punctuation: ".,;:!。,;:" # List of not allowed -MD029: false # Ordered list item prefix -MD033: false # Allow inline HTML -MD036: false # Emphasis used instead of a heading -MD041: false # First line in file should be a top level heading, PULL_REQUEST_TEMPLATE.md is an exception + punctuation: '.,;:!。,;:' # List of not allowed +MD029: false # Ordered list item prefix +MD033: false # Allow inline HTML +MD036: false # Emphasis used instead of a heading +MD041: false # First line in file should be a top level heading, PULL_REQUEST_TEMPLATE.md is an exception ################# # Rules by tags # ################# -blank_lines: false # Error on blank lines +blank_lines: false # Error on blank lines diff --git a/src/overrides/assets/javascripts/abbreviation-preview.js b/src/overrides/assets/javascripts/abbreviation-preview.js deleted file mode 100644 index 1db79df..0000000 --- a/src/overrides/assets/javascripts/abbreviation-preview.js +++ /dev/null @@ -1,98 +0,0 @@ -/* global document$ */ -(function () { - "use strict"; - - // Map abbreviations to glossary pages. Add entries as glossary coverage expands. - var ABBR_TO_PAGE = { - API: "Dictionary/api/", - "CI/CD": "Dictionary/ci-cd/", - CI: "Dictionary/ci-cd/", - CD: "Dictionary/ci-cd/", - GH: "Dictionary/github/", - GitHub: "Dictionary/github/", - Git: "Dictionary/git/", - LTS: "Dictionary/lts/", - MkDocs: "Dictionary/mkdocs/", - REST: "Dictionary/rest-api/", - "REST API": "Dictionary/rest-api/", - YAML: "Dictionary/yaml/", - }; - - function titleCase(value) { - return value - .toLowerCase() - .split(/\s+/) - .filter(Boolean) - .map(function (part) { - return part.charAt(0).toUpperCase() + part.slice(1); - }) - .join(" "); - } - - function getAbbreviationText(node) { - return (node.textContent || "").trim(); - } - - function toAbsoluteHref(path) { - var scopeBase = "/"; - if ( - typeof window !== "undefined" && - window.__md_scope && - window.__md_scope.base - ) { - scopeBase = window.__md_scope.base; - } - - if (!scopeBase.endsWith("/")) { - scopeBase += "/"; - } - - return scopeBase + path; - } - - function upgradeAbbreviation(node) { - if (!node || node.dataset.abbrLinked === "true") { - return; - } - - var key = getAbbreviationText(node); - var target = ABBR_TO_PAGE[key]; - if (!target) { - return; - } - - var link = document.createElement("a"); - link.href = toAbsoluteHref(target); - link.className = "abbr-preview-link"; - link.innerHTML = node.innerHTML; - - // Keep native tooltip text as fallback while enabling preview-on-hover for links. - if (node.hasAttribute("title")) { - link.setAttribute("title", node.getAttribute("title")); - } else { - link.setAttribute("title", titleCase(key)); - } - - // Mark transformed to avoid repeated wrapping on instant navigation reloads. - link.dataset.abbrLinked = "true"; - node.replaceWith(link); - } - - function enhanceAbbreviations() { - var nodes = document.querySelectorAll("abbr"); - nodes.forEach(upgradeAbbreviation); - } - - if (typeof document$ !== "undefined" && document$.subscribe) { - document$.subscribe(function () { - enhanceAbbreviations(); - }); - return; - } - - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", enhanceAbbreviations); - } else { - enhanceAbbreviations(); - } -})(); From f5cf2106617634f42e2cb129ef99b4fdaa1f47dc Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:34:21 +0200 Subject: [PATCH 06/10] Refactor Update-MDSection to improve error handling; replace warnings with exceptions for missing markers. Update AGENTS.md references to point to canonical guidance in PSModule/docs. --- .github/actions/update-index/src/Helper.psm1 | 23 +++----------------- .github/actions/update-index/src/main.ps1 | 4 ++-- src/docs/Modules/Repository-Defaults.md | 6 ++--- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index ff76cdd..6575fae 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -98,35 +98,18 @@ function Update-MDSection { $startSegment = "" $endSegment = "" - function Write-UpdateWarning { - param([string] $Message) - - Write-Warning $Message - if ($env:GITHUB_ACTIONS -eq 'true') { - Write-Output "::warning::$Message" - } - } - - if (-not (Test-Path -Path $Path)) { - Write-UpdateWarning "[$Name] Skipping update because target file was not found: $Path" - return - } - $currentContent = Get-Content -Path $Path $startIndex = $currentContent.IndexOf($startSegment) $endIndex = $currentContent.IndexOf($endSegment) if ($startIndex -lt 0) { - Write-UpdateWarning "[$Name] Skipping update because the start marker was not found in: $Path" - return + throw "[$Name] The start comment segment was not found in the file." } if ($endIndex -lt 0) { - Write-UpdateWarning "[$Name] Skipping update because the end marker was not found in: $Path" - return + throw "[$Name] The end comment segment was not found in the file." } if ($endIndex -lt $startIndex) { - Write-UpdateWarning "[$Name] Skipping update because marker order is invalid in: $Path" - return + throw "[$Name] The end comment segment was found before the start comment segment." } $updatedContent = $currentContent[0..$startIndex] + $Content + $currentContent[($endIndex)..($currentContent.Length - 1)] diff --git a/.github/actions/update-index/src/main.ps1 b/.github/actions/update-index/src/main.ps1 index c49d528..c2d68fb 100644 --- a/.github/actions/update-index/src/main.ps1 +++ b/.github/actions/update-index/src/main.ps1 @@ -1,6 +1,6 @@ Import-Module -Name (Join-Path $PSScriptRoot 'Helper.psm1') Show-RepoList -Update-ActionList -Update-FunctionAppList +# Update-ActionList +# Update-FunctionAppList Update-ModuleList diff --git a/src/docs/Modules/Repository-Defaults.md b/src/docs/Modules/Repository-Defaults.md index d8eb4a1..3575b76 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 PSModule and MSX documentation for the why, how, and what. | +| `AGENTS.md` | Agent onboarding entry point. Points agents to the canonical guidance in `PSModule/docs`. | | `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 PSModule and MSX documentation. | +| `AGENTS.md` | Cross-tool agent instructions pointing to the canonical guidance in `PSModule/docs`. | | `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. | @@ -132,7 +132,7 @@ Each repository must stand on its own. It carries its own copy of every file abo 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 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. +- `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. From dd20de9679f36cab5028647045153715cc5d9396 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:35:24 +0200 Subject: [PATCH 07/10] Remove extra blank line in Update-MDSection --- .github/actions/update-index/src/Helper.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 6575fae..30ed03a 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -97,7 +97,6 @@ function Update-MDSection { $startSegment = "" $endSegment = "" - $currentContent = Get-Content -Path $Path $startIndex = $currentContent.IndexOf($startSegment) $endIndex = $currentContent.IndexOf($endSegment) From 124be48b2cac2d8818b81e4c63952029546e981c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:48:42 +0200 Subject: [PATCH 08/10] Fix GitHub capitalization in AGENTS.md --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index aca5719..e9818ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ If you find a problem, fix it if it's small; otherwise, register it as an issue To install: Clone the repos in the users home folder under a sub-folder named `.msx/PSModule`. -- Set configs locally to each of these repos using the github username and email. +- Set configs locally to each of these repos using the GitHub username and email. ## Working with the ecosystem From c0e6edec164e2e124e99da2f8ccd0f53671ee620 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:53:51 +0200 Subject: [PATCH 09/10] Update MODULE_LIST path in Update-ModuleList function to point to the correct markdown file location --- .github/actions/update-index/src/Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 30ed03a..33bd642 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -229,7 +229,7 @@ $moduleTableRows "@ - Update-MDSection -Path '.\src\docs\PowerShell\Modules\index.md' -Name 'MODULE_LIST' -Content $moduleTable + Update-MDSection -Path '.\src\docs\Modules\Catalog\index.md' -Name 'MODULE_LIST' -Content $moduleTable } function Update-FunctionAppList { From 6cfa46763c320478ea4876c2e8ce312bfce868f6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 18 Jul 2026 14:57:57 +0200 Subject: [PATCH 10/10] Fix Update-ModuleList to target the MODULE_CATALOG section marker --- .github/actions/update-index/src/Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index 33bd642..dbba6f8 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -229,7 +229,7 @@ $moduleTableRows "@ - Update-MDSection -Path '.\src\docs\Modules\Catalog\index.md' -Name 'MODULE_LIST' -Content $moduleTable + Update-MDSection -Path '.\src\docs\Modules\Catalog\index.md' -Name 'MODULE_CATALOG' -Content $moduleTable } function Update-FunctionAppList {