# Astro Starlight Compatibility Spike Report

**Date:** 2026-05-06
**Executor:** Claude (Opus 4.7, Explanatory style, xhigh effort)
**Time spent:** ~50 minutes execution + ~15 minutes report
**Astro version (tested):** 5.13.11 (pinned to ~5.13.0)
**Starlight version (tested):** 0.34.8 (pinned to ~0.34.0)
**astro-mermaid version:** 2.0.1
**Material version (baseline):** Material for MkDocs 9.7.6 (mkdocs.yml current)
**Spike POC location:** `_spike/starlight-poc/` (gitignored; deleted in W1 of the migration plan)
**Library samples count clarification:** `library/skill-output-samples/` contains ~132 markdown files total of which 100 are samples-with-frontmatter (the rest are READMEs / SAMPLE_CREATION.md / etc.). The spike report's references to "132 sample files" mean the file count to mount; the 100 figure is what `spec_frontmatter-correction.md` operates on (frontmatter-bearing samples that need byte-0 correction).
**Plan:** [`plan_v2.14_starlight-spike.md`](./plan_v2.14_starlight-spike.md)

---

## Outcome

**Decision: GO-WITH-CAVEATS pending pre-ship validation gates**

Starlight built the pm-skills documentation successfully with all three v2.13 BLOCKERs cleared. The build produces 123 pages in 12-21 seconds depending on integrations, with redirects, excludes, generator output, search indexing, sidebar rendering, base-path routing, and mermaid diagrams all working. The caveats are bounded remediation tasks (revised estimate: 30-40 hours including risk reserve; see Estimated migration effort table), not architectural blockers. The migration is recommended for v2.14.0 migration execution, conditioned on the migration validation gates listed below clearing before ship.

The key signal: the cycle-defining v2.13 disqualifiers (broken redirects, leaked excludes, parser-warning storm) all resolve cleanly under Starlight. Where Material gives `--strict` 13 broken-link warnings and Zensical gave 2,940 false-positive parser warnings, Starlight gave 0 content/parser warnings (one Vite chunk-size warning for the Mermaid bundle catalogued separately as a performance item per D4).

### Performance NO-GO trigger: explicit maintainer waiver (D1)

The published spike plan rubric (Section 3.3) triggers NO-GO at "cold build regresses ≥2x against Material with no clear path to remediation." Recomputed cold build on tool-reported times: 2.04x without Mermaid, 3.12x with Mermaid. By strict reading of the published rubric, the verdict should be NO-GO.

**Maintainer decision recorded 2026-05-06** (full Decision Brief in [`plan_v2.14.0.md`](./plan_v2.14.0.md) Decisions section): waive the trigger; ship without a hard remediation gate; monitor cold-build performance in real use and revisit only if it causes actual problems for contributors or CI. This is a deliberate trade of audit purity for shipping momentum, appropriate for a doc-stack migration where users are not pages-per-second sensitive. The rubric-vs-decision divergence is recorded explicitly in the audit trail rather than glossed over.

### Pre-ship validation gates (must clear before v2.14 ships)

These are GO criteria from the spike plan that the spike did NOT exercise within the time-box. They become acceptance gates for the migration:

1. **Production content-source strategy verified** per D2 (in-place mount via custom `docsLoader` pattern). Contributors edit `docs/` directly; edit links resolve to real source files; production build asserts zero `internal/` paths in `dist/`.
2. **Library samples render correctly** when mounted as a Starlight content collection. The 132 sample files were not exercised in the spike; sample-matrix smoke test required.
3. **Custom CSS port complete.** All Material-targeting selectors in `docs/stylesheets/extra.css` either ported to Starlight equivalents or deliberately retired.
4. **Sidebar IA hybrid implemented** per D3 (manual top-level ordering + labels, autogenerate within sections).
5. **GitHub Pages deploy verified end-to-end.** Built site loads at `https://product-on-purpose.github.io/pm-skills/` with assets resolving and base path correct. Same `gh-pages` branch, new publisher (Astro GitHub Action replaces `mkdocs gh-deploy`).
6. **Edit links resolve** to actual repo source files (regression caught in spike when content was copied; mitigated by D2 Option B in-place mount).
7. **Browser visual smoke test** on key page types: home, skill page, workflow, guide with mermaid, reference, release notes.

---

## v2.13 BLOCKER retest results

### BLOCKER 1: Redirects - PASS

All 12 `mkdocs.yml redirect_maps` entries were ported to Astro `redirects:` config. 7/7 spot-checked redirect URLs generated meta-refresh HTML pages in `dist/`. Sample output (for `/pm-skills/concepts/triple-diamond/`):

```html
<!doctype html>
<title>Redirecting to: /concepts/triple-diamond-delivery-process/</title>
<meta http-equiv="refresh" content="0;url=/concepts/triple-diamond-delivery-process/">
<meta name="robots" content="noindex">
<link rel="canonical" href="https://product-on-purpose.github.io/concepts/triple-diamond-delivery-process/">
```

**Caveat (MEDIUM polish; can fix or defer):** Astro's `redirects:` config does NOT auto-prepend `base: '/pm-skills'` to destination URLs. Source paths are correctly routed as `/pm-skills/{source}/`, but destination paths in the meta-refresh and canonical link are bare (`/{destination}/`). On GitHub Pages this would 404 for users hitting the OLD Material URL paths.

**Maintainer decision 2026-05-06:** lower priority - we don't care that much about preserving old Material URL structure. Treating as MEDIUM polish item rather than pre-ship gate. The 12 redirects themselves still get ported (config is 5 minutes); the destination base-path bug ships unfixed unless cheap to address. Two fix options if applied:
1. Write each destination with the explicit base prefix in `astro.config.mjs` (12 manual edits; ~30 min).
2. Use a build-time hook to inject base into destinations.

Compared against v2.13's Zensical NO-GO (zero redirect HTML files generated for any of the 10 mapped paths under Zensical 0.0.40), Starlight's redirect routing is a structural pass.

### BLOCKER 2: Excludes - PASS (filesystem level)

The spike used filesystem-level exclusion (robocopy `/XD internal`) to keep `docs/internal/` out of the Starlight content collection. Build output `dist/` contains 0 internal/* paths.

**Production migration note:** the more authentic approach is path-based exclusion via `docsLoader({ pattern: '!internal/**' })` or by adding `draft: true` frontmatter to internal pages. I did NOT test config-based exclusion in the spike (defaulted to filesystem exclusion to save time-box budget). Both approaches are documented as supported in Starlight 0.34. Risk is low; the production migration plan should include one verification round.

Compared against v2.13's Zensical NO-GO (183 `docs/internal/*` HTML files leaked into `site/` despite `exclude_docs: internal/`), Starlight's exclusion is structurally sound.

### BLOCKER 3: Parser warnings - PASS (pristine)

Build log analysis: **0 content/parser warnings** in Starlight build. Excluded from this count: (a) pagefind notes about redirect pages having no `<html>` element (normal handling of meta-refresh pages, not a content issue), (b) one Vite chunk-size warning for the Mermaid `mermaid.core` bundle (>500 kB minified; catalogued as a performance/UX item under "What didn't work" and feeding D4 Mermaid loading strategy decision).

Compared against:
- Zensical 0.0.40 (v2.13): 2,940 false-positive parser warnings on bracketed-text patterns (`[role]`, `[yes / no]`, `cards[3]`). Made `--strict` mode unusable.
- Material `--strict` (current): 13 warnings as observed by the spike's clean-checkout build; v2.13.1 release prep observed 11 pre-existing warnings (small variance across builds; both numbers are in the same ballpark). All real broken cross-references (the F5/F7 issues catalogued in v2.13 final-sweep). Real bugs but per v2.13.1 plan deferred to v2.14 since "the Starlight migration replaces the mkdocs build entirely; fixing pre-Starlight warnings would be wasted work." Note: same broken cross-refs may surface in Starlight's `check-internal-link-validity` validator (promoted to enforcing in W10.3 of the migration plan); fix any that still apply during W13 final validation.

Starlight's MDX/Markdown parser handled all bracketed-text patterns without false positives. This is a clean win.

---

## What worked

### Build pipeline

- `astro build` exits 0 with full content collection (123 pages from 125 source files; 2 files were redundant or merged).
- Build output at `dist/` has 356 files (HTML + sitemap + assets + pagefind index + redirect pages).
- `astro preview` serves the built site at `http://localhost:4321/pm-skills/` (verified via build-only; preview not separately invoked).

### Content shape compatibility

- **All 12 `mkdocs.yml` redirects** ported to Astro `redirects:` config (with the destination-base caveat above).
- **Generator output (Pattern 5C)** schema-compatible: `generated: true` and `source: scripts/generate-skill-pages.py` frontmatter pass through Starlight's content collection schema (extended via custom Zod schema in `src/content.config.ts`) without build error. Note: the spike verified the schema accepts the fields; it did not separately verify the fields survive into HTML metadata at the rendered-page level.
- **Tag fields** (`tags: [Define, ideation]` etc.) parsed correctly by the schema.
- **Custom skill frontmatter** (`name`, `description`, `phase`, `version`, `updated`, `license`, `metadata`) all preserved via the schema extension.
- **Mermaid diagrams** render via `astro-mermaid` 2.0.1 integration. The `using-meeting-skills.md` guide's 3 mermaid blocks all transform to `<pre class="mermaid">` elements for client-side rendering. No build errors.
- **Sidebar autogenerate** populates from directory structure: Home / Getting Started / Skills / Workflows / Guides / Concepts / Showcase / Reference / Contributing / Releases all render.
- **Pagefind search** indexes 122 pages and 10,806 words. Search UI inherited from Starlight defaults.
- **Base path** correctly applied to all canonical URLs, sitemap entries, internal nav links, and asset paths (`/pm-skills/...`).

### Theme + UX

- Default Starlight theme (dark + light + auto via system preference) works out of the box.
- Right-side TOC on individual pages: present.
- Sidebar collapsible groups: present.
- Mobile responsive defaults: not separately tested (per scope guard in spike plan Section 2.3) but Starlight's defaults are 2025-modern.
- `editLink` config produces the GitHub edit-this-page link.

### Performance

**Measurement methodology note:** the spike captured two kinds of timing data, which are NOT interchangeable. Recomputing ratios on the consistent (tool-reported) baseline below per Codex S2.M1.

| Source | What it measures | Used in this report |
|---|---|---|
| Astro / mkdocs tool-reported "X built in Y seconds" | Internal build time excluding Node/npm script startup overhead | **Yes (canonical for ratios; matches CI)** |
| PowerShell `Stopwatch` around `npm run build` | Wall-clock including Node startup + npm script wrapper | Documented for transparency; not used for ratios |

Recomputed table (tool-reported times, the canonical CI-relevant measure):

| Build | Tool-reported time | vs Material | Wall-clock equivalent |
|---|---|---|---|
| Material clean rebuild (no `--strict`) | 6.00s | baseline | 6.99s |
| Starlight cold build (no Mermaid) | 12.23s | **2.04x** | 14.55s |
| Starlight cold build (with Mermaid) | 18.69s | **3.12x** | 20.76s |
| Starlight warm rebuild (no Mermaid) | (not separately captured tool-reported) | ~1.30x | 9.12s |

Cold-build performance misses the spike plan's 1.5x soft target (would have wanted 9s or under at tool-reported) AND crosses the 2x NO-GO trigger. Per D1 (full Decision Brief in cycle plan and Outcome section above), the trigger is explicitly waived by maintainer with light monitoring as the follow-up. Warm rebuild is acceptable.

Note: Material's measured 6.00s tool-reported / 6.99s wall-clock is faster than the v2.13 Zensical spike report's stated 8.16s baseline. Variance is likely environmental (plugin warm-up, fewer concurrent processes today). Both numbers are in the same ballpark.

---

## What didn't work

### Title frontmatter required on every page (MEDIUM; cross-session sync 2026-05-07: full scope is 153 files not 51)

Starlight's `docsSchema` requires `title: string` on every doc. **In `docs/` alone: 51 of 125 source files (~41%) lack `title:` frontmatter** as the spike originally found:
- 12 files have other frontmatter but no title.
- 39 files have no frontmatter at all (mostly index pages and READMEs).

**Cross-session sync 2026-05-07 - additional scope discovered:** the `discovery/spec_frontmatter-correction.md` (parallel-session work) audited the full repo and found 102 ADDITIONAL markdown files outside `docs/` with frontmatter starting at line 2 (after an HTML attribution comment) instead of byte 0:
- 100 library samples in `library/skill-output-samples/**/sample_*.md`
- 2 OKR-skill `references/EXAMPLE.md` files

These 102 files need both placement correction AND `title:` injection (per the spec's Decision Brief 2 schema enhancement). Total title scope across the migration: **153 files** (51 in docs/ + 100 library samples + 2 EXAMPLE.md). The 102-file sweep is now its own workstream (W3.5 in `plan_v2.14_starlight-migration.md`).

The spike's POC handled the 51 docs/ files via a PowerShell script (parser-aware FM boundary detection). Production migration approach for all 153:
- W3 (51 docs/ files): same script approach (~1 hour write + audit).
- W3.5 (102 library + skills files): deterministic mechanical sweep per `spec_frontmatter-correction.md` (~3-5 hours; bundles placement fix + title-injection + lint extension).

**Severity:** MEDIUM. Bounded one-shot remediation across both workstreams. Real production work but not architectural.

### Redirect destination base-path bug (MEDIUM polish; defer-OK)

Per BLOCKER 1 caveat above. Source paths route correctly with base; destination paths do not. The fix is mechanical (12 destination strings).

**Maintainer 2026-05-06:** lower priority - we don't care that much about preserving old Material URL structure. Treating as MEDIUM polish; can fix in migration if cheap, otherwise defer. The 12 redirects themselves still get ported (5-min config); the destination-base bug remains until/unless someone wants the old-URL bookmarks to land correctly.

**Severity:** MEDIUM. Polish item; not a pre-ship gate.

### Templates folder has placeholder YAML (MINOR)

`docs/templates/skill-template/SKILL.md` and `docs/templates/skill-template/references/{TEMPLATE,EXAMPLE}.md` use `<placeholder>` syntax in YAML frontmatter for fields like `metadata.category: <one of: research, problem-framing, ...>`. The `<one of: research, ...>` value contains a `:` which YAML parses as a nested mapping, triggering a parse error.

These are template files for skill authoring, not user-facing content. Material's tags plugin or nav structure presumably hid them from the rendered site (they're not in `mkdocs.yml nav`). The spike fix: remove `docs/templates/` from the Starlight content collection.

**Production fix:** add `templates/**` to the docsLoader pattern exclusion, OR move templates out of `docs/` entirely (e.g., to `templates/` at repo root). Either is trivial.

**Severity:** MINOR. One-line fix.

### Node version requirement (MINOR)

Astro 6.x (current latest) requires Node `>=22.12.0`. Local environment had Node 22.11.0, which Astro 6 hard-fails on (not just a warning). The spike pinned to Astro 5.13.x + Starlight 0.34.x to proceed; this combo accepts any Node 22.x.

**Production fix:** bump Node to 22.12+ before running Astro 6, OR stay on Astro 5.x for v2.14 and migrate to Astro 6 in v2.15. Astro 5 is current-maintained; no urgency.

**Severity:** MINOR. One Node install; or pin choice.

### Auto-applied Starlight class names differ from Material (informational)

The spike's first sidebar-presence check failed because I grepped for `starlight-sidebar` (no such class). Starlight uses generic class names: `sidebar`, `sidebar-pane`, `sidebar-content`, `right-sidebar` plus per-component Astro scoped class hashes (e.g., `astro-vrdttmbt`).

**Implication for migration:** any custom CSS in `docs/stylesheets/extra.css` that targets Material-specific class names (`md-nav`, `md-content`, `md-header`, `md-tabs`, etc.) will be no-ops in Starlight and need rewriting against Starlight's class names. The current `extra.css` is small (single file, not large) so this is bounded.

**Severity:** MEDIUM (need to port custom CSS); not BLOCKER.

### Mermaid client-side bundle size (MEDIUM, performance/UX)

`astro-mermaid` 2.0.1 by default eager-loads `mermaid.core` (601.87 kB minified per the Vite chunk-size warning in `_spike-starlight-build5-mermaid.log`) on every page that includes the integration globally. Pages without diagrams pay the bundle cost anyway.

**Maintainer decision 2026-05-06 per D4** (full Decision Brief in cycle plan): lazy-load via per-page integration if `astro-mermaid` supports it; else code-split via dynamic import; else defer to v2.15. migration verifies the lazy-load API and applies the chosen path.

**Severity:** MEDIUM. User-facing performance item; bounded fix.

---

## Cosmetic diffs (informational)

These are non-blocking visual differences worth knowing for migration sequencing:

- **Theme defaults:** Starlight's default theme (Tailwind-inspired, 2025-modern) differs from Material's Indigo/Deep-Purple palette. The migration should decide between (a) keeping Starlight defaults (likely an upgrade) or (b) reproducing the Material palette via Starlight's CSS custom properties.
- **Top header layout:** Material's `header.autohide` + tabs.sticky behavior is replaced by Starlight's fixed-header pattern. Different visual rhythm; not worse.
- **Mermaid theme:** astro-mermaid uses Mermaid's default theme; Material's pymdownx-mermaid integration may have used a different palette. Visual diff in diagram style.
- **Code block styling:** Starlight uses Expressive Code by default (richer syntax highlighting + copy button + line numbers config). Visually different from Material's pymdownx.highlight.
- **No "Edit on GitHub" pencil icon by default at the right place:** Starlight has `editLink` config which I configured; visually appears in a different spot than Material's `content.action.edit`.
- **Search UI:** Pagefind UI has different keyboard shortcuts and result styling than Material's lunr-based search.

None of these blocks migration; all are stylistic decisions for the migration team.

---

## Stakeholder impact

| Stakeholder | What changes | Severity / Action |
|---|---|---|
| **Skill consumers** (read-only docs site users) | Theme palette shifts to Starlight defaults (likely an upgrade from Material's Indigo/Deep-Purple). Search behavior shifts from Lunr to Pagefind (different keyboard shortcuts; different result ranking). Old Material URL paths may 404 if redirect destination base-path bug stays unfixed (per maintainer "don't care that much" call); new URLs work normally. | LOW for content; INFO for theme/search; LOW for old URLs. |
| **Contributors** (skill authors, doc editors) | New requirement: every doc needs `title:` frontmatter (51 of 125 files affected; one-time injection script). Edit-on-GitHub link behavior depends on D2 Option B in-place mount working in production (otherwise breaks). MDX is available but Markdown-first; existing files unchanged. Build commands change from `mkdocs serve / mkdocs build` to `npm run dev / npm run build`. | MEDIUM. Contributor guide updates required as part of migration. |
| **pm-skills-mcp users** | **Not affected.** The MCP server consumes embedded SKILL.md files, not the docs site; doc-stack choice is invisible to MCP. | NONE. |
| **Search engines / external scrapers** | URL structure for current docs unchanged (same paths under `/pm-skills/`). Old Material URLs may 404 (per maintainer "don't care" call). Canonical URL behavior verified for current pages; redirect canonical behavior follows the polish-or-defer treatment. | LOW. |

---

## Recommendation for v2.14.0

**Commit to Starlight migration in v2.14.0 (migration).** The spike's GO-WITH-CAVEATS verdict means:

- All structural compatibility cleared.
- Caveats are bounded one-shot remediations (~1-2 days total estimated).
- Production-readiness signal: Astro + Starlight built our actual content shape (130 source files including generator output, library samples NOT yet tested but expected to work) on first serious attempt with no architectural compromises.

### Estimated migration effort

Revised post-Codex review. Split into base work + validation reserve to surface contingency for untested surfaces. D1-D4 maintainer decisions (in cycle plan) reflected in task scoping and ownership.

#### Base work

| Task | Effort | Owner | Notes |
|---|---|---|---|
| Title frontmatter audit + injection script | ~1 hour | Codex | Filename-derived titles; manual quality pass on edge cases |
| Redirect destination base-path fix (12 entries) - OPTIONAL polish | ~30 min | Claude | Per maintainer "don't care that much" call; can defer if not cheap |
| Templates folder exclusion (1-line config or path move) | ~15 min | Claude | |
| Custom CSS inventory + browser screenshot pass | ~1 hour | Claude | Prerequisite before locking the port estimate (Codex S3.M3) |
| Custom CSS port (Material classes to Starlight classes) | ~4-8 hours | Claude | Locked after inventory pass |
| Library samples dedicated workstream (mount + sample-matrix smoke test) | ~4-6 hours | Claude | Promoted from "spot-verification" per Codex S3.M1 |
| Production content-source strategy implementation per D2 (in-place docsLoader pattern) | ~2-4 hours | Claude | Includes verification that pattern API works with our content shape |
| Production-mode `internal/` exclusion automated check (CI one-liner) | ~30 min | Claude | migration acceptance gate per Codex S6.M1 |
| Sidebar IA hybrid implementation per D3 | ~3-5 hours | Claude | Manual top-level ordering + labels; autogenerate within sections |
| Mermaid loading: verify lazy-load support (D4 Option B); else code-split (Option C) | ~1-2 hours | Claude | Lazy-load preferred per D4 |
| Generator updates (verify Pattern 5C `source:` continues) | ~1 hour | Codex | |
| `engines.node` field + dependency pinning policy | ~30 min | Claude | Per Codex S7.M2 |
| GitHub Pages deploy workflow update (mkdocs build to astro build) | ~1 hour | Claude | Same `gh-pages` branch; new publisher (Astro Action replaces `mkdocs gh-deploy`) |
| Edit-link resolution verification (migration acceptance gate) | ~15 min | Claude | Tied to D2 Option B mount strategy |
| Performance benchmark + light monitoring per D1 waiver | ~1 hour | Claude | No hard remediation gate; observe and revisit only if it causes problems |
| Documentation: contributor guide updates (skill authoring under Astro) | ~3 hours | Claude | |

**Base total: ~22-28 hours.**

#### Validation reserve

| Item | Reserve |
|---|---|
| Untested compatibility surfaces emerging mid-migration (sample MDX collisions; custom CSS edge cases; CI environment differences) | ~4-6 hours |
| Browser visual smoke test (human + Claude paired) on key page types | ~2 hours |
| Codex adversarial review cycles (2 rounds + resolution) | ~2-4 hours |

**Reserve total: ~8-12 hours.**

**Grand total: ~30-40 hours focused work. ~5-8 calendar days assuming context-switching.**

(Up from the original 17-22 hour estimate after risk buffer + samples workstream + content-source verification + IA decision are reflected per Codex S3.M4.)

### Decisions for the v2.14.0 master plan

> The four maintainer-signoff decisions (D1 perf waiver, D2 production content-source strategy, D3 sidebar IA, D4 Mermaid loading) are recorded in [`plan_v2.14.0.md`](./plan_v2.14.0.md) Decisions section as Decision Briefs. Decisions below are scoped to the migration plan, not maintainer signoff.

1. **Astro version pin:** start on Astro 5.x (no Node bump needed) OR bump Node to 22.12+ and use Astro 6.x. Recommend Astro 5.x for v2.14, Astro 6 in a follow-up if compelling. Add `engines.node` field per Codex S7.M2.
2. **Mermaid integration:** `astro-mermaid` confirmed. Pin to `~2.0.0` (current) for v2.14. Loading mode per D4.
3. **Search:** Starlight's built-in Pagefind. No third-party.
4. **Material plugins to retire:** `search`, `privacy`, `social`, `tags`, `redirects`, `git-revision-date-localized`, plus all of `pymdownx.*`. Replaced by Starlight built-ins + remark/rehype standards.
5. **Custom theme:** start with Starlight defaults; defer custom palette work to v2.15+ unless user feedback demands otherwise.

---

## Evidence

- **Spike POC directory:** `_spike/starlight-poc/` (gitignored; ~400 MB node_modules + ~5 MB content + ~20 MB dist)
- **Build logs (relocated to `_archive/spike-evidence/`):**
  - `_archive/spike-evidence/_spike-mkdocs-baseline.log` - Material `--strict` baseline (13 warnings = real broken xrefs)
  - `_archive/spike-evidence/_spike-mkdocs-baseline-clean.log` - Material clean baseline (6.99s wall-clock; 6.00s tool-reported)
  - `_archive/spike-evidence/_spike-starlight-build1.log` - first attempt, Astro 6 + Node 22.11 mismatch
  - `_archive/spike-evidence/_spike-starlight-build2.log` - Astro 5 baseline, title-required schema error
  - `_archive/spike-evidence/_spike-starlight-build3.log` - title-injected build, templates YAML error
  - `_archive/spike-evidence/_spike-starlight-build4.log` - templates removed, BUILD SUCCESS (12.23s tool-reported, 123 pages)
  - `_archive/spike-evidence/_spike-starlight-build5-mermaid.log` - mermaid added, BUILD SUCCESS (18.69s tool-reported)
  - npm install logs were piped via Tee but did not persist on disk (timing issue with PowerShell Tee + --silent); install exit codes were 0 in both cases (initial Astro 6 install + Astro 5 reinstall after pin)
- **Built output sample inspected:**
  - `_spike/starlight-poc/dist/skills/define/define-hypothesis/index.html` (136 KB; renders correctly)
  - `_spike/starlight-poc/dist/workflows/triple-diamond/index.html` (123 KB; H1, TOC, footer all present)
  - `_spike/starlight-poc/dist/concepts/triple-diamond/index.html` (redirect; meta-refresh works)
  - `_spike/starlight-poc/dist/guides/using-meeting-skills/index.html` (3 mermaid blocks rendered as `<pre class="mermaid">`)
- **Configuration files:**
  - `_spike/starlight-poc/astro.config.mjs` (site, base, redirects, sidebar, mermaid integration, Starlight title + social)
  - `_spike/starlight-poc/src/content.config.ts` (extended docsSchema with our custom frontmatter fields)
  - `_spike/starlight-poc/package.json` (dependencies pinned to Astro 5.13.x + Starlight 0.34.x)

Spike workspace is gitignored (entry added to `.gitignore` at session start). Safe to delete after report consumed.

---

## Open questions

1. **Auto-base-prepend for redirect destinations:** Is there an Astro 5/6 config option I missed, or is the manual prefix the right answer? Worth a 15-min investigation during migration execution.
2. **Custom CSS migration scope:** the current `extra.css` should be inventoried at migration start. If it's just a few rules, port directly; if it's heavily Material-themed, decide between full re-skin and minimal-changes-only.
3. **Library samples mount strategy:** `library/skill-output-samples/` (132 files) is outside `docs/`. Should it become a Starlight content collection (browseable) or stay as a curated reference linked from docs? Recommendation: collection, for searchability. Adds ~30 min to the migration plan.
4. **Pre-existing broken cross-references (the 13 Material `--strict` warnings):** these are real bugs catalogued in v2.13 final-sweep as F5/F7. Recommend fixing in the same v2.14 cycle as part of migration verification, not as a separate effort.
5. **Site URL + base path final form:** spike used `site: 'https://product-on-purpose.github.io'` + `base: '/pm-skills'`. Verify this matches the GitHub Pages deploy expectations before migration kickoff.
6. **Migration cycle code-review approach:** v2.13 ran the Phase 0 Adversarial Review Loop (5 Codex review rounds + 3 resolution passes). For a doc-stack migration where most defects are visual/rendering, recommend running 2 Codex review rounds + 1 human visual smoke test, not the full v2.13 loop.

---

## Comparison summary: Zensical (v2.13) vs Starlight (v2.14)

| Dimension | Zensical 0.0.40 | Astro Starlight 0.34.8 |
|---|---|---|
| **BLOCKER 1 (redirects)** | FAIL (zero redirect HTML generated) | PASS (with destination-base caveat, IMPORTANT) |
| **BLOCKER 2 (excludes)** | FAIL (183 internal files leaked) | PASS (filesystem-level verified; config-level expected to work) |
| **BLOCKER 3 (parser warnings)** | FAIL (2,940 false positives) | PASS (0 warnings) |
| **Build time (cold)** | 15.92s (1.95x Material) | 14.55-20.76s (2.08-2.97x Material) |
| **Build time (warm rebuild)** | 6.40s (faster than Material full) | 9.12s (1.30x Material) |
| **Mermaid integration** | Untested (build failed earlier) | PASS (astro-mermaid) |
| **Generator output preserved** | Untested | PASS (Pattern 5C frontmatter intact) |
| **Toolchain** | Python (mkdocs-compat) | Node only |
| **Maintenance posture** | New project (0.0.40) | Production-ready since 1.0 (Sept 2024) |
| **Verdict** | NO-GO (2 BLOCKERs) | GO-WITH-CAVEATS (no BLOCKERs; 5 bounded caveats) |

The Starlight verdict's caveats sum to ~1-2 days of remediation work; the Zensical NO-GO required upstream parser changes outside our control (no migration path within our cycle scope).

---

## Change Log

| Date | Change |
|---|---|
| 2026-05-06 | Spike executed against current `mkdocs.yml`; report authored. Verdict: GO-WITH-CAVEATS; recommend v2.14 migration. |
| 2026-05-06 | Codex adversarial review applied (9 Major / 8 Minor / 2 Notes / 0 Blockers). Verdict reframed to "GO-WITH-CAVEATS pending pre-ship validation gates." Performance NO-GO trigger explicitly waived per D1 maintainer call (no hard remediation gate; light monitoring). Redirect destination base-path bug downgraded from IMPORTANT to MEDIUM polish per maintainer "don't care that much about old Material URLs." Estimated effort revised 17-22 to 30-40 hours (base + validation reserve). New sections: Pre-ship validation gates, Stakeholder impact, Mermaid bundle size finding. Performance ratios recomputed on tool-reported baseline (2.04x cold no-Mermaid; 3.12x with Mermaid). Pattern 5C wording softened to "schema accepts" not "preserved into HTML metadata." |
| 2026-05-07 | Cross-session sync: absorbed concurrent v2.13.1 ship + `spec_frontmatter-correction.md`. Caveat 1 expanded to acknowledge full title scope (153 files: 51 docs + 100 library samples + 2 EXAMPLE.md); the 102 additional files are now W3.5 in the migration plan. Material `--strict` warnings count disambiguated (13 spike-time vs 11 v2.13.1-prep-time; same defect class; both deferred to mkdocs deletion). Library samples count clarified (~132 files in collection / 100 frontmatter-bearing). Header note added re: spike POC deletion + samples-count clarification. |
