From cdb64afe8bc1a94c19ff92ed6f4ac1e9405124f8 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Mon, 27 Jul 2026 14:15:52 +1000 Subject: [PATCH 1/2] Docs site: publish the repo's Markdown to GitHub Pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements #9. The documentation had grown into a real set — three guides, two plugin guides, the evaluation framework, the audit doctrine — readable only as GitHub blob pages. Nothing moves. `myst.yml` points at every file where it already lives, including `benchmark/README.md` and `audit/references/*.md` inside the plugin directories, so the repo view and the site render from one source and an installed plugin keeps shipping the documentation it needs. The cost of that choice is that the sources must stay plain, GitHub-readable Markdown, which is stated in developing-skills.md rather than left for someone to discover. CI builds on every PR and deploys only from `main`, so a broken docs change cannot replace the live site. The link check runs over the Markdown sources rather than the built HTML: the theme renders as a single-page app with no crawlable link graph, and the sources are what has to stay correct in both contexts anyway. It runs offline, because several links point at private QuantEcon repos that answer 404 to an unauthenticated checker — a job that cries wolf is a job everyone learns to ignore. That check found seven already-broken links in the 2026-07-21 design review, written repo-root-relative from a file in `reviews/`; they have never resolved on GitHub either. Fixed. All 113 relative links in the repo now resolve. Two known limitations, both cosmetic and neither worth a content rewrite (#9's stated non-goal). The plugin guides land at `/readme` and `/readme-1`, because mystmd derives slugs from filenames and ignores a `slug:` key in the TOC; the alternative is YAML frontmatter, which GitHub renders as a table at the top of each plugin README. And four deep links into `doctrine.md` reach the right page without jumping to the section, because GitHub emits `#3-read-only-boundary` for a numbered heading where mystmd emits `#id-3-read-only-boundary`. --- .github/workflows/docs.yml | 88 +++++++++++++++++++ .gitignore | 4 + README.md | 2 + docs/developing-skills.md | 11 +++ myst.yml | 47 ++++++++++ ...benchmark-design-2026-07-21-independent.md | 2 +- 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/docs.yml create mode 100644 myst.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..06404d8 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,88 @@ +name: docs + +# Builds the MyST site on every PR and publishes it to GitHub Pages on main. +# A PR gets build + link check and never deploys, so a broken docs change is +# caught before it can replace the live site. + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +# One deploy at a time, but never cancel a running main deploy — a cancelled +# deployment can leave Pages serving a half-published site. +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "22" + + # Pinned: an unpinned docs toolchain turns an upstream release into a + # surprise failure on an unrelated PR. + - name: Install MyST + run: npm install -g mystmd@1.10.1 + + # The site is served from a subpath (quantecon.github.io/skills), so the + # built asset URLs have to carry it. PR builds use the root, since they + # are only ever checked for whether they build. + - name: Build + run: myst build --html + env: + BASE_URL: ${{ github.event_name == 'push' && '/skills' || '' }} + + - name: Upload Pages artifact + if: github.event_name == 'push' + uses: actions/upload-pages-artifact@v3 + with: + path: _build/html + + links: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Checked against the Markdown sources rather than the built site: the + # theme renders as a single-page app, so its HTML holds no crawlable + # link graph, and the sources are what has to stay correct in both + # contexts anyway — the GitHub repo view and the published site. + # + # Offline only. Several links point at private QuantEcon repos, which + # answer 404 to an unauthenticated checker; failing CI on those would + # teach everyone to ignore this job. + - name: Check relative links + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --offline + --no-progress + --exclude-path node_modules + --exclude-path _build + "**/*.md" + fail: true + + deploy: + # Only main deploys, and only after both gates pass. + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: [build, links] + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 88c478e..6f7214a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ __pycache__/ benchmark/references/examples/*/results/as_used.json benchmark/references/examples/*/results/cold_start.json benchmark/references/examples/*/results/env.json + +# MyST docs site build output +_build/ +node_modules/ diff --git a/README.md b/README.md index 8738c77..cc79a2b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A [Claude Code plugin marketplace](https://code.claude.com/docs/en/plugin-market Each plugin bundles one area of work — a skill (the instructions Claude follows) plus the deterministic scripts it drives — so the same versioned toolkit works locally for authors and RAs, and headlessly in CI. +📖 **[quantecon.github.io/skills](https://quantecon.github.io/skills)** — the documentation, rendered and navigable. It is built from the files in this repository, so reading either one gets you the same content. + ## Plugins | Plugin | For | Covers | diff --git a/docs/developing-skills.md b/docs/developing-skills.md index 320ca24..645fa89 100644 --- a/docs/developing-skills.md +++ b/docs/developing-skills.md @@ -77,6 +77,17 @@ Two things to know: Confirm with `/plugin marketplace list` (the source should read `QuantEcon/skills`, not your local path) and `/plugin list` (the version should match the merged `plugin.json`). Routine setup and updating for end users is covered in [using-skills.md](using-skills.md). +## The documentation site + +These guides, the plugin guides, and the shared reference material are published to [quantecon.github.io/skills](https://quantecon.github.io/skills) by [`.github/workflows/docs.yml`](../.github/workflows/docs.yml) on every push to `main`. Preview it before you push: + +```bash +npm install -g mystmd +myst start # live-reloading preview +``` + +Two things follow from how it is wired. **Pages are rendered from the files where they already live** — [`myst.yml`](../myst.yml) points at `benchmark/README.md` and `audit/references/*.md` in place, never a copy — so editing a plugin's docs updates the site, and no plugin loses documentation it needs to ship with it. And **the sources have to stay readable on GitHub**, since the repo view is the other half of the audience: prefer plain Markdown, and keep relative links relative, because CI checks that every one of them resolves. + ## Versioning and releases Bump the version in **both** `plugin.json` and the plugin's `marketplace.json` entry — the validator enforces they match. Scaffolding → first usable content is a minor bump (the benchmark plugin's evaluation-system landing was 0.1.0 → 0.2.0). diff --git a/myst.yml b/myst.yml new file mode 100644 index 0000000..cb0eeef --- /dev/null +++ b/myst.yml @@ -0,0 +1,47 @@ +# MyST site configuration — renders the repo's existing Markdown as a +# navigable site at https://quantecon.github.io/skills. +# +# Content is never moved here. Every entry below points at the file where it +# already lives, so the repo view and the published site render from one +# source (AGENTS.md, "Single source of truth") and an installed plugin keeps +# shipping its own documentation inside its own directory. +version: 1 + +project: + id: quantecon-skills + title: QuantEcon Skills + description: >- + QuantEcon's shared Claude Code skills and the deterministic scripts they + drive — style checks for authors, acceleration evaluation, and bulk + repository audits. + github: https://github.com/QuantEcon/skills + toc: + - file: README.md + - title: Guides + children: + - file: docs/using-skills.md + - file: docs/developing-skills.md + - file: docs/tutorial-run-an-evaluation.md + - title: Plugins + children: + - file: benchmark/README.md + title: Benchmark plugin + children: + - file: benchmark/references/EVALUATION_FRAMEWORK.md + - file: audit/README.md + title: Audit plugin + children: + - file: audit/references/doctrine.md + - file: audit/references/quantecon-context.md + - file: audit/references/deliverables.md + - title: Project + children: + - file: CATALOG.md + - file: FUTURE-IDEAS.md + +site: + template: book-theme + title: QuantEcon Skills + options: + logo_text: QuantEcon Skills + hide_outline: false diff --git a/reviews/benchmark-design-2026-07-21-independent.md b/reviews/benchmark-design-2026-07-21-independent.md index 954df3f..66822ea 100644 --- a/reviews/benchmark-design-2026-07-21-independent.md +++ b/reviews/benchmark-design-2026-07-21-independent.md @@ -3,7 +3,7 @@ **Date:** 2026-07-21 **Branch reviewed:** `docs-skills-usage` **Scope:** the full evaluation system in `benchmark/` — rubric dimensions and weights, metrics, aggregation and verdict method, thresholds and calibration, measurement architecture. Everything treated as open to revision; the goal is the best possible evaluation system for QuantEcon, where lectures are teaching materials first. -**Method:** read every design document ([README.md](benchmark/README.md), [EVALUATION_FRAMEWORK.md](benchmark/references/EVALUATION_FRAMEWORK.md), [scripts/README.md](benchmark/scripts/README.md), [SKILL.md](benchmark/skills/review-acceleration/SKILL.md), [examples README](benchmark/references/examples/README.md)), the scoring engine ([rubric.py](benchmark/scripts/scoring/rubric.py), [score.py](benchmark/scripts/scoring/score.py)), both worked evaluations (evidence, results, reports), and the measurement scripts; then ran the rubric against synthetic edge cases to test the aggregation empirically. The numbered edge-case results below (A–D) were produced by executing `rubric.score_all` directly on constructed evidence. +**Method:** read every design document ([README.md](../benchmark/README.md), [EVALUATION_FRAMEWORK.md](../benchmark/references/EVALUATION_FRAMEWORK.md), [scripts/README.md](../benchmark/scripts/README.md), [SKILL.md](../benchmark/skills/review-acceleration/SKILL.md), [examples README](../benchmark/references/examples/README.md)), the scoring engine ([rubric.py](../benchmark/scripts/scoring/rubric.py), [score.py](../benchmark/scripts/scoring/score.py)), both worked evaluations (evidence, results, reports), and the measurement scripts; then ran the rubric against synthetic edge cases to test the aggregation empirically. The numbered edge-case results below (A–D) were produced by executing `rubric.score_all` directly on constructed evidence. ## Bottom line From 5e4eab0dcdafc2c365b67ab1ee0b091a62c56a1c Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Mon, 27 Jul 2026 14:22:39 +1000 Subject: [PATCH 2/2] Docs site: pin the preview version, and upload on PRs too (Copilot review) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two review comments, one adopted as filed and one adopted for a different reason than the one given. The preview instructions installed mystmd unpinned while CI pinned 1.10.1, so a contributor could preview against a version CI never runs. Pinned to match, with the workflow named in the comment so the pair is findable when it needs bumping. The permissions comment was wrong on its facts — `upload-pages-artifact` does not need `actions: write`, and GitHub's own Pages starter workflow runs it under `contents: read` alone, with artifact upload authenticating via ACTIONS_RUNTIME_TOKEN rather than GITHUB_TOKEN scopes. But it pointed at something real next to it: the upload was gated to `push`, so its first execution would have been the merge commit. Ungated, PRs now exercise the upload and still never deploy. --- .github/workflows/docs.yml | 9 ++++++--- docs/developing-skills.md | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 06404d8..66fbf48 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -34,15 +34,18 @@ jobs: run: npm install -g mystmd@1.10.1 # The site is served from a subpath (quantecon.github.io/skills), so the - # built asset URLs have to carry it. PR builds use the root, since they - # are only ever checked for whether they build. + # built asset URLs have to carry it. PR builds use the root: their + # artifact is never deployed, so the subpath would only make local + # inspection of it harder. - name: Build run: myst build --html env: BASE_URL: ${{ github.event_name == 'push' && '/skills' || '' }} + # Deliberately not gated to `push`: if the upload only ran on main, its + # first real exercise would be the merge commit, which is the worst + # place to discover it is broken. PRs upload and simply never deploy. - name: Upload Pages artifact - if: github.event_name == 'push' uses: actions/upload-pages-artifact@v3 with: path: _build/html diff --git a/docs/developing-skills.md b/docs/developing-skills.md index 645fa89..bd11bbc 100644 --- a/docs/developing-skills.md +++ b/docs/developing-skills.md @@ -82,8 +82,8 @@ Confirm with `/plugin marketplace list` (the source should read `QuantEcon/skill These guides, the plugin guides, and the shared reference material are published to [quantecon.github.io/skills](https://quantecon.github.io/skills) by [`.github/workflows/docs.yml`](../.github/workflows/docs.yml) on every push to `main`. Preview it before you push: ```bash -npm install -g mystmd -myst start # live-reloading preview +npm install -g mystmd@1.10.1 # same version CI pins in docs.yml +myst start # live-reloading preview ``` Two things follow from how it is wired. **Pages are rendered from the files where they already live** — [`myst.yml`](../myst.yml) points at `benchmark/README.md` and `audit/references/*.md` in place, never a copy — so editing a plugin's docs updates the site, and no plugin loses documentation it needs to ship with it. And **the sources have to stay readable on GitHub**, since the repo view is the other half of the audience: prefer plain Markdown, and keep relative links relative, because CI checks that every one of them resolves.