From f46e838313730fd980fa557e78347ec3d2000db7 Mon Sep 17 00:00:00 2001
From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com>
Date: Tue, 21 Jul 2026 06:24:31 +0100
Subject: [PATCH 1/2] ci: give CodeQL real source to scan; make Ddraig the sole
 Pages deployer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Two independent red checks on main, two root causes.

CodeQL (exit 32, "could not process any of it")
------------------------------------------------
The scan was failing because it had nothing to look at, not because it
found anything. statistikles is Julia + Agda + Zig — CodeQL supports none
of the three — so the only analysable file in the repo is the ~100-line
agent harness at .claude/workflows/prod-readiness.js. The JavaScript
extractor skips dot-directories by default, so it extracted zero files
and reported a configuration error.

Adds .github/codeql/codeql-config.yml naming that directory explicitly and
wires it in via config-file:. The job now either passes having actually
analysed something, or fails on a real finding.

Scope is deliberately honest and documented in the config header: this
covers the agent harness, NOT src/**/*.jl. The real correctness gates
remain e2e.yml (Julia test suite) and agda.yml (agda --safe).

GitHub Pages (two deployers, both red)
--------------------------------------
casket-pages.yml and pages.yml both declared `concurrency: group: "pages"`,
so they serialised rather than raced — and both failed. casket-pages.yml
died in ghcup (GHC 9.8.2 / cabal 3.10.3.0 not installed) and is superseded
by the Ddraig SSG deployer mass-deployed estate-wide in #56.

Removes casket-pages.yml. Neither had real site content to lose — casket
built from site/ (absent here) and synthesised a placeholder index; Ddraig
falls back to README.md the same way.

Note: pages.yml still 404s until Pages is enabled for this repository
(Settings -> Pages, source: GitHub Actions). That is an owner action and is
not addressed here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
 .github/codeql/codeql-config.yml   |  42 +++++++++++
 .github/workflows/casket-pages.yml | 108 -----------------------------
 .github/workflows/codeql.yml       |   4 ++
 3 files changed, 46 insertions(+), 108 deletions(-)
 create mode 100644 .github/codeql/codeql-config.yml
 delete mode 100644 .github/workflows/casket-pages.yml

diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
new file mode 100644
index 0000000..bd52c18
--- /dev/null
+++ b/.github/codeql/codeql-config.yml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: MPL-2.0
+# // Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
+#
+# CodeQL scan configuration for statistikles.
+#
+# WHY THIS FILE EXISTS
+# --------------------
+# statistikles is a Julia package with Agda proofs and a Zig FFI shim. CodeQL
+# supports none of those three languages, so the only thing here it *can*
+# analyse is JavaScript. The repository contains exactly one JavaScript file:
+#
+#     .claude/workflows/prod-readiness.js   (agent harness, ~100 lines)
+#
+# The CodeQL JavaScript extractor skips dot-directories by default, so with no
+# configuration it extracted zero files and the run died with
+#
+#     "CodeQL detected code written in JavaScript/TypeScript but could not
+#      process any of it"  (exit 32, configuration error)
+#
+# — i.e. the scan was failing *because it had nothing to look at*, not because
+# it found a problem. Naming the directory explicitly below gives the extractor
+# a real file, so the job either passes having actually analysed something or
+# fails on a genuine finding.
+#
+# HONEST SCOPE
+# ------------
+# This covers the agent harness, NOT the statistical code that is the point of
+# this project. A green CodeQL badge here means "the one JS file is clean"; it
+# says nothing about src/**/*.jl. The real correctness gates are the Julia test
+# suite (.github/workflows/e2e.yml) and `agda --safe` (.github/workflows/agda.yml).
+
+name: "statistikles CodeQL config"
+
+# Explicit include — required to reach a dot-directory the extractor would
+# otherwise skip. Extend this list if shipped JavaScript is ever added.
+paths:
+  - .claude/workflows
+
+paths-ignore:
+  # Build/interface artefacts that carry no reviewable source.
+  - "**/_build"
+  - "**/*.agdai"
diff --git a/.github/workflows/casket-pages.yml b/.github/workflows/casket-pages.yml
deleted file mode 100644
index 8a1a036..0000000
--- a/.github/workflows/casket-pages.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-# SPDX-License-Identifier: MPL-2.0
-# // Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
-name: GitHub Pages
-on:
-  push:
-    branches: [main, master]
-  workflow_dispatch:
-permissions:
-  contents: read
-  pages: write
-  id-token: write
-concurrency:
-  group: "pages"
-  cancel-in-progress: false
-jobs:
-  build:
-    runs-on: ubuntu-latest
-    # Cold cabal build of casket-ssg (GHC 9.8) exceeds 15 min and was being
-    # cancelled before the cache could ever save; warm-cache runs are fast.
-    timeout-minutes: 60
-    steps:
-      - name: Checkout
-        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
-      - name: Checkout casket-ssg
-        uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
-        with:
-          repository: hyperpolymath/casket-ssg
-          path: .casket-ssg
-      - name: Setup GHCup
-        uses: haskell-actions/setup@cd0d9bdd65b20557f41bea4dbe43d0b5fbbfe553 # v2
-        with:
-          ghc-version: '9.8.2'
-          cabal-version: '3.10'
-      - name: Cache Cabal
-        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
-        with:
-          path: |
-            ~/.cabal/packages
-            ~/.cabal/store
-            .casket-ssg/dist-newstyle
-          key: ${{ runner.os }}-casket-${{ hashFiles('.casket-ssg/casket-ssg.cabal') }}
-      - name: Build casket-ssg
-        working-directory: .casket-ssg
-        run: cabal build
-      - name: Prepare site source
-        shell: bash
-        run: |
-          set -euo pipefail
-          rm -rf .site-src _site
-
-          if [ -d site ]; then
-            cp -R site .site-src
-          else
-            mkdir -p .site-src
-            TODAY="$(date +%Y-%m-%d)"
-            REPO_NAME="${{ github.event.repository.name }}"
-            REPO_URL="https://github.com/${{ github.repository }}"
-            README_URL=""
-
-            if [ -f README.md ]; then
-              README_URL="${REPO_URL}/blob/${{ github.ref_name }}/README.md"
-            elif [ -f README.adoc ]; then
-              README_URL="${REPO_URL}/blob/${{ github.ref_name }}/README.adoc"
-            fi
-
-            {
-              echo "---"
-              echo "title: ${REPO_NAME}"
-              echo "date: ${TODAY}"
-              echo "---"
-              echo
-              echo "# ${REPO_NAME}"
-              echo
-              echo "Static documentation site for ${REPO_NAME}."
-              echo
-              echo "- Source repository: [${{ github.repository }}](${REPO_URL})"
-              if [ -n "${README_URL}" ]; then
-                echo "- README: [project README](${README_URL})"
-              fi
-              if [ -d docs ]; then
-                echo "- Docs directory: [docs/](${REPO_URL}/tree/${{ github.ref_name }}/docs)"
-              fi
-              echo
-              echo "Project-specific site content can be added later under site/."
-            } > .site-src/index.md
-          fi
-      - name: Build site
-        run: |
-          mkdir -p _site
-          cd .casket-ssg && cabal run casket-ssg -- build ../.site-src ../_site
-          touch ../_site/.nojekyll
-      - name: Setup Pages
-        uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
-      - name: Upload artifact
-        uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
-        with:
-          path: '_site'
-  deploy:
-    environment:
-      name: github-pages
-      url: ${{ steps.deployment.outputs.page_url }}
-    runs-on: ubuntu-latest
-    timeout-minutes: 15
-    needs: build
-    steps:
-      - name: Deploy to GitHub Pages
-        id: deployment
-        uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 200ef67..333ecf4 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -38,6 +38,10 @@ jobs:
         with:
           languages: ${{ matrix.language }}
           build-mode: ${{ matrix.build-mode }}
+          # Without this the extractor skips .claude/ (dot-directory), finds no
+          # JavaScript at all, and the run fails with exit 32 "could not process
+          # any of it". See .github/codeql/codeql-config.yml for the full why.
+          config-file: ./.github/codeql/codeql-config.yml
       - name: Perform CodeQL Analysis
         uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v3
         with:

From ddb5a139b5e1d963f30ef0123aa0bfecfaf80543 Mon Sep 17 00:00:00 2001
From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com>
Date: Tue, 21 Jul 2026 06:41:01 +0100
Subject: [PATCH 2/2] ci: add the missing SPDX header to pages.yml
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

`governance / Workflow security linter` fails with

    ERROR: .github/workflows/pages.yml missing SPDX header

This is pre-existing, not caused by removing casket-pages.yml — pages.yml
arrived via the estate-wide Ddraig mass-deploy (#56) without the header
that every other workflow in this repo carries. Deleting casket-pages.yml
did make it the *only* Pages workflow, so the gap is now unmasked rather
than introduced.

One-line fix; matches the header format used by codeql.yml, e2e.yml and
the rest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
 .github/workflows/pages.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 649dcb1..c6ba491 100755
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: MPL-2.0
+# // Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
 name: GitHub Pages (Ddraig SSG)
 on:
   push:
