From cb3495e114ee44012df82b6fd6b60abd1a2f0afa Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:03:11 -0600 Subject: [PATCH 01/13] Fixes #7: Run PR tests for main and milestone branches --- .github/workflows/test.yml | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4db22b5 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,41 @@ +name: Merge Test Workflow + +on: + pull_request: + branches: + - main + - "milestone/**" + +jobs: + run_tests: + runs-on: windows-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ vars.DOTNET_VERSION }} + + - name: Clean + shell: pwsh + run: dotnet clean "${{ github.workspace }}/src/HelpGenerator.sln" --configuration Release + + - name: Restore dependencies + shell: pwsh + run: dotnet restore "${{ github.workspace }}/src/HelpGenerator.sln" + + - name: Build + shell: pwsh + run: dotnet build "${{ github.workspace }}/src/HelpGenerator.sln" --configuration Release --no-restore + + - name: Test + shell: pwsh + run: dotnet test "${{ github.workspace }}/src/HelpGenerator.sln" --configuration Release --no-build --logger "trx;LogFileName=test_results.trx" + + - name: Publish Test Results + if: always() + uses: actions/upload-artifact@v6 + with: + name: Test Results + path: '**/TestResults/*.trx' From ff4192e02d9a544a912211cd5b61cb65bd2cff16 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:03:59 -0600 Subject: [PATCH 02/13] Fixes #8: Pack preview artifacts and upload as build artifact --- .github/workflows/build.yml | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..98cf55d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,64 @@ +name: Build and Package (Preview) + +on: + push: + branches: + - main + +jobs: + build_and_pack: + runs-on: windows-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ vars.DOTNET_VERSION }} + + - name: Get Project Version + id: get_version + uses: mod-posh/GetProjectVersion@main + with: + Filename: 'Directory.Build.props' + verbose: "verbose" + + - name: Compose preview version parts + shell: pwsh + run: | + $sha7 = "${env:GITHUB_SHA}".Substring(0,7) + $prefix = "${{ steps.get_version.outputs.version }}" + if ([string]::IsNullOrWhiteSpace($prefix)) { $prefix = $env:VERSION } + if ([string]::IsNullOrWhiteSpace($prefix)) { throw "Could not resolve VersionPrefix" } + + "VERSION_PREFIX=$prefix" >> $env:GITHUB_ENV + "VERSION_SUFFIX=preview.${env:GITHUB_RUN_NUMBER}-g$sha7" >> $env:GITHUB_ENV + + - name: Clean + shell: pwsh + run: dotnet clean "${{ github.workspace }}/src/HelpGenerator.sln" --configuration Release + + - name: Pack (preview) + shell: pwsh + run: > + dotnet pack "${{ github.workspace }}/src/HelpGenerator.sln" + --configuration Release + --output "${{ github.workspace }}/publish" + /m:1 + -p:UseSharedCompilation=false + -p:ContinuousIntegrationBuild=true + -p:PackageVersion=${{ env.VERSION_PREFIX }}-${{ env.VERSION_SUFFIX }} + -p:RepositoryCommit=${{ github.sha }} + -p:RepositoryBranch=${{ github.ref_name }} + + - name: List packages + shell: pwsh + run: | + Get-ChildItem -Path "${{ github.workspace }}/publish" | + ForEach-Object { Write-Host "Packaged: $($_.FullName)" } + + - name: Upload packages as artifact + uses: actions/upload-artifact@v6 + with: + name: preview-packages + path: publish/*.nupkg From 7184cac7d30113d5b532ff1f038ea46a08af005a Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:04:24 -0600 Subject: [PATCH 03/13] Fixes #9: Lean milestone-close release workflow with version guardrail --- .github/workflows/release.yml | 83 +++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b460043 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,83 @@ +name: New Release + +on: + milestone: + types: [closed] + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository (main) + uses: actions/checkout@v6 + with: + ref: main + fetch-depth: 0 + + - name: Get Project Version + id: get_version + uses: mod-posh/GetProjectVersion@main + with: + Filename: 'Directory.Build.props' + verbose: "verbose" + + - name: Guardrail milestone title must match version + shell: pwsh + run: | + $milestoneTitle = '${{ github.event.milestone.title }}'.Trim() + $version = '${{ steps.get_version.outputs.version }}'.Trim() + + if ([string]::IsNullOrWhiteSpace($milestoneTitle)) { + throw "Milestone title is empty. Refusing to create release." + } + + if ([string]::IsNullOrWhiteSpace($version)) { + throw "Project version is empty. Refusing to create release." + } + + if ($milestoneTitle -ne $version) { + throw "Refusing to create release: milestone title '$milestoneTitle' does not match project version '$version'." + } + + Write-Host "Guardrail passed: milestone title '$milestoneTitle' matches version '$version'." + + - name: Create Release Notes + uses: mod-posh/Issue2ReleaseNotes@v0.0.3.3 + with: + milestone_number: ${{ github.event.milestone.number }} + verbose: 'verbose' + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release (Tag + GitHub Release) + uses: mod-posh/NewTaggedRelease@v0.0.3.2 + with: + name: 'Release v${{ env.VERSION }}' + filename: 'RELEASE.md' + version: ${{ env.VERSION }} + verbose: 'verbose' + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ vars.DOTNET_VERSION }} + + - name: Build + run: dotnet build "${{ github.workspace }}/src/${{ vars.PROJECT_NAME }}.sln" --configuration Release + + - name: Test + run: dotnet test "${{ github.workspace }}/src/${{ vars.PROJECT_NAME }}.sln" --configuration Release --no-build + + - name: Pack (Release) + run: dotnet pack "${{ github.workspace }}/src/${{ vars.PROJECT_NAME }}.sln" --configuration Release --output "${{ github.workspace }}/publish" --no-build + + - name: Upload release packages + uses: actions/upload-artifact@v6 + with: + name: release-packages + path: publish/*.nupkg + + # PSGallery publishing will be added once the PowerShell module packaging is implemented. + # - name: Publish to PowerShell Gallery + # shell: pwsh + # run: Publish-Module ... From c576f74ed9f80eb6e7d608afafcbaf160f4237cf Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:04:49 -0600 Subject: [PATCH 04/13] Fixes #10: Add docs PR workflow triggered after release --- .github/workflows/docs-pr.yml | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/docs-pr.yml diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml new file mode 100644 index 0000000..607236c --- /dev/null +++ b/.github/workflows/docs-pr.yml @@ -0,0 +1,62 @@ +name: Docs PR After Release + +on: + workflow_run: + workflows: ["New Release"] + types: + - completed + +jobs: + docs_pr: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout Repository (main) + uses: actions/checkout@v6 + with: + ref: main + fetch-depth: 0 + + - name: Get Latest Tag + id: latest_tag + run: | + LATEST_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName') + echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ vars.DOTNET_VERSION }} + + # TODO: Replace with actual HelpGenerator docs generation when implemented. + - name: Generate Documentation (stub) + shell: bash + run: | + echo "Docs generation is currently stubbed." + echo "Replace this step once ${{ vars.PROJECT_NAME }} can generate docs." + + - name: Create Pull Request with Docs Updates + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "Update docs for ${{ vars.PROJECT_NAME }} ${{ env.LATEST_TAG }}" + title: "Update docs for ${{ vars.PROJECT_NAME }} ${{ env.LATEST_TAG }}" + body: | + This PR updates generated documentation following release ${{ env.LATEST_TAG }}. + + Notes: + - Generated via workflow: Docs PR After Release + - No code changes intended + branch: "docs/${{ env.LATEST_TAG }}" + base: main + delete-branch: true + add-paths: | + docs/** + README.md From b908e1e4bcd2bbd74315bf713d09948645b42800 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:05:32 -0600 Subject: [PATCH 05/13] Fixes #11: Normalize Actions variables (DOTNET_VERSION, PROJECT_NAME) --- .github/workflows/notifications.yml | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/notifications.yml diff --git a/.github/workflows/notifications.yml b/.github/workflows/notifications.yml new file mode 100644 index 0000000..a91fd25 --- /dev/null +++ b/.github/workflows/notifications.yml @@ -0,0 +1,41 @@ +name: Announce New Release + +on: + workflow_run: + workflows: ["New Release"] + types: + - completed + +jobs: + send_notification: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + + - name: Get Latest Tag + id: latest_tag + run: | + LATEST_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName') + echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Post to Bluesky + uses: mod-posh/Post2BlueSky@v0.0.3.0 + with: + Message: | + Version ${{ env.latest_tag }} of ${{ vars.PROJECT_NAME }} is available! 🎉 + See details here: ${{ github.server_url }}/${{ github.repository }} + verbose: "verbose" + bluesky_api_key: ${{ secrets.bluesky_api_key }} + bluesky_identifier: ${{ secrets.bluesky_identifier }} + + - name: Post to Discord + uses: mod-posh/Post2Discord@v0.0.3.2 + with: + message: | + Version ${{ env.latest_tag }} of ${{ vars.PROJECT_NAME }} is available! 🎉 + See details here: ${{ github.server_url }}/${{ github.repository }} + discordWebhook: ${{ secrets.DISCORD_WEBHOOK }} From 1057503889094f6f9949ee4178e713ebbfaae262 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:07:18 -0600 Subject: [PATCH 06/13] Fixes #12: Add CODEOWNERS for repo governance --- .github/CODEOWNERS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..ce1daa9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,14 @@ +# Default owner +* @jeffpatton1971 + +# Core engine +/src/HelpGenerator.Core/ @jeffpatton1971 + +# PowerShell layer +/src/HelpGenerator.Powershell/ @jeffpatton1971 + +# Documentation & ADRs +/docs/ @jeffpatton1971 + +# CI/CD workflows +/.github/workflows/ @jeffpatton1971 \ No newline at end of file From 8273d249138933497b36aaf780e03c60c34d4fd3 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:19:35 -0600 Subject: [PATCH 07/13] Fixes #2: Add ADR-014 and update ADR index --- docs/adr/ADR-001.md | 36 ++++ docs/adr/ADR-002.md | 45 +++++ docs/adr/ADR-003.md | 32 ++++ docs/adr/ADR-004.md | 49 +++++ docs/adr/ADR-005.md | 26 +++ docs/adr/ADR-006.md | 198 ++++++++++++++++++++ docs/adr/ADR-007.md | 345 ++++++++++++++++++++++++++++++++++ docs/adr/ADR-008.md | 294 +++++++++++++++++++++++++++++ docs/adr/ADR-009.md | 285 ++++++++++++++++++++++++++++ docs/adr/ADR-010.md | 317 ++++++++++++++++++++++++++++++++ docs/adr/ADR-011.md | 439 ++++++++++++++++++++++++++++++++++++++++++++ docs/adr/ADR-012.md | 225 +++++++++++++++++++++++ docs/adr/ADR-013.md | 179 ++++++++++++++++++ docs/adr/ADR-014.md | 149 +++++++++++++++ docs/adr/README.md | 98 ++++++++++ 15 files changed, 2717 insertions(+) create mode 100644 docs/adr/ADR-001.md create mode 100644 docs/adr/ADR-002.md create mode 100644 docs/adr/ADR-003.md create mode 100644 docs/adr/ADR-004.md create mode 100644 docs/adr/ADR-005.md create mode 100644 docs/adr/ADR-006.md create mode 100644 docs/adr/ADR-007.md create mode 100644 docs/adr/ADR-008.md create mode 100644 docs/adr/ADR-009.md create mode 100644 docs/adr/ADR-010.md create mode 100644 docs/adr/ADR-011.md create mode 100644 docs/adr/ADR-012.md create mode 100644 docs/adr/ADR-013.md create mode 100644 docs/adr/ADR-014.md create mode 100644 docs/adr/README.md diff --git a/docs/adr/ADR-001.md b/docs/adr/ADR-001.md new file mode 100644 index 0000000..629f5c8 --- /dev/null +++ b/docs/adr/ADR-001.md @@ -0,0 +1,36 @@ +# ADR-001 — Scope and non-goals + +**Status:** Accepted +**Date:** 2026-02-20 + +## Context + +We are building a suite to generate PowerShell help assets quickly and consistently. The suite must support both script-based help sources and compiled cmdlets. + +### Decision + +This project **only** does: + +1. Parse **comment-based help** from PowerShell scripts/modules and generate: + + * **MAML external help** (command help content) + * **HelpInfo.xml** (updatable help metadata) +2. If comment-based help is missing, generate **placeholder scaffolds** (script help blocks and/or markdown placeholders). +3. Parse **HelpInfo.xml** and **MAML** and generate **discrete Markdown documentation**. +4. Validate generated artifacts against **official schemas** (HelpInfo schema + MAML schema where applicable). +5. Support **updatable help** distribution structure (CAB packaging layout + expected metadata). + +### Non-goals + +Explicitly out of scope: + +* General documentation tooling unrelated to PowerShell help +* Website generation / doc hosting / static site generation +* API documentation generation for arbitrary languages/frameworks +* PlatyPS integration, extension, or consumption +* Arbitrary markdown “beautification” beyond help-document clarity + +### Consequences + +* Feature proposals must directly serve *help artifacts* (comment help ↔ MAML/HelpInfo ↔ markdown ↔ CAB/updateable layout). +* Anything that doesn’t shorten “time to correct help” is rejected. diff --git a/docs/adr/ADR-002.md b/docs/adr/ADR-002.md new file mode 100644 index 0000000..a31211a --- /dev/null +++ b/docs/adr/ADR-002.md @@ -0,0 +1,45 @@ +# ADR-002 — Source-of-truth and supported inputs + +**Status:** Accepted +**Date:** 2026-02-20 + +## Context + +Help content can come from: + +* Script functions/modules (comment-based help) +* Compiled cmdlets (C#) where content often originates from XML docs or embedded MAML +* Existing help artifacts (MAML, HelpInfo.xml, CABs) + +### Decision + +We support these primary inputs: + +**Script-based.** + +* `.ps1` and `.psm1` containing functions/advanced functions +* Associated `.psd1` module manifest when provided (preferred for metadata) + +**Compiled cmdlets.** + +* `.dll` (PowerShell module assembly) +* Optional `.xml` documentation file emitted by build (recommended) +* Optional embedded resources if we define them (future-friendly) + +**Artifact-based.** + +* `HelpInfo.xml` +* MAML XML help files +* CAB files containing MAML help payloads + +Source-of-truth hierarchy: + +1. If input is **comment-based help**: that is the authoritative content for command help. +2. If input is **compiled cmdlets**: the authoritative content is the **XML docs** (preferred) or existing MAML. +3. HelpInfo.xml is authoritative for updatable metadata (cultures, versions, URIs), never for per-command content. + +### Consequences + +* Script path: Comment-help → normalized model → MAML + markdown (+ HelpInfo.xml metadata). +* Compiled path: XML docs/assembly metadata → normalized model → MAML + markdown (+ HelpInfo.xml metadata). +* Artifact path: MAML/HelpInfo.xml → markdown (+ validation). diff --git a/docs/adr/ADR-003.md b/docs/adr/ADR-003.md new file mode 100644 index 0000000..a9cd141 --- /dev/null +++ b/docs/adr/ADR-003.md @@ -0,0 +1,32 @@ +# ADR-003 — Parsing strategy and normalization model + +**Status:** Accepted +**Date:** 2026-02-20 + +## Context + +We need consistent output regardless of input type (script vs compiled vs existing artifacts). PowerShell help has multiple shapes (comment blocks, XML docs, MAML). + +### Decision + +Create an internal **normalized help model** (single object graph) representing: + +* Module metadata (name, GUID, version, cultures, URIs) +* Command metadata (name, verb-noun, synopsis/description) +* Parameters (name, type, required, pipeline, position, description) +* Examples +* Inputs/Outputs +* Links/notes + +All generators (MAML, HelpInfo.xml, Markdown) consume the normalized model. + +Parsing: + +* Script functions: use **PowerShell AST** to locate functions and attach preceding/help blocks. +* Compiled cmdlets: reflect cmdlet metadata from assembly; hydrate descriptions from XML docs where available. +* MAML ingestion: map MAML nodes back into normalized model. + +### Consequences + +* Output consistency becomes testable with golden fixtures. +* We can add new input types without rewriting generators. diff --git a/docs/adr/ADR-004.md b/docs/adr/ADR-004.md new file mode 100644 index 0000000..82fbecf --- /dev/null +++ b/docs/adr/ADR-004.md @@ -0,0 +1,49 @@ +# ADR-004 — Output contracts and file layout + +**Status:** Accepted +**Date:** 2026-02-20 + +## Context + +Users need predictable outputs for CI, release packaging, and doc publishing. + +### Decision + +We define stable output contracts: + +*Markdown output** + +```bash +/docs + /module + module.md # module overview + usage + update-help instructions + helpinfo.md # HelpInfo.xml explained + fields rendered + /commands + .md # one file per command + /about + .md # if present / supported +``` + +**External help output (MAML).** + +```bash +/help + / + -Help.xml # MAML external help payload for that culture +``` + +**Updatable help output.** + +```bash +/updatable-help + HelpInfo.xml + / + __.cab +``` + +Filenames are deterministic; no spaces; command names match actual export names. + +### Consequences + +* Release pipelines can package and host content without custom glue. +* Tests can compare directories exactly. diff --git a/docs/adr/ADR-005.md b/docs/adr/ADR-005.md new file mode 100644 index 0000000..50083fc --- /dev/null +++ b/docs/adr/ADR-005.md @@ -0,0 +1,26 @@ +# ADR-005 — Schema validation and offline strategy + +**Status:** Accepted +**Date:** 2026-02-20 + +## Context + +We must “understand the schema” and guarantee validity. Online schemas may move; offline builds must still work. + +### Decision + +* We implement schema validation as a first-class feature: + + * `Test-HelpInfoXml` validates HelpInfo.xml against schema + semantic rules. + * `Test-MamlHelp` validates MAML structure (schema where practical + semantic rules). +* Schema retrieval: + + * Provide a cmdlet to **fetch/update schema bundles** into a local cache folder (repo or user profile) + * Tool defaults to **offline cached schemas**; online update is explicit. + +### Consequences + +* Deterministic builds in CI. +* Reduced risk of schema drift breaking releases. + +--- diff --git a/docs/adr/ADR-006.md b/docs/adr/ADR-006.md new file mode 100644 index 0000000..5cf1392 --- /dev/null +++ b/docs/adr/ADR-006.md @@ -0,0 +1,198 @@ +# ADR-006 — Compiled C# Cmdlets Help Pipeline + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The Help Generator suite must support both: + +* Script-based PowerShell functions/modules (comment-based help) +* Compiled C# cmdlets (binary modules) + +Because this project generates MAML, HelpInfo.xml, and Markdown documentation, it must support compiled cmdlets as first-class citizens — including cmdlets written as part of this project. + +We explicitly do **not** leverage or extend PlatyPS. The suite must own the compiled cmdlet help pipeline end-to-end. + +--- + +## Decision + +### 1. Compiled cmdlets are supported as primary inputs + +Supported input types for compiled modules: + +* PowerShell module assembly (`.dll`) +* XML documentation file emitted during build (`.xml`) +* Optional future: structured help sidecar file (if defined by this project) + +The build for compiled cmdlets **must enable XML documentation generation**: + +```xml + + true + +``` + +The XML documentation file is required to provide human-authored help content. + +--- + +### 2. Metadata discovery via reflection + +The suite will use reflection to discover cmdlet structure: + +* `[Cmdlet(Verb, Noun)]` +* `[Parameter]` +* Parameter sets +* Parameter types +* Mandatory flags +* Pipeline binding attributes +* Output types (via `[OutputType]`) +* Aliases (via `[Alias]`) +* Cmdlet class inheritance (Cmdlet vs PSCmdlet) + +Reflection provides **structural metadata only**. + +Reflection does **not** provide authoritative help prose. + +--- + +### 3. Human-authored content source + +Human-authored documentation content must originate from one of: + +1. XML documentation file (preferred) +2. A structured sidecar help file (future extension if needed) + +The following XML doc elements are used: + +| XML Element | Mapped To | +| ------------------------------- | --------------------- | +| `` | Synopsis | +| `` | Description | +| `` | Parameter description | +| `` | Output description | +| `` (custom convention) | Examples | +| `` | Paragraph formatting | + +If `` is not part of the official XML schema, we support it as a convention within `` or as a structured extension. + +If XML documentation is missing: + +* The suite will generate placeholder help scaffolds. +* Validation will warn that prose is missing. + +--- + +### 4. Normalized model integration + +Compiled cmdlets are transformed into the same **normalized help model** used for script-based help. + +Pipeline: + +```bash +Assembly + XML docs + ↓ +Reflection + XML parsing + ↓ +NormalizedHelpModel + ↓ +MAML Generator +Markdown Generator +HelpInfo.xml Generator +``` + +All output generators operate identically regardless of source type. + +This guarantees: + +* Consistent output format +* Testable golden fixtures +* Stable markdown contracts +* Identical MAML shape for script and compiled modules + +--- + +### 5. Generated artifacts + +For compiled modules, the suite generates: + +* External help MAML (`-Help.xml`) +* HelpInfo.xml +* Discrete Markdown documentation +* Optional updatable help folder structure + +Artifact layout remains governed by ADR-004. + +--- + +## Guardrails + +1. Reflection is metadata-only. + + * It defines structure. + * It does not define prose quality. + +2. XML documentation (or future structured help sidecar) is the authoritative prose source. + +3. We do not attempt to infer meaningful descriptions from: + + * Parameter names + * Types + * Attribute metadata alone + +4. We do not auto-generate “AI-written” prose. + +If human-written documentation is absent, we generate placeholders. + +--- + +## Rationale + +Supporting compiled cmdlets: + +* Enables first-class documentation for binary modules. +* Allows this project to dogfood itself. +* Supports broader adoption beyond script-only modules. +* Preserves deterministic output independent of PlatyPS. + +Using XML documentation files: + +* Integrates cleanly with standard .NET build workflows. +* Encourages maintainable, version-controlled help content. +* Keeps prose close to source code. + +Using a normalized model: + +* Avoids dual logic paths. +* Simplifies testing. +* Ensures future extensibility without rewriting generators. + +--- + +## Consequences + +Positive: + +* Full parity between script and compiled cmdlet support. +* Deterministic documentation generation. +* Clean separation of structure (reflection) and prose (XML docs). + +Trade-offs: + +* XML documentation becomes mandatory for quality output. +* Developers must follow documentation discipline during build. + +--- + +## Future Considerations (Not Committed) + +* Structured `` XML extension schema +* Custom attributes for richer help metadata +* Roslyn-based source parsing for deeper analysis +* Validation rule set for missing or incomplete XML documentation + +These are explicitly optional and must remain within help-generation scope. diff --git a/docs/adr/ADR-007.md b/docs/adr/ADR-007.md new file mode 100644 index 0000000..78b840d --- /dev/null +++ b/docs/adr/ADR-007.md @@ -0,0 +1,345 @@ +# ADR-007 — MAML Generation Contract + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The Help Generator suite produces **external help (MAML)** files for: + +* Script-based modules +* Compiled C# cmdlets + +PowerShell external help must conform to the MAML schema used by PowerShell help engines. Even when schema validation passes, structural inconsistencies (ordering, missing sections, unexpected nesting) can cause rendering issues or future incompatibility. + +To ensure: + +* Deterministic output +* Schema validity +* PowerShell compatibility +* Testable golden fixtures + +We define a strict MAML generation contract. + +--- + +## Decision + +All MAML generated by this suite must: + +1. Follow a deterministic node ordering. +2. Render all supported sections in a consistent structure. +3. Be generated solely from the NormalizedHelpModel. +4. Avoid runtime-specific formatting logic. +5. Be stable across runs for identical inputs. + +--- + +## 1. File-Level Structure + +Each culture produces one MAML file: + +```bash +-Help.xml +``` + +Root structure: + +```xml + + + ... + + + ... + + +``` + +Rules: + +* One `` per exported command. +* Commands are sorted alphabetically by command name. +* No runtime-dependent ordering. + +--- + +## 2. Command Node Contract + +Each `` node must contain the following sections in this exact order: + +1. `
` +2. `` +3. `` +4. `` +5. `` (if applicable) +6. `` (if applicable) +7. `` (if present) +8. `` (if present) + +Sections may be omitted only if no data exists, except: + +* `
` is required. +* `` is required. +* `` must exist (even if empty). + +--- + +## 3. `
` Section + +Required structure: + +```xml +
+ Get-Example + Get + Example + + Short synopsis text. + +
+``` + +Rules: + +* `` must match exported command name exactly. +* Verb and noun must match `[Cmdlet]` or parsed function name. +* Synopsis is single-paragraph content from normalized model. + +--- + +## 4. `` Section + +```xml + + Full description paragraph 1. + Paragraph 2. + +``` + +Rules: + +* Derived from `` (compiled) or `.DESCRIPTION` (script). +* Multiple paragraphs rendered as multiple `` nodes. +* No raw markdown inside `` nodes. +* No HTML. + +--- + +## 5. `` Section + +Each parameter set produces one ``. + +```xml + + + Get-Example + + Id + String + + + +``` + +Rules: + +* Parameter sets are sorted alphabetically. +* Parameters within each set are sorted by: + + 1. Position (if defined) + 2. Alphabetically +* Switch parameters omit `` type text if appropriate. +* Pipeline support is expressed via attributes when supported. +* Mandatory attribute reflected as `required="true"`. + +--- + +## 6. `` Section + +Each parameter rendered once, independent of parameter sets: + +```xml + + + Id + + Specifies the identifier. + + String + + +``` + +Rules: + +* Description derived from XML doc `` or script help `.PARAMETER`. +* If no description exists, placeholder text is inserted. +* Aliases included where applicable. +* Default values may be rendered if available. + +--- + +## 7. `` Section + +Rendered only if explicitly defined. + +```xml + + + + System.String + + + +``` + +Rules: + +* Derived from reflection or script metadata. +* If none defined, section omitted. + +--- + +## 8. `` Section + +```xml + + + + System.String + + + Returns a string. + + + +``` + +Rules: + +* Derived from `[OutputType]` or XML ``. +* Omitted if not available. + +--- + +## 9. `` Section + +```xml + + + Example 1 + Get-Example -Id 1 + + Retrieves example with ID 1. + + + +``` + +Rules: + +* Ordered as defined in source. +* Title auto-generated if absent. +* Code blocks preserved exactly as authored. +* Multiple examples supported. +* No formatting inference. + +--- + +## 10. `` Section + +Rendered if links are defined. + +```xml + + + About Examples + https://example.com + + +``` + +--- + +## 11. Determinism Requirements + +The following must be deterministic: + +* Command ordering +* Parameter ordering +* Parameter set ordering +* XML indentation +* Attribute ordering +* Namespace declaration placement + +Golden fixture tests must be able to perform exact file comparisons. + +--- + +## 12. Culture Handling + +* One MAML file per culture. +* Default culture: `en-US`. +* If additional cultures are supported, each must produce separate file trees. +* Culture is controlled by HelpInfo.xml and generation options. + +--- + +## 13. Validation Rules + +The suite must provide: + +* Schema validation (where feasible) +* Semantic validation: + + * Missing synopsis + * Missing parameter descriptions + * Duplicate parameter names + * Invalid verb-noun combinations + * Missing examples (warning level) + +Validation does not auto-fix content. + +--- + +## 14. Guardrails + +We do not: + +* Generate synthetic prose +* Infer examples automatically +* Inject markdown formatting +* Reorder content based on heuristics +* Deviate from PowerShell help expectations + +The generator is structural and deterministic, not creative. + +--- + +## Rationale + +Defining a strict MAML contract: + +* Prevents format drift +* Enables stable CI validation +* Ensures PowerShell compatibility +* Simplifies test design +* Allows side-by-side diffing in releases + +--- + +## Consequences + +Positive: + +* Predictable help artifacts +* Easy regression detection +* Clear separation between parsing and rendering + +Trade-offs: + +* Requires disciplined input +* Strict structure may require iterative refinement during early development diff --git a/docs/adr/ADR-008.md b/docs/adr/ADR-008.md new file mode 100644 index 0000000..98f44d1 --- /dev/null +++ b/docs/adr/ADR-008.md @@ -0,0 +1,294 @@ +# ADR-008 — Normalized Help Model Specification + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The suite must support multiple input sources: + +* Comment-based help in scripts/modules +* Compiled cmdlets via reflection + XML documentation +* Existing MAML files +* HelpInfo.xml metadata + +To guarantee consistent output and keep generator logic simple, we need one canonical internal representation for: + +* Module metadata +* Command help content +* Parameter sets and parameter metadata +* Examples, inputs/outputs, and related links +* Localization/culture support + +This ADR defines the **normalized help model** used across the entire suite. + +--- + +## Decision + +We define a single internal object graph (the “Normalized Help Model”) with these top-level entities: + +1. `HelpPackage` (root) +2. `ModuleHelp` (module metadata + updatable help metadata) +3. `CommandHelp` (per-command content) +4. `ParameterHelp` (per-parameter metadata + prose) +5. `ParameterSetHelp` (syntax grouping) +6. `ExampleHelp` +7. `TypeHelp` (input/output types) +8. `LinkHelp` (related links) +9. `Localization` (culture-aware values) + +All parsers must produce this model. All generators must consume this model. + +--- + +## 1. Root Entity: `HelpPackage` + +Represents one module’s help content (optionally multi-culture). + +Required fields: + +* `Module`: `ModuleHelp` (required) +* `Commands`: `List` (required; can be empty) +* `AboutTopics`: `List` (optional; future-friendly) +* `Cultures`: `List` (required; default: `["en-US"]`) + +Rules: + +* `Commands` is sorted/stabilized by `CommandHelp.Name` for output determinism. +* `Cultures` must align with HelpInfo.xml supported cultures. + +--- + +## 2. Module Entity: `ModuleHelp` + +Required fields: + +* `Name`: string (module name) +* `Guid`: string (module GUID; required for updatable help) +* `Version`: string (semantic version string) +* `Description`: LocalizedText (optional; module overview) +* `Author`: string (optional) +* `CompanyName`: string (optional) +* `Copyright`: string (optional) + +Updatable help metadata (for HelpInfo.xml generation): + +* `HelpContentUri`: string (required when generating HelpInfo.xml for updatable help) +* `SupportedCultures`: `List` (required; at least one) + + * Each culture entry includes: + + * `Culture`: string (`en-US`) + * `HelpVersion`: string (version of help payload for that culture) + * `CabPath` / `CabName` (optional, derived during packaging) + +Rules: + +* Module `Guid` must be stable across releases. +* `HelpVersion` must be independently bumpable from `ModuleHelp.Version`. + +--- + +## 3. Localized Text: `LocalizedText` + +Many text fields must support localization. + +Representation: + +* `Dictionary` keyed by culture (e.g., `en-US`) +* Convenience: `Get(culture)` with fallback to default culture + +Rules: + +* Default culture is `en-US` unless otherwise configured. +* If a culture is missing a value, fallback to default culture for generation (with warning). + +--- + +## 4. Command Entity: `CommandHelp` + +Required fields: + +* `Name`: string (`Verb-Noun`) +* `Verb`: string +* `Noun`: string + +Prose fields: + +* `Synopsis`: LocalizedText (required; placeholder allowed) +* `Description`: LocalizedText (optional but recommended) +* `Notes`: LocalizedText (optional) + +Structural fields: + +* `Parameters`: `List` (required; may be empty) +* `ParameterSets`: `List` (required; at least one) +* `Examples`: `List` (optional) +* `Inputs`: `List` (optional) +* `Outputs`: `List` (optional) +* `Links`: `List` (optional) +* `Aliases`: `List` (optional) + +Rules: + +* `ParameterSets` must include a “default” set if the source does not define sets. +* `Parameters` are unique by name (case-insensitive). +* `Verb`/`Noun` must match `Name` split unless command name is atypical (still stored explicitly). + +--- + +## 5. Parameter Entity: `ParameterHelp` + +Required fields: + +* `Name`: string +* `TypeName`: string (e.g., `System.String`) +* `Description`: LocalizedText (required; placeholder allowed) + +Metadata fields: + +* `IsMandatory`: bool (default false) +* `Position`: int? (null if named-only) +* `AcceptsPipelineInput`: enum `{ None, ByValue, ByPropertyName, Both }` +* `AcceptsWildcardCharacters`: bool? (optional) +* `IsSwitch`: bool (default false) +* `DefaultValue`: string? (optional; preserved as text) +* `Aliases`: `List` (optional) +* `ParameterSets`: `List` (names of sets this parameter participates in; optional) +* `ValidateSet`: `List` (optional) +* `ValidateRange`: `{ Min: string?, Max: string? }` (optional; stored as text) +* `AllowNull`: bool? (optional) +* `AllowEmptyString`: bool? (optional) +* `AllowEmptyCollection`: bool? (optional) + +Rules: + +* If `IsSwitch` is true, `TypeName` should still be recorded (e.g., `System.Management.Automation.SwitchParameter`) but generators may render it specially. +* Validation metadata is preserved but not invented. + +--- + +## 6. Parameter Set Entity: `ParameterSetHelp` + +Required fields: + +* `Name`: string +* `IsDefault`: bool +* `Syntax`: `List` (required; may be empty) + +`SyntaxParameterRef` includes: + +* `ParameterName`: string +* `IsMandatory`: bool (set-level view) +* `Position`: int? +* `TypeName`: string (optional if derivable) +* `IsSwitch`: bool + +Rules: + +* Syntax parameter ordering within a set is deterministic: + + 1. Position ascending (null last) + 2. ParameterName ascending + +--- + +## 7. Example Entity: `ExampleHelp` + +Required fields: + +* `Title`: LocalizedText (required; auto-generated if absent) +* `Code`: LocalizedText (required) +* `Remarks`: LocalizedText (optional) + +Rules: + +* Examples maintain original order from source. +* Code is preserved exactly (no reformatting). + +--- + +## 8. Type Entity: `TypeHelp` + +Fields: + +* `TypeName`: string (e.g., `System.String`) +* `Description`: LocalizedText (optional) + +Rules: + +* If a source provides only type names, description remains empty. + +--- + +## 9. Link Entity: `LinkHelp` + +Fields: + +* `LinkText`: LocalizedText (required) +* `Uri`: string (required) + +Rules: + +* No URL normalization beyond basic validation. +* Generators may omit invalid URIs (with warning). + +--- + +## 10. Placeholder Policy + +When source content is missing, the model must still be complete enough to generate valid artifacts. + +Placeholder requirements: + +* `Synopsis` must exist (placeholder allowed) +* Parameter `Description` must exist (placeholder allowed) +* ParameterSets must exist (at least one) + +Placeholders are marked via an internal flag (e.g., `IsPlaceholder = true`) to enable: + +* Warnings in validation +* Optional reporting without changing output structure + +--- + +## 11. Determinism Policy + +Before generation, the model must be normalized: + +* Sort commands by name +* Sort parameters by name +* Sort parameter sets by name (default set first) +* Stabilize link ordering (by LinkText then Uri) +* Preserve example ordering + +Determinism is required to enable golden fixture tests and exact diffs. + +--- + +## Rationale + +A strict normalized model: + +* Reduces generator complexity +* Enables multiple input types without duplicated logic +* Makes validation and testing straightforward +* Provides a stable foundation for future localization support + +--- + +## Consequences + +Positive: + +* Predictable and consistent output across sources +* Easier to evolve generators independently of parsers +* Strong contract for tests and fixtures + +Trade-offs: + +* Requires upfront modeling work +* Requires normalization passes and validation rules diff --git a/docs/adr/ADR-009.md b/docs/adr/ADR-009.md new file mode 100644 index 0000000..869c8bf --- /dev/null +++ b/docs/adr/ADR-009.md @@ -0,0 +1,285 @@ +# ADR-009 — Validation Rules and Severity Levels + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The Help Generator suite produces: + +* MAML external help +* HelpInfo.xml +* Markdown documentation +* Updatable help packaging structure + +To ensure correctness, determinism, and PowerShell compatibility, the suite must validate: + +* Structural integrity +* Schema compliance +* Semantic completeness +* Authoring quality + +However, not all validation issues should block generation. Some issues represent fatal errors; others represent incomplete documentation that should only warn the developer. + +This ADR defines: + +* Validation categories +* Severity levels +* Default behaviors +* CI integration expectations + +--- + +## Decision + +Validation is divided into three layers: + +1. **Structural Validation** +2. **Schema Validation** +3. **Semantic Validation** + +Each rule produces a severity: + +* `Error` (generation must fail) +* `Warning` (generation succeeds but reports issue) +* `Info` (non-blocking informational message) + +--- + +### 1. Structural Validation + +Structural validation ensures the Normalized Help Model is internally consistent. + +These are **Errors**: + +* Duplicate command names (case-insensitive) +* Duplicate parameter names within a command +* Parameter referenced in a ParameterSet but not defined +* ParameterSet marked as default but multiple default sets exist +* Missing required model properties: + + * Command `Name` + * Command `Verb` or `Noun` + * Module `Name` + * Module `Guid` (when generating HelpInfo.xml) +* Invalid culture identifier format +* HelpVersion missing when generating updatable help + +These are **Warnings**: + +* Command has no examples +* Command has no output type defined +* Parameter has no description (but placeholder exists) +* Synopsis is placeholder text +* Description missing entirely +* HelpContentUri not provided (if HelpInfo generation requested but not explicitly required) + +--- + +### 2. Schema Validation + +Schema validation applies to generated XML artifacts. + +## HelpInfo.xml + +**Errors:** + +* XML fails XSD validation +* Missing required nodes +* Culture entries missing required attributes +* Invalid version format +* HelpContentUri malformed + +**Warnings:** + +* HelpVersion equals module version (allowed but flagged for clarity) +* Multiple cultures share identical HelpVersion (allowed but flagged) + +--- + +## MAML + +**Errors:** + +* XML not well-formed +* Missing required `
` node +* Missing `` node +* Invalid nesting structure +* Schema validation failure (if XSD available) + +**Warnings:** + +* Empty `` section omitted +* Parameter has no description +* Return type has no description + +--- + +### 3. Semantic Validation + +Semantic validation enforces PowerShell conventions and authoring quality. + +## Command Naming + +**Errors:** + +* Verb not in approved PowerShell verb list (configurable strict mode) +* Command name missing dash (`-`) + +**Warnings:** + +* Non-standard verb (if not strict mode) +* Noun contains invalid characters +* Alias conflicts with another command + +--- + +## Parameter Quality + +**Warnings:** + +* Mandatory parameter without description +* Switch parameter documented with type prose that contradicts switch behavior +* Parameter description shorter than configurable minimum length +* Default value documented but not reflected in metadata (compiled cmdlets only) + +--- + +## Example Quality + +**Warnings:** + +* Example contains no code +* Example code does not contain command name +* Duplicate example titles + +--- + +## Localization + +**Errors:** + +* Culture listed in HelpInfo.xml but no corresponding MAML file generated + +**Warnings:** + +* Culture missing localized text and falling back to default +* Inconsistent HelpVersion across cultures + +--- + +## + +Placeholders are allowed but flagged. + +Placeholder-related rules: + +| Condition | Severity | +| ------------------------------------------------------- | ---------------------------- | +| Placeholder Synopsis | Warning | +| Placeholder Parameter Description | Warning | +| Entire Command fully placeholder | Warning | +| Placeholder in release mode (configurable strict build) | Error (optional strict mode) | + +This allows: + +* Development scaffolding +* Strict CI enforcement in production pipelines + +--- + +### 5. Validation Execution Model + +Validation runs in three phases: + +1. Model validation (before generation) +2. Artifact validation (after generation) +3. Packaging validation (when building updatable help structure) + +Validation results are aggregated into a structured report: + +```json +{ + "Errors": [], + "Warnings": [], + "Info": [] +} +``` + +--- + +### 6. CLI / Cmdlet Behavior + +Default behavior: + +* Errors stop generation. +* Warnings do not stop generation. +* Exit code non-zero if Errors > 0. + +Optional switches: + +* `-TreatWarningsAsErrors` +* `-Strict` (enables stricter semantic rules) +* `-Quiet` +* `-VerboseValidation` + +--- + +### 7. CI Integration Expectations + +In CI environments: + +Recommended default: + +* Fail on Errors +* Warn on Warnings +* Optionally treat warnings as errors for release builds + +The suite must expose: + +* Machine-readable validation output (JSON) +* Human-readable summary (console format) +* Deterministic ordering of reported issues + +--- + +### 8. Guardrails + +Validation must not: + +* Modify source content automatically +* Rewrite prose +* Attempt to “fix” grammar +* Infer missing descriptions +* Reorder author-intended examples + +Validation reports problems; generation remains deterministic. + +--- + +### Rationale + +Clear validation tiers: + +* Prevent invalid artifacts +* Encourage high-quality documentation +* Support scaffolding workflows +* Enable strict CI enforcement +* Avoid silent generation of broken help + +--- + +### Consequences + +Positive: + +* Strong quality guarantees +* Predictable CI behavior +* Clear separation between correctness and quality + +Trade-offs: + +* Additional complexity in rule engine +* Requires documentation of severity expectations diff --git a/docs/adr/ADR-010.md b/docs/adr/ADR-010.md new file mode 100644 index 0000000..43c5cfe --- /dev/null +++ b/docs/adr/ADR-010.md @@ -0,0 +1,317 @@ +# ADR-010 — HelpInfo.xml and Updatable Help Packaging Contract + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The Help Generator suite must support: + +* Generation of HelpInfo.xml +* Generation of external help (MAML) +* Packaging for PowerShell updatable help (CAB-based distribution) +* Deterministic, testable output structure + +PowerShell’s `Update-Help` mechanism relies on: + +* HelpInfo.xml metadata +* Versioned help content per culture +* Downloadable CAB files +* Consistent module GUID + module name alignment + +To avoid ambiguity and distribution inconsistencies, this ADR defines: + +* HelpInfo.xml contract +* Versioning rules +* CAB naming conventions +* Folder layout requirements +* Packaging assumptions + +--- + +### 1. HelpInfo.xml Contract + +HelpInfo.xml is generated from the `ModuleHelp` model. + +Minimum required structure: + +```xml + + https://example.com/help + + + en-US + 1.0.0.0 + + + +``` + +If multiple cultures: + +```xml + + fr-FR + 1.0.0.0 + +``` + +--- + +## Required Fields + +* `HelpContentUri` +* At least one `Culture` +* `HelpVersion` per culture + +--- + +## Not Included in HelpInfo.xml + +HelpInfo.xml does **not** contain: + +* Command help content +* Module description prose +* Parameter descriptions +* Examples + +It is strictly metadata for locating versioned help payloads. + +--- + +### 2. Versioning Rules + +We distinguish between: + +* Module Version +* Help Version + +#### Module Version + +From: + +* `.psd1` manifest +* Assembly version (compiled modules) +* Explicit user override + +#### Help Version + +HelpVersion is independently managed and: + +* Must be in `Major.Minor.Build.Revision` format +* Must increment when help content changes +* Does not have to match module version + +--- + +#### Versioning Guardrails + +Errors: + +* HelpVersion missing +* HelpVersion invalid format +* HelpVersion decreases between generations (if baseline provided) + +Warnings: + +* HelpVersion equals Module Version (allowed but flagged) +* HelpVersion unchanged but content changed (if diff detectable) + +--- + +## 3. External Help (MAML) Layout + +Generated MAML layout: + +```bash +/help + /en-US + -Help.xml + /fr-FR + -Help.xml +``` + +Rules: + +* Exactly one MAML file per culture. +* File name must match module name exactly. +* Culture folder must match CultureName in HelpInfo.xml. + +--- + +## 4. CAB Packaging Contract + +CAB files are culture-specific. + +Naming convention: + +```bash +__.cab +``` + +Example: + +```bash +MyModule_1.0.0.0_en-US.cab +``` + +CAB contents: + +```bash +-Help.xml +``` + +Only the MAML file for that culture is included. + +No nested folders inside CAB. + +--- + +### Packaging Folder Layout + +When generating updatable help output: + +```bash +/updatable-help + HelpInfo.xml + /en-US + MyModule_1.0.0.0_en-US.cab + /fr-FR + MyModule_1.0.0.0_fr-FR.cab +``` + +This structure is deterministic and testable. + +--- + +## 5. GUID Alignment Requirement + +If module manifest exists: + +* `ModuleHelp.Guid` must match `.psd1` GUID. + +If compiled module: + +* GUID must be provided explicitly or sourced from manifest. + +Error if: + +* GUID missing when generating HelpInfo.xml. +* GUID mismatch detected (optional strict validation). + +--- + +## 6. HelpContentUri Strategy + +HelpContentUri is the base URL where: + +* HelpInfo.xml is hosted +* CAB files are hosted + +The suite does not: + +* Host content +* Upload content +* Generate static websites + +It only validates: + +* URI format +* That CAB names match declared versions + +--- + +## 7. Packaging Execution Modes + +We support two modes: + +### 1. Generate Only + +* Produces MAML + HelpInfo.xml +* Does not build CAB + +### 2. Package Mode + +* Produces CAB files +* Produces full updatable-help folder structure + +Switch example: + +```powershell +Export-HelpPackage -Module MyModule -Package +``` + +--- + +## 8. Validation Requirements + +Packaging validation includes: + +Errors: + +* Missing MAML file for culture listed in HelpInfo.xml +* Missing CAB file when packaging enabled +* CAB filename mismatch with HelpVersion +* Culture mismatch between folder and HelpInfo.xml entry + +Warnings: + +* HelpContentUri not HTTPS +* Multiple cultures share identical help payload hash (informational) + +--- + +## 9. Determinism Requirements + +The following must be deterministic: + +* HelpInfo.xml element ordering +* Culture ordering (alphabetical) +* CAB naming +* Folder structure +* XML indentation and attribute ordering + +Golden fixture tests must compare entire folder trees exactly. + +--- + +## 10. Guardrails + +The suite does not: + +* Publish help to servers +* Modify module manifests automatically +* Auto-bump HelpVersion +* Generate hosting configurations +* Integrate with NuGet or PowerShell Gallery publishing + +Distribution automation is external to this project. + +--- + +## Rationale + +Separating help packaging from publishing: + +* Keeps scope tight +* Keeps tool deterministic +* Avoids platform-specific deployment logic +* Ensures updatable help compatibility without drift + +--- + +## Consequences + +Positive: + +* Predictable updatable help structure +* Clear separation between content and distribution +* CI-friendly packaging +* Clean release workflow + +Trade-offs: + +* Requires external hosting solution +* HelpVersion discipline is developer-managed diff --git a/docs/adr/ADR-011.md b/docs/adr/ADR-011.md new file mode 100644 index 0000000..ab63d28 --- /dev/null +++ b/docs/adr/ADR-011.md @@ -0,0 +1,439 @@ +# ADR-011 — Markdown Generation Contract + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +The Help Generator suite must convert: + +* NormalizedHelpModel +* MAML +* HelpInfo.xml + +into structured, readable Markdown documentation. + +Markdown output must: + +* Be deterministic +* Be CI-friendly +* Be readable in GitHub and similar renderers +* Not depend on a specific static site generator +* Avoid hidden rendering assumptions +* Avoid "style drift" + +This ADR defines the canonical Markdown output contract. + +--- + +## 1. Markdown Philosophy + +Markdown output is: + +* Structural, not decorative +* Predictable, not clever +* Clean, not over-styled +* Portable across renderers +* Free of custom extensions + +We do **not**: + +* Inject front matter by default +* Assume Jekyll/Docusaurus/Hugo +* Inject HTML +* Auto-generate badges +* Infer links beyond defined related links + +--- + +## 2. Directory Structure + +Markdown output must follow ADR-004 layout: + +```bash +/docs + /module + module.md + helpinfo.md + /commands + .md + /about + .md (optional) +``` + +All filenames: + +* Exact command name +* No spaces +* Case preserved +* Deterministic ordering + +--- + +## 3. Command Markdown Structure + +Each `.md` file must follow this exact section order: + +```bash +# CommandName + +## Synopsis + +## Description + +## Syntax + +## Parameters + +## Inputs + +## Outputs + +## Examples + +## Notes + +## Related Links +``` + +Sections may be omitted if no data exists, except: + +* `# CommandName` (always present) +* `## Synopsis` (always present) +* `## Syntax` (always present) +* `## Parameters` (always present) + +--- + +## 4. Header Rules + +Top-level header: + +```bash +# Get-Example +``` + +No module prefix. +No extra text. +No trailing metadata in header. + +--- + +## 5. Synopsis Section + +```bash +## Synopsis + +Short single-paragraph summary. +``` + +Rules: + +* Single paragraph. +* No bold formatting. +* No trailing punctuation enforcement. + +--- + +## 6. Description Section + +```bash +## Description + +Paragraph one. + +Paragraph two. +``` + +Rules: + +* Paragraph breaks preserved. +* No forced line wrapping. +* No HTML. + +--- + +$# 7. Syntax Section + +Syntax is rendered as fenced code blocks. + +For single parameter set: + +````markdown +## Syntax + +```powershell +Get-Example -Id [-Verbose] +``` +```` + +For multiple parameter sets: + +````markdown +## Syntax + +### ById + +```powershell +Get-Example -Id +``` + +### ByName + +```powershell +Get-Example -Name +``` +```` + +Rules: + +* Parameter sets sorted alphabetically. +* Default set appears first. +* Parameters rendered in deterministic order. +* Switch parameters shown without `` placeholder. +* Optional parameters wrapped in brackets. + +--- + +$# 8. Parameters Section + +Each parameter rendered as: + +```bash +### -Id + +Type: `String` +Required: Yes +Position: 0 +Pipeline Input: ByValue + +Specifies the identifier. +``` + +Rules: + +* Parameter sections sorted alphabetically. +* Type shown inline as backticked. +* Boolean values shown as Yes/No. +* Blank metadata lines omitted. +* Description rendered as paragraph after metadata block. + +No parameter tables (tables introduce formatting drift and poor diffing). + +--- + +## 9. Inputs Section + +```bash +## Inputs + +### System.String + +Description text. +``` + +If no description: + +```bash +## Inputs + +System.String +``` + +--- + +## 10. Outputs Section + +```bash +## Outputs + +### System.String + +Returns a string. +``` + +--- + +## 11. Examples Section + +Each example rendered as: + +````markdown +## Examples + +### Example 1 + +```powershell +Get-Example -Id 1 +``` + +Retrieves example with ID 1. +```` + +Rules: + +* Examples remain in original order. +* Code block language always `powershell`. +* Title auto-generated if absent. +* No additional formatting. + +--- + +## 12. Notes Section + +Only rendered if content exists. + +Used for: + +* Notes +* Special behaviors +* Remarks not appropriate for description + +--- + +## 13. Related Links Section + +```bash +## Related Links + +- [About Examples](https://example.com) +``` + +Rules: + +* Sorted alphabetically by link text. +* Standard Markdown link syntax only. + +--- + +## 14. Module-Level Markdown + +`module.md`: + +```bash +# ModuleName + +## Overview + +Module description. + +## Commands + +- [Get-Example](../commands/Get-Example.md) +- [Set-Example](../commands/Set-Example.md) + +## Updating Help + +Instructions about Update-Help and HelpContentUri. +``` + +Rules: + +* Command list sorted alphabetically. +* Relative links only. + +--- + +## 15. HelpInfo Markdown (`helpinfo.md`) + +Rendered as structured explanation: + +```bash +# HelpInfo Metadata + +## Help Content URI + +https://example.com/help + +## Supported Cultures + +- en-US (1.0.0.0) +- fr-FR (1.0.0.0) +``` + +No raw XML embedded unless explicitly requested. + +--- + +## 16. Determinism Rules + +Must be deterministic: + +* Section ordering +* Parameter ordering +* Parameter set ordering +* Culture ordering +* Bullet ordering +* Line endings (LF) +* Indentation (2 spaces) +* No trailing whitespace + +Golden fixture tests must pass exact text comparison. + +--- + +## 17. Guardrails + +Markdown generator must not: + +* Reword descriptions +* Auto-link parameter names +* Insert emojis +* Add badges +* Inject front matter +* Change casing +* Wrap lines arbitrarily +* Inject site-specific anchors + +It is a structural renderer only. + +--- + +## 18. Strict Mode Option (Future) + +Optional flag: + +```bash +-StrictMarkdown +``` + +Enforces: + +* No empty sections +* No placeholder prose +* Examples required +* Output types required + +Strict mode converts certain warnings into errors. + +--- + +## Rationale + +This structure: + +* Mirrors PowerShell help mental model +* Avoids rendering surprises +* Works cleanly in GitHub +* Diff-friendly in PRs +* Easy to test +* Human-readable without tooling + +--- + +## Consequences + +Positive: + +* Stable, predictable docs +* Easy CI enforcement +* Clean GitHub rendering +* Simple mental model + +Trade-offs: + +* No advanced site features +* No automatic navigation hierarchy +* No dynamic TOC injection diff --git a/docs/adr/ADR-012.md b/docs/adr/ADR-012.md new file mode 100644 index 0000000..57563c4 --- /dev/null +++ b/docs/adr/ADR-012.md @@ -0,0 +1,225 @@ +# ADR-012 — Comment-Based Help AST Parsing Contract + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +To generate help consistently from script-based PowerShell, the suite must: + +* Discover exported functions in `.ps1` and `.psm1` +* Detect and parse comment-based help blocks +* Correctly associate help blocks with their target function +* Scaffold placeholders deterministically when help is missing +* Avoid fragile regex-only parsing + +PowerShell scripts can include: + +* Multiple functions +* Nested functions +* Regions +* Dot-sourced includes +* Multiple comment blocks near a function + +This ADR defines the contract for discovery, association, parsing, and scaffolding. + +--- + +## Decision + +### 1. Discovery uses PowerShell AST + +We use PowerShell’s parser to build an AST and identify: + +* `FunctionDefinitionAst` nodes +* Advanced functions (presence of `CmdletBinding`) +* Function name and declared parameters +* Parameter attributes (e.g., `Parameter`, `Alias`, validations) + +We do not rely on regex for function discovery. + +--- + +### 2. Which functions are “documented targets” + +In `.ps1` (single script file): + +* All top-level functions are considered targets unless excluded by configuration. + +In `.psm1` (module script): + +* All top-level functions are targets by default. +* If a manifest `.psd1` is provided and includes `FunctionsToExport`, we treat that as the authoritative export list. +* If the module uses `Export-ModuleMember`, we will optionally honor it (future improvement), but initial contract assumes `.psd1` is the preferred export authority. + +Exclusions: + +* Functions may be excluded via: + + * `-ExcludeFunction ` option, or + * a recognized marker in help (e.g., `.EXTERNALHELPGENERATORIGNORE`) (future; not required). + +--- + +### 3. Help block association rules (deterministic) + +For a function `F`, the associated comment-based help block is determined by: + +**Primary association rule:** + +* The closest comment-based help block **immediately preceding** the function definition, with only whitespace and/or attribute lines between it and the function definition. + +Accepted separation between help block and function: + +* Blank lines +* Attribute blocks applied to the function (e.g., `[CmdletBinding()]`, `[OutputType()]`) + +Not accepted separation: + +* Any executable statement +* Another function definition +* Another comment-based help block closer to the function + +If multiple candidate help blocks exist: + +* Choose the nearest valid help block. +* Emit a warning if ambiguity is detected (e.g., two help blocks within N lines). + +--- + +### 4. Supported comment-based help formats + +We support: + +**Block help:** + +```powershell +<# +.SYNOPSIS +... +#> +function Get-Thing { } +``` + +**Line help:** + +```powershell +function Get-Thing { + # .SYNOPSIS + # ... +} +``` + +Initial v1 contract prioritizes block help (`<# #>`). Line help support is allowed but may be limited to well-formed patterns. + +--- + +### 5. Parsing contract (tokenization, not prose rewriting) + +We parse standard help directives: + +* `.SYNOPSIS` +* `.DESCRIPTION` +* `.PARAMETER ` +* `.EXAMPLE` +* `.INPUTS` +* `.OUTPUTS` +* `.NOTES` +* `.LINK` +* `.COMPONENT`, `.ROLE`, `.FUNCTIONALITY` (captured as notes/metadata if present) + +Rules: + +* Preserve paragraph breaks. +* Preserve example code exactly. +* Preserve ordering of examples. +* Do not auto-correct spelling, punctuation, or casing. +* Treat unknown directives as Notes (warning level). + +--- + +### 6. Parameter reconciliation rules + +After parsing help content, we reconcile parameter help with actual function parameters from AST: + +Errors: + +* Help documents a parameter that does not exist in function signature (configurable strict mode) + Warnings: +* Function has a parameter that is undocumented in help +* Help describes parameter but signature differs (type/position mismatch if discoverable) + +We always generate a complete `CommandHelp.Parameters` model: + +* Missing prose becomes placeholder text (per ADR-009). + +--- + +### 7. Scaffolding contract (when help is missing) + +If no help block is associated with a function, we generate a deterministic scaffold. + +For scripts: + +* Default behavior: create a new help block inserted immediately above the function definition. + +Scaffold structure: + +```powershell +<# +.SYNOPSIS +TODO: Add synopsis. + +.DESCRIPTION +TODO: Add description. + +.PARAMETER Name +TODO: Describe -Name. + +.EXAMPLE +TODO: Add example. + +.NOTES +TODO: Add notes. +#> +``` + +Rules: + +* Include `.PARAMETER` sections for every parameter in signature. +* Include at least one `.EXAMPLE`. +* Do not include `.INPUTS`/`.OUTPUTS` unless discoverable. +* Preserve original formatting and indentation as much as possible. +* No rewriting of existing code beyond insertion of help block. + +If configured “no in-place edits” mode: + +* Emit scaffold blocks as sidecar files in `/scaffolds/.help.txt`. + +--- + +### 8. Guardrails + +We do not: + +* Execute PowerShell code +* Resolve dot-sourced includes automatically (future enhancement) +* Infer intent from code behavior +* Generate prose beyond placeholders + +--- + +## Consequences + +Positive: + +* Correct and repeatable help association +* Robust against code formatting differences +* Clear behavior for missing/ambiguous help blocks + +Trade-offs: + +* Dot-sourcing/module composition isn’t fully resolved in v1 without explicit inputs +* Some edge cases may require explicit configuration (e.g., export lists) diff --git a/docs/adr/ADR-013.md b/docs/adr/ADR-013.md new file mode 100644 index 0000000..2d1105a --- /dev/null +++ b/docs/adr/ADR-013.md @@ -0,0 +1,179 @@ +# ADR-013 — Test Strategy and Golden Fixture Design + +**Status:** Accepted +**Date:** 2026-02-20 + +--- + +## Context + +This project requires deterministic outputs across multiple inputs and generators: + +* Script-based comment help → MAML + HelpInfo.xml + Markdown +* Compiled cmdlets → MAML + HelpInfo.xml + Markdown +* Artifact ingestion (MAML/HelpInfo.xml) → Markdown + +To prevent regressions and ensure stability, tests must use golden fixtures and directory-tree comparisons. + +This ADR defines the test strategy and fixture layout. + +--- + +## Decision + +### 1. Test layers + +We implement three test tiers: + +1. **Unit Tests** + + * Parsing of directives into normalized model + * Reflection extraction from compiled cmdlets + * Markdown rendering for a single command + * MAML node generation rules (ordering, presence) + +2. **Integration Tests** + + * End-to-end for a sample script module + * End-to-end for a sample compiled module + * Validate generated artifacts against schemas + * Validate directory layout contracts + +3. **Golden Fixture Tests** + + * Generate outputs into a temp folder + * Compare folder trees + file contents to a committed “golden” baseline + +--- + +### 2. Fixture repository layout + +```text +/tests + /fixtures + /script-module-basic + input/ + MyModule.psm1 + MyModule.psd1 + expected/ + help/ + docs/ + updatable-help/ + /script-module-missing-help + input/ + expected/ + /compiled-module-basic + input/ + MyModule.dll + MyModule.xml + MyModule.psd1 (optional) + expected/ + help/ + docs/ + updatable-help/ + /maml-ingest-basic + input/ + help/en-US/MyModule-Help.xml + HelpInfo.xml + expected/ + docs/ +``` + +Rules: + +* `expected/` is the golden output. +* Tests must run generation and compare outputs exactly. + +--- + +### 3. Golden comparison rules (deterministic diffing) + +Golden comparisons must include: + +* Directory structure equality +* File presence equality +* Exact file contents equality + +Normalization for comparison: + +* Line endings normalized to LF before compare +* Trailing whitespace not ignored (must be deterministic) +* XML normalized only if generator claims canonical formatting; otherwise compare raw text + +When diff fails: + +* Test output prints: + + * Missing files + * Extra files + * First differing line for file content mismatch + +--- + +### 4. Schema validation tests + +We validate generated artifacts: + +* HelpInfo.xml: + + * XSD validation where feasible + * Semantic rules per ADR-009 and ADR-010 + +* MAML: + + * Well-formed XML validation always + * XSD validation where feasible + * Semantic rules per ADR-007/ADR-009 + +If XSD availability is offline-cached: + +* Tests must include the schema bundle in the repo or in test assets. + +--- + +### 5. Cross-source parity tests + +We include parity tests to prove that script and compiled sources generate equivalent structures for the same conceptual command: + +* Same command name +* Same parameter list and parameter metadata +* Same section ordering in markdown +* Equivalent MAML structure + +Prose differences are allowed if authored differently. + +--- + +### 6. Performance guardrails + +We add basic performance regression tests (non-benchmark) to ensure: + +* Parsing does not scale superlinearly with file size +* Reflection does not load assemblies repeatedly unnecessarily + +These are informational unless thresholds are exceeded in CI. + +--- + +### 7. “Update golden fixtures” workflow + +We intentionally make golden updates explicit: + +* Tests do not auto-update expected files. +* A dedicated dev command/script generates outputs into `tests/fixtures/**/expected`. +* Fixture update requires a conscious commit + review. + +--- + +## Consequences + +Positive: + +* Strong regression protection +* Deterministic outputs enforced by tests +* Confident refactoring and generator iteration + +Trade-offs: + +* Golden fixtures require maintenance when contracts evolve +* Early development may see frequent fixture updates until stabilized diff --git a/docs/adr/ADR-014.md b/docs/adr/ADR-014.md new file mode 100644 index 0000000..2c50afa --- /dev/null +++ b/docs/adr/ADR-014.md @@ -0,0 +1,149 @@ +# ADR-014: Governance and Branch Protection Policy + +## Status + +Accepted + +## Context + +HelpGenerator is governed by Architecture Decision Records (ADRs) that define scope, output contracts, and behavioral constraints. + +To ensure these architectural contracts remain enforceable and to prevent drift, governance must be enforced at the repository level through: + +- Branch protection +- Required status checks +- Code Owner review +- Controlled release triggers + +Without enforcement, ADR compliance becomes optional rather than structural. + +This ADR formalizes the repository governance model. + +--- + +## Decision + +### 1. Protected `main` Branch + +The `main` branch represents the releasable state of HelpGenerator. + +The following protections are required: + +- Direct pushes are prohibited +- Pull requests are required for all changes +- At least one approval is required +- Code Owner review is required +- Required status checks must pass +- Branch must be up-to-date before merge +- Force pushes and deletions are disabled + +--- + +### 2. Milestone-Based Development + +Development occurs on milestone branches: + +```bash + +milestone/ + +``` + +Example: + +```bash + +milestone/0.0.0 + +``` + +Milestone branches may receive multiple pull requests. + +When milestone work is complete: + +1. The milestone branch is merged into `main` +2. The milestone is closed +3. Closing the milestone triggers the release workflow + +--- + +### 3. Release Guardrail + +The release workflow must validate: + +- The milestone title matches the version defined in `Directory.Build.props` + +If they do not match, the release workflow must fail. + +This prevents accidental releases triggered by prematurely closing a milestone. + +--- + +### 4. Hotfix Model + +Hotfixes branch from `main`: + +```bash + +hotfix/ + +``` + +After fix: + +1. Pull request into `main` +2. Patch release is created +3. Fix is backported into active milestone branch if necessary + +--- + +### 5. Documentation Automation + +Post-release documentation updates must not push directly to `main`. + +Documentation updates are handled via: + +- A workflow triggered after successful release +- A generated pull request into `main` + +This preserves branch protection integrity. + +--- + +## Consequences + +### Positive + +- Prevents architectural drift +- Ensures ADR contracts are enforced structurally +- Reduces accidental releases +- Makes release automation deterministic +- Establishes professional governance standards + +### Trade-offs + +- Slightly more ceremony for merging changes +- Requires discipline in milestone management +- Requires branch protection configuration in GitHub UI + +These trade-offs are intentional and align with project goals. + +--- + +## Alternatives Considered + +### Tag-driven releases only + +Rejected because milestone-close release aligns better with issue-grouped release notes and project board workflow. + +### No branch protection + +Rejected because it makes ADR compliance unenforceable. + +--- + +## References + +- ADR-001 (Project Scope) +- ADR-004 (Repository Layout) +- ADR-013 (Testing Strategy) diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..bbeb23e --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,98 @@ +# Architecture Decision Records (ADR) + +This folder contains the authoritative architectural contracts for the PowerShell Help Generator project. + +These ADRs are not documentation fluff. +They are binding agreements that define: + +- Scope boundaries +- Supported inputs and outputs +- Generation contracts (MAML, Markdown, HelpInfo.xml) +- Validation rules +- Packaging rules +- Testing strategy +- Determinism requirements + +If implementation ever conflicts with an ADR, one of two things must happen: + +1. The implementation changes. +2. The ADR is formally updated with a new decision. + +Silent drift is not allowed. + +--- + +## Why ADRs Matter Here + +This project has a very tight scope: + +> Generate clean, well-structured PowerShell help artifacts from comment-based help, compiled cmdlets, MAML, and HelpInfo.xml — nothing more. + +Without guardrails, it would be easy to drift into: + +- A generic documentation tool +- A static site generator +- A help hosting platform +- A PlatyPS extension +- A “smart” prose rewriter + +The ADRs prevent that. + +--- + +## Current ADR Index + +| ADR | Title | +| ----- | ------- | +| ADR-001 | Scope and Non-Goals | +| ADR-002 | Supported Inputs and Source of Truth | +| ADR-003 | Parsing Strategy and Normalization | +| ADR-004 | Output Contracts and File Layout | +| ADR-005 | Schema Validation Strategy | +| ADR-006 | Compiled C# Cmdlets Support | +| ADR-007 | MAML Generation Contract | +| ADR-008 | Normalized Help Model Specification | +| ADR-009 | Validation Rules and Severity Levels | +| ADR-010 | HelpInfo.xml and Packaging Contract | +| ADR-011 | Markdown Generation Contract | +| ADR-012 | Comment-Based Help AST Parsing Contract | +| ADR-013 | Test Strategy and Golden Fixture Design | +| ADR-014 | Governance and Branch Protection Policy | + +--- + +## How to Propose a Change + +If a new idea arises: + +1. Identify which ADR it impacts. +2. Determine whether it violates the current decision. +3. If so, create a new ADR or update the existing one. +4. Document the rationale clearly. +5. Only then implement. + +We do not “just try something.” + +--- + +## Core Principles + +- Deterministic output +- Structural, not creative +- Schema-valid artifacts +- Strong separation of parsing and rendering +- Zero scope creep +- CI-safe and diff-friendly +- Developer-first ergonomics + +--- + +## The Discipline Rule + +If implementation and ADR conflict: + +> The ADR wins. + +Unless formally updated. + +This keeps the project stable, predictable, and professional. From 8f791ec694d4e4857770e37825a9019c7479f357 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:30:39 -0600 Subject: [PATCH 08/13] Fixes #5: Update contributing guide for governance and milestone releases --- CONTRIBUTING.md | 180 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 157 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 108e4e6..c441fe6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,41 +1,175 @@ -# Contributing to [Your Project Name] +# Contributing to HelpGenerator ## Introduction -Thank you for your interest in contributing to [Your Project Name]! We value the contributions from the community and are glad that you're interested in helping improve this project. This document outlines the guidelines for contributing, which help maintain the project's quality and keep the process efficient and respectful. +Thanks for your interest in contributing to HelpGenerator. + +This project is intentionally narrow in scope: it generates and validates PowerShell help artifacts (comment-based help, MAML, HelpInfo.xml, Markdown, and updatable-help packaging structure). Everything else is out of scope. + +Before contributing, please read the Architecture Decision Records (ADRs). They are the contract for this project. + +- Architecture overview: [`docs/adr/README.md`](docs/adr/README.md) +- ADRs: `docs/adr/ADR-001.md` through `docs/adr/ADR-014.md` + +If an implementation idea conflicts with an ADR, either: + +1. The implementation changes, or +2. The ADR is formally updated first. + +Silent drift is not allowed. + +--- + +## Governance Policy + +This repository enforces governance structurally. + +See: **ADR-014 — Governance and Branch Protection Policy** + +Key principles: + +- `main` is protected and always releasable +- All changes must go through pull requests +- Code Owner review is required +- Required checks must pass +- Releases are milestone-driven +- Closing a milestone triggers a release +- A release will fail if milestone title does not match project version + +--- ## How to Contribute -There are many ways to contribute to this project: +There are several ways to contribute: + +- **Reporting bugs**: Open an issue describing expected vs actual behavior and include repro steps and sample inputs if possible. +- **Suggesting enhancements**: Open an issue describing the goal and which ADR(s) the change aligns with. +- **Documentation improvements**: Updates to Quickstart, README, ADRs, and usage docs are always welcome. +- **Code contributions**: Submit changes through pull requests (PRs). See workflow below. + +--- + +## Workflow: Milestones, Projects, and Issues + +Work is organized around **milestones**. + +- Each milestone is associated with a GitHub Project board. +- Milestone work is tracked as GitHub issues. +- Issues should be labeled: + - by type (e.g., `bug`, `documentation`, `enhancement`) + - by ADR alignment (`adr-001` … `adr-014`) + - optionally by component (`parser:*`, `generator:*`, `packaging:cab`, `tests:golden`, `ci-cd`, etc.) + +### When to create a new issue during coding + +Create a new issue when: + +- a change introduces a new requirement not covered in the original issue scope, or +- fixing it is non-trivial and should be tracked independently, or +- it represents a regression or a contract change. + +Small fixes discovered while implementing an issue can stay within the same issue. + +--- + +## Branching Model + +`main` is protected and must remain releasable. + +We use: -- **Reporting Bugs**: If you find a bug, please open an issue in the repository using the bug report template. -- **Suggesting Enhancements**: If you have ideas on improving the project, open an issue using the feature request template. -- **Code Contributions**: You can contribute to the codebase through pull requests. Please read the section below on how to submit a pull request. +- `milestone/` branches for milestone work +- optional short-lived branches for specific issues: + - `issue/-short-title` + +Typical flow: + +1. Create a milestone branch from `main` +2. Open PRs into the milestone branch +3. When milestone work is complete, merge milestone branch into `main` +4. Close the milestone (this triggers release) + +### Important + +Milestones must only be closed after the milestone branch has been merged into `main`. + +The release workflow validates that the milestone title matches the project version. If not, the release fails. + +--- + +## Hotfixes + +If a bug is discovered in a released version: + +1. Branch from `main`: `hotfix/` +2. Fix + PR into `main` +3. Patch release is created +4. Backport the fix into the active milestone branch if necessary + +--- ## Pull Request Process -1. **Fork the Repository**: Start by forking the repository to your own GitHub account. -2. **Clone the Fork**: Clone your fork to your local machine. -3. **Create a New Branch**: For each new feature or fix, create a separate branch. -4. **Make Your Changes**: Implement your changes or fixes in the branch, adhering to the coding standards and guidelines of the project. -5. **Test Your Changes**: Ensure your changes don't break any existing functionality. -6. **Commit Your Changes**: Commit your changes with a clear and descriptive message. -7. **Push to Your Fork**: Push your changes to your fork on GitHub. -8. **Submit a Pull Request**: Open a pull request from your fork to the main repository. Fill in the pull request template with all relevant information. -9. **Review and Merge**: Your pull request will be reviewed by the maintainers and, if deemed appropriate, merged into the project. +1. Create an issue (unless trivial documentation). +2. Create a branch from the appropriate base. +3. Make changes aligned with ADR contracts. +4. Run tests locally. +5. Commit with issue-closing reference. +6. Open a PR to the correct target branch. + +### Commit message conventions + +Examples: + +- `Fixes #123: Add HelpInfo.xml schema validation` +- `Closes #456 (ADR-007): Deterministic MAML syntax ordering` -## Coding Standards and Guidelines +--- -- Follow the coding style and best practices as much as possible. -- Include comments in your code where necessary. -- Update the documentation to reflect your changes. +## Required Checks + +Pull requests must pass required CI checks before merging. + +At minimum: + +- Build +- Tests +- Validation (as implemented) + +--- + +## Release Process + +Releases are milestone-driven. + +1. Merge milestone branch into `main` +2. Close milestone +3. Release workflow runs +4. Tag is created +5. GitHub Release is generated +6. Docs PR workflow runs +7. Notifications are sent + +Publishing to the PowerShell Gallery occurs via the release pipeline once module packaging is implemented. + +--- + +## Coding Standards + +- Keep behavior deterministic +- Do not introduce new output shapes without ADR updates +- Prefer small composable changes +- Avoid scope expansion beyond help generation + +--- ## Community Guidelines -We expect all contributors to be respectful and constructive in their communication. Harassment, trolling, and abuse are strictly prohibited. +Be respectful and constructive. + +--- -## Feedback and Questions +## Questions -If you have any questions or feedback about contributing, open an issue for discussion. +If unsure whether a change fits scope, open an issue labeled `question` and reference the relevant ADR(s). -Thank you for your contributions, and we look forward to your participation in making [Your Project Name] better! From 6a7e2be567b1f0dcc55c4b3a975c9a7dd21332ea Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:53:38 -0600 Subject: [PATCH 09/13] Fixes #4: Update root README for HelpGenerator scope and links --- HelpGenerator.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 HelpGenerator.md diff --git a/HelpGenerator.md b/HelpGenerator.md new file mode 100644 index 0000000..0d966ec --- /dev/null +++ b/HelpGenerator.md @@ -0,0 +1,73 @@ +# HelpGenerator + +HelpGenerator is a focused tool suite for generating and validating PowerShell help artifacts **quickly and deterministically**. + +It is designed to make it easy for developers to produce clean, readable help documentation from: + +- Script-based comment help (functions and modules) +- Compiled C# cmdlets (reflection + XML documentation) +- Existing help artifacts (MAML + HelpInfo.xml) + +It generates: + +- **MAML** external help (command help XML) +- **HelpInfo.xml** and structure required for updatable external help (CAB packaging support) +- **Markdown** documentation (command/module docs derived from the normalized help model) +- Deterministic placeholder scaffolding when help is missing + +## Scope + +This project has a narrow scope by design: + +- Consume: comment-based help, compiled cmdlet metadata + XML docs, MAML, HelpInfo.xml +- Produce: Markdown docs, MAML, HelpInfo.xml, and updatable help packaging structure + +If it’s not part of generating or validating PowerShell help artifacts, it is out of scope. + +## Non-goals + +HelpGenerator is **not**: + +- A static site generator +- A documentation hosting platform +- A prose rewriter or “smart” help authoring tool +- A PlatyPS extension or wrapper + +## Quickstart + +See: [`docs/usage/quickstart.md`](docs/usage/quickstart.md) + +## Architecture and Governance + +This repository is governed by Architecture Decision Records (ADRs). +ADRs define scope, output contracts, validation rules, and repository governance. + +- ADR index: [`docs/adr/README.md`](docs/adr/README.md) + +If implementation conflicts with an ADR: + +- the implementation changes, or +- the ADR is formally updated first. + +Silent drift is not allowed. + +## Development workflow + +Work is milestone-driven: + +- Milestones map to GitHub Projects/boards +- Issues are tied to milestones and ADR labels +- Milestone branches are used for development +- Closing a milestone triggers a release workflow (with guardrails) + +See: [`CONTRIBUTING.md`](CONTRIBUTING.md) + +## Distribution + +HelpGenerator will be published to the **PowerShell Gallery** via the release pipeline once module packaging is implemented. + +Repository: + +## License + +See: [`LICENSE`](LICENSE) From fbbf33eac1da74e74731e4b0326e7b888b5954fa Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:54:04 -0600 Subject: [PATCH 10/13] Fixes #3: Add quickstart documentation --- docs/governance/branch-protection.md | 92 +++++++++++ docs/usage/quickstart.md | 221 +++++++++++++++++++++++++++ 2 files changed, 313 insertions(+) create mode 100644 docs/governance/branch-protection.md create mode 100644 docs/usage/quickstart.md diff --git a/docs/governance/branch-protection.md b/docs/governance/branch-protection.md new file mode 100644 index 0000000..a7c1aa8 --- /dev/null +++ b/docs/governance/branch-protection.md @@ -0,0 +1,92 @@ +# Branch Protection & Governance Policy + +## Protected Branch: `main` + +The `main` branch represents the releasable state of HelpGenerator. + +Direct pushes to `main` are prohibited. + +All changes must: + +1. Be associated with a GitHub issue +2. Align with one or more ADRs +3. Be submitted via pull request +4. Pass required status checks +5. Receive Code Owner review + +### Required Checks + +At minimum, the following must pass before merge: + +* Merge Test Workflow (build + test) + +Additional checks may be added as the project evolves. + +### Code Owner Review + +The repository uses a CODEOWNERS file to enforce ownership boundaries. Pull requests modifying owned paths require explicit review before merge. + +This enforces governance and prevents architectural drift. + +### Milestone Branching Model + +Development occurs on milestone branches: + +```bash +milestone/ +``` + +Example: + +```bash +milestone/0.0.0 +``` + +Milestone branches may receive multiple PRs. + +When a milestone is complete: + +1. Merge milestone branch into `main` +2. Close the milestone +3. Closing the milestone triggers the release workflow + +### Release Guardrail + +The release workflow validates that: + +* The milestone title matches the project version in `Directory.Build.props` + +If they do not match, the release fails. + +This prevents accidental releases. + +### Hotfix Model + +Hotfixes branch from `main`: + +```bash +hotfix/ +``` + +After fix: + +* PR into `main` +* Tag new patch version +* Backport fix into active milestone branch if necessary + +--- + +## Why this matters (and why you're doing the right thing) + +You’re building: + +* Deterministic outputs +* Contract-driven architecture (ADRs) +* Structured milestone releases +* Automated release notes +* Post-release documentation PRs + +Branch protection is the enforcement layer that keeps those promises intact. + +Without it, all of the above is optional. +With it, the structure becomes durable. diff --git a/docs/usage/quickstart.md b/docs/usage/quickstart.md new file mode 100644 index 0000000..f889936 --- /dev/null +++ b/docs/usage/quickstart.md @@ -0,0 +1,221 @@ +# Quickstart + +This guide demonstrates the primary workflows supported by the PowerShell Help Generator suite. + +The goal: generate clean, structured help artifacts quickly and deterministically. + +--- + +## 1. From Script Module with Comment-Based Help + +### Input + +```BASH + +MyModule.psm1 +MyModule.psd1 + +``` + +Functions include properly written comment-based help. + +### Generate MAML + Markdown + HelpInfo.xml + +```powershell +Export-HelpPackage ` + -ModulePath ./MyModule.psm1 ` + -ManifestPath ./MyModule.psd1 ` + -OutputPath ./out ` + -GenerateMarkdown ` + -GenerateMaml ` + -GenerateHelpInfo +``` + +### Output + +```BASH +/out + /help + /en-US + MyModule-Help.xml + /docs + /module + module.md + helpinfo.md + /commands + Get-Thing.md + Set-Thing.md + /updatable-help + HelpInfo.xml +``` + +All outputs follow ADR-004, ADR-007, ADR-010, and ADR-011 contracts. + +--- + +## 2. From Script Module with Missing Help + +If functions have no comment-based help: + +```powershell +Initialize-CommentHelp -ModulePath ./MyModule.psm1 +``` + +This inserts deterministic scaffold blocks: + +```BASH +.SYNOPSIS +TODO: Add synopsis. +``` + +Then run: + +```powershell +Export-HelpPackage -ModulePath ./MyModule.psm1 -OutputPath ./out +``` + +Warnings will be emitted for placeholder content (ADR-009). + +--- + +## 3. From Compiled C# Cmdlet Module + +### Requirements + +The project must enable XML documentation: + +```xml +true +``` + +### Input + +```BASH +MyModule.dll +MyModule.xml +MyModule.psd1 (optional but recommended) +``` + +### Generate Help + +```powershell +Export-HelpPackage ` + -AssemblyPath ./MyModule.dll ` + -XmlDocPath ./MyModule.xml ` + -OutputPath ./out ` + -GenerateMarkdown ` + -GenerateMaml ` + -GenerateHelpInfo +``` + +Reflection provides structure. +XML docs provide prose. +Outputs follow the same contracts as script modules (ADR-006). + +--- + +## 4. From Existing MAML + HelpInfo.xml + +```powershell +Convert-HelpArtifactsToMarkdown ` + -HelpPath ./help/en-US/MyModule-Help.xml ` + -HelpInfoPath ./HelpInfo.xml ` + -OutputPath ./docs +``` + +Generates: + +```bash +/docs + /commands + /module +``` + +No rewriting occurs. Structure is preserved. + +--- + +## 5. Generate Updatable Help Package + +```powershell +Export-HelpPackage ` + -ModulePath ./MyModule.psm1 ` + -Package ` + -OutputPath ./release +``` + +Produces: + +```bash +/release + HelpInfo.xml + /en-US + MyModule_1.0.0.0_en-US.cab +``` + +CAB naming and layout follow ADR-010. + +--- + +## 6. Validate Help Artifacts + +```powershell +Test-HelpPackage -Path ./out +``` + +Validation includes: + +* Structural validation (ADR-009) +* Schema validation +* Semantic checks +* Packaging validation (if applicable) + +Errors stop generation. +Warnings do not (unless `-TreatWarningsAsErrors` is specified). + +--- + +## 7. Strict Mode (CI-Friendly) + +```powershell +Export-HelpPackage -ModulePath ./MyModule.psm1 -Strict +``` + +Strict mode may: + +* Require examples +* Treat missing descriptions as errors +* Enforce verb rules + +Designed for release pipelines. + +--- + +## Mental Model + +Everything flows through: + +```bash +Input (Script | Assembly | MAML) + ↓ +NormalizedHelpModel + ↓ +Generators + ↓ +MAML | Markdown | HelpInfo.xml | CAB +``` + +No shortcuts. No hidden logic. Deterministic output. + +--- + +## What This Tool Does NOT Do + +* Does not publish help. +* Does not host help. +* Does not generate websites. +* Does not rewrite prose. +* Does not extend PlatyPS. +* Does not infer undocumented behavior. + +If it’s not about generating or validating PowerShell help artifacts, it’s out of scope. From 06a8ed48441879502a9964e708713623615e5637 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 13:54:31 -0600 Subject: [PATCH 11/13] Fixes #1: Establish repo skeleton and solution scaffolding --- .../HelpGenerator.Core.csproj | 9 ++++ .../HelpGenerator.Powershell.csproj | 9 ++++ src/HelpGenerator.sln | 48 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 src/HelpGenerator.Core/HelpGenerator.Core.csproj create mode 100644 src/HelpGenerator.Powershell/HelpGenerator.Powershell.csproj create mode 100644 src/HelpGenerator.sln diff --git a/src/HelpGenerator.Core/HelpGenerator.Core.csproj b/src/HelpGenerator.Core/HelpGenerator.Core.csproj new file mode 100644 index 0000000..125f4c9 --- /dev/null +++ b/src/HelpGenerator.Core/HelpGenerator.Core.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + enable + enable + + + diff --git a/src/HelpGenerator.Powershell/HelpGenerator.Powershell.csproj b/src/HelpGenerator.Powershell/HelpGenerator.Powershell.csproj new file mode 100644 index 0000000..125f4c9 --- /dev/null +++ b/src/HelpGenerator.Powershell/HelpGenerator.Powershell.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + enable + enable + + + diff --git a/src/HelpGenerator.sln b/src/HelpGenerator.sln new file mode 100644 index 0000000..6ce4384 --- /dev/null +++ b/src/HelpGenerator.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelpGenerator.Core", "HelpGenerator.Core\HelpGenerator.Core.csproj", "{43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelpGenerator.Powershell", "HelpGenerator.Powershell\HelpGenerator.Powershell.csproj", "{152D5266-0518-4BEC-AC25-2F8FD5384A3A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|x64.ActiveCfg = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|x64.Build.0 = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|x86.ActiveCfg = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Debug|x86.Build.0 = Debug|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|Any CPU.Build.0 = Release|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|x64.ActiveCfg = Release|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|x64.Build.0 = Release|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|x86.ActiveCfg = Release|Any CPU + {43FE7CE4-68EA-4C4C-832F-BE44070FDCC7}.Release|x86.Build.0 = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|x64.ActiveCfg = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|x64.Build.0 = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|x86.ActiveCfg = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Debug|x86.Build.0 = Debug|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|Any CPU.Build.0 = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|x64.ActiveCfg = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|x64.Build.0 = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|x86.ActiveCfg = Release|Any CPU + {152D5266-0518-4BEC-AC25-2F8FD5384A3A}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal From e1291361e74063eccb852764dd8e25386cf994d0 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 14:09:25 -0600 Subject: [PATCH 12/13] Fixes #11: Add Directory.Build.props for versioning and pipelines --- Directory.Build.props | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Directory.Build.props diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..b051764 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,33 @@ + + + + + mod-posh + Jeffrey Patton + https://github.com/mod-posh/HelpGenerator + git + + + 0.0.0 + true + + + GPL-3.0-only + + + true + true + snupkg + true + + + enable + enable + AnyCPU + + + + + + + From 4e0ae20abe987c26bd18319809f29f0c9aeb4a15 Mon Sep 17 00:00:00 2001 From: Jeffrey Patton Date: Fri, 20 Feb 2026 14:14:29 -0600 Subject: [PATCH 13/13] =?UTF-8?q?Fixes=20#1=20=E2=80=94=20Repository=20ske?= =?UTF-8?q?leton=20+=20solution=20scaffolding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nuget.config | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/nuget.config b/nuget.config index 37e2751..0cde4bb 100644 --- a/nuget.config +++ b/nuget.config @@ -1,14 +1,12 @@ - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + +