Skip to content

Release v2.14.0. Doc Stack Migration: MkDocs Material to Astro Starlight

Released: 2026-05-10 Type: Doc-stack migration release (minor) Skill count: 40 (unchanged from v2.13.x) Key theme: MkDocs Material to Astro Starlight migration


TL;DR

v2.14.0 is the doc-stack migration release. The 40-skill catalog is unchanged from v2.13.x, so day-to-day usage of /prd, /hypothesis, /user-stories, and the rest of the catalog is identical. What changed is the documentation site itself: MkDocs Material is retired; Astro Starlight ships in its place. The user-visible site at https://product-on-purpose.github.io/pm-skills/ continues to serve the same content under a modern static-site stack.

  • For readers, the docs site renders faster, has client-side Pagefind search, native dark-mode auto-toggle, and inline-SVG icon rendering. Same URL, same content, better performance under the hood.
  • For contributors and forkers, the build moves from mkdocs build --strict (Python pip toolchain) to npm run build (Node 22.x toolchain). All editing flows still work against the in-place docs/ source tree; the new build infrastructure is invisible to anyone editing markdown. Validator inventory adjusts net -1 (24 to 23) after check-nav-completeness retirement (Starlight autogenerate solves the orphan class structurally).
  • For inbound-link consumers, all 12 redirect entries from mkdocs.yml redirect_maps are preserved with proper /pm-skills/ base path handling. Old Material-era URLs redirect cleanly to current pm-skills pages instead of bouncing to a generic GitHub Pages “Site not found”.

If you use pm-skills as a Claude Code plugin, via the sync helper, or via npx skills add, the upgrade requires no action: the catalog is unchanged. The doc-stack migration is invisible to source-skill consumers.


What changed

graph TD
    A[v2.13.1 tagged]
    B[2026-05-06 spike: Astro Starlight GO-WITH-CAVEATS]
    C[Phase 1 Foundation: spec, lint, YAML parse-validity]
    D[Phase 2 Parity: W3.5 frontmatter sweep, W4 sidebar IA, W5 CSS port, W5.5 Starlight-native admonitions, W6 mermaid, W7 samples mount, W8 generator regen, W9 redirects]
    E[Phase 3 Cutover: W10 CI migration, W11 Pages deploy via Actions, post-cutover icon-leakage fix]
    F[Phase 4 Material retirement: W12 mkdocs.yml + deploy-docs.yml + 4 validator decoupling]
    G[W13 final validation: B1 perf benchmark + auto-gates, B2 visual smoke, B2.5 routing fixes, B3 Codex PR.2, B3.5 P1+P3 fixes, B4 release artifacts]
    H[v2.14.0 tagged]

    A --> B --> C --> D --> E --> F --> G --> H

    style A fill:#c8e6c9
    style B fill:#fff4e1
    style G fill:#c8e6c9
    style H fill:#81c784

Doc stack: Astro Starlight replaces MkDocs Material

  • astro ~5.13.0 + @astrojs/starlight ~0.34.0 as the core stack. Pin policy documented in docs/internal/dependency-policy.md with the static-site CVE exemption (5 advisories on astro ~5.13.0 covering SSR / server islands / Cloudflare adapter features that pm-skills does not use).
  • astro-mermaid ~2.0.1 for client-side Mermaid rendering. Code-splits the mermaid bundle (601 kB) and dynamically imports only on pages with <pre class="mermaid"> blocks. autoTheme: true integrates with Starlight’s light/dark mode toggle. 31 mermaid blocks shipped across 31 pages.
  • sharp ^0.34.5 explicit pin for Astro’s image-optimization transitive (cross-platform binary parity).
  • docs/ mounted in-place via custom glob loader in src/content.config.ts (D2 Option B). Contributors keep editing the same docs/ files; no copy step. internal/, templates/, workflows/README.md, and reference/README.md are excluded from the build.
  • 115 library samples mounted under /samples/ via the same glob loader (W7). 11 historical legacy/orbit samples are excluded from the docs site (Path B); they remain in the library/ source for historical record.
  • 12 redirect entries ported from mkdocs.yml redirect_maps to astro.config.mjs redirects: config. All destinations include the /pm-skills/ base path so meta-refresh navigates to working pm-skills pages, not the bare GitHub Pages domain.

CI and deploy

  • .github/workflows/validation.yml runs on Node 22.x with npm ci + 23 validators on Ubuntu + Windows + npm run build smoke test.
  • .github/workflows/deploy-pages.yml (new) deploys via GitHub Actions Pages source. Composable steps (checkout + setup-node + npm ci + npm run build + upload-pages-artifact + deploy-pages) preserve the Phase 2 post-build .md link sweep. Push trigger on main + workflow_dispatch.
  • .github/workflows/deploy-docs.yml (mkdocs gh-deploy) and .github/workflows/validate-docs.yml (mkdocs build —strict) retired.
  • GitHub Pages source flipped from “Deploy from a branch (gh-pages)” to “GitHub Actions” via repo Settings during W11 cutover. The dormant gh-pages branch remains as an emergency rollback target (frozen pre-cutover state).

Generator output reframe

3 Python generators rewritten in W5.5 to emit Starlight-native syntax instead of Material/pymdownx admonitions:

  • !!! warning "Generated file" to :::caution[Generated file] (Starlight aside)
  • !!! info "Quick facts" to :::note[Quick facts]
  • ??? example "..." to MDX <details><summary>...</summary>
  • { .md-button } line removed (Material attr_list pattern; Starlight does not need it)

Affected: scripts/generate-skill-pages.py (5 sites), scripts/generate-workflow-pages.py (2 sites), scripts/generate-showcase.py (4 sites). 38 doc pages regenerated. Source files in skills/, commands/, library/, and plugin manifests are untouched throughout.

Routing fixes (W13 B2.5, late-cycle catch from visual smoke)

Browser visual smoke test on production (W13 B2) surfaced 3 routing defects that local validators had missed:

  • /reference/ returned 404. Cause: docs/reference/README.md mapped to /reference/readme/ via Starlight’s README slug rule, not /reference/. Fix: workflows-style pattern. README.md kept as the GitHub-directory landing page (short pointer). New docs/reference/index.md is the Astro source-of-truth at /reference/. README.md added to the glob exclusions.
  • /samples/ returned 404. Cause: no source docs/samples/index.md. Fix: authored docs/samples/index.md with corpus overview (115 samples, 40 skills, 3 threads). Samples sidebar in astro.config.mjs switched to hybrid items (slug ref + Library autogen).
  • Redirect destinations landed at “Site not found · GitHub Pages”. Cause: redirect destinations used plain paths without the /pm-skills/ base. Fix: prepended /pm-skills/ to all 12 destinations in astro.config.mjs.

The B2.5 catch demonstrates the value of the visual smoke test layer: mechanical CI passes did not surface the section-root 404s or the redirect base-path bug because both are inherent to client-rendered URLs (the build artifacts technically existed; only browser-following revealed the failure).


Infrastructure / process

  • Phase 0 Adversarial Review Loop applied via codex:rescue skill against the release-state at HEAD da11498 (post-B2.5). 0 P0, 3 P1, 4 P2, 2 P3 findings. P1.2 (Astro 5.13.x CVE exemption documentation) and P3.1 (stale 26 legacy/orbit comment) addressed in B3.5; P1.1 partial (CI step labels relabeled to advisory; full true-enforcement deferred to v2.14.x cleanup); P1.3 release artifacts addressed in B4. P2 findings deferred to v2.14.x.
  • B2.5 routing fix re-decided the 2026-05-06 redirect base-path deferral. The original maintainer call (“don’t care that much about breaking links”) was made on the framing “wrong URL”. Live-impact evidence revealed “Site not found · GitHub Pages” with no recovery, qualitatively worse than the original framing assumed. Re-deciding on actual evidence improved the cost-benefit; 3-minute fix preserved the migration-headline UX.
  • Spike methodology repeated. v2.14 cycle started with a 60-min Astro Starlight spike (2026-05-06) which returned GO-WITH-CAVEATS (5 bounded caveats; all closed during execution). This is the second consecutive cycle (after v2.13’s Zensical NO-GO spike) where a time-boxed compatibility spike preceded the major decision.
  • PowerShell parity gap discovered late. During W13 B3.5, local --strict runs of check-internal-link-validity revealed the bash version misses 7 broken links in docs/skills/foundation/foundation-meeting-* generator output that the pwsh version catches. Promoting both to --strict would create cross-OS asymmetric CI failures. Both relabeled to advisory; v2.14.x will fix the bash parity bug, fix the 7 broken links, then promote.

Why this matters

For users, v2.14.0 is the release that future-proofs the docs site. MkDocs Material is healthy as of 2026-05; Astro Starlight is on a faster modernization path with native dark mode, Pagefind search, MDX components, and inline-SVG icons. The migration positions pm-skills’ docs to absorb the next several years of static-site evolution without further stack changes. Same URL, same content, better foundation.

For contributors and forkers, the build pipeline switches from Python pip (mkdocs + theme + plugins) to Node 22.x (Astro + Starlight + a single mermaid plugin). The npm-based build is faster cold (warm builds particularly competitive), and the source-of-truth boundary is cleaner: docs/ is mounted in place, no synthetic docs/ copy step. The generator output reframe (Starlight asides instead of pymdownx admonitions) is a one-time cost; future skill additions inherit the simpler shape.

For maintainers of similar repos, the 4-phase / 13-workstream cycle plan plus the spike-then-execute pattern is reproducible. The Phase 0 Adversarial Review Loop via codex:rescue worked end-to-end against a release-state without needing an open PR; this is the first cycle where Codex review ran against trunk. The migration plan at docs/internal/release-plans/v2.14.0/plan_v2.14_starlight-migration.md documents the full decision lineage (DM-1 through DM-4 architectural decisions; Q1 through Q5 spec decisions; W1 through W13 status blocks; B1 through B4 W13 sub-batches).


Validation: Phase 0 Adversarial Review Loop

RoundLayerFindingsOutcome
Spike (2026-05-06)Pre-cycleGO-WITH-CAVEATS; 5 bounded caveatsAll 5 closed during execution
PR.1 (per-strand)Per-workstreamPer-workstream Codex tasks landed alongside W2-W12 closuresClosed at workstream level
PR.2 (release-state)Release-state0 P0 + 3 P1 + 4 P2 + 2 P3P1.2 + P3.1 resolved B3.5; P1.1 partial (relabeled to advisory; full enforcement deferred to v2.14.x); P1.3 resolved B4; P2 deferred to v2.14.x
W13 visual smokeBrowser3 routing defects (F1 /reference/ 404, F2 /samples/ 404, F3 redirect base-path)All 3 resolved B2.5
W13 mechanical CIMechanical23 validators on Ubuntu + Windows green on da11498 (run 25631391363) and on B3.5 pushPASS

Counts at v2.14.0

Snapshot at tag time (5718440, 2026-05-10). Post-tag cleanup (FU1-FU8 + M1-M3 + V1-V11 batches; ~20 commits) is shipped to main but not part of the v2.14.0 tag. See the CHANGELOG [Unreleased] section for post-tag drift from these numbers (added pages, promoted validators, etc.).

SurfaceCountNote
Skills40unchanged from v2.13.x (26 phase + 8 foundation + 6 utility)
Workflows9unchanged
Slash commands4740 skill + 7 workflow
Library samples115mounted under /samples/ via W7; 11 legacy/orbit excluded (9 + 2); post-tag V11 swept en-dashes in all 45 affected sample files
Validators (total) at tag23net -1 from v2.13.x (24 to 23); check-nav-completeness retired (Starlight autogenerate solves orphan class structurally). Post-tag: 24 (+1 for new check-no-body-h1 enforcing validator added in post-V15 deferral closure C)
Validators (enforcing at tag)11structurally enforcing CI steps; 2 of these ran in advisory mode at tag pending bash/pwsh parity fix. Post-tag: 14 enforcing (+1 FU6 check-internal-link-validity promoted; +1 V5 validate-docs-frontmatter promoted; +1 new check-no-body-h1 added enforcing).
Validators (advisory at tag)12post-tag: 10 (2 promoted; see above)
Pages built at tag239124 docs + 115 samples. Post-tag: 254 pages (added 7 README stubs via FU7, Mermaid style guide MD+HTML via FU8, samples/index.md + reference/index.md via B2.5, etc.)
Redirect entries preserved12all destinations include /pm-skills/ base
Mermaid blocks across pages31rendered client-side via astro-mermaid
pm-skills-mcp tools (frozen at v2.9.2 build)59maintenance line; v2.14.0 doc-stack migration does not affect MCP. Post-tag V9 updated pm-skills-mcp/pm-skills-source.json metadata to v2.14.0 + maintenance: true flag

