diff --git a/skills/create-gh-pages-site/SKILL.md b/skills/create-gh-pages-site/SKILL.md index 426711c..8187bcf 100644 --- a/skills/create-gh-pages-site/SKILL.md +++ b/skills/create-gh-pages-site/SKILL.md @@ -3,8 +3,9 @@ name: create-gh-pages-site description: >- Scaffold a working GitHub Pages website from a vetted template and wire it to deploy automatically. Use when the user wants to create, scaffold, or publish a - site on GitHub Pages: a static page, an Astro or Eleventy site, a React (Vite) - SPA, or a Jekyll site. Picks the right template, injects the correct base path + site on GitHub Pages: a reviewable VitePress specification, a static page, an + Astro or Eleventy site, a React (Vite) SPA, or a Jekyll site. Picks the right + template, injects the correct base path for the target repo (the #1 thing people get wrong), adds the official GitHub Actions Pages deploy workflow, and sets it up in the user's current repo by default or a new one if asked. Does not stop at demo content: it digests the @@ -43,11 +44,14 @@ and default to `static-html` for the simplest ask. | `eleventy` | A data/Markdown-driven site (blog, docs) where content is files + structured data. | data SSG | `eleventy` | | `jekyll` | The user wants the GitHub-native path, or is migrating an existing Jekyll site. | native | Jekyll | | `skills-catalog` | A browsable catalog for a repository of Copilot skills, especially when composing `create-skills-repo`. | catalog | registry-defined | +| `spectator` | A technical specification, RFC, architecture proposal, design proposal, engineering decision, or policy proposal built for structured review. | SSG | `vitepress build docs` | -The built-in registry pin includes `skills-catalog`. A custom registry requires an -explicit `--registry-ref`, and a local checkout uses `--templates-dir`. +The built-in registry pin must include the selected template. A custom registry +requires an explicit `--registry-ref`, and a local checkout uses +`--templates-dir`. -These six cover the static / SSG / SPA / data / native / catalog quadrants. For richer +These seven cover the static / SSG / SPA / data / native / catalog / specification +quadrants. For richer *themes*, point the user at upstream galleries (astro.build/themes, jamstackthemes.dev, github.com/topics/github-pages-template) and adapt — don't try to hand-build a theme from scratch. @@ -70,6 +74,7 @@ repo name; you rarely set it by hand: | `react-vite` | `base` in `vite.config.js` + `basename` + `404.html` | `/repo/` | `/` | | `eleventy` | `pathPrefix` via `PATH_PREFIX` env + `url` filter | `/repo/` | `/` | | `jekyll` | `baseurl` in `_config.yml` + `relative_url` | `/repo` (no slash) | `""` (empty) | +| `spectator` | `base` in `spectator.config.ts` and VitePress config | `/repo/` | `/` | **The generator detects the `.github.io` user-site pattern and uses `/` automatically.** If the user hasn't named the repo yet, scaffold with the repo @@ -109,6 +114,9 @@ only for what's missing, one focused question at a time, using the `ask_user` to path or are migrating an existing Jekyll site) - "an app / dashboard / interactive / single-page app" → `react-vite` - "a catalog of Copilot skills / create a skills repo" → `skills-catalog` + - "a specification / RFC / architecture or design proposal / engineering + decision / policy proposal / site like the Eval Authoring Guide" → + `spectator` If they're unsure, ask the single discriminating question — *content site or interactive app?* — and default to `static-html` for the simplest ask. @@ -341,6 +349,13 @@ yourself too — the digest points you at them; it doesn't replace judgment. base-path-aware internal links the template already wires — never hand-write absolute `/...` links (use the template's base helper, or it breaks on a project site). +- **Keep Spectator free-form.** Do not force a standard specification outline. + Derive pages, headings, and navigation from the supplied context. Preserve the + Spectator reading and feedback system, but remove every Project Northstar sample + page, label, requirement, source, and image reference. +- **Label uncertainty in Spectator.** Distinguish verified current behavior, + user-approved decisions, proposals, assumptions, risks, and open questions. + Do not invent owners, dates, requirements, interfaces, or security claims. ### 4. Add image placeholders the user can supply @@ -362,41 +377,20 @@ dimensions. Then: (e.g. a `docs/*.png`), use it instead of a placeholder. - **Put images where the template serves static files:** - `astro`, `react-vite` → `public/images/` (served at `${BASE_URL}images/…`) + - `spectator` → `docs/public/images/` (VitePress applies its configured base) - `static-html` → `assets/images/` (relative `./assets/images/…`) - `eleventy` → `src/assets/images/` (through the `url` filter) - `jekyll` → `assets/images/` (via `relative_url`) - **Leave `IMAGES.md` in the images dir** as the hand-off, and tell the user it's there. A placeholder still deploys fine; it just visibly says "replace me". -### Ask the user for the real images +### Ask for real images -Placeholders unblock the deploy, but a finished site needs real art. After you've -authored the pages and know exactly which images the site references, **prompt the -user for them** with a short, specific checklist — don't make them guess. For each -image give the role, the filename it should land at, and the recommended size, e.g.: - -> This site needs a few images. You can **paste a screenshot straight into the chat** -> and I'll drop it in, or point me at a file/URL: -> 1. **Social card** → `og.png`, 1200×630 (used for link previews) -> 2. **Hero** → `hero.png`, 1280×640 -> 3. **Skill thumbnail** → `thumb-create-gh-pages-site.png`, 640×400 -> -> Send any you have; I'll keep placeholders for the rest. - -Then, as the user supplies them: - -- **Accept pasted screenshots.** Images pasted into the conversation are available - to you directly — save each to the right path (matching the reference or - `IMAGES.md`), no upload step needed. A local file path or URL works too. -- **Don't block on it.** Anything the user doesn't provide keeps its placeholder; - the site still builds and deploys. Update `IMAGES.md` to tick off what's now real. -- **Only ask for what the site actually uses.** Don't request a logo or a hero the - page never references (drop unused placeholders instead of asking for art for them). - -### Helper scripts (alongside `new-site.mjs`) - -- `scripts/digest-repo.mjs` — analyze a repo → JSON signals + a type classification. -- `scripts/make-placeholder.mjs` — generate placeholder images + an `IMAGES.md`. +After authoring, ask only for images the site references. Give each role, filename, +and recommended dimensions; accept pasted images, file paths, or URLs. Keep +unprovided placeholders, update `IMAGES.md`, and do not block deployment. +`digest-repo.mjs` discovers source material; `make-placeholder.mjs` creates the +placeholder set and handoff manifest. ## Per-template notes @@ -414,9 +408,13 @@ Then, as the user supplies them: - **jekyll** — `baseurl` (no trailing slash) in `_config.yml`; links use `relative_url`. Built in CI by `jekyll-build-pages` (honors the `Gemfile`). Local dev needs Ruby + Bundler; CI does not. +- **spectator**: VitePress reads `base` from `spectator.config.ts`. Content is + free-form Markdown under `docs/`; navigation is explicit in the shared config. + Preserve local search, page outlines, light/dark appearance, plain-language + callouts, page feedback, selected-text feedback, and GitHub edit links. Run + `npm test`, `npm run build`, and `npm run test:e2e`. ## Current repo vs. new repo - - **Current repo (the default)**: assume the site is for the repo in context. The generator infers the base path from its `origin` remote when you omit `--repo`. Put the site at the root for a whole-repo site, or in a subfolder and point the @@ -427,13 +425,11 @@ Then, as the user supplies them: is `/` — the generator handles the base when you pass that repo name. ## Custom domains (documented, not automated) - For a custom domain: add a `CNAME` file (for static/Jekyll, at the served root; for Astro, `public/CNAME`), set DNS at the registrar, and in Astro set `site` to the domain and drop `base`. Don't automate DNS — explain the steps. ## Template registry & contributing - Templates live in **one** place: the **[`jongio/gh-pages-templates`](https://github.com/jongio/gh-pages-templates)** registry. The skill does **not** bundle its own copy — the generator fetches @@ -463,7 +459,7 @@ land in the registry, not here. phrases — "Hello", "islands", "lorem", the sample post titles — and for leftover `__…__` sentinels). The page kind matches the repo type (CLI ref / API ref / feature tour / catalog). Image placeholders exist and `IMAGES.md` is present. -2. **Build it.** For `astro`/`react-vite`/`eleventy`, run +2. **Build it.** For `astro`/`react-vite`/`eleventy`/`spectator`, run `npm ci --ignore-scripts --no-audit --no-fund` then `npm run build` and confirm both exit 0 and emit the output dir (`dist` / `_site`). For `jekyll`, `bundle exec jekyll build` if Ruby is present. @@ -480,7 +476,6 @@ placeholder checks, offline via a fixture). Template/workflow validation lives i the `jongio/gh-pages-templates` registry. ## Footguns - - **Never** ship a project site built for `/` — assets 404. Set the base path (the generator does this; verify it). - **Never** put a subpath base on a **user site** (`.github.io`) — it must be `/` (Jekyll: `baseurl: ""`). - **Never** use `actions/upload-artifact` for Pages — it's `upload-pages-artifact`. @@ -488,7 +483,9 @@ the `jongio/gh-pages-templates` registry. - **Never** forget to set **Source → GitHub Actions** in Settings → Pages; the workflow can't publish until Pages is enabled for Actions. - **Don't** leave the repo "Website" link blank — set `homepage` to the Pages URL (`gh repo edit --homepage`) so visitors find the site; it's the same as the "Use your GitHub Pages website" checkbox. - **Never** claim success because the workflow is green — load the URL and check an asset and an internal link actually resolve. -- **Never** ship the template's demo content. A stamped template that still says "Hello, Astro" (or lists the sample blog posts) for someone's CLI or library is a failure — digest the repo and author real content of the right kind. +- **Never** ship the template's demo content. A stamped template that still says + "Hello, Astro", lists sample blog posts, or contains Project Northstar is a + failure. Digest the repo and author real content of the right kind. - **Never** fabricate features, commands, or APIs to fill the page. Author only what the repo actually shows; leave a visible `TODO` when unsure. - **Don't** leave bare image references with nothing behind them — add the placeholders + `IMAGES.md`, or reuse the repo's existing images. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/eval.yaml b/skills/create-gh-pages-site/evals/create-gh-pages-site/eval.yaml index badd23f..615f3d5 100644 --- a/skills/create-gh-pages-site/evals/create-gh-pages-site/eval.yaml +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/eval.yaml @@ -150,6 +150,241 @@ stimuli: Score 1.0 if yes with real content, 0.5 if partially specific, 0.0 if still generic demo content. + - name: explicit-spectator-specification + prompt: >- + Use the create-gh-pages-site skill and the spectator template to publish a + reviewable GitHub Pages specification for "octocat/reviewable-cache-rfc". + Use the local template registry at "registry/templates". The current + directory contains the repository README and proposal-notes.md. Keep the + content structure free-form, preserve the GitHub feedback and edit + workflow, and replace all Project Northstar sample content. + tags: + template: spectator + cost: high + rubric: + - The generated site accurately describes the offline cache proposal, including read-only behavior, the 24-hour maximum age, and the unresolved storage-location decision. + - The site uses a free-form specification structure and does not retain Project Northstar sample content. + - The Spectator review configuration and GitHub Pages base path remain intact. + environment: + files: + - src: fixtures/spectator-repo/README.md + dest: README.md + - src: fixtures/spectator-repo/proposal-notes.md + dest: proposal-notes.md + - src: fixtures/spectator/template.json + dest: registry/templates/spectator/template.json + - src: fixtures/spectator/package.json + dest: registry/templates/spectator/package.json + - src: fixtures/spectator/spectator.config.ts + dest: registry/templates/spectator/spectator.config.ts + - src: fixtures/spectator/docs/index.md + dest: registry/templates/spectator/docs/index.md + - src: fixtures/spectator/docs/proposal.md + dest: registry/templates/spectator/docs/proposal.md + - src: fixtures/spectator/docs/system-shape.md + dest: registry/templates/spectator/docs/system-shape.md + - src: fixtures/spectator/docs/.vitepress/config.mts + dest: registry/templates/spectator/docs/.vitepress/config.mts + - src: fixtures/spectator/docs/.vitepress/theme/index.ts + dest: registry/templates/spectator/docs/.vitepress/theme/index.ts + - src: fixtures/spectator/docs/.vitepress/theme/FeedbackPrompt.vue + dest: registry/templates/spectator/docs/.vitepress/theme/FeedbackPrompt.vue + - src: fixtures/spectator/docs/.vitepress/theme/SelectionActions.vue + dest: registry/templates/spectator/docs/.vitepress/theme/SelectionActions.vue + - src: fixtures/spectator/.github/workflows/deploy.yml + dest: registry/templates/spectator/.github/workflows/deploy.yml + graders: + - type: file-exists + name: spectator-config-created + config: + path: "spectator.config.ts" + - type: file-exists + name: spectator-content-created + config: + path: "docs/index.md" + - type: file-exists + name: deploy-workflow-created + config: + path: ".github/workflows/deploy.yml" + - type: file-contains + name: project-base-injected + config: + path: "spectator.config.ts" + value: "/reviewable-cache-rfc/" + - type: file-contains + name: proposal-content-authored + config: + path: "docs/index.md" + value: "offline" + - type: file-contains + name: workflow-uploads-pages-artifact + config: + path: ".github/workflows/deploy.yml" + value: "actions/upload-pages-artifact" + - type: file-contains + name: workflow-orders-deploy-after-build + config: + path: ".github/workflows/deploy.yml" + value: "needs: build" + - type: file-contains + name: page-feedback-preserved + config: + path: "docs/.vitepress/theme/FeedbackPrompt.vue" + value: "issues/new" + - type: file-contains + name: selected-text-feedback-preserved + config: + path: "docs/.vitepress/theme/SelectionActions.vue" + value: "window.getSelection" + - type: file-contains + name: edit-page-action-preserved + config: + path: "docs/.vitepress/theme/SelectionActions.vue" + value: "Edit page" + - type: file-contains + name: page-feedback-mounted + config: + path: "docs/.vitepress/theme/index.ts" + value: "doc-footer-before" + - type: file-contains + name: selection-feedback-mounted + config: + path: "docs/.vitepress/theme/index.ts" + value: "layout-bottom" + - type: file-not-contains + name: sample-content-removed + config: + path: "docs/index.md" + value: "Project Northstar" + - type: file-not-contains + name: proposal-sample-content-removed + config: + path: "docs/proposal.md" + value: "Project Northstar" + - type: file-not-contains + name: system-sample-content-removed + config: + path: "docs/system-shape.md" + value: "Project Northstar" + - type: prompt + name: spectator-content-quality + config: + prompt: >- + Review the generated Spectator site. Does it accurately cover the + offline read-only cache, 24-hour maximum age, cache-only mode, + security boundary, and open storage-location decision without + forcing a generic outline? Score 1.0 if yes, 0.5 if partially, and + 0.0 if the content is generic or still uses Project Northstar. + + - name: inferred-spectator-specification + prompt: >- + Publish the offline cache proposal in this repository as a GitHub Pages + website like the Eval Authoring Guide. It should be easy to search and + navigate, let reviewers comment on a page or selected text through GitHub, + and let them propose edits. Use the local template registry at + "registry/templates". Choose the right template from the skill and replace + all fictional sample content. + tags: + template: spectator + selection: inferred + cost: high + rubric: + - The agent infers that Spectator is the right template for a reviewable technical specification. + - The generated site accurately reflects the repository proposal notes and keeps content organization free-form. + - Page, selected-text, and GitHub edit review affordances remain configured. + environment: + files: + - src: fixtures/spectator-repo/README.md + dest: README.md + - src: fixtures/spectator-repo/proposal-notes.md + dest: proposal-notes.md + - src: fixtures/spectator/template.json + dest: registry/templates/spectator/template.json + - src: fixtures/spectator/package.json + dest: registry/templates/spectator/package.json + - src: fixtures/spectator/spectator.config.ts + dest: registry/templates/spectator/spectator.config.ts + - src: fixtures/spectator/docs/index.md + dest: registry/templates/spectator/docs/index.md + - src: fixtures/spectator/docs/proposal.md + dest: registry/templates/spectator/docs/proposal.md + - src: fixtures/spectator/docs/system-shape.md + dest: registry/templates/spectator/docs/system-shape.md + - src: fixtures/spectator/docs/.vitepress/config.mts + dest: registry/templates/spectator/docs/.vitepress/config.mts + - src: fixtures/spectator/docs/.vitepress/theme/index.ts + dest: registry/templates/spectator/docs/.vitepress/theme/index.ts + - src: fixtures/spectator/docs/.vitepress/theme/FeedbackPrompt.vue + dest: registry/templates/spectator/docs/.vitepress/theme/FeedbackPrompt.vue + - src: fixtures/spectator/docs/.vitepress/theme/SelectionActions.vue + dest: registry/templates/spectator/docs/.vitepress/theme/SelectionActions.vue + - src: fixtures/spectator/.github/workflows/deploy.yml + dest: registry/templates/spectator/.github/workflows/deploy.yml + graders: + - type: file-exists + name: spectator-selected + config: + path: "spectator.config.ts" + - type: file-contains + name: inferred-project-base + config: + path: "spectator.config.ts" + value: "/reviewable-cache-rfc/" + - type: file-contains + name: inferred-content-authored + config: + path: "docs/index.md" + value: "offline" + - type: file-contains + name: inferred-page-feedback-preserved + config: + path: "docs/.vitepress/theme/FeedbackPrompt.vue" + value: "issues/new" + - type: file-contains + name: inferred-selection-feedback-preserved + config: + path: "docs/.vitepress/theme/SelectionActions.vue" + value: "window.getSelection" + - type: file-contains + name: inferred-workflow-uploads-pages-artifact + config: + path: ".github/workflows/deploy.yml" + value: "actions/upload-pages-artifact" + - type: file-contains + name: inferred-page-feedback-mounted + config: + path: "docs/.vitepress/theme/index.ts" + value: "doc-footer-before" + - type: file-contains + name: inferred-selection-feedback-mounted + config: + path: "docs/.vitepress/theme/index.ts" + value: "layout-bottom" + - type: file-not-contains + name: inferred-sample-content-removed + config: + path: "docs/index.md" + value: "Project Northstar" + - type: file-not-contains + name: inferred-proposal-sample-content-removed + config: + path: "docs/proposal.md" + value: "Project Northstar" + - type: file-not-contains + name: inferred-system-sample-content-removed + config: + path: "docs/system-shape.md" + value: "Project Northstar" + - type: prompt + name: inferred-template-quality + config: + prompt: >- + Did the agent select Spectator without being told its name, preserve + the GitHub review workflow, and author a specific offline cache + proposal from the repository context? Score 1.0 for all conditions, + 0.5 for partial compliance, and 0.0 for another template or generic + content. + - name: skills-catalog-safe-staging prompt: >- Use the create-gh-pages-site skill and the skills-catalog template to stage diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/README.md b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/README.md new file mode 100644 index 0000000..f3a5fb5 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/README.md @@ -0,0 +1,7 @@ +# reviewable-cache-rfc + +A proposal for adding an offline cache to the Acme command line tool. + +The cache should let users repeat read-only commands while disconnected. Writes +must continue to fail offline. Reviewers need to decide cache invalidation, +maximum age, storage location, and the security treatment of cached responses. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/proposal-notes.md b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/proposal-notes.md new file mode 100644 index 0000000..4dc5fc1 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator-repo/proposal-notes.md @@ -0,0 +1,13 @@ +# Offline cache proposal notes + +Current behavior requires network access for every command. + +Proposed behavior: + +- Cache successful read-only responses for up to 24 hours. +- Never cache credentials or write responses. +- Add `--offline` to require cache-only reads. +- Return a clear error when no eligible entry exists. + +Open decision: whether the default storage location should be user-wide or +repository-local. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/.github/workflows/deploy.yml b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/.github/workflows/deploy.yml new file mode 100644 index 0000000..bae30f2 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/.github/workflows/deploy.yml @@ -0,0 +1,42 @@ +name: github-pages +on: + push: + branches: + - main + workflow_dispatch: +permissions: + contents: read +jobs: + build: + permissions: + contents: read + pages: read + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + persist-credentials: false + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 + with: + node-version: 24 + - run: npm install --ignore-scripts --no-audit --no-fund + - run: npm run build + - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d + - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 + with: + path: docs/.vitepress/dist + deploy: + permissions: + contents: read + pages: write + id-token: write + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: build + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/config.mts b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/config.mts new file mode 100644 index 0000000..e04efce --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/config.mts @@ -0,0 +1,10 @@ +import { defineConfig } from "vitepress"; + +export default defineConfig({ + base: "__BASE_PATH__", + themeConfig: { + editLink: { + pattern: "https://github.com/__REPO_SLUG__/edit/main/docs/:path", + }, + }, +}); diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/FeedbackPrompt.vue b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/FeedbackPrompt.vue new file mode 100644 index 0000000..99af100 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/FeedbackPrompt.vue @@ -0,0 +1,5 @@ + diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/SelectionActions.vue b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/SelectionActions.vue new file mode 100644 index 0000000..a77ee55 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/SelectionActions.vue @@ -0,0 +1,13 @@ + + + diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/index.ts b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/index.ts new file mode 100644 index 0000000..3c732af --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/.vitepress/theme/index.ts @@ -0,0 +1,14 @@ +import DefaultTheme from "vitepress/theme"; +import { h } from "vue"; +import FeedbackPrompt from "./FeedbackPrompt.vue"; +import SelectionActions from "./SelectionActions.vue"; + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + "doc-footer-before": () => h(FeedbackPrompt), + "layout-bottom": () => h(SelectionActions), + }); + }, +}; diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/index.md b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/index.md new file mode 100644 index 0000000..c5c5430 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/index.md @@ -0,0 +1,8 @@ +--- +layout: home +title: __SITE_NAME__ +--- + +# Project Northstar + +Replace this fictional specification with the target repository context. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/proposal.md b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/proposal.md new file mode 100644 index 0000000..39cf888 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/proposal.md @@ -0,0 +1,5 @@ +# Project Northstar proposal + +Project Northstar proposes a fictional specification workflow. + +Replace this page with repository-specific proposal content. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/system-shape.md b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/system-shape.md new file mode 100644 index 0000000..002ad17 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/docs/system-shape.md @@ -0,0 +1,5 @@ +# Project Northstar system shape + +Project Northstar uses a fictional system diagram. + +Replace this page with repository-specific technical content. diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/package.json b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/package.json new file mode 100644 index 0000000..c071c71 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/package.json @@ -0,0 +1,8 @@ +{ + "name": "__PKG_NAME__", + "private": true, + "type": "module", + "scripts": { + "build": "node -e \"console.log('built')\"" + } +} diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/spectator.config.ts b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/spectator.config.ts new file mode 100644 index 0000000..65c3407 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/spectator.config.ts @@ -0,0 +1,6 @@ +export const spectatorConfig = { + siteName: "__SITE_NAME__", + siteUrl: "__SITE_URL__", + basePath: "__BASE_PATH__", + repo: "__REPO_SLUG__", +}; diff --git a/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/template.json b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/template.json new file mode 100644 index 0000000..c252867 --- /dev/null +++ b/skills/create-gh-pages-site/evals/create-gh-pages-site/fixtures/spectator/template.json @@ -0,0 +1,7 @@ +{ + "name": "spectator", + "title": "Spectator", + "tagline": "Specifications built for review.", + "needsBuild": true, + "order": 1 +} diff --git a/skills/create-gh-pages-site/scripts/new-site.mjs b/skills/create-gh-pages-site/scripts/new-site.mjs index 7bd8680..ffdea0c 100644 --- a/skills/create-gh-pages-site/scripts/new-site.mjs +++ b/skills/create-gh-pages-site/scripts/new-site.mjs @@ -78,7 +78,16 @@ const TEMPLATES_DIR = resolve(__dirname, "..", "templates"); // bundles its own copy; the generator fetches from here unless --templates-dir // (or a local templates/ next to the script) provides an offline source. // Files/dirs never copied into a stamped site. -const SKIP_ENTRIES = new Set(["node_modules", "dist", "_site", ".git", ".cache", ".jekyll-cache", "template.json"]); +const SKIP_ENTRIES = new Set([ + "node_modules", + "dist", + "_site", + ".git", + ".cache", + ".jekyll-cache", + "template.json", + "spec.md", +]); // Sentinels replaced during stamping. Replacement is a single pass over a // combined regex so an injected value (e.g. a --site-name that happens to diff --git a/skills/create-gh-pages-site/scripts/template-registry.mjs b/skills/create-gh-pages-site/scripts/template-registry.mjs index 655ea6b..86acc10 100644 --- a/skills/create-gh-pages-site/scripts/template-registry.mjs +++ b/skills/create-gh-pages-site/scripts/template-registry.mjs @@ -13,7 +13,7 @@ const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)); const LOCAL_TEMPLATES_DIR = resolve(SCRIPT_DIR, "..", "templates"); export const DEFAULT_REGISTRY = "jongio/gh-pages-templates"; -export const DEFAULT_REGISTRY_REF = "9caf1c8ad0bbfab1c020a498393673abe033c7cc"; +export const DEFAULT_REGISTRY_REF = "101139f9c8bb872b13ad84e18d90435e7a15f107"; const registryClones = new Map(); let exitHookInstalled = false; diff --git a/skills/create-gh-pages-site/test/generator.test.mjs b/skills/create-gh-pages-site/test/generator.test.mjs index 057ecac..d148ca7 100644 --- a/skills/create-gh-pages-site/test/generator.test.mjs +++ b/skills/create-gh-pages-site/test/generator.test.mjs @@ -24,6 +24,7 @@ import { assertNoSymlinks, assertSafeDestination, normalizePinnedLegacyWorkflows, + DEFAULT_REGISTRY_REF, validateWorkflowFile, validateStagedTree, registryCloneUrl, @@ -254,6 +255,13 @@ test("registry revisions must be full immutable commit SHAs", () => { assert.throws(() => assertFullCommitSha("abc123"), /40-character commit SHA/); }); +test("default registry pin includes the reviewed Spectator release", () => { + assert.equal( + DEFAULT_REGISTRY_REF, + "101139f9c8bb872b13ad84e18d90435e7a15f107", + ); +}); + test("resolveInside rejects template path traversal", () => { const root = join(tmpdir(), "registry", "templates"); assert.equal(resolveInside(root, "skills-catalog"), join(root, "skills-catalog")); @@ -320,6 +328,7 @@ function mkTemplate(root, name, manifestExtra = {}) { writeFileSync(join(d, "_config.yml"), `baseurl: "__BASE_URL__"`); writeFileSync(join(d, ".github", "workflows", "deploy.yml"), safeWorkflow()); writeFileSync(join(d, "node_modules", "junk.js"), "__SITE_NAME__ should never be copied"); + writeFileSync(join(d, "spec.md"), "Registry development specification"); return d; } @@ -427,9 +436,10 @@ try { assert.match(html, /https:\/\/octocat\.github\.io\/demo-site\//); }); - test("stamp: does not copy template.json or node_modules into the site", () => { + test("stamp: excludes registry-only and dependency files", () => { assert.ok(!existsSync(join(dir, "template.json"))); assert.ok(!existsSync(join(dir, "node_modules"))); + assert.ok(!existsSync(join(dir, "spec.md"))); }); test("stamp: ships the deploy workflow", () => {