diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d1afbba6..be1d8f5e 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -46,7 +46,7 @@ Because inline copies can drift, run the `check-content-alignment` skill after e ## Building, previewing, and verifying -The tooling for building, previewing, and verifying the site — dev server, clean build, the page-count invariant, and the lychee link check — lives in the [`build-and-verify-docs`](skills/build-and-verify-docs/SKILL.md) skill. Run that verification sequence before every commit, and don't commit if any step fails. +The tooling for building, previewing, and verifying the site lives in the [`build-and-verify-docs`](skills/build-and-verify-docs/SKILL.md) skill. Run that verification sequence before every commit, and don't commit if any step fails. Derive expected pages from the current content and configuration rather than fixed totals. Before opening or updating a PR, also make the **PR-time consistency pass** documented in that skill — a structural-drift sweep (renamed paths, stale skill/instruction references, CI claims, repository-structure trees, and copied prose alignment) that the build and link check can't catch. diff --git a/.github/instructions/astro.instructions.md b/.github/instructions/astro.instructions.md index 26e3c0a6..19502d94 100644 --- a/.github/instructions/astro.instructions.md +++ b/.github/instructions/astro.instructions.md @@ -20,4 +20,4 @@ This is a docs wrapper. Don't add interactive framework islands (Svelte, React, ## Building and verifying -After changing `astro.config.mjs` or anything under `website/src/`, build and verify the site with the [`build-and-verify-docs`](../skills/build-and-verify-docs/SKILL.md) skill. Its page-count invariant is the tripwire for unexpected routed pages: Starlight emits each of the 36 workshop routes for the root language and five configured locales, then adds the legacy redirect, for 217 built `index.html` pages excluding the 404 page. If the count changes without a corresponding route or locale change, check the locale layout under `docs/` and the underscore-directory exclude in `src/content.config.ts`. +After changing `astro.config.mjs` or anything under `website/src/`, use the [`build-and-verify-docs`](../skills/build-and-verify-docs/SKILL.md) skill. Check affected routes and translations against the current source, locale configuration, and content-loader rules. Confirm support assets remain excluded from routing; do not maintain fixed page totals in authoring guidance. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 43ed097c..50b21681 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,12 +14,12 @@ ## Verification - + -- [ ] `cd website && rm -rf dist && npm run build` succeeds (target: 36 routes × 6 locales + 1 redirect = 217 built pages excluding 404; build reports 218 HTML files including 404, or note any intentional change) -- [ ] Lychee link check passes: - `mkdir -p /tmp/lychee-root && ln -sfn $PWD/website/dist /tmp/lychee-root/copilot-workshops && lychee --offline --no-progress --root-dir /tmp/lychee-root 'website/dist/**/*.html'` -- [ ] External GitHub URLs that I changed have been clicked manually (lychee runs offline) +- [ ] Type checks and a clean site build pass. +- [ ] Affected pages and translations match their source and intended routes. +- [ ] Offline internal link checks pass. +- [ ] Changed external links have been checked separately. ## Screenshots diff --git a/.github/skills/README.md b/.github/skills/README.md index 785acb30..eb10bd7f 100644 --- a/.github/skills/README.md +++ b/.github/skills/README.md @@ -10,8 +10,8 @@ These encode conventions unique to this Astro + Starlight workshop content repo. | Skill | What it does | Use it when | |---|---|---| -| [`build-and-verify-docs`](./build-and-verify-docs/SKILL.md) | Canonical build/preview/verify process: dev server, clean build, page-count invariant, lychee link check, and the **PR-time consistency pass** for structural drift. | Building, previewing, or verifying any change under `docs/`; before every commit/PR. | -| [`check-content-alignment`](./check-content-alignment/SKILL.md) | Scans a diff (staged/unstaged or a branch range) for content changes, then finds other lessons that duplicate or parallel the changed prose — formerly-shared passages now copied across pages, and the same concept taught across the VS Code / CLI / App / Cloud harnesses — so duplicated copies don't drift out of sync. Reports candidate files and line ranges; does not edit content. | After editing lesson content under `docs/`, before committing/opening a PR, to find other pages that should change too. | +| [`build-and-verify-docs`](./build-and-verify-docs/SKILL.md) | Small Bash and PowerShell wrappers for existing type checks, build, and offline links; AI guidance for source-page, semantic, visual, and structural review. | Building, previewing, or verifying the site; before every commit/PR. | +| [`check-content-alignment`](./check-content-alignment/SKILL.md) | Uses the diff and current content tree to find inconsistent repeated passages, parallel concepts, translations, and cross-references. Reports candidates without editing content. | After lesson edits or when reviewing content drift. | | [`validate-site-playwright`](./validate-site-playwright/SKILL.md) | Optional deeper **browser** QA: drives the Playwright MCP server against a local preview to confirm pages render, catch console/hydration errors, find broken images, and confirm Starlight components mounted. | A deeper render/visual pass before a PR that changes how pages render. Complements (doesn't replace) `build-and-verify-docs`. | ## General-purpose skills diff --git a/.github/skills/build-and-verify-docs/SKILL.md b/.github/skills/build-and-verify-docs/SKILL.md index f2453bbd..22d81b16 100644 --- a/.github/skills/build-and-verify-docs/SKILL.md +++ b/.github/skills/build-and-verify-docs/SKILL.md @@ -1,115 +1,56 @@ --- name: build-and-verify-docs -description: Build, preview, and verify the Copilot Workshops Astro + Starlight workshop site before committing or opening a PR. Use whenever an author or agent is about to build the site, run a local preview/dev server, check links with lychee, confirm the page-count invariant, run the pre-commit verification sequence for any change under `docs/` (content) or `website/` (tooling), or make a PR-time consistency pass to catch structural drift (renamed paths, stale skill/instruction references, inaccurate CI claims, out-of-date structure trees). +description: Build, preview, and verify the workshop site using existing checks. Use before committing or updating a PR. Inspect affected content and translations separately rather than relying on fixed page counts. --- # Build and verify the docs site -The workshop content is plain Markdown in the repo-root `docs/` directory; the Astro + Starlight site that publishes it lives in `website/` (sourcing content via the loader's `base: '../docs'`). This skill is the single source of truth for **how to build, preview, and verify** that site. The instruction files (`.github/instructions/*`, `.github/copilot-instructions.md`) describe *what content should look like*; this skill describes *how to run the tooling*. +Lesson source lives in `docs/`; the Astro + Starlight publisher lives in `website/`. This skill owns the verification procedure. Other authoring guidance should link here instead of repeating commands. -Run every command from the **repo root** unless a step says otherwise. +## Run existing checks -## When to use - -Trigger this skill whenever you: - -- are about to build the site (`npm run build`) or start the dev server, -- need to preview content locally, -- are running the pre-commit / pre-PR verification pass on any change under `docs/` (content) or `website/` (tooling), -- want to confirm the page-count invariant or check links, -- are about to open or update a PR that touches `docs/` or `website/`. - -For an optional **deeper, browser-based** pass that confirms pages actually render (console errors, broken images, mounted components), use the [`validate-site-playwright`](../validate-site-playwright/SKILL.md) skill after the static checks here. - -## Local preview - -The Astro dev server is the primary preview surface (hot reload): +Use the wrapper for your shell, from the repository root or by absolute script path from any directory: ```bash -cd website && npm install && npm run dev +bash .github/skills/build-and-verify-docs/scripts/verify.sh ``` -Open . Lesson content lives in the repo-root `docs/` directory; the loader sources it via `base: '../docs'`, so no symlinks are required for preview. - -## Verification sequence (run before every commit) - -Run all three. Don't commit if any fails. - -### 1. Build (clean) - -```bash -cd website && rm -rf dist && npm run build +```powershell +& ./.github/skills/build-and-verify-docs/scripts/verify.ps1 ``` -### 2. Page-count invariant - -The workshop has 36 distinct route slugs. Starlight emits each route for the English root locale and the five configured localized routes, using English fallback content when a translation is unavailable. The built site therefore contains $36 \times 6 = 216$ workshop routes plus the one legacy redirect (`/shared/0-prereqs/`, authored as a full-HTML redirect page at `website/src/pages/shared/0-prereqs.astro`). The expected count is 217 `index.html` files when excluding the 404 page. Astro reports 218 HTML files because it includes the 404 page. - -```bash -# distinct route slugs in the English root locale (docs/README.md + docs//*.md) -find docs -maxdepth 2 -name '*.md' \ - ! -path 'docs/es-es/*' \ - ! -path 'docs/ja-jp/*' \ - ! -path 'docs/ko-kr/*' \ - ! -path 'docs/pt-br/*' \ - ! -path 'docs/zh-cn/*' | wc -l -# built pages (excludes the 404) -find website/dist -name index.html | grep -v 404 | wc -l -``` +Use an installed Node.js/npm version supported by `website/`, existing site dependencies, and Lychee on `PATH`. Ask before installing missing software. Run PowerShell under your normal execution policy; do not bypass it. The Bash wrapper has been run on macOS; the PowerShell wrapper has not been executed or parser-validated because PowerShell was unavailable. -`built pages` should equal `(distinct route slugs × configured locales) + 1`. If the build emits **more** pages than that without a matching route or locale change, confirm localized content is directly under `docs//` rather than an extra parent directory, then check the underscore-directory exclude in `website/src/content.config.ts`; it is still needed so support directories such as `_images/` are not routed as pages. +Both wrappers run `npm run check:all`, remove only `website/dist` (refusing a linked output directory), run `npm run build`, then run `lychee --offline --no-progress` against the built HTML. Package scripts remain the source of truth. Output is not suppressed, failures stop verification, and native command exit codes are returned. Each run creates and cleans its own temporary link root. Like the existing Pages workflow, the wrappers map `/copilot-workshops/` to the build; update that mapping alongside the workflow if the configured site base changes. -### 2b. Translations actually render (not silent English fallback) +Stop on failure and resolve it before committing. The wrappers do not install dependencies, start servers, compare source text with HTML, or validate translation quality. Offline Lychee checks internal links and images, not external destinations. -The build and the page-count above are **blind to which content actually renders** — a mis-nested or wrongly-identified locale tree still emits 217 pages served from English fallback. Assert that a known translated page carries translated text and the right `lang` attribute: +## Inspect affected content -```bash -grep -o '[^<]*' website/dist/es-es/app/2-add-star-rating/index.html # Spanish title -grep -o 'lang="[^"]*"' website/dist/es-es/app/2-add-star-rating/index.html | head -1 # lang="es-ES" -``` +Use the diff, source paths and `slug` frontmatter, `website/src/content.config.ts`, and `website/astro.config.mjs` to select and inspect affected output. Do not use a fixed page total as proof of correctness. -The Spanish title should read `Lección 2 - Ejecutar tu primera sesión de agente`, not the English string. Spot-check a second locale (e.g. `ja-jp` -> `lang="ja-JP"`). +- Confirm changed lessons appear at their intended routes with their titles, headings, prompts, and admonitions rendered correctly. +- Compare translated pages with their locale source and language; English fallback is expected only when a translation is absent. +- Check references and navigation after renames or removals, and confirm support assets are not published as lessons. +- Review semantic accuracy, teaching flow, translation quality, intentional harness differences, and whether navigation or redirects lead to the appropriate next task. -### 3. Link check (lychee, offline) +These inspections are not automated by the wrappers. Use the [browser validation skill][browser-validation] for layout, styling, client-side behavior, console errors, and visual image loading. Existing plain-div admonition styling is not fixed or certified by a successful build. Open changed external links separately and confirm their intended destinations. Report any blocked checks honestly. -The site builds with `base=/copilot-workshops/`, so internal hrefs are absolute (`/copilot-workshops/foo/`). Symlink that prefix to `website/dist` so lychee can follow internal links: +## Local preview ```bash -mkdir -p /tmp/lychee-root && ln -sfn "$PWD/website/dist" /tmp/lychee-root/copilot-workshops \ - && lychee --offline --no-progress --root-dir /tmp/lychee-root 'website/dist/**/*.html' +(cd website && npm run dev) ``` -Lychee runs offline and won't catch broken **external** GitHub URLs. When you change absolute `https://github.com/...` links, click through them manually. - -## What CI enforces vs. what is local-only - -`.github/workflows/pages.yml` runs on PRs and on push to `main`. It runs **only**: +Open the URL printed by the server, including the configured base path. Stop only the server you started when finished. -1. `npm ci` -2. `npm run build` (Astro build) — must succeed -3. lychee offline link check against `website/dist/` — must pass +## Consistency before updating a PR -After a push to `main`, `pages.yml` deploys `website/dist` to GitHub Pages. Browser validation and content-alignment analysis are separate optional/safety-net workflows, not part of the Pages build job. +- Search for references to paths, names, or conventions changed by the diff, including repository guidance and navigation. +- Use the [content alignment skill][content-alignment] for duplicated lesson passages and translations that may need matching changes. +- Keep CI descriptions aligned with `website/package.json` and `.github/workflows/pages.yml`. -## PR-time consistency pass +The Pages workflow remains unchanged: it runs type checks, the build, and offline link validation, with deployment restricted to pushes to `main`. Source-page inspection, browser validation, and content-alignment review remain separate. -The build and link check above catch *mechanical* breakage. They do **not** catch *structural drift* — prose and reference material that silently falls out of sync when files move or conventions change. Before opening or updating a PR, make a consistency pass over everything your change touched: - -- **Renamed or moved a file or folder?** Grep the whole repo for the old path and update every hit — `.md`, instruction files, skills, and the repository-structure trees in `README.md`, `docs/README.md`, `website/README.md`, `AUTHORING.md`, and `.github/copilot-instructions.md`. Example: when `images/` became `_images/`, every `../images/...` reference and every structure tree had to change. -- **Added or removed a skill, agent, instruction file, or workflow?** Grep for references to the old name and remove them. Add a new `.github/instructions/*.instructions.md` file to the **Deeper conventions** list in `AUTHORING.md`, and to the structure block in `.github/copilot-instructions.md` if it's structural. -- **Changed duplicated lesson prose?** Run the `check-content-alignment` skill to identify other inline copies that need the same update. The `.github/workflows/content-alignment.md` agentic workflow runs the same analysis on PRs as a safety net. -- **Described what CI does anywhere?** Confirm it matches `.github/workflows/pages.yml`, which runs the build and the lychee link check. -- **Changed the build or verify steps?** This skill is the single source of truth. `README.md`, `AUTHORING.md`, and `CONTRIBUTING.md` should *point here*, not re-document the commands. Keep any summary in those files consistent with this skill. -- **Repository-structure trees** in `README.md`, `docs/README.md`, `website/README.md`, `AUTHORING.md`, and `.github/copilot-instructions.md` should all reflect the real tree. If you add or rename a top-level content directory, update all of them. -- **Page-count invariant** (section 2 above) should still hold after the build. - -When in doubt, `grep -rn "" --include='*.md' .` (excluding `node_modules` and `website/dist`) is the fastest way to surface stale references. - -## Quick reference - -```bash -# from repo root -cd website && rm -rf dist && npm run build && cd .. -mkdir -p /tmp/lychee-root && ln -sfn "$PWD/website/dist" /tmp/lychee-root/copilot-workshops \ - && lychee --offline --no-progress --root-dir /tmp/lychee-root 'website/dist/**/*.html' -``` +[browser-validation]: ../validate-site-playwright/SKILL.md +[content-alignment]: ../check-content-alignment/SKILL.md diff --git a/.github/skills/build-and-verify-docs/scripts/verify.ps1 b/.github/skills/build-and-verify-docs/scripts/verify.ps1 new file mode 100644 index 00000000..678d906d --- /dev/null +++ b/.github/skills/build-and-verify-docs/scripts/verify.ps1 @@ -0,0 +1,53 @@ +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $false +$exitCode = 1 +$linkRoot = $null +$link = $null +$locationPushed = $false + +try { + $repo = (Resolve-Path (Join-Path $PSScriptRoot '../../../..')).Path + $website = Join-Path $repo 'website' + Push-Location -LiteralPath $website + $locationPushed = $true + $npm = if ($env:OS -eq 'Windows_NT') { 'npm.cmd' } else { 'npm' } + Get-Command $npm, lychee -ErrorAction Stop | Out-Null + if (!(Test-Path -LiteralPath 'astro.config.mjs' -PathType Leaf) -or + !(Test-Path -LiteralPath 'package.json' -PathType Leaf)) { + throw 'Expected the workshop website configuration and package.json.' + } + + & $npm run check:all + if ($LASTEXITCODE -ne 0) { $exitCode = $LASTEXITCODE; throw 'Type checks failed.' } + $dist = Join-Path $website 'dist' + if (Test-Path -LiteralPath $dist) { + $existing = Get-Item -LiteralPath $dist -Force + if (!$existing.PSIsContainer -or ($existing.Attributes -band [IO.FileAttributes]::ReparsePoint)) { + throw 'Refusing to remove dist: expected a directory, not a link or file.' + } + Remove-Item -LiteralPath $dist -Recurse -Force + } + & $npm run build + if ($LASTEXITCODE -ne 0) { $exitCode = $LASTEXITCODE; throw 'Site build failed.' } + $built = Get-Item -LiteralPath $dist -Force + if (!$built.PSIsContainer -or ($built.Attributes -band [IO.FileAttributes]::ReparsePoint)) { + throw 'Build did not produce a regular dist directory.' + } + + $linkRoot = Join-Path ([IO.Path]::GetTempPath()) ('workshop-links-' + [guid]::NewGuid()) + New-Item -ItemType Directory -Path $linkRoot | Out-Null + # Match the current base in website/astro.config.mjs, as the Pages workflow does. + $link = Join-Path $linkRoot 'copilot-workshops' + $linkType = if ($env:OS -eq 'Windows_NT') { 'Junction' } else { 'SymbolicLink' } + New-Item -ItemType $linkType -Path $link -Target $dist | Out-Null + & lychee --offline --no-progress --root-dir $linkRoot (Join-Path $dist '**/*.html') + $exitCode = $LASTEXITCODE +} catch { + Write-Error $_ -ErrorAction Continue +} finally { + # Delete the link itself, never recurse into the built site through it. + if ($link -and (Test-Path -LiteralPath $link)) { [IO.Directory]::Delete($link) } + if ($linkRoot -and (Test-Path -LiteralPath $linkRoot)) { [IO.Directory]::Delete($linkRoot) } + if ($locationPushed) { Pop-Location } +} +exit $exitCode diff --git a/.github/skills/build-and-verify-docs/scripts/verify.sh b/.github/skills/build-and-verify-docs/scripts/verify.sh new file mode 100644 index 00000000..93869880 --- /dev/null +++ b/.github/skills/build-and-verify-docs/scripts/verify.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../../.." && pwd -P) +cd -- "$repo/website" +for tool in npm lychee; do + command -v "$tool" >/dev/null || { echo "Required tool not found: $tool" >&2; exit 1; } +done +if [[ ! -f astro.config.mjs || ! -f package.json ]]; then + echo "Expected the workshop website configuration and package.json." >&2 + exit 1 +fi + +npm run check:all +if [[ -L dist || ( -e dist && ! -d dist ) ]]; then + echo "Refusing to remove dist: expected a directory, not a symlink or file." >&2 + exit 1 +fi +rm -rf -- "$PWD/dist" +npm run build +if [[ ! -d dist || -L dist ]]; then + echo "Build did not produce a regular dist directory." >&2 + exit 1 +fi + +link_root=$(mktemp -d) +trap 'status=$?; rm -f -- "$link_root/copilot-workshops"; rmdir -- "$link_root"; exit "$status"' EXIT +trap 'exit 130' INT +trap 'exit 143' TERM +# Match the current base in website/astro.config.mjs, as the Pages workflow does. +ln -s -- "$PWD/dist" "$link_root/copilot-workshops" +lychee --offline --no-progress --root-dir "$link_root" "$PWD/dist/**/*.html" diff --git a/.github/skills/check-content-alignment/SKILL.md b/.github/skills/check-content-alignment/SKILL.md index 9fbbaf54..d8a1cd1a 100644 --- a/.github/skills/check-content-alignment/SKILL.md +++ b/.github/skills/check-content-alignment/SKILL.md @@ -1,95 +1,49 @@ --- name: check-content-alignment -description: Find workshop lessons that should change alongside an edit. Scans a diff (staged, unstaged, or a branch range) of the Copilot Workshops docs, extracts what changed, then searches the rest of docs/** for duplicated or parallel passages that now risk drifting out of sync — prose that used to be a shared partial and is now copied across pages, the same concept taught across the VS Code / CLI / App / Cloud harnesses, and cross-references to the changed page. Use after editing lesson content under docs/, before committing or opening a PR, or whenever asked to "check content alignment", "find related content to update", "what else should change", or "check for drift". Reports candidate files with line ranges and rationale; it does NOT edit content. +description: Find workshop content that may need matching changes after a lesson edit. Use for content drift reviews before committing or updating a PR. Discover duplicated passages, parallel concepts, translations, and cross-references from the diff and current content tree. Report actionable candidates without editing files. --- # Check content alignment -This workshop is **pure Markdown** with no partials. Prose that is conceptually shared is **duplicated inline** across lessons instead of single-sourced. That makes editing simpler but removes the partials system's guarantee that one edit updates every copy. This skill is the replacement guardrail: given a change, it finds the *other* places that should probably change too, so duplicated copies don't drift apart. +Lessons repeat concepts, prompts, and instructions across harnesses and translations. Given a content change, find other passages that may now be inconsistent. This skill is advisory and read-only: recommend changes, but do not edit files or publish comments unless separately requested. -It is **advisory and read-only** — it surfaces candidates and rationale for a human (or agent) to act on. It never edits lesson content. +## 1. Establish the review scope -Run every command from the **repo root** unless a step says otherwise. - -## When to use - -- After editing one or more lessons under `docs/**`, before committing or opening a PR. -- When asked to "check content alignment", "find related content to update", "what else should I change", or "check for drift". -- As the local counterpart to the **content-alignment agentic workflow** (`.github/workflows/content-alignment.md`), which runs this same analysis automatically on pull requests and comments its findings. Run the skill locally to catch drift *before* you push. - -## The drift surface (what to look for) - -There are three recurring kinds of duplication in this repo. Most alignment gaps fall into one of them: - -1. **Formerly-shared callouts and steps.** Several short callouts and exercise steps used to live in `_shared/` and were imported into many lessons. They are now copied verbatim into each consumer. When you change one copy, the others usually need the same change. Examples of high-fan-out prose to watch: - - The "start Copilot CLI / **Allow all**" approval callout (was used across several CLI/app pages). - - The "**Approve and run workflows**" step (appears in `cloud/5-iterating.md` and `vscode/6-iterating.md`). - - Shared prerequisites, MCP-setup, and recap blurbs. -2. **Parallel concepts across harnesses.** The same idea is taught up to four times, once per harness: `cli/`, `vscode/`, `app/`, and `cloud/`. A conceptual change (how MCP works, what a custom instruction is, how an agent proposes changes, the description of the Tailspin Toys demo app) often needs the same correction in the sibling lessons of the other harnesses. -3. **Cross-references and shared facts.** Reference-style links to a renamed/retitled lesson, lesson numbers in prose, the published URL shape (`/cli/3-generating-code/`), the demo-app repo URL (`github.com/github-samples/tailspin-toys/...`), tool/library names, and screenshots referenced from multiple pages. - -## Procedure - -### 1. Get the diff - -Pick the comparison that matches what you're reviewing: +Use the comparison requested by the user. For in-progress work, inspect both unstaged and staged changes: ```bash -# Unstaged + staged working-tree changes (default: reviewing your own in-progress edits) git diff -- docs git diff --staged -- docs - -# A whole branch vs. the base it will merge into (reviewing a PR-sized change) -git fetch origin -git diff origin/main...HEAD -- docs +git ls-files --others --exclude-standard -- docs ``` -Limit to `docs` — content drift is the only thing this skill reasons about. - -### 2. Extract the semantic changes - -For each changed lesson, summarize *what actually changed in meaning*, not just which lines moved: - -- Reworded or corrected **facts** (versions, library names, counts, behavior, UI labels, the demo-app description). -- Edited **callouts / steps** that look like formerly-shared prose (see drift surface #1). -- New, renamed, or removed **headings, lesson titles, or files** (these invalidate cross-references). -- Changed **links**, lesson numbers, URLs, or image references. +Read relevant untracked files as well; they do not appear in a normal diff. For a PR or branch review, identify its actual base ref and compare from the merge base to the head. Do not assume every PR targets `main`. Fetch the relevant refs when needed. -Ignore pure formatting (wrapping, whitespace) and changes that are genuinely page-specific. +If there are no lesson changes under `docs/`, report that this content review does not apply. Repository guidance and tooling belong to the [build and verification consistency pass][build-verification]. -### 3. Find the parallel copies +## 2. Identify changes in meaning -For each semantic change, search the rest of the content for passages that should match. Use the changed wording (and its near-synonyms) as the query, and always search the sibling harnesses. +Extract changed facts, requirements, prompts, steps, UI labels, titles, navigation, links, and image references. Ignore formatting-only changes. -```bash -# Find other pages that carry the same callout/step/sentence (quote a distinctive phrase) -grep -rn "Approve and run workflows" docs --include='*.md' - -# Find the parallel lesson in the other harnesses (same concept, different harness) -grep -rln "custom instruction" docs/cli docs/vscode docs/app docs/cloud --include='*.md' - -# Find cross-references to a page you renamed/retitled -grep -rn "2-custom-instructions" docs --include='*.md' -``` +Use the current content tree and locale configuration in `website/astro.config.mjs` to discover related harnesses and translations. Do not maintain a list of lesson numbers, filenames, locale counts, or historical shared passages in this skill. -Exclude the file(s) you already changed from the candidate list. +## 3. Find and inspect related passages -### 4. Report candidates +Search across `docs/` using distinctive old and new phrases, technical identifiers, link targets, and related concepts from the diff. Inspect surrounding text before reporting a match. -Produce a concise, actionable report. For each candidate, give: +- **Repeated content:** copied prompts, instructions, setup steps, and facts that should still agree. +- **Parallel concepts:** the same topic taught through another harness. Preserve intentional differences in UI, permissions, setup, and workflow. +- **Translations:** corresponding localized lessons. Match by content paths and meaning; an English text search alone will miss translated prose. +- **References:** links, titles, lesson numbers, and shared image references affected by a rename or content change. -- **File** and approximate **line range** (or heading) of the passage that may need updating. -- **Why** it's a candidate: which change it parallels, and which drift category (shared-copy, cross-harness, or cross-reference). -- **Suggested action**: the specific edit to mirror, or "review — may be intentionally different." +Check already-modified related files too; being included in the diff does not prove the matching change is complete. Exclude passages whose alignment is already resolved, not every file that was touched. -Group by the source change. Lead with the highest-confidence matches (verbatim shared-copy duplicates) and separate the lower-confidence cross-harness "you may also want to mirror this" items. Be explicit when a parallel passage is *intentionally* harness-specific and should NOT be changed. +## 4. Report actionable candidates -### 5. Hand off +Group findings by the source change. For each candidate, give the file and line range or heading, explain the inconsistency, and suggest the matching edit or a review of an intentional difference. -This skill stops at recommendations. If the user wants the aligned edits made, treat that as a follow-up content-editing task and apply the changes with the normal authoring conventions, then re-run **build-and-verify-docs**. +Lead with confirmed mismatches. Clearly separate uncertain candidates from required corrections, and do not recommend identical wording where behavior legitimately differs. If no likely drift remains, say so briefly and identify the scope reviewed. -## Boundaries +Stop at recommendations. Apply edits only as a separately authorized content-editing task, then verify them using the normal authoring process. -- **Read-only.** Never edit lesson content as part of this skill. -- **docs content only.** Don't flag instruction files, skills, or other repo docs — only `docs/**`. -- **Advisory, not a gate.** False positives are expected; the human decides. Prefer surfacing a borderline candidate (clearly marked low-confidence) over missing a real drift. +[build-verification]: ../build-and-verify-docs/SKILL.md diff --git a/.github/skills/make-repo-contribution/SKILL.md b/.github/skills/make-repo-contribution/SKILL.md index 30f8ea91..5e8d93ed 100644 --- a/.github/skills/make-repo-contribution/SKILL.md +++ b/.github/skills/make-repo-contribution/SKILL.md @@ -39,7 +39,7 @@ The authoritative sources are [`AUTHORING.md`](../../../AUTHORING.md), [`CONTRIB Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> ``` - **Commits:** small, logically grouped, with short messages. -- **Verify before a PR** with the [`build-and-verify-docs`](../build-and-verify-docs/SKILL.md) skill (build, page-count check, lychee link check); CI runs the build + link check. An optional deeper browser pass lives in [`validate-site-playwright`](../validate-site-playwright/SKILL.md). +- **Verify before a PR** with the [`build-and-verify-docs`](../build-and-verify-docs/SKILL.md) skill. It owns the current verification procedure and explains CI coverage. An optional deeper browser pass lives in [`validate-site-playwright`](../validate-site-playwright/SKILL.md). ## Using existing guidelines diff --git a/.github/skills/validate-site-playwright/SKILL.md b/.github/skills/validate-site-playwright/SKILL.md index b611531d..f0b22f9f 100644 --- a/.github/skills/validate-site-playwright/SKILL.md +++ b/.github/skills/validate-site-playwright/SKILL.md @@ -5,7 +5,7 @@ description: Render-validate the built Copilot Workshops site in a real browser # Validate the built site with Playwright -`build-and-verify-docs` checks the site *statically* — it builds, confirms the page-count invariant, and link-checks the HTML with lychee. It never opens a page in a browser, so it cannot see runtime failures: console/hydration errors, images that 404 at load time, or rendered Markdown that looks wrong. +`build-and-verify-docs` checks the site *statically* — it type-checks, builds, inspects affected output against its source, and link-checks the HTML with lychee. Browser checks complement that evidence by finding runtime failures: console/hydration errors, images that fail to load, or visual rendering problems. This skill is the **optional, deeper, browser-based pass**. It drives the **Playwright MCP server** against a local preview of the built site. It is **interactive/local only** — CI (`pages.yml`) has no browser step, so this is never a merge gate. Run it before a PR that changes how pages render (new site-shell components, image-heavy lessons, layout changes), or whenever you want to confirm the real rendered output. diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 2e853b76..3f1cffaf 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -2,7 +2,7 @@ name: Build and deploy workshop site # Builds the Astro + Starlight site under `website/` (sourcing lesson Markdown from # `docs/`) and deploys to GitHub Pages on pushes to main. Every push and pull -# request runs a build-only validation pass plus a link check, so the build can +# request runs type-check, build, and offline link validation, so this job can # serve as a required status check on any PR. on: diff --git a/AUTHORING.md b/AUTHORING.md index bd8cefb1..fd226b81 100644 --- a/AUTHORING.md +++ b/AUTHORING.md @@ -41,7 +41,7 @@ copilot-workshops/ Body starts here. ``` Only `title` is required; it becomes the H1 and the page title. Don't add a body H1 — Starlight renders the title automatically. -3. **Write the body.** Use Markdown and GitHub admonition syntax (`> [!NOTE]`) for callouts. See **Style essentials** below. +3. **Write the body.** Follow the [lesson pattern](#lesson-pattern), using Markdown and GitHub admonition syntax (`> [!NOTE]`) for callouts. See **Style essentials** below. 4. **Add prev/next navigation.** Define `[previous-lesson]` and `[next-lesson]` reference links at the bottom of the page, pointing at the adjacent lessons in the same path: ```markdown [previous-lesson]: ../2-custom-instructions/ @@ -60,7 +60,19 @@ copilot-workshops/ ``` The first lesson in a path omits `[previous-lesson]`; the last omits `[next-lesson]`. 5. **Register in the sidebar.** Open `website/astro.config.mjs` and add an entry to the appropriate `items: []` block. The sidebar is *manually* maintained — order in the file is the order learners see. -6. **Preview and verify, then open a PR.** Preview locally and run the verification sequence before committing — see [Building and verifying](#building-and-verifying) below. CI runs the Astro build and the lychee link check; both must pass. +6. **Preview and verify, then open a PR.** Preview locally and run the verification sequence before committing — see [Building and verifying](#building-and-verifying) below. CI runs type checks, the Astro build, and the lychee link check; all must pass. + +### Lesson pattern + +Use the same teaching flow across harnesses without forcing identical exercises or wording: + +1. **Introduction and objectives.** Connect to the previous work and give a short list of what the learner will do. +2. **Scenario.** Before the technical explanation or steps, use a `## Scenario` section to explain the Tailspin Toys need and why this task matters. +3. **Concepts and guided work.** Explain new concepts where needed, then use task-specific headings and ordered steps. Keep prompts next to the actions they support. +4. **Review and verification.** Tell the learner what to inspect, what evidence to expect, and how to handle failures before moving on. This can be part of the guided steps rather than a separate section. +5. **Summary and next steps.** Briefly connect the completed work to the next module, making the branch, session, checkpoint, or PR handoff clear where relevant. Add a Resources section when useful. + +Prerequisite modules use setup goals and a readiness check instead of an artificial feature scenario. Final recap modules review outcomes and further learning rather than introduce a new task. Landing pages remain workshop overviews. Preserve harness-specific controls and workflow boundaries, and mirror structural changes in existing translations. ### Landing pages (folder `README.md`) @@ -98,25 +110,9 @@ Because copied prose can drift, run the `check-content-alignment` skill when you ## Building and verifying -Before opening a PR, preview the site and run the full verification sequence. The canonical commands live in the [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill — the summary below mirrors it. - -**Preview** with the Astro dev server (hot reload): - -```bash -cd website -npm install -npm run dev -``` - -The site runs at . - -**Verify** before committing: - -1. **Build** — `cd website && rm -rf dist && npm run build`. Must succeed. -2. **Page-count invariant** — Starlight emits 36 workshop routes for English and each of the five configured locales, then adds the legacy redirect. This equals 217 built `index.html` pages when excluding the 404 page; the build reports 218 HTML files including the 404 page. -3. **Link check** — lychee (offline) against the built `website/dist/`. Catches broken internal links/images. +Use the [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill for preview commands and pre-commit verification: type checks, a clean build, inspection of affected pages and translations, and offline link checking. Expected output comes from the current source and site configuration, not a fixed page total. -**What CI enforces vs. what you run locally:** CI (`pages.yml`) runs the **build** and the **lychee** link check on every PR. It does not run browser validation or the content-alignment agentic workflow as part of the Pages build job. After merge to `main`, `pages.yml` deploys the site to GitHub Pages. +**What CI enforces vs. what you run locally:** CI (`pages.yml`) runs **`check:all`**, the **build**, and the **lychee** link check on every PR. It does not run browser validation or the content-alignment agentic workflow as part of the Pages build job. After merge to `main`, `pages.yml` deploys the site to GitHub Pages. **Consistency pass.** When a change renames a file or folder, adds or removes a skill or instruction file, touches duplicated prose, or changes how the build works, also sweep for stale references — the structure trees and cross-doc pointers in `README.md`, `AUTHORING.md`, and `.github/copilot-instructions.md` aren't checked by the Astro build. The [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill has the full checklist, and the `check-content-alignment` skill plus `.github/workflows/content-alignment.md` help catch prose that needs aligned updates. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64292b5f..72f0cbec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,10 +24,11 @@ If you want to **author or edit content**, start with [`AUTHORING.md`](./AUTHORI CI (`pages.yml`) must be green on your PR. It runs: +- **Type checks** — `npm run check:all` (Astro and TypeScript checks). - **`pages.yml` build** — `npm run build` (Astro site build). - **Lychee** — offline link check of the built `website/dist/`. -Before you push, run the full local verification sequence described in [AUTHORING.md → Building and verifying](./AUTHORING.md#building-and-verifying): clean build, page-count check, and lychee link check. +Before you push, follow the [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill for type checks, a clean build, inspection of affected pages, and offline link checking. ## Commit messages diff --git a/README.md b/README.md index 38c04eb2..f86ad396 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The site runs at . ## Verification -Before opening a PR, build the site and run the full verification sequence — clean build, page-count check, and offline link check (lychee). The canonical commands live in **[AUTHORING.md → Building and verifying](./AUTHORING.md#building-and-verifying)** and the [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill. CI (`pages.yml`) runs the build and the lychee link check. +Before opening a PR, follow the [`build-and-verify-docs`](./.github/skills/build-and-verify-docs/SKILL.md) skill for type checks, a clean build, inspection of affected pages, and offline link checking. See [AUTHORING.md](./AUTHORING.md#building-and-verifying) for authoring context. ## License