What’s deferred to v2.14.x (tag-time deferral list with post-tag dispositions)

This table reflects the deferral list as of the v2.14.0 tag (2026-05-10, HEAD 5718440). The Post-tag column documents what happened to each item after tag, across the v2.14.1 + v2.14.2 patch tags shipped same day.

Item (at v2.14.0 tag)Reason at tagPost-tag disposition
check-internal-link-validity bash/pwsh parity fix + 7 broken-link cleanuppwsh -Strict catches 7 broken links in foundation-meeting-* generator output (doubled-docs-prefix paths from source SKILL.md); bash —strict misses them. Adding —strict to both creates cross-OS CI asymmetry.CLOSED in v2.14.1 FU6: LC_ALL=C.UTF-8 fallback closed the parity gap (root cause was Windows Git Bash locale); generator path-rewrite in rewrite_internal_paths() fixed the 7 broken links at copy boundary; both bash + pwsh promoted to truly enforcing in CI.
check-internal-link-validity and validate-docs-frontmatter content scope expansionCurrently scan only *.md; src/content.config.ts also includes .mdx and library/skill-output-samples/.Partially CLOSED: v2.14.1 V6 added .mdx to check-internal-link-validity; v2.14.2 added .mdx to validate-docs-frontmatter. Library samples (library/skill-output-samples/) scope expansion remains deferred to v2.15+ due to different path structure.
verify-edit-links.mjs minimum-count assertionCurrently passes on 0 occurrences; should fail if edit-link count drops below an expected threshold.CLOSED in v2.14.1 V3: MIN_EDIT_LINKS env var added (default 100); silent regression where edit-link emission breaks now caught.
README stub coverage across docs sectionsreference/ and workflows/ have both README.md (GitHub auto-render) and index.md (Astro). Other docs sections have only index.md.CLOSED in v2.14.1 FU7: 7 README stubs added across docs/{skills,guides,concepts,contributing,getting-started,showcase,releases}/ with !docs/**/README.md glob exclusion.
Tags-as-featuredocs/tags.md is draft: true and removed from sidebar (Material tags plugin had no Starlight equivalent at migration time).STILL DEFERRED to v2.15+: re-evaluate when a Starlight tags plugin emerges or when a custom remark plugin is in scope.
URL slug shape (preserves casing and dots, e.g. /releases/Release_v2.13.0/)Functional but non-conventional.STILL DEFERRED to v2.15+: slug normalization with redirect map for in-the-wild URLs.
Architectural workaround documentation in CONTRIBUTING.mdThree workarounds (autogenerate prefix, post-build link sweep, EXCLUDE_PATHS arrays) are well-commented inline; v2.14.x adds a maintainer note in CONTRIBUTING.md.CLOSED in v2.14.1 V2 + post-V15 deferral closure A: CONTRIBUTING.md “Maintainer notes: architectural workarounds” section now documents 6 workarounds (added: generator path-rewrite, LC_ALL fallback, Starlight title-vs-body-H1 convention).
Node 20 deprecation in GitHub Actionsactions/checkout@v4, actions/setup-node@v4, actions/upload-artifact@v4 use Node 20 internally. GitHub forces Node 24 starting 2026-06-02.CLOSED in v2.14.1 FU4: 9 workflow files bumped to @v5 for checkout, setup-node, upload-pages-artifact, deploy-pages.
Astro 6 + Node 22.12+ upgradeDeferred to v2.15+ per Decision 11 in the v2.14 cycle plan.STILL DEFERRED to v2.15+: reserved as the v2.15.0 cycle theme; static-site CVE exemption table in docs/internal/dependency-policy.md becomes mostly moot at that cycle.

Net v2.14.x backlog disposition: 6 of 9 closed in v2.14.1 + v2.14.2 (full bash/pwsh parity, .mdx scope expansion across two validators, edit-links min-count, README stub coverage, workaround docs, Node 20 actions bump). 3 remain deferred to v2.15+: tags-as-feature, URL slug normalization, Astro 6 + Node 22.12+ upgrade. Plus additional v2.15+ items surfaced post-tag (JS theme-listener for dark-mode Mermaid; library samples scope in link validator; sync-agents-md.yml full rewrite; check-version-references —strict promotion; etc.